Repository navigation
fix(picker): #69 のマージ後レビュー指摘への対応と 0.24.0 への bump - #70
Conversation
…the cap bounds The cap on the hover's description was documented as keeping a tooltip from being the size of a file, which it did not: it counted Characters (one letter under a thousand combining marks passed), trimmed before cutting (so padding could push a 280-character description over, and a cut could leave a gap before the ellipsis) and re-read the whole text on every keystroke. It now counts Unicode scalars, reads only the start of the text, ends in the ellipsis only when more than whitespace follows the cut, and the comment, README and ARCHITECTURE say that it bounds the description alone.
…ts entry carries help(of:) already ignored a broken package's description, but artwork(of:) relied on the catalog never handing one a thumbnail, and its test used a fixture that had none. It now gates on availability itself and the test gives the broken entry a thumbnail. A description-only listing is now pinned as a new state at the UseCase and as a new hover at the Presenter, as a picture-only one already was.
… and to pixels-not-points EffectThumbnailDecodingTests decoded only synthetic 8-bit grey bitmaps and cut a picture inside its header. They now also decode Examples/Ripple.lens/thumbnail.png (256 x 256, RGB) and check that it is not one flat colour, check that a solid colour comes back as that colour in both formats, pin that a zero-size PNG is nil, and judge the 2048 x 2048 limit by pixels with a picture whose points are half its pixels. The truncation test says what it pins (a cut inside the header); a cut inside the pixel data decodes to a partly drawn image on this OS, which is recorded in the suite and in ARCHITECTURE rather than held to. The decoder comment gives the measured cost of an over-limit file.
…here the Router holds a decode ARCHITECTURE quoted a 1.7 MB PNG as the case the 2048 x 2048 limit guards against, which the catalog's 1 MiB limit would refuse first; it now quotes a 15 000 x 15 000 PNG of 982 742 bytes with its measured open and draw costs. The Known limits paragraph said a thumbnail is small and that the decode repeats on every body pass; it now gives the counted behaviour (once per built cell) and the real worst case, and ImageIO is stated as a choice and not as an import-list rule. A picture cut off inside its pixel data decodes partly and is written down as such, and that an undecodable or over-limit picture is not logged is stated in README and ARCHITECTURE. The Router row of architecture-boundaries.md, the chain note in CLAUDE.md, AGENTS.md, the Entity comment and the Package.swift label now name the picker's thumbnail decode and its pixel limit, and Lane 1 gets the command that makes its corrupt-PNG file.
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 46 minutes. View limit details
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
There was a problem hiding this comment.
🟡 Changes recommended
Two active issues remain: an integer-overflow crash is possible when validating untrusted thumbnail dimensions, and description matching can still scan unbounded whitespace-padded suffixes.
2 open issues
What changed in this PR
This follow-up addresses post-merge review findings from #69, improves effect-picker descriptions and thumbnail handling, expands regression coverage, updates documentation, and bumps the version to 0.24.0.
Changes:
- Truncates descriptions by Unicode scalar count while preserving full names and authors.
- Restricts thumbnail artwork to ready entries and expands decoder/catalog test coverage.
- Synchronizes architecture, testing, and verification documentation.
- Updates
version.txtfrom0.23.0to0.24.0. - Open findings remain around overflow-safe pixel-limit handling and unbounded whitespace scanning.
This pull request requires changes.
| File | Summary |
|---|---|
version.txt |
Bumps the version to 0.24.0. |
Tests/PresentersTests/EffectPickerPresenterTests.swift |
Adds coverage for description trimming, scalar limits, updates, and broken-entry artwork. |
Tests/PresentersTests/EffectArtworkResolutionTests.swift |
Clarifies the resolver test name and no-memory behavior. |
Tests/EffectCatalogUseCaseTests/EffectCatalogThumbnailTests.swift |
Verifies description-only catalog updates publish state without preparation. |
Tests/AppRouterTests/EffectThumbnailDecodingTests.swift |
Expands coverage for bundled artwork, colors, zero-size images, and pixel limits. |
Sources/Presenters/EffectPickerText.swift |
Applies ready-state artwork checks and scalar-based description formatting; an unbounded suffix scan remains under review. |
Sources/Entity/EffectThumbnail.swift |
Updates thumbnail decoding and fallback documentation. |
Sources/AppRouter/EffectThumbnailDecoding.swift |
Documents decoder behavior and pixel limits; overflow-safe dimension multiplication remains required. |
README.md |
Updates description and thumbnail behavior documentation. |
Package.swift |
Updates the AppRouter responsibility comment. |
docs/ARCHITECTURE.md |
Synchronizes picker, decoder, testing, and architecture documentation. |
AGENTS.md |
Updates guidance for thumbnail limits and decoder placement. |
.claude/rules/testing.md |
Documents the bundled-thumbnail decoder fixture. |
.claude/rules/dev-verification.md |
Adds malformed-thumbnail verification instructions. |
.claude/rules/architecture-boundaries.md |
Documents the AppRouter thumbnail-decoding responsibility. |
.claude/CLAUDE.md |
Updates the architecture chain to include picker thumbnail decoding. |
Review effort: Lite
| /// thumbnail over the limit is not drawn and the cell draws its tile. Counted in pixels, not in | ||
| /// points: a Retina export says it is half as wide as it is. |
| let content = description.unicodeScalars.drop { $0.properties.isWhitespace } | ||
| let head = String(Substring(content.prefix(helpDescriptionLimit))).trimmingCharacters(in: .whitespacesAndNewlines) | ||
| guard !head.isEmpty else { return nil } | ||
| return content.dropFirst(helpDescriptionLimit).contains { !$0.properties.isWhitespace } ? head + "…" : head |
There was a problem hiding this comment.
ご指摘のとおり、切り口のあとの空白を最後まで読むで、コメントの「先頭だけを読む」と食い違っていました。切り口のあと 280 スカラーまでしか見ないようにしました(b39fd97)。長い空白の隙間のあとの文章は、省略記号なしで隠れます。この
はコメント・ARCHITECTURE・
の 1 ケースに書きました。
一方、を Presenter に届く
に切る案は採っていません。
は
の方針なので Presenter に置き、カタ
の値は manifest のまま渡す、という #69 の
を変えないためです。また、本文の
にある空白は、読み飛ばさないと本文が隠れてしまうため、引き続き読み飛ばします。
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
pixelsWide * pixelsHigh traps in Swift when a header claims sides near UInt32.max, so a crafted thumbnail could crash the picker instead of drawing the tile. The limit is now width <= maxPixels / height, with zero sides refused in the same guard.
The ellipsis check scanned the rest of the description until a non-whitespace scalar, so a description padded with whitespace after the cut was read through on every keystroke. It now looks at no more than 280 scalars past the cut, which the comment, ARCHITECTURE and a test case state, including that a longer gap hides what follows it without an ellipsis.


