Przejdź do treści
Biblioteka skilli
Programowanie · Przegląd i audyt

review-map

/review-map

Buduje stronę HTML, która pomaga zrozumieć pull request lub gałąź: co się zmieniło, od czego zacząć i co może się zepsuć gdzie indziej.

Licencja
MIT
Ostatnia zmiana repozytorium
26.10.2026

Ocena i bezpieczeństwo

91/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść26 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
302
Skrypty
55
Komentarze HTML
0
Adresy URL w SKILL.md
0
Przestarzałość

Brak sygnałów. Repozytorium zmienione 26.10.2026, bez odwołań do wycofanych modeli i API.

Licencja

MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.

Co sprawdzić przed instalacją
  • 55 skryptów w paczce. Przejrzyj je przed instalacją, bo Claude może je uruchomić.

Skrypty: evals/check.rb, evals/checks/build-state.rb, evals/checks/completeness.rb, evals/checks/excerpts.rb, evals/checks/figures.rb, evals/checks/frozen.rb, evals/checks/impact-paths.rb, evals/checks/lib/review_map/changed.rb

Co robi i kiedy

Buduje stronę HTML, która pomaga zrozumieć pull request lub gałąź: co się zmieniło, od czego zacząć i co może się zepsuć gdzie indziej.

Wyzwalacze z opisu

s work, even if they never sayor
Oryginalny opis (EN)

Use this skill when someone needs to understand a pull request or branch before judging it: what a PR does, where to start on a large diff, which files matter, what the change might break in code it did not touch, or whether frontend and backend still agree. Also use it to bring a reviewer up to speed on someone else's work, even if they never say "review map" or "walkthrough". It builds one HTML page: what changed, the judgments the reviewer must make with the exact lines that settle each one, the order to read the code in, and the change's reach outside the diff. Works on Rails, Elixir/Phoen

Jak działa

  1. Host and invocation
  2. What is bundled
  3. The run at a glance
  4. 1. Resolve the target and the effort
  5. 2. Discover the project
  6. 3. Inventory the diff
  7. 4. Derive what changed
  8. 5. Trace the flows and find affected-but-unchanged code
  9. 6. Cluster into flows, write the analysis notes, spawn the falsifiers
  10. 7. Synthesise the agenda
Sekcje z nagłówków SKILL.md, w oryginale · 1 509 linii, 19 619 słów
Podgląd SKILL.md
---
name: review-map
description: >-
  Use this skill when someone needs to understand a pull request or branch before judging it: what a PR does, where to start on a large diff, which files matter, what the change might break in code it did not touch, or whether frontend and backend still agree. Also use it to bring a reviewer up to speed on someone else's work, even if they never say "review map" or "walkthrough". It builds one HTML page: what changed, the judgments the reviewer must make with the exact lines that settle each one, the order to read the code in, and the change's reach outside the diff. Works on Rails, Elixir/Phoenix, Rust and React/Next.js codebases, including APIs, LiveView apps, libraries and workspaces. Takes a PR number, URL, branch or diff range. Not for posting review comments, approving, grading a change, or writing PR descriptions or release notes.
---

# Review Map

Turns a diff into one HTML page a reviewer can work from: what the change is for, which
judgments it asks of them and where to look to make each one, the order to read the code in, and
what the change reaches outside the lines it touched.

**The page is a review agenda, and the deep analysis is how it is built — not what it prints.** A run
traces consumers across the whole diff, reads the tests, follows a value across the boundary and
attacks its own conclusions. What reaches the reader is the part they have to act on. Reducing the
reading obligation is the goal; reducing the analysis is the failure.

**Do not determine whether the PR is correct. Help a competent reviewer determine whether it is.**
That is the whole product. A page good enough to approve from without reading code is a failure — the
reviewer ends up holding a verdict instead of a mental model, and the debt lands on whoever touches
the code next.

So the page is a navigation aid, never a replacement for reading the code. The question it has to
pass is: *after following this, can the reviewer explain what changed, why it works, and where the
important decisions live?* Not: *can a model summarize this diff?*

You are not a code reviewer here. Do not grade the change, do not recommend approval, do not post
comments on the PR. If the project has a review command, say so at the end and let it do that job.

## Host and invocation

Use `/accountable-review:review-map` in Claude Code or `$accountable-review:review-map` in Codex
(`/review-map` and `$review-map` when installed as a standalone skill, as `npx skills add` does).
Both accept a
PR number, URL, branch, or diff range; `--effort high` (default) or `--effort low`;
`--mentor` with an optional stack or `off`; `--context auto|never|always|collapsed`; and
`--output <dir>`. The repository's `.accountable-review.yml` supplies the first three when no flag
does (step 1).

Before step 1, read **only your host's reference**: [Claude Code](references/hosts/claude-code.md)
in Claude Code, and [the one for every other host](references/hosts/generic.md) anywhere else — Codex
and Pi being the primary examples, and any other agent that loaded this skill getting the same
local-file delivery. It owns delegation and delivery mechanics;
the ten steps below own the review. Resolve bundled paths relative to this `SKILL.md`,
not the repository being reviewed. User instructions take precedence over skill guidance.

## What is bundled

The procedure below relies on the bundled files in this table. Read each at the step that needs it
rather than up front — the procedure itself is the only part that has to be in context the whole way
through.

The stack's files are chosen per run, and **you read your own and never another's.** Step 2's stack
detection picks the discovery file, the lens and the catalogue: a Rails run reads the Rails pair, a Phoenix run the
Phoenix pair, a Rust run the Rust lens and the Rust catalogue, a React run the React lens and the
React catalogue — and reading another stack's file costs context and teaches the wrong searches.
**Two stacks have a lens of two files, and they are built the same way.** The Rust backend reads
`references/rust.md`, the lens every Rust run gets, and then `references/rust-backend.md` on top of
it, because a server is still a crate and the backend file restates none of the language. A Next.js
app reads `references/react.md`, the lens every React run gets, and then `references/nextjs.md` on top
of it, because a Next.js app is still a React tree. A Rust run that is not a backend reads `rust.md`
alone, and a React run that is not Next.js reads `react.md` alone. The host reference is the same
rule one level up — yours, not the other host's.

| File | Read at | For |
|---|---|---|
| `references/hosts/claude-code.md` *or* `references/hosts/generic.md` | before step 1 | Delivery and delegation mechanics for **the host this run is in** — Claude Code's, or the one for every other host (Codex, Pi, …) — how a stage reaches the reader, and how step 6c's independent reader is launched. The ten steps own the review; this owns the machinery under it |
| `references/report-format.md` | step 1 § *Deep links* only; whole at step 7, for 7, 8 and 9 | The six sections, the review checkpoint, the Context section, the chain component, the evidence tiers, source excerpts, impact paths, the canonical-home rule, the agenda budget and the deep-link ladder |
| `references/discover/rails.md`, `phoenix.md`, `rust.md` *or* `react.md` | step 2, once, after detection | What to detect about **the stack step 2 found** — its layout, libraries and test runner — and which versions the documentation links are pinned to. Small, and read whole |
| `references/rails-nextjs.md`, `references/phoenix-liveview.md`, `references/rust.md` (+ `references/rust-backend.md` for a Rust backend) *or* `references/react.md` (+ `references/nextjs.md` for a Next.js app) | step 5, then while reading any layer | What a senior reviewer of **the stack step 2 detected** looks for, the runtime probes, and the search recipes for code the diff did not touch. Step 2 names it; step 5 is where it is read |
| `references/rails-docs.md`, `references/elixir-docs.md`, `references/rust-docs.md` *or* `references/react-docs.md` | step 7, when a claim first asks for an anchor | The documentation URLs the page may cite, for that same stack. It is an allowlist, not a starting point: you look a concept up in it, you never read it to find concepts |
| `references/update.md` | step 1, only with `--update` | Re-running over new commits: whether this can be an update at all, `scripts/carry-plan.sh` and its plan, which steps run in full or narrowed, and how the existing page is edited. A run without the flag never opens it |
| `references/page-template.html` | step 9 | The design system. A run reads its **markup half** — component classes, two assembled checkpoints, the chain and the impact panel — with `scripts/page-skeleton.sh --markup`. The head, the whole token block and the page's one script are in the same file and are emitted rather than read |
| `scripts/page-skeleton.sh` | step 9, once | Writes that head, token block and script straight into the page, so none of it is read and none of it is typed. `--markup` is how the rest of the template is read |
| `references/themes/` | never | The three looks — Daylight (default), Workshop, Field Notes — each a font link, a token block and its overrides. `page-skeleton.sh` writes all three into the head with the repository's choice switched on, and the tail script builds the reader's *Aa* menu that switches them; a run never reads one, never chooses one, and never types the menu |
| `scripts/diff-render.sh` | step 3, once | Says per path whether GitHub will render that file's diff, which is what decides the URL form for a line inside it |
| `scripts/excerpt.sh` | step 9 | Generates the collapsed source excerpts — the quotation has to be the real bytes |
| `scripts/ledger-rows.sh` | step 10 | Generates the diff inventory the evidence foot holds, and its deep links, from the diff |
| `scripts/coverage-gate.sh` | step 10 | Runs the completeness check |
| `scripts/page-lint.sh` | step 10 | Reads the finished page: placeholders are a FAIL to fix, a tier that disagrees with the diff is a WARN to read |
| `scripts/usage.sh` | steps 1 and 10, outside Claude Code | What the run spent, for a host with no status line to show it — the host reference says when. Its line goes in chat, never on the page |

