Skip to content

tri pr preflight: land the glue net-zero, paid by deleting inflight's unused merge_outcome (Closes #11126) - #11207

Merged
gHashTag merged 3 commits into
masterfrom
t27o/preflight-glue-g2
Oct 20, 2026
Merged

gHashTag merged 3 commits into
masterfrom
t27o/preflight-glue-g2

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Closes #11126

What

tri pr preflight [--quick] exists now. tri pr --help lists landed, ready and preflight.

The glue is preflight in cli/tri/src/prcheck.rs: 40 added lines in that file (the #[path] mount of gen/rust/tri/pr/preflight.rs at lines 22-23, the Preflight { quick } subcommand at 125-130, one dispatch line at 135, the function at 166-194). It holds no rule:

  • it loops k over the spec's STEPS and keeps the steps step_runs(k, quick) says run, so the steps spec(tri/pr): preflight -- the own-language budget from the merge base and the developer-home-path scan (Closes #11070) #11125 added (STEP_DUPES_BASE, STEP_BUDGET, STEP_DEVHOME) run without a glue change; a per-target step runs once per entry of the CHANGES output that is_target, with SPEC set to path_start..path_end of that entry;
  • each run is sh -c step_cmd(k) with SPEC, T27C (default t27c on PATH) and TRI (the running binary) in the environment, framed as @@ preflight <k> <n> <exit> <len>\n<output>\n (exit 255 when a signal ended it, 127 when the shell could not start);
  • the CHANGES output goes to the spec only when its command exited 0, so a failed git diff is UNREAD (exit 2) and not a FAIL on an error message read as a diff;
  • it prints rule_name, name and, for a rule that did not pass, rule_why and the evidence_from..evidence_to slice of evidence_step; the last line is preflight_exit_why, and the process exits with preflight_exit (0 every rule passed, 1 a rule FAILed, 2 evidence could not be read);
  • it runs at the repository root (git rev-parse --show-toplevel), and prints one progress line per run on stderr.

tools/queen/publish.py is not touched.

What pays for it (own-language net-zero, no exception)

git diff --numstat --no-renames BASE...HEAD, counted foreign files only: cli/tri/src/prcheck.rs +40 / -0, cli/tri/src/inflight.rs +0 / -52. Net -12. Per-file cap 40, total cap 80, gate compiled from the merge base cf2d61eb1 (the own-language step), rc=0. tools/policy/foreign-exceptions.txt is not touched.

Deleted: pub enum Merge, pub fn merge_outcome(rc: i32) -> Merge and the test module outcome_tests (3 tests) in cli/tri/src/inflight.rs. Proof it is dead:

  • cargo check -p tri on master cf2d61eb1 lists enum Merge and function merge_outcome as never used (inflight.rs), and run in that file, the only entry point of tri merging, never calls it;
  • the only callers anywhere in the tree (grep over the whole repository, cli/tri/src included) are the three tests deleted with it; the same-named merge_outcome(ran_ok, on_branch) in prcheck.rs is another function with another signature and its tests are untouched;
  • no gen/ mount, #[cfg(test)] module, doc or script refers to it;
  • the lesson it encoded (exit 128 is a refusal, not a conflict) stays in the module doc of inflight.rs.

Honest limit: there is no item in cli/tri/src with no caller at all. cargo check -p tri --tests on master prints no never-used warning, so each of the 11 never-used warnings of the plain build is an item with a test caller. This deletes 2 of them (Merge, merge_outcome) because they and their three tests form one block that nothing else leans on: no other test, no doc, no gen file. I left the other nine warnings alone; deleting any of them means editing tests that exercise other code or a module doc that describes the design (merkle_root and hash_pair_test are used by the depin proof tests, gf16_inv by the full-rank test of the champion weights, mutable_sites by eight gates tests, CONTROL_IS_ALSO_A_GATE by a gates test, PidPath is the first half of the piddir.rs module doc, renum::plan and vsim::label by their modules' tests), and the pair above already covers the 40 lines. Open PRs deleting the same lines: none (no open PR touches cli/tri/src, specs/tri/pr/preflight.t27, its gen file or its seal; 43 non-port PRs checked by file list, the port PRs add specs under specs/port/ only).

A spec defect found by running it, fixed in the spec

STEP_DUPES_BASE made its scratch checkout with a bare mktemp -d. On macOS that ignores TMPDIR, so inside a sandbox it fails and git worktree add was handed an empty path: BUG: builtin/worktree.c:464: How come '' becomes empty after sanitization?, exit 134. With a finding in dupe_scan the dupes rule then read UNREAD for a reason that is not the branch's. The step now is d="$(mktemp -d "${TMPDIR:-/tmp}/dupes.XXXXXX")" || exit 3; ... like the budget step, so a failed mktemp ends with 3, never with the 1 that dupe_scan itself exits.

Test first: the_dupes_base_scratch_is_made_under_tmpdir failed (24 pass, 1 FAIL), then 25 tests, 25 pass, 0 vacuous. gen/rust/tri/pr/preflight.rs regenerated with t27c gen-rust (two lines differ: the test count in the header and that command), seal re-saved, t27c seal specs/tri/pr/preflight.t27 --verify prints all hashes MATCH.

The real runs

tri is cargo build --release -p tri of this branch; t27c is the release build of master cf2d61eb1. Every run sets T27C=<that t27c>, ZIG_GLOBAL_CACHE_DIR and a fresh ZIG_LOCAL_CACHE_DIR. Scratch branches were made in a separate worktree from origin/master, committed locally, never pushed.

1. Clean branch (t27o/preflight-glue-g2, head 59fdc5128): every rule PASS, the corpus ratchet NOT RUN

$ tri pr preflight --quick
exit=0
changes PASS
base    PASS
check   PASS
tests   PASS
seal    PASS
types   PASS
dupes   PASS
ledgers PASS
suite   NOT RUN  not run: --quick leaves the corpus ratchet out; the full preflight runs it

census  PASS
budget  PASS
devhome PASS
kept    PASS
exit 0: every rule that ran passed

2. Dupes: a scratch branch from origin/master appends cut_at_copy, a copy of the body of cut_at, to specs/tri/pr/preflight.t27 and re-saves its seal, so the only rule that should fail is dupes

$ tri pr preflight --quick
exit=1
changes PASS
base    PASS
check   PASS
tests   PASS
seal    PASS
types   PASS
dupes   FAIL  a body is already written elsewhere: delete the copy and `use` the one the evidence names
duplicate bodies: 1634 of 17572 in 633 group(s) across 2481 spec(s)
::error::a body written under cut_at is now copied [2] time(s) and was in no ledger

A body written twice is a bug that has to be fixed twice. Reuse the
one that exists, or if this copy is deliberate, say so by moving the
ledger in the SAME commit:
    python3 tools/dupe_scan.py --bless

ledgers PASS
suite   NOT RUN  not run: --quick leaves the corpus ratchet out; the full preflight runs it

census  PASS
budget  PASS
devhome PASS
kept    PASS
exit 1: a rule FAILed -- do not open the pull request

3. Budget: a scratch branch adds 9 hand-written lines to cli/tri/src/main.rs and deletes none (the #10538 shape)

$ tri pr preflight --quick
exit=1
changes PASS
base    PASS
check   PASS
tests   PASS
seal    PASS
types   PASS
dupes   PASS
ledgers PASS
suite   NOT RUN  not run: --quick leaves the corpus ratchet out; the full preflight runs it

census  PASS
budget  FAIL  the foreign-line budget (the merge base's own_language gate) refuses this diff: at most 40 hand-written foreign lines added per file and 80 per diff, never more added than deleted -- write the logic in .t27 and generate it
all files: more hand-written foreign lines added than deleted (owner rule 2026-10-09: no hand-written code in any language but t27 may grow; port it to .t27 and generate it); no exception and no label lifts this

devhome PASS
kept    PASS
exit 1: a rule FAILed -- do not open the pull request

4. Developer home: a scratch branch adds a doc under docs/now/ that names a developer home directory

$ tri pr preflight --quick
exit=1
changes PASS
base    PASS
check   PASS
tests   PASS
seal    PASS
types   PASS
dupes   PASS
ledgers PASS
suite   NOT RUN  not run: --quick leaves the corpus ratchet out; the full preflight runs it

census  PASS
budget  PASS
devhome FAIL  a file this branch changes names a developer home directory (tools/check_devhome_paths.py): take the path from the environment or `git rev-parse --show-toplevel`; never re-bless to hide it
FAIL new     docs/now/g2-scratch-devhome.md  (1 occurrence(s))

  Use `git rev-parse --show-toplevel`, or an environment variable the
  caller sets. Re-bless with: python3 tools/check_devhome_paths.py --bless

kept    PASS
exit 1: a rule FAILed -- do not open the pull request

5a. Fail closed, output of the wrong shape: a scratch branch with a one-line spec edit; python3 on PATH is a stub that prints hello and exits 0, T27C=/usr/bin/true exits 0 and prints nothing

$ PATH=<stub dir>:$PATH T27C=/usr/bin/true tri pr preflight --quick
exit=2
changes PASS
base    PASS
check   PASS
tests   UNREAD  undecided: the command did not run, or its output is not the shape this rule reads

seal    UNREAD  undecided: the command did not run, or its output is not the shape this rule reads

types   PASS
dupes   UNREAD  undecided: the command did not run, or its output is not the shape this rule reads
hello

ledgers PASS
suite   NOT RUN  not run: --quick leaves the corpus ratchet out; the full preflight runs it

census  PASS
budget  PASS
devhome UNREAD  undecided: the command did not run, or its output is not the shape this rule reads
hello

kept    PASS
exit 2: undecided -- a rule's evidence could not be parsed; this is never a pass

5b. Fail closed, a step that did not run: the same branch, T27C=/nonexistent/t27c (the shell answers 127)

$ T27C=/nonexistent/t27c tri pr preflight --quick
exit=2
changes PASS
base    PASS
check   UNREAD  undecided: the command did not run, or its output is not the shape this rule reads
sh: /nonexistent/t27c: No such file or directory

tests   UNREAD  undecided: the command did not run, or its output is not the shape this rule reads
sh: /nonexistent/t27c: No such file or directory

seal    UNREAD  undecided: the command did not run, or its output is not the shape this rule reads
sh: /nonexistent/t27c: No such file or directory

types   PASS
dupes   PASS
ledgers PASS
suite   NOT RUN  not run: --quick leaves the corpus ratchet out; the full preflight runs it

census  PASS
budget  PASS
devhome PASS
kept    PASS
exit 2: undecided -- a rule's evidence could not be parsed; this is never a pass

5c. SPEC names a file that is missing: the same branch with specs/tri/pr/preflight.t27 deleted from the work tree (the diff still names it). The real t27c exits 1 on it, which is a FAIL, not an unreadable output, so the exit is 1; kept is the rule that reads UNREAD (cat of the missing file). The exit is 2 only when no rule FAILs, as 5a and 5b show

$ tri pr preflight --quick
exit=1
changes PASS
base    PASS
check   FAIL  t27c check failed: the spec does not parse or typecheck
Error: No such file or directory (os error 2)

tests   FAIL  a test FAILs, the spec is BLOCKED, or a test passed with 0 runtime asserts (vacuous, T730): make every test assert something that runs
Error: not a file: specs/tri/pr/preflight.t27

seal    FAIL  the seal is missing or does not MATCH: regenerate, run `t27c seal <spec> --save`, commit the seal
Error: No such file or directory (os error 2)

types   PASS
dupes   PASS
ledgers PASS
suite   NOT RUN  not run: --quick leaves the corpus ratchet out; the full preflight runs it

census  PASS
budget  PASS
devhome PASS
kept    UNREAD  undecided: the command did not run, or its output is not the shape this rule reads
exit 1: a rule FAILed -- do not open the pull request

6. The full command once, on the clean branch at head 59fdc5128 (started 08:54:43, ended 09:06:01), the corpus ratchet included

$ tri pr preflight
exit=0
changes PASS
base    PASS
check   PASS
tests   PASS
seal    PASS
types   PASS
dupes   PASS
ledgers PASS
suite   PASS
census  PASS
budget  PASS
devhome PASS
kept    PASS
exit 0: every rule that ran passed

Checks before the push

  • cargo check -p tri: 28 warnings; master has 30; the diff of the two warning lists is exactly the two inflight.rs never-used items gone, 0 new. cargo check -p tri --tests: no never-used warning, no error.
  • cargo test -p tri --bin tri -- inflight:: prcheck::: 70 passed, 0 failed.
  • python3 -I tools/dupe_scan.py: duplicate bodies: 1632 of 17571 in 632 group(s) across 2481 spec(s) and ok: no new duplicate body, the same as the merge base.
  • python3 -I tools/check_devhome_paths.py: OK: 29 file(s), 37 occurrence(s), all pinned.
  • tri types ratchet: RATCHET: CLEAN.
  • T27_SEAL_SKIP_GEN=1 python3 tools/check_seal_coverage.py: OK: 2939 seals, 2826 hold, 113 known-broken.
  • Own-language gate from the merge base on this diff: rc=0 (numbers above).

Not run

  • The whole check_seal_currency.py (it recomputes the four gen hashes of all 2939 seals); replaced by t27c seal specs/tri/pr/preflight.t27 --verify on the one seal this diff changes, and check_seal_coverage.py with the gen recompute skipped.
  • The whole cargo test -p tri (879 tests, some of them build lake packages in the temp dir); only the inflight:: and prcheck:: tests ran.
  • The commit hooks printed no tri binary is built; the commit-time gates did not run: they look for target/release/tri in the worktree, which the shared target dir does not provide. The gates above were run by hand.
  • Nothing from the Queen's side: tools/queen/publish.py does not call this command yet (the note says so under Open).
  • tri pr preflight on Linux or in CI.

🤖 Generated with Claude Code

claude and others added 3 commits October 20, 2026 08:40
… by deleting inflight's unused merge_outcome (Closes #11126)

WIP commit for the real runs; the final message replaces it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… and a failed mktemp ends the step with 3 (Closes #11126)

On macOS mktemp -d with no template ignores TMPDIR. In a sandbox it fails,
and git worktree add was handed an empty path: "BUG: builtin/worktree.c:464"
and exit 134. With a finding in dupe_scan this read as UNREAD for a reason
that is not the branch's. The step now makes its directory as the budget
step does and exits 3 before git is called, so dupe_scan's own exit 1 is
never mistaken for it.

Test first: the_dupes_base_scratch_is_made_under_tmpdir failed 24 pass, 1
FAIL, then 25/25 with 0 vacuous. gen/rust regenerated with t27c gen-rust
(two lines differ), seal re-saved and --verify prints all hashes MATCH.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…es budget and devhome (Closes #11126)

The note said the glue was parked and that nothing calls the spec; the
command now exists. It also listed 19 tests and 11 rules; the spec has 25
tests and 13 rules since #11125.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-20 02:18:42 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 48
PRs with All Checks Green 2
READY 2
FAILING 48
PENDING 0
NO CHECKS YET 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=08d882e79f8d != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

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.

tri pr preflight: land the parked glue net-zero, paid by dead-code deletions (the command does not run today)

2 participants