Repository navigation
Agent pane: one column, one gap for the bottom stack (tray chevron on 22, narrow outset, radius token) - #28587
teamleaderleo wants to merge 23 commits into
Conversation
Add agent-pane.bottom-stack-styles, the whole bottom stack with synthetic data (nine background subagents, one chat waiting, two PRs, the composer), and a geometry test: every card over the composer takes the composer card's left and right x to 1px, the cards stand one --acpmux-stack-gap apart, and a one-line "N PRs" row opens on the click to chips at the card's width. Red on base: no PR row, no stack gap token. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
…s, with its N PRs row back Leo, 2026-10-30: "you guys fucking removed the # prs thing entirely instead of just simply fucking doing it". cmux#26082 moved the PR pills into each message's action row and dropped the dock's collapsed count. The count comes back as one row in the bottom stack (summary/PullRequestStack.tsx): the PR mark, "N PRs" and a disclosure on the tray header's columns, opening on the click with no fade to one full-width chip per PR with the reply links' hover card. The per-message pills stay. Every card over the composer takes the composer card's two edges and stands --acpmux-stack-gap over the next; the selected look is one glass stack (gap 0, squared joins, one hairline between parts). The gallery compares it with separate cards 4px apart and a compact strip. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
…the chips, each with × Keep the settled PR dock design (design/session-info.md, Leo 2026-10-26): the count opens Session Info > Changes and counts what Changes counts; the disclosure beside it opens the chips, and a chip's × hides that shortcut only, in the dock's existing per-chat dismissal list. The disclosure's glyph centers on the stack's trailing line, 22 from the card's right edge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
bottomStack.css and the PR stack join the composer surface (design/composer.md); the running tray gets its own surface (design/running-tray.md). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
…ith the composer agent-pane-dock-gutters lists the PR row among the stack's parts and checks its gutter passes the wheel through as the tray's does; pr-dock-inline-layout lets the dock and the PR row move up with a queued prompt that grows the form, their own size unchanged. The styles gallery covers PullRequestStack.tsx only (a cover names a component, not a sheet). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
The N PRs row's disclosure, the tray header's chevron and each tray line's chevron must center within 1px of each other at 1100, 760 and 420px. Red at 7e9f7a6: the N PRs chevron sits about 25px right of the tray's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
--acpmux-stack-trail-end is the stack's one trailing chevron column, the running tray's (row padding, Stop track, gap); the N PRs disclosure ends on it, so the stacked rows' chevrons share one x. Once the tray moves its chevron past Stop (#27930), this variable becomes the row padding alone, and the geometry test fails until it does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
…; no PRs without the composer Leo, 2026-10-30: "BUT IF IT'S ONLY N PRS DON'T FUCKIGN TAKE THE ENTIRE ROW AND FUCKING BLANK IT OUT". The edges test now holds the stack as tall with the folded count as with no pull requests (with and without the tray), the count to its content's width with its own highlight, the tray's chevrons to one x, and the opened chips' × to their row's hover or focus (Tab reaches it, Delete dismisses). agent-pane-pr-stack-gate reads App.tsx's syntax tree: the pull requests live only inside the composer's element, so a handoff review or the Sandboxed receipt shows none. The dock-gutter and inline-layout tests go back to base: no row of the count stands in the stack. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
…w, not a row The folded count is one content-sized button beside the permission mode in the composer's quiet row, a row already there, so it adds no row with or without the tray; its pill lights only itself. It opens the chips on the click with no fade, right over the composer at the card's width; a chip's × shows only on its row's hover or focus, with no fade, and Delete or Backspace on a focused row dismisses it. The count and the chips share one provider that is the composer element's own `!reviewing` branch, so they cannot show without the composer. The gallery compares the count on the tray's header line and over the composer's left edge; the tray-line one falls back to the quiet row with no tray. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
The rule that turns the stack's ui-enter off for the chips came before the ui-enter rule with the same specificity, so the chips still rose and faded in on the click. It now comes after it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
… row Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
…expanded gallery state settles Router review at 3106205: after the last PR row was dismissed, focus went to the count, which is disabled with nothing left to open, so keyboard focus was lost. It now goes on to the composer's prompt; the edges test dismisses the last row with Delete and checks the active element is the prompt, never the body. gallery-health's agent-pane.bottom-stack-styles#expanded timed out: its play waited for every animation in the dock to end, and a running line's spinner never ends. The play now waits only for motion that ends. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
1235d62 to
e2d5716
Compare
|
Found 2 test failures on Blacksmith runners: Failures
|
|
MODE-03 / UX-12 source-pinned visual audit: https://github.com/manaflow-ai/cmuxterm-hq/issues/5457#issuecomment-6536782475 At |
|
Owned by an agent session · took over from an earlier session · session |
|
Owned by an agent session · session |
…wn menu dismisses it The opened chips drew a × on every row (shown on hover or focus), which repeats a control on every row. A row is now its link alone; right-click (or Shift-F10) opens its menu with "Dismiss pull request #N", and Delete or Backspace on a focused row still dismisses it. The edges test asserts no row carries a control at rest, hovered or focused, Tab goes row to row, and the menu's Dismiss removes the row and moves focus to the next one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
1b674d0 to
8ebdf51
Compare
…ard from the earlier hover sat over the row) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
…dius, one gap, and 22/42 trailing marks One column, one gap, nothing removed (Leo, 2026-10-30: "the stupid right indent misalignemnt"). A new gallery-frame test measures every .acpmux-dock part and the queue at 1100, 420 and 280px: edges and radius equal the composer box's, the gap under each is the stack token (0 under the last part), and each row's last trailing mark centres 22px from the right, a mark before it 42px. Parts this change fixes fail on a miss; the rest are warnings (grid.md section 7). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
…radius, one gap; the tray's chevron at 22 Leo, 2026-10-30: "the stupid right indent misalignemnt". ui-think-tank's rule, one column, one gap, nothing removed: - The running tray's header ended in an empty 24px Stop slot, so its chevron sat about 46px from the right (43 in a narrow tray) against Send at 22. The header has no Stop slot now; every row ends 12px in with a 20px mark box, so the chevron (header, line, View all) centres 22px from the right, and a line's Stop (or its empty column) centres 42px from the right. Narrow rows keep the same columns. - At composer columns under 298px the box and its quiet row reach 8px past the column; every stack part now follows (--acpmux-stack-start/end on the dock write the same step out, since the composer's container query cannot reach its siblings). - The tray (10px), the opened pull requests and the recap's card (12px) take the box's radius token, now defined on the dock as well. - The recap, the legacy PR bars, the host's line and the agents pill drop their own bottom padding and take the stack's edges; the PR fallback row and the in-transcript tray take --cv-inset-end on the right; one dock rule gives the stack token between parts. The recap's card joins the glass like the tray. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
…ss its narrow outset) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
8ebdf51 to
c86b0e6
Compare
|
Review (codex gpt-6.1-sol high fast, router-review): SHIP at df31d42 Follow-ups:
|
|
drain-ship: not landing. After the lander's base merge, the head (df31d42) still fails |
#28559 moved the box's radius rule to state attributes; the dock takes it with a child-scoped :has(> .acpmux-composer[data-composer-grid]). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-f71664ebfb6cf5206479
|
Orphaned: no activity for 13 h, and no lane holds a lease on it. The orphan sweep could not merge |
|
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. Consolidating the still-needed running-tray changes in #29794, preserving commit authorship and the newer tray layout already on base. This keeps the tray alignment, folding and hidden-row fixes together for validation and landing. |
Conflicts: - App.tsx: base removed the per-message PR chip row (#29614) and the agents pill (#29792). Keep both removals; keep this PR's N PRs stack (PullRequestStackProvider, PullRequestList, PullRequestCountInStack). useTranscriptPullRequests moves into summary/PullRequestStack.tsx (without the removed legacy modes), and its three strings (prDock.label, prDock.count, prDock.countOne) come back. - bottomStack.css: keep the stack edge tokens; drop the agents-pill anchor, pr-dock and pr-comparison selectors base removed. - summary.css: take base (the pr-dock and pr-comparison rules are gone). - design-tokens-baseline.jsonl: base's, regenerated with --update-baseline (one entry shrinks: the recap's old padding). - Tests and gallery: drop the legacy-bars variant, the agent-pane.pr-dock frames and the agents-pill part; the per-message pills now count 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-f71664ebfb6cf5206479
check-default-cursor (Leo, 2026-10-30: "change all pointers back to cursor-default") flagged the two cursor: pointer rules this branch added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
Base #29276 made a settled tray (nothing runs) draw no card. The stack's join rules gave it a rim and squared the part under it, so the subagent-row-anatomy#done-one scene threw. A settled tray now joins nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
There was a problem hiding this comment.
10 issues found across 16 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/src/agent-session/acpmux/bottomStackStyles.gallery.ts">
<violation number="1" location="webviews/src/agent-session/acpmux/bottomStackStyles.gallery.ts:64">
P3: The `no-prs` variants still display “Both PRs are open” even though `prs: false` removes both pull-request activities. Branch the assistant fixture text on `prs` as well, so these gallery states describe the data they render.</violation>
</file>
<file name="webviews/src/agent-session/acpmux/Localizable.xcstrings">
<violation number="1" location="webviews/src/agent-session/acpmux/Localizable.xcstrings:16388">
P2: These count entries are English in every non-English locale, so localized users see `1 PR`/`{count} PRs` even though the surrounding dock label is translated. Add locale-specific count wording, including each locale’s plural form, instead of duplicating the English value across all locale entries.</violation>
</file>
<file name="webviews/test/agent-pane-pr-stack-gate.test.ts">
<violation number="1" location="webviews/test/agent-pane-pr-stack-gate.test.ts:67">
P2: This gate ignores every JSX-attribute use of `composer`, not just the known `QuickSurface` prop, so a later unguarded composer prop could bypass the Sandboxed visibility check while the test still passes. Restrict the exclusion to the verified `QuickSurface` attribute (or assert that all excluded uses are exactly that one).</violation>
</file>
<file name="webviews/test/agent-pane-stack-edges.test.ts">
<violation number="1" location="webviews/test/agent-pane-stack-edges.test.ts:103">
P2: The width matrix is not exercising its requested widths because `open` never passes `width` to `galleryFrame`; the gallery defaults to its `normal` width. Pass `width` in the frame parameters so the 420px and 280px narrow-screen assertions actually run against narrow layouts.</violation>
<violation number="2" location="webviews/test/agent-pane-stack-edges.test.ts:159">
P2: This test can pass vacuously when a target part is not rendered, because it derives the parts under test from the DOM instead of asserting expected parts per fixture. Add fixture expectations and fail when a required part is missing, especially for the parts in `FIXED`.</violation>
</file>
<file name="webviews/test/agent-pane-bottom-stack-edges.test.ts">
<violation number="1" location="webviews/test/agent-pane-bottom-stack-edges.test.ts:44">
P2: This matrix never exercises the narrow outset: 420px is above the `max-width: 297px` breakpoint. Include 280px so the new edge and chip-width assertions cover the narrow layout.</violation>
</file>
<file name="webviews/src/agent-session/acpmux/summary/PullRequestStack.tsx">
<violation number="1" location="webviews/src/agent-session/acpmux/summary/PullRequestStack.tsx:45">
P2: This reverses first-seen order instead of newest-touch order, so mutating an older pull request leaves its chip behind newer untouched requests. Sort the visible results by `touched` (or reuse the Changes ordering) before rendering the stack.</violation>
</file>
<file name="webviews/src/agent-session/acpmux/bottomStack.css">
<violation number="1" location="webviews/src/agent-session/acpmux/bottomStack.css:210">
P2: This `pointer-events: none` declaration is overridden in the floating dock by the more-specific direct-child rule, so the `above` count host captures clicks across its full row rather than only its button. Increase this selector’s specificity or otherwise ensure the host remains pointer-transparent.</violation>
</file>
<file name=".github/design-surfaces.json">
<violation number="1" location=".github/design-surfaces.json:42">
P2: This new composer mapping points to a file that does not exist, so the design-surface validity test fails and the map emits a stale-path warning. Remove this entry; `PullRequestStack.tsx` is already mapped.</violation>
</file>
<file name="webviews/src/agent-session/acpmux/subagents/subagents.css">
<violation number="1" location="webviews/src/agent-session/acpmux/subagents/subagents.css:839">
P2: The Labs `after-latest-message` tray is outside `.acpmux-dock`, so `--acpmux-stack-gap` is undefined and this change removes its existing 8px bottom spacing. Preserve the 8px gap for this transcript placement, or define the shared token on an ancestor that also contains this tray.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
| } | ||
| }, | ||
| "prDock.countOne": {"comment":"Agent pane: compact count of one pull request above the composer (si-prpills)","extractionState":"manual","localizations":{"en":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"ar":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"bs":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"da":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"de":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"es":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"fr":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"it":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"ja":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"km":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"ko":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"nb":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"pl":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"pt-BR":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"ru":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"th":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"tr":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"uk":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"vi":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"zh-Hans":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"zh-Hant":{"stringUnit":{"state":"needs_review","value":"1 PR"}}}}, | ||
| "prDock.count": {"comment":"Agent pane: compact count of pull requests above the composer; {count} is the number (si-prpills)","extractionState":"manual","localizations":{"en":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"ar":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"bs":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"da":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"de":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"es":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"fr":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"it":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"ja":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"km":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"ko":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"nb":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"pl":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"pt-BR":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"ru":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"th":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"tr":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"uk":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"vi":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"zh-Hans":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"zh-Hant":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}}}}, |
There was a problem hiding this comment.
P2: These count entries are English in every non-English locale, so localized users see 1 PR/{count} PRs even though the surrounding dock label is translated. Add locale-specific count wording, including each locale’s plural form, instead of duplicating the English value across all locale entries.
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/Localizable.xcstrings, line 16388:
<comment>These count entries are English in every non-English locale, so localized users see `1 PR`/`{count} PRs` even though the surrounding dock label is translated. Add locale-specific count wording, including each locale’s plural form, instead of duplicating the English value across all locale entries.</comment>
<file context>
@@ -16252,6 +16252,140 @@
+ }
+ },
+ "prDock.countOne": {"comment":"Agent pane: compact count of one pull request above the composer (si-prpills)","extractionState":"manual","localizations":{"en":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"ar":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"bs":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"da":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"de":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"es":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"fr":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"it":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"ja":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"km":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"ko":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"nb":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"pl":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"pt-BR":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"ru":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"th":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"tr":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"uk":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"vi":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"zh-Hans":{"stringUnit":{"state":"needs_review","value":"1 PR"}},"zh-Hant":{"stringUnit":{"state":"needs_review","value":"1 PR"}}}},
+ "prDock.count": {"comment":"Agent pane: compact count of pull requests above the composer; {count} is the number (si-prpills)","extractionState":"manual","localizations":{"en":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"ar":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"bs":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"da":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"de":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"es":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"fr":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"it":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"ja":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"km":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"ko":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"nb":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"pl":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"pt-BR":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"ru":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"th":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"tr":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"uk":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"vi":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"zh-Hans":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}},"zh-Hant":{"stringUnit":{"state":"needs_review","value":"{count} PRs"}}}},
"prDock.dismiss": {
"comment": "Agent pane: button that hides a pull request's bar above the composer for this chat; {number} is the PR number (cx-ncc.81)",
</file context>
| while (node && !ts.isJsxExpression(node)) node = node.parent; | ||
| return node as ts.JsxExpression | undefined; | ||
| }) | ||
| .filter((use): use is ts.JsxExpression => use !== undefined && !ts.isJsxAttribute(use.parent)); |
There was a problem hiding this comment.
P2: This gate ignores every JSX-attribute use of composer, not just the known QuickSurface prop, so a later unguarded composer prop could bypass the Sandboxed visibility check while the test still passes. Restrict the exclusion to the verified QuickSurface attribute (or assert that all excluded uses are exactly that one).
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/agent-pane-pr-stack-gate.test.ts, line 67:
<comment>This gate ignores every JSX-attribute use of `composer`, not just the known `QuickSurface` prop, so a later unguarded composer prop could bypass the Sandboxed visibility check while the test still passes. Restrict the exclusion to the verified `QuickSurface` attribute (or assert that all excluded uses are exactly that one).</comment>
<file context>
@@ -0,0 +1,85 @@
+ while (node && !ts.isJsxExpression(node)) node = node.parent;
+ return node as ts.JsxExpression | undefined;
+ })
+ .filter((use): use is ts.JsxExpression => use !== undefined && !ts.isJsxAttribute(use.parent));
+ expect(uses.length).toBeGreaterThan(0);
+ for (const use of uses) {
</file context>
| return fill || s.boxShadow !== "none" || parseFloat(s.borderTopWidth) > 0 || parseFloat(s.borderLeftWidth) > 0; | ||
| }; | ||
| const composer = dock.querySelector(":scope > .acpmux-composer"); | ||
| const nodes = [...dock.children].filter((el) => el !== composer && shown(el)); |
There was a problem hiding this comment.
P2: This test can pass vacuously when a target part is not rendered, because it derives the parts under test from the DOM instead of asserting expected parts per fixture. Add fixture expectations and fail when a required part is missing, especially for the parts in FIXED.
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/agent-pane-stack-edges.test.ts, line 159:
<comment>This test can pass vacuously when a target part is not rendered, because it derives the parts under test from the DOM instead of asserting expected parts per fixture. Add fixture expectations and fail when a required part is missing, especially for the parts in `FIXED`.</comment>
<file context>
@@ -0,0 +1,319 @@
+ return fill || s.boxShadow !== "none" || parseFloat(s.borderTopWidth) > 0 || parseFloat(s.borderLeftWidth) > 0;
+ };
+ const composer = dock.querySelector(":scope > .acpmux-composer");
+ const nodes = [...dock.children].filter((el) => el !== composer && shown(el));
+ const queue = composer?.querySelector(":scope > .acpmux-composer-queue");
+ if (queue && shown(queue)) nodes.push(queue);
</file context>
| async function open(entry: string, variant: string, width: number, theme?: string, scale = 1): Promise<Page> { | ||
| const port = (vite!.httpServer!.address() as { port: number }).port; | ||
| const page = await browser!.newPage({ viewport: { width, height: 680 }, deviceScaleFactor: scale }); | ||
| await page.goto(`http://127.0.0.1:${port}${galleryFrame(entry, { variant, theme })}`); |
There was a problem hiding this comment.
P2: The width matrix is not exercising its requested widths because open never passes width to galleryFrame; the gallery defaults to its normal width. Pass width in the frame parameters so the 420px and 280px narrow-screen assertions actually run against narrow layouts.
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/agent-pane-stack-edges.test.ts, line 103:
<comment>The width matrix is not exercising its requested widths because `open` never passes `width` to `galleryFrame`; the gallery defaults to its `normal` width. Pass `width` in the frame parameters so the 420px and 280px narrow-screen assertions actually run against narrow layouts.</comment>
<file context>
@@ -0,0 +1,319 @@
+ async function open(entry: string, variant: string, width: number, theme?: string, scale = 1): Promise<Page> {
+ const port = (vite!.httpServer!.address() as { port: number }).port;
+ const page = await browser!.newPage({ viewport: { width, height: 680 }, deviceScaleFactor: scale });
+ await page.goto(`http://127.0.0.1:${port}${galleryFrame(entry, { variant, theme })}`);
+ await page.locator(".acpmux-composer-box").first().waitFor({ timeout: 90_000 });
+ await page.waitForFunction(() => document.documentElement.dataset.galleryReady === "1", undefined, {
</file context>
| await page.goto(`http://127.0.0.1:${port}${galleryFrame(entry, { variant, theme })}`); | |
| await page.goto(`http://127.0.0.1:${port}${galleryFrame(entry, { variant, theme, width })}`); |
| setDefaultTimeout(840_000); | ||
| const ENTRY = "agent-pane.bottom-stack-styles"; | ||
| const out = process.env.CMUX_BOTTOM_STACK_CAPTURE ?? process.env.FAST_CHECKS_OUT; | ||
| const WIDTHS = [1100, 760, 420]; |
There was a problem hiding this comment.
P2: This matrix never exercises the narrow outset: 420px is above the max-width: 297px breakpoint. Include 280px so the new edge and chip-width assertions cover the narrow layout.
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/agent-pane-bottom-stack-edges.test.ts, line 44:
<comment>This matrix never exercises the narrow outset: 420px is above the `max-width: 297px` breakpoint. Include 280px so the new edge and chip-width assertions cover the narrow layout.</comment>
<file context>
@@ -0,0 +1,361 @@
+ setDefaultTimeout(840_000);
+ const ENTRY = "agent-pane.bottom-stack-styles";
+ const out = process.env.CMUX_BOTTOM_STACK_CAPTURE ?? process.env.FAST_CHECKS_OUT;
+ const WIDTHS = [1100, 760, 420];
+ /** The selected look's states, held to every rule; the comparisons are measured for the record
+ * and held to the no-row rule where they claim it. */
</file context>
| parsed.current = { key, repository, prs: transcriptPullRequests(rows, { folder: repository, replies: false }) }; | ||
| } | ||
| const all = parsed.current.prs; | ||
| return useMemo(() => visibleChanges(all, headerStatus(live)).reverse(), [all, live]); |
There was a problem hiding this comment.
P2: This reverses first-seen order instead of newest-touch order, so mutating an older pull request leaves its chip behind newer untouched requests. Sort the visible results by touched (or reuse the Changes ordering) before rendering the stack.
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/summary/PullRequestStack.tsx, line 45:
<comment>This reverses first-seen order instead of newest-touch order, so mutating an older pull request leaves its chip behind newer untouched requests. Sort the visible results by `touched` (or reuse the Changes ordering) before rendering the stack.</comment>
<file context>
@@ -0,0 +1,291 @@
+ parsed.current = { key, repository, prs: transcriptPullRequests(rows, { folder: repository, replies: false }) };
+ }
+ const all = parsed.current.prs;
+ return useMemo(() => visibleChanges(all, headerStatus(live)).reverse(), [all, live]);
+}
+
</file context>
| position: relative; | ||
| flex: none; | ||
| margin: 0 var(--acpmux-stack-end) 0 var(--acpmux-stack-start); | ||
| pointer-events: none; |
There was a problem hiding this comment.
P2: This pointer-events: none declaration is overridden in the floating dock by the more-specific direct-child rule, so the above count host captures clicks across its full row rather than only its button. Increase this selector’s specificity or otherwise ensure the host remains pointer-transparent.
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/bottomStack.css, line 210:
<comment>This `pointer-events: none` declaration is overridden in the floating dock by the more-specific direct-child rule, so the `above` count host captures clicks across its full row rather than only its button. Increase this selector’s specificity or otherwise ensure the host remains pointer-transparent.</comment>
<file context>
@@ -49,10 +49,265 @@
+ position: relative;
+ flex: none;
+ margin: 0 var(--acpmux-stack-end) 0 var(--acpmux-stack-start);
+ pointer-events: none;
+}
+.acpmux-dock > .acpmux-pr-count-host > .acpmux-pr-count {
</file context>
| pointer-events: none; | |
| pointer-events: none !important; |
| "webviews/src/agent-session/acpmux/composerStates.css", | ||
| "webviews/src/agent-session/acpmux/bottomStack.css", | ||
| "webviews/src/agent-session/acpmux/summary/PullRequestStack.tsx", | ||
| "webviews/src/agent-session/acpmux/summary/PullRequestDockLegacy.tsx" |
There was a problem hiding this comment.
P2: This new composer mapping points to a file that does not exist, so the design-surface validity test fails and the map emits a stale-path warning. Remove this entry; PullRequestStack.tsx is already mapped.
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 .github/design-surfaces.json, line 42:
<comment>This new composer mapping points to a file that does not exist, so the design-surface validity test fails and the map emits a stale-path warning. Remove this entry; `PullRequestStack.tsx` is already mapped.</comment>
<file context>
@@ -36,7 +36,18 @@
+ "webviews/src/agent-session/acpmux/composerStates.css",
+ "webviews/src/agent-session/acpmux/bottomStack.css",
+ "webviews/src/agent-session/acpmux/summary/PullRequestStack.tsx",
+ "webviews/src/agent-session/acpmux/summary/PullRequestDockLegacy.tsx"
+ ]
+ },
</file context>
| .acpmux-running-tray[data-placement="after-latest-message"] { | ||
| flex: none; | ||
| margin: 0 var(--cv-inset) 8px; | ||
| margin: 0 var(--cv-inset-end, var(--cv-inset)) var(--acpmux-stack-gap, 0px) var(--cv-inset); |
There was a problem hiding this comment.
P2: The Labs after-latest-message tray is outside .acpmux-dock, so --acpmux-stack-gap is undefined and this change removes its existing 8px bottom spacing. Preserve the 8px gap for this transcript placement, or define the shared token on an ancestor that also contains this tray.
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/subagents/subagents.css, line 839:
<comment>The Labs `after-latest-message` tray is outside `.acpmux-dock`, so `--acpmux-stack-gap` is undefined and this change removes its existing 8px bottom spacing. Preserve the 8px gap for this transcript placement, or define the shared token on an ancestor that also contains this tray.</comment>
<file context>
@@ -830,9 +831,12 @@ button.cv-subagent > :last-child {
.acpmux-running-tray[data-placement="after-latest-message"] {
flex: none;
- margin: 0 var(--cv-inset) 8px;
+ margin: 0 var(--cv-inset-end, var(--cv-inset)) var(--acpmux-stack-gap, 0px) var(--cv-inset);
}
.acpmux-agent-card__state[data-status="failed"] {
</file context>
| margin: 0 var(--cv-inset-end, var(--cv-inset)) var(--acpmux-stack-gap, 0px) var(--cv-inset); | |
| margin: 0 var(--cv-inset-end, var(--cv-inset)) 8px var(--cv-inset); |
| assistant( | ||
| tray | ||
| ? "Both PRs are open. Nine subagents are still checking in the background." | ||
| : "Both PRs are open and the checks are done.", | ||
| 2, | ||
| ), | ||
| ], |
There was a problem hiding this comment.
P3: The no-prs variants still display “Both PRs are open” even though prs: false removes both pull-request activities. Branch the assistant fixture text on prs as well, so these gallery states describe the data they render.
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/bottomStackStyles.gallery.ts, line 64:
<comment>The `no-prs` variants still display “Both PRs are open” even though `prs: false` removes both pull-request activities. Branch the assistant fixture text on `prs` as well, so these gallery states describe the data they render.</comment>
<file context>
@@ -0,0 +1,190 @@
+ ? [activity([create("fix(picker): keep the model list in view", 128), create("Composer: one edge", 129)], 13)]
+ : []),
+ ...(tray ? [row(SUBAGENTS, 12, { subagents: agents })] : []),
+ assistant(
+ tray
+ ? "Both PRs are open. Nine subagents are still checking in the background."
</file context>
| assistant( | |
| tray | |
| ? "Both PRs are open. Nine subagents are still checking in the background." | |
| : "Both PRs are open and the checks are done.", | |
| 2, | |
| ), | |
| ], | |
| assistant( | |
| prs | |
| ? tray | |
| ? "Both PRs are open. Nine subagents are still checking in the background." | |
| : "Both PRs are open and the checks are done." | |
| : tray | |
| ? "Nine subagents are still checking in the background." | |
| : "The checks are done.", | |
| 2, | |
| ), |
|
Merge of
What is still this PR's own on top of base is small: the recap ( |
|
Carried to #32669 on current feat-cmux-next. Base already covers the tray's edges, narrow outset, radius and gap, and removed the PR chips (#29614), and the per-row Stop this PR's HOLD waited on is now base's settled design (#29264). #32669 ports only what was still this PR's own: the recap card's and the host line's edges ( |
… edges (carries #28587) (#32669) * Agent pane: the recap card and the host's line on the composer card's edges The recap card and the host's line now take --cv-inset-end on the right and the composer's 8px narrow outset, as the running tray already does, and the recap card takes the composer's radius token. Carries the still-needed part of #28587 onto base's bottom stack. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-627034dbf10a04318c5c * Recap card: its inline edges in padding-inline, so the spacing ratchet keeps base's baseline Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-627034dbf10a04318c5c --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
HOLD: this head still carries the per-row Stop button in SubagentTray.tsx; it lands after that fix is merged in.
Leo, 2026-10-30, on the agent pane's bottom stack:
This follows #28533 and is stacked on its head e61c418 (#28533 hasn't landed yet), so its diff shows #28533's commits until that lands. It implements ui-think-tank's audit of Leo's bottom-stack complaints:
#28533's "N PRs" design is unchanged: an inline control in the quiet row that opens the chips (Leo: "DON'T … TAKE THE ENTIRE ROW").
What changed
The tray's trailing grid is carry of #27602: compact waiting messages and subagent tray grid #28113's, taken whole. Base's carry of #27602: compact waiting messages and subagent tray grid #28113 (Leo, 2026-10-29: "There's this right indent for no reason.") already put the header's, every line's and View all's chevrons on one x, with a line's Stop after the chevron. This PR merged base and kept that grid as the settled design: its
SubagentTray.tsx, the tray's trailing-track CSS and its tray tests are base's, unchanged. The 22/42 tray grid an earlier head of this PR had is dropped (design/running-tray.mdrecords it under Replaced).agent-pane-stack-edgesstill checks 22/42 for the other parts and only records the tray's trailing marks;subagent-tray-columnschecks its one chevron x.The narrow outset. At composer columns under 298px, the box and its quiet row reach 8px past the column on each side (
composerLocation.css). Every stack part now does the same.--acpmux-stack-startand--acpmux-stack-endon the dock write out the same step, because the composer's container query can't reach its siblings.Radius. The tray (10px), the opened PR chips and the recap's card (12px) now take the box's radius token,
--acpmux-composer-radius, which is now also defined on the dock. That gives 11px in the Claude look and 18px otherwise.Own margins and padding. These parts take the stack's edges and drop their own bottom padding; one dock rule now gives
--acpmux-stack-gapbetween parts:summary.css);styles.css, 8px bottom padding);bottomStack.css, 8px bottom padding).The PR fallback row and the in-transcript tray (Labs) now take
--cv-inset-endon the right, and the in-transcript tray uses the stack token instead of its 8px margin. The recap's card joins the glass the same way the tray does.Measurements (
test/agent-pane-stack-edges.test.ts, gallery, Chromium)Each "before" figure was measured on #28533's head e2d5716 (run 41146240957; also run 41144611936). The "after" figures come from the head 3360d26 (run 41172778670,
stack-edges.json).Stills (2x, light and dark, synthetic data)
Each image is one 2x2 grid: top row before (#28533's head), bottom row after (3360d26; its tray lines show #28113's subagent icon from base); left light, right dark. Ten images in all.
Viewed after image: https://raw.githubusercontent.com/manaflow-ai/cmux/pr-media/28587/ux-bs4-recap-1100.png (and every grid below: the recap card, the tray, the opened PRs and the chevron close-ups all stand on the box's edges and radius in the bottom row; at 280 the before row shows the 8px inset).
Recap, 1100 (its card's radius and edges)
Recap, 280 (the card on the box's narrow outset)
Right-edge chevrons close-up, 1100
Right-edge chevrons close-up, 280
Tray expanded, 1100
Tray expanded, 280
Tray collapsed, 1100
Tray collapsed, 280
PR control opened, 1100 (first row hovered)
PR control opened, 280 (first row hovered)
Tests
test/agent-pane-stack-edges.test.ts, committed before the fix. It runs on the agent-pane-column-edges harness at 1100, 420 and 280px..acpmux-dock > :not(.acpmux-composer)part plus.acpmux-composer-queue. Each one's left and right edges and radius must equal.acpmux-composer-box's within 0.5px, and the gap under each must be the stack token, or 0 under the last part, which sits on the box.agent-pane.subagent-tray(between-turns, which is the "Running in background" between-turns state; several-running; duration-columns; panel-two; and the 300px narrow short-dock),agent-pane.bottom-stack(pr-queue, trusted-permission-queue, compact-trust-queue, short-400-long-draft),agent-pane.pr-dock(inline-pills, full-bars),agent-pane.recap-card, andagent-pane.bottom-stack-styles(collapsed, expanded, prs-open).subagent-tray-columnsandsubagent-trayare base's (carry of #27602: compact waiting messages and subagent tray grid #28113's), unchanged.subagent-tray-layoutchecks that the tray's margin is the stack's insets.agent-pane-bottom-stack-edges,agent-pane-pr-stack-gate,subagent-tray-columns,subagent-tray,subagent-tray-layout,agent-pane-column-edges,agent-pane-dock-gutters,agent-pane-bottom-stack,composer-bottom-space,composer-edgesandpr-dock-inline-layout. The one red wassubagent-tray-layoutstill asserting the old margin literal. It was fixed at 1b674d0 (49 of 49, run 41161006984). At c86b0e6 (rebased onto Agent pane: the bottom stack on one edge as one glass, Stop in the tray row's menu #28533's e61c418)agent-pane-stack-edges,agent-pane-bottom-stack-edges,agent-pane-pr-stack-gate,subagent-tray-layout,subagent-tray-columnsandsubagent-traypass 56 of 56 (run 41170446218); at the head 3360d26, with base merged and carry of #27602: compact waiting messages and subagent tray grid #28113's tray tests, the same six files pass 56 of 56 (run 41172778670).scripts/web-lint.shandprepush-gate.pypass. The design-token baseline went down by one entry: the recap's 6px bottom padding is gone.Still at warning level (not fixed here)
.acpmux-permission): radius 8 in trusted-permission-queue, and at 280px it stands +8/−8px inside the box's narrow outset.Observed / Not run
stack-edges.jsonin those runs' artifacts.Spec: design/composer.md rule 9 now carries this rule, and
design/running-tray.mdrecords #28113's one trailing track as settled (the 22/42 tray grid under Replaced), both in leo-workspace#1751 (lane/ux-bottom-stack-spec). This PR doesn't duplicate them.Risk: normal. The change is CSS only (edges, radius, gap and outset); the tray's markup and trailing grid are base's.
Changelog
Fixed: the running tray's chevrons line up with the composer's right edge, and every part over the composer shares its edges and corner radius at every width.
Agent session: agent session
🤖 Generated with Claude Code