fix(ios): guest removal actually clears the composer chip#7
Merged
Conversation
The X on the iOS guest chip never removed the guest. Two compounding causes: 1. removeGuestParticipant marks the guest CHILD chat lifecycleState:'closed' (it is not deleted), but the projection never sent the lifecycle, and the phone detects the active guest purely from that child card (isGuestSideChat). So the closed child kept satisfying the detector and the chip lingered. 2. The inline X was an 8pt glyph with no frame (~8x8pt hit area, well under the 44pt minimum), so taps usually missed — the user fell back to re-picking a provider, which made the guest agent acknowledge the change without removing it (the "ensemble participant change" they saw). Fix: - Mac: project sideChatLifecycleState on the task card. - iOS: RemoteTaskCard.sideChatIsActive (absent => active, back-compat); guestParticipant(of:) now requires isGuestSideChat && sideChatIsActive, so a removed guest drops out and the chip clears. - iOS UX: give the X a 22pt hit target + a11y label, and add a destructive "Remove guest" item to the provider/model picker menu (per the user's suggestion) as a reliable, discoverable removal path. Tests: RemoteTaskProjection projects active/closed lifecycle; new GuestCardLifecycleTests pins the decode + sideChatIsActive predicate (active/closed/terminated/absent). Needs both a Mac release (projection) and an iOS build to take effect end-to-end. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
boggspa
added a commit
that referenced
this pull request
Jun 18, 2026
Build 22 = merged iOS batch: - PR #6: compact idle composer (collapses to a one-line text + send + model pill per shell when not typing/empty; expands on focus or content). - PR #7: guest removal actually clears the composer chip (Mac projects sideChatLifecycleState; iOS filters closed guests; bigger X hit target + "Remove guest" picker item). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
boggspa
added a commit
that referenced
this pull request
Jun 23, 2026
…lassified Roadmap #7. In tool-capable turns shouldReleaseOllamaContentDelta gated every release on `streamed.length + pending.length >= 24 || sentence-end`. Because the threshold is relative to total visible length, a short released sentence keeps resetting it, so prose was re-buffered ~24 chars after every short sentence — the source of Ollama's uniquely choppy cadence. Once prose has begun streaming (streamed non-empty, having passed the unchanged hold-guard that vets the cumulative content on every chunk), the turn is classified as ordinary assistant text, so release per token. The first-exposure length/ sentence gate and the JSON/tool-stub hold-guard are preserved. Exports the gate and adds focused unit tests, including the per-token regression that fails under the old re-buffering behavior. Co-Authored-By: Claude Opus 4.8 <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.
The bug
On iOS, tapping the X on the guest chip (or trying to remove the guest at all) didn't work — the guest agent would acknowledge a change in its child chat (the "ensemble participant change" the user saw) but the guest was never removed.
Root cause (two compounding issues)
removeGuestParticipantclears the parent'sguestParticipantand marks the guest child chatlifecycleState: 'closed'— it does not delete it (store/index.ts). But iOS detects the active guest purely from that child card (isGuestSideChat, Models.swift), and the projection never sent the lifecycle. So the closed child kept satisfying the detector → the chip lingered..frame/.contentShape→ ~8×8pt hit area (HIG minimum is 44pt). Taps missed, so the user fell back to re-picking a provider in the menu, which re-ransetGuestParticipantand made the guest agent acknowledge the change — without removing it.Fix
RemoteTaskProjection.ts): projectsideChatLifecycleStateon the task card.Models.swift,RemoteSessionModel.swift): addRemoteTaskCard.sideChatIsActive(absent ⇒ active, back-compat with older Mac builds);guestParticipant(of:)now requiresisGuestSideChat && sideChatIsActive, so a removed guest drops out and the chip clears. The child stays labelled "Guest" in the Side-chats history.TWSharedViews.swift): give the X a real 22pt hit target + accessibility label, and add a destructive "Remove guest" item to the provider/model picker menu (the user's suggestion) as a reliable, discoverable removal path.Tests
RemoteTaskProjection.test.ts: projects active and closed lifecycle.GuestCardLifecycleTests.swift: pins the decode +sideChatIsActivepredicate (active / closed / terminated / absent).Verification
typecheck✓ ·RemoteTaskProjection.test.ts12/12 ✓swift build✓ ·swift test73/73 ✓ · simulator app-target build BUILD SUCCEEDED ✓Rollout note
Takes effect end-to-end only once both a Mac release (the projection) and an iOS build (the detector/UX) ship — same as the turn-based guest fix. The "Remove guest" menu item + bigger X tap target work on the iOS build alone; the chip actually clearing needs the Mac side too.
🤖 Generated with Claude Code