Skip to content

Agent chat: PR chips read (number plus a readable title), +N lists the rest, own line under the reply - #29279

Merged
cmux-bot[bot] merged 10 commits into
feat-cmux-nextfrom
lane/pr-dock-readable-chips
Oct 31, 2026
Merged

cmux-bot[bot] merged 10 commits into
feat-cmux-nextfrom
lane/pr-dock-readable-chips

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Leo flagged the row of PR chips at the end of an agent message in the cmux NEXT transcript. It read #29007 cm… #28969 cm… +53: each title was cut to two letters, +53 was a bare count with no way to see what it held, and the row was glued onto the reply's last prose line. His exact words didn't reach this lane (the coordinator's brief was truncated). This PR fixes the three defects in his screenshot and keeps the chips.

Builds on: #26082 (PR pills share the message action row: #N repo pills, up to two, +N popover). It is merged and nothing else in flight touches these chips. Prior art acknowledged for PullRequestDock.tsx / MessageActions.tsx: #26082, #25207, #25208, #26619, #27252, #24715, #24662 (merged) and #28837, #28674, #28559, #28058, #26819, #26779, #26720, #26374, #29169 (open). None of the open ones change the chip contents, the overflow or the placement.

What changes

  • A chip reads. Each chip is #N plus the PR's title, or #N alone, never a stub. A new planner (summary/pullRequestChipPlan.ts) works from measured widths. It tries titled chips first (up to two), then numbers only, then one number. A title is drawn only when at least 12 characters of it fit (or all of it, if shorter). The title comes from the header's live state, the chat's --title, or GitHub's page title. The chip's existing hover card still gives the whole title, the repository and the state.
  • +N lists the rest. It is still a button and still opens the instant portaled popover, so the transcript never moves. The popover now lists every PR the row left out, each #N with its title (or the repository when cmux has no title). The list scrolls inside a capped height instead of running off the screen, as it did before (see the before stills). Focus stays on +N when the list opens, so no chip's hover card covers it. Tab moves into the chips and Escape returns to +N.
  • Placement. Where the message has an action row, the chips stay beside it (unchanged). On a reply without one (streaming or footerless), the chips used to share a line with the final word. They now get their own line, right-aligned under the last words, up to 70% of the width. Final code, tables, math, rules and diagrams keep their bottom-edge tail (BlockTail, unchanged). On a received message's line, the dock is capped at min(320px, 45vw), the same cap as the inline tail.
  • Nothing is removed: the chips, the hover card, the overflow, the action-row placement, the fallback above the composer and the legacy comparison modes all remain.

Gallery (agent-pane.pr-dock): three variants for 55 PRs, picked readable-titles

Light Dark
readable-titles (picked): number + readable title, own right-aligned line
numbers-only: numbers alone, titles on hover and in the list
inline-last-line: readable chips kept on the reply's last line

Why readable-titles: it is the only variant where both chips tell you which PR they are without hovering. numbers-only is tidy, but with 55 PRs a number alone means nothing. inline-last-line cramps the titles back toward stubs and still glues the row to the prose, which is the third defect.

Before / after (2x, Linux Chromium gallery, synthetic 55-PR fixture)

Before is the base renderer with this PR's fixture (commit 89f2a9e, run 41196311350). After is this head (run 41212927635).

Before After
Light
Dark
Light, +N open
Dark, +N open

Viewed the after images: yes, all of them. Before, the row reads #1254 atlas-web +54 stuck to "pick them up.", and the open list is 54 identical atlas-web rows running off the bottom of the pane. After, the row is #1254 Retry uploads on transient fa… #1253 Keep the upload progress o… +53 on its own line, right-aligned, and the open list shows each PR's title and scrolls within the pane.

Tests

cmux-ci test on fleet Linux at e6a34d6 (run 41212927635): 107 pass, 0 fail. Typecheck, vp fmt --check, vp lint and check:design-tokens are clean.

  • New pr-chip-plan.test.ts (truncation): two titled chips when they fit; one titled chip before two stubbed ones; numbers alone when no readable title fits; a title is never cut below its readable minimum (a sweep over widths); short titles count at their own width; untitled PRs; numbers-only and one-chip modes; at least one chip always.
  • New in pr-dock-inline-layout.test.ts (real Chromium, light and dark, 760/420/320 px): with 55 PRs, every drawn chip is #N with a whole title or at least 12 characters of one. The row sits on its own line below the last words, right-aligned to the reply. +N reads +(55 − drawn) and opens a list of exactly the rest, each titled. Drawn and listed together cover all 55. The list stays inside the viewport and scrolls. Escape closes it. A chip's hover card gives the whole title. These six layout tests are red on base (run 41193251052: "on its own right-aligned line", 6 fail) and green here.
  • Existing suites unchanged and passing: agent-pane-pr-dock, pr-hover-card, transcript-pr-revision, agent-pane-bottom-stack, agent-pane-dock-gutters, popover-instant-open*, and the rest of pr-dock-inline-layout (action-row, fallback, tail variants, overflow never moves the transcript). pr-dock-stale-state now expects the number alone in JSDOM, which has no layout, so no title fits.

Performance

Nothing new runs per streamed token. The PR list is still memoized on the producer's revision key (transcript-pr-revision.test.tsx: "200 reply/thought tokens without new PR findings do not recompute the dock's PR list" passes). The planner runs only in the existing ResizeObserver callback (the one observer, disconnected on cleanup, unchanged). It measures at most two hidden titles, and setPlan bails out when the plan is unchanged.

Metric Before After Delta Harness
Dock PR-list recomputes over 200 reply tokens with no new PR 0 0 0 transcript-pr-revision.test.tsx, run 41212927635
ResizeObservers per dock 1 1 0 code read

Risk

Low to medium, webview only. The row's planner now measures titles, so the case to watch is a narrow pane with long titles: the tests cover it at 320 px. The visible behavior change is the placement of chips on a reply with no action row (own line instead of after the last word); the old treatment remains as the inline-last-line gallery comparison.

Spec: leo-workspace design/chat-transcript.md §"Pull request chips" plus a Rules line, in teamleaderleo/leo-workspace#1924.

Changelog

Fixed: Pull request chips at the end of an agent message now show the PR number with a readable title (or the number alone), and +N opens a list of the rest.

Agent session: agent session

🤖 Generated with Claude Code

The fixture and the tests first, on the current renderer, so the stills show the
before and the tests show what is red there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review b81724a: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr29279 -f ref=lane/pr-dock-readable-chips -f platform=macos -f backend_mode=local

Gallery before/after for b81724a: 16 states rendered, 0 images differ, 2690 more touched states not rendered. Images are in the run's artifact, not on this public PR; the independent review of this head reads them on its own, so the PR needs no hand-made screenshots of these states.

gh run download 41230101648 -R manaflow-ai/cmux -n gallery-advisory-29279-b81724a10c74ab516f0539d341073d74f1d90120 (then read gallery-review.json)

States
State Theme Status Diff Picked by
agent-pane.background-activity/duration-columns Apple System Colors Light unchanged 0% own summary.css
agent-pane.background-activity/duration-columns Apple System Colors unchanged 0% own summary.css
agent-pane.background-activity/pinned-live-tail-light Apple System Colors Light unchanged 0% own summary.css
agent-pane.background-activity/pinned-live-tail-light Apple System Colors unchanged 0% own summary.css
agent-pane.background-activity/pinned-live-tail-dark Apple System Colors Light unchanged 0% own summary.css
agent-pane.background-activity/pinned-live-tail-dark Apple System Colors unchanged 0% own summary.css
agent-pane.background-activity/after-latest-message-light Apple System Colors Light unchanged 0% own summary.css
agent-pane.background-activity/after-latest-message-light Apple System Colors unchanged 0% own summary.css
agent-pane.background-activity/after-latest-message-dark Apple System Colors Light unchanged 0% own summary.css
agent-pane.background-activity/after-latest-message-dark Apple System Colors unchanged 0% own summary.css
agent-pane.background-activity/compact-pill-light Apple System Colors Light unchanged 0% own summary.css
agent-pane.background-activity/compact-pill-light Apple System Colors unchanged 0% own summary.css
agent-pane.background-activity/compact-pill-dark Apple System Colors Light unchanged 0% own summary.css
agent-pane.background-activity/compact-pill-dark Apple System Colors unchanged 0% own summary.css
agent-pane.background-activity/side-panel-light Apple System Colors Light unchanged 0% own summary.css
agent-pane.background-activity/side-panel-light Apple System Colors unchanged 0% own summary.css
agent-pane.harness-status/claude Apple System Colors Light unchanged 0% own summary.css
agent-pane.harness-status/claude Apple System Colors unchanged 0% own summary.css
agent-pane.harness-status/codex Apple System Colors Light unchanged 0% own summary.css
agent-pane.harness-status/codex Apple System Colors unchanged 0% own summary.css
agent-pane.harness-status/opencode Apple System Colors Light unchanged 0% own summary.css
agent-pane.harness-status/opencode Apple System Colors unchanged 0% own summary.css
agent-pane.harness-status/copy-and-escape Apple System Colors Light unchanged 0% own summary.css
agent-pane.harness-status/copy-and-escape Apple System Colors unchanged 0% own summary.css
agent-pane.harness-status/copy-value Apple System Colors Light unchanged 0% own summary.css
agent-pane.harness-status/copy-value Apple System Colors unchanged 0% own summary.css
agent-pane.harness-status/header-action-alignment Apple System Colors Light unchanged 0% own summary.css
agent-pane.harness-status/header-action-alignment Apple System Colors unchanged 0% own summary.css
agent-pane.harness-status/overlay-escape-priority Apple System Colors Light unchanged 0% own summary.css
agent-pane.harness-status/overlay-escape-priority Apple System Colors unchanged 0% own summary.css
agent-pane.narrow/controls Apple System Colors Light unchanged 0% own PullRequestDock.tsx
agent-pane.narrow/controls Apple System Colors unchanged 0% own PullRequestDock.tsx

