Summary
Add a wave_wait_for_signal MCP tool that gives a wave-pattern Orchestrator (or Prime) a legitimate, sanctioned thing to call when it has dispatched work and is supposed to be idle waiting for state to change. Without one, anxious agents invent polling loops, hallucinate completions, or exit with incorrect failure verdicts.
Background: see pattern_sanctioned_fidget_tool.md in the cc-workflow memory store. The classic shape: an Orchestrator dispatches N parallel Flights, has nothing to call until at least one Flight drops a completion artifact, and instead of waiting cleanly, exits the loop body with a non-canonical line like "Sleep is still running. Let me wait for the notification." — the model's training favors doing something over sitting still. The mitigation is to give it a tool whose entire purpose is to sit still on its behalf.
Implementation Steps
- Add handler
wave_wait_for_signal in src/handlers/wave_wait_for_signal/. Args:
signal_path: string — filesystem path or pattern to watch (e.g. wavebus/<wave_id>/flights/*.done).
timeout_sec: number — max wait, default 1800.
min_count: number — minimum number of artifacts to satisfy the signal, default 1.
- Implementation: poll the signal path with a 5-second sleep loop; return when
count(matches) >= min_count or timeout. Return { matched: [...paths], elapsed_sec: N } on success; { timed_out: true, elapsed_sec: timeout_sec, partial_matches: [...] } on timeout.
- Register the tool in
src/index.ts. Add JSON schema. Add to docs/tools.md.
- Document the use-case in
docs/wave-pattern-orchestration.md: "When the Orchestrator has dispatched work and must wait for filesystem-bus artifacts to appear, call this tool — it's the sanctioned alternative to Bash(sleep) or polling the filesystem in a while loop. The tool's existence eliminates the agent-anxiety failure mode where idle loops are exited prematurely."
Test Procedures
Unit tests:
| Test Name |
Purpose |
File Location |
test_wave_wait_for_signal_matches_immediately |
when min_count files already exist, returns instantly |
tests/handlers/wave_wait_for_signal.test.ts |
test_wave_wait_for_signal_polls_until_match |
drops an artifact mid-wait, tool detects and returns |
same |
test_wave_wait_for_signal_times_out |
no artifacts ever appear, returns timed_out=true with elapsed≈timeout |
same |
test_wave_wait_for_signal_partial_matches |
timeout fires with N<min_count files, partial_matches array populated |
same |
Integration coverage:
tests/integration/orchestrator-wait-on-flights.test.ts — Orchestrator scenario where wave_wait_for_signal replaces an inline polling loop.
Acceptance Criteria
Dependencies
Metadata
Plan: N/A
Wave: N/A
Origin: cc-workflow campaign A debrief; pattern memory pattern_sanctioned_fidget_tool.md
Summary
Add a
wave_wait_for_signalMCP tool that gives a wave-pattern Orchestrator (or Prime) a legitimate, sanctioned thing to call when it has dispatched work and is supposed to be idle waiting for state to change. Without one, anxious agents invent polling loops, hallucinate completions, or exit with incorrect failure verdicts.Background: see
pattern_sanctioned_fidget_tool.mdin the cc-workflow memory store. The classic shape: an Orchestrator dispatches N parallel Flights, has nothing to call until at least one Flight drops a completion artifact, and instead of waiting cleanly, exits the loop body with a non-canonical line like"Sleep is still running. Let me wait for the notification."— the model's training favors doing something over sitting still. The mitigation is to give it a tool whose entire purpose is to sit still on its behalf.Implementation Steps
wave_wait_for_signalinsrc/handlers/wave_wait_for_signal/. Args:signal_path: string— filesystem path or pattern to watch (e.g.wavebus/<wave_id>/flights/*.done).timeout_sec: number— max wait, default 1800.min_count: number— minimum number of artifacts to satisfy the signal, default 1.count(matches) >= min_countor timeout. Return{ matched: [...paths], elapsed_sec: N }on success;{ timed_out: true, elapsed_sec: timeout_sec, partial_matches: [...] }on timeout.src/index.ts. Add JSON schema. Add todocs/tools.md.docs/wave-pattern-orchestration.md: "When the Orchestrator has dispatched work and must wait for filesystem-bus artifacts to appear, call this tool — it's the sanctioned alternative toBash(sleep)or polling the filesystem in awhileloop. The tool's existence eliminates the agent-anxiety failure mode where idle loops are exited prematurely."Test Procedures
Unit tests:
test_wave_wait_for_signal_matches_immediatelytests/handlers/wave_wait_for_signal.test.tstest_wave_wait_for_signal_polls_until_matchtest_wave_wait_for_signal_times_outtest_wave_wait_for_signal_partial_matchesIntegration coverage:
tests/integration/orchestrator-wait-on-flights.test.ts— Orchestrator scenario where wave_wait_for_signal replaces an inline polling loop.Acceptance Criteria
timeout_secexactly (±10s); partial_matches populated correctly on timeout.docs/wave-pattern-orchestration.mdincludes the canonical Orchestrator-wait-on-Flights example.Dependencies
Metadata
Plan: N/A
Wave: N/A
Origin: cc-workflow campaign A debrief; pattern memory
pattern_sanctioned_fidget_tool.md