Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion .claude/skills/t27f/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ Traps from this tick (ffmpeg on the lab):
- lavfi rejects `d=.900`. Print the duration as `$((m/1000)).$(printf %03d $((m%1000)))`.
- `pkill -f` on the loop script leaves its child renders running. Find them with `ps -eo pid,args | grep '[s]h xf'` and kill them by pid.
- Through `fs-lab.sh`, `pkill -f 'why_seal'` also matches the ssh command line that carries it and kills your own session; the output comes back empty. Bracket the first letter (`pkill -f '[w]hy_seal'`) so the pattern does not match itself. A killed session leaves the detached ratchets it started running, so several end up writing one log; list them with `ps -eo pid,etimes,args | grep '[c]orpus-only'` before you read a verdict.
- **A new spec needs its own row in `docs/reports/t27b_expectations.json`**, or `t27b-native-ratchet` fails with UNLISTED. The issue gate still auto-merges the PR red: #10784 landed that way and left five unlisted specs for #10792 to carry. The lab is x86_64, and `t27b test` there ends with "the t27b JIT runs only on arm64". The front end still runs first: `t27b test <spec> --check` prints every blocker before that line. Run a blocked control next to your spec; `specs/t27f/frame_shard.t27` prints `unsupported construct ExprCall(rejected fn)`. If your spec reaches the JIT line with no blocker, and `t27c test-report` passes it, write a pass row. The PR's own arm64 run confirms or refutes the row. Keep the PR a draft until the row is in. Never guess "pass" without that check: a `[N]T` or `ExprCall` blocker turns a guessed row into a regression. Measured on glyph57, idea_factory and petal_menu (#10792).

