summaryrefslogtreecommitdiff
path: root/makima/src/server/handlers/contracts.rs
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-02-01 00:42:53 +0000
committersoryu <soryu@soryu.co>2026-02-01 00:42:53 +0000
commit96ad3af6051af69e2e8b34b35e8b40926bdd13a1 (patch)
tree2e2aedd39c66dedf7da301273306a0c77440ecf4 /makima/src/server/handlers/contracts.rs
parentbb14010db99b40792372bfcb4348cf4984f30b3f (diff)
downloadsoryu-96ad3af6051af69e2e8b34b35e8b40926bdd13a1.tar.gz
soryu-96ad3af6051af69e2e8b34b35e8b40926bdd13a1.zip
feat: Implement Phase 3 Tasks 3.3 and 3.4 - Supervisor State Persistence and Restoration
Task 3.3: Supervisor State Persistence - Add migration 20260201000001_enhanced_supervisor_state.sql with new columns: - state (supervisor state enum) - current_activity (description) - progress (0-100) - error_message (for failed states) - spawned_task_ids (tasks created by supervisor) - pending_questions (questions awaiting user response) - restoration_count, last_restored_at, restoration_source (restoration tracking) - Update SupervisorState model with new fields - Add PendingQuestion struct for tracking unanswered questions - Add SupervisorRestorationContext for returning restoration info - Add StateValidationResult and StateRecoveryAction for state validation State persistence functions in repository.rs: - update_supervisor_detailed_state() - Update state, activity, progress - add_supervisor_spawned_task() - Track spawned tasks - add_supervisor_pending_question() - Track pending questions - remove_supervisor_pending_question() - Clear answered questions - save_supervisor_state_full() - Full state save (UPSERT) - mark_supervisor_restored() - Increment restoration count - get_supervisors_with_pending_questions() - Find supervisors with pending questions - get_supervisor_state_for_restoration() - Load state for restoration - validate_spawned_tasks() - Validate task consistency - update_supervisor_phase() - Update on phase change - update_supervisor_heartbeat_state() - Lightweight heartbeat update State save points: - On task spawn (save_state_on_task_spawn) - On question asked (save_state_on_question_asked) - On question answered (clear_pending_question) - On phase change (save_state_on_phase_change) - On heartbeat (update_supervisor_heartbeat_state) Task 3.4: Supervisor Restoration Protocol - Add restoration detection when supervisor starts with existing state - Implement validate_supervisor_state() for state consistency checks - Implement restore_supervisor() with validation and context generation - Add redeliver_pending_questions() for re-delivering questions after crash - Add generate_restoration_context_message() for Claude context injection - Update resume_supervisor endpoint to return RestorationInfo - Re-deliver pending questions when supervisor resumes Restoration flow: 1. Daemon restarts or task reassigned 2. Load supervisor state from supervisor_states 3. If NOT FOUND: Start fresh, log warning 4. If FOUND: Validate state consistency 5. If INVALID: Start from last checkpoint 6. If VALID: Restore conversation history 7. Check for pending questions - re-deliver to user 8. Check for waiting tasks - resume waiting state 9. Send restoration context to Claude 10. Resume execution from last state 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.rs16
1 files changed, 16 insertions, 0 deletions
diff --git a/makima/src/server/handlers/contracts.rs b/makima/src/server/handlers/contracts.rs
index b15667d..5a87616 100644
--- a/makima/src/server/handlers/contracts.rs
+++ b/makima/src/server/handlers/contracts.rs
@@ -1461,6 +1461,22 @@ pub async fn change_phase(
.await
{
Ok(PhaseChangeResult::Success(updated_contract)) => {
+ // Save supervisor state on phase change (Task 3.3)
+ // This is a key save point for restoration
+ let new_phase_for_state = updated_contract.phase.clone();
+ let contract_id_for_state = updated_contract.id;
+ let pool_for_state = pool.clone();
+ tokio::spawn(async move {
+ if let Err(e) = repository::update_supervisor_phase(&pool_for_state, contract_id_for_state, &new_phase_for_state).await {
+ tracing::warn!(
+ contract_id = %contract_id_for_state,
+ new_phase = %new_phase_for_state,
+ error = %e,
+ "Failed to save supervisor state on phase change"
+ );
+ }
+ });
+
// Notify supervisor of phase change
if let Some(supervisor_task_id) = updated_contract.supervisor_task_id {
if let Ok(Some(supervisor)) = repository::get_task_for_owner(pool, supervisor_task_id, auth.owner_id).await {