Follow-up of #69
NSBitmapImageRepのfeat:の feat(picker): ピッカーのセルにマニフェストのサムネイルを描き、ホバーに説明を加える #69 が上げ損ねた minor を0.24.0として上げます(chore(release)の 1 コミット)。Character数で数え(artwork(of:)が可用性を見ていなかった(nit、7d8ea69):help(of:)は broken のavailability == .readyを見るようにし、EffectCatalogThumbnailTests)と Presenter(ホバーが変わる)の両方で固定しました。Examples/Ripple.lens/thumbnail.png(256 × 256 RGB)を実際にデコードして一色でないことをnilであること、解像度(pt)が半分の画像でも画素数でnil)を足しました。「途中で切れた」testing.mdの読み取り例外に、2 つ目の読み手としてEffectThumbnailDecodingTestsを明記しました。architecture-boundaries.mdの Router 行、.claude/CLAUDE.mdのチェーン注記、AGENTS.md(2048 × 2048 のEffectThumbnailのコメント、Package.swiftの Router 行を、printfコマンドを足しました。EffectArtworkResolutionTests.nothingIsRememberedはキャッシュの有無を約束するように読めたので、「リゾルバは何も覚えない」という意味の名前に直しました(ee92e9e)。pixelsWide * pixelsHighは、ヘッダがUInt32.max近い辺を宣言するとトラップするので、積を使わずwidth <= maxPixels / heightで判定し、0 の辺もversion.txtを 0.23.0 から 0.24.0 に上げました(chore(release))。NSHostingViewにデコーダの代わりのカウンタを置き、絵のあるセル 9 つ + タイルのセル 2 つで数えたところ、最初の描画が 9 回、LazyVGridから出入りしたときや画像が変わったとき)だけです。コストが見えていないものに、キャッシュか第二の経路を足さないことにしました。ARCHITECTURE の Known limits に、数えたNSBitmapImageRep(data:)が先にデコードしているからarchitecture-boundaries.mdなどに明記)を採っています。NSBitmapImageRepがnilを返すので、nilにする(should-fix): 切れた位置から先が黒や灰で描かれるIENDなら確実ですが、JPEG は終端マーカーのあとに余りがあっても.claude/CLAUDE.mdの「SwiftUI の view body は unit test しない」というルールを変えるmaxPixelsの判定とそのb39fd97でローカルのゲートを通しました(gate.py、全段testは 1 回、無関係なMach loopbackのa failed register gives back the receive right it allocated(プロセス内の受信権の増減を数えるmake testの再実行とゲートの通し直しはどちらも通っています。format: PASS(lint: PASS/check: PASS/build: PASS/build-dev-harness: PASStest: PASS—Test run with 1052 tests in 139 suites passed ... with 12 known issues(12 件は main に元からある既知の issue で、このtest-gpu: PASS—Test run with 27 tests in 6 suites passedEffectPickerPresenterTests(余白 3 通り、EffectCatalogThumbnailTests(EffectThumbnailDecodingTests(NSBitmapImageRepの