fix(gate_main): refuse a verbatim-asm draft at slate load

I converted 9 main SDK functions from §265 verbatim bodies to INCLUDE_ASM
stubs so they could be decompiled, then 'banked' all 9 from stored drafts
that were those same verbatim asm blocks. match_one printed closeness 0 nine
times and the whole-binary gate went BYTE-IDENTICAL — both truthfully, since
a raw asm blob assembles to the bytes it was copied from. Nothing was
decompiled. progress.py caught it by not moving: REAL 882, VERBATIM 164,
INCLUDE_ASM 37, identical before and after. The banks are reverted.

The cookbook's closing paragraph, written last session, describes this exact
trap. I read it and hit it anyway ~4 hours later, because the rule was
addressed to 'any burst over this class' and I was hand-picking stored
drafts, and because 'no byte gate can catch it' reads as unpreventable. The
byte CHECK cannot; a slate-load refusal can.

draft_prechecks.is_verbatim_asm_draft: a file-scope __asm__ naming the fn via
.ent/.globl/label AND no C definition of it. Both spellings of .ent handled
(inside a C string it is a backslash-t, not a tab — five censuses of this
class disagreed until that was fixed). gate_main refuses such a slate beside
its existing INCLUDE_ASM no-op refusal (R43).

Census of the draft store: 1,099 of 704,375 .c files are verbatim-asm drafts
under ordinary <fn>.c names. Negative control: 0 false positives across
45,898 drafts carrying both a C definition and an inline __asm__ (R39).
This commit is contained in:
Drew T
2026-09-03 13:20:19 -06:00
parent 9992cab319
commit 9ab0d9eb67
3 changed files with 102 additions and 0 deletions
+45
View File
@@ -35133,3 +35133,48 @@ its own source by construction**. The adversarial verifier refuted it on the rul
containing `__asm__` or `INCLUDE_ASM` is a no-op that passes for free. Any burst over this class MUST
carry that check: the trivially-passing draft is not a hypothetical here, it is the *default* thing to
produce, and a byte gate cannot tell the difference.
#### ADDENDUM to §265 (P31 S76) — THE PROSE GUARD DID NOT HOLD. IT IS A GATE REFUSAL NOW.
**The paragraph immediately above this one was written in S75 and is correct. I tripped over the
exact trap it describes about four hours later, in the next session, having read it.** That is the
finding worth keeping — not the trap, which was already known, but the fact that knowing it in
prose did not prevent it.
**What happened.** The 9 remaining `DECOMPILE-NOW` SDK functions in `src/800c3.c` / `src/800c2_2.c`
were converted from §265 verbatim bodies to `INCLUDE_ASM` stubs *specifically so they could be
decompiled*. I then searched the draft store for stored drafts, scored 195 candidates with
`match_one`, and got **closeness 0 on all nine**. Slate, gate, `BANKED 9 main functions —
143dbb89 BYTE-IDENTICAL`, 58 seconds. Every one of those nine "drafts" was the function's own
assembly, emitted by `tools/asm_verbatim.py` into `<fn>.c` in the same directories as real drafts.
I had converted verbatim → stub → verbatim. A perfect round trip that decompiled nothing.
**What caught it: `progress.py` did not move.** REAL 882, VERBATIM 164, INCLUDE_ASM 37 — identical
before and after "banking nine functions". The instrument was right and the claim was wrong
(`check-against-a-known-true-case`: the count you already know is the cheapest oracle you own).
**Why the prose could not hold.** S75's rule was addressed to a *burst over this class* — "any
burst over this class MUST carry that check". I was not running a burst. I was hand-picking stored
drafts one function at a time, which the rule did not name, and the conditional in a reader's head
("does this apply to me?") is exactly where a prose guard fails. S75 also concluded "a byte gate
cannot tell the difference", which is true and which reads as *unpreventable*. It is not: the byte
CHECK cannot tell, but a **slate-load refusal** can, because the verbatim form is trivially
decidable from the text.
**The guard, where it can actually fire.** `draft_prechecks.is_verbatim_asm_draft(text, fn)` — a
file-scope `__asm__` naming this fn via `.ent`/`.globl`/label, AND no C definition of it. Both
halves matter: a real draft may carry a small inline `__asm__`, and a verbatim body may omit
`.globl` for a static. Match BOTH spellings — `".ent\tNAME"` inside a C string is a *backslash-t*,
not a tab; five S75/S76 censuses of this class disagreed with each other until both were handled.
`gate_main` now refuses such a slate at load, beside its existing `INCLUDE_ASM` no-op refusal (R43).
**The scale of the landmine.** A census of the draft store: **1,099 of 704,375 `.c` files are
verbatim-asm drafts**, sitting under ordinary `<fn>.c` names in ordinary wave directories. Negative
control: **0 false positives across 45,898** drafts that carry both a real C definition and an
inline `__asm__` (R39). Any future "search the store for a stored draft" pass — and that pass is now
a standard move, since S75 banked 20 functions from drafts already on disk — is drawing from a pool
with 1,099 of these in it.
**The general law.** *A lesson that is only prose will be re-learned. If a check is decidable, the
knowledge base is where you explain it and the pipeline is where you enforce it* — the same
relationship R32 sets between "assert your coverage" and a scanner that actually does.
+38
View File
@@ -116,3 +116,41 @@ def undefined_data(binary, dest_text, syms, self_name=None, body=""):
continue
out.append(s)
return out
def is_verbatim_asm_draft(text, fn):
"""True if `text` is the target's own assembly, not a decompile of it (P31 S76).
THE DEFECT THIS CATCHES, and why no byte gate can. `tools/asm_verbatim.py` emits a §265
verbatim body -- the function's own .s pasted into a file-scope `__asm__` string. Those files
sit in the same draft directories as real C drafts and are named `<fn>.c` like everything else.
Score one with match_one and it prints MATCH, truthfully: a raw asm blob assembles to the bytes
it was copied from. Substitute one and the whole-binary gate goes GREEN, also truthfully. The
function is then reported BANKED while nothing whatsoever has been decompiled.
S75 hit this once (an agent submitted the verbatim block as its own "decompile"; only an
adversarial reader caught it) and recorded "No byte gate can" catch it. That is true of the
BYTE check and false of a slate-load refusal, which is why this lives here: the verbatim form
is trivially decidable from the text (R43 -- refuse the input, never mishandle it).
S76 hit it again, from the other direction and at scale: nine functions were converted from
verbatim bodies to stubs precisely so they could be decompiled, then "banked" from stored
drafts that were the same verbatim blocks -- a round trip through the gate that moved
progress.py by exactly zero and read as 9 of 9 MATCH. The instrument was right and the claim
was wrong.
A draft is verbatim iff a file-scope `__asm__` names this function as a .ent/.globl/label AND
no C definition of it exists. Both halves matter: a real draft may legitimately carry a small
inline `__asm__`, and a verbatim body may omit .globl for a static."""
if '__asm__' not in text:
return False
f = re.escape(fn)
# The escaped forms are what the emitters write INTO a C string: `.ent\tfoo\n` is backslash-t,
# not a tab. Match both the escaped and the literal spellings -- five S76 censuses of this
# class disagreed with each other until both were handled.
asm_names = re.search(rf'\.(?:ent|globl)(?:\\t|[ \t])+{f}\b', text) or \
re.search(rf'"\s*{f}:\s*(?:\\n|$)', text)
if not asm_names:
return False
c_def = re.search(rf'^[A-Za-z_][\w \*]*\b{f}\s*\([^;]*\)\s*(?:/\*.*?\*/\s*)?\{{', text, re.M | re.S)
return not c_def
+19
View File
@@ -39,6 +39,7 @@ import hashlib
import time, collections, fcntl, functools, glob, json, os, re, subprocess, sys
sys.path.insert(0, 'tools')
import corpus
import draft_prechecks as DP
# stdout is BUFFERED when redirected to a file -- a long run then looks hung with an
# empty log (measured: 16 min of silence during a bisect). Always flush.
@@ -932,6 +933,24 @@ def main():
'passes for free: %s' % (len(_noop), ', '.join(_noop)))
# THE SAME NO-OP, WEARING C's CLOTHES (P31 S76). A §265 verbatim body is the function's own
# assembly in a file-scope `__asm__` string; `tools/asm_verbatim.py` writes them as `<fn>.c`
# into the same draft directories as real drafts. Substituting one assembles the bytes it was
# copied from, so match_one prints MATCH and this gate goes GREEN -- both truthfully -- while
# nothing has been decompiled. S75 saw it once from an agent and concluded "no byte gate can"
# catch it; that is true of the BYTE check and false of a slate-load refusal. S76 then did it
# at scale: 9 functions converted from verbatim bodies to stubs *so they could be decompiled*,
# then "banked" from stored drafts that were those same verbatim blocks. 9 of 9 MATCH, and
# progress.py moved by exactly zero. Refuse at load, like the INCLUDE_ASM no-op above (R43).
_verb = [e['fn'] for e in slate
if os.path.exists(e.get('draft', ''))
and DP.is_verbatim_asm_draft(open(e['draft'], errors='replace').read(), e['fn'])]
if _verb:
raise SystemExit("gate_main: REFUSED — %d draft(s) are the target's own assembly in a "
"file-scope __asm__ (a §265 verbatim body), not a decompile. They would "
"pass this gate for free and bank nothing: %s"
% (len(_verb), ', '.join(_verb)))
kept, dropped = resolve_conflicts(slate)
print(f"slate {len(slate)} -> {len(kept)} compatible, {len(dropped)} dropped for in-TU decl conflict")
for d in dropped: