Skip to content

Integrate triage fixes: #62, #63/#64, #65, #66, #68/#73, #74 and CI lint - #76

Merged
aa2246740 merged 27 commits into
mainfrom
integrate/triage-2026-10
Oct 26, 2026
Merged

aa2246740 merged 27 commits into
mainfrom
integrate/triage-2026-10

Conversation

@aa2246740

Copy link
Copy Markdown
Owner

Description

Integrates every open issue and contributor PR that triage confirmed as a real defect or a wanted feature. Each item was developed and verified on its own branch first, then merged here with --no-ff:

Not included: Dependabot #70 (tsdown) waits for the repo's 7-day rule; #69 (katex 0.19) needs a host katex upgrade first.

Testing

Context

Fixes #62
Fixes #63
Fixes #65
Fixes #66
Fixes #73
Fixes #74

Supersedes #64 and #68: their commits are included here, rebased onto current main with authorship preserved. Those PRs will be closed by hand after this merges. Merge with a merge commit (not squash) to keep the per-item merge history.

Harness: 0.2.0-rc.2 (compat check baseline). The reporter environment for #74 was DSH Desktop 0.2.1-rc.3 on Windows, which was not tested.

🤖 Generated with Claude Code

El1mir and others added 27 commits October 26, 2026 08:52
Narration (assistant body segments) is display content, not process detail.
It now stays visible as ordinary body prose when the process folds, and the
folded reasoning/tool run between two body blocks becomes a compact
process-chain summary in the gap: 1px --reader-rail rule plus the familiar
思考×N · 工具×K label with a chevron that expands the real rows in place.

- projection: hasProcessContent only advertises literal reasoning; earlier body
  steps no longer count as foldable process content.
- Reader: body segments render with normal answer typography (no annotation
  colour, indent or per-block left rule); only the final answer keeps
  copy/fork actions. A per-turn seam plan counts the rows folded between
  consecutive body blocks and renders the process-chain summary seam.
- live-turn: body narration is a fold-chain boundary; fold boxes contain only
  reasoning/tool/record steps and summaries never count narration as 输出×N.
- tests: projection/live-turn/fold-choreography contracts updated; a real-Reader
  browser fixture verifies red (both 0.3.4 and 0.3.9 baselines hide narration)
  and green (always-visible body, seam geometry, expand/collapse interaction,
  auto-fold off, failed and interrupted turns).
Live folding used to break its chain at every narration block, so any turn
that alternated thinking and report text left every past reasoning card
expanded while it ran (only folding again after the turn closed).

presentLiveTurn now splits at user inserts and, once a later reasoning step
exists, folds each earlier reasoning/tool run at its own source position. The
latest reasoning and everything after it stay open; narration continues to
render in place and never enters a fold box.

- live-turn: replace splitChain with the per-segment run folding described
  above (fold keys remain live-fold:<first step key> so rows keep identity).
- tests: live-turn/fold-choreography/fold-intensity contracts updated for
  cross-narration folding and user-insert chain resets.
- fixture: open-turn check now requires exactly one 思考×1 fold, the earlier
  reasoning hidden, and narration visible between the folds and latest reasoning.
- docs: lifecycle wording updated.
.userCluster was align-self:flex-end with only a max-width, so it shrank
to the text and the host .userStack 82% resolved against that shrink-wrap.
Give the cluster the host min(column * 0.702, 82%) width. The slot outlet
is display:contents, so the cap has to reach the host row and stack, not
the direct child. Pending bubbles use the host 14px/22px metrics.

#74
These symbols were already unused at fbf7bae. npm run lint is a required
check for this branch, and it failed before the reader change.
An open turn folds an earlier reasoning/tool run in place. The narration
seam counted that same run again and, via data-reader-seam-after, dropped
the previous body's bottom spacing. Skip the seam only when every folded
step is already inside a live-fold cell. Closed turns still show the seam.

DESIGN.md now matches per-run live folds, and the Unreleased notes credit
@Adamaik (#68) and @sugar-syl (#73).

Also clear unused bindings that already failed eslint on main, including
the unused toolSummary helper, so npm run lint exits 0.
A conversation.chat.node registration for assistant-step whose priority
is below the official renderer (0) is a replacement. Reader mirrors that
winner and gives it each answer-body segment, with groupPart response
and only that segment's blocks. Reasoning, folding, and process motion
stay on the reading view, so dsh-raw-html-v2 can draw raw HTML cards
without taking over the reading layout.

Also remove unused symbols that already failed npm run lint on main, and
count non-text blocks on pending inbox rows.

#65
Issue #62. Another client plugin can register
dsh-better-display.text-transform and rewrite reasoning or answer text
before the reveal. The session, the transcript, and the fold stay on the
original blocks. Copy still uses the original answer. An appended batch
keeps the reveal instead of starting it over. The block chain owner now
also receives presentation, holdFormatting, and liveText.

Clear unused names that already failed npm run lint on main.

Thanks @lin636.
Wallpaper themes clear --dsw-alias-bg-base, so the elapsed-time row and the
closed process summary no longer mask the answer heading that scrolls under
them. Lane offsets follow the measured row and --dsh-content-font-delta, and
a transparent canvas falls back to the opaque surface token.

Drop unused bindings that already failed npm run lint on fbf7bae.
Drop bindings nothing reads, and raise the host-bundle budget to the
size a fresh tsdown build emits now that flags, log, and metrics are
included.
A successful rewind still rolls the Reader back to before the target message. The cut is the plugin's closed range [target, marker]: previews and a target past the marker do not open a span, and a turn loses its process and tail rows only when every content row of that turn is gone. Streaming, a reconnect, and a plain re-render do not withdraw rows. The collapse stays 220ms, still dies on the #60 deadline, and settles at once when motion is off or the page is hidden. User and steering chat seats stay, so the rewind control still shows.

Also drop unused bindings that already failed eslint, and keep historical files out of printWidth 100 so the max-lines cap still holds.
The narration port renamed the body article marker to data-reader-body,
but usePinnedSelection still only queried data-reader-answer, so a live
selection in streaming body text was cleared when final formatting
landed. Query both markers and lock it with a test.
…r throws

A throwing read() reached the Reader's error boundary and replaced both
reasoning and answer with error notices that never recovered. Catch
read/subscribe/unsubscribe failures, show the original text, and re-read
on the next change or notify so a recovered transformer takes over.
The lint cleanup removed inboxAttachmentCount while nothing called it.
The assistant-step merge counts non-submission inbox rows with it.
The mirrored seat is dsh-better-display.official.nodes/conversation.chat.node, so a selector for conversation.chat.node matched nothing. The host row shrink-wrapped and its own 82% ran a second time. Stretch that row to the column and leave .userStack alone. Pending bubbles carry the same cap directly.
A theme that clears or fades the background token was painting the text
colour into the lane, and one global height map let a second Reader freeze
the first row. Underlay the lanes with Canvas, keep the 40px floor, and
give each Reader its own lane-height map.
…tory

A supplementary rewind still rolled the chat keys back, then readerFlow put the cut step's tool draft back on screen. Loading older history appended the new turns after the ones already shown. Reduced motion unmounted focused cut content and left focus on the document.

Live slots now follow the incoming group order, and a departing slot stays next to the live neighbour that preceded it. A draft with no tool-call node yet still shows while its step is outside the cut. Reduced motion moves focus to a surviving turn or the reading column before the cut unmounts, and still does not pin the collapse.
…rty themes (#66)

Conflicts were the lint cleanup both sides made independently. Keep the
integration side, plus two semantic repairs the textual merge missed:
restore inboxAttachmentCount (#65 calls it, #66 deleted it as unused) and
restore the raw-key fallback in redactString (each side fixed the lint
warning differently and the combination left `key` unassigned).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The animated path returned early while focus sat inside cut content, before
the visibilitychange listener was registered, and document.hidden is not
state. A page hidden while the collapse waited kept the rows mounted. The
focus-held branch now listens too and retires at once, moving focus with
focusSurvivesRetire like the hidden-page path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reading column is a tabIndex -1 target for focus that leaves cut
content. In keyboard modality a programmatic focus matched :focus-visible
and the host drew the UA outline around the whole transcript. Suppress the
outline on the column itself only; descendants keep their rings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts were again the shared lint cleanup, the AssistantNode that #65
moved to AssistantNode.tsx (#64 did not change it), and the sticky-lane
rule #66 rewrote next to #64's retiring-lane margin; keep both CSS
intents. Restore inboxAttachmentCount, which #64 deleted as unused while
the pending-inbox row still calls it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ula (#74)

Conflicts were the shared lint cleanup (McpAppFrame setReady, live-turn
foldableRun, GroupStatus props), the AssistantNode move from #65, and the
#66/#64 sticky-lane and turn-spacing rules next to the new .userCluster
rules. Kept the integration side for all of those and took #74's bubble
rules. Restored inboxAttachmentCount, which #74 also dropped as unused
while #65 still calls it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@aa2246740
aa2246740 merged commit 5f77e6f into main Oct 26, 2026
1 check passed
LingMoe404 added a commit to LingMoe404/dsh-better-display that referenced this pull request Oct 29, 2026
The official COT translation bundle registers translated reasoning on
`conversation.chat.reasoning.body`, and the reading view replaces that view,
so enabling the bundle cannot paint translation here. aa2246740#76's text-transform
seam is the supported way in, but the docs only sketch a synchronous
uppercase example.

Add a worked adapter under `examples/cot-translation-reader/` that registers
`reasoning`, reads `ctx.cotTranslation` lazily, splits completed paragraphs
to `maxTextChars`, caches results per block, and leaves the source on screen
when a request fails. The new section in `docs/extension-points.md` records
the four traps: synchronous `read`, no half-written streaming tail, per-block
caching, and `undefined` on failure.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment