From cf00c7c59019cb7a91e7c72fecddd46e6eabe817 Mon Sep 17 00:00:00 2001 From: Fini Date: Sat, 9 May 2026 20:59:31 +0800 Subject: [PATCH] =?UTF-8?q?fix(ai):=20drop=20`image`=20from=20icon=20resol?= =?UTF-8?q?ver=20noise=20list=20=E2=80=94=20it's=20a=20real=20lucide=20key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: my prior C3 resolver fix added `image` to ICON_NOISE_WORDS so "Image Placeholder Path" (a non-icon container name) wouldn't collapse to a circle. That was overcorrecting — `image` is also the canonical Lucide icon key for the picture/photo glyph, and the model frequently emits "Image Icon" meaning exactly that. With image stripped, "Image Icon" tokenised to [] and the resolver returned without writing the matched lucide:image path. What: remove `image` from ICON_NOISE_WORDS, with an inline note that the multi-word "Image Placeholder Path" pattern still resolves through the prefix fallback (`image` covers >= 50% of `imageplaceholder` so findPrefixFallback picks it up). Add a regression test for "Image Icon" → /image/. 1070 / 1070 AI tests pass (was 1069; +1). --- apps/web/src/services/ai/__tests__/icon-resolver.test.ts | 6 ++++++ apps/web/src/services/ai/icon-resolver.ts | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/web/src/services/ai/__tests__/icon-resolver.test.ts b/apps/web/src/services/ai/__tests__/icon-resolver.test.ts index 4a59a1140..2ab128aff 100644 --- a/apps/web/src/services/ai/__tests__/icon-resolver.test.ts +++ b/apps/web/src/services/ai/__tests__/icon-resolver.test.ts @@ -166,6 +166,12 @@ describe('applyIconPathResolution — opt-in marker gate', () => { ['Dismiss Icon', /x/], ['Cancel Icon', /x/], ['Remove Icon', /x/], + // `image` must NOT be in the noise word list — "Image Icon" is the + // standard lucide:image lookup and the user almost certainly means + // a picture icon, not "no signal". (`Image SVG` alone has no icon + // marker word so it bypasses the resolver entirely — that's correct + // because the path could be a real SVG file ref.) + ['Image Icon', /image/], ])('resolves multi-word path name "%s" to %s', (name, expectedIconId) => { const node = makePath({ name }); applyIconPathResolution(node); diff --git a/apps/web/src/services/ai/icon-resolver.ts b/apps/web/src/services/ai/icon-resolver.ts index 3b73af9dc..3f5c2c742 100644 --- a/apps/web/src/services/ai/icon-resolver.ts +++ b/apps/web/src/services/ai/icon-resolver.ts @@ -68,7 +68,11 @@ const ICON_NOISE_WORDS = new Set([ 'fill', 'svg', 'graphic', - 'image', + // Note: `image` is INTENTIONALLY not a noise word. It's a real lucide + // icon key, and "Image Icon" / "Image SVG" should resolve to lucide:image + // — not collapse to empty after stripping. Multi-word name patterns like + // "Image Placeholder Path" still resolve via the prefix fallback (`image` + // covers >= 50% of `imageplaceholder`). ]); function tokenizeName(name: string): string[] {