Skip to content

Agent pane: status, tool and message rows and the action row line up with the prose - #29124

Merged
teamleaderleo merged 18 commits into
feat-cmux-nextfrom
lane/transcript-row-alignment
Nov 1, 2026
Merged

teamleaderleo merged 18 commits into
feat-cmux-nextfrom
lane/transcript-row-alignment

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Leo, 2026-10-30: "see how claude code has those centered tool calls

id like more alignment too"

Leo, 2026-10-30: "1 CODEX 2 US 3 US 4 CODEX 5 CLAUDDE WE NEED TO LINE OUR STUFF UP LIKE THEIRS"

What changed

Agent pane transcript (cmux NEXT), alignment only. No row type, icon or action was removed, and the incoming agent-message action buttons were left alone.

  • Centred status rows. A status row between two replies now has equal room above and below. That covers a tool run, a subagent finishing, a background command finishing, another agent's message, compaction, failover and session start. statusEdge (model.ts) reads both sides from the reply above, and only a row with a reply on both sides takes the room: a turn that starts with a tool (prompt, tool, reply) keeps its own spacing. Since Transcript: copy once per turn and keep pre-steer replies visible #29740 replies draw no action row of their own (the turn's footer has Copy), so the room is the plain 12px each side (--cv-status-gap-plain). If a reply draws its own row again, both sides become --cv-status-gap (30px). model.ts estimates the same edge, so estimated heights match drawn ones.
  • One left edge. The footer's first action glyph and the "Worked for" label start at the reply text's left edge. The stray padding-inline-start: 2px on .cv-turn-actions and .cv-activity is gone, and the first 24px icon button overhangs the column by its glyph's 4px inset.
  • One icon column. This keeps fix(next): unify transcript activity rows #29754's shared column (--cv-row-icon, --cv-row-icon-gap) as merged. Agent pane: messages between agents share the tool rows' icon column and text inset #28796's two commits, carried here with their authorship, add the check that a message row's mark sits in the same 16px slot and draws at the same size as a tool row's. This PR subsumes Agent pane: messages between agents share the tool rows' icon column and text inset #28796.
  • A drag can start from the blank part of a reply's action row (data-transcript-gap="blank", gutterSelect.ts), never from its buttons.

Measured by the new browser test at 2x (both themes give the same numbers):

before (5179e65) after (bc7616b)
gap above / below a tool row between replies 38 / 4 px 12 / 12 px
gap above / below subagent finished, background task, agent message 38 / 10 px 12 / 12 px
first footer action glyph and "Worked for" label, from the prose edge 6 / 2 px 0 / 0 px
agent-message icon, from the prose edge 8 px 0 px

Before / after (2x, gallery agent-pane.transcript-row-alignment)

I opened both after images. Every row starts on the prose edge, and each status row sits in the middle of its gap.

before after
light
dark

Gallery variants: mix (shipped), roomy (a wider gap), off (the old spacing), and footer (the summary row hovered).

Tests

Risk

Layout only. model.ts row height estimates change for a status row next to a reply. The drawn height is reported with its status edge, and a mismatch drops the cached height, so a stale estimate is re-measured rather than kept.

Performance

statusEdge is O(1) per row and reads only the next row. It adds no timer, observer or animation loop, and no per-token work.

metric before after delta harness or run link
layoutConversation 192k rows, cold (median of 5-6) 35.5 ms 36.3 ms +2% (within run noise: 26-38 ms) rowLayoutLinearity 192k, base 625b1ca vs head model.ts, https://github.com/manaflow-ai/cmux/actions/runs/41207768964
layoutConversation 192k rows, p50 (median of 5-6) 1.51 ms 1.58 ms +0.07 ms same

Spec: design/chat-transcript.md, "Rows between replies" (leo-workspace#1916).

Agent session: agent session

🤖 Generated with Claude Code

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

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · session

@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_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)/
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)
View Logs

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

@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 bc7616b: 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=pr29124 -f ref=lane/transcript-row-alignment -f platform=macos -f backend_mode=local

Gallery before/after for bc7616b: 16 states rendered, 18 images differ, 2715 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 41261973633 -R manaflow-ai/cmux -n gallery-advisory-29124-bc7616bbc751044f8246900f6cae493674baeb65 (then read gallery-review.json)

States
State Theme Status Diff Picked by
agent-pane.access-offer/turn-no-credits Apple System Colors Light changed 1.06% own conversation.css
agent-pane.access-offer/turn-no-credits Apple System Colors changed 1.04% own conversation.css
agent-pane.access-offer/turn-low-credits Apple System Colors Light changed 1.06% own conversation.css
agent-pane.access-offer/turn-low-credits Apple System Colors changed 1.04% own conversation.css
agent-pane.access-offer/turn-no-offer Apple System Colors Light changed 1.05% own conversation.css
agent-pane.access-offer/turn-no-offer Apple System Colors changed 1.03% own conversation.css
agent-pane.addressed-message/relayed Apple System Colors Light changed 1.45% own IncomingMessageCard.tsx
agent-pane.addressed-message/relayed Apple System Colors changed 1.44% own IncomingMessageCard.tsx
agent-pane.agent-message-row/icon-column Apple System Colors Light new 0% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/icon-column Apple System Colors new 0% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/unicode-boundary Apple System Colors Light unchanged 0% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/unicode-boundary Apple System Colors unchanged 0% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/sent Apple System Colors Light changed 0.0136% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/sent Apple System Colors changed 0.0119% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/lanes Apple System Colors Light unchanged 0% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/lanes Apple System Colors unchanged 0% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/sent-subagents Apple System Colors Light unchanged 0% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/sent-subagents Apple System Colors unchanged 0% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/sent-hover Apple System Colors changed 0.0111% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/sent-hover Apple System Colors Light changed 0.0086% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/sent-opened Apple System Colors changed 0.0101% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/sent-opened Apple System Colors Light changed 0.0064% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/sent-opened-long Apple System Colors Light changed 0.005% own AgentMessageRow.gallery.ts
agent-pane.agent-message-row/sent-opened-long Apple System Colors changed 0.0047% own AgentMessageRow.gallery.ts
agent-pane.approval-edits/single Apple System Colors Light unchanged 0% own conversation.css
agent-pane.approval-edits/single Apple System Colors unchanged 0% own conversation.css
agent-pane.approval-edits/grouped Apple System Colors Light unchanged 0% own conversation.css
agent-pane.approval-edits/grouped Apple System Colors unchanged 0% own conversation.css
agent-pane.approval-edits/single-multiedit Apple System Colors Light unchanged 0% own conversation.css
agent-pane.approval-edits/single-multiedit Apple System Colors unchanged 0% own conversation.css
agent-pane.approval-edits/grouped-multiedit Apple System Colors Light unchanged 0% own conversation.css
agent-pane.approval-edits/grouped-multiedit Apple System Colors unchanged 0% own conversation.css

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

Passes: CI passes on bc7616bbc7.

CI passes on bc7616bbc7 (run 41261973518 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:

@teamleaderleo
teamleaderleo force-pushed the lane/transcript-row-alignment branch from 4e0307f to fa1b0a2 Compare October 31, 2026 10:11
@teamleaderleo
teamleaderleo force-pushed the lane/transcript-row-alignment branch from fa1b0a2 to 869d573 Compare October 31, 2026 10:25
teamleaderleo and others added 4 commits October 31, 2026 11:24
… centred between replies

A gallery entry (agent-pane.transcript-row-alignment) with a reply, a subagent that finished, a
reply, a background command that ended, a reply, another agent's message and a reply, under a
folded turn's Worked for line and a footer with its time, tokens and actions; and a browser test
that measures every row's first ink against the prose's left edge, the iconed rows' shared text x,
and the room above and below each status row.

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

A gallery state (agent-pane.agent-message-row / icon-column) stacks a command
row, a message from a Codex session (its logo), this agent's send (the
envelope) and a message from a sender with no mark (the bot). The browser test
measures each top-level row's icon slot, glyph center, drawn glyph size and
first word's x, and fails while a received message's mark sits 8px right of
the tool rows' slot, its name 5.5px right of their words, and its logo draws
at 14px beside the envelope's 11.5px.

Leo: "the alignment i feel like we might as well"

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
Tool rows lay out as a grid: the 16px glyph slot at the row's left edge, the
8px gap, the words at 24px (grid.md 5.5). Messages did not:
- a received message's line and sender each added 4px of inline padding, so
  its mark sat 8px right of the slot and its name started at 28px; the line
  drops the padding and the mark takes the slot (its hover chips keep their
  place before the chevron);
- a sent message's line is flex, where the tool icon's -1.5px end margin (a
  no-op in the grid) pulled its words to 22.5px; it is 0 there;
- the waiting group's chevron moves into the same slot.
A harness logo draws at 12px, the stroke glyphs' drawn size, instead of 14px.

Leo: "the alignment i feel like we might as well"

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
…t on the prose's left edge

Leo, 2026-10-30: "see how claude code has those centered tool calls / id like more alignment too",
and "1 CODEX 2 US 3 US 4 CODEX 5 CLAUDDE WE NEED TO LINE OUR SHIT UP LIKE THEIRS".

- A status row between two replies (a tool run, a subagent's or a background command's end,
  another agent's message, a compaction, a failover, a session start: model.ts isStatusRow) has as
  much room under it as over it: the reply's action row (4 + 24) and the step's 2px margin, 30px
  each side (--cv-status-gap). It was 38 over and 4 to 10 under. Inside an opened Worked for, whose
  replies draw no action row, 12 each side. model.ts statusEdge marks the rows from the next drawn
  row alone (acpmux-row--before-status / --before-reply), and the estimates follow.
- The reply's and the footer's action row starts its first glyph on the prose's left edge, its 24px
  button overhanging by the glyph's 4px inset; the footer's "Worked for 5s" label and the activity
  line under a plan drop their 2px inset. Rows that hold an action row keep layout containment
  alone, so the overhanging hover pill is not cut.
- Gallery agent-pane.transcript-row-alignment gains roomy and off variants.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-92fa78a91e29868c5eaa
@teamleaderleo
teamleaderleo force-pushed the lane/transcript-row-alignment branch from d9e26de to 5179e65 Compare October 31, 2026 11:33
teamleaderleo added a commit that referenced this pull request Oct 31, 2026
teamleaderleo added a commit that referenced this pull request Oct 31, 2026
teamleaderleo added a commit that referenced this pull request Oct 31, 2026
teamleaderleo added a commit that referenced this pull request Oct 31, 2026
teamleaderleo added a commit that referenced this pull request Oct 31, 2026
teamleaderleo added a commit that referenced this pull request Oct 31, 2026
teamleaderleo added a commit that referenced this pull request Oct 31, 2026
teamleaderleo added a commit that referenced this pull request Oct 31, 2026
@teamleaderleo
teamleaderleo marked this pull request as ready for review October 31, 2026 12:51
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#28018 made .cv-tool a flex row; the icon's -1.5px right margin, which the grid's fixed 16px track used to absorb, now pulled the label to 22.5px, off the agent-message rows' 24px. Drop it so every iconed row's words share one x (design/grid.md 5.5).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check:design-tokens refuses a raw calc in padding-bottom; the derived value lives in --cv-status-gap-plain-over beside its parts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Toward base: #29754's one icon column (--cv-row-icon, --cv-row-icon-gap, the tool text inset) is kept whole, and #29740 removed per-reply action rows (hasReplyActions is false), so base's reply-actions test stands. statusEdge now reads the room under a status row from the reply above, as the room over it, so the two always match (12px each side while replies draw no action row; #29585, #29853).

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

Copy link
Copy Markdown
Collaborator Author

Awareness note from an agent lane that does not own this PR; it is not a review or a request to take the PR over.


For awareness, at head c839b6f: the base merge keeps --cv-row-icon-gap: calc(var(--cv-tool-gap) - 1.5px) from #29754. This PR's own commits had dropped that 1.5px so every row's text starts at +24, so on this head row text may start at 22.5px. transcript-row-alignment / transcript-icon-column should show it if so.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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

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 c839b6f

Visual verdict: inspected all supplied after renders; no clipping, bloated controls, or off-screen layout.

  1. [P1] [follow-up] statusEdge marks any assistant followed by a status row as before-status, but only marks the status row’s matching before-reply edge when its next row is immediately another assistant (model.ts:1195). Valid sequences such as assistant → backgroundTask → turnSummary, or consecutive status rows, therefore receive extra space above but ordinary space below, so the new centering is visibly asymmetric. Compute the edge from both neighbors or handle contiguous status groups, with a regression test.

Follow-ups:

  • [P1] [follow-up] Fix asymmetric spacing for status rows that precede a footer or another status row.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (independent Codex gpt-6.1-sol, high, via the review router; full diff from merge base db63437 to this head): BLOCK at c839b6f.

[P2] [blocking] webviews/test/transcript-row-alignment.test.ts:224 - Artifact-enabled runs always time out here: hasReplyActions() returns false, so .acpmux-assistant:has(.cv-reply-actions) never exists. This affects runs with FAST_CHECKS_OUT or CMUX_ROW_ALIGNMENT_ARTIFACT_DIR set. Capture the turn footer’s controls instead.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (independent Codex gpt-6.1-sol, high, via the review router; full diff from merge base db63437 to this head): BLOCK at c839b6f.

[P2] [blocking] webviews/test/transcript-row-alignment.test.ts:224 - With FAST_CHECKS_OUT set by the fast-checks workflow, both theme cases time out here: hasReplyActions() always returns false at this head, so .cv-reply-actions never mounts. Fix the capture to hover and await the turn footer’s actions.

…ere one exists

#29740 left a turn's copy to its footer, so no reply in the gallery draws its own action row and the hover waited out its timeout. The geometry (every lead at 0, every status gap 12/12) already held.

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

cursor Bot commented Nov 1, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

teamleaderleo added a commit that referenced this pull request Nov 1, 2026
teamleaderleo added a commit that referenced this pull request Nov 1, 2026

@cubic-dev-ai cubic-dev-ai 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.

13 issues found across 13 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="webviews/test/transcript-icon-column.test.ts">

<violation number="1" location="webviews/test/transcript-icon-column.test.ts:32">
P2: This catch can silently skip the test in GitHub Actions after `requireBrowserLane` has already accepted the lane, allowing a transient Chromium launch failure to produce a green run with no alignment assertions. Use `probeEngineOrSkip("transcript-icon-column", "chromium", chromium)` here so required lanes fail while local runs retain the intended skip behavior.</violation>
</file>

<file name="webviews/src/agent-session/acpmux/conversation/MessageActions.tsx">

<violation number="1" location="webviews/src/agent-session/acpmux/conversation/MessageActions.tsx:337">
P2: The new `data-transcript-gap="blank"` marker turns the reply action row's empty box into a drag start, but no browser test covers it. Add a case that presses the blank box (and a button inside it) to confirm selection starts only on the box.</violation>
</file>

<file name="webviews/test/transcript-row-alignment.test.ts">

<violation number="1" location="webviews/test/transcript-row-alignment.test.ts:40">
P2: This catch can silently skip the suite on the required GitHub Actions browser lane. Let the launch error fail there, or use the shared browser probe so missing engines are skipped only in environments where skipping is permitted.</violation>

<violation number="2" location="webviews/test/transcript-row-alignment.test.ts:240">
P2: This test never requires or measures a reply action row. Hover a reply before `measure(page)` and require `"reply actions"` in `kinds`, otherwise regressions in that alignment can pass unnoticed.</violation>
</file>

<file name="webviews/src/agent-session/acpmux/model.ts">

<violation number="1" location="webviews/src/agent-session/acpmux/model.ts:1173">
P2: `isToolRun` treats a pending edit as a tool line, but the height estimate in `fallbackRowHeight` sizes the same row as an edited-files card. Check `isEditRow` and align the two rules so a pending-edit row is classed the same way in both places.</violation>

<violation number="2" location="webviews/src/agent-session/acpmux/model.ts:1195">
P2: `statusEdge` marks every assistant immediately before a status row, including terminal status rows that are not between replies. Require a later drawn assistant before applying the centered-status edge, and handle consecutive status rows as one status block.</violation>
</file>

<file name="webviews/src/agent-session/acpmux/App.tsx">

<violation number="1" location="webviews/src/agent-session/acpmux/App.tsx:3359">
P2: The kept-prefix reuse in the `measured` memo does not account for a status edge change on the row above the first changed row. The existing `hasReplyActions` check resets `kept` to that reply for this reason, but the new status edge has no equivalent, so an unmounted reply keeps its stale height until it mounts. Apply the same reset for `statusEdge` on the last drawn row before `kept`.</violation>
</file>

<file name="webviews/src/agent-session/acpmux/conversation/conversation.css">

<violation number="1" location="webviews/src/agent-session/acpmux/conversation/conversation.css:2585">
P3: This comment drops the 1.5px overlap, so it now describes a 24px inset. The rule uses `--cv-tool-text-inset`, which is 22.5px. Restore the overlap wording.</violation>

<violation number="2" location="webviews/src/agent-session/acpmux/conversation/conversation.css:2818">
P3: The new comment says "No inline padding", but this rule still sets `padding-inline: var(--ds-space-1)`. The negative margin cancels that padding so the mark lands on the column edge. Reword the comment to say that, and fold it into the older comment above the rule.</violation>

<violation number="3" location="webviews/src/agent-session/acpmux/conversation/conversation.css:2860">
P3: The hover pill now ends 16px from the line's end, which runs into the 20px chevron box instead of clearing it. The comment's "one small gap" is not true. Restore the previous 20px inset, or measure the chevron box before changing it.</violation>

<violation number="4" location="webviews/src/agent-session/acpmux/conversation/conversation.css:2886">
P3: The comment's 24px is wrong. The sender's name starts at 22.5px (16px slot plus 6.5px gap), matching `--cv-tool-text-inset`. Correct the number to 22.5px.</violation>
</file>

<file name="webviews/src/agent-session/acpmux/conversation/TranscriptRowAlignment.gallery.ts">

<violation number="1" location="webviews/src/agent-session/acpmux/conversation/TranscriptRowAlignment.gallery.ts:57">
P2: This fixture does not render the completed-subagent status row it claims to test: `SUBAGENTS` renders a group header, while `SubagentDoneLine` requires the `subagentDone` row kind. Use a `subagentDone` row here so the alignment scenario covers the intended line.</violation>
</file>

<file name="webviews/src/agent-session/acpmux/conversation/PendingMessagesCard.css">

<violation number="1" location="webviews/src/agent-session/acpmux/conversation/PendingMessagesCard.css:49">
P2: The waiting-message text still starts 1.5px to the right of tool and received text: its 8px flex gap omits the shared icon-overlap adjustment. Apply the tool row's negative icon margin to `.cv-pending__icon`.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic


try {
await (await chromium.launch({ headless: true })).close();
} catch {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: This catch can silently skip the test in GitHub Actions after requireBrowserLane has already accepted the lane, allowing a transient Chromium launch failure to produce a green run with no alignment assertions. Use probeEngineOrSkip("transcript-icon-column", "chromium", chromium) here so required lanes fail while local runs retain the intended skip behavior.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/test/transcript-icon-column.test.ts, line 32:

<comment>This catch can silently skip the test in GitHub Actions after `requireBrowserLane` has already accepted the lane, allowing a transient Chromium launch failure to produce a green run with no alignment assertions. Use `probeEngineOrSkip("transcript-icon-column", "chromium", chromium)` here so required lanes fail while local runs retain the intended skip behavior.</comment>

<file context>
@@ -0,0 +1,204 @@
+
+  try {
+    await (await chromium.launch({ headless: true })).close();
+  } catch {
+    describe.skip("transcript icon column", () => test("browser", () => {}));
+    return;
</file context>

// Over a status row this line is the reply's whole bottom room (conversation.css
// `--cv-status-gap`), so its own blank box, never its buttons, is a transcript gap a drag
// can start from (gutterSelect.ts).
<div className="cv-turn-actions cv-reply-actions" data-transcript-gap="blank">

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: The new data-transcript-gap="blank" marker turns the reply action row's empty box into a drag start, but no browser test covers it. Add a case that presses the blank box (and a button inside it) to confirm selection starts only on the box.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/acpmux/conversation/MessageActions.tsx, line 337:

<comment>The new `data-transcript-gap="blank"` marker turns the reply action row's empty box into a drag start, but no browser test covers it. Add a case that presses the blank box (and a button inside it) to confirm selection starts only on the box.</comment>

<file context>
@@ -331,7 +331,10 @@ export function ReceivedActions({ row, more }: { row: AcpmuxRow; more?: ReactNod
+    // Over a status row this line is the reply's whole bottom room (conversation.css
+    // `--cv-status-gap`), so its own blank box, never its buttons, is a transcript gap a drag
+    // can start from (gutterSelect.ts).
+    <div className="cv-turn-actions cv-reply-actions" data-transcript-gap="blank">
       <span className="cv-turn-action-group">
         <MessageCopy text={text} />
</file context>

"reply",
"worked-for",
"footer label",
"footer actions",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: This test never requires or measures a reply action row. Hover a reply before measure(page) and require "reply actions" in kinds, otherwise regressions in that alignment can pass unnoticed.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/test/transcript-row-alignment.test.ts, line 240:

<comment>This test never requires or measures a reply action row. Hover a reply before `measure(page)` and require `"reply actions"` in `kinds`, otherwise regressions in that alignment can pass unnoticed.</comment>

<file context>
@@ -0,0 +1,258 @@
+          "reply",
+          "worked-for",
+          "footer label",
+          "footer actions",
+          "tool",
+          "subagent finished",
</file context>


try {
await (await chromium.launch({ headless: true })).close();
} catch {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: This catch can silently skip the suite on the required GitHub Actions browser lane. Let the launch error fail there, or use the shared browser probe so missing engines are skipped only in environments where skipping is permitted.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/test/transcript-row-alignment.test.ts, line 40:

<comment>This catch can silently skip the suite on the required GitHub Actions browser lane. Let the launch error fail there, or use the shared browser probe so missing engines are skipped only in environments where skipping is permitted.</comment>

<file context>
@@ -0,0 +1,258 @@
+
+  try {
+    await (await chromium.launch({ headless: true })).close();
+  } catch {
+    describe.skip("transcript row alignment", () => test("browser", () => {}));
+    return;
</file context>

for (const item of row.items ?? []) {
if (!item.tool) continue;
tool = true;
if (card && (item.tool.kind === "edit" || item.tool.kind === "fileChange") && item.tool.status !== "pending")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: isToolRun treats a pending edit as a tool line, but the height estimate in fallbackRowHeight sizes the same row as an edited-files card. Check isEditRow and align the two rules so a pending-edit row is classed the same way in both places.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/acpmux/model.ts, line 1173:

<comment>`isToolRun` treats a pending edit as a tool line, but the height estimate in `fallbackRowHeight` sizes the same row as an edited-files card. Check `isEditRow` and align the two rules so a pending-edit row is classed the same way in both places.</comment>

<file context>
@@ -1144,6 +1144,81 @@ export const hasReplyActions = (_row: AcpmuxRow, _next: AcpmuxRow | undefined) =
+  for (const item of row.items ?? []) {
+    if (!item.tool) continue;
+    tool = true;
+    if (card && (item.tool.kind === "edit" || item.tool.kind === "fileChange") && item.tool.status !== "pending")
+      return false;
+  }
</file context>
Suggested change
if (card && (item.tool.kind === "edit" || item.tool.kind === "fileChange") && item.tool.status !== "pending")
if (card && (item.tool.kind === "edit" || item.tool.kind === "fileChange"))

align-items: center;
justify-content: center;
width: 16px;
width: var(--cv-glyph-slot);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: The waiting-message text still starts 1.5px to the right of tool and received text: its 8px flex gap omits the shared icon-overlap adjustment. Apply the tool row's negative icon margin to .cv-pending__icon.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/acpmux/conversation/PendingMessagesCard.css, line 49:

<comment>The waiting-message text still starts 1.5px to the right of tool and received text: its 8px flex gap omits the shared icon-overlap adjustment. Apply the tool row's negative icon margin to `.cv-pending__icon`.</comment>

<file context>
@@ -43,7 +46,7 @@
   align-items: center;
   justify-content: center;
-  width: 16px;
+  width: var(--cv-glyph-slot);
   color: var(--cv-text-muted);
 }
</file context>
Suggested change
width: var(--cv-glyph-slot);
width: var(--cv-glyph-slot);
margin-right: calc(var(--cv-row-icon-gap) - var(--cv-tool-gap));

ui is all quite inconsistent"): one plate under the whole line on hover, its name, preview,
chevron and actions in it; the preview takes the line's room, so every line's chevron ends at the
same place; the actions show only on hover or focus, over the preview's tail, never moving it. */
/* No inline padding: the sender's mark sits in the tool rows' glyph slot at the row's left edge and

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The new comment says "No inline padding", but this rule still sets padding-inline: var(--ds-space-1). The negative margin cancels that padding so the mark lands on the column edge. Reword the comment to say that, and fold it into the older comment above the rule.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/acpmux/conversation/conversation.css, line 2818:

<comment>The new comment says "No inline padding", but this rule still sets `padding-inline: var(--ds-space-1)`. The negative margin cancels that padding so the mark lands on the column edge. Reword the comment to say that, and fold it into the older comment above the rule.</comment>

<file context>
@@ -2791,6 +2815,10 @@ pre.cv-math-source {
    ui is all quite inconsistent"): one plate under the whole line on hover, its name, preview,
    chevron and actions in it; the preview takes the line's room, so every line's chevron ends at the
    same place; the actions show only on hover or focus, over the preview's tail, never moving it. */
+/* No inline padding: the sender's mark sits in the tool rows' glyph slot at the row's left edge and
+   the chevron ends at its right edge, as every tool row's do (design/chat-transcript.md "One icon
+   column"; Leo, 2026-10-31: "the alignment i feel like we might as well"). The hover plate is the
</file context>

}
/* A failed call's cause (ToolFailureCause.tsx, the `tool-error-look` experiment): one quiet line
under the row, starting under its words (the 16px glyph, less its 1.5px overlap, and the 8px
under the row, starting under its words (the 16px glyph and the 8px

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: This comment drops the 1.5px overlap, so it now describes a 24px inset. The rule uses --cv-tool-text-inset, which is 22.5px. Restore the overlap wording.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/acpmux/conversation/conversation.css, line 2585:

<comment>This comment drops the 1.5px overlap, so it now describes a 24px inset. The rule uses `--cv-tool-text-inset`, which is 22.5px. Restore the overlap wording.</comment>

<file context>
@@ -2558,7 +2582,7 @@ pre.cv-math-source {
 }
 /* A failed call's cause (ToolFailureCause.tsx, the `tool-error-look` experiment): one quiet line
-   under the row, starting under its words (the 16px glyph, less its 1.5px overlap, and the 8px
+   under the row, starting under its words (the 16px glyph and the 8px
    gap), cut to the width; the opened call has the rest. The error tone stays on the row's word. */
 .cv-tool-error {
</file context>
Suggested change
under the row, starting under its words (the 16px glyph and the 8px
under the row, starting under its words (the 16px glyph, less its 1.5px overlap, and the 8px

name, which opens its chat. The name's hover highlight is its own, never the row's. The mark takes
the tool rows' glyph slot (--cv-glyph-slot wide at the row's left edge, glyph centered, then the
8px gap), so a sender's logo and a send's envelope share one center line and the name starts where
every tool row's words do: the slot plus the gap, 24px (grid.md 5.5; transcript-icon-column.test.ts). */

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The comment's 24px is wrong. The sender's name starts at 22.5px (16px slot plus 6.5px gap), matching --cv-tool-text-inset. Correct the number to 22.5px.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/acpmux/conversation/conversation.css, line 2886:

<comment>The comment's 24px is wrong. The sender's name starts at 22.5px (16px slot plus 6.5px gap), matching `--cv-tool-text-inset`. Correct the number to 22.5px.</comment>

<file context>
@@ -2852,7 +2880,10 @@ pre.cv-math-source {
+   name, which opens its chat. The name's hover highlight is its own, never the row's. The mark takes
+   the tool rows' glyph slot (--cv-glyph-slot wide at the row's left edge, glyph centered, then the
+   8px gap), so a sender's logo and a send's envelope share one center line and the name starts where
+   every tool row's words do: the slot plus the gap, 24px (grid.md 5.5; transcript-icon-column.test.ts). */
 .cv-received__sender {
   display: inline-flex;
</file context>
Suggested change
every tool row's words do: the slot plus the gap, 24px (grid.md 5.5; transcript-icon-column.test.ts). */
every tool row's words do: the slot plus the gap, 22.5px (grid.md 5.5; transcript-icon-column.test.ts). */

/* Before the chevron (12px) and the line's inset. */
inset-inline-end: calc(var(--ds-space-1) + 12px + var(--ds-space-1));
/* Before the chevron (12px), one small gap clear of it. */
inset-inline-end: calc(12px + var(--ds-space-1));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The hover pill now ends 16px from the line's end, which runs into the 20px chevron box instead of clearing it. The comment's "one small gap" is not true. Restore the previous 20px inset, or measure the chevron box before changing it.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/acpmux/conversation/conversation.css, line 2860:

<comment>The hover pill now ends 16px from the line's end, which runs into the 20px chevron box instead of clearing it. The comment's "one small gap" is not true. Restore the previous 20px inset, or measure the chevron box before changing it.</comment>

<file context>
@@ -2828,8 +2856,8 @@ pre.cv-math-source {
-  /* Before the chevron (12px) and the line's inset. */
-  inset-inline-end: calc(var(--ds-space-1) + 12px + var(--ds-space-1));
+  /* Before the chevron (12px), one small gap clear of it. */
+  inset-inline-end: calc(12px + var(--ds-space-1));
   display: inline-flex;
   align-items: center;
</file context>

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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

SHIP at bc7616b

Visual verdict: Light/dark after images show the intended alignment without clipped or repeated controls.

  1. [P2][follow-up] Tool text is still 1.5px left of the claimed 24px column. --cv-row-icon-gap remains gap - 1.5px, and .cv-tool__icon still applies that as a negative margin (conversation.css, conversation.css). Thus tool labels and indented tool content start at 22.5px, despite the PR’s “margin is gone” claim and changed inset comment. The new tests compare rows relative to each other, so they do not catch this absolute drift.

Follow-ups:

  • [P2][follow-up] Remove the remaining 1.5px tool-icon overlap so tool text and indented content start at the intended 24px inset.

@teamleaderleo
teamleaderleo merged commit 9d0d544 into feat-cmux-next Nov 1, 2026
168 of 178 checks passed
@teamleaderleo
teamleaderleo deleted the lane/transcript-row-alignment branch November 1, 2026 02:34
teamleaderleo added a commit that referenced this pull request Nov 1, 2026
Resolves #29124 (status rows centred between replies, shared icon column):
App.tsx keeps its status edge class beside acpmux-row--line; the waiting
group's head takes base's slot geometry and keeps no margins of its own; a
one-line row's padding yields to the status edges (same specificity, later)
and statusDelta counts a line row's 4px run gap as a tool run's.

Also, from review: a message this agent sent another one (SendMessage,
acpmux send, a sub-session's send_message) estimates as one 22px tool line.

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

This branch was previously deployed

1 inactive deployment
ci-routing-agent — bc7616bb Deployed Nov 1, 2026 by teamleaderleo via cmux-tui tree preflight #92682
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