wait-discipline: no dead-man coverage — arm a watchdog per teammate, verify DONE as a claim #58

Closed
opened 2026-08-24 15:23:07 +00:00 by jbr870 · 1 comment
Owner

Finding

wait-discipline.md tells the orchestrating lead to wait for teammate completion/idle
notifications instead of polling — but provides no dead-man coverage for the case where the
notification never arrives (teammate dies silently, notification lost, or the registry/UI
misrepresents state). The observed cost is an idle lead and an operator who returns after 30
minutes to find nothing happened.

Evidence (recurrence)

  • wait-discipline.md itself already records: "~an hour lost to unsent subagent reports and two
    dead stalls to improvised polling" (pre-existing).
  • Operator reports the "agent looks stopped, is it?" confusion is happening more often lately.
  • 2026-08-24, issue #57 /dev:develop run, three fresh specimens:
    1. The operator's terminal showed the spawned Test Writer as stopped while it was actively
      working — background in-process teammates are invisible to the task registry the UI reads
      (TaskOutput cannot resolve them by name or name@team), and the idle main loop reads as
      "nothing running". Ground truth (teammate transcript mtime, files landing on disk) showed it
      healthy.
    2. The lead's first improvised watchdog produced a FALSE completion: it grepped the raw teammate
      transcript for the completion promise, which matched the prompt echo (the spawn prompt quotes
      "Output WU_N_COMPLETE" and is the transcript's first entry). It fired ~30s
      after arming and exited — which also silently removed the stall coverage it existed to provide.
    3. Verification-before-acting caught it: no commits, suites still red → the DONE was a claim, not
      a fact.

Proposed amendment (for /meta-amend to scope)

Amend _shared/procedures/wait-discipline.md (and, if the amender judges it load-bearing, the
"Waiting on the team" pointer in /dev:develop) with the watchdog discipline as principles,
harness mechanics as illustrative example only:

  1. Arm an independent watchdog when spawning any teammate expected to run more than a couple of
    minutes.
    It must cover BOTH terminal states: the real completion signal, and a stall alarm
    (no observable progress for N minutes). Silence is never success.
  2. Choose watchdog signals the teammate cannot emit by accident. Never grep for a marker you
    quoted in the teammate's own briefing (prompt echo); prefer out-of-band ground truth (the WU's
    commit marker in git log, deliverable files appearing) or role-filtered transcript output.
  3. Treat any DONE/COMPLETE signal as a claim, not a fact — verify the deliverable (commits
    landed, suites green) before recording the outcome or advancing the wave.
  4. Liveness ground truth is observable progress (teammate transcript growth / files / commits),
    not the task registry or the terminal display — both can misrepresent background teammates in
    either direction.
  5. Tell the operator which teammates are running when handing a turn back, so an idle main loop
    is not mistaken for a dead run.

Portability note for the amender: any watchdog glue the skill emits falls under the CLAUDE.md
portability baseline (POSIX, no bashisms); the harness watch mechanism itself (e.g. the Monitor
tool, transcript paths under the session directory) is harness-specific and must stay an
illustrative example, not a required value.

Lane

Meta lane (/meta-amend) — evidence-driven amendment of existing skill text, no new capability.

