Skip to content

spec(tri/pr): preflight -- the own-language budget from the merge base and the developer-home-path scan (Closes #11070) - #11125

Merged
gHashTag merged 1 commit into
masterfrom
t27o/preflight-rules-p1
Oct 19, 2026
Merged

gHashTag merged 1 commit into
masterfrom
t27o/preflight-rules-p1

Conversation

@gHashTag

@gHashTag gHashTag commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

Closes #11070

tri pr preflight (specs/tri/pr/preflight.t27, see #10190) gets the two checks the t27o loop still ran by hand before every push: the own-language foreign-line budget compiled from the merge base, and the developer-home-path scan. A lane learns about both from one command, before CI, instead of from a red check.

What changed (specs/tri/pr/preflight.t27, its generated Rust, its seal)

Step Rule What it reads
budget STEP_BUDGET (17), once R_BUDGET (10) The merge base's own gen/c/policy/own_language.c, compiled around the same one-line check_budget main as .github/workflows/own-language.yml, fed git diff --numstat --no-renames BASE...HEAD.
devhome STEP_DEVHOME (18), once R_DEVHOME (11) python3 -I tools/check_devhome_paths.py.

STEPS 17 -> 19, NO_STEP 17 -> 19, RULES 11 -> 13; R_COUNT ("kept") moves 10 -> 12 and stays the last rule and the default of rule_name / rule_why. Print order: ... census, budget, devhome, kept. One helper changes_under(c, lit) is new for the baseline test and touches_census now calls it (no copied loop); finding_path and names_home read the scan's finding lines.

Verdicts:

  • budget: a line the gate prints (the three messages or the unreadable-numstat line), or any non-zero exit with one, is FAIL. Exit 0 with no output is PASS. Everything else (a compile error, no cc, a failed git, a missing section) is UNREAD. The gate comes only from the merge base: there is no fallback to the branch's copy (CI falls back to HEAD only while the base predates check_budget; here that case reads UNREAD, and rule base fails it anyway). The numstat goes to a file first, so a git that fails leaves the gate no empty input to pass on.
  • devhome: exit 0 and an OK: line is PASS. Exit 1 with FAIL new|grew|shrank|fixed <path> lines fails only for a path the branch changes (any status, so a deleted baseline file is caught by FAIL fixed), or for any finding when the branch edits tools/devhome_baseline.txt or the scan itself. A finding on another file is master's own and does not fail the branch ("own defects only"). A changed path git had to quote cannot be compared with the scan's text, so it is UNREAD when the scan has findings. Exit 2 (no baseline, grep failed), a traceback, a missing python3 and any other shape are UNREAD.

Evidence: PR #10538 (head 1e20cfb, +9/-0 hand lines in cli/tri/src/main.rs)

I ran the committed step_cmd(STEP_BUDGET) text with HEAD at 1e20cfb and origin/master at 2e2ca5f (merge base b4fc955):

git diff --numstat --no-renames b4fc95571...1e20cfb34
9	9	.trinity/seals/t27o_T27oLedger.json
9	0	cli/tri/src/main.rs
218	0	gen/rust/tools/t27o/ledger.rs
57	0	specs/tools/t27o/ledger.t27

gate compiled from b4fc95571:gen/c/policy/own_language.c, exit 1:
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

That output, framed as @@ preflight 17 0 1 212, with the real git diff --name-status of the PR as the changes, goes through the new rule (a scratch spec that uses the preflight functions, not committed):

PASS the_budget_rule_on_pr_10538_is_FAIL      rule_verdict(changes, evidence, R_BUDGET) == P_FAIL; rule_name == "budget"; evidence_step == STEP_BUDGET; the evidence slice holds "more hand-written foreign lines added than deleted"
FAIL negative_control_the_same_evidence_is_not_PASS   (the same call asserted == P_PASS)

So the preflight reports budget FAIL for #10538 and prints the gate's own line as evidence, with the spec's rule_why: "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". The same line is committed as the fixture BUDGET_OUT of rule_budget_fails_on_the_gates_own_output.

Negative controls, real runs: the same step text with HEAD = origin/master exits 0 with 0 bytes of output (PASS); on this branch the budget step exits 0 with no output and the devhome step prints OK: 29 file(s), 37 occurrence(s), all pinned in tools/devhome_baseline.txt (PASS). The four finding shapes of the home-path scan were captured from the real script in a scratch tree; the committed fixtures use them (paths shortened).

Tests

  • Tests first: the five new tests and three extended ones failed (6 failed of 24) before the rules were written, and passed after.
  • t27b test specs/tri/pr/preflight.t27: 24 passed, 0 failed, 1 invariant held.
  • t27c test-report specs/tri/pr/preflight.t27 --specs-dir specs: 24 pass, 0 FAIL, vacuous passes 0 of 24.
  • t27c seal specs/tri/pr/preflight.t27 --save then --verify: all four hashes MATCH; gen-rust regenerated, byte-identical on a second run, and the base spec reproduces the base file byte for byte with the same binary. t27c check: Typecheck OK.
  • New tests: rule_budget_fails_on_the_gates_own_output, rule_budget_fails_closed, the_budget_gate_is_compiled_from_the_merge_base (no HEAD:gen/c/..., no #include "gen/c/policy), rule_devhome_fails_for_a_file_the_branch_changes, rule_devhome_fails_closed. Extended: the_steps_are_named_and_ordered, the_changes_are_read_entry_by_entry, the_exit_is_the_worst_rule, each_rule_and_verdict_says_what_it_means, and the numbering invariant.

Own language, DRY

  • Own-language: the diff is 3 files (spec, its generated Rust, its seal); the budget gate compiled from the merge base prints nothing and exits 0; check_all exits 0. Foreign lines added: 0. cli/tri/src/prcheck.rs is not touched.
  • python3 -I tools/dupe_scan.py: on this branch and on a clean copy of the merge base 2e2ca5f the output is the same (632 group(s), 1632 duplicate bodies, "ok: no new duplicate body, and none of the known groups grew"; the total body count is 17432 -> 17434). No ::error:: finding on either side; the 15 inherited findings the lane brief mentions did not appear in this scan. dupe_scan.py --like specs/tri/pr/preflight.t27: "nothing in this file is written elsewhere".
  • python3 -I tools/check_devhome_paths.py: OK on this branch; no developer-home literal in the diff.

The glue

The task brief says the glue is cli/tri/src/prcheck.rs preflight. It is not on master: docs/now/2026-10-18-pr-preflight.md records it as parked (38 lines, refused by the foreign-line budget), and no ref in the local object store carries it. So there is no glue to change and none was read. The new steps need only what the spec header already promises: sh -c step_cmd(k) for every step step_runs accepts, run once (they are not step_each), at the repository root, no SPEC, T27C or TRI. When the glue lands it must iterate 0..STEPS and 0..RULES as the header says; if it hard-codes 17 and 11 it needs the same two numbers changed.

Not run

  • tri pr preflight itself (no glue, no tri build; the cargo build was out of scope for this lane).
  • The full t27c test-report over the corpus, t27c suite --ratchet, tools/check_seal_coverage.py and tools/check_seal_currency.py (they need target/release/t27c, which is not built here), tri types ratchet (the diff declares no struct or enum).
  • .trinity/seals/land_TriLand.json lists preflight in its closure with the previous spec hash. t27c seal --verify does not read the closure (it prints all hashes MATCH for land) and t27b test specs/tri/land/land.t27 still passes 26/26, so land was not re-sealed (outside the issue boundary); a re-seal would only refresh that closure entry.
  • No edit to docs/reports/t27b_expectations.json (the preflight row stays pass) or to .claude/skills.

🤖 Generated with Claude Code

… developer-home-path scan are two more steps and rules (Closes #11070)

specs/tri/pr/preflight.t27 gains STEP_BUDGET and STEP_DEVHOME (the steps become 19) and
R_BUDGET and R_DEVHOME (the rules become 13, kept stays the last).

budget: the step compiles gen/c/policy/own_language.c as it is at the merge base of
origin/master and HEAD -- never the branch's copy -- around a one-line main that calls
check_budget, and feeds it git diff --numstat --no-renames BASE...HEAD, as the "Foreign-line
budget" step of .github/workflows/own-language.yml does. The numstat goes to a file first, so a git
that fails leaves the gate no empty input to pass on. A line of the gate's own text, or its
exit, fails the rule; exit 0 with no output passes; anything else (a compile error, no cc, a
git that failed) is UNREAD.

devhome: the step runs python3 -I tools/check_devhome_paths.py. Exit 0 with its OK line
passes. Exit 1 with FAIL lines fails only for a finding that names a file the branch changes
(new, grew, shrank, fixed), or for any finding when the branch edits the baseline or the scan
itself; a finding on another file is master's own and does not fail the branch. A path git
quoted cannot be matched against the scan's text, so it is UNREAD. Exit 2 (no baseline, grep
failed), a crash and any other shape are UNREAD.

Tests first: 5 new (budget verdicts, budget fails closed, the merge-base gate command, devhome
verdicts, devhome fails closed) plus the steps, labels and worst-exit tests extended; 24 tests,
0 vacuous. The PR #10538 head 1e20cfb (+9/-0 in cli/tri/src/main.rs) is a fixture: the gate
compiled from its merge base prints the shrink-only line and exits 1, the rule reads FAIL.
changes_under replaces the loop in touches_census (no copied body). Generated Rust and seal
are regenerated by t27c; no glue change (cli/tri/src/prcheck.rs is not touched).

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

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-19 18:16:12 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)=e34e1b174c96 != 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: add the own-language budget and the developer-home-path rules the t27o loop runs by hand

2 participants