Every AI review tool starts with a model reading a diff. PatchArc starts with a database reading Git. The review it produces is computed, not generated: seal the same Arc twice and you get byte-identical output. This post explains why we chose that, and exactly how each of the six sections is derived in 0.2.0, including the places where the derivation is a deliberately simple placeholder.
Why deterministic
A signature is only as useful as the thing it signs. If the review were a model's paragraph, signing it would prove that paragraph was not edited, which is not what a reviewer wants to know. By computing the review from evidence that is itself inside the capsule, the signature covers the whole chain: these commits, these files, these notes, and this review derived from them. Anyone can recompute it. A model summary can sit on top later, clearly labelled inferred, without touching the verified layer.
The inputs
The local SQLite store records sessions, commits (SHA, author, time, message, parents), file changes per commit (path, status, additions, deletions), checkpoints, and events (notes, decisions, risks). The observer fills the Git tables by polling plumbing every 1.5 seconds; you fill the events table by typing one-line commands.
Section by section
1. Goal
The string passed to patcharc start, or Untitled Arc. Trivially deterministic, and the most under-used input: write the sentence you would put at the top of the PR.
2. What changed
Counts and the file list, from the recorded commits and git diff-tree --no-commit-id -r --name-only <sha> per commit. This second pass is what makes per-scope attribution correct; the first pass in the code is a placeholder that attributes every commit to every scope and is then overwritten.
3. Affected scopes
Each changed file is classified in order: graph cross-cutting globs, config cross-cutting globs, scope paths in declaration order, else unclassified. Per scope: commits, files, additions, deletions, and a severity band (500+ changed lines major, 100+ moderate, otherwise minor). Untouched scopes are omitted. Ten workspace detectors or explicit config supply the scopes.
4. Verification
Passed, failed, skipped, summed from recorded test runs. Honest status: nothing records test runs in 0.2.0, so this section is zero. The classifier (junit, pytest, vitest, jest, go as unit; playwright and cypress as end-to-end) exists and waits for a parser.
5. Phases
Commits sorted by author time, split into thirds, labelled Foundation, Implementation, Verification and cleanup. One commit yields a single phase. This is a reading aid, not inference; the labels are positional. We considered inferring phases from content and decided a transparent rule beats a plausible guess in a signed artifact.
6. Decisions and remaining risk
Every decision and risk event with its timestamp, then notes. This is the only section that depends on a human, and it is the section reviewers value most.
Evidence ids
Each entry carries ids like commit_a1b2c3d and file_apps_web_src_… pointing at files inside the capsule, so any claim in the review resolves to the patch that supports it. A future claim-validation step in the cloud pipeline will check those links; today the step exists and is a no-op.
What a model would add
Prose. A model can turn section two into three readable sentences and section six into a paragraph. It cannot add facts the evidence does not contain, and in our design it never will: model output is a separate layer with the trust level inferred, rendered apart from the computed review. When summaries ship, they will be built from the capsule you already chose to upload, through either your own key or managed models with content logging off.
Recompute it yourself
$ unzip -p capsule.parc evidence/summary/review.json | jq '.scope_summaries[] | {scope_id, severity, additions, deletions}'
$ unzip -p capsule.parc evidence/file_changes.json | jq 'group_by(.commit_sha) | map({sha: .[0].commit_sha, files: length})'
If the numbers do not match the review, the capsule would not verify. That is the whole point.