Skip to content

BF-2441: iOS photo previews, drop snippet chips, show Muse Code subagents - #1742

Merged
swu-gb-deployer[bot] merged 9 commits into
mainfrom
cursor/ios-photo-chips-muse-activity-d6a2
Nov 11, 2026
Merged

swu-gb-deployer[bot] merged 9 commits into
mainfrom
cursor/ios-photo-chips-muse-activity-d6a2

Conversation

@jaywedgeworth22

@jaywedgeworth22 jaywedgeworth22 commented Nov 11, 2026 •

Copy link
Copy Markdown
Member

Issue: BF-2441.

The receipt treats the words failed and failure as Failed.  BF-2440 stays open.  A card still shows Failed when the stored outcome is false, including when the detail text says the child finished.

Kody's three findings on e3b76a76 are fixed in 4b8918dc, and the review threads are left open.  Done is only an explicit success.  Failed is only a failure or an error.  Cancelled or stopped reads as Stopped, and pending, empty, or unknown stays Running.  Composer photo chips downsample with ImageIO off the main thread.  The thumbnail cache has count and cost limits and drops an entry when the attachment leaves the strip.  A chip is suppressed for a canned title only when its prompt is empty or is one of the canned prompts.

This VM cannot run Swift.  The CompanionCore tests, the unsigned iOS build, the receipt badge, the photo chip, and the remove button were not runtime-verified here.  CI is the check for the tests and the build.

Summary

Implements BF-2441 for iOS chat composer and activity transcript.  Pending image attachments now show a photo thumbnail in the draft strip, with file or undecodable-image fallback to a system icon.  Empty-composer snippet chips that only paste a canned sentence are removed, while / slash commands are preserved.  Tool subagent child steps are shown as indented rows and kept out of folded activity runs, with run wording changed from Complete to Done.

Changes

  • Composer pending attachments add previewImageData for displayable images and render a 36pt thumbnail via PendingAttachmentGlyph with NSCache reuse.  Draft strip layout adjusts padding and minimum height.
  • Predictive chips default to empty and filter any chip matching ComposerPromptChips.isCannedSnippet, covering prior Show diff, Run tests, Explain steps and What's next prompts.  Slash-prefixed prompts are exempted.
  • Tool activity adds itemId and parentItemId to model parent-child steps.  New ToolStepStatus maps outcome to Done, Running or Failed with corresponding receipt status.  Receipt status parsing is case-insensitive and accepts in_progress and failed / failure variants.
  • Activity transcript indents child steps with a leading rule via ChildStepInset.  Running steps and child steps are excluded from folded activity runs and message-run grouping.

Tests added

Adds ComposerPromptChipsTests for canned-snippet rejection and slash-command exemption.  Adds ActivityRunsTests cases for running steps staying unfolded, child steps staying on their own row, and decoding of parent linkage and status mapping.  Adds MessageGroupingTests coverage for running and child steps staying visible.  Adds ChatAttachmentTests coverage for image preview bytes, non-displayable format, file and empty payload handling.  No test-run results, device verification, deployment or approval status is reported in the changes, so runtime behavior remains unverified.

Open review findings

The three medium findings on unknown receipt status, main-thread thumbnail decode, and title-only chip suppression are addressed in the follow-up commit.  Threads stay open until review.


BF-2441: iOS photo previews, snippet chips, and skill receipt status.

Summary

Updates iOS chat composer and skill receipts for correctness and performance. Photo attachments now render efficient thumbnails, canned prompt chips no longer hide custom prompts, and cancelled tool calls no longer read as Done.

Changes

  • Attachment photo previews: Pending image chips load downsampled thumbnails off the main thread via ImageIO and cache them with count and cost limits. Cache entries are removed when attachments are cleared, replaced, or deleted.
  • Prompt chips: A shared canned title hides a chip only when the prompt is empty. Custom prompts keep their chip, while canned snippet prompts remain hidden regardless of title.
  • Skill receipts: Status parsing moved to new SkillReceiptStatus in CompanionCore. Only success reads as Done, only error/failure reads as Failed, cancelled/canceled/stopped reads as neutral Stopped, and pending/empty/unknown stays Running. Receipt badge, icon, and border updated to match.

Tests

Added SkillReceiptStatusTests covering success, failure, stopped, and running mappings, and extended ComposerPromptChipsTests for custom prompts and empty-prompt cases. No test-run results, deployment, or runtime verification reported.

Risks / Open review findings

Automated review reported 2 medium findings, unverified as resolved: reused attachment glyph may show a stale thumbnail, and thumbnail decode work may continue after removal wasting CPU. Thumbnail cache eviction and off-main decode behavior otherwise unverified in production.


Resolves BF-2441 for iOS composer photo previews. Moves pending-attachment thumbnail caching out of ChatView into shared ComposerPendingThumbnailCache with ComposerThumbnailCachePolicy gating UI and cache updates.

