Provisional executable: git-review, normally invoked as git review
Provisional storage file: codereviews.ndjson
Status: design draft for discussion
Schema target: v1
i18n phase: prepare
Primary design goal: answer, with inspectable evidence, who reviewed which code, at which immutable Git state, for what concerns, using what procedure, when, with what findings and independence—and identify code whose review evidence is absent, stale, invalidated, or inadequate for current policy.
Build a Git-native review-evidence ledger and a local-first CLI around it. The ledger records immutable, individually signed events. Each review binds to:
- a stable project identifier;
- an immutable Git commit;
- explicit files and review units within that commit;
- one or more named review scopes;
- reviewer, producer, agent-runner, prompt, tool, and evidence provenance;
- start and completion times;
- structured findings;
- per-scope verdicts;
- facts from which independence can be assessed; and
- enough derived fingerprints to conservatively map unchanged code across later commits, renames, and moves.
The canonical code identity is commit + path + range or blob, not a second content hash. Git already binds the commit to a tree and each path to a blob. Blob IDs, selection digests, syntax-unit identities, and context digests are derived mapping aids and cache fields. They must never disagree with the Git objects from which they are derived.
The canonical ledger is an immutable event set represented as deterministic NDJSON. An optional SQLite database is a disposable query index, never the source of truth.
The tool must support two storage profiles:
- Sideband review branch — recommended. The policy stays on the source branch, while codereviews.ndjson lives on a protected, orphaned code-reviews branch. Its unrelated history and strict tree invariant keep it mechanically separate from product source. Review-only commits do not alter source trees, invalidate Nix flake source hashes, or trigger ordinary product builds.
- Embedded ledger — compatibility/simple mode. codereviews.ndjson lives in the normal source tree and is committed with ordinary repository history. This is easy to understand but causes review-only commits, source/review self-reference problems, merge noise, and potentially costly rebuilds.
Reports must say review evidence coverage, never imply that “reviewed” means “correct,” “secure,” or “bug-free.” A review record can prove who or what attested to a procedure and its results. It cannot, by itself, prove that the procedure was competent or that no defect exists.
At any target commit, the tool must answer:
- Who has reviewed this file, line, symbol, hunk, change, or repository area?
- Which review scopes did each reviewer actually claim?
- Which evidence is historical, and which remains effective now?
- When did each review start and finish?
- Which prompt or review protocol was followed?
- Which model, human, runner, tools, and inputs participated?
- Was the reviewer plausibly independent of the code producer?
- What findings were opened, fixed, accepted, disputed, or superseded?
- Which code has never been reviewed for a required scope?
- Which review evidence is stale under current policy?
- Which code changed enough to invalidate prior review evidence?
- Why did a policy gate pass or fail?
- Can another machine reproduce the mechanical parts of the claim?
- Can humans and LLMs add records without hand-editing NDJSON?
- Work offline after Git objects and any required artifacts are present.
- Be useful in a one-person repository without requiring a server.
- Scale to fleets, monorepos, protected branches, and CI build machines.
- Make concurrent review appends merge safely.
- Keep source history and review evidence independently queryable.
- Preserve all historical review layers instead of collapsing to “latest.”
- Generate attractive terminal, JSON, NDJSON, SARIF, and self-contained static HTML reports from the same pure report model.
- Make advisory adoption easy, then permit progressively stronger enforcement.
- Use deterministic algorithms and injected time/randomness so the core is straightforward to test.
- Keep the on-disk model language- and hosting-provider-neutral.
Version 1 is not:
- a replacement for GitHub, GitLab, Gerrit, email, or conversational review;
- a guarantee of correctness or security;
- a source-code hosting service;
- a full issue tracker;
- a raw transcript archive;
- an employee surveillance or productivity-scoring system;
- a semantic proof that two changed pieces of code are equivalent;
- an autonomous arbiter of whether one LLM model is “better” than another;
- a reason to block all development until historical coverage reaches 100%;
- a web UI, HTTP service, or mutable application for editing attestations;
- a badge/status hosting service; or
- a database server that every local command depends upon.
Lines are excellent report coordinates but weak semantic units. A one-line review can depend on a function, type, invariant, call chain, test, or external contract. The canonical subject therefore uses review selections or review atoms, normally a symbol, diff hunk, contiguous range, whole file, binary blob, submodule pointer, or declared set of related selections.
Reports project those atoms onto line gutters so Peter can ask “who reviewed line 47?” without pretending that line 47 was understood in isolation.
“Are you sure you did not write this code?” is a useful declaration, but it is not independent evidence. A mistaken or optimizing reviewer can answer it incorrectly. The ledger records observable provenance facts:
- known producers and their actor IDs;
- Git authorship and committer data;
- producer-session attestations, when available;
- reviewer actor, runner, and session;
- whether producer and reviewer sessions were isolated;
- whether the reviewer received prior producer conversation;
- whether the reviewer could modify the reviewed worktree;
- whether an external oracle or independent reproducer was used; and
- signatures identifying who attests to each fact.
Policy derives an independence classification from those facts. Unknown stays unknown. A self-declaration alone cannot satisfy a strong independence gate.
A correctness review does not satisfy a security review. A test-adequacy review does not satisfy FFI-boundary review. Fresh shallow review does not erase older deep review, and old deep review does not satisfy a current freshness rule forever.
Every report and gate operates per scope and protocol. An optional overall state is derived from required scopes; it is never a free-standing green boolean stored by a reviewer.
Elapsed time is one staleness input. Other invalidators include changed code, changed context, a superseded protocol, revoked signing keys, newly required scopes, unresolved blocking findings, or a deliberately launched re-review campaign.
A new model release must not automatically stale the whole repository. “Newer” does not mechanically mean “better at this review.” A maintainer may create a campaign that requires a named protocol/model profile for selected paths or scopes, with a recorded reason and bounded rollout.
A mutable database makes fast queries easy but creates backup, synchronization, portability, and trust problems. The NDJSON event set is canonical because it is inspectable, diffable, signable, and carried by Git. A database under .git/git-review/ may be rebuilt at any time and must never contain the only copy of a review, finding, disposition, or signature.
Putting codereviews.ndjson at the repository root is attractive and remains a supported profile. It has serious costs:
- a review can only refer cleanly to a code commit that already exists;
- adding the review creates another commit that the review did not review;
- concurrent reviewers touch the same file;
- the ledger can eventually dominate ordinary source diffs;
- CI may rebuild code even though only review metadata changed; and
- Nix source derivations can change because the tracked source tree changed.
The recommended sideband branch keeps the evidence in the same Git repository and in ordinary commits while preventing those costs. The CLI hides branch plumbing during normal use.
Instructions such as “review carefully” are advisory. Stronger assurance comes from mechanically falsifiable evidence: exact input manifests, reproducible commands, mutation tests, differential results, external oracles, independent producer/reviewer separation, signed runner observations, and protected acceptance gates.
The tool should support an enforcement ladder:
- advisory instructions;
- warnings and visible report states;
- blocking CI policy;
- signed reviewer and runner attestations;
- protected review-ledger writes and trusted receipts; and
- narrowly granted cryptographic capabilities where the threat model actually justifies them.
Projects need not begin at the top, but reports must not overstate the level they have reached.
The branch machinery is deliberately database-like:
- UUIDv7 event IDs are primary keys;
- canonical NDJSON events are immutable rows;
- the protected ref tip is the committed database version;
- compare-and-swap ref updates provide optimistic concurrency;
- the validator provides schema, foreign-key, append-only, and signature constraints;
- Git object IDs provide content addressing;
- fetch/push provide replication; and
- signed bundles provide offline transactions.
Git is not a good query engine, so a local SQLite index supplies joins, coverage projections, full-text search, and report speed. It is rebuilt from the ref and never accepted as evidence on its own.
A coordinating service may also use a transactional database to queue proposed events and serialize writers. Its successful transaction is incomplete until the signed events have been committed to the protected review ref; its database can be lost without losing accepted review history. This gives central constraint enforcement without separating the durable evidence from the repository.
If measured scale eventually exceeds a practical Git ledger, the next step is a dedicated content-addressed ledger repository or transparency service with a signed checkpoint committed into the source repository—not silently making an unexported service database canonical. That migration is outside v1.
Actor
A human, LLM invocation, automated service, runner, or external oracle with a
stable identifier inside the review model.
Producer
An actor known or believed to have authored, generated, transformed, or
substantively directed the reviewed code.
Reviewer
The actor that performed the semantic review and issued findings/verdicts.
Runner
The program or service that assembled inputs, invoked an LLM or tool, captured
outputs, and optionally signed observed execution facts. An LLM normally
cannot protect a private key; its runner can.
Review protocol
A versioned procedure: scope definitions, prompt template, required inputs,
checklist, output schema, tools allowed, completion rules, and evidence
requirements.
Review packet
A content-addressed input manifest presented to a reviewer. It identifies the
subject commit, selections, context, policy, protocol, prompt, and constraints.
Selection / review atom
The smallest unit for which one review validity claim is made. It can project
to many lines.
Context selection
Code or documentation read to understand a target but not itself claimed as
exhaustively reviewed.
Historical review
A valid record that once reviewed a subject. Historical evidence is never
erased merely because it becomes ineffective.
Effective review
A historical review that maps unambiguously to the target commit and satisfies
current policy for scope, age, protocol, independence, signature, context, and
finding state.
Fresh / stale
An effective mapping whose accepted time/protocol falls inside or outside the
current freshness rule.
Changed
The reviewed validity boundary no longer maps unchanged to the target.
Superseded
A later event replaces a record because of correction or a deliberately new
review.
Revoked
An explicit event states that a record must no longer be trusted. Revocation
does not delete history.
Exemption
A signed, time-bounded policy exception with owner, rationale, and scope.
Receipt
A trusted service's statement that it observed a record or ledger commit at a
particular time. Receipts make backdating harder.
Gate
A deterministic policy decision over evidence. The gate is computed, not
reviewer-authored.
Recommended:
codereview-policy.json
.git-review/
prompts/
deep-code-review-v1.md
protocols/
deep-code-review-v1.json
.gitattributes
Only codereview-policy.json is mandatory. Prompt/protocol files may instead live in another content-addressed store, but repository-local versions are easier to audit and reproduce.
The policy contains a persistent project UUID. URLs are metadata, not identity, because remotes can move and forks can have several URLs.
Recommended branch:
refs/heads/code-reviews
It is created as an orphan branch with no common ancestor with any source branch. Its root tree contains exactly:
.git-review-sideband
codereviews.ndjson
README.md
.git-review-sideband is a small machine-readable sentinel containing the schema, project ID, and an explicit do-not-merge marker. README.md explains that the branch is tool-managed and must never be merged. The source policy records the resulting bootstrap commit ID; that ID cannot be embedded in its own tree without creating a circular hash dependency. The sentinel and README blob IDs and file modes are fixed by the bootstrap commit.
Every accepted descendant commit must satisfy the sideband tree invariant:
- It has exactly one parent. The bootstrap commit has none. Merge commits are forbidden.
- Its complete tree contains exactly the three allowlisted paths above; no directories, source files, symlinks, submodules, or additional metadata.
- The sentinel and README blobs and modes are identical to bootstrap.
- codereviews.ndjson remains a normal non-executable file at the same path.
- The only tree change is codereviews.ndjson.
- Every prior ledger event remains canonically identical and every new event passes schema, identity, signature, and append-only validation.
- The commit descends linearly from the configured bootstrap object and from the remote's previously accepted tip.
The reason for this intentionally severe rule is that a sideband branch is valuable only if it cannot become an alternate source tree, an artifact dump, or a route around ordinary review. It also lets a verifier answer “is this really only review evidence?” by examining Git objects, without trusting a working tree or filename convention.
The CLI updates the branch with Git plumbing or an internal temporary worktree; it does not switch the developer's checkout.
Normal clones fetch remote branches, so origin/code-reviews is discoverable. The CLI must still run git review sync because a stale remote-tracking branch must never be silently treated as current.
For repositories where branch naming or hosting policy differs, the ref is configured. A custom ref such as refs/git-review/ledger is permitted, but it requires explicit fetch refspec configuration and is therefore not the default.
git review init may offer to install a versioned local pre-push hook that calls:
git review verify-ref-update OLD_OID NEW_OID refs/heads/code-reviews
This catches accidents and gives fast feedback. It is not authoritative: local hooks are not cloned, can be deleted, and can be bypassed with --no-verify or another Git client.
The remote must enforce the same ref-update predicate before accepting the update:
- on a controlled Git server, install a pre-receive hook that calls verify-ref-update;
- on a forge that supports pre-accept repository rules, make the invariant a required rule;
- where the forge cannot run a trustworthy pre-accept validator, protect the branch so ordinary users/tokens cannot write it and give write authority only to a Git App or Mechatron ledger writer that validates the proposed old/new objects before performing a compare-and-swap update; or
- as a weaker compatibility mode, require a pull request plus the invariant check and clearly report that enforcement is forge-mediated.
A CI job that runs only after an unrestricted push is detection, not prevention, because an invalid tip has already become canonical. It may be a useful alarm but must not be labeled enforced. The report exposes the active enforcement level: local-only, post-accept detection, forge-gated, or pre-accept/capability-gated.
The writer must use a least-privilege credential limited to the review ref where the hosting platform supports it. Source-build credentials do not need review-ledger write access.
The orphaned history is the first mechanical guard: ordinary git merge code-reviews refuses to combine unrelated histories. A person must explicitly request --allow-unrelated-histories to cross that boundary.
Protected source-branch policy adds independent guards:
- Reject any source target whose tree contains .git-review-sideband or the sideband ledger path.
- Reject any source target for which the configured sideband bootstrap commit is an ancestor. This catches an explicit unrelated-history merge even if a later commit deletes the sentinel and ledger.
- Reject a source update containing a parent from the sideband lineage.
- Keep review-ref events out of ordinary source CI triggers, while running the cheap ledger/report pipeline for them.
- Display a loud doctor/status error if the source and review histories ever become connected.
These checks belong in the protected source-branch gate, not only in a local hook. They also explain why the review branch must be orphaned: a normal branch forked from main would already share ancestry, eliminating the strongest accidental-merge tripwire.
If an invalid connection somehow reaches a remote, recovery first preserves the bad tip under an archival ref, records an incident, restores the last verified source/review tips through the hosting authority, and replays only validated review events. The tool never silently force-pushes either branch.
Embedded mode adds this to the normal branch:
codereviews.ndjson
The tool must refuse to claim that the commit containing a new review record was itself covered by that record. A review of code commit C is added in later commit R. Ledger/policy files are excluded from ordinary product-code coverage unless a separate meta-policy explicitly includes them.
Embedded mode should configure a merge driver:
codereviews.ndjson merge=git-review-ledger
The driver is optional in sideband mode but still useful.
All local state is disposable or resumable:
.git/git-review/
index.sqlite
index.meta.json
drafts/
packets/
reports/
locks/
None is committed. Drafts may contain sensitive material and must use owner-only permissions. git review doctor identifies unsafe permissions.
Large prompts, transcripts, screenshots, model responses, test logs, and external reports do not belong inline in NDJSON. An evidence reference stores:
- SHA-256 digest;
- media type;
- byte size;
- retention class;
- visibility;
- content-addressed URI or repository blob reference; and
- optional encryption/key metadata.
Default retention is hash-only for rendered prompts and transcripts, with the reusable protocol/template committed when safe. Hash-only proves that a later-presented artifact matches; it does not make the artifact recoverable. Reports must distinguish “digest verified” from “artifact available.”
Secrets, private code, API responses, and personal data must not be placed in the public ledger. The CLI displays a redaction/visibility preview before a human confirms a write.
Each physical line is exactly one complete JSON event. Blank lines, comments, duplicate keys, NaN/Infinity, and trailing data are forbidden. The file ends with one LF.
Events are serialized with a documented deterministic JSON canonicalization. Object member order in human-pretty examples is illustrative; signed bytes use the canonical form.
The file is sorted lexicographically by UUIDv7 event ID. UUIDv7 provides useful time locality and collision resistance, but:
- the embedded time is not authoritative review time;
- clock rollback can make creation order surprising;
- signatures and receipts determine time trust;
- duplicate UUIDs with identical bytes collapse during merge; and
- duplicate UUIDs with different bytes are corruption and must hard-fail.
Because sorting can insert a new event before an existing physical line, “append-only” is semantic, not textual: every pre-existing event ID and canonical payload must remain present and byte-equivalent. New commits may only add new IDs.
Version 1 defines:
- review — a reviewer attestation with selections, scopes, verdicts, evidence, and initial findings;
- review_supersession — replaces a mistaken or obsolete review with another review ID while retaining both;
- review_revocation — withdraws trust in a review, with rationale and actor;
- finding_disposition — marks a finding fixed, accepted-risk, false-positive, duplicate, deferred, or superseded;
- exemption — creates or closes a bounded policy exception;
- receipt — a trusted service records first-seen or accepted time and ledger location; and
- import — records provenance for evidence imported from another review system or project identity.
An extension event uses a reverse-DNS type such as com.example.git-review.custom. Unknown extension events are preserved and reported. A policy gate must not let an unknown event silently satisfy a core requirement.
No command edits or deletes an existing event. Corrections are new supersession or revocation events. Finding lifecycle changes are new finding_disposition events.
git review verify --against BASE checks:
- every base event still exists;
- every base event has the same canonical payload;
- every new event has a unique valid UUIDv7;
- every referenced event/finding/selection exists or is explicitly allowed as an unresolved cross-ledger reference;
- signatures verify under the event's declared scheme;
- schema and resource limits are satisfied; and
- the canonical sort is correct.
The merge driver parses base, ours, and theirs as sets keyed by event ID:
- validate all three inputs before producing output;
- union the event sets;
- collapse byte-identical duplicates;
- reject any same-ID/different-payload pair;
- reject loss or mutation of a base event;
- canonicalize and lexicographically sort;
- write one LF-terminated event per line; and
- never choose “ours” or “theirs” merely because one parsed last.
Malformed input produces a normal Git conflict plus a precise diagnostic. It must never emit a partial ledger.
git review sync:
- fetches the configured review ref;
- verifies the orphan bootstrap, complete sideband tree invariant, remote ledger history, and policy expectations;
- unions locally staged/unpushed events with fetched events;
- creates one deterministic, single-parent ledger commit directly atop the fetched remote tip—never a merge commit;
- verifies the proposed old/new ref update locally;
- compare-and-swaps the local ref;
- pushes without force to the protected writer/pre-accept path;
- on non-fast-forward, fetches, unions, and retries a bounded number of times;
- leaves every local event in a recoverable signed bundle if the remote remains contested.
Commit timestamps and messages are not canonical evidence. Event signatures are independent, so unioning or reserializing the ledger does not invalidate them.
The remote acceptance mechanism runs the same old/new validation before updating the ref. A local pre-push hook is optional defense in depth and cannot substitute for it.
Version 1 uses one file until measurements justify sharding. Streaming parse and a generated index should handle substantial ledgers. A future policy may select deterministic time or ID-prefix shards:
codereviews/2026/07.ndjson
Because the v1 sideband tree invariant permits only one ledger path, sharding starts a new, policy-authorized sideband epoch with a new orphan bootstrap and a signed checkpoint to the previous tip. It is a storage migration, not an event rewrite: signed event bytes and IDs remain unchanged, and the reader must not require old signed events to be reserialized into a new schema. The old epoch remains fetchable and verifiable.
codereview-policy.json contains:
- project_id — UUIDv7 created by git review init;
- project_name — display-only;
- upstream_project_id — optional, for a fork or split;
- storage profile/ref;
- default policy version; and
- optional hosting metadata.
A fork may intentionally retain project_id to share upstream review lineage or run git review fork to create a new identity and record upstream provenance. The tool must not decide this solely from a changed remote URL.
Every object ID is algorithm-qualified:
{"algorithm":"sha1","hex":"0123456789abcdef0123456789abcdef01234567"}This supports both SHA-1 and SHA-256 Git repositories. The tool validates object length and verifies that the object exists and has the expected type.
A review subject is one of:
- snapshot — selections in one commit tree;
- diff — a base commit, head commit, and reviewed change selections;
- blob — a whole binary or non-text Git blob;
- gitlink — a submodule commit pointer; or
- external — only when no Git object exists, with a mandatory content digest and explicit reduced portability.
Snapshot review is best for durable line/symbol coverage. Diff review is best for pull requests and must separately identify:
- head-side additions/context that can cover current code;
- base-side deletions that remain historical evidence only;
- renamed paths;
- reviewed but unchanged context; and
- unreviewed portions of the diff.
Text line ranges are:
- one-based;
- inclusive at both ends;
- calculated from raw Git blob bytes;
- split on LF bytes;
- valid for a final non-LF-terminated line; and
- invalid for a binary-classified blob unless policy explicitly selects a whole blob.
Working-tree CRLF conversion is irrelevant; the commit blob is authoritative. Paths are UTF-8 in JSON when Git's raw path bytes are valid UTF-8. Otherwise the schema uses a reversible byte encoding and reports the escaped display form. No report may silently replace undecodable path bytes.
Canonical identity:
- project ID;
- subject commit(s);
- path as present in the subject tree;
- selection kind;
- start/end line or whole-blob marker; and
- validity boundary.
Derived and independently recomputable:
- tree ID;
- blob ID;
- SHA-256 of selected bytes;
- SHA-256 of normalized input manifest;
- surrounding-context digest;
- detected language;
- symbol name/kind/signature;
- diff hunk fingerprint; and
- mapping chain to a later target.
git review verify recomputes every derived field. A mismatch is corruption or a tool defect, never a warning to ignore.
- lines — a contiguous line range;
- symbol — a parser-identified symbol plus its concrete fallback line range;
- hunk — a concrete diff hunk plus head/base coordinates;
- file — an entire text blob;
- blob — an entire non-text blob;
- gitlink — a submodule pointer;
- generated-set — files tied to a generator/input declaration;
- relationship — a declared invariant spanning two or more selections; and
- repository — a finite, enumerated selection manifest, never an unbounded phrase such as “the whole repo.”
Every selection receives a stable ID within its review event. A finding can anchor to the whole selection or a subrange.
- exhaustive — the reviewer claims to have applied every named scope to the full selection;
- targeted — the reviewer investigated a specific question; useful evidence but not general coverage;
- sampled — only a sample was examined;
- context_only — read for understanding, not reviewed; and
- unable — the selection could not be reviewed, with reason.
Only exhaustive selections satisfy general review-coverage gates. Reports show targeted, sampled, and context evidence without coloring them as fully covered.
Every exhaustive selection declares what must remain stable for the evidence to carry forward:
- selection_bytes — selected bytes must remain identical and map uniquely;
- symbol — the entire parsed symbol and signature must remain identical;
- file — the entire blob must remain identical;
- diff — the reviewed change set must remain identical;
- context — selected bytes plus declared surrounding context must remain identical;
- dependency_set — all explicitly enumerated target/context objects must remain identical; or
- no_carry — valid only at the subject commit.
Policy sets minimum boundaries per path and scope. A reviewer cannot choose a weaker boundary than policy permits.
For example, a spelling/documentation review may carry on selection bytes. A concurrency or security review may require the whole symbol, file, or declared call-chain context.
Review packets distinguish:
- target selections;
- required context;
- optional context;
- excluded files;
- unreadable/unavailable inputs; and
- truncation or token-budget omissions.
An LLM run that omitted required input cannot issue exhaustive coverage for that selection. The runner must convert token truncation, context overflow, file read failure, or model refusal into explicit partial/unable state rather than a green verdict.
Historical evidence carries only when the tool can mechanically establish an unambiguous mapping that satisfies the recorded validity boundary. Ambiguity never becomes an optimistic match.
For a review at commit C and report target T:
- Confirm C is reachable from T, or label the record imported/cross-branch.
- If the reviewed path and blob ID are identical, map directly.
- If another path has the same blob ID, map an exact rename/move.
- For a selection/symbol/context boundary, find byte-identical candidates using derived digests and verify their raw bytes.
- Require one unique candidate after context and path-history constraints.
- For diff-aware line tracking, verify every inherited atom rather than trusting Git's heuristic rename percentage.
- Across merge commits, require the selected lineage to be explicit or all viable parent mappings to agree.
- Record the complete mapping explanation in generated index/report data.
- A common one-line brace copied into fifty functions does not map uniquely.
- Two identical helper functions require symbol/path context or remain ambiguous.
- A formatter rewrite changes bytes. It does not carry automatically merely because a semantic model claims equivalence.
- A cherry-pick changes commit ID. Exact selections may be imported only under policy, with import provenance and any independence downgrade shown.
- A whole-file security review becomes changed if any byte changes when its validity boundary is file.
A project may accept a separately attested transformation such as a deterministic formatter, generated-file reproduction, or verified refactor. That requires an external/differential oracle with:
- exact tool and version;
- input/output object IDs;
- reproducible command;
- result digest;
- policy authorization; and
- signed runner evidence.
This is an explicit bridge event, not an inference hidden inside line mapping.
- Generated files should normally be excluded from ordinary review coverage and tied to reviewed generator/input selections plus reproducibility evidence.
- Vendored code should have a distinct supply-chain/update policy, not fake first-party line coverage.
- Git LFS stores pointer blobs. Reviewing materialized content requires its object digest and availability evidence in addition to the pointer.
- A submodule review of the gitlink proves only that its pinned commit was considered. Content coverage belongs to the submodule's own project ledger.
- Binary review uses whole-blob identity plus format-specific evidence; line metrics do not apply.
The v1 core vocabulary is growable and versioned:
- correctness
- contract_completeness
- test_adequacy
- test_validity
- duplication
- maintainability
- algorithmic_complexity
- performance
- memory_safety
- concurrency
- security
- privacy
- error_handling
- resource_management
- ffi_abi
- portability
- accessibility
- internationalization
- operability
- documentation
- dependency_supply_chain
Each scope definition includes intent, required questions, permitted verdicts, default validity boundary, and evidence expectations. The definitions are versioned independently of display labels.
Custom scopes use reverse-DNS names, for example:
com.mecha.review.deep-validation-preservation
Unknown custom scopes are retained but satisfy no core gate unless policy maps them explicitly.
“Security” is too vague to reproduce. A review records:
- scope ID and definition version;
- protocol ID and version;
- exact prompt-template Git object or artifact digest;
- rendered-prompt digest;
- review packet digest;
- required tools/oracles;
- completion criteria;
- output schema version; and
- deviations from protocol.
The reusable prompt should be committed when it contains no secrets. Dynamic rendered prompts and transcripts are referenced by digest and optional secure artifact URI.
Each review contains one result per claimed scope:
- scope;
- coverage mode;
- protocol;
- reviewer verdict;
- confidence as a coarse enum, not a fabricated percentage;
- finding IDs;
- evidence IDs;
- deviations;
- unable/blocked reason; and
- validity boundary.
The overall reviewer verdict is derived from scope results but retained as a convenient summary:
- approved
- approved_with_findings
- changes_requested
- blocked
- inconclusive
The policy gate has separate states:
- pass
- pass_with_advisories
- fail
- indeterminate
No review record stores “gate pass”; policy computes it at a target commit.
- human
- llm
- service
- runner
- external_oracle
- composite_team
Actor IDs are stable strings within a trust domain, such as:
human:pmarreck
llm:openai:gpt-family:run-019...
service:mechatron-prime
runner:thelio-nixos:mechatron-reviewer
oracle:zig-test-suite
Display names are not identifiers.
- actor ID;
- display name;
- optional organization/team;
- signing-key fingerprint;
- role/capability asserted;
- identity-provider references;
- declared producer relationship; and
- optional expertise tags.
Do not put private email addresses in a public ledger by default.
- provider;
- model family;
- exact model/version identifier returned by the provider;
- provider request/run ID when available;
- knowledge/tool mode when disclosed;
- runner actor and runner version;
- session ID;
- temperature/seed/reasoning settings when exposed;
- tools made available;
- network access policy;
- input packet digest;
- prompt-template and rendered-prompt digests;
- output artifact digest;
- context truncation/omission status; and
- provider-side attestation or receipt when available.
The schema permits unknown values. The CLI must never invent a precise model version, seed, or setting that the provider did not disclose.
Producer identification can draw from:
- Git author/committer identities;
- signed commit or build provenance;
- pull-request author;
- session/run manifests;
- explicit producer attestations;
- generated-code metadata; and
- maintainer declarations.
Git authorship alone is weak: a human may commit LLM-generated code, or one agent may commit another agent's patch. Reports show the evidence source and confidence of producer attribution.
The record stores facts, not a self-awarded rank. Current policy derives:
- self_review — known producer and reviewer overlap;
- separated_context — same human/controller but a clean reviewer session with declared isolation;
- independent_reviewer — no known producer overlap and policy-required isolation evidence exists;
- external_oracle — a mechanically independent reference/check adjudicated a claim;
- mixed — different classifications across selections/scopes; or
- unknown — evidence is insufficient.
Separate-session/same-model can be useful, but it is not equivalent to a different producer and reviewer. A human reviewing code they directed an LLM to write may still be a producer under strict policy.
Independence is assessed per selection and scope because a reviewer may have written one file but be independent of another.
Reports may label procedural assurance:
- assertion_only
- signed_assertion
- runner_observed
- artifact_reproducible
- independently_reproduced
- external_oracle
These labels describe evidence mechanics, not reviewer intelligence or result correctness.
Every finding has:
- UUIDv7 finding ID;
- title;
- severity;
- category/scope;
- one or more precise anchors;
- concise description;
- impact/risk;
- supporting evidence;
- reproduction or falsification steps when available;
- recommendation;
- reviewer confidence enum;
- related finding IDs;
- external taxonomy references such as CWE, when applicable; and
- initial state, normally open.
Default severity vocabulary:
- critical — immediate severe harm or release blocker;
- high — substantial defect/risk requiring prompt correction;
- medium — material defect or maintainability/operability risk;
- low — bounded defect or improvement;
- info — useful observation with no required remediation.
Projects may display aliases such as WARNING or ADVISORY, but canonical severity must remain comparable.
A finding anchor references:
- review event ID;
- selection ID;
- subject-side path/range;
- optional symbol;
- optional base/head side for diff findings; and
- derived context used for later mapping.
Findings about missing code, architecture, process, or repository-wide behavior may use a relationship/repository selection and supporting anchors. They must not invent a meaningless line number merely to satisfy a schema.
An immutable finding_disposition event changes operational state:
- fixed — with fixing commit and verification evidence;
- accepted_risk — with accountable actor, rationale, and optional expiry;
- false_positive — with falsifying evidence;
- duplicate — with canonical finding ID;
- deferred — with reason/target;
- superseded — by another finding;
- reopened — when prior disposition is no longer valid.
A producer saying “fixed” does not satisfy a policy that requires independent verification. The disposition can exist while the gate remains unsatisfied.
Zero findings is valid only when the record explicitly states:
- selections completed;
- scopes completed;
- no required input was omitted;
- protocol completion criteria passed; and
- verdict per scope.
An empty finding array by itself must not be interpreted as approval.
Each event can carry multiple signatures with roles:
- reviewer;
- runner;
- witness;
- importer; and
- receipt issuer.
The signed payload is a domain-separated canonical representation of the event excluding the signatures array:
git-review/event/v1 LF
<canonical JSON bytes>
Initial implementations should support SSH Ed25519 signatures because Git users commonly have compatible keys. The schema is algorithm-agile for hardware-backed keys, Sigstore-style identities, or future schemes.
A Git commit signature does not replace event signatures. One ledger commit may union records from several reviewers and be committed by a synchronization service.
An LLM does not normally possess a trustworthy private key. The runner signs:
- exact input packet digest;
- model/provider identifiers it observed;
- exact output digest;
- process isolation facts it can observe;
- timing it measured; and
- the resulting structured review event.
The semantic claims remain attributed to the LLM reviewer; the execution facts are attributed to the runner. A provider-signed response can add another signature when available.
The policy identifies trusted keys/issuers, roles, paths/scopes, validity periods, and revocations. Trust can be:
- advisory;
- required for selected scopes;
- limited to a team/path;
- limited to runner observations but not semantic approval; or
- accepted only with a second independent signature.
Key rotation adds new policy and revocation state. It never rewrites old events.
Review events contain RFC 3339 UTC started_at and completed_at plus measured duration. The UI renders local time and always exposes UTC.
Signed self-reported timestamps can be backdated. Time assurance levels are:
- declared — event timestamp only;
- runner_observed — trusted runner clock;
- ledger_observed — protected remote observed the event/commit;
- transparency_observed — independent timestamp/log receipt.
UUIDv7 time and Git author/committer dates are useful ordering hints, not trusted wall-clock evidence. Freshness policy states which assurance level is required.
If a key or runner is compromised:
- update policy trust/revocation;
- append review_revocation events where needed;
- generate a report of affected effective coverage;
- open a bounded re-review campaign; and
- retain historical evidence with a visible revoked state.
History rewriting or force-pushing the ledger is detectable only relative to a trusted remote, receipt, mirror, or previous local state. The spec does not pretend Git alone is a transparency log.
All events include:
{
"schema": "git-review/event/v1",
"id": "0198139d-8a45-7b7e-8c3a-4f78f9be9210",
"type": "review",
"project_id": "0198138a-87bd-7e1f-b6ac-6e824e30b43d",
"created_at": "2026-07-15T18:42:31.248Z",
"actor_id": "runner:thelio-nixos:mechatron-reviewer",
"payload": {},
"extensions": {},
"signatures": []
}Core fields are closed and validated. Extension data must live below extensions with reverse-DNS keys.
The ledger stores the following as one canonical line; it is pretty-printed here only for readability:
{
"schema": "git-review/event/v1",
"id": "0198139d-8a45-7b7e-8c3a-4f78f9be9210",
"type": "review",
"project_id": "0198138a-87bd-7e1f-b6ac-6e824e30b43d",
"created_at": "2026-07-15T18:42:31.248Z",
"actor_id": "runner:thelio-nixos:mechatron-reviewer",
"payload": {
"subject": {
"kind": "snapshot",
"commit": {
"algorithm": "sha1",
"hex": "0123456789abcdef0123456789abcdef01234567"
},
"policy_blob": {
"algorithm": "sha1",
"hex": "89abcdef0123456789abcdef0123456789abcdef"
}
},
"reviewer": {
"actor_id": "llm:openai:gpt-family:run-0198139c",
"kind": "llm",
"provider": "openai",
"model_family": "gpt",
"model_version": "provider-returned-exact-value",
"provider_run_id": "provider-run-id",
"session_id": "review-session-id"
},
"runner": {
"actor_id": "runner:thelio-nixos:mechatron-reviewer",
"tool": "git-review-runner",
"version": "1.0.0",
"read_only_worktree": true,
"network_policy": "denied"
},
"producers": [
{
"actor_id": "human:pmarreck",
"basis": ["git_author", "session_attestation"]
}
],
"protocol": {
"id": "com.mecha.review.deep-code-review",
"version": "1.0.0",
"template_git_blob": {
"algorithm": "sha1",
"hex": "fedcba9876543210fedcba9876543210fedcba98"
},
"rendered_prompt_sha256": "sha256:base64-value",
"packet_sha256": "sha256:base64-value",
"output_schema": "git-review/reviewer-output/v1",
"deviations": []
},
"timing": {
"started_at": "2026-07-15T18:32:02.104Z",
"completed_at": "2026-07-15T18:41:59.890Z",
"duration_ns": 597786000000,
"assurance": "runner_observed"
},
"selections": [
{
"id": "s1",
"kind": "symbol",
"path": "src/ledger.zig",
"start_line": 141,
"end_line": 238,
"symbol": "mergeEventSets",
"coverage": "exhaustive",
"validity_boundary": "symbol",
"derived": {
"blob": {
"algorithm": "sha1",
"hex": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
"selection_sha256": "sha256:base64-value",
"context_sha256": "sha256:base64-value"
}
}
],
"context": [
{
"path": "docs/ledger-invariants.md",
"kind": "file",
"use": "required_context",
"blob": {
"algorithm": "sha1",
"hex": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
}
}
],
"scope_results": [
{
"scope": "correctness",
"scope_version": "1.0.0",
"selection_ids": ["s1"],
"coverage": "exhaustive",
"verdict": "changes_requested",
"confidence": "high",
"validity_boundary": "symbol",
"finding_ids": [
"0198139d-6a11-7611-83ca-c20ac508e313"
]
}
],
"findings": [
{
"id": "0198139d-6a11-7611-83ca-c20ac508e313",
"title": "Conflicting duplicate event IDs can be overwritten",
"severity": "high",
"category": "correctness",
"confidence": "high",
"anchors": [
{
"selection_id": "s1",
"start_line": 186,
"end_line": 193
}
],
"description": "The map insertion path replaces an existing payload before comparing canonical bytes.",
"impact": "A malicious or accidental collision can destroy one attestation during merge.",
"recommendation": "Compare before insertion and hard-fail same-ID/different-payload inputs.",
"evidence_ids": ["e1"],
"initial_state": "open"
}
],
"evidence": [
{
"id": "e1",
"kind": "reproduction",
"media_type": "text/plain",
"sha256": "sha256:base64-value",
"size": 412,
"availability": "artifact",
"uri": "git-review-artifact:sha256:base64-value",
"visibility": "project"
}
],
"completion": {
"required_inputs_present": true,
"truncated": false,
"tool_failures": [],
"overall_verdict": "changes_requested"
},
"independence_claims": {
"reviewer_declares_no_contribution": true,
"same_session_as_producer": false,
"producer_context_available_to_reviewer": false
}
},
"extensions": {},
"signatures": [
{
"role": "runner",
"scheme": "ssh-ed25519",
"key_fingerprint": "SHA256:example",
"signature": "base64-value"
}
]
}The independence_claims object records declarations. The derived independence class is intentionally absent from the signed record because current policy and external provenance determine it.
{
"schema": "git-review/policy/v1",
"project_id": "0198138a-87bd-7e1f-b6ac-6e824e30b43d",
"project_name": "example",
"storage": {
"mode": "sideband_branch",
"ref": "refs/heads/code-reviews",
"ledger_path": "codereviews.ndjson",
"sentinel_path": ".git-review-sideband",
"bootstrap": {
"algorithm": "sha1",
"hex": "cccccccccccccccccccccccccccccccccccccccc"
},
"allowed_paths": [
".git-review-sideband",
"README.md",
"codereviews.ndjson"
]
},
"tracking": {
"include": ["**"],
"exclude": [
".git-review/**",
"codereviews.ndjson",
"vendor/**",
"zig-out/**"
],
"generated": ["src/generated/**"],
"binary": ["fixtures/**"]
},
"scopes": {
"default_required": ["correctness", "test_adequacy"],
"path_rules": [
{
"paths": ["src/crypto/**"],
"require": ["security", "memory_safety"],
"minimum_independence": "independent_reviewer",
"minimum_time_assurance": "runner_observed",
"validity_boundary": "file"
}
]
},
"freshness": {
"default_max_age_days": 365,
"per_scope_days": {
"security": 180,
"dependency_supply_chain": 90
}
},
"gates": [
{
"id": "protected-branch-diff",
"when": "target_is_protected",
"require_changed_selection_coverage": 1.0,
"block_severities": ["critical", "high"],
"allow_exemptions": true
}
],
"i18n": {
"phase": "prepare",
"default_locale": "en"
}
}The production schema replaces informal expressions such as target_is_protected with a documented, typed policy predicate language. It must not evaluate arbitrary code.
Every review records the policy blob present at its subject commit. Reports show:
- whether the review complied with that historical policy; and
- whether it satisfies policy at the current target.
Current policy controls current gates. Tightening policy can make older evidence insufficient without altering history. Loosening policy can make valid old evidence effective again unless it was revoked or changed.
Include/exclude/generated/vendor/binary/path-risk rules are classifiers over the complete tracked path set. Order and precedence are explicit. Tests must assert classification over representative sets, including overlaps and negations, rather than checking one example or merely finding a pattern in the configuration.
A gate may require:
- every changed review atom covered for named scopes;
- minimum independence class;
- accepted protocol versions;
- maximum evidence age;
- minimum time/signature assurance;
- no unresolved findings at or above severity;
- independent verification of fixed findings;
- required tests/oracles;
- explicit coverage of high-risk paths;
- no unknown mapping ambiguity;
- no expired exemption; and
- a synchronized/verified ledger.
An exemption requires:
- UUIDv7;
- accountable actor/signature;
- exact target paths/selections/scopes;
- rationale;
- issue or incident reference when available;
- created and expiry time;
- maximum allowed duration;
- whether renewal is permitted; and
- closure event.
Break-glass is explicit, logged, narrowly scoped, and visible in every report. It must never silently convert a failure to a normal green pass.
For every target atom and required scope:
- fresh — effective and within policy;
- stale — maps but exceeds age/protocol campaign limits;
- unreviewed — no historical exhaustive evidence;
- changed — historical evidence exists but validity boundary changed;
- ambiguous — possible mapping is not unique;
- insufficient — review exists but protocol/independence/signature is below policy;
- blocked — review could not be completed;
- exempt — active bounded exception;
- excluded — policy does not track the atom; or
- not_applicable — scope does not apply by an explicit classifier.
Reports must not merge these into a single gray “missing” state.
Age uses the strongest policy-accepted time:
- trusted receipt;
- trusted runner observation;
- signed reviewer declaration;
- otherwise unknown.
Unknown time cannot satisfy a strict freshness gate. UI can still display a best-effort date with its assurance label.
A re-review campaign is policy/report state with:
- campaign ID;
- rationale;
- selected paths/scopes;
- accepted protocols/reviewer profiles;
- start/target dates;
- priority rule;
- completion definition; and
- owner.
Typical reasons:
- a materially improved review protocol;
- a newly discovered defect class;
- a compromised reviewer key/runner;
- an architectural change;
- an incident retrospective; or
- an intentionally evaluated new model.
Campaigns do not rewrite the original freshness dates. Reports show ordinary policy freshness and campaign completion separately.
git review queue assigns a deterministic score from policy-configured factors:
- never reviewed;
- overdue age;
- risk classification;
- change frequency;
- dependency centrality when available;
- open finding severity;
- incident/campaign membership;
- ambiguity/insufficient evidence; and
- estimated atom size.
The report explains every score component. There must be no opaque AI-assigned priority number.
No single percentage is sufficient. Reports show:
- tracked files and review atoms;
- tracked non-whitespace text lines, including comments;
- tracked bytes;
- changed atoms/lines for a diff;
- fresh coverage per required scope;
- any-scope historical coverage;
- stale/changed/insufficient counts; and
- excluded/generated/vendor/binary counts.
The policy gate should normally use changed atoms for required scopes, not a repository-wide percentage that can be gamed by reviewing easy files.
Blank lines are excluded from line denominators. Comments are included because contracts and dangerous misinformation can live in comments. Generated, vendor, binary, and untracked files are reported separately according to policy.
The executable is git-review, allowing both:
git-review status
git review status
All commands support:
- -h and --help;
- --about with one-line description, version, OS, and architecture;
- --repo PATH;
- --at COMMIT;
- --format terminal, json, ndjson, html, or sarif where meaningful;
- --output PATH, - or @stdout;
- --lang CODE;
- --simple;
- --no-ansi and --no-color;
- --quiet;
- --non-interactive; and
- --strict.
Later conflicting arguments override earlier ones. A literal -- ends option parsing. Paths with spaces and non-ASCII characters are first-class. Machine interfaces never depend on localized text.
Structured stdout uses a versioned envelope:
{
"schema": "git-review/cli-result/v1",
"ok": true,
"command": "status",
"data": {},
"warnings": [],
"errors": []
}Diagnostics and progress go to stderr. In non-interactive mode, the program never prompts or opens an editor.
- 0 — command succeeded; requested gate/status passed;
- 1 — command succeeded but policy/status gate failed;
- 2 — invalid arguments, input schema, or user-correctable selection;
- 3 — corrupt ledger, invalid signature, violated append-only invariant, or trust failure;
- 4 — required Git object/tool/environment unavailable;
- 5 — synchronization conflict or remote refusal with local data preserved;
- 70 — internal software error.
JSON output includes stable machine error codes independent of process exit code and localized message.
git review init
git review init --storage sideband
git review init --storage embedded
git review fork
git review config get
git review config validate
git review enforcement status
git review enforcement install-local-hook
git review enforcement render-pre-receive --output @stdout
git review doctor
init:
- detects the repository and default branch without renaming it;
- creates project ID and policy;
- creates and records the no-parent sideband bootstrap when selected;
- configures ledger storage and merge driver;
- offers, but does not silently install, local hooks;
- reports remote enforcement as unconfigured until a pre-accept path is established and verified;
- emits the source-branch separation check required by CI/rulesets;
- creates English i18n resources and prepare-phase metadata;
- validates remote/ref feasibility; and
- performs no network write without explicit confirmation.
git review queue
git review queue --scope security --state unreviewed,stale
git review queue --next --campaign crypto-2026
git review packet create --commit HEAD --select src/ledger.zig --symbol mergeEventSets
git review packet verify packet.json
git review packet show packet.json
packet create freezes:
- subject and policy object IDs;
- target/context selections;
- protocol;
- producer provenance known at creation;
- permitted tools/network;
- expected output schema;
- packet digest; and
- explicit omissions.
Selection flags are repeatable:
git review packet create \
--commit HEAD \
--select "src/path with spaces/ledger.zig" --lines 40:120 \
--select tests/ledger.zig --whole-file \
--scope correctness --scope test_adequacy
For machine use, --input - or --input @stdin accepts the packet-request JSON schema. The CLI does not require parsing an ambiguous path:line shorthand.
git review add
git review add --packet packet.json
git review add --input @stdin --non-interactive
git review add --draft DRAFT_ID
git review add --sign
git review add --dry-run
Interactive add:
- verifies the packet and Git objects;
- shows reviewer/producer/independence facts;
- walks each scope and selection;
- opens $VISUAL for long finding text if desired;
- validates anchors and evidence;
- shows the exact canonical event and privacy summary;
- signs only after confirmation;
- writes locally with an atomic compare-and-swap; and
- offers a separate sync/push action.
Ctrl-C or validation failure leaves a resumable owner-only draft and does not touch the ledger.
Non-interactive add validates a strict JSON Schema. It never infers approval from absent fields, an empty findings array, or process exit 0.
git review finding show FINDING_ID
git review finding resolve FINDING_ID --fixed-in COMMIT --evidence FILE
git review finding accept-risk FINDING_ID --until DATE --reason TEXT
git review finding false-positive FINDING_ID --evidence FILE
git review finding reopen FINDING_ID
git review finding verify-fix FINDING_ID --packet-out -
Resolution commands append disposition events. They never edit the originating review.
git review supersede REVIEW_ID --with NEW_REVIEW_ID --reason TEXT
git review revoke REVIEW_ID --reason TEXT
git review exempt add ...
git review exempt close EXEMPTION_ID
git review import github --input FILE
git review import sarif --input FILE
git review import ledger --from PROJECT_OR_REF
Import preserves source-system IDs, raw artifact digests, identity mapping, and assurance downgrade. Imported “approved” text does not automatically become exhaustive line coverage.
git review status
git review status --at HEAD --scope security
git review line --path src/ledger.zig --line 187
git review file --path src/ledger.zig
git review symbol --path src/ledger.zig --name mergeEventSets
git review blame --path src/ledger.zig
git review diff BASE..HEAD
git review history REVIEW_OR_FINDING_ID
git review explain --path src/ledger.zig --line 187 --scope correctness
git review reviewers
git review campaign status
line/file/symbol results show all historical layers and separately identify the currently effective records. explain gives a deterministic proof trace: selection, mapping chain, signature/trust, independence, policy rule, freshness calculation, findings, and final state.
review blame is deliberately named after Git blame but displays review layers, not authorship. It must clearly label itself “review evidence,” not “blame.”
git review verify
git review verify --against origin/code-reviews
git review verify-ref-update OLD_OID NEW_OID refs/heads/code-reviews
git review verify-source-separation --at HEAD
git review policy check --base origin/main --head HEAD
git review sync
git review sync --pull-only
git review index rebuild
git review cache clear
git review merge-driver %O %A %B %P
git review migrate --dry-run
cache clear can remove only generated state. There is no ledger gc command that deletes canonical events.
git review report --format terminal
git review report --format json --output -
git review report --format html --output review-report.html
git review report --format sarif --output findings.sarif
HTML is a generated report format, not a web UI or resident service. By default it produces one self-contained, read-only HTML file with embedded CSS and report data. --assets separate may produce a directory with content-addressed static assets when a repository is too large for one file. Opening or hosting that output is outside git-review's runtime responsibilities.
- Producer commits code.
- git review packet create --diff MERGE_BASE..HEAD emits the exact review packet.
- An independent human or runner receives the packet.
- Reviewer records exhaustive/partial status and findings.
- git review add validates and signs the event.
- git review sync publishes it to code-reviews.
- CI fetches source and review refs, then runs policy check.
- Fixes create new code commits; finding dispositions and re-review events refer to those commits.
- The merge gate passes only when current head coverage and findings satisfy policy.
Changing the feature branch after review invalidates affected selections. It does not silently preserve the PR's old green check.
- git review queue --state unreviewed,stale groups work by symbol/hunk.
- Reviewer requests the next bounded packet.
- The queue reserves nothing globally unless a collaboration service is in use; two reviewers may independently review the same atom.
- Both records are retained. Redundant independent layers can be valuable.
- Reports update without changing source commits in sideband mode.
- Producer queries finding and reproduces it.
- Producer commits the fix and records fixed disposition.
- If policy requires independence, another reviewer receives a focused packet containing original finding, original/fixed selections, and evidence.
- Verification review either confirms, reopens, or replaces the finding.
- Reports preserve original discovery and complete disposition chain.
git review line --at HEAD --path src/ledger.zig --line 187
The result contains:
- Git authorship as an optional adjacent fact;
- every historical review intersecting the line;
- scopes and protocols;
- reviewer/runner/model;
- independence classification and basis;
- completion/freshness time and assurance;
- findings anchored there;
- mapping from original subject to HEAD;
- effective versus stale/changed state; and
- exact reason a record does or does not satisfy policy.
Each reviewer creates UUIDv7 events locally. git review sync unions them. Network failure leaves signed local events recoverable. Same-ID/different-data is never auto-resolved. A reviewer can export a signed bundle for sneaker-net or email import without handing over a mutable database.
Use a bounded exemption rather than editing policy or fabricating a review. The gate becomes pass-with-break-glass, every report remains visibly exceptional, and the queue schedules the debt before expiry.
LLMs interact through versioned JSON, not terminal scraping:
- git review packet create --format json
- runner invokes the reviewer with the packet/protocol;
- reviewer emits git-review/reviewer-output/v1 JSON;
- runner validates output, captures artifact digest, and records observed limitations;
- git review add --input @stdin --non-interactive;
- independent mechanical checks verify anchors, objects, tests, and signatures; and
- policy decides whether the evidence is sufficient.
Free-form Markdown can be generated from structured output, but it is not the canonical input.
Packets include byte/token estimates and deterministic chunks. Chunking:
- never splits a UTF-8 code point;
- prefers semantic atoms;
- identifies shared context once by digest;
- records every omitted atom;
- requires a completion manifest over the original target set; and
- cannot yield exhaustive repository coverage until every required atom has a completed result.
If the model context window, runner, or tool fails, the result is partial or unable—not approved.
The preferred automated pipeline uses:
- one producer session with write access;
- an immutable committed subject;
- a separate reviewer session with read-only access;
- a runner that does not reuse producer conversation;
- independently written or externally anchored tests where feasible; and
- a separate approval capability for protected changes.
Same-agent re-review is still recorded and useful but labeled self_review or separated_context according to evidence.
For each finding or approval claim, use the strongest appropriate independent control:
- exhaustive finite tests;
- property-based tests;
- metamorphic tests;
- differential comparison;
- mutation testing;
- model-based/state-machine checking;
- sanitizer/static analyzer evidence;
- deterministic reproduction; or
- an external reference oracle.
An LLM's statement that tests passed is not evidence unless the runner captures the command, environment, exit status, and output digest, and policy trusts that runner for this role.
Protocol IDs are immutable in meaning. Editing a prompt creates a new protocol version/blob. Reports can compare finding yield, false-positive disposition, cost, and coverage across versions without rewriting history.
No automatic metric should reward reviewers for producing more findings; that would incentivize noise. Quality evaluation uses confirmed findings, falsification rate, missed defects discovered later, reproducibility, and scope completion—with caveats about survivorship and ground truth.
All terminal rendering is a pure function of report data, terminal width, capabilities, locale, and injected current time. It performs no I/O and reads no clock/global state.
Use:
- restrained semantic color;
- Unicode bars/sparklines where supported;
- icons plus text, never color alone;
- stable column alignment based on grapheme display width;
- hyperlinks when the terminal supports them;
- progressive layouts for wide, medium, and narrow terminals;
- --simple ASCII without ANSI/emoji;
- --no-color while retaining structure;
- screen-reader-friendly plain output; and
- JSON for exact automation.
Before freezing golden visual assertions, render examples and have Peter act as output eyes. Test approved output at several widths.
The precise styling is intentionally not a golden design yet:
Git Review · validate @ c5f5c7b11 Gate: FAIL
Ledger: synced · 428 events · signatures valid · policy v3
Changed evidence
correctness 41/44 atoms ██████████████████░░ 93% 3 changed
test adequacy 36/44 atoms ████████████████░░░░ 82% 8 unreviewed
memory safety 12/12 atoms ████████████████████ 100% fresh
Review debt
Never reviewed 18 atoms
Stale 27 atoms oldest: 2025-11-02
Changed 3 atoms
Insufficient 4 atoms independence below policy
Open findings
CRITICAL 1 HIGH 3 MEDIUM 8 LOW 12 INFO 7
Next: git review explain --finding 0198...e313
src/ledger.zig:187 @ HEAD
Effective
✓ correctness · GPT reviewer via Mechatron · 2026-07-15 · independent
reviewed as mergeEventSets:141-238 @ 0123456
mapped by unchanged symbol → HEAD
protocol deep-code-review/1.0 · runner-observed · signed
Historical
◷ security · Human: Peter · 2025-12-14 · stale after 180 days
× correctness · Agent run 018f... · changed at commit 7ab4210
Finding
HIGH 0198...e313 Conflicting duplicate IDs can be overwritten OPEN
Queue output groups nearby work to minimize context switching:
- priority and its component explanation;
- project/path/symbol;
- required scopes;
- current evidence state;
- size estimate;
- relevant open findings;
- campaign;
- suggested packet command; and
- whether another reviewer has published overlapping evidence.
It must not claim an exclusive lock without a coordinating server.
Useful terminal reports include:
- scopes × reviewers;
- paths × freshness state;
- producer × reviewer independence matrix;
- protocol/model version timeline;
- finding discovery/disposition timeline;
- review debt aging buckets;
- campaign burn-down;
- signature/trust failures; and
- policy changes that altered current acceptance.
HTML is one serialization of the immutable report model. It is not a web UI, server, API, status endpoint, or ledger editor.
git review report --format html --at HEAD --output review-report.html
The default output is one self-contained HTML file:
- generated from explicit source, review-ref, policy, locale, and current-time inputs;
- deterministic apart from those explicit inputs;
- usable directly from a local file URL;
- no network requests, remote fonts, analytics, or live data;
- no server/runtime dependency;
- no mutation controls;
- no JavaScript required for the report's meaning or navigation;
- embedded CSS and compact report data; and
- suitable for a CI artifact or for an unrelated host to serve as a static file.
For exceptionally large reports, --assets separate may create an HTML file plus content-addressed static CSS/data assets. The report must warn that the files travel as one bundle. --output - and --output @stdout emit HTML to stdout.
Every report header identifies:
- project and target commit;
- review-ref commit;
- policy blob;
- tool/schema/mapping versions;
- generated-at time and time source;
- effective locale;
- whether source/review separation verified; and
- any incomplete inputs.
A linked table of contents leads to:
- Executive summary — gate, exact reasons, synchronization/trust, coverage, freshness, open findings, campaigns, and recent changes.
- Coverage and debt — per-scope atoms/lines/bytes, stale/unreviewed/ changed/ambiguous/insufficient breakdown, and denominator/exclusions.
- Changed-code report — base/head coverage, changed-after-review warnings, and current gate failures.
- Files and selections — path/symbol/hunk tables with effective and historical reviewer layers. Optional --detail lines includes code excerpts with line gutters; summary mode does not embed an entire repository.
- Findings — severity, anchors, lifecycle, reproduction, disposition, and verification evidence.
- Freshness queue — aging, risk priority explanation, and campaign progress.
- Reviewers and provenance — humans/agents/runners, scopes, independence, protocols, signatures, receipts, producer mapping, and evidence availability.
- Policy explanation — effective rules, path classifications, exemptions, and the complete gate trace.
- Appendices — schema/tool versions, warnings, excluded/generated/vendor/ binary inventory, and reproducibility command.
Stable fragment IDs link directly to files, selections, reviews, findings, and policy reasons inside the generated document.
- Responsive content width up to roughly 1600–1800 px for dense code/report tables.
- Vertical stacking for narrow charts and detail cards.
- Light/dark themes honoring system preference.
- Professional typography with a monospaced code face drawn only from local system fonts.
- Restrained status palette with patterns/icons/text labels.
- Tables degrade to labeled cards at narrow widths.
- Charts always include accessible tabular values.
- Dates show local time with UTC alongside or in an accessible detail.
- Every percentage links to its numerator, denominator, and exclusions.
- A print stylesheet produces a legible audit packet.
Target WCAG 2.2 AA:
- logical heading/landmark order;
- keyboard-reachable links and disclosure elements;
- visible focus;
- semantic tables;
- sufficient contrast;
- reduced-motion support;
- no color-only status;
- accessible chart summaries; and
- screen-reader text for icons.
All repository strings, code, findings, Markdown, and filenames are untrusted:
- escape HTML and attributes;
- sanitize any permitted Markdown;
- never include or execute repository JavaScript;
- emit a restrictive Content Security Policy;
- strip dangerous URL schemes;
- suppress terminal controls before embedding text;
- cap input/event/render sizes; and
- test malicious closing tags, bidi controls, long strings, and malformed Unicode.
Machine consumers use the separate JSON/NDJSON/SARIF report formats. There are no HTTP endpoints in this specification.
- Git subcommand discovery through git-review executable.
- Optional merge driver.
- Optional local pre-push invariant check for fast feedback.
- Authoritative pre-receive/forge-app validation of review-ref updates.
- Orphan review history plus source-branch ancestry/sentinel rejection.
- No mandatory pre-commit review because an immutable commit does not yet exist.
- Optional post-commit suggestion that creates no event automatically.
- Branch/ref protection for policy and ledger.
- Commit/PR trailers may carry producer session or review IDs, but the ledger remains canonical.
CI flow:
- fetch source target/base and review ref;
- verify ledger invariants/signatures;
- rebuild generated index;
- evaluate policy for exact target commit;
- publish terminal summary, JSON, static HTML, and SARIF artifacts;
- attach precise annotations for current findings;
- fail only according to configured enforcement phase.
Mechatron Prime can generate/archive the HTML report, publish forge checks, issue trusted receipts, and rerun policy checks when the review ref changes. Review-ref events should not trigger full product builds unless policy explicitly asks; they trigger the much cheaper review verification/report job. Serving the resulting HTML, if desired, is an independent static-hosting concern and not part of git-review.
- Publish a Check Run or commit status for the exact source SHA.
- Link annotations to finding IDs and report anchors.
- Import forge review metadata as lower-assurance evidence unless exact selections/protocols are known.
- Listen for review-ledger changes and refresh source-SHA status.
- Do not depend on a mutable PR number as canonical subject identity.
- Protect against stale approval after force-push by checking exact head SHA.
- Reject source targets connected to the orphan review lineage or containing its sentinel/ledger path.
- Restrict review-ref writes to a pre-validating path when the forge cannot execute an authoritative pre-receive hook.
Future adapters can use stable JSON or an LSP extension to show:
- line/symbol review layers;
- stale/unreviewed markers;
- findings;
- queue actions; and
- exact explain trace.
Editors should invoke CLI commands rather than reimplement policy/mapping.
Export current actionable findings to SARIF. Preserve git-review finding IDs in properties so imported dispositions can map back. SARIF cannot represent the whole review ledger; it is a findings interchange, not canonical storage.
git review import markdown may assist a human in converting existing CODE_REVIEW.md or inbox reports, but it cannot infer exhaustive line coverage or independence automatically. The import wizard must show every inferred field and default uncertainty to unknown/targeted.
The initial implementation is in prepare phase:
- English UI is complete.
- User-facing strings live behind typed keys from day one.
- The locale loader recognizes the canonical 50 locale codes: am, ar, az, bg, bn, bs, da, de, el, en, es, fa, fi, fil, fr, ha, he, hi, hr, hu, id, ig, is, it, ja, km, ko, mk, nb, nl, pa, pl, ps, pt_br, ro, ru, sl, sq, sr, sv, sw, ta, th, tr, uk, ur, vi, yo, zh_hans, and zh_hant.
- Missing non-English catalogs are loud but non-fatal during prepare phase.
- English-is-complete is tested immediately.
- --lang overrides GIT_REVIEW_LANG, then LANG, LC_ALL, LC_MESSAGES, and LANGUAGE, with platform-native signals where supported.
- Machine JSON keys, schema enums, signatures, and IDs never translate.
- Human display labels, help, prompts, and errors do.
- Non-English errors include the English original as a searchable shadow.
- RTL locales ar, he, fa, ps, and ur receive correct bidi marks, layout mirroring, and grapheme-aware terminal width.
- HTML reports set language and direction semantically.
When the UI stabilizes, switch to enforce phase: all 50 catalogs complete, missing keys fail the build, localized command aliases are collision-checked, and locale/RTL/env-precedence tests become mandatory.
Public ledger defaults:
- actor IDs without private email;
- prompt/protocol references and digests;
- no raw conversation;
- concise findings with only necessary code excerpts;
- artifact visibility/retention metadata;
- no environment-variable dumps;
- no provider API secrets;
- no absolute home paths unless explicitly public; and
- configurable redaction before signing.
Once signed and published, sensitive data cannot be truly removed without history rewriting and signature/provenance consequences. The confirmation UI must make this clear.
Impose configurable hard limits:
- maximum event bytes;
- maximum string bytes;
- maximum selections/findings/evidence references per event;
- maximum nesting depth;
- maximum ledger events per command before explicit override;
- maximum diff/blob rendered in one view; and
- maximum decompressed artifact size.
Reject duplicate JSON keys and invalid UTF-8 where the schema requires text. Sanitize ANSI/OSC escape sequences in terminal output.
Threats and mitigations:
- Fabricated reviewer identity: trusted event signature and identity policy.
- Runner lies about model/session: runner trust, provider receipts, and clear assurance labels.
- Self-review presented as independent: producer provenance plus policy-derived classification.
- Ledger record edited/deleted: semantic append-only verification, protected ref, receipts/mirrors.
- Backdated fresh review: trusted observation receipt.
- Prompt substitution: template/rendered prompt and packet digests.
- Coverage inflation: explicit exhaustive modes, finite selection manifests, completion checks.
- Ambiguous code move: conservative mapping and ambiguous state.
- Finding hidden as “fixed”: immutable lifecycle and independent verification policy.
- Concurrent merge loss: set-union merge and same-ID conflict.
- Non-review files pushed to sideband: complete-tree allowlist plus authoritative old/new ref validation.
- Local hook bypass: local hook is advisory; remote pre-accept or capability-gated writer is authoritative.
- Review branch merged into source: unrelated-history refusal plus source sentinel/path/ancestry gate.
- Malicious HTML/terminal content: escaping, CSP, control stripping.
- Huge ledger/event DoS: streaming parser and resource limits.
- Policy weakened to pass: protected policy, policy-change report, and optional meta-review requirement.
Zig is a strong fit for a portable, fast, single-binary Git extension with a pure core. The initial executable should use:
- pure Zig domain core;
- thin Zig CLI/I/O adapter;
- Git command adapter or libgit adapter behind an interface;
- pluggable signer;
- optional SQLite index adapter only after measurement; and
- pure terminal/HTML report renderers.
A C CLI solely to “dogfood” an FFI would add substantial JSON, Unicode, and subcommand plumbing without an immediate consumer. Do not add a public C ABI until an editor/service integration actually needs it. If one is added, keep the core in-memory and expose explicit ownership-safe functions.
Pure domain:
- schema validation;
- canonicalization;
- event-set merge;
- policy classification/evaluation;
- selection mapping;
- freshness calculation;
- independence assessment;
- finding lifecycle reduction;
- report model construction; and
- terminal/HTML rendering.
Injected adapters:
- Git objects/diffs/refs;
- filesystem;
- clock;
- UUID RNG;
- signature provider/verifier;
- artifact store;
- network/forge;
- generated index; and
- terminal capabilities.
The core receives immutable data and returns immutable results/errors. No core function reads the current clock, environment, Git repository, or network.
Version 1 may invoke the installed Git executable because:
- git-review already requires Git;
- command behavior is portable and well-tested;
- object-format and ref operations are available;
- it avoids binding a large native Git library immediately.
The adapter must use argument arrays, never shell command interpolation, and must parse stable plumbing formats with NUL separators. Replace it only if benchmarks or deployment constraints justify the complexity.
Start with streaming ledger parsing plus an in-memory index. Add SQLite under .git/git-review only when benchmarks show need. Index metadata binds to:
- ledger ref commit;
- target source commit;
- policy blob;
- tool/schema version; and
- mapping algorithm version.
Any mismatch causes rebuild. Reports never quietly mix index state from a different commit.
The project provides:
- ./test — all unit, integration, and CLI tests;
- ./build — optimized build by default;
- ./bm — benchmarks, if established;
- ./fuzz — fuzz suites, when established; and
- flake.nix — hermetic dependencies and CI checks.
No implementation behavior lands without a prior failing test except covered refactoring.
Use injected clocks and deterministic UUID randomness. Cover:
- every event type/schema boundary;
- canonical JSON and signature vectors;
- UUIDv7 validation/order/collision;
- semantic append-only comparisons;
- three-way event union;
- same-ID/same-payload and same-ID/different-payload;
- finding state-machine transitions;
- policy predicates and precedence;
- path filters as classifiers over full sets;
- every evidence state;
- sideband bootstrap/tree/linear-parent invariants;
- source/review ancestry and sentinel separation;
- freshness boundary instants;
- signature/key rotation/revocation;
- independence fact combinations;
- selection validity boundaries;
- line parsing including final non-LF line;
- SHA-1 and SHA-256 object IDs;
- binary, LFS, submodule, generated, and vendor handling;
- merge-parent ambiguity;
- rename/move/duplicate-selection mapping;
- no-carry and transformation bridges;
- JSON/NDJSON/SARIF report models; and
- locale parsing/RTL preparations.
Create isolated RAM-backed Git fixtures with:
- normal commits and branches;
- sideband ledger branch;
- no-parent bootstrap with immutable sentinel/README;
- rejected extra sideband path and rejected sideband merge commit;
- ordinary source merge refusing unrelated review history;
- explicit unrelated-history merge rejected by the source gate even after sentinel deletion;
- embedded ledger mode;
- two concurrent reviewers;
- rejected push/retry;
- rename, move, copy, deletion, cherry-pick, and merge;
- SHA-256 repository where supported;
- signed/unsigned/tampered events;
- shallow clone and missing objects;
- corrupted/stale generated index;
- policy tightened/loosened across commits;
- compromised key/revocation;
- report generation; and
- network-unavailable sync.
Do not use sleeps. Coordinate concurrent tests with barriers, callbacks, or mock adapters.
Bash tests assert:
- all commands/help/about;
- stdout/stderr separation;
- exit-code contract;
- @stdin/@stdout and - support;
- paths with spaces and Unicode;
- no prompts in non-interactive mode;
- Ctrl-C/draft recovery;
- later-option precedence and -- terminator;
- clean expected-error capture;
- terminal widths/capabilities;
- no ANSI/control injection;
- JSON envelope stability; and
- i18n prepare warnings.
Render terminal and HTML from pure fixtures at wide, medium, narrow, and mobile dimensions. First dump real output for Peter's visual approval; only then encode golden assertions. Test progressive degradation, dark/light, no-color, simple ASCII, RTL, long paths, many reviewer layers, and large counts.
- Property: event union is commutative, associative, and idempotent unless a conflicting duplicate ID exists.
- Property: canonicalize(parse(canonicalize(x))) is stable.
- Property: adding events cannot remove an existing historical event.
- Property: mapping never yields more unique effective targets after ambiguity is introduced.
- Property: policy explain trace and decision agree.
- Mutation: event-loss/conflict/signature checks must kill deliberately broken implementations.
- Fuzz: JSON/NDJSON parser, policy parser, diff/path decoder, merge driver, signature envelope, SARIF import, and HTML/terminal escaping.
ReleaseFast only. Track CPU and wall time for:
- streaming 10K/100K/1M events;
- rebuilding index;
- querying one line/file/reviewer;
- mapping a large rename-heavy history;
- merging concurrent ledgers;
- generating static reports; and
- evaluating large path classifier sets.
Record event count, bytes, repository size, Git version, CPU, and memory. A regression threshold requires explicit acceptance; benchmark rerun is that acceptance.
Build/test:
- Linux x86_64;
- Linux aarch64;
- macOS aarch64;
- Windows x86_64; and
- Windows aarch64.
Path parsing, executable discovery, terminal capability, signing, file locking, and atomic ref/update behavior need platform fixtures.
- Schema identifiers are explicit strings, not inferred from fields.
- Readers preserve unknown extension events.
- Core unknown fields fail closed unless a newer compatible schema declares them.
- Signed historical events are never rewritten merely to upgrade schema.
- New readers reduce old versions into the current in-memory model.
- git review migrate --dry-run reports effects before adding bridge/import events or changing storage layout.
- Policy schema and event schema version independently.
- Mapping-algorithm version is included in generated explanations/indexes, not signed as if it were historical fact.
- Export can materialize a normalized current-state report without pretending it is the canonical event ledger.
- Initialize policy and sideband ledger.
- Configure authoritative review-ref invariant enforcement before sharing the ledger; local hook alone is reported as advisory.
- Configure source sentinel/path/ancestry rejection.
- Import existing review documents as targeted/unknown-assurance evidence.
- Generate reports.
- No blocking gate.
- Require packets and structured records for new important changes.
- Warn on missing required-scope coverage.
- Sign runner observations where possible.
- Publish reports without failing merges.
- Block protected-branch changes with uncovered required atoms or unresolved blocking findings.
- Require exact head SHA and synchronized ledger.
- Permit visible, expiring break-glass.
- Require independent reviewer classifications on high-risk paths.
- Enforce scope-specific freshness.
- Launch bounded campaigns for historical debt.
- Require reproducible or externally anchored evidence for critical scopes.
- Add trusted receipts/protected review ref.
- Use cryptographic capability separation only where justified.
Historical unreviewed code should not prevent initial adoption. Gate the diff first, then burn down debt deliberately.
Version 1 is done when:
- git review init creates a valid sideband or embedded configuration;
- humans can record a multi-file, multi-scope review without editing JSON;
- LLM runners can submit strict JSON non-interactively;
- every event is canonical, immutable, UUIDv7-addressed, and optionally signed;
- concurrent ledgers union without loss;
- conflicting duplicate IDs fail loudly;
- status can distinguish fresh, stale, unreviewed, changed, ambiguous, insufficient, exempt, excluded, and not-applicable;
- line/file/symbol queries show all historical and effective layers;
- exact renames/moves carry conservatively and ambiguous copies do not;
- findings have immutable lifecycle events;
- policy check produces a deterministic decision and explanation trace;
- static terminal/JSON/HTML/SARIF reports agree on the same report model;
- HTML output is self-contained, read-only, and needs no server;
- review-ref updates enforce the orphan tree/linear-history/append-only invariant before acceptance;
- source gates reject the sideband sentinel, ledger path, and review ancestry;
- source-only CI can ignore sideband review commits while review status updates;
- secrets/raw transcripts are not stored by default;
- English UI is complete and i18n prepare infrastructure exists;
- the entire test suite is one clean ./test command;
- builds pass on the five target OS/architecture combinations; and
- documentation includes threat model, storage recovery, key rotation, sideband sync, and emergency exemption procedures.
Recommendation: executable git-review; repository/project name may be git-review unless package registries require a more distinctive name.
Recommendation: sideband code-reviews branch for Peter's Nix/Mechatron fleet; embedded mode for small third-party projects that reject extra branches.
Recommendation: schema/signing support from the first release, advisory unsigned records during Stage 0, signatures required before a record can satisfy protected-branch policy.
Recommendation: commit reusable protocol/templates; retain rendered prompt and transcript digests by default; store full artifacts only in an explicitly configured private content-addressed store. A hash-only record is honest but not independently readable after artifact loss.
Recommendation: ranges and whole files are mandatory v1; add parser-backed symbols incrementally. Always store a concrete range fallback. Do not delay the ledger waiting for universal language parsing.
Recommendation: no global blocking age until projects observe real usage. Start with advisory 365-day default, shorter explicit rules for security and supply-chain scopes, then tune from evidence.
Recommendation: do not make one percentage the primary truth. Show per-scope atom/line/byte metrics and gate changed atoms. Any headline number must link to exact denominator/exclusions.
Recommendation: generated HTML report only. Do not implement an HTTP server, live API, badge host, or browser mutation controls. This keeps key custody, authentication, CSRF, synchronization, and canonical writes in the CLI/CI paths and prevents report presentation from becoming a second product.
Recommendation: exclude raw ledger data from product coverage; include codereview-policy.json and the git-review tool itself under a separate, high-independence meta-review protocol. Policy changes should be prominent in reports and protected by code ownership.
Recommendation: keep v1 explicitly experimental until at least several Peter-owned projects and one external fork have exercised concurrent review, renames, stale campaigns, CI gates, and recovery. Freeze a public schema only after those migrations reveal what is missing.
- The hardest problem is not JSON storage; it is making the coverage claim precise enough that green means what readers think it means.
- File/line identity is mechanical. Review quality and semantic equivalence are not. Keep that boundary visible.
- Independence must be based on provenance and controls, not reviewer confidence or a checkbox.
- Review age is useful, but indiscriminate staling can create enormous busywork and incentivize shallow rubber-stamping.
- Raw LLM transcripts are both bulky and likely to leak secrets. Hash and retain selectively.
- A headline HTML status is an invitation to overinterpret. Label it as a policy gate or evidence freshness, never a safety warranty.
- A Git ledger can still be rewritten. Trusted receipts, mirrors, protected refs, and signatures are what make tampering meaningfully detectable.
- Sideband storage avoids Nix rebuild churn but CI must fetch and synchronize the review ref explicitly.
- Automatic mapping must prefer false negatives over false positives. “Ambiguous” is a successful, honest result.
- The tool should reduce review friction. If entering one ordinary review feels like filing taxes, people and agents will route around it. Packets, drafts, defaults, strict machine schemas, and excellent reports are core product behavior, not polish.
Build the smallest vertical slice that can disprove the core design:
- git review init with sideband branch and policy;
- review-event schema, UUIDv7, deterministic JSON, and event-set merge;
- interactive add for one snapshot range and one scope;
- non-interactive add from strict JSON;
- verify, sync, status, line, and explain;
- freshness by injected clock;
- exact blob rename mapping and ambiguous-copy refusal;
- one terminal overview, one JSON report, and one static HTML report;
- optional SSH Ed25519 runner signature; and
- CI policy check for changed ranges.
That slice exercises identity, concurrency, storage, trust, mapping, human UX, LLM UX, reporting, and the Nix-friendly sideband decision before committing to symbol parsers, a database, or forge importers.