Ships a lane-arg change without losing drafts: the running python still carries the
pre-S59 args, and killing it mid-wave discards everything the fleet has drafted for
that wave. Waits for .run/ready/<wave>.json, then pkills only the python — the
drafter SHELL, the lane that must never stop, relaunches it from .run/drafter.sh.
90-minute deadline so it never lingers.
main is the one binary splat writes to asm/nonmatchings/800/ and asm/data/ rather
than asm/<alias>/...; the hardcoded asm/<ov>/ in nine places made every main lookup
miss a directory that does not exist and report it as 'already spliced AND no stale
copy' — a true-sounding message about the wrong tree (R43).
With the path, the base and parse_config all fixed, main now reaches the real
analysis: func_8001A114 refuses because subseg 800 would host non-contiguous
.rodata carves (0x63238 = the existing LZSS table, 0x6327c = the new one), i.e.
isolate first — the same architectural refusal an overlay gets.
The island guard also moved AHEAD of jtbl_range, so an island table no longer
reports 'not found in the raw data asm — already carved / stale asm?' (true and
useless: an island table was never in the data asm). It now prints the exact line
the review prescribes: - [0x268, .rodata, md_SC03_076_jr_801F218C].
Review doc gets an S59 addendum with the measured class facts and where the two
examples now stop.
parse_config's docstring said 'the trailing run of {data,.rodata} pieces after
the last c piece'; its code took data_pieces[0], the first such piece anywhere in
the file. Those agree on 171 configs and disagree on 42: the md_* modules open
with the 154-A leading island - [0x0, .rodata, md_XXX] BEFORE their c piece, so
apply()'s splice lines[:lo] + region + lines[hi:] deleted the c line and wrote the
yaml to disk before the tool errored out for unrelated reasons.
Fixed by deriving the region from the last c piece, plus an R43 guard that refuses
outright if any c piece lands inside the window apply() rewrites wholesale.
Also, correcting what S58's blanket refusal had lumped together:
* md_* (42 configs) was the whole corruption class.
* main was never in it - its pieces are already [all c ..., data, .rodata, data].
main's real defects were the config PATH (there is no config/splat.main.yaml,
it is splat.us.exe.yaml) and the FILE BASE: the EXE has a 0x800 header, so the
delta is 0x8000F800, not the yaml's first vram: 0x80010000, and with the naive
value payload_word silently read 0x800 early. Both fixed; the base comes from
the single derivation in family_remap.vram_of (R33).
The cfg_path class refusal is lifted and replaced by an operation-level one: a carve
whose table lies below the data region is in the leading island, which a tail carve
cannot reach, so build_carve refuses and names the island-split lane (R43).
tools/test_jtbl_parse_config.py proves all three, read-only:
NC-1 regression 171/171 configs byte-unchanged by the fix
NC-2 defect 42/42 md_* lose a c line under the historical derivation; 42/42
keep every c line under the fix
NC-3 main cfg=splat.us.exe.yaml base=0x8000F800, region starts after the last c
The S58 removal cited four waves (as/aw/az/bd) and blamed the lane. All four ran
at band 120-2000. The campaign ledger splits the population by band instead:
tells @ 120-2000 228 drafts -> 18 banked = 7.9%
tells @ full band 655 drafts -> 161 banked = 24.6%
default @ full 2,996 drafts -> 1,335 banked = 44.6%
Of drafts that actually reach a gate the lanes are indistinguishable (tells 54.4%,
default 56.4%) — the whole loss is reloc_identity discarding phantom-symbol drafts,
which is cookbook 235 and a BRIEF fix, not a lane deletion (R40).
Rotation now pins lane index%4 against band index%4 so slot 1 (tells) always draws
the full band and slot 3 (the large band) is always default; asserted over 200 waves.
Takes effect on the next drafter-python bounce; the running process still carries the
old args and the drafter SHELL is never stopped to ship a change.
jtbl (36,685 ins, but 150 of 177 groups are singletons): Fable's review says the fix is SMALLER
than proposed — ONE inserted .rodata carve line plus jr_isolate_all --only. No _pre piece (it
cannot build), no ld_interleave change (the native script is already rodata-first). Harden
parse_config FIRST: it corrupts md_*/main configs on disk before erroring, which is why
jtbl_carve now hard-refuses them. The ox study's negative control is misattributed — build a
fresh one.
o0/cc1 (6,564 + 6,511 ins): the study is half refuted, and the doc header says which half.
md_MAIN_003/011 do NOT carry the -O0 fingerprint; the 311 files that contain $fp are the real
population. The unanswered load-bearing question for both is whether the EXISTING gate can bank
them unchanged — a lane that drafts what the gate cannot accept has already cost two sessions.
tells (86,602 ins): removed from drafting on four waves of evidence. aprop_autodraft is NOT the
destination (4.2% overlap, checked after I asserted it three times). The live hypothesis is
cookbook §235, the phantom symbol — one wave with it in the brief tests it cheaply.
Closes the gap that made main red for nine hours. R42 ('commit a dirty tree rather than
revert it') is correct for a per-binary gate that leaves PROVEN banks uncommitted, and WRONG
for gate_main, whose substitution is unverified by construction until the SHA matches.
Two guards, defense in depth:
1. gate_main installs atexit + SIGTERM/SIGINT/SIGHUP handlers that revert its own substitution
unless a bank actually succeeded. Killed mid-run, it now cleans up after itself.
2. ox_campaign's dirty-tree commit REFUSES top-level src/*.c (main's sources), reverting those
and committing the rest. Verified: src/800c.c and src/800.c refused, src/ov_*/... and
src/shared/engine_core.h still commit.
Also versions the autonomous lane scripts under tools/lanes/ — they lived only in gitignored
.run/, so a fresh clone had no drafter, gater, maintenance or stallguard at all.
All 1,101 novel-idiom candidates read (33 waves, 4,888 verdict lines, 4,764 notes), restricted
to functions the WHOLE-BINARY BYTE-GATE banked. Append-only: 1450 insertions, 0 deletions,
prefix md5 unchanged.
§233 header+index · §234-§257 the laws · §258 the 21 addenda (append-only forbids inserting
them into their parents) · §259 the discard ledger.
Three claims were HEDGED rather than promoted (§253, §254, §213's right-rotate rule); four
were byte-verified against asm/ before being written; §217/§230/§232 were promoted from
'single observation' to CROSS-CONFIRMED by independent cards.
~1,040 discarded across 18 ledgered clusters — ~700 self-reported 'nothing the cookbook did
not already cover' (the flywheel working), ~400 Law-1c compliance reports, ~70 bare
'reordering fixed it' with no mechanism (unindexable). Two clusters deliberately left as OPEN
PROBLEMS rather than written up as false laws: forcing own_thread_p on a call-bearing join,
and suppressing a constant-offset second giv. Both are permuter jobs.
Highest-value: §234 (store lvalue signedness picks addiu vs li/ori — 12 cards each burned a
one-instruction residual on this), §236 (the nine-class declaration-layer taxonomy — ~90 cards
banked bodies that were already instruction-correct), §235 (the phantom symbol: match_one masks
relocations so a green MATCH can name a nonexistent symbol, with NO instruction diff).
Main has been RED since ~00:20 overnight: it built to e9fffcf45 instead of 143dbb89, so no
main draft could bank regardless of quality, and R22 ran 212/213 for nine hours.
CAUSE — R42 has a gap. 'Commit a dirty tree rather than revert it' is right for a lane that
gates per-binary and leaves PROVEN banks uncommitted (sweep_parallel gates commit=False by
design). It is WRONG for a killed gate_main, whose substitution is by definition unverified.
Two auto-commits swept up abandoned main batches:
src/800c.c <- commit:2598 6 INCLUDE_ASM stubs substituted
src/800.c <- commit:2611 4 INCLUDE_ASM stubs substituted
Ten function bodies committed as banked work that never passed a byte-gate.
VERIFIED IN THE ISOLATED WORKTREE, by elimination rather than assumption:
HEAD -> e9fffcf45 RED
revert 800c.c only -> a9d9870c1 RED (still drifting)
revert 800.c + 800c.c + engine_core.h -> 143dbb89 GREEN
restore HEAD engine_core.h -> 143dbb89 GREEN (header INNOCENT)
restore HEAD 800.c -> a9d9870c1 RED (800.c guilty too)
So the minimum revert is exactly these two files. src/shared/engine_core.h is exonerated —
I had proposed its C89 prototype change as the cause and that hypothesis was WRONG.
NOTHING IS LOST: the ten bodies remain in commit:2598 and commit:2611 and can be re-gated
properly once gate_main's fixes (terminating bisect + idempotent hoist, commit:2633) are
exercised against a green baseline.
The P31 S58 main probe ran 38 minutes on 8 drafts and never produced a verdict. Two
independent non-termination bugs, both fixed and negative-controlled:
1. THE BISECT COULD NOT TERMINATE. On a failing multi-element chunk it did 'lo = head + lo',
restoring lo to exactly its prior value, so the next iteration recomputed the same head and
failed identically — forever. Replaced with an explicit-stack bisect that SPLITS a failing
chunk and pushes both halves, so work strictly decreases and termination is structural.
GATE_MAIN_MAX_STEPS (24) is a loud backstop, not the mechanism.
Verified: 8 drafts with one poisoned -> 7 banked, 1 rejected, 7 rebuilds.
2. THE TYPEDEF HOIST WAS NOT IDEMPOTENT. The block is inserted AT the anchor, so anything
hoisted previously still started after it and was re-hoisted every call, stacking a fresh
marker comment each time ('hoisted 2 typedef(s)' x150; the tree held a duplicated marker).
Now tracks the already-hoisted region and reuses the existing marker.
Verified: 3 consecutive passes hoist [Foo,Bar], [], [] with exactly 1 marker.
Together these unblock main: 170 parked drafts and ~1,041 open stubs.
Uncommitted src/ changes found at gate entry. These are banked functions from a lane that gates with commit=False, not residue — preserved, not reverted.
Uncommitted src/ changes found at gate entry. These are banked functions from a lane that gates with commit=False, not residue — preserved, not reverted.
Uncommitted src/ changes found at gate entry. These are banked functions from a lane that gates with commit=False, not residue — preserved, not reverted.
Uncommitted src/ changes found at gate entry. These are banked functions from a lane that gates with commit=False, not residue — preserved, not reverted.
Uncommitted src/ changes found at gate entry. These are banked functions from a lane that gates with commit=False, not residue — preserved, not reverted.
The main probe (8 drafts) ran 38 minutes without a verdict. Two defects, neither about the
drafts:
1. FIXED — the compile-error shortcut matched only 'previous declaration of', but gcc printed
'previous implicit declaration of func_80017930'. So a batch whose culprit gcc had already
named fell through to bisection, which costs a full clean EXE rebuild per step. The matcher
now accepts the implicit and conflicting-types forms too. (resolve_conflicts is separately
blind to this class: an implicit decl comes from a call site with no prototype.)
2. NOT FIXED, documented — the typedef-hoist repair is not idempotent. It emitted 'hoisted 2
typedef(s)' 150 times and left a duplicated marker comment; it re-hoists, rebuilds, fails
identically and repeats, so it cannot converge. Make it idempotent and bound the bisect
before gating main again.
Also: ox_campaign pre-draws the next wave AFTER launching shards (doing it before left the
fleet at 8 agents while a card job ran), collect_drafts grants stragglers a grace period
instead of letting 2 of 220 shards idle the fleet for 34 minutes, and drafter bands are now
mostly full-range (the 400-2000 band drew 9 cards for a 2,000-worker fleet).
Uncommitted src/ changes found at gate entry. These are banked functions from a lane that gates with commit=False, not residue — preserved, not reverted.
ox's study correctly found that the atlas o0-lane lever is MISCLASSIFIED on its probe
instance (func_801F0A9C @ md_SC03_076 has no frame pointer — verified, zero $fp under
asm/md_SC03_076/). Its proposed replacement population is fabricated: md_MAIN_003 and
md_MAIN_011 have zero $fp in either module. $fp does appear in 311 files across asm/,
which is the population an -O0 lane would really target.
Recorded rather than discarded: the misclassification finding is load-bearing (a lane
built on the lever label drafts the wrong functions) and the study named checkable files
for every claim, which is what made the refutation cheap.
Uncommitted src/ changes found at gate entry. These are banked functions from a lane that gates with commit=False, not residue — preserved, not reverted.
Uncommitted src/ changes found at gate entry. These are banked functions from a lane that gates with commit=False, not residue — preserved, not reverted.
Two independent reviews (ox design study + Fable validation) found parse_config does not
implement its own documented contract on md_*/main: it can DELETE the c config line and
corrupt the yaml on disk before failing. main also has no config/splat.main.yaml (it is
splat.us.exe.yaml), which is the FileNotFoundError seen on every main jtbl target.
Refuse loudly rather than corrupt quietly (R43). Lift only after parse_config is hardened
and proven on two examples.
Also: gate() stages into a per-run dir (a killed gate's 3,186 stale drafts survived into the
next gate of the same tag and poisoned every group); reloc_filter no longer treats
NOT-A-STUB as a pass (it means ALREADY BANKED — wave an staged 480 of them over source that
already byte-matches).
Designs recorded: docs/tool-designs/jtbl-island-split.md (ox) and -review.md (Fable):
14 CONFIRMED / 8 WRONG / 1 UNVERIFIABLE, verdict GO-WITH-CHANGES, and the correct fix is
SMALLER than proposed — one inserted .rodata carve line + jr_isolate_all.py --only, no _pre
piece and no ld_interleave leading mode.
CURRENT_PHASE.md gains a CRASH-RECOVERY checkpoint (not a fresh-session handoff): what is
running, restart order, the measured fleet/scaling facts, the fixes that must not regress,
and the ordered work queue.
Lanes: drafter (never stop it), gater (restartable), maintenance (free A-prop sibling lane),
stallguard (60s auto-repair). Drafting holds no lock; one narrow draw-vs-gate lock exists
because build_wave_atlas reads corpus.stubs and misreads substituted drafts mid-gate.
main is off the wave critical path — 157 drafts parked to .run/main_queue/ rather than
stalling the gater for another hour on a bisecting whole-EXE rebuild.
api_agent: 5xx retried like 429 (a 502 was abandoning functions at near-19), HTTP_TIMEOUT
420s not 1800 (a hung request parked an agent 30 min), EXTRA_READABLE for tooling briefs,
and bare-directory paths no longer refused against their own granted root.
Uncommitted src/ changes found at gate entry. These are banked functions from a lane that gates with commit=False, not residue — preserved, not reverted.
Uncommitted src/ changes found at gate entry. These are banked functions from a lane that gates with commit=False, not residue — preserved, not reverted.
R42: gate_main reverted 61 byte-proven overlay banks it could not distinguish from its own
substitution (sweep_parallel gates commit=False by design). Fixed by committing overlay banks
before the main batch, chunking main at 8 to bound bisect cost, and replacing every blind
'git checkout -- src/ config/' with commit-or-refuse in ox_campaign and idiom_serial.
R43: sweep_parallel had an explicit branch admitting main, which cannot be gated incrementally
— wave ab banked 0/105 main cards while its non-main cards banked 94/115 (82%), and the wave
read as a drafting failure. sweep_parallel now refuses main and names gate_main.py.
Also: validate_targets now prefers the card's own addr field (named symbols like SYS_OBJ_F00
were MALFORMED and discarded whole 220-card waves); ox_campaign deals model lanes by
smallest-ratio scheduling (a 73-card wave had put 73 shards on ox and 0 on deepseek);
docs/accelerators.md gains the four vacuous-check defects.
278 novel-idiom candidates extracted by tools/idiom_harvest.py from 1,004 drafting notes,
restricted to functions the WHOLE-BINARY BYTE-GATE banked (banked-ness derived from
corpus.stubs, not from match_one, whose relocation masking would admit lessons drawn from
functions we never actually reproduced).
26 new sections (§207 is the harvest header + discard ledger, §208-§232 the laws), 6 folded
as addenda to existing sections (§30, §194-B, §176-B, §165-40, §164-63, §193-A/§194-E).
~200 candidates discarded or merged — 103 of them self-reported 'nothing the cookbook did
not already cover', which is the knowledge base doing its job.
§209 CORRECTS existing guidance: §194-B's 'needs >=2 sh stores' bound is byte-wrong
(func_801A8738 has one sb and still needs the s16 declaration). Insertions only; the
existing file is byte-identical by prefix md5.