Paths are relative to this skill's base directory; do not rely on a plugin-root environment
variable such as `$CLAUDE_PLUGIN_ROOT`, which is not set in the shell.

One bundled file is not one you read: `references/claim-falsifier.md`, the independent reader's
mandate. At `--effort high`, which is the default, a reader is sent at each analysis note this run
wrote at the end of step 6, and its challenges are folded in at step 8. You hand that reader the
mandate's absolute path; you never load it yourself — its instructions are its own, which is the
point of putting them in a separate context. The host reference owns how the reader is launched.

## The run at a glance

Copy this into your own notes and tick it as you go; a long run loses its place in the middle.

- [ ] 1 · Resolve the target, the settings, `$W` and the link rung (`--update`: read `references/update.md`)
- [ ] 2 · Detect the stack, read its discovery file, record the versions
- [ ] 3 · Inventory the diff; ask `diff-render.sh` which files GitHub withholds
- [ ] 4 · Derive what changed → **stage 1 publishes** (skeleton, masthead, *What changed*)
- [ ] 5 · Read the lens's sections, trace consumers, record every search
- [ ] 6 · One analysis note per flow; at `high`, send the falsifiers and keep working
- [ ] 7 · Read `report-format.md`, synthesise into `agenda.md` → **stage 2** (stubs, then each checkpoint) → **stage 3** (Context, impact)
- [ ] 8 · Verify every claim before it lands; fold the falsifiers' challenges in
- [ ] 9 · Write by `Edit` only, generated excerpts only
- [ ] 10 · Reading path, inventory, **coverage gate**, lint, banner off → **stage 4**, then say it is complete

## 1. Resolve the target and the effort

- Argument may be a PR number, a PR URL, a branch, or a diff range. With no argument, use the
  current branch against its base.
- **There is one page shape, and no flag chooses it.** No argument selects a length, a depth or a
  second document, and there is nothing to map one onto if someone invents one. An argument starting
  with `--` that is not one of `--effort`, `--mentor`, `--context`, `--output`, `--update`, `--repository`,
  `--base-sha` or `--head-sha` with its value is **reported, not guessed at**. A misread flag silently produces the
  wrong run, and the reader has no way to tell.
- **Read the repository's settings before the flags that override them.** If the repository's top
  level has an `.accountable-review.yml`, run, once:

  ```sh
  <skill base directory>/scripts/read-config.sh "<repo top level>/.accountable-review.yml"
  ```

  It prints one `CFG_<key>='<value>'` line per key the file sets and nothing for a key it does not.
  `CFG_effort`, `CFG_mentor` and `CFG_context` are the team's standing answers, and the order is
  **flag, then file, then default** — the same order CI applies, so a person's run and a CI run of
  the same repository start from the same settings. `CFG_mentor` reads as the flag would: `true`
  is a bare `--mentor`, `false` is off, a stack name is checked at step 2 like one on the command
  line. `CFG_theme` is `page-skeleton.sh`'s, which reads it itself; `update`, `trivial_*` and
  `delivery` are CI's and change nothing here — `--update` is only ever a flag on this skill.

  **A non-zero exit stops the run**, with the parser's message: the file names a key or a value
  that does not exist, and a setting read as nothing is a team's decision silently replaced by a
  default — the unknown-flag rule, one file over. The file read is the working tree's, which is the
  copy the person has checked out. Say in chat which settings came from it.
- **The page has a word budget, stated as guidance, and you write to it rather than trimming to
  it.** `references/report-format.md` § *The agenda budget* owns the numbers, and you read it with
  the rest of that file at step 7, before a word of the page is drafted. It caps prose and nothing
  else, and **the number it never touches is the checkpoint count.**
- **Resolve the page settings — effort, mentor, context — flag first, then the file, then the
  default**, and hold them for the whole run. Every value not listed below is **reported, not
  guessed at**: a flag read wrongly is work that silently differs, with nothing on the page to tell
  the reader which run they got.

  | Flag | Values | Default | What it decides | Owned by |
  |---|---|---|---|---|
  | `--effort` | `high`, `low` | `high` | Whether step 6c sends falsifiers at the notes | step 6c, step 8 |
  | `--mentor` | bare, a stack name, `off` | off | Whether a checkpoint may carry a primer | `report-format.md` § *Mentor mode*, step 7g |
  | `--context` | `auto`, `never`, `always`, `collapsed` | `auto` | How much of section 02 the page carries, and nothing else | `report-format.md` § *How much Context*, step 7k |
  | `--output <dir>` | a directory outside the repository | — | Where the page lands: `<dir>/index.html`, nothing published | below |
  | `--update` | — | — | Edit the existing page over the commits since its revision | `references/update.md` |

  **None of them is announced on the page** — no marker, chip, banner or sentence for any setting.
  Two pages of one target at different settings differ in their claims (effort), their primers
  (mentor) or section 02 (context), never in a component that names the setting. Say which settings
  you took, and from where, in chat.

  - **`--effort`.** `high` is the default because it changes what the page finds, and what it costs
    is tokens rather than time: on one 28-file PR the falsifiers cost **23 seconds of blocked
    parent, 0.9% of a 2607-second run**, because they read while the next stage is drafted, and the
    same target at `low` missed five findings the falsified run carried, including the two the
    reviewer most needed. Step 6c says what the tokens are. `--effort low` is for a diff small
    enough that a second reader has nothing to find. **`--effort normal` is accepted silently and
    means `low`** — the old name of the opt-out, still in people's scripts, and the one value that
    is not guessing. Nothing makes a run faster by making the page shorter: the time goes into
    tracing consumers at step 5.
  - **`--mentor`** says the reviewer is new to the **stack** rather than to the change. A stack name
    — `rails`, `elixir`, `phoenix`, `rust`, `react`, `nextjs` — **is checked at step 2, never used to
    choose**: taking it as an override would put a Rails lens over a service that is not Rails.
    `react` agrees with either React stack; `nextjs` only with a Next.js one. A bare `--mentor` is
    the form to prefer; `--mentor off` matters only when the repository's file turned it on.
    `report-format.md` § *Mentor mode* owns the rest — above all the subtraction rule: delete the
    primers and what remains is the page the run would have written without the flag.
  - **`--context`** tunes section 02 and nothing else; `never` compensates nowhere, and `always`
    lowers the bar without filling the section. § *How much Context* owns all four values.
- **`--output <dir>` makes the run non-interactive.** It changes where the page goes and nothing
  else: the page is written to `<dir>/index.html` and **nothing is published** — no `Artifact` call,
  at any stage. Same sections, same depth rules, same excerpt budget, same gate; the moment this flag
  starts meaning a cheaper page, there are two products and only one of them is developed against.

  Three flags travel with it, carrying what `gh` would otherwise be asked for:

  ```
  --repository <owner/repo>   --base-sha <sha>   --head-sha <sha>
  ```

  **Prefer them over anything you derive.** `--base-sha` is `BASE` and `--head-sha` is `HEAD` for
  every diff in this run; do not compute a merge-base over them and do not call `gh` for what they
  already say — a base recomputed from a branch that has since moved describes a revision nobody
  requested. With `--repository` and a PR number the run has what link rung 1 needs without `gh`;
  check reachability as always. The flags are legal on their own.

  `<dir>` must be **outside the repository under review** (the hard rules say why), and holds the
  page and nothing else, because whatever is in it is what gets delivered. **`$W` is unchanged**:
  excerpt fragments and notes still go there, and the page itself is written straight to
  `<dir>/index.html`, so a crash leaves a useful page where the caller looks.
  `ci/generate-review-map.sh` drives this path, supplies all four flags, and refuses to deliver a
  page that does not name its revision or still says it is being written.
- **`--update` re-reads only the commits since the last map**, editing the page that already exists
  where this run would write. `references/update.md` owns every rule about it; read that file before
  acting on the flag. **It is not a level and not an effort**: it never lowers a cap, skips the gate,
  skips step 8 for anything it writes, or admits or removes a component. **With no previous page, or
  when its carry plan refuses, it falls back to a full run and says so in chat** — a full run is
  always the better page, so every way the flag can fail leads to one.
- Find the base *ref*: the PR's base if there is one, else the default branch
  (`git symbolic-ref refs/remotes/origin/HEAD`, falling back to `main`, then `master`). This gives
  you a ref, not a merge point — do not compute a merge-base yourself. The three-dot diff below
  already resolves it, and hand-rolling one is how you end up diffing against a moved base.
- Use three-dot diffs throughout (`git diff BASE...HEAD`) so you see the branch's own work and not
  unrelated commits from the base.
- **Check the working tree** with `git status --porcelain`. Three-dot diffs ignore it entirely, so
  uncommitted edits mean the page can describe code that differs from what the reviewer has checked
  out. Say so in the page and cover the committed state only. If the uncommitted changes are
  substantial enough that the page would be misleading, stop and say why instead.
- If there is a GitHub PR, capture `owner`, `repo`, number, head SHA, title, author, body via
  `gh pr view <target> --json number,title,author,body,headRefOid,headRefName,baseRefName,url`.
  The number and the head SHA are what the links are built from.
- **Record the SHA the diff's left side comes from** as well — `git merge-base <BASE> HEAD` — with or
  without a PR. Deep links need both ends: head for a line that still exists, the left side for a line
  the change removed or for behaviour cited as it was. This is the one legitimate merge-base here, a
  permalink needs a commit rather than a range; keep using `BASE...HEAD` for every diff.
- If `gh` is missing or there is no PR, continue anyway with the local branch. This is a normal
  case, not an error.
- **Fix the work directory now, and derive it rather than choosing it.** Everything this run writes
  goes in one place, named after the target so a re-run recomputes it instead of remembering it:

  ```sh
  W="${TMPDIR:-/tmp}/review-map/<repo>-pr-<N>"      # a PR
  W="${TMPDIR:-/tmp}/review-map/<repo>-<branch>"    # no PR; / in the branch becomes -
  mkdir -p "$W"                                     # the page is $W/page.html
  ```

  Derived, not invented, because step 9 republishes to the same file path across stages and a re-run
  finds the previous page there — `--update` edits it, a fresh run sets it aside — and a
  session-scoped scratch directory cannot satisfy that: the next session gets a different one.
  Whether a fresh run keeps the earlier page's link is the host reference's to say. A fresh run that
  finds a page there moves the directory aside — `mv "$W" "$W.prev-$(date +%Y%m%d%H%M)"`, then
  `mkdir -p "$W"` — before writing anything: never delete it, and never `--force` the skeleton over
  it. Export `W` once and use it in every later command, so excerpt fragments land beside the page
  rather than somewhere they have to be moved from.
- **Fix the deep-link mode now, not at render time.** Check whether the head SHA is even reachable
  on a remote — `git branch -r --contains <HEAD_SHA>`, where **exit 0 and empty output** means it was
  never pushed and every permalink to it would 404. Unpushed branches and worktrees are among the most
  common targets for this skill, so expect this. **A non-zero exit is a state of its own and neither
  of the other two**: git was asked and could not answer, so nothing is known about reachability. Do
  not read it as unpushed — say in the masthead that reachability could not be determined and render
  citations as plain text, rather than asserting a branch is unpushed on an answer git never gave.
  Pick one rung from the ladder in
  `references/report-format.md` § *Deep links* and hold it for every citation. Read that section
  alone now — it is the file's last, so `sed -n '/^## Deep links$/,$p'` prints it whole — and leave
  the rest of the file for step 7: nothing in steps 2 to 6 writes the page, and every token loaded
  here is billed again on each of the requests the tracing makes. This defers one file, the page's
  rules; it is not a rule against reading before step 7 — step 5 reads the stack's lens, because
  its search recipes are the tracing. The rung decides whether anything is
  clickable; it does not decide the form — inside a rung, a line in the diff links to the diff page
  and a line outside it links to a blob, with one exception that is settled per file in step 3 and
  not per citation. At rung 2 there is no PR page, so check the base SHA for reachability too:
  without it there is no `compare` view to anchor into.

## 2. Discover the project

Assume nothing about layout or conventions — this skill travels between repos.

**Detect the stack first**, because it decides which of the bundled files the rest of the run
reads:

- `config/application.rb`, or a `Gemfile`, → **Rails**: the lens file is `references/rails-nextjs.md`,
  the catalogue `references/rails-docs.md`.
- `mix.exs` → **Elixir/Phoenix**: the lens file is `references/phoenix-liveview.md`, the catalogue
  `references/elixir-docs.md`.
- `Cargo.toml` → **Rust**, and then one more question decides which of the two Rust stacks: **does
  the code this diff touches serve requests?** It does when a crate the diff changes — or a crate
  that one is a path dependency of, inside this workspace — lists a server framework among its
  `[dependencies]`: `axum`, `actix-web`, `rocket`, `warp`, `poem`, `salvo`, `tonic` or `loco-rs`.
  Then it is a **Rust backend**: the lens is `references/rust.md` *and then*
  `references/rust-backend.md`. Otherwise it is **Rust in general** — a library, a CLI, an embedded
  target, a WASM module — and the lens is `references/rust.md` alone. Either way the catalogue is
  `references/rust-docs.md`.

  **A workspace is one root, not several.** A `Cargo.toml` with a `[workspace]` table and a dozen
  members is one Rust project, and the members are where step 5's consumers live; it is never the
  "more than one root" case below. Neither is a workspace that holds one server crate and several
  libraries — the backend question above is answered by what the diff touches, so a change confined
  to a library the server does not depend on is Rust in general even in a repository that serves
  requests. The name of the framework is evidence and its absence is too: a crate depending on
  `hyper` or `reqwest` alone is a client, not a backend.
- `package.json` listing `react` among its `dependencies`, `devDependencies` or `peerDependencies` —
  and no Rails, Phoenix or Rust root that this diff touches — → **React**, and then one more question
  decides which of the two React stacks: **does the package this diff touches depend on `next`?** It
  does when the changed files' nearest `package.json` lists `next`, or a `next.config.*` sits beside
  it. Then it is a **Next.js app**: the lens is `references/react.md` *and then*
  `references/nextjs.md`. Otherwise it is **React in general** — a Vite or Create React App
  single-page app, a component library, a React Router or TanStack Router app, the React half of an
  Electron or React Native codebase — and the lens is `references/react.md` alone. Either way the
  catalogue is `references/react-docs.md`.

  **A JavaScript workspace is one root, not several**, for the reason a Cargo workspace is: a
  `workspaces` field, a `pnpm-workspace.yaml` or a Turborepo or Nx config holding an `apps/web` and a
  `packages/ui` is one React project, and the shared packages are where step 5's consumers live. The
  Next.js question is answered per diff, so a change confined to `packages/ui` is React in general
  even in a workspace whose app is Next.js.

  **A client beside a backend is the backend's client, until the diff says otherwise.** A Rails,
  Phoenix or Rust repository carrying a Next.js or React app in `web/` or `frontend/` is the backend's
  stack when the diff touches the backend: its lens already treats the client as the other half of
  the contract, and `rails-nextjs.md`'s client sections are where that half lives. When every changed
  application path sits in the client, it is the React stack instead — detected from the diff, with
  no question to put, by the rule in the next bullet. A repository whose only root is a
  `package.json` with `react` is React, whatever serves its API.
- **More than one root, or one of each** — a monorepo with an `api/` and a `services/`, engines, an
  umbrella, a Rails or Phoenix app carrying a Rust crate for a native extension (`rb-sys`,
  `magnus`, `rustler`), or a Rust or Phoenix service and an unrelated React app side by side —
  **ask which to cover** rather than picking. Same rule as several Rails
  roots, and for the same reason: covering the wrong half produces a page that is confidently about
  code the reviewer is not reading.

  **Look at the diff before asking, and answer it from there when you can.** If every changed
  application path sits under one root, that root is detected rather than chosen and there is no
  question to put. Ask only when the diff genuinely spans more than one.

  **Non-interactively (`--output`) there is nobody to ask, and picking is still forbidden.** So when
  the diff does not settle it, **stop** and say which roots were found and that the run needs one
  named — a missing map is reported by the caller and a confidently wrong one is not. This is the
  case CI meets most often, which is why it is spelled out rather than left to the general rule.
- **None of these** — say so plainly, cover the diff with the stack-independent material (the five
  sections, the checkpoints, the tiers, the impact chains, the evidence foot), and **emit no documentation link and no
  probe.** Do not default to Rails: a Rails lens applied to a Go service invents findings, and a
  catalogue that does not describe this application is the failure every catalogue fails closed to
  avoid.

**If `--mentor` named a stack, check it here and nowhere else.** The detection above is the answer;
the name on the command line is a claim to test against it. Agreement is silent. A disagreement —
`--mentor rails` in a repository whose only root is `mix.exs`, `--mentor rust` in a Rails app
with no `Cargo.toml`, or `--mentor nextjs` on a Vite app — **stops the run**, names both
readings and says to re-run with a bare `--mentor`. It is never correct input, which is why it is
handled like any other flag value that cannot apply rather than resolved in the run's favour: the
likeliest cause is the wrong checkout, and a page confidently about the wrong repository is the
failure a one-line stop is cheap against. What it must never do is let the name pick the lens.

**Detecting the stack is not reading its files.** This step decides *which* pair the rest of the run
uses. The lens is read at step 5, where its search recipes are the work; the catalogue at step 7,
when a claim first asks for a URL. Nothing between here and there needs either, and both are large —
a run that opens them now carries them through the whole of steps 3 to 6, which is where the
consumer tracing happens and where the context is already largest. The versions this step records
come out of `Gemfile.lock`, `mix.lock`, `Cargo.lock` or the JavaScript lock file, not out of the
catalogue.

**Then read the detected stack's discovery file, once, whole**: `references/discover/rails.md`,
`phoenix.md`, `rust.md` or `react.md` — the Rust and React files carry the backend and Next.js
additions in a section of their own. It says what to detect about the application before any
tracing and which versions to record. Read no other stack's; a run whose stack step 2 did not
detect reads none.

