Skip to content

ci: gate pull requests on an adversarial review and a fixed body - #1894

Merged
joshunrau merged 9 commits into
DouglasNeuroInformatics:mainfrom
joshunrau:docs/trim-root-agents-md
Nov 10, 2026
Merged

joshunrau merged 9 commits into
DouglasNeuroInformatics:mainfrom
joshunrau:docs/trim-root-agents-md

Conversation

@joshunrau

Copy link
Copy Markdown
Collaborator

Agents working in this repo now follow one process from change to pull request: a green pnpm check, an adversarial review of the branch against upstream main, and a PR body in a fixed shape that a workflow enforces by closing any PR without it. The root AGENTS.md shrinks to the rules that have no other home, and the skills lose their odc- prefix.

Changes

  • Root AGENTS.md keeps only rules that bind every directory. The map of nested docs moves to .agents/docs/index.md and the coding guidelines to .agents/docs/coding-guidelines.md, both pulled in with @ imports. Turbo no longer rewrites its managed block into the file.
  • pnpm check runs lint, coverage and e2e in sequence and is what "done" means. The old "every change needs a unit and an e2e test" rule is gone: coverage stays at 100% and e2e covers important functionality.
  • finishing-changes (was odc-done) owns the close-out order, ending with the review and the PR. writing-agent-docs (was odc-agent-docs) and troubleshooting (was odc-debugging) are renames only.
  • adding-dependencies holds the ask-first, catalog and release-age rules that used to sit in the root file.
  • adversarial-review runs a prosecutor sub-agent over the branch's code files and a defence sub-agent over its findings, and returns only what the defence could not refute. Neither runs lint or tests.
  • opening-pr writes the body: an opening paragraph, Changes in effect terms, Decisions and Risks only when there are any, and the review block with every confirmed finding under Fixed or Declined. Verification, Validation, Notes and Implementation-notes sections are refused.
  • The PR Body workflow checks the body on open, edit, push and reopen. It closes the PR, with a comment naming each rule broken, when the review block is missing, names a commit other than the head, drops a finding, or a forbidden section is present. It runs on pull_request_target so it can act on fork PRs, checks out main only, and reads nothing but the event payload.

Decisions

  • Closing rather than a failing check. It is the signal an agent cannot miss. A human contributor gets the comment, fixes the body and reopens.
  • The edited event skips the head-stamp comparison. The body is edited for a new head before that head is pushed, so an edit can only be checked once the push's synchronize run arrives, which still compares it.
  • Prosecutor then defence, rather than parallel review axes. The caller acts on every finding with no human to filter for it, so precision was worth more than breadth.
  • The review reads code files only. The docs on this branch were checked line by line against the writing-skills-for-agents method instead.

Risks

  • pull_request_target runs with a write token. The job never checks out or executes the PR's code, so a PR cannot reach the token. Accepted.
  • The gate can be satisfied by a fabricated block. It turns skipping the review into an explicit false claim per commit rather than an omission, which is as far as a text check goes. Accepted.
  • The default token needs pull-requests: write, which repository Actions settings can deny. Check that setting after merge; the close step fails visibly in the job if it is denied.

Adversarial review

Reviewed at commit 3697377. pnpm check: green.

Findings

  1. scripts/check-pr-body.ts:44 — The edited run compared a body rewritten for a new head against the old head, so the prescribed edit-then-push order got the PR closed before the push — skip the head comparison on edited, which synchronize then performs.
  2. scripts/check-pr-body.ts:19 — The event payload was cast with as instead of parsed at the boundary, so a malformed payload failed inside the checks with a misleading reason — narrow it at read time and throw a named error.
  3. scripts/check-pr-body.ts:86 — The forbidden-heading test ran on fenced code too, so a # Validation comment in a shell snippet closed the PR — skip fenced lines and require a space after the hashes.
  4. scripts/check-pr-body.ts:41 — The stamp regex accepted a 7-character sha while the skill requires the full sha — accept 40 characters only and compare exactly.

Fixed

    1. action === 'edited' skips only the head comparison; a missing stamp still fails.
    1. parseEvent narrows the payload and names what is missing.
    1. outsideFences drops fenced lines before the heading test, whose pattern now needs a space.
    1. The pattern is [0-9a-f]{40} and the comparison is includes.

joshunrau and others added 9 commits November 9, 2026 17:36
Cut the sections that duplicated a nested AGENTS.md, a playbook or an eslint rule: the DNP
package list, the code-philosophy section, the route-tree rule, and the lint-enforced halves
of the formatting, tests, coverage and translation rules. The scoped-run tips move to
testing-strategy.md, which had no copy. Set agentGuidance: false in turbo.json and drop the
managed Turborepo block it maintained.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
writing-agent-docs and troubleshooting follow the gerund names of the other skills, with the
directories, .claude/skills symlinks, display names and cross-references updated to match.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Three skills carry the process: adversarial-review runs a prosecutor and a defence sub-agent
over the branch against upstream main and returns only confirmed findings; opening-pr writes
the body a reviewer can read in seconds, with the review block and what was fixed or declined;
finishing-changes links them in order. The pr-body workflow checks every body and closes a PR
whose block is missing, stale, or drops a finding, or that carries a Verification or Notes
section.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@joshunrau
joshunrau merged commit aa36aa4 into DouglasNeuroInformatics:main Nov 10, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant