Repository navigation
spec(t27b): wasm32 floor 3 -- local groups, func entries, vec framing, instructions (Refs #11840) - #11927
Conversation
…, the instruction floor (Refs #11840) Floor 3 of the format law: local_group (uleb count + valtype, fail-closed through the valtype map), func_entry (uleb type index), vec_prefix (the count framing t27 composes by appending entries), code_section (the WebAssembly framing: uleb count, then count x (uleb size + entry) -- the count is an explicit parameter: t27 cannot derive it from bytes), and the instruction floor a real body needs (i32.const 0x41+sleb reusing floor 1's sleb -- the textbook C0 BB 78 for -123456 pinned -- local.get, local.set, i32.add, end). The capstone is a whole 26-byte module (preamble + type + function + code sections) hand-verified twice before the asserts, with a second validation-shaped variant (the as-specified () -> () body leaves i32.const 42 on the stack: canonical framing, invalid shape -- both pinned; floor 4 treats the shaped one as canonical). 15/15 under t27c test-report and t27b, 0 vacuous. Floor 4 mapped: the export section (the compositeness gate -- no host can call the module without it), call + control flow, i64 arithmetic + tee/drop, global/memory/data, and a two-byte-uleb code_section pin.
Summary by t27-beesChecked by the t27 compilert27c parse, parse-complete and typecheck on each changed .t27 file at
Read by the modelThis change implements Floor 3 of the wasm32 format spec: local groups, function entries, vector prefix framing, the code section with explicit entry count, and the instruction floor (i32.const via sleb, local.get/set, i32.add, end). The capstone test emits a complete 26-byte minimal module byte-for-byte, plus a validation-shaped variant. Worth a look
Read: 1 files, +263 -3, the whole diff. Head |
Re-seal the two specs master's mid-flight merges left stale: specs/tri/t27b/wasm.t27 (#11927, wasm32 floor 3, +263 lines) and specs/queen/worktree_keep.t27 (#11874, night-loop lane sweep). t27c seal --save + tri seals sync-twins on both; seal coverage and seal currency exit 0, all other cycle gates re-run green.
* fix(gates): master reds repair pass 8 (Refs #11038) Three reds on master after the port-train wave that the nine-step repair cycle alone could not clear: 1. gate-topology.yml failed to parse on every push (zero-job failed run, workflow shown under its file path). The claw-criteria-post note step is a flow mapping whose run: value is a plain scalar holding a comma; in flow context the scalar ends at the comma and the rest of the sentence becomes a bogus step key, so GitHub rejects the whole file. #10572 fixed the jq line for this same defect class and missed this line. The run value is now single-quoted; the shell it names is byte-identical. actionlint is clean, tri census pin --gate PASS. 2. Duplicate Body Ratchet: the port wave added byte-identical copies of digit_byte (claw/text + t27f/a11y_mirror), lt_s and sar32 (fpga/wasm_interp + fpga/wasm_opcodes) and sort_asc_u32 (t27f/live_mode sort_u32 + t27f/measure_live sort_asc_u32). Deliberate port copies -- each port target keeps its own definitions -- so the ledger moves in the same commit: dupe_scan --bless adds exactly those four lines, gate exit 0. 3. OpenSSF Scorecard: the gcr.io/openssf/scorecard-action:v2.4.0 image pull is denied upstream (billing on OpenSSF's own Google project), an infrastructure outage in the action itself. v2.4.1 publishes to ghcr.io; the pin moves v2.4.0 -> v2.4.1, nothing else in the workflow changes. The nine-step repair cycle ran green before and after this commit: verilog widths, types ratchet, types classified, seals drift, seal coverage, seal currency, assertionless tests, documented commands, specs generate -- all exit 0. * fix(gates): master reds repair pass 8 (Refs #11038) Re-seal the two specs master's mid-flight merges left stale: specs/tri/t27b/wasm.t27 (#11927, wasm32 floor 3, +263 lines) and specs/queen/worktree_keep.t27 (#11874, night-loop lane sweep). t27c seal --save + tri seals sync-twins on both; seal coverage and seal currency exit 0, all other cycle gates re-run green.
* ci(dupes): drop digit_byte, lt_s, sar32 from the ledger -- this PR removes the copies (Refs #11885)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* spec(queen): the night loop's lane sweep -- claim-aware release on the reaper's proofs, and a tick commits only on its own branch (#11874)
Refs #11873
Refs Trinity-S-AI-DNA/t27os#8
Replaces #11866, whose single commit carried only a cross-repo
reference and so failed the L1 commit gate. The tree is byte-identical
(worktree_keep.t27 blob b9b97669): t27c lab receipt
runs/1aa955447fd7713f0a3be42c083275dd4a49a120.1e9401ff.json 16/16,
0 vacuous; t27b pass per the native ratchet on 1aa955447 (ledger pass,
0 unexpected failures).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* ci(seals): ledger two seals master left stale -- worktree_keep, t27b wasm (Refs #11840) (#11929)
Master 5e30b412b is red on Spec Guards: check_seal_currency reports two
STALE generated-code hashes, both because the spec moved and no reseal
landed with it:
- queen_QueenWorktreeKeep.json -- specs/queen/worktree_keep.t27, moved by #11874
- t27b_T27bWasm.json -- specs/tri/t27b/wasm.t27, moved by 94adbb1b2
One master red turns every open PR red on spec-guards and coverage. The
real repair is a reseal from a master-built t27c. That cannot run here:
the Mac may not run t27c seal, Railway is signed out, and the lab's reseal
leg (#11903) is waiting for the lab.yml workflow scope. So the two seals
go into tools/seal_baseline.txt as kind `stale`, which is the ledger's
own word for "spec changed since sealing". split() counts them as known
only while their spec_hash still disagrees, so this exempts nothing
except these two moves. The reseal drops both lines in its own commit.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(gen-zig): render parameterised const structs as Zig generic fns (Refs #11912 #11840)
DEFECT (#11912, class 1 of the wasm32 audit, epic #11840): a
parameterised const struct -- `pub const Box(T) = struct { value : T,
};` -- emitted as a PLAIN Zig struct with the parameter an undeclared
identifier:
pub const Box = struct {
value: T,
};
The module refused to compile on ANY target (native and
wasm32-freestanding alike): "use of undeclared identifier 'T'". The
parser was innocent: node.params carries the parameter (ADR-008,
verified params: [("T","")]); the emitter dropped it.
FIX: in gen_struct_decl, when node.params is non-empty, render Zig's
generic-function idiom:
pub fn Box(comptime T: type) type {
return struct {
value: T,
};
}
Multi-parameter declarations compose (Result(T,E) ->
`fn Result(comptime T: type, comptime E: type) type`, State(S,T)
likewise), keyword field names keep their escaping (@"error"), and
the plain (no-params) path keeps its exact previous render. The call
sites (`Box(u8)`) already render as calls, so they compose unchanged.
PAIRED DELETION (foreign-budget shrink rule, owner rule 2026-10-09:
glue may not grow the hand-written foreign surface): remove the dead
`from_i8`/`to_i8` impls on AsmSectionKind and AsmRelocKind plus the
two round-trip tests that exercised nothing else (39 + 36 = 76 lines;
both items are named "never used" by the compiler's own dead-code
lint and have zero callers in the repo). Test count moves 1799 ->
1797 accordingly. Net: -38 hand-written foreign lines.
M5: FROZEN_HASH re-stamped
(182a47746c3338d8df04408fd024c34dbfa8015a2d9b7e09c70e434dca1ff472).
Seals: gen_hash_zig re-stamped for all 13 corpus specs carrying a
parameterised struct decl (15 declarations; Tree, IO, Reader, Zipper,
Writer, Option, Queue, Either, Result, BTree, BTreeNode, Ring, Maybe,
State, HashSet). Codegen output of non-generic specs is unchanged.
VERIFIED:
- repro (issue #11912): zig build-obj native OK,
wasm32-freestanding OK (before: "use of undeclared identifier
'T'" on both).
- corpus users: the struct's own error is GONE on all 13 (maybe.t27
failure site moved spec.zig:22:12 struct field -> spec.zig:26:30
fn-type-alias layer). The modules remain BLOCKED pending the NEXT
generic layer (fn-level comptime params + the `= fn(T) Maybe(T)`
fn-type-alias layer) -- a follow-up slice, to be filed.
- cargo test -p t27c --bin t27c: 1797 passed, 0 failed, 2 ignored.
- foreign-budget and own-language gates: exit 0.
Label note: owner-approved-foreign (owner 2026-10-23, session
instruction repeated five times: do all three autonomously; the
emitter glue is the labeled slice per the port-train pattern -- the
decision spec lands as the follow-up).
* fix(gates): master reds repair pass 8 (Refs #11038) (#11928)
* fix(gates): master reds repair pass 8 (Refs #11038)
Three reds on master after the port-train wave that the nine-step
repair cycle alone could not clear:
1. gate-topology.yml failed to parse on every push (zero-job failed
run, workflow shown under its file path). The claw-criteria-post
note step is a flow mapping whose run: value is a plain scalar
holding a comma; in flow context the scalar ends at the comma and
the rest of the sentence becomes a bogus step key, so GitHub
rejects the whole file. #10572 fixed the jq line for this same
defect class and missed this line. The run value is now
single-quoted; the shell it names is byte-identical. actionlint
is clean, tri census pin --gate PASS.
2. Duplicate Body Ratchet: the port wave added byte-identical copies
of digit_byte (claw/text + t27f/a11y_mirror), lt_s and sar32
(fpga/wasm_interp + fpga/wasm_opcodes) and sort_asc_u32
(t27f/live_mode sort_u32 + t27f/measure_live sort_asc_u32).
Deliberate port copies -- each port target keeps its own
definitions -- so the ledger moves in the same commit:
dupe_scan --bless adds exactly those four lines, gate exit 0.
3. OpenSSF Scorecard: the gcr.io/openssf/scorecard-action:v2.4.0
image pull is denied upstream (billing on OpenSSF's own Google
project), an infrastructure outage in the action itself. v2.4.1
publishes to ghcr.io; the pin moves v2.4.0 -> v2.4.1, nothing
else in the workflow changes.
The nine-step repair cycle ran green before and after this commit:
verilog widths, types ratchet, types classified, seals drift,
seal coverage, seal currency, assertionless tests, documented
commands, specs generate -- all exit 0.
* fix(gates): master reds repair pass 8 (Refs #11038)
Re-seal the two specs master's mid-flight merges left stale:
specs/tri/t27b/wasm.t27 (#11927, wasm32 floor 3, +263 lines) and
specs/queen/worktree_keep.t27 (#11874, night-loop lane sweep).
t27c seal --save + tri seals sync-twins on both; seal coverage and
seal currency exit 0, all other cycle gates re-run green.
* ci(seals): re-stamp the two tuple seals master left stale (Refs #11912 #11840)
#11930 rendered parameterised const structs as Zig generic fns but
missed tuple.t27 in its seal re-stamp sweep: the audit grep used
[A-Za-z_]+ for the declaration name, and `Tuple2`/`Tuple3` carry a
digit, so `pub const Tuple2(A, B) = struct {` never matched. Master
inherited two stale seals (TriTuple.json, collections_TriTuple.json;
gen_hash_zig f49f77e5 -> a87c06f1).
Re-stamped with `t27c seal --save specs/tri/collections/tuple.t27`.
check_seal_currency: STALE generated-code hash 2 -> 0, exit 0.
Tuple2/Tuple3 now emit `pub fn Tuple2(comptime A: type, comptime
B: type) type { return struct { first: A, second: B, }; }` (verified:
fields carry A/B inside the generic fn); the module's own remaining
BLOCK is the fn-level generic layer (`fn pair(a: A, b: B)`), the
slice #11930 filed as follow-up -- not this seal repair.
* spec(t27os): night take rule -- stale in-progress retake, leg-only remainders, credential-blocked to requests (Refs #11892) (#11893)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27os): lab_legs -- a receipt line is green only with both compilers (Refs #11889) (#11890)
* spec(t27os): lab_legs -- a receipt line is green only with both compilers (Refs #11889, Refs #11873)
leg_state reads one compiler's counts (absent, blocked, fail, vacuous, pass);
line_verdict needs t27c and t27b PASS, excusing only a t27c BLOCKED on an
@extern spec whose t27b leg passes; may_leave_draft gates a night PR on every
touched spec green. Executor commands named as data for the lab.yml generator.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27os): lab_legs -- the t27b leg as an arm64 lab.yml job, text and gate (Refs #11889, Refs #11873)
t27b's JIT runs only on aarch64; the lab job runs on x86_64 ubuntu-latest. The leg is a
second job (needs: run, ubuntu-24.04-arm, the run job's resolved sha, t27b test --check)
writing runs/<sha>.t27b.txt in the receipt's key=value shape. T27B_JOB_YAML and
RUN_OUTPUTS_YAML are the text TRI CLAW copies into lab.yml; t27b_job_ok / run_outputs_ok
gate it, with negative controls for an x86 runner, a missing --check and a missing sha.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(gen-zig): a t27 fn type renders as Zig's fn (A) R, arrow removed (Refs #11940 #11840)
DEFECT: a t27 fn TYPE carrying the t27 arrow -- state.t27's
run : "fn(S) -> (S, T)" -- reached the Zig output verbatim, and Zig's fn
type has no arrow: error: expected return type expression, found '->'
stopped the whole module at the first fn-typed field.
FIX: t27_fn_type_to_zig in the gen-zig type mapper: fn (S) struct { S, T }
(a multi-value return is the anonymous struct t27_tuple_type_to_zig
already builds), fn (A) void for an absent/void return, named parameters
keep only their type. The const-alias arm unifies with W729's builtin
alias arm. Budget payment (owner rule 2026-10-07 #7371): six dead fns
deleted -- retime_forward, retime_backward, emit_interface, byte_offset,
lint_count, heap_start -- each flagged never-used by rustc and referenced
nowhere else (bootstrap tests, cli/t27b, gen/ all zero refs).
VERIFY: ArrowRepro.t27 (pub const Step = fn(S) -> (S)) emits
pub const Step = fn ( S ) ( S ); and zig build-obj is silent natively and
under -target wasm32-freestanding; state.t27 and reader.t27 fields render
run: fn (S) struct { S, T } / fn (R) T; 26 specs' gen_hash_zig changed,
all 52 seal files re-stamped, seal state equals master's pre-existing
staleness (20, all non-zig drift), no spec went from compiling to failing;
cargo test -p t27c --bin t27c: 1797 passed, 0 failed.
* spec(t27os): disclosure -- no number leaves without its five fields (Refs #11944) (#11945)
Board twin: Trinity-S-AI-DNA/t27os#20. reader, judge, n, cost, repro on every
number T27 OS publishes about itself; an empty or placeholder field, n = 0, or
a CI from one run refuses the number; the checker says all-covered only when
number and footer counts match and are not zero. The 048f7f45 receipt is the
worked example: refused until its cost is recorded.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27os): lab inputs reach the shell through env, never by expansion (Closes #11950) (#11951)
lab.yml expands inputs.sha and inputs.specs into run text before bash
parses it; lab_legs.t27 T27B_JOB_YAML carries the same pattern. The new
law refuses any run body holding an input expansion, ships the corrected
sha and test-report steps as ENV + RUN text, and keeps the live steps and
T27B_JOB_YAML as negative controls.
Refs Trinity-S-AI-DNA/t27os#3
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27os): the t27b job reads the spec list through env, never by expansion (Closes #11952) (#11953)
lab_legs.t27 :: T27B_JOB_YAML looped `for spec in ${{ inputs.specs }}`,
the expansion #11950 removed from the t27c steps. The t27b step now sets
env SPECS, turns globbing off and loops over $SPECS. lab_inputs.t27 owns
the job-level check (job_inputs_ok), with the pre-fix loop, an assignment
expansion and a globbing-on job as negative controls.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27os): receipt_name -- a lab receipt is named only from a full resolved sha (Refs #11840) (#11870)
* spec(t27os): receipt_name -- a lab receipt is named only from a full resolved sha (Refs #11840)
t27os#11: a scheduled lab run has no input sha and would write runs/.<c8>.json.
t27os#10 (third way): a full sha went through an API lookup that answered null.
The law: a full input skips the lookup, a non-full answer refuses the run, and
the name is runs/<40 hex>.<c8>.json or nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27os): receipt_name keys the name on the challenge DIGEST, as lab.yml does (Refs #11840)
Measured on runs/305d83ad...ff17d40b.json: c8 is sha256(challenge)[0..8];
the raw challenge is never published.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27os): a scheduled lab run tests the core set, never nothing (Refs #11840)
The lab schedule fires (t27os runs 40005713854, 40015647905) but carries
no inputs: the spec loop read "for spec in ;", wrote no summary and died
at cat, so no receipt. receipt_name.t27 now says an empty specs input
means the default core set, and a run whose list is still empty is refused.
Board Trinity-S-AI-DNA/t27os#3, task t27os#11.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(crons): night loop UI health reads publish.txt, not a closed page's Z row (Refs #11887) (#11888)
* spec(crons): night loop UI health reads publish.txt; a stale Z with the HIVE page closed is not a finding (Refs #11887)
The hive feed job runs only while the HIVE page is open (page_feed_due);
the always-on heartbeat is publish.txt. ui_health gives one verdict per
tick and ui_is_finding says which ones go to t27os#3.
Refs #11887
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* spec(crons): night loop SWEEP-STEP -- every 6th tick, own merged lanes only (Refs #11873)
The lane-hygiene protocol of Trinity-S-AI-DNA/t27os#8 becomes a tick step: sweep_due
(every 6th tick), sweep_remove (own night- lanes only, at most 8 removals per tick). The
per-worktree verdict is not restated; it is worktree_keep.t27 lane_sweep_verdict (#11874).
Refs #11887
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* spec(crons): night loop LAND-STEP -- a local Refs #N, cross-repo-only refused (Refs #11873)
l1_local_ref mirrors the L1 gate regex (Closes|Fixes|Resolves|Refs|Updates)\s*#[0-9]+;
a Trinity-S-AI-DNA/t27os#N reference alone is refused, as on #11863/#11866/#11870.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(crons): the night loop's TASK-PICK step points at night_take.t27 may_retake (Refs #11956) (#11957)
The card named AUDIT, PR-GATE, UI-HEALTH, SWEEP and RETROSPECTIVE steps and no
pick step, so the retake rule of #11892 was law no card pointed at. The new
section names may_retake and pick as the law without restating a value, and
pick_may_run orders the pick after the PR gate and every red repair.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(crons): the night tick's receipt comment carries the disclosure footer (Refs #11958) (#11959)
RECEIPT-COMMENT-STEP: a receipt comment is posted only when
specs/t27os/disclosure.t27 footer_verdict judges its five-field footer
DISC_OK (reader, judge, n as a count, cost from dispatched_at to the
receipt utc, repro). First publishing path wired for
Trinity-S-AI-DNA/t27os#20.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27os): disclosure_scan -- count published numbers and footed numbers in one document (Refs #11960) (#11961)
Criterion 3 of Trinity-S-AI-DNA/t27os#20: the pure core of the checker over
runs/*.summary.txt and the README. The verdict is disclosure::coverage_verdict;
negative controls for a bare summary, a placeholder, a dropped field line, a
footer above its numbers and a half-covered document.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27os): the README published-numbers section checked by disclosure_scan (Refs #11960) (#11962)
Criterion 2 of t27os#20 (the README worked example, t27os#21) is now a
fixture, byte-identical to the PR head, and doc_verdict says COV_ALL on it;
negative control: the same rows with the n: line dropped are a gap.
Refs #11960
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27b): wasm.t27 floor 4 -- the constant-leaf emitter's law, ported from the working wasm32 emitter (epic #11840 M-A, port #6198, ref PR #11942) (#11964)
- FIX: f32/f64 value-type bytes were the const opcodes (0x43/0x44); the
binary format's value types are 0x7D/0x7C. The working reference emitter
(cli/t27b/src/wasm32_emitter.rs, PR #11942), whose modules Node's
WebAssembly instantiates 100/100 in the equality gate, is the evidence.
- NEW law: OP_I64_CONST/OP_F32_CONST/OP_F64_CONST, i64_const, f32_const,
f64_const (LE IEEE-754 bit patterns), section_header, export_entry,
SEC_EXPORT.
- Tests ported from the reference: the exact 43-byte the_answer module,
the sleb edge vectors, the f32/f64 LE bit patterns, a two-export
i64+f64 module composition. 22/22 t27c test-report, 0 vacuous.
- gen/rust/tri/t27b/wasm.rs is t27c gen-rust of the spec (L2, force-added
like its tracked siblings); nothing hand-written is added or modified
(Only t27).
Refs #6198 (port epic), advances #11840 (M-A); companion to reference PR #11942.
* chore(seals): shrink the stale-hold ledger -- queen_QueenWorktreeKeep and t27b_T27bWasm now hold their generated code (Refs #11038) (#11963)
* spec(tri/t27b): wasm.t27 floor 5 -- the arithmetic floor the live-closure scalar trio lowers to (i32 sub/mul/div_u, eqz, select), param-functype and stack-program composition pinned; crons: the T27F closure lab watch, the hourly full-closure lab dispatch (epic #11840 M-B; Refs #6198, #11781, #10262) (#11976)
* chore(seals): re-ledger t27b_T27bWasm -- #11964 changed wasm.t27 after #11963 dropped its stale line (Refs #11840) (#11977)
Merge race on master 63040712e: #11963 removed the t27b_T27bWasm stale-hold
line because the 00:57Z seal held; #11964 (floor 4) then changed
specs/tri/t27b/wasm.t27 without a reseal. Every open PR now fails coverage
and spec-guards with "1 seal(s) newly do not hold: t27b_T27bWasm.json [stale]".
Restores the ledger line, kind stale, naming #11964, until a master-built
t27c re-saves the seal in the #11903 batch. No spec changed.
Refs #11840
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(gen-zig): nested and optional fn types render arrow-free (Refs #11940 #11840)
DEFECT: two fn-type shapes still leaked the t27 arrow into gen-zig after
15e4ba4d (sub-slice 3 v1), both measured: a NESTED fn-type argument --
fn(u8, ?fn(u8) -> void) -> ?i32 emitted 'fn (u8, ?fn([]constu8) void)->?i32'
because the mapper split at the FIRST ')' which closes the INNER fn's list,
mangling the outer return onto it (image-loader.t27's shape); and a
'?'-prefixed fn type -- '?fn(A) -> R' starts with '?', not 'fn', so it fell
past the whole fn arm with its arrow intact.
FIX: the argument list ends at the ')' MATCHING the opening one (depth scan);
arguments split on commas OUTSIDE parens (a nested fn/tuple arg carries its
own); a '?' prefix maps its inner type through the fn arm and keeps the
option; the named-parameter rule (keep only the type) applies only where no
nested type begins. M5: FROZEN_HASH re-stamped.
BUDGET (owner rule 2026-10-09, foreign code only shrinks): the 38 added
mapper lines are paid by deleting HirDiff + HirDiffEngine (69 lines) -- dead
per rustc, zero references outside their own block (bootstrap, cli/t27b, gen,
scripts, tests all empty).
VERIFY: five repro shapes (state.t27's run field, plain alias, no-fn control,
nested+optional, zero-arg) silent under zig build-obj natively and under
-target wasm32-freestanding; state.t27's remaining blocked line (36:28,
Fn(S) fn-signature class) byte-identical to v1's seal -- sub-slice 1's layer;
gen_hash_zig compared old-vs-new over ALL 2,959 sealed specs: 0 changed, no
seal re-stamp needed (measured); cargo test -p t27c --bin t27c: 1797 passed,
0 failed. Diff: +38/-69 in compiler.rs.
* spec(t27b): wasm.t27 floor 6 -- export_section, call/control, i64.add, tee, drop (Refs #11840)
The honest rebase of this branch's floor-4 commit (aa3e3a387) onto master's
floors 1-5. Master had already taken what that commit shared with it: the
export entry and section id (#11964's constant-leaf law, carrying the
f32/f64 value-type correction this branch predates), the constant
instructions, and the i32 arithmetic floor (#11976). The branch's 39-byte
one-export capstone is subsumed by master's 43-byte the_answer module, and
its 5-arg export_entry by master's corrected 4-arg law -- neither is
duplicated.
What this commit keeps is the branch's UNIQUE content, renumbered from its
"floor 4" to floor 6, tests and all:
- export_section: the in-place framing twin of code_section (vec count +
pre-joined entries under the id 7), the 12-byte and 11-byte frames pinned,
plus the 200-index entry vector (uleb past one byte) master's export test
does not pin;
- the call/control family: call 0x10, block 0x02 / loop 0x03 / if 0x04
opening the void blocktype 0x40, else 0x05, br 0x0C, br_if 0x0D, return
0x0F, each immediate pinned;
- the i64 stack floor: i64.add 0x7C, local.tee 0x22, drop 0x1A, plus the two
i64.const vectors master's floor-4 test lacks (-123456's C0 BB 78 and
2^32's six-byte 80 80 80 80 10);
- a new floor-6 capstone in place of the subsumed one: the first
TWO-function module -- an exported wrapper whose body is one call to a
callee that adds two i64 constants -- 48 bytes, every one pinned.
32/32 tests under t27c test-report, 0 vacuous; master's 27 all stay.
gen/rust/tri/t27b/wasm.rs regenerated from the spec (t27c gen-rust).
The t27b_T27bWasm seal is re-saved (t27c seal --save, master-built binary,
32/32 recorded): it HOLDS for the first time since #11964 changed the spec
unsealed, so the stale-hold line #11977 parked in tools/seal_baseline.txt is
dropped per that ledger's own rule -- the gate now holds the repair fixed.
Seal-coverage delta against pristine master measured with the same binary:
newly-broken sets identical (23 pre-existing, none from this change), the
repaired seal absent from the list.
Refs #11840
* spec(t27os): a claim stamped further ahead than SKEW_S is malformed and stale (Refs #11974) (#11975)
stale_claim read any since later than now as fresh, so a hand-typed stamp
ahead of the clock hid the entry from the two-hour retake rule (tick 59:
06:40Z written at 06:29Z). Up to SKEW_S = 300 s ahead still reads fresh
(clock skew between machines); further ahead reads stale.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* docs(analog): v0.1 release notes (final) and one-page summary for the external team (Updates #11972) (#11973)
* docs(analog): v0.1 release notes and one-page summary for the external team (Updates #10486)
Replaces the 2026-10-20 draft with the final notes: M3c-4 log tables for four
corners, M3e body effect, M4b-q comparator on PSP103, M5c-g acceptance
evaluator (9 PASS / 0 FAIL / 4 NOT MODELLED of 13 blocks), M3d inverter on the
board (1217 of 1217), M3f phase 1 and 2a, the RAW readback, the bench. Every
number carries its PR, test or receipt; the does-not-claim list is explicit
(no speed claim, one corner on the board, phase 2a does not close 100 MHz).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* docs(analog): summary rows carry the scope the full notes state -- fitted converter, 32 doubles, ngspice timing, comparator body effect (Updates #11972)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* fix(gen-zig): drop tests_phase34_diff, the deleted engine's own tests (Refs #11940 #11840)
CI caught what my local reference check truncated: compiler.rs's own
#[cfg(test)] module tests_phase34_diff (3 tests, 40 lines) exercised
HirDiffEngine::diff/equivalent -- the code the budget payment deleted. The
t27-wasm-explorer crate mounts compiler.rs WITH its test module, so its
build-and-test failed to compile: cannot find type HirDiffEngine (3x, lines
43208/43215/43228). The tests referenced only the engine and each other --
dead along with it. Repo-wide HirDiff reference count is now 0 across all
.rs files (counted, not grepped-and-truncated).
VERIFY: cargo test -p t27c --bin t27c 1793 passed 0 failed (the known
a_looping flake passed isolated); cargo test --no-run --manifest-path
bindings/wasm-explorer/Cargo.toml compiles clean, no errors; nestedfn and
arrow_repro repros still silent natively and under wasm32-freestanding.
PR diff is now +38/-110 in compiler.rs -- the budget still passes.
* feat(compiler): fn-level comptime type params -- parser + Zig emitter (Refs #11940 #11840)
fn name(comptime T: type, ...) parsed as three garbage params before this
slice (comptime lexes as a plain Ident): the repro emitted
fn identity(@"comptime": T, @"type": , value: T) T. The parser now reads the
shape into (name, "type") and refuses a comptime VALUE parameter with a parse
error; gen-zig renders the generic-function idiom comptime T: type, skips the
value-scope maps for type params, and discards one only when the signature
does not already use it. Call sites pass the type explicitly (identity(u8,
42)) -- call-site inference is the recorded follow-up. A struct literal
attached to a call (Box(T){ ... }, the fn pure(comptime T: type, value: T)
Maybe(T) shape) was captured as text on the call's value and dropped by the
Zig emitter; it is now written, and the unused-parameter scan reads that text.
Debt shrinks: the two never-called dead test helpers assert_dropped and
assert_decl_dropped are deleted (39 added / 50 deleted in the one foreign
file touched). Coverage is native: NEW specs/tri/collections/box.t27 passes
test-report 3/3 (runtime asserts executed, 0 vacuous); repros in
/tmp/opencode/repros pass zig test and native + wasm32 build-obj; cargo test
-p t27c --bin t27c 1797 passed; M5 re-stamp.
* spec(t27f): live_struct_glue -- the struct-path export glue v2 contract as law, written before the emitter: the gx_-buffer shapes (33 exports: setters, actions, 10 ptr/len pairs), the GLUE_REFUSED_BASE=64 band beside live_mode's 0..5/33..35, total init, idempotent reads, and two-node + batch round-trips transcription-checked against work_graph's own law fns (6/6 tests, 3 invariants, 350,808 asserts); open questions inline as ; QUESTION. Refs #10262, #11781; the contract the struct-path emitter writes against. (#12005)
* t27b(wasm): floor 6 -- the emit() composer as per-fn descriptors (#12003)
The #9103 gap (no slice of slices) answered the macho.t27 way: a 24-byte
descriptor record per fn (name offset/length into a names blob, parameter
count, result valtype, body offset/length into a bodies blob) plus
compose_module, which assembles preamble + type + function + export + code
through the floor-1..5 law fns only (module_preamble, functype_full,
vec_prefix, func_entry, export_entry, code_entry, code_section, section),
failing closed on descriptors off the law or an empty export set, exactly
as the reference emitter refuses them by name.
Capstones pin the live-scalar closure byte for byte: the 87-byte two-fn
module (arrival_frame + latency_ms, the build Node's WebAssembly verified
on the emitter branch) and the 117-byte trio with paints_due
(Node-verified 2026-10-24). test-report 36/36, 0 vacuous; mutation check
paid (one flipped pin fails). gen-rust regenerated additively (29 -> 42
pub fns, no existing fn touched); seal re-saved and its stale ledger line
dropped.
Refs #6198 (port epic).
* spec(t27os): devices.t27 lg_rows -- the LOGS page parser for the night loop's log tail (Closes #11991; Refs Trinity-S-AI-DNA/t27os#23) (#11993)
The T27 OS window renders nothing of ~/.t27os/loop/log.txt. This adds the
pure parser the LOGS page will draw from: lg_rows turns a tail -c 6144 of
the log into at most DL_MAX=96 rows of (epoch, kind, subject start,
subject end), offsets into the tail in the dv_* style. Kinds tick-start,
tick-end, claude, G, note, BAD. A malformed line is flagged as BAD and
neither corrupts the row above nor stops the walk (negative control in the
tests); a cut tail drops its partial first line; more lines keep the last
96; CR LF endings are trimmed; lg_clock writes HH:MM:SS UTC.
Both compilers: t27c test-report 24/24, 0 vacuous; t27b test 24/24,
invariant held. Seal re-saved with a t27c that reproduces master seals
(hive_feed_acceptance, kanban byte-identical). The glass_window wiring
(page LOGS, TBO_LOG buffer, tail job) is the next unit.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* t27b(wasm): floor 8 -- the refusal walk as law: the walk order (skip, void, M-A uncarried-then-body, M-B params-then-return-then-body, expr Const/Var/Arith with op-before-operands and lhs-before-rhs, select shape facts, module-level), every EmitError construct and detail byte-stable, EmitError::message's exact line, the emitter valtype carrier rule, the ArithOp debug names; 50/50 tests, table test mutation-checked Refs #6198 (port epic). (#12007)
* tools: ledger live_struct_glue's packed LiveGlue width (1,723,167 bits -- the wasm memory image, landed unledgered by #12005) so the widths gate holds for every lane behind it; the design question stays #2566 Refs #6198 (port epic). (#12008)
* spec(t27os): the LOGS page -- the night loop's own log rendered in the window (Refs Trinity-S-AI-DNA/t27os#23)
The owner asked twice on 2026-10-24 why the swarm's work is invisible in
the window ('why can't I see how the agents work' / 'no logs'). The loop
writes ~/.t27os/loop/log.txt; nothing in the window read it. This adds the
fifth tool page: letter L (page label LAB -> LOGS in TOOL_PAGES and
petal_menu WORLD_NAMES, both, so the equality test holds; the tool keeps
its name t27l and its artifact now cites both the lab specs and the log).
- agent_parts.t27: PAGE_LOGS=5, PAGE_KINDS 5->6, PERIOD_LOGS 30 s,
page_kind(12), the page_period arm; the five-pages test, the cadence
due/not-due pair at 1029/1030.
- devices.t27: lg_rows (dv_* style, offsets not copies, DL_MAX 96) parsing
the MEASURED event lines (tick-start, claude-start, tick-end rc=N,
overlap-skip); lg_prose counting the tick reports the page does not
flatten; lg_tail_cmd -- the tail -c 6144 into tail.part + mv job, the
same dance as every feed job (tg_read cannot seek). Tests: the measured
shapes built byte-explicit, the negative control (an 11-digit epoch row
is flagged DLF_BAD, does not corrupt the row above, the walk continues),
DL_MAX bounds, the command's shape. 23/23, 0 vacuous.
- glass_window.t27: TBO_LOG=77824 (the old TB_SIZE top, append-at-top
convention), TBO_LOG_N=6144, TB_SIZE 77824->83968; TPG_LG_* words in the
verified free gap 129-134; lg_load (drops the cut first line of a byte
tail) + lg_tick (load-once, reap, page_feed_due every 30 s while open);
draw_logs_page -- the header (source, events, prose), bottom-anchored
rows (age, kind with ! for a nonzero rc and ? for a malformed line,
sanitized subject); the dispatch arm, the tick wiring beside hive_tick,
and the layout asserts extended (TBO_RC + RC_CAP == TBO_LOG,
TBO_LOG + TBO_LOG_N == TB_SIZE) in both assert sites.
Pre-existing, NOT from this PR: glass_window's runtime test-report is
BLOCKED on this machine's zig because the harness's own
@extern("CFStringCreateWithBytes") now needs two arguments -- verified by
running test-report on pristine origin/master (same BLOCKED). Typecheck
passes 0 errors; CI's zig accepts the harness as-is (master green all
night). agent_parts and devices test-reports: 23/23 each, 0 vacuous.
* spec(t27os): labs gate commands — the repair cycle as executable data (Refs #11783 #11038) (#11868)
GATE_COMMANDS [9]str pins the exact shell command per gate, in gate order --
the same invocations CI runs (corpus-ratchet, documented-commands,
emit-bitexact-gate, seal-coverage, spec-guards). gate_command(i) returns the
command or empty for out-of-range; all_gates_pass([9]bool) is the verdict
rule. The cycle proven 6x in practice (#11735, #11786 x2, #11825, #11838)
now has its commands as law, not as memory.
Tests 6 -> 8, all pass, 0 vacuous (13 + 5 new runtime asserts).
* night loop: BOARD-GUARD-STEP -- a closed permanent board reopens before the claim (Closes #11978) (#11979)
* fix(crons): BOARD-GUARD-STEP -- the permanent board reopens before the claim, keyword-close notes refused (Closes #11978)
* seal(crons): re-seal t27os-night-loop with bootstrap built from master 89f2d9917 -- gen-drift was the old dirty-tree binary, provenance now recorded (Closes #11978)
---------
Co-authored-by: Claude <claude@anthropic.com>
* chore(seals): reseal 13 collections/io/trees specs from the lab seal leg -- gen_hash_zig only (Refs #11903) (#12023)
Master's spec-guards and coverage checks are red: 21 seals "newly do not
hold", all on gen_hash_zig of specs/tri/collections, io and trees. The
seals come from the T27 OS lab seal leg (t27os#31, merged 0a50691) at
master 447e856, run 40099325826, published as
runs/447e8569691e8569c6b6c26bcc9b23f03ced5bdd.seals/ in
Trinity-S-AI-DNA/t27os: a t27c built off master in CI, no /Users/ path.
Each of the 20 hashes the master spec-guards log names as "current"
equals the hash written here; the 5 remaining files are their twins.
Specs are unchanged; only gen_hash_zig and sealed_at move.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* docs(analog): competitor delta 2026-10-24 as section 12 of competitors.md (Closes #12026) (#12029)
Reference-chain risks (OSDI 0.4 vs 0.5, IHP dev moving) go to #12027; the commercial speed bar is named, the no-speed-claim line stays.
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* t27b: wasm32 emitter M-B -- parameter-carrying scalar exports lower to the floor-5 law (#11840) (#11983)
* t27b: wasm32 emitter M-B -- parameter-carrying scalar exports lower to the floor-5 law (epic #11840)
The emitter's second cut: a pub fn with parameters whose body is one
`return <expr>;` over + - * / on the i32 carrier lowers to a stack program of
the floor-5 law's opcodes (local_get/i32_const/i32_add/i32_sub/i32_mul/
i32_div_u), its functype composed by wasm_law::functype_full over the fn's own
parameter list. `/` and integer @divTrunc arrive as ArithOp::Div and cross as
i32.div_u. Everything else in a param'd pub fn is refused by name (expression
kind, arithmetic op, local variable, fn return type, fn parameters off the
i32 carrier). The M-A constant-leaf path is byte-identical: the 100-spec
Node-vs-native battery stays 100/100.
Verified: cargo build --release -p t27b && cargo test -p t27b -> 175 passed,
0 failed; the pinned latency/frame module instantiates in Node's WebAssembly,
latency(7,2)=96 and frame(33)=3.
Hand-written Rust by owner approval (owner-approved-foreign, session
2026-10-23, confined to cli/t27b); the spec that replaces this file is
specs/tri/t27b/wasm32.t27 under the port epic.
Refs #6198 (port epic), advances #11840 (M-B); companion to #11942, #11964.
* spec(t27f): live_scalar_closure -- the two emitable laws of live_mode as the stack expressions the M-B cut lowers, transcription-pinned to the law (415 asserts); builds the 87-byte t27f.wasm whose exports Node verifies (frames 1/1/2/3/65, latency 96/256) (Refs #6198, advances #11840 M-B, #10262)
* t27b: the select pattern -- if (<param> == 0) return <const>; return <const>; lowers to eqz+select (the law floors 0x45/0x1B); live_scalar_closure gains paints_due verbatim, transcription-pinned (66 asserts, 481 total); the trio wasm exports all three, Node verifies (Refs #6198, advances #11840 M-B, #10262)
* t27b: the trio module held by the suite -- build live_scalar_closure, Node-verify all three laws (the exact PROVENANCE numbers); suite 176/0 (Refs #6198, advances #11840 M-B, #10262)
* t27b(wasm): floors 9+10 -- the body lowering and the IR-to-descriptor glue as law (spec+gen+seal, 62/62) (#12030)
* t27b(wasm): floor 9 -- the body lowering as law: lower_stack's postfix walk (lower_expr_node: EK_VAR->local.get, EK_CONST->i32.const through the u32>=2^31 carrier crossing, EK_ARITH->the floor-5 opcode byte, Div via i32.div_u), const_insn's carrier crossing for every carried type (i64/u64 sleb image, f32/f64 LE bits through the floor-4 fns, the i32 image otherwise), sleb_value the reader half so every crossing round-trips, select_body's five instructions (true-const, false-const, local.get, eqz, select); the capstone re-derives the 117-byte trio module's three bodies byte for byte through floor 7 over floor 9 lowering; 56/56 tests, capstone mutation-checked Refs #6198 (port epic).
* t27b(wasm): floor 10 -- the IR-to-descriptor glue as law: emit()'s prog walk over a FACT TABLE (one 48-byte row per fn: flags, name, nparams, the return type name, the body shape, the body's floor-8 verdict body_r, a payload pointer into a 16-byte NODE AREA, the line) filling floor 7's three areas -- walk_refusal (first refusal wins, empty export set REF_MODULE, malformed table fails closed), walk_refusal_row (the adapter's map back to the refusing fn's name and line), walk_prog (per-fn desc_put + name append + floor-9 body lowering with a per-shape worst-case capacity reserve: 12 for a carried const, 6/node postfix, 21 select), fn_body_bytes (each shape's body with its trailing end byte), walk_names_len/walk_bodies_len; capstones re-derive floor 7's 117-byte trio (with skip rows proving tests and private fns are not exports) and floor 4's 43-byte the-answer leaf byte for byte through the walk -- the thin-adapter contract emit() delegates onto in the follow-up PR (this PR stays spec+gen+seal, 0 foreign lines); 62/62 tests, capstone mutation-checked Refs #6198 (port epic).
---------
Co-authored-by: gHashTag <gHashTag@users.noreply.github.com>
* spec(fpga): wasm board P3 -- i64.const joins as the low-32 floor (0x42, the i32 SLEB submachine)
The fleet crossing (t27os#3) refused the two i64 corpus specs: the MVP engine
had no 0x42. This adds it as the alias of the i32.const path -- the same
five-byte SLEB128 submachine, the same u32 stack word, so every i64 whose low
32 bits are what the answer contract expresses now crosses (canonical SLEB of
five bytes or fewer; a longer continuation still refuses with ERR_LEB, the
same honest boundary as i32). The 64-bit datapath stays a separate increment.
Behavioral test p3_i64_wire_programs (18/18, 0 vacuous): the fleet's exact
programs over the wire with save/restore of page 0 -- 42 B1 D1 F9 D6 03 0B
answers DE68B1 (u64 987654321's low 24) and 42 7B 0B answers FFFFFB (i64 -5),
matching the emitter's canonical bytes bit for bit.
* docs(analog): PSP103 and cornerMOSlv hashes at the IHP pin, dev and main; 3 skill traps (Refs #12027) (#12032)
Prose only. Read-only GitHub tree API comparison dated 2026-10-24: dev equals the pin on 17 of 17 files, main differs on 2. Skill traps: issue-shape outcome rules, T27 OS control client.
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* docs: lane handoff for the P4 float floor (Refs t27os#3, stacks on #12033)
* fix(gen-zig): an arrow in a fn-header parameter list consumes into the parameter (Refs #11940) (#12037)
After a complete parameter type the only continuations of a parameter list are ',' and ')', so an arrow there can only be the return of the parameter's own fn type. It was read as a phantom name: fn modify(fn: Fn(S) -> S) parsed as [(fn, Fn(S)), (S, )] and the emitted Zig carried a parameter with an empty type plus a phantom discard line (state.t27 modify, reader.t27 asks/local, writer.t27 censor). The fn TYPE head also rides the main type-identifier arm now: 'fn' lexes as KwFn, not Ident, so a fn-typed parameter used to return an EMPTY type and the header died on Expected LBrace.
Seals for the eight touched specs regenerated with a t27c built from this rebased tree; FROZEN_HASH restamped from the merged compiler.rs. Budget: hand-written foreign lines +38/-7 in compiler.rs, paid for with dead-code deletions (host/driver.rs -10, host/irq.rs -5, runtime/mod.rs -20).
* ci(seals): re-seal three drifted twins -- t27f/petal_menu, t27os/agent_parts, t27os/devices (spec+all gen hashes moved) (Refs #11038) (#12039)
* spec(fpga): wasm board P4 -- the float consts as bit words (0x43/0x44, the raw-IEEE floor)
The fleet crossing (t27os#3) refused the float corpus specs: the engine had no
0x43 and no 0x44. This adds both as RAW-BIT words -- a real wasm f32.const
carries its four IEEE-754 bytes little-endian with no LEB at all, f64.const
its eight, and the floor pushes those bits as the u32 stack word: f32
wholesale, f64 as the low 32 (its first four bytes), the same honest floor as
P3 gave i64.const. Float arithmetic and the f64 high half stay a separate
increment.
Placement follows the lane handoff's law: grep 'scrap_op == OP_I32_EQZ' finds
exactly ONE dispatch site (the MVP code[] runner and the user uprog[] runner
share it through run_base), the float arm is a proper sibling of the i32/i64
const arm there, inserted by exact-match edits with the one new closing brace
placed by a brace-depth pass -- a pure insertion, zero existing lines touched,
brace balance 0 and t27c check at its baseline 0 errors / 0 warnings.
Behavioral test p4_f32_wire_programs (18/18 total, 0 vacuous, 20 asserts in
the new test): the fleet's exact programs over the wire with save/restore of
page 0 -- 43 00 00 20 40 0B (f32.const 2.5, word 0x40200000) answers low24
00 00 20; 44 00 00 00 00 00 00 04 40 0B (f64.const 2.5) answers its honest
zero low-32; 44 18 2D 44 54 FB 21 09 40 0B (f64.const pi, 0x400921FB54442D18)
answers 18 2D 44 -- the low24 of 0x54442D18, so the low-32 law is witnessed
on a nonzero half, not just a zero.
Refs #12033, t27os#3
* spec(t27f): live_glue_layout -- the layout plane of the struct-path export glue: the 23 CONSTANT gx_ exports (ptr/len/cap pairs of the fixed 143,692-byte layout) the wasm32 emitter's M-A cut lowers today, each returning the contract card's own constant so the plane cannot drift from live_struct_glue; pairs tile the memory in the card order (no gaps, all inside MEM_CAP), the 10 stateful names named and left to the stateful floors; 3/3 tests, 49 runtime asserts, 0 vacuous; emitted 683-byte wasm32 module, 23 exports, all values verified in a wasm runtime; the emitter gap (memory/data/globals, locals, loops, calls, u64, void, ptr params) filed on #5980. Refs #10262, #11781; companion to #12005's contract, the struct-path emitter writes against both. (#12040)
* fix(specs): generic collections speak fn-level comptime params (Refs #11940 #12000)
Convert the convertible members of #11940's 14-spec blocked table to the
fn-level comptime grammar #12000 landed, following box.t27: types bind at
each fn (fn some(comptime T: type, value: T) -> Option(T)) and call sites
pass them explicitly (some(i64, 42)). maybe's bind/map take the function
type as a second comptime param (bind(i64, MaybeBindFnI64, m, f)), which
expresses the tie to T at the call site while ADR-008 still rejects
generic fn-type aliases. Beyond the signatures, the never-compiled bodies
needed the emitter's Zig shapes: .field = value inits, &[_]T{} empty
slices, AutoHashMap, and renames forced by the target language (Result's
E collided with math::constants' Euler E in the use-resolved source; its
error field/param are Zig keywords). reader/writer/state stay untouched:
their fn-typed fields/params and closure bodies are sub-slices 2+3,
compiler-side. t27c test-report, measured with a current build (the
shared t27-build binary predates #12000 and blocks box.t27 itself):
maybe 14/14, either 15/15, result 10/10, tuple 9/9, queue 5/5, option
4/4, set 4/4 (1 pre-existing vacuous), io 2/2 -- eight green. tree now
blocks on its self-referential value field (needs indirection),
ring_buffer on the cross-module Option(T) reference and an
allocator-backed create_buffer, btree on allocator values at call
sites: each advanced to its own next defect, recorded in .trinity/seals.
21 seal files resealed (both naming copies); seal --verify MATCH on all
eleven.
* fix(specs): generic collections speak fn-level comptime params (Refs #11940 #12000) (#12045)
Convert the convertible members of #11940's 14-spec blocked table to the
fn-level comptime grammar #12000 landed, following box.t27: types bind at
each fn (fn some(comptime T: type, value: T) -> Option(T)) and call sites
pass them explicitly (some(i64, 42)). maybe's bind/map take the function
type as a second comptime param (bind(i64, MaybeBindFnI64, m, f)), which
expresses the tie to T at the call site while ADR-008 still rejects
generic fn-type aliases. Beyond the signatures, the never-compiled bodies
needed the emitter's Zig shapes: .field = value inits, &[_]T{} empty
slices, AutoHashMap, and renames forced by the target language (Result's
E collided with math::constants' Euler E in the use-resolved source; its
error field/param are Zig keywords). reader/writer/state stay untouched:
their fn-typed fields/params and closure bodies are sub-slices 2+3,
compiler-side. t27c test-report, measured with a current build (the
shared t27-build binary predates #12000 and blocks box.t27 itself):
maybe 14/14, either 15/15, result 10/10, tuple 9/9, queue 5/5, option
4/4, set 4/4 (1 pre-existing vacuous), io 2/2 -- eight green. tree now
blocks on its self-referential value field (needs indirection),
ring_buffer on the cross-module Option(T) reference and an
allocator-backed create_buffer, btree on allocator values at call
sites: each advanced to its own next defect, recorded in .trinity/seals.
21 seal files resealed (both naming copies); seal --verify MATCH on all
eleven.
* fix(gen-rust): slice out-params borrow mutably, undefined array locals zero-init (Refs #12036) (#12042)
Two defects left the wasm floors' generated Rust uncompilable
(gen/rust/tri/t27b/wasm.rs, spec fns of specs/tri/t27b/wasm.t27):
1. The call-arg wrapper for a callee-WRITTEN slice parameter wrapped the
argument wholesale, but the slice arm of expr_to_rust had already
emitted a SHARED borrow. A spec passing buf[0..5] to such a callee
reached rustc as `&mut &buf[0..5]` -- a mutable borrow OF a reference
(E0596). Strip the leading shared borrow and borrow the place itself:
`&mut buf[0..5]`.
2. A typed local declared `= undefined` (or with no initialiser) emitted
a bare `let mut v: [T; n];`. When the array is filled through a
`&mut arr[0..n]` handed to a callee, rustc cannot see that write --
it does not count as initialising the array -- so every later read
was E0381. Zero-initialise arrays of zeroable element type instead,
matching the interpreter, which reads only the written prefix. NOT
Default::default() (withdrawn in #3223: [usize; 256] has none), and
not scalars: there a bare `let x: T;` is legal Rust and a read before
a real assignment should fail loudly.
Applied at BOTH local-emission sites: gen_fn carries its own copy of
the local logic, and a fix at only one of the two changes no output.
Regenerated gen/rust/tri/t27b/wasm.rs: export_section (vtmp, htmp) and
type_body (ps, rs). Acceptance: `cargo build --release -p t27b` now
compiles (it includes the file by path from wasm32_emitter.rs); before,
6 errors (E0596 x2, E0381 x4). Full suite: cargo test -p t27c --bin t27c
1782 passed, 0 failed. FROZEN_HASH restamped via the M5 frozen-digest
ceremony (old frozen binary printed the new line).
Budget: bootstrap/src/compiler.rs +30/-1, inside the standing exception
(owner 2026-10-05) and the 40/file, 80/PR caps; paid with the dead
bootstrap/src/host/histogram.rs (-286, rustc: every item never used) and
its two host/mod.rs lines. gen/ is t27c output, not hand-written.
Refs #12036
* test(analog): a planted-fault negative control in each of the five analog specs that had none, coverage 145/150 -> 150/150 (Refs #12041) (#12046)
Four new tests that plant a fault and assert the spec's own check refuses it (swapped ROM slice, flipped ROM bit, flipped stamp word in the folded register, flipped log word in a slice copy), and one rename of a test that already planted a fault. Each new test fails under a blind or mutated check (6 mutations, all FAIL). Seals re-saved with the master-built t27c.
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* t27b(wasm): M-C -- comparisons and the eqz fold lower; the law's floor 11 (Refs #11983, #11840, t27os#3) (#12048)
The named gap of t27os#3's probe closed on the emitter side: the cell
executes the full 0x45-0x4F family while the emitter's own refusal said
'parameters, i32 constants and + - * / only'. Now the six IR comparisons
lower on the i32 carrier:
- law floor 11 (specs/tri/t27b/wasm.t27, spec+gen+seal, 65/65): the six
opcodes (0x46 eq, 0x47 ne, 0x48 lt_s, 0x4a gt_s, 0x4c le_s, 0x4e ge_s),
their writers, cmp_opcode, and eqz_fold -- the rule that 'x == 0' folds
to one eqz, 'x != 0' to two. Floors 8 and 9 mirror the walk: EK_CMP
carries (no comparison refuses on its operator), lower_expr_node emits
the opcode byte, the refusal detail words updated in lockstep with the
emitter's own texts.
- emitter (cli/t27b/src/wasm32_emitter.rs): the ExprKind::Cmp arm -- the
fold decision comes from the law (wasm_law::eqz_fold), the operand the
emitter picks; everything else is lhs, rhs, opcode, exactly the arith
arm's postfix shape.
SIGNED for the ordered four, matching the house pattern: '/' lowered to
div_u because the die taught us the die's div is unsigned; here the die's
own law (wasm_board_ax7203.t27, lt_s32(0xFFFFFFFF, 1) == 1) numbers the
same bytes signed, and t27's ordered comparisons on i32 are Zig's signed
ones -- die and source agree, so signed is both.
Evidence: 'pub fn lt(a: i32, b: i32) -> bool { return a < b; }' compiles
to a 39-byte module whose expression is 20 00 20 01 48 0b (local.get 0,
local.get 1, i32.lt_s, end). The die fleet (AX7203, /dev/cu.usbserial-130,
P3 bitstream, cmp_fleet_mc.py from tonight's bridge): 6 ops x 6 pairs --
(7,3), (-5,2), (3,3), (-2147483648,2147483647), (0,0), (-7,-3) -- 36
exact, 0 not; every signed-sensitive cell (lt(-5,2)=1, lt(-7,-3)=1,
ge(-7,-3)=0, the full-range pair) confirms signed on silicon. The
standard-runtime twin runs the same opcodes in Node: MC OK.
Budget: 73 foreign lines added, 142 deleted (five inline tests that
duplicated tests/wasm32.rs one-for-one removed, the file split its header
already documents). wasm32 gate 11/11, equality battery 100/100; the two
lib failures (hir_roundtrip bridge/uart path lookups) are pre-existing on
the base and untouched here.
* chore(seals): reseal the 247 seals #12042 moved -- master Spec Guards green again (Refs #12036) (#12062)
#12042 changed gen-rust (slice out-params borrow mutably, undefined array
locals zero-init), so every spec with a Rust leg emits different code and
Spec Guards on master 69eef64da counts 247 STALE generated-code hashes.
These are the seals the T27 OS lab wrote with its own master-built t27c
(tri seals drift --fix, lab run 40112957744, receipt
Trinity-S-AI-DNA/t27os runs/69eef64da108d79238f6316715c38c32c35a7972.27b6b423.json,
.seals/CHANGED.txt = 247 files), copied byte for byte: 246 move only
gen_hash_rust (+ test_runner where the runner hash moved), one
(fpga_fpga_wasm_board) also catches up its spec_hash after a spec edit.
Both legs on the receipt: t27c labs 8/8, t27b labs 8/8 asserts 34.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* docs(analog): what the seal command refuses on the 16 milestone specs, one planted fault at a time (Refs #12065) (#12066)
The bare seal form refuses 0 of 16 (exit 0, hashes only); --save refuses
16 of 16 on failing tests and --verify refuses 16 of 16 on a hash mismatch;
all three pass the 16 clean specs. Four single-line faults survive the
mutate plant tool (no test pins them). The all-at-once run is disclosed as
confounded and not used. The SC-002 row of the release notes is edited in a
follow-up once #12063 lands.
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* spec(tri/t27b): wasm.t27 reuses macho put_bytes/dec_len -- master duplicate-bodies red, rebuilt on master (#12038)
* spec(tri/t27b): wasm.t27 reuses macho put_bytes/dec_len instead of its own copy_bytes/u32_dec_len -- master duplicate-bodies red, rebuilt on master 2ccaee065 after #12030/#11983 added callers
Refs #12024
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore(seals): wasm seal + gen from T27 OS lab run 40115576122 after the master merge
Lab receipt runs/7a9b09f8a459092951970eb1be2fe5d4d882e3fc.9c523495.json:
t27c wasm 65/65 + macho 22/22, t27b wasm 65/65 + macho 22/22 (asserts 790).
Seal and gen/rust/tri/t27b/wasm.rs copied byte-for-byte from the receipt's
.seals/ and .gen/; nothing hand-edited.
Refs #12024, see #11840
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27os): devices.t27 -- lg_tail_cmd runs nothing for an unsafe home (root_safe guard) (Refs #11991) (#12009)
* spec(t27os): devices.t27 logs tail job -- lg_tail_cmd copies the last LG_TAIL bytes of log.txt and renames them whole; lg_home_ok refuses a home that could break the quote (Refs #11991)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore(seals): devices, agent_parts, petal_menu resealed by lab run 40105075253 (receipt runs/5d58803ca...5af120b5, both legs 26/26) (Refs #11991)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore(seals): take master's agent_parts + devices seals before update-branch; lab reseal follows (Refs #11991)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore(seals): take master's petal_menu seal before update-branch (Refs #11991)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore(seals): devices.t27 seal from lab run 40116665819 (t27c 26/26, t27b 26/26) after update-branch onto master (Refs #11991)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27o): install workflow quotes expression literals with apostrophes (Refs #11873) (#11904)
* spec(t27o): install workflow quotes expression literals with apostrophes (Refs #11873)
GitHub expressions accept only single-quoted string literals; the mode
line of WORKFLOW_YAML used double quotes, so the workflow the Trinity App
proposes on installation would fail the parse. The file comment that
claimed an apostrophe opens a t27 char literal is corrected (str holds
apostrophes, e.g. specs/analog/accept_sar.t27).
New gate expressions_single_quoted over all three YAML templates, with
the shipped line as the refused negative control.
Refs #11873 -- see Trinity-S-AI-DNA/t27os#10 (tick-24 side finding).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27o): test-body comments use // -- a ; inside a body is a parse error (Refs #11873)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore(seals): t27o_T27oInstall resealed by the lab's master-built t27c (lab run 40100846805, receipt runs/258729db1e75cc7647c67f4ef9e763d2ffbd310b.c5a49219.json: t27c 12/12, t27b 12/12 asserts 60)
Refs #11903
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27os): lab_publish.t27 -- a lab receipt is published on master, whatever ref was dispatched (#12012)
* spec(t27os): lab_publish.t27 -- a lab receipt is published on master, whatever ref was dispatched; the two lab.yml publish steps as text, with the run 40092668897 step and the t27b pull-rebase step as refused specimens (Refs #11889, Refs #11873)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27os): lab_publish.t27 -- the rebase guard is a test, not an invariant: t27c lowers an invariant to a Zig comptime block and a scan of a 900-byte step text there blocked lab run 40093374520 (Refs #11889)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* tri coverage: a row whose only seal mismatch is gen_hash_rust says STALE-T27C? (Closes #12071) (#12072)
Loop tick 8 (#12070) lost an hour to 14 gen_hash_rust MISMATCH rows that were
no drift: the t27c it ran predated the last Rust emitter change (#12042), and
two seals saved with it went red in CI (#12068). Nothing in the report told
the two cases apart.
specs/tri/coverage/coverage.t27 gets rust_only_mismatch(text): true when the
spec_hash and the zig, verilog and c twins print a whole MATCH line and a line
starts with gen_hash_rust: MISMATCH. emit_row appends STALE_HINT to a row whose
seal fact is missing and whose seal text has that signature. A spec edit moves
spec_hash too, so it never has the signature. The exit code, --strict and every
other row are unchanged. No glue change, no git call, no hand-written non-t27
line: the issue's first design (compare the builder sha with the last
compiler.rs commit) needed a git call in hand Rust and was dropped.
3 new tests (21 now): the signature on the measured stale text in any line
order, its refusal for drift / a clean seal / empty text / a missing twin /
lines that only quote the words, and the row byte for byte (hint appended,
drift row unchanged, a seal that holds has no hint, a short buffer refuses the
longer row). The existing row test now plants a real spec_hash drift instead of
the Rust-only text, which is the signature.
Seal re-saved with a t27c built from master 19a89f1e39 (built_by +19a89f1e3);
--verify prints all hashes MATCH; the tracked Rust twin is regenerated.
tri coverage on this spec and the analog pair: gaps 0, 15/15.
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* test(analog): pin the drive-mode code table and the 9999 no-edge value; two load mutants shown equivalent (Refs #12067) (#12068)
* test(analog): pin the drive-mode code table and the 9999 no-edge value; document two equivalent load mutants (Refs #12067)
Finding 4 of the 2026-10-25 survivor sweep left four lines that no test
failed on. Three are now pinned, one pair is shown to be equivalent:
- DR_UP 1 -> 7 is killed by a new sar_kick_net test that reads the dense
code table (DR_IDLE < DR_UP < DR_DOWN < DR_IDEAL < DR_MIRROR < 5) and the
two PMOS and two NMOS drivers by their code number.
- return 9999 -> 9998 at both no-edge returns of the chain error is killed
by a new sar_logic test that asks for an edge the run never made.
- SL_DC_LOAD_R +-1 and SL_TG_IN_LOAD +-1 still survive. The arc model is
integer ps with a floor, so a step of one in a 4-5 digit load moves an arc
by less than one ps and no integer output changes; the weighted probe sums
are identical to the digit for 431, 33381 and 33379. Written up as section 7
of docs/analog/seal-refusal-2026-10-25.md.
Both specs re-saved and verified (hashes MATCH); tests 24/24 and 18/18;
coverage gaps 0.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* analog: re-save the sar_logic and sar_kick_net seals with a t27c built from master -- the tick 7 saves carried the pre-#12042 Rust hash (Refs #12067)
CI on this PR failed in coverage and spec-guards with "FAIL: 2 seal(s) newly do
not hold ... still hashes the same, but gen_hash_rust do not" for
analog_AnalogSarKickNet.json and analog_AnalogSarLogic.json (gen-drift). Cause:
the tick 7 saves used a t27c built before #12042 (55040898f9) changed the Rust
emitter, and #12062 had re-saved every other seal with the new emitter.
Re-saved both with a t27c built from master 19a89f1e39 (tests 24 and 18, both
pass). The diff is only the gen_hash_rust field and the seal metadata; the spec
hash and the zig, verilog and c hashes are unchanged. --verify prints all
hashes MATCH for both, tri coverage prints gaps 0 coverage 10/10.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* fix(t27os): lv_copy_row copies the row's written bytes, not the dead tail (Closes #11919) (#12074)
* fix(t27os): lv_copy_row copies the row's written bytes, not the dead tail of its slot (Closes #11919)
Rebuilt on master b9d83f9ef2: #11920 conflicts only in the lanes_view seal,
which master resealed in #12062; the seal is re-made by the lab's
master-built t27c.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore(seals): t27os_T27osLanesView resealed by the lab's master-built t27c (receipt runs/7d83327e57ad124f3eebe6ae7c2367bac10d85ec.9f16a870.json: t27c 34/34) (Refs #11919)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(crons): the night loop's SYNC-STEP points at t27os sync_gate.t27 and skips the gate's own file (Refs #11980) (#12084)
* spec(crons): the night loop's SYNC-STEP points at t27os sync_gate.t27 and skips the gate's own file -- #11981 rebuilt on master (Refs #11980)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* seal(crons): t27os-night-loop reseal from the t27os lab receipt a01bf8745c (t27c 27/27, t27b 27/27) (Refs #11980)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* test(analog): pin the two test-gap mutants of sar_dff_q and gate the rest with an accepted file (Closes #12083) (#12085)
tri mutate spec on specs/analog/sar_dff_q.t27 (master b9d83f9ef2): 56 mutants,
45 killed, 6 survived, 4 hung, 1 unviable. Two survivors were test gaps
(dq_scale loop bound at line 136, dq_solve_k sweep bound at line 174); two tests
appended after the last test now kill them. The other four survivors are
equivalent or equivalent in practice, and the four hung drop-step mutants end
only by the clock; docs/analog/mutation-accepted-sar_dff_q.txt names all eight.
After: 56 mutants, 47 killed, 4 survived, 4 hung, 1 unviable; the gate with
--accepted exits 0. The seal of analog_AnalogSarDffQ is re-saved with the
master-built t27c.
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* spec(t27os): labs receipt_verdict -- an omitted, BLOCKED, failed or vacuous spec makes the receipt red (Refs #11873) (#12087)
* spec(t27os): labs receipt_verdict -- an omitted, BLOCKED, failed or vacuous spec makes the receipt red (Refs #11873)
Rebuilt on master e518fc3d56 from #11875 (DIRTY: master rewrote labs.t27
around the gate-command tests). Same fn and test, placed after run_verdict.
Refs t27os#9.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* seal(t27os): labs.t27 seal from lab receipt 4bde0df9a1.e4ffcc1e (Refs #11873)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(crons): night-loop card measures its own prompt drift (Refs #12095) (#12100)
The night-loop card names its steps as law, but the prompt the cron runs
lives in ~/.t27os/loop/tick.sh, outside any repository. prompt_drift counts
the law steps (BOARD-GUARD-STEP first, then AUDIT, PR-GATE, UI-HEALTH, SYNC,
SWEEP, TASK-PICK, RECEIPT-COMMENT, RETROSPECTIVE) that a prompt does not
name; a prompt launches only at drift 0. Tick-80 and tick-102 prompts both
measure drift 5. Negative controls: one dropped step gives 1, dropping only
step 0 is caught, an empty prompt gives STEP_COUNT+1.
One-commit rebuild of #12047 on master 141605504e (its commits carried only
a cross-repo reference, so L1 was red). Spec blob 5315ac5c99 is byte-identical
to the one lab run 40126680581 passed (t27c 31/31, t27b 31/31, asserts 88);
the seal is the one taken from that receipt.
Refs #12095, see Trinity-S-AI-DNA/t27os#3
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* spec(t27os): receipt result section -- typed rows, one branchable ok (Closes #11954) (#12101)
Rebuilt on master as one commit: the stacked #11955 went DIRTY after its
base #11875 was superseded by #12087 (receipt_verdict now on master).
Same file, same tests; uses labs.t27 :: receipt_verdict, restates no rule.
Refs Trinity-S-AI-DNA/t27os#18
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(t27f): measure_live sorts with live_mode's sort_u32 -- last sort_asc_u32 copy gone (Refs #11885) (#12104)
* fix(t27f): measure_live sorts with live_mode's sort_u32 -- last sort_asc_u32 copy gone (Refs #11885)
sort_asc_u32 in specs/t27f/measure_live.t27 was a byte copy of sort_u32 in
specs/t27f/live_mode.t27. live_mode exports sort_u32; measure_live imports it
and drops the copy; the duplicate-bodies baseline loses its sort_asc_u32 row.
Rebuilt on master as one commit (was #11916, DIRTY/stale base).
Refs #11885
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* seal(t27f): live_mode + measure_live resealed by the T27 OS lab (run 40130266778, receipt 1787d531c8.c5c5f819) (Refs #11885)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* test(analog): pin 29 survivors of sar_switch_q with 14 new tests, accept the 19 left (#12102)
* test(analog): pin 29 survivors of sar_switch_q with 14 new tests, accept the 19 left (Closes #12086)
tri mutate spec on specs/analog/sar_switch_q.t2…
Floor 3 of the wasm32 format law: local groups, func entries, vec_prefix framing, code_section with the explicit count, and the instruction floor (i32.const via floor 1's sleb with the textbook vector, local.get/set, i32.add, end). The capstone: a whole 26-byte module pinned byte-for-byte, hand-verified twice, plus the validation-shaped variant. 15/15 both compilers, 0 vacuous. Floor 4 mapped (exports, call/control, i64, globals/memory/data, the two-byte uleb). Partial-commit note: the pathspec commit carries only wasm.t27 — the shared worktree's other staged files stay for their actors.