Skip to content

fix(mobile): keep namesake requalification from dropping recipients - #9438

Closed
brow wants to merge 8 commits into
peon/mobile-namesake-mentionsfrom
fix-9325-code-binding
Closed

brow wants to merge 8 commits into
peon/mobile-namesake-mentionsfrom
fix-9325-code-binding

Conversation

@brow

@brow brow commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

Follow-up to #9325 namesake mention qualifying, targeting its branch. It fixes two recipient regressions in how picking a second same-name identity requalifies earlier mentions.

A binding beside code backticks was dropped. When a second namesake is picked, _requalifyNamesakes drops the earlier plain binding unless renameMentions reports a kept occurrence. A mention sitting directly against code backticks (`@Scout`) is not an occurrence to that matcher, so the binding was removed, while draft persistence (which ignores backticks) still treats it as present. If the user then deleted the qualified prose mention and removed the code formatting, the plain @Scout became an ambiguous unbound name and the send was rejected (or, with one Scout left in the roster, resolved by name to whoever that is). The fix keeps the plain binding for any renamed key that still has a plain occurrence under persistence's presence rule. Found by nettie (finding).

A longer typed member name lost its prefix. The rewrite only knew the selected labels, so with members Scout, Scout and Scout Leader, picking the second Scout also qualified the @Scout at the start of a typed @Scout Leader. That broke the longer mention, and Scout Leader was silently dropped from the send. Requalification now also gives the typed member labels the send resolves (same candidates, no new fetch) to the longest-occurrence walk, after the selected keys, so a longer member name keeps its occurrence; only the earlier selection's own occurrences are rewritten. Found by corey (finding).

The send path and requalification now share one member-candidate builder, which also keeps compose_bar_widget.dart under the mobile file-size limit.

Validation

  • Added tests (composer journeys, each fails without its fix):
    • a namesake selection touching code backticks stays bound after unformatting: pick, pick the namesake with `@Scout` in the draft, delete the qualified prose mention, unformat, send to both.
    • qualifying a namesake leaves a longer typed member name intact: Scout, Scout and Scout Leader roster; the earlier Scout is qualified, @Scout Leader stays as typed, and all three are sent.
  • Compose bar suite and full mobile suite pass.
  • No full-app run: the change is confined to binding bookkeeping on namesake selection and is covered end to end by the widget journeys.

kalvinnchau and others added 8 commits November 11, 2026 16:08
… casing

- selectedmentionlabel qualifies any mention whose name is shared by another
  selected identity; insertmention requalifies earlier plain namesake
  selections (map keys and draft text) when a namesake is added
- a qualified occurrence denies the plain name on render, so a lone plain
  namesake never resolved; all namesakes now carry the pubkey qualifier
- message_content pre-pass keeps the authored text of each mention range
  instead of the lowercased binding key (binding lookup lowercases itself)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Kalvin Chau <[email protected]>
selecting a second same-name identity now requalifies earlier selections too.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Kalvin Chau <[email protected]>
…dget

keeps compose_bar_widget.dart within the mobile file size ratchet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Kalvin Chau <[email protected]>
- mention-bindings: renameMentions appends the qualifier to each matched
  spelling and skips excluded spans, reporting renamed and kept keys
- compose-bar: requalification excludes inline and fenced code; a key left
  in code stays bound beside its qualified label, so its recipient still
  sends and the send-time resolver sees no ambiguous bare name
- agent-mention-prefill: qualify every same-name agent, including the first
- docs/mention-editor: describe casing, code and prefill behavior

Co-authored-by: goose-wayne <ae6b377e5b6d090ee22558d19246413a5731628a127e25371111badfd4861535@buzz.block.builderlab.xyz>
Signed-off-by: Kalvin Chau <[email protected]>
requalification skipped occurrences by independent per-rule code matches,
which paired backticks that bold or italics consume. code the editor
styled could gain a qualifier and editor prose could stay bare.

- markdown-editing-controller: _styledCodeRanges repeats the editor
  leftmost-rule walk and returns the code spans and fences it draws;
  _isInCode keeps gating link chips unchanged
- compose-bar: requalification excludes those ranges
- tests: composer journeys for fences, list fences, list spans, spans
  after bold and italics, and prose around code and list text
- docs/mention-editor: unstyled markdown code forms are qualified like
  prose

Co-authored-by: goose-wayne <ae6b377e5b6d090ee22558d19246413a5731628a127e25371111badfd4861535@buzz.block.builderlab.xyz>
Signed-off-by: Kalvin Chau <[email protected]>
keeps compose_bar_widget within the mobile file size limit; behavior is
unchanged.

Co-authored-by: goose-wayne <ae6b377e5b6d090ee22558d19246413a5731628a127e25371111badfd4861535@buzz.block.builderlab.xyz>
Signed-off-by: Kalvin Chau <[email protected]>
…icks

Requalifying namesakes dropped the earlier plain binding when its only
remaining occurrence sat directly against code backticks, because the
occurrence matcher does not see a backtick-adjacent mention. Draft
persistence still counted it, so unformatting that code later left an
ambiguous unbound name. Keep the binding using persistence's presence rule.

Signed-off-by: Tom Brow <[email protected]>
…esakes

Requalification only knew the selected labels, so picking a second Scout
also qualified the @scout prefix of a typed @scout Leader, breaking that
mention and silently dropping Scout Leader from the send. Give the typed
member labels the send resolves to the longest-occurrence walk, after the
selected keys, so only the earlier selection's own occurrences are
rewritten. The send path and requalification now share one builder.

Signed-off-by: Tom Brow <[email protected]>
@brow brow changed the title fix(mobile): keep a namesake binding whose code mention touches backticks fix(mobile): keep namesake requalification from dropping recipients Nov 13, 2026
@brow
brow marked this pull request as ready for review November 13, 2026 01:58
@brow
brow requested a review from a team as a code owner November 13, 2026 01:58
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

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

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-13T02:00:06.139988Z 289c100 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.

@kalvinnchau
kalvinnchau force-pushed the peon/mobile-namesake-mentions branch from e664a37 to fa4032d Compare November 13, 2026 02:31
@brow brow closed this Nov 13, 2026
@brow
brow deleted the fix-9325-code-binding branch November 13, 2026 02:50
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.

3 participants