Skip to content

fix(solo): keep the composer caret in the prose - #1310

Merged
baxen merged 2 commits into
mainfrom
mbot/solo-mention-cursor
Oct 18, 2026
Merged

baxen merged 2 commits into
mainfrom
mbot/solo-mention-cursor

Conversation

@baxen

@baxen baxen commented Oct 18, 2026

Copy link
Copy Markdown
Collaborator

Fixes two Solo composer caret bugs from the Solo TODO list.

Mention menu put the tag at the end. In a Solo chat, choosing an agent from the composer's bottom-left mention menu inserted the tag at the caret. After typing, the caret is at the end of the draft, so a draft like alpha draft became alpha draft@Owned Honey . In Solo chats the menu now adds the tag after the draft's leading tags (@Owned Honey alpha draft, or @Honey @Brain first when a tag is already there). The caret stays where it was in the prose. A rejected insert restores the caret.

Unchanged:

  • Inline @ completion still inserts at the caret.
  • Non-Solo conversations still insert at the caret.
  • Message edits still insert at the caret.

Returning to New chat put the caret at 0. The New chat view's focus request focused the restored draft without setting a selection, so the caret landed before the default tag. It now goes to the end of the draft. Existing chats already did this through the composer's autofocus.

Tests

  • New browser test in tests/browser/solo-chats.spec.mjs ("Solo composer caret") covers both bugs. It passes on Chromium and WebKit, and fails when either fix is reverted.
  • In MessageComposer.test.tsx, the "resolves a sole Solo chat agent" case expected a menu-picked tag at the end of Keep going . It now expects it at the front.
  • Full Vitest run is green (10101 passed).
  • 246 browser tests in the picker, Solo and composer specs pass on Chromium and WebKit.
  • Independent agent review ran. I fixed its two findings: caret restore on a rejected insert, and keeping edit mode on the caret path.

Human test

  1. In New chat, type xyz after the default tag, then open another Solo chat. Return to New chat: the caret should be after xyz.
  2. In an existing Solo chat, type some text and pick an agent from the bottom-left @ menu. The tag should appear at the start of the draft, and further typing should continue at the end.

🤖 Generated with Claude Code

Two Solo composer caret bugs:

- Picking an agent from the composer's mention menu inserted the tag at
  the caret, which after typing is the end of the draft (or wherever a
  restored caret happened to sit). In Solo chats the menu now adds the tag
  after the draft's leading tags and leaves the caret where it was in the
  prose. Inline @ completion still inserts at the caret, other
  conversations are unchanged, and message edits keep the caret path.
- Returning to New chat focused the restored draft with the caret at 0,
  before its default tag. The focus request now puts the caret at the end.

Co-authored-by: mbot <3754f8729004d95654c46dbab3129e4ab9ef05cc2534e2a3fbfc155983bd637b@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Bradley Axen <baxen@squareup.com>
@baxen
baxen marked this pull request as ready for review October 18, 2026 04:55
@baxen
baxen requested a review from a team as a code owner October 18, 2026 04:55
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-18T04:59:24.514409Z 301e5d7 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 301e5d77a2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}
const from = input.current?.selectionStart ?? before.text.length;
const to = input.current?.selectionEnd ?? from;
if (!add({ start, end: start, query: "" })) {

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 Badge Keep mention undo anchored in the prose

When a Solo user picks an agent while the caret is in existing prose, this ranged insertion calls EditableInput.insertText with its default focus=true, which first moves the editor selection to the leading-tag insertion point. The later setSelectionRange restores only the live selection, not the selection bookmark stored in ProseMirror's undo history, so undoing the added tag moves the caret to the beginning of the draft; subsequent typing can then land before the prose. Preserve/map the original selection in the insertion transaction, such as by using the input's automatic-edit (focus=false) path, so undo also restores the prose caret.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤖 Fixed in b1040c4: Solo picks now insert through the non-focusing path, so the insertion maps the caret and history keeps the pre-edit prose caret; the editor is focused afterwards. Applies to single and team picks. The "Solo composer caret" browser case now does Undo-then-type (alpha draft| → pick → Undo → caret 11 → alpha draft!); it fails on the previous head with caret 0 in WebKit.

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 Star Lord’s automated source review via Wes’s account.

Reviewed head 301e5d77a23a2eae9fa29d837cd98408b7b2966a against base dc305c9e3bff304719cde2d06994a4c163c096db.

One P2 correctness finding; 8/10 against the repository’s review bar. The inline finding concerns Undo’s caret restoration and corroborates the existing Codex review. No additional actionable defects found in the four-file change, supported callers, admission/rejection paths or draft-focus lifecycle. Rocket, Mantis and Groot completed independent source-review lanes; Star Lord reconciled them.

The implementation remains narrowly scoped and reuses the composer/editor owners. Returning to New chat, ordinary successful picker insertion, inline completion and edit-mode scope are consistent in source. The new browser case has a valid native-selection purpose, but does not cover Undo-then-type. The public PR description and commit message were inspected; no attached images or disclosure findings.

Validation: source analysis only, including the pinned prosemirror-history 1.5.0 bookmark implementation; no PR code, tests, builds or app launches executed. One hosted-check snapshot showed WebKit 7/9 still running, Windows skipped and the other listed checks successful. Browser/native caret behavior, IME, screen-reader announcements, rendered themes/viewports/enlarged text and human acceptance remain unverified. This is a non-blocking COMMENT review, not approval.

}
const from = input.current?.selectionStart ?? before.text.length;
const to = input.current?.selectionEnd ?? from;
if (!add({ start, end: start, query: "" })) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 [P2] Preserve the prose selection in Undo history

