Skip to content

feat(pikchr): inline grammar, progress keep-alives, and UI card for diagram sub-sessions - #893

Merged
matt2e merged 3 commits into
mainfrom
diagram-sessions-improvements
Jul 27, 2026
Merged

feat(pikchr): inline grammar, progress keep-alives, and UI card for diagram sub-sessions#893
matt2e merged 3 commits into
mainfrom
diagram-sessions-improvements

Conversation

@matt2e

@matt2e matt2e commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Improvements to the generate_pikchr diagram sub-session flow, covering reliability of long runs, the specialist's prompt, and how the injected grammar renders in the session UI.

Inline the grammar in the sub-session prompt (f445f116)

  • The specialist sub-session has no repo access, so referencing the grammar file by path was a dead reference. The full bundled Pikchr grammar text is now inlined into the first prompt message, falling back to naming the public grammar URL when the bundled resource is missing or unreadable. Remote blox note sessions are unaffected and keep referencing the uploaded grammar file.
  • Accepted-render layout warnings are no longer surfaced to the parent session: the warnings text and the renderWarnings structured field are removed from the tool result, along with the now-unused plumbing in GenOutcome/PreviewOutcome.
  • The generate_pikchr wall-clock timeout is doubled from 10 to 20 minutes.

Send MCP progress keep-alives during generate_pikchr (28c65618)

  • A generate_pikchr call was one silent MCP request for the entire specialist run, and Claude Code aborts any MCP tool call that produces no response or progress for 300 s — so every run past ~5 minutes failed in the parent while the child session finished cleanly with nobody left waiting.
  • The handler now takes its rmcp RequestContext and ticks a progress notification back to the caller every 30 s (monotonic elapsed seconds, no total) while awaiting the worker, under select! against the worker's oneshot so it stops the moment the worker reports or the call is dropped. When the caller provides no progress token, the loop pends forever and the call behaves exactly as before, per the MCP spec.

Collapse the inlined grammar into an expandable context card (03e1d6a6)

  • Inlining the grammar left ~10.5 KB of grammar text as a wall in the first prompt bubble when opening a diagram session in the UI. The backend now wraps it in a <pikchr-grammar> tag, and the session UI renders it as a collapsed, expandable "Pikchr grammar" card (BookOpen icon) above the prompt text — the same treatment as the existing action/branch-history/launch-context blocks.
  • The tag whitelist previously lived in three hand-maintained regexes across two files; it's now a single exported XML_BLOCK_TAGS list that the block/open-tag patterns derive from.

Test plan

  • Prompt tests updated for the inlined grammar (<pikchr-grammar> block, URL fallback) and removal of the warnings plumbing.
  • CI (crates-fmt, crates-lint, crates-test, differ-ci, staged-ci) green on push.

🤖 Generated with Claude Code

matt2e and others added 3 commits July 27, 2026 12:16
…nt warnings, double timeout

Diagram sub-session improvements for generate_pikchr:

- Inline the full bundled Pikchr grammar text into the specialist's
  prompt instead of referencing the grammar file by path — the
  sub-session has no repo access, so a path was a dead reference. When
  the bundled grammar is missing or unreadable, the prompt falls back to
  naming the public grammar URL. Remote blox note sessions are
  unaffected and keep referencing the uploaded grammar file.
- Stop surfacing accepted-render layout warnings to the parent session:
  the warnings text content and the renderWarnings structured field are
  gone from the tool result, and the now-unused warnings plumbing is
  removed from GenOutcome and PreviewOutcome.
- Double the generate_pikchr wall-clock timeout from 10 to 20 minutes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
A generate_pikchr call was one silent MCP request for the entire
specialist run, and Claude Code aborts any MCP tool call that produces
no response or progress notification for 300 s — well under a long
diagram run. The abort never reached the server-side worker, which kept
going, accepted a render, and completed the child session with nobody
left waiting: every specialist run past ~5 minutes failed in the parent
while the diagram session finished cleanly.

Claude Code's idle timer explicitly resets on progress, so the handler
now takes its rmcp RequestContext and, while awaiting the worker, ticks
a progress notification back to the caller every 30 s, reporting
elapsed seconds (monotonic, no total) with a short liveness message.
The keep-alive loop runs under select! against the worker's oneshot, so
it stops the moment the worker reports or the call future is dropped.
When the caller sends no progress token, the loop pends forever instead
— the MCP spec only allows progress against a caller-provided token —
and the call behaves exactly as before.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
Since the Pikchr grammar was inlined into the diagram sub-session's
first user message, opening a diagram session in the UI showed ~10.5 KB
of grammar text as a wall in the first prompt bubble. Give the grammar
the same treatment as the existing injected-context blocks (action,
branch-history, launch-context): the backend now wraps it in a
<pikchr-grammar> tag, and the session UI renders it as a collapsed,
expandable card above the prompt text.

- pikchr_subsession.rs: initial_prompt wraps the appended grammar in
  <pikchr-grammar>…</pikchr-grammar> instead of the plain "Pikchr
  grammar reference:" heading, and grammar_line points the specialist
  at the tagged block. The URL fallback (bundled grammar missing) is
  unchanged. Prompt tests updated.
- sessionModalHelpers.ts: the tag whitelist previously lived in three
  hand-maintained regexes across two files; export a single
  XML_BLOCK_TAGS list (now including pikchr-grammar) and derive the
  block/open-tag patterns from it, so previews, hints, and titles keep
  stripping the new block.
- SessionChatPane.svelte: derive parseContentSegments' tagPattern from
  XML_BLOCK_TAGS and map the new tag to a "Pikchr grammar" card with
  the BookOpen icon.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
@matt2e
matt2e requested review from baxen and wesbillman as code owners July 27, 2026 05:57
@matt2e
matt2e merged commit 2d109c4 into main Jul 27, 2026
4 checks passed
@matt2e
matt2e deleted the diagram-sessions-improvements branch July 27, 2026 06:24
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