Commit Graph

4 Commits

Author SHA1 Message Date
Drew T bb65d36341 fix(phase-26a): A1 — dedup_integrate was a gate that could print a FALSE GREEN
The audit's priority #1: a fail-closed byte-honesty validator whose silent skips nothing
downstream can catch. Three false-green paths, all measured, all now fail-closed with
negative controls.

R33 FIRST (derive, don't re-derive). The registry makes two claims; the tool only ever
checked one, and mis-described that one:
  C1 EQUIVALENCE ("these vrams hold the same code in the ORIGINAL") — checked against the
     sigs, which sign the ORIGINAL bytes. KEPT. But the docstring claimed it also caught
     SOURCE drift: it cannot. A sig is a property of the ROM, immutable w.r.t. src/. Source
     drift is caught by the BUILD. Docstring corrected (P9).
  C2 BANK ("matched once in the source header, instantiated at every member") — NEVER
     CHECKED. Now DERIVED from the build invariant: INCLUDE_ASM pastes the ORIGINAL asm, so
     a member NOT wrapped in it is byte-exact, and one that IS wrapped is not banked —
     whatever the registry says. C2a: the group's macro token must occur in its source file.
     C2b: no member may still be an INCLUDE_ASM stub.

THE THREE FALSE GREENS
 1. 1808 groups claimed a DEFINE_func_* macro; only 1801 exist. The 7 ghosts printed [ OK ] —
    hiding 532 member-instances / 22,344 instructions of REAL, UNBANKED work (4 fns matched in
    ov_SC01_077, still INCLUDE_ASM in the other 133 overlays).
 2. An absent .run/sig.<bin>.jsonl degraded to "0 validated, 0 failed" and EXIT 0. On a fresh
    clone the gate validated NOTHING and passed. Now fails; --allow-unsigned is the escape.
 3. The bank claim was never checked at all.

THE CAUSAL CHAIN (the audit's thesis in one example). 3 of the 4 hidden fns are defined in
ov_SC01_077_jr_8012ACE0.c — a _jr_* split file. dedup_propagate.overlay_files allowlists only
("_a","_o0","_o0b","_after"), so the propagator could not SEE them; the group was registered
anyway; dedup_integrate greenlit the lie. TWO silent-skip bugs compounding: one created the
hole, the other hid it. Harvest fuel -> .run/audit/a1_harvest_fuel.json, banked in A5.

BLAST RADIUS, MEASURED NOT PREDICTED (R14). Headline metrics UNCHANGED to the decimal
(instr-weighted 66.5%, distinct-code 46.8%) — weighted_metrics() derives from the invariant and
was structurally immune to the lying registry. FLEET REAL substantive unchanged (282,466):
progress.py had already been taught to distrust it (commit:0574). Only dedup_integrate still
believed it. A null result that CONFIRMS R33: the tool that refused to re-derive was the one
that was right.

- registry repaired: 1813 -> 1806 groups (7 ghosts removed; instances 223,725 -> 222,787)
- make report GREEN end-to-end: 1806 validated, 0 failed | C1 coverage 222,787/222,787 signed
- negative controls: stubbed member -> exit 1; missing sig -> exit 1; --allow-unsigned -> exit 0
- report-only tool: no compiled artifact depends on it, so no R22 clean-fleet is owed here
2026-07-14 02:50:28 -06:00
Drew T aefe2eac18 feat(phase-15): T5a — bulk-propagate 553 shared functions fleet-wide (3.82% -> 22.14%)
- dedup_propagate --auto-from ov_SC01_077: propagated 553 already-matched, self-contained
  shared engine functions across all 134 overlays, each byte-gated. 9 functions skipped
  (use 077-local struct types -> not mechanically liftable; honest, P9). One R22 CLEAN
  rebuild: 136/136 byte-identical.
- fleet REAL 947 -> 74,527; byte-identical 13,132 -> 76,174 / 344,010 = 22.14%; 561 dedup
  groups, dedup-check 561 validated / 0 failed
- tool hardening for fleet scale: registry SHORTHAND (vram + binaries; dedup.us.yaml ~4k
  lines vs ~77k verbose); per-overlay apply (one read/write per file); gate-only-changed;
  skip already-registered (additive/resumable); compile pre-filter (body must build with
  common.h alone); group_members() reader (both forms) in dedup_integrate + progress;
  progress _DEDUP_CACHE (fleet 6m -> 7s)
- the first bulk attempt fail-closed-reverted on a local-typed body (byte-gate working) ->
  added the compile filter; cookbook 14a documents the 5 fleet-bulk lessons
- ghidra/ churn NOT staged (R23)
2026-06-16 20:35:39 -06:00
Drew T a8ae190fa3 feat(phase-11): T3 — intra-binary collapse PROOF (one body, two addresses, byte-identical)
- src/shared/clearTbl40.h: CLEAR_TBL40 macro = the matched byte-clear loop body, authored ONCE;
  instantiated at both func_80037004 and func_80037334 in src/800.c (one source -> two vrams)
- matched first try; clean rebuild main -> 143dbb89 BYTE-IDENTICAL WITH the shared C AND WITHOUT
  it (INCLUDE_ASM stub fallback) -> dual invariant proven (R22 clean rebuilds, both states)
- config/dedup.us.yaml: I0_clearTbl40 group registered (h_exact a0744d60…); dedup_integrate
  --check validates it; negative tests (corrupt hash / wrong vram) fail-closed (exit 1)
- tools/progress.py: count dedup-shared members as REAL via the registry (the macro form isn't a
  parseable function def); REAL 52 -> 54, byte-identical 50.24% -> 50.33%; honest measurement (P9)
- tools/dedup_integrate.py: display vram in hex in diagnostics
- the machinery half of the Phase-11 milestone is proven on the byte-verified EXE
2026-06-16 00:56:35 -06:00
Drew T b06d74c1be feat(phase-11): T2 — dedup.us.yaml registry + dedup_integrate byte-honesty validator
- config/dedup.us.yaml: cross-binary code-share registry (group -> {id,tier,hash,
  source,func,members[{binary,vram,name}]}); empty for now (T3 adds the first group)
- tools/dedup_integrate.py: --check validator. Fail-closed if a shared function's
  current sig hash drifted from the recorded hash (a stale share can never silently
  mislead, P9/G3); unsigned binary -> WARN (unvalidated), not a hard fail
- Makefile: dedup-check is the fail-closed last line of `make report` (gated BINARY=main)
- DEVIATION D1: game-code dedup is SOURCE-LEVEL (shared body in src/shared/<fn>.h,
  instantiated per site), NOT a psyq_integrate object-swap — game funcs are interior to
  one object per binary so the linker can't swap them; the byte-gate is the existing
  per-binary make check. .ld interpose stays the library mechanism (Phase 8)
- verified: --check passes on empty registry; make report runs it; clean rebuild main
  -> 143dbb89 BYTE-IDENTICAL (T2 is a proven build no-op, R22)
2026-06-16 00:47:20 -06:00