Repository navigation
tri mutate: load survivors.t27 and lab.t27 through gen-rust, drop the hand copies #7472
Copy link
Copy link
Closed
Labels
Description
Problem
cli/tri/src/mutate.rs holds two hand-written Rust copies of rules that already live in t27:
- the survivor gate (
gate_on,unaccepted,survivor_exit,mutate_exit, near line 1325), a copy ofspecs/tri/mutate/survivors.t27; mod lab(133 lines, near line 1376), a copy ofspecs/tri/mutate/lab.t27.
Each copy is kept honest by a test that evaluates every assert row of its spec against the Rust (the_gate_agrees_with_every_assert_row_of_its_spec, the_lab_rules_agree_with_every_assert_row_of_their_spec). That is two homes for one rule, plus a small evaluator to compare them. Since #7433, mutate.rs loads specs/tri/mutate/census.t27 through t27c gen-rust (gen/rust/tri/mutate/census.rs, a #[path] module, as cli/t27b loads check_budget.rs), so the copies are no longer needed.
Plan
t27c gen-rust specs/tri/mutate/survivors.t27andspecs/tri/mutate/lab.t27intogen/rust/tri/mutate/(force-added; L2 compares them with the spec).- Replace each hand copy with a
#[path]module of the generated file; call sites use the module's names. - Drop the agreement tests and their evaluator once nothing is left to compare; the spec's own tests compile into the generated module.
- A rule the generator cannot lower yet is filed against t27c and its copy stays, named in the PR.
Acceptance criteria
grep -c 'fn survivor_exit\|^mod lab {' cli/tri/src/mutate.rsprints 0.cargo test --release -p tri mutate::passes on the lab, andtri mutate spec --file specs/queen/priority.t27 --accepted Fgives the same exit and the same lines as before the change.git diff --numstatshows more hand-written Rust lines removed than added.
Boundary
cli/tri/src/mutate.rs
gen/rust/tri/mutate/
User Scenarios
- Given
cli/tri/src/mutate.rscontains hand-written copies ofsurvivors.t27andlab.t27rules, whent27c gen-rustgenerates Rust modules for both specs intogen/rust/tri/mutate/, then the hand-written copies are replaced with#[path]imports of the generated modules and call sites use the module's names. - Given agreement tests (
the_gate_agrees_with_every_assert_row_of_its_spec,the_lab_rules_agree_with_every_assert_row_of_their_spec) and their evaluator exist to compare hand-written Rust against spec asserts, when the hand-written copies are removed, then the agreement tests and evaluator are dropped because the spec's own tests compile into the generated modules.
Requirements
- FR-001:
t27c gen-rustMUST generategen/rust/tri/mutate/survivors.rsfromspecs/tri/mutate/survivors.t27andgen/rust/tri/mutate/lab.rsfromspecs/tri/mutate/lab.t27. - FR-002: The hand-written survivor gate (
gate_on,unaccepted,survivor_exit,mutate_exitnear line 1325) incli/tri/src/mutate.rsMUST be replaced with a#[path]module importing the generatedsurvivors.rs. - FR-003: The hand-written
mod lab(133 lines near line 1376) incli/tri/src/mutate.rsMUST be replaced with a#[path]module importing the generatedlab.rs. - FR-004: The agreement tests and their evaluator code MUST be removed once no hand-written copies remain to compare.
- FR-005:
cargo test --release -p tri mutate::MUST pass andtri mutate spec --file specs/queen/priority.t27 --accepted FMUST produce the same exit code and output lines as before the change.
Reactions are currently unavailable
Activity
gHashTag commentedon Oct 7, 2026
Implemented locally as 3560eb7 on
claude/tri-mutate-gen-rules-7472. It is stacked on #7475 and will be pushed after #7475 merges, because the Actions queue holds 864 queued runs.Two changes from the plan above:
t27c gen-rustemits declarations only. The generated files say so in their first lines:NOT LOWERED BY THIS BACKEND: 10 test(s)insurvivors.rs, and21 test(s)inlab.rs. Deletingthe_gate_agrees_with_every_assert_row_of_its_specandthe_lab_rules_agree_with_every_assert_row_of_their_specwould leave no Rust-side run of the specs' asserts. So both tests now evaluate every assert row against the generated Rust instead of the hand copy. A row that fails there means one of two things: the lowering disagrees with the spec, or agen/rustfile is stale.lab.t27:var jandvar fitare nowconst. Neither is reassigned. Asvar, gen-rust lowered them tolet mut, which would add twounused_mutwarnings to the tri build.Lab results:
mutate.rs: 20 lines added, 198 removed.mutate::tests pass.trigive byte-identical stdout and the same exit code for spec-full (0), spec-minus-one-accepted (2) and census (0).Census of
specs/tri/mutate:lab.t27are equivalent boundary flips; the commit body lists each one with the reason.census.t27drop the step of a scan loop, so the loop never ends.gHashTag commentedon Oct 7, 2026
Taken: the work for this issue is done and pushed as branch claude/tri-mutate-gen-rules-7472 (3560eb7) (lab-verified; see the branch's docs/now entry). It lands as a PR after #7475 merges (one PR at a time while the Actions queue is long). A bee need not start this issue; a bee branch for it would duplicate that commit.
refactor(tri): mutate loads the survivor gate and lab rules from gen-…
refactor(tri): a mutate --lab run uploads any number of files (Refs #…