Skip to content

policy: a foreign-line budget no label lifts, and a local list from origin/master (Closes #7371) - #7399

Merged
gHashTag merged 1 commit into
masterfrom
claude/own-language-budget-7371
Oct 7, 2026
Merged

gHashTag merged 1 commit into
masterfrom
claude/own-language-budget-7371

Conversation

@gHashTag

@gHashTag gHashTag commented Oct 7, 2026

Copy link
Copy Markdown
Owner

Closes #7371

Why

The owner ordered this in chat on 2026-10-07 (translated): make lefthook stop agents that write hand-written foreign code. #7363 landed 804 hand-written Rust lines in bootstrap/src/service.rs through three holes in the Only-t27 gate:

  • locally the exception list was read from the working tree, so a branch could list itself;
  • in CI the label owner-approved-foreign waived the whole check, and the label is applied through the same account the agents use;
  • an exception covered a whole file with no limit on its growth.

What

  • specs/policy/own_language.t27: check_budget() caps hand-written foreign additions at 40 lines per file and 80 per diff, read from git diff --numstat --no-renames. It reads no exception list, and no label lifts it. Deletions are free. Specs, generated roots, prose and data do not count; the gate's own foreign files do. Unreadable lines fail closed.
  • gen/c/policy/own_language.c: regenerated with t27c gen-c on the Railway lab.
  • lefthook.yml: own-language reads the list from origin/master; new foreign-budget command on pre-commit and pre-push.
  • .github/workflows/own-language.yml: a budget step with no label condition, compiled from BASE (HEAD only while BASE predates check_budget).
  • own-language is now a required status check in the master ruleset (the owner's decision in chat).

Label

owner-approved-foreign is set because this PR changes the gate's protected files, on the owner's explicit order in chat. The owner made the commit and the push himself (LEFTHOOK=0), because the gate denies every local change to its own files. The label waives the path check only; the new budget step still runs on this PR (34 foreign lines added).

Verified

  • Lab: 32/32 zig tests; the C test main exits 0.
  • 19/19 hand mutants killed: limits 40/80 moved both ways, > vs >=, each counted kind dropped, the protected/generated/own branches flipped, binary -, empty path, digit bounds, base 10, the total and unreadable failures.
  • Negative control: the verified: t27c signs receipts and run-record judges their level -- R3-1 tool half (Closes #7332) #7363 merge diff gives 3 DENYs (service.rs, signed_receipt_reader.rs, the 80-line total). 7 of the last 30 master commits would have been denied.

🤖 Generated with Claude Code

…rigin/master (Closes #7371)

The Only-t27 gate had three holes, all used by #7363 (804 hand-written Rust
lines in bootstrap/src/service.rs):

- locally the exception list was read from the working tree, so a branch
  could list itself;
- in CI the label owner-approved-foreign waived the whole check, and the
  label is applied through the same account the agents use;
- an exception covered a whole file with no limit on how much it may grow.

The rule now has check_budget() in specs/policy/own_language.t27: at most
40 added hand-written foreign lines per file and 80 per diff, read from
`git diff --numstat --no-renames`. It reads no exception list and no label
lifts it. Deletions are free; specs, generated roots, prose and data do
not count; the gate's own foreign files (lefthook.yml, its workflow) do.
Unreadable numstat lines fail closed.

- gen/c/policy/own_language.c regenerated with t27c gen-c (Railway lab).
- lefthook.yml: own-language reads the list from origin/master; a new
  foreign-budget command on pre-commit and pre-push.
- own-language.yml: a budget step with no label condition, compiled from
  BASE (HEAD only while BASE predates check_budget).
- own-language is now a required check in the master ruleset.

Verified on the lab: 32/32 zig tests, the C test main exits 0, 19/19 hand
mutants killed (limits 40/80 moved both ways, > vs >=, every counted
kind dropped, protected/generated/own branches flipped, binary '-',
empty path, digit bounds, base 10, the total and unreadable failures).
Negative control: the #7363 merge diff gives 3 DENYs (service.rs,
signed_receipt_reader.rs, the 80-line total). This diff adds 34 foreign
lines. Committed by the owner with LEFTHOOK=0: the gate denies every
local change to its own files, by design.

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

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-07 09:31:50 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 38
PRs with All Checks Green 12
READY 1
FAILING 38
PENDING 0
NO CHECKS YET 0

These columns do not partition: 1 + 38 + 0 + 0 = 39, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=1aa228450491 != 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).

@gHashTag
gHashTag merged commit 3df7065 into master Oct 7, 2026
24 of 30 checks passed
gHashTag added a commit that referenced this pull request Oct 7, 2026
…oses #7453) (#7454)

`tri census pin --gate` is red on master. Two moves were found by running the
census at each commit that touched a workflow, on the Railway lab:

- quiet "named a path but not quiet" 167 -> 181 came from #7320 (33756b3).
  Its master-failure-discount block adds 14 non-quiet lines that name a path.
  "steps in a quiet shape" stays 30. Two quiet steps now name
  specs/queen/merger_gate.t27, so they move from "no path ANYWHERE" (9 -> 7)
  to "a tracked path, present" (10 -> 12). #7388 already re-blessed this.
- quiet 181 -> 182 and shell "run: steps" 301 -> 302 (runner 280 -> 281) came
  from #7399 (3df7065). It adds the foreign-line budget step to
  own-language.yml: one more runner step, plus one non-quiet line naming
  gen/c/policy/own_language.c. NOBODY stays 15, and quiet shapes stay 30.

No quiet step was added, so this re-bless is legitimate.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Oct 7, 2026
…allet v1 from 999-multibots-telegraf (#7477)

The three specs existed only as vendored copies in gHashTag/999-multibots-telegraf
(apps/vibee-editor/render/src/spec/ and packages/vibee-atoms/src/spec/), so 999's
check-t27-specs --t27 failed t27-same for each (999#3828). They are copied byte
for byte from 999 origin/main to the paths their own headers name, with seals.

test-report --verbose (judged by the table):
- browser-tab-strip: 10 tests, 10 pass, FAIL 0, 0 vacuous
- owner-studio: 2 tests, 2 pass, FAIL 0, 0 vacuous
- token-wallet: 6 tests, 6 pass, FAIL 0; "the warnings come at seven, three
  and one day left" counts 0 runtime asserts (const-folded), but setting
  WARN_DAYS_FIRST=2 turns it red, so it discriminates.
Negative controls in scratch copies: POLL_MS 3000->2999, STUDIO_COUNT 3->4,
MARKUP_PCT 200->199 each gave FAIL 1.

Census re-bless in this commit: quiet "named a path but not quiet" 181->182 and
shell "run: steps" 301->302 (runner-named 280->281). Neither is moved by this
change; master drifted with #7399's new workflow step and the pre-commit gate
refuses any commit until the ledger matches. #7454 carries the identical bless.

Closes #7463
Closes #7464
Closes #7465

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Oct 7, 2026
…er 84 -> 110 (Refs #5906) (#7482)

* corpus: judge the 26 type conflicts the port batches added, and re-bless the ledger 84 -> 110 (Refs #5906)

Corpus Ratchet's step "A type name may not gain a second definition"
(`tri types ratchet`) and the classified cross-check (`tri types
classified`) are red on master: 26 names gained a second definition in
the 2026-10-06/07 batch merges of port specs, and none had a verdict.

Every one was read: both (or all) definitions opened, fields compared,
and the reading written into docs/reports/type_conflicts_classified.json
with evidence, confidence and a suggested repair. 18 DRIFT, 8 DISTINCT.
docs/TYPE_CONFLICTS.md gains the 26 rows (its tables regenerate the
old 84 rows byte-for-byte from the JSON) and its stale header counts
(51/37 against a JSON of 50/34) now read the JSON's 67/43.

The ledger docs/reports/type_conflicts.json rises 84 -> 110 via
`tri types ratchet --bless`. That is a loosening, stated on purpose:
every added name is a real conflict that is now judged and carries a
repair, and the repairs are cross-module decisions about port specs
that do not belong in a CI-unblocking change. The ratchet still refuses
the 111th name.

Census re-blessed, byte-identical to #7454: quiet 181 -> 182, shell
run: steps 301 -> 302, both moved by #7399.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(type-conflicts): the 26 new names split 17 DRIFT / 9 DISTINCT (Refs #5906)

The previous commit's prose and message said 18/8; the JSON and the
table headers (67/43 = 50+17 / 34+9) were right. Inputs is DISTINCT,
following the Outputs precedent for the same files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Oct 7, 2026
…#7476)

The ledger is rewritten by `tri t27b ratchet --bless --accept-new` from a full
t27b Railway lab corpus run at master ba161bb (1539 of 1539 files, --jobs 2,
reference = that head's t27c; crash 0, mismatch 0, JIT/interpreter mismatch 0,
reference disagree 0 of 992). The four specs master added or changed up to
848490e were run again with the same binaries. The result is byte-identical
to the lab's blessed ledger, and the ratchet of the run against it is green.

Moves: 123 pass_vacuous -> pass, plus 224 new rows (170 pass, 12 pass_vacuous,
39 blocked, 3 codegen). Counts pass 535 -> 828, pass_vacuous 262 -> 151,
not_pass 24 -> 66; the cap rise of 42 is all new specs.

specs/policy/own_language.t27 keeps master's pass row (lab, cfda070); since
#7399 it uses @intcast, which t27b blocks (lane 4, #7412).

Refs #6063

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Oct 7, 2026
…es own_language (Refs #7023) (#7479)

#7399 wrote `@as(u32, @intcast(c - '0'))` in added_lines. `c - '0'` is
already a u8 that @as widens to u32 losslessly; the @intcast adds nothing,
and t27b refuses it (ExprCall(@intcast), lane 4, #7412), so the t27b-native
ratchet row for specs/policy/own_language.t27 went from pass to fail.

`@as(u32, c - '0')` says the same thing. gen/c/policy/own_language.c is
regenerated with `t27c gen-c` (one line: a redundant pair of parentheses).

t27b test specs/policy/own_language.t27: 32 passed, 0 failed (was a
compile refusal). t27c test-report: 0 of 32 vacuous.

Census re-blessed (tri census pin --bless), byte-identical to #7454:
quiet `named a path but not quiet` 181 -> 182 and shell `run: steps`
301 -> 302, both moved by #7399's new own-language.yml step. Without it
the pre-commit census gate refuses every commit on master.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Oct 7, 2026
…nflict (Refs #7383) (#7488)

Follows #7386. That PR added `pub const Entry = struct { name, value }` to
specs/tri/utils/template.t27, but master already declares a type `Entry` in
specs/port/browseros/trios/agent-server/apps/server/src/tools/filesystem/ls.t27,
so `tri types ratchet` reports `+ Entry NEW conflict`. Rename the template's
struct to TemplateEntry at all six uses in that file; no other spec touched.

Evidence (merge of this branch with PR #7482, local scratch, not pushed):
  tri types ratchet               observed 111 -> 110, RATCHET CLEAN
  t27c test-report template.t27   3 pass, 0 fail, 0 vacuous
  t27c seal --verify template.t27 all hashes MATCH (both seal files resealed)
  check_seal_currency / check_seal_coverage / check_duplicate_declarations  rc 0

Census re-bless, not caused by this change: master is already off its pin
since #7399 (.github/workflows/own-language.yml adds one run: step), which
moves quiet "named a path but not quiet" 181 -> 182 and shell "run: steps"
301 -> 302 ("the runner does" 280 -> 281). `tri census explain` names that
file as the only mover for both. The pre-commit census gate refuses every
commit on master until re-blessed, so tools/census/{quiet,shell}.txt are
re-recorded here with `tri census pin --bless`.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Oct 7, 2026
#7537)

* t27b: the Mach-O object layout and bytes are a t27 spec (Closes #7526)

specs/tri/t27b/macho.t27 states the MH_OBJECT writer: the mach_header_64,
LC_SEGMENT_64 with its __text and __const sections, LC_BUILD_VERSION,
LC_SYMTAB and LC_DYSYMTAB, the alignment math, the relocation pairs and
the nlist_64 entries. Its 15 tests assert the exact bytes master's Rust
wrote for three inputs. t27c gen-rust gives gen/rust/tri/t27b/macho.rs,
which cli/t27b/src/macho.rs mounts the way check_budget is mounted.

cli/t27b/src/macho.rs: +21 glue, -153 hand Rust. Generated: 278 lines.
Spec: 476 lines. t27b build over all 1552 specs: the 980 objects are
byte-identical to master's; the t27b lab corpus counts are unchanged
apart from the new spec itself, mismatch 0, cargo test 126/126.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci/affected: Markdown anywhere and seal files select nothing (Closes #7527) (#7529)

The selector sent every path outside specs/ to RUN_ALL. Over the last 400
first-parent master commits that ran everything on 373 of them, 208 because
of docs/*.md alone, so wiring it into CI would have saved almost nothing.

Two exceptions, both things no spec test reads: a .md file anywhere is
prose, and .trinity/seals/*.json is the verdict record t27c writes, not an
input. .txt stays RUN_ALL outside specs/ (tools/*.txt are baselines).

Measured on the lab with the regenerated gen/c/ci/affected.c: 284 of 400
commits are now selective, median 1 affected spec of 1545, p90 5, max 49.
15/15 tests (zig and the C runner); 5/5 mutants of the new lines killed.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* gen-rust: wrap a value returned from a ?T fn in Some (Closes #7534) (#7536)

* gen-rust: wrap a value returned from a ?T fn in Some (Closes #7534)

gen-rust lowered a `?T` return type to `Option<T>` and `return null;` to
`return None;`, but a plain value return reached rustc as is: E0308 at
`return (x / 2);`. expr_to_rust_as, which every return and fn tail goes
through, now wraps the value in `Some(..)` when it is surely not optional
already (literal, operator, cast, struct, tuple, `x.?`, or a name or call
whose declared type is not Option). `null`, an optional local, a call to a
`?T` fn and anything of unknown type pass through unchanged, so output
that compiled before is not double-wrapped. The width cast for a narrower
integer goes inside the `Some`.

Fixture: specs/compiler/rust_optional_returns.t27. The compiler.rs seal
moves in bootstrap/stage0/FROZEN_HASH (shasum -a 256 of the new file).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* spec(compiler): no lone ; line in the rust_optional_returns header (Refs #7534)

A ; alone on a line made the parser read the next comment as a statement
(parse error at line 6). Joined the two comment paragraphs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* seals: gen_hash_rust for the 16 seals whose Rust output the Some wrap changes (Refs #7534)

Only the gen_hash_rust line moves, and only in seals whose gen_hash_rust
held with the master binary (7959d8b): 9 specs, 16 seal files, of 1400
checked (1394 held with master). Computed by `t27c seal` with this
branch's binary on the Railway lab.

Each moved output was compiled with rustc on the lab, master vs this
branch: no new rustc error in any of the 9; E0308 drops by one or two in
array, bitmap, net, regex and bytes. The other four stop at a parse error
before type checking, unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* seal: compiler_RustOptionalReturns for the #7534 fixture (Refs #7534)

t27c seal --save with this branch's binary on the Railway lab, zig on PATH:
7 of 7 tests pass. Without a seal the suite's seal-verify phase counts the
new spec as a failure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* t27b: the A64 instruction encoders come from specs/tri/t27b/a64.t27 (Closes #7531) (#7535)

Port slice of #6198. The functions that build one 32-bit AArch64 instruction
word from register numbers and immediates, the Cond/Ext/Shift/LogOp enums, the
register and access-kind constants and the two patch helpers move from
hand-written cli/t27b/src/a64.rs into specs/tri/t27b/a64.t27. cli/t27b mounts
its `t27c gen-rust` output gen/rust/tri/t27b/a64.rs the way main.rs mounts
check_budget.rs; the encoder `b` is `branch` in the spec (the Zig prelude's
assert_eq(a, b) shadows a fn named b, #7532) and is re-exported as `b`.

Hand Rust: -531 lines, +11 glue (a64.rs 1067 -> 547). Generated: 531 lines.
Spec: 1253 lines, 30 tests, all with runtime asserts.

Still hand-written in a64.rs: impl Cond (invert/name/from_bits), bitmask_imm,
logic_imm (now calls the generated logic_imm_word), mov_imm and the
disassembler. bitmask_imm/logic_imm wait on #7534 (gen-rust does not wrap a
?T return value in Some).

Checks: spec asserts hold on the old hand Rust and on the generated Rust;
18.6M random-argument words identical between the two; 56 words checked
against LLVM's assembler; 639 literal mutants of the encoder half: 582
killed, 52 rejected by the compiler, 5 equivalent. t27b lab, head vs master
ec5c3cf over the same 1553-file tree: pass 844, pass_vacuous 151, fail 16,
blocked 536, mismatch 0 on both, per-file verdicts/tests/asserts identical;
`t27b asm` output byte-identical for all 995 passing files (10.85 MB);
cargo test -p t27b 126 passed, 0 failed.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* t27b ledger: batch bless from a full lab run on master (Closes #7432) (#7476)

The ledger is rewritten by `tri t27b ratchet --bless --accept-new` from a full
t27b Railway lab corpus run at master ba161bb (1539 of 1539 files, --jobs 2,
reference = that head's t27c; crash 0, mismatch 0, JIT/interpreter mismatch 0,
reference disagree 0 of 992). The four specs master added or changed up to
848490e were run again with the same binaries. The result is byte-identical
to the lab's blessed ledger, and the ratchet of the run against it is green.

Moves: 123 pass_vacuous -> pass, plus 224 new rows (170 pass, 12 pass_vacuous,
39 blocked, 3 codegen). Counts pass 535 -> 828, pass_vacuous 262 -> 151,
not_pass 24 -> 66; the cap rise of 42 is all new specs.

specs/policy/own_language.t27 keeps master's pass row (lab, cfda070); since
#7399 it uses @intcast, which t27b blocks (lane 4, #7412).

Refs #6063

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* spec(policy): drop a redundant @intcast in added_lines so t27b compiles own_language (Refs #7023) (#7479)

#7399 wrote `@as(u32, @intcast(c - '0'))` in added_lines. `c - '0'` is
already a u8 that @as widens to u32 losslessly; the @intcast adds nothing,
and t27b refuses it (ExprCall(@intcast), lane 4, #7412), so the t27b-native
ratchet row for specs/policy/own_language.t27 went from pass to fail.

`@as(u32, c - '0')` says the same thing. gen/c/policy/own_language.c is
regenerated with `t27c gen-c` (one line: a redundant pair of parentheses).

t27b test specs/policy/own_language.t27: 32 passed, 0 failed (was a
compile refusal). t27c test-report: 0 of 32 vacuous.

Census re-blessed (tri census pin --bless), byte-identical to #7454:
quiet `named a path but not quiet` 181 -> 182 and shell `run: steps`
301 -> 302, both moved by #7399's new own-language.yml step. Without it
the pre-commit census gate refuses every commit on master.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* specs(tri): TemplateEntry, not Entry, so template.t27 adds no type conflict (Refs #7383) (#7488)

Follows #7386. That PR added `pub const Entry = struct { name, value }` to
specs/tri/utils/template.t27, but master already declares a type `Entry` in
specs/port/browseros/trios/agent-server/apps/server/src/tools/filesystem/ls.t27,
so `tri types ratchet` reports `+ Entry NEW conflict`. Rename the template's
struct to TemplateEntry at all six uses in that file; no other spec touched.

Evidence (merge of this branch with PR #7482, local scratch, not pushed):
  tri types ratchet               observed 111 -> 110, RATCHET CLEAN
  t27c test-report template.t27   3 pass, 0 fail, 0 vacuous
  t27c seal --verify template.t27 all hashes MATCH (both seal files resealed)
  check_seal_currency / check_seal_coverage / check_duplicate_declarations  rc 0

Census re-bless, not caused by this change: master is already off its pin
since #7399 (.github/workflows/own-language.yml adds one run: step), which
moves quiet "named a path but not quiet" 181 -> 182 and shell "run: steps"
301 -> 302 ("the runner does" 280 -> 281). `tri census explain` names that
file as the only mover for both. The pre-commit census gate refuses every
commit on master until re-blessed, so tools/census/{quiet,shell}.txt are
re-recorded here with `tri census pin --bless`.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

owner-approved-foreign Owner-approved exception to the only-t27 rule: hand-written foreign code allowed in this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Only-t27 gate: a foreign-line budget the label cannot lift; local hook reads exceptions from origin/master

1 participant