Commit Graph

433 Commits

Author SHA1 Message Date
Drew T bfc0f43c92 docs(phase-31): S77 CLOSE — 30 banked, main 57.1%->59.4%, ten instrument defects, R61
S77w wave: 30 workflows, 30/30 reported, 9 banked, 21 NEAR, 0 errors.
R22 clean-fleet 213/213 (fourth run this session). Cookbook §477-§483.
2026-09-03 20:52:15 -06:00
Drew T 9d15598b5a docs(phase-31): S77 FINAL checkpoint — 21 banked, self_decl_tu closed, the permuter yield curve, eight instrument defects 2026-09-03 19:51:02 -06:00
Drew T b5751c7c1e docs(phase-31): S77 checkpoint — 17 banked, the self_decl_tu lane closed, six instrument defects
T11 4/7, T12 13 banked of a 34-draft pool, T13 R22 213/213 twice (a green
baseline before the overlay banks and again after all 17).

main REAL 895 -> 899, stubs 46 -> 42. Fleet stubs 82 -> 65, distinct-code
99.3% -> 99.4%, MAIN game-code 57.1% -> 57.3%.
2026-09-03 19:25:02 -06:00
Drew T ce79a3e432 docs(cookbook): §449 — four compiler dials from the S75 redraft wave, two byte-gate confirmed
Provenance stated per row (CONFIRMED = banked through the whole-binary gate;
CLAIMED = the agent's own measurement on a function that did not bank), because
one of these came from a function that was adversarially upheld and then FAILED
the real gate.

A. reg_n_sets is a one-line scheduling dial (CONFIRMED, func_80180ABC 257 ins).
   sched1 schedules backward; a pseudo set exactly once gets the birthing_insn_p
   launch boost (priority = 7f000001 in cc1 -dS), which drags its load LATE.
   Splitting the RMW as 't = t + 1; *p = t;' makes reg_n_sets 2, suppresses the
   boost, and floats the load to the block head -- the block-local dual of §350's
   shared temp, WITHOUT the global-allocno penalty that costs the in-place addiu.
   Companions: 180 legal statement permutations all scored identically while one
   cc1 -dS dump named the cause (diagnose, don't permute); a pin-free fix for
   paired-register inversion; and gcc frame slot order is NOT declaration order
   (BLKmode aggregates go in order at expand_decl, an addressable scalar is
   forced to the stack later -- declare 's32 x[2]' to place a slot between two
   aggregates).

B. A single-set local's VALUE is visible at a switch join and erases a
   zero-extension (CONFIRMED, func_801806F8 241 ins). combine.c:10035 lets
   get_last_value bypass the label_tick guard when reg_n_sets == 1, so all seven
   narrowing spellings emit nothing. Diagnostic: a visible extension in the
   target means the variable has MORE THAN ONE SET in the original source.
   Verified against a matched sibling: andi is the multi-set zero-extend and
   sll;srl is NEVER reachable from a single expression.

C. CORRECTION to §439 -- the sll 16; srl 16 pair lands AFTER the jal, not before
   it (sched1 sinks the ashift past the call), and it works even for a KNOWN
   CONSTANT, because the call-split defeats folding structurally rather than by
   hiding the value.

D. An offline jtbl-rodata placement audit (CLAIMED, func_800CB00C -- did not
   bank, which is the point: both matchers compare .text only, so a jtbl
   function's MATCH says nothing about its table).
2026-09-03 00:30:55 -06:00
Drew T c05ea15cbe feat(tools): asm_in_c.py — 154 game functions are assembly wearing a .c extension
A .c file in src/ looks decompiled. 199 functions are not: they are the target
assembly pasted into a C string literal (§265), byte-identical BY CONSTRUCTION
and completely unexplained. 45 are PsyQ/CRT routines where that is defensible;
154 are GAME CODE, 171 of the 199 in main, the largest being SaveLoadRoutine at
1,165 instructions.

They were invisible because progress.py's classify() matched INCLUDE_ASM,
INCLUDE_RODATA and C definitions, and a file-scope __asm__ block is none of
those -- so each landed in NO bucket, either swallowed by a surrounding
construct or surfacing as the single `UNPLACED (parse hole)` line the tool has
been printing all along.

progress.py gains a VERBATIM __asm__ bodies line: counted byte-identical (it is,
by construction) but NEVER as REAL. main's headline moves 45.88% -> 42.15%.
Nothing regressed and no work was lost -- the denominator was missing 173
functions that are real remaining work.

THE COUNTING LESSON IS THE REUSABLE PART. Counting these by hand went
116 -> 112 -> 108 -> 178 -> 199 across five attempts in one session, every
intermediate number reported confidently. All five errors were one shape, a
pattern narrower than the claim it supported:
  * the sources use BOTH ".ent\tNAME\n" and ".ent NAME\n" -- anchoring on either
    silently drops every instance of the other;
  * a bare ".ent\t" fragment yields a phantom function literally named `t`, six
    times, which is the only reason the error was noticed;
  * __asm__ appears in 3,182 of 4,224 sources, almost all the §3a barrier, so
    counting files or counting __asm__ measures nothing;
  * `.globl NAME` + `NAME:` proves EXPORT, not CODE -- the first real run
    reported jtbl_80072ED4/EEC/F0C/F24 as four "functions";
  * a hand-written SDK name list reported 170 game functions because it did not
    know VectorNormalSS / SquareRoot12 / OuterProduct12 are libgte.

So the tool does not trust one regex: THREE independent detectors that must
agree with disagreement reported as a defect (R34 -- that is what caught the
jump tables); SDK-ness DERIVED from the 14 shipped PsyQ archives via nm (2,227
symbols) rather than a list (R33); coverage asserted so a definition-shaped
block no detector claims fails loudly (R32/R43); and --selftest carrying a
known-true case of every spelling plus the phantom `t` and the jtbl regression.

Cookbook §448, SETUP row. Law: when a count comes from a text pattern, the
pattern has a denominator too -- validate it against one known-true case of
every FORM the corpus contains before quoting the number.
2026-09-03 00:01:11 -06:00
Drew T cf7f837231 fix(gate): main's TABLE REJECT verdict was unreachable — SaveLoadRoutine is a CARVE, not plumbing
SaveLoadRoutine (1,165 ins) is the largest open function in the project, 9.2%
of all remaining work, and has been carried as the §434 WALL. Gated alone
through gate_main, with the §376/§378 chain already applied, the verdict layer
says: "SaveLoadRoutine is BYTE-IDENTICAL; all 3989 differing bytes are
ELSEWHERE". The body has been correct the whole time.

What rejects it is where its FOUR jump tables (jtbl_80072ED4/EEC/F0C/F24) land:

    .data/.rodata (jump tables)  3,787 bytes   94.9%
    .text (perturbed code)         202 bytes    5.1%

and the built image is 4 bytes SHORTER than retail (413,692 vs 413,696) --
§446's first diagnostic, firing on a function §446 was not written about.

main_diff_locate.classify() already HAD a TABLE REJECT class, added in S72 under
a docstring reading "THE THIRD CLASS EXISTS BECAUSE THE FIRST TWO MISLABELLED
IT". It could not fire here for two independent reasons:

  * it keyed on the literal string `(.rodata)`, but main's section_order is
    [.rodata, .text, .data, .bss] -- its rodata sits BELOW .text and its jump
    tables live in `.data` objects, so TABLE REJECT was UNREACHABLE BY
    CONSTRUCTION on the binary with the most jump-table functions left. A
    section NAME is not a section ROLE.
  * it demanded purity (ro == outside), so 5% perturbed code defeated an
    all-or-nothing test and dropped the verdict through to PLUMBING REJECT --
    whose advice (fix_arity_callers -> cast_self_callers) addresses the 5% and
    cannot touch the 95% that is data. That chain was run on this function
    TWICE today and fixed nothing, exactly as the evidence predicts.

Now: table bytes counted in (.data) OR (.rodata), and the test is DOMINANCE
(>=60%) rather than purity, reporting the split and naming which part is the
carve problem and which the declaration problem.

Negative control over all five pre-existing verdict shapes (pure BODY, pure
PLUMBING, pure TABLE, MIXED, NOT FOUND) plus the S75 shape: 5 of 6 verdicts
UNCHANGED, only the SaveLoadRoutine shape flips PLUMBING REJECT -> TABLE
REJECT (MIXED).

Cookbook §447. The law: a class that cannot fire is worse than a class that does
not exist -- it converts "I don't know" into confident, specific, wrong advice.
When a verdict names a subsystem, check that subsystem owns the MAJORITY OF THE
BYTES before acting on it.
2026-09-02 23:05:27 -06:00
Drew T 9f8242d63c fix(progress): the #else half of a NON_MATCHING block is LIVE — REAL was undercounting by 7
classify() consumed everything from '#ifdef NON_MATCHING' through '#endif', swallowing
the #else half. But banking replaces the #else INCLUDE_ASM with the real body and leaves
the old attempt in the dead half — so every function banked that way landed in NO bucket:
not real, not a stub, invisible in both numerator and denominator.

Measured: CdReadStateMachine, CdReadSectorReadyCB and StreamLoadStateMachine are
byte-identical in the shipped build and counted as zero. REAL 873 -> 880, matchable
1911 -> 1918 (seven functions fleet-wide, not the three I first checked).

Now consumes only the DEAD half, then decides from the LIVE half: an INCLUDE_ASM there
still buckets as NON_MATCHING (accounting unchanged), anything else rewinds and is
classified normally.

THIRD coverage defect of this exact shape in this one function — the K&R-definition case
(~190k instructions erased) and the '#if 0' case are both documented in its own comments,
which is what pointed me at it. A scanner that walks preprocessor structure needs a test
per branch, not per directive.

Found by the S73 documentation audit, which I had written off as producing only doc typos.
2026-09-02 17:14:32 -06:00
Drew T 2c1d21bb9d docs(phase-31): S73 CLOSE — R22 213/213, 23 main banked this session, main 56.5%, frontier 124
The jump-table class on main is resolved: 25 -> 2, and both survivors are the §434 frame
pair, provably unmatchable as separate C functions (resegmentation, not drafting).

Wave S73m_1 banked 9 of 9 drafts (2,413 ins). Cookbook entries written this morning
cracked functions this afternoon; two of mine were refuted by later MATCHes and rewritten.
2026-09-02 16:34:13 -06:00
Drew T 09886be66b docs(phase-31): S72 FINAL — R22 213/213, 14 main banked, main 52.6%, frontier 133
The carve + the src/800.c split at the original TU boundaries. 7 of the 14 banks were
span B/C — impossible before the split. Next session starts with 11 functions /
4,479 instructions that are now merely undrafted rather than unbankable.
2026-09-02 13:54:16 -06:00
Drew T 8e8521da22 fix+docs: make every consumer aware of main's new TU layout (R36)
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').
2026-09-02 13:48:00 -06:00
Drew T f0148e6822 docs(phase-31): S72 CLOSE — R22 green 213/213, 7 main banked, main past 51.8%, frontier 140
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.
2026-09-02 12:58:44 -06:00
Drew T 9631949339 docs(phase-31): S71 CLOSE — R22 green 213/213, frontier 147, 63 banked, main past 50% 2026-09-02 11:15:21 -06:00
Drew T 6716100e57 docs: regenerated progress + backlog from the R22-green fleet (853/1919 = 44.45%, frontier 187) 2026-09-02 01:51:14 -06:00
Drew T 02e1b3a7e6 feat(waves): every pack now carries that function's own PAST-ATTEMPT history
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.
2026-09-02 01:11:52 -06:00
Drew T 1632c6adec docs(phase-31): S70 FINAL-4 — 145 banked (355->210), 115/118 wave MATCH, 5 card defects (3 fixed), cookbook 1074 2026-09-01 23:40:28 -06:00
Drew T 64dc914afe chore(report): refresh digests after the §332b banks 2026-09-01 20:46:09 -06:00
Drew T 9b57eaa2f0 chore(report): refresh digests after the S70 twin banks 2026-09-01 17:48:01 -06:00
Drew T 2fbf93d2e0 chore(report): refresh backlog + fleet progress after the S70 banks 2026-09-01 17:30:02 -06:00
Drew T 49f27f2293 chore(report): refresh backlog + fleet progress after the S69 banks 2026-09-01 15:45:46 -06:00
Drew T 4cf531beea docs(cookbook): §399 — four levers from the final S69 round, harvested late
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.
2026-09-01 15:18:40 -06:00
Drew T f8e522ea0d docs(cookbook): §378b — the four decl-blocker variants, and the two places §378 does NOT apply
Correcting my own guidance from earlier today. §378 gave the self-caller chain;
three more variants appeared within hours and two of them BREAK the chain.

Variant 3 (NEW, byte-proven ov_SC04_018/func_8017F35C, banked): conflicting
RETURN type on a decl that is ALREADY no-proto, where the symbol is
ADDRESS-TAKEN rather than called. --any-proto has nothing to relax and
cast_self_callers has no call site to cast; --sync-decls ALONE fixes it, and is
safe precisely because an address-taken site has no arguments to convert.

Variant 4 (REFUTATION of what I wrote in the playbook this morning): "run the
same chain on the callee the diagnostic names" is wrong at scale. Applied to
func_8012AD44 in ov_SC07_000 it no-protoed 60 caller decls and the binary went
RED (265b24bb vs 9dbe4241); reverted via journal. The self case is safe because
step 2 casts the call sites so the decl change cannot alter argument conversion;
for a callee, cast_self_callers correctly refuses and the decl change runs
unprotected. It banked main/func_80021D38 only because that callee had ONE decl,
not sixty.

Rule added: never --any-proto a symbol whose call sites you are not also casting;
count the sites first. The chain is a DECISION TABLE, not a sequence to run
blindly.
2026-09-01 13:34:21 -06:00
Drew T 1dd15eda32 feat(triage): the triage ladder — built, wired, and acceptance-green
tools/triage_ladder.py — the zero-token pre-agent pass, split PRE (target-side:
BANKED/WALL-332/PARKED, no build) from POST (residual_rules_b, needs a draft).
--escalate refuses a walled or banked target; --acceptance is the R39/R32 harness.
Refuses on a non-quiescent tree: a merging gate makes the stub oracle wrong in
both directions (measured, ov_SC01_004:func_8017EB30).

Acceptance, on the whole corpus: false-skip 0/1367 open stubs, recall 426/426
matched, wall tier fires on exactly the 10 enumerated walls (0 extra, 0 missing).
The first wall control asked for evidence that CANNOT exist — it scanned banked
functions' .s, which splat never writes — and printed '0 scanned / 0 tripped',
indistinguishable from a pass. The R32 empty-denominator assertion caught it on
its first run; replaced with a two-sided sweep over all open stubs.

tools/cast_self_callers.py — the §378 lever + --sync-decls for the narrow-param
case C89 forbids no-proto from reaching (§378a).

Wiring: wave_args drops walled/parked targets at draw time via pre_classify (one
implementation, R33); escalate_fable.js refuses any target without triage:'DRAFT'.

Tool fixes found by measurement:
* fix_arity_callers was blind to main entirely (globbed src/main/main*.c; main is
  src/*.c) — reported success over an empty file set through three gates. Now
  refuses when --binary selects no files.
* parallel_gate records each worker's 'failed by class' line (was truncated out of
  the 200-char tail); gater_lane retries in-tree ONLY on the diagnostic-free
  blind-worktree signature — S69 ran 22 serial retries against real cc1 errors.

docs: cookbook §376/§377/§378 (index 1033), SETUP.md, wave-playbook §4b.
2026-08-31 23:53:50 -06:00
Drew T 0816ea0576 chore: refresh the backlog + fleet digests after the S68 banks 2026-08-31 17:27:15 -06:00
Drew T ed53a68f18 feat(p31 s68): deferred propagation done honestly (2 banked) + seed_ref was offering DEAD TEXT
The S67 FINAL-3 OPEN item, plus the two defects found while doing it.

* fix(dedup_propagate): the tool could not run AT ALL. S67's -j patch wrote
  `os.environ` at module level in the one module that imports `os as _os`, so
  every invocation died with NameError before doing any work. Propagation was
  not deferred, it was impossible. Import-checked the other 7 -j-patched tools.

* propagation, honestly scoped: the real closable set is 11, not 32, derived two
  independent ways that agree (seed_ref exact+same_addr, and a direct corpus
  derivation). The 3,161-entry --auto-from plan over 53 overlays is dedup
  hygiene over already-matched code and closes almost no open stub.
  Applied: 2 banked byte-green (ov_SC04_018 func_80181270, func_80182AF8);
  3 gate-refused and cleanly reverted; 6 blocked with named blockers
  (3 CARRY-FIXABLE, 3 func_80144B9C not-inline-def -> needs the o0 whale carve).
  R22 clean fleet: extract 212/212, check 213 passed 0 failed of 213, rc 0/0/0.
  Frontier 453 -> 451.

* fix(seed_ref): REFUSE targets in LINKED subsegs. The playbook calls this tool
  "the fleet-wide answer" and it reported 82 open stubs with a banked twin --
  43 of them main stubs whose TUs the linker script never references. Any C
  written there compiles, links and leaves the SHA1 green WHETHER OR NOT IT IS
  CORRECT, so a mechanical twin lane fed from that list could have minted up to
  43 gate-green FALSE matches the byte gate cannot see. draw_waves has refused
  these since S66; this oracle did not. The refusal is counted and printed, not
  silent. NC: guarded 39 subset of raw 82, all 43 dropped are main, the non-main
  population is identical.

* wave drawn: .run/S68o1 (24 opus 187-770 ins) + .run/S68m1 (30 main), cards +
  packs + wave_args asserted, queue of 53. Drafting opened at concurrency 5.
2026-08-31 15:59:01 -06:00
Drew T 34da91b45e docs(p31 s67): harvest §339-§345 from the 30-workflow streaming burst
Seven sections from 30 single-function opus workflows on 187-297 instruction targets (30/30 MATCH):
 §339 a 2-case switch OMITS gcc's low-bound range test (stmt.c emit_case_nodes) — so slti/bnez
      between two beqs is a COUNT TELL that a case node is missing from your draft
 §340 §194-K corollary: a 'scheduler' residual can be sched.c's ALIAS ORACLE inventing a false
      true-dependence; source order picks the edge's DIRECTION, so reverse it into an anti-dep
      rather than fighting it (10->0, zero bytes; 3 alternatives refuted with reasons)
 §341 an HImode store temp reweights a sched2 tie no statement order can reach
 §342 NEW LAW: a twin's  param cast in a local is NOT byte-neutral when a later param also
      needs a callee-saved reg — and the §333 converse does NOT hold (gcc may already pad the gap)
 §343 decl_prior's fleet MAJORITY can be wrong about the true signature — read the RIVALS.
      Measured: void(s32) x1374 vs the truth s32(s32) x163. The tool is honest, the corpus is wrong.
 §344 raise a biv's global_alloc priority with a zero-byte REFERENCE; a register pin kills LSR
 §345 volatile STORE evicts the MEM from cse and keeps sh; volatile LOAD blocks combine and
      degrades lh into lhu+sll+sra — the qualifier is not symmetric

Also: seed_ref validated on a live A/B. The same 187-ins body cost 102,193 tokens / 476 s in
ov_SC03_107 when the card said 'no banked twin', and 72,077 tokens / 135 s in ov_SC07_006 once the
card carried the twin — 30% fewer tokens, 3.5x faster. A second instance (func_8017F62C) went
63,595 vs 118,485 tokens. others_open=137 on that one exemplar, so it compounds.
2026-08-31 14:14:26 -06:00
Drew T bac7537564 fix(p31 s67): repair ov_SC04_018 — dedup_propagate deleted a decl layer the surviving bodies needed
R22 caught it: 212/213 after the S67-cc1 gate run. `ov_SC04_018` was RED.

ROOT CAUSE (from the diff, not inferred). Commit commit:3354's propagation replaced three bodies in
`ov_SC04_018_jr_80135D20.c` with DEFINE_func_*() instantiations and deleted the 981 lines they
occupied — INCLUDING the TU's file-scope declaration layer, which the two surviving non-deduped
bodies still referenced. A duplicate copy of those decls survived at line 225, BELOW the function
that uses them at line 42, so C89 ordering made it fatal (`D_8018D7A4' undeclared).

THE STRUCTURAL GAP: gate_stage byte-gates the SOURCE binary, then propagation writes to N OTHER
binaries and nothing re-verifies them. "fleet 99.2%" in the commit subject is a metric, not a gate.
This is the blind spot R50 exists for, and only the periodic whole-fleet R22 could see it.

REPAIR: restored src/ov_SC04_018 to commit:3354^, re-extracted (banking had pruned the .s stubs the
restored INCLUDE_ASM lines need), rebuilt rc=0 at the locked SHA fe9b413f. dedup-check clean
(2193 validated, 0 failed, C1 255302/255302). Cost: the 2 banks in that binary.

NEW tools/restore_dropped_decls.py — compiler-driven recovery for this failure mode: build, read
which identifiers cc1 calls undeclared, look each one up in the pre-deletion git ref, insert it
above the leading #include block, repeat. Two defects found and fixed in it while using it:
  * anchoring after "the last extern in the first 400 lines" inserts BELOW the point of use, so the
    build fails identically and the loop re-inserts forever (measured: 25 rounds, 100 dead decls).
    The only safe anchor is the top of the file.
  * a no-progress guard now REFUSES when a round asks for what the last round already inserted.
It also correctly refused when the failure changed class (link-level undefined references), which
is how the wider damage was found rather than papered over.

NOT a defect of the S67 §8d rung: scope_demote_drafts only ever writes draft dirs under .run/.

FLEET: make clean + extract-all + check-all = 213 passed, 0 failed of 213.
FRONTIER: 530 -> 526 (4 functions closed this session, measured from corpus.stubs).
2026-08-31 09:44:50 -06:00
Drew T c4380c19e4 feat(p31 s67): stranded-draft census + honest jtbl probe — the frontier's biggest class is carve plumbing
MEASURED (denominators in .run/S67_findings.md):
* 193 of the 530 open functions ALREADY have a draft on disk (1,885 wave targets seen,
  1,521 banked, 171 open-no-draft, 166 never drawn). Classified in their real TUs:
  37 MATCH / 67 NEAR / 89 CC1-FAIL.
* 159 open functions (30% of the frontier) reference a jump table; 96 are PLAN-REFUSED
  by build_carve (non-contiguous same-subseg .rodata), 75 non-main across 38 subsegs.
  Not a codegen wall and not a decl wall — carve plumbing.

NEW
* tools/strand_census.py — coverage-asserted census + rtu_match classifier + draft staging.
  Keys binary:fn (R48); classifies each pair once after merging every manifest's view.
* tools/o0_detect.py — the -O0 prologue tell extracted from match_one (which parses argv at
  import and therefore cannot be imported). match_one re-exports it; ONE definition (R33).
  Wiring it into the classifier turned md_MAIN_003 from 8 NEAR (7 of them >20) into 6 MATCH.
  Negative-controlled both directions.
* tools/scope_demote_drafts.py — §8d as an _xform-contract gate rung. NOT yet exercised.

FIXED
* jtbl_carve --probe now runs build_carve (a pure planner) and reports plan-refused. It
  previously called only island_probe, which answers a necessary-not-sufficient question —
  every blocked function probed "carveable", and S66 priced 32 of them as free on that.
* blocker_probe.macro_scope selects the LAST #define per macro name, matching cpp.
  engine_core.h has 1,037 duplicate DEFINE_func_ names and 4 with DIFFERENT bodies.

NOT VALIDATED — DO NOT SCALE
* jr_isolate_all: two real defects fixed (carried types deduped by name; header-provided
  types no longer re-emitted) but ov_SC02_000 STILL fails the byte gate after them.
  Open lead: file_scope_types carries a block without its enclosing #if guard. 20 of 35
  blocked overlays dry-run clean and that number means nothing until one round-trips.

0 functions banked this session. tools-health has ONE pre-existing cdecl defect
(1 of 74,749 declarations, func_8017EE08_p55352/struct ZnRec) — cdecl.py and its inputs
are byte-identical to HEAD, so it is not from this change.

Knowledge banked: cookbook §322/§323/§323a/§323b, decision-log pivot, accelerators #13/#14.
2026-08-31 01:46:16 -06:00
Drew T d343892b4c chore: --only-main draw mode + progress/backlog refresh after the S66 gates
draw_waves.py gains --only-main (the main lane draws main and nothing else; implies --main so the
LINKED refusal still applies). Progress/backlog regenerated: fleet 99.2% instruction-weighted,
98.1% distinct.
2026-08-31 00:00:37 -06:00
Drew T 45cf37ee02 docs: refresh progress/backlog after the S66 gates (260 fns closed, fleet 213/213) 2026-08-30 14:28:10 -06:00
Drew T d804449be5 fix(distill): carry banked=False through to the distiller and the verifier
The distill prompt asserted 'the whole-binary byte-gate ACCEPTED the final draft, so the final body is
ground truth' for EVERY target. With --with-unbanked now feeding it drafts the gate REFUSED, that
sentence would have laundered an unproven body into a byte-proven cookbook entry (R14/G3). A target
with banked=False now gets an explicit PROVENANCE WARNING telling the distiller to extract the lever
anyway (cookbook 52: a model that FAILS still distils the idiom that cracks its siblings) but to mark
every claim UNPROVEN and never assert byte-equality; the verifier is told the same so its
entry_markdown carries the label. Exercised this session: the one surviving ADDENDUM came from an
unbanked draft and is filed UNPROVEN.

Also regenerates the scoreboard after the day's banks.
2026-08-29 19:03:28 -06:00
Drew T 201c683325 docs(report): regenerate the scoreboard + backlog after t5s and the S65 recovery banks 2026-08-29 13:42:01 -06:00
Drew T 1bdd62455e docs(report): regenerate the fleet scoreboard after t5o-t5r + the 741-ins bank 2026-08-29 11:44:42 -06:00
Drew T 1856524bec docs(report): regenerate the fleet scoreboard after t5m/t5n (1,968 -> 1,741 stubs; 98.7% instr / 97.3% distinct) 2026-08-27 14:05:55 -06:00
Drew T e268956de6 docs(report): regenerate the fleet scoreboard after t5g/t5i 2026-08-27 11:31:57 -06:00
Drew T 689bbc7c2f docs(report): regenerate the fleet scoreboard after t5b-t5h + the free lane (2,310 -> 2,068 stubs; 98.6% instr / 97.1% distinct) 2026-08-27 09:43:27 -06:00
Drew T 59bb3a23f8 docs(report): regenerate the fleet scoreboard after t5a + lane G (R32 digest describes the tree again) 2026-08-26 20:26:01 -06:00
Drew T 5962bb70ed fix(api_agent): prior_draft accepts a warm-start body only when its symbols overlap the target .s (law 1c) — 22/60 T4 agents had received another overlay's same-named function; fleet ledger regenerated (2,380 stubs) (P31 S62) 2026-08-26 19:02:07 -06:00
Drew T 5382025752 chore(docs): fleet ledger + backlog regenerated after T3 (2,397 stubs, 98.5% instr, 96.8% distinct) 2026-08-26 15:57:18 -06:00
Drew T 85b7577886 chore(docs): progress.fleet.md regenerated after T1 (2,511 stubs) 2026-08-26 14:05:15 -06:00
Drew T bd37b7eb7b docs(phase-31): frontier-analysis-s61 — the post-ox finish-plan ground truth (2,520 open instances fully classed, zero unassigned; wall = 86 fns; done-denominator reconciled; engines measured per class) 2026-08-26 12:45:16 -06:00
Drew T 04e685e8dc docs(phase-31): correction — true morning fleet numbers 98.4% iw / 96.6% dc / 2,540 stubs (the earlier line quoted a stale file; --fleet was required) 2026-08-26 09:06:46 -06:00
Drew T 96847afcf0 docs(phase-31): S61 overnight close — 378+ net stubs; gen0 goal beaten (392/421 drafted, 196 banked); ox window closed 07:55; fleet regenerated 2026-08-26 09:05:05 -06:00
Drew T 75bfb04226 fix(maintenance): restore the S59 lane logic a stale second copy had reverted
.run/maintenance.sh (what runs) and tools/lanes/maintenance.sh (a pre-S59 copy) had
diverged. The 150->50 threshold tune landed on the stale copy and was then copied over
the live one, silently reverting five S59 fixes:

* the R47 shape filter (staging fell back to status=='AGREE' alone — the exact defect
  that staged 82 hopeless drafts every 45 minutes)
* the R48 (binary, fn) keying (bare-fn keys collide across overlays)
* reloc --fix MISMATCH auto-repair (measured 4/4 repaired to AGREE)
* rtu_second_chance (re-judges standalone COMPILE-FAILs against the real TU)
* fix_tu_ret_decls (the return-type half of the stale-decl wall)

Rebuilt from the S59 lineage with the 150->50 threshold and the periodic fleet R22
re-applied, both paths now byte-identical, `bash -n` clean, and the two-path hazard
documented in the header so the next edit cannot repeat it.

Also: relaunch_drafter_shell.sh 30s -> 5s ready-marker poll; regenerated backlog and
fleet progress artifacts.
2026-08-25 00:35:27 -06:00
Drew T e7ebb1cd45 docs+rules(S58): R42 commit-banked-work-immediately, R43 refuse-unsupported-input
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.
2026-08-23 12:59:59 -06:00
Drew T 34b8f772b4 feat(phase-31): wave Z closed — 127 banked, R22 213/213, fleet 96.1/91.8/97.11
Wave Z: 74/75 MATCH, 72 banked first gate, 2 recovered for zero agent tokens
(§203 address-order typedef hoist; §202 alias on a DEFINITION for the §183.3
DEF-side return wall). Sibling sweep re-scoped after --only was keyed on the
atlas gid rather than family_hseq's exemplar: 3 -> 50 banked.

Harvest: 82 gap reports -> 5 laws, 16 rejected, 30 already-covered; the
adversarial verifier killed 7 of 12 claims. §204 written (510 lines).

Tooling, all negative-controlled:
  - the S46 validity gate was off the path for waves T-Z; wired into
    build_wave_atlas where cards are born, with the PRE-DRAFT-ONLY constraint
    documented (it condemns banked work if run later)
  - wave_snapshot honors the card's `sub` (9/9 legacy byte-identical, 66/66
    split-TU recovered)
  - §204-E: decl_prior's %hi/%lo arm had never fired (jal 306->306 zero
    regressions, data 0->299)
2026-08-18 15:25:49 -06:00
Drew T c33df33297 feat(phase-31): wave Y recovery — §200 the alias is the universal declaration escape (5 drops recovered, 0 agent tokens)
Wave Y's recovery lane ran during a total API outage (two rounds of 529 Overloaded, 12 agents, 0
tokens), so the five gate drops were fixed by hand -- and the fix turned out to be ONE repeatable
move rather than five negotiations. §183's playbook negotiates with the TU's spelling; §200 declines
to share the C identifier at all, binding a private name to the same link symbol with gcc's asm
label (§37/§124). Five different refusal classes -- array-vs-scalar where reconcile_slate's own fix
had broken the match, a slate-mate's private struct, void* vs s32, and two DEF-side return conflicts
including a function whose only in-TU use takes its ADDRESS -- all five aliased, all five still
MATCH, 4 re-gated and banked.

Ordering recorded so it stays the escape hatch and not the first move: adopt the TU's spelling ->
cast at the use site -> alias. An alias is a readability debt; every one in the tree carries a
comment naming the spelling it could not use.
2026-08-18 10:48:38 -06:00
Drew T a89d7ae0af feat(phase-31): §199 wave-X harvest (7 laws) — and §189-A's inference direction is byte-refuted
13 agents, 63 gap reports: 7 CONFIRMED, 2 REJECTED, 56 already-covered. TWO of the seven correct
laws banked EARLIER THE SAME SESSION, from two independent readers -- the adversarial-verifier
design earning its cost.

§189-A (banked this morning) claimed an interloper between a split constant's lui/ori PROVES the
target wrote two source steps, because the halves are LUID-adjacent and "no statement order and no
pin can put a third constant between them". Byte-refuted four ways: the banked one-statement slice
`prim.col[1] = 0x101010;` compiles with SEVEN insns between its lui and ori; the two-step spelling
§189-A prescribes is BYTE-IDENTICAL (the fix is inert); moving an unrelated statement moves a third
constant in and out of the gap; and one separated pair is 0x88888889 -- gcc's synthesized reciprocal
magic for a `/ 0x3C`, a constant with NO source spelling, making "the target wrote two steps"
unsatisfiable. rank_for_schedule tests INSN_PRIORITY FIRST (sched.c:2395) and reaches the LUID
tie-break only at :2428, so the derivation dropped its equal-priority scope; the real separator is
the BIRTHING BOOST (birthing_insn_p, gated reg_n_sets == 1), which the split pair can never have
because try_split gives its pseudo two sets. Verified off cc1's own -dS dump, which also corrects
the submitting reader: sched1 is a BACKWARD list scheduler, so it is the LUI that sinks, not the ORI.
8 separated pairs across 5 functions in 3 binaries. §189-A's split-TIMING half survives and now
carries a correction banner.

Recovery note: this run was killed by the session usage limit with 3 verifiers outstanding;
resumeFromRunId replayed 10 cached agents and re-ran 3 for 398k tokens vs the original 1.31M.
2026-08-18 09:04:26 -06:00
Drew T 5f174cce53 feat(phase-31): §197 wave-W harvest + §198 UNKNOWN promoted to a default lever lane
HARVEST (10 agents, 68 gap reports): 4 CONFIRMED, 3 REJECTED, 41 already-covered. Yield fell from
14 because the readers were seeded with §193 AND §194 AND §195 -- three sessions of laws off the
table before they started, which is the flywheel working.

§197-A IS BANKED AS ONE ENTRY WITH ITS ATTRIBUTION FLAGGED CONTESTED. Two verifiers independently
confirmed the same phenomenon (lhu;sll 16;sra 16+K where the target has lh;sra K) and attributed it
to DIFFERENT passes -- one to cse's fold_rtx associative block with -da dumps showing the middle insn
already gone in x.i.cse, one to combine preferring the count-merge over forming lh. R34 forbids
treating agreement between disagreeing oracles as corroboration, so the observable, the tell and the
cure (a zero-byte asm re-tie; a fresh temp works with no second SET at all) are banked, and the pass
question is recorded as open. Both verifiers independently byte-refuted §136 type-form rule 9's cure:
u16 v[4] and SVECTOR v compile BYTE-IDENTICALLY in rule 9's own context. Banner added at rule 9.

§198 (in the tool's own help text): UNKNOWN was excluded from the default --levers while the wave
PROMPT told every agent "UNKNOWN does NOT mean hard -- it means the atlas could not name a lever."
The tool was silently overriding the doctrine. Measured: UNKNOWN held 607 of 1,179 in-band members,
more than every other lane combined; wave W drew 73 cards from it into 3 gate groups (24.3 drafts per
rebuild vs wave V's 7.8) for 71/71 drafted, 68 banked. Recorded cost: UNKNOWN groups are mostly
singletons, so the free sibling remap yielded ZERO where waves T/U/V got 49/34/25.

Also releases func_80185480 and func_8017EC98 from wave W's spent-card file -- their agents died on
server rate-limiting and no draft exists, so they must not be marked already-waved.
2026-08-18 02:17:23 -06:00
Drew T 0d39cd97e1 feat(phase-31): S54 wave-V harvest — cookbook §195 (14 laws) + close the internal-j blind spot in masked_diff
32 agents over wave V's 67 index_gap reports: 14 CONFIRMED, 9 REJECTED, 76 already-covered (the
third harvest this session; readers seeded with §193 AND §194 so neither could be re-derived).

THE HEADLINE IS A DEFECT IN OUR OWN VERIFIER (§195-D). masked_diff.mask_for short-circuited on the
OPCODE -- `if (word >> 26) in (2, 3): return 0` -- ahead of the reloc dispatch, so every `j` to a
LOCAL label was dropped from the comparison. The assembler resolves those itself and emits no
relocation, so there was nothing link-time about them. For a loop or switch arm, which label a `j`
targets is the difference between `break` (fall into the shared tail and execute its calls) and
`return` (skip them): byte-proven on ov_SC03_118:func_801825EC, where the banked `break;` and a
call-skipping `return;` variant differ in exactly one word (0800003e vs 08000041) and BOTH reported
MATCH. The blindness reached match_one, the permuter's MaskedScorer, family_cousins.tok and the
atlas similarity tiers at once -- nothing between a draft and the whole-binary gate could see it.
Now the 26-bit field is masked only when reloc_kind == "26" (the linker really does fill it).
R39 control: 35/35 already-banked wave-V drafts still MATCH against their snapshot .s.

Other confirmations of note: §195-A bounds §167-08 with a byte-proven false-negative class (an
argument that DIES at the call is allocated straight into $aN, so its only def is a plain load and
every use reads $aN -- there is no positive tell in either direction, only the two-arity A/B);
§195-B a CALL_INSN does not start a basic block in gcc-2.7.2, so a call-crossing temp can be a
LOCAL-alloc quantity; §195-M frame `vars` is a sequential bump-allocation, unifying §193-I's
CEIL(aggregate,8) term with §165-03/§167-06's 8x-orphan term as one frame_offset walk.
2026-08-17 21:37:23 -06:00
Drew T 6025676745 chore(phase-31): regenerate progress + family map after wave U (fleet 95.8% instr-weighted) 2026-08-17 19:18:14 -06:00