amont-agent 2.30.2

A guard that inspects a shell command before Claude Code runs it
# The implementation review

Before the push of a branch that carries a plan, one independent reviewer
has read the diff against that plan and the repository's active rules, and
its verdict is recorded in the plan (ADR-0022, fleet rule
`work.implementation-review`). The worktree-task skill runs the review
(step F4b). The `implementation-review` rule checks, at `git push`, that it
happened for the tree being pushed.

The plan step has a panel; the quality loop has one reviewer. A diff with
its surrounding code is larger than a plan and arrives on every push, and
the reviewer's job is narrower: findings only, never an edit, never a
waiver.

## What the reviewer reads

Its prompt carries, in order: the review block, `Round 1.` or `Delta.`, a
brief the session builds once, and its output contract. The brief is the
landed plan's path and Verification section, the diff against the default
branch without `docs/plans/` (its stat when it is large), the repository's
active constraints (`aval rules --level constraint`), and the plan's
Non-goals. It checks plan conformance, that every recorded verification is
an observable check, violated constraints (rule id and `file:line`), tests
that cannot fail, and scope past the phases or the Non-goals.

Its result begins with the verdict, exactly, because the hook reads it:

```
Verdict: approve | approve-with-changes | rework
Findings:
1. [blocking|high|medium|low] <problem>. Evidence: <file:line>. Rule: <id or —>. Edit: <concrete change>.
Would still check by hand: <one to three things>
```

## What a review binds to

The **canonical tree id**: the sha256 of `git ls-tree -r` of the commit
with every entry under `docs/plans/` left out, 64 hex in any object format,
computed read-only. Recording the review in the plan therefore never makes
it stale; a code change does.

```sh
amont-agent tree-sha [--block] [-C <dir>] [--] [<rev>]
```

`--block` prints the block the reviewer's prompt carries:

```
<<<TREE repo=<name> sha=<64 hex>>>>
```

`<name>` is the basename of the directory holding the repository's common
`.git`, so a worktree checked out as `amont-agent-wt-x` says `amont-agent`.
Exit 0; 1 outside a repository or for a rev that names no tree (the reason
on stderr); 2 on a usage error.

## What the hook does at a push

1. Resolves the push (`crate::push_target`): the repository and the commit
   each refspec publishes. A dry run, a push to `main`/`master`, and a
   push of tags only are not its business.
2. **No plan on the branch**: `docs/plans/` unchanged between
   `merge-base(<pushed>, <base>)` and the pushed commit, where `<base>` is
   the first of `<remote>/HEAD`, `<remote>/main`, `<remote>/master` that
   exists, never the branch's own tracking ref and never `HEAD`. The rule
   declines, silently.
3. Computes the canonical tree of the pushed commit.
4. Looks for a binding: a completed `implementation-review` agent in this
   session's transcript whose block names this repository and tree, or a
   pass remembered under `~/.claude/amont-agent/implementation-review/by-tree/`.
   Completion is read from structured fields only, as the review panel
   reads it; a notification echoed inside a tool result never counts. A
   reviewer **resumed** with `SendMessage` on a new block counts as a
   review of that block ([below]#a-resumed-review).
5. **Reads the verdict.** A review that said `rework` and got no later
   delta on the same tree is not a pass.
6. On the first transcript binding that passes, writes the pass file
   (0700 directory, 0600 file), so a new session pushing the same tree
   passes without a transcript.

| situation | `advise` (ships) | `deny` |
|---|---|---|
| reviewed this tree, verdict not `rework` | silent | passes |
| no plan on the branch | silent | silent |
| reviewed an older tree | note, names both trees | held, names both trees |
| verdict `rework`, no delta | note | held |
| never reviewed | note | held |
| transcript unreadable, git failed, no default branch known | note | held |
| a push shape this guard cannot read (`--all`, `--mirror`, …) | journalled, passes | held |

Every note ends with the next step:

```
amont-agent/implementation-review: no implementation review of amont-agent tree 5085edae1d66 is in this session. worktree-task F4b: `amont-agent tree-sha --block`, then launch the implementation-review agent …
```

## A resumed review

The delta (F4b.6) may resume the same reviewer with `SendMessage`, giving
it the new block, instead of launching a fresh one. Each round is a review
of its own, read from the shape a real session recorded
(`tests/fixtures/sendmessage-resume.jsonl`, 2026-10-08):

1. the launch's result carries `toolUseResult.agentId`;
2. a `SendMessage` whose `input.to` is that agent id, and whose result
   carries `toolUseResult.resumedAgentId` = the same id, starts a round:
   its prompt is `input.message` (the block is read from it) and its id is
   the SendMessage's own;
3. the round completes only on a structured task notification whose
   `<tool-use-id>` is that SendMessage's id and whose `<task-id>` is the
   agent id. The launch's own result is never overwritten.

A message to an agent that was not launched as `implementation-review`, a
round whose notification names another task, or a notification typed or
echoed rather than queued by Claude Code does not count. Only this rule
reads resumes: the plan-review panel counts fresh launches alone.

## The person's overrule

A `rework` that survives the delta goes to the person on a marked
question: its text starts with `[implementation-review <repo>@<sha64>]`
and its options are exactly `Overrule`, `Fix`, `Hold`. As with the preview
approval, the hook records the question before it runs and trusts the
answer only when that record exists and the question did not arrive with
`answers` pre-filled. On `Overrule`, and only when this session's
transcript shows a completed review of that tree that said `rework`, the
hook writes the pass file with `verdict: overruled`. An overrule that
bound nothing says so in the model's context.

## Only the hook writes a pass file

Under `deny` a pass file is a trust boundary. A Write, Edit or MultiEdit
under `~/.claude/amont-agent/implementation-review/` is refused, with `.`
and `..` folded before the comparison; a Bash command that would write
there — a redirect into it, or `rm`, `cp`, `tee`, `python`, `chezmoi` and
the like with a word naming it — is refused too, whatever the rule's
stance. Reading the record (`ls`, `cat`, `find`, `grep`) is allowed. The
Bash half is best-effort by nature: a parser cannot see inside `python -c`
beyond its words.

## What the journal records

One line per push, under the rule's id, in the buckets `amont-agent
status` counts: a declined push as `unconfirmed` with the reason
(`reviewed`, `overruled`, `no-plan`, `dry-run`, `no-branch`,
`unresolvable`), a spoken one as `advised`, `denied` or `watched`. The
excerpt of a spoken line is structured:

```
tree=<12 hex> review=<stale|rework|missing|unknown> verdict=<approve|approve-with-changes|rework|->
```

Away from a push: `overruled`, `answered`, `unbound`, `unknown`,
`prefilled`, `unrecorded` for the marked question, and `denied` for a
refused write. The soak reads them with:

```sh
grep -E ' implementation-review ' ~/.claude/amont-agent/journal.log
```

## Stance

Ships `advise`. `git config --global amont.agent.implementation-review.stance
deny` holds a push whose review is missing, stale, `rework` or unknown;
`observe` journals and says nothing. The 2026-10-06 soak review, alongside
`push-preview`, decides between `deny`, `advise` and retiring the gate from
the journal's `review=` counts and the first real cycles' finding quality.