Commit Graph

10 Commits

Author SHA1 Message Date
Drew T 5a9f455e60 tools(phase-35): T6 part 1 — 14 macro-era tools FROZEN (tools/frozen.py: one refusal from main(), imports never exit; the plan's 7 + 7 the guard census found, family_remap's CLI among them), 4 retired to tools/sunset/ (dedup_propagate + dedup_extend -> share_body.py with add_members_surgical and the load_sig library moved verbatim; macro_draft; test_reconcile_ledger), six lane callers repointed to share_body --apply --bucket new, validate_targets imports share_body, tool_census accepts FROZEN; dictionary + sunset README rows; kit corpus 2026-09-08 20:34:41 -06:00
Drew T 3222eb454c feat(resolver/aprop): decl-from-use wired into the A-prop drafter; TU-BROKEN classification; dup-def→extern candidates (P31 S61 follow-up, all zero-token)
aprop_autodraft: where the seed carries no decl, infer a minimal extern from the MEMBER'S OWN
target .s (decl_from_use, negative-controlled 97.4%/4,702) and place it at BLOCK scope via
insert_decls — file scope collides with the fleet's per-function loose-typing (the ov_SC04_018
lesson). Strictly additive: runs only where the old path refused; genuine refusals keep the old
behaviour with the class named.
integration_resolver: (1) a CC1/CPP verdict is billed to the DRAFT only after the split TU passes
a TU-alone compile probe WITHOUT the draft — else TU-BROKEN, no demotion, auto-reopened when the
TU's hash changes (S61: one broken TU was billed to 39 drafts; one-off sweep over the CC1 stock:
1 broken TU of 55, 39 verdicts reclassified). (2) dup-def→extern demotion: a draft that DEFINES
data a still-stubbed sibling .s in the same TU also emits dies at the assembler with 'symbol
already defined' — invisible to rtu (INCLUDE_ASM neutralized). Single-line file-scope defs whose
symbol a sibling .s emits are demoted to extern as an ADDITIONAL candidate (new sha, so the
ledger's unchanged-skip does not hide it). Smoke test: md_MAIN_003/func_800D3204 demoted
D_800D3200 → rtu MATCH (12 ins); the whole-binary SHA remains the sole arbiter.
2026-08-26 01:14:36 -06:00
Drew T 40dea1c2a2 fix(aprop): three more decl-layer defects, each traced to a wrong-name or wrong-scope lookup
1. decl_for searched the DESTINATION for the SEED's name: a RENAMED symbol's
   destination spelling can only exist under the MEMBER's name, so the
   destination preference silently never applied to renamed data symbols
   (D_801B9DF8 adopted the seed's 'short' against the TU's file-scope 's32').
   dest/fleet tiers now search target_sym; seed tiers keep the seed name.
2. dest_scope is FILE-SCOPE-ONLY (brace-masked): the TUs are full of
   block-scope externs inside banked bodies, and a flat regex adopted one of
   those as 'the destination spelling' over the DEFINE macro's true file-scope
   decl.
3. A body-embedded block extern that diverges from the destination file scope
   is rewritten to the destination spelling when every use is ADDRESS-ONLY
   (type is codegen-irrelevant for &sym); valued uses keep the seed spelling.
+ fix_tu_ret_decls.draft_ret now parses K&R definitions (its first run SKIPped
  30 of 32 because the param decls sit between ')' and '{').
2026-08-24 23:19:47 -06:00
Drew T 3d1a79a70c fix(aprop): reloc --fix keyed by (binary,fn); lane gains rtu second-chance, MISMATCH auto-repair, borrow-tier decls
reloc_identity --fix's rowmap keyed rows by fn alone, so three same-named
func_8013BCDC rows across binaries all received ONE binary's draft — 2 of 4
'no textual occurrence' refusals were the tool editing the wrong file. Keyed
by (binary, fn): 4/4 repaired to AGREE/MATCH (byte-checked by re-run).

maintenance.sh: stage on status in {AGREE,UNRESOLVED} AND shape==MATCH keyed
(binary,fn); run reloc --fix on MISMATCH rows and re-check so repairs stage the
same pass; add rtu_second_chance for standalone COMPILE-FAILs (7/27 measured
TU-byte-MATCH, previously dropped unjudged).

aprop_autodraft decl_for gains the BORROW tier: when both home TU and seed are
silent, adopt a sibling TU's extern spelling under the same body-compatibility
guards — 'which TU may conflict' (home only) and 'where a guess may come from'
(anywhere) are different questions; refusing outright left 125 members undrafted.
2026-08-24 22:29:29 -06:00
Drew T b2c2b23007 fix(aprop): S59 lane overhaul — four measured defects, each byte-diagnosed before the fix
Baseline measured on the 21:04 pass (117 staged, 0 banked): 82 near real-diff /
19 standalone compile-fail / 16 near-0 TU-integration; zero drafts invisible to
the gate (the 'drafts: 0' probe was the triage harness racing itself — a shared
per-fn probe dir rm -rf'd by a concurrent triage run, not lane plumbing).

1. K&R definitions (aprop_autodraft.kr_definition): the near-0 class is the TU's
   own '(void)' decls + empty K&R call sites rejecting the draft's ANSI def
   ('too few arguments' after the arity pre-pass relaxes the decls). K&R the def
   when every param is promotion-safe; byte-proven MATCH on func_80162CCC's real
   TU (rtu_match) where the ANSI form CC1-failed.
2. decl_for scope: the destination is the HOME TU ONLY, macro-expanded
   (dest_scope) — the whole-binary concat adopted spellings the home TU never
   declares; and a dest spelling is adopted only when the seed body can compile
   against it (void-return-value guard + call-arity guard; measured 42 and 15
   fresh drafts died on each before the guards).
3. Ordinal IMM pairing is now a CANDIDATE SET (family_remap._ordinal_candidates):
   the single-guess form paired the first spelling's occurrences only and shipped
   35 of 117 drafts with value/offset swapped ('*(p+3)=2' for '*(p+2)=3',
   closeness-2 forever); candidates are adjudicated with match_one at draft time.
4. Staging filter (maintenance.sh): stage only AGREE + shape==MATCH, keyed by
   (binary, fn) — status-only staging burned 82 whole-binary builds per pass on
   drafts match_one had already refuted, every 45 minutes.
+ tools/rtu_second_chance.py: standalone COMPILE-FAIL is the wrong oracle for a
  TU-destined draft; re-judge those against the real TU (rtu_match) and stage
  the MATCHes.
2026-08-24 22:22:12 -06:00
Drew T 6a48a490fc fix(recovery): validate the binary before staging; aprop_autodraft adopts the TU's spelling and refuses asm bodies
MY BUG, SAME DAY, SAME CLASS. recover_rejects staged by the binary field of
aprop_symfix's output slate — and aprop_symfix tags its REBASE VARIANTS into that
field (ov_MAIN_012-cn, -cn-cast, -cn-cast-rc, -s2in, -s2in-uni). Staged verbatim,
each variant became its own directory and sweep_parallel was handed 273 directories
naming binaries THAT DO NOT EXIST: 553 drafts that could never be gated against
anything, while the sweep reported 'over 331 binaries'. It now resolves the variant
tag back to a real binary, keeps ONE variant per target, and COUNTS what it cannot
resolve (R43). The 290 bogus staging dirs are cleaned; 118 real drafts remain.

aprop_autodraft, per Drew:
  * decl_for prefers the DESTINATION TU's own spelling and falls back to the seed's
    only when the destination is silent (wave law 2 — the destination is
    authoritative; 45 of 188 staged drafts declared a conflicting type).
  * it REFUSES a seed whose body is a verbatim __asm__ block. Those transcribe
    instructions rather than decompiling them, trivially 'MATCH' the local oracle
    because they ARE the target's bytes, and would count as matched functions in every
    progress number while nothing was decompiled. 26 of 188 were this shape. §265 is a
    deliberate human escape hatch for hand-written asm, not something an unattended
    lane propagates across a family.

Measured before changing the drafting prompt instead: model waves bw/bx/by/bz produced
ZERO whole-body asm across 530 drafts, so this is a tool behaviour, not a model one. A
blanket 'no asm' rule on every card would have cost us the sanctioned one-line levers
(§5a fences, §17 register pins) that appear in 32-47 drafts per wave.
2026-08-24 21:33:32 -06:00
Drew T e7d61e823d feat(phase-30 S50): bank the top-reach families 0x801F1CD8 (41/41) and 0x8017D290 (9/9)
Three carries a mechanical seed-body draft needs beyond the symbol rebase (cookbook §171b),
each found from one compiler verdict:

- DATA DEFINED INSIDE THE MEMBER'S OWN .s must be DEFINED, not externed — it vanishes with
  the stub it lives in. Re-initialised with THIS member's bytes (the 0x801F1CD8 family carries
  4 distinct 8-byte patterns across 42 members). Flat-byte-list initializers only; refuse the
  rest rather than mis-initialise something the gate would reject unexplainably.
- SHARED TYPES the destination cannot see: MATRIX/SVECTOR live in engine_types.h, which md_*
  TUs never include. `parse error before 'm1'` was the only thing between 4 of 9 members and a
  bank. Carried brace-matched, vetoed by the destination.
- A POSITIONAL LITERAL MAP where imm_map_tier1 gives up: it refuses a value that also appears
  at a non-differing slot (0x10 collides with the struct offsets), but the 8 differing slots
  map 1:1 onto the C's call sites in order. Asserted ([C literals] == [seed slot values])
  before substituting — that assert is the whole safety argument. 10/10 refused -> 9/9 banked.

- ROOT-CAUSE FIX: body_text matched `extern void func_X(...);` at column 0 and returned the
  NEXT function's body — silently shipping wrong seed bodies, visible only as "no definition
  after rename" skips. A definition is now confirmed by a `{` with no `;` before it.

R22 clean rebuild: check-all 213 passed, 0 failed of 213. Stubs 12,161 -> 12,111.
Fleet 95.3% instr / 90.0% distinct / 96.66% fn-count.
2026-08-14 11:23:26 -06:00
Drew T e903713b71 feat(phase-30 S50): the mechanical A-prop draft — 256 members banked with no agent in the loop
Final S50 state: 307 instances banked, stubs 12,468 -> 12,161, fleet 95.3% instr / 90.0%
distinct / 96.65% fn-count. R22 clean rebuild 4x, check-all 213/213 every time.

- tools/aprop_autodraft.py + tools/draft_prechecks.py: seed body + symbol_map + a MINIMAL
  synthesized preamble. The seed's decl layer never travels — that layer is family_sweep's
  dominant failure (331 of 458 S49 verdicts). 256 banked at zero agent tokens, against the
  ~20M the same work would have cost as a wave.
- Macro seeds (567 of 1196 members, all 3737 de-macroize) take the DEFINITION only; the block
  stays the decl source. Pasting it whole measured 28% vs inline's 68% — func_8016AB6C's macro
  is 1,891 lines of which 108 are the function.
- IMM is a second engine, not a wall: T2a's imm_map_tier1 resolves a per-location LITERAL like
  symbol_map resolves a per-location SYMBOL. 131 of 275 IMM members resolve.
- draft_prechecks negative-controlled against ALL 205 banked drafts: zero false positives,
  catches 39 of 67 known failures. That control found two bugs in the checks themselves —
  C89 `f()` declares UNSPECIFIED parameters (not zero), and a member's own definition read as
  a call to itself. Conservative by design: a pre-check that discards good drafts is worse
  than one that lets a few builds fail.
- The A-prop pool is now priced exactly: PURE 437/37,376 ins, IMM 275/8,849, STRUCT 238/4,259.
- Cookbook §171a; SETUP rows; CURRENT_PHASE S50 FINAL checkpoint.
2026-08-14 07:42:19 -06:00
Drew T 9a3e438ed9 fix(phase-30 S50): macro seeds carry only the DEFINITION, not the macro's decl layer
Measured on the 489-draft run: inline seeds banked 145/213 (68%), macro seeds 77/276 (28%),
and the macro failures were decl collisions to a fault — 'parse error before *', 'too few
arguments to function'. Cause: a de-macroized DEFINE_ block is decls + definition, and
pasting it wholesale reintroduces the exact decl-agreement failure the minimal-preamble
design exists to avoid. func_8016AB6C's block is 1,891 lines of which 108 are the function.

- seed_body() now returns the DEFINITION as the body and keeps the macro block as the DECL
  SOURCE, so only the externs the definition actually references are emitted.
- aprop_symfix.body_in_text(): text-based sibling of body_text (R33 — one implementation).
  Indented-definition fallback for macro blocks, confirmed by a '{' with no ';' before it,
  so an indented CALL can never be mistaken for a definition.
2026-08-14 05:28:40 -06:00
Drew T f3c509f7e1 feat(phase-30 S50): aprop_autodraft — mechanical A-prop drafts at zero token cost (§171a)
A lane-A member's body IS its matched sibling's body with the per-location symbols rebased.
Two mechanisms had each left that population on the table: family_sweep remaps but CARRIES
the seed's decl layer (decl-agreement = 331 of 458 S49 failures), and the agent wave
re-derives the same body at ~80k tok/fn. This does neither — seed body + symbol_map
(positional reloc zip) + a minimal synthesized preamble.

- Byte-proven before the tool existed: a hand-written draft of exactly this shape banked
  func_801E2858@md_SC03_132, in a family the mechanical sweep had refused. Then 9/9 banked
  on the first generated batch.
- THE SELECTOR, measured: only PURE members (every diff site a RELOC) are drafted. An IMM
  (per-location literal) or STRUCT (register/opcode drift) site cannot be reached by a
  rename — the first 5 gated 0/5, all IMM or STRUCT. classify_member now decides that
  BEFORE a build is spent, not after. --allow-impure to override.
- Macro seeds supported: DEFINE_<fn>() de-macroizes back to a plain self-contained block
  (3737/3737 extract). They were the largest skip bucket — 567 of 1196 members.
- 592 drafts emitted (304 macro / 288 inline) from 1196 members; every skip is named (R32).
- aprop_symfix: asm_syms_ordered() so an n:m card hands over the target's reference ORDER.
- Two defects caught by probes before they scaled: a typedef regex that stopped at the `;`
  INSIDE the struct braces, and a continuation walk that started on the empty pre-newline
  element and returned an empty body.
2026-08-14 00:50:55 -06:00