Skip to content

spec(ml): train_slice_model -- main() trains 20 steps and writes a checkpoint to a real file (Closes #10183) - #10186

Merged
gHashTag merged 1 commit into
masterfrom
spec/train-slice-model
Oct 18, 2026
Merged

gHashTag merged 1 commit into
masterfrom
spec/train-slice-model

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Closes #10183. Part of epic #10024 ("our own model"), cell 25 "t27c --backend ml". Follows #10165.

What

specs/ml/train_slice_model.t27 (pure t27): pub fn main() -> void trains the 3-head slice of specs/nn/hslm_backward.t27 for 20 steps, asserts the last loss is below half the first, writes a 379-byte checkpoint (243 trits, 27 biases, alpha, first and last loss, checksum) to /tmp/t27_train_slice.bin with host_open / host_write / host_close, reads it back with host_read, compares every byte, and re-checks the losses decoded from the bytes that came off the disk. The training step (init_model, mean_loss, train_step) is reached through use, not copied. put_u32 / get_u32 and the magic bytes come from ml::file_io_contract; its ckpt_write is not used because the checkpoint (379 bytes) does not fit one 256-byte slot.

No Rust, no other language: t27c compile --backend ml from #10165 lowered the spec as it is. Two t27-only adaptations to the import splice were needed and are in the diff:

  1. use_resolve splices fn/struct/enum/const/type from an import but not module-level var. The new spec declares the sixteen state variables of hslm_backward (declarations only; if one is added there, this file stops compiling with "use of undeclared identifier" instead of drifting).
  2. use_resolve rewrites module::name only in the importing file, not inside spliced declarations, so ternary_ste::requantize(...) inside the spliced train_step reached Zig as an undeclared ternary_ste. specs/nn/hslm_backward.t27 now calls the five ternary_ste functions by bare name (10 call sites, use nn::ternary_ste; unchanged). Its result is identical: 15/15 pass, 0 vacuous before and after.

Both are limits of use_resolve.rs (hand-written Rust), recorded here and not patched.

Lab measurements (Railway lab, x86_64, t27c built from origin/master 8887f17, zig 0.16.0)

  1. t27c test-report specs/ml/train_slice_model.t27: tests 5, pass 5, FAIL 0, vacuous 0 of 5 (runtime asserts per test: 1, 1, 6, 1, 3). t27c test-report specs/nn/hslm_backward.t27 after the edit: tests 15, pass 15, FAIL 0, invariants 3 proved, vacuous 0 of 15.
  2. t27c compile specs/ml/train_slice_model.t27 --backend ml built a 10118114-byte binary; running it: exit 0. /tmp/t27_train_slice.bin is 379 bytes, sha256 0dfdef2200b3daa2930cb081f8fb4a58caf5677bae3f329ee23f0e2c328cdbeb (identical on a second run). Losses recorded in the file (f32): first 3.2975044, last 0.32346588 (ratio 0.098, bar is below 0.5). A third f32, alpha, is 0.57535255.
  3. Negative control: with /tmp/t27_train_slice.bin made a directory the binary aborts, exit 134, run(STEPS) = 61 (TRAIN_ERR_OPEN) against TRAIN_OK = 0. Removing the directory and rerunning gives exit 0 and the same sha256. In the spec itself, zero_steps_do_not_halve_the_loss shows the loss check can fail (TRAIN_ERR_LOSS, nothing reaches the disk) and a_flipped_byte_is_refused shows the checksum and magic checks can fail.

t27b ledger

t27b test --blockers specs/ml/train_slice_model.t27 on the lab: exit 2, first blocker ExprCall(undeclared fn) (host_open), same as host_io_model. One row added to docs/reports/t27b_expectations.json (blocked, unimplemented) and max_not_pass 32 -> 33; the ledger holds 33 non-pass entries, equal to the cap.

Not claimed

Head slice only (9 inputs, 27 classes), not the three transformer blocks; plain SGD, not AdamW; one fixed batch; f32 checkpoint; Linux x86_64 syscall shim only. specs/igla/own_model.t27 and own_model_board.t27 are not touched.

🤖 Generated with Claude Code

…eckpoint to a real file (Closes #10183)

Part of epic #10024, cell 25. specs/ml/train_slice_model.t27 reuses init_model,
mean_loss and train_step from specs/nn/hslm_backward.t27 through `use`, runs 20
steps, refuses a run whose loss did not halve, writes a 379-byte checkpoint
(trits, biases, alpha, first and last loss) to /tmp/t27_train_slice.bin with
host_open/host_write/host_close, reads it back with host_read and compares every
byte. 5 tests, 0 vacuous, one negative (0 steps does not halve the loss).

Two t27-only adaptations to the import splice, no Rust touched:
- use_resolve splices fn/struct/enum/const/type but not module-level `var`, so the
  new spec declares the sixteen state variables of hslm_backward (declarations
  only, none of the logic).
- use_resolve rewrites `module::name` only in the importing file, not inside the
  spliced declarations, so hslm_backward now calls ternary_ste functions by bare
  name (10 call sites). Behaviour is unchanged: 15/15 tests, 0 vacuous, as before.

t27b ledger row for the new spec (blocked, host calls) and max_not_pass 32 -> 33.

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

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-18 03:41:00 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)=0f8c66b9ed0e != 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 enabled auto-merge (squash) October 18, 2026 03:41
@gHashTag
gHashTag merged commit 0d6c3d3 into master Oct 18, 2026
28 of 32 checks passed
gHashTag added a commit that referenced this pull request Oct 18, 2026
…or the same review (Refs #10184)

#10186 added ml/train_slice_model and merged at 03:42Z through another
session's auto-merge, with no review. Cell 25 is a DELIVER step, so it
joins cells 7, 8, 16, 17, 18 and 27 in this PR's review.

Lab, master 2d358a7 + this change: ml/train_slice_model 5/5, 0
vacuous. Its --backend ml binary exits 0, trains one 3-head slice 20
steps (loss 3.2975044 to 0.32346588) and writes a 379-byte
/tmp/t27_train_slice.bin, sha256 0dfdef22...cdbeb; with that path made
a directory it aborts, exit 134.

Cell 25: grounded, PCT 30 (one slice, not the whole model), DRAFT.
Tally 1 published, 17 verified, 7 drafts, 2 gaps; 60%. own_model 9/9,
board 6/6, 0 vacuous. Negative control (STATUS[24] back to a gap):
2 FAIL. METRICS_BYTES 629.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Oct 18, 2026
…of a copy (Closes #10203) (#10205)

byte_total in specs/ml/train_slice_model.t27 (added in #10186) was a
line-for-line copy of byte_sum in specs/ml/file_io_contract.t27, which
that spec already imports. duplicate-bodies has been red on master since.
byte_sum is now pub and the copy is deleted; the two bodies were
identical, so no checksum changes and no ledger bless is needed.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Oct 18, 2026
…vidence to review again (Closes #10184) (#10185)

* spec(igla): own_model -- ground cells 8 and 24, put the DELIVER evidence to review again (Closes #10184)

Cell 8: playra/tern-tc-100m is public (API 200, a made-up name 401).
final.pt sha256 620c80b6...d08300, val bits per byte 0.4722 ternary
vs 0.4217 fp. It is a DELIVER step with no review, so it is a DRAFT.

Cell 24: t27c --backend ml (#10165) lowers host file I/O.
ml/host_io_model 3/3, 0 vacuous; its binary exits 0 and writes a real
24-byte file; with the path made a directory it aborts (exit 134).
It is a PRACTICE step with a passing test, so it is VERIFIED.

Tally 1 published, 17 verified, 6 drafts, 3 gaps; 59%. Lab, master
8887f17: own_model 9/9, board 6/6, 0 vacuous. Negative control
(STATUS[23] back to a gap): 2 FAIL.

#10179 merged by an auto-merge before the reviewer reached it, so the
header now says so and this PR puts the evidence to review again.

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

* spec(igla): own_model -- ground cell 25, the slice training binary, for the same review (Refs #10184)

#10186 added ml/train_slice_model and merged at 03:42Z through another
session's auto-merge, with no review. Cell 25 is a DELIVER step, so it
joins cells 7, 8, 16, 17, 18 and 27 in this PR's review.

Lab, master 2d358a7 + this change: ml/train_slice_model 5/5, 0
vacuous. Its --backend ml binary exits 0, trains one 3-head slice 20
steps (loss 3.2975044 to 0.32346588) and writes a 379-byte
/tmp/t27_train_slice.bin, sha256 0dfdef22...cdbeb; with that path made
a directory it aborts, exit 134.

Cell 25: grounded, PCT 30 (one slice, not the whole model), DRAFT.
Tally 1 published, 17 verified, 7 drafts, 2 gaps; 60%. own_model 9/9,
board 6/6, 0 vacuous. Negative control (STATUS[24] back to a gap):
2 FAIL. METRICS_BYTES 629.

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

spec(ml): train_slice_model -- a model spec that trains for real and writes its checkpoint to a file (own model cell 25)

1 participant