feat(scripts): precision-tune rule violation scanner (hex false positives)

Three precision improvements that drop total findings from 2548 to 1643
without losing real violations:

1. web-hardcoded-hex: switch from grep -oE to grep -nE so the scanner
   can examine each match in CONTEXT, then apply context filters:
   - Skip CSS custom property DEFINITIONS:  '--bl-accent: #5A8CFF'
   - Skip var(--token, #fallback) patterns: defensive design-token
     fallbacks for boot-order safety, not raw hardcodes
   - Skip globals.css, *.tokens.*, *Theme.{ts,tsx,swift,kt} files
   - Skip design-system/ and color-picker/markdown-preview tool pages

2. b5-hardcoded-product-id: scripts/ exclusion (was previously bypassed
   for the script case but still caught churn-alert.ts genuinely).

3. Updates baseline report. Findings by category:

   Before                              After
   -----                                -----
   web-hardcoded-hex       1370        465  (-66%)
   b7-emoji-in-code         465        465
   b4-python-print          351        351
   ts-any-type              249        249
   b4-console-log            93         93
   b5-hardcoded-product-id   13         13
   b4-swift-print             7          7
                          ----        ----
   Total                  2548       1643

Remaining hex findings are now substantively real:
  - flowmonk:  114 (zone seed data: { color: '#5A8CFF' })
  - fastgap:   102 (BodyCanvas organ colors, organ-data.ts)
  - mindlyst:   97 (mixed UI + data)
  - common_plat: 59 (brand colors in login page: Google #4285F4 etc.)
  - efforise:   39
  - mac_tooling: 18

These fall into three classes which will be triaged in Phase 2:
  A. Brand colors (Google login etc.) - keep, document as exceptions
  B. Data seeds (zone colors, category colors) - migrate to design tokens
  C. Inline styling (color: '#fff') - replace with var(--xx-token)
This commit is contained in:
saravanakumardb1 2026-05-23 14:10:59 -07:00
parent 4967b125fd
commit 14ab38e49e
2 changed files with 40 additions and 929 deletions

File diff suppressed because it is too large Load Diff

View File

@ -233,14 +233,30 @@ scan_ts_any_type() {
# snippet, so triage doesn't need to open the file for trivial cases.
scan_web_hardcoded_hex() {
local repo="$1" repo_dir="$2"
# Use grep -oE with --only-matching-line position so we can show the real match.
# Pattern: '#' followed by either 6 or 3 hex chars at a word boundary.
while IFS=: read -r file line match; do
# Strategy: grep returns full line (so we can examine context), then we
# extract the hex match from each result and apply context filters.
while IFS=: read -r file line content; do
[[ -z "$file" ]] && continue
# Allow hex colors in tokens / generated / design-system files
[[ "$file" =~ /(tokens\.css|.*\.tokens\..*|generated/|design-tokens/) ]] && continue
# 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" =~ /(generated|design-tokens|design-system)/ ]] && continue
# Allow markdown-preview / code-picker tools where hex is the demo content.
[[ "$file" =~ /(color-picker|markdown-preview)/ ]] && 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
# defensive fallbacks for the design-token loading order, not raw hardcodes.
[[ "$content" =~ var\(--[a-zA-Z0-9_-]+ ]] && continue
# Skip comment lines (// or /* or *).
[[ "$content" =~ ^[[:space:]]*(//|\*|/\*) ]] && 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)
[[ -z "$match" ]] && continue
emit_finding "web-hardcoded-hex" "major" "$repo" "$file" "$line" "Hardcoded hex color: $match"
done < <(grep -rnoE '#[0-9a-fA-F]{6}\b|#[0-9a-fA-F]{3}\b' "$repo_dir" \
done < <(grep -rnE '#[0-9a-fA-F]{6}\b|#[0-9a-fA-F]{3}\b' "$repo_dir" \
--include='*.ts' --include='*.tsx' --include='*.css' --include='*.scss' \
"${EXCLUDE_DIRS[@]}" "${TEST_EXCLUDES[@]}" 2>/dev/null || true)
}