Changes

  • Shows downsampled photo previews in the composer attachment strip. Clears the row image on reuse and only applies a decode when the requested attachment still matches the row and the task was not cancelled.
  • Evicts cached thumbnails when an attachment is removed from the strip and blocks late decodes from repopulating the cache after removal or cancellation. Keeps image decoding off the main thread.

Tests added

  • Adds ComposerPendingThumbnailCacheTests for chip-size downsampling, cache reuse, eviction on remove, removal during decode, and cancelled-task behavior. Adds ComposerThumbnailCachePolicyTests for stale row identity and removed-attachment store decisions. Run results were not reported in the changes, so passing status is unverified.

Open risks

  • Automated review reported 2 medium findings in ComposerPendingThumbnailCache.swift: possible race between removal check and cache store, and unbounded growth of removed-ID tracking for app lifetime. Resolution is unverified.

Summary

BF-2441 iOS composer photo preview hardening: reworks ComposerPendingThumbnailCache to correctly handle remove and re-add of pending photo attachments. Late decodes no longer repopulate thumbnails for attachments dropped from the strip, reinstated strip items can load again, and removal tombstones are pruned and capped to bound growth. Additional scope implied by the title such as snippet chips and Muse Code subagents is not visible in this diff and remains unverified.

Changes

  • ChatView.swift: after syncing pendingAttachments, prunes tombstones not in the kept set and reinstates tombstones for current strip items.
  • ComposerPendingThumbnailCache.swift: replaces simple removed-ID set with gated CacheGate tracking removedIds and in-flight decodes, with remove, reinstate, pruneTombstones, gated store, decode begin/end tracking, and tombstoneLimit of 32.
  • Preserves 36pt downsampled off-main decoding and NSCache limits while blocking cancelled or removed decodes from caching.

Tests

  • Added testReinstateLetsAThumbLoadAgainAfterReplacement, testManyRemovesStayWithinTheTombstoneCap, testPruneDropsTombstonesThatNoLongerGuardAStripId, and testDecodeCompletionClearsItsTombstone; updated testRemoveDuringDecodeDoesNotPopulateCache to race decode against removal. Test execution results were not provided in the diff and remain unverified.

Open risks

  • Automated review reported 2 medium unverified findings: cache policy check sees droppedFromStrip as false with gating moved to store, and concurrent duplicate decodes may clear in-flight state early. No resolution or runtime verification is evidenced in the diff.

Summary

Addresses BF-2441 for iOS photo previews by hardening the composer pending thumbnail cache against overlapping decodes. Consolidates the store eligibility check inside the cache gate so cancellation and strip-removal are evaluated at store time. Replaces the in-flight decode set with per-attachment reference counts so removal tombstones are retained until the last decode ends.

Changes

  • Moved ComposerThumbnailCachePolicy.shouldStoreThumbnailInCache evaluation into CacheGate.store.
  • Switched inFlightDecodes tracking to decodeCounts with updated prune, end-decode, and tombstone-cap logic.
  • Added test-only decode-count helpers.

Tests

Added testOverlappingDecodesKeepGuardsUntilTheLastOneEnds to verify tombstone retention across overlapping decodes and cleanup after the final decode. No run results, deployment, or runtime verification reported in the provided changes.


Related to BF-2441. Updates ComposerPendingThumbnailCacheTests to call inFlightDecodeCountForTests(id:) with the correct argument label. No production code is modified in the provided change, so no user-visible or operational impact is verified.


Summary

BF-2441: Fix iOS photo previews on failed-send restore. Restores outgoing pending attachments via replacePendingAttachments so thumbnail cache state is reset correctly.

Changes

  • Updated ChatView restore path to call replacePendingAttachments(outgoing) instead of direct assignment when pending attachments are empty.
  • Added testAFailedSendRestoreMustReinstateBeforeThumbnailsCache covering thumbnail regeneration after reinstate.

User impact

Pending photo attachments should show previews again after a failed send is restored. Reload behavior is unverified in the provided changes.

Tests

  • New cache regression test added; no run results reported in the changes. Successful thumbnail reload after reinstate remains unverified.

Risks

  • Open review finding (medium) in ComposerPendingThumbnailCacheTests.swift:63: restore test may clear tombstone before reinstate, giving a false pass.

Summary

Updates testAFailedSendRestoreMustReinstateBeforeThumbnailsCache in ComposerPendingThumbnailCacheTests to explicitly verify thumbnail gating for failed-send restore (BF-2441). Blocked state now asserts thumbnail(for:) returns nil with no cached entry, and restored state asserts it returns a thumbnail with a cached entry.

Impact

The provided patch changes test-only logic; user-visible impact is unverified. It tightens coverage for pending-attachment thumbnail reinstatement after a failed send.

Testing

Test logic updated as described; no test run results were reported in the provided context. Automated code review reported no issues in the reviewed changes.

Photos in the composer use the attached picture.  Chips that only paste a sentence are gone.  Child and in-progress steps stay visible when the transcript already has them.

Co-authored-by: Jay Wedgeworth <jaywedgeworth22@users.noreply.github.com>
@linear-code

linear-code Bot commented Nov 11, 2026

Copy link
Copy Markdown

BF-2441

@github-actions github-actions Bot added the ui Touches UI or UX: wakes BF-Designer label Nov 11, 2026
@kody-ai

This comment has been minimized.

Comment thread ios/App/ChatView.swift Resolved
@kody-ai

kody-ai Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Automatic approval held

Kody's assessment:

Complex iOS UI and concurrency change with unverified runtime: off-main thumbnail cache with tombstone gating has open race findings, plus receipt status and activity folding semantics in historically bug-prone files; needs human review.

@swu-gb-designer

Copy link
Copy Markdown
Contributor

[GB-DESIGNER 📁BF]
UI pass at e3b76a7: nits, not blocking, and fixes are on the way.

  • Kody's three findings stand from a UI view as well.  A cancelled or pending run must never show Done, the composer thumbnails should be downsampled off the main thread, and a custom chip shouldn't vanish just because its title matches a canned one.
  • A follow-up agent is pushing those fixes to this same branch now.  The PR stays a draft until they land and CI is green.

Done and Failed are only those outcomes.  Cancelled or stopped reads as Stopped.  Composer photos downsample off the main thread, and a canned title no longer hides a custom prompt.

Co-authored-by: Jay Wedgeworth <jaywedgeworth22@users.noreply.github.com>
@kody-ai

This comment has been minimized.

Comment thread ios/App/ChatView.swift Resolved
Comment thread ios/App/ChatView.swift Resolved
PendingAttachmentGlyph clears the chip when item.id changes and ignores decode results whose identity no longer matches the row.  ComposerPendingThumbnailCache decodes with a cancellable off-main wait, records strip removals, and skips cache writes after cancellation or removal.  CompanionCore tests cover the policy and cache.

Co-authored-by: Jay Wedgeworth <jaywedgeworth22@users.noreply.github.com>
@kody-ai

This comment has been minimized.

Dropping removedIds.clear from thumbnail load stops a remove during decode from being erased by a late task start.  reinstate runs when replacePendingAttachments keeps an id, and the decode race test yields to removal before asserting.

Co-authored-by: Jay Wedgeworth <jaywedgeworth22@users.noreply.github.com>
CacheGate holds one lock across the removal check and NSCache write. Tombstones track in-flight decodes, clear when a decode finishes, and prune with replacePendingAttachments; the cap matches twice the 16-entry image cache.

Co-authored-by: Jay Wedgeworth <jaywedgeworth22@users.noreply.github.com>
@kody-ai

This comment has been minimized.

Per-id decode refcounts keep tombstones and prune guards until the last overlapping decode ends. shouldStoreThumbnailInCache now runs inside the cache gate lock with the live tombstone set.

Co-authored-by: Jay Wedgeworth <jaywedgeworth22@users.noreply.github.com>
@kody-ai

This comment has been minimized.

Co-authored-by: Jay Wedgeworth <jaywedgeworth22@users.noreply.github.com>
@kody-ai

This comment has been minimized.

@swu-gb-deployer
swu-gb-deployer Bot marked this pull request as ready for review November 11, 2026 11:09
@github-actions

Copy link
Copy Markdown
Contributor
Autofix run https://github.com/Simple-With-Us/BotFleet/actions/runs/43009838922 started for `sentry[bot]`'s tagged request. Owner/sentry request: exempt from the per-bot cap (owner rule 2026-10-20).

Failed-send recovery now calls replacePendingAttachments(outgoing) so restored chips clear thumbnail tombstones, matching the queued-edit path.

Co-authored-by: Jay Wedgeworth <jaywedgeworth22@users.noreply.github.com>
@kody-ai

This comment has been minimized.

Re-apply remove after the tombstoned decode so endDecode cannot
substitute for reinstate before the success assertions.

Co-authored-by: Jay Wedgeworth <jaywedgeworth22@users.noreply.github.com>
@kody-ai

kody-ai Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Kody Review Complete

Great news! 🎉
No issues were found that match your current review configurations.

Keep up the excellent work! 🚀

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Validate Business Logic: Ask Kody to validate your code against business rules by adding a comment with the @kody -v business-logic command.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug ✅
Performance ✅
Security ✅
Business Logic ✅

Access your configuration settings here.

​

Automatic approval held: Complex iOS UI and concurrency change with unverified runtime: off-main thumbnail cache with tombstone gating has open race findings, plus receipt status and activity folding semantics in historically bug-prone files; needs human review.

@swu-gb-deployer
swu-gb-deployer Bot merged commit 54a4616 into main Nov 11, 2026
22 checks passed
@swu-gb-deployer
swu-gb-deployer Bot deleted the cursor/ios-photo-chips-muse-activity-d6a2 branch November 11, 2026 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ui Touches UI or UX: wakes BF-Designer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants