# Claims review — 0.2.41

- base: v0.2.40
- head: dfce48b
- surface: sha256:7cc3272b04d9e8784ff14e73a882a7497998f7f0f12c240ec0c8c44e7609e51f
- verdict: pass
- reviewer: maintainer, reading a paragraph that was written to withdraw an
  earlier version of itself

Two surfaces changed.

`docs/RECEIPT-SPEC.md` — one section, replacing a stated limit that was true
about the vectors and wrong about where the limit would bite. Its heading moves
from `prose` to `measured` because `test/spec_jcs_class.mjs` now measures every
claim under it. Findings 1 and 2 are against the replacement text, not the text
it replaces.

`standards/README.md` — a "What `-06` added" paragraph, which every other
posted revision already had. Finding 3.

## Findings

### 1. docs/RECEIPT-SPEC.md — "the only surface" counted one caller out of five

- Claim: "That is the only surface where a second implementation can disagree
  with us about canonicalisation."
- Mechanism: `hashArgs()` is the one entry point taking `any`, so arbitrary keys
  and arbitrary numbers can only arrive through it. That much holds.
- Why it falls short: `canonicalize` has five callers — receipt bodies,
  countersign records, coverage rows, licence payloads, `hashArgs`. And a
  receipt's string *values* (`actor.id`, `model.name`, `policy.rules[]`) are
  free text with no ASCII constraint anywhere in `src/receipt.ts`, so
  `receiptHash` reaches string escaping on its own. "Only surface" was a claim
  about the whole codebase resting on a fact about one function signature.
  Written in the same commit that added a guard against exactly this shape of
  error.
- Disposition: reworded in `75dfe72`. The sentence now claims only that
  `hashArgs` is the surface whose *shape* is unbounded, and the paragraph
  names the other four callers and the free-text values.

### 2. docs/RECEIPT-SPEC.md — the heading moved to `measured`, and one row of the table under it is a sample

- Claim: heading "Canonical form, and where JCS is actually reachable —
  measured", over a table one of whose rows reads "3,000 published IEEE-754
  doubles".
- Mechanism: `test/spec_jcs_class.mjs` runs all six reference pairs, all 3,000
  vendored number lines, all eight preimages and all eight mutants on every
  `test:checks` run, and check 6 fails if the stated sample size and the
  fixture disagree.
- Why it falls short: `measured` is accurate for every row, but the number row
  measures 3,000 of 100,000,000 published values. A reader who takes `measured`
  to mean `covered` would be wrong about that one row, and the number class is
  the row where the difference matters — it is the only unbounded one.
- Disposition: accepted, and answered in the text rather than by softening the
  heading. The row is marked **sampled** in the table, a paragraph headed "What
  is still a limit" gives the ratio and the split between the reference's
  deliberate block and its pseudorandom tail, the guard prints `SAMPLED` on the
  passing line, and `test-vectors/jcs/rfc8785/PROVENANCE.md` states what was
  not vendored. Four places, because the one that gets read is not predictable.

### 3. standards/README.md — a third hand-written declaration of what `-06` says

- Claim: the whole "What `-06` added" paragraph, e.g. "every behavioural
  statement is bound to a run of the shipped reconciliation tool over a fixture
  the document names".
- Mechanism: the statement is true of the code — `test/implementation_status.mjs`
  holds the claim table between the prose and the CLI and runs every claim
  against the shipped binary, and `test/reconciliation_label_coverage.mjs` reads
  the outcome list from the tool's own result. The paragraph was written from
  the `-05..-06` diff rather than from memory.
- Why it falls short: writing it from the diff is a procedure, not a check.
  Nothing compares this paragraph to the draft it summarises. `standards_claim`
  and `datatracker_draft_status` read this file for other properties and neither
  reads this. So there are now three declarations of what `-06` contains — the
  draft, this paragraph, and the changelog — and two of them are prose that can
  drift while every test stays green. That is the same shape as the "twelve
  frozen cases" fork against a manifest holding thirteen.
- Disposition: accepted, shipping. The draft is normative and posted; this
  paragraph is a repo reader's summary, and the file already says two paragraphs
  below that the Datatracker link is the check and a revision history written
  here is not. The risk is bounded by that sentence rather than removed, and the
  paragraph is short enough that the next revision rewrites it rather than
  editing around it. Recorded because bounded is not the same as absent.

## Not a finding, recorded so the next reader does not re-derive it

The thirteen receipt vectors still do not exercise JCS beyond ASCII keys with
integer and string values. That is unchanged and is now stated in both
`RECEIPT-SPEC.md` and `test-vectors/README.md` as an unchanged fact rather than
as a gap awaiting a fix — the gap was never in the receipt vectors. A receipt
cannot carry the class; `hashArgs` can, and that is where the vectors went.
