Skip to content

feat: t27f_view draws T27F reel stills and presentation slides from the spec as SVG - #3

Merged
gHashTag merged 5 commits into
masterfrom
t27f-view
Oct 17, 2026
Merged

gHashTag merged 5 commits into
masterfrom
t27f-view

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Summary

This PR adds a new tool, t27f_view. It draws a still of the T27F demo reel as an SVG file and returns the file's absolute path, plus a one-line summary, as plain text. The Claude Code desktop app opens that path in its Browser pane. A terminal client gets the same path and opens the file itself. MCP Apps UI resources are not used, because the terminal CLI does not render them.

All the geometry comes from the spec. Cell positions, hexagon corners, the camera at frame f, the screen mapping per preset, the cell style from lesson status, the scene names and the channel per host are all taken from specs/t27f/reel.t27 (gHashTag/t27 PR gHashTag/t27#9982, issue gHashTag/t27#9965). They reach JS in two ways:

  • Bodies run as wasm/reel.wasm. It is built from the Zig that t27c gen emits, plus wasm/export.zig. That shim knows no spec function and holds no number: it exports every scalar pub fn under its own name.
  • Constants come from wasm/reel.mjs, which is the gen-js output.

wasm/BUILD records the commands, the compiler and zig versions, and the sha256 of every file.

The only numbers in server.mjs are presentation: the colour palette indexed by STYLE_*, the stroke widths, and the label font size.

Hand glue (gate #7371)

File Lines
wasm/export.zig 38
server.mjs 40 added, one of which replaces the old tools/call line so that string results pass through unwrapped
Total 78 (limits: 40 per file, 80 per diff)

wasm/reel.zig, wasm/reel.mjs and wasm/reel.wasm are generated. wasm/BUILD, the README row and the docs/t27f_view/ images are prose and data.

Opened in the desktop pane

Calling t27f_view with a status per cell, and otherwise defaults (scene 2 = focus, frame 224, wide preset), returned:

/var/folders/.../T/t27f-demo-f224-p0.svg
T27F demo reel, scene 2 (focus), frame 224 of 360, 1280x720, focus cell 10; channel for host 1: CHANNEL_FILE_AND_PANE.

The Browser pane in the Claude Code desktop app opened that file:// path. Its page tools cannot screenshot a file:// tab, so the screenshots below are the same pane showing the same files served from 127.0.0.1.

Focus still, frame 224: cell 10 sits at the frame centre (640, 360), as the spec's test asserts.

focus still in the desktop pane

Overview still, frame 59: every cell fits the frame, which is the spec's overview_still_fits_every_frame.

overview still in the desktop pane

The raw SVGs are in docs/t27f_view/.

Checks run

  • tools/list lists t27f_view.
  • These calls draw:
    • the default still (written to the temp directory);
    • the focus still, with out;
    • the overview still;
    • the tall preset (all 27 cells fit).
  • These calls are refused with a message: frame 9999, preset 3, status code 300.
  • The spec side ran on the Railway lab: 19/19 tests pass and 3/3 negative controls are killed. Details are in spec(t27f): reel host entry points for wasm hosts (Closes #9980) t27#9982.
  • gitleaks: no leaks.

Not done

  • No smoke test in smoke.mjs for t27f_view.
  • No video, only stills.

🤖 Generated with Claude Code

Every position, size and style index comes from specs/t27f/reel.t27
(gHashTag/t27 PR #9982): its bodies run as wasm/reel.wasm, built from the
generated Zig plus a 38-line export shim, and its constants are the generated
wasm/reel.mjs. server.mjs only writes polygons and labels to an SVG file and
returns the path, which the Claude Code desktop app opens in its Browser pane.

Hand glue: wasm/export.zig 38 lines, server.mjs 40 added lines (one of them
the changed tools/call line that passes string results through) -- 78 in all.

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

tri-claw Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Summary by t27-bees

This PR adds t27f_view, a tool that renders T27F demo reel stills and presentation slides as SVG. Geometry and layout come from specs (reel.t27, deck.t27) via generated WASM (wasm/t27f.wasm) and JS constants (wasm/reel.mjs, wasm/deck.mjs). The glue code (server.mjs, deck-view.mjs) handles SVG construction, text wrapping, and file output.

Worth a look

  • server.mjs (tools/call handler): The change "replaces the old tools/call line so that string results pass through unwrapped" — this alters the return-value contract for all tools, not just t27f_view. If any existing tool returns a string expecting the old wrapper, its consumers will break.
  • deck-view.mjs:28 (throw new Error(\this text does not fit...`)): Uncaught exceptions here will crash the tool call with a generic error instead of a structured MCP error response. The caller (server.mjs`) doesn't appear to wrap this in a try/catch.
  • deck-view.mjs:12 (R.valid_cell(k) in a loop with no visible upper bound): If valid_cell never returns false, this loops infinitely. The generated wasm/deck.mjs / wasm/reel.mjs must guarantee termination, but the glue assumes it.
  • wasm/export.zig (not fully shown, described as 38 lines exporting "every scalar pub fn"): If the generated Zig adds non-scalar exports (pointers, slices, structs), the shim will export them as-is, likely causing WASM instantiation or runtime failures.
  • server.mjs (temp file creation): The tool writes SVGs to the system temp directory but there's no cleanup logic shown. Accumulated files could fill disk over time.

Read: 25 files, +1765 -2, the whole diff up to 60000 characters (the rest was not read). Head 9e8105e. Model: openai-compatible/nvidia/nemotron-3-ultra-550b-a55b. Commands: @t27-bees review | summary | help | pause | resume. Free for every repository.

gHashTag and others added 2 commits October 17, 2026 22:22
The default look is now a deck slide from specs/t27f/deck.t27: a cover,
stage or split layout by scene kind, regions, type sizes, palette and
card opacity all from the spec, with the map placed by slide_x/slide_y.
look 0 keeps the plain map. wasm/t27f.wasm now carries reel and deck
bodies; export.zig handles two modules and five parameters.

WIP: split stills wait on a deck.t27 answer for card_alpha at the still
frame (it is 0 there).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
deck.t27 (gHashTag/t27 PR #9992) adds STILL_CARD_ALPHA: a still is the last
frame of its scene, where card_alpha is 0, so a still drawn with card_alpha
showed no card. A scene still now uses STILL_CARD_ALPHA; an exact frame keeps
card_alpha. deck.zig and deck.mjs regenerated on the Railway lab (15/15 deck
tests, 0 vacuous); t27f.wasm is byte-identical (the change is a constant).
Adds deck renders and pane screenshots under docs/t27f_view/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Regenerated wasm/deck.zig, deck.mjs and t27f.wasm from deck.t27 at
gHashTag/t27#10036: BACKDROP 0x000000, both aurora strengths 0. Only
those three constants differ in deck.mjs; reel.* byte-identical. Built
on the Railway lab (t27c 0.5.2, zig 0.16.0), sha256 in wasm/BUILD.

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

Copy link
Copy Markdown
Owner Author

Merged on the owner's explicit instruction of 2026-10-18 (translated): "merge it yourself, autonomously -- I allow everything".

For the record: this stack adds hand-written non-t27 code, all of it drawing glue -- deck-view.mjs (40 lines), server.mjs (+47 lines) and wasm/export.zig (40 lines). Every number and every function body it draws comes from specs/t27f/reel.t27 and specs/t27f/deck.t27 in gHashTag/t27, through files t27c generates (wasm/*.zig, wasm/*.mjs, t27f.wasm). This is above the 40-per-file / 80-per-diff budget of the t27 own-language gate, which this repo does not run, so the merge rests on the owner's word rather than on the gate.

t27f_view: presentation slides by default (T27fDeck)
@gHashTag gHashTag changed the title feat: t27f_view draws T27F demo reel stills from the spec as SVG feat: t27f_view draws T27F reel stills and presentation slides from the spec as SVG Oct 17, 2026
@gHashTag
gHashTag merged commit 1208743 into master Oct 17, 2026
1 check passed
@gHashTag
gHashTag deleted the t27f-view branch October 17, 2026 18:21
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.

1 participant