Unblinded after review: A = Claude Haiku 5.5, B = GPT-6 Luna, C = Mercury 3. Written by a reviewing agent (Opus) and published unedited. # c09-sha256-validate review All three candidates validate `sha256` in `WardFile::from_toml` with the same byte-level check: length 64, and every byte in `[0-9a-f]`. Each passes its own suite (A 204, B 202, C 205 tests), all 5 hidden tests, `cargo fmt`, clippy (0 new diagnostics) and dprint. I also ran an extra battery against each candidate's built binary, using copies of the trees. It covered: - a root ward containing `abc` under `status`, `status --all`, `status --diff`, `verify`, `update`, `update --dry-run`, `update --allow-init`, `update --fingerprint` and `init` - a TOML `\u001b` escape - a corrupt subdirectory ward with the root uninitialized (`init` walks it) - uppercase hex in a subdirectory ward - an entry name containing control characters (to check how the error renders) - a bad sha on an entry whose file was deleted - a valid but mismatching digest carried through `update` Every failing command exited 255 and left both ward files byte-identical. ## Candidate A: overall 9/10 Verdict: a reference-equivalent fix, plus an `init` fix so the error names the entry. Thorough tests, an accurate summary. | Requirement | Verdict | Evidence | | ------------------------------------------------- | ------- | ---------------------------------------------------------------------------- | | Reject malformed sha256 (all shapes) | met | Byte-level check; repro: abc, `\u001b`, uppercase, multi-byte rejected | | Exit 255 for status (all modes), verify, init/update | met | Every command in the repro battery exits 255 | | Fail before use; update doesn't carry it forward | met | Load-time check; ward files unchanged | | Error names the entry | met | `Invalid checksum for ward entry "a.txt"`, including init on an existing root | | Subdirectory wards validated | met | Corrupt `sub/.treeward` gives exit 255 naming b.txt | | Valid mismatching digest unchanged | met | status 0, update keeps it, `--always-verify` gives 1 | Bugs: - minor (verified): the `ward_directory` doc comment in `src/update.rs` still says an existing root is always `AlreadyInitialized`. It now returns a ward-file error when the root ward is malformed. Scope: - SPEC.md updated. - The `init` load-before-refuse change is justified: the prompt lists `init` and asks for the entry name. - The fixture migration was required, and it keeps each fixture's intent. - CHANGELOG left alone. The summary explains why: the file is generated by git-cliff. Tests: - Unit matrix of 9 malformed TOML literals, including the `\u001b` escape and a trailing space. - Non-file entries are not checked; a valid mismatching digest loads. - CLI matrix of 7 commands × 3 values. - `init` does not rewrite the file; a valid mismatching digest reports `M`. ## Candidate B: overall 8/10 Verdict: correct and complete, with the same `init` fix as A plus a write-side guard in `to_toml`. The tests are thinner, and it adds CHANGELOG churn. | Requirement | Verdict | Evidence | | ------------------------------------------------- | ------- | ------------------------------------------------------ | | Reject malformed sha256 (all shapes) | met | Byte-level check; repro confirms | | Exit 255 for status (all modes), verify, init/update | met | Whole battery exits 255 | | Fail before use; update doesn't carry it forward | met | Load-time check, plus `to_toml` check; ward files unchanged | | Error names the entry | met | `Invalid SHA-256 checksum for entry "a.txt"`, including init | | Subdirectory wards validated | met | Repro: b.txt named | | Valid mismatching digest unchanged | met | Own CLI test and repro | Bugs: none found. Scope: - SPEC.md updated. `update.rs` doc comment updated alongside the `init` change. - The hand-written `[Unreleased]` entry in `CHANGELOG.md` is unjustified. CONTRIBUTING.md says the changelog is regenerated by `git-cliff -o`. - Minor blank-line nits. Tests: - Unit test: 6 malformed values, including a `\n` escape and 32×`é`, plus a serialization-rejection test. - CLI test: 11 command variants with an assertion that stdout is empty. - Gaps: only `abc` is used at the CLI level, there is no subdirectory case, and nothing checks that the ward file is left unchanged. ## Candidate C: overall 7/10 Verdict: reference-equivalent and with the broadest spread of tests. However, `init` on a corrupt existing root does not name the entry, the CHANGELOG edit is unwanted, and the summary contains one inaccurate claim. | Requirement | Verdict | Evidence | | ------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------- | | Reject malformed sha256 (all shapes) | met | Byte-level check; repro confirms | | Exit 255 for status (all modes), verify, init/update | met | All exit 255 | | Fail before use; update doesn't carry it forward | met | Load-time check; ward files unchanged | | Error names the entry | met | `... for entry 'a.txt'`. Exception: `init` on an existing corrupt root prints only "Already initialized" (that path never loads the file; the reference does the same) | | Subdirectory wards validated | met | Repro, plus its own init test with a corrupt subdirectory ward | | Valid mismatching digest unchanged | met | Repro | Bugs: none found. The `init` path behaves exactly like the reference and is documented in the summary, so I do not count it as a bug. Scope: - SPEC.md updated. - The `CHANGELOG.md` `[Unreleased]` entry is unjustified. C even notes that the file is generated by git-cliff. - The `tests/common` helper is justified. - Formatting nits: no blank lines between the new items. Tests: - 10 unit cases, including escaped `\n` and `\"`, and a sibling test checking that the error names the bad entry rather than a good one. - CLI tests spread across status (5 modes), verify, update, and init (corrupt subdirectory ward). - A valid mismatching digest returns exit 1. Summary honesty: accurate except for one claim. It says the manual CHANGELOG entry "will be folded on next release". `git-cliff -o` overwrites the file from commit metadata, so the entry is not folded in. ## Ranking 1. A (9) 2. B (8) 3. C (7) ## Comparison All three implemented the same correct core at the parse boundary and passed every hidden test and my extra repros. They differ only at the margins: - **A** is the cleanest. It names the entry even for `init` on an existing root, makes no CHANGELOG change, and has the most careful malformed-literal matrix plus a check that the ward file is not rewritten. Its only flaw is a stale doc comment. - **B** has the same `init` behavior as A and a defensible write-side guard. Its tests are thinner, and it edits the generated CHANGELOG by hand. - **C**'s tests are broader than B's. However, it leaves `init` reporting a bare "Already initialized" for a corrupt root, makes the same CHANGELOG edit, and slightly misstates how git-cliff handles that edit.