**Record the versions the documentation links are pinned to.** This is not bookkeeping: **every
documentation link on the page is pinned with them**, so a run that skipped this step cannot emit a
doc link at all — recording the version is this step's job, and knowing which URL to pin is
step 7's. What to record differs by stack, and so does its shape — the stack's discovery file says
which versions, from which lock file, and in what form.

Each catalogue's § *Pinning* owns the emitted forms. The same versions also decide what the page may
**claim**, because two marks in each catalogue turn a version-sensitive behaviour into a probe rather
than a sentence.

**At `--mentor`, a closed catalogue also decides whether the flag can do anything.** A primer is what
a doc link escalates into and is gated on carrying one, so while `elixir-docs.md` § *Version*
withholds every link a Phoenix run at `--mentor` writes no primers at all and produces the ordinary
page — and the same holds for a React or Next.js run while `react-docs.md` is closed. Say that to
the user, in chat, when the run starts — a flag that silently did nothing is worse than one that
says why it could not. Do **not** say it on the page: a line explaining the absence of
primers is the mentor badge § *Mentor mode* refuses, with an apology attached.

**Frontend.** The discovery file says what the frontend is on this stack — LiveView templates, a
library with none, or on React the application itself — and when to skip what follows. Where a
separate client exists, locate it (`package.json`, `next.config.*`, `app/` versus `pages/`) and find
the seam between the two sides, because that is what a contract judgment is built from:

- the API client or fetch wrapper, and where base URLs and error handling live;
- **whether types crossing the boundary are generated from the backend or hand-written.** Generated
  types drift loudly, at build time. Hand-written ones drift silently, which is the case worth
  hunting;
- runtime validation at the boundary (Zod or similar) and whether it is applied to every response or
  only some;
- the data-fetching layer: React Query, SWR, server components, route handlers.

**Conventions.** Look for the project's own in `CLAUDE.md`, `AGENTS.md`, `docs/`, `README`,
`CONTRIBUTING.md`. If found, check the PR against them. If not, infer the house style from adjacent
unchanged code of the same kind — often more accurate than a stale document. Note which top-level
directories under `app/` (or `lib/<app>/`, a Rust crate's `src/` and the workspace's crate
list, or a React app's `src/` and a JavaScript workspace's `apps/` and `packages/`) exist and what
each holds: that inventory is the evidence
step 7b needs to ask whether a coding decision in this diff departs from one, and a departure it
cannot cite — from this inventory, a convention doc, or the lens file's stack conventions — is a
question it may not ask. A written decision found here is worth noting with its line.

**Architecture, written down.** Look too for what the repository says about its own structure: an
`ARCHITECTURE.md`, ADRs (`docs/adr/`, `doc/architecture/`), and the files a tool enforces boundaries
from — packwerk's `package.yml`, an Elixir `boundary` declaration, an eslint import-restriction rule,
a Cargo workspace's member dependencies. Note each with its path. They are the first source step 7b
cites for an architectural question, and a shift the repository has written down as allowed is no
question at all.

## 3. Inventory the diff

- `git diff --name-status BASE...HEAD` is the source of truth for what changed.
- Bucket every path: migrations and schema, models, routes and controllers and serializers, services
  and jobs and mailers, config and dependencies, backend tests, frontend source, frontend types and
  API client, frontend tests, agent and developer tooling, generated files.
- **Keep the full file list.** Every path must appear in the finished page. This is a hard invariant,
  checked in step 10.
- **Ask which of those files GitHub will actually render**, at link rungs 1 and 2, and hold the
  answer for the whole run:

  ```sh
  <skill base directory>/scripts/diff-render.sh BASE HEAD --collapsed-only
  ```

  Every path it prints is one whose diff sits behind *Load diff* — a generated file, a lockfile, a
  binary, a diff past 400 lines or 20 KB — so **a citation into one of those takes the blob form even
  though the line is inside the diff**, because a diff anchor there lands on a stub with the cited
  line nowhere in the page. Nothing about the page says which files these were; the only thing that
  changes is the href, and `references/report-format.md` § *When the diff will not render* owns the
  rule, the asymmetry and what the excerpt beside such a claim has to be. Read its trailing summary
  too: past 300 files or 1 MB of diff, GitHub withholds files that are individually small, and that
  is a limit to state in prose rather than to guess at per link. At rungs 3 and 4 there are no
  hrefs, so skip this.
- **Notice a uniform transform before you start opening its instances.** A rename, a codemod, a
  regenerated lockfile or a vendored bump shows itself in the cheap signals you already have — a run
  of `R` status letters, eighty files each moving three lines with the same add-to-delete ratio in
  `git diff --numstat`, the paths `--collapsed-only` just printed. **That bulk is one judgment — *is
  the transform uniform, and what did it miss?* — plus an inventory**, so open the exceptions rather
  than the instances: the files where the transform did something different, and the places that
  should have been transformed and were not. Reading the eighty spends the run's scarcest resource on
  the part of the diff carrying the least to decide.
- If the whole diff is trivial (a few files, no migration, no new behaviour), say so and offer to
  stop rather than generate ceremony. A page nobody needs is worse than no page.
  **Non-interactively (`--output`), make the page.** There is nobody to offer to, and the offer has
  already been answered upstream: `ci/application-code.sh` measures exactly this and skips the job
  before the skill is reached, so a run that got here is one that gate judged worth a map. Say the
  diff is slight in *What changed*, as a stated limit, and carry on.

## 4. Derive what changed

Before any layer, establish what the change is *for*. The reviewer cannot judge a mechanism without
knowing the behaviour it is meant to produce.

Answer, concretely: what problem does this solve; what were the user or system use cases; what was
possible before; what becomes possible or changes after; which actors are involved; what are the
primary execution paths.

**Rank your sources by how much they can be trusted:**

| Source | Worth |
|---|---|
| Tests | The best available statement of *intended* behaviour, because someone had to write the expectation down |
| The code itself | What actually happens, which is not always the intent |
| Commit messages | Often carry the *why* that comments do not |
| The PR description | A **claim**. Cite it as intent, never as fact — it is frequently stale or thin, and that gap is exactly what this page exists to close |

Write each behaviour down for yourself as an actor plus a behaviour plus a path, not as a feature
name. This is the notation step 6 clusters on and step 7 builds chains from:

```
A workspace admin archives a project — new time entries are prevented, historical ones preserved.
ProjectSettings → PATCH /api/projects/:id → ProjectsController#update
  → Projects::Archive → Project → projects.archived_at
```

**That is analysis, and it is not the page.** *What changed* gets one paragraph and at most a handful
of bullets — `references/report-format.md` § *Section 1* — and the paths feed step 6's clustering and
step 7's chains rather than being published as a list. A page that opened with five use cases and
their execution paths spent its first screen on material the checkpoints then said again.

**Say which parts you inferred.** Where the intended behaviour is not pinned by a test or spelled out
in code, name the gap instead of smoothing it over: *"It is unclear whether existing time entries stay
editable after archival. No test covers it."* An honest gap is more useful to a reviewer than a
confident guess, and it is the kind of thing they can resolve in one question to the author.

## 5. Trace the flows and find affected-but-unchanged code

**This is the step that makes the page worth generating.** A diff already shows changed lines well.
What no diff shows is the unchanged code those lines just changed the meaning of — and that is where
the expensive bugs are. Spend more turns here than on prose.

**The step's first call is the lens's heading index, before any consumer search**: `grep -n '^## '`
over the lens file the stack selected in step 2 (both files on a Rust backend or a Next.js app).
Then, in the next turn and side by side, `Read` with `offset` and `limit` the file's opening (above
its first `##`), § *Search recipes*, and every section for a layer this diff touches. Skipping it is
not a saving. Its per-layer questions are what a trace improvised from the diff alone does not think
to ask, and a missing finding fails no check: the page just reads complete. A run that greps for its
own guesses in the lens instead of reading those sections finds only what it already knew to look for.

Work outward from each changed thing to its consumers:

| Changed thing | Who you have to go find |
|---|---|
| A method, class, context function or Rust function | Its callers, and anything that subclasses, includes, imports or re-exports it — in Rust, across every member of the workspace |
| A Rust trait, a `pub` item, or an enum a downstream `match` covers | Every implementor and every downstream crate; a new enum variant reaches only the `match`es with a wildcard arm, silently — the exhaustive ones were already fixed for the diff to compile |
| A column or schema field | Whatever exposes it (a serializer, a `Jason.Encoder` derive list, a JSON render module), scopes and queries filtering on it, factories and fixtures setting it, forms writing it |
| A validation, callback or changeset | Every write path that now behaves differently — `update_all` and `insert_all` bypass it in Rails and Ecto alike, and a second changeset function on the same schema is a second write path |
| An enum or status value | Every branch on that value, on both sides of the boundary, including every exhaustive `case` |
| A JSON key or response shape | The API client, the TS type, and every component reading it |
| A LiveView event name | Its `handle_event/3` clause, **and** every `.heex` template and JS hook that fires it. Either half can be the stale one, and no diff shows the two together |
| A route | Anything constructing that URL, including the client and any external caller — and, for a `live` route, which `live_session` block it landed in |
| A job or its arguments | Every enqueue site, plus in-flight jobs already queued with the old shape |
| A migration, on a Rust backend | Every query on the changed columns — and, where queries are compile-time checked, whether the offline query data (`.sqlx/`) moved with it, because an unchanged query checked against stale data compiles |
| A Cargo feature or a dependency's version | Every crate in the workspace that enables it, every `#[cfg(feature = …)]` it gates, and which combinations CI builds |
| A React component's props, a hook's return value, or a context's value | Every place it is rendered or called — including through a barrel re-export, a `lazy()` import, a map of components and a story — and, for a context, which subtrees have no provider above them |
| A query key, a cache tag, or a Next.js server action that writes data | Every reader of that key or tag, and every mutation that should invalidate it; on Next.js, every page that renders the data the action writes against the paths and tags it revalidates |
| A file under a Next.js `app/` or `pages/` tree | The URL it serves: every link, `router.push`, `redirect` and `revalidatePath` to it, the middleware `matcher` that does or does not cover it, and whether a new request-time read made the routes rendering it dynamic |

The lens file the stack selected in step 2 — `references/rails-nextjs.md`,
`references/phoenix-liveview.md`, `references/rust.md` with `references/rust-backend.md` on a Rust
backend, or `references/react.md` with `references/nextjs.md` on a Next.js app — carries the concrete search patterns per artifact kind. Use them;
do not improvise a grep and call the area clear.

**Record what you searched, not just what you found — but the finding goes in the open prose and the
search goes in the collapsed record.** "Nothing else calls `Project#archive`" is the finding, and it
is a sentence a reader meets without opening anything; `rg 'archive[!?]?\b' app lib` is how you know,
and it belongs in `details.searched`, shut, inside the evidence foot. Unrecorded entirely, absence and omission look identical
and the reviewer redoes the work; left *only* inside the toggle, the finding is hidden rather than
disclosed. **One row per search: the command, then what it returned in a clause** — the form and the
budget are `references/report-format.md` § *What was searched*, which owns them.

**Every affected entry needs a row that reproduces it, including one you reached without searching.**
That file is not read until step 7, so the rule is here, where the rows are made: an evaluation re-runs
each recorded search and fails an entry no row returns. The entry this misses is the one found by
following a call — the diff adds `AuditTrail.record(changes: …)`, you open `record` and see what it
does with the hash. Reading the callee is how you found it; a search is how the reviewer re-finds it,
so record the one that does (`rg -n 'def (self\.)?record\b' app`).

**Then measure the structure, on both sides.** For each changed file, note what it now depends on
that its module did not: a reference from one top-level module, context, package or crate into
another, a new writer of a table or a fact, a new process, queue, cache or external call. For each
candidate, search the merge-base too — `git grep -n -P '<pattern>' <merge-base sha> -- <scope>`, with the sha
written out so the recorded row reproduces — because *new* is a claim about the base and the hunk
does not show the base. **The base search measures what the head search measures, at another
revision** — the same pattern and scope wherever `git grep` can carry them; two patterns measure two
facts, and their difference is not a shift. `-P`, not `-E`:
git's ERE takes no `\b`, `\w` or `\s` on macOS and returns nothing rather than failing, which reads
as *absent at the base*. An empty result at the base for
an edge that exists at head is the shift; an empty result at head outside the diff for a kind of
thing the diff adds is a precedent. Record both searches like any other, and write the result into
the flow's note, because step 7 opens nothing the notes have not cited. The lens file's
§ *Architectural questions* has the patterns per stack; searches only, never a tool that compiles or
boots the application to answer.

Then draw the primary flow end to end, from user action to persistence and back, and list the
secondary effects hanging off it. That flow is the run's backbone: step 6 splits it into flows for
analysis, *Impact outside the diff* shows the crossings whole, and the checkpoints are the judgments
it turns on. **Nothing publishes after this step**: the crossings found here reach the page at
milestone 3, after 7c has had its chance to merge two of them into one judgment and after there is a
checkpoint for each card to point at (step 9).

## 6. Cluster into flows, write the analysis notes, spawn the falsifiers

**Group by behaviour, never by directory.** `Services / Models / Hooks / Components` is the repository's
structure, not the change's, and a reviewer who reads it still has to assemble the behaviour themselves.
Group into vertical slices instead — one per use case, each cutting through controller, service, model,
client and tests:

```
Flow A — Archiving a project
Flow B — Preventing time entries against archived projects
Flow C — Showing archived projects in historical reports
```

Say why you split it that way, to yourself. The split *is* the insight, and it is what keeps a
checkpoint from turning out to be a directory.

**The flow is the unit of ANALYSIS and never a unit of the page.** Nothing below writes a flow
section: a flow becomes a note, the note is what gets attacked, and step 7 turns notes into the
ranked handful of judgments the reader actually gets.

**And no sentence on the page ever names one.** These letters are yours, for the notes in
`$W/analysis/` and for your own ranking; the page's designators are *Checkpoint A* and *Impact path
A*, which are the reader's. A checkpoint reading *"a leader-opened thread (Flow A) has no
`connection_id`"* has pointed at a section nobody wrote. It is easy to write and hard to see, because
the note you are holding, the checkpoint you are writing and the impact path beside it are all
lettered — `references/report-format.md` § *One canonical home* owns the rule.

**Nor does the page ever write `§`.** This file and its references use it for their own headings —
*§ Something* — and pages have carried it as *§ 01* for *What changed*; the page has no such names
and nothing that links them, so a `§` that reaches a sentence points nowhere a reader can go. Name a
section of the page by its title, linked to its id; name a heading in a repository file in words,
with the file cited; or, best, say the thing the section stood for. Same rule, same owner.

Then label each flow and each leftover file, for your own ranking in step 7 — the label reaches the
page only as what *What changed* leads with and what the agenda leaves off:

- **Primary** — directly implements the stated use cases.
- **Supporting** — refactors or infrastructure the primary behaviour needed.
- **Secondary** — independently reviewable, outside the primary mental model.

**Stay neutral about secondary work.** The point is to tell the reviewer which changes they can hold
separately, not to criticize the author for bundling. "Appears unrelated to archival; no correctness
concern identified; review independently" is the whole register.


### 6b. Write one analysis note per flow

Before anything is synthesised, write `$W/analysis/flow-<x>.md` for each flow — plain markdown, no
page markup. It is the record the falsifier attacks and the record step 7 ranks from, so it is
written for both readers at once: complete, cited, and dull.

Each note carries, under these headings:

- **Behaviour** — the actor, the behaviour and the path, from step 4.
- **Trace** — every hop with a `file:line`, in execution order, and the hunk each changed hop turns
  on.
- **Affected, not changed** — one entry per finding: `path:line`, the clause on why the change
  reaches it, and its evidence tier written out (`diff`, `from unchanged code`, `inferred from
  tests`, `inferred`, `uncertain`). Write the tier on **every** entry here, the `diff` ones included.
  On the page silence means the first tier; in a note silence is a claim nobody labelled, and the
  falsifier is told to treat it as one. **Affected means a file `git diff --name-only` does not
  list**: an untouched method inside a changed file goes in *Trace*, because the page splits changed
  from unchanged by file and a run that files it here draws it teal and labels it
  `from unchanged code` on a page whose inventory lists the file as changed. **And it means the
  change reaches it.** Code the search found that the change does *not* reach — the check that
  reads a value the change stores nowhere, the status computation whose inputs an edit leaves alone
  — is insulation: file it under *Trace* or *Open* as evidence for whichever judgment asks whether
  it is reached, never here, because whatever is filed here becomes an *Affected, not changed* entry.
- **Searched** — one line per search, the command then the result clause, in the form
  `details.searched` will take. **Every *Affected, not changed* entry is in some line's output**;
  for one you reached by opening a callee rather than by searching, add the search that finds it
  now. The reviewer re-finds an entry by re-running the record; one no line returns is an assertion
  however true it is, and a later run's replay of the record cannot see it.
- **Tests** — which behaviour each pins, which branch it leaves open.
- **Open** — what you could not establish, and what would settle it.

**Why a file and not a slice of the page.** A note can be attacked before any of it is public, and
the falsifier reads claims rather than markup, excerpts and a rail. It also survives the run: on a diff that strains the context, `$W/analysis/` is what says which
region got a trace and which got skimmed.

### 6c. At `--effort high`: send the falsifiers at the notes

Everything so far is this run checking its own work. That is the weakest kind of check — the context
that wrote a claim is the one least able to see what it assumed. At `--effort high` the notes get a
second reader whose only job is to break them.

**When.** Here, as soon as the notes are written, and **before any of it reaches the page**, so a
corrected claim is never one a reader saw.

**How.** One independent reader per note, launched the way **your host reference** says — Claude
spawns the registered `accountable-review:claim-falsifier` agent (a general-purpose one when
installed without the plugin), and every other host works down its reference's ladder: its own
subagent tool, else a read-only background run of its own CLI —
**up to the host’s available concurrency.** This is the one exception to the rule against subagents in
§ *Hard rules*.

**Then keep working — do not wait on them.** They come back as notifications, not as a blocked turn,
and the parent's job in the meantime is step 7. Launch receipts come back in seconds and the first
challenges minutes later, which is why the pass costs under 1% of the run's wall clock — and only
while you keep drafting. A run that spawns them and then idles has converted the cheapest thing in
this procedure into the most expensive.

**Cheap in wall clock is not free in tokens, and the cap is what holds both costs down.** Each
falsifier reads in its own context, and those tokens are the run's: with one note per falsifier the
pass came to **2-5% of every cache-read token the run spent**, over 13-33 requests, and none of it
shows in the parent's transcript — `evals/profile.sh` reads the subagents' to count it. It is that
small because a note is all a falsifier reads; hand one more than its note and the share grows with
what it was handed. Claude's falsifier runs on its own model (`agents/claim-falsifier.md`), so that
share can be bought down without touching the wall clock; Codex inherits its configured model, and
both measurements are from Claude runs.

The other cost lands in your context, not theirs: every challenge comes back to you, and step 8 has
you open its cited file before acting on it. That is the cap's real job. Six agents is the point past
which a second reader stops paying for itself — in their tokens and in the verification each
challenge asks of you.

Launch the selected readers without waiting between launches, up to the host’s concurrency
limit. Queue any remaining notes and continue drafting; one blocking spawn is the failure the hard
rules describe.

Give each agent four things and no more: the absolute path of `references/claim-falsifier.md`, which
it is asked to read first; the repository path; `BASE` and `HEAD`; and **the path of that one note**.
Not the whole set — a falsifier holding every note is one long blocked turn again, and it has no way
to tell which claims are its to attack.

**Cap it at six.** Past that, take the notes carrying the most *affected, not changed* entries and
the most `inferred` and `uncertain` tiers. Those are the claims a reader cannot check cheaply, which
is the only reason to spend an agent on them.

## 7. Synthesise the agenda

The notes are the analysis. This step turns them into the page's argument, and it is a step of its
own because the failure it prevents is structural: a run that goes from notes straight to prose
writes one section per flow, which is the page this one replaced.

**Read `references/report-format.md` now, whole**, if this run has not — step 1 read only its
§ *Deep links*. Every rule about the page lives there, and from here to step 10 the run is writing
the page. **Read it in one turn**: four `Read` calls side by side, at offsets 1, 701, 1401 and 2101
with a limit of 700 each, and one more at 2801 only if the last came back full. A `cat` spills past
the output limit into a file that then comes back one chunk per request, and each of those requests
re-bills the whole context the run has built by now.

Nothing else here opens a file the notes have not already cited. The work is deciding, not tracing. Do it
in this order, and write the outcome of each part into `$W/analysis/agenda.md` before moving on — the
falsifiers' challenges are arriving while you do this, and a written agenda is what lets step 8 fold
one in without re-deriving the ranking.

**7a. Name the semantic delta.** One sentence: what is true of the system after this change that was
not true before, in behavioural terms. Not what files moved — what a user, an operator or a
downstream caller now experiences differently. If the notes support two unrelated sentences, the PR
bundles two changes and *What changed* says so, neutrally. This sentence is the spine of section 01,
and almost every checkpoint has to be a judgment about it.

**Almost, because there are three kinds of checkpoint and only the first answers to this sentence.**
A **behavioural** checkpoint is a judgment about the delta — what the system now does. An
**architectural** checkpoint is a judgment about what the change makes true of the system's
structure: a dependency that now runs a new way, a second owner of a fact, a boundary crossed, a new
runtime component, the first of its kind. A **coding-decision** checkpoint is a judgment about how
the change was built: where a class was put, what kind of object it is, which existing abstraction it
went around. The second and third kinds never displace the first, and 7b to 7e say why and how.

**Then class each delta: behavioural or refactor.** A behavioural delta changes what a user, an
operator or a downstream caller experiences; a refactor intends to change structure and leave
behaviour as it was. Write the class beside the delta's sentence in `agenda.md`. It reaches the page
only through the masthead's *Change shape* chip, which is the class itself — *behavioural*,
*refactor*, or *mixed* when the deltas differ — and it decides the order in 7d. The chip follows your
class, never the PR's title: where the two disagree, *What changed* names the title's claim in a
clause, attributed. **A refactor whose notes show behaviour that moved is
not a refactor**: class it behavioural, and the moved behaviour is its first judgment. The author
calling it a refactor is a claim, attributed, per step 4.

**7b. Identify the human judgments.** For each note, ask what a competent reviewer has to *decide*
rather than *learn*: whether a scope is still the one that was intended, whether a nil default is
safe for every consumer, whether a guard's new order admits a class it used to refuse, whether a
migration is safe to run against the rows that already exist. Write each as a question.

A judgment is something the reviewer could get wrong, with consequences. A fact is something they
read once. Facts feed the explanations; only judgments become checkpoints.

**Then ask the two structural questions, each behind the same bar: no citation, no question.**

- **A coding decision names the departure**: *the PR chose X; this codebase already does Y for the
  same job; is X deliberate?* — a value object under `app/models` where `app/services/` holds four of
  its kind, a query built in a controller where `app/queries/` exists, a lookup table re-declared
  beside the module that already owns it. **Placement is one axis of three** — where it was put,
  what kind of object it is, which existing abstraction it went around — and the third is the one a
  run stops before reaching: a second source of truth for a fact the app already defines. `Y` is
  cited from **this repository's decision** (a convention-doc line, else a populated directory or a
  sibling file step 2 inventoried) or **a stack convention on the lens file's closed list**, through
  its catalogue row, and **the repository outranks the stack**. A convention you know but the lens
  does not list is taste.
- **An architectural question states the shift**: *before this PR, X was not true of the system; at
  `file:line` it now is; is that intended?* — a module that now names one it never did, a second
  writer of a column, an outbound call inside a request where every other one is enqueued, the first
  cache in the app. It is cited from a written decision step 2 found (an ADR, an `ARCHITECTURE.md`, a
  boundary a tool enforces), else from the two searches step 5 recorded, base and head. A shift the
  repository has written down as allowed is no shift.

**A citation admits a candidate; it does not make one.** Something similar existing is where the
question starts, and most candidates end there: `report-format.md` § *Coding decisions* and
§ *Architectural questions* each own three tests, and the one both share is **no reason in any note**
— read the candidate against every note, because the ordering that explains a copy, or the
requirement that explains a shift, is usually in another flow's trace.

**Ask it; never answer it.** No *should have been*, *unidiomatic*, *the Rails way*, *coupled*,
*leaky* or *cleaner*. The reviewer knows why the codebase is shaped as it is and you do not — step
6's neutrality rule is the register, and a decision you cannot resolve goes on the *Open question*
line, not into a verdict.

**In a refactor delta, ask the equivalence first.** A refactor's claim is that nothing a caller sees
moved, so its first judgment is *is behaviour preserved?*, with the lines where it would not be — a
guard reordered, a default that travelled, a callback no longer run, a scope that changed shape. Skip
it only when the notes found no place the two versions could differ. **A behavioural delta owes it
too** where it moves code whose callers are meant not to notice — checks relocated, a 

