The phase's FIRST merge was rejected: "expected three or four fields", while all four workers
were already staging files in the format my charter had given them.
charter said: range<TAB>source<TAB>md5<TAB>differing_bytes<TAB>result<TAB>options
with range written 0xSTART..0xEND
tool reads: start<TAB>end<TAB>source[<TAB>overrides]
Finding 179 says a rule every worker must follow belongs in a TRACKED tool, not in a file each
worker copies, because a copied artefact cannot be fixed for the people who already copied it.
Phase 11 earned that from a worker's free.sh. **A charter IS a file each worker copies**, so
writing a FORMAT into prose recreates the defect one level up — and this time the unfixable
copied artefact was the coordinator's.
AND THE TOOL HAD ALREADY LEARNED IT. validate_overrides exists because a Phase 11 worker put
md5= in the 4th column, and its error message says in terms: "Per-claim metadata such as a
source md5 belongs in report.tsv, not in the registry row." The convention was documented
INSIDE THE TOOL, I did not read it, and I wrote prose contradicting it — including renaming
the evidence file to evidence.tsv when report.tsv is the established name in the tool's own
error string and in every Phase 8/9/11 worker's staging directory.
Standing rule: before writing a staging format, an interface, or an exit-code contract into a
charter, READ THE TOOL THAT ENFORCES IT. "The tool is the contract" is not advice for workers
only. Workers compute addresses rather than eyeballing them; the coordinator must derive
formats rather than inventing them.
FIXED AS A COMMAND, NOT AS CORRECTED PROSE. New `sf3_merge check-claims --claims F [--regions R]`
validates the format, flags a duplicate start, a missing source file and an already-registered
row, so a worker answers "is my staging mergeable?" itself before reporting. 11 tests, one of
which asserts THE CHARTER'S OWN WRONG FORMAT IS REJECTED, so the message stays honest for the
next coordinator — who will also write prose.
Charter §10 rewritten to specify the tool's format by READING THE TOOL, to separate claims.tsv
(the merge input) from report.tsv (the evidence, where the md5 lives), and to name
check-claims as a required pre-report step; §5 gained rule 17.
What worked: fail-fast validation caught it in under a second at the merge, not as a confusing
failure at the gate. Phase 11's override-key guard paid off again. A staging format a tool can
CHECK is worth more than one that is documented well.
Cost: one rejected merge, four correction messages, ~10 minutes. Cheap because the tool refuses
to guess.
make test 301 tests, OK (from 290)
The phase's first two bodies, and both are recorded negatives rather than worklist rows.
Worker C found them with the NAMED UNTRIED LEVER I handed it: tools/sf3_family driven over the
101 negative rows against the 611 registered regions. I measured candidates=0 for the fresh
band and told C that said nothing about its own pool. It didn't:
score >= 1.000 : 3 rows (NOT 0)
score >= 0.99 : 4 rows
score >= 0.95 : 15 rows
-> 0x800518BC (88 B) -> 0x80051864 MATCHED (this merge)
-> 0x800B34A4 (88 B) -> 0x800B34FC MATCHED (this merge)
-> 0x8010804C (16 B) -> 0x80085B80 blocked class (gp-thunk), correctly not attempted
Transfer rate 2/2 on the unblocked score-1.000 rows, against finding 166's 7/7.
I re-verified BOTH claims from fresh --work directories before merging (differing_bytes=0,
result=MATCH, exit 0 each), merged to a candidate, gated the whole binary, and promoted only on
result=MATCH.
./tools/sf3_merge apply ... exit 0, added_regions=2
./tools/sf3_match gate --expect-sha1 e173... exit 0, c_regions=613
differing_bytes=0, result=MATCH
sha1 e173426c157384ebf1b6caf8c6fea18a85a14af9
make check exit 0
make extents-verify regions=613 disagreements=0 result=AGREE
registry audit 613 rows, ordered, non-overlapping,
604 distinct sources, 0 missing files
Worklist regenerated. It still lists 1001 rows, and the reason is worth recording because it
looks like nothing happened:
excluded_already_registered 611 -> 613 (+2)
excluded_recorded_negative 169 -> 167 (-2)
The two rows were NEVER in the worklist -- they were excluded as recorded negatives. Registering
them MOVES each row from the negatives-exclusion bucket to the registered bucket, so `listed`
is unchanged while both counts shift by exactly 2. excluded_already_registered == the registry
size, as required. No partition refilter is needed: both rows were in C's negatives partition,
not in any fresh partition.
WORKER C'S FINDING, which is worth more than the two bodies and is a Goal-B-grade result: BOTH
rows' recorded class strings were WRONG ABOUT THEIR OWN MECHANISM.
0x800518BC was classed "return-merge/sltiu", with a note that three spellings all came out
80 B and sltiu fixed the compare byte but not the 8-byte layout. RAW WORDS: 21 of 22 words
are IDENTICAL to matched 0x80051864. The sole difference is the forward `j` to the shared
return, and its target differs only because `j` encodes an ABSOLUTE address and the two
bases are 0x58 apart. The body is a literal twin; no re-spelling was ever needed.
0x800B34A4 was classed "alloc-tiebreak" (bit-index/base register pair a0/a1 vs cc1 a0/v1).
RAW WORDS: 20 of 22 identical to matched 0x800B34FC; both differences are the OFFSET
CONSTANT (`li a0,3` vs `li a0,20`). The register pair the note asked for was already there.
The lever is the constant, not the allocator.
Both rows abut their matched twin, so the negatives index contains whole RUNS of repeated
bodies -- and C's operational conclusion is that the cheapest finder is a raw-word HAMMING scan
against the 611 registered regions, which the histogram tool only half-finds. C is running that
scan across all 101 rows now. That map, not the bodies, is likely the largest thing this phase
produces.
Note the discipline this vindicates: an unclassified negative is not overturnable (finding 182),
but these two WERE classified -- wrongly, in the same dimension, by earlier sessions that then
wrote off the row. Cookbook 182's rule needs its other half: a recorded mechanism is a HYPOTHESIS,
and a WRONG named mechanism is as unattemptable as no mechanism at all until someone reads the
raw words.
T0's defect was proven three ways (the patch rejects, the guard tests fail, the transform emits
an extra nop). This adds the end-to-end one, and its arithmetic closes exactly.
Gating the CURRENT 611-region registry with the SUPERSEDED transform:
rebuilt_bytes=1886260 original_bytes=1886208 -> 52 bytes LONG
rebuilt_sha1=24c4c2a9c99cc7f5daf88c0a30107bda2d16340f
original_sha1=e173426c157384ebf1b6caf8c6fea18a85a14af9
result=DIFF
52 bytes is 13 instructions, and 13 was derived INDEPENDENTLY from the original payload: the 15
maspsx=epilogue regions split 2 shapes A / 13 shapes B, classified by asking whether the word
before the `jr $31` is a nop (A) or a real instruction (B), with the frame release after the jump
in both cases. Each shape-B region gets one extra nop, so 4 x 13 = 52.
A count taken from the bytes and a count taken from the failing gate AGREE. That is what makes
this a measurement rather than an argument, and it is why the T0 record does not rest on a single
line of tool output.
ALSO RECORDED, because it is the trap this phase's own documentation warns about: my demonstration
command piped the gate through `tail` and then printed `$?`, so the `>>> gate exit=0` line in that
log is MEANINGLESS -- `$status` is a fish variable and the pipeline masked the gate's real status.
`result=DIFF` is the authoritative field and the byte arithmetic is the independent check. Workflow
section 6's rule is "use the gate's EXIT CODE as the gate"; I broke it while quoting it. Standing
note for every future gate call: capture the exit code directly, never through a pipeline.
Roster (fresh, spawned by the orchestrator; tab w1:t5, 2x2 grid):
A w1:pC 01a0d529 A1 lever-a.tsv 334 rows
B w1:pE 01a0d52a-2c40 A1 lever-b.tsv 334 rows
C w1:pD 01a0d52a-55d3 A2 negatives-c.tsv the 101 NAMED negatives
D w1:pF 01a0d52a-6198 A1+B lever-d.tsv 333 + negatives-d.tsv the 92 UNCLASSIFIED
Four agent_pane_not_found errors on first start, all cleared on retry after a few seconds --
the documented transient, not a bad id.
PARTITIONS ARE PROVEN, NOT ASSERTED (.run/p12/partition-proof.txt):
worklist rows 1001; a=334 b=334 d=333; sum 1001; distinct union 1001; overlaps 0;
union == worklist True; negatives 193 (c=101 d=92); negatives overlap worklist 0;
negatives c/d overlap 0.
The phase's structural premise was verified by set comparison: 0 of the 193 negatives rows
appear in the 1001-row worklist, because sf3_triage plan --negatives excludes them. The
negatives are an INDEX, not a queue, and worker C is the first worker in this project whose
partition is that index.
THE MEASURED RANKING, and it produced a real number. Band first, density second, with the
density statistic IMPORTED from the tracked tools/sf3_rank (which declares itself the reference
implementation and warns scores are not comparable across implementations -- reimplementing it
would silently break that guarantee):
band rows median density max size range
0 (<=244 B) 410 0.359 0.912 4-244 B
1 (245-400 B) 225 0.491 0.920 248-400 B
2 (401-800 B) 221 0.604 0.896 404-796 B
3 (>800 B) 145 0.720 0.940 804-11516 B
Median density rises MONOTONICALLY with band. That is worker D's warning ("density is
correlated with size, which biases the top of the list") measured on this corpus, and it is
exactly why a pure density ranking is wrong when the milestone counts BODIES rather than bytes:
one body at 80 B and one at 8000 B are worth the same. Band-first suppresses the bias; density
then orders within the band, where it is the measured cost signal.
MEASURED NEGATIVE, recorded so three workers do not each rediscover it: tools/sf3_family
--top 25 returns candidates=0 against the fresh band at ratio 1.000. The family lever is
EXHAUSTED for the worklist (Phase 11's 7 rows were all of it). It has NEVER been run against
the 193 negatives -- sf3_family reads the worklist, which excludes them -- so that is a named,
UNTRIED lever handed to workers C and D, who were both told to report who runs it.
Baseline revalidated from clean before dispatch: make clean/all exit 0; cmp exit 0; SHA-1
e173426c157384ebf1b6caf8c6fea18a85a14af9 unchanged; make test 290 OK (253 -> 281 -> 290);
extents-verify regions=611 disagreements=0 AGREE; gate c_regions=611 differing_bytes=0 MATCH.
CURRENT_PHASE.md rewritten for the phase, with the milestone warning stated plainly (+148 is
larger than any phase so far) and the cycle-1 requirement that at least 8 bodies must come from
the negatives pool -- so a low overturn rate is measured in cycle 1, not discovered at the close.
Worker B, worker C and worker D all probed `tools/sf3_cc` with `--help` during the Phase 12
capability probe, and all three got a raw coreutils `basename` error instead of help:
./tools/sf3_cc: line 29: .run/sf3_cc/Usage: basename NAME [SUFFIX] ... : No such file
ANY leading-`-` argument was taken as a source path. `basename --help .c` prints coreutils'
own help text, and that entire text then became the output filename, so the failure surfaced
as a confusing redirection/cpp error. Every worker lost time on it, on the first command they
tried, and worker D spent probe effort diagnosing it as a "genuinely broken path".
This is cookbook 179 from the other side. That finding says a rule every worker must follow
belongs in a TRACKED tool rather than a file each worker copies. Here the tool WAS tracked --
and it was still unusable the way every single worker reaches for it first. Tracking a tool
is necessary but not sufficient; it also has to survive first contact.
Fixed: `--help`/`-h` print real help and exit 0, an unknown option is rejected BY NAME, and a
missing source file says so rather than failing inside cpp. The compile path is unchanged.
Also documented its LIMIT, which was previously unwritten and is easy to misread as a match:
the maspsx stage always runs with DEFAULT options and no region option is passed, so this
shows a SPELLING's shape and NOT a region's final bytes. A region needing `maspsx=epilogue`,
`nopmarker`, `moves`, `regread`, `off` or `gp=`/`cc1=`/`as=` looks different here than under
`sf3_match range`. Sweep spellings with this; decide matches with `sf3_match range` -- and
decide an `epilogue` token from the CANDIDATE's tail, never the original's (finding 165/180).
9 new tests (tools/tests/test_sf3_cc.py): the argument-handling cases run without a toolchain,
including one that pins the exact symptom (no coreutils help text in the output, and no file
created named after it); the compile-path test skips cleanly when the ignored toolchain or any
src/func_*.c is absent, and one test pins the documented LIMIT so it cannot be dropped.
make test 290 tests, OK (from 281)
Approved by the developer 2026-09-24: milestone 750, stretch 800; both harness repairs
authorised; Goal B (the 92-unclassified negatives) in scope and bounded; 4 workers —
two on the fresh band, one on the 101 named negatives, one on the third fresh slice plus
the 92 unclassified as the Goal B worker; compaction-first.
THE ONE STRUCTURAL FACT THIS PLAN IS BUILT ON, measured at the open:
0 of the 193 near_match_negatives rows appear in the 1001-row worklist.
The negatives index is held OUT of the worklist (sf3_triage plan --negatives) and is not a
queue — it is an index, and a worker dispatched only from the worklist can never reach it.
So the negatives pool becomes a first-class partition with its own worker, and the phase's
structural change is that it stops being an appendix.
Two pools, measured: 1001 fresh rows (410 of them <=244 B) plus 193 attempted-but-unresolved
negatives, of which 101 carry a NAMED mechanism and are overturnable by cookbook 182's rule,
and 92 carry no class at all and cannot be attempted until someone re-reads them. That is
what Goal B is for.
The plan states plainly that +148 is LARGER THAN ANY PHASE SO FAR (Phase 11 closed +118) and
that it cannot be reached from the fresh worklist alone — it depends on the negatives-overturn
programme working at scale, which is a measured route but only a ONE-ROW demonstration so far
(worker F's 0x8002622C). Two safeguards are built in rather than discovered late: the cycle-1
checkpoint must include at least 8 bodies from the negatives pool, so a low overturn rate is
measured in cycle 1 and not at the close; and the leading-indicator rule stands unchanged —
report the projection and ask, never redefine or self-certify the milestone.
Also recorded: the fresh-band size distribution, the negatives class distribution, and the
baseline revalidation table including the failed precondition that T0 repaired.
Both defects were found by the Phase 12 open checklist, and both were then PROVEN by
direct test rather than by inspection.
*** 1. THE TRACKED PATCH WAS STALE, AND THE TOOLCHAIN WAS NOT REPRODUCIBLE ***
ea51ac9 ("the epilogue transform now handles BOTH shapes") corrected maspsx=epilogue in
the working tree but never regenerated the tracked patch, which still carried the
superseded shape-A-only transform from 05be974.
patch -p1 < tools/patches/maspsx-phase10-r1r2.patch (pristine 86ccd7d)
-> exit 1, 4 of 10 hunks FAILED, .rej files for BOTH files
The superseded transform emits `nop / jr $31 / addiu sp,sp,32` where 0x800F44D0 has
`jr $31 / addiu sp,sp,32`, so every shape-B row comes out 4 bytes long. 15 registered
regions carry maspsx=epilogue, so a fresh clone could NOT have rebuilt the 611-region
green gate from tracked files. The working tree was right, so every gate was green; the
patch was wrong, so nothing failed. That is why it survived the rest of Phase 11.
Regenerated as pristine -> working tree for exactly the two files the patch touches, and
verified: applies with exit 0 and no rejects; reconstructs both files byte-identically
(cmp exit 0); reverse-applies cleanly, proving the tree IS pristine+patch; still carries
all four opt-in modes.
4bd21823402d73659f76b3afbf60f8f93daaa3e8 (stale, 167 lines)
0d7f643ba1c31d1ae28de257737c16c623a9eb00 (regenerated, 229 lines)
*** A TEST, NOT ANOTHER RULE ***
The standing §11 rule — "do not edit a git-ignored tool without carrying the change as a
tracked patch" — WAS followed in Phase 11: 05be974 regenerated the patch and explicitly
verified it. It was stale by the very next commit that touched the transform. The
generalisable defect is that the artifact which is verified is not the artifact that is
enforced: a verification performed once by hand decays the moment the OTHER side of the
diff changes, and the ignored side is the side no review sees. Cookbook 188.
So the remedy is executable. tools/tests/test_maspsx_patch.py reconstructs the vendored
tool from pristine + the tracked patch and requires a byte-identical match against the
working tree; it also requires the pinned commit, requires ONLY those two files to be
modified, requires all four opt-in mode flags to survive a regeneration, and exercises
BOTH epilogue shapes through the reconstructed script. It skips cleanly when the ignored
checkout is absent, like the existing local-toolchain skips.
PROVEN TO CATCH THE DEFECT: run against the superseded patch it fails 4 of its 7 tests
(2 failures, 2 errors); against the regenerated patch it is green. A stale patch now
fails `make test` instead of being found by a human reading a diff — which is exactly how
it was found this time.
*** 2. sf3_free HARD-CODED .run/p11/, AND WOULD HAVE READ A DEAD LEDGER ***
The tracked free-check hard-coded INFLIGHT = .run/p11/inflight.tsv. .run/ is git-ignored
and the ledger is session-scoped BY DESIGN: it coordinates the workers who are alive now.
In Phase 12 the tool would have read a 306-line p11 ledger and never the ledger its own
workers were writing to.
The direction of that failure is the opposite of cookbook 187's, and worse. A stale `wip`
row produces a false TAKEN — a worker is told a free row is held and wastes an
opportunity. A BLIND ledger produces a false FREE — a worker is told a row another worker
is actively holding is free. That is the 0x800320D8 incident: two workers matching the
same region independently, one overwriting the other's source file. Cookbook 189.
The fix encodes the semantics the ledger already had: one phase's ledger is dead to the
next. Resolution is --ledger, then --phase N, then the highest existing .run/pN/ — and a
previous phase is deliberately NOT a fallback, because a row held `wip` by a worker
retired at that phase's close must read FREE. The resolved path is printed to stderr, so
"which ledger did that read?" is always answerable while stdout stays parseable.
21 new tests (tools/tests/test_sf3_free.py) pin end-exclusive containment, last-row-wins,
the phase resolution order, and the no-fallback rule.
*** VERIFICATION ***
make clean && make all exit 0
cmp exit 0
SHA-1 (both files) e173426c157384ebf1b6caf8c6fea18a85a14af9 (unchanged)
make test 281 tests, OK (from 253; the clean run captured 253 before
these suites existed, independently
reconfirming the Phase 11 baseline count)
make extents-verify regions=611 disagreements=0 result=AGREE
make gate c_regions=611 differing_bytes=0 result=MATCH
No src/, config/ or toolchain working-tree change, so the gate cannot be affected.
The firewall line in all four close records said 720 tracked files. That figure was measured BEFORE the
two close records themselves were added, so the true post-close count is 722
(phase-ends/PhaseEnd_Phase11.md and docs/PHASE11_VERIFICATION.md). Corrected in the PhaseEnd, the digest
entry, the verification record and the ledger.
Same class of error as the two the close already records: a number measured at one moment, then quoted
in a document that itself changes the thing being measured. The firewall RESULT is unaffected --
0 tracked paths under any prohibited root either way.
Developer confirmation of the 600-body milestone was requested and given before this record was
written, per the plan. The phase closes at 602 distinct matched bodies / 611 registered regions, from
the Phase 10 close state of 484 / 493 (+118 / +118).
Closing gate set, all green from a clean tree:
make clean && make all exit 0
cmp exit 0
SHA-1 (both files) e173426c157384ebf1b6caf8c6fea18a85a14af9 (UNCHANGED from Phase 10)
make test 253 tests, OK (from 237)
make extents-verify regions=611 disagreements=0 result=AGREE
make gate c_regions=611 differing_bytes=0 result=MATCH
The SHA-1 being identical to the Phase 10 close is the point: all +118 bodies are additions to a
binary that still reproduces exactly.
Records written:
phase-ends/PhaseEnd_Phase11.md the close record
docs/PHASE11_VERIFICATION.md the verification record
phase-ends/DIGEST.md Phase 11 section
phase-ends/CURRENT_PHASE.md rewritten: NO PHASE ACTIVE, roster-restart warning
phase-ends/logs/Phase11.md Cycle 3 close, corrections, ledger reconciliation
docs/MATCHING_COOKBOOK.md 187
docs/ORCHESTRATOR_WORKFLOW.md section 4.0 roster rule, section 10 close steps, section 11
Three corrections made during the close, each to something already reported:
1. The negatives index was reported as "200 rows, 82 with a mechanism". Measured: 194 data rows
(200 LINES, 6 of them header), 101 with a named class, 86 with a substantive note, 92 with no
class at all. The 700-body route is LARGER than reported. wc -l on a file with header comments is
not a row count -- and the same error was then made again with the symbol count (413 lines, 400
rows) inside this very record.
2. One in-flight ledger row was STALE-TAKEN and invisible. 0x800298C0 (392 B) traced
C wip -> C released -> A wip -> C wip, so last-row-wins read it TAKEN while NEITHER holder was
working it -- both were out of context and would never append a release. It is a live worklist
row and is NOT in the negatives index, so nothing else would have surfaced it. Released with
coordinator as the worker field; tools/sf3_free now reports FREE. This is cookbook 179's failure
mode in its OTHER half: the copied script blocked rows that HAD been released, while this row
shows the ledger cannot express "the holder no longer exists" at all. Now a standing close step
(cookbook 187).
3. Worker A's "32 first-attempt" claims are not reconcilable from its artefact -- only 27 of its 46
report rows carry an explicit first-attempt note. 27 is recorded as the verifiable figure and 32
is flagged unverified, because a first-attempt rate is a COST claim and cost claims drive
dispatch.
Ledger reconciliation at close: 275 rows over 135 addresses; last row released for 113, claimed for
21, wip for 1. The 21 claimed rows are all already registered, so they need no action -- claimed is a
legitimate resting state.
The roster does NOT survive this close. All six worker sessions are retired and their herdr panes
closed, so Phase 12 MUST spawn a fresh roster; there is nothing to reconnect to. This is a change
from Phase 10, which left three retired sessions listed in `intercom list` -- and a roster that is
retired but still listed is indistinguishable from one that is live. Both halves are now standing
rules in ORCHESTRATOR_WORKFLOW section 4.0.
No changes to AGENTS.md.
b29963e promoted worker F's staging tools, and in the same commit I copied F's
staging `diff.py` over `tools/sf3_diff` WITHOUT READING IT FIRST -- a direct
violation of AGENTS.md rule 3, 'Never overwrite blind.'
`tools/sf3_diff` was a 364-line Phase 9 tool: two subcommands (diff, resolve), a
PS-X-EXE header parser that reads the text address rather than hardcoding it, a
symbol-registry loader, and a lui/addiu + gp-relative address resolver. It had
17 tests of its own. Replacing it with a 97-line staging script dropped
`make check` from 253 tests to 237 and failed it with exit 2.
Restored from b29963e^ and verified byte-identical to it (cmp exit 0).
make check exit 0, 253 tests OK
extents-verify regions=611 disagreements=0 result=AGREE
gate rebuilt 1886208 B, differing_bytes=0, result=MATCH
sha1 e173426c157384ebf1b6caf8c6fea18a85a14af9
Documentation corrected, because the overwrite also left the record wrong:
* cookbook 185 documented the interface of F's STAGING script
(`sf3_diff 0xSTART 0xEND <workdir>`), which is NOT the interface of the
tracked tool and never was. Replaced with the real one, and the reason the
Phase 9 tool is worth more is now stated: its `notes` column resolves
lui/addiu pairs against the symbol registry and gp offsets against the gp
base, so a residual row can name WHICH GLOBAL an address is.
* cookbook 186 records the defect. The question to ask before promoting into
tools/ is not 'is the new one better?' but 'what does the old one already do
that the new one does not?'
* ORCHESTRATOR_WORKFLOW.md section 11 gains both as standing prohibitions, with
the diagnostic: a SHRINKING TEST COUNT means a tool that had tests no longer
satisfies them, and it fires before the failure itself is explained.
* phase-ends/logs/Phase11.md: 'seven defects' -> nine, recording the free-check
defect (cookbook 179) and this one.
Worker F's judgement, which I agree with: these two together are the highest-value tooling built
this phase, because the first removes the COST of a spelling and the second removes the GUESSWORK
about what is wrong.
tools/sf3_cc <file.c> one-file cpp -> cc1 -> maspsx, printing the assembly.
A spelling costs ~0.1s, which turns 'try a few variants'
into 'grid the whole space'.
tools/sf3_diff 0xS 0xE <workdir> opcode-level diff of the candidate object against the
original, difflib-aligned, so you see the SHAPE of the
residual rather than a byte count.
A differing-byte count tells you HOW WRONG a candidate is; it does not tell you WHICH DIMENSION
the error lives in. sf3_diff marks differing instructions with '<<', so a run of identical
mnemonics with differing register names is the allocator class -- a CLASSIFY signal, not a
spelling signal.
184: a load's BASIC BLOCK is not source-movable -- sched2 cannot cross blocks, so a load in a
different block than the candidate's is a SOURCE-ORDER fact.
Worker E's 0x8007F9B0 was recorded as '8 bytes short' and the cause was a transcription error:
it had written TWO dereference levels where the original has THREE. The deficit is exactly the
missing lw plus its load-delay nop = 2 instructions = 8 bytes.
The diagnostic: a body exactly TWO instructions short, where the original has one more lw in a
pointer chain, is a MISSING DEREFERENCE LEVEL -- not a missing statement. Recompute the chain
from the displacements.
And the distinction matters: finding 149 is for bodies short by missing nops around INDEPENDENT
BLOCKS; this is short by a missing LOAD. Two different causes with the same 4-8 byte signature.
Worker F's 0x8002622C (44 B) — A RECORDED NEGATIVE OVERTURNED, with a new class.
The old record said 'cc1 folds it, unreachable' and tried FOUR ALGEBRAIC re-spellings. All four
were doomed: the fold is at RTL combine, not in the front end, so no re-spelling can avoid it.
Only LIVENESS can. Same body with 'return 0' is 32 B LENGTH-MISMATCH; with 'return n' (the
difference live past the addition) it is 44/0/MATCH. Diagnostic that proves the pass: cc1 -da
shows the minus present in the .flow dump and gone in the .combine dump, while cse/cse2/jump/
loop/sched/sched2 all still contain it.
181: when an original keeps an arithmetically-cancelling pair (subu+addu, x-c+c), the intermediate
is LIVE PAST the second operation — find the later reader.
182: a negative with a NAMED mechanism is overturnable; one without is not. 'cc1 folds it' is not
a classification; 'RTL combine cancels it, and algebraic re-spelling cannot reach combine' is,
and it immediately implies the liveness lever.
179: a rule every worker must follow belongs in a TRACKED tool, not a copied script. The registry
free-check lived in a worker's staging dir and the orchestrator told everyone to copy it. It was
WRONG -- it reported TAKEN if ANY ledger row for the address was not 'released', so a row that was
wip and later released stayed blocked FOREVER. Worker E found it and measured 13 released rows
reading as taken, several of them the cheapest rows left, and the same stale pattern existed for
workers A and D too. Fixed and promoted to tools/sf3_free (tracked, docstring explains the bug).
A copied script cannot be fixed for the people who already copied it.
180: worker E's maspsx=epilogue token table, MEASURED not inferred -- 5 rows REQUIRED, 3 HARMFUL
or NO-OP, 2 HARMFUL-but-unmatched. Three of E's fourteen claims sit on that list and TWO would
have failed outright if the token had been applied by shape. The cheap read: '4 bytes SHORT with
the token on' means the token was unnecessary.
609 regions / 600 distinct bodies, from the 484 / 493 baseline at phase start (+116 regions,
+116 bodies). Worker E's 0x80077D04 (120 B) is the 600th.
VERIFIED, not asserted:
full-binary gate : 609 regions, differing_bytes=0, result=MATCH, exit 0
make check : 253 tests, OK, exit 0
every source file : present on disk and tracked by git
working tree : clean
Corpus maximum 1232 B; 28 regions exceed the 244 B ceiling the phase was planned around.
Delivered by six workers over the phase: A 46, D 21, B 17, C 13, E 14, F 3 = 114 claims,
every one gated before merge.
The phase's premise was falsified early and replaced with working tooling:
- the 244 B ceiling was a DISPATCH ARTEFACT (5 of 427 rows above it had ever been attempted);
- ASPSX does not fill delay slots at all, so the authorised post-pass shrank from a modelling
project to one mnemonic (maspsx=moves) plus an epilogue swap (maspsx=epilogue);
- cost is TIE-BREAK DENSITY, not size, measured independently by two workers from opposite
directions;
- the GTE class moved from BLOCKED to OPEN (worker D's 0x800F3E18 is the first GTE row matched
in this project).
175: mask chains must be SEPARATE STATEMENTS -- one expression folds to a single and; three
statements emit the original's lw/and/and/and/sw. cc1 does not fold constants across statements.
176: a MECHANISM, not a tip. Three separate RMW statements give one lw, three ands and ONE sw
(cse forwards each load from the previous store within a block); an intervening early return makes
that store land in the beq delay slot and the tail's store stays alive because its load is
forwarded from a store in the PREVIOUS block. A local chain loses the delay-slot store (100 B);
volatile keeps both stores but flips the entry branch (100 B).
177: fold REASSOCIATES | -- one statement becomes v | (C1 | X), a 17-byte residual; two statements
give the original (v | C1) | X.
178: finding 170 has a CONSTANT-clobber variant -- the same entry-block copies arise because mask
constants are materialised into the parameters' own homes, with no call involved. The rule
generalises: a redundant entry copy means the value is live when its home is clobbered, whether by
a call's argument setup OR by constant materialisation.
172: a MISSING sign bias is evidence of a shift, not a division -- the values are non-negative in
the source but cc1 cannot know that after a conditional, so the absence of the addiu is the
diagnostic. Finding 97 read backwards.
173: the absolute value is a SWAPPED SUBTRACTION (subu with operands exchanged), not negu -- the
natural -x is the trap. Second instance of finding 101.
174: the idiom-redundant-by-construction class, and the discipline of declining a row. Worker E
decoded 0x800FECF8 -- one of the highest-scoring fresh small rows -- and RELEASED it without
attempting it, because it is a magic-division row where every division has several equally
plausible spellings. A high redundancy score is not sufficient if the row is in a class known to
be spelling-ambiguous.
Worker E's 0x8005E17C and 0x8002FAB8; worker F's first two claims 0x800FBE84 (216 B, FIRST
SPELLING with worker A's derivation) and 0x80026274 (108 B).
170 generalises the argument-evidence levers (157/164) into a mechanism: a redundant ENTRY-BLOCK
copy of an argument means that value is still live at a call whose argument setup CLOBBERS that
same register. The copy is materialised in the entry block because the tie to a0's home is
illegal. The test that nailed it: the same body with a 2-arg call is 104 B LENGTH-MISMATCH; with
the 3-arg call it is 108/0. Two prior corpus instances had the copy AT the call; this is the
hoisted-to-entry variant.
171: worker F confirmed EXHAUSTIVELY that the constant-division divisor is unique per magic --
(n*M)>>(32+s) == n/D has exactly one D. So finding 67's identity is not an approximation.
Worker A calibrated sf3_family by checking two 0.97 entries and finding neither shared its
sibling's body. I have now confirmed that on eight candidates by raw-word diff, which is the
decisive test: 0x8006EBA0 vs 0x80028CE0 differs in 60 of 61 words; 0x800FFFEC vs 0x8007E8B8 in
18 of 19; 0x8005E17C vs 0x800FB54C in 25 of 26. Contrast the genuine sibling 0x800F3DC0 vs
0x800F3E18: 1 of 22 words.
So a high cosine with ratio 1.00 is NOT evidence of a shared body -- at 0.96-0.99 the histogram
matches common IDIOMS. The useful band is ratio 1.000 AND a near-zero raw-word diff.
Tool bug fixed: sf3_family did not exclude already-claimed rows, so its top hit was a row
matching ITSELF. The registry is now the authority and claimed rows are skipped.
Worker E's 0x8002311C (160 B) CLOSES COOKBOOK 123'S OPEN QUESTION. Finding 123 recorded the
branchless MAX0 (x & -(x > 0)) as unreached -- 'no ternary and no bitwise spelling reached it'.
Worker E solved it: the lever is NAMING THE BOOLEAN.
return s & -(s > 0); -> BRANCHES
return s > 0 ? s : 0; -> branches
flag = s > 0; return s & -flag; -> EXACT (slt / negu / and)
Mechanism: naming the comparison forces cc1 to materialise it as a VALUE (slt) rather than a
test feeding a branch. That is finding 44's 'name the boolean' lever applied to the MAX half --
finding 44 previously had only the cond-into-&& direction for this family.
167: a 4-byte store cc1 DELETES means the object's address is never taken -- fold the word into
the array whose address IS taken by a call.
168: s = f(); s += f(); s += f(); loses one instruction vs three named results summed.
0x800F3DC0 (88 B) — a ONE-WORD sibling of the matched 0x800F3E18, found by worker E via
sf3_family at ratio 1.000 and confirmed by raw-word diff: identical in all 22 words except the
COP2 command field (0x4B70000C vs 0x4B78000C). The route was one copy, two renames and one field
change; every __asm__ and register binding carried over untouched.
166 records it, and notes it is the MIRROR of finding 161: on 0x800F3E18 the field 0x178000c was
the WRONG answer (one byte off, 0x170000c correct); on 0x800F3DC0 0x178000c IS correct. A count
tells you a field is COMMON, not that it is right -- and a ratio-1.000 sibling is the cheapest
place to learn which one a row wants. When the family tool reports one, diff the raw words FIRST.
Records worker output (104 claims total), the GTE class moving from BLOCKED to OPEN (worker D's
0x800F3E18 is the first GTE row matched in the project), the epilogue post-pass and its two
corrections, seven defects in coordinator-written rules, the central finding restated with worker
D's seven-finder breakdown, and the ranker's known blind spot with both failed proxies.
Worker E's 0x80107DE8 (128 B, maspsx=epilogue) and 0x8007D5FC (132 B, DEFAULT toolchain).
163: a recurring epilogue-list class WITH A SHAPE TELL -- correct length, identical instruction
multiset, and the residual is where cc1's reorg put the EPILOGUE LOADS relative to the last
gp-relative read-modify-write block. The original's epilogue loads FILL the global load's delay
slot; cc1 emits a #nop instead. Tell: the row's last statement is a gp-relative read-modify-write
immediately before the epilogue. NOT a spelling problem -- worker E probed the maspsx mode split
and the nop is a cc1 #nop, not maspsx, so no option changes it. Classify it: post-pass territory.
164: a register residual can be ARGUMENT EVIDENCE -- when the only residual is a value in an
argument register and there is no argument setup at the jal, try passing it as that argument.
165: finding 147 confirmed a second time -- 0x8007D5FC is on the epilogue list but cc1 fills its
own slot, so the token is a no-op and the row is claimed with '-'. The list was selected on the
ORIGINAL's tail; the token must be decided from the CANDIDATE's.
Worker A's final row 0x8010A6C4 (132 B, first attempt, maspsx=epilogue) -- its ninth epilogue
row and its 46th claim.
162: a callee called with DIFFERENT argument counts needs a NON-PROTOTYPE declaration --
func_8010A444(1) / (2, x) / (3, s1, s0) is only expressible as 'void func_8010A444();', the C89
empty-parameter form, not '(void)'. Same constraint that cost worker A a compile on 0x8002DD14.
Worker A's final totals: 46 claims (33 first-attempt), 95 evidence rows, 39 levers, 3 deferred
rows with derivations, 1 blocked row, 9 rows carrying maspsx=epilogue.
Worker D's 0x800F3E18 (88 B) -- THE FIRST GTE/COP2 ROW MATCHED IN THIS PROJECT.
159: lwc2/swc2 move a word straight between MEMORY and COP2, unlike mtc2/mfc2 which move
between a GPR and COP2. The row uses lwc2 $9/$10/$11 and swc2 $25/$26/$27, so a row can use
the IR/MAC registers WITHOUT the IR/MAC macros. Added gte_lwc2IR1/2/3 and gte_swc2MAC1/2/3.
160: register variables PIN the COP2 operand registers -- worker D's entire residual was that
cc1 chose its own cfc2/mfc2 destinations. The GTE analogue of the named-locals family: an
inline-asm row's residual is usually the operand REGISTERS, not the sequence.
161 IS A CORRECTION TO THE COORDINATOR'S OWN ADVICE. I broadcast the command-field values with
their occurrence counts as if they were a lookup table. They are a DISTRIBUTION, not a per-row
answer: worker D wrote 0x178000c (counted 51x) into the row and it came out ONE BYTE wrong; the
correct field is 0x170000c. The low bits carry the shift/matrix/vector selectors, so two commands
differing only there are different instructions. Read the field off the ORIGINAL WORD.
Worker A's 0x800F4B88 (128 B, first attempt) -- its eighth epilogue-class row and its last.
158: two type views over the same halfwords are DELIBERATE. The first helper call loads with lh
(signed) and the second with lhu (unsigned) over the SAME pointer, so the source declared a
short* view for one expression and an unsigned short* view for the other. Writing the whole row
as short* gives lh for the second call too and changes the bytes. When one function reads the
same field both ways, the mixed lh/lhu pair over one pointer is the evidence.
Worker A's three epilogue rows (0x800F452C, 0x800F6DD0, 0x800F6E50).
155 is a DISPATCH finding: the epilogue list is ALSO a family list. 0x800F6DD0 and 0x800F6E50 are
siblings differing in exactly two ways, and worker A read one and got the second for free, both
first try. Adjacent pairs already identified: 0x800F6DD0/0x800F6E50, 0x800F42AC/0x800F452C,
0x800FFFEC/0x80100038. A worker taking an epilogue row should read its NEIGHBOURS first -- the
class was selected on a TAIL SHAPE, and tail shape correlates with the translation-unit layout
that makes neighbours siblings. Generalised: any class selected by a structural feature clusters
its results by address.
156: the three writes are ASSIGNMENTS not accumulations -- the original never loads the old
destination value, so writing += adds three loads.
157: fewer argument registers set than parameters means the source passes its OWN LIVE parameters
directly. Now confirmed on three rows.
Worker A's 0x800F452C (112 B, maspsx=epilogue, second attempt) -- a sibling of its own
0x800F4098, matched with the mid-function-branch-target lever applied first try.
Worker A asked FIVE TIMES for the lui-page rule to be prominent, having made the mistake five
times. It is now cookbook 154 and the FIRST of the five things the workflow doc tells a new
worker, with all five instances tabulated. The fifth instance added the missing half: the
immediate is a SIGNED DISPLACEMENT, and the signature of the error is 'a residual of ONE
differing byte whose only difference is a lui or addiu immediate'.
Also confirmed from worker A's side: the shape A/B correction works -- 0x800F452C is a shape-B
row and closed with the single token, so the tail filter is obsolete and A has dropped it.
Worker A's 0x800F4098 and worker D's 0x800FB54C (104 B, first attempt, maspsx=epilogue).
151: the 2^k-1 add-back rule is CONFIRMED on two independent divisors -- worker C derived it
from 63 (0x800FEE3C) and worker D found it again on 127 (0x800FB54C, magic 0x81024409). Same
structure, two divisors, so finding 67's decision table is complete and not hypothesised.
152: FIVE finders each produced bodies over worker D's 20 -- redundancy rank 6, size rank 5,
adjacency 4, epilogue class 2, constant-division census 1, family 1. No single finder dominates.
This broadens finding 109: 'five different finders each produced bodies, and the price was set
by the LEVER, not the finder.' The tools cover different parts of the population, so keep every
finder running rather than consolidating onto the current best.
153: a saved register can force a local to be SMALLER than the data written through it, and
enlarging it to fix that breaks the frame.
Worker E's first four claims (0x80028CE0, 0x80028C34, 0x8009D798, 0x80091674).
147 IS A CORRECTION TO THE COORDINATOR'S OWN BROADCAST. I sent workers a 120-row epilogue list
selected by scanning the ORIGINAL's tail. Worker E showed that is not sufficient: 0x80091674 has
that exact tail shape but cc1 FILLS the slot itself, so the default toolchain matches (104 B) and
--fill-epilogue BREAKS it (100 B LENGTH-MISMATCH). The mode must be decided per row by compiling
and reading the CANDIDATE's tail. Diagnostic: 4 bytes SHORT with the mode on means the candidate
was already correct.
148: order and allocation are SEPARABLE -- the la position and the addu destination are two
independent facts, and the fix is to split the base into its own named local. Three spellings
with exact results.
149: a body 4-8 bytes SHORT with MISSING load-delay nops means a later independent block must
move earlier in the source -- the opposite tell from finding 100.
150: worker E hit a RACE DUPLICATE on 0x80100038 (free.sh read a registry 6 rows stale),
restored HEAD's file verbatim, re-verified it, dropped the row, and reported the incident.
Nothing corrupted because both spellings match -- but it proves the protocol's window is real.
Worker D's 0x800FAF84 (104 B), its first maspsx=epilogue match.
144: THE EPILOGUE CLASS NEEDS ONLY ONE TOKEN. Worker A asked for a second one; it does not need
it. The 120 rows split into two shapes -- A) lw $31 immediately before the release, which needs
the release moved AND a nop inserted after lw $31; B) other loads in between, where the release
moves and the trailing nop is DROPPED. My first implementation did A only and left every B row
4 bytes long. Verified on both: 0x800FFBEC (80/0/MATCH) and 0x800F44D0 (92/0/MATCH, a row worker
A had released as unfixable).
145: read the frame arithmetic and the saved-register offsets TOGETHER -- worker D's local had to
be 8 bytes not 12 because the saved s0 sits at sp+24 and the callee writes through sp+16. Third
instance of the size family, first where the constraint came from a saved register.
146: the SAME expression at two divisors produces two unrelated code shapes (/64 branchy bias vs
/63 add-back magic), which is why worker D's divisor sweep missed it.
Worker A released this row as 'the three-load-with-nop shape that the swap cannot fix' and
requested a --no-load-delay-nop token. It does not need one: the corrected transform already
handles it, by DROPPING the trailing nop for shape B rather than moving it. Verified: 92 bytes,
differing_bytes=0, MATCH, with maspsx=epilogue. It was 96 bytes before the fix.
So the epilogue class does NOT need a second token -- it needed the transform to distinguish the
two shapes, which worker A's report 24 is what revealed. The 120 rows should now be attemptable
with maspsx=epilogue alone.
Worker A's two epilogue-class rows (0x800F42AC 96 B, 0x80100038 104 B), both carrying the
maspsx=epilogue token -- the first rows closed through the new mode.
AND THE TRANSFORM IS NOW CORRECT FOR BOTH SHAPES, which worker A's report 24 showed was
necessary. The 120 rows split:
A) lw $31 IMMEDIATELY before the release -> the release moves into the slot AND a nop must be
inserted after lw $31, or j $31 lands in its load-delay slot. 0x800FFBEC.
B) other loads between lw $31 and the release -> the release moves into the slot and the
trailing nop is DROPPED; no load-delay nop is needed. Worker A's 0x800F44D0.
My first implementation did A only and left every B row 4 bytes long. Both are handled now, and
the discriminator is whether the jump's own register was loaded immediately before the release.
A BUG WORTH RECORDING: reading out[-1] to find that preceding instruction saw maspsx's own
'#nop # DEBUG: ...' comment instead of the lw, silently producing the shape-B answer for a
shape-A row and turning a MATCH back into a LENGTH-MISMATCH. The scan now skips comments.
Finding 122 declared GTE rows a blocked class needing a harness token. The gap was smaller than
it looked: the header already covered $0-$7 and $13-$31 but NOT $8-$12, which is where
IR1/IR2/IR3 ($9/$10/$11) live, and it had no macro for the GTE command instruction itself.
Added gte_ldIR1/2/3, gte_stIR1/2/3, gte_ldMAC1/2/3, gte_stMAC1/2/3, and a GENERIC gte_cmd(field)
so any command whose 25-bit field has been read off the original can be emitted without first
earning a semantic name.
VERIFIED, NOT ASSUMED: the field values are confirmed by counting them over the whole binary
(0x486012 x51, 0x49E012 x11, 0x41E012 x4) and a test compilation emits gte_cmd(0x486012) ->
cop2 0x486012 -> 0x4A486012, exactly the original's word.
Five rows were blocked on this across three workers, all with complete or partial derivations.
The disposition matters as much as the token: three workers independently reached 'no amount of
spelling will find this' and declared it BLOCKED rather than grinding -- which is what made the
gap visible as a TOOLING problem instead of three separate source puzzles.
141: worker D's own reads_unsaved_saved scanner flagged 0x80103434, D read the row, and the
verdict is NOT a fragment -- the detector treats op 0x12 (COP2) as a GPR use, which for
ctc2/mtc2/mfc2 is wrong. Every COP2 row in that flag list is suspect. That is the THIRD
independent instance of the same lesson: every shape heuristic in this project has needed a
worker to read a flagged row and say 'this is legal, and here is why'.
142: worker C's 2^k-1 add-back rule CLOSES worker D's open question on 0x82082083. D recorded it
as a bounded negative with a named direction; C recognised the answer from an unrelated row.
The third time a worker's finding closed another worker's negative -- the strongest argument for
recording a named open question rather than a vague failure.
Worker A's two: the addition operand-order row (a1[i]+a0[i] vs a0[i]+a1[i] -- same length,
16 bytes apart, because cc1 evaluates the right-hand operand first) and the unconditional
p[0]=0 that lands in a branch delay slot.
Worker D's two: 0x8009B56C closed on cookbook 43 trigger 1 after D had nearly written the row
off, and 0x80018458.
Finding 84 named the transform; it is now implemented and 0x800FFBEC matches (80 B, 0 differing)
where it was 6 differing bytes without it.
IT IS A SWAP, NOT A MOVE, and getting that wrong cost one implementation: the candidate is
lw $31,16(sp) / addiu sp,sp,24 / jr $31 / nop and the original is lw $31 / nop / jr $31 /
addiu sp,sp,24 -- SAME instruction count, two words swapped. My first version moved the release
after the jump and dropped the nop, producing 3 instructions instead of 4 and turning an 80-byte
row into a 76-byte LENGTH-MISMATCH. A 'small mechanical transform' still has to be checked
against the bytes.
SCALE: 120 unclaimed rows have the filled epilogue in the ORIGINAL (scanned every worklist row's
tail for jr $31 followed by a positive addiu sp,sp,N). They are mostly SMALL -- 76, 76, 80, 92,
92, 96, 104 B -- so this is a large class of cheap rows that were blocked on a HARNESS GAP rather
than on source shape. 770 other rows have the unfilled shape and need nothing.
The tracked patch is regenerated and verified to reproduce both modified maspsx files from the
pristine checkout.
Worker D's 0x80025A2C (176 B, 2 spellings) -- the EXACT MIRROR of its own 0x80025ADC.
131 is now THREE instances with an identical mechanism (88->96, 48->56, 56->64, always a clean
8-byte frame deficit with everything else identical, always fixed by an unreferenced array
local). It is a rule with a one-line fix, not a trick.
138: a MIRROR PAIR -- the two rows are inverse conversions, adjacent in the image, both callees
of 0x80031BBC. Finding one made the other a two-spelling row. sf3_family cannot see this relation
because inverses are not similar: their opcode histograms DIFFER (one stores where the other
loads). A pair of inverse functions has a STRUCTURAL signature, not a similarity one.
Worker A's 0x80036F70 (460 B, first attempt, family score 1.000 AND adjacent to its own
0x80036DA4). Its family run finished 7 for 7 with five first-spelling matches.
136: worker A CALIBRATED the family tool. It checked the two 0.97-scoring entries and NEITHER
shares its sibling's body at all -- one is a table-allocation routine, the other a summing
loop. '1.000 is the useful band; below ~0.99 the histogram is matching common idioms, not
bodies.' That is the same false-positive mode as the redundancy ranker (finding 110). The
default threshold is now 0.99.
137: a family's signature can be a CONSTANT TRIPLE -- worker A's 0x80036F70 differs from its
sibling only in six constants, whose signature is (A, A+12, A-58). Searchable in a way no
similarity metric can be, because the shapes are identical and only the immediates differ.
132: worker B found the SECOND independent instance of 'when the original's short path is the
fall-through, INVERT the condition' (30 bytes of layout on 0x800A8984; the same shape as its
own 0x800FCA90). That promotes it from a heuristic to a rule with a stated direction -- and it
is the opposite of the usual instinct to write the guard as an early-exit.
133: worker A's one-byte family residual was a DECLARATION -- 'int i' emits slt where 'unsigned
int i' emits the original's sltiu. The family transfers the SHAPE and the LEVERS; the
declarations must still be re-derived.
134: a family hit is also a hint about the CALLEE -- the relation crosses the call graph, and
sf3_family does not model it. Two of worker A's family rows call rows that are themselves
unclaimed with the same object layout.
135: worker A predicted a fourth family member by pattern; I scanned all 1046 unclaimed rows for
the predicted bases and ZERO reference them. The family has exactly three members. A predicted
member that does not exist is worth recording so nobody re-derives the search.
Worker A closed 0x800259A0, 0x80012918, 0x8006B2D4, 0x8003022C and 0x800506E4 -- every one a
sibling found by tools/sf3_family, which was built an hour ago from worker D's insight that
'the finder varies, the price does not' and therefore families should be SEARCHED for rather
than waited for.
That is the tool's first harvest and it is 5 bodies from one list. The family scores were
1.000/1.000/1.000/1.000/0.998 -- exact opcode-histogram and size matches against rows worker A
had already matched, so the levers transferred unchanged.
Records the cycle: five defects in coordinator-written rules (all found by workers following
them), the merge-flow defect the coordinator inflicted on itself, four new tools, the central
finding confirmed from both directions, the ranker's known blind spot with two failed proxies,
adjacency at 9-for-9, and the open items (GTE token, the post-pass, the solved 0x82082083).
Worker D's 0x80025ADC (136 B). Partitions re-interleaved 5 ways because workers B and C
are both at ~94% context and effectively exhausted, leaving 2 active workers against 45
remaining bodies. A fifth worker restores capacity.