Pick other states with a Gallery: entry.id, entry.id/variant line in the PR body.

Passes: CI passes on b81724a10c.

CI passes on b81724a10c (run 41232452852 attempt 1).

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

web and size checks: green

Shipped in:

A chip is its number, or its number and a title of at least 12 characters
(whole when shorter), planned from measured widths (pullRequestChipPlan.ts);
never a two-letter stub. Its hover card gives the whole title. +N opens a
list of every PR the row left out, with titles, scrolling in a capped
popover. Under a paragraph the row is its own right-aligned line, never glued
to the prose. Gallery: readable-titles (picked), numbers-only, inline-last-line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@blacksmith-sh

blacksmith-sh Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Found 1 test failure on Blacksmith runners:

Failure

Test View Logs
test_every_listed_hook_is_one_glaeda_released_with_the_check (main.SigningHooksInSt
epWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check)/
test_every_listed_hook_is_one_glaeda_released_with_the_check (main.SigningHooksInSt
epWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check)
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e dock capped

On its own line the row may take 70% of the reply (max 560px), so titles read
longer. Opening +N focuses the list, so no chip hover card covers it. A
received line hover box sizes to content: cap its dock at min(320px, 45vw) as
the inline tail does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo
teamleaderleo marked this pull request as ready for review October 31, 2026 16:21
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, next-review): SHIP at e6a34d6

SHIP at e6a34d6

Visual verdict: Reviewed all 12 images. The selected after layout has readable titles on a separate line and bounded overflow lists in both themes. No visual blocker.

  1. [P2] [follow-up] pullRequestChipPlan.ts:40 underestimates short, wide titles. The planner caps their measured width at 12ch, but summary.css:186 prevents titles of 12 characters or fewer from shrinking. A short CJK or wide-uppercase title can therefore overlap +N despite passing the fit check. Reserve the full measured width for these unshrinkable titles and add coverage for wide glyphs.

Validation: All nine planner tests passed using Node/Babel with an assertion shim. Full browser and Bun suites could not run because their dependencies aren’t installed.

Follow-ups:

  • Fix the planner/CSS width mismatch for short, wide titles.

@teamleaderleo teamleaderleo removed the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026

@cmux-bot cmux-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmux-bot approves e6a34d6: an independent review passed this exact head (next-review receipt by teamleaderleo). A push needs a new review; a later BLOCK at this head dismisses this approval.

…both parents

Review (Astra, BLOCK at e6a34d6): the planner measured +{total-1} even for two
chips; it now measures +N for each candidate count. A title keeps its own width
when the planner measured it no wider than the readable minimum (data-short now
comes from that measurement, not a character count), so CSS and the plan agree.
The received-line dock cap matches .cv-received__line and .cv-received__hover.

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

Copy link
Copy Markdown
Collaborator Author

Review (codex, router-review): SHIP at 28a8de9

Reviewer: codex gpt-6-astra high, fast tier.

SHIP at 28a8de9

Visual verdict: after screenshots reviewed; no overlap, off-screen layout, or bloated controls observed.

No findings.

Follow-ups: none

@teamleaderleo teamleaderleo removed the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
…k-readable-chips

# Conflicts:
#	webviews/src/agent-session/acpmux/summary/summary.css
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex, router-review): SHIP at b81724a

Reviewer: codex gpt-6-astra high, fast tier.

Follow-ups: 1. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward.

SHIP at b81724a

Visual verdict: reviewed all supplied after screenshots; no repeated controls, bloated menus, or off-screen layouts.

  1. [P2] [follow-up] Keyboard focus may skip the overflow chips: initialFocus={false} keeps focus on +N, but this is a non-modal portaled popover with no focus redirection. Pressing Tab can continue through later transcript controls instead of entering .acpmux-pr-dock__list as documented. Add a focus boundary or explicit Tab handling and a browser test. (webviews/src/agent-session/acpmux/summary/PullRequestDock.tsx:164-170)

Follow-ups:

  • [P2] Keyboard Tab should enter the opened overflow list immediately.

@teamleaderleo teamleaderleo removed the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
@cmux-bot
cmux-bot Bot merged commit ddaeb53 into feat-cmux-next Oct 31, 2026
220 of 221 checks passed
@cmux-bot
cmux-bot Bot deleted the lane/pr-dock-readable-chips branch October 31, 2026 19:44
teamleaderleo added a commit that referenced this pull request Oct 31, 2026
…anner, its tests and CSS)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64

This branch was previously deployed

1 inactive deployment
ci-routing-agent — b81724a1 Deployed Oct 31, 2026 by teamleaderleo via wait for same-key tree publisher #90982
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant