Skip to content

Chat composer: Backspace at the prompt's start removes the last attached image - #23889

Merged
austinywang merged 8 commits into
feat-cmux-nextfrom
feat-cmux-next-chat-image-backspace
Oct 23, 2026
Merged

austinywang merged 8 commits into
feat-cmux-nextfrom
feat-cmux-next-chat-image-backspace

Conversation

@austinywang

@austinywang austinywang commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

In the agent chat composer and on the New Tab page, Backspace with the caret at the very start of the prompt now removes the last staged attachment chip (a pasted or dropped image, a file, a pasted-text chip), one per press. Before, only the chip's × removed it.

  • The check is shared: backspacedAttachment in webviews/src/agent-session/acpmux/composer/attachmentIntake.tsx.
  • Holding Backspace: a held key's auto-repeat does not remove chips, so holding Backspace to clear the text stops at the start of the prompt.
  • Formatting at the start: the chat composer asks the editor whether Backspace would do nothing there (new MarkdownFieldHandle.atStart()): an empty caret at the start of a plain first paragraph. A heading, list item or quote at the start still takes Backspace to lift itself, and the chips stay.
  • Shell mode and IME composition are unchanged.

Testing

Regression tests were committed before the fix (035e6410b7c9b953e2c263844a170131afe0faad):

  • webviews/test/composer-paste-text.test.tsx (jsdom, the real Milkdown composer).
    • Backspace at the start removes chips one per press.
    • Backspace with the caret after text, or as a key repeat, removes none.
    • Backspace at the start of a heading leaves the chips.
  • webviews/test/new-tab-paste-attachments.test.ts (browser lane, real Chromium and WebKit key presses).
    • With two pasted images, Backspace deletes the typed text first, then one image per press.

Command: cmux-ci run --class light --script scripts/ci/run-webviews-tests.sh --env CMUX_WEB_TEST_FILES=<file> [--env CMUX_BROWSER_TESTS=1] --ref <sha>

File Base (tests only, 035e641) Head (7552e7c)
composer-paste-text FAIL, 1 fail: the chip stays (step d21a02e0306bb44c6f7eab68) PASS (step 0b5b7ffdeb4ddfb057787d91)
new-tab-paste-attachments FAIL, chromium and webkit: the image stays (step 3217df91f69a352148b26d8d) PASS (step ecbaa60d31f5069b4fc6f562)

Observed / Not run

  • Ran: the two test files above on the AWS Macs, red and green. scripts/web-lint.sh and scripts/cmux-next/prepush-gate.py both pass.
  • Not run: a tagged app dogfood of the chat pane, and the full webviews suite (PR CI runs it).

No capture: a keyboard behavior change with no visual change.

Review

A correctness review subagent ran on the first version. It found that Backspace at the start of a heading or list item would remove a chip instead of lifting the block; fixed with atStart(), and covered by the heading test. It also flagged an unmounted-editor fallback that read as "at start" (atStart() returns false there) and racy negative checks in the browser test (a frame is now awaited before counting). A re-review on this head follows in a comment.

Changelog

  • Fixed: Backspace at the start of the chat prompt removes the last attached image or file, like the chip's ×.

🤖 Generated with Claude Code


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


Summary by cubic

Backspace with the caret at the very start of the prompt now removes the last staged attachment chip (a pasted or dropped image, a file, or pasted text) in the chat composer and on both New Tab templates, one per press. Previously only the chip's × removed it.

  • Shared check lives in backspacedAttachment; the chat composer uses a new MarkdownFieldHandle.atStart() so a heading, list item, or quote at the start still takes Backspace to lift itself and keeps the chips.
  • The Classic New Tab template first takes a Backspace that would undo a prefix switch (like ! to terminal), then removes the last image, which the default template removes directly.
  • A held key's auto-repeat does not remove chips, so holding Backspace to clear the prompt stops at its start.
  • Shell mode and IME composition are unchanged; regression tests cover the composer (jsdom) and New Tab (real Chromium and WebKit presses).

Written for commit f1bf9e4. Summary will update on new commits.

View guided diff Turn on auto-fix

austinywang and others added 2 commits October 21, 2026 16:53
Backspace with the caret at the start of the prompt should take back the
last staged attachment (a pasted image) in the chat composer and the New
Tab field; today only the chip's x removes it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In the chat composer and the New Tab field, Backspace with an empty caret
at the start of the prompt removes the last attachment chip, one per press,
as Claude's composer does. A held key's repeat does not, and a heading or
list item at the start still takes Backspace to lift itself
(MarkdownFieldHandle.atStart).

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

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

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

Review f1bf9e4: 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=pr23889 -f ref=feat-cmux-next-chat-image-backspace -f platform=macos -f backend_mode=local

Passes: CI passes on f1bf9e4214.

CI passes on f1bf9e4214 (run 39911740080 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.

red: cmux-next checks (god files, concurrency, crash safety, l10n); no finished base run on 3b82593 to compare; do not merge until green; see lane-rules

Tour of f1bf9e4214 (run): no media. The tour did not run: only webview code changed (7 path(s)), which the gallery advisory run checks in Linux Chromium on the pull request (its artifact holds any captures); add the media-tour-mac label, then re-add media-tour, to tour it on a Mac.

Gallery before/after for f1bf9e4: 16 states rendered, 1 images differ, 633 more touched states not rendered. Images are in the run's artifact, not on this public PR.

gh run download 39911740055 -R manaflow-ai/cmux -n gallery-advisory-23889-f1bf9e42144d5a32e8b9e235d5227353aed33770 (then read gallery-review.json)

States
State Theme Status Diff Picked by
agent-pane.composer/new-chat Apple System Colors Light unchanged 0% own ComposerBox.tsx
agent-pane.composer/new-chat Apple System Colors unchanged 0% own ComposerBox.tsx
agent-pane.composer/side-session Apple System Colors Light unchanged 0% own ComposerBox.tsx
agent-pane.composer/side-session Apple System Colors unchanged 0% own ComposerBox.tsx
agent-pane.composer/new-chat-suggest-open Apple System Colors Light unchanged 0% own ComposerBox.tsx
agent-pane.composer/new-chat-suggest-open Apple System Colors unchanged 0% own ComposerBox.tsx
agent-pane.composer/new-chat-suggest-failing Apple System Colors Light unchanged 0% own ComposerBox.tsx
agent-pane.composer/new-chat-suggest-failing Apple System Colors unchanged 0% own ComposerBox.tsx
agent-pane.composer/new-chat-suggest-draft Apple System Colors Light unchanged 0% own ComposerBox.tsx
agent-pane.composer/new-chat-suggest-draft Apple System Colors unchanged 0% own ComposerBox.tsx
agent-pane.composer/new-chat-reasoning Apple System Colors Light unchanged 0% own ComposerBox.tsx
agent-pane.composer/new-chat-reasoning Apple System Colors unchanged 0% own ComposerBox.tsx
agent-pane.composer/agent-home Apple System Colors Light unchanged 0% own ComposerBox.tsx
agent-pane.composer/agent-home Apple System Colors unchanged 0% own ComposerBox.tsx
agent-pane.composer/agent-home-path Apple System Colors changed 0% own ComposerBox.tsx
agent-pane.composer/agent-home-path Apple System Colors Light unchanged 0% own ComposerBox.tsx
agent-pane.new-tab/empty Apple System Colors Light unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/empty Apple System Colors unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/model-picker-open Apple System Colors Light unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/model-picker-open Apple System Colors unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/reasoning-chip Apple System Colors Light unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/reasoning-chip Apple System Colors unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/reasoning-chip-stage Apple System Colors Light unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/reasoning-chip-stage Apple System Colors unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/minimal-default Apple System Colors Light unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/minimal-default Apple System Colors unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/minimal-widgets Apple System Colors Light unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/minimal-widgets Apple System Colors unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/minimal-stage-foot Apple System Colors Light unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/minimal-stage-foot Apple System Colors unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/minimal-widgets-ordered Apple System Colors Light unchanged 0% own NewTabPage.tsx
agent-pane.new-tab/minimal-widgets-ordered Apple System Colors unchanged 0% own NewTabPage.tsx

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

@austinywang

Copy link
Copy Markdown
Contributor Author

Review (Claude subagent, correctness first): SHIP at 7552e7c

  • First pass: found that Backspace at the start of a heading or list item would remove a chip instead of lifting the block. Fixed with MarkdownFieldHandle.atStart(), and covered by the heading test. The other findings, also fixed: the unmounted-editor fallback, the racy negative checks in the browser test, and a test title.
  • Re-review on this head: no blocking findings. It confirmed:
    • atStart() against Milkdown's paragraph schema, including the empty-document and leading-atom cases.
    • Every implementer of the handle still type-checks (DictationField is a Pick<>).
    • The keydown order: the composer's handler runs before ProseMirror's keymap.
    • The tests are sound.
  • Low follow-ups, not blocking:
    • The heading test's title says "lifts the heading" but only asserts that the chip stays.
    • The New Tab test checks the count, not which image went (the composer test checks the order).

Tests on the AWS Macs: red at 035e641 (steps d21a02e0306bb44c6f7eab68, 3217df91f69a352148b26d8d), green at this head (steps 0b5b7ffdeb4ddfb057787d91, ecbaa60d31f5069b4fc6f562).

@austinywang austinywang added the ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds label Oct 22, 2026
@blacksmith-sh

blacksmith-sh Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Found 8 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmpe58_y_ha/summary-missing.json (live):/summary-missing.json (live): View Logs
/tmp/tmpka15wll6/summary-fail.json (live):/summary-fail.json (live): View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
test_base_passes (main.NoticesPairTests.test_base_passes)/
test_base_passes (main.NoticesPairTests.test_base_passes)
View Logs
test_targets_outside_the_app_go_to_the_mac_canary (main.SwiftCanaryFleetCoverage.te
st_targets_outside_the_app_go_to_the_mac_canary)/
test_targets_outside_the_app_go_to_the_mac_canary (main.SwiftCanaryFleetCoverage.te
st_targets_outside_the_app_go_to_the_mac_canary)
View Logs

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

@teamleaderleo

Copy link
Copy Markdown
Collaborator

Bead cx-3n3z7 created for this PR by the cmux coordinator.

@austinywang

austinywang commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor Author

CI on c142e4a (the head after the feat-cmux-next merge). This PR's diff is unchanged: the same 6 webviews files. None of these reds is caused by this change:

  • web / react-apps-check (all shards), Web status: inspector/ContextSection.css is not in the agent pane bundle script. The merged base brought it in; base fixed it in 5b32501.
  • cmux-next CI guard group:
    • "bash watcher retirement": an infra flake, the runner could not get the apt lock (/var/lib/dpkg/lock-frontend).
    • "macOS job class" and "test determinism": the guard reports both red on the base too. The determinism findings name none of this PR's files.
  • nightly-guards / release-notary: the base's restored-terminals-come-back.md highlight.

Dev build of 7552e7c (the fix before the merge): job 34a180ee0565efab82f50e95, tag 23889-chat-image-backspace.

@austinywang austinywang added ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds and removed ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds labels Oct 22, 2026
teamleaderleo and others added 2 commits October 21, 2026 18:28
…ext-chat-image-backspace

# Conflicts:
#	webviews/src/agent-session/acpmux/newtab/NewTabScreen.tsx
@cursor

cursor Bot commented Oct 22, 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.

…ext-chat-image-backspace

# Conflicts:
#	webviews/src/agent-session/acpmux/composer/attachmentIntake.tsx
#	webviews/src/agent-session/acpmux/newtab/NewTabScreen.tsx
@austinywang

Copy link
Copy Markdown
Contributor Author

Merge conflicts with feat-cmux-next resolved at 1ea70e2. Both conflicts were additive:

  • NewTabScreen.tsx imports: kept base's useSendWhenAttached and DropOverlay alongside backspacedAttachment.
  • attachmentIntake.tsx: kept base's reworded strip comment alongside backspacedAttachment.

The PR diff is still the same 6 webviews files. scripts/web-lint.sh and prepush-gate.py pass.

CI at this head:

  • web run 39726641598 is green. PASS test/composer-paste-text.test.tsx (react-apps-check 4) and PASS test/new-tab-paste-attachments.test.ts (react-apps-check 1).
  • The remaining reds are not from this PR:
    • gallery health / health (2): agent-pane.composer#steer-read-hover waitFor timeout. The same state fails on unrelated PRs at the same time (runs 39727257370, 39727391902, 39727483523).
    • cmux-next checks: namespace-type errors in base's CmuxNextDesign and CmuxNextSettings Swift, and workflow-structure assertions.
    • CI guard group, nightly-guards, rails: workflow guards, the release-notes highlight, and Rails migration tests. None touch webviews.

@austinywang austinywang added ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds and removed ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds labels Oct 22, 2026
austinywang and others added 2 commits October 22, 2026 23:18
…ext-chat-image-backspace

# Conflicts:
#	webviews/src/agent-session/acpmux/Composer.tsx
The Classic template (NewTabPage.tsx) took the Backspace chip removal in
the merge with feat-cmux-next. A prefix it switched to is undone first,
then the last image goes, one per press.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@austinywang
austinywang merged commit b9c3d5a into feat-cmux-next Oct 23, 2026
132 of 136 checks passed
@austinywang
austinywang deleted the feat-cmux-next-chat-image-backspace branch October 23, 2026 06:44
@austinywang

Copy link
Copy Markdown
Contributor Author

Merged by next-autoland at head f1bf9e4 as b9c3d5a, which is on feat-cmux-next.

Last conflict resolution:

  • Composer.tsx → ComposerBox.tsx: base extracted the composer card into ComposerBox.tsx, so the Backspace check moved into its prompt onKeyDown, ahead of the host's. It still uses MarkdownFieldHandle.atStart() and skips IME composition.
  • NewTabPage.tsx: the Classic New Tab page got the same check, after its own rule that Backspace on an empty field undoes a !/? kind prefix. The new Classic case in new-tab-paste-attachments.test.ts covers it.

Review (Claude subagent, correctness first): SHIP at bc0fff8. The only gap it raised, the missing Classic test, was added in f1bf9e4.

CI at f1bf9e4:

  • CI run 39911740080 is green. PASS test/composer-paste-text.test.tsx and PASS test/new-tab-paste-attachments.test.ts (Chromium and WebKit).
  • The remaining reds come from base: a cmux-next checks workflow-structure test and nightly-guards / release-notary.

@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/39913961585 at a62351d failed: cmux-next fast tier, cmux-next perf gate.
Those jobs last passed at 3b82593. This pull request is one of 3 merged since: #23889, #23783, #24352.
If the failure is in your change, fix forward on feat-cmux-next. Pull requests run only the tiers their paths reach (docs/ci/cmux-next-tiers.md); label a batch PR full-ci to run them all before merging.

@github-actions

Copy link
Copy Markdown
Contributor

The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/39922732738 at ab42b3c failed: cmux-next fast tier.
Those jobs last passed at 3b82593. This pull request is one of 3 merged since: #23889, #23783, #24352.
If the failure is in your change, fix forward on feat-cmux-next. Pull requests run only the tiers their paths reach (docs/ci/cmux-next-tiers.md); label a batch PR full-ci to run them all before merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants