From 54c6d409e1d5667f4ab7f63a43e1459e68575c94 Mon Sep 17 00:00:00 2001 From: soryu Date: Tue, 20 Jan 2026 17:19:18 +0000 Subject: Clean contract lifecycle: Add supervisor complete command (#13) * feat: Add contract lifecycle management commands (complete and resume-contract) Add supervisor commands for properly managing contract lifecycle: - `makima supervisor complete` - Mark a contract as complete and stop the supervisor - `makima supervisor resume-contract` - Resume a completed contract (reactivate it) Also adds `api_key` field to TaskConfig for authenticated API calls. This consolidates the lifecycle management features from the contract-lifecycle-cleanup branch. Co-Authored-By: Claude Opus 4.5 * Fix: prevent supervisor auto-start for completed contracts When viewing a completed contract, the supervisor was auto-starting on component mount. This would resurrect completed contracts and cause them to continue running. Changes: - Add contract.status !== 'completed' check to the auto-start condition - Add contract.status to the useEffect dependency array Co-Authored-By: Claude Opus 4.5 * Task completion checkpoint --------- Co-authored-by: Claude Opus 4.5 --- makima/src/daemon/api/supervisor.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'makima/src/daemon/api') diff --git a/makima/src/daemon/api/supervisor.rs b/makima/src/daemon/api/supervisor.rs index 9614cfc..bd3aefd 100644 --- a/makima/src/daemon/api/supervisor.rs +++ b/makima/src/daemon/api/supervisor.rs @@ -249,6 +249,41 @@ impl ApiClient { .await } + /// Mark a contract as complete. + /// This will update contract status to 'completed', stop the supervisor, and clean up worktrees. + pub async fn supervisor_complete(&self, contract_id: Uuid) -> Result { + #[derive(Serialize)] + #[serde(rename_all = "camelCase")] + struct CompleteContractRequest { + status: String, + } + let req = CompleteContractRequest { + status: "completed".to_string(), + }; + self.put(&format!("/api/v1/contracts/{}", contract_id), &req) + .await + } + + /// Resume a completed contract (reactivate it). + /// + /// This updates the contract status from 'completed' back to 'active' + /// and optionally respawns the supervisor task. + pub async fn supervisor_resume_contract( + &self, + contract_id: Uuid, + ) -> Result { + #[derive(Serialize)] + #[serde(rename_all = "camelCase")] + struct ResumeContractRequest { + status: String, + } + let req = ResumeContractRequest { + status: "active".to_string(), + }; + self.put(&format!("/api/v1/contracts/{}", contract_id), &req) + .await + } + /// Delete a task. pub async fn delete_task(&self, task_id: Uuid) -> Result<(), ApiError> { self.delete(&format!("/api/v1/mesh/tasks/{}", task_id)).await -- cgit v1.2.3