Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude/commands/adversarial.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ argument-hint: "[branch] (defaults to the current one)"
# Attack the branch before the pull request

AGENTS.md asks for this after the push and before the PR is opened, and for a revision of
an open PR, before the push that asks for re-review. This is the prompt it tells you to
an open PR, after its push and before review is re-requested. This is the prompt it tells you to
write.

Work out the branch (`$ARGUMENTS`, or `git rev-parse --abbrev-ref HEAD`), confirm it is
Expand All @@ -17,7 +17,7 @@ the worktree until the pass reports.

## The prompt

> You are doing an adversarial pre-PR review in the sstriker/durable-memory repository.
> You are doing an adversarial pre-PR review in this repository.
> Read AGENTS.md and PLAN.md first. **Change nothing, commit nothing, post nothing to
> GitHub.** Report findings.
>
Expand Down
90 changes: 90 additions & 0 deletions .claude/commands/reader-test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
description: Hand a docs-only branch to two fresh subagents, one that reads only the changed files and their diff and one that fact-checks them against the code
argument-hint: "[branch] (defaults to the current one)"
---

# Read the branch before the pull request

AGENTS.md asks for this in place of `/adversarial` on a docs-only branch, one where
`git diff --name-only --no-renames origin/main...origin/<branch> | scripts/docs-only.sh`
exits 0: after the push and before the PR is opened, and for a revision of an open PR,
after its push and before review is re-requested. A doc fails in two ways that a reviewer
who knows the code does not see: a reader comes away believing something other than what
was meant, or the doc says something the code does not do. One subagent tests each.

Work out the branch (`$ARGUMENTS`, or `git rev-parse --abbrev-ref HEAD`), confirm it is
pushed and that `origin/<branch>` is what you mean to have read. Then, before spawning
anything:

1. **Write the questions.** Three to five questions the change should let a reader
answer, each with the answer you mean the doc to give. Ask what a reader would act on
("which part stops X", "what do you lose if you Y"), not what a sentence says. Keep the
answers to yourself; the reader never sees them. The reader is not quite cold: every
session here loads CLAUDE.md, AGENTS.md through it, and the user's own memory and
context, before it reads anything. Ask what that text cannot answer, and when the
change is to AGENTS.md itself, tell the reader that the copy in its directory is the
one to go by.
2. **Copy the changed files** as they stand on `origin/<branch>` into a fresh directory in
your scratchpad, with nothing else in it, and save `git diff origin/main...origin/<branch>`
beside them as `change.diff`.

Then spawn **two fresh subagents of the `general-purpose` type** in one message, never
forks, which would inherit the reasoning that wrote the branch and agree with it. Do not
edit the worktree until both report.

## The reader

> You are a reader new to this project. Read only the files in `<dir>`: the changed
> documents, and `change.diff`, which shows what changed in them. **Read nothing else**: no
> other file in the repository, no code, no web. What a reader cannot find in these files,
> you do not know. Change nothing.
>
> 1. Before the questions: in five sentences or fewer, what does the change tell you that
> the old text did not?
> 2. Answer each question below from the documents alone. Quote the sentence each answer
> rests on. Where the documents do not answer, say so; do not guess from what such
> projects usually do.
> 3. List each place where you stopped or read twice: a term used before it is defined,
> two passages that disagree, a sentence you could read two ways (give both readings),
> a claim about a part the documents never introduce.
>
> <the questions, without the answers>

## The fact check

> You are checking a documentation change in this repository against the code. Read
> AGENTS.md as it stands on `origin/<branch>` first. **Change nothing, commit nothing,
> post nothing to GitHub.** The change is `git diff origin/main...origin/<branch>`.
>
> List every claim the added or changed lines make about what the code does, what a
> command does, what a file holds, or which part does what. For each, read the code on
> `origin/<branch>` and give one verdict: **HOLDS** with the `file:line` that shows it,
> **WRONG** with the `file:line` that shows otherwise and what the text should say, or
> **UNCHECKED** with why you could not settle it. A claim the text implies but does not
> state counts: a component given a job, a list that reads as complete. Where the doc
> describes a plan as well as what is built, say whether a claim about the plan fits the
> code that exists, rather than marking it WRONG for not being built yet. Where the change
> is to the repository's own rules, also check that it agrees with the rest of AGENTS.md,
> the other commands, the hooks, the scripts and CI. Report WRONG first. Do not report
> style.
>
> <on a re-run, add: Check only the lines that `git diff <commit>..origin/<branch>`
> changes, but report anything WRONG you find anywhere in the full diff. `<commit>` is the
> one the last fact check read.>

## When they report

Grade the reader's answers against yours. A wrong or missing answer is a finding against
the text, not against the reader: change the text until a fresh reader would answer it.
Verify each WRONG from the fact check yourself before acting on it, and settle each
UNCHECKED or name it in the PR description as open.

A revision of one word or one punctuation mark needs no new pass. A larger revision is new
text: push it and run two fresh agents again, with the same questions, since a fix for one
reader's confusion can make a claim the code does not hold. Once the latest reader has
answered every question correctly, a revision for that reader's other notes needs only the
fact check, on the lines the revision changed. These rules hold for a revision of an open
PR too.

Then say in the PR description that the pass ran, the questions, how the reader did, what
the fact check found, and what is still open, so a pass that found nothing leaves a trace.
16 changes: 13 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ to the repository is committed under `.claude/`:
| `.claude/hooks/guard-bash.sh` | refuses a command that stages with a wildcard, reaches into the shared stash, passes `--no-verify`, pipes `cargo` or `make` into `head` or `tail`, or posts an issue or pull request body that does not say who wrote it |
| `.claude/hooks/guard-bash.test.sh` | what the guard refuses, and what it must go on allowing. Run by `make check` |
| `.claude/commands/adversarial.md` | the prompt the pre-PR pass is given, and the classes it attacks |
| `.claude/commands/reader-test.md` | the prompts for a docs-only branch instead: a reader with only the changed files and their diff, and a fact check against the code |

If the guard refuses something this repository actually asks for, that is a bug in the
guard: add the case to the test and fix it rather than working around it. Whatever else
Expand Down Expand Up @@ -127,12 +128,21 @@ is the direction (PLAN.md, Build speed); until then the cache is local.
## Pull requests

- Branch from `main`, open the PR against `main`, `make check` passing first.
- **A fresh subagent attacks the branch after the push and before the pull request.** The
- **A fresh subagent attacks the branch after the push and before the pull request**, and
again after each push that revises an open one, before review is re-requested. The
prompt is `/adversarial`, in `.claude/commands/adversarial.md`. A fresh agent, never a
fork: a fork inherits the reasoning that wrote the branch and agrees with it. Answer what
it finds as you would a reviewer, and say in the PR description that the pass ran and
what came of it, so a pass that found nothing leaves a trace. Skip it for a branch that
touches only docs.
what came of it, so a pass that found nothing leaves a trace.
- **A docs-only branch, one whose changed paths `scripts/docs-only.sh` accepts, gets a
reader test instead**, at the same points. The prompt is `/reader-test`, in
`.claude/commands/reader-test.md`: write the questions the change should answer first,
then one fresh agent answers them from the changed files and their diff and from nothing
else but what every session loads, and another fact-checks each claim against the code.
A wrong or missing answer is a finding against the text. The command says when a
revision needs both agents again, the fact check alone, or neither. Say in the PR
description that the pass ran, the questions, how the reader did, what the fact check
found, and what is still open.
- **A review is tied to a commit, so re-request it after every push**, and do not read a
clean round as a verdict.

Expand Down
Loading