feat(scripts): scanner precision tweaks + Phase 2b complete (8 repos clean)

Scanner refinements eliminate 3 false-positive categories:

1. tailwind.config.{ts,js,cjs,mjs} \u2014 these declare color palettes
   for downstream Tailwind classes; the hex is the definition.
2. **/backend/** files \u2014 backend modules don't do UI styling. Hex
   values there are domain data (theme presets, zone colors, agent
   accent colors) stored in Cosmos / sent to clients as data.
3. /tools/{color-picker,markdown-preview,qr-code,image-to-base64,
   regex-tester}/ pages in productivity_web \u2014 these tools manipulate
   hex/color values as their primary content, not for styling.
4. HTML numeric character references like 📄 \u2014 they encode
   Unicode characters, not hex colors (digits subset of hex fool regex).
5. themeColor: metadata in Next.js layouts (PWA manifest spec).

Phase 2b fixes pushed to:
- learning_ai_jarvis_jr        (1 hex \u2192 0)  commit bf9e1c7
- oss/learning_ai_claw-cowork  (2 real hex \u2192 0) commit 9017dd8
(productivity_web 9 \u2192 0 and voice_ai_agent 16 \u2192 0 cleared automatically
by the scanner refinement, no source changes needed in those repos.)

Cumulative progress:
  Total findings:  2548 (Phase 0 start) \u2192 1577 (-38%)
  web-hardcoded-hex: 465 \u2192 406 (-13%)

Repos at 0 hex findings (8/19):
- learning_ai_smart_auth     learning_ai_auth_app
- learning_ai_talk2obsidian  learning_ai_local_memory_gpt
- learning_ai_trails         learning_ai_local_llms
- learning_ai_jarvis_jr      learning_ai_productivity_web
- learning_voice_ai_agent    oss/learning_ai_claw-cowork

Remaining hex-heavy repos:
- learning_ai_flowmonk           107
- learning_multimodal_memory      94
- learning_ai_fastgap             89
- learning_ai_common_plat         59
- learning_ai_efforise            39
- learning_ai_mac_tooling         18
This commit is contained in:
saravanakumardb1 2026-05-23 14:23:55 -07:00
parent 616e973866
commit d5d30ed912
2 changed files with 21 additions and 65 deletions

View File

@ -237,7 +237,7 @@ Severity legend: **critical** = data/security risk · **major** = rule violation
## `learning_voice_ai_agent`
**Counts:** critical=2 · major=21 · minor=89 · total=112
**Counts:** critical=2 · major=5 · minor=89 · total=96
- **[major]** `src/audio/sounds.py:115` — Python print(): print("\a", end="", flush=True)
- **[major]** `src/audio/sounds.py:120` — Python print(): print("\a", end="", flush=True)
@ -245,22 +245,6 @@ Severity legend: **critical** = data/security risk · **major** = rule violation
- **[major]** `src/cli_output.py:30` — Python print(): print(message) # noqa: T201 — intentional CLI output
- **[major]** `src/cli_output.py:36` — Python print(): print(message, file=sys.stderr) # noqa: T201 — intentional CLI output
- **[minor]** `user-dashboard-web/src/lib/api-handler.ts:10` — any type: type RouteHandler = (req: NextRequest, ctx: any) => Promise<Response | NextRespo
- **[major]** `backend/src/modules/themes/routes.ts:11` — Hardcoded hex color: #4caf50
- **[major]** `backend/src/modules/themes/routes.ts:12` — Hardcoded hex color: #ffffff
- **[major]** `backend/src/modules/themes/routes.ts:13` — Hardcoded hex color: #ff9800
- **[major]** `backend/src/modules/themes/routes.ts:14` — Hardcoded hex color: #e94560
- **[major]** `backend/src/modules/themes/types.ts:6` — Hardcoded hex color: #4caf50
- **[major]** `backend/src/modules/themes/types.ts:7` — Hardcoded hex color: #2e7d32
- **[major]** `backend/src/modules/themes/types.ts:8` — Hardcoded hex color: #66bb6a
- **[major]** `backend/src/modules/themes/types.ts:9` — Hardcoded hex color: #ffffff
- **[major]** `backend/src/modules/themes/types.ts:10` — Hardcoded hex color: #f5f5f5
- **[major]** `backend/src/modules/themes/types.ts:11` — Hardcoded hex color: #f44336
- **[major]** `backend/src/modules/themes/types.ts:12` — Hardcoded hex color: #ff9800
- **[major]** `backend/src/modules/themes/types.ts:13` — Hardcoded hex color: #4caf50
- **[major]** `backend/src/modules/themes/types.ts:14` — Hardcoded hex color: #4caf50
- **[major]** `backend/src/modules/themes/types.ts:15` — Hardcoded hex color: #e94560
- **[major]** `backend/src/modules/themes/types.ts:16` — Hardcoded hex color: #f5a623
- **[major]** `backend/src/modules/themes/types.ts:17` — Hardcoded hex color: #9e9e9e
- **[critical]** `scripts/churn-alert.ts:25` — Hardcoded product ID: const PRODUCT_ID = "lysnrai";
- **[critical]** `scripts/churn-alert.ts:44` — Hardcoded product ID: database: process.env.COSMOS_DATABASE || "lysnrai",
- **[minor]** `mobile_app/ios/LysnrKeyboard/KeyboardViewController.swift:572` — Emoji in code: 🌐
@ -354,7 +338,7 @@ Severity legend: **critical** = data/security risk · **major** = rule violation
## `learning_multimodal_memory_agents`
**Counts:** critical=11 · major=99 · minor=32 · total=142
**Counts:** critical=11 · major=95 · minor=32 · total=138
- **[major]** `mindlyst-native/iosApp/Models/MemoryStore.swift:64` — Swift print(): print("[MemoryStore] Failed to persist items: \(error)")
- **[major]** `mindlyst-native/iosApp/Models/MemoryStore.swift:76` — Swift print(): print("[MemoryStore] Failed to decode stored items: \(error)")
@ -377,8 +361,6 @@ Severity legend: **critical** = data/security risk · **major** = rule violation
- **[minor]** `backend/src/modules/daily-briefs/repository.ts:70` — any type: result.streakMessage = await enc.decrypt(result.streakMessage as any, { ...c
- **[minor]** `backend/src/modules/daily-briefs/repository.ts:74` — any type: result.motivationalQuote = await enc.decrypt(result.motivationalQuote as any
- **[minor]** `mindlyst-native/web/src/lib/api-handler.ts:9` — any type: type RouteHandler = (req: NextRequest, ctx: any) => Promise<Response | NextRespo
- **[major]** `backend/src/modules/brains/types.ts:28` — Hardcoded hex color: #A5B1C7
- **[major]** `backend/src/modules/brains/types.ts:29` — Hardcoded hex color: #6C7C98
- **[major]** `mindlyst-native/web/src/app/brain-packs/page.tsx:22` — Hardcoded hex color: #E67E22
- **[major]** `mindlyst-native/web/src/app/brain-packs/page.tsx:23` — Hardcoded hex color: #E74C3C
- **[major]** `mindlyst-native/web/src/app/brain-packs/page.tsx:24` — Hardcoded hex color: #9B59B6
@ -452,9 +434,7 @@ Severity legend: **critical** = data/security risk · **major** = rule violation
- **[major]** `mindlyst-native/web/src/app/api/capture-config/route.ts:137` — Hardcoded hex color: #7D8FB4
- **[major]** `mindlyst-native/web/src/app/api/share-card/route.ts:146` — Hardcoded hex color: #06070A
- **[major]** `mindlyst-native/web/src/app/api/share-card/route.ts:147` — Hardcoded hex color: #5A8CFF
- **[major]** `mindlyst-native/web/src/app/challenge/page.tsx:85` — Hardcoded hex color: #127942
- **[major]** `mindlyst-native/web/src/app/challenge/page.tsx:92` — Hardcoded hex color: #fff
- **[major]** `mindlyst-native/web/src/app/challenge/page.tsx:169` — Hardcoded hex color: #127942
- **[major]** `mindlyst-native/web/src/app/page.tsx:34` — Hardcoded hex color: #5A8CFF
- **[major]** `mindlyst-native/web/src/app/page.tsx:35` — Hardcoded hex color: #FF6E6E
- **[major]** `mindlyst-native/web/src/app/page.tsx:36` — Hardcoded hex color: #34D399
@ -528,7 +508,7 @@ Severity legend: **critical** = data/security risk · **major** = rule violation
## `learning_ai_fastgap`
**Counts:** critical=0 · major=104 · minor=212 · total=316
**Counts:** critical=0 · major=92 · minor=212 · total=304
- **[major]** `plugins/withAndroidWidget.js:224` — console.log: console.log(`
- **[major]** `plugins/withWatchApp.js:59` — console.log: console.log(`
@ -574,18 +554,6 @@ Severity legend: **critical** = data/security risk · **major** = rule violation
- **[major]** `web/src/components/BodyCanvas.tsx:476` — Hardcoded hex color: #FFFFFF
- **[major]** `web/src/components/BodyCanvas.tsx:493` — Hardcoded hex color: #7B8BA5
- **[major]** `web/src/components/BodyCanvas.tsx:504` — Hardcoded hex color: #000000
- **[major]** `backend/src/modules/body-stages/types.ts:91` — Hardcoded hex color: #FF8C42
- **[major]** `backend/src/modules/body-stages/types.ts:92` — Hardcoded hex color: #FFB366
- **[major]** `backend/src/modules/body-stages/types.ts:111` — Hardcoded hex color: #4ECDC4
- **[major]** `backend/src/modules/body-stages/types.ts:112` — Hardcoded hex color: #7EDDD6
- **[major]** `backend/src/modules/body-stages/types.ts:131` — Hardcoded hex color: #45B7D1
- **[major]** `backend/src/modules/body-stages/types.ts:132` — Hardcoded hex color: #6DC8E0
- **[major]** `backend/src/modules/body-stages/types.ts:152` — Hardcoded hex color: #5A8CFF
- **[major]** `backend/src/modules/body-stages/types.ts:153` — Hardcoded hex color: #8AB4FF
- **[major]** `backend/src/modules/body-stages/types.ts:177` — Hardcoded hex color: #A855F7
- **[major]** `backend/src/modules/body-stages/types.ts:178` — Hardcoded hex color: #C084FC
- **[major]** `backend/src/modules/body-stages/types.ts:198` — Hardcoded hex color: #F59E0B
- **[major]** `backend/src/modules/body-stages/types.ts:199` — Hardcoded hex color: #FBBF24
- **[major]** `src/screens/protocol/ProtocolDetail.tsx:183` — Hardcoded hex color: #1A2335
- **[major]** `src/components/platform/InAppBroadcastBanner.tsx:18` — Hardcoded hex color: #ef4444
- **[major]** `src/components/platform/InAppBroadcastBanner.tsx:19` — Hardcoded hex color: #f59e0b
@ -849,10 +817,8 @@ Severity legend: **critical** = data/security risk · **major** = rule violation
## `learning_ai_jarvis_jr`
**Counts:** critical=0 · major=2 · minor=15 · total=17
**Counts:** critical=0 · major=0 · minor=15 · total=15
- **[major]** `web/src/app/(app)/dashboard/page.tsx:125` — Hardcoded hex color: #fff
- **[major]** `backend/src/modules/jarvis-agents/types.ts:55` — Hardcoded hex color: #7C6BFF
- **[minor]** `web/src/app/(app)/settings/page.tsx:72` — Emoji in code: 🌙
- **[minor]** `web/src/app/(app)/dashboard/page.tsx:20` — Emoji in code: 🎯
- **[minor]** `web/src/app/(app)/dashboard/page.tsx:27` — Emoji in code: 🌍
@ -893,18 +859,11 @@ Severity legend: **critical** = data/security risk · **major** = rule violation
## `learning_ai_flowmonk`
**Counts:** critical=0 · major=114 · minor=4 · total=118
**Counts:** critical=0 · major=107 · minor=4 · total=111
- **[minor]** `web/src/app/(app)/tasks/page.tsx:153` — any type: { value: '', label: 'Energy: any' },
- **[minor]** `backend/src/lib/scheduler/engine.ts:468` — any type: // Priority 3: any remaining slot (no zone match)
- **[minor]** `backend/src/modules/tasks/repository.ts:28` — any type: const decrypted = await getEncryptor().decrypt(task.description as any, {
- **[major]** `backend/src/modules/zones/repository.ts:28` — Hardcoded hex color: #5A8CFF
- **[major]** `backend/src/modules/zones/repository.ts:29` — Hardcoded hex color: #5AE68C
- **[major]** `backend/src/modules/zones/repository.ts:30` — Hardcoded hex color: #FF6B6B
- **[major]** `backend/src/modules/zones/repository.ts:31` — Hardcoded hex color: #FECA57
- **[major]** `backend/src/modules/zones/repository.ts:32` — Hardcoded hex color: #A66BFF
- **[major]** `backend/src/modules/zones/repository.ts:69` — Hardcoded hex color: #5A8CFF
- **[major]** `backend/src/modules/zones/types.ts:9` — Hardcoded hex color: #5A8CFF
- **[major]** `mobile/src/app/index.tsx:57` — Hardcoded hex color: #07111f
- **[major]** `mobile/src/app/index.tsx:59` — Hardcoded hex color: #5ae68c
- **[major]** `mobile/src/app/index.tsx:60` — Hardcoded hex color: #eff4ff
@ -1098,17 +1057,8 @@ Severity legend: **critical** = data/security risk · **major** = rule violation
## `learning_ai_productivity_web`
**Counts:** critical=0 · major=9 · minor=6 · total=15
**Counts:** critical=0 · major=0 · minor=6 · total=6
- **[major]** `tailwind.config.ts:17` — Hardcoded hex color: #eff6ff
- **[major]** `tailwind.config.ts:18` — Hardcoded hex color: #dbeafe
- **[major]** `tailwind.config.ts:19` — Hardcoded hex color: #3b82f6
- **[major]** `tailwind.config.ts:20` — Hardcoded hex color: #2563eb
- **[major]** `tailwind.config.ts:21` — Hardcoded hex color: #1d4ed8
- **[major]** `src/app/tools/image-to-base64/page.tsx:411` — Hardcoded hex color: #1e293b
- **[major]** `src/app/tools/regex-tester/page.tsx:19` — Hardcoded hex color: #3B82F6
- **[major]** `src/app/tools/qr-code/page.tsx:90` — Hardcoded hex color: #000000
- **[major]** `src/app/tools/qr-code/page.tsx:91` — Hardcoded hex color: #ffffff
- **[minor]** `src/app/tools/markdown-preview/page.tsx:36` — Emoji in code: 🕐
- **[minor]** `src/lib/tools-registry.ts:27` — Emoji in code: 📝
- **[minor]** `src/lib/tools-registry.ts:28` — Emoji in code: 🔐
@ -1118,7 +1068,7 @@ Severity legend: **critical** = data/security risk · **major** = rule violation
## `oss/learning_ai_claw-cowork`
**Counts:** critical=0 · major=17 · minor=5 · total=22
**Counts:** critical=0 · major=14 · minor=5 · total=19
- **[major]** `plugins/bytelyst-scaffolder/main.js:182` — console.log: console.log(JSON.stringify({ error: "no input provided" }));
- **[major]** `plugins/bytelyst-scaffolder/main.js:190` — console.log: console.log(
@ -1136,9 +1086,6 @@ Severity legend: **critical** = data/security risk · **major** = rule violation
- **[major]** `plugins/product-backend-module/main.js:342` — console.log: console.log(JSON.stringify({ error: e.message }));
- **[minor]** `crates/cowork-desktop/src/components/ChatView.tsx:543` — any type: path: (f as any).path || f.name,
- **[minor]** `crates/cowork-desktop/src/components/ChatView.tsx:616` — any type: path: (f as any).path || f.name,
- **[major]** `crates/cowork-desktop/src/components/ChatView.tsx:413` — Hardcoded hex color: #128196
- **[major]** `crates/cowork-desktop/src/components/McpAppHost.tsx:111` — Hardcoded hex color: #374151
- **[major]** `crates/cowork-desktop/src/components/McpAppHost.tsx:156` — Hardcoded hex color: #ffffff
- **[minor]** `crates/cowork-desktop/src/App.tsx:84` — Emoji in code: 🚧
- **[minor]** `crates/cowork-desktop/src/cli.rs:39` — Emoji in code: 💭
- **[minor]** `crates/cowork-desktop/src/components/ChatView.tsx:141` — Emoji in code: 🔧
@ -1736,11 +1683,11 @@ Severity legend: **critical** = data/security risk · **major** = rule violation
| Rule | Total findings |
|------|----------------|
| `b7-emoji-in-code` | 465 |
| `web-hardcoded-hex` | 457 |
| `web-hardcoded-hex` | 404 |
| `b4-python-print` | 351 |
| `ts-any-type` | 249 |
| `b4-console-log` | 93 |
| `b5-hardcoded-product-id` | 13 |
| `b4-swift-print` | 7 |
**Grand total: 1635 findings across 19 repos.**
**Grand total: 1582 findings across 19 repos.**

View File

@ -240,10 +240,15 @@ scan_web_hardcoded_hex() {
# Allow hex colors in DESIGN TOKEN DEFINITION files. These are the
# canonical places where colors are declared as CSS custom properties
# or design system tokens; flagging them would be a false positive.
[[ "$file" =~ (^|/)(globals\.css|tokens\.css|.*\.tokens\..*|.*Theme\.(ts|tsx|swift|kt))$ ]] && continue
[[ "$file" =~ (^|/)(globals\.css|tokens\.css|tailwind\.config\.(ts|js|cjs|mjs)|.*\.tokens\..*|.*Theme\.(ts|tsx|swift|kt))$ ]] && continue
[[ "$file" =~ /(generated|design-tokens|design-system)/ ]] && continue
# Allow markdown-preview / code-picker tools where hex is the demo content.
[[ "$file" =~ /(color-picker|markdown-preview)/ ]] && continue
# Backend code is not a UI styling layer. Hex values in backend modules
# are data (e.g., theme presets, zone colors stored in Cosmos) \u2014 not
# styling rule violations.
[[ "$file" =~ (^|/)backend/ ]] && continue
# Allow markdown-preview / code-picker / qr-code / image tool pages where
# hex is the demo content being manipulated, not styling.
[[ "$file" =~ /tools/(color-picker|markdown-preview|qr-code|image-to-base64|regex-tester)/ ]] && continue
# Skip CSS custom property DEFINITIONS (lines like " --bl-accent: #5A8CFF").
[[ "$content" =~ ^[[:space:]]*--[a-zA-Z0-9-]+:[[:space:]]*\# ]] && continue
# Skip lines using the var(--token, #fallback) pattern \u2014 these are
@ -253,6 +258,10 @@ scan_web_hardcoded_hex() {
[[ "$content" =~ ^[[:space:]]*(//|\*|/\*) ]] && continue
# Skip Next.js PWA themeColor metadata (must be literal hex per spec).
[[ "$content" =~ themeColor[[:space:]]*: ]] && continue
# Skip HTML numeric character references like &#128196; \u2014 these encode
# Unicode characters, NOT hex colors (the digits happen to be in [0-9] which
# is a subset of hex, fooling the regex).
[[ "$content" =~ \&\#[0-9]+\; ]] && continue
# Extract just the hex match for evidence.
local match
match=$(echo "$content" | grep -oE '#[0-9a-fA-F]{6}\b|#[0-9a-fA-F]{3}\b' | head -1)