Thales
← research journal

An internal research document, published verbatim by the automated daily export — not written for an audience, and better for it. All performance discussed is simulated paper trading; nothing here is investment advice.

FRZ-2 — FRZ-1 said B4 and B5 were "the only" unenforced append-only pre-registrations; they are four. The C2 null-calibration memo and the C4 purge-leak memo declare the same freeze and have none — and both are cited as BINDING by CLAUDE.md and by the current production purge_days

status: open · raised 2026-10-21 (implementer, building FRZ-1 — found by the generalisation test that build added, not by reading; FILED not fixed, because cutting a freeze hash is the owner's input) · class: C0, registration hygiene (G5) — a declared freeze with no mechanism behind it · judgement: YES · effort ~0.1 pd (the apparatus now exists; this is two hashes and one allowlist entry removed) · horizon: decidable immediately


Plain-language summary for an owner reading one paragraph. FRZ-1 fixed two documents that claimed a checksum lock they did not have. Its body states that those two "are the only self-declared-append-only pre-registrations in research/ with no mechanical enforcement." That is false, and the FRZ-1 build proved it mechanically rather than by argument: the generalisation test it added — any file under research/ that declares itself append-only must be named by a hash test — failed on first run and named two more, the C2 null calibration memo and the C4 purge-leak memo. Both open with the words "Status: BINDING PRE-REGISTRATION, append-only after today." Neither is hashed. Both are load-bearing right now: CLAUDE.md makes C2 the binding convention for how every PBO and IS-OOS-correlation figure in the shop must be quoted, and C4 is the memo behind the current production cpcv.purge_days: 504. The fix is the one FRZ-1 just built, applied twice more.

Verified at HEAD fad1d78 (FRZ-1's base commit)

  • research/2026-08-01_c2_null_calibration_memo.md:3 — "Status: BINDING PRE-REGISTRATION, append-only after today. Written and committed BEFORE any calibration run exists (panel item C2 …). The runner (scripts/run_null_calibration.sh) refuses to execute unless this file is present, and every result JSON records this …" — 213 lines, no hash test.
  • research/2026-08-01_c4_purge_leak_memo.md:3 — the same sentence, same structure, for the C4 grid (scripts/run_c4_purge_grid.sh) — 181 lines, no hash test.
  • The hash-frozen set in tests/test_docs_consistency.py before FRZ-1 was exactly five (December memo, micro-cap battery, A4 DTC memo, VRP v2 spec, NORTHSTAR §1–§5); FRZ-1 makes it seven. Neither C2 nor C4 is in it.
  • Both are currently carried as RECORDED, not silently passing: test_every_self_declared_append_only_registration_has_a_hash_test holds them in a RECORDED_UNENFORCED dict that cites this row by name. Delete the two entries and the test reds until the hashes are cut — so this row cannot be forgotten, and closing it is mechanically checked.

Why the stakes are not lower than FRZ-1's. C2 fixes what "no-skill" looks like on this harness (its no-skill band, median |corr| 0.443, is the reason a negative IS-OOS correlation is not standalone evidence of overfitting) and every PR in the shop is required to quote null percentiles "per research/2026-08-01_c2_null_calibration_memo.md". C4 is the pre-registration behind a production config value that was actually changed — purge_days 252 → 504. A quiet edit above either line would rewrite the standard by which results are read, after the results exist. That is the exact act the freeze doctrine exists to prevent.

The fix

Exactly FRZ-1's, applied twice:

  1. Two sentinel-hash tests in tests/test_docs_consistency.py on the December-memo pattern. Neither memo carries a sentinel phrase today — unlike B4/B5, whose §8 blocks name one — so the owner picks the freeze boundary, or a sentinel line is appended to each as a dated append (which is itself legitimate under their own declaration) and the hash cut above it.
  2. Add both to DENY_PATTERNS in scripts/automerge_guard.py, beside the two FRZ-1 added.
  3. Delete the two RECORDED_UNENFORCED entries, which reds until (1) lands.

Test design + negative control

Identical to FRZ-1's, which the owner has already accepted: an in-place edit above each sentinel must red the gate suite as CI invokes it (pytest tests/ -m "not observability and not research"), and a dated append below it must still pass. Plus: deleting a RECORDED_UNENFORCED entry while the hash test is absent must red — the allowlist must not be able to go stale in the silent direction.

Pre-registered kill criterion

This row dies if the owner rules that C2 and C4 are not append-only, in which case the declaration at :3 of each is removed by a dated append and they become ordinary living records. It does not die on "git history is the record" — the December memo's own test docstring rejects that argument, and FRZ-1 was approved over it.

Note on provenance and on the claim it corrects

Found while building FRZ-1 (PR for 2026-10-21). This row is the reason the FRZ-1 build kept its generalisation test rather than the two hard-coded tests its approval literally scoped: the hard-coded pair would have left this undiscovered and the false "only two" claim standing. FRZ-1's body is not edited to fix that claim — an in-place rewrite of an open registration is the same act FRZ-1 is about. It is corrected here, in a dated row, which is the discipline.