# 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:

1. Two tests in `tests/test_docs_consistency.py` modelled on
   `test_december_memo_frozen_section_unchanged` (`:316`): sentinel lookup,
   sha256 of everything above it, pinned hex. The B4 pin's sentinel is its
   `## 8. Change discipline` block at `:219-226`; B5's is at `:163`.
2. Add `^research/2026-08-01_b4_skew_activation_pin\.md$` and
   `^research/2026-08-01_b5_turn_of_month_pin\.md$` to `DENY_PATTERNS` in
   `scripts/automerge_guard.py:61-73`, beside the `NORTHSTAR.md` entry.

**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**:

1. **You rule that the two pins are not append-only.** The declarations at
   `b4…:221` and `b5…:163` are 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.
2. **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`, no `data/raw`, no `data/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.
