gha#393's run_in_background: false prompt mitigation for gha#392 (reviewer spawns background Agent calls, then ends its turn waiting on completion notifications that never arrive in a headless CI run) is live in run-claude-review-attempt/action.yml and has been for a while (v2 slid to 70c7fa8 carrying it, per gha#392's own measurement comments). It has now recurred with the identical signature.
Evidence
Run 32347489886, job review / claude-review, on Morrison-Lab/ai-config#1744 at head 185054b, is_error: false, subtype: success, num_turns: 13, total_cost_usd: $4.21.
The final result message:
Stopping Point: Not a clean stopping point / work remains queued: four background review agents (2 CLAUDE.md compliance passes, 2 Opus bug-scan passes) on PR Morrison-Lab/ai-config#1744 are still running. Once they complete, I still need to validate any flagged issues, then produce the final review output ending in a ### Verdict line, per this review-only run's requirements.
Despite claude_args's --append-system-prompt explicitly stating (verbatim, still present in run-claude-review-attempt/action.yml at the time of this run):
This run is a single, synchronous CI job with a fixed timeout and no one to resume it afterward. Do NOT spawn a background agent or sub-task to continue the review in a future turn or after this job ends... every one of those calls MUST be synchronous: pass run_in_background: false on each Agent/Task call.
the reviewer spawned four background agents anyway and ended its turn waiting on them -- exactly the gha#392 failure shape, just with the review's own multi-pass structure (2 CLAUDE.md compliance + 2 Opus bug-scan) instead of #392's eight-way fan-out.
Why this is likely worth a second look
A prompt instruction is not a hard constraint -- the model can and (per this run) does deviate from it. gha#392's own "Suggested direction" section named the mechanical alternative (constrain the tool rather than instruct around it) and its follow-up comment on gha#392 walked that back specifically for denying Agent outright (breaks the plugin's legitimate synchronous fan-out). Nothing in that thread evaluated a narrower mechanical constraint -- e.g. whether Claude Code's tool-permission syntax supports a parameter-scoped grant (something like an Agent(run_in_background:false)-shaped allow rule, if the permission engine supports matching on tool input rather than only tool name) that would make the synchronous-only constraint enforced rather than requested. Worth checking whether that's possible before concluding a prompt-only fix is the ceiling here.
Also unaddressed from gha#392 itself
Its closing "Suggested direction" paragraph asked: "Worth checking whether the guard can also treat 'final message names background agents' as a distinct outcome from a generic stub, since the retry is unlikely to help and the spend is large." That's still open -- check-review-execution.sh treats this the same as any other no-verdict stub (retryable when denial count is low, per gha#185's threshold), even though a same-prompt retry of a run that just demonstrated it ignores the synchronous-only instruction is not obviously more likely to recover than #198's high-denial pattern is.
gha#393's
run_in_background: falseprompt mitigation for gha#392 (reviewer spawns backgroundAgentcalls, then ends its turn waiting on completion notifications that never arrive in a headless CI run) is live inrun-claude-review-attempt/action.ymland has been for a while (v2slid to70c7fa8carrying it, per gha#392's own measurement comments). It has now recurred with the identical signature.Evidence
Run 32347489886, job
review / claude-review, onMorrison-Lab/ai-config#1744at head185054b,is_error: false,subtype: success,num_turns: 13,total_cost_usd: $4.21.The final
resultmessage:Despite
claude_args's--append-system-promptexplicitly stating (verbatim, still present inrun-claude-review-attempt/action.ymlat the time of this run):the reviewer spawned four background agents anyway and ended its turn waiting on them -- exactly the gha#392 failure shape, just with the review's own multi-pass structure (2 CLAUDE.md compliance + 2 Opus bug-scan) instead of #392's eight-way fan-out.
Why this is likely worth a second look
A prompt instruction is not a hard constraint -- the model can and (per this run) does deviate from it. gha#392's own "Suggested direction" section named the mechanical alternative (constrain the tool rather than instruct around it) and its follow-up comment on gha#392 walked that back specifically for denying
Agentoutright (breaks the plugin's legitimate synchronous fan-out). Nothing in that thread evaluated a narrower mechanical constraint -- e.g. whether Claude Code's tool-permission syntax supports a parameter-scoped grant (something like anAgent(run_in_background:false)-shaped allow rule, if the permission engine supports matching on tool input rather than only tool name) that would make the synchronous-only constraint enforced rather than requested. Worth checking whether that's possible before concluding a prompt-only fix is the ceiling here.Also unaddressed from gha#392 itself
Its closing "Suggested direction" paragraph asked: "Worth checking whether the guard can also treat 'final message names background agents' as a distinct outcome from a generic stub, since the retry is unlikely to help and the spend is large." That's still open --
check-review-execution.shtreats this the same as any other no-verdict stub (retryable when denial count is low, per gha#185's threshold), even though a same-prompt retry of a run that just demonstrated it ignores the synchronous-only instruction is not obviously more likely to recover than #198's high-denial pattern is.