Commit Graph

656 Commits

Author SHA1 Message Date
Drew T 9f61cd33c5 feat(phase-30 S6): BOTH GIANT WALLS CRACKED ×138 (+50,094 ins) — the verdicts were stale, not wrong
The two functions the roadmap has carried as PERMANENT WALLS since Phase 24 are matched in all 138
overlays. Neither needed a siege. Both matched from drafts ALREADY ON DISK.

  func_80178004  165 ins x 138 = 22,770   Phase 26: Fable5, ~477k tokens, "intrinsic 3-integer
                                          regalloc wall". THREE stored drafts report match_one
                                          MATCH today; one banked first try, no new work.
  func_801412A8  198 ins x 138 = 27,324   close=29/110 since Phase 24. Matched from 1 of 31 stored
                                          drafts + the §37/§124 alias.

WHY func_801412A8 LOOKED INTRINSIC (worth understanding — match_one is structurally blind to it):
the TU declares `extern int func_801412A8(int,int,int,int,int,int)` and its callers USE the return
(`param_1 = func_801412A8(...)`), while the byte-true definition is
`Prim_1412A8 *(Prim_1412A8 *, int, int, int, u16, u16)`. Narrow params cannot agree with an `int`
prototype and the no-prototype escape is illegal once a param promotes, so NEITHER side can move --
and the resulting byte difference is in the CALLERS, which match_one never compiles. The §37/§124
def-side asm-label alias decouples them: the TU decl keeps governing the call sites (codegen
untouched), the definition keeps its byte-true signature.

THEN PROPAGATION RETURNED 0/137 TWICE, both times a missing TYPE, not codegen:
  family_remap's `_carry_macros` carries file-scope #defines but (a) NOT typedefs, and (b) is NOT
  TRANSITIVE -- it brought addPrim_1412A8 and stopped, though that macro calls setaddr/getaddr and
  getaddr casts to PTag_1412A8. Lifted Env_1412A8 / PTag_1412A8 / Prim_1412A8 + OT/getaddr/setaddr
  into src/shared/engine_types.h (inside the include guard) -> 137/137, 0 failed.

MY ERROR, CAUGHT BY THE GATE: I lifted the typedefs but did not STRIP them from ov_SC01_077.c, so
they were declared twice and gcc-2.7.2 rejects a repeated typedef even when identical -- the lesson
already recorded at the foot of engine_types.h. R22 came back 139/140 with [FAIL] ov_SC01_077 (the
exemplar's own overlay). Stripped, re-verified, 140/140. A proper lift strips the source;
build_engine_types --strip does both and I did it by hand.

Also a measurement error worth recording: I checked whether the draft defined Prim_1412A8 with a
plain `grep -c` -- which matches inside `addPrim_1412A8` -- and briefly concluded the carry worked.
Substring false positive; the same shape as reading a `return` as a declaration.

VERIFIED: make clean && make extract-all && make check-all -> 140 passed, 0 failed of 140.
Fleet 12432941 -> 12483035 instr (+50,094 -- EXACTLY the two giants x138); fn-count +276;
instr-weighted 94.5% -> 94.8%. audit-digest OK. 0 NON_MATCHING (G4).

THE RULE THIS BUYS: re-measure a wall before respecting it, and SCAN every stored draft rather than
sampling (my first pass checked 8 of 31 and reported "closeness 40" for a function whose MATCH was
in the 9th). Four minutes of re-measurement was worth 50,094 instructions.
2026-08-05 12:51:06 -06:00
Drew T 669367dab0 feat(phase-30 S40): propagate the 19 wave exemplars — 61/87 members banked (+7,087 ins), R22 140/140
Propagation behind every crack, same session (the multiplier the waves exist for). 19 newly-banked
exemplars from waves 1+2, all in the family_sweep lane (0 has_mid_jr):

  87 candidate members / 10,212 ins  ->  61 BANKED / 26 failed across 39 overlays

The 26 that did not bank are the known plumbing shapes, not codegen: 20 CC1-FAIL + 5 callee
`conflicting types` (func_8017EFA0 x3, func_8012B23C x2) -- the same classes the S40 recovery ladder
already has levers for (§17a-1 no-proto + call-site cast; recover_giant block-scoping). Left open
deliberately rather than force-banked (P9); they are the cheapest fuel on the board next session.

TOOLING GAP RECORDED: the sweep's classifier writes "CC1-FAIL: make: *** Error 33" WITHOUT the actual
cc1 message, so 20 of 26 failures carry no actionable reason. Diagnosing one currently requires
manually splicing the draft into its TU and rebuilding (done twice this session). The classifier
should capture cc1 stderr the way harvest_verify already does -- worth fixing before the next big
sweep, or every CC1-FAIL costs a manual reproduction.

VERIFIED: make clean && make extract-all && make check-all -> 140 passed, 0 failed of 140.
Fleet 12425854 -> 12432941 instr (+7,087); distinct +6,145 / +51 uniq; fn-count +61.
instr-weighted back to 94.5% ON THE HONEST (post-main-regen) denominator of 13,160,961.
audit-digest OK. 0 NON_MATCHING (G4).
2026-08-05 11:53:05 -06:00
Drew T 443a3e3afe feat(phase-30 S40): waves 1+2 bank 24/24 after recovery — ZERO codegen walls; +5,479 ins
Two ultracode waves over the open-only h_norm clusters (the pool nobody had ever aimed a wave at),
pool VERIFIED from the sigs first (R14).

  wave 1   8 targets   8/8 match_one   5/8 gate first pass   ->  8/8 after recovery
  wave 2  16 targets  16/16 match_one  14/16 gate first pass -> 16/16 after recovery

THE HEADLINE IS NOT 24/24 -- IT IS THAT NOT ONE FAILURE WAS CODEGEN. All six first-pass gate
failures were TU-integration plumbing, each with an already-documented lever:

  func_801802EC  redefinition of morph_lerp    strip the §77 PROBE LAYER (the draft carries types +
                                               a static inline so match_one can compile standalone;
                                               the real TU already defines them -- scaffolding is
                                               not part of the bank)
  func_8018B238  conflicting types D_80115158  recover_giant: draft declared it file-scope as a
                                               struct array, TU declares u8[] BLOCK-scope inside
                                               other functions -> block-scope the draft's externs
  func_8017EF54  conflicting types (SELF)      §37/§124 def-side asm-label alias (TU declares
                                               void f(void) for no-arg callers; byte-true def takes
                                               s32 in $a0; no-proto escape illegal once a param
                                               promotes)
  func_80183D78  conflicting types (callee)    recover_giant
  func_8017F278  conflicting types func_80146C3C  §17a-1: the fleet canonical is the NO-PROTOTYPE
                                               form + the intended signature applied AT THE CALL
                                               SITE; a concrete prototype collides with it
  (wave-2's 14 first-pass banks needed nothing -- the wave-1 lessons were folded into the prompt)

=> the gate number measures INTEGRATION, not matching. Run the recovery ladder before recording a
wave's yield or the metrics under-report the drafters and send the next wave hunting walls that are
not there. docs/wave-metrics.md S40-1.

POOL VERIFICATION (R14, and it cut both ways): the frontier report's cluster pool MEASURED
1,677 clusters / 5,795 fns / 319,755 ins at a 3.68x multiplier vs its claimed 1,689 / 5,956 /
326,261 at 2.7x -- within 2-4%, and the multiplier is BETTER than claimed. The SAME document's whale
claim was 3/4 wrong. Verify each claim separately; do not accept or reject a source wholesale.

ALSO: 24/24 members propagated from wave 1's 5 banked exemplars (0 failed) -- the same machinery
that returned 0/39 before this session's cast_call_sites fix.

NEW IDIOMS, distilled in-session (R16/R30):
  §144  the LITERAL'S SPELLING picks the immediate encoding (`cnt + 0xff` vs `cnt - 1`: mod-256
        identical, both one addiu, but gcc emits 0x00FF vs 0xFFFF from the source text)
  §145a combine_givs ANCHOR RULE -- the address-giv group anchors on the LAST address-giv in SOURCE
        order (record_giv prepends, combine_givs takes the head); store order decides the base and a
        wrong choice spawns a third induction register
  §145b a bare `p = r;` is a COMBINE BARRIER (can_combine_p/use_crosses_set_p) -- it preserves a
        pointer-bump addiu that combine would otherwise fold into every MEM offset
  §145c chained assignment `a=b=c=0` emits stores RIGHT-TO-LEFT

VERIFIED: make clean && make extract-all && make check-all -> 140 passed, 0 failed of 140.
Fleet 12420375 -> 12425854 instr (+5,479); distinct +5,479 / +43 uniq; fn-count +43.
audit-digest OK. 0 NON_MATCHING (G4). Cost: 3.73M subagent tokens across 24 agents, 0 errors.
2026-08-05 11:47:31 -06:00
Drew T 84d1193f21 docs(phase-30 S40): cookbook §144 (literal spelling = immediate encoding) + wave-metrics S40-1 (8/8 after recovery, 0 codegen walls) 2026-08-05 11:15:15 -06:00
Drew T 6e0b1605c6 fix(phase-30 S40): cast_call_sites read a RETURN as a prototype and deleted it — 0/39 sweep becomes 18/39
THE BUG. tools/cast_call_sites.py classifies a declaration line with

    ^([ \t]*)(extern\s+)?([A-Za-z_][\w \t\*]*?)\b([A-Za-z_]\w*)\s*\(([^;{]*)\)\s*;

Feed it a return statement and `return` is a perfectly good identifier where a type is expected:

    return func_8012CB64((s32)out, -0xC0, 0x40, -0x60, 0);
     ^^^^^^ captured as the return TYPE, func_8012CB64 as the DECLARED NAME

so the "rewrite this decl to canonical" path REPLACED the statement with
`extern s32 func_8012CB64(s32,s32,s32,s32,s32);`, DELETING the return. In C89 a declaration after a
statement is a parse error, so the damage surfaced as a bare syntax error in the DRAFT -- reading as
the draft's fault, not the tool's. 9 of 9 staged members of family 0x801848dc lost their return.

  fix: a keyword guard (a declaration's type-specifier can never begin with a statement keyword)
  family_sweep --hseq --band all over 5 families:   0/39  ->  18/39 banked   (only the guard changed)

⚠️ AND THE TRAP INSIDE THE FIX: the obvious R33 move is "route it through cdecl". CHECKED, and it is
WRONG -- cdecl.parse() is a DECLARATOR-GRAMMAR parser that assumes it was handed a declaration; it
reports `return func_X(...);` as declaring func_X and `if (f(a));` as declaring `if`.
Statement-vs-declaration is a question cdecl does not answer. Routing there would have been a silent
non-fix that looked principled. §134's law still holds for line-SHAPE masking; this is a different
question.

BLAST RADIUS (measured, not assumed -- R14): cast_call_sites is in gate_stage's DEFAULT pipeline
(canon_resident_calls -> cast_call_sites -> sig_unify -> harvest_verify) and has been since Phase 20.
Of 44,833 stored drafts, 318 (0.7%) carry a `return f(...);` line this mis-reads, across 67 callees
(func_8014F468 x41, func_8014F6F4 x37, func_8014F74C x32, ratan2 x25). Every one, every time it
passed the gate pipeline, lost its return and failed as PLUMBING. Part of the historical plumbing
tail is this bug.

ALSO IN THIS COMMIT

- S5 CALIBRATION WAVE (8 agents, ultracode, 1.31M tokens). Pool VERIFIED FIRST (R14 -- Fable's whale
  claim was 3/4 wrong): measured 1,677 clusters / 5,795 fns / 319,755 ins at a 3.68x multiplier vs
  its claimed 1,689 / 5,956 / 326,261 at 2.7x -- its numbers hold, and the multiplier is BETTER.
  Result: 8/8 match_one MATCH (close=0), and 5/8 banked whole-binary -- the §52b/§61 gap is
  integration, not codegen. Banked: func_801822E0 func_8017EC98 func_801851A8 func_80189A34
  func_80188E10 (693 ins x1 before propagation). Not banked: func_8018B238 (FAILED),
  func_8017EF54 + func_801802EC (NEAR) -- drafts kept in .run/wave-s40/ for recovery.
- 18 member-banks from the re-run sweep (the cross-address free-h_exact pool: h_exact-identical at
  DIFFERENT addresses, which dedup_propagate correctly refuses since it assumes position-locking --
  family_sweep is the right lane).
- cookbook §143 (this bug + the cdecl trap + the blast radius); index regenerated.

VERIFIED: make clean && make extract-all && make check-all -> 140 passed, 0 failed of 140.
Fleet 12419169 -> 12420375 instr; distinct +1,526 / +5 uniq; fn-count +23. audit-digest OK.
0 NON_MATCHING (G4).

NEW IDIOM FROM THE WAVE, not yet folded into §31 (agent was told to write only its draft): a byte
counter must be spelled `cnt + 0xff`, NOT `cnt - 1`. Both are mod-256 identical and both compile to
one addiu, but gcc-2.7.2 picks the immediate encoding from the SOURCE SPELLING (0xFFFF vs 0x00FF).
Also flagged: .run/ghidra_c/func_8017EF54.c is a stale decompile of the WRONG function.
2026-08-05 11:05:35 -06:00
Drew T 070687d8fa docs(phase-30 S39): burn-down for T5 prep — with the -0.14pp last row annotated as a denominator correction 2026-08-05 00:50:01 -06:00
Drew T b9a7eddef8 docs(phase-30 S39): measured frontier snapshot — main is now the single largest open target (10.7%) 2026-08-05 00:49:07 -06:00
Drew T 6d684ac650 docs(phase-30 S39): cookbook §142 — the free h_exact pool; propagate the matched body, don't gate a draft 2026-08-05 00:47:56 -06:00
Drew T e6e05d727a fix(phase-30 S39/S7): regenerate main's 7-week-stale Ghidra sig — honest denominator, metrics re-baselined
main's sig was dated 2026-06-14 and covered only 1,525 of its 2,002 INCLUDE_ASM stubs: 477
stubs were INVISIBLE to the weighted metrics, so main was being graded against two-thirds of
itself and the fleet denominator was understated.

  tools/ghidra_mcp_stop.sh  (R23 - clean stop, "Save succeeded", releases the .rep lock)
  make sig-refresh BINARY=main  -> DumpFunctionSignatures.java, read-only, -noanalysis

  signatures      1,729 -> 2,205  (+476)
  stubs covered   1,525 -> 2,001  of 2,002   (1 still uncovered, named below)
  main .text ins  60,201 -> 79,510  (+19,309)

METRICS RE-BASELINED (a DENOMINATOR CORRECTION, not a regression -- the Phase-27 precedent,
where onboarding 4 hidden overlays honestly moved 68.9% -> 67.0%):

  instr-weighted   94.5% -> 94.4%   (12,419,169 / 13,160,961; numerator UNCHANGED)
  distinct-code    89.3% -> 89.0%   (5,029,454 / 5,654,184;   numerator UNCHANGED)
  fn-count         96.51% (unchanged -- it never read the sig)
  MAIN game-code   0.72% -> 0.55%   (436 / 79,510)

Both numerators are identical across the change; only the denominator grew. audit-digest OK.

CAVEAT UNCHANGED (R34): main still has no INDEPENDENT boundary oracle -- sig_image cannot sign a
PS-X EXE (header offset, interleaved islands), so main's function list rests on Ghidra alone and
audit-corpus cannot cross-check it. That is the open item in docs/second-oracle.md and part of
task #9's denominator work.

NOTE the sig itself is gitignored/regenerable, so this commit lands only the digests; a fresh
clone reproduces it with `make sig-refresh BINARY=main` (Ghidra required, MCP stopped).

MCP IS NOW DOWN (I stopped it for the project lock). The SessionStart hook restarts it next
session; run /mcp before any Ghidra work (R29).
2026-08-05 00:41:54 -06:00
Drew T e9c66a6720 fix(phase-30 S39): close the §134 class — the last two line-shape scanners route through cdecl._mask
§134 had been patched individually in six tools; the standing note said the fix is ONE masking
oracle, not a seventh regex (R33). The last two holdouts are migrated.

progress.py.strip_comments — a private 2-line regex, NOT string-aware, feeding three line-shape
decisions in classify(): the {-vs-; definition/declaration scan, the count('{')-count('}') body
walk, and the empty-vs-real body test. A brace inside a string literal therefore mis-buckets a
function in the FN-COUNT metric. Negative control:

    void f(void) { puts("}"); x = 1; }
      old regex   -> body-depth -1  (the string's brace was counted)
      cdecl._mask -> body-depth  0  (correct)

Metrics IDENTICAL before/after on today's corpus (341365/353717; REAL 339510, empty 896, stubs
12345) -- a latent defect, harmless until someone banks a function containing "{".

lint_symbol_refs.strip_comments_strings — correct, but a SECOND implementation of the same
masking. Deleted in favour of cdecl._mask. The one behavioural difference (_mask blanks the quote
DELIMITERS, the private scanner kept them) was CHECKED not assumed: irrelevant because every token
the linter hunts lives outside the quotes. Gated on the linter's OUTPUT being byte-identical across
the change (it is), not on the two masks being byte-identical -- the right gate is the tool's
answer, not its internals.

cookbook §141 + index regenerated. No src/ or config/ change; no bytes touched.
2026-08-05 00:37:59 -06:00
Drew T 85519f1e32 feat(phase-30 S39): propagate free h_exact class 0x8017d174 (8 ins x 1) - R22 140/140 2026-08-05 00:32:32 -06:00
Drew T 49a3efa14d feat(phase-30 S39): propagate free h_exact class 0x801880f8 (8 ins x 1) - R22 140/140 2026-08-05 00:28:41 -06:00
Drew T 7604e294f2 feat(phase-30 S39): propagate free h_exact class 0x80188f90 (8 ins x 1) - R22 140/140 2026-08-05 00:25:22 -06:00
Drew T c07ee02282 feat(phase-30 S39): propagate free h_exact class 0x80182bb0 (9 ins x 1) - R22 140/140 2026-08-05 00:21:32 -06:00
Drew T 8059ac8a53 feat(phase-30 S39): propagate free h_exact class 0x80182bd4 (10 ins x 1) - R22 140/140 2026-08-05 00:17:59 -06:00
Drew T e88eccac60 feat(phase-30 S39): propagate free h_exact class 0x8018625c (19 ins x 1) - R22 140/140 2026-08-05 00:13:15 -06:00
Drew T 638f97dbbb feat(phase-30 S39): propagate free h_exact class 0x80176144 (53 ins x 1) - R22 140/140 2026-08-05 00:09:28 -06:00
Drew T ff4bc60e09 feat(phase-30 S39): propagate free h_exact class 0x8017bee0 (10 ins x 6) - R22 140/140 2026-08-05 00:00:20 -06:00
Drew T c3bf1c988d feat(phase-30 S39): func_801758FC propagated x137 (+7,535 ins) — the largest free h_exact class
Measured the h_exact free pool from the bytes rather than trusting the frontier report's
numbers (R14 — its whale claim was 3/4 wrong: it said the whale was open in all four SC07
overlays; three were already banked and I closed the fourth earlier this session).

MEASURED: 215 open function-instances / 8,763 instructions are byte-identical (h_exact,
including reloc payloads) to an already-matched function. ONE class is 86% of that pool:

  func_801758FC — 55 ins, same address in all 138 overlays, matched in ov_SC01_000 only,
  OPEN in the other 137  =>  7,535 instructions.

h_exact means identical INCLUDING jal/lui/%lo reloc immediates, so the matched body compiles
byte-identically at every member with NO remap (dedup_extend's correctness argument, §14).
dedup_propagate --addr authored it once as DEFINE_func_801758FC() in engine_core.h and
instantiated it at all 137 open sites in address order.

  [ OK ] 138 overlays byte-identical after propagation; 1 new group in config/dedup.us.yaml

VERIFIED: make clean && make extract-all && make check-all -> 140 passed, 0 failed of 140.
Fleet instr 12411467 -> 12419002 = +7,535 EXACTLY; fn-count +137; instr-weighted crosses to
94.5%. distinct-code unchanged BY DESIGN -- the class was already matched in ov_SC01_000, so
the 137 add fleet instructions but no new DISTINCT function. audit-digest OK. 0 NON_MATCHING.

Note this function had been sitting in the stored-draft backlog for ov_SC06_030 and
ov_SC07_010 and re-gated "no" earlier tonight -- because gating a DRAFT is the wrong move for
an h_exact class. The right move is propagating the already-MATCHED body. Same function, two
routes, and only one of them is free.

Remaining free pool after this: 78 instances / 1,228 ins across 32 classes.
2026-08-04 23:56:15 -06:00
Drew T a216cb1b57 feat(phase-30 S39/S4): propagate func_80183AF0 family (47 ins x 2 members) - R22 140/140 2026-08-04 23:43:56 -06:00
Drew T a1d6ea3002 feat(phase-30 S39/S4): propagate func_80183CF4 family (57 ins x 2 members) - R22 140/140 2026-08-04 23:40:16 -06:00
Drew T 55332bfc42 feat(phase-30 S39/S4): propagate func_8018281C family (76 ins x 2 members) - R22 140/140 2026-08-04 23:36:34 -06:00
Drew T 99ff84ed8b feat(phase-30 S39/S4): propagate func_80182E7C family (85 ins x 2 members) - R22 140/140 2026-08-04 23:33:17 -06:00
Drew T 0f73618fa8 feat(phase-30 S39/S4): propagate func_801820DC family (94 ins x 2 members) - R22 140/140 2026-08-04 23:29:28 -06:00
Drew T 0414171237 feat(phase-30 S39/S4): 8/35 draft-exemplar heads re-gate and bank (+474 ins, 4 gate cycles, 0 agent tokens)
The 39 draft-exemplar families all have their exemplar still OPEN in ov_SC01_077 -- a
draft-exemplar family cannot propagate until its head banks. Re-gated the newest stored
ov077 draft per head, in 4 small batches (§61: a wide harvest broke a TU in S38).

Set aside the top 4 heads (65% of the pool's weight, all known-hard): func_801412A8 +
func_80178004 ARE S6's two giant walls (198x138 + 165x138 = 50,094 ins riding on 2 cracks),
func_8017C974 is today's byte-proven close=47, func_8017C294 its 246-ins neighbour.

  batch 0  1/9      batch 1  3/9      batch 2  4/9      batch 3  0/8     = 8/35 (23%)

BANKED: func_8017EC7C func_8018281C func_801820DC func_80182988 func_80183BAC
        func_80183AF0 func_80183CF4 func_80182E7C
(+474 ins x1 now; ~1,441 ins of templatable weight behind them once their families propagate.)

CALIBRATION REFINEMENT (docs/calibration.md, S39): this population re-gates at 23%, vs 8%
for the general stored pool and 4/6 for fresh post-repair drafts. Three different populations,
three different rates -- which is exactly why the rule is "re-gate what a repair plausibly
touched", not "re-gate the ledger". ov_SC01_077 is the split-heaviest overlay, so the S38
alias-deletion repair plausibly touched all of these.

VERIFIED: make clean && make extract-all && make check-all -> 140 passed, 0 failed of 140.
Fleet 12410275 -> 12410749 instr (+474), distinct +474 / +8 uniq, fn-count +8. audit-digest OK.
0 NON_MATCHING (G4).
2026-08-04 23:22:42 -06:00
Drew T 957dada2f8 docs(phase-30 S39): decision-log — MASTER_REMAINING proposal: adopt the goal (denominator completeness + a reconciliation gate), reject the maintained list (R33) 2026-08-04 22:43:28 -06:00
Drew T 7b5eda0424 feat(phase-30 S39/S4): re-gate probe — A10 broadly stands; 4 banked from the reverted overlays (+146 ins)
Tested whether decision-log A10 ("stored drafts re-gate at 0/958", measured in T1) survives
S38's tool repairs. Three populations, plain re-gate, no draft edits:

  fresh wave-6 drafts (diagnosed "blocked on a class")   4/6
  stored pool, unbiased sample (every 96th of 1,155)     1/12   <- hit was in a REVERTED overlay
  the two REVERTED overlays, targeted                    3/17

A10 BROADLY STANDS. ~8% on the general stored pool is not a harvest, and a 1,155-wide sweep
(= 1,155 whole-binary builds) is not justified by it. Do NOT generalise the fresh-draft rate
(4/6) onto the stored pool -- different populations. The honest rule is narrower and cheaper:

  after a tool repair, re-gate the drafts THAT DEFECT plausibly touched, targeted by its
  blast radius -- not the whole ledger. (R35 applied to the backlog, not just to metrics.)

BANKED (+146 ins): ov_SC06_030 func_80161208 + func_80162CCC; ov_SC07_010 func_801506A4 +
func_8016F0AC. R22 clean-fleet 140 passed, 0 failed of 140 -- which also proves byte-neutral a
fleet-shared engine_core.h edit the bank required (extern s32 func_801506A4(s32,s32) -> the
no-prototype form), reaching all 138 overlays (T2 blast radius).

Fleet 12410129 -> 12410275 instr; distinct +95 / +1 uniq; fn-count +4. audit-digest OK.

Also documents the LEDGER MECHANICS in calibration.md (Drew asked): .run/backlog.jsonl is
append-only and nothing is deleted on bank -- open-ness is DERIVED from corpus.stubs at every
read (load_best drops now-banked rows per-binary, P9) and `make report` runs `backlog.py prune`.
Membership is therefore self-maintaining and currently clean: 863 rows, 0 already-banked, 14
duplicate-addr (was 6,867 rows / 98% banked before Phase-29 compaction). What pruning does NOT
re-validate is the VERDICT on surviving rows -- closeness + residual class are as old as the
tooling that wrote them (Phase 28 found a corrupt one: func_80178004 close=0 -> 91). That is
the staleness that matters, and it is exactly what this probe measured.
2026-08-04 22:42:54 -06:00
Drew T a2a50635b3 feat(phase-30 S39/S4): func_801878E8 family 4/4 siblings banked ×N (+2,052 ins, ~0 agent tokens)
Propagation behind the crack banked this session. jtbl_family_bank.py over the 4 open
h_seq siblings of func_801878E8 (513 ins each):

  ov_SC03_001  BANKED    ov_SC03_124  BANKED
  ov_SC04_019  BANKED    ov_SC05_017  BANKED

ROUTE NOTE (§53, worth keeping): family_sweep --hseq REFUSED this family by design --
has_mid_jr => it needs the jtbl carve, not the remap sweep, and the interlock says plainly
that "a 0% from this path would be a TOOL artifact, not a wall". Taking the refusal at face
value and using the named tool banked 4/4 first try. This is the same lesson as the rest of
the session from the other side: the instrument told the truth about its own limits.

jtbl_family_bank also enforces a CLEAN tree (it reverts from HEAD per sibling, so an
uncommitted prior bank would be destroyed) -- which is why the ×1 banks committed first (H4).

VERIFIED: make clean && make extract-all && make check-all -> 140 passed, 0 failed of 140
(each sibling carves its own jtbl => config changed => fleet blast radius). Fleet
instr-weighted 12408077 -> 12410129 = +2,052, exactly 4 x 513; distinct +1,539 / +3 unique
fns (the 4th sibling shares an h_exact class already matched); fn-count +4. audit-digest OK.
0 NON_MATCHING (G4).

Session running total: +4,727 instructions (whale 770 + 4 drafts 1,905 + family 2,052),
12405402 -> 12410129, every step R22 clean-fleet 140/140.
2026-08-04 22:16:33 -06:00
Drew T f2696653ef feat(phase-30 S39/S4): 4 wave-6 drafts bank UNCHANGED — the block was our tooling, not the code (+1,905 ins)
The 6 still-open wave-6 drafts were triaged against S38's own diagnosis table; 4 banked,
R22 clean-fleet 140/140.

  func_801919A0  ov_SC06_032  710 ins   (was: undefined ref func_8018B878 -- "alias class")
  func_80189030  ov_SC03_001  557 ins   (was: undefined ref func_80186F88 -- "alias class")
  func_801878E8  ov_SC04_018  513 ins   (was: undefined ref func_801848DC -- "alias class")
  func_8018A564  ov_SC02_027  125 ins   (was: CC1-FAIL Error 33)

THE FINDING: all four banked with NO change to the drafts. S38 recorded them blocked on a
class that needed cracking ("cracking this one class frees 6 drafts at once"); they had
ALREADY been freed by S38's own tool repairs -- the jr_isolate_all/overlay_src_split
alias-DEFINITION-deletion blindness and harvest_verify._reload_corpus. The drafts were
correct all along; the instruments were failing them. That is the FIFTH recorded "wall"
this phase to resolve to our own tooling.

  => RE-GATE STORED DRAFTS AFTER ANY TOOL REPAIR before treating a stored verdict as a
     fact about the code. A verdict is only as current as the instrument that produced it
     (R35 applied to the backlog, not just to metrics).

Each bank also performed a jtbl carve, so config/ changed => fleet blast radius => full R22
(clean + extract-all + check-all) = 140 passed, 0 failed of 140.

Metrics move exactly as the model predicts: instr 12406172 -> 12408077 = +1,905, the exact
sum of the four (710+557+513+125); distinct +1,905 / +4 unique fns; fn-count +4.
audit-digest OK. 0 NON_MATCHING (G4).

LEFT ON THE BACKLOG as genuine codegen residuals, not forced (P9):
  func_8017C974 (ov_SC01_077, 947 ins, close=47, REGALLOC-PERM, 12 permuter variants inert)
  func_80188C68 (ov_SC03_124, 551 ins, close=370, the only target with no twin anywhere)

NEXT: the func_801878E8 family (4 open siblings x 513 ~= +2,052). family_sweep --hseq
correctly REFUSED it via the §53 interlock (has_mid_jr => jtbl carve route; "a 0% from this
path would be a TOOL artifact, not a wall"), and jtbl_family_bank.py requires a clean tree
because it reverts from HEAD per sibling -- which is why this commit lands first.
2026-08-04 22:10:49 -06:00
Drew T 3c0f60861d feat(phase-30 S39): the whale is 138/138 — ov_SC07_010 carved + banked (+770 ins, R22 140/140)
Closes the first of S38's two reverted R22 failures. ov_SC07_010 was the lone overlay
still shipping func_80144B9C (770 ins) as INCLUDE_ASM while the other 137 banked it.

Its _jr_80140608 object ran 0x184b0..0x2c2f4 straight through the whale; the sibling
ov_SC07_006 carves the same span into _o0d (0x1ca44) + _jr_801457A4 (0x1d64c). Note
0x1ca44 + 0x80128158 = 0x80144B9C exactly.

  tools/o0_subsplit.py ov_SC07_010 --lo 0x80144B9C --hi 0x801457A4
    -> 1 unmatched stub, 0 ALREADY-MATCHED in range (so no §126 island; K=0 => 3 regions)
    -> split BYTE-NEUTRAL first (d7b5875d), then banked via ../shared/func_80144B9C.h

The S38 cause ("its -O0 split reused an EXISTING _o0c instead of a fresh _o0d") did NOT
recur: o0_subsplit.free_letters derives the unused suffix (_o0c is free in THIS overlay).

Two decl conflicts on the way, enumerated with `cdecl` in ONE pass (R33) rather than one
build at a time — of the whale header's 94 symbols the §8b carried layer re-declares 3,
and 2 conflict: D_801274D0 (layer `s32 (*)(s32)`) and D_801274CC (layer `void *`) vs the
header's canonical `s32`. Dropped both: nothing in the region uses them, they are carried
from an earlier region of the old object, and 0 of the 137 other whale-including files
carry either. Decls emit no code => byte-neutral (§8c), and byte-gated.

ov_SC06_030/func_8017E120 needed NO work — it is already banked (defined at
ov_SC06_030_jr_8017C8D0.c:3491). S38 reverted the surrounding batch, not that function.

VERIFIED: make clean && make extract-all && make check-all -> 140 passed, 0 failed of 140
(config changed => fleet blast radius, R22 mandatory). Fleet instr-weighted
12405402 -> 12406172 = +770, exactly the whale's size. distinct-code unchanged by design:
that h_exact class was already matched via the other 137, so the 138th adds fleet
instructions but no new DISTINCT function. audit-digest OK (the new S1e gate, on its first
real use). 0 NON_MATCHING (G4).

Metric note (R30, same class as S1e): a body banked by #include-ing a shared header is
invisible to fn-count's NUMERATOR (the definition is not in the .c) while its stub leaves
the denominator -- 341186/353718 -> 341186/353717. The weighted metrics counted it
correctly because they derive from corpus.stubs, not re-parsed C. Trust the weighted pair.

Still open from S3: the 61 SC07 -O0 members (untouched).
2026-08-04 21:58:53 -06:00
Drew T 1576570271 fix(phase-30 S1e): the distinct-code "regression" was a STALE DIGEST — alias lever ungated
The S38 checkpoint gated the phase's best lever ("do NOT scale the alias lever") on
distinct-code falling 89.3 -> 89.2. It never fell.

PROOF (each commit's metric recomputed from its OWN committed tree, 0 unresolved):
  commit:1426 TRUE     : instr 12394533  distinct 5022306  (77895 uniq)
  commit:1426 COMMITTED: instr 12402412  distinct 5029324  (78025 uniq)   <- stale
  HEAD TRUE == COMMITTED: instr 12405402  distinct 5025082  (77952 uniq)
  => true delta 843->HEAD: instr +10869, distinct +2776 ins / +57 uniq. ALL ROSE.
The 843 digest was generated from a working tree still holding work REVERTED before the
commit landed (+7,879 ins / +130 uniq overstated) and never regenerated, so the next
HONEST digest read as a fall. => THE ALIAS LEVER IS UNGATED (scale it, §61 small batches).

Both recorded leads were wrong (R14): progress.py:423's SIG regex feeds fn-count ONLY
(neither weighted metric sees a C identifier — both derive matched = sig - corpus.stubs),
and "the harvest reverted functions to INCLUDE_ASM" died on one grep (483 removed, 0 added).
The 3-grep proof: identical sigs + unchanged tools/ + zero +INCLUDE_ASM => HEAD's stub set
is a strict subset => both numerators are FORBIDDEN to fall.

THREE INSTRUMENT DEFECTS, all one class (a bare except around a fail-CLOSED oracle):
- progress.py stub_addrs wrapped corpus.stubs in `except Exception: return set()`. An empty
  stub set means "could not answer", not "no stubs", so matched = sig - stubs credited EVERY
  function. Byte-witnessed: instr 100.00% / distinct 100.00% in a tree with no asm/. Now
  propagates.
- cast_call_sites.tu_for + reconcile_tu.tu_for had the identical swallow, falling back to the
  default <ov>.c instead of the jr/-O0 split TU — silently reinstating the exact bug
  cast_call_sites' own docstring says it exists to fix. A wrong-TU reconcile fails the gate,
  and this phase's base rate is ~24k PLUMBING vs 4,917 DIFF, so it presents as a codegen wall.
  Now propagate CorpusError; ValueError fallback for curated names preserved; derived-TU path
  re-verified (a _jr_ split stub resolves correctly, both tools agree).

NEW GATE (R34 — the byte-gate is a null oracle for DOCUMENTS; check-all stays 140/140 over a
stale digest forever): tools/audit_digest.py + `make audit-digest`, wired into tools-health
after report. Recomputes the three headline metrics from the current tree and fails if the
committed digest disagrees. Compares INTEGERS, not percentages — the +7,879-instruction
staleness printed as "94.4%" on both sides. Negative-control-proven against the stale 843
digest (fails, exit 1) and green on HEAD.

Verified: make report exit 0 (dedup-check 1910 validated / 0 failed, C1 coverage
241216/241216); audit-digest OK; cookbook-index OK (398 sections); metrics unchanged by the
fix (94.40% / 89.18%). No src/ or config/ edits — no bytes touched, nothing banked.

cookbook §140 · decision-log 2026-08-04 · SETUP.md inventory (R21) · R14/R32/R34/R35.
2026-08-04 21:48:57 -06:00
Drew T d8016c49c8 docs(phase-30 S38): checkpoint v4 — POST-S1d, fresh-session safe
Refreshes a checkpoint that had gone stale (v3 predated S1d) — stale is worse than absent.

FLEET 96.46 / 94.4 / 89.2, +37,166 instructions this session, ~0 agent tokens after the opening
wave. R22 run thirteen times: 140/140 on eleven, TWO REAL FAILURES (ov_SC07_010, ov_SC06_030), both
caught by the clean-tree rebuild after passing their per-binary gate, both reverted and recorded.

Records the session's biggest find: the §37/§124 DEFINITION-SIDE ASM-LABEL ALIAS is a CLASS lever,
not a one-off. It cracked the 208-conflict narrow-parameter class 138/138 after cast_call_sites,
--normalize-self-decls and --fix-def-sig were each eliminated BY MEASUREMENT. S33 proved it once and
it was never generalised.

Carries the unresolved accounting anomaly prominently (new task #11 / S1e): distinct-code FELL
89.3 -> 89.2 across the alias harvest while fn-count ROSE, which no pure naming artifact explains.
The bytes are proven; the yield number is not. Next session starts there, before scaling the lever.

Also records eleven tool defects fixed (nine of ten "walls" were our own instruments, two of them
mine), that §134 has now appeared in SIX tools and wants cdecl._mask rather than a seventh patch,
and seven process errors of my own including piping away a gate summary I then could not report.
2026-08-04 21:25:18 -06:00
Drew T 10f9546272 chore: regenerate the fleet digest + backlog after S1/S2/S3
docs/progress.fleet.md is the authoritative metric source the checkpoint's staleness self-check
compares against — committing it keeps that check meaningful for the next session.
2026-08-04 20:10:23 -06:00
Drew T be2eaa1842 feat(phase-30 S38/S1c): re-sweep the matched-exemplar families after the type lift — 97 members banked
Families that returned 0/N before the 895-type lift now bank: 97 member-matches across 137 families
(1,138 failed; skipped 186 STRUCT-class by design, 106 unresolved-immediate, 6 not-stub).
R22 clean-fleet 140/140. Fleet 94.2 -> 94.3% instr / 88.9 -> 89.1% distinct / 96.29 -> 96.32% fn.

RESIDUE PRICED FROM THE SWEEP'S OWN .classified.txt PAYLOADS, not inferred: in the 400 most recent
failure records, 133 are genuine DIFF and the clear majority are `conflicting types for <sym>` —
the §103/§20 extern-conflict class, across ~12 overlays. That confirms S1b (wire reconcile_tu /
cast_call_sites into the --hseq path) is the correct next lever, and it is now justified by
measurement rather than by the plan's projection.

Method note worth keeping: those per-member diagnoses have been written on every sweep run for a
month and were never read — including by me, until after I had spent two probes and a manual
--stage-only round rediscovering one of them. Every remaining task now starts by reading the payload.
2026-08-04 19:04:56 -06:00
Drew T bc04f65562 docs(phase-30 S38): checkpoint — wave 6 banked (+10,616 ins), the gate defect fixed, 9 drafts diagnosed
FLEET 96.29% fn / 94.2% instr / 88.9% distinct, R22 140/140 twice. Session banked 7 wave-6 heads
+ 25 propagated siblings = +10,616 instructions (12,368,236 -> 12,378,852; the digest delta matches
the hand-derivation exactly).

wave-metrics.md gains Findings 5 and 6:
 - RANK WAVES BY INSTRUCTIONS, NOT HEADS. Wave 6 banked ~45% more instructions than wave 5 while
   banking less than half as many heads, because a bigger head carries more instructions AND its
   family propagates at the same cost per sibling (func_8017FEE0: ONE 299-ins head -> 4,485 ins
   across 15 siblings, ~0 agent tokens). The metric to beat is POOL REALISATION (21%), not bank
   rate — and wave 6's bank rate is NOT comparable to waves 3-5 because the difficulty knob moved
   deliberately (median target 438 ins vs 143, mostly has_mid_jr).
 - A WAVE TALLY IS A COVERAGE CLAIM and needs its own assertion.

The 9 unbanked drafts are diagnosed and preserved, and 6 of them are ONE class worth cracking
first: `undefined reference` to a sibling that IS defined in the overlay but only via a
definition-side __asm__ alias (§37/§124) — the carve repartitions the object and separates the call
site from the alias definition. One fix frees 6 already-paid-for drafts and will recur in every
carve-heavy wave. The other two are genuine near-misses (close=47 REGALLOC-PERM, close=370).

Tooling committed for reuse: w6_pool.py (the pool derivation, now a script), w6_diag.py (runs the
REAL gate path — s36_capture.py splices without the carve and is wrong for jr targets),
w6_jtbl_prop.py (carve-path propagation with the per-family commit jtbl_family_bank requires).
2026-08-04 18:10:19 -06:00
Drew T 65f0184f7d chore: regenerate docs/family-hseq.md after the wave-6 banks
Derived digest; committed so the next family map regen has a clean base.
2026-08-04 17:50:35 -06:00
Drew T e977205bb8 docs(cookbook): §139 — a gate that greps for verdicts must assert 1:1 accounting
The wave-6 gate printed BANKED 5 / FAILED 1 over SIXTEEN drafts and nothing said so. Captured with
the three corollaries that outlive the bug (R30 — written in the session that produced them):
 (a) the byte-gate is a perfect CORRECTNESS oracle and a NULL COVERAGE oracle (R34 again), so every
     wave-level tally is a coverage claim and needs its own assertion;
 (b) a pipeline's exit status is the LAST command's — "family_sweep ... | tail" hid a non-zero exit
     in this same session; use pipefail/PIPESTATUS or the tail IS the error handler;
 (c) a reverted CONFIG needs a re-extract before the next measurement means anything (the Phase-20
     R22 corollary; skipping it made three genuinely-banked functions read as failures).
Plus the inverse-lookup trap: a just-banked head LEAVES its family's members list and becomes
exemplar.kind='matched', so a member-list lookup reports "no family" for exactly the heads you just
banked. Distinct from §138 rule 4, which governs target SELECTION.

Index regenerated: 393 sections, 3 new symptom keys.
2026-08-04 17:50:05 -06:00
Drew T e5380ff6fb fix(tools): family_hseq's stdout claimed "fleet" for an OVERLAYS-ONLY number
load() globs .run/sig.ov_*.jsonl, so main and the resident are absent from every denominator —
the numbers run ~0.3-1.0pp above the authoritative `make report` fleet (measured today: 96.6/94.6/
89.7 vs the digest's 96.28/94.1/88.7). docs/family-hseq.md has always carried the "(overlays)"
qualifier; the stdout print did not.

That asymmetry matters because stdout is the channel a session actually reads and transcribes into
a checkpoint — a right number under a wrong label is how a wrong number propagates (R35: the
measurement was fine, the instrument's LABEL was the defect; R14: a checkpoint that disagrees with
the digest must lose, and it can only lose if the disagreement is visible).

Print-only; the metric itself is unchanged and correct for its scope.
2026-08-04 16:14:13 -06:00
Drew T b42b1885ae docs(phase-30): SESSION-33..37 checkpoint — wave 5 banked, nothing owed; wave-metrics findings reordered 2026-08-04 13:43:53 -06:00
Drew T af16c38a62 feat(phase-30 S37): wave 5 banks 16/16 with ZERO reconcile + 26 members; wave metrics logged
Fleet 96.27 -> 96.28% fn-count / 94.1% instr / 88.6 -> 88.7% distinct (77,765
uniq). R22 clean-fleet: 140 passed, 0 failed of 140. dedup 1910/0.

16 targets / 16,884 templatable ins. 19 agents, 2.71M tokens, 82 min wall.
The gate banked 16/16 — the FIRST perfect gate of the session, and the first
needing NO reconcile at all. Sweep: +26 members / 3 failed across 17 overlays.

NEW: docs/wave-metrics.md — the wave-by-wave performance log, with the derivation
commands so future rows are COMPUTED, not hand-transcribed (R33). Four findings,
each recorded with its caveat rather than as a bare number:

 1. THE PROMPT IS THE LEVER, AND THE AGENTS WRITE IT. Bank rate 76 -> 77 -> 100
    -> 100 -> 100% with models and gate held constant. The jump was STEP 0 (a
    magic-literal grep of src/, ahead of engine_core.h) — which came from a
    wave-2 agent's index_gap report. Caveat recorded: waves 3-5 targets also
    trended easier, so the mechanism is the durable claim, not the exact %.
 2. pipeline() vs batched parallel(): 136 min/14 targets -> 82 min/16 targets,
    parallelism 2.5x -> 3.8x. The two-batch design was a hard barrier with 37-50
    min dead gaps; the harness already caps at 16 so it bought nothing. Floor
    recorded honestly: the slowest agent is still ~50 min of real match_one
    iteration, so the lever there is target SELECTION, not concurrency.
 3. ECONOMICS: ~170-300k tokens per banked head in the stable regime — but a head
    is not the unit of value. Head + propagated members is, and sweep yield is
    BIMODAL not average (21/21 vs 18/165), because it is a property of the FAMILY.
    Averaging those two predicts nothing.
 4. A perfect gate is a signal the prompt rules landed. Waves 1-4 each needed 1-2
    post-gate reconciles; wave 5 needed zero. The reconcile lane is the fallback,
    not the plan. Lifetime 21/22.
2026-08-04 13:42:58 -06:00
Drew T 9064840757 feat(phase-30 S36): wave 4 banks 14/14 + 26 members — step 0 is now the agents' default move
Fleet: R22 clean-fleet 140 passed, 0 failed of 140. dedup 1910/0.

14 targets / 16,844 templatable ins. 17 agents, 3.0M tokens. Claimed 14/14; the
whole-binary gate banked 13, the 14th on reconcile. Sweep: +26 members / 0 failed
across 18 overlays. Reconcile lane 21/22 lifetime.

STEP 0 HAS BECOME THE AGENTS' DEFAULT MOVE. Nearly every wave-4 verdict cites the
cross-overlay magic-literal grep BY NAME, several reporting `index_gap: none`
because it resolved the target in one pass with no cookbook derivation needed:
 - func_8018BED0: grep 0xE100000A -> func_80188C04 (ov_SC03_089), verbatim, MATCH first try
 - func_8018BAB4: grep D_800A6610/D_800B9A02 -> func_801887E8, verbatim + callee swap
 - func_8017ED54: grep named all 5 family members -> reused func_8017D9F0's body, 14 data remaps
 - func_8017C290: grep found byte-identical twins ALREADY banked in two other overlays
Bank rate by wave, same models + same gate, prompt the only variable:
  76% -> 77% -> 100% -> 100%.

THE ONE FAILURE IS THE §138 RECONCILE-DIRECTION RULE, in its purest form:
`redefinition of struct B16_8018A758` — the agent copied its sibling's struct tag
verbatim, and that sibling had banked into the SAME TU earlier in THIS wave. Decl
ABOVE the splice => DELETE the duplicate (do not rename it). Worth noting the
mechanism: a wave can create its own reconcile work when two targets share a TU.

func_8018A808's own family swept 0/14 — its members are the per-location kind
that do not template (the settled h_seq ceiling), not a plumbing failure.
2026-08-04 12:05:32 -06:00
Drew T cbf0bce26c feat(phase-30 S35): wave 3 banks 13/13 — the flywheel paid off one wave later
Fleet 96.24 -> 96.25% fn-count / 94.0% instr / 88.4 -> 88.5% distinct.
R22 clean-fleet: 140 passed, 0 failed of 140. dedup 1910/0.

13 targets / 17,644 templatable ins. 14 agents, 2.7M tokens. Claimed 13/13;
the whole-binary gate banked 12, the 13th on reconcile (another §37/§124
SELF-axis alias — the TU declares `(void)`, the def takes an s32). Reconcile
lane 20/21 lifetime. Sweep: +21 members / 0 failed across 16 overlays.

THE FLYWHEEL, MEASURED ACROSS THREE WAVES (same models, same gate):
  wave 1  baseline prompt              15/17 claimed -> 13 banked (76%)
  wave 2  + the S33 rules              11/13         -> 10        (77%)
  wave 3  + S34 magic-grep as STEP 0   13/13         -> 13       (100%)
Multiple wave-3 agents report the cross-overlay magic-literal grep landing the
answer on the FIRST search. One found a banked twin whose own header comment
already documented it as byte-identical to the new target, so the body
transferred verbatim with only file-local type suffixes renamed. That is the
wave-2 discovery paying off one wave later (R16).

Sweep quality also differed for a reason worth keeping: 21/21 here vs 18/165 in
wave 2. Wave 2's two big families are the per-location kind I then probed and
ruled out (BUILD OK + byte diff = genuine per-member codegen, not plumbing);
wave 3's are genuinely templatable. The sweep rate is a property of the FAMILY,
not of the wave.

TOOLING: an agent left 8 scratch files (test_licm*.c) in the drafts dir and the
gate driver died on `int('full', 16)`, taking the whole gate with it. Hardened to
treat a non-conforming filename as a NAMED, COUNTED skip rather than a crash
(R32) — a drafts dir is agent-writable by design, so it must not be trusted to
contain only deliverables.
2026-08-04 09:42:58 -06:00
Drew T 7a4abddbfa feat(phase-30 S34): wave 2 — 10 heads + 18 members; the search order had a cross-overlay hole
Fleet 96.24% fn-count / 93.9 -> 94.0% instr / 88.4% distinct. R22 clean-fleet:
140 passed, 0 failed of 140. dedup 1910/0.

WAVE 2: 13 targets / 37,943 templatable ins. 19 agents, 4.5M tokens. Claimed 11
MATCH; the whole-binary gate banked 9, +1 on reconcile (func_8017E5D0 via the
§37/§124 DEFINITION-side alias — the TU declares it `(void)`, the byte-true def
takes a pointer). Reconcile lane now 19/20 lifetime. 18 members swept.

THE FINDING (an agent caught a hole in our own procedure). §136c's search order
— engine_core.h near-twin -> same-TU banked sibling -> the .s — is entirely
SAME-TU or SHARED-HEADER scoped, so no step can reach a banked twin in a
DIFFERENT overlay's TU. But the large template classes live cross-overlay by
construction. func_80188C04 (328 ins) turned out byte-identical to an
already-banked func_801833F0 in ov_SC02_028, and ONE command found it:
`grep -rn "E100000A" src/` — a magic word lifted from the target .s. The body was
then reused verbatim, only file-local suffixes renamed. Promoted to STEP 0 of
§136c, ahead of engine_core.h.

That compounds with the manifest finding this session: the family map's
`exemplar` is an IN-FAMILY pointer, so a family whose twin is banked elsewhere
looks un-cracked — and the pointer can itself name an ALREADY-BANKED instance,
hiding the family from any ranking built on it. Derive open sites from
corpus.stubs over the member list instead. Measured on this wave: ranking off the
map's exemplar gave 16,696 templatable ins; deriving from corpus.stubs gave
41,023, including a 55-ins family open in 138 overlays and a 46-ins one in 133.

HONEST ON THE SWEEP: those two big families templated 18/165. That is the known
h_seq refusal ceiling, not a new wall. One agent reported "all 10 members
distance 0" — that is NORMALIZED distance, not h_exact, which is why
dedup_propagate correctly answered reach<2. Do not read a normalized-distance
claim as an h_exact guarantee.

LEDGERED (real residual, not paperwork): func_8017F7B4 — needed its sibling's
type names AND a data asm-label alias for a u8-shaped symbol, and still refuses.
Plus func_8017C294 (DIFF close=12: 4 register/schedule permutations + a frame
where I can get the 0x138 size OR pEnd's slot at 0x108, not both) and
func_801898E4.
2026-08-04 07:14:28 -06:00
Drew T 138e21c7d4 feat(phase-30 S33e): both gate-refused drafts reconciled — the lane is 18/18 lifetime
Fleet 96.23 -> 96.24% fn-count / 93.9% instr / 88.3 -> 88.4% distinct.
R22 clean-fleet: 140 passed, 0 failed of 140. dedup 1910/0.

func_8017D318 (184 ins) + func_80181EE0 (198 ins) both banked, + 6 members swept
(6 per-overlay variants failed — ledger material, not a lever).

THE RECONCILE DIRECTION DEPENDS ON WHERE THE TU'S DECL IS, and picking wrong
CREATES the next error (-> cookbook §138):
 - decl ABOVE the splice point  -> DELETE the draft's duplicate (§100).
   func_8017D318: the TU defines MATRIX_/SVECTOR_8017C290, D_801EA8C0 AND a
   `struct PW8017C290` tag above it; I missed the tag on the first pass, so it
   took two rounds.
 - decl BELOW the splice point  -> KEEP a decl in the TU's EXACT shape and cast
   at the use (§17a-1 D2). func_80181EE0: I removed its decl assuming the TU
   provided one; the TU's `extern int func_80143C74(short *, int);` is at L5082,
   ~180 lines BELOW the splice at 4901, so the identifier went undeclared.
Grep the TU for the symbol and compare line numbers with the stub line first.

MY OWN §136a VIOLATION, recorded: the blocker-capture filtered the build log for
`error|conflicting|undefined reference` and reported "NO COMPILE ERROR" on a
build that was failing with `redefinition of struct PW8017C290` and
`'func_80143C74' undeclared` — neither phrase matched. A narrow keyword filter is
exactly how a real error goes unseen, which is the thing §136a exists to say.
Widened to keep any line naming a source position.
2026-08-04 03:34:51 -06:00
Drew T 0bdc7f44a0 feat(phase-30 S33d): Sonnet wave — 13 heads + 65 members banked (78 instances)
Fleet 96.21 -> 96.23% fn-count / 93.8 -> 93.9% instr / 88.0 -> 88.3% distinct
(+73 unique fns). R22 clean-fleet: 140 passed, 0 failed of 140. dedup 1910/0.

THE WAVE. Re-ran S10's 17 unbanked targets (26,227 templatable ins) at LOW
concurrency in two batches of ~9 — S10's finding was that 14 of 30 agents were
SERVER-throttled, i.e. the limiter is capacity, not capability. Targets
re-derived against corpus.stubs first (R35): all 17 still live, paths verified.
25 agents, 6.87M tokens, ~2.8h. Claimed 15 MATCH; the whole-binary gate — the
sole arbiter (G3/P9) — banked 13, then family_sweep propagated 65 members across
38 overlays.

HEADLINE: func_8017D174 (793 ins) — the largest single crack of this phase. Its
agent closed two compiler-internal residuals jointly: a §137 allocno-priority tie
between &g.sz0/&g.sz1 (R=7, L=607 vs 606 -> 230/231) that spilled the wrong one
and cost a load-delay nop in BOTH switch arms, and a sched2 rotation in the
outer-loop head block that survived 470+ statement orderings. Fix was four
zero-byte asms: two `"=r"/"0"` re-ties splitting wz's live range, plus two
volatile sliders placed in a DIFFERENT basic block so they lift the live-length
count without perturbing the head schedule.

THE 4 NON-BANKS SPLIT CLEANLY (§136b — none is a wall on one attempt):
 - func_8017E2EC (close=20) and func_80186E24 (close=187): honest DIFF verdicts,
   real codegen residuals, ledger material.
 - func_8017D318 and func_80181EE0: claimed MATCH, gate refused -> the known
   match_one->gate gap, which is DECLARATION plumbing (agents cannot run the
   gate, so a TU-level conflict is invisible to them). Routed to the reconcile
   lane, not retired.

AGENT-REPORTED INDEX GAPS worth acting on (the flywheel closing on itself):
 - no symptom key for "schedule rotation at a loop-head block that NO statement
   permutation reaches" — the index's nearest line points at §76 regalloc, and
   the decisive doc was gcc-2.7.2-map/sched.md, which no scheduling symptom
   cross-references.
 - §137 is written as a two-compile arithmetic on ONE contender pair; the real
   fix here was an N-zero-byte-insn budget that ties only for N in {1,3,4} and
   splits the WRONG way for N=2, so a naive "add one slider, add another" walk
   silently regresses.
 - no key for "gcc hoists a loop-invariant SYMBOL_REF base out of a loop the
   target keeps in the `sym(reg)` macro form" (~105 of func_80186E24's 187).
2026-08-04 03:27:54 -06:00
Drew T b497ee1649 feat(phase-30 S33c): PROPAGATE head COMPLETE — func_801466F0 x137 took three fixes + a type-lift
Fleet 96.17 -> 96.21% fn-count / 93.8% instr / 88.0% distinct; dedup 1909 -> 1910
groups, 0 failed, C1 241216/241216. R22 clean-fleet: 140 passed, 0 failed of 140.

The head is now 5/5 classes, 18,545 templatable ins, all banked this session from
a standing start of 0.

func_801466F0 had sat since S6b behind THREE separate blockers, each of which
looked sufficient on its own to explain the failure:
 1. Its definition is under a §37/§73 ASM-LABEL ALIAS (`aF801466F0` in C, bound to
    the real symbol by `__asm__`), and dedup_propagate.find_site anchored its head
    regex on the literal `func_<ADDR>` — structurally blind to the form, returning
    None, which every caller reads as "not matched". Now reuses
    family_remap._alias_decl_for rather than growing a second matcher (R33).
 2. That matcher was itself blind to the WRAPPED (multi-line) declaration — the
    §134 shape, third tool. Fixed by matching over the joined text and mapping the
    offset back to the decl's FIRST line (extract_unit carries from there).
    Regression control: the single-line form still resolves. Fleet census after:
    2,768 of 2,768 alias sites resolve, 0 missed.
 3. Its record type was a draft-local typedef, so the body failed
    compiles_standalone. Lifted Rec801466F0 to src/shared/engine_types.h INSIDE
    the include guard (the SESSION-19 double-include note) and switched both the
    macro and the exemplar to it — byte-neutral, gate-proven.

Probed on ONE member before the fleet run: byte-identical 9052dc0e first try.

MEASURED, NOT INHERITED (R37): the S6b note frames the alias-regex gap as a CLASS
of missed work. It is ONE function — 91 distinct alias decls fleet-wide, the
per-line matcher resolved 90. Recording it so a future session does not scope a
phase against a class that does not exist.

cookbook §138 extended with the alias-form tool boundary and the three-blocker
story; index regenerated.
2026-08-04 00:44:33 -06:00
Drew T 4f6b0e8de1 feat(phase-30 S33b): PROPAGATE head 82% banked — 15,257 of 18,545 ins, four levers
Fleet 96.10 -> 96.17% fn-count / 93.7 -> 93.8% instr / 88.0% distinct.
dedup 1908 -> 1909 groups, 0 failed, C1 241078/241078.
R22 clean-fleet: 140 passed, 0 failed of 140.

  func_80147364  4,110  x137  definition-side asm-label alias
  func_8016BA68  3,886  x134  dedup_extend + the MIRROR decl relax
  func_8012F274  3,973  x136  hand-authored macro, source overlay excluded
  func_8012A598  3,288  x138  cdecl._mask backscan fix + shared-type switch
  func_801466F0  3,288  OPEN  the wrapped-alias regex — measured as ONE function

THREE DISTINCT CARRY VARIANTS were hiding in one "CARRY-FIXABLE" bucket, and
only one is a tool bug (-> cookbook §138):
  - a MULTI-LINE comment halts the preamble backscan -> fix the tool (cdecl._mask)
  - a draft-local `struct Tag {…}` -> switch the exemplar to the SHARED type
  - a file-scope `static inline` helper -> hand-author, EXCLUDE the source overlay
The third is the sneakiest: gcc-2.7.2 accepts implicit function declarations, so
the extracted body PASSED compiles_standalone with the helper undeclared and the
miss surfaced only as a whole-binary byte DIFF 137 gates later. Instantiating
that macro in the SOURCE overlay is a duplicate definition (its file-scope helper
is still there), so the shape is `--source-overlay X --binaries <all-but-X>`;
`--binaries` alone removes the source from the scan pool and errors.

TOOL BOUNDARY: once a group's members are DEFINE_func_*() sites, dedup_propagate
cannot extend it (find_site never returns a `def`). dedup_extend is the tool for
an already-macro-ized group — and `dedup_extend --check-only` across ordinary
overlays is a cheap fleet-wide wiring census (measured: exactly 1 group per
overlay, so no hidden backlog).

MEASURED, NOT INHERITED (R37): the S6b note frames _alias_decl_for's single-line
regex as a CLASS of missed work. It is not — 91 asm-label alias decls exist
fleet-wide, the regex matches 90, and the single miss is func_801466F0. Worth
3,288 ins, but a one-function fix. Correcting the expectation so a future session
does not scope against it.
2026-08-04 00:30:56 -06:00
Drew T 356373efab fix(phase-30 S33b): the PAIR rule — my 42-decl relax did NOT unblock the lane; the mirror form did
HONEST CORRECTION to commit:1382. That commit's message implies the 42 `(void)`
relaxes unblocked the PROPAGATE remainder. They did NOT: the re-run banked 0/1
in all 134 overlays with the same error, because DEFINE_func_8016BA68 declares
func_80146C3C `(u8*)` — the MIRROR of the EXTEND-lane pair — and my relax only
touched the `(void)` direction.

Root cause is the R37 shape a third time: I bucketed by SYMBOL and stopped. The
lever is set by the (macro-shape, TU-shape) PAIR, and the same symbol conflicts
in BOTH directions across this fleet. One awk over the macro I was ACTUALLY
fixing — which I ran for the EXTEND macros and not for this one — shows the pair
before a 134-build run. §138 amended with the PAIR rule; correction logged in
CURRENT_PHASE.md rather than rewritten out of history.

The 42-decl relax still stands: byte-neutral, R22 140/140, removes a real
conflict class. It just did not do what I predicted.

THIS commit relaxes the 2 remaining `(u8*)` decls (uses are cast; `()` is
compatible with the (void)/()/(u8*) forms the fleet carries and no decl of this
symbol has a default-promotion param). R22 clean-fleet: 140 passed, 0 failed.

ALSO: tools/overlay_src_split.py `_split_macro_body` — the §134 sweep's one real
target, fixed. It carried the identical single-line-only comment test, and it
decides where a macro body's file-scope externs END, so a multi-line comment
truncated the extern set. SIZED FIRST: 38 live lines in engine_core.h macro
bodies hit it today. Now decides on cdecl._mask (one oracle, R33) with the
length-preservation invariant asserted (R32). Proven both directions by a
control: pre-fix it stopped at `/* multi` carrying 1 of 2 externs and treated the
comment as the definition head; post-fix both externs carry and the def head is
correct. Not in the gate path (only o0_subsplit + jr_isolate_all import it).
2026-08-04 00:16:23 -06:00
Drew T 3daa647bb3 docs(phase-30 S11): cookbook §138 + SESSION-33 checkpoint
§138 — "the propagation lanes: a gate refusal is a DECLARATION, and which lever
you owe depends on blast radius". The durable content of this session:
- the 4-lever triage table ranked by blast radius, and the rule to grep the
  fleet's decl shapes BEFORE relaxing to `()` (illegal only against a
  default-promotion param — 4,020 decls measured, 8 of 36 banked for one token)
- `volatile` in the host TU is a SCHEDULING BARRIER that masquerades as a codegen
  wall; the tell is a positional shift with a `nop` at a delay slot, and the
  h_exact contract is confirmed/refuted in ONE command with no build
- the DEFINITION-side asm-label alias as the only zero-radius escape when the
  fleet canon disagrees on a promoting param (1,725 in-tree precedents)
- rank a lane by measured concentration, not class count (5 of 45 classes carried
  89%), and `--recover` is not a retry (16/16 on drafts, 4/138 on a propagation)
- §134 multi-line blindness recurring in a second tool; decide on `cdecl._mask`
- the waiter rule CORRECTED: `pgrep -x make` is wrong for a campaign of
  sequential makes, `pgrep -f` self-matches, `nohup … &` signals the wrapper

Checkpoint refreshed and placed below the task checklist (fresh-session safe):
fleet 96.10 / 93.7 / 88.0, dedup 1908/0, R22 140/140 four times this session,
nothing running, lock free. Three named next items, none yet diagnosed against a
build — the PROPAGATE head remainder (11,147 ins), the 41-class tail (2,316),
and EXTEND's last 5 (the whale needs the §38 -O0 route; dedup_extend should
refuse-and-name that class per R32).
2026-08-03 23:55:53 -06:00
Drew T 62042f65ca fix(phase-30 S11): multi-line-comment blindness in dedup_propagate; func_8012A598 x138
Fleet 96.06 -> 96.10% fn-count / 93.7% instr / 88.0% distinct; dedup 1907 -> 1908
groups, 0 failed, C1 240807/240807. R22 clean-fleet: 140 passed, 0 failed of 140.

func_8012A598 (3,288 templatable ins) was being written off as CARRY-FIXABLE.
It took TWO fixes; either alone leaves it skipped.

1. TOOL (R33) — find_site's preamble backscan. The SESSION-18 fix handled blank,
   `//`, and SINGLE-LINE `/* … */` lines, but a MULTI-LINE block comment still
   halted the walk: its middle lines start with `*` and its last line ends `*/`
   without starting `/*`. So the three externs above the body were dropped and
   the body then failed compiles_standalone on now-undeclared data. This is the
   §134 multi-line-blindness class — S6b fixed the identical shape three times in
   family_remap (D1/D2/D5) and this copy was never reached.

   Fixed by deciding skippability on `cdecl._mask` — the project's ONE masking
   oracle — instead of on line syntax: it subsumes every comment form at once and
   cannot be fooled by a `/*` inside a string, with an R32 assertion on the
   length-preservation invariant it rests on. Strictly monotone (it can only
   carry MORE preamble), and dedup_propagate is a byte-gate feeder, so a bug here
   can fail to bank but never falsely bank.

2. EXEMPLAR — the body also declared a draft-local `struct BigCopy164` tag, which
   the tool refuses by design (two macros defining one tag would redefine it in a
   single TU). The shared `struct BigCopy` (engine_types.h L312) is the identical
   layout and is ALREADY used this exact way at engine_core.h:16158, so switching
   the exemplar to it is byte-neutral and drops the alias too.

Probed on ONE member before scaling (R37/S29): byte-identical 9052dc0e first try;
then 138 overlays byte-identical.

PROPAGATE head accounting after this: 7,398 of 18,545 ins banked (func_80147364
4,110 + func_8012A598 3,288). Still open, each with a NAMED cause and none yet
diagnosed against a build: func_8012f274 (3,973, dropped), func_8016ba68 (3,886,
4/138), func_801466f0 (3,288, the S6b D4 wrapped-alias gap).
2026-08-03 23:53:50 -06:00