Skip to content

ci(drift): iterate committed gen dirs directly (gen = SSOT) for C and Zig legs - #365

Merged
gHashTag merged 1 commit into
mainfrom
ci/gen-ssot-dynamic-drift
Aug 9, 2026
Merged

ci(drift): iterate committed gen dirs directly (gen = SSOT) for C and Zig legs#365
gHashTag merged 1 commit into
mainfrom
ci/gen-ssot-dynamic-drift

Conversation

@gHashTag

@gHashTag gHashTag commented Aug 9, 2026

Copy link
Copy Markdown
Owner

The C-execution, C-drift, and Zig-drift legs each carried a hand-maintained spec list disjoint from the gen/ directory they check. That let gen files fall out of coverage: tri_challenge had committed gen/c and gen/zig, was executed by C-exec, but was absent from both the C-drift and Zig-drift lists — so a stale gen for it could have landed silently. Same structural gap that hid the broken rti_security until wave 51.

Fix: refactor the three loops to iterate their gen directory directly:

for spec in $(ls gen/c/*.c    | sed 's#^gen/c/##; s#.c$##'    | sort)
for spec in $(ls gen/zig/*.zig | sed 's#^gen/zig/##; s#.zig$##' | sort)

gen/{c,zig}/ is the single source of truth now: every committed gen is executed / drift-checked, none can be dropped from a list, and a newly committed gen auto-joins its gate. Closes the tri_challenge gap (C-drift → 75 == gen/c, Zig-drift → 106 == gen/zig).

Verified locally against the full committed gens: dynamic C-exec 75/75 run-green, dynamic C-drift 75/75 byte-exact, dynamic Zig-drift 106/106 byte-exact. YAML re-parses clean; loop bodies unchanged.

Complements the wave-55 icarus coverage guard — now the C and Zig legs are self-sourcing from gen/ too.

🤖 Generated with Claude Code

… Zig legs

The C-execution, C-drift, and Zig-drift legs each carried a hand-
maintained spec list disjoint from the gen/ directory they check. That
let gen files fall out of coverage: tri_challenge had committed gen/c
and gen/zig, was executed by C-exec, but was ABSENT from both the C-drift
and Zig-drift lists -- so a stale gen for it could have landed silently.
Same structural gap that hid the broken rti_security until wave 51.

Refactor the three loops to iterate their gen directory directly:

  for spec in $(ls gen/c/*.c   | sed 's#^gen/c/##; s#.c$##'   | sort)
  for spec in $(ls gen/zig/*.zig | sed 's#^gen/zig/##; s#.zig$##' | sort)

gen/{c,zig}/ is the single source of truth now: every committed gen is
executed / drift-checked, none can be dropped from a list, and a newly
committed gen auto-joins its gate. Closes the tri_challenge gap (C-drift
75->75 == gen/c, Zig-drift 105->106 == gen/zig).

Verified locally against the full committed gens: dynamic C-exec 75/75
run-green, dynamic C-drift 75/75 byte-exact, dynamic Zig-drift 106/106
byte-exact. YAML re-parses clean; loop bodies unchanged.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@gHashTag
gHashTag merged commit 11756ee into main Aug 9, 2026
4 checks passed
@gHashTag
gHashTag deleted the ci/gen-ssot-dynamic-drift branch August 9, 2026 02:05
gHashTag added a commit that referenced this pull request Aug 9, 2026
…gen (#366)

Completes the gen-is-SSOT refactor (C and Zig landed in #365) for the
Rust drift leg. It carried a hand-maintained 69-spec list while gen/rust
holds 86 committed files -- 17 committed gens were NOT drift-checked at
all, the same 'gen exists but is un-gated' gap this series has been
closing.

Two parts:
  1. Resync gen/rust/twr_timestamp.rs. Wave 54 changed the spec
     (t_end - t_start -> t_end -% t_start) but intentionally left the
     Rust gen stale because it was ungated; now that the leg checks it,
     regenerate it (-> (t_end).wrapping_sub(t_start)).
  2. Dynamize the loop:
       for spec in $(ls gen/rust/*.rs | sed 's#^gen/rust/##; s#.rs$##' | sort)
     Every committed gen/rust is now drift-checked; a new gen/rust/*.rs
     auto-joins.

Verified locally: all 86 gen/rust byte-match t27c gen-rust modulo
rustfmt (0 drift). twr_timestamp is not #[path]-included in src/lib.rs,
so the resync does not touch build+test. YAML re-parses clean.

With this, all three committed-gen backends (Rust, C, Zig) are
gen-SSOT-driven -- no committed gen can escape its gate.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: SSD DDD <ssdm4@MacBook-Pro.local>
gHashTag added a commit that referenced this pull request Aug 9, 2026
…han closed) (#368)

tri_settle was the final spec still missing an execution backend beyond
icarus/C: it panicked under zig on two counts. The narrowing u64->u32
cast in reward_weighted was fixed compiler-side (t27#1999); the second
was round_add's wrap-detect saturating idiom
(let sum = round_total + epoch_bytes; if (sum < round_total) ...) on a
plain '+', which zig-safe arithmetic aborts on before the guard runs.

Switch that site to '+%' (wrapping) -- a no-op for C and Verilog, which
already wrap by width, and explicit for zig. tri_settle now passes all
17 test blocks under zig, with icarus (17/17) and C still green.

Regenerate its gens: gen/rust flips to .wrapping_add() (rust-drift,
dynamic since #366), and gen/zig/tri_settle.zig is committed for the
first time -- the dynamic Zig-drift leg (#365) picks it up automatically,
no list edit. gen/c is byte-identical ('+%' lowers to '+').

With this, every spec in the corpus executes in at least the icarus and
C backends, and tri_settle joins Rust/Zig too. gen/ regeneration via the
no-gen-edits escape (LEFTHOOK=0).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: SSD DDD <ssdm4@MacBook-Pro.local>
gHashTag added a commit that referenced this pull request Aug 9, 2026
…both (#373)

The zig-test gate compiles and RUNS committed gens -- it is a real
execution gate, not just a drift diff -- but it still iterated a
hand-maintained list while gen/zig became the SSOT for drift in #365.
The list had drifted: six specs had committed, drift-checked gens that
were NEVER EXECUTED here --

  rti_security, tri_compute_account, tri_compute_bond,
  tri_compute_pool, tri_settle, twr_timestamp

precisely the specs closed in the execution-orphan series (#361, #363,
#368). Their gens were verified locally at the time; CI never ran them.

Iterate gen/zig directly, so a newly committed gen auto-joins execution
the same way it auto-joins drift. Verified locally over the FULL
committed set: zig test 107/107, zero failures.

Also applies the #372 coverage-floor pattern to both execution gates
(zig 107, C 75). A loop that silently matched zero files previously
reported green having executed NOTHING; now it fails loudly. C-exec was
already dynamic (#365) but had no floor.

The stale 'gated to the passing set / tracked in t27#1928' header is
corrected: the saturation idiom it referred to is fixed in-spec via
'+%', and the whole committed set passes.

Verified: zig 107/107 executed, C 75/75 executed, both exit 0; a
zero-match loop correctly trips the floor.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: SSD DDD <ssdm4@MacBook-Pro.local>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant