You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
gen/c: 32 of 43 tracked C copies are stale since 2026-07-05, and L2 does not check a spec changed without its copy #7103
gen/ holds the generated copies of the specs (L2). On master 96cf7c8, 32 of the 43 tracked gen/c/*.c files that have a spec at specs/<path>.t27 are not what t27c gen-c of that spec prints today.
Every one of the 32 was last written by one commit on 2026-07-05 (ea15cd5):
ar/* (7)
base/ops, base/types
compiler/parser
fpga/* (5)
isa/registers
math/constants, math/sacred_physics
nn/attention, nn/hslm
numeric/* (10)
queen/lotus
vsa/ops
They differ by 166 to 2626 diff lines each.
The 11 that match are exactly the ones a tool or a gate compiles:
policy/own_language
queen/priority and queen/review_valve
tri/catalog/health
tri/t27b/* (5)
ci/affected and ci/delivery_metrics
Nothing in scripts/, tools/, cli/ or .github/ reads the 32 stale copies.
Docs still point at them:
docs/NUMERIC_FORMATS_SSOT.md links gen/c/numeric/gf16.c as the C codegen;
README.md names gen/c/numeric/ as a header source.
A second gap lets this keep happening. tools/l2_regen_check.py (#6226) checks a modified gen/ file against t27c gen-<backend>. It does not check a modified spec whose tracked copy stayed as it was.
PR #7091 hit this. It added test asserts to specs/queen/priority.t27 and review_valve.t27 and did not regenerate their C copies, and no gate said so. tri priority builds gen/c/queen/priority.c. I found it by hand and fixed it in 5b338c7.
Measurement
Run from a worktree, so that use resolves; a spec copied to /tmp changes the output:
for g in $(git ls-files gen/c); do s=specs/${g#gen/c/}; s=${s%.c}.t27; [ -f $s ] || continue
t27c gen-c $s | diff -q - $g >/dev/null && echo SAME $g || echo DRIFT $g; done
gen/c/vsa/core.c has no spec at specs/vsa/core.t27 and is not counted.
Fix
Gate, both directions. L2 also lists the specs a PR modified. For each one that has a tracked gen/<backend>/<path> copy, it runs the same byte compare. A spec change with a stale copy then fails the way a hand-edited copy does.
The 32 stale copies. For each, either regenerate it with t27c gen-c, which the only-t27 rule allows as t27c output, or delete it if nothing should read a C copy of that spec.
The docs that link a deleted copy are fixed in the same PR.
Scope correction and the fix, measured 2026-10-06T21:05Z on branch claude/gen-c-drift-7103 (local, three commits on master 96cf7c8; the PR opens after #7091 and #7092 land, one PR at a time).
The issue undercounted the drift. It said 32 of 43 gen/c copies. Measured with every tracked copy regenerated by the master t27c, the drift was:
32 gen/c copies;
the same 32 specs in gen/verilog;
gen/rust/memory/notebooklm.rs;
two orphans, gen/c/vsa/core.c and gen/verilog/vsa/core.v. Their spec specs/vsa/core.t27 does not exist; specs/vsa_core.t27 does.
Decision: delete, not regenerate. Commit 2b74dc600 drops 65 tracked copies.
No tool, script, workflow or build reads them (git grep of each deleted path, outside gen/ and docs/now). Prose mentions three paths: STATUS.md and FORMAT_REGISTRY.md say TF3 is generated to gen/verilog/numeric/tf3.v, which stays true of t27c gen-verilog; fpga/uart.v and fpga/mac.v are named in an ADR, docs/NOW.md and a wave report, all history.
A copy nobody reads goes stale again at the next gen-c change.
Kept: 14 copies. 11 C copies that match and are read (ci/affected, ci/delivery_metrics, policy/own_language, queen/priority, queen/review_valve, tri/catalog/health, tri/t27b/{dogfood,fuzz,fuzz_oracle,reduce,steward}), gen/rust/tri/t27b/check_budget.rs, and gen/c/numeric/gf16.c + gen/verilog/numeric/gf16.v. The gf16 pair is left to #6996 item 5.
The other direction (commit 2af2517a4, closes this issue).tools/l2_regen_check.py now also checks a tracked copy when its spec, or any spec in its use closure, is added, modified or deleted in the PR. gen-c splices imports, so a changed import changes the copy. Copies of specs the PR did not touch are not charged to it, so a gen-c change does not turn every PR red. --all checks every tracked copy. The workflow file is unchanged: --list now prints these copies, so the step builds t27c for them.
Controls, old script vs new, in a throwaway worktree:
case
old
new
DENY changed in specs/policy/own_language.t27, no copy regenerated
ok, rc 0
2 STALE COPY (own_language.c and its importer ci/affected.c), rc 1
only the importer's copy left behind
-
1 STALE COPY, rc 1
both copies regenerated
-
ok, rc 0
spec deleted, copy kept
-
"no spec", rc 1
this branch, PR mode
-
ok, rc 0
this branch, --all
-
12 of 14 t27c output; gf16.c (byte 362) and gf16.v (byte 469) NOT OUTPUT, rc 1
The script is foreign Python: an edit to an existing tool, listed in tools/policy/foreign-exceptions.txt, and the PR carries the owner-approved-foreign label. The debt is moving the L2 rule into a spec, as specs/policy/own_language.t27 did for the Only-t27 gate.
Activity
gHashTag commentedon Oct 6, 2026
Scope correction and the fix, measured 2026-10-06T21:05Z on branch
claude/gen-c-drift-7103(local, three commits on master 96cf7c8; the PR opens after #7091 and #7092 land, one PR at a time).The issue undercounted the drift. It said 32 of 43 gen/c copies. Measured with every tracked copy regenerated by the master t27c, the drift was:
gen/rust/memory/notebooklm.rs;gen/c/vsa/core.candgen/verilog/vsa/core.v. Their specspecs/vsa/core.t27does not exist;specs/vsa_core.t27does.Decision: delete, not regenerate. Commit 2b74dc600 drops 65 tracked copies.
git grepof each deleted path, outside gen/ and docs/now). Prose mentions three paths: STATUS.md and FORMAT_REGISTRY.md say TF3 is generated togen/verilog/numeric/tf3.v, which stays true oft27c gen-verilog;fpga/uart.vandfpga/mac.vare named in an ADR, docs/NOW.md and a wave report, all history..gitignore.lexer::TokenKind::RBrace) is still refused -- 477 in the specs #5712 family; regeneratedgf4.creferencessacred_physics::PHI_INVverbatim).Kept: 14 copies. 11 C copies that match and are read (ci/affected, ci/delivery_metrics, policy/own_language, queen/priority, queen/review_valve, tri/catalog/health, tri/t27b/{dogfood,fuzz,fuzz_oracle,reduce,steward}),
gen/rust/tri/t27b/check_budget.rs, andgen/c/numeric/gf16.c+gen/verilog/numeric/gf16.v. The gf16 pair is left to #6996 item 5.The other direction (commit 2af2517a4, closes this issue).
tools/l2_regen_check.pynow also checks a tracked copy when its spec, or any spec in itsuseclosure, is added, modified or deleted in the PR. gen-c splices imports, so a changed import changes the copy. Copies of specs the PR did not touch are not charged to it, so a gen-c change does not turn every PR red.--allchecks every tracked copy. The workflow file is unchanged:--listnow prints these copies, so the step builds t27c for them.Controls, old script vs new, in a throwaway worktree:
DENYchanged in specs/policy/own_language.t27, no copy regenerated--allThe script is foreign Python: an edit to an existing tool, listed in
tools/policy/foreign-exceptions.txt, and the PR carries the owner-approved-foreign label. The debt is moving the L2 rule into a spec, asspecs/policy/own_language.t27did for the Only-t27 gate.Merge origin/master into claude/l2-rule-in-spec-land (Refs #7113)
policy: the L2 GENERATION rule lives in specs/policy/l2_generation.t2…
t27b: tail expressions and discarded calls as the reference prints th…
ci(spec-guards): published figures are red only for a defect of the c…