docs: the README, shorter and with every lens
Half the words, the same facts: what it reviews, what the machine provides, the config's keys, a run, and every lens of every mode in one place - the kernel modes' ten and the persona were prose before. The migration, sandbox and build sections stay out; AGENTS.md has them.
This commit is contained in:
parent
90e1725313
commit
f5a674f13f
1 changed files with 65 additions and 57 deletions
122
README.md
122
README.md
|
|
@ -1,21 +1,16 @@
|
|||
# Crafter Review
|
||||
|
||||
The pre-push review pipeline: adversarial lenses review a frozen commit range, one `claude --print` process per inventory unit, before the range is pushed. Five lenses in a fixed order: the approach, the range exercised in the running application through the Playwright MCP server, side by side the static bug proof and the security review, and last the commit truth of the messages and the documentation. Every lens is off until the repository's config turns it on, and the config says what each gets: the browser, the local Supabase database, both, or neither.
|
||||
Adversarial review before a push or a send. A range of commits is frozen, cut into units, and every unit is read by review lenses - one `claude --print` process each - in a fixed order of gates. Each lens asks one question and reports defects with their evidence; a gate passes when its lenses find nothing, and the last gate is the owner, who approves the exact frozen hash. A static lens's clean read of a unit is kept and reused only once three rounds have read it clean.
|
||||
|
||||
| Gate | Lens | Question |
|
||||
|---|---|---|
|
||||
| 1 | `repo-better-solution` (a whole pass gating code blocks) | the right mechanism, layer and commit shape? compatible with what users have? |
|
||||
| 2 | `repo-functional` (a whole pass gating code blocks; the `browser` or `browser+supabase` environment) | in the running application, does the range do what its code and messages say, and does it leave the flows next to it working? |
|
||||
| 3 | `repo-bug-prover` (code blocks, static; with the database a proof may also run there) | a demonstrated defect in the range's code |
|
||||
| 3 | `repo-security` (code blocks, static, beside the bug-prover) | a demonstrated gap in a protection the repository promises |
|
||||
| 4 | `repo-facts` (message blocks, documentation blocks and the `whole:order` / `whole:absent` slots, static) | every claim in every commit message, and in the documentation the range adds or changes, proven or gone |
|
||||
| 5 | the owner | approves the exact frozen hash, then the push happens |
|
||||
It reviews three kinds of artifact:
|
||||
|
||||
crafter-review's prompts, reuse keys, exit codes and shared files are pinned byte for byte by its goldens (`tests/Goldens`): a review one driver started, another resumes and reuses, and every driver on a machine sees the others' passes on its seat board.
|
||||
- `commits`: a commit range of one of your own repositories, before the push;
|
||||
- `series`: a kernel patch series as `git format-patch` exports it, with its cover letter, before the send;
|
||||
- `reply`: a mailing-list reply draft.
|
||||
|
||||
## Install
|
||||
|
||||
crafter-review ships as a Flatpak with its own git, Node (for the Playwright MCP server) and ripgrep, so every machine reviews with the same tools. Inside it the lenses see the host's filesystem, with the host's `/usr` at `/run/host/usr`, but not the user and system Flatpak installations (`~/.local/share/flatpak` is empty in the sandbox, `/var/lib/flatpak` absent, by Flatpak's rule): a repository whose dependencies live in another Flatpak points its lens sections at the host's copies.
|
||||
crafter-review ships as a Flatpak with its own git, Node and ripgrep, so every machine reviews with the same tools.
|
||||
|
||||
```bash
|
||||
flatpak remote-add --if-not-exists catcrafts https://flatpak.catcrafts.net/catcrafts.flatpakrepo
|
||||
|
|
@ -23,15 +18,17 @@ flatpak install catcrafts net.catcrafts.CrafterReview
|
|||
alias crafter-review='flatpak run net.catcrafts.CrafterReview'
|
||||
```
|
||||
|
||||
What the machine provides:
|
||||
The machine provides the rest:
|
||||
|
||||
- **The Claude Code CLI.** It is proprietary and not bundled. crafter-review looks for it in this order: `CLAUDE_BIN` or `REVIEW_GATES_CLAUDE_BIN`, the PATH, the editor extensions' bundled binary (newest first), then `~/.claude/local` and `~/.local/bin`. It runs inside the sandbox, so every pass is measured and every pass's process tree can be killed.
|
||||
- **Seats.** The lens processes run on the seats of a dotenv file (`CLAUDE_CODE_OAUTH_TOKEN1..6`, `ANTHROPIC_API_KEY1..6`): `--env-file`, else `$SEATS_ENV_FILE`, else the working directory's `.env` if it is a file holding a seat or a placement setting, or one that cannot be read as UTF-8 text (its read error then stops `run` and `seats`) - a readable application `.env` is passed over, and the run says so - else the machine's own `~/.config/crafter-review/env` (`$XDG_CONFIG_HOME/crafter-review/env`: one file for every repository, a repository's seats `.env` winning over it). Its seat lines go over the process environment's; with no seat in either, this machine's own login. The placement settings among its lines - the seat order, the budgets, the concurrency, the utilisation ceilings - are read with it, under the process environment; any other `REVIEW_GATES_*` line (a path, a binary) is not, and `run` and `seats` name it. `crafter-review seats` probes and reports them. It never prints a token. An account whose 5-hour limit Anthropic has removed shows `no limit` in that column and is placed by its weekly window. Every account takes at most 128 passes at once, every driver's counted, and there is no machine-wide cap beyond that and free memory (`run --concurrency N` sets one).
|
||||
- **Chromium, for a lens with the browser.** Run `crafter-review browser install` once. It installs the Chromium build the pinned `@playwright/mcp@0.0.83` drives into `~/.cache/ms-playwright`, where the MCP server looks. It runs Playwright's own installer, which also removes the browser builds no installed Playwright on the machine refers to.
|
||||
- **A local Supabase stack, for a lens with the database** (`supabase start`, or the repository's own bring-up). The `sql` helper speaks the Postgres protocol itself: no `psql` and no driver to install. Every call is one transaction, rolled back.
|
||||
- **gpg, if your commits are signed.** `freeze` reads each commit's signature through gnupg's keyboxd socket, which is all the sandbox is given. The agent, which signs, stays out of reach.
|
||||
| | |
|
||||
|---|---|
|
||||
| **The Claude Code CLI** | Proprietary, not bundled. Found through `CLAUDE_BIN` or `REVIEW_GATES_CLAUDE_BIN`, the PATH, an editor extension's bundled binary, `~/.claude/local` or `~/.local/bin`. |
|
||||
| **Seats** | A dotenv file with `CLAUDE_CODE_OAUTH_TOKEN1..6` or `ANTHROPIC_API_KEY1..6`: `--env-file`, else `$SEATS_ENV_FILE`, else the working directory's `.env` when it holds a seat or a placement setting, else `~/.config/crafter-review/env`. Its seats go over the environment's; with none, your own login. The file's `REVIEW_GATES_*` placement settings count too. `crafter-review seats` probes them; every driver on the machine shares one seat board. |
|
||||
| **Chromium** | For a lens with the browser: `crafter-review browser install`, once. |
|
||||
| **A local Supabase stack** | For a lens with the database (`supabase start`, or the repository's own bring-up). The `sql` helper speaks the Postgres protocol itself; every call is one transaction, rolled back. |
|
||||
| **gpg** | Only for signed commits: `freeze` reads the signatures through gnupg's keyboxd socket. |
|
||||
|
||||
## Setting a repository up
|
||||
## Set a repository up
|
||||
|
||||
From the repository's toplevel:
|
||||
|
||||
|
|
@ -40,62 +37,73 @@ crafter-review init
|
|||
crafter-review config # edit .review-gates/config.json until it prints no problem
|
||||
```
|
||||
|
||||
`init` does four things:
|
||||
- it writes `.review-gates/config.json` from the template when there is none - the three artifact kinds as modes with every lens of their kind: trim each to what this repository runs;
|
||||
- it adds `.review-gates/push/` and `.review-gates/trees/` to `.gitignore`;
|
||||
- it writes the `/prepush` skill to `.claude/skills/prepush/SKILL.md`, which a later `init` refreshes (the line after its frontmatter marks it as init's), with a `.gitignore` of `*` beside it: the skill is generated from the shipped text, so it stays out of git and every checkout runs `init` once (a tracked copy would lag the installed binary); a skill the repository wrote itself, without that line, is left alone and not ignored, unless `--force`;
|
||||
- it prints the next steps.
|
||||
`init` writes `.review-gates/config.json` from the template when there is none, adds `.review-gates/push/` and `.review-gates/trees/` to `.gitignore`, and writes the `/prepush` skill to `.claude/skills/prepush/`. The skill is generated: it ignores itself in git, and a later `init` refreshes it. `init` writes nothing it did not make, unless `--force`.
|
||||
|
||||
It writes nothing in a subdirectory, in your home directory or over a `SKILL.md`, a `.gitignore` beside it or a link there that it did not make (the old link into the review-gates submodule aside, which it removes); `--force` allows all but the first.
|
||||
`.review-gates/config.json` is committed. It says:
|
||||
|
||||
`.review-gates/config.json` is committed. It says what the pipeline must know about the repository:
|
||||
- who may author its commits, and which branch a range is measured against;
|
||||
- its modes (`modes.<name>`): each an artifact kind (`reply`, `series`, `commits`; a kind is a mode of its own name), the lenses it runs (every lens is off until a mode lists it; they run in their kind's gate order - the table above for commits, the kernel modes' gates below for a series or a reply) and the effort it runs at; `run --mode` names one;
|
||||
- the environment each lens gets (`none`, `browser`, `supabase` or `browser+supabase`);
|
||||
- each lens's own section (`lenses.<name>.section`), a file in the repository appended to that lens's shipped charter, for the calibration entries and conventions that are this repository's rather than the lens's (the reuse keys carry the combined text's hash); a lesson general to the lens goes into the shipped charter;
|
||||
- how its application is started and reached: one stack, or several side by side (`slots`);
|
||||
- where its local database answers;
|
||||
- which paths carry no runtime behaviour.
|
||||
- what `freeze` checks: `authors`, `aiTrailers`, `requireSigned`, and the branch a range is measured against (`base`, `rangeFrom`);
|
||||
- `modes.<name>`: the kind of artifact, the lenses it runs and their effort. Every lens is off until a mode lists it; `run --mode` picks one;
|
||||
- `lenses.<name>`: the environment a lens gets (`none`, `browser`, `supabase` or `browser+supabase`) and, if the repository has one, its `section` - a file of this repository's own appended to the lens's charter;
|
||||
- `functional`, `slots`, `supabase`: how the application is started and reached, one stack or several, and where its database answers;
|
||||
- `allowDirty`, `gate0`: the tracked paths the stack rewrites, and the commands Gate 0 runs by hand.
|
||||
|
||||
`crafter-review doc config` prints the template; `crafter-review doc prepush` prints the procedure, `process/prepush.md`.
|
||||
`crafter-review doc config` prints the template; `crafter-review doc prepush` prints the procedure the `/prepush` skill follows.
|
||||
|
||||
## Running a review
|
||||
## Run a review
|
||||
|
||||
```bash
|
||||
crafter-review freeze --slug <branch> # Gate 0: checks, export, hash, run line
|
||||
# start the application / the stack from the checkout at HEAD, when a lens has the browser / the database
|
||||
crafter-review run --artifact .review-gates/push/<branch>/ --hash <sha256> \
|
||||
--base <sha> --trees . --dispositions .review-gates/push/<branch>/gate-state/dispositions.json --date <date>
|
||||
crafter-review freeze --slug <branch> # Gate 0: the checks, the export, the hash - and the run line
|
||||
crafter-review run … # the line freeze printed (run-line.txt), from a detached shell
|
||||
```
|
||||
|
||||
`freeze` prints the exact run line and writes it to `run-line.txt`; launch from there in a detached shell (`setsid nohup … &`). The exit codes:
|
||||
- 0: SEND-READY (push-ready);
|
||||
- 1: FIX FIRST;
|
||||
- 2: INCOMPLETE, PARTIAL or CONFIRMING (run the same line again);
|
||||
- 3: preflight.
|
||||
Exit codes: 0 SEND-READY, 1 FIX FIRST, 2 run the same line again (INCOMPLETE, PARTIAL or CONFIRMING), 3 preflight. Every finding, note and coverage entry is in the dump, `gate-state/commits-<hash8>-run-<n>.json`. `crafter-review stop --hash <hash8>` kills a run's passes and writes its dump.
|
||||
|
||||
The dump with every finding, note and coverage entry is `gate-state/commits-<hash8>-run-<n>.json`.
|
||||
A directory can review other repositories: `freeze --repo <path> --out <dir> --worktree`, then the printed run line. The config, the seats and the records are the reviewing directory's.
|
||||
|
||||
### Reviewing another repository
|
||||
The kernel modes take `--subsystem <name>`, whose journal (`ledger.md`, `captures/`) is the lenses' evidence, and the trees `--trees` names; lore.kernel.org is read through `utilities/lore.py` in the working directory. `--reviewers "A B,C D"` adds one maintainer persona per reviewer, calibrated on their own lore mail; clean gates without a persona pass are GATES CLEAN, not SEND-READY.
|
||||
|
||||
A directory can review repositories other than itself: a workbench whose config, `.env` and records serve several. From it, `crafter-review freeze --repo <path> --out <dir> --worktree`, then the printed run line. The run reads the repository under review from the artifact's `freeze.json`: the prompt names it, the calibration is kept under it, and `--trees` defaults to the recorded worktree. The config and the slots are the working directory's, the seats file is looked up from it (Seats, above), the lenses run in it, and `--context-paths` are relative to it.
|
||||
## The lenses
|
||||
|
||||
### The kernel modes: a patch series, a mailing-list reply
|
||||
Gates run in order, and each must pass before the next starts. The owner is the last gate of every mode.
|
||||
|
||||
Beside the push gates, crafter-review runs the pre-send review a kernel contributor's workbench keeps: `--mode series` over a `git format-patch` export with its cover letter, and `--mode reply` over a mail draft (a reply's gate-state sits beside the draft). Both take `--subsystem <name>`, whose journal - `journal/<name>/ledger.md`, `captures/`, `captures/threads/` - is the lenses' evidence, and the trees `--trees` names (default `work/linux,work/milos-linux`; history only in the full clone). lore.kernel.org is reached through `python3 utilities/lore.py` in the working directory, which also prefetches every reference the artifact cites into `gate-state/refs/` before the gates run. The series gates are structure (better-solution), code (code-quality, minimalism, bug-prover) and artifact truth (facts, consistency, process-docs, etiquette, conciseness); a reply runs an artifact truth of its own alone (facts, etiquette, consistency, conciseness). `--reviewers "A B,C D"` adds the persona gate after them: one instance of the maintainer-persona lens per reviewer, calibrated on their own lore mail, its whole pass gating its blocks and pruning the units that are not theirs (`--persona-blocks all` keeps them). Gates clean without a persona pass is GATES CLEAN, not SEND-READY. These lenses are off until the config turns them on, like every other; the effort defaults to max, and a reply's units are read once.
|
||||
**`commits`** - a commit range:
|
||||
|
||||
To stop a run, run `crafter-review stop <its scratch dir>`, or `crafter-review stop --hash <hash8>` for every live run of a hash. Its running passes are killed, no later gate starts and the dump is written. A run takes its passes with it however it ends, SIGKILL included: each pass runs under a supervisor that kills its whole tree, the MCP server and Chromium included. `flatpak kill net.catcrafts.CrafterReview` is the hard stop.
|
||||
| Gate | Lens | Asks |
|
||||
|---|---|---|
|
||||
| 1 Approach | `repo-better-solution` | the right mechanism, layer and commit shape? compatible with what users have? |
|
||||
| 2 Functional | `repo-functional` (needs the browser) | in the running application, does the range do what its code and messages say, and leave the flows next to it working? |
|
||||
| 3 Proof | `repo-bug-prover` | a demonstrated defect in the range's code |
|
||||
| 3 Proof | `repo-security` | a demonstrated gap in a protection the repository promises |
|
||||
| 4 Commit truth | `repo-facts` | every claim in every commit message and changed document, proven or gone |
|
||||
|
||||
| Command | What it does |
|
||||
**`series`** - a kernel patch series:
|
||||
|
||||
| Gate | Lens | Asks |
|
||||
|---|---|---|
|
||||
| 1 Structure | `better-solution` | should the series be replaced: another mechanism, layer or shape? |
|
||||
| 2 Code | `code-quality` | the defects a careful subsystem maintainer finds: interactions, error and teardown paths, style |
|
||||
| 2 Code | `minimalism` | can it be done with less: fewer lines, hunks, patches, files? |
|
||||
| 2 Code | `bug-prover` | a demonstrable defect in the code the series produces |
|
||||
| 3 Artifact truth | `facts` | every claim in the cover letter, the messages and the notes, disproved or proven |
|
||||
| 3 Artifact truth | `consistency` | contradictions between the artifacts, the ledger and what was said on-list |
|
||||
| 3 Artifact truth | `process-docs` | the series against the kernel's own in-tree process documentation |
|
||||
| 3 Artifact truth | `etiquette` | how it lands with the humans on the thread: tone, attribution, conventions |
|
||||
| 3 Artifact truth | `conciseness` | the shorter text, every dropped clause accounted for |
|
||||
| 4 Persona | `maintainer-persona` | one named reviewer's reading of the final artifact (`--reviewers`) |
|
||||
|
||||
**`reply`** - a mailing-list reply: Gate 3, artifact truth, with `facts`, `etiquette`, `consistency` and `conciseness`, then the persona gate.
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | |
|
||||
|---|---|
|
||||
| `init`, `config`, `doc` | set a repository up; the merged config and its problems; the shipped texts |
|
||||
| `freeze` | Gate 0: the checks, the export, the hash, the run line; `--verify` at push time |
|
||||
| `run` | the gates of the mode (`--mode`: `commits`, `series`, `reply` or one of the repository's own, as the config defines it): the lenses, the dump; `--dry-run` launches nothing |
|
||||
| `slots` | how many stacks fit in free memory, and the commands for the missing ones |
|
||||
| `config` | the merged config and its problems |
|
||||
| `seats` | every seat probed: both windows, their resets, the drivers running |
|
||||
| `init`, `doc`, `browser install`, `stop` | the setup, the shipped texts, the Chromium, a stop |
|
||||
| `sql`, `totp`, `inventory` | the helpers a lens runs, and the partition of an export, a series or a reply |
|
||||
|
||||
| `run` | the gates of a mode (`--mode`); `--dry-run` launches nothing |
|
||||
| `stop` | stop a run: its passes are killed, the dump written |
|
||||
| `seats`, `slots` | every seat probed; how many stacks fit in free memory |
|
||||
| `browser install` | the Chromium the Playwright MCP server drives |
|
||||
| `sql`, `totp`, `inventory` | the helpers a lens runs; the partition of an artifact into units |
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue