diff --git a/plugins/omo/components/ultrawork/directive.md b/plugins/omo/components/ultrawork/directive.md index 0ac61fa..ad79b33 100644 --- a/plugins/omo/components/ultrawork/directive.md +++ b/plugins/omo/components/ultrawork/directive.md @@ -289,10 +289,16 @@ as inconclusive. Do not generate a plan before spawned research lanes that feed the plan have returned or been closed as inconclusive. Do not write the final answer, PR handoff, or completion summary while active child agents remain open. Use short `multi_agent_v1.wait_agent` cycles. -After two silent waits send `TASK STILL ACTIVE: return or -BLOCKED: `. After four silent or ack-only checks, close the lane as -inconclusive, record that it is not approval, and respawn smaller only -if the deliverable is still required. +A silent wait is not a child-state transition and must not by itself +trigger `TASK STILL ACTIVE`, `close_agent`, or a respawn. Send +`TASK STILL ACTIVE: return or BLOCKED: ` only when +the child has completed without the deliverable, responded ack-only +after a targeted followup, explicitly reported `BLOCKED:`, or is no +longer running. If no final status or completion signal exists, treat +the child as still active and continue independent root work. Close the +lane as inconclusive and respawn smaller only after one of those +non-running or non-delivering states is observed and the deliverable is +still required. # Verification gate (TRIGGERED, NOT OPTIONAL) diff --git a/plugins/omo/components/ultrawork/test/codex-hook.test.ts b/plugins/omo/components/ultrawork/test/codex-hook.test.ts index 5864a70..7602d0c 100644 --- a/plugins/omo/components/ultrawork/test/codex-hook.test.ts +++ b/plugins/omo/components/ultrawork/test/codex-hook.test.ts @@ -244,6 +244,25 @@ describe("codex ultrawork hook", () => { expect(directive).toMatch(/WORKING:/); }); + it("#given directive #when wait_agent is silent #then timeout counters never close running children", () => { + // given + const payload = { + hook_event_name: "UserPromptSubmit", + prompt: "ulw", + }; + + // when + const output = runUserPromptSubmitHook(payload); + const parsed = parseHookOutput(output); + + // then + const directive = parsed.hookSpecificOutput.additionalContext; + expect(directive).toMatch(/A silent wait is not a child-state transition/); + expect(directive).toMatch(/must not by itself\s+trigger `TASK STILL ACTIVE`/); + expect(directive).not.toMatch(/After two silent waits/); + expect(directive).not.toMatch(/After four silent/); + }); + it("#given directive #when inspected #then keeps impact-proportional sizing invariants", () => { // given const payload = { diff --git a/plugins/omo/components/ulw-loop/directive.md b/plugins/omo/components/ulw-loop/directive.md index 0ac61fa..ad79b33 100644 --- a/plugins/omo/components/ulw-loop/directive.md +++ b/plugins/omo/components/ulw-loop/directive.md @@ -289,10 +289,16 @@ as inconclusive. Do not generate a plan before spawned research lanes that feed the plan have returned or been closed as inconclusive. Do not write the final answer, PR handoff, or completion summary while active child agents remain open. Use short `multi_agent_v1.wait_agent` cycles. -After two silent waits send `TASK STILL ACTIVE: return or -BLOCKED: `. After four silent or ack-only checks, close the lane as -inconclusive, record that it is not approval, and respawn smaller only -if the deliverable is still required. +A silent wait is not a child-state transition and must not by itself +trigger `TASK STILL ACTIVE`, `close_agent`, or a respawn. Send +`TASK STILL ACTIVE: return or BLOCKED: ` only when +the child has completed without the deliverable, responded ack-only +after a targeted followup, explicitly reported `BLOCKED:`, or is no +longer running. If no final status or completion signal exists, treat +the child as still active and continue independent root work. Close the +lane as inconclusive and respawn smaller only after one of those +non-running or non-delivering states is observed and the deliverable is +still required. # Verification gate (TRIGGERED, NOT OPTIONAL)