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:
parent
616e973866
commit
d5d30ed912
@ -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.**
|
||||
|
||||
@ -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 📄 \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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user