From ea71a1d55a0036b0452e8b2b4f95022b19274343 Mon Sep 17 00:00:00 2001 From: soryu Date: Sun, 18 Jan 2026 17:19:10 +0000 Subject: Add phaseguard flag to supervisor ask command When phaseguard is enabled (--phaseguard flag), the supervisor's ask command will block indefinitely waiting for user response instead of timing out after the default 1 hour. This ensures that phase transitions requiring user confirmation cannot proceed without explicit approval. Changes: - Add phaseguard field to AskQuestionRequest in server handler - Add phaseguard field to AskQuestionRequest in API client - Add --phaseguard CLI flag to AskArgs - Update supervisor_ask() to accept phaseguard parameter - Modify ask_question handler to skip timeout check when phaseguard=true Co-Authored-By: Claude Opus 4.5 --- makima/src/bin/makima.rs | 2 +- makima/src/daemon/api/supervisor.rs | 4 ++++ makima/src/daemon/cli/supervisor.rs | 4 ++++ makima/src/server/handlers/mesh_supervisor.rs | 7 +++++-- 4 files changed, 14 insertions(+), 3 deletions(-) (limited to 'makima/src') diff --git a/makima/src/bin/makima.rs b/makima/src/bin/makima.rs index 47e627b..df85c3f 100644 --- a/makima/src/bin/makima.rs +++ b/makima/src/bin/makima.rs @@ -349,7 +349,7 @@ async fn run_supervisor( .map(|c| c.split(',').map(|s| s.trim().to_string()).collect()) .unwrap_or_default(); let result = client - .supervisor_ask(&args.question, choices, args.context, args.timeout) + .supervisor_ask(&args.question, choices, args.context, args.timeout, args.phaseguard) .await?; println!("{}", serde_json::to_string(&result.0)?); } diff --git a/makima/src/daemon/api/supervisor.rs b/makima/src/daemon/api/supervisor.rs index 8b3d480..adeda22 100644 --- a/makima/src/daemon/api/supervisor.rs +++ b/makima/src/daemon/api/supervisor.rs @@ -71,6 +71,8 @@ pub struct AskQuestionRequest { #[serde(skip_serializing_if = "Option::is_none")] pub context: Option, pub timeout_seconds: i32, + /// When true, the request will block indefinitely until user responds (no timeout) + pub phaseguard: bool, } // Generic response type for JSON output @@ -202,12 +204,14 @@ impl ApiClient { choices: Vec, context: Option, timeout_seconds: i32, + phaseguard: bool, ) -> Result { let req = AskQuestionRequest { question: question.to_string(), choices, context, timeout_seconds, + phaseguard, }; self.post("/api/v1/mesh/supervisor/questions", &req).await } diff --git a/makima/src/daemon/cli/supervisor.rs b/makima/src/daemon/cli/supervisor.rs index db30cf1..0e2da32 100644 --- a/makima/src/daemon/cli/supervisor.rs +++ b/makima/src/daemon/cli/supervisor.rs @@ -180,6 +180,10 @@ pub struct AskArgs { /// Timeout in seconds (default: 3600 = 1 hour) #[arg(long, default_value = "3600")] pub timeout: i32, + + /// Block indefinitely until user responds (no timeout) + #[arg(long, default_value = "false")] + pub phaseguard: bool, } /// Arguments for status command (get contract status including phase). diff --git a/makima/src/server/handlers/mesh_supervisor.rs b/makima/src/server/handlers/mesh_supervisor.rs index 1014fdc..d1f3129 100644 --- a/makima/src/server/handlers/mesh_supervisor.rs +++ b/makima/src/server/handlers/mesh_supervisor.rs @@ -70,6 +70,9 @@ pub struct AskQuestionRequest { /// How long to wait for a response (seconds) #[serde(default = "default_question_timeout")] pub timeout_seconds: i32, + /// When true, the request will block indefinitely until user responds (no timeout) + #[serde(default)] + pub phaseguard: bool, } fn default_question_timeout() -> i32 { @@ -1556,8 +1559,8 @@ pub async fn ask_question( ).into_response(); } - // Check timeout - if start.elapsed() >= timeout_duration { + // Check timeout (skip timeout if phaseguard is enabled - wait indefinitely) + if !request.phaseguard && start.elapsed() >= timeout_duration { // Remove the pending question on timeout state.remove_pending_question(question_id); -- cgit v1.2.3