[Bug] new-work's decision-page fallback is gated on exit 2, so a harness that cannot hold a blocking `--wait` has no route but to strand the tab

Author: tehzunm-ctrlCreated Sep 14, 2026Updated Sep 16, 2026
Labelsbugneeds triage

What happened?

In skill/reference/new-work.md, the direction round must be presented on the page the skill serves itself, and the answer collected by blocking on serve-question --wait --key <key>, repeating while it exits 3. The rule then reads:

Never --start a second server or fall back to chat here: either strands the open tab on a hand that never arrives. [...] Never predict the fallback: run the script, and only exit code 2 from starting it routes the decision to the structured tool; that exit is the fallback, never an error to retry.

Exit 2 detects the server failed to start. It cannot detect the server will start fine and the caller cannot safely await it — which is a property of the calling harness's process model, not of the script.

I hit the second case. The harness moves any command running past 120s into the background, and twice in the same session a backgrounded child was orphaned when its parent was reaped and left sleeping on a pipe with no reader. A blocking --wait is exactly that shape. So the mandated path had a live risk of producing the precise failure the rule exists to prevent — a user in front of an open tab whose answer nobody is waiting for — while the substitution the rule forbids had no such risk.

The skill already recognises the capability one sentence earlier:

A harness that can leave a shell blocked in the background may run the script without --start and let it auto-open and block.

So the capability is named. It just is not wired to the fallback, which stays gated on one enumerated failure code.

Steps to reproduce

  1. Run /impeccable new work from a harness that cannot hold a long-lived blocking foreground process (one that backgrounds a command past a timeout, or reaps the parent of a backgrounded child).
  2. Reach the direction round. serve-question --start succeeds and prints the URL and key — exit 0, so the exit-2 fallback is unreachable by construction.
  3. Block on --wait --key <key>. The wait is backgrounded and then orphaned; no reader remains on the pipe.
  4. The user's tab is live and answerable, and nothing will ever collect the answer.

Expected behavior

The fallback should be selected on the capability the primary channel requires, not on one way that channel can fail: permit the structured question tool whenever the caller cannot hold a blocking wait for the answer — no long-lived foreground process available, or a harness that backgrounds or reaps one — alongside the existing exit-2 case. Require the substitution be disclosed in the first reply, which the autonomy directive already asks for.

The cost of allowing this is bounded and the skill already says so: the two channels "differ only in richness". In practice the only irreplaceable feature of the served page is the live re-roll loop over a held connection (--update on one open key) — which is exactly the thing a harness that cannot hold a blocking wait could never provide anyway. Substituting there loses nothing that was available.

Provider & environment

  • Provider (Cursor / Claude Code / Gemini CLI / Codex / Copilot / Kiro / OpenCode): Claude Code (desktop app)
  • Provider version: Opus 5, September 2026 build
  • OS: macOS 15 (Darwin 25.5.0, arm64)
  • Verified against upstream HEAD cb56ed6 on a clean checkout — the quoted rule is present verbatim in skill/reference/new-work.md.

Additional context

Hit twice, in two separate direction rounds on the same project. On the second round the substitution — the hand published as an Artifact for viewing, plus the structured question tool for the lock, disclosed in the first reply — cost nothing in card richness, because that round's cards had to be full-size rendered screens anyway. What it cost was the re-roll loop, replaced by a second question offering the three registers.

Related, and deliberately distinct: #789. That issue asks for a degraded Setup path when the launcher is refused in non-interactive hosts. This one is about the new-work decision round after setup has succeeded, and about a channel that starts successfully and then cannot be completed. Same family — a mandate outrunning the environment it assumes — different surface and different trigger, so I have filed it separately rather than adding to #789. If you would rather they were one issue about gating on capability generally, happy to fold this in there instead.

The general form, for whatever it is worth: a fallback gated on a specific error code answers "did the primary channel fail?" when the question that matters is "can this environment run the primary channel safely?" Those come apart exactly where the mechanism starts successfully and then cannot be completed — which is the half-finished state the rule was written to avoid. Gate on the capability and an unanticipated environment degrades instead of stranding.

Willing to work on a fix?

Yes, if useful — the change looks like one clause in the rule:skill-visual-decision-page paragraph. Per the template I'll wait for your go-ahead before opening a PR.