Skip to content

t27b: ts -- consts, scalar fns and tests as TypeScript, decided in .t27 plans (Closes #9994) - #10047

Merged
gHashTag merged 5 commits into
masterfrom
claude/hungry-hopper-cadb4e
Oct 17, 2026
Merged

gHashTag merged 5 commits into
masterfrom
claude/hungry-hopper-cadb4e

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Closes #9994 (phase 1)

What

t27b ts <file.t27> writes a spec's consts, its pure scalar fns and its tests as one TypeScript module, with real bodies. It covers u8..u32, i8..i32 and bool.

  • Each test becomes export function t27_test_<name>(): number, a self-check that returns how many asserts it ran.
  • Each invariant becomes a self-check too.
  • t27_report() prints the assert table of t27c test-report, line for line.
  • t27_failures() names each check that throws.

Anything outside the subset is refused with exit 2 and t27b: ts: unsupported construct <what> at line <n>.

The decisions and the writer are both in t27, modelled on t27b verilog:

  • specs/tri/t27b/ts_plan.t27 holds the decisions:
    • the types, peer types and coercions
    • folding
    • the operator forms:
      • + - * are checked
      • +% -% *% wrap (*% with Math.imul)
      • / % are unsigned
      • shifts take a width and a sign
      • a narrowing cast truncates
    • reserved names
    • the prelude and the coda
  • specs/tri/t27b/ts_emit.t27 is the writer. It reaches cli/t27b through gen/rust/tri/t27b/ts_emit.rs (generated) and one #[path] mod.

The Rust

The only hand-written Rust is the mod line and the subcommand arm, plus its USAGE line. That comes to +10/-10 lines across cli/t27b/src/lower.rs and main.rs, and the foreign-budget and own-language gates pass. No TypeScript codegen is written by hand.

Evidence (Railway lab, node 24.22.0)

The two targets in the issue:

  • t27b ts specs/queen/dispatch_exit.t27 and t27b ts specs/queen/key_failover.t27 both emit.
  • Every test and invariant passes under node.
  • Each t27_report() is byte-identical to the assert table from t27c test-report: 10 tests (dispatch_exit) and 9 tests (key_failover), 0 vacuous.
  • A negative control was run: one comparison in dispatch_exit flipped, and the failing assert was reported.

Whole-repo sweep, 2050 specs:

  • 96 emit and 1954 are refused with exit 2. There were no panics.
  • All 96 that emit produce an assert table byte-identical to t27c test-report, with no node failures.
  • The most common refusals:
    • const that is no integer or bool: 725
    • UseDecl: 539
    • StructDecl: 258
    • fn whose result is no integer or bool: 107
    • EnumDecl: 74

Counting asserts. test-report does not count an assert whose operands are all compile-time constants (#6509). The TS matches this: such an assert goes through t27_check, which checks it without counting it. Before this change, 23 of the 96 tables differed.

The specs' own checks. t27c test-report:

  • ts_plan: 6/6, 0 vacuous
  • ts_emit: 4/4, 0 vacuous

Both are sealed in .trinity/seals/t27b_T27bTs{Plan,Emit}.json.

Limitations

  • "at line 0". A refused top-level declaration reports at line 0, because the t27c parser records no line for it. Fixing that means changing the parser in compiler.rs, which is out of scope here.
  • Const order. A module-level const whose value does not fold, and which names a const declared below it, would hit TypeScript's temporal dead zone. Every const that folds is written as its value, so the order of those does not matter.
  • Ledger rows not measured. The docs/reports/t27b_expectations.json rows for the two new specs are written as pass, the same as the verilog plan and emit rows. The JIT runs only on arm64 and the lab is x86_64, so t27b-native CI gives the measured verdict.

🤖 Generated with Claude Code

gHashTag and others added 5 commits October 18, 2026 00:03
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gen/rust/tri/t27b/ts_emit.rs is generated from specs/tri/t27b/ts_emit.t27
on the lab; the two seals were saved there too.

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

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-17 17:29:05 UTC

Summary

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

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

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=e769ef021713 != 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 d03afb0 into master Oct 17, 2026
30 of 36 checks passed
gHashTag added a commit that referenced this pull request Oct 17, 2026
The duplicate-bodies gate refused #10047: ts_emit.t27 repeated 18 helper
bodies of verilog_emit.t27 word for word (byte writers, to_front,
line_near, the scope and name resolver, the symbol encoding, the test-tree
builders). They now live once, in specs/tri/t27b/emit_kit.t27, with tests
of their own, and both writers `use` it.

A whole-module `use` of verilog_emit from ts_emit was tried first and does
not work: the splice counts words inside string literals as references, so
ts_emit's "export function" pulled verilog_emit's fn `function`, and the
generated-Rust typecheck refused it against ts_emit's own param_type and
stmts.

Measured on the Railway lab: test-report emit_kit 4/4, ts_emit 4/4,
verilog_emit 5/5, 0 vacuous; dupe_scan: no new duplicate body; t27b ts and
t27b verilog print byte-identical output and exit codes before and after
on all 2051 specs (4102 of 4102). Generated writers and the three affected
records regenerated there; ledger row added for emit_kit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Oct 17, 2026
#10047 merged at its head before this fix reached the branch, and master's
duplicate-bodies gate went red: ts_emit.t27 repeats 18 helper bodies of
verilog_emit.t27 word for word (byte writers, to_front, line_near, the
scope and name resolver, the symbol encoding, the test-tree builders).
They now live once, in specs/tri/t27b/emit_kit.t27, with tests of their
own, and both writers `use` it by name.

A whole-module `use` of verilog_emit from ts_emit does not work: the
splice counts words inside string literals as references, so ts_emit's
"export function" pulls verilog_emit's fn `function`, and the generated
Rust typecheck refuses it against ts_emit's own param_type and stmts.

The ledger also loses its ternary_matmul row: that group is gone on
master and the gate refuses a ceiling left above the real count.

Measured on the Railway lab, on top of master 896d87b: test-report
emit_kit 4/4, ts_emit 4/4, verilog_emit 7/7, 0 vacuous; dupe_scan ok
after the bless; t27b ts and t27b verilog print byte-identical output and
exit codes before and after on all 2095 specs (4190 of 4190). Generated
writers and the three records regenerated there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Oct 17, 2026
#10047 merged at its head before this fix reached the branch, and master's
duplicate-bodies gate went red: ts_emit.t27 repeats 18 helper bodies of
verilog_emit.t27 word for word (byte writers, to_front, line_near, the
scope and name resolver, the symbol encoding, the test-tree builders).
They now live once, in specs/tri/t27b/emit_kit.t27, with tests of their
own, and both writers `use` it by name.

A whole-module `use` of verilog_emit from ts_emit does not work: the
splice counts words inside string literals as references, so ts_emit's
"export function" pulls verilog_emit's fn `function`, and the generated
Rust typecheck refuses it against ts_emit's own param_type and stmts.

The ledger also loses its ternary_matmul row: that group is gone on
master and the gate refuses a ceiling left above the real count.

Measured on the Railway lab, on top of master 896d87b: test-report
emit_kit 4/4, ts_emit 4/4, verilog_emit 7/7, 0 vacuous; dupe_scan ok
after the bless; t27b ts and t27b verilog print byte-identical output and
exit codes before and after on all 2095 specs (4190 of 4190). Generated
writers and the three records regenerated there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Oct 17, 2026
… (#10065)

#10047 merged at its head before this fix reached the branch, and master's
duplicate-bodies gate went red: ts_emit.t27 repeats 18 helper bodies of
verilog_emit.t27 word for word (byte writers, to_front, line_near, the
scope and name resolver, the symbol encoding, the test-tree builders).
They now live once, in specs/tri/t27b/emit_kit.t27, with tests of their
own, and both writers `use` it by name.

A whole-module `use` of verilog_emit from ts_emit does not work: the
splice counts words inside string literals as references, so ts_emit's
"export function" pulls verilog_emit's fn `function`, and the generated
Rust typecheck refuses it against ts_emit's own param_type and stmts.

The ledger also loses its ternary_matmul row: that group is gone on
master and the gate refuses a ceiling left above the real count.

Measured on the Railway lab, on top of master 896d87b: test-report
emit_kit 4/4, ts_emit 4/4, verilog_emit 7/7, 0 vacuous; dupe_scan ok
after the bless; t27b ts and t27b verilog print byte-identical output and
exit codes before and after on all 2095 specs (4190 of 4190). Generated
writers and the three records regenerated there.

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

t27b ts: emit the Queen's rules as TypeScript with function bodies, from .t27 (supersedes the blocked gen-ts PR #7872)

1 participant