Found P31 S72; COULD have been found 2026-06-15 (Phase 7, commit:0025), which wrote the
island's contents by hand and named loadDestPtrTable as the divider. The signal needs no
matching progress — it is a property of the retail image.
The number that matters is the cost curve: at Phase 6 src/800.c had 13 externs and 0
typedefs and the split was a yaml edit; at S72 it had 2,378 externs and 175 typedefs and
cost 57 crossing declarations, a shared header and 4 stale consumers. Plus a session of
wrong conclusions (11 'PROVEN gate-rejects', 10 of which banked once the carve existed).
PREREQ recorded honestly: the binding constraint came from the OVERLAY work two phases
later, so this is knowledge that never got carried back to main — not carelessness.
General principle: segmentation is the exception to probe-before-investing. When a
decision is evidenced at t=0, cheap now, and strictly more expensive later, make it early
even though its payoff is unproven.
The split created two new TUs and a shared header; four consumers still described main's
game code as one file:
* tools/reconcile_slate.py — HARDCODED open('src/800.c'), so after the split it saw a
THIRD of main's typedefs while reporting success (silently-narrowed scope, R32).
Measured: 133 visible before the fix, 187 after, 0 lost. Now globs
corpus.src_files('main') + src/800_shared.h, so a future split is already handled.
* docs/wave-playbook.md 1c — still said spans B/C/D were NOT drawable and that drawing
one is an R45 violation. That is now false and would have STOPPED a future session
from drawing the very targets this work unlocked.
* cookbook §426 — its 'the remaining spans need src/800.c split' paragraph now records
that it was done the same session, and points at §431 for the method.
* config/dedup.us.yaml + src/shared/clearTbl40.h — both said dedup group I0 is
instantiated 'at both sites in src/800.c'; both sites are above 0x80035270 and are now
in src/800_c.c.
Byte-neutral: dedup.us.yaml parses, gate_main --assert-baseline BYTE-IDENTICAL.
SETUP.md gains a row describing the layout and the rule it implies: never hardcode
src/800.c, glob corpus.src_files('main').
I wrote the rule for declaration edits and then lost two byte-proven banks to the same
mechanism an hour later. gate_main's opening 'git checkout -- src/*.c' destroys anything
uncommitted in src/, banks included. R42 is 'commit before the next command that can
touch src/', not 'commit at a good stopping point' — and count banks from the SOURCE,
which is the only oracle that caught it.
Quoted '2,318 scattered externs' as measured-not-guessed. It was measured, and it
measured the wrong quantity: what a split costs is declarations used OUTSIDE their
region (57 of 1,247), not the total. R41's denominator discipline applied to an EFFORT
estimate. Also records the correction to the '1998' premise: the spans prove at least
three TU boundaries, not that the devs' files were exactly these three.
Where to split: the jtbl spans (tables pack tight within a TU, separated across TUs), and
that is also the MINIMUM — a TU with no switch emits no table and is invisible, so what
you recover is a lower bound on the original structure, not the structure.
What crosses: ask the compiler. 2,318 externs is the scary number and the wrong one; only
57 of 1,247 declared names cross a boundary, 19 of them typedefs with one definition each
and zero shape conflicts. Fix TYPES first — a missing typedef cascades into dozens of
parse errors that all evaporate at once.
Plus the general defect it exposed (a typedef stripper must read the destination's
includes) and the operational rule it cost twice (gate_main reverts src/*.c first, so
commit alignment edits before gating).
The 11 'PROVEN gate-rejects' were one missing rodata carve, not bad bodies. Next
session starts at the span B/C carve: 18 jtbl functions left in main's frontier holding
most of its remaining instruction mass, blocked on splitting src/800.c at 0x8002B0B4
and 0x80035270 — the original TU boundaries the jtbl spans reveal.
Counterweight to §3-B, with a precise discriminator. When two arms converge on a shared
block, that block is usually a late cross_jump merge of per-arm DUPLICATED statements
(§298). Spelling it as a real goto is not equivalent when the label sits INSIDE a loop:
the goto becomes a jump into the loop body, jump.c's mark_loop_jump marks it
loop_invalid, cc1 -dL prints 'Loop at N ignored due to multiple entry points', and
loop.c silently drops invariant hoisting — measured: the 1/0x80 constant hoist into
$a0/$a1 vanished, 2 insns plus a spurious andi.
Discriminator: shared tail outside every loop -> fold it (§3-B, and you may free a hard
ABI register). Shared tail inside a loop body -> duplicate per arm and let cross_jump
merge. A -dL line is a free oracle for this.
Also records CdReadSectorReadyCB's three remaining residual clusters as pack fuel so the
next attempt starts from the draft, not from the .s.
I predicted §428's UID barrier would resolve func_8001B0D4's fence<->over-merge
coupling, reasoning that it changes no liveness. The escalation that tested it did not
use §428 at all. §3-B did it: seven in-block 'return 0;' -> 'goto L_ret0;' to one shared
tail removed the priority-1 hard-$v0 sets, freeing $v0 for the D_800747E4 reload and
$v1 for CdQueueBusy's result, AND fired all three cross-jumps (92->86). One edit, both
residuals.
The real law is the opposite of my framing: two residuals moving in opposite directions
under every lever are usually not in tension — they are two symptoms of ONE starved
resource, and every lever so far was paying for one with the other. Ask what they are
both competing for, and inventory the hard register sets the source forces. A repeated
'return <const>;' in switch arms is the commonest way to pin $v0 many times over.
The wrong prediction is kept in the section as the refutation (R14).
From main/CdReadStateMachine (MATCH 385/385, opus). One root: gcc-2.7.2 canonicalises
(mem (reg)) back to a symbol when the pseudo has a single reachable set, so reusing a
pointer local changes the addressing mode downstream. p[-0x10] re-folds to
lui %hi(sym-0x10) unless the offset pointer gets its own single-set local; and a
multi-set pseudo defeats the canonicalisation for every use, costing a load-delay nop.
Same mechanism as §421 read from the source side.
Also confirms the §333 frame dial and the merged-tail label pin (gcc's cross_jump picks
the other end of a merge than you expect) as the cheap alternative to a §5a fence.
A volatile __asm__ barrier is a scheduling AND allocation event, so on a function whose
residual is allocation-shaped every fence that kills the double-hop re-enables a
cross-jump over-merge. Two residuals in tension, which is why ~20 variants across two
attempts never converged. §428's UID-based barrier is the predicted resolution because
it changes no liveness; the escalation now running is the test.
Flagged explicitly as one agent's report, not a byte-proof (R14).
Sharpens §5a/§336, supplies the missing precondition to §162. Writing the cursor
advance inside each switch arm instead of a shared temp makes the converging addu a
label CREATED by cross_jump (get_label_before), so its INSN_UID >= max_uid and
jump.c:1988's guard stops the minimum=2 jump-to-jump search from ever running — only
minimum=1 survives, which is exactly the target's single merge. Killed a -23
LENGTH-DRIFT (5 spurious tail merges) in one edit, with no volatile asm.
Found by the S72 main wave on func_80026D64 (MATCH in 2 compiles). The agent also
verified the .rodata table against jtbl_80072BFC past match_one's .text-only blind
spot — because the pack carried the §426 carve note telling it to.
A wave verdict is a claim about what the AGENTS returned, not what is on disk.
claude_wave_draft.js has no filesystem access, so its .catch() reports NO-DRAFT for
any agent that dies — including one that already wrote a finished body.
S72: a Fable agent on main/func_80024448 spent 133k tokens / 17 tool calls / 10 min,
wrote its draft, then died on 'You've reached your Fable limit'. The workflow returned
NO-DRAFT with an empty draft_path; match_one on that same file returns
{status: match, closeness: 0, nins: 362}. A complete byte-perfect body reported as no
work at all.
§426 — main's switch functions were never a codegen wall: one .rodata carve had been
missing since Phase 7, so a drafted switch double-emitted its jump table (+28/+52/+76/+84
image growth, 238 symbols shifted, first mover jtbl_80072A4C every time). Includes the
derived name-address overlay that names a layout shift with no reference build, the span
table, and why spans B-D need src/800.c split at the original TU boundaries the spans reveal.
§427 — a hash is a correctness oracle with zero diagnostic content; preserve the red
artifact before anything rebuilds over it, attribute per byte, and negative-control the
localizer in both directions.
playbook 1c — which main jtbl functions are drawable (R45), and the gate note: main is not
in the parallel lane, read the BODY/PLUMBING/MIXED verdict before recording a main reject.
Audit found real gaps rather than assumed coverage:
* SETUP.md (R21) had NONE of the five tools written this session. Added a table for
journal_notes / launch_check / gate_triage / restage_matching / weave_sweep, each with
when you need it, plus the two gating rules now enforced in code (parallel_gate refuses
main; gate_main refuses a no-op draft and counts banks from the source).
* wave-playbook: launch_check as step 4c (payloads go stale while gates run - 3 of 27
wave-2 targets were already banked) and gate_triage as step 6b with the measured
blocker census.
* decision-log (R31) held only the §406 pivot. Added the two strategic entries this
session actually turned on: gating main with a tool documented as unable to gate it
(false PASS, caught only by R22), and the drafting pool running dry while the lever
was an exclude list nobody re-probed after a tool fix.
* CURRENT_PHASE: the per-gate ledger for all 14 cycles plus the carve/rebase/main gates.
* Two memories: gate-main-only-with-gate-main, reprobe-exclude-lists-after-tool-fixes.
Four byte-verified findings from md_MAIN_003/func_800CF3E8 (467/469 ins), read off
-dS/-dR/-dl/-dr:
1. sched.c true_dependence guards on GET_MODE(mem) != QImode, so a `sb` store aliases
scalar global loads while sh/sw struct stores are exempt - that is what pins the
colour lbu after `sb 0xb` and gives it a mandatory filler slot. A property of the
store's MODE, not of what it points at.
2. An OT-index re-read must be a MEM_IN_STRUCT_P FIXED-address lhu to depend on its
store; expand's memory_address() forces the constant into a reg (la+lhu 0(reg))
unless you copy the whole struct into a 2-byte register local. This was the 468/469
wall for every prior attempt.
3. A `la` above an idx*24 chain needs a single-set base pseudo emitted before the
multiply: block-scope `{ Sprt24 *b_ = ARR; p = &b_[idx]; }`.
4. Recorded as NOT reachable from C: $v1-vs-$a0 for the last prim pointer is
local-alloc's pointer-vs-temp priority tie. Permuter or a §419 density manoeuvre.
Byte-proven on ov_SC07_006/func_801890FC (387 ins). For two stores at equal priority,
sched1's LUID tie picks the LAST statement's store first; regalloc then gives the other
load $v0, where it sits behind its own $v0 predecessors, and sched2 pins that chain last.
Each equal-priority pair therefore appears reversed: source FE;E-=0x40;A-=0xEE;88;8A;8C
emits as E,88,A,8C,8A.
This is why "statement order is inert" is such a common wrong conclusion here - the
mapping is not identity, so trying orders at random explores the wrong space. Compute the
intended emission order, then invert each equal-priority pair.
Companion (§193-E): the prior draft left no different-address store between `sh 0xA` and
its re-read, so cse forwarded it as `andi 0xffff`. A store to a different address between
the two re-seeds cse - §416's "re-read the store" seen from the failure side.
§422 (resident/func_800D06E8, 344 ins): mips.h has no PROMOTE_MODE, so a u8 local is
really QImode - `(u8)(c-3) < 2` gives widen_operand a paradoxical subreg (raw $a0) and
combine.c:9246 drops the truncation before the sltiu, while `(u32)(c-3)` re-widens and
loses it. And `s1 = (cmp) ^ 1` puts the comparison in the destination pseudo; the flag
needs its own temp.
§423 (ov_SC03_092/func_8017FA74): match_one closeness 0 + gate reject + "cause not
determined" has a checkable cause. harvest_verify splices the draft where the
INCLUDE_ASM stub was; a file-scope typedef the TU also defines (five lines below, here)
makes gcc-2.7.2 exit 33 on a C89 redefinition, the TU fails, the gate reverts, and
nothing names the typedef. Fix is block scope, proven with a three-way control. Mirror
of §409 law 2 - together they cover collisions above and below the splice point.
Tool trap: a scratch TU copy needs -Isrc/<overlay> or cpp exits 1 on the relative
engine_core.h include and EVERY variant passes identically.
Byte-proven on md_SC07_003/func_801A293C (313 ins, 6 -> 0 in 23 compiles). $t0 there is
reload's scratch (regalloc.md L80: first wholly-unused call-clobbered reg), not an
allocation: a launder output goes to $v0 via local-alloc, and any $8 pin evicts every
mfhi/reload to $t1 (measured 3x). The reach is §385's single-instruction non-volatile
asm with the bare symbol as an INPUT.
Also: spelling an addPrim RMW as a libgpu P_TAG 24-bit addr bitfield makes
store_fixed_bit_field mask the value first, hoisting 0xFFFFFF before 0xFF000000 and
closing both the lui/ori and lw-swap clusters at once (6 -> 3); and an in-place `and $s0`
needs `s0 = s0 & 0xFFFFFF` written out, not the compound form.
The law: before spending iterations on a register you cannot get, ask whether it belongs
to regalloc at all - reload runs after every dial C gives you.
aprop_symfix deduped its slate by BARE FUNCTION NAME, so a four-row slate for
func_8016AB6C across ov_SC03_107/ov_SC07_007/010/011 reported "1 drafts audited" - and
the three dropped rows each needed a DIFFERENT rebase, because each overlay has its own
target symbols. Same root as reloc_filter's binof and gate_lane's homonym staging: three
tools, one R48/§238 defect.
With all four visible, the structure is two uniform delta clusters of two, identical in
shape across all four overlays - one seed body's two data clusters each moving as a
block. STALE-DELTA only admits ONE cluster, so it refused all four as AMBIGUOUS. §420
records the safe generalisation (runs of constant delta, every run >= 2 members, D_
symbols only) and the verification step.
Rebased by hand under that rule, all four still MATCH at closeness 0, and the gate
banked 4/4 in 57 seconds with no drafting (commit:3629). Frontier 165, 45 banked.
Byte-proven on ov_SC01_000/func_8017DD04 (297 ins). Pinning the 0x80 constant to $7
loses its sched1 birthing boost, because $a3 and $a2 are ALSO set by the function's own
call-argument copies (reg_n_sets == 2) - a hard-register pin on an argument register is
unavailable to any function that passes arguments in it.
So win the ranking instead. local-alloc ranks by refs/live_length: 0x80 scored
13/319 = 4890 and took $6 (a pure $a2<->$a3 swap, 24 wrong). One six-input zero-byte
asm on mlo at the blk3/blk4 boundary buys 6 references, 5217 > 4890, mlo takes $6 and
0x80 falls to $7 with its boost intact. The boundary must be the one cut no hoisted
constant crosses, or you move the live lengths you are exploiting.
Measured inert: pinning mlo to $6 (cse never substitutes a hard reg for a bitfield
constant), and a dead hard-reg copy as a register suggestion (flow deletes it).
Byte-proven on ov_SC04_016/func_8017DF8C (184 ins, 32 -> 0 in seven compiles).
1. Writing the stride as `off = j * 0x50` (a giv of biv j) rather than a second biv
fixes 14 preheader rows and 8 latch rows at once: loop.c chains givs LIFO
(loop.c:4421), so with `j = 0` spelled first the `move $s0,$zero` emits last and the
arg-3 giv lands in its natural record slot. When the PREHEADER ORDER is wrong, check
which variables are bivs and which are givs before touching anything else.
2. To emit la + addu + lh 0(reg) instead of a folded %hi/%lo(sym+K), hoist the table
pointer to a function-scope local set ONCE outside both loops. No LOG_LINK crosses
basic blocks so combine cannot fold it, and with every $s taken reload rematerialises
it from reg_equiv_constant at the use and deletes the init - so the hoist is free.
Spell the sum `idx + (s32)tbl`; the reverse costs one operand swap.
Measured inert here: §328's volatile cast on a reg+sym address.
Byte-proven on ov_SC03_013/func_8017E6F4 (182 ins). A pinned select arm expands as
ior+copy (two insns), so jump.c:728's `x=b; if(c) x=a;` collapse cannot fire. Unpinning
lets it fire - and then cse_end_of_basic_block's skip_blocks path walks between the two
D_80184D2C[idx] reads and CSEs the symbol_ref into $s3. The earlier agent read that as
"unpinning costs +2" and restored the pin, which re-blocked jump.c and hid the cse
behaviour: the function plateaued for three attempts on that misattribution.
The law: when removing a lever MOVES the residual instead of shrinking it, the new
residual is a different pass. Attribute it with a pass dump before re-adding the lever.
Four new byte-proven levers from the overnight lane, none previously in the cookbook:
re-read the store instead of passing the value (CSE store-forwarding), (&SYM)[3] vs a
pointer local as an ADDRESSING choice, one biv with +0/+2/+4 for combine_givs, and a
local's width choosing lh vs lhu+sll/sra.
Also recorded: the same-address twin hint was false three times tonight (ov_SC06_000,
ov_SC01_080, ov_SC03_030) while the same-TU neighbour was the real fuel in every case.
Three of the night's five post-limit MATCHes recovered a body off disk rather than
re-deriving it - func_80181A60 in 2 minutes instead of 16.
gcc-2.7.2 pushdecl/different_binding_level: adding a file-scope extern for a callee that
the TU also declares at BLOCK scope merges those later externs into the global, which
then conflicts with the TU's own definition - and the error names the definition, not the
decl you added. Match the TU's binding LEVEL, not just its type. Byte-proven on
ov_SC04_011/func_80180B24 (215 ins), which also needed the house __asm__ alias for a
file-scope vs block-scope D_ spelling collision.
S71 ran main through parallel_gate, got "11 banked", committed it, and the R22
clean-fleet verify came back 212/213. main did not compile from clean; once the two
declaration conflicts were reconciled it built and was STILL not byte-identical. All 11
were then re-gated one at a time against a clean build — 11 of 11 REJECT.
The rule was already written down in ox_campaign.gate_main_batch: "main is gated by ONE
CLEAN REBUILD of the whole EXE, never incrementally … main's extract rewrites the linker
script, so an incremental main gate returns a FALSE DIFF." parallel_gate's worker IS
gate_stage, so it inherits that — and S58 recorded the false-DIFF direction while this is
the false-PASS one, which is worse: a false diff wastes drafts, a false pass commits wrong
bytes and reads green until the next clean fleet check (R53's signature — a failed build
leaves the previous object on disk and the SHA check downstream reads it).
Now a refusal naming tools/gate_main.py, not a docstring in the callee (R43).
Cookbook §414, including the two instrument errors made while recovering.
Measured on S71's own wave: wall-clock tracks iteration count, and iteration count
tracks the residual class, not size. A 26-instruction function took 18 min / 31 tool
calls (regalloc, finished NEAR); a 122-instruction one took 80 s / 10. The 20-33 min
runs were all compiler-internal residuals — scheduling ties, birthing boost, register
colouring, LUID order — where every hypothesis costs a compile-and-measure cycle.
arm_for keys on nins alone, so a 47-instruction regalloc wall could not be drawn at
the higher tier and nothing escalates mid-run. arm_from_history() now reads the
function's own journal notes at draw time and returns fable when they name one of
those classes; it never downgrades the size ladder's choice.
R39 control over 3,147 functions with history x 3 bands = 9,441 decisions:
4,020 upgrades (43%), 0 downgrades.
The control's FIRST form passed over an empty set — it keyed on journal rows carrying
a binary, and there are none: the agent verdict schema never had that field, so every
historical note is name-keyed and the same name is a different function in another
overlay (§238). claude_wave_draft.js's VERDICT now requires `binary`, so new rows are
exact. Cookbook §413.
Task Manager showed WSL holding 30 GB while Linux was using 4 GB and ~22 GB was
reclaimable page cache (a gate wave reads the 450 MB asm/ tree plus every build
object). .wslconfig had a memory cap but no reclaim policy, so WSL2 never handed
freed pages back to Windows. Added autoMemoryReclaim=gradual (needs wsl --shutdown),
recorded the no-restart manual reclaim, and .run/memkeeper.sh as the interim
automatic form. R21.
tools/journal_notes.py mines the agent journals per (binary, fn) and appends a
PAST ATTEMPTS section to the pack; claude_wave_packs.py calls it automatically, so
it is the default rather than a step to remember. Idempotent, and R48-safe (a note
stamped with a different binary is never served — §238 homonyms).
Measured before adopting (S71 wave 1, 50 one-agent workflows over the 210-function
real frontier where every target had already refused an earlier wave):
* 38/39 MATCH at closeness 0 (97.4%) vs S70's 124/131 (94.7%) on an EASIER pool
* 29/39 agents cite a prior attempt as what they used
* 4/39 banked by RECOVERING a body that already matched, from a path a note named
* 11/39 matched on the first compile
The two costs it removes are re-testing a measured-inert lever (§406 lists twelve,
§407 fifteen, §410 four — each paid for by an agent and never seen again) and
re-deriving a body that already exists on disk.
Also: jr_isolate_all places file-local `static` definitions with the region that uses
them instead of refusing the whole file. A `static inline` helper (§82.1) has no
address by construction, which is not a defect; the R32 guard was refusing these and
blocking the isolate on 4 of the 6 overlays whose CARVE-REFUSED functions it is the
named remedy for. Two regions using one static is still a hard refusal (duplicating a
used static is a byte change, R43).
docs: cookbook §411, wave-playbook step 3b, accelerators entry.
* Every pack carried PAST ATTEMPTS ON THIS EXACT FUNCTION, mined per-function from the
historical agent journals (52 of 60 targets, 131 notes). Every landed agent returned
MATCH at closeness 0 on the hardest frontier we have.
* §409 — the wave and the nine laws it produced. Law 1: a relocation-stream
TRANSPOSITION is invisible to match_one, the permuter scorer and every similarity
tier (HI16/LO16 masking; the §195-D blind spot for a different reloc class), and it
retroactively explains "MATCH but the gate rejected it" verdicts.
* §410 — COPY THEN ACCUMULATE ON THE COPY: satisfies the $s2 in-place destination and
the sched1 birthing boost at once, with the agent's measured refutation list.
* `binof = {c["fn"]: c["binary"]}` was last-writer-wins, and `status`, `det` and `subof`
had the same shape — a draft of a name carried by two binaries was stamped with
whichever card came last and then reloc-checked against the OTHER binary's symbols.
* Resolve per draft instead: the shard's own target list first
(`.run/wave_<tag>_targets.<i>.json` = `targets[i::workers]`, each row carrying its
binary), a unique-name card second, a counted refusal when neither can answer (R43).
* R39 negative control over every historical wave: 42,655 drafts, 0 regressions,
2,317 (5.4%) previously mis-stamped; 2,107 homonym card names fleet-wide.
Intra-shard ambiguity: 0 of 50,684 (shard, name) pairs over 302,370 shard files.
docs: §408 — §406 refuted as a sweep (0 MATCH / 14 applied, 0 / 210). The 134-member
census counted main's 960 LINKED library stubs and matched a symmetric SHAPE; derived
from the mine-vs-target residual the addressable set is 15 / 210. Decision-log entry
records the pivot: 64 of 210 (30.5%) already match standalone, so the frontier's
largest lane is §376 integration, not codegen.
tools/weave_sweep.py — the derived-selector sweep (R32 coverage, R41 denominators,
--lever-all ablation control).
§405 — the generalisable residue of three waves, grouped by lever family:
A. match_one compares .text ONLY, so a switch's jump table is invisible to it —
a draft can score 110/110 with a PERMUTED table emitted as identity
(resident/func_800D02D0, byte-witnessed). Some historical 'MATCH but gate
rejected' verdicts were the ORACLE being wrong (R34 in our most-trusted tool).
B. the scheduler dials, incl. the birthing-boost re-tie's PLACEMENT rule (must be
a LATER basic block) and reorg's stop_search_p halting at any asm.
C. regalloc from C without pins: variable identity picks global- vs local-alloc;
a cross-arm join value loses first-fit and should be duplicated per arm for
cross_jump to refund; pass-through params reserve arg regs at zero cost.
D. integration is still the bottleneck — ~1/3 had byte-correct bodies blocked
only by declarations; the TU is the authority.
E. what the agents REFUTED: §137 invariance is false for CONFLICT-driven ties;
§153's 'cse2 puts it back' fails for the dead-def case; §257-8 volatility
polarity is per-site, not portable.
§406 — the prologue-weave class: 134 of 1,237 open stubs (11%) share the
sw / move , / sw shape, cause traced in cc1's .i.sched2 dump
(memrefs_conflict_p finds no dependence, potential_hazard picks sw $ra early), 12
variants measured inert, and ONE working lever (non-volatile memory-clobber asm
after the param copy). One lever x 134 known targets = a sweep, not an idiom.
claude_wave_packs writes out_dir/SYS.md + out_dir/packs/<fn>.md, so out_dir is the
WAVE dir. The playbook documented plus an mv to undo the
resulting packs/packs nesting — which also put SYS.md at <wave>/packs/SYS.md while
claude_wave_draft.js tells every agent to read <wave>/SYS.md.
Net effect: the laws file did not exist where any agent looked, in every wave run
this way, and the brief silently degraded to the pack alone. Two S70 agents said so
verbatim; the rest never noticed. Passing the wave dir fixes it and removes the mv.
§400 — a baseline check that conflates "absent everywhere" with "changed under
us" silently drops new files. The general law: when a comparison uses two
different sentinels for "nothing" ("" from a failed command, None from a missing
file), it reports a difference that does not exist — and in a GUARD, a phantom
difference becomes a refusal, which looks exactly like the guard working.
Corollary recorded in both §400 and the carve-state memory: "never blanket-add"
covers SHARED carve state (overlays.mk, splat yamls). It does NOT cover a carve's
own new per-binary source file, which is named by a committed yaml and whose 31
siblings are tracked — that one must be adopted with the bank that created it.
Docstring correction: parallel_gate does NOT use `git add -u src/` (that is
gate_stage's form); it adds exactly the adopted paths. My first diagnosis of this
bug blamed `-u` on the strength of that stale line and was WRONG — the cause was
the baseline comparison. Noted in the docstring so the next reader is not
misdirected the same way.
Caught by Drew asking whether the last waves were harvested. They were not: I
banked 1 of 5 (§398b) and left four lever sets in the notifications. Also found
two paid-for MATCHes that were never staged or gated.
(a) a fence BETWEEN two prologue loads, where source reorder does nothing —
the order is fixed before statement order matters (md_MAIN_013/func_800CB56C)
(b) SINK a call into BOTH arms and let cross_jump keep only the jal suffix;
88ins/close86 -> 92/13, then §3-T2 field order let each sh $zero fill an lhu
load-delay. Duplicate in source so the compiler merges, rather than writing
the merged form yourself (ov_SC07_001/func_8017EDC0)
(c) a $v0->$a0->$s3 DOUBLE COPY is a two-pseudo tell: SImode temp for the compare
+ separate HImode var for the tail (70->37); plus §195-N precondition 5 —
nesting `return 1` with ONE trailing `return 0` blocks jump.c's store-flag
transform so reorg fills both delay slots (18->0) (ov_SC02_017/func_8018347C)
(d) the re-tie as a BIV KILLER: a second set makes n_times_set>1 so loop.c
refuses the pseudo as a biv, killing the combined address giv. volatile was
worse, a dead read did nothing (ov_SC07_001/func_8017E4DC)
(d) makes THREE distinct uses of the zero-byte re-tie in one session — §380
un-hoists a move_movables invariant, §393 kills the scheduler's birthing boost,
§399d denies a biv. One line, three passes: when a single-set pseudo is being
treated specially, give it a second set.