Files
Syphon_Filter_3/config
Christopher Williams 9053a4dc51 phase12: merge 11 (646 bodies / 655 regions) + sf3_free: claimed is HELD, not FREE
MERGE 11: +7 bodies. All seven re-verified by me from fresh --work dirs BEFORE merging:
  0x800A6B38 (104 B, D)        0x8010036C (56 B, A, maspsx=epilogue)
  0x800690E4 (68 B, A)         0x800FE970 (84 B, C, maspsx=epilogue)
  0x80022E44 (52 B, B)         0x80047468 (72 B, B, gp=-D_80121BFC)
  0x80042D88 (76 B, B)
Gate: c_regions=655 differing_bytes=0 result=MATCH, SHA-1 unchanged. make check exit 0.
Registry: 646 distinct bodies, 0 missing sources, 4 carry cc1bin. Phase: 602 -> 646 = +44.

**sf3_free: a `claimed` ledger row is HELD, not FREE.** Worker D found this and reported it rather
than changing a tracked tool on its own judgement, which is the right instinct. The old rule was
`wip` -> TAKEN, else FREE, so a row whose last ledger row was `claimed` -- a worker holding a
STAGED, UNMERGED claim -- read as free. That is a false FREE in the dangerous direction: the row is
neither registered nor abandoned, so the next worker re-derives it and the merge can then receive two
claims for one address.

**This was not hypothetical. It is exactly what the credit outage produced**: all four workers
stopped with claims in flight, and I re-dispatched the pools underneath them. I recovered those rows
by auditing the staging files, but that was luck of ordering, not a mechanism. D reported the two
live instances it could see (`0x800460AC` held by B, `0x800FE970` held by C). `0x800460AC` I had
already merged, which masked the first one; `0x800FE970` was live when D wrote.

A registered row never reaches the changed branch -- `region_owner()` returns TAKEN first -- so the
new rule only ever fires for a claim whose merge has NOT landed, which is precisely the window at
issue. Measured after the fix:
    0x800FE970  TAKEN by inflight (claim staged, merge pending)
    0x80012A98  FREE (last ledger row 'released')      <- a genuine release still reads FREE
    0x800FECF8  FREE (last ledger row 'released')
    0x800ACA10  FREE (last ledger row 'released')

The residual risk is the opposite direction and is now an orchestrator DUTY, recorded here: if a
claim is ever REJECTED rather than merged, the merge path must append a `released` row, or that
address stays held forever. Nothing has been rejected so far this phase.

Also recorded from this batch:
* **B's `0x80047468` is the second worked case of cookbook 46's per-site override**: the registry
  marks `D_80121BFC` gp, but this row reads it absolutely (`lui v1,0x8012 / lw v1,7164(v1)`), so
  without `gp=-D_80121BFC` the candidate is one instruction SHORT (68 vs 72). C independently hit the
  same class on `0x800A6658` with `D_801226E0`. **The registry's gp marker is per-SYMBOL and the
  access form is per-SITE**, and two workers in one hour each lost time to that.
* **B and C independently converged on the same conclusion about what these negatives are worth:**
  B -- "the recorded class named the SYMPTOM (a merged store, a folded shift, a strength-reduce)
  while the fix was an ORDER or a claim-row option"; C -- "in every one the recorded class NAME was
  right and the recorded MECHANISM was half wrong". Two workers, different partitions, same finding.
  That is the strongest argument yet for dispatching onto named negatives, and simultaneously a
  warning: **the class is a signpost, not an instruction.**
2026-09-24 18:30:21 -04:00
..