Commit Graph

133 Commits

Author SHA1 Message Date
Drew T 9a4104247d feat(phase-25): T2 — structural-family target manifest (tools/family_manifest.py)
Regroups the unmatched frontier by h_norm: 44,101 families; 2,764 multi-member / 11.1 MB.
Per family: the ov_SC01_077 drafting exemplar + INSTANCE leverage (not h_exact-reach). The
endgame decomposes into 3 levers by ov_SC01_077 membership:
  draftable 127/6.7MB (unmatched member -> draft exemplar, T5/T7)
  matched-free 156/2.3MB (matched member + unmatched siblings -> free --tier h_norm, T3)
  absent 2481/2.1MB (no member -> draft from another overlay)
-> docs/family-manifest.md (digest) + .run/family_manifest.json.
2026-07-08 09:12:55 -06:00
Drew T d7b877f12c fix(phase-25): recover_integration split-aware (§39) — per-stub asm-subdir, gate per split group
--auto silently skipped the 263-stub ov_SC01_077_after cohort: the drift-check hardcoded
the main asm subdir and gate_stage was never passed src/asm/src_file. Now stub_map() reads
each stub asm subdir from its INCLUDE_ASM line, the drift-check uses the per-fn subdir, and
reconcile_and_gate groups targets by split file, gating each via run_gate(src=,asm=,src_file=).
fix_arity_callers/dedup_propagate already split-aware; harvest_verify self-filters per split.
2026-07-08 01:23:08 -06:00
Drew T 41e454ec1f chore(phase-25): T0 — refresh sigs/surveys, regen worklist+backlog, fix sig_image h_norm doc
- housekeeping: deleted stale root gccdump.lreg (gcc default -da RTL dump, dumpbase
  "gccdump"; a one-off RTL-inspection run at root CWD, NOT a committed tool). Practice:
  RTL dumps go to a .run/ CWD or -dumpbase .run/gccdump (R12)
- make sig-overlays (134 sigs); worklist.py --refresh -> build_fuel_manifest + backlog
  render: docs/worklist.md + docs/backlog.md regenerated (stale Jun-26 ranking killed;
  the banked whale func_80144B9C dropped from backlog, P9)
- fix tools/sig_image.py docstring: h_norm is the live norm_stream normalizer, not a
  "T5 placeholder" (R21/R30)
- CURRENT_PHASE.md: Phase-25 plan-of-record + T0 frontier survey (R14): h_norm 2,764
  multi-member families / 11.1 MB; 46% of large solo monsters (3,989/8,670) are family
  members; reach-134 h_exact warm-up = 130 classes / 4.11 MB
2026-07-08 01:02:58 -06:00
Drew T 8e6658ee85 feat(phase-24): T7 §G — func_801770E0 banked ×134 (native DEFINE-macro path); fleet 65.95→65.99%
- func_801770E0 (152 ins, reach-134) propagated ×134 via dedup_propagate --recover.
  Chose the NATIVE DEFINE-macro path over a hand-rolled shared header: func_8014E048
  (pins+asm) is already ×134 via a DEFINE macro, proving that path handles pin/asm -O2
  giants (the whale needed a shared header only because it is -O0 -> separate object).
  Clean fleet check-all 136/136 (R22), dedup-check 1811->1812/0.
- R14: func_8014E048 was ALREADY ×134 (T6 §A) — the whale-session handoff was stale;
  only func_801770E0 + func_801372B0 actually remained ×1.
- tooling (reusable): dedup_propagate.overlay_files now also scans the whale-rollout
  _o0b/_after splits — post-whale-region fns (func_801770E0 in _after.c) were invisible
  for both source-def-find and stub-replacement. func_801770E0 extern block made
  contiguous (a comment between externs made find_site drop 5 externs; byte-neutral).
2026-07-07 23:21:20 -06:00
Drew T 8cfbbf2d47 feat(phase-24): T7 whale func_80144B9C banked ×134 (-O0 reach-134 rollout) — clean fleet 136/136
The single biggest byte-weight lever (770 ins ×134 ~ +1.6% byte-weight), banked across all 134
overlays as -O0 compiled C (was ×1 in ov_SC01_077, commit:0463).

- ROLLOUT (tools/rollout_whale_o0.py): per single-file overlay, LINE-split <ov>.c at the whale
  (splat emits in vram order), carve the yaml code subseg into before/<ov>_o0b(-O0)/<ov>_after,
  thin <ov>_o0b.c #includes the shared src/shared/func_80144B9C.h (the whale C moved there — DRY,
  TU-local typedefs, not a fragile 200-line DEFINE_ macro). Makefile WHALE_O0B_OBJS wildcard -O0.
- DEDUP: group E_func_80144B9C (134 members, h_exact 74186b97, source=the header; group_members
  keys on binary+vram so a header-share validates like a macro-share).
- MILESTONE: clean fleet check-all 136/136 (R22); dedup-check 1811/0; FLEET REAL 225816->225949,
  byte-identical 65.91->65.95% function-count (the gain is byte-weighted). Validated on ov_SC01_000
  + spot-checks SC02/SC03/SC07 before the full fleet.
- cookbook §38 + SETUP inventory.
2026-07-07 22:23:10 -06:00
Drew T c106774776 feat(phase-24): T7 §G — 6/8 giants cracked, 4 ×134; fleet 65.75→65.91%
- MATCHED 6 reach-134 giants: func_801571C4 (permuter), func_8014EA4C/801372B0/
  801770E0/80176D94/80148094 (Fable5, sequential idiom-banking chain)
- 2 genuine walls stay INCLUDE_ASM (G4): func_80178004 (close=7), func_801412A8 (close=29)
- propagated x134: func_801571C4/8014EA4C/80176D94/80148094 (134 overlays byte-identical;
  dedup 1810 groups/0 failed; genuinely-clean make-clean+extract-all+check-all = 136/136)
- func_801372B0/801770E0 banked x1 (x134 follow-up: pin/asm + local-type self-containment gaps)
- tools: p16_permute.py comment-fix (unblocked the permuter fleet-wide) + permuter_ils.py (warm-restart ILS)
- knowledge: cookbook §37 + docs/gcc-2.7.2-map/t7g-giant-harvest.md
2026-07-07 20:20:43 -06:00
Drew T bdc349e3b0 feat(phase-24): T7b/T2+T3 — reconcile_decls.py (data-symbol canonical reconcile); byte-proven on func_80129CF8
- tools/reconcile_decls.py: the DATA-symbol analog of cast_call_sites.py. A fleet-majority
  canonical-type ORACLE (engine_core.h-authoritative + plurality across all overlays+resident —
  the picker gen_harvest_targets lacked) + a byte-neutral access-cast TRANSFORM (array/struct/
  scalar/ptr taxonomy, single-pass so no double-wrap). Mechanizes the manual giant decl-reconcile
  that func_80129CF8 got by hand.
- wired into gate_stage after cast_call_sites (canon -> cast -> reconcile_decls -> byte-gate);
  idempotent / no-op on drafts without a data conflict -> can't regress the wave; the whole-binary
  byte-gate stays the sole arbiter (G3/P9).
- VALIDATED: oracle 8/8 correct picks for func_80129CF8's symbols; full loose giant ->
  reconcile_decls -> swapped into the DEFINE_ macro -> make build BINARY=ov_SC01_077 = BYTE-IDENTICAL
  d19c9580; idempotent (0 reconciled) on the already-canonical committed draft.
2026-07-03 17:55:43 -06:00
Drew T 99ccc37480 feat(phase-24): T6.4 — find_site trailing-comment externs → func_8014E048 + func_80157580 ×134
- find_site extern-collection: allow a trailing `/* comment */` after the `;`. The
  comment-blind regex `^\s*extern\b.*;\s*$` stopped the backward scan at
  `extern u8 D_801152A8[];   /* canonical TU type */`, dropping every EARLIER extern →
  compiles_standalone failed on the now-undeclared callees/data (func_80135A4C,
  func_80133784, D_801152A8). R14: THIS — not "pin/asm" as the backlog framed it — was
  func_8014E048's real self-containment blocker.
- propagated func_8014E048 (the T5b S11 pins+barrier crack) + func_80157580 ×134;
  dedup 1797→1799 groups (0 failed). CLEAN fleet check-all 136/136 BYTE-IDENTICAL (R22).
  Fleet byte-identical 65.40% → 65.48%.
2026-07-03 15:17:50 -06:00
Drew T 5b3697553f feat(phase-24): T6 — 13 leaf-MATCH fns propagated ×134 (fleet 64.90→65.40%)
find_site + dedup_propagate --recover + build_engine_types fixes, then re-bank
the 13 recover_integration leaf-MATCHes and propagate each across all 134 overlays.

- find_site: match INDENTED inline defs (was column-0 only, silently dropping every
  recover_integration-banked def from propagation — T6 blocker 1). Unit-tested:
  indented defs match; indented call-exprs (if/assign/bare/return) correctly rejected.
- dedup_propagate --recover: on a straggler byte-gate failure, FIRST no-proto that
  overlay's conflicting caller extern + re-gate (Part B, byte-neutral, same lever as
  fix_arity_callers --any-proto); else EXCLUDE only that overlay (Part A, ×N-1) rather
  than the historical all-or-nothing drop. Wired into gate_stage.
- build_engine_types: comment-aware find_defs/find_typedefs (blank_comments). The
  generated header's own "...typedef lift" comment was captured as a bogus `typedef
  vec`, self-colliding and blocking every --strip. NOTE: full --strip still conflicts
  with the _a/_o0 split files, so split-file overlays need a TARGETED lift.
- banked + propagated 13 fns ×134: func_8014F74C 801542A4 8015BE94 8015F380 80160F00
  801653B8 80166244 8016E778 801732C4 8017331C 80173374 80174554 801745AC.
  func_8014F74C needed PosT/MoveT lifted to engine_types.h (targeted, byte-neutral).
- dedup 1784→1797 groups (0 failed). CLEAN fleet check-all 136/136 BYTE-IDENTICAL (R22:
  make clean && extract-all && check-all). Fleet REAL 224073, byte-identical 65.40%.

R14: the confounding stale-asm/ tree (13 missing .s) that masked the first --recover
test is fixed by re-extract; the 3 pre-existing --auto-from stragglers (0x80174650/
8012A018/80165CA0) are pin/asm + uncaptured-local-macro (SHB) bodies, correctly dropped.
2026-07-03 15:00:46 -06:00
Drew T 91e5c4c294 feat(phase-24): T6 — integration-recovery tool (gate-recovery proven; ×134 propagation deferred)
The integration-recovery tool for leaf-MATCH-but-whole-binary-gate-rejected fns ("declaration/TU
plumbing" — the dominant residual gate_stage's canon/cast/sig_unify pipeline doesn't reach).

- tools/recover_integration.py (NEW): batch recovery — gather leaf-MATCH candidates (--auto from
  the backlog, drift-checked R14; or --funcs/--from-file) → no-proto their conflicting caller decls
  → gate_stage (byte-gate + log). 2-PASS snapshot/restore: pass 1 finds the bankable set, pass 2
  re-banks ONLY winners from the clean snapshot (so non-banks are never corrupted).
- tools/fix_arity_callers.py: extended with --binary — scan+rewrite the overlay's OWN inline caller
  decls (src/<bin>/<bin>*.c), not just engine_core.h. That was THE gap: a conflicting caller extern
  is often inline in the overlay src (e.g. func_8016E778's `extern void f(void)` vs def `f(int)`),
  which fix_arity_callers never saw -> the fn stayed unbanked.
- VALIDATED: banked 13 leaf-MATCH fns (func_8014F74C/801542A4/8015BE94/8015F380/80160F00/801653B8/
  80166244/8016E778/801732C4/8017331C/80173374/80174554/801745AC), CLEAN-verified together
  (ov_SC01_077 d19c9580). The banks themselves are reverted here (they re-bank via the tool and
  will land ×134 once propagation-recovery lands — cleaner than committing ×1).
- R14 lesson (clean-verify caught it, R22): fix_arity_callers --revert is LOSSY for --any-proto
  (()->(void), not back to the original args) -> corrupted non-banks; fixed with the 2-pass snapshot.
- REMAINING T6 (×134 propagation-recovery, 3 diagnosed blockers): (1) dedup_propagate find_site
  misses INDENTED inline defs (Phase-15 class); (2) overlay-local-type lift; (3) auto-reconcile the
  straggler's conflicting caller externs (the flagship func_80132784 / ov_SC02_005 class, done by
  hand — needs automating). See CURRENT_PHASE.
2026-07-03 13:33:13 -06:00
Drew T 0cda15c6de fix(phase-24): T5c — restore main's clean-rebuild: propagate the Phase-21 PsyQ renames to 62 stub refs
Pre-existing latent breakage (Phase-21 close commit:0292, "+62 PsyQ names"), found during T5b's
R22 fleet verify. A genuinely-clean `make clean` + re-extract + build of `main` failed with
dozens of `can't open asm/nonmatchings/800c3/func_*.s` — clean-rebuild broken since Phase 21,
masked all along by incremental builds reusing stale pre-rename .s/.o (the exact R22 failure mode).

- Root cause (byte-proven): Phase-21 xdedup renamed 62 PsyQ library functions to their proper
  names (InitHeap, FlushCache, GetTPage, SysEnqIntRP, SpuWrite, CdMix, __main …) in
  symbols.us.txt, but never regenerated/renamed the committed src/*.c stub refs that call them by
  the OLD func_<ADDR> name. splat's FRESH regeneration of a stub .c uses the CURATED names (move
  src/800c3.c aside -> splat writes INCLUDE_ASM(InitHeap) + emits InitHeap.s); the committed stubs
  were simply stale.
- Fix: rename all 62 INCLUDE_ASM(func_<ADDR>) -> the curated name across 12 files (800c.c 1,
  800c3.c 22, apicard1/2/4 4/6/2, boot.c 1, libcd1.c 8, libetc.c 6, libgpu.c 3, sgap.c 1,
  snd1.c 7, snd2.c 1). Pure rename to match splat's canonical output; byte-neutral.
- VERIFIED: main clean-builds 143dbb89 from a fully clean tree; full clean fleet check-all 136/136.
- Lesson (cookbook): a symbols.us.txt rename must be propagated to (a) shared-macro bodies
  (engine_core.h — the T5b GetTPage fix) AND (b) INCLUDE_ASM stub refs (this), AND verified by a
  genuinely-clean check-all (make clean + full re-extract), never incremental. Added a lint check.
2026-07-03 02:50:03 -06:00
Drew T 0eadf313ee feat(phase-24): T5 — §31-directed permuter mutation + grinder input-changed gating
- tools/permuter_weights.py (NEW): classify(klass,where) -> regalloc|schedule|cse|None
  + render_settings_toml emitting the [weight_overrides] table decomp-permuter merges over
  the gcc defaults (main.py:336 / helpers.py per-key replace). Biases pass-selection toward
  each class's §31 levers (perm_reorder_decls RC-1/3, perm_reorder_stmts RC-2/S1,
  perm_temp_for_expr S2, perm_commutative cse); value/type noise -> ~0.1. NO submodule edit.
- p16_permute.setup(..., klass=, where=) writes it (+--klass, backlog auto-lookup);
  grinder.py auto-threads klass/where_stuck. klass=None -> gcc defaults (undirected superset).
- grinder fix (R14): replace the blind tried.clear() idle churn with input-changed gating
  (draft_sig=(best_draft mtime, closeness) — re-open a fn only when the worker improved it).
- VALIDATED: regalloc profile drove func_8014E048 masked 36->29 (match_one -drz 35->28) where
  the undirected search stalled; re-logged (28, improved draft promoted). Flagship S11/RC-6
  count-exact seeds improve but do not gate (intrinsic, §31 "two probes dont grind") -> T5b fuel.
- distill: cookbook §3b + SETUP inventory (R16/R30). No build-input changed -> 136/136 untouched.
2026-07-03 00:14:29 -06:00
Drew T 0abcd250ab feat(phase-24): T3 — permuter setup fixes (pins/GTE-asm, typedefs, -O0); flagship closed
- p16_permute.hide_asm: b64literal-pragma carrier for register pins + GTE __asm__ blocks.
  pycparser parses the pragma; decomp-permuter's process_pragmas decodes it back so cc1 sees
  the real pins/asm (regalloc steered, mvmva compiles). No submodule edit (reuses its own carrier).
- drop_preproc_and_scalar_typedefs: keep #define + custom struct/typedefs, drop only #include
  (fixes func_801412A8 'OTLINK undeclared'); +f32 typedef gap; make_base_c hides asm.
- compile.sh/compile_o0.sh: prepend .include "macro.inc" so GTE mvmva assembles (the real build
  gets it via include_asm.h, which base.c omits + -DPERMUTER disables). Byte-neutral for non-GTE.
  compile_o0.sh (-O0) auto-selected for _o0 targets.
- run_masked.py: expr_type->int fallback for hidden-pin vars -> 0 internal-permuter-failures
  (perm_split_assignment/perm_temp_for_expr no longer KeyError on pinned drafts).
- ALL 5 seeds parse+compile (base 4/110/36/52/77). FLAGSHIP func_80132784 (4/400) CLOSED to a
  masked-0 that match_one confirms MATCH (400 ins) -> .run/wave/func_80132784.win.c for T4 gate.
- no build-input changed (136/136 untouched)
2026-07-02 23:32:38 -06:00
Drew T 5984749421 feat(phase-24): T2 — floor-free relocation-masked permuter scorer (-drz)
- tools/masked_diff.py: shared objdump -drz masking oracle (jal/j 26-bit + HI16/LO16
  immediate mask; -z keeps nop runs -> no GTE under-count). object-vs-object (permuter,
  +reloc-operand equality) and object-vs-.s (match_one) modes.
- match_one.py refactored onto masked_diff (-dr -> -drz); regression-clean on count-exact
  seeds (35/52/72/110, leaf-MATCHes), output format unchanged (gate_stage/grinder compatible)
- tools/masked_scorer.py MaskedScorer: drop-in for decomp-permuter's Scorer; scores masked
  .text closeness (bottoms out at 0) not the stock mnemonic-diff floor
- tools/permuter/run_masked.py: rebinds src.main.Scorer -> MaskedScorer (NO submodule edit,
  R3/R20); p16_permute.run_permuter wired to it
- VALIDATED: masked_self=0; masked_cand~match_one; STOCK floor 1750-2100 vs masked 36-77
  (the wander cause); live permuter base score = masked 77 (not stock 1930), descends to 74
- R14 SELF-CORRECTION: -drz confirms func_80132784 is 4/400 count-exact (T1's -dr 204 was a
  16-nop-collapse artifact); backlog re-logged close 4. The flagship IS 4 ins away.
- no build-input changed (136/136 untouched); 2 compile FAILs surfaced -> T3 (GTE asm, typedefs)
2026-07-02 23:10:54 -06:00
Drew T 394e3a81b3 chore(phase-24): T1 — re-log map-wave seeds (byte-verified) + backlog/gate_stage hygiene
- re-logged 7 map-wave seeds in .run/backlog.jsonl with match_one-verified
  closeness (dropped 19 stale/unreproducible records, .bak kept):
  func_8014E048=35 (was mis-logged 'failed'), func_80176D94=52,
  func_80148094=72 (best draft vG2, not the named file), func_801412A8=110;
  T6 leaf-MATCHes func_8014F4C0/func_80155800=0; best_draft -> .run/backlog_drafts/
- R14 FINDING: the 'func_80132784 is 4/400' premise is NOT reproducible from any
  on-disk draft (best=204-off, wrong instr count 384!=400 -- match_one -dr collapses
  ~16 nops on this GTE seed); true closeness pends T2's -drz scorer -> T4 reframed
- gate_stage.py: fixed the stale 'sig_unify SKIPPED with --src-file' doc-drift
  (code runs it; sig_unify.py:151 has --src-file support)
- wave_targets --class REGALLOC + grinder now surface the 4 count-exact permuter
  seeds with true closeness; no build-input changed (136/136 invariant untouched)
- added T5b (Fable5 S11/RC-6 map-extension spike) per Drew
2026-07-02 22:55:05 -06:00
Drew T 6678c6868a feat(phase-23): Fable5Max cracks §20 "unsteerable" giant func_8014EE14 ×134
- Fable5Max agent (Agent model=fable) matched a 248-ins reach-134 GIANT on the
  §20/§10 store-vs-load wall (22 phases "CONFIRMED unsteerable") by reading the
  gcc-2.7.2 source (tools/reference/gcc-papermario) + RTL -da dumps. Leaf
  MATCH(248 ins) -> whole-binary banked:1 -> dedup_propagate ×134. Verified:
  check-all 136/136 byte-identical, dedup-check 1780 validated/0 failed.
- 3 byte-proven idioms -> cookbook §30 (corrects §29's "not a bigger model"):
  (1) store-vs-load is a deterministic MEM_IN_STRUCT_P /s aliasing flag, not a
      scheduler tie-break; steer via ((struct{s32 f;}*)p)->f (anon struct keeps
      /s AND propagates ×134) to grant, *p to deny
  (2) def-side return-type wall has a MACRO escape: widen a discarding caller
      macro's extern void->s32 (byte-neutral, check-all-verified) -- extends §29
  (3) birthing-boost prologue-order lever: __asm__("":"=r"(x):"0"(x)) re-tie in a
      later bb kills sched.c's REG_N_SETS==1 priority boost
- tools/glm_parallel.sh: K concurrent OpenRouter/GLM cloud drafters (parallel
  api_draft), key read from .env at runtime
- §10/§20 "store-vs-load unsteerable" backlog now re-test candidates:
  func_8014F2E0, func_80150528, func_8014EA4C
2026-07-02 16:56:56 -06:00
Drew T d71305fa5f feat(phase-23): T10.8 idiom-hunt harness + calibration — GLM confirms our idioms, no NEW ones
- tools/idiom_hunt.py: group backlog near-misses by residual class -> GLM names the reusable idiom +
  emits corrected C -> byte-gate to validate; captures reasoning; HARD --budget cap
- CALIBRATION ($0.51 total, 2 classes): struct + regalloc-order -> 0 banks. GLM re-derives our OWN
  idioms (register-pin §17, array-of-struct §18, type-width §25) and confirms walls, but banks nothing
  new — the backlog near-misses are the residual our idioms already failed on (irreducible/def-side wall).
- VERDICT: the new-idiom well is DRY (Fable5 review confirmed empirically for $0.51, not $300 overnight).
  GLM's value stays: direct drafter for FRESH def-conflict-free hard fns (~22%), not an idiom generator.
2026-07-01 23:13:29 -06:00
Drew T 8562aa89c1 feat(phase-23): T10.7 Option-3 — GLM reasons the def-side wall; +1 bank (func_80175184)
- tools/glm_reconcile.py (NEW): aim GLM's reasoning at the DEF-side loose-typing wall (body + conflicting
  TU decls + reconciliation toolkit -> consistent buildable byte-identical decls); captures reasoning
  (.run/glm_reason/, idiom source R16); relax-in-any-TU-file + crash-robust call
- api_draft: REASON=1 saves the reasoning trace per draft (idiom mining on any GLM run)
- fix_arity_callers: --any-proto (relax any prototype, not just (void))
- RESULT: GLM's reasoning is expert-level (store-width/sh-vs-sw awareness, K&R promotion, independently
  derives the cast idiom) but banks only 1/7 reconciliations; mechanical relaxation 0/7. The def-side
  wall is INTRINSIC (narrow-param + byte-level addressing defeat reconciliation) — Fable5 §3c re-test
  CONFIRMS the wall holds even vs a frontier reasoning model aimed directly at it. func_80175184 banked,
  check-all 136/136
2026-07-01 21:03:08 -06:00
Drew T 1caff3dc4c feat(phase-23): api_draft MAXTOK env + OpenRouter cost capture (T10.7 reasoning-model support)
- MAXTOK env (default 512 = local v3 unchanged); reasoning models (GLM5.2) need a high cap or
  they spend the budget on reasoning tokens and return empty content
- accumulate usage.cost from the response -> per-run $ + $/fn readout (OpenRouter reports it)
2026-07-01 18:29:27 -06:00
Drew T 35bc7c3873 feat(phase-23): bulk_harvest --cycles campaign mode (resumable, per-cycle commit, dry/STOP-aware) 2026-06-30 23:34:31 -06:00
Drew T c5cca1c6d4 feat(phase-23): T10 tooling — parallel-safe gate spine + bulk_harvest
- gate_stage.run_gate: optional lock_path (per-binary lock), verified_out/failed_out
  (per-worker harvest scratch), compute_fleet toggle — all default to today's behavior,
  so grinder/orchestrator/lora_grind are byte-unaffected
- harvest_verify: --verified-out/--failed-out (per-worker result paths for parallel gating)
- bulk_harvest.py (NEW): phase-separated saturation factory — bulk-draft (GPU) ->
  ProcessPool parallel-gate over distinct binaries (build/<bin>/** isolated) ->
  dedupe-once + one commit; round-robin fuel spread; whole-binary byte-gate stays the
  sole arbiter (G3/P9); on-demand/bounded (STOP sentinel); lora_grind kept as fallback
2026-06-30 22:48:26 -06:00
Drew T 7dbdd1ce47 perf(phase-23): cap api_draft max_tokens 4096->512 (no-stop ramble) + capture saturation/throughput findings
- the model rambled to 4096 tokens on no-stop-token drafts (~80-130s each); a
  ≤15-ins fn's C is ~100-300 toks, so 512 truncates the ramblers (gate-rejected anyway)
- CURRENT_PHASE: ≤15 band NOT saturated (~4,597 unique / 4,087 untried, SC03=12,497);
  drafting ~15-18s/func serial is the throughput wall; architecture = phase-separate +
  parallel-gate + vLLM batched serving (the real GPU lever); fresh bank-rate still TBD
2026-06-30 15:52:04 -06:00
Drew T 5a984886af perf(phase-23): lora_grind computes progress.py --fleet only on propagate sweeps (was every batch, ~14s overhead dominating small batches) 2026-06-30 15:32:56 -06:00
Drew T eb3b18efcc feat(phase-23): lora_grind --min-nins (skip the saturated small band for a fresh-band pass) 2026-06-30 15:05:25 -06:00
Drew T 205fc202e9 feat(phase-23): macro-extern-injection lever — 8 reach-134 fns freed ×134 (fleet 63.82→64.09%)
- tools/inject_capped_externs.py (new): source each propagation-capped reach≥2
  inline match's externs from ov_SC01_077's own file-scope decls, inject them
  block-scope so the lifted macro is self-contained (the Phase-20-backlog
  macro-extern-injection lever; byte-neutral, fail-safe via compiles_standalone)
- 8 reach-134 fns freed from ov_SC01_077.c, 077 byte-identical; dedup_propagate
  --auto-from registered 7 new shared groups ×134 (1678->1685), check-all 136/136
- the LLM reach≥2 measurement run already banked +7 (v3 banks reach≥2: 6/15 in 005
  vs v2's 0/15) — committed earlier (commit:0359, commit:0360)
- cookbook §28d + SETUP tooling inventory (R16/R21/R30)
- fleet 63.82% -> 64.09%, 0 NON_MATCHING, dedup-check 1685/0 failed
2026-06-30 11:15:11 -06:00
Drew T 066a2e5c8f feat(phase-23): local GPU serving + prompt-fix + corpus-v3 (macro+struct mining)
LM Studio was ejected, so serving is ours now: tools/serve_local.py serves base+LoRA via
Unsloth (.venv-train cu128) as an OpenAI endpoint — no llama.cpp build (this CPU has no
AVX-512, which SIGILLs the prebuilt llama-cpp-python CUDA wheels). api_draft/lora_grind hit
it unchanged.

PROMPT FIX (api_draft.LEAN_SYS + format_finetune.SYS, kept in sync): 'translate EVERY
instruction, never an empty body' — a prompt test took the small-leaf band 0/3 -> 2/3 MATCH
(the v2 corpus overfit an empty void f(void){} leaf pattern). Validated end-to-end: a fresh
ov_SC01_001 batch banked 3 via the local server + better prompt.

CORPUS-V3 (export_pairs + format_finetune):
- export_pairs now ALSO mines the 1623 DEFINE_func macro bodies in engine_core.h (the shared
  setters/return-const/dispatchers extract_defs never saw -> 96.6% of v2 was overlay-unique,
  the root of the empty-leaf overfit). Corpus 1312 inline -> 2891 (1312 inline + 1579 macros).
- format_finetune inlines engine_types.h structs in the compile-filter so struct-using bodies
  are KEPT not dropped: train 2534/2591 (97.8%) compile standalone (v2 was 1111 total).
2026-06-30 01:46:54 -06:00
Drew T e91859fb4a feat(phase-23): grinder per-binary fix (5-layer) — unlock non-077 near-miss grinding
The grinder/backlog pipeline was ov_SC01_077-hardcoded 5 layers deep (same class as the
T7 lora_grind bug). Fixed all so the permuter grinder can process a non-077 near-miss:
1. gate_stage.append_record stores the source "binary"
2. backlog.FIELDS keeps it (else append_record dropped it)
3. backlog.load_best/_open_stubs is fleet-aware: a fn matched in ov_SC01_077 but
   propagation-stuck stays OPEN in its overlay, so it surfaces via that record instead
   of being dropped as "matched" (the grinder must SEE it to grind it)
4. p16_permute.setup takes the target binary's asm-subdir (was hardcoded 077)
5. grinder resolves per-binary asm + gates grouped by binary + allows unknown nins
Backward-compatible: legacy records (no binary) default ov_SC01_077.

Validated end-to-end: the 3 fresh reach-134 close=1 ov_SC01_000 fns now surface, resolve
to ov_SC01_000's asm, and gate via ov_SC01_000.

TWO byte-evidenced findings (redirect the fuel strategy):
- the reach>=2 close=1 fuel is MODEL semantic-misses, not permuter fuel: func_8012E27C's
  target is "return 1" but the 7B drafted an empty "void f(void){}" (corpus overfit
  empty-leaf); func_8012BF4C/AD64 are trivial sw/sh setters drafted empty. A corrected
  draft banks them (+3 byte-identical via the fixed gate, @commit:0326); the permuter cannot
  add a missing return/store. Lever = corpus-v3 leaf variety, not the permuter.
- x reach is propagation-capped: the 3 are inline-matched in ov_SC01_077_a.c (the stuck-
  local cap) -> dedup_propagate "nothing to propagate" -> banked x1. Lever = dedup-collapse.

check-all 136/136 throughout. docs/gen2-mips-matching-model.md + CURRENT_PHASE updated.
2026-06-30 00:58:13 -06:00
Drew T 366f7e4c7f feat(phase-23): T9 — reach>=2 targeting (lora_grind --min-reach); shared-code is the model's weak band
Add a sig-based reach oracle + --min-reach N to lora_grind so the mass-run can prefer
SHARED functions (one bank propagates x reach — the fleet-% multiplier). The oracle reads
the same .run/sig.ov_*.jsonl dedup_propagate uses (validated: 0 mismatch over 60 stubs +
the func_8017CE24=2 ground truth), so a reach>=N target is exactly one dedup_propagate
will stamp x reach after the bank.

Bounded reach>=2 mass-run (ov_SC01_000, 15 shared <=15-ins stubs): 0/15 banked, vs the
reach-1-heavy spot-run's 7/15. The model is weakest exactly on reach>=2 (shared) code:
(1) the corpus skipped the shared DEFINE_func macro bodies (export_pairs reads only src/
defs -> 96.6% of the corpus is overlay-unique), and (2) the shared engine fns are the
harder regalloc/schedule residuals. So reach>=2 model-only is NOT a fleet lever by itself.

BUT the reach>=2 drafts are high-value FUEL: 5/15 are close<=3 reach-134 near-misses
(3x close=1: func_8012E27C/BF4C/AD64) -> x134 each if closed. The real lever is
reach>=2 draft -> permuter-grinder close (x134), which needs the SAME per-binary fix T7
applied to lora_grind: grinder.py calls run_gate with no binary (-> 077) and the backlog
stores no binary field. That two-part fix is the next step. byte-neutral: check-all 136/136.

- docs/gen2-mips-matching-model.md: T9 RESULT
- phase-ends/CURRENT_PHASE.md: T9 done; next = grinder per-binary fix, then corpus-v3
2026-06-30 00:12:45 -06:00
Drew T bff03dbdb5 fix(phase-23): T7 — lora_grind broad-rotation banking (two gate bugs); ov_SC01_000 7/15
The 500-fn calibration banked 0/222 across the binary rotation. Root-caused (R14, by
reading the code + the run's own backlog — resolving a flat contradiction between two
scout agents) to TWO independent bugs in lora_grind's use of gate_stage.run_gate, NOT
model quality:
- Bug A: good_sha() passed the sha1sum line "<sha>  <name>" vs harvest_verify's bare
  sha1() -> 0 banks for EVERY binary incl. 077 (so the "0/12" was a bug artifact, not
  an exhausted tail)
- Bug B: the gate call left src/asm/out at the hardcoded ov_SC01_077 defaults -> non-077
  drafts dropped at the 077 stub-filter, silently (and the asm mis-resolution contaminated
  the backlog near-miss classification)

Fix (tools/gate_stage.py): run_gate resolves src/asm/out/good_sha from `binary` when unset
(binary-agnostic, no silent ov_SC01_077 default an overlay inherits; good_sha bare-hash
normalized) + a loud negative-control guard (0-overlap binary/src mismatch warns, so a 0
can never again masquerade as 'nothing matched'). tools/lora_grind.good_sha fixed at source.
Byte-neutral: make check-all 136/136.

Proof: ov_SC01_000 spot-run banked 7/15 (47%) byte-identical (@commit:0322); reach-2
func_8017CE24 propagated x2. ROI finding: 6/7 banks are reach-1 (overlay-unique) -> broad
rotation is high bank-RATE / low fleet-% ROI; the fleet lever is reach>=2 targeting (T9) +
corpus-v3 (T8). Backlog now correctly classified (4x close=1 = grinder fuel).

- docs/gen2-mips-matching-model.md: T7 RESULT section
- phase-ends/CURRENT_PHASE.md: T7 done; next = T8 corpus-v3 / T9 reach>=2 selection
2026-06-29 23:44:12 -06:00
Drew T edd62ef992 feat(phase-22): lora_grind.py — the free local-model mass-run (draft source for the grinder flywheel)
Rotates over every binary with open small stubs, drafts with the fine-tuned model (api_draft LEAN, GPU
via LM Studio), banks via gate_stage, propagates fleet-wide periodically. Near-misses -> backlog ->
grinder.py permuter closes regalloc/schedule residuals (synergy). Writes a classified near-miss
histogram (the 'missing idioms' signal -> corpus-v3 priorities). STOP/heartbeat/stats like grinder.py.
Smoke OK; histogram shows struct(49)+schedule/regalloc(94) dominate the backlog.
2026-06-29 22:10:05 -06:00
Drew T b4c312a30c feat(phase-22): FIRST free-local-model banks — 4 open stubs matched by the v2 LoRA
The fine-tuned 7B (bfm-match-7b-v2) drafted real OPEN ov_SC01_077 stubs; whole-binary gate banked 4
(func_80160B34 func_8015CC74 func_8016084C func_801705C0). Sample: 9/22 match_one proxy -> 4/22
whole-binary banked (18%; the proxy->gate gap is the TU-plumbing wall). Model is format-robust (raw .s
== normalized). api_draft: NORMALIZE_ASM bridge (unused — model handles raw .s) + ghidra_c-empty fix.
2026-06-29 21:58:09 -06:00
Drew T 748dece7fc feat(phase-22): train_lora auto-cleans GGUF intermediates (the ~30GB that crashed C:) 2026-06-29 20:07:48 -06:00
Drew T 8537706006 feat(phase-22): corpus-v2 — capture the extern block above each def (self-contained completions)
The pilot failed because the compile-filter dropped the 536 hard (global/struct) fns: bare defs
reference undeclared D_xxxx globals -> cc1 error. The src declares them as 'extern <type> D_xxx;'
immediately ABOVE each def with correct byte-verified types. Capturing that contiguous extern block
lifts standalone-compile 52%->92% (16/40 hard fns recovered) AND teaches the model to declare globals
with the right types (a real matching skill). Fixes the trivial-bias that capped the 7B pilot.
2026-06-29 20:03:53 -06:00
Drew T 803be6341c feat(phase-22): eval_lora held-out scorer (validated) + train_lora --max-steps
eval_lora.py: feeds a fine-tuned model the LEAN asm of held-out BANKED test fns, compiles its C,
compares to the corpus target reloc-masked (banked fns have no .s — corpus carries the asm). Validated:
known-good corpus C scores MATCH vs its own asm. train_lora --max-steps for smoke runs. GPU confirmed
(3080 Ti, torch 2.10+cu128); install + corpus-filter (638/75 clean pairs) done; smoke-train running.
2026-06-29 16:49:11 -06:00
Drew T dfd97226cc feat(phase-22): format_finetune compile-filter — keep only standalone-compilable pairs
Found 50% of bare-def corpus completions fail standalone compile (undeclared globals/structs — externs
lived in TU headers). Filtering to compile-verified pairs so the pilot LoRA learns to emit COMPILABLE
matching C, not uncompilable bodies. (Drops harder struct/global fns; corpus v2 = add externs to recover.)
2026-06-29 16:43:19 -06:00
Drew T 1c80b25ac6 feat(phase-22): LoRA specialist pilot tooling — format_finetune + train_lora + api_draft LEAN
format_finetune.py: corpus -> Qwen chat-template instruction JSONL (lean asm->C, 1174 train/133 test).
train_lora.py: Unsloth QLoRA recipe (Qwen2.5-Coder-7B 4-bit, fits 12GB; merges to GGUF for LM Studio).
api_draft.py LEAN=1: ~350-tok asm-only prompt matching the training shape (fine-tuned model needs no
inlined cookbook -> fast). Datasets gitignored. Eval: beat stock-local ~0 on the held-out frozen 20.
2026-06-29 16:35:06 -06:00
Drew T 4895843dda feat(phase-22): api_draft fair-harness — inline common.h + live cookbook + corpus examples
Gives the no-tool local model the context the agents read: common.h, live matching cookbook
(COOKBOOK_FULL toggle), 2 byte-matched corpus examples. Qwen3.6-35B-A3B result: harness fixes
compile-fails but model stays stuck at fixed near-misses; FULL cookbook worse+2.3x slower than
curated (dilution, gate-confirmed). Bottleneck is model refinement, not context.
2026-06-29 16:24:37 -06:00
Drew T ad535ad1ab feat(phase-22): gen2 matching-model design + export_pairs.py corpus miner
docs/gen2-mips-matching-model.md: the BFM/gcc-2.7.2 matching-specialist idea (LoRA on our own
gate-verified pairs — the corpus off-the-shelf RE LLMs lack). export_pairs.py mines 1307 banked
(asm<->C) pairs from build objects (asm/ is gitignored, so disasm the ROM-identical build, splat-like
format) + src defs -> datasets/match_pairs/{pairs,train,test}.jsonl (gitignored, 1174/133 split).
api_draft.py: TEMP env-tunable. .gitignore: datasets/ models/ weights.
2026-06-29 14:27:19 -06:00
Drew T 3549f756f7 feat(phase-22): api_draft.py — provider-agnostic draft worker (local/OpenRouter)
Script equivalent of one worker_wave drafter for any OpenAI-compatible endpoint (LM Studio /
llama.cpp / vLLM / OpenRouter). Inlines asm+ghidra_c+toolkit, calls /chat/completions, extracts C,
iterates against match_one (diff fed back, keep best). Output scores as a 'local'/'glm' arm via
ab_score.py. Env: API_BASE/API_KEY/MODEL. Logic self-tested; HTTP is standard OpenAI format.
2026-06-29 13:05:18 -06:00
Drew T f154822f7b feat(phase-22): cheap-tier A/B experiment harness + findings
ab_match.js (per-arm-model fan-out fork of worker_wave) + ab_score.py (disk-truth
match_one scorer, --measured for real $). Haiku drafters vs Opus on 20 reach1 fns:
proxy 10 vs 15 matches, Haiku ~4.8x more matches/$, parity on <=52-ins band. Whole-binary
gate banked 4 (proxy over-counts; TU-plumbing wall). backlog/fleet refreshed.
2026-06-29 12:52:39 -06:00
Drew T 0375cd529b docs(phase-22): T3 — distill §28 canonical-extern recovery + recover_giant.py + decomp.wiki patterns
- cookbook §28: the 4-way triage of a close=0 gate-rejected giant (pure-extern plumbing /
  masked-residual / struct-walled / regressed-draft) + the canonical-extern recovery (the NEW
  lever that banked func_8015126C, which Phase-21 left as a close=0 wall) + the coalescing pin
  (register __asm__ + lazy in-&& assign). §28a: PS1-applicable decomp.wiki GCC patterns
  (negative-offset loops, branch-duplication, load-coalescing, div-magic table, slti-0)
- tools/recover_giant.py: canonicalize a draft's engine_core.h-callee externs to def-sigs +
  move all externs block-scope (validated func_8015126C -> MATCH)
- R14: close=0-giant fan-out NOT uniformly near-free — only func_8015126C was pure-extern;
  the rest are struct-walled / masked-residual / regressed -> genuine per-giant hand-work
2026-06-26 03:06:54 -06:00
Drew T 013806b075 feat(phase-22): T0 — unified byte-weighted ranked worklist (the loop's decision spine)
- tools/worklist.py: join fuel_manifest (class/reach/nins/leverage/cached/region)
  + backlog near-misses (closeness/where_stuck/best_draft) -> docs/worklist.md +
  .run/worklist.json, ranked by byte-weighted gain (gain_ins = reach*nins),
  grouped by idiom class, with %rem + cum% columns; --refresh re-runs
  build_fuel_manifest + backlog.render for one-command loop use
- docs/worklist.md: 451 live stubs, 1.85M ins remaining gain; GIANT queue =
  23 fns = 37.2% of remaining gain; surfaces the idiom sub-groups (close=0
  plumbing-wall / won't-compile loose-typing / regalloc-coalescing / irreducible)
- phase-ends/CURRENT_PHASE.md: Phase-22 plan + per-task crash-recovery log
- no source touched -> byte-locked binaries unaffected (no build needed)
2026-06-26 02:07:03 -06:00
Drew T 62fa026f7e feat(phase-21): worker_wave — GIANT-guarded §27 hint (arg-arity decls, sibling templates, coalescing residual) 2026-06-25 16:46:35 -06:00
Drew T cf23808d5c feat(phase-21): cont.7 — cheap close=0 recovery EXHAUSTED (byte-proven); fix --assess double inflation
- THE FINDING (R14/P9): the _a close=0 recovery banks 0/20 (same def-side multi-way
  loose-typing wall as MAIN 0/40, cont.6). cont.6's func_8012F568 was the lone simple-arity
  win; the rest need a C type that conflicts caller-decl-vs-def with no single fitting sig.
  The cheap close=0 ×134 recovery lever is EXHAUSTED.
- TOOLING (R16, idiom_loop.py --assess was DOUBLY inflated, now fixed):
  (1) load_backlog drops banked-since-logged fns (intersect ledger w/ live INCLUDE_ASM stub
      set, mirrors backlog._matched_now) -> killed the bogus 'unknown 14' class + ~10/class
      stale-matched inflation (schedule 49->39 r134, regalloc 44->39).
  (2) DETERMINISTIC-RECOVERY splits FRESH (never recovery-gated = genuine fuel) vs WALLED
      (recovery-failed = def-side wall, do NOT re-run). Post-fix: 0 FRESH / 46 WALLED.
- schedule wave NOT fired (ROI-gate, S20/S26): ~50% x134 fraction on n=2, median 15 ins off,
  over an h_exact-inflated count. No tokens spent speculatively.
- cont.6 option-3 CONFIRMED: cached reach-134 cheap fuel is dry; the genuine levers are
  token-heavy fresh-session work (the 8 giants / per-fn pin-cracking / build a resolved-reach
  probe). cookbook S26. 0 banks; fleet 63.17% unchanged; 136/136 byte-identical; 0 NON_MATCHING.
2026-06-25 13:09:02 -06:00
Drew T 790326057a feat(phase-21): cont.6 — sig_unify --src-file + gate two-stage; schedule idiom = coalescing (§25)
- sig_unify.py --src-file: read cur_stubs/decls from the SPLIT .c (_a/_o0) so split-file
  drafts aren't dropped + get the def-side recovery (closes the §24 gap). gate_stage passes
  it to cast + sig_unify in --src-file mode. Banked func_8012F568 x134 earlier (commit:0277).
- gate_stage.py CANON-FIRST two-stage (§19 folded into the shared gate): stage1 canon+cast
  gate (already-correct/hand-pinned cracks bank), stage2 sig_unify ONLY the failures (def-side
  recovery, no regression). Fixes sig_unify regressing the func_80128ED8 crack.
- schedule idiom CRACKED (cookbook §25): func_80128ED8 = gcc copy-COALESCING, not scheduling;
  2 register pins (idc->$a3 forces the multiply onto $v1; idc+1->dead $v0 temp) -> MATCH,
  banked x1 (commit:0278). + the rank_for_schedule tie-break (priority->class->LUID source-order)
  + the genuine walls (§10 cross-jump/delay-slot, store-vs-load).
- FINDING (R14/P9): h_exact OVER-COUNTS x134 (relocation-masked) -> func_80128ED8 is x1 not
  x134; probe dedup_propagate --addr before a token-heavy wave. schedule is NOT a confirmed
  x134 vein -> the wave is ROI-deferred.
- check-all 136/136 byte-identical (R22); 0 NON_MATCHING (G4); fleet 63.13% -> 63.17%
2026-06-25 01:17:12 -06:00
Drew T a79aa410bd feat(phase-21): idiom_loop.py — the neverending idiom-learning meta-loop (wall->assess->fuel)
Drew's directive: Phase 21 is neverending (harvest easy fuel -> learn next gcc-quirk idiom ->
fresh session -> repeat, toward 100% decomp). idiom_loop.py: --fuel-status (wall), --assess
(cluster backlog by quirk class, rank by reach-134 leverage, name next idiom + cheap recovery
lever), --gen-fuel (research+harvest manifest). First assessment: next idiom = SCHEDULE (49
reach-134, sched.c tie-break); +64 close=0 reach-134 fns bankable x134 for ~0 tokens (def-side
recovery). CURRENT_PHASE cont.5 = the neverending cycle + the /loop prompt for the fresh session.
2026-06-24 22:59:04 -06:00
Drew T 5e5423e953 feat(phase-21): dedup_propagate drop-straggler retry — _a pipeline now hands-free
The 2nd straggler class (cont.4 wave-2): cross-overlay loose-typing COMPILE errors (not just
the -O0 byte-mismatch class). The -O0 exclusion alone was insufficient. Refactor the propagation
into a drop-straggler retry loop: extract apply_plan(subplan, restrict=); on a byte-gate failure,
isolate the culprit(s) for the failing overlay (per-fn trial), drop them (kept x1), retry the
survivors. Handles BOTH straggler classes failing ANY overlay; plan strictly shrinks (terminates);
byte-gate stays sole arbiter (a dropped fn never banks where it isn't byte-identical).

Validated end-to-end: wave-2 --auto-from auto-dropped 2 loose-typing stragglers + propagated 3
clean x134 (commit:0271); fleet 62.70 -> 62.82%. Future _a waves now auto-realize x134, no manual probe.
2026-06-24 22:11:27 -06:00
Drew T 04c5c9b47f fix(phase-21): dedup_propagate skips -O0 overlay-local fns + gate_stage surfaces prop failures
The cont.4 root-cause fixes so future _a waves auto-realize ×134:
- dedup_propagate --auto-from now excludes *_o0.c (-O0) defs: -O0 codegen embeds per-overlay
  %lo data, so masked h_exact falsely reports reach-134 (§18/§20). One such straggler
  (func_8013C360) reverted 10 clean ×134 matches under the all-or-nothing batch gate (cont.4).
  Detected via find_site on the -O0 split file; --addr still forces them. (6 fns excluded.)
- gate_stage: capture dedup_propagate's exit; on a real byte-gate revert (not the benign
  'nothing to propagate' no-op) write .run/auto/last_propagate_error.log + add prop_error to
  the summary + warn. A swallowed revert previously hid the gain silently.
2026-06-24 21:32:05 -06:00
Drew T e30697a081 docs(phase-21): _a vein is a x134 lever (10/11) — worker_wave region-fix + cont.4 findings
- worker_wave.js: derive match_one self-check --asm-subdir per-target from t.asm
  (was hardcoded main subdir -> every _a agent self-check crashed on missing .s ->
  blind drafting). Enabled the 16/24 close rate on the _a measurement wave.
- CURRENT_PHASE cont.4: the _a vein is x134 (10/11 propagate byte-identical), not the
  cont.3/§24 x1 wall. The gate's propagated:0 was 2 bugs: dedup_propagate all-or-nothing
  batch-revert poisoned by 1 stale -O0 overlay-local straggler (func_8013C360), and
  gate_stage sh() swallows dedup_propagate's non-zero exit. Realized +0.39% (commit:0267).
2026-06-24 20:37:57 -06:00
Drew T 91430e9309 feat(phase-21): _a wave is turnkey — gate_stage --src-file + wave_targets region-aware asm
- gate_stage.py --src-file: cast canonicalizes vs the SPLIT .c's decls + sig_unify SKIPPED (it reads
  main .c only -> drops _a/_o0 drafts). Validated end-to-end: gate_stage _a-mode banked func_8012C098.
- wave_targets.py region-aware asm paths (REGION_SUB/asm_for): --region a serves the 68 fresh _a
  reach-134 fns with correct ..._a .s paths (pool + --class modes).
- the _a wave is now fully wired (wave_targets --region a -> worker_wave -> gate_stage --src-file ->
  dedup_propagate split-aware). Turnkey runbook in CURRENT_PHASE.md (cont.3) for a fresh session.
- no net banks; fleet 62.31%; ov_SC01_077 d19c9580 (R22).
2026-06-24 19:35:17 -06:00