## Finding `wait-discipline.md` tells the orchestrating lead to wait for teammate completion/idle notifications instead of polling — but provides no dead-man coverage for the case where the notification never arrives (teammate dies silently, notification lost, or the registry/UI misrepresents state). The observed cost is an idle lead and an operator who returns after 30 minutes to find nothing happened. ## Evidence (recurrence) - `wait-discipline.md` itself already records: "~an hour lost to unsent subagent reports and two dead stalls to improvised polling" (pre-existing). - Operator reports the "agent looks stopped, is it?" confusion is happening more often lately. - 2026-08-24, issue #57 `/dev:develop` run, three fresh specimens: 1. The operator's terminal showed the spawned Test Writer as *stopped* while it was actively working — background in-process teammates are invisible to the task registry the UI reads (`TaskOutput` cannot resolve them by name or `name@team`), and the idle main loop reads as "nothing running". Ground truth (teammate transcript mtime, files landing on disk) showed it healthy. 2. The lead's first improvised watchdog produced a FALSE completion: it grepped the raw teammate transcript for the completion promise, which matched the *prompt echo* (the spawn prompt quotes "Output <promise>WU_N_COMPLETE</promise>" and is the transcript's first entry). It fired ~30s after arming and exited — which also silently removed the stall coverage it existed to provide. 3. Verification-before-acting caught it: no commits, suites still red → the DONE was a claim, not a fact. ## Proposed amendment (for /meta-amend to scope) Amend `_shared/procedures/wait-discipline.md` (and, if the amender judges it load-bearing, the "Waiting on the team" pointer in `/dev:develop`) with the watchdog discipline as **principles**, harness mechanics as illustrative example only: 1. **Arm an independent watchdog when spawning any teammate expected to run more than a couple of minutes.** It must cover BOTH terminal states: the real completion signal, and a stall alarm (no observable progress for N minutes). Silence is never success. 2. **Choose watchdog signals the teammate cannot emit by accident.** Never grep for a marker you quoted in the teammate's own briefing (prompt echo); prefer out-of-band ground truth (the WU's commit marker in `git log`, deliverable files appearing) or role-filtered transcript output. 3. **Treat any DONE/COMPLETE signal as a claim, not a fact** — verify the deliverable (commits landed, suites green) before recording the outcome or advancing the wave. 4. **Liveness ground truth is observable progress** (teammate transcript growth / files / commits), not the task registry or the terminal display — both can misrepresent background teammates in either direction. 5. **Tell the operator which teammates are running when handing a turn back**, so an idle main loop is not mistaken for a dead run. Portability note for the amender: any watchdog *glue the skill emits* falls under the CLAUDE.md portability baseline (POSIX, no bashisms); the harness watch mechanism itself (e.g. the Monitor tool, transcript paths under the session directory) is harness-specific and must stay an illustrative example, not a required value. ## Lane Meta lane (`/meta-amend`) — evidence-driven amendment of existing skill text, no new capability.
Author
Owner

/meta-amend outcome — amended

Commit 3b82a77 on main.

Verified at HEAD (cda2366)

The gap held, and it is genuinely distinct from the two neighbouring rules already in the file:

  • §1 says wait for the signal and do nothing meanwhile — correct, and it had no floor. It assumes the signal eventually arrives.
  • The liveness caveat (#154) covers lag: an agent that has sent nothing is unobserved, not dead. It tells you not to conclude "dead" — it does not tell you to notice.
  • §1a (#44, 8440c90) covers an idle signal that arrives without a report.

None of the three covers the notification that never arrives at all. That is this issue.

The amendment

New §1b — "Arm a watchdog when you spawn — silence is never success", principles first, harness mechanics as illustration only per the issue's portability note:

  1. Both terminal states. The completion signal and a stall alarm on no observable progress for N minutes. "A watchdog that can only fire on success is not a watchdog; it is a second way of being told the good news."
  2. A signal the teammate cannot emit by accident. Never watch for a marker quoted in its own briefing — the brief is the transcript's first entry, so the watchdog matches the prompt echo. The text states why this is worse than having no watchdog at all: firing disarmed the stall coverage it existed to provide, and reported a completion that had not happened. Prefer out-of-band ground truth (commit marker in git log, the deliverable appearing) or role-filtered output.
  3. A DONE is a claim; the deliverable is the fact. Verify before recording an outcome or advancing the wave — reusing §1a's tree read rather than restating it.
  4. Liveness is observable progress, not the display. Background teammates can be invisible to the registry the terminal reads, so it misreports in both directions — a working teammate shown stopped, an idle main loop read as "nothing running". The display is a hint, never evidence.
  5. Name the live teammates when handing a turn back.

Closing note keeps the harness out of the rule: "The mechanism is the harness's; the discipline is yours" — a monitor/watch tool, a backgrounded command, a growing file are implementation details that vary by harness and session; none is a required value. Emitted watchdog glue is skill-authored shell and obeys the portability baseline.

develop/SKILL.md §3.2 gains the two points that bite hardest there, judged load-bearing per the issue's invitation: never watch for WU_N_COMPLETE in a raw transcript (the spawn prompt directly above it quotes that promise — the trap is built into this skill's own text), and wu-status.md is the roster to read back to the operator, since a dispatched phase-runner has no ListAgents.

Not amended: the QA playbook. §2 already routes waiting to this file as canonical, and it gained a driver rule in the #44 pass; a third pointer would be bloat, not coverage.

Gate

scripts/lint-conventions.sh — clean.

Desk-check against the originating scenario (#57 /dev:develop, 2026-08-24)

Specimen Covered by
Terminal showed the spawned Test Writer as stopped while it was actively working 4 — the registry misreports background teammates; ground truth is transcript growth / files landing
Watchdog grepped the raw transcript for the completion promise, matched the prompt echo, fired ~30s after arming and exited — silently removing the stall coverage 2, which names this exact failure and its second-order cost (firing disarms). develop/SKILL.md names WU_N_COMPLETE specifically, because that skill's own prompt is where the echo comes from
The false DONE was caught only by verifying: no commits, suites still red 3
Operator returned after 30 minutes to an idle lead 1 (the floor) and 5 (say who is running)

All four specimens land on a numbered point, and the one that produced a false green — the prompt echo — is the one written up in the most detail, because a watchdog that lies is worse than none.

What validates it next

The next multi-teammate /dev:develop run. The honest bar is narrow: a stall alarm that actually fires on a teammate that stops progressing. Point 2 is the one to watch — the tempting implementation is always the cheapest grep, and the cheapest grep is the prompt echo.

## /meta-amend outcome — amended Commit `3b82a77` on `main`. ### Verified at HEAD (`cda2366`) The gap held, and it is genuinely distinct from the two neighbouring rules already in the file: - **§1** says wait for the signal and do nothing meanwhile — correct, and it had **no floor**. It assumes the signal eventually arrives. - **The liveness caveat (#154)** covers *lag*: an agent that has sent nothing is unobserved, not dead. It tells you not to conclude "dead" — it does not tell you to notice. - **§1a (#44, `8440c90`)** covers an idle signal that arrives without a report. None of the three covers the notification that **never arrives at all**. That is this issue. ### The amendment New **§1b — "Arm a watchdog when you spawn — silence is never success"**, principles first, harness mechanics as illustration only per the issue's portability note: 1. **Both terminal states.** The completion signal *and* a stall alarm on no observable progress for N minutes. *"A watchdog that can only fire on success is not a watchdog; it is a second way of being told the good news."* 2. **A signal the teammate cannot emit by accident.** Never watch for a marker quoted in its own briefing — the brief is the transcript's first entry, so the watchdog matches the **prompt echo**. The text states why this is worse than having no watchdog at all: firing *disarmed* the stall coverage it existed to provide, and reported a completion that had not happened. Prefer out-of-band ground truth (commit marker in `git log`, the deliverable appearing) or role-filtered output. 3. **A DONE is a claim; the deliverable is the fact.** Verify before recording an outcome or advancing the wave — reusing §1a's tree read rather than restating it. 4. **Liveness is observable progress, not the display.** Background teammates can be invisible to the registry the terminal reads, so it misreports in **both** directions — a working teammate shown stopped, an idle main loop read as "nothing running". The display is a hint, never evidence. 5. **Name the live teammates when handing a turn back.** Closing note keeps the harness out of the rule: *"The mechanism is the harness's; the discipline is yours"* — a monitor/watch tool, a backgrounded command, a growing file are implementation details that vary by harness and session; none is a required value. Emitted watchdog glue is skill-authored shell and obeys the portability baseline. **`develop/SKILL.md` §3.2** gains the two points that bite hardest there, judged load-bearing per the issue's invitation: never watch for `WU_N_COMPLETE` in a raw transcript (**the spawn prompt directly above it quotes that promise** — the trap is built into this skill's own text), and `wu-status.md` is the roster to read back to the operator, since a dispatched phase-runner has no `ListAgents`. **Not amended: the QA playbook.** §2 already routes waiting to this file as canonical, and it gained a driver rule in the #44 pass; a third pointer would be bloat, not coverage. ### Gate `scripts/lint-conventions.sh` — clean. ### Desk-check against the originating scenario (#57 `/dev:develop`, 2026-08-24) | Specimen | Covered by | |---|---| | Terminal showed the spawned Test Writer as *stopped* while it was actively working | **4** — the registry misreports background teammates; ground truth is transcript growth / files landing | | Watchdog grepped the raw transcript for the completion promise, matched the **prompt echo**, fired ~30s after arming and exited — silently removing the stall coverage | **2**, which names this exact failure *and* its second-order cost (firing disarms). `develop/SKILL.md` names `WU_N_COMPLETE` specifically, because that skill's own prompt is where the echo comes from | | The false DONE was caught only by verifying: no commits, suites still red | **3** | | Operator returned after 30 minutes to an idle lead | **1** (the floor) and **5** (say who is running) | All four specimens land on a numbered point, and the one that produced a *false green* — the prompt echo — is the one written up in the most detail, because a watchdog that lies is worse than none. ### What validates it next The next multi-teammate `/dev:develop` run. The honest bar is narrow: a stall alarm that actually fires on a teammate that stops progressing. Point 2 is the one to watch — the tempting implementation is always the cheapest grep, and the cheapest grep is the prompt echo.
Sign in to join this conversation.
No description provided.