diff options
Diffstat (limited to 'makima/src/db')
| -rw-r--r-- | makima/src/db/models.rs | 86 | ||||
| -rw-r--r-- | makima/src/db/repository.rs | 214 |
2 files changed, 295 insertions, 5 deletions
diff --git a/makima/src/db/models.rs b/makima/src/db/models.rs index bc90942..eff2df0 100644 --- a/makima/src/db/models.rs +++ b/makima/src/db/models.rs @@ -2849,12 +2849,37 @@ pub struct UpdateDirectiveRequest { pub version: Option<i32>, } +/// Lightweight contract summary attached to a chain step. +#[derive(Debug, FromRow, Serialize, ToSchema)] +#[serde(rename_all = "camelCase")] +pub struct StepContractSummary { + pub id: Uuid, + pub name: String, + pub contract_type: String, + pub phase: String, + pub status: String, + pub task_count: i64, + pub tasks_done: i64, + pub tasks_running: i64, + pub tasks_failed: i64, +} + +/// Chain step enriched with optional contract summary. +#[derive(Debug, Serialize, ToSchema)] +#[serde(rename_all = "camelCase")] +pub struct ChainStepWithContract { + #[serde(flatten)] + pub step: ChainStep, + pub contract_summary: Option<StepContractSummary>, +} + /// Directive with its chains and steps for detail view. #[derive(Debug, Serialize, ToSchema)] #[serde(rename_all = "camelCase")] pub struct DirectiveWithChains { #[serde(flatten)] pub directive: Directive, + pub orchestrator_contract_summary: Option<StepContractSummary>, pub chains: Vec<ChainWithSteps>, } @@ -2903,6 +2928,8 @@ pub struct ChainStep { pub status: String, pub contract_id: Option<Uuid>, pub supervisor_task_id: Option<Uuid>, + pub monitoring_contract_id: Option<Uuid>, + pub monitoring_task_id: Option<Uuid>, pub confidence_score: Option<f64>, pub confidence_level: Option<String>, pub evaluation_count: i32, @@ -2922,5 +2949,62 @@ pub struct ChainStep { pub struct ChainWithSteps { #[serde(flatten)] pub chain: DirectiveChain, - pub steps: Vec<ChainStep>, + pub steps: Vec<ChainStepWithContract>, +} + +/// Full row from directive_evaluations table. +#[derive(Debug, Clone, FromRow, Serialize, ToSchema)] +#[serde(rename_all = "camelCase")] +pub struct DirectiveEvaluation { + pub id: Uuid, + pub directive_id: Uuid, + pub chain_id: Option<Uuid>, + pub step_id: Option<Uuid>, + pub contract_id: Option<Uuid>, + pub evaluation_type: String, + pub evaluation_number: i32, + pub evaluator: Option<String>, + pub passed: bool, + pub overall_score: Option<f64>, + pub confidence_level: Option<String>, + #[sqlx(json)] + pub programmatic_results: serde_json::Value, + #[sqlx(json)] + pub llm_results: serde_json::Value, + #[sqlx(json)] + pub criteria_results: serde_json::Value, + pub summary_feedback: String, + pub rework_instructions: Option<String>, + #[sqlx(json)] + pub directive_snapshot: Option<serde_json::Value>, + #[sqlx(json)] + pub deliverables_snapshot: Option<serde_json::Value>, + pub started_at: DateTime<Utc>, + pub completed_at: Option<DateTime<Utc>>, + pub created_at: DateTime<Utc>, +} + +/// Full row from directive_events table. +#[derive(Debug, Clone, FromRow, Serialize, ToSchema)] +#[serde(rename_all = "camelCase")] +pub struct DirectiveEvent { + pub id: Uuid, + pub directive_id: Uuid, + pub chain_id: Option<Uuid>, + pub step_id: Option<Uuid>, + pub event_type: String, + pub severity: String, + #[sqlx(json)] + pub event_data: Option<serde_json::Value>, + pub actor_type: String, + pub actor_id: Option<Uuid>, + pub created_at: DateTime<Utc>, +} + +/// Response for evaluation list endpoint. +#[derive(Debug, Serialize, ToSchema)] +#[serde(rename_all = "camelCase")] +pub struct EvaluationListResponse { + pub evaluations: Vec<DirectiveEvaluation>, + pub total: i64, } diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs index e072eb8..d50ef61 100644 --- a/makima/src/db/repository.rs +++ b/makima/src/db/repository.rs @@ -11,12 +11,13 @@ use super::models::{ ContractTypeTemplateRecord, ConversationMessage, ConversationSnapshot, CreateContractRequest, CreateDirectiveRequest, CreateFileRequest, CreateTaskRequest, CreateTemplateRequest, Daemon, DaemonTaskAssignment, DaemonWithCapacity, - DeliverableDefinition, Directive, DirectiveChain, DirectiveSummary, + DeliverableDefinition, Directive, DirectiveChain, DirectiveEvaluation, DirectiveEvent, + DirectiveSummary, File, FileSummary, FileVersion, HistoryEvent, HistoryQueryFilters, MeshChatConversation, MeshChatMessageRecord, PhaseChangeResult, PhaseConfig, - PhaseDefinition, SupervisorHeartbeatRecord, SupervisorState, Task, TaskCheckpoint, - TaskEvent, TaskSummary, UpdateContractRequest, UpdateDirectiveRequest, - UpdateFileRequest, UpdateTaskRequest, UpdateTemplateRequest, + PhaseDefinition, StepContractSummary, SupervisorHeartbeatRecord, SupervisorState, + Task, TaskCheckpoint, TaskEvent, TaskSummary, UpdateContractRequest, + UpdateDirectiveRequest, UpdateFileRequest, UpdateTaskRequest, UpdateTemplateRequest, }; /// Repository error types. @@ -5184,6 +5185,29 @@ pub async fn list_steps_for_chain( .await } +/// Batch-fetch lightweight contract summaries for a set of contract IDs. +pub async fn get_contract_summaries_batch( + pool: &PgPool, + contract_ids: &[Uuid], +) -> Result<Vec<StepContractSummary>, sqlx::Error> { + sqlx::query_as::<_, StepContractSummary>( + r#" + SELECT c.id, c.name, c.contract_type, c.phase, c.status, + COUNT(t.id) as task_count, + COUNT(t.id) FILTER (WHERE t.status IN ('done','merged')) as tasks_done, + COUNT(t.id) FILTER (WHERE t.status IN ('running','initializing','starting')) as tasks_running, + COUNT(t.id) FILTER (WHERE t.status = 'failed') as tasks_failed + FROM contracts c + LEFT JOIN tasks t ON t.contract_id = c.id + WHERE c.id = ANY($1) + GROUP BY c.id, c.name, c.contract_type, c.phase, c.status + "#, + ) + .bind(contract_ids) + .fetch_all(pool) + .await +} + // ── Directive orchestration functions ─────────────────────────────────────── /// Update directive status with automatic timestamp management. @@ -5479,3 +5503,185 @@ pub async fn update_chain_status( .fetch_optional(pool) .await } + +// ── Directive monitoring / evaluation functions ───────────────────────────── + +/// Create a directive evaluation record. evaluation_number is auto-incremented per step. +pub async fn create_directive_evaluation( + pool: &PgPool, + directive_id: Uuid, + chain_id: Uuid, + step_id: Uuid, + contract_id: Uuid, + evaluation_type: &str, + evaluator: Option<&str>, + passed: bool, + overall_score: Option<f64>, + confidence_level: Option<&str>, + criteria_results: &serde_json::Value, + summary_feedback: &str, + rework_instructions: Option<&str>, +) -> Result<DirectiveEvaluation, sqlx::Error> { + sqlx::query_as::<_, DirectiveEvaluation>( + r#" + INSERT INTO directive_evaluations ( + directive_id, chain_id, step_id, contract_id, + evaluation_type, evaluation_number, evaluator, + passed, overall_score, confidence_level, + criteria_results, summary_feedback, rework_instructions, + completed_at + ) + VALUES ( + $1, $2, $3, $4, + $5, COALESCE((SELECT MAX(evaluation_number) FROM directive_evaluations WHERE step_id = $3), 0) + 1, $6, + $7, $8, $9, + $10, $11, $12, + NOW() + ) + RETURNING * + "#, + ) + .bind(directive_id) + .bind(chain_id) + .bind(step_id) + .bind(contract_id) + .bind(evaluation_type) + .bind(evaluator) + .bind(passed) + .bind(overall_score) + .bind(confidence_level) + .bind(criteria_results) + .bind(summary_feedback) + .bind(rework_instructions) + .fetch_one(pool) + .await +} + +/// List evaluations for a step, ordered by evaluation_number. +pub async fn list_evaluations_for_step( + pool: &PgPool, + step_id: Uuid, +) -> Result<Vec<DirectiveEvaluation>, sqlx::Error> { + sqlx::query_as::<_, DirectiveEvaluation>( + r#" + SELECT * FROM directive_evaluations + WHERE step_id = $1 + ORDER BY evaluation_number ASC + "#, + ) + .bind(step_id) + .fetch_all(pool) + .await +} + +/// Create a directive event. +pub async fn create_directive_event( + pool: &PgPool, + directive_id: Uuid, + chain_id: Option<Uuid>, + step_id: Option<Uuid>, + event_type: &str, + severity: &str, + event_data: Option<&serde_json::Value>, + actor_type: &str, + actor_id: Option<Uuid>, +) -> Result<DirectiveEvent, sqlx::Error> { + sqlx::query_as::<_, DirectiveEvent>( + r#" + INSERT INTO directive_events (directive_id, chain_id, step_id, event_type, severity, event_data, actor_type, actor_id) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + RETURNING * + "#, + ) + .bind(directive_id) + .bind(chain_id) + .bind(step_id) + .bind(event_type) + .bind(severity) + .bind(event_data) + .bind(actor_type) + .bind(actor_id) + .fetch_one(pool) + .await +} + +/// Update step evaluation fields after an evaluation completes. +pub async fn update_step_evaluation_fields( + pool: &PgPool, + step_id: Uuid, + confidence_score: Option<f64>, + confidence_level: Option<&str>, + last_evaluation_id: Uuid, +) -> Result<Option<ChainStep>, sqlx::Error> { + sqlx::query_as::<_, ChainStep>( + r#" + UPDATE chain_steps + SET confidence_score = $2, + confidence_level = $3, + evaluation_count = evaluation_count + 1, + last_evaluation_id = $4 + WHERE id = $1 + RETURNING * + "#, + ) + .bind(step_id) + .bind(confidence_score) + .bind(confidence_level) + .bind(last_evaluation_id) + .fetch_optional(pool) + .await +} + +/// Update step monitoring contract/task references. +pub async fn update_step_monitoring_contract( + pool: &PgPool, + step_id: Uuid, + monitoring_contract_id: Uuid, + monitoring_task_id: Uuid, +) -> Result<Option<ChainStep>, sqlx::Error> { + sqlx::query_as::<_, ChainStep>( + r#" + UPDATE chain_steps + SET monitoring_contract_id = $2, + monitoring_task_id = $3 + WHERE id = $1 + RETURNING * + "#, + ) + .bind(step_id) + .bind(monitoring_contract_id) + .bind(monitoring_task_id) + .fetch_optional(pool) + .await +} + +/// Increment step rework_count. +pub async fn increment_step_rework_count( + pool: &PgPool, + step_id: Uuid, +) -> Result<Option<ChainStep>, sqlx::Error> { + sqlx::query_as::<_, ChainStep>( + r#" + UPDATE chain_steps + SET rework_count = rework_count + 1 + WHERE id = $1 + RETURNING * + "#, + ) + .bind(step_id) + .fetch_optional(pool) + .await +} + +/// Get a chain step by its monitoring contract ID. +pub async fn get_step_by_monitoring_contract_id( + pool: &PgPool, + contract_id: Uuid, +) -> Result<Option<ChainStep>, sqlx::Error> { + sqlx::query_as::<_, ChainStep>( + r#"SELECT * FROM chain_steps WHERE monitoring_contract_id = $1"#, + ) + .bind(contract_id) + .fetch_optional(pool) + .await +} |
