From 77634568ec8060765f77dbb89899cd58c810fd38 Mon Sep 17 00:00:00 2001 From: Evan Harmon Date: Wed, 12 Aug 2026 00:37:07 +0000 Subject: [PATCH] fix(shepherd): correct the settle procedure and stop restating its command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #427. Both files told agents to answer a non-thread finding "(fix it, decline it, or file it), then settle" — and only two of those three can end there. `settle --disposition` accepts `declined|filed` and nothing else, and a fix means a push, which moves the head, invalidates the cycle the state file describes, and starts a fresh one. An agent that fixed such a finding and followed the prose reached a command that cannot succeed, having been told it completes the cycle. Both now separate the paths: fixing means push and let the new head be reviewed on its own merits; settle records the two answers that leave the code alone, with its required note, because the record is a human's adjudication and not a suppression. AGENTS.md additionally stops restating the invocation and routes to the recipe in the shepherd SKILL.md. That is not tidying: harmon-init#799 inlined the same command and three consecutive review rounds each found a different defect in it — missing required flags, this impossible fix path, and `--surface comment|review` parsing as a shell pipe when copied. Deleting the duplicate converged it immediately, and one authoritative copy in the file that ships the command cannot drift from itself. SKILL.md's fenced recipe was already correct and is unchanged apart from the fix-path sentence. Consumers already have the corrected text: harmon-init#799 fixed its own copy rather than waiting on this release, so a `task sync:skills` after this ships re-vendors matching guidance instead of overwriting it. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01JzKn4zxYJAZXX3zg9v4Nqy --- AGENTS.md | 28 ++++++++++++++++----------- ai/skills/universal/shepherd/SKILL.md | 8 ++++++-- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 3c4d6ce1..f9c56f3b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -324,17 +324,23 @@ error silently reverts the lifecycle rather than fixing anything. A badged finding stated **outside an inline thread** — in a top-level comment or in a review's own body — has no reply linkage, so the reply-based adjudication path cannot reach it and findings outrank a later - clean result on the same head. Record its disposition with the checker's - `settle` subcommand: answer the finding on the PR as usual (fix it, decline - it with evidence, or file it), then `settle --surface comment|review --id N - --disposition declined|filed --note …`, adding `--covers ` where the - target states more than one finding. `check` then treats that finding as - answered and the cycle can reach terminal-clean, reported with a detail - naming the disposition. The record is durable and head-bound: it is - fingerprinted against the body it settled, so a finding Codex edits - afterwards blocks again, and any push starts a fresh cycle as usual. - Settling is not a substitute for answering — it records an adjudication a - human wrote, and the note is required for that reason. + clean result on the same head. The checker's `settle` subcommand records the + disposition instead; its exact invocation lives with the recipe in + `ai/skills/universal/shepherd/SKILL.md`, which this file deliberately does + not restate — the same reason it routes you to the checker rather than + describing how to poll. + What belongs here is when it applies. Answer the finding on the PR as usual, + and note that only two of the three answers end with `settle`: **fixing** it + means a push, which moves the head and starts a fresh cycle that reviews the + fix on its own merits, and `settle` neither applies nor accepts that + disposition. It records the two answers that leave the code alone — + declining with evidence, or filing it as follow-up work — and requires a + note for exactly that reason: the record is a human's adjudication, not a + suppression. It is head-bound and fingerprinted against the body it settled, + so a finding Codex edits afterwards blocks again while the superseded entry + survives as the record of what was decided about the earlier text. Once + every non-thread finding on the head carries one, `check` reports clean with + a detail naming the disposition applied. Shepherd is **externally driven** — CI results and other people's comments are its input, so it cannot manufacture a round on its own. A round is one fix push, or one no-change cycle where everything is answered and nothing diff --git a/ai/skills/universal/shepherd/SKILL.md b/ai/skills/universal/shepherd/SKILL.md index 71a4c3b2..950d653f 100644 --- a/ai/skills/universal/shepherd/SKILL.md +++ b/ai/skills/universal/shepherd/SKILL.md @@ -700,8 +700,12 @@ you rather than the bot): reply to, so no act on GitHub can ever record that you answered it and `check` returns exit 10 for that head forever — the deadlock the inline adjudication path was built to end, reappearing on the two surfaces it - cannot see. Answer the finding on the PR as usual (fix it, decline it with - reasoning, or file it), then record the disposition: + cannot see. Answer the finding on the PR as usual — and note that only two + of the three answers end here. **Fixing** it means a push, which moves the + head and starts a fresh cycle that reviews the fix on its own merits; + `settle` neither applies nor accepts that disposition. For the two answers + that leave the code alone — declining with reasoning, or filing it as + follow-up work — record the disposition: ```bash "$helper" settle --state "$state" --actor-id 199175422 \