From f13352a3a5860477957d16b7ce00169d385f56da Mon Sep 17 00:00:00 2001 From: soryu Date: Wed, 3 Jun 2026 19:38:27 +0100 Subject: fix: directive step dispatch — drop dead column refs (#137) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #136 dropped directive_steps.contract_id/contract_type and tasks.contract_id, but several SQL queries still SELECTed or filtered on them. The directive reconciler tripped on the first failing query (get_ready_steps_for_dispatch), so no step ever transitioned to a running task — symptoms were "Task has no assigned daemon" when opening any task view, because no orchestrator-spawned tasks ever got a daemon_id assigned. Fixed queries: - get_ready_steps_for_dispatch: drop SELECT ds.contract_type, drop WHERE ds.contract_id IS NULL filter (vacuously true now). - get_running_steps_with_tasks: drop WHERE ds.contract_id IS NULL. - create_directive_step: drop contract_type column from INSERT. - cleanup_stale_anonymous_tasks: rewrite "anonymous" filter (contract_id IS NULL) as directive_step_id IS NULL — that was the intent: terminal tasks not part of a directive flow. Also removed StepForDispatch.contract_type, CreateDirectiveStepRequest.contract_type, and the now-orphaned warn! in phase_execution. Co-authored-by: Claude Opus 4.7 (1M context) --- makima/src/db/models.rs | 4 ---- makima/src/db/repository.rs | 17 ++++------------- makima/src/orchestration/directive.rs | 14 -------------- 3 files changed, 4 insertions(+), 31 deletions(-) diff --git a/makima/src/db/models.rs b/makima/src/db/models.rs index bfb8bf3..b874df8 100644 --- a/makima/src/db/models.rs +++ b/makima/src/db/models.rs @@ -1999,10 +1999,6 @@ pub struct CreateDirectiveStepRequest { /// Optional order ID to auto-link this step to an order. #[serde(default)] pub order_id: Option, - /// Optional: create a contract for this step instead of a standalone task. - /// Valid values: "simple", "specification", "execute" - #[serde(default)] - pub contract_type: Option, /// Optional: attach this step to a specific directive document. When /// omitted, the repository falls back to the directive's most-recently /// updated active document (if any). diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs index d453f99..b97943f 100644 --- a/makima/src/db/repository.rs +++ b/makima/src/db/repository.rs @@ -2642,9 +2642,7 @@ pub async fn get_task_conversation( // Anonymous Task Cleanup Functions // ============================================================================= -/// Delete stale anonymous tasks (tasks with contract_id = NULL) that: -/// - Are in a terminal state (done, failed, merged) -/// - Are older than the specified number of days +/// Delete stale terminal tasks not linked to a directive step. /// /// Returns the number of deleted tasks. pub async fn cleanup_stale_anonymous_tasks( @@ -2654,7 +2652,7 @@ pub async fn cleanup_stale_anonymous_tasks( let result = sqlx::query( r#" DELETE FROM tasks - WHERE contract_id IS NULL + WHERE directive_step_id IS NULL AND status IN ('done', 'failed', 'merged') AND created_at < NOW() - INTERVAL '1 day' * $1 "#, @@ -3324,7 +3322,6 @@ pub async fn create_directive_step( ) -> Result { let generation = req.generation.unwrap_or(1); let order_id = req.order_id; - let contract_type = req.contract_type.clone(); // Resolve the document this step belongs to. If the caller supplied one, // honour it; otherwise pick the directive's most recently-updated @@ -3342,9 +3339,9 @@ pub async fn create_directive_step( r#" INSERT INTO directive_steps ( directive_id, name, description, task_plan, depends_on, - order_index, generation, contract_type, directive_document_id + order_index, generation, directive_document_id ) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING * "#, ) @@ -3355,7 +3352,6 @@ pub async fn create_directive_step( .bind(&req.depends_on) .bind(req.order_index) .bind(generation) - .bind(&contract_type) .bind(&directive_document_id) .fetch_one(pool) .await?; @@ -4568,8 +4564,6 @@ pub struct StepForDispatch { pub order_index: i32, pub generation: i32, pub depends_on: Vec, - /// Optional contract type — when set, orchestrator creates a contract instead of a task. - pub contract_type: Option, // Directive fields pub owner_id: Uuid, pub directive_title: String, @@ -4596,7 +4590,6 @@ pub async fn get_ready_steps_for_dispatch( ds.order_index, ds.generation, ds.depends_on, - ds.contract_type, d.owner_id, d.title AS directive_title, d.repository_url, @@ -4607,7 +4600,6 @@ pub async fn get_ready_steps_for_dispatch( JOIN directives d ON d.id = ds.directive_id WHERE ds.status = 'ready' AND ds.task_id IS NULL - AND ds.contract_id IS NULL AND d.status = 'active' ORDER BY ds.order_index "#, @@ -4679,7 +4671,6 @@ pub async fn get_running_steps_with_tasks( JOIN tasks t ON t.id = ds.task_id WHERE ds.status = 'running' AND ds.task_id IS NOT NULL - AND ds.contract_id IS NULL "#, ) .fetch_all(pool) diff --git a/makima/src/orchestration/directive.rs b/makima/src/orchestration/directive.rs index 3d00a8f..ada6b4b 100644 --- a/makima/src/orchestration/directive.rs +++ b/makima/src/orchestration/directive.rs @@ -121,20 +121,6 @@ impl DirectiveOrchestrator { let steps = repository::get_ready_steps_for_dispatch(&self.pool).await?; for step in steps { - // contract_type used to spawn a heavyweight contract+supervisor - // for a step. The contracts subsystem has been removed (Phase 5); - // we now treat any contract-backed step as a plain standalone - // task. The column itself is left in place for one more release - // so old data still reads cleanly, but it has no effect. - if step.contract_type.is_some() { - tracing::warn!( - step_id = %step.step_id, - directive_id = %step.directive_id, - contract_type = ?step.contract_type, - "Step has legacy contract_type; falling back to standalone task spawn" - ); - } - tracing::info!( step_id = %step.step_id, directive_id = %step.directive_id, -- cgit v1.2.3