[…] pełny plik w paczce .zip
Pliki w paczce (302)
  • SKILL.md 113 KB
  • evals/DEFERRED.md 4 KB
  • evals/README.md 60 KB
  • evals/check.rb 4 KB
  • evals/profile-fmt.jq 6 KB
  • evals/profile.jq 14 KB
  • evals/profile.sh 10 KB
  • evals/trigger-eval.json 2 KB
  • evals/verify-catalogue.sh 27 KB
  • evals/checks/build-state.rb 5 KB
  • evals/checks/completeness.rb 2 KB
  • evals/checks/excerpts.rb 11 KB
  • evals/checks/figures.rb 17 KB
  • evals/checks/frozen.rb 7 KB
  • evals/checks/impact-paths.rb 25 KB
  • evals/checks/link-form.rb 11 KB
  • evals/checks/page-invariants.rb 28 KB
  • evals/checks/rails-anchors.rb 47 KB
  • evals/checks/searches.rb 22 KB
  • evals/checks/self-test-cases.txt 35 KB
  • evals/checks/self-test.rb 7 KB
  • evals/checks/start-here.rb 11 KB
  • evals/checks/frozen/build-state.txt 32 KB
  • evals/checks/frozen/completeness.txt 34 KB
  • evals/checks/frozen/excerpts.txt 70 KB
  • evals/checks/frozen/figures.txt 48 KB
  • evals/checks/frozen/impact-paths.txt 145 KB
  • evals/checks/frozen/link-form.txt 107 KB
  • evals/checks/frozen/page-invariants.txt 384 KB
  • evals/checks/frozen/rails-anchors.txt 170 KB
  • evals/checks/frozen/searches.txt 76 KB
  • evals/checks/frozen/start-here.txt 92 KB
  • evals/checks/lib/review_map/changed.rb 2 KB
  • evals/checks/lib/review_map/check.rb 6 KB
  • evals/checks/lib/review_map/fixture.rb 2 KB
  • evals/checks/lib/review_map/page.rb 11 KB
  • evals/checks/lib/review_map/vocabulary.rb 2 KB
  • evals/checks/lib/test/test_page.rb 13 KB
  • evals/e2e/calibrate.rb 13 KB
  • evals/e2e/criteria.yml 2 KB
  • evals/e2e/grade.rb 7 KB
  • evals/e2e/judge.rb 8 KB
  • evals/e2e/lib.rb 7 KB
  • evals/e2e/progress.rb 9 KB
  • evals/e2e/prs.yml 3 KB
  • evals/e2e/report.rb 10 KB
  • evals/e2e/run.rb 11 KB
  • evals/e2e/summary.rb 8 KB
  • evals/e2e/test_grade.rb 8 KB
  • evals/e2e/test_triage.rb 6 KB
  • evals/e2e/triage.html 21 KB
  • evals/e2e/triage.rb 11 KB
  • evals/e2e/verdicts.rb 4 KB
  • evals/e2e/calibration/README.md 6 KB
  • evals/e2e/calibration/status.json 41 KB
  • evals/e2e/calibration/discourse-43002/gold.html 126 KB
  • evals/e2e/calibration/discourse-43002/gold.yml 1 KB
  • evals/e2e/calibration/discourse-43002/labels.yml 8 KB
  • evals/e2e/calibration/discourse-43002/make-defects.rb 28 KB
  • evals/e2e/calibration/discourse-43002/defects/checkpoint-claims-corrected.patch 3 KB
  • evals/e2e/calibration/discourse-43002/defects/checkpoint-claims-explanation.patch 1 KB
  • evals/e2e/calibration/discourse-43002/defects/checkpoint-claims-gap.patch 3 KB
  • evals/e2e/calibration/discourse-43002/defects/checkpoint-claims-lookat-line.patch 1 KB
  • evals/e2e/calibration/discourse-43002/defects/checkpoint-judgments-category.patch 1 KB
  • evals/e2e/calibration/discourse-43002/defects/checkpoint-judgments-ranked.patch 1 KB
  • evals/e2e/calibration/discourse-43002/defects/checkpoint-judgments-unmerged.patch 2 KB
  • evals/e2e/calibration/discourse-43002/defects/checkpoint-judgments-verdict.patch 1 KB
  • evals/e2e/calibration/discourse-43002/defects/evidence-corrected.patch 15 KB
  • evals/e2e/calibration/discourse-43002/defects/evidence-hidden-claim.patch 1 KB
  • evals/e2e/calibration/discourse-43002/defects/evidence-labelled-diff-claim.patch 15 KB
  • evals/e2e/calibration/discourse-43002/defects/evidence-uncited-untouched-line.patch 15 KB
  • evals/e2e/calibration/discourse-43002/defects/evidence-unearned-excerpt.patch 2 KB
  • evals/e2e/calibration/discourse-43002/defects/evidence-unlabelled-inference.patch 16 KB
  • evals/e2e/calibration/discourse-43002/defects/impact-changed-as-affected.patch 4 KB
  • evals/e2e/calibration/discourse-43002/defects/impact-corrected.patch 4 KB
  • evals/e2e/calibration/discourse-43002/defects/impact-false-edge.patch 6 KB
  • evals/e2e/calibration/discourse-43002/defects/impact-why-walks-hops.patch 5 KB
  • evals/e2e/calibration/discourse-43002/defects/impact-wrong-consumer.patch 4 KB
  • evals/e2e/calibration/discourse-43002/defects/reading-path-corrected.patch 4 KB
  • evals/e2e/calibration/discourse-43002/defects/reading-path-false-claim.patch 4 KB
  • evals/e2e/calibration/discourse-43002/defects/reading-path-restates.patch 4 KB
  • evals/e2e/calibration/discourse-43002/defects/reading-path-unreasoned-order.patch 4 KB
  • evals/e2e/calibration/discourse-43002/defects/reading-path-wrong-pointer.patch 1 KB
  • evals/e2e/calibration/discourse-43002/defects/what-changed-coverage.patch 1 KB
  • evals/e2e/calibration/discourse-43002/defects/what-changed-false-limit.patch 1 KB
  • evals/e2e/calibration/discourse-43002/defects/what-changed-grading.patch 1 KB
  • evals/e2e/calibration/discourse-43002/defects/what-changed-headline.patch 1 KB
  • evals/e2e/calibration/discourse-43002/defects/what-changed-steps-as-deltas.patch 1 KB
  • evals/e2e/calibration/discourse-43002/defects/what-changed-unattributed-intent.patch 1 KB
  • evals/e2e/calibration/discourse-43002/defects/what-changed-wrong-delta.patch 1 KB
  • evals/e2e/history/baseline-2212dec.json 21 KB
  • evals/e2e/judges/IDEAS.md 11 KB
  • evals/e2e/judges/checkpoint-claims.md 4 KB
  • evals/e2e/judges/checkpoint-judgments.md 5 KB
  • evals/e2e/judges/evidence.md 7 KB
  • evals/e2e/judges/impact.md 5 KB
  • evals/e2e/judges/reading-path.md 4 KB
  • evals/e2e/judges/what-changed.md 5 KB
  • evals/golden/README.md 5 KB
  • evals/golden/agenda-clean.html 15 KB
  • evals/golden/agenda-probe-unlabelled.html 16 KB
  • evals/golden/agenda-probes-over-budget.html 16 KB
  • evals/golden/anchors-clean.html 2 KB
  • evals/golden/anchors-demo-loose.html 1 KB
  • evals/golden/anchors-docsrs-clean.html 2 KB
  • evals/golden/anchors-docsrs-unpinned.html 1 KB
  • evals/golden/anchors-docsrs-wrong-crate.html 1 KB
  • evals/golden/anchors-fabricated-output.html 2 KB
  • evals/golden/anchors-hexdocs-clean.html 2 KB
  • evals/golden/anchors-hexdocs-unpinned.html 1 KB
  • evals/golden/anchors-hexdocs-wrong-package.html 1 KB
  • evals/golden/anchors-invented-attribute.html 2 KB
  • evals/golden/anchors-invented-scope.html 2 KB
  • evals/golden/anchors-link-alone.html 2 KB
  • evals/golden/anchors-link-in-excerpt.html 2 KB
  • evals/golden/anchors-mixed-series.html 2 KB
  • evals/golden/anchors-nextjs-wrong-router.html 1 KB
  • evals/golden/anchors-primer-clean.html 3 KB
  • evals/golden/anchors-primer-doubled.html 4 KB
  • evals/golden/anchors-primer-marked.html 2 KB
  • evals/golden/anchors-primer-orphan.html 2 KB
  • evals/golden/anchors-primer-over-budget.html 9 KB
  • evals/golden/anchors-primer-probe-nested.html 3 KB
  • evals/golden/anchors-primer-rails-framed.html 2 KB
  • evals/golden/anchors-primer-rust-clean.html 3 KB
  • evals/golden/anchors-primer-rust-unframed.html 2 KB
  • evals/golden/anchors-primer-uncited.html 2 KB
  • evals/golden/anchors-primer-ungated.html 2 KB
  • evals/golden/anchors-probe-js-forms.html 2 KB
  • evals/golden/anchors-probe-label-thin.html 2 KB
  • evals/golden/anchors-probe-legit-forms.html 3 KB
  • evals/golden/anchors-probe-lens-forms.html 3 KB
  • evals/golden/anchors-probe-rust-forms.html 2 KB
  • evals/golden/anchors-probe-sandbox-lie.html 2 KB
  • evals/golden/anchors-probe-unlabelled.html 2 KB
  • evals/golden/anchors-reactdocs-clean.html 2 KB
  • evals/golden/anchors-reactdocs-unpinned.html 1 KB
  • evals/golden/anchors-runner-mutates.html 2 KB
  • evals/golden/anchors-uncatalogued-url.html 2 KB
  • evals/golden/anchors-unpinned-link.html 2 KB
  • evals/golden/build-state-updated-clean.html 1 KB
  • evals/golden/build-state-updated-missing.html 1 KB
  • evals/golden/build-state-updated-nosha.html 1 KB
  • evals/golden/build-state-updated-twice.html 1 KB
  • evals/golden/context-clean.html 4 KB
  • evals/golden/context-collapsed.html 4 KB
  • evals/golden/context-dead-pointer.html 4 KB
  • evals/golden/context-no-pointer.html 4 KB
  • evals/golden/context-shift-only.html 4 KB
  • evals/golden/excerpt-at-head.html 2 KB
  • evals/golden/excerpt-clean.html 1 KB
  • evals/golden/excerpt-diff-lang.html 1 KB
  • evals/golden/excerpt-duplicate.html 1 KB
  • evals/golden/excerpt-linked-clean.html 1 KB
  • evals/golden/excerpt-linked-duplicate.html 1 KB
  • evals/golden/excerpt-open.html 1 KB
  • evals/golden/excerpt-overlap-clean.html 1 KB
  • evals/golden/excerpt-overlap.html 1 KB
  • evals/golden/excerpt-typed-highlight.html 1 KB
  • evals/golden/excerpt-typed-tag.html 1 KB
  • evals/golden/excerpt-unchanged-changed-file.html 1 KB
  • evals/golden/figures-chain-aff.html 1 KB
  • evals/golden/figures-clean.html 4 KB
  • evals/golden/figures-context-chain.html 2 KB
  • evals/golden/figures-converge-grading-note.html 1 KB
  • evals/golden/figures-converge-one-path.html 1 KB
  • evals/golden/figures-converge-rel.html 1 KB
  • evals/golden/figures-converge-target-loc.html 1 KB
  • evals/golden/figures-lifecycle-aff.html 1 KB
  • evals/golden/figures-lifecycle-method-label.html 1 KB
  • evals/golden/figures-lifecycle-no-loc.html 1 KB
  • evals/golden/figures-shift-clean.html 3 KB
  • evals/golden/figures-shift-in-checkpoint.html 3 KB
  • evals/golden/figures-shift-no-cases.html 3 KB
  • evals/golden/figures-shift-not-moved.html 3 KB
  • evals/golden/figures-shift-one-moved.html 3 KB
  • evals/golden/figures-shift-one-pointer.html 3 KB
  • evals/golden/figures-structure-erd.html 2 KB
  • evals/golden/figures-two-figures.html 2 KB
  • evals/golden/figures-unknown-kind.html 1 KB
  • evals/golden/impact-aff-changed-file.html 5 KB
  • evals/golden/impact-aff-ledger-clean.html 4 KB
  • evals/golden/impact-card-no-lanes.html 4 KB
  • evals/golden/impact-entities-vocab-clean.html 5 KB
  • evals/golden/impact-four-paths.html 6 KB
  • evals/golden/impact-loc-not-last.html 4 KB
  • evals/golden/impact-loc-on-outcome.html 4 KB
  • evals/golden/impact-missing-loc.html 4 KB
  • evals/golden/impact-no-affected.html 3 KB
  • evals/golden/impact-no-outcome.html 4 KB
  • evals/golden/impact-no-why.html 4 KB
  • evals/golden/impact-prose-nodes.html 5 KB
  • evals/golden/impact-shared-card.html 4 KB
  • evals/golden/impact-two-locators.html 4 KB
  • evals/golden/impact-unlabelled-edge.html 4 KB
  • evals/golden/impact-why-citation.html 4 KB
  • evals/golden/impact-why-variant-class.html 5 KB
  • evals/golden/invariants-assurance.html 1 KB
  • evals/golden/invariants-bill-in-comment.html 1 KB
  • evals/golden/invariants-bill-in-prose.html 1 KB
  • evals/golden/invariants-clean.html 1 KB
  • evals/golden/invariants-draft-narration.html 2 KB
  • evals/golden/invariants-flow-designator.html 2 KB
  • evals/golden/invariants-flow-io.html 1 KB
  • evals/golden/invariants-loose-data-path.html 1 KB
  • evals/golden/invariants-no-tier.html 1 KB
  • evals/golden/invariants-risk-score-leading.html 1 KB
  • evals/golden/invariants-risk-score-trailing.html 1 KB
  • evals/golden/invariants-risk-score.html 1 KB
  • evals/golden/invariants-section-sign-quoted.html 1 KB
  • evals/golden/invariants-section-sign.html 1 KB
  • evals/golden/invariants-severity-chip.html 1 KB
  • evals/golden/invariants-shape-missing.html 15 KB
  • evals/golden/invariants-shape-reflowed.html 15 KB
  • evals/golden/invariants-shape-retired.html 15 KB
  • evals/golden/invariants-shape-spelling.html 15 KB
  • evals/golden/invariants-shape-wrapped.html 15 KB
  • evals/golden/invariants-standing-disclaimer.html 2 KB
  • evals/golden/invariants-strip-files.html 15 KB
  • evals/golden/invariants-strip-kind.html 15 KB
  • evals/golden/invariants-tier-clean.html 2 KB
  • evals/golden/invariants-tier-modifier-only.html 1 KB
  • evals/golden/invariants-tier-on-changed.html 2 KB
  • evals/golden/invariants-tier-uncited.html 2 KB
  • evals/golden/invariants-tier-unlabelled.html 2 KB
  • evals/golden/invariants-update-assurance.html 1 KB
  • evals/golden/invariants-update-clean.html 1 KB
  • evals/golden/invariants-update-narration.html 1 KB
  • evals/golden/invariants-update-recency.html 1 KB
  • evals/golden/invariants-update-resolved.html 1 KB
  • evals/golden/invariants-verdict.html 1 KB
  • evals/golden/links-clean.html 2 KB
  • evals/golden/links-collapsed-anchor.html 1 KB
  • evals/golden/links-collapsed-no-excerpt.html 1 KB
  • evals/golden/links-range-truncated.html 1 KB
  • evals/golden/links-repo.sh 2 KB
  • evals/golden/links-unknown-anchor.html 1 KB
  • evals/golden/reach-clean.html 5 KB
  • evals/golden/searches-bre-dialect.html 1 KB
  • evals/golden/searches-clean.html 2 KB
  • evals/golden/searches-context-beyond.html 1 KB
  • evals/golden/searches-context-flag.html 1 KB
  • evals/golden/searches-git-grep.html 2 KB
  • evals/golden/searches-other-tree.html 2 KB
  • evals/golden/searches-unreachable.html 1 KB
  • evals/golden/start-here-clean.html 1 KB
  • evals/golden/start-here-no-why.html 1 KB
  • evals/golden/start-here-orphan-checkpoint.html 15 KB
  • evals/golden/start-here-style-comment.html 16 KB
  • evals/golden/start-here-two-lists.html 2 KB
  • evals/golden/verdicts-bad-value.json 1 KB
  • evals/golden/verdicts-clean.json 1 KB
  • evals/golden/verdicts-fenced.json 1 KB
  • evals/golden/verdicts-mixed.json 1 KB
  • evals/golden/verdicts-prose.json 1 KB
  • evals/golden/verdicts-short.json 1 KB
  • evals/golden/searches-repo/README.md 1 KB
  • evals/golden/searches-repo/app/controllers/projects_controller.rb 1 KB
  • evals/golden/searches-repo/app/models/project.rb 1 KB
  • evals/golden/searches-repo/src/archive.rs 1 KB
  • evals/golden/searches-repo/src/components/ProjectCard.tsx 1 KB
  • evals/results/.gitkeep 1 KB
  • references/claim-falsifier.md 6 KB
  • references/elixir-docs.md 18 KB
  • references/nextjs.md 24 KB
  • references/page-template.html 170 KB
  • references/phoenix-liveview.md 35 KB
  • references/rails-docs.md 24 KB
  • references/rails-nextjs.md 31 KB
  • references/react-docs.md 18 KB
  • references/react.md 33 KB
  • references/report-format.md 205 KB
  • references/rust-backend.md 25 KB
  • references/rust-docs.md 21 KB
  • references/rust.md 35 KB
  • references/update.md 11 KB
  • references/discover/phoenix.md 2 KB
  • references/discover/rails.md 1 KB
  • references/discover/react.md 3 KB
  • references/discover/rust.md 3 KB
  • references/hosts/claude-code.md 4 KB
  • references/hosts/generic.md 6 KB
  • references/themes/daylight.html 9 KB
  • references/themes/field-notes.html 13 KB
  • references/themes/workshop.html 14 KB
  • scripts/carry-plan.sh 21 KB
  • scripts/coverage-gate.sh 4 KB
  • scripts/diff-render.sh 10 KB
  • scripts/excerpt.sh 18 KB
  • scripts/ledger-rows.sh 6 KB
  • scripts/page-lint.sh 10 KB
  • scripts/page-skeleton.sh 10 KB
  • scripts/read-config.sh 11 KB
  • scripts/usage.sh 8 KB
  • tests/activity.rb 6 KB
  • tests/budgets.yml 2 KB
  • tests/codex-plugin.rb 5 KB
  • tests/frontmatter.rb 4 KB
  • tests/run.rb 1 KB
  • tests/self-test.rb 39 KB

