FRZ-1 — the B4 and B5 pins say they are append-only "like the December memo"; the December memo is enforced by a hash test and these two are enforced by nothing, while the auto-merge guard grades an in-place edit of either as ALLOW
status: open · raised panel run 30 (2026-09-29; panel-chair catch, verified with both a negative and a positive control — a records/trust defect row, not a research or capture proposal, so it does NOT discharge the scout's 8-week cadence clock; same treatment as BTB-1 and CQA-3) · class: C0, registration hygiene (G5) — a declared freeze with no mechanism behind it · effort ~0.25 pd · horizon: decidable immediately; the BTB-1 ruling it unblocks is already pending
Plain-language summary for an owner reading one paragraph. This shop freezes its pre-registrations so that nobody — including a future agent — can quietly rewrite the exam after seeing the answers. For five documents that freeze is real: a test computes a checksum of the protected text, and any edit above the line turns the test suite red. Two documents say they have that same protection and do not have it: the B4 option-skew activation pin and the B5 turn-of-month pin — the pre-registrations for the only two live forward experiments in the shop. Nothing computes a checksum for either. Worse, the automatic-merge guard treats an edit to either file as an ordinary record change and grades it ALLOW, so a routine's pull request that rewrote the B4 pin's pre-registered text would merge unattended with no human ever seeing it. This is not hypothetical bookkeeping: the open row BTB-1 is waiting on your ruling about a false number inside the B4 pin, and one of the two options it offers you — "re-cut the hash with a recorded reason" — cannot be executed, because no hash was ever cut. The fix is to give the two pins the protection they already claim.
Mechanism — verified at HEAD ada5bff, with both controls
1. The declaration. research/2026-08-01_b4_skew_activation_pin.md:221:
"Append-only after today, like the December memo: corrections and context arrive as dated appends below this line, never edits above it."
and :3 — "Status: BINDING, append-only after today." The B5 pin carries
the same declaration at research/2026-08-01_b5_turn_of_month_pin.md:163.
2. The December memo really is enforced.
tests/test_docs_consistency.py:316 test_december_memo_frozen_section_unchanged
finds a sentinel line, hashes everything above it, and asserts a pinned
sha256. The same pattern protects the micro-cap battery pre-registration, the
A4 DTC memo, the frozen VRP v2 spec, and NORTHSTAR.md §1–§5.
3. Neither pin is in that set. grep over tests/ for b4_skew,
skew_activation or the pin's own figure 889 returns nothing. The two pins
are the only self-declared-append-only pre-registrations in research/ with no
mechanical enforcement.
4. NEGATIVE CONTROL — the edit that should be impossible is invisible. In a
scratch copy (never the repo), the pin's pre-registered §1 claim was inverted
in place — :43 "0 of 889 Russell-1000" → "45 of 903 Russell-1000", and
"degenerate on this universe" → "NOT degenerate on this universe",
i.e. the reasoning for a pinned design decision reversed:
pytest tests/test_docs_consistency.py -q -> 20 passed (unchanged)
5. POSITIVE CONTROL — the mechanism works where it exists. The same class of edit, applied above the December memo's sentinel in the same scratch copy:
pytest tests/test_docs_consistency.py -q
-> FAILED tests/test_docs_consistency.py::test_december_memo_frozen_section_unchanged
1 failed, 19 passed
So the detector is not broken — it simply does not cover these two files.
6. The auto-merge guard admits the edit. scripts/automerge_guard.py:44
allows the pattern ^research/[^/]+\.md$ and :100
ALLOWED_STATUSES = ("added", "modified"). Both pins sit at that path:
python3 scripts/automerge_guard.py \
--files research/2026-08-01_b4_skew_activation_pin.md \
--statuses research/2026-08-01_b4_skew_activation_pin.md:modified
-> ALLOW: records-only (1 file(s)); no gate touched
(same for research/2026-08-01_b5_turn_of_month_pin.md)
Control — NORTHSTAR.md, which IS named in DENY_PATTERNS at :69 with the
comment "hash-frozen span":
-> DENY: `NORTHSTAR.md` is in the never-auto-merge set
7. The path is live, not theoretical — and the point is that the guard
cannot tell the two shapes apart. Commit 57308d3 (panel run 27, PR #179, a
self-authored routine PR) carries
M research/2026-09-18_two_forward_gate_numbers_were_wrong.md. That change was
entirely legitimate — 127 insertions, zero deletions, i.e. a dated append,
exactly the discipline these documents ask for. That is the finding. A
dated append below the line and a rewrite above it are both modified on the
same allowed path, the guard grades them identically, and no test distinguishes
them for the B4 and B5 pins.
Why this is live this week rather than abstract
BTB-1 is blocked on a belief that is false.
research/queue/open/btb-1-borrow-flag-not-degenerate.md is open and awaiting
your ruling on the "0 of 889" figure. Its title says "one of them
hash-frozen"; :48 says "NO — hash-frozen pin. A post-hoc edit is
exactly the C0 breach the freeze exists to prevent"; and :159 puts a binary
choice to you: "dated append to the hash-frozen pin, or re-cut the hash with
a recorded reason."
The second option does not exist. There is no hash to re-cut. The queue's own memory is wrong about the protection state of the document the pending ruling concerns.
This run also measured how contagious the belief is: three independent agents in this single panel run — two lenses and an earlier reviewer — described the B4 pin as "hash-frozen" in their reports without checking. So did panel run 29 and the 2026-09-28 triage.
Separately, the B4 pin's 2026-09-02 append is still uncountersigned, and its clause (c) changes what counts as a valid signal date. A ruling on it is owed this week (see the run-30 note's expiry watch). Ruling on the contents of a document whose freeze is nominal is the wrong order of operations.
The fix
Copy the pattern that already works, verbatim — no new mechanism:
- Two tests in
tests/test_docs_consistency.pymodelled ontest_december_memo_frozen_section_unchanged(:316): sentinel lookup, sha256 of everything above it, pinned hex. The B4 pin's sentinel is its## 8. Change disciplineblock at:219-226; B5's is at:163. - Add
^research/2026-08-01_b4_skew_activation_pin\.md$and^research/2026-08-01_b5_turn_of_month_pin\.md$toDENY_PATTERNSinscripts/automerge_guard.py:61-73, beside theNORTHSTAR.mdentry.
The PR must carry the negative control (this panel's own standard): show that the in-place edit class which passes today now reds, and that a dated append below the sentinel still passes. A freeze that also blocks legitimate appends would be a worse defect than the one it fixes.
Do NOT fix BTB-1's wrong prose by editing BTB-1 in place. Annotate it at triage. An in-place rewrite of an open row is the same act this row is about.
Pre-registered kill criterion
This row dies if either:
- You rule that the two pins are not append-only. The declarations at
b4…:221andb5…:163are then removed by a dated append, and this row closes as mis-premised — the documents would simply be living records, and BTB-1's correction becomes an ordinary edit. - Someone produces a test showing an in-place edit above either sentinel
already reds the gate suite as CI actually invokes it — i.e. the negative
control above does not transfer to
pytest tests/ -m "not observability and not research". Then the protection exists and I measured the wrong thing.
It does not die on the argument that "git history is the record." That is
precisely the argument the December memo's own test docstring rejects
(tests/test_docs_consistency.py:318-321: "this memo claims append-only; git
history alone guarded that").
Cost, honestly
research/queue/open/ holds exactly 12 items, which is the pre-registered
cap (ops/QUEUE_TRIAGE.md:86-91). Opening this row means Monday's triage must
evict an incumbent. The adversarial reviewer's eviction nominee is RWG-1
(the queue's oldest, raised run 11 on 2026-08-20; its first leg was discharged
by you the same day, and the remainder has no date and no active bleed) — the
same nominee run 29 named and did not spend. Not CQA-3 (evicting it fires
CQA-2's reopen leg (c)) and not BTB-1 (this row exists to make BTB-1
decidable). The ranking call is triage's mechanical one on Monday, not the
panel's.
Registry cost: zero. No results/research_registry.jsonl row, no trial, no
deflated-Sharpe debt. This is apparatus, not a hypothesis.
What did not run
- No broker, no
config/.env, nodata/raw, nodata/lab, no owner-Mac access. None of the above needed any of them — every control is a text edit plus a test run plus one guard invocation. - The two hash values themselves are deliberately not computed here: cutting the hash is the build step, and the freeze must be cut from text you have agreed is the text to freeze.