summaryrefslogtreecommitdiff
path: root/makima/src/db
diff options
context:
space:
mode:
Diffstat (limited to 'makima/src/db')
-rw-r--r--makima/src/db/models.rs86
-rw-r--r--makima/src/db/repository.rs214
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
+}