spec, master: headless roles must not background gates; tell a stalled revise from a declined one - #457
Merged
Conversation
…d revise from a declined one Three pipeline rounds on PR #437 were lost on 2026-09-15 the same way: a headless role (qa twice, developer once) started its cargo gate as a background command, ended its turn "waiting for the notification", and the claude -p process exited with nothing posted. The developer's fix sat uncommitted in the worktree. .agents/AGENTS.md gains an every-role "headless sessions" section: no later turn exists, so never background a command whose result you need, run gate steps in the foreground one call each, and have the deliverable (comment, push, labels) in place before the turn ends. The three session excerpts are quoted as the concrete bad example. qa.md, developer.md and codex-qa.md point to it where each role runs commands. bin/master.sh: "revise pushed nothing" always told the operator the developer had declined ("the block is one only you can clear"). It now counts PR comments around revise.sh. A comment keeps that message. No comment reports that the session did not finish, not a decline, and names any uncommitted tracked files left in the branch worktree plus the session log. needs-work and STATE=needs-human stay in both cases. Checked with a throwaway harness sourcing master.sh with gh_retry and revise.sh stubbed: commented, stalled with a dirty worktree, unreadable comment count and moved tip each take their own path, and the three unchanged-tip cases end in STATE=needs-human. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FuCG3RuLHArnC8snRZVDYG
mkovero
force-pushed
the
fix-headless-agent-gates
branch
from
September 15, 2026 13:56
b1c884f to
79144ae
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Pipeline roles run headless (
bin/*.sh→claude -p/codex exec). On 2026-09-15 three rounds on PR #437 were lost the same way. The role started its cargo gate as a background command and ended its turn to wait for a completion notification that never comes in-pmode, so the process exited with nothing posted:cargo test --workspacebackground run to finish before posting the PR comment."master.shreported the developer case as a decline: "revise pushed nothing … the block is one only you can clear: a rig measurement, acceptance of an assumed criterion, a design call." The developer had declined nothing. The fix was in the worktree, uncommitted.Changes (rebased onto
mainafter #458).agents/AGENTS.md: new every-role section headless sessions, placed after #458's bounded reading discipline:.agents/qa.md,developer.md,codex-qa.md: a pointer where each role runs commands.bin/master.sh(qa_loop, needs-work → revise), fitted to #458's version of that block:revise.shcall. If it can't be read, the revise doesn't start. That is the same fail-closed rule as the tip read.revise.shexit other than an interrupt. A session that backgrounded its gate exits 0, so the retry never covers this case, which is why the distinction below is still needed.needs-design/needs-uxon the issue) still run first when the tip is unchanged.$WT_BASE/<branch>and the session-log commandneeds-workandSTATE=needs-humanstay in every one of those cases.Verification (on the rebased commit)
bash -n bin/master.sh: clean.shellcheck -x -S warning bin/master.sh: 0 warnings, same asmain.bin/has no test harness, so I used a throwaway one. It sources the rebasedmaster.shwith the top-level dispatch removed, and refuses to source it if that removal did not match. It stubsgh_retryandrevise.sh(exit 0), and uses a real git repo as$WT_BASE/<branch>:STATE=needs-humanSTATE=needs-humanSTATE=needs-humanclaude --help(2.1.272) has no flag that disables background Bash, and--disallowedToolsworks per tool, not per parameter.Not in this PR
architect.mdtemplate: its**file manifest**block isn't a```filesfence, whichmanifest_ofrequires. The architect manifests on it_loopback_ir's daemon clamps at the -10 dBFS default, not the rig ceiling, when driving real ports #442 and epic EPIC: Close confirmed ac-core and ac-daemon audit findings #423 had to be fenced by hand.🤖 Generated with Claude Code
https://claude.ai/code/session_01FuCG3RuLHArnC8snRZVDYG