Repository navigation
cmux-next iOS lists: follow-ups from the #27664 reviews - #30681
Conversation
…s (red) - SentAttachmentThumbnailsTests.twoVeryTallImagesSettleUnderTheBound: two 600x9000 images under the 32 MB bound evict each other and re-decode forever. - AgentCardPictureTests.anEvictedThumbnailIsDecodedOnceThenTheCardIsDrawn: a thumbnail the card already had is decoded again when the cache lets it go while the card waits. - NativeRowFoldTests.aNativeRowKeepsTheHeightItsCellMeasured: a native cell's measurement is dropped (no ChatRowAttributes.shown). - NativeRowFoldTests.anotherRowsGrowthIsKeptWhileADisclosureIsPending: every row's measurement is dropped while any disclosure change is pending. - aRowsHeightForAStateIsTheOneItSettledAt now requires a kept height. Test hooks only (SentAttachmentThumbnails.evict(attachmentID:), AgentCardRasterizer.frame internal); no behavior change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Very tall images: a thumbnail scaled only its short side, so a 1290x20000 screenshot kept 600x9300 px (~22 MB); two in a card's last turns passed the 32 MB bound, each landing evicted the other and the rasterizer re-queued and re-decoded them on every frame. A thumbnail now also cuts its long side to the middle 2x side its fill frame shows (600x1200, 2.9 MB), and the rasterizer holds the thumbnails a waiting card already has (AgentChatPreview.PictureHold) and lends them to the cache while it draws, so an eviction cannot race the draw and the bubble's own .task (started by ImageRenderer) does not decode them again. - Native-cell measurements: ChatNativeRowCell's sizing pass returned attributes without ChatRowAttributes.shown, so the layout dropped every native measurement and a non-exact native row fell back to its estimate. The native cell carries the state it was configured with, as ChatRowCell does. - measuresSettle is per row: while a disclosure change waits for the list's reload, only rows whose disclosures (ChatRowLookup.fold) it moves are held; other rows' growth (a streaming answer) is kept. Red (0139cca) / green (this commit), aws-m4pro-6, iOS simulator cmux-listperf-1: xcodebuild test -scheme CmuxMobileKit-Package -only-testing:CmuxMobileAgentChatTests/SentAttachmentThumbnailsTests -only-testing:CmuxMobileAgentChatTests/NativeRowFoldTests -only-testing:CmuxMobileWorkspacesTests/AgentCardPictureTests red: twoVeryTallImagesSettleUnderTheBound (decodes 62 -> 82, 21.6 MB kept), anEvictedThumbnailIsDecodedOnceThenTheCardIsDrawn (2 decodes), aNativeRowKeepsTheHeightItsCellMeasured (nothing kept, back to estimate -30 pt), anotherRowsGrowthIsKeptWhileADisclosureIsPending (growth dropped); green: all 16 pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ve measurements From the correctness review of ac20cd3: - The hold is a reference (AgentChatPreview.PictureHold / SentAttachmentHold), so the cache can fill it (next commit); a test that a waiting picture keeps what is decoded for it (aWaitingPictureHoldsWhatIsDecodedForIt, red here: 3 decodes). - A card whose key no longer needs drawing drops its hold (it pinned up to its thumbnails until the tab closed). - A thumbnail whose scaled copy could not be made draws the whole image scaled into its crop, not a zoomed-in middle. - A native cell keeps its measurement only at the width its layout was made for, always returns it with the state it drew, and a reused cell clears its state before a configure that may return early. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A waiting card's hold took a thumbnail only on the card's next turn in the rasterizer's queue; with many image cards waiting, the byte bound could let a fresh decode go before then, and it was decoded again (the eviction ping-pong at queue scale, review of ac20cd3 P2). SentAttachmentThumbnails registers a hold for each decode it waits on and fills it when the decode lands. Red (previous commit) / green (this commit), aws-m4pro-6, iOS simulator: xcodebuild test -only-testing:CmuxMobileAgentChatTests/SentAttachmentThumbnailsTests aWaitingPictureHoldsWhatIsDecodedForIt: red (not resident, 3 decodes) -> green. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Shipped in:
|
This comment has been minimized.
This comment has been minimized.
…et go when the grid moves Review of #30681 (P2): every waiting card held the thumbnails it had until its picture was drawn, outside the cache's 32 MB bound and after the grid moved or hid (about 175 MB with 30 cards waiting), with no release on a memory warning. The card waiting now stays first in the queue until its decodes land, so only one card holds (at most six cropped thumbnails); the hold is let go when the grid stops resting, on a memory warning, when the card is dropped or undrawable. Also: the decode-count test counts decodes for its own attachments only (SentAttachmentThumbnails.decodes(attachmentID:)), so another suite sharing the cache cannot move it, and its ids are unique per run (it failed 1 of 3 iterations when a previous iteration's settled keys were reused). Tests (iOS 26.5 simulator, aws-m4pro-6): new onlyTheCardWaitingHoldsAndAMovingGridOrMemoryWarningLetsGo (does not compile without the change: no single hold existed); AgentCardPictureTests and SentAttachmentThumbnailsTests -test-iterations 5 all green; full CmuxMobileKit-Package suite green. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot needs on-demand usage enabledBugbot 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. |
|
Review (Claude subagents, read-only, correctness first): SHIP at 6758f50.
iOS 26.5 simulator (aws-m4pro-6): full CmuxMobileKit-Package suite green; AgentCardPictureTests and SentAttachmentThumbnailsTests 5/5 iterations. |
|
Merge service note: this PR has The red |
|
Review (claude-lead-review-subagent): SHIP at 6758f50 Read-only review of the diff from merge-base d9d62ba to 6758f50 (9 files). I did not build or run anything. Correctness came first, then the CLAUDE.md rules. Checked and found correct:
Non-blocking notes (P3):
Checks: the only reds are |
Summary
Follow-ups left by the reviews of #27664 (landed as 5e4c938), in the cmux-next iOS chat transcript and agent tab cards.
SentAttachments.fillscaled only the short side, so a 1290x20000 screenshot kept a 600x9300 thumbnail (about 22 MB). A card whose last turns carried two of them passed the 32 MB bound, each landing evicted the other,resident()never held for both, andAgentCardRasterizer.framere-queued and decoded again at 60 Hz.2 x sidethat its fill frame shows (SentAttachments.thumbnail): 600x1200 px, 2.9 MB.AgentChatPreview.PictureHold) and lends them to the cache while it draws, so an eviction cannot race the draw..task, whichImageRendererstarts during the draw, finds the lent thumbnail and does not decode it again.ChatNativeRowCell.preferredLayoutAttributesFittingreturned attributes withoutChatRowAttributes.shown, and the layout keeps only measurements that carry it. A native row that is not exact went back to its estimate on the next change above it. The native cell now carries the state it was configured with, and keeps a measurement only at the width its layout was made for.aRowsHeightForAStateIsTheOneItSettledAtnow requires a kept height (knownHeight != nil) for both the open and closed states, so it fails if measurements are dropped.measuresSettleis per row. While a disclosure change waits for the list's reload, only rows whose disclosures (ChatRowLookup.fold) it moves are held. Another row's growth, such as a streaming answer, is kept.Fixes, tests, red/green
Command for every red/green below (aws-m4pro-6, simulator
cmux-listperf-1, Xcode 26.6):xcodebuild test -scheme CmuxMobileKit-Package -destination "id=<cmux-listperf-1>,arch=arm64" -enableCodeCoverage NO CODE_SIGNING_ALLOWED=NO -only-testing:CmuxMobileAgentChatTests/SentAttachmentThumbnailsTests -only-testing:CmuxMobileAgentChatTests/NativeRowFoldTests -only-testing:CmuxMobileWorkspacesTests/AgentCardPictureTestsRed commit 0139cca holds the tests only (plus test hooks:
SentAttachmentThumbnails.evict(attachmentID:), andAgentCardRasterizer.framemade internal).SentAttachmentThumbnailsTests.twoVeryTallImagesSettleUnderTheBound(two 600x9000 images, 32 MB bound)AgentCardPictureTests.anEvictedThumbnailIsDecodedOnceThenTheCardIsDrawnSentAttachmentThumbnailsTests.aWaitingPictureHoldsWhatIsDecodedForItNativeRowFoldTests.aNativeRowKeepsTheHeightItsCellMeasuredNativeRowFoldTests.aRowsHeightForAStateIsTheOneItSettledAt(strengthened)NativeRowFoldTests.anotherRowsGrowthIsKeptWhileADisclosureIsPendingThe review subagent's P3s are fixed in d11d586:
shownbefore a configure that may return early.Testing
CmuxMobileKit-Packagesuite at ee1dc9c, aws-m4pro-6: TEST SUCCEEDED. 1,904 Swift Testing tests in 13 test runs, all passed.swift testin CmuxMobileKit at ee1dc9c, aws-m4pro-5: 1,598 tests, 4 failures. All 4 are the known host-onlyPreviewInsufficientSpacefailures (LinkFilePreviewStreamTests x3, TerminalFloodTests x1); nothing else failed.python3 scripts/cmux-next/prepush-gate.py: no new violations.Observed / Not run
lentcheck inSentAttachmentThumbnails.startis dead because the bubble's.taskruns after the draw. A diagnostic run showed otherwise: the decode started insideImageRenderer's synchronous draw (2 decodes at draw time). The check is what turnsanEvictedThumbnailIsDecodedOnceThenTheCardIsDrawngreen, so it stays.AgentCardPictureTestsusesSentAttachmentThumbnails.shared. Its decode-count assertion could be disturbed by another suite decoding into the shared cache at the same moment; its suite is.serialized, and it passed in every run here.No capture: no visible change apart from tall images in agent cards no longer re-decoding. The thumbnails draw the same pixels: the crop keeps everything the bubble's fill frame shows.
Changelog
Fixed: an agent tab card showing two very tall screenshots no longer re-decodes its images in a loop.
🤖 Generated with Claude Code