With the caret at alpha draft|, picking Honey produces @Honey alpha draft|, but Undo restores |alpha draft: the next typed characters land before the prose. This call supplies a prefix range to EditableInput.insert, whose default focusing path dispatches setRange before the document change (EditableInput.tsx:516,531). That new history event therefore saves the prefix selection. Restoring the live selection below cannot replace its saved bookmark: prosemirror-history 1.5.0 records the pre-edit selection and ignores selection-only transactions for that purpose.

Keep the original selection until the insertion transaction maps it (the adapter already supports non-focusing ranged insertion), then explicitly restore editor focus after a successful pick. Apply this to individual and team picks, and add an Undo-then-type caret regression. This independently corroborates the existing Codex finding; the scenario is established from source, not a runtime reproduction.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤖 Fixed in b1040c4: Solo picks now insert through the non-focusing path, so the insertion maps the caret and history keeps the pre-edit prose caret; the editor is focused afterwards. Applies to single and team picks. The "Solo composer caret" browser case now does Undo-then-type (alpha draft| → pick → Undo → caret 11 → alpha draft!); it fails on the previous head with caret 0 in WebKit.

A Solo pick moved the selection to the leading-tag insertion point before
inserting, so the history event saved that point: Undo put the caret at
the front of the draft and later typing landed before the prose. Insert
through the non-focusing path, which maps the caret through the insertion
and leaves the pre-edit caret in history, then focus the editor.

Co-authored-by: mbot <3754f8729004d95654c46dbab3129e4ab9ef05cc2534e2a3fbfc155983bd637b@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Bradley Axen <baxen@squareup.com>

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 Star Lord’s automated source review via Wes’s account.

Reviewed head b1040c4c597b8e3e0b45aab6e237e6f2438d5d26 against base dc305c9e3bff304719cde2d06994a4c163c096db, focusing on the repair since previously reviewed 301e5d77a23a2eae9fa29d837cd98408b7b2966a.

No actionable findings; 9/10 against the repository’s review bar. The prior Undo-caret P2 is addressed in source. Both Solo picker paths reuse the editor’s non-focusing ranged insertion, which maps the prose selection while preserving the pre-edit selection for Undo; successful picks then restore editor focus. Rejected insertions leave the draft and selection intact. Inline completion, non-Solo composition and message editing retain their existing paths. The added Undo-then-type assertion covers the reported failure and belongs at the browser layer because it exercises native selection and popup focus handoffs.

Rocket, Mantis and Groot completed independent lifecycle, correctness/security and product/accessibility source lanes; Star Lord reconciled the results. Scope was the two-file follow-up and relevant four-file feature/callers, including success, rejection, cancellation and draft-navigation focus. No new lifecycle owner or adapter is introduced. The public PR description and both commit messages were inspected; no attached images or disclosure finding.

Validation: immutable source analysis and diff checks only; no PR code, tests, builds or app launches executed. A single hosted-check snapshot showed browser journeys, browser flake checks, measurements, JavaScript and Rust checks still running; Windows was skipped, and the other listed checks were successful. Full CI, browser/native caret and IME behavior, screen-reader feedback, rendered themes/viewports/enlarged text, and human acceptance remain unverified. This is a non-blocking COMMENT review, not approval.

@baxen
baxen merged commit 6b67a4c into main Oct 18, 2026
34 checks passed
@baxen
baxen deleted the mbot/solo-mention-cursor branch October 18, 2026 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants