From 356373efabb08b6470aad01ea43951a69b09ac79 Mon Sep 17 00:00:00 2001
From: Drew T <50529377+Druthulu@users.noreply.github.com>
Date: Tue, 4 Aug 2026 00:16:23 -0600
Subject: [PATCH] =?UTF-8?q?fix(phase-30=20S33b):=20the=20PAIR=20rule=20?=
=?UTF-8?q?=E2=80=94=20my=2042-decl=20relax=20did=20NOT=20unblock=20the=20?=
=?UTF-8?q?lane;=20the=20mirror=20form=20did?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
HONEST CORRECTION to commit:1382. That commit's message implies the 42 `(void)`
relaxes unblocked the PROPAGATE remainder. They did NOT: the re-run banked 0/1
in all 134 overlays with the same error, because DEFINE_func_8016BA68 declares
func_80146C3C `(u8*)` — the MIRROR of the EXTEND-lane pair — and my relax only
touched the `(void)` direction.
Root cause is the R37 shape a third time: I bucketed by SYMBOL and stopped. The
lever is set by the (macro-shape, TU-shape) PAIR, and the same symbol conflicts
in BOTH directions across this fleet. One awk over the macro I was ACTUALLY
fixing — which I ran for the EXTEND macros and not for this one — shows the pair
before a 134-build run. §138 amended with the PAIR rule; correction logged in
CURRENT_PHASE.md rather than rewritten out of history.
The 42-decl relax still stands: byte-neutral, R22 140/140, removes a real
conflict class. It just did not do what I predicted.
THIS commit relaxes the 2 remaining `(u8*)` decls (uses are cast; `()` is
compatible with the (void)/()/(u8*) forms the fleet carries and no decl of this
symbol has a default-promotion param). R22 clean-fleet: 140 passed, 0 failed.
ALSO: tools/overlay_src_split.py `_split_macro_body` — the §134 sweep's one real
target, fixed. It carried the identical single-line-only comment test, and it
decides where a macro body's file-scope externs END, so a multi-line comment
truncated the extern set. SIZED FIRST: 38 live lines in engine_core.h macro
bodies hit it today. Now decides on cdecl._mask (one oracle, R33) with the
length-preservation invariant asserted (R32). Proven both directions by a
control: pre-fix it stopped at `/* multi` carrying 1 of 2 externs and treated the
comment as the definition head; post-fix both externs carry and the def head is
correct. Not in the gate path (only o0_subsplit + jr_isolate_all import it).
---
docs/cookbook-index.md | 12 ++++++------
docs/matching-cookbook.md | 8 ++++++++
phase-ends/CURRENT_PHASE.md | 20 ++++++++++++++++++++
src/shared/engine_core.h | 4 ++--
tools/overlay_src_split.py | 18 ++++++++++++++++--
5 files changed, 52 insertions(+), 10 deletions(-)
diff --git a/docs/cookbook-index.md b/docs/cookbook-index.md
index 4906ba081..f7ac78b4d 100644
--- a/docs/cookbook-index.md
+++ b/docs/cookbook-index.md
@@ -138,7 +138,7 @@
- **§3-The** — three-hypothesis trail, because two of them were wrong and the wrongness is instructive L6864
- **§129** — Post-carve, `rtu_match`/`match_one` COUNT THE JUMP TABLE AS INSTRUCTIONS; and a carve must never be committed without its owner (P30 S28, `func_8013BD74`) L8430
- **§129a** — the target instruction count is INFLATED after a carve L8434
-- **§3-The** — DEFINITION-side alias is the only escape when the fleet canon disagrees on a promoting param L9455
+- **§3-The** — DEFINITION-side alias is the only escape when the fleet canon disagrees on a promoting param L9463
### types, signedness & load/store width (29)
@@ -472,7 +472,7 @@
- **§3-The** — splitting/merging rules (each closed a residual, byte-gated) L8846
- **§137a** — A gate verdict has a TIMESTAMP; re-check it against the draft's mtime L9376
- **§138** — The propagation lanes: a gate refusal is a DECLARATION, and which lever you owe depends on blast radius L9405
-- **§134** — again, in a second tool — and the waiter rule corrected L9472
+- **§134** — again, in a second tool — and the waiter rule corrected L9480
### process, measurement & doctrine (53)
@@ -528,7 +528,7 @@
- **§136g** — When the index points at the WRONG lever: two byte-refuted routings (func_801863B4) L9201
- **§136h** — CORRECTION: the zero-crack pool does NOT "refill with cheap work" (my error, byte-measured) L9230
- **§136j** — The failure MIX flips with function size (measured across four bands, one session) L9292
-- **Rank** — the lane by measured concentration, not by class count L9463
+- **Rank** — the lane by measured concentration, not by class count L9471
### (unbucketed — title matched no symptom vocabulary) (108)
@@ -1028,6 +1028,6 @@
- **§137a** — A gate verdict has a TIMESTAMP; re-check it against the draft's mtime L9376
- **§138** — The propagation lanes: a gate refusal is a DECLARATION, and which lever you owe depends on blast radius L9405
- **§3-The** — triage, cheapest first L9411
-- **§3-The** — DEFINITION-side alias is the only escape when the fleet canon disagrees on a promoting param L9455
-- **Rank** — the lane by measured concentration, not by class count L9463
-- **§134** — again, in a second tool — and the waiter rule corrected L9472
+- **§3-The** — DEFINITION-side alias is the only escape when the fleet canon disagrees on a promoting param L9463
+- **Rank** — the lane by measured concentration, not by class count L9471
+- **§134** — again, in a second tool — and the waiter rule corrected L9480
diff --git a/docs/matching-cookbook.md b/docs/matching-cookbook.md
index e4f83637c..2bf15002a 100644
--- a/docs/matching-cookbook.md
+++ b/docs/matching-cookbook.md
@@ -9432,6 +9432,14 @@ bought 8 of 36 for one token.
says nothing about what is behind it (the S29 law). Fixing `func_8012E5CC` immediately revealed
`func_80147364` at the same site. Re-run after every fix; do not price the lane off the first error.
+**Bucket by the (macro-shape, TU-shape) PAIR — NOT by the symbol.** The same symbol conflicts in
+BOTH directions across the fleet, and the lever differs. `func_80146C3C` cost this lesson twice in
+one session: in the EXTEND lane the macro said `(void)` and the TU `(u8*)`; in the PROPAGATE lane
+the *mirror* — macro `(u8*)`, TU `(void)`. Relaxing only the `(void)` form (42 decls, byte-neutral,
+R22-clean) fixed the first and did **nothing** for the second, which then banked 0/1 in all 134
+overlays. One `awk` over the macro you are ACTUALLY fixing — not its sibling — shows the pair before
+you spend a 134-build run. *Read the declaration of the macro in front of you.*
+
### `volatile` in the host TU is a SCHEDULING BARRIER — and it looks exactly like a codegen wall
The four "undiagnosed DIFF"s in `dedup_extend`'s own header were this. Its correctness argument says
diff --git a/phase-ends/CURRENT_PHASE.md b/phase-ends/CURRENT_PHASE.md
index 7009df1ac..08e36e06e 100644
--- a/phase-ends/CURRENT_PHASE.md
+++ b/phase-ends/CURRENT_PHASE.md
@@ -207,6 +207,26 @@ is either a no-arg call or already cast ⇒ codegen-neutral.
an already-macro-ized group.** Probe: exactly **1** extendable group per ordinary overlay (so the
fleet has no hidden wiring backlog beyond this) ⇒ run it across the 134 non-SC07 overlays.
+## ⚠️ MY WRONG PREDICTION, CORRECTED BY THE BYTES (R14/R37) — and it refines §138
+Commit `commit:1382` relaxed 42 `extern void func_80146C3C(void);` decls and its message implies that
+unblocked the PROPAGATE remainder. **It did not.** The re-run banked **0/1 in every one of the 134
+overlays**, with the same error — because **`DEFINE_func_8016BA68` declares that symbol
+`(u8*)`, not `(void)`**, and the TU declares it `(void)`. That is the **MIRROR** of the EXTEND-lane
+pair, and my relax only touched one direction.
+
+**Root cause (the R37 shape, again): I bucketed by SYMBOL and stopped there.** §138 says "bucket by
+which symbol is named" — that is not sufficient. **The lever is determined by the (macro-shape,
+TU-shape) PAIR**, and the same symbol conflicts in BOTH directions across the fleet:
+· EXTEND lane: macro `(void)` vs TU `(u8*)` → relax the MACRO decl.
+· PROPAGATE lane: macro `(u8*)` vs TU `(void)` → relax the MACRO decl *of the other form*.
+One `awk` over the specific macro's own body — which I ran for the EXTEND macros and NOT for this
+one — would have shown it before the 134-build run. **Read the decl of the macro you are actually
+fixing, not of its sibling.**
+
+The 42-decl relax is still **byte-neutral and still useful** (it removes a real conflict class and
+R22 proved it 140/140) — it simply did not do the thing I predicted. Relaxing the remaining **2**
+`(u8*)` decls is the actual fix for this lane. §138 to be amended with the PAIR rule.
+
## 🧹 THE §134 SCANNER SWEEP — sized, one clear target
Hand-rolled comment tests still outside the `cdecl._mask` oracle:
· **`tools/overlay_src_split.py:345`** (`_split_macro_body`) — **the IDENTICAL single-line-only
diff --git a/src/shared/engine_core.h b/src/shared/engine_core.h
index 2d2160050..eed55adcc 100644
--- a/src/shared/engine_core.h
+++ b/src/shared/engine_core.h
@@ -429,7 +429,7 @@
#define DEFINE_func_8016BA68() \
extern s32 func_80146A6C(s32 a0, void *a1, s32 a2, s32 a3, s32 a4, s32 a5, s32 a6); \
extern s32 func_8014C050(s32 a0, s32 a1); \
- extern void func_80146C3C(u8*); \
+ extern void func_80146C3C(); \
s32 func_8016BA68(s32 arg0, s32 arg1) { \
extern s32 D_80126B58; \
s32 temp_v0; \
@@ -30189,7 +30189,7 @@
#define DEFINE_func_8016BA68() \
extern s32 func_80146A6C(s32 a0, void *a1, s32 a2, s32 a3, s32 a4, s32 a5, s32 a6); \
extern s32 func_8014C050(s32 a0, s32 a1); \
- extern void func_80146C3C(u8*); \
+ extern void func_80146C3C(); \
s32 func_8016BA68(s32 arg0, s32 arg1) { \
extern s32 D_80126B58; \
s32 temp_v0; \
diff --git a/tools/overlay_src_split.py b/tools/overlay_src_split.py
index 29c7e70c4..dbb263f7a 100644
--- a/tools/overlay_src_split.py
+++ b/tools/overlay_src_split.py
@@ -33,6 +33,8 @@ The whole-binary SHA1 byte-gate remains the sole correctness arbiter (G3/P9).
import os
import re
import sys
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+import cdecl # the ONE comment/string masking oracle (Phase 26-A) — see _split_macro_body
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -338,11 +340,23 @@ _MACRO_TABLE = None
def _split_macro_body(body):
"""(leading_externs, def_lines) — a macro body's FILE-SCOPE extern lines (everything
- before the definition header) and the definition itself."""
+ before the definition header) and the definition itself.
+
+ S33: the skip test used to be `startswith("//") or (startswith("/*") and endswith("*/"))`,
+ which sees a SINGLE-LINE comment and is blind to a MULTI-LINE block one — its opening line
+ does not end `*/` and its middle lines start `*`. The loop then treats that comment line as
+ the definition header and returns a TRUNCATED extern set. Measured at the time of the fix:
+ 38 such lines live in engine_core.h macro bodies (the levers document themselves in block
+ comments). Same §134 class fixed in family_remap (S6b D1/D2/D5) and dedup_propagate.find_site
+ (S33). Decide on `cdecl._mask` — one oracle (R33), every comment form, immune to a `/*`
+ inside a string — with the length-preservation invariant asserted, not assumed (R32)."""
+ mbody = cdecl._mask("\n".join(body)).split("\n")
+ if len(mbody) != len(body):
+ mbody = body
out = []
for k, ln in enumerate(body):
s = ln.strip()
- if not s or s.startswith("//") or (s.startswith("/*") and s.endswith("*/")):
+ if mbody[k].strip() == "":
continue
if s.startswith("extern"):
out.append(s)