fix: adversarial review fixes — failure shape, CHANGELOG guard, vet coherence

Claude adversarial subagent findings (11), all verified before applying:
- The dispatch JSON contract gains an explicit FAILURE shape
  ({"error":...}) and a parent branch for it — a doc-sync that could not
  run (spawned marking failed, broken preamble) previously had only the
  no-updates shape to emit, which the parent printed as 'Documentation is
  current': a silent false-clean of exactly the VAS-449 class.
- Scope guard now covers CHANGELOG: skip Step 5 voice polish and resolve
  CHANGELOG-touching gates to leave-as-is (the parent authored the
  release entry; the prompt's older auto-choose clause conflicted with
  the contract's never-rewrite invariant).
- Recovery vet is sequence-coherent: pushing a commit pushes its
  ancestors, so ANY non-doc commit (VERSION, package.json, CHANGELOG.md)
  blocks the whole sequence — no more push-the-vetted-child-of-an-
  unvetted-parent hole.
- Steps 7/8/10 failure branches stop a still-running backgrounded task
  before falling back, so a late result never races the inline audit.
- 'Documentation synced' print gated on pushed:true (item 6 owns the
  local-only outcome); doc-review skip note's backward step pointer
  fixed; foreground note scoped 'at initial dispatch' so the sanctioned
  inline FALLBACKS in Steps 7/8 read as sanctioned; constants docstring
  no longer overclaims single-sourcing (names the 3 inline templates).
- Runtime-hook TODO raised P2 → P1: the spawned trust chain is
  agent-self-asserted; prose cannot close it, the hook can.

Both docsync gate E2Es re-verified green on the amended prompt, including
the strict run_in_background === false dispatch assert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-09-01 21:31:37 +00:00
co-authored by Claude Fable 5
parent a54f742179
commit 6c63ac2ae4
14 changed files with 61 additions and 47 deletions
+2 -2
View File
@@ -4,7 +4,7 @@
**Dispatch the fetch + classification as a subagent** using the Agent tool with `subagent_type: "general-purpose"`. The subagent pulls every Greptile comment, runs the escalation detection algorithm, and classifies each comment. Parent receives a structured list and handles user interaction + file edits.
**Foreground required:** pass `run_in_background: false` on the Agent call — subagents run in the BACKGROUND by default since Claude Code v2.1.198. (Merely omitting the flag no longer produces a foreground run; it must be explicitly false.) Dispatch with the Agent tool itself — never substitute the Skill tool or inline execution to "guarantee" blocking: the explicit flag already makes the Agent call block, and running the work inline forfeits the fresh-context isolation this dispatch exists for.
**Foreground required:** pass `run_in_background: false` on the Agent call — subagents run in the BACKGROUND by default since Claude Code v2.1.198. (Merely omitting the flag no longer produces a foreground run; it must be explicitly false.) Dispatch with the Agent tool itself — never substitute the Skill tool or inline execution at initial dispatch to "guarantee" blocking: the explicit flag already makes the Agent call block, and running the work inline forfeits the fresh-context isolation this dispatch exists for.
**Subagent prompt:**
@@ -23,7 +23,7 @@ Parse the LAST line as JSON.
If `total` is 0, skip this step silently. Continue to Step 12.
**If the subagent fails, returns invalid JSON, or never completes (backgrounded despite the flag, or no final output after ~10 minutes — stop waiting):** print `Greptile triage did not complete — review the PR comments manually` and continue to Step 12, recording the triage as UNAVAILABLE — not as zero comments — in the PR body wherever review results are reported (an unavailable triage must not read as a clean one; Step 20's metrics schema carries no triage field, so the PR body is the record). Do not block /ship on the triage subagent.
**If the subagent fails, returns invalid JSON, or never completes (backgrounded despite the flag, or no final output after ~10 minutes — stop waiting; if a backgrounded task is still running, stop it first so a late result never lands mid-ship):** print `Greptile triage did not complete — review the PR comments manually` and continue to Step 12, recording the triage as UNAVAILABLE — not as zero comments — in the PR body wherever review results are reported (an unavailable triage must not read as a clean one; Step 20's metrics schema carries no triage field, so the PR body is the record). Do not block /ship on the triage subagent.
Otherwise, print: `+ {total} Greptile comments ({valid_actionable} valid, {already_fixed} already fixed, {false_positive} FP)`.