Skip to content

feat(t27f): visual-output rule -- initialize instructions and an inline verdict on every t27f SVG - #27

Open
gHashTag wants to merge 1 commit into
t27mcp/one-servicefrom
t27mcp/visual-output
Open

gHashTag wants to merge 1 commit into
t27mcp/one-servicefrom
t27mcp/visual-output

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

What

The t27 MCP server now carries the visual-output rule from specs/t27mcp/visual_output.t27 (gHashTag/t27#10504):

  • initialize returns instructions built from RULE_CLAUDE_CODE. Claude Code puts server instructions in the model's system prompt, so every session that loads this server is told: an answer that explains a spec, a flow, numbers or a piece of work carries one visual; in the desktop app it goes inline, otherwise the SVG path is opened in the pane, otherwise a markdown table.
  • t27f_graph and t27f_view end with an inline: line, the spec's inline_source verdict: embed the SVG as it is, or redraw it 680 px wide from t27f_outline rows. The verdict comes from the drawing's own numbers (viewBox width, smallest font-size, bytes).
  • t27-mcp/visual exports RULE_TRI_CLAW and the helpers, so TRI CLAW's chat prompt reads the same rule from the same spec.

Stacked on #26 (base t27mcp/one-service).

Files

File Kind
wasm/visual_output.wasm, wasm/visual_output_table.mjs generated (t27c gen-c + zig, t27c gen-js); steps and sha256 in wasm/BUILD
visual.mjs glue, 24 lines: loads the wasm, joins the rule text, measures an SVG
server.mjs +8 / -6: instructions, the inline: line, two tool descriptions
package.json exports ./visual, ships the three files

visual.mjs and the server.mjs lines are hand-written JavaScript, so this PR needs the owner's owner-approved-foreign label.

Evidence (lab, node 20, at 5166b13)

  • node smoke.mjs: rc 0, all checks pass.
  • JSON-RPC over stdio, rc 0:
    • initialize carries "instructions":"Visual output (specs/t27mcp/visual_output.t27):\n- Every answer that explains a spec, ...
    • t27f_graph fixture 1: inline: redraw it 680 wide from t27f_outline rows (1860 wide, smallest text 13 px, 5923 bytes; ...)
    • t27f_view scene 3: inline: redraw ... (1280 wide, smallest text 15 px, 8557 bytes; ...)
    • t27f_view scene 3, look 0: inline: redraw ... (1280 wide, smallest text 20 px, 6839 bytes; ...)

All three tool drawings are too wide for their smallest text to read at 680 px, which matches the spec's measured tests.

🤖 Generated with Claude Code

…ne verdict on every t27f SVG

specs/t27mcp/visual_output.t27 (gHashTag/t27#10504) is compiled to
wasm/visual_output.wasm and wasm/visual_output_table.mjs (both generated,
rebuild steps in wasm/BUILD). The server now:

- sends RULE_CLAUDE_CODE as the initialize `instructions`, so Claude Code puts
  the rule "every answer that explains a spec, flow, numbers or work carries
  one visual" in the model's system prompt;
- ends t27f_graph and t27f_view with an `inline:` line from inline_source:
  embed the SVG as it is, or redraw it 680 wide from t27f_outline rows.

visual.mjs is the glue: it measures an SVG's viewBox width, smallest
font-size and bytes, and exports RULE_TRI_CLAW for TRI CLAW's chat prompt.

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

tri-claw Bot commented Oct 18, 2026

Copy link
Copy Markdown

Summary by t27-bees

This PR adds the visual-output rule from specs/t27mcp/visual_output.t27 to the t27 MCP server. The initialize response now includes instructions (the Claude Code rule text), and the t27f_graph/t27f_view tools append an inline: verdict line derived from the generated SVG's viewBox width, smallest font-size, and byte size.

Worth a look

  • server.mjs:778 — The initialize handler now returns instructions: ruleClaudeCode. If visual.mjs fails to load (e.g., WASM missing, import error), the server will crash on startup instead of degrading gracefully.
  • visual.mjs:15 — inlineNote extracts viewBox width via regex /viewBox="0 0 (\d+)/. If the SVG uses single quotes, different spacing, or a non-zero origin (e.g., viewBox="10 10 800 600"), the width parse returns 0, forcing a redraw verdict incorrectly.
  • visual.mjs:16 — Smallest font-size defaults to 0 when no font-size="..." attributes exist. Per the spec, 0 px means "never embedded", so any SVG without explicit font-size attributes will always get the redraw verdict.
  • visual.mjs:3 — W._initialize() is called at module load time. If the WASM module lacks _initialize (e.g., build mismatch), the import of visual.mjs throws, breaking server.mjs and any consumer (including TRI CLAW) that imports it.
  • wasm/BUILD:337 — The rebuild instructions say "never on the owner's Mac" but the generated visual_output.wasm and visual_output_table.mjs are committed. If the checked-in artifacts drift from the source spec (visual_output.t27), the runtime behavior will diverge from the spec's tests.

Read: 6 files, +132 -8, the whole diff. Head 5166b13. Model: openai-compatible/nvidia/nemotron-3-ultra-550b-a55b. Commands: @t27-bees review | summary | help | pause | resume. Free for every repository.

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