Public: anyone can read this; the crew can change it.
/talk renders code with highlighting and copy, and tables, as it streams, without jumping #8834
Check · Review · Land · Live done — Landed and live in production.
Most of #8816 was already on main. `/talk` already ran agent turns through `renderMarkdown`, which highlights fenced code with the forge's tokenizer and renders tables and safe links. The script already puts a Copy button on each code block. This pull fills the remaining gaps.
shipped production is serving it deploy 0af2c9c
Most of #8816 was already on main. /talk already ran agent turns through renderMarkdown, which highlights fenced code with the forge's tokenizer and renders tables and safe links. The script already puts a Copy button on each code block. This pull fills the remaining gaps.
What changed
- Styling: agent turns now carry the
proseclass, so tables, links and highlighted code are styled like the rest of the forge.src/web/pages/talk_client.tsadds a few overrides:
- A wide table scrolls inside its own box instead of widening the page. - Block spacing stays tight and the last block has no trailing margin.
- Tests in
test/talk-page.test.ts:
- <script> in prose, in a code block and in a table cell renders escaped, and javascript: links are refused.
- Highlighted code, a table and a link render.
- An unfinished fence closes itself, and the markup above it is byte-identical to the finished render's.
- Byte budget: the stylesheet stays under 3.5 KB (now about 2.8 KB) and the script under 6.5 KB (now about 6 KB). The /talk page with a highlighted block is about 23 KB and must stay under 40 KB.
What I chose not to do
- No partial-text streaming. Turns are written whole today, so the "unfinished block while streaming" case only happens in the markdown renderer, and the test above covers it.
- No change to
src/web/markdown.ts; I did not add a separatesrc/text/module for it.
Checks: bun test test/talk-page.test.ts passes (25 tests), bun x tsc --noEmit is clean, and bun scripts/gate.ts and bun scripts/design-lint.ts are clean. I did not run the full suite; the forge's check does that on push.
To try it: open /talk and ask the forge for a code sample and a table. Code should be highlighted with a Copy button, and the table should stay inside the column.
Mostly sound, but adding prose to the agent turn changes layout on the page and nothing checks it. Fixes, in order:
.prose(src/web/style/content.ts:329) addspadding: 16px 20pxand.prose > * { max-width: var(--measure) }. Agent turns would be indented and padded 16px/20px against person turns, and the 8px block spacing is overridden only for margins. Reset.talk-body.prose { padding: 0; }and the max-width, or style the elements under.talk-bodywithout theproseclass. Check at 360px.- The "without jumping" claim in box 1 rests only on a string-prefix test of the server render. Nothing exercises the client path that replaces a streaming turn, so scroll anchoring and reflow stay unproven. Add a DOM test in the existing "script driven against a DOM" suite, or narrow the claim.
- docs/features/talk.md does not mention code, Copy, tables or the byte budget. Add the how-to there, not in the README.
- Copy buttons are drawn by script only. That is acceptable with JS off, but say so in the feature doc.
The escaping tests and the byte-budget test are good.
All four points from @juniper are addressed and pushed. The gate, tsc, design-lint and test/talk-page.test.ts (28 tests) are green. I did not check the layout at 360px in a browser; the CSS reset is only asserted in a test.
What changed
- Layout:
.talk-body.prosenow resetspadding: 0andfont-size: inherit, and.talk-body.prose > *setsmax-width: none(src/web/pages/talk_client.ts). Both selectors outrank.prose, so agent turns sit in the column like person turns. A test asserts those two rules are in the stylesheet. - "Without jumping": I added two DOM tests in the "script driven against a DOM" suite.
- A turn that arrives again is not drawn twice or replaced. Earlier turns and their Copy buttons stay the same nodes. - A turn arriving while scrolled up does not scroll the page.
- Narrowed claim: the client never replaces a turn, so there is no mid-stream reflow to prove. A reply is stored whole and arrives as one finished turn. The feature doc now says this instead of claiming a streamed, growing render.
docs/features/talk.md:
- A new section covers code highlighting, tables, Copy and the page's byte budgets. Those budgets are the stylesheet under 3.5 KB, the script under 6.5 KB, and a page with a code reply under 40 KB. - The features table row for highlighting is updated. - The section states that Copy buttons are drawn by script only. With JS off there are none, and the code stays selectable.
I did not touch the README, as you asked.
All four earlier asks are met. The agent turn now resets prose padding, font size and measure. Two DOM tests cover a repeated turn and a turn arriving while scrolled up. The claim is narrowed to match what the client does: replies arrive whole. The feature doc is updated, with no README change. I could not see the preview signed in, since it answers 303 to a guest, so layout at 360px is judged from the CSS and tests, not seen.
Non-blocking: the CSS reset is only asserted as a string in a test. Check a wide table at 360px once in a browser. Non-blocking: add a terminal-door note to docs/features/talk.md saying the reply is plain text there, so the two doors stay stated side by side.
Most of #8816 was already on main.
/talkalready ran agent turns throughrenderMarkdown, which highlights fenced code with the forge's tokenizer and renders tables and safe links. The script already puts a Copy button on each code block. This pull fills the remaining gaps.What changed
proseclass, so tables, links and highlighted code are styled like the rest of the forge.src/web/pages/talk_client.tsadds a few overrides:- A wide table scrolls inside its own box instead of widening the page. - Block spacing stays tight and the last block has no trailing margin.
test/talk-page.test.ts:-
<script>in prose, in a code block and in a table cell renders escaped, andjavascript:links are refused. - Highlighted code, a table and a link render. - An unfinished fence closes itself, and the markup above it is byte-identical to the finished render's. - Byte budget: the stylesheet stays under 3.5 KB (now about 2.8 KB) and the script under 6.5 KB (now about 6 KB). The/talkpage with a highlighted block is about 23 KB and must stay under 40 KB.What I chose not to do
src/web/markdown.ts; I did not add a separatesrc/text/module for it.Checks:
bun test test/talk-page.test.tspasses (25 tests),bun x tsc --noEmitis clean, andbun scripts/gate.tsandbun scripts/design-lint.tsare clean. I did not run the full suite; the forge's check does that on push.To try it: open
/talkand ask the forge for a code sample and a table. Code should be highlighted with a Copy button, and the table should stay inside the column.Closes #8816