Wersje

W bazie nie ma innych skilli o nazwie review-map.

Migawka bazy z 28.10.2026 · wersja paczki 71947e63dde2 (skrót SHA-256 całej paczki)

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 90pr-review
    Przygotowuje analizę pull requesta na pięciu poziomach, od prymitywów kodu po cel, z tym, co się zmieniło, co może się zepsuć i jakie decyzje podejmuje człowiek.
  • 100code-review
    Recenzuje pull request, merge request, gałąź lub diff, audytuje zmienione pliki i sprawdza jakość kodu.
  • 100pr-explainer
    Tworzy przystępną, samodzielną stronę HTML w katalogu .pr-review/ pomagającą recenzentom zrozumieć pull request: co się zmieniło, dlaczego i jak wpisuje się w system.
  • 100understand-diff
    Ustala, czego dotyka gałąź, pull request lub niezatwierdzona zmiana i kto od niej zależy, na grafie wiedzy Understand-Anything, i zapisuje plik nakładki podświetlany w dashboardzie.
  • 100explain-diff
    Wyjaśnia zmianę kodu, diff, gałąź, commit lub PR jako bogatą samodzielną stronę: tło, intuicję z przykładami, przejście w porządku wykonania, co może się zepsuć i quiz sprawdzający zrozumienie.
  • 100understand-diff
    Analizuje git diffy i pull requesty, by zrozumieć, co się zmieniło, które komponenty są dotknięte i jakie są ryzyka.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.