diff options
| author | soryu <soryu@soryu.co> | 2026-02-05 23:42:48 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2026-02-05 23:42:48 +0000 |
| commit | 88a4f15ce1310f8ee8693835be14aa5280233f17 (patch) | |
| tree | 5c1a0417e02071d2198d13478ffa85533b19f891 /makima/src/server/handlers/contracts.rs | |
| parent | f1a50b80f3969d150bd1c31edde0aff05369157e (diff) | |
| download | soryu-88a4f15ce1310f8ee8693835be14aa5280233f17.tar.gz soryu-88a4f15ce1310f8ee8693835be14aa5280233f17.zip | |
Add directive-first chain system redesign
Redesigns the chain system with a directive-first architecture where
Directive is the top-level entity (the "why/what") and Chains are
generated execution plans (the "how") that can be dynamically modified.
Backend:
- Add database migration for directive system tables
- Add Directive, DirectiveChain, ChainStep, DirectiveEvent models
- Add DirectiveVerifier and DirectiveApproval models
- Add orchestration module with engine, planner, and verifier
- Add comprehensive API handlers for directives
- Add daemon CLI commands for directive management
- Add directive skill documentation
- Integrate contract completion with directive engine
- Add SSE endpoint for real-time directive events
Frontend:
- Add directives route with split-view layout
- Add 6-tab detail view (Overview, Chain, Events, Evaluations, Approvals, Verifiers)
- Add React Flow DAG visualization for chain steps
- Add SSE subscription hook for real-time event updates
- Add useDirectives and useDirectiveEventSubscription hooks
- Add directive types and API functions
Fixes:
- Fix test failures in ws/protocol, task_output, completion_gate, patch
- Fix word boundary matching in looks_like_task()
- Fix parse_last() to find actual last completion gate
- Fix create_export_patch when merge-base equals HEAD
- Clean up clippy warnings in new code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'makima/src/server/handlers/contracts.rs')
| -rw-r--r-- | makima/src/server/handlers/contracts.rs | 140 |
1 files changed, 76 insertions, 64 deletions
diff --git a/makima/src/server/handlers/contracts.rs b/makima/src/server/handlers/contracts.rs index 2b2fc26..8a6ce0f 100644 --- a/makima/src/server/handlers/contracts.rs +++ b/makima/src/server/handlers/contracts.rs @@ -575,78 +575,90 @@ pub async fn update_contract( }), ).await; - // If contract is part of a chain, check evaluation requirements - if let Some(chain_id) = contract.chain_id { - let pool_clone = pool.clone(); - let owner_id = auth.owner_id; - let contract_id = contract.id; - tokio::spawn(async move { - // Check if chain has evaluation enabled - let chain = match repository::get_chain_for_owner(&pool_clone, chain_id, owner_id).await { - Ok(Some(c)) => c, - Ok(None) => { - tracing::warn!(chain_id = %chain_id, "Chain not found for progression"); - return; - } - Err(e) => { - tracing::error!(chain_id = %chain_id, error = %e, "Failed to get chain"); - return; - } - }; - - // If evaluation is enabled, mark contract for evaluation - if chain.evaluation_enabled { - // Mark the chain_contract as pending evaluation - if let Ok(Some(chain_contract)) = repository::get_chain_contract_by_contract_id(&pool_clone, contract_id).await { - if let Err(e) = repository::update_chain_contract_evaluation_status( - &pool_clone, - chain_contract.id, - "pending_evaluation", - None, - None, - ).await { - tracing::error!( - chain_id = %chain_id, - contract_id = %contract_id, - error = %e, - "Failed to mark contract for evaluation" - ); - } else { - tracing::info!( - chain_id = %chain_id, - contract_id = %contract_id, - "Contract marked for evaluation - waiting for directive contract to evaluate" + // If contract is part of a directive chain step, update the step status + // and emit an event for the directive engine to process + let pool_for_step = pool.clone(); + let contract_id_for_step = contract.id; + tokio::spawn(async move { + // Look up the step by contract_id + match repository::get_step_by_contract_id(&pool_for_step, contract_id_for_step).await { + Ok(Some(step)) => { + // Get the chain to find the directive_id + let directive_id = match repository::get_directive_chain(&pool_for_step, step.chain_id).await { + Ok(Some(chain)) => chain.directive_id, + Ok(None) => { + tracing::warn!( + chain_id = %step.chain_id, + "Chain not found for step" ); + return; } - } - // Don't progress chain - directive contract will evaluate and progress - return; - } - - // If evaluation is disabled, progress chain directly - match repository::progress_chain(&pool_clone, chain_id, owner_id).await { - Ok(result) => { - if !result.contracts_created.is_empty() { - tracing::info!( - chain_id = %chain_id, - contracts_created = ?result.contracts_created, - "Chain progressed - created new contracts" + Err(e) => { + tracing::warn!( + chain_id = %step.chain_id, + error = %e, + "Failed to get chain for step" ); + return; } - if result.chain_completed { - tracing::info!(chain_id = %chain_id, "Chain completed"); - } - } - Err(e) => { - tracing::error!( - chain_id = %chain_id, + }; + + // Update step status to 'evaluating' + if let Err(e) = repository::update_step_status(&pool_for_step, step.id, "evaluating").await { + tracing::warn!( + step_id = %step.id, + contract_id = %contract_id_for_step, error = %e, - "Failed to progress chain after contract completion" + "Failed to update step status to evaluating" ); + } else { + tracing::info!( + step_id = %step.id, + contract_id = %contract_id_for_step, + chain_id = %step.chain_id, + directive_id = %directive_id, + "Contract completed - step transitioned to evaluating" + ); + + // Emit directive event for contract completion + if let Err(e) = repository::emit_directive_event( + &pool_for_step, + directive_id, + Some(step.chain_id), + Some(step.id), + "contract_completed", + "info", + Some(serde_json::json!({ + "contract_id": contract_id_for_step, + "step_id": step.id, + "step_name": step.name + })), + "system", + None, + ).await { + tracing::warn!( + step_id = %step.id, + error = %e, + "Failed to emit contract_completed directive event" + ); + } } } - }); - } + Ok(None) => { + tracing::debug!( + contract_id = %contract_id_for_step, + "Contract not linked to any directive chain step" + ); + } + Err(e) => { + tracing::warn!( + contract_id = %contract_id_for_step, + error = %e, + "Failed to look up step for completed contract" + ); + } + } + }); } // Get summary with counts |
