summaryrefslogtreecommitdiff
path: root/makima/src/db
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-02-07 00:01:50 +0000
committersoryu <soryu@soryu.co>2026-02-07 00:01:50 +0000
commitb8d563d45f14a2b1db1f684aa0a8dcd7e5b6ad56 (patch)
tree95543fd150270018e384fbcf9d3df3dc45f052f6 /makima/src/db
parentcececbf326e258211ceae7afce716a5d1e46014f (diff)
downloadsoryu-b8d563d45f14a2b1db1f684aa0a8dcd7e5b6ad56.tar.gz
soryu-b8d563d45f14a2b1db1f684aa0a8dcd7e5b6ad56.zip
Remove directives for reimplementation
Diffstat (limited to 'makima/src/db')
-rw-r--r--makima/src/db/models.rs666
-rw-r--r--makima/src/db/repository.rs1169
2 files changed, 0 insertions, 1835 deletions
diff --git a/makima/src/db/models.rs b/makima/src/db/models.rs
index f951751..3b10cb5 100644
--- a/makima/src/db/models.rs
+++ b/makima/src/db/models.rs
@@ -2596,672 +2596,6 @@ pub struct HeartbeatHistoryQuery {
}
// =============================================================================
-// Directives (Goal-driven orchestration with chains of steps)
-// =============================================================================
-
-/// Directive status
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
-#[serde(rename_all = "snake_case")]
-pub enum DirectiveStatus {
- Draft,
- Planning,
- Active,
- Paused,
- Completed,
- Archived,
- Failed,
-}
-
-impl Default for DirectiveStatus {
- fn default() -> Self {
- DirectiveStatus::Draft
- }
-}
-
-impl std::fmt::Display for DirectiveStatus {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- DirectiveStatus::Draft => write!(f, "draft"),
- DirectiveStatus::Planning => write!(f, "planning"),
- DirectiveStatus::Active => write!(f, "active"),
- DirectiveStatus::Paused => write!(f, "paused"),
- DirectiveStatus::Completed => write!(f, "completed"),
- DirectiveStatus::Archived => write!(f, "archived"),
- DirectiveStatus::Failed => write!(f, "failed"),
- }
- }
-}
-
-impl std::str::FromStr for DirectiveStatus {
- type Err = String;
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- match s.to_lowercase().as_str() {
- "draft" => Ok(DirectiveStatus::Draft),
- "planning" => Ok(DirectiveStatus::Planning),
- "active" => Ok(DirectiveStatus::Active),
- "paused" => Ok(DirectiveStatus::Paused),
- "completed" => Ok(DirectiveStatus::Completed),
- "archived" => Ok(DirectiveStatus::Archived),
- "failed" => Ok(DirectiveStatus::Failed),
- _ => Err(format!("Invalid directive status: {}", s)),
- }
- }
-}
-
-/// Directive - the top-level goal-driven orchestration entity
-#[derive(Debug, Clone, FromRow, Serialize, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct Directive {
- pub id: Uuid,
- pub owner_id: Uuid,
- pub title: String,
- pub goal: String,
- /// Structured requirements: [{ id, title, description, priority, category }]
- #[sqlx(json)]
- pub requirements: serde_json::Value,
- /// Acceptance criteria: [{ id, requirementIds, description, testable, verificationMethod }]
- #[sqlx(json)]
- pub acceptance_criteria: serde_json::Value,
- /// Constraints: [{ id, type, description, impact }]
- #[sqlx(json)]
- pub constraints: serde_json::Value,
- /// External dependencies: [{ id, name, type, status, requiredBy }]
- #[sqlx(json)]
- pub external_dependencies: serde_json::Value,
- pub status: String,
- pub autonomy_level: String,
- pub confidence_threshold_green: f64,
- pub confidence_threshold_yellow: f64,
- pub max_total_cost_usd: Option<f64>,
- pub max_wall_time_minutes: Option<i32>,
- pub max_rework_cycles: Option<i32>,
- pub max_chain_regenerations: Option<i32>,
- pub repository_url: Option<String>,
- pub local_path: Option<String>,
- pub base_branch: Option<String>,
- pub orchestrator_contract_id: Option<Uuid>,
- pub current_chain_id: Option<Uuid>,
- pub chain_generation_count: i32,
- pub total_cost_usd: f64,
- pub started_at: Option<DateTime<Utc>>,
- pub completed_at: Option<DateTime<Utc>>,
- pub version: i32,
- pub created_at: DateTime<Utc>,
- pub updated_at: DateTime<Utc>,
-}
-
-impl Directive {
- /// Parse status string to DirectiveStatus enum
- pub fn status_enum(&self) -> Result<DirectiveStatus, String> {
- self.status.parse()
- }
-}
-
-/// Directive chain - a generated execution plan (DAG) for a directive
-#[derive(Debug, Clone, FromRow, Serialize, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct DirectiveChain {
- pub id: Uuid,
- pub directive_id: Uuid,
- pub generation: i32,
- pub name: String,
- pub description: Option<String>,
- pub rationale: Option<String>,
- pub planning_model: Option<String>,
- pub status: String,
- pub total_steps: i32,
- pub completed_steps: i32,
- pub failed_steps: i32,
- pub current_confidence: Option<f64>,
- pub started_at: Option<DateTime<Utc>>,
- pub completed_at: Option<DateTime<Utc>>,
- pub version: i32,
- pub created_at: DateTime<Utc>,
- pub updated_at: DateTime<Utc>,
-}
-
-/// Chain step status
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
-#[serde(rename_all = "snake_case")]
-pub enum StepStatus {
- Pending,
- Ready,
- Running,
- Evaluating,
- Passed,
- Failed,
- Rework,
- Skipped,
- Blocked,
-}
-
-impl Default for StepStatus {
- fn default() -> Self {
- StepStatus::Pending
- }
-}
-
-impl std::fmt::Display for StepStatus {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- StepStatus::Pending => write!(f, "pending"),
- StepStatus::Ready => write!(f, "ready"),
- StepStatus::Running => write!(f, "running"),
- StepStatus::Evaluating => write!(f, "evaluating"),
- StepStatus::Passed => write!(f, "passed"),
- StepStatus::Failed => write!(f, "failed"),
- StepStatus::Rework => write!(f, "rework"),
- StepStatus::Skipped => write!(f, "skipped"),
- StepStatus::Blocked => write!(f, "blocked"),
- }
- }
-}
-
-impl std::str::FromStr for StepStatus {
- type Err = String;
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- match s.to_lowercase().as_str() {
- "pending" => Ok(StepStatus::Pending),
- "ready" => Ok(StepStatus::Ready),
- "running" => Ok(StepStatus::Running),
- "evaluating" => Ok(StepStatus::Evaluating),
- "passed" => Ok(StepStatus::Passed),
- "failed" => Ok(StepStatus::Failed),
- "rework" => Ok(StepStatus::Rework),
- "skipped" => Ok(StepStatus::Skipped),
- "blocked" => Ok(StepStatus::Blocked),
- _ => Err(format!("Invalid step status: {}", s)),
- }
- }
-}
-
-/// Chain step - a node in the DAG execution plan
-#[derive(Debug, Clone, FromRow, Serialize, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct ChainStep {
- pub id: Uuid,
- pub chain_id: Uuid,
- pub name: String,
- pub description: Option<String>,
- pub step_type: String,
- pub contract_type: String,
- pub initial_phase: Option<String>,
- pub task_plan: Option<String>,
- #[sqlx(default)]
- pub phases: Vec<String>,
- #[sqlx(default)]
- pub depends_on: Vec<Uuid>,
- pub parallel_group: Option<String>,
- #[sqlx(default)]
- pub requirement_ids: Vec<String>,
- #[sqlx(default)]
- pub acceptance_criteria_ids: Vec<String>,
- #[sqlx(json)]
- #[serde(default)]
- pub verifier_config: serde_json::Value,
- pub status: String,
- pub contract_id: Option<Uuid>,
- pub supervisor_task_id: Option<Uuid>,
- pub confidence_score: Option<f64>,
- pub confidence_level: Option<String>,
- pub evaluation_count: i32,
- pub rework_count: i32,
- pub last_evaluation_id: Option<Uuid>,
- pub editor_x: Option<f64>,
- pub editor_y: Option<f64>,
- pub order_index: i32,
- pub started_at: Option<DateTime<Utc>>,
- pub completed_at: Option<DateTime<Utc>>,
- pub created_at: DateTime<Utc>,
-}
-
-impl ChainStep {
- /// Parse status string to StepStatus enum
- pub fn status_enum(&self) -> Result<StepStatus, String> {
- self.status.parse()
- }
-}
-
-/// Confidence level (traffic light)
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
-#[serde(rename_all = "snake_case")]
-pub enum ConfidenceLevel {
- Green,
- Yellow,
- Red,
-}
-
-impl ConfidenceLevel {
- pub fn from_score(score: f64, green_threshold: f64, yellow_threshold: f64) -> Self {
- if score >= green_threshold {
- Self::Green
- } else if score >= yellow_threshold {
- Self::Yellow
- } else {
- Self::Red
- }
- }
-}
-
-impl std::fmt::Display for ConfidenceLevel {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- ConfidenceLevel::Green => write!(f, "green"),
- ConfidenceLevel::Yellow => write!(f, "yellow"),
- ConfidenceLevel::Red => write!(f, "red"),
- }
- }
-}
-
-/// Directive evaluation - composite programmatic + LLM evaluation result
-#[derive(Debug, Clone, FromRow, Serialize, Deserialize, 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)]
- #[serde(default)]
- pub programmatic_results: serde_json::Value,
- #[sqlx(json)]
- #[serde(default)]
- pub llm_results: serde_json::Value,
- #[sqlx(json)]
- #[serde(default)]
- 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>,
-}
-
-/// Directive event - audit stream entry
-#[derive(Debug, Clone, FromRow, Serialize, Deserialize, 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>,
-}
-
-/// Directive verifier - pluggable verification configuration
-#[derive(Debug, Clone, FromRow, Serialize, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct DirectiveVerifier {
- pub id: Uuid,
- pub directive_id: Uuid,
- pub name: String,
- pub verifier_type: String,
- pub command: Option<String>,
- pub working_directory: Option<String>,
- pub timeout_seconds: Option<i32>,
- #[sqlx(json)]
- #[serde(default)]
- pub environment: serde_json::Value,
- pub auto_detect: bool,
- #[sqlx(default)]
- pub detect_files: Vec<String>,
- pub weight: f64,
- pub required: bool,
- pub enabled: bool,
- pub last_run_at: Option<DateTime<Utc>>,
- #[sqlx(json)]
- pub last_result: Option<serde_json::Value>,
- pub created_at: DateTime<Utc>,
- pub updated_at: DateTime<Utc>,
-}
-
-/// Directive approval - human-in-the-loop gate
-#[derive(Debug, Clone, FromRow, Serialize, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct DirectiveApproval {
- pub id: Uuid,
- pub directive_id: Uuid,
- pub step_id: Option<Uuid>,
- pub approval_type: String,
- pub description: String,
- #[sqlx(json)]
- pub context: Option<serde_json::Value>,
- pub urgency: String,
- pub status: String,
- pub response: Option<String>,
- pub responded_by: Option<Uuid>,
- pub responded_at: Option<DateTime<Utc>>,
- pub expires_at: Option<DateTime<Utc>>,
- pub created_at: DateTime<Utc>,
-}
-
-// =============================================================================
-// Directive Request/Response Types
-// =============================================================================
-
-/// Request to create a directive from a goal
-#[derive(Debug, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct CreateDirectiveRequest {
- pub goal: String,
- pub title: Option<String>,
- pub repository_url: Option<String>,
- pub local_path: Option<String>,
- pub base_branch: Option<String>,
- pub autonomy_level: Option<String>,
- pub requirements: Option<serde_json::Value>,
- pub acceptance_criteria: Option<serde_json::Value>,
- pub confidence_threshold_green: Option<f64>,
- pub confidence_threshold_yellow: Option<f64>,
- pub max_total_cost_usd: Option<f64>,
- pub max_wall_time_minutes: Option<i32>,
-}
-
-/// Request to update a directive
-#[derive(Debug, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct UpdateDirectiveRequest {
- pub title: Option<String>,
- pub goal: Option<String>,
- pub requirements: Option<serde_json::Value>,
- pub acceptance_criteria: Option<serde_json::Value>,
- pub constraints: Option<serde_json::Value>,
- pub external_dependencies: Option<serde_json::Value>,
- pub autonomy_level: Option<String>,
- pub confidence_threshold_green: Option<f64>,
- pub confidence_threshold_yellow: Option<f64>,
- pub max_total_cost_usd: Option<f64>,
- pub max_wall_time_minutes: Option<i32>,
- pub max_rework_cycles: Option<i32>,
- pub max_chain_regenerations: Option<i32>,
- pub version: i32,
-}
-
-/// Directive summary for list views
-#[derive(Debug, Clone, Serialize, FromRow, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct DirectiveSummary {
- pub id: Uuid,
- pub title: String,
- pub goal: String,
- pub status: String,
- pub autonomy_level: String,
- pub current_confidence: Option<f64>,
- pub completed_steps: i32,
- pub total_steps: i32,
- pub chain_generation_count: i32,
- pub started_at: Option<DateTime<Utc>>,
- pub created_at: DateTime<Utc>,
-}
-
-/// Directive with progress, chain, events, and approvals
-#[derive(Debug, Serialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct DirectiveWithProgress {
- #[serde(flatten)]
- pub directive: Directive,
- pub chain: Option<DirectiveChain>,
- pub steps: Vec<ChainStep>,
- pub recent_events: Vec<DirectiveEvent>,
- pub pending_approvals: Vec<DirectiveApproval>,
-}
-
-/// Request to add a step to a chain
-#[derive(Debug, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct AddStepRequest {
- pub name: String,
- pub description: Option<String>,
- pub step_type: Option<String>,
- pub contract_type: Option<String>,
- pub initial_phase: Option<String>,
- pub task_plan: Option<String>,
- pub phases: Option<Vec<String>>,
- pub depends_on: Option<Vec<Uuid>>,
- pub parallel_group: Option<String>,
- pub requirement_ids: Option<Vec<String>>,
- pub acceptance_criteria_ids: Option<Vec<String>>,
- pub verifier_config: Option<serde_json::Value>,
- pub editor_x: Option<f64>,
- pub editor_y: Option<f64>,
-}
-
-/// Request to update a step
-#[derive(Debug, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct UpdateStepRequest {
- pub name: Option<String>,
- pub description: Option<String>,
- pub task_plan: Option<String>,
- pub depends_on: Option<Vec<Uuid>>,
- pub requirement_ids: Option<Vec<String>>,
- pub acceptance_criteria_ids: Option<Vec<String>>,
- pub verifier_config: Option<serde_json::Value>,
- pub editor_x: Option<f64>,
- pub editor_y: Option<f64>,
-}
-
-/// Chain graph response for DAG visualization
-#[derive(Debug, Serialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct DirectiveChainGraphResponse {
- pub chain_id: Uuid,
- pub directive_id: Uuid,
- pub nodes: Vec<DirectiveChainGraphNode>,
- pub edges: Vec<DirectiveChainGraphEdge>,
-}
-
-/// Node in directive chain graph
-#[derive(Debug, Serialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct DirectiveChainGraphNode {
- pub id: Uuid,
- pub name: String,
- pub step_type: String,
- pub status: String,
- pub confidence_score: Option<f64>,
- pub confidence_level: Option<String>,
- pub contract_id: Option<Uuid>,
- pub editor_x: Option<f64>,
- pub editor_y: Option<f64>,
-}
-
-/// Edge in directive chain graph
-#[derive(Debug, Serialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct DirectiveChainGraphEdge {
- pub source: Uuid,
- pub target: Uuid,
-}
-
-/// Start directive response
-#[derive(Debug, Serialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct StartDirectiveResponse {
- pub directive_id: Uuid,
- pub chain_id: Uuid,
- pub chain_generation: i32,
- pub steps: Vec<ChainStep>,
- pub status: String,
-}
-
-/// Request to create a verifier
-#[derive(Debug, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct CreateVerifierRequest {
- pub name: String,
- pub verifier_type: String,
- pub command: Option<String>,
- pub working_directory: Option<String>,
- pub timeout_seconds: Option<i32>,
- pub environment: Option<serde_json::Value>,
- pub weight: Option<f64>,
- pub required: Option<bool>,
-}
-
-/// Request to update a verifier
-#[derive(Debug, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct UpdateVerifierRequest {
- pub name: Option<String>,
- pub command: Option<String>,
- pub working_directory: Option<String>,
- pub timeout_seconds: Option<i32>,
- pub weight: Option<f64>,
- pub required: Option<bool>,
- pub enabled: Option<bool>,
-}
-
-/// Approval action request
-#[derive(Debug, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct ApprovalActionRequest {
- pub response: Option<String>,
-}
-
-/// Request to update directive requirements
-#[derive(Debug, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct UpdateRequirementsRequest {
- pub requirements: Vec<DirectiveRequirement>,
-}
-
-/// Request to update directive acceptance criteria
-#[derive(Debug, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct UpdateCriteriaRequest {
- pub acceptance_criteria: Vec<DirectiveAcceptanceCriterion>,
-}
-
-/// Request to trigger step rework
-#[derive(Debug, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct ReworkStepRequest {
- pub instructions: Option<String>,
-}
-
-/// Directive requirement (shared type used in directive specification)
-#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct DirectiveRequirement {
- pub id: String,
- pub title: String,
- pub description: String,
- pub priority: String,
- pub category: Option<String>,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub parent_id: Option<String>,
-}
-
-/// Directive acceptance criterion
-#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
-#[serde(rename_all = "camelCase")]
-pub struct DirectiveAcceptanceCriterion {
- pub id: String,
- #[serde(default)]
- pub requirement_ids: Vec<String>,
- pub description: String,
- #[serde(default = "default_true")]
- pub testable: bool,
- pub verification_method: Option<String>,
-}
-
-fn default_true() -> bool {
- true
-}
-
-// Old chain types (Chain, ChainContract, ChainContractDefinition, ChainDirective,
-// ContractEvaluation, ChainEvent, ChainRepository, etc.) have been replaced by
-// the directive system above: Directive, DirectiveChain, ChainStep,
-// DirectiveEvaluation, DirectiveEvent, DirectiveVerifier, DirectiveApproval.
-
-// Legacy types kept temporarily for chain runner/parser compatibility during migration.
-// These will be removed once the chain daemon module is replaced.
-
-/// Request payload for creating a new chain (legacy - used by chain runner)
-#[derive(Debug, Clone, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CreateChainRequest {
- pub name: String,
- pub description: Option<String>,
- pub repository_url: Option<String>,
- pub repositories: Option<Vec<AddChainRepositoryRequest>>,
- pub loop_enabled: Option<bool>,
- pub loop_max_iterations: Option<i32>,
- pub loop_progress_check: Option<String>,
- pub contracts: Option<Vec<CreateChainContractRequest>>,
-}
-
-/// Request to add a repository to a chain (legacy - used by chain runner)
-#[derive(Debug, Clone, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct AddChainRepositoryRequest {
- pub name: String,
- pub repository_url: Option<String>,
- pub local_path: Option<String>,
- #[serde(default = "default_source_type")]
- pub source_type: String,
- #[serde(default)]
- pub is_primary: bool,
-}
-
-fn default_source_type() -> String {
- "remote".to_string()
-}
-
-/// Request to create a contract within a chain (legacy - used by chain runner)
-#[derive(Debug, Clone, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CreateChainContractRequest {
- pub name: String,
- pub description: Option<String>,
- #[serde(default)]
- pub contract_type: Option<String>,
- pub initial_phase: Option<String>,
- pub phases: Option<Vec<String>>,
- pub depends_on: Option<Vec<String>>,
- pub tasks: Option<Vec<CreateChainTaskRequest>>,
- pub deliverables: Option<Vec<CreateChainDeliverableRequest>>,
- pub editor_x: Option<f64>,
- pub editor_y: Option<f64>,
-}
-
-/// Task definition within a chain contract (legacy - used by chain runner)
-#[derive(Debug, Clone, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CreateChainTaskRequest {
- pub name: String,
- pub plan: String,
-}
-
-/// Deliverable definition within a chain contract (legacy - used by chain runner)
-#[derive(Debug, Clone, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CreateChainDeliverableRequest {
- pub id: String,
- pub name: String,
- pub priority: Option<String>,
-}
-
-// =============================================================================
// Unit Tests
// =============================================================================
diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs
index cd806f0..863d927 100644
--- a/makima/src/db/repository.rs
+++ b/makima/src/db/repository.rs
@@ -6,7 +6,6 @@ use sqlx::PgPool;
use uuid::Uuid;
use super::models::{
- // Core types
CheckpointPatch, CheckpointPatchInfo, Contract, ContractChatConversation,
ContractChatMessageRecord, ContractEvent, ContractRepository, ContractSummary,
ContractTypeTemplateRecord, ConversationMessage, ConversationSnapshot,
@@ -17,11 +16,6 @@ use super::models::{
PhaseDefinition, SupervisorHeartbeatRecord, SupervisorState, Task, TaskCheckpoint,
TaskEvent, TaskSummary, UpdateContractRequest, UpdateFileRequest, UpdateTaskRequest,
UpdateTemplateRequest,
- // Directive types
- AddStepRequest, ChainStep, CreateDirectiveRequest, Directive, DirectiveApproval,
- DirectiveChain, DirectiveChainGraphEdge, DirectiveChainGraphNode, DirectiveChainGraphResponse,
- DirectiveEvaluation, DirectiveEvent, DirectiveSummary, DirectiveVerifier,
- DirectiveWithProgress, UpdateDirectiveRequest, UpdateStepRequest,
};
/// Repository error types.
@@ -4905,1169 +4899,6 @@ pub async fn sync_supervisor_state(
}
// =============================================================================
-// Directive Operations (top-level orchestration entity)
-// =============================================================================
-// TODO: Implement directive CRUD functions
-// - create_directive_for_owner
-// - get_directive_for_owner
-// - list_directives_for_owner
-// - update_directive_for_owner
-// - archive_directive_for_owner
-// - update_directive_status
-
-// =============================================================================
-// Directive Chain Operations (generated execution plans)
-// =============================================================================
-// TODO: Implement chain CRUD functions
-// - create_directive_chain
-// - get_current_chain
-// - supersede_chain
-
-// =============================================================================
-// Chain Step Operations (nodes in the DAG)
-// =============================================================================
-// TODO: Implement step CRUD functions
-// - create_chain_step
-// - update_chain_step
-// - delete_chain_step
-// - find_ready_steps
-// - update_step_status
-// - update_step_contract
-// - update_step_confidence
-// - increment_step_rework_count
-
-// =============================================================================
-// Directive Evaluation Operations
-// =============================================================================
-// TODO: Implement evaluation functions
-// - create_directive_evaluation
-// - list_step_evaluations
-// - list_directive_evaluations
-
-// =============================================================================
-// Directive Event Operations (audit stream)
-// =============================================================================
-// TODO: Implement event functions
-// - emit_directive_event
-// - list_directive_events
-
-// =============================================================================
-// Directive Verifier Operations
-// =============================================================================
-// TODO: Implement verifier CRUD functions
-// - create_directive_verifier
-// - list_directive_verifiers
-// - update_directive_verifier
-
-// =============================================================================
-// Directive Approval Operations (human-in-the-loop)
-// =============================================================================
-// TODO: Implement approval functions
-// - create_approval_request
-// - resolve_approval
-// - list_pending_approvals
-
-// NOTE: Old chain functions removed. See git history for reference.
-// Old functions included: create_chain_for_owner, get_chain_for_owner,
-// list_chains_for_owner, update_chain_for_owner, delete_chain_for_owner,
-// add_contract_to_chain, remove_contract_from_chain, list_chain_contracts,
-// get_chain_with_contracts, list_chain_repositories, add_chain_repository,
-// delete_chain_repository, set_chain_repository_primary, get_chain_graph,
-// record_chain_event, list_chain_events, increment_chain_loop, complete_chain,
-// get_ready_chain_contracts, is_chain_complete, get_chain_editor_data,
-// create_chain_contract_definition, list_chain_contract_definitions,
-// update_chain_contract_definition, delete_chain_contract_definition,
-// get_chain_definition_graph, update_chain_status, progress_chain,
-// create_chain_directive, get_chain_directive, update_chain_directive,
-// delete_chain_directive, create_contract_evaluation, get_contract_evaluation,
-// list_chain_evaluations, update_chain_contract_evaluation_status,
-// mark_chain_contract_original_completion, get_chain_contract_by_contract_id,
-// init_chain_for_owner.
-
-// =============================================================================
-// Directive Operations
-// =============================================================================
-
-/// Create a new directive for an owner.
-pub async fn create_directive_for_owner(
- pool: &PgPool,
- owner_id: Uuid,
- req: CreateDirectiveRequest,
-) -> Result<Directive, sqlx::Error> {
- let title = req.title.unwrap_or_else(|| truncate_string(&req.goal, 100));
- let autonomy_level = req.autonomy_level.unwrap_or_else(|| "guardrails".to_string());
- let green_threshold = req.confidence_threshold_green.unwrap_or(0.85);
- let yellow_threshold = req.confidence_threshold_yellow.unwrap_or(0.60);
- let requirements = req.requirements.unwrap_or(serde_json::json!([]));
- let acceptance_criteria = req.acceptance_criteria.unwrap_or(serde_json::json!([]));
-
- sqlx::query_as::<_, Directive>(
- r#"
- INSERT INTO directives (
- owner_id, title, goal, requirements, acceptance_criteria,
- autonomy_level, confidence_threshold_green, confidence_threshold_yellow,
- repository_url, local_path, base_branch,
- max_total_cost_usd, max_wall_time_minutes
- )
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
- RETURNING *
- "#,
- )
- .bind(owner_id)
- .bind(&title)
- .bind(&req.goal)
- .bind(&requirements)
- .bind(&acceptance_criteria)
- .bind(&autonomy_level)
- .bind(green_threshold)
- .bind(yellow_threshold)
- .bind(&req.repository_url)
- .bind(&req.local_path)
- .bind(&req.base_branch)
- .bind(req.max_total_cost_usd)
- .bind(req.max_wall_time_minutes)
- .fetch_one(pool)
- .await
-}
-
-/// Get a directive by ID, scoped to owner.
-pub async fn get_directive_for_owner(
- pool: &PgPool,
- id: Uuid,
- owner_id: Uuid,
-) -> Result<Option<Directive>, sqlx::Error> {
- sqlx::query_as::<_, Directive>(
- r#"
- SELECT * FROM directives WHERE id = $1 AND owner_id = $2
- "#,
- )
- .bind(id)
- .bind(owner_id)
- .fetch_optional(pool)
- .await
-}
-
-/// Get a directive by ID (no owner check - for internal use).
-pub async fn get_directive(pool: &PgPool, id: Uuid) -> Result<Option<Directive>, sqlx::Error> {
- sqlx::query_as::<_, Directive>(
- r#"SELECT * FROM directives WHERE id = $1"#,
- )
- .bind(id)
- .fetch_optional(pool)
- .await
-}
-
-/// List directives for an owner.
-pub async fn list_directives_for_owner(
- pool: &PgPool,
- owner_id: Uuid,
- status_filter: Option<&str>,
-) -> Result<Vec<DirectiveSummary>, sqlx::Error> {
- let query = if let Some(status) = status_filter {
- sqlx::query_as::<_, DirectiveSummary>(
- r#"
- SELECT
- d.id, d.title, d.goal, d.status, d.autonomy_level,
- dc.current_confidence,
- COALESCE(dc.completed_steps, 0) as completed_steps,
- COALESCE(dc.total_steps, 0) as total_steps,
- d.chain_generation_count, d.started_at, d.created_at
- FROM directives d
- LEFT JOIN directive_chains dc ON dc.id = d.current_chain_id
- WHERE d.owner_id = $1 AND d.status = $2
- ORDER BY d.created_at DESC
- "#,
- )
- .bind(owner_id)
- .bind(status)
- } else {
- sqlx::query_as::<_, DirectiveSummary>(
- r#"
- SELECT
- d.id, d.title, d.goal, d.status, d.autonomy_level,
- dc.current_confidence,
- COALESCE(dc.completed_steps, 0) as completed_steps,
- COALESCE(dc.total_steps, 0) as total_steps,
- d.chain_generation_count, d.started_at, d.created_at
- FROM directives d
- LEFT JOIN directive_chains dc ON dc.id = d.current_chain_id
- WHERE d.owner_id = $1
- ORDER BY d.created_at DESC
- "#,
- )
- .bind(owner_id)
- };
- query.fetch_all(pool).await
-}
-
-/// Update a directive with optimistic locking.
-pub async fn update_directive_for_owner(
- pool: &PgPool,
- id: Uuid,
- owner_id: Uuid,
- req: UpdateDirectiveRequest,
-) -> Result<Directive, RepositoryError> {
- // First get current version
- let current = sqlx::query_scalar::<_, i32>(
- "SELECT version FROM directives WHERE id = $1 AND owner_id = $2"
- )
- .bind(id)
- .bind(owner_id)
- .fetch_optional(pool)
- .await?
- .ok_or_else(|| RepositoryError::Database(sqlx::Error::RowNotFound))?;
-
- if current != req.version {
- return Err(RepositoryError::VersionConflict {
- expected: req.version,
- actual: current,
- });
- }
-
- let directive = sqlx::query_as::<_, Directive>(
- r#"
- UPDATE directives SET
- title = COALESCE($3, title),
- goal = COALESCE($4, goal),
- requirements = COALESCE($5, requirements),
- acceptance_criteria = COALESCE($6, acceptance_criteria),
- constraints = COALESCE($7, constraints),
- external_dependencies = COALESCE($8, external_dependencies),
- autonomy_level = COALESCE($9, autonomy_level),
- confidence_threshold_green = COALESCE($10, confidence_threshold_green),
- confidence_threshold_yellow = COALESCE($11, confidence_threshold_yellow),
- max_total_cost_usd = COALESCE($12, max_total_cost_usd),
- max_wall_time_minutes = COALESCE($13, max_wall_time_minutes),
- max_rework_cycles = COALESCE($14, max_rework_cycles),
- max_chain_regenerations = COALESCE($15, max_chain_regenerations),
- version = version + 1,
- updated_at = NOW()
- WHERE id = $1 AND owner_id = $2 AND version = $16
- RETURNING *
- "#,
- )
- .bind(id)
- .bind(owner_id)
- .bind(&req.title)
- .bind(&req.goal)
- .bind(&req.requirements)
- .bind(&req.acceptance_criteria)
- .bind(&req.constraints)
- .bind(&req.external_dependencies)
- .bind(&req.autonomy_level)
- .bind(req.confidence_threshold_green)
- .bind(req.confidence_threshold_yellow)
- .bind(req.max_total_cost_usd)
- .bind(req.max_wall_time_minutes)
- .bind(req.max_rework_cycles)
- .bind(req.max_chain_regenerations)
- .bind(req.version)
- .fetch_one(pool)
- .await?;
-
- Ok(directive)
-}
-
-/// Update directive status.
-pub async fn update_directive_status(
- pool: &PgPool,
- id: Uuid,
- status: &str,
-) -> Result<Directive, sqlx::Error> {
- sqlx::query_as::<_, Directive>(
- r#"
- UPDATE directives SET
- status = $2,
- started_at = CASE WHEN $2 = 'active' AND started_at IS NULL THEN NOW() ELSE started_at END,
- completed_at = CASE WHEN $2 IN ('completed', 'failed', 'archived') THEN NOW() ELSE completed_at END,
- updated_at = NOW()
- WHERE id = $1
- RETURNING *
- "#,
- )
- .bind(id)
- .bind(status)
- .fetch_one(pool)
- .await
-}
-
-/// Set the orchestrator contract ID for a directive.
-pub async fn set_directive_orchestrator_contract(
- pool: &PgPool,
- directive_id: Uuid,
- contract_id: Uuid,
-) -> Result<(), sqlx::Error> {
- sqlx::query(
- r#"
- UPDATE directives SET orchestrator_contract_id = $2, updated_at = NOW()
- WHERE id = $1
- "#,
- )
- .bind(directive_id)
- .bind(contract_id)
- .execute(pool)
- .await?;
- Ok(())
-}
-
-/// Find a directive by its orchestrator contract ID.
-pub async fn get_directive_by_orchestrator_contract_id(
- pool: &PgPool,
- contract_id: Uuid,
-) -> Result<Option<Directive>, sqlx::Error> {
- sqlx::query_as::<_, Directive>(
- r#"
- SELECT * FROM directives WHERE orchestrator_contract_id = $1
- "#,
- )
- .bind(contract_id)
- .fetch_optional(pool)
- .await
-}
-
-/// Archive a directive (soft delete).
-pub async fn archive_directive_for_owner(
- pool: &PgPool,
- id: Uuid,
- owner_id: Uuid,
-) -> Result<bool, sqlx::Error> {
- let result = sqlx::query(
- r#"
- UPDATE directives SET status = 'archived', updated_at = NOW()
- WHERE id = $1 AND owner_id = $2
- "#,
- )
- .bind(id)
- .bind(owner_id)
- .execute(pool)
- .await?;
- Ok(result.rows_affected() > 0)
-}
-
-/// Get directive with full progress info.
-pub async fn get_directive_with_progress(
- pool: &PgPool,
- id: Uuid,
- owner_id: Uuid,
-) -> Result<Option<DirectiveWithProgress>, sqlx::Error> {
- let directive = match get_directive_for_owner(pool, id, owner_id).await? {
- Some(d) => d,
- None => return Ok(None),
- };
-
- let chain = if let Some(chain_id) = directive.current_chain_id {
- get_directive_chain(pool, chain_id).await?
- } else {
- None
- };
-
- let steps = if let Some(ref c) = chain {
- list_chain_steps(pool, c.id).await?
- } else {
- vec![]
- };
-
- let recent_events = list_directive_events(pool, id, Some(20)).await?;
- let pending_approvals = list_pending_approvals(pool, id).await?;
-
- Ok(Some(DirectiveWithProgress {
- directive,
- chain,
- steps,
- recent_events,
- pending_approvals,
- }))
-}
-
-// =============================================================================
-// Directive Chain Operations
-// =============================================================================
-
-/// Create a new chain generation for a directive.
-pub async fn create_directive_chain(
- pool: &PgPool,
- directive_id: Uuid,
- name: &str,
- description: Option<&str>,
- rationale: Option<&str>,
- planning_model: Option<&str>,
-) -> Result<DirectiveChain, sqlx::Error> {
- // Get next generation number
- let generation = sqlx::query_scalar::<_, i32>(
- "SELECT COALESCE(MAX(generation), 0) + 1 FROM directive_chains WHERE directive_id = $1"
- )
- .bind(directive_id)
- .fetch_one(pool)
- .await?;
-
- let chain = sqlx::query_as::<_, DirectiveChain>(
- r#"
- INSERT INTO directive_chains (directive_id, generation, name, description, rationale, planning_model)
- VALUES ($1, $2, $3, $4, $5, $6)
- RETURNING *
- "#,
- )
- .bind(directive_id)
- .bind(generation)
- .bind(name)
- .bind(description)
- .bind(rationale)
- .bind(planning_model)
- .fetch_one(pool)
- .await?;
-
- // Update directive to point to new chain and increment generation count
- sqlx::query(
- r#"
- UPDATE directives SET
- current_chain_id = $2,
- chain_generation_count = chain_generation_count + 1,
- updated_at = NOW()
- WHERE id = $1
- "#,
- )
- .bind(directive_id)
- .bind(chain.id)
- .execute(pool)
- .await?;
-
- Ok(chain)
-}
-
-/// Get a directive chain by ID.
-pub async fn get_directive_chain(pool: &PgPool, id: Uuid) -> Result<Option<DirectiveChain>, sqlx::Error> {
- sqlx::query_as::<_, DirectiveChain>(
- "SELECT * FROM directive_chains WHERE id = $1"
- )
- .bind(id)
- .fetch_optional(pool)
- .await
-}
-
-/// Get the current chain for a directive.
-pub async fn get_current_chain(pool: &PgPool, directive_id: Uuid) -> Result<Option<DirectiveChain>, sqlx::Error> {
- sqlx::query_as::<_, DirectiveChain>(
- r#"
- SELECT dc.* FROM directive_chains dc
- JOIN directives d ON d.current_chain_id = dc.id
- WHERE d.id = $1
- "#,
- )
- .bind(directive_id)
- .fetch_optional(pool)
- .await
-}
-
-/// Update chain status.
-pub async fn update_chain_status(
- pool: &PgPool,
- chain_id: Uuid,
- status: &str,
-) -> Result<DirectiveChain, sqlx::Error> {
- sqlx::query_as::<_, DirectiveChain>(
- r#"
- UPDATE directive_chains SET
- status = $2,
- started_at = CASE WHEN $2 = 'active' AND started_at IS NULL THEN NOW() ELSE started_at END,
- completed_at = CASE WHEN $2 IN ('completed', 'failed', 'superseded') THEN NOW() ELSE completed_at END,
- updated_at = NOW()
- WHERE id = $1
- RETURNING *
- "#,
- )
- .bind(chain_id)
- .bind(status)
- .fetch_one(pool)
- .await
-}
-
-/// Supersede a chain (mark as superseded and update directive).
-pub async fn supersede_chain(pool: &PgPool, chain_id: Uuid) -> Result<(), sqlx::Error> {
- sqlx::query(
- r#"
- UPDATE directive_chains SET status = 'superseded', completed_at = NOW(), updated_at = NOW()
- WHERE id = $1
- "#,
- )
- .bind(chain_id)
- .execute(pool)
- .await?;
- Ok(())
-}
-
-// =============================================================================
-// Chain Step Operations
-// =============================================================================
-
-/// Create a new step in a chain.
-pub async fn create_chain_step(
- pool: &PgPool,
- chain_id: Uuid,
- req: AddStepRequest,
-) -> Result<ChainStep, sqlx::Error> {
- let step_type = req.step_type.unwrap_or_else(|| "execute".to_string());
- let contract_type = req.contract_type.unwrap_or_else(|| "simple".to_string());
- let phases = req.phases.unwrap_or_default();
- let depends_on = req.depends_on.unwrap_or_default();
- let requirement_ids = req.requirement_ids.unwrap_or_default();
- let acceptance_criteria_ids = req.acceptance_criteria_ids.unwrap_or_default();
- let verifier_config = req.verifier_config.unwrap_or(serde_json::json!({}));
-
- // Get next order index
- let order_index = sqlx::query_scalar::<_, i32>(
- "SELECT COALESCE(MAX(order_index), 0) + 1 FROM chain_steps WHERE chain_id = $1"
- )
- .bind(chain_id)
- .fetch_one(pool)
- .await?;
-
- let step = sqlx::query_as::<_, ChainStep>(
- r#"
- INSERT INTO chain_steps (
- chain_id, name, description, step_type, contract_type,
- initial_phase, task_plan, phases, depends_on, parallel_group,
- requirement_ids, acceptance_criteria_ids, verifier_config,
- editor_x, editor_y, order_index
- )
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
- RETURNING *
- "#,
- )
- .bind(chain_id)
- .bind(&req.name)
- .bind(&req.description)
- .bind(&step_type)
- .bind(&contract_type)
- .bind(&req.initial_phase)
- .bind(&req.task_plan)
- .bind(&phases)
- .bind(&depends_on)
- .bind(&req.parallel_group)
- .bind(&requirement_ids)
- .bind(&acceptance_criteria_ids)
- .bind(&verifier_config)
- .bind(req.editor_x.unwrap_or(0.0))
- .bind(req.editor_y.unwrap_or(0.0))
- .bind(order_index)
- .fetch_one(pool)
- .await?;
-
- // Update chain total_steps count
- sqlx::query(
- "UPDATE directive_chains SET total_steps = total_steps + 1, updated_at = NOW() WHERE id = $1"
- )
- .bind(chain_id)
- .execute(pool)
- .await?;
-
- Ok(step)
-}
-
-/// Get a chain step by ID.
-pub async fn get_chain_step(pool: &PgPool, id: Uuid) -> Result<Option<ChainStep>, sqlx::Error> {
- sqlx::query_as::<_, ChainStep>(
- "SELECT * FROM chain_steps WHERE id = $1"
- )
- .bind(id)
- .fetch_optional(pool)
- .await
-}
-
-/// List all steps in a chain.
-pub async fn list_chain_steps(pool: &PgPool, chain_id: Uuid) -> Result<Vec<ChainStep>, sqlx::Error> {
- sqlx::query_as::<_, ChainStep>(
- "SELECT * FROM chain_steps WHERE chain_id = $1 ORDER BY order_index"
- )
- .bind(chain_id)
- .fetch_all(pool)
- .await
-}
-
-/// Update a chain step.
-pub async fn update_chain_step(
- pool: &PgPool,
- step_id: Uuid,
- req: UpdateStepRequest,
-) -> Result<ChainStep, sqlx::Error> {
- sqlx::query_as::<_, ChainStep>(
- r#"
- UPDATE chain_steps SET
- name = COALESCE($2, name),
- description = COALESCE($3, description),
- task_plan = COALESCE($4, task_plan),
- depends_on = COALESCE($5, depends_on),
- requirement_ids = COALESCE($6, requirement_ids),
- acceptance_criteria_ids = COALESCE($7, acceptance_criteria_ids),
- verifier_config = COALESCE($8, verifier_config),
- editor_x = COALESCE($9, editor_x),
- editor_y = COALESCE($10, editor_y)
- WHERE id = $1
- RETURNING *
- "#,
- )
- .bind(step_id)
- .bind(&req.name)
- .bind(&req.description)
- .bind(&req.task_plan)
- .bind(&req.depends_on)
- .bind(&req.requirement_ids)
- .bind(&req.acceptance_criteria_ids)
- .bind(&req.verifier_config)
- .bind(req.editor_x)
- .bind(req.editor_y)
- .fetch_one(pool)
- .await
-}
-
-/// Delete a chain step.
-pub async fn delete_chain_step(pool: &PgPool, step_id: Uuid) -> Result<bool, sqlx::Error> {
- // Get chain_id first for updating count
- let chain_id = sqlx::query_scalar::<_, Uuid>(
- "SELECT chain_id FROM chain_steps WHERE id = $1"
- )
- .bind(step_id)
- .fetch_optional(pool)
- .await?;
-
- let result = sqlx::query("DELETE FROM chain_steps WHERE id = $1")
- .bind(step_id)
- .execute(pool)
- .await?;
-
- // Update chain total_steps count
- if let Some(cid) = chain_id {
- sqlx::query(
- "UPDATE directive_chains SET total_steps = total_steps - 1, updated_at = NOW() WHERE id = $1"
- )
- .bind(cid)
- .execute(pool)
- .await?;
- }
-
- Ok(result.rows_affected() > 0)
-}
-
-/// Find steps that are ready to execute (all dependencies met, status=pending).
-pub async fn find_ready_steps(pool: &PgPool, chain_id: Uuid) -> Result<Vec<ChainStep>, sqlx::Error> {
- sqlx::query_as::<_, ChainStep>(
- r#"
- SELECT s.* FROM chain_steps s
- WHERE s.chain_id = $1
- AND s.status = 'pending'
- AND NOT EXISTS (
- SELECT 1 FROM chain_steps dep
- WHERE dep.id = ANY(s.depends_on)
- AND dep.status NOT IN ('passed', 'skipped')
- )
- ORDER BY s.order_index
- "#,
- )
- .bind(chain_id)
- .fetch_all(pool)
- .await
-}
-
-/// Update step status.
-pub async fn update_step_status(
- pool: &PgPool,
- step_id: Uuid,
- status: &str,
-) -> Result<ChainStep, sqlx::Error> {
- let step = sqlx::query_as::<_, ChainStep>(
- r#"
- UPDATE chain_steps SET
- status = $2,
- started_at = CASE WHEN $2 = 'running' AND started_at IS NULL THEN NOW() ELSE started_at END,
- completed_at = CASE WHEN $2 IN ('passed', 'failed', 'skipped') THEN NOW() ELSE completed_at END
- WHERE id = $1
- RETURNING *
- "#,
- )
- .bind(step_id)
- .bind(status)
- .fetch_one(pool)
- .await?;
-
- // Update chain completed_steps and failed_steps counts
- if status == "passed" || status == "skipped" {
- sqlx::query(
- "UPDATE directive_chains SET completed_steps = completed_steps + 1, updated_at = NOW() WHERE id = $1"
- )
- .bind(step.chain_id)
- .execute(pool)
- .await?;
- } else if status == "failed" {
- sqlx::query(
- "UPDATE directive_chains SET failed_steps = failed_steps + 1, updated_at = NOW() WHERE id = $1"
- )
- .bind(step.chain_id)
- .execute(pool)
- .await?;
- }
-
- Ok(step)
-}
-
-/// Link a step to a contract.
-pub async fn update_step_contract(
- pool: &PgPool,
- step_id: Uuid,
- contract_id: Uuid,
- supervisor_task_id: Option<Uuid>,
-) -> Result<ChainStep, sqlx::Error> {
- sqlx::query_as::<_, ChainStep>(
- r#"
- UPDATE chain_steps SET contract_id = $2, supervisor_task_id = $3
- WHERE id = $1
- RETURNING *
- "#,
- )
- .bind(step_id)
- .bind(contract_id)
- .bind(supervisor_task_id)
- .fetch_one(pool)
- .await
-}
-
-/// Update step confidence score and level.
-pub async fn update_step_confidence(
- pool: &PgPool,
- step_id: Uuid,
- score: f64,
- level: &str,
- evaluation_id: Uuid,
-) -> Result<ChainStep, sqlx::Error> {
- sqlx::query_as::<_, ChainStep>(
- r#"
- UPDATE chain_steps SET
- confidence_score = $2,
- confidence_level = $3,
- last_evaluation_id = $4,
- evaluation_count = evaluation_count + 1
- WHERE id = $1
- RETURNING *
- "#,
- )
- .bind(step_id)
- .bind(score)
- .bind(level)
- .bind(evaluation_id)
- .fetch_one(pool)
- .await
-}
-
-/// Increment step rework count.
-pub async fn increment_step_rework_count(pool: &PgPool, step_id: Uuid) -> Result<ChainStep, sqlx::Error> {
- sqlx::query_as::<_, ChainStep>(
- r#"
- UPDATE chain_steps SET rework_count = rework_count + 1, status = 'rework'
- WHERE id = $1
- RETURNING *
- "#,
- )
- .bind(step_id)
- .fetch_one(pool)
- .await
-}
-
-/// Get chain graph for visualization.
-pub async fn get_chain_graph(
- pool: &PgPool,
- chain_id: Uuid,
-) -> Result<DirectiveChainGraphResponse, sqlx::Error> {
- let chain = get_directive_chain(pool, chain_id).await?
- .ok_or_else(|| sqlx::Error::RowNotFound)?;
-
- let steps = list_chain_steps(pool, chain_id).await?;
-
- let nodes: Vec<DirectiveChainGraphNode> = steps.iter().map(|s| {
- DirectiveChainGraphNode {
- id: s.id,
- name: s.name.clone(),
- step_type: s.step_type.clone(),
- status: s.status.clone(),
- confidence_score: s.confidence_score,
- confidence_level: s.confidence_level.clone(),
- contract_id: s.contract_id,
- editor_x: s.editor_x,
- editor_y: s.editor_y,
- }
- }).collect();
-
- let mut edges = Vec::new();
- for step in &steps {
- for dep_id in &step.depends_on {
- edges.push(DirectiveChainGraphEdge {
- source: *dep_id,
- target: step.id,
- });
- }
- }
-
- Ok(DirectiveChainGraphResponse {
- chain_id,
- directive_id: chain.directive_id,
- nodes,
- edges,
- })
-}
-
-// =============================================================================
-// Directive Evaluation Operations
-// =============================================================================
-
-/// Create a directive evaluation.
-pub async fn create_directive_evaluation(
- pool: &PgPool,
- directive_id: Uuid,
- chain_id: Option<Uuid>,
- step_id: Option<Uuid>,
- contract_id: Option<Uuid>,
- evaluation_type: &str,
- evaluator: Option<&str>,
- passed: bool,
- overall_score: Option<f64>,
- confidence_level: Option<&str>,
- programmatic_results: serde_json::Value,
- llm_results: serde_json::Value,
- criteria_results: serde_json::Value,
- summary_feedback: &str,
- rework_instructions: Option<&str>,
-) -> Result<DirectiveEvaluation, sqlx::Error> {
- // Get next evaluation number for this step/directive
- let evaluation_number = if let Some(sid) = step_id {
- sqlx::query_scalar::<_, i32>(
- "SELECT COALESCE(MAX(evaluation_number), 0) + 1 FROM directive_evaluations WHERE step_id = $1"
- )
- .bind(sid)
- .fetch_one(pool)
- .await?
- } else {
- sqlx::query_scalar::<_, i32>(
- "SELECT COALESCE(MAX(evaluation_number), 0) + 1 FROM directive_evaluations WHERE directive_id = $1 AND step_id IS NULL"
- )
- .bind(directive_id)
- .fetch_one(pool)
- .await?
- };
-
- 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,
- programmatic_results, llm_results, criteria_results,
- summary_feedback, rework_instructions,
- completed_at
- )
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, NOW())
- RETURNING *
- "#,
- )
- .bind(directive_id)
- .bind(chain_id)
- .bind(step_id)
- .bind(contract_id)
- .bind(evaluation_type)
- .bind(evaluation_number)
- .bind(evaluator)
- .bind(passed)
- .bind(overall_score)
- .bind(confidence_level)
- .bind(&programmatic_results)
- .bind(&llm_results)
- .bind(&criteria_results)
- .bind(summary_feedback)
- .bind(rework_instructions)
- .fetch_one(pool)
- .await
-}
-
-/// List evaluations for a step.
-pub async fn list_step_evaluations(
- pool: &PgPool,
- step_id: Uuid,
-) -> Result<Vec<DirectiveEvaluation>, sqlx::Error> {
- sqlx::query_as::<_, DirectiveEvaluation>(
- "SELECT * FROM directive_evaluations WHERE step_id = $1 ORDER BY evaluation_number DESC"
- )
- .bind(step_id)
- .fetch_all(pool)
- .await
-}
-
-/// List evaluations for a directive.
-pub async fn list_directive_evaluations(
- pool: &PgPool,
- directive_id: Uuid,
- limit: Option<i64>,
-) -> Result<Vec<DirectiveEvaluation>, sqlx::Error> {
- let limit = limit.unwrap_or(100);
- sqlx::query_as::<_, DirectiveEvaluation>(
- "SELECT * FROM directive_evaluations WHERE directive_id = $1 ORDER BY created_at DESC LIMIT $2"
- )
- .bind(directive_id)
- .bind(limit)
- .fetch_all(pool)
- .await
-}
-
-// =============================================================================
-// Directive Event Operations
-// =============================================================================
-
-/// Emit a directive event.
-pub async fn emit_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
-}
-
-/// List directive events.
-pub async fn list_directive_events(
- pool: &PgPool,
- directive_id: Uuid,
- limit: Option<i64>,
-) -> Result<Vec<DirectiveEvent>, sqlx::Error> {
- let limit = limit.unwrap_or(100);
- sqlx::query_as::<_, DirectiveEvent>(
- "SELECT * FROM directive_events WHERE directive_id = $1 ORDER BY created_at DESC LIMIT $2"
- )
- .bind(directive_id)
- .bind(limit)
- .fetch_all(pool)
- .await
-}
-
-// =============================================================================
-// Directive Verifier Operations
-// =============================================================================
-
-/// Create a directive verifier.
-pub async fn create_directive_verifier(
- pool: &PgPool,
- directive_id: Uuid,
- name: &str,
- verifier_type: &str,
- command: Option<&str>,
- working_directory: Option<&str>,
- auto_detect: bool,
- detect_files: Vec<String>,
- weight: f64,
- required: bool,
-) -> Result<DirectiveVerifier, sqlx::Error> {
- sqlx::query_as::<_, DirectiveVerifier>(
- r#"
- INSERT INTO directive_verifiers (
- directive_id, name, verifier_type, command, working_directory,
- auto_detect, detect_files, weight, required
- )
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
- RETURNING *
- "#,
- )
- .bind(directive_id)
- .bind(name)
- .bind(verifier_type)
- .bind(command)
- .bind(working_directory)
- .bind(auto_detect)
- .bind(&detect_files)
- .bind(weight)
- .bind(required)
- .fetch_one(pool)
- .await
-}
-
-/// List verifiers for a directive.
-pub async fn list_directive_verifiers(
- pool: &PgPool,
- directive_id: Uuid,
-) -> Result<Vec<DirectiveVerifier>, sqlx::Error> {
- sqlx::query_as::<_, DirectiveVerifier>(
- "SELECT * FROM directive_verifiers WHERE directive_id = $1 ORDER BY name"
- )
- .bind(directive_id)
- .fetch_all(pool)
- .await
-}
-
-/// Update a directive verifier.
-pub async fn update_directive_verifier(
- pool: &PgPool,
- verifier_id: Uuid,
- enabled: Option<bool>,
- command: Option<&str>,
- weight: Option<f64>,
- required: Option<bool>,
-) -> Result<DirectiveVerifier, sqlx::Error> {
- sqlx::query_as::<_, DirectiveVerifier>(
- r#"
- UPDATE directive_verifiers SET
- enabled = COALESCE($2, enabled),
- command = COALESCE($3, command),
- weight = COALESCE($4, weight),
- required = COALESCE($5, required),
- updated_at = NOW()
- WHERE id = $1
- RETURNING *
- "#,
- )
- .bind(verifier_id)
- .bind(enabled)
- .bind(command)
- .bind(weight)
- .bind(required)
- .fetch_one(pool)
- .await
-}
-
-/// Update verifier last run result.
-pub async fn update_verifier_result(
- pool: &PgPool,
- verifier_id: Uuid,
- result: serde_json::Value,
-) -> Result<DirectiveVerifier, sqlx::Error> {
- sqlx::query_as::<_, DirectiveVerifier>(
- r#"
- UPDATE directive_verifiers SET last_run_at = NOW(), last_result = $2, updated_at = NOW()
- WHERE id = $1
- RETURNING *
- "#,
- )
- .bind(verifier_id)
- .bind(result)
- .fetch_one(pool)
- .await
-}
-
-// =============================================================================
-// Directive Approval Operations
-// =============================================================================
-
-/// Create an approval request.
-pub async fn create_approval_request(
- pool: &PgPool,
- directive_id: Uuid,
- step_id: Option<Uuid>,
- approval_type: &str,
- description: &str,
- context: Option<serde_json::Value>,
- urgency: &str,
- expires_at: Option<chrono::DateTime<Utc>>,
-) -> Result<DirectiveApproval, sqlx::Error> {
- sqlx::query_as::<_, DirectiveApproval>(
- r#"
- INSERT INTO directive_approvals (
- directive_id, step_id, approval_type, description, context, urgency, expires_at
- )
- VALUES ($1, $2, $3, $4, $5, $6, $7)
- RETURNING *
- "#,
- )
- .bind(directive_id)
- .bind(step_id)
- .bind(approval_type)
- .bind(description)
- .bind(context)
- .bind(urgency)
- .bind(expires_at)
- .fetch_one(pool)
- .await
-}
-
-/// Resolve an approval request.
-pub async fn resolve_approval(
- pool: &PgPool,
- approval_id: Uuid,
- status: &str,
- response: Option<&str>,
- responded_by: Uuid,
-) -> Result<DirectiveApproval, sqlx::Error> {
- sqlx::query_as::<_, DirectiveApproval>(
- r#"
- UPDATE directive_approvals SET
- status = $2,
- response = $3,
- responded_by = $4,
- responded_at = NOW()
- WHERE id = $1
- RETURNING *
- "#,
- )
- .bind(approval_id)
- .bind(status)
- .bind(response)
- .bind(responded_by)
- .fetch_one(pool)
- .await
-}
-
-/// List pending approvals for a directive.
-pub async fn list_pending_approvals(
- pool: &PgPool,
- directive_id: Uuid,
-) -> Result<Vec<DirectiveApproval>, sqlx::Error> {
- sqlx::query_as::<_, DirectiveApproval>(
- r#"
- SELECT * FROM directive_approvals
- WHERE directive_id = $1 AND status = 'pending'
- ORDER BY
- CASE urgency
- WHEN 'critical' THEN 1
- WHEN 'high' THEN 2
- WHEN 'normal' THEN 3
- ELSE 4
- END,
- created_at
- "#,
- )
- .bind(directive_id)
- .fetch_all(pool)
- .await
-}
-
-/// Get step by contract ID.
-pub async fn get_step_by_contract_id(
- pool: &PgPool,
- contract_id: Uuid,
-) -> Result<Option<ChainStep>, sqlx::Error> {
- sqlx::query_as::<_, ChainStep>(
- "SELECT * FROM chain_steps WHERE contract_id = $1"
- )
- .bind(contract_id)
- .fetch_optional(pool)
- .await
-}
-
-// =============================================================================
// Helper Functions
// =============================================================================