**Holding the address when the voice runs long (t27#10629).** If an overlay must stay on screen for a minimum time and must also stay off a crossfade, then the crossfade has to move; the overlay cannot. Work out in frames the latest cut that still leaves the last scene its minimum: cut 1 is capped at `BEAT_CUT1_LAST_MS` = 13249. Prove it is the latest with a one-ms-later control. Only the voices the reel speeds up are affected, so the `cmp` diff is limited to those voices and to crossfade 1's offset. The cost is real: the crossfade starts up to 184 ms under the task's last word, and lesson 1's measured voice (1300/4200/6800) is one of the affected voices. Write a test that bounds that overlap.

Expand Down Expand Up @@ -405,7 +406,7 @@ of particles, and runnable in the OS itself and on FPGA. Two specs do this:
`BG`, `COL_A/B/C`, `RADIUS`, `GAIN`, `SPRING`, `DAMP`, `LAW`, `FORCE`, `KICK`, `CARD`. The five
are noir, neon, trit, paper and rain. **Add a preset by adding a column, never a branch in code.**
- **`specs/t27f/idea_factory.t27` is the factory**, `(IDEA, PRESET) -> RGB24 frames`. It wraps
(at most 9 characters per line, 4 lines per scene, `|` cuts a scene), lays out in the 3x5 font,
(at most 9 characters per line, 4 lines per scene, `|` cuts a scene), lays out in glyph57's 5x7 font,
assigns particles to glyph sub-slots and the card border, and closes on `CTA`.

**Keep it FPGA-shaped.** Use Q8 fixed point. The per-step and per-pixel paths use only add,
Expand Down Expand Up @@ -442,6 +443,28 @@ particles never settled into letters.
- **Base the branch on master's tip before the PR.** If the base PR (R3) merged first, reset the branch onto
`origin/master`. Untracked new specs survive the reset.

### Russian text: UTF-8 and the 5x7 font (t27#10788)

`specs/t27f/glyph57.t27` gives the factory Cyrillic. It decodes UTF-8 (`cp_len`, `cp_at`,
`cp_count`), folds lower case to capitals, and stores a 5x7 font. The font holds ASCII 32..95
and only the 21 Cyrillic capitals that have no Latin twin. The 11 look-alikes (A, Ve, Ie, Ka, Em,
En, O, Er, Es, Te, Ha) and Yo reuse the Latin glyph through the 32-entry `CYR_MAP`.

- **Write non-ASCII text as a `u8` array, never as `"\xNN"`.** L3 keeps sources ASCII. The t27c
lexer lowers only `\n`, `\t`, `\\` and `\"`, and keeps `\xD0` as four characters, so a
`\xNN` test fails with no error. Use `pub const RU_IDEA : [80]u8 = [208, 167, ...];` and pass
`RU_IDEA[0..80]` to a `[]const u8` parameter. `specs/tri/utils/terminal.t27` records the same
trap for `\x1b`.
- **Count widths in characters, keep positions in bytes.** Wrapping compares `cp_count` with
`MAXC`. The line start and end stay byte offsets, and the layout loop steps by
`bi = bi + cp_len(t, bi)`. An ASCII idea's numbers do not change, so the old tests still pin
the old layout.
- **Guard the font with a duplicate-bitmap test.** Every pair of stored glyphs must differ, and
every look-alike must light exactly its Latin twin's pixels.
- **Render a Russian idea without touching the committed constant.** In the lab copy, `sed`
`reel_frames(IDEA)` and `reel_cell(IDEA,` to use `RU_IDEA[0..80]`, next to the `PRESET` and
module renames.

## Check the whole corpus for import cycles (t27#10693)

dependency-cruiser's `no-circular` and madge's `--circular` list every module on a cycle.
Expand Down
33 changes: 33 additions & 0 deletions .trinity/seals/t27f_glyph57.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"built_by": "t27c-bootstrap@0.5.2+355d44a39",
"closure": [
{
"spec": "specs/t27f/scene_raster.t27",
"spec_hash": "sha256:7be7118d865aa65fd1ccb989ab160df2feb46c9ded0a15ca6510b747301ee4a6"
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:7b616c3b258394696d96adfd9f33a21a788063f0fcc37c591d2982b9e5c44645",
"gen_hash_rust": "sha256:cfe5802136fe85e748ec9880d796a0ddb5ee6fe69a4de466dc544f373aa1bfab",
"gen_hash_verilog": "sha256:bc6fce86cf24c30a17e3d29e3afebdd28d1aed88c760196a055aec250d2a549e",
"gen_hash_zig": "sha256:d57c0bf3b612b865a9df137514ae0e66790196114c7111977ca43d795f67c0e4",
"module": "glyph57",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-19T02:41:07Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:75e98adfcf86a4070c03154e29cf533833c618a1252652f2c20bf91b8425e6cd",
"spec_path": "specs/t27f/glyph57.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 7,
"total": 7,
"vacuous": 0
},
"toolchain": {
"test_runner": "sha256:8512b80da533b79289110fca4a65f3336abd7a059ca4b72ea595d5e33ff8ad10",
"zig": "0.16.0"
}
}
20 changes: 12 additions & 8 deletions .trinity/seals/t27f_idea_factory.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"built_by": "t27c-bootstrap@0.5.2+355d44a39",
"closure": [
{
"spec": "specs/t27f/glyph57.t27",
"spec_hash": "sha256:75e98adfcf86a4070c03154e29cf533833c618a1252652f2c20bf91b8425e6cd"
},
{
"spec": "specs/t27f/particle_ds.t27",
"spec_hash": "sha256:00e84a7492536bf54ac69aa0cd852dea4727477acee12538f9c4b145c3d9c8f3"
Expand All @@ -11,23 +15,23 @@
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:49e275c87108c8621d521226b89afb5f6c6a39f74de8e8bba502fbd1e39ad843",
"gen_hash_rust": "sha256:7d03e6e99a15344a1c8272b7f96ffc8ddcbfdb1cf44ab7f70f7a0e37847529bc",
"gen_hash_verilog": "sha256:0f761cb6e48d10ac555e51b8e5722eb8b02074a87ca2055aaec9241754140c49",
"gen_hash_zig": "sha256:0730d911d7047dc707075d16c8ff04afe222f4422a24344eff10b90e72edfdf0",
"gen_hash_c": "sha256:6a6ffcf30791e08b93221c1067abfc7e053f13c23dff90de4d9f7c9e23461479",
"gen_hash_rust": "sha256:d64150e24319f74e2b9413d45cfbd96a7d8bbc0df9d51c9fac0b68c8837b2efb",
"gen_hash_verilog": "sha256:387961ee44ce4ce7f32d4ccb23a4ac58ac6ef688db3b4c8aef38d1c60e41cc18",
"gen_hash_zig": "sha256:115d3f8ff262b6fd65b59d760aeb7eff66500b9f77f56577fb22233fefaa65e7",
"module": "idea_factory",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-19T02:25:39Z",
"sealed_at": "2026-10-19T02:41:09Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:34f59b06d780be9cbbae1b0577e7c96ed5b6b7d2451e61ada1b1dde2fd58b6b8",
"spec_hash": "sha256:249909fbd1679b488be14be323c0079735a55895560423934c21daf28c824db9",
"spec_path": "specs/t27f/idea_factory.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 8,
"total": 8,
"passed": 10,
"total": 10,
"vacuous": 0
},
"toolchain": {
Expand Down
Loading
Loading