Skip to content

Syntax highlighting, a transcript render budget, and a gated call that says so - #645

Merged
0x-copilot-dev merged 1 commit into
devfrom
claude/desktop-app-ui-ux-9af65c
Aug 26, 2026
Merged

0x-copilot-dev merged 1 commit into
devfrom
claude/desktop-app-ui-ux-9af65c

Conversation

@0x-copilot-dev

Copy link
Copy Markdown
Owner

Three of the six remaining UI gaps. The other three (shell execution, subagent
control, typography) are PRDs under docs/plan/agent-execution/ and land
separately — both engineering PRDs came back NEEDS-REVISION and should not be
implemented from as-is.

What lands

Syntax highlighting. There was none anywhere — streamdown 2.5.0 carries no
highlighter. Adds shiki behind a small seam.

The lockfile stayed surgical: two lines, no regeneration, because
shiki@4.4.2 was already hoisted at the root as a transitive dep of astro at
exactly the pinned version. npm ci --dry-run exits 0. This was the main risk in
the change — a regenerated lock reds the SBOM gate and blocks every PR in the repo.

Token colour rides on top of the diff — only color is set per span, so
add/remove backgrounds survive, and a refused edit gets no tokens at all, since
colour is the card's "this happened" signal.

A render budget, not a virtualizer. Rows here are variable-height,
interactive, and hold state; an approval card unmounted from under someone would
break the one reachable exit from a parked run. So the newest N turns render
fully and older tool/fleet/reasoning items fold behind an expandable summary.
Approvals and the composer are never elidable. Cost is O(budget), not O(run) —
tested by tripling the input and asserting under double the DOM.

A gated call now says so. A refused write and a write parked on an approval
rendered identically, though the remedies are opposite — attach a folder vs
approve. Observed live, twice. The card now reads "Needs you" for the call the
decision is about, carries the server's own question, and stamps
data-tool-blocked so a journey need not read copy. No second approve control.

Four defects caught before merge

  1. ci-gates was red — three dark-wiring symbols. No Python changed: a new
    test fixture named keys previously invisible to the scan (api-types is
    excluded from it), turning "unmentioned" into "mentioned but never read".
    Baselined with the reason text their siblings already carry.
  2. A live journey broke on copy. workspace_consent.py asserts "Waiting"
    over every parked card, and the new copy renames exactly that one. The copy
    is better, so the assertion moved.
  3. Highlighting blocked the streaming path. streamdown re-tokenizes the
    whole block per model delta on the main thread, so MAX_HIGHLIGHTED_CHARS
    was a frame budget wearing a readability justification: 49 ms at 40k on
    tsx, 87 ms on dense TS — ~11 fps while tokens arrive. Now 8k, ~10 ms, still
    ~135 lines.
  4. The budget elided the gated card — in precisely the long runs it was
    written for. Fixed, and pinned by a test verified to fail without the fix.

One correction worth recording

Both verifiers reported the desktop bundle growth (+623 KB) as an unintended
regression. It is not: syntaxTokens.ts:60-66 states the trade in advance and
the grammar list was sized for it, with html and javascript dropped for cost.
The review caught that the verifiers were wrong. Splitting the desktop renderer
(splitting: true + outdir) remains available as its own change with a
file:// load check.

Verification

typecheck ×4 green · desktop builds · check_dark_wiring 0 new · lockfile 2
lines · chat-surface 4162 passed, with the same 2 pre-existing failures as a
clean tree (ChatsArchive's jsdom viewBox selector; canvasLifecycle's
deleted Python module).

🤖 Generated with Claude Code

…and a gated call that says so

Three tracks, plus four fixes an adversarial review returned before any of it
could merge.

SYNTAX HIGHLIGHTING. Code blocks and diff rows had no colour anywhere —
streamdown 2.5.0 carries no highlighter. Adds shiki behind a small seam, with an
enumerated grammar list rather than the full bundle: the desktop renderer is one
esbuild `outfile:` with no splitting, so a dynamic import() is INLINED, and the
list is sized for that cost (~623 KB, measured). Deliberate, documented at
syntaxTokens.ts:60-66, and the web host still splits per grammar.

The lockfile stayed SURGICAL — two lines, no regeneration — because shiki@4.4.2
was already hoisted at the root as a transitive dep of astro at exactly the
pinned version. `npm ci --dry-run` exits 0. That mattered: a regenerated lock
reds the SBOM gate and blocks every PR in the repo.

Token colour rides ON TOP of the diff: only `color` is set per span, so add and
remove backgrounds survive, and a refused edit gets no tokens at all — colour is
this card's "this happened" signal and an unapplied diff has not earned it.

A RENDER BUDGET, not a virtualizer. Rows here are variable-height, interactive
and hold state, and an approval card unmounted from under someone would break
the one reachable exit from a parked run. So the newest N turns render fully and
older tool/fleet/reasoning items fold behind an expandable summary. Approvals
and the composer are never elidable.

A GATED CALL NOW SAYS SO. A refused write and a write parked on an approval
rendered identically, and their remedies are opposite — attach a folder vs
approve. The card now reads "Needs you" for the call the decision is about,
carries the server's own question, and stamps `data-tool-blocked` so a journey
need not read copy. No second approve control: the ask card remains the only
place a decision is taken.

FIXES FROM REVIEW:

1. ci-gates was RED — three dark-wiring symbols (`_Fields.batch_id` ×2,
   `batch_index`). No Python changed; a new test fixture NAMED keys that were
   previously invisible to the scan (api-types is excluded from it), turning
   "unmentioned" into "mentioned but never read". The fixture is right to
   include them — a fixture richer than the wire is how a green suite ships over
   a field the client never receives — so the keys are baselined with the same
   reason text their siblings already carry.
2. `workspace_consent.py` asserted `"Waiting" in card["text"]` over every parked
   card, and the new copy renames exactly that one to "Needs you". The copy is
   better, so the assertion moved, not the product.
3. `MAX_HIGHLIGHTED_CHARS` 40_000 → 8_000. streamdown re-tokenizes the whole
   block per model delta on the main thread, so that bound is a FRAME budget,
   not the readability budget its comment claimed: 49ms at 40k on tsx (87ms on
   dense TS) is ~11fps while tokens arrive. 8k is ~10ms and still ~135 lines.
4. The budget elided the gated card — in precisely the long runs track (c) was
   written for. A call parked on a live decision is no longer elidable; a DENIED
   call still is, because that one is history. Pinned by a test verified to fail
   without the fix.

Also corrected: both verifiers reported the desktop bundle growth as an
unintended regression. It is not — syntaxTokens.ts:60-66 states the trade in
advance and the grammar list was sized for it. The review caught that; splitting
the desktop renderer remains available as its own change.

typecheck ×4 green · desktop builds · dark-wiring 0 new · lockfile 2 lines
chat-surface 4162 passed, with the same 2 pre-existing failures as a clean tree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@0x-copilot-dev
0x-copilot-dev merged commit 700bcd0 into dev Aug 26, 2026
14 checks passed
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