summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-01-18 17:44:18 +0000
committerGitHub <noreply@github.com>2026-01-18 17:44:18 +0000
commit219bca168508e1ea5e91e8a9ce98338afeddfbd2 (patch)
treea50e801ff8801dffc2c76d5a067dd019f360a34e
parent5b1f886db9b92722c1b4f1524f09456febc824e0 (diff)
downloadsoryu-219bca168508e1ea5e91e8a9ce98338afeddfbd2.tar.gz
soryu-219bca168508e1ea5e91e8a9ce98338afeddfbd2.zip
Add phaseguard flag for supervisor questions to wait indefinitely (#4)
* 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 <noreply@anthropic.com> * Task completion checkpoint --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
-rw-r--r--makima/src/bin/makima.rs2
-rw-r--r--makima/src/daemon/api/supervisor.rs4
-rw-r--r--makima/src/daemon/cli/supervisor.rs4
-rw-r--r--makima/src/server/handlers/mesh_supervisor.rs7
4 files changed, 14 insertions, 3 deletions
diff --git a/makima/src/bin/makima.rs b/makima/src/bin/makima.rs
index 37dc81a..45dd5b7 100644
--- a/makima/src/bin/makima.rs
+++ b/makima/src/bin/makima.rs
@@ -350,7 +350,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<String>,
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<String>,
context: Option<String>,
timeout_seconds: i32,
+ phaseguard: bool,
) -> Result<JsonValue, ApiError> {
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 29eef81..8c7ecb5 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 {
@@ -1578,8 +1581,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);