Repository navigation
Agent chat: one bottom stack, so the queue never covers the PR dock - #20521
Merged
Merged
Conversation
…r inset hq#1957 composer controls row (item 15). A gallery entry (agent-pane.composer-row) draws Leo's row (Claude Opus 5.5, ring, Medium, Auto), a long model name, the chat-wide allowance chip and a queued running turn at 420, 720 and 1100 px. The browser test measures it: one contiguous left cluster, free space only before mic/Send, no cut label while the row has room, permission labels cut first and the model last, and the footer inset from the card's bottom edge. Red: CMUX_BROWSER_TESTS=1 bun test test/composer-row-layout.test.ts -> 0 pass, 12 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hq#1957 composer controls row (item 15). The permission chip was a fixed 180 px wide behind a flex spacer, so the row kept a large empty gap while the model and effort chips truncated, and below 480 px the model went icon-only before anything else. - The chips hug their controls (+, model, ring, effort, permission mode, then the granted status); mic and Send/Stop keep margin-left: auto. Free space sits only between the two clusters. The permission chip stays in the left cluster with the other session settings; the right cluster stays the input's own actions. - A short row drops the permission labels to their lock first (composerRowFit.ts measures the row and sets data-fit=icons; hidden labels stay laid out so the decision never toggles to measure), then effort shortens, the model last (flex-shrink weights 1e5:1 with min widths). The 480 px icon-only model and fixed access widths are gone. - The footer grows with its content (min-height, no fixed height), never shrinks, and keeps the bar's 12 px side inset and a 10 px bottom inset inside the card. The composer-menu-width case that pinned the 180 px chip now checks the contract that mattered: a mode change moves no other control. Green: CMUX_BROWSER_TESTS=1 bun test test/composer-row-layout.test.ts -> 12 pass, 0 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hq#1957 composer controls row (item 15), layout-shift follow-up. A gallery entry (agent-pane.composer-turn-cycle) opens a chat's first turn idle, before any context usage, and its cycle play delivers running, one then three subagents, a subagent's permission ask, a queued prompt and finished through the pane bridge. The browser test checks that the prompt, controls row, footer and every control keep their boxes within 0.5 px at 420, 720 and 1100 px, and that typing during the turn (Stop -> Steer + Send) moves neither the mic nor Send. Red: CMUX_BROWSER_TESTS=1 bun test test/composer-turn-cycle.test.ts -> 0 pass, 6 fail (the context ring mounts when the turn starts and shifts effort and the permission chip; Steer lands between the mic and Send and pushes the mic left). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hq#1957 composer controls row (item 15), layout-shift follow-up. - The context ring holds its slot from the session's start (inert until the first usage report, as ContextRing already draws it) instead of mounting when the turn starts, which slid effort and the permission chip 34 px right on every chat's first turn. - Steer comes in at the leading edge of the right cluster, so when typing during a turn turns Stop into Steer and Send, the mic and Send keep their places (it used to land between them and push the mic left). The queued-prompt stack, a subagent's permission ask and the PR dock already grow upward over the transcript; Send and Stop share one 32 px circle. Green: CMUX_BROWSER_TESTS=1 bun test test/composer-turn-cycle.test.ts -> 6 pass, 0 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…xel band (hq#1957 item 15) Red: bun test test/composer-row-fit.test.ts -> 1 pass, 2 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#1957 item 15) Hysteresis on the labels/icons switch so a sub-pixel squeeze cannot flip it every frame; drops a leftover spacer from the dictation gallery. Green: bun test test/composer-row-fit.test.ts -> 3 pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…q#1957 composer location strip) Unit test for the disambiguation rule: projects sharing a name each take the fewest trailing folders of their path that no other of that name shares; ~ for the home folder; the parent folder when nothing else tells it apart. Red: `bun test test/project-suffix.test.ts` -> 0 pass, 1 fail, 1 error (projectSuffix.ts does not exist yet). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…composer location strip) projectSuffixes(): projects sharing a name each take the fewest trailing folders of their path that no other of that name shares at the same depth (the name's own folder left out), the home folder as ~, and the parent folder when nothing else tells them apart. Green: `bun test test/project-suffix.test.ts` -> 8 pass, 0 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ct row) hq#1957 item 15 compact row. Leo's nightly row reads as toy blocks: a context ring that looks like a spinner, uneven gaps, two locks (Auto and the "Trusted this chat's..." status chip) and a large white Stop disc. The row-layout test now checks, at 420, 720 and 1100 px in every variant: the left cluster's controls sit 8-12 px apart and within 1 px of each other; no ring or spinner in the row; one lock at most; no granted-status chip; Stop's glyph is a square of at most 12 px; and Stop takes Send's box (within 0.5 px) and its resting fill. The turn-cycle test checks no ring or spinner, one lock and no status chip in every phase, and no longer tracks the ring's slot. Red: CMUX_BROWSER_TESTS=1 bun test test/composer-row-layout.test.ts test/composer-turn-cycle.test.ts -> 3 pass, 30 fail (model-effort 36 px apart around the ring, effort-access 2 px; ring in the row in every phase; 2 locks and the status chip in "granted"; Stop's fill rgb(255,255,255) against Send's grey). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…omposer location strip) Chromium layout tests on new gallery entries (agent-pane.composer-strip: project, no-project, host-loading, queued, awaiting, reported; and agent-pane.composer-context duplicate-worktrees / duplicate-search) plus the New Tab's `empty` page: - the strip's bottom edge is the card's top edge (within 1 px), chat and New Tab, at 420 and 720 px; the card holds one controls row and no location row; - the strip is as tall with no project, a project and while the host loads; - queued prompts sit above the strip; - no skeleton/placeholder while effort and access load, and the controls keep their x positions when the values arrive; - the folder popover suffixes duplicate names, keeps the path for hover, checks the current project, filters as typed, ends with Choose folder…. Red: `CMUX_BROWSER_TESTS=1 bun test test/composer-location-strip.test.ts` -> 0 pass, 10 fail (no strip; the folder menu has no search or suffixes; effort moves 34 px when the session reports, as the context ring arrives). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t row)
hq#1957 item 15 compact row. The row is "+ · model · effort · access" on the left and
mic, then Send/Stop on the right, with free space only between the two.
- Gaps: the chips sit the bar's 8 px apart (they were 2 px, plus the ring's 36 px slot), so
the left cluster's gaps are all 8 px. Model, effort and access are the bar's regular 28 px
(were 30) with tighter padding.
- Hover: the shared quiet wash (ui.css --ui-hover's fallback, the control's ink at 6% over
the card; 12% on press) tight to the control, in place of the opaque composer-hover block.
Mic, Plan and Steer use it too.
- No context ring in the row. This undoes the earlier fixed ring slot. The chat's usage is
in the model chip's tooltip ("Opus 5.5 · 42% of context used", the existing picker.context
string), shown while showContextUsage is on. The row's right-click no longer offers
Hide/Show Context Usage, which has no control to act on now. Compact stays reachable as
/compact. ContextRing itself and its gallery are kept.
- One lock: the granted-permission status chip (PermissionStatus) is no longer placed in the
row. The component and its gallery stay. Trust undo and chat-allowance revoke keep their
other entry points in App.tsx.
- Stop is Send's 28 px circle at its resting fill (the accent at 34% over the base), with a
7 px square in the text color, not a white disc. Its hover and press step the circle.
- composerRowFit.ts no longer watches the status chip. Galleries drop the ring plays
(composer context-usage-menu, picker context-details/context-focus).
Green: CMUX_BROWSER_TESTS=1 bun test test/composer-*.test.ts -> 53 pass, 0 fail
(composer-row-layout + composer-turn-cycle: 33 pass, 0 fail). bun run check -> pass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…popover with search (hq#1957 composer location strip) - The folder · computer row (and the branch) leaves the card's bottom: ComposerContext always draws `.acpmux-composer-strip`, a tab on the card's top edge with the card's fill and edge, a 10 px top radius, inset by the card's corner radius and a fixed 30 px height. The card keeps one controls row. Composer drops `contextFirst`; App stops passing it. - New Tab: the strip sits on `.nt-box`'s top edge inside `.nt-composer`. - Queued prompts stack above the strip at its insets. - FolderPopover (new): the shared Combobox in a Popover. Rows show the project name plus a suffix only for duplicate names (projectSuffix.ts), the path on hover, a check on the current folder; the search filters by name, suffix and path; arrows reach New Worktree, Add project and Choose folder… after the folders; Escape returns to the strip. The started chat's folder combobox uses the same suffixes and tooltip. - Hooks shared by the location menus move to locationPopover.ts. - Tests and plays that read the old footer or menu roles follow the strip and the popover (composer-row-layout, new-tab-composer-layout, new-tab-add-project-layer, chat-new-worktree, started-chat-folder-new-chat, start-folder and composer-context plays). Green: `CMUX_BROWSER_TESTS=1 bun test test/composer-location-strip.test.ts` -> 9 pass, 1 fail. The remaining red is the effort/access x-position check: the context ring joins the row when the session reports and moves effort 34 px; the updated base (cg-lane-adopt/composer-row) takes the ring out of the row, merged next. `bun run check` passes; composer-row-layout and composer-turn-cycle pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…7 composer location strip) The base's compact row (no context ring or status chip in the row, even gaps, Stop as Send) merges cleanly but for composer-row-layout.test.ts, where both sides changed Row: keep the base's new compact-row fields and the strip's checks, drop the old footer-inset fields. After the merge: `CMUX_BROWSER_TESTS=1 bun test test/composer-location-strip.test.ts` -> 10 pass, 0 fail (the effort/access x-position check is green now that the ring left the row); 23 related files (composer-row-layout, composer-turn-cycle, location side, menus, New Tab, gallery coverage/play, ui-rules, ...) -> 116 pass, 0 fail. `bun run check` passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lass (hq#1957 border hunt) Red: CMUX_BROWSER_TESTS=1 bun test test/composer-edges.test.ts -> 0 pass, 5 fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…asured at rest (hq#1957 border hunt) Red (New Tab box): CMUX_BROWSER_TESTS=1 bun test test/composer-edges.test.ts -> New Tab box: no drop shadow fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ass shadow and rim (hq#1957 border hunt) The composer card keeps only its --acpmux-composer-edge hairline (clear under appearance.borders = none); permission cards take the same hairline and no shadow; the New Tab box loses its drop shadow at rest and on focus. Focus still steps the edge toward the accent. Green: CMUX_BROWSER_TESTS=1 bun test test/composer-edges.test.ts -> 6 pass. Related composer/New Tab/permission suites: 132 pass, 1 fail (new-tab-chat-title-width, fails identically on the base). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#1957 border hunt) The permission panel's gallery entry loaded only styles.css and sat outside .acpmux-shell, so the card's edge rules (composerLocation.css, --acpmux-composer-edge) never applied and its edge checks passed vacuously. The entry now loads the pane's stylesheets inside the shell, and a guard keeps the card's one .5px hairline (Leo: a thin Liquid Glass rim is good, don't strip it to zero). Red on the pre-fix CSS (1bebce0): 1 pass, 6 fail. Green: 7 pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- vp fmt webviews/src/agent-session/acpmux/modelPickerLayout.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38521546851
…-location-strip # Conflicts: # webviews/src/agent-session/acpmux/composerLocation.css
…(hq#1957 composer location strip) Red: CMUX_BROWSER_TESTS=1 bun test test/composer-location-strip.test.ts -t seam -> 0 pass, 2 fail (the chat card's top hairline 24 levels off the fills around it). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o seam hairline (hq#1957 composer location strip) The card's rim (resting, focused, shell, Increase Contrast) is --acpmux-card-ring; under a strip the card draws it on ::before with the strip's stretch masked out, so the card's edge meets the strip's sides. The strip takes the card's edge color (clear under appearance.borders = none), and the strip inset lives on the composer so the card knows it. Chat composer and New Tab. Green: CMUX_BROWSER_TESTS=1 bun test test/composer-location-strip.test.ts test/composer-edges.test.ts -> 19 pass. Composer/New Tab/permission suites: 154 pass, 1 fail (new-tab-chat-title-width, fails on the base too). bun run check passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pt/composer-location-strip # Conflicts: # webviews/src/agent-session/acpmux/modelPickerLayout.ts
- vp fmt webviews/src/agent-session/acpmux/App.tsx - vp fmt webviews/src/agent-session/acpmux/subagents/subagents.gallery.ts - vp fmt webviews/src/agent-session/acpmux/summary/SubagentStatusList.tsx - vp fmt webviews/src/agent-session/acpmux/summary/cardState.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38524642314
…pt/composer-location-strip # Conflicts: # webviews/src/agent-session/acpmux/newtab/screen.css
…-next merge (hq#1957 item 15) The merge took feat-cmux-next's modelPickerLayout.ts and dropped ModelPickerProps.usage, which the compact row passes for the context-usage tooltip (TS2339 in web / react-apps-check). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- regenerated schemas/defaults/cmux-next.json - vp fmt webviews/src/pages/home-channels/ConversationList.tsx - vp fmt webviews/src/pages/home-channels/HomeChannelsPage.tsx - vp fmt webviews/src/pages/home-channels/ThreadSheet.tsx - vp fmt webviews/src/pages/home-channels/daemonHome.ts - vp fmt webviews/src/pages/home-channels/model.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38535029393
The summary card's raw z-index goes into the layers baseline (op-next-toolbar is reworking that card), and its auto-open checkbox gets the label the lint wants. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…strip' into cg-lane-adopt/composer-location-strip
Red: the queued prompts are laid over the transcript's foot, so with pull requests docked above the composer the queue draws over the dock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo
added a commit
that referenced
this pull request
Oct 14, 2026
Base's one bottom stack (#20521) already puts the queue in the page's flow above the composer, which this branch did with its own queue slot. Kept base's structure (no queue slot, no floating queue) and this branch's content: the Queued header, Steering vs Queued, the steer landed state and the readable two-line rows. Catalog rebuilt from base text plus this branch's six keys; strings regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo
added a commit
that referenced
this pull request
Oct 14, 2026
Since #20521 the queue sits in the composer form, under the pull request bar and over the location strip; the tests still wanted it above the bar. The steer test waits for the composer to empty after each Enter: the prompt stays until the host takes it, which can land after its row draws. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Leo saw the queued prompts drawn over the pull request dock and clipped. The queue was laid over the transcript's foot with absolute positioning, at a fixed offset above the card, so anything else above the composer collided with it.
Now everything under the transcript is one bottom stack in the layout flow (
bottomStack.css). From top to bottom:How it behaves:
The queue's published height (
--acpmux-queue-space, its ResizeObserver and its JSDOM test) is removed. The flow itself now keeps the question above the queue clear (hq #1893). The new browser test covers that case.This is the slot op-next-steering's queue/steer panel (#20391) plugs into, and the PR + subagent strip will join it next.
#20454 landed (e2a6fac). This branch takes base's strip and keeps only the bottom stack: the red test (07e8841) and the fix (f4675cf), replayed on 590d535.
Testing
agent-pane-bottom-stack.test.ts, run withCMUX_BROWSER_TESTS=1 bun test. Fixture: a running chat with a permission question, three PRs and six queued prompts. It checks for no overlap, no clipping and nothing over the transcript at 900×760; at 900×480 the transcript must also stay ≥96px and the queue must scroll.bun run checkpasses.subtle-elevationon.lg-sheet, is base's (e111f3f in home-channels/ledger.css).Recording
Before/after, recorded headless in Chromium from the bottom-stack test's fixture (the pane's dev entry and a stand-in acpmux daemon): 900×760, then the pane shrinks to 480. The native app recording is blocked on this host (the window is occluded). I watched both recordings frame by frame.
Files on big-red:/tmp/cg-lane-adopt-dogfood/bottom-stack/:
bottom-stack-before-after.mp4(side by side) and{before,after}-{tall-760,short-480}.png.Changelog
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Makes the agent chat's bottom area under the transcript one flow stack, so queued prompts no longer draw over the pull request dock or clip in short panes.
The stack runs: question waiting for an answer, notices, PR dock, then inside the composer the queued prompts, location strip and card. Every part takes its own height; in a short pane the transcript shrinks first (down to 96 px), then the dock and queue collapse to one scrolling row. The queue's published-height mechanism (
--acpmux-queue-space) and its JSDOM test are gone, replaced by a browser test that checks nothing overlaps or clips.Written for commit 2ce21bd. Summary will update on new commits.