diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..f27d4bb --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "allow": [ + "Bash(ls -la c:/Users/BSOR/CascadeProjects/Cesar/*.png c:/Users/BSOR/CascadeProjects/Cesar/static/icons/ c:/Users/BSOR/CascadeProjects/Cesar/store-assets/)" + ] + } +} diff --git a/.claude/skills/arch-audit/skill.md b/.claude/skills/arch-audit/skill.md new file mode 100644 index 0000000..6093246 --- /dev/null +++ b/.claude/skills/arch-audit/skill.md @@ -0,0 +1,339 @@ +--- +name: "arch-audit" +description: "Architecture, performance & improvement audit for César Chrome Extension. Evaluates code organization, detection pipeline quality, security, performance, testing gaps, error handling, and DX. Does NOT make changes — only analyzes and reports. Use when you want a technical health check of the codebase." +--- + +# Architecture, performance & improvement audit + +You are a senior software architect with deep knowledge of Chrome Extension (Manifest V3) development. Your job is to perform a comprehensive technical audit of the César extension across 7 categories. **Do NOT make any changes** — only analyze and report. + +--- + +## Step 1 — Orientation: read the architectural intent + +Before auditing code, understand what was intended. Read these files first: + +1. `CLAUDE.md` — project overview, architecture, key constraints, style guide +2. `manifest.json` — extension permissions, content scripts, service worker config + +Then build a file inventory using Glob: + +``` +src/content/engine/ — 3-layer detection pipeline (regex, behavioral, LLM) +src/content/patterns/ — regex pattern definitions for lead magnet detection +src/content/scanner/ — LinkedIn feed scanning and auto-expand logic +src/content/ui/ — overlay UI, icons, comment prefill +src/content/config.js — content script configuration +src/content/index.js — content script entry point +src/background/llm/ — LLM provider implementations (Anthropic, OpenAI, Gemini) +src/background/ — service worker: LLM routing, system prompt, verification +src/popup/ — extension popup UI (HTML + CSS + JS) +src/debug/ — debug bridge running in MAIN world +src/shared/ — utilities shared across content/background/popup +static/ — icons and CSS copied to dist/ +tests/ — Vitest unit tests with jsdom +build.js — esbuild build script +manifest.json — Manifest V3 configuration +package.json — dependencies and scripts +``` + +Output the inventory as a table so the user can see the audit scope before you begin. + +--- + +## Step 2 — Systematic audit across 7 categories + +Audit every file or group relevant to each category. Be specific: reference exact file paths and line numbers. Do not be generous — rate honestly. + +For each issue found, report in this format: + +``` +**[Category] — Severity: Critical | High | Medium | Low** +- **File**: `src/path/to/file.js:42` +- **Issue**: What's wrong (quote code where helpful) +- **Impact**: Effect on correctness, security, detection accuracy, or DX +- **Fix**: Concrete, actionable recommendation +``` + +--- + +### Category 1 — Architecture & code organization + +**What to check:** + +- Does the folder structure cleanly separate concerns? Content script (detection + UI) vs background (LLM) vs popup (settings) vs shared (utilities)? +- Are there files in the wrong layer? (e.g., LLM calls in content script, DOM manipulation in background, business logic in popup) +- Is the detection pipeline layered correctly? Layer 1 (regex) → Layer 2 (behavioral signals) → Layer 3 (LLM verification) — are these cleanly separated? +- Is `src/content/index.js` thin? (should orchestrate, not contain detection logic) +- Is `src/background/index.js` thin? (should route messages, not contain LLM logic) +- Are LLM providers in `src/background/llm/` isolated from each other and from the verification logic? +- Does `src/shared/` only contain truly shared utilities? Are there files that belong in content or background instead? +- Is message passing between content ↔ background cleanly structured? (e.g., consistent message format, typed actions) +- Does `src/debug/debug.js` stay standalone with no imports? (it runs in MAIN world) +- Are there circular dependencies between modules? + +**Key files to read:** +- `src/content/index.js` +- `src/content/engine/detection-engine.js` +- `src/content/engine/layer1.js`, `layer2.js` +- `src/background/index.js` +- `src/background/verify.js` +- `src/background/providers.js` +- All files in `src/background/llm/` +- All files in `src/shared/` +- `src/debug/debug.js` + +--- + +### Category 2 — Detection pipeline quality + +**What to check:** + +- **Regex patterns**: Are the patterns in `src/content/patterns/` specific enough to avoid false positives? Are they too narrow, missing common lead magnet phrasing? +- **Pattern maintainability**: Are patterns well-organized, commented, and easy to extend? Or are they a monolithic regex wall? +- **Layer 1 → Layer 2 handoff**: Is the scoring from regex to behavioral signals well-calibrated? Are thresholds documented or magic numbers? +- **Layer 2 → Layer 3 handoff**: When does the system decide to call the LLM? Is the threshold configurable? Is it clear why some posts skip LLM verification? +- **LLM system prompt**: Read `src/background/system-prompt.js` — is the prompt well-structured? Does it clearly define what constitutes a parasitic lead magnet? +- **LLM response parsing**: Is the LLM response parsed robustly? What happens if the LLM returns unexpected formats? +- **DOM extraction**: Read `src/content/engine/dom-extractors.js` — is it resilient to LinkedIn DOM changes? Are selectors hardcoded or configurable? +- **Feed scanning**: Read `src/content/scanner/feed-scanner.js` — does it handle infinite scroll correctly? Does it debounce or throttle scans? +- **Auto-expand**: Read `src/content/scanner/auto-expand.js` — does it handle edge cases (already expanded, missing "see more" button)? + +**Key files to read:** +- All files in `src/content/patterns/` +- All files in `src/content/engine/` +- All files in `src/content/scanner/` +- `src/background/system-prompt.js` +- `src/background/verify.js` + +--- + +### Category 3 — Security + +**What to check:** + +- **XSS via LLM responses**: Is `escapeHTML` from `src/shared/sanitize.js` applied to ALL LLM output before `innerHTML` injection? Are there any code paths that bypass sanitization? +- **Content Security Policy**: Does `manifest.json` CSP restrict script sources appropriately? Is `unsafe-eval` or `unsafe-inline` present? +- **Message passing security**: Are `chrome.runtime.onMessage` handlers validating the sender? Could a malicious page send messages to the background script? +- **API key storage**: Are LLM API keys stored in `chrome.storage.local` (not `sync`)? Are they ever logged or exposed in error messages? +- **Host permissions**: Are the `host_permissions` in `manifest.json` minimal? Are there unnecessary origins? +- **MAIN world risks**: `debug.js` runs in MAIN world — does it expose any privileged APIs or data to the page context? +- **Input validation**: Is user input from the popup (settings, API keys) validated before storage? +- **External API calls**: Are LLM API calls using HTTPS? Are responses validated before processing? +- **innerHTML usage**: Search for ALL `innerHTML` assignments — each one is a potential XSS vector. Are they all safe? + +**Key files to read:** +- `src/shared/sanitize.js` +- `manifest.json` (CSP, permissions) +- `src/background/index.js` (message handler) +- `src/debug/debug.js` (MAIN world exposure) +- `src/popup/popup.js` (settings handling) +- `src/content/ui/overlay-manager.js` (DOM injection) +- All files in `src/background/llm/` + +--- + +### Category 4 — Performance + +**What to check:** + +**Content script performance:** +- Is the feed scanner using `MutationObserver` efficiently? Is it observing too much of the DOM tree? +- Are regex pattern matches running on every DOM mutation, or are they debounced/throttled? +- Is the overlay UI created lazily (only when needed) or eagerly for all posts? +- Are there memory leaks? (event listeners not cleaned up, references to detached DOM nodes, growing Maps/Sets) +- Does `auto-expand.js` cause layout thrashing by reading and writing DOM in tight loops? + +**Background script performance:** +- Are LLM API calls queued or rate-limited? What happens if 20 posts trigger LLM verification simultaneously? +- Is there any caching of LLM results for duplicate/similar posts? +- Are API responses streamed or buffered? (streaming reduces time-to-first-result) + +**Extension-wide:** +- Does the content script do unnecessary work on non-feed LinkedIn pages (profile, messaging, etc.)? +- Is `chrome.storage` accessed excessively? Are there reads that could be batched or cached in memory? +- Are there synchronous operations that block the main thread? (e.g., large regex on long post text) +- Does the build output size seem reasonable? Check for unnecessary code in the bundle. + +**Key files to read:** +- `src/content/scanner/feed-scanner.js` +- `src/content/scanner/auto-expand.js` +- `src/content/engine/detection-engine.js` +- `src/content/ui/overlay-manager.js` +- `src/background/index.js` +- `src/background/verify.js` +- `build.js` + +--- + +### Category 5 — Testing gaps + +**What to check:** + +- **Unit test coverage**: For every file in `src/content/engine/` and `src/content/patterns/`, is there a corresponding test? The CLAUDE.md states focus on regex patterns and detection scoring. +- **Critical paths without tests**: Are any of these untested? + - Layer 1 regex pattern matching (false positives + false negatives) + - Layer 2 behavioral signal scoring + - Detection engine threshold logic + - LLM response parsing (`parse-json` tests exist — are they comprehensive?) + - LLM provider selection and routing + - Sanitize function edge cases (XSS payloads) + - Chrome storage wrapper functions + - Message passing between content ↔ background +- **Mock correctness**: Are Chrome API mocks in `tests/setup.js` realistic? Do they cover `chrome.storage`, `chrome.runtime.sendMessage`, `chrome.runtime.onMessage`? +- **Edge case coverage**: Do tests cover the unhappy path? (malformed posts, empty text, LinkedIn DOM changes, LLM timeouts, invalid API keys) +- **DOM-dependent tests**: Are content script tests using jsdom effectively? Are LinkedIn DOM structures realistic in test fixtures? +- **Missing test files**: Compare `src/` files to `tests/` files — which modules lack any test coverage? + +**Key files to read:** +- `tests/setup.js` +- All files in `tests/` +- Cross-reference with `src/content/engine/`, `src/content/patterns/`, `src/shared/`, `src/background/` + +--- + +### Category 6 — Error handling + +**What to check:** + +- **Swallowed errors**: `catch(e) { }` or `catch(e) { return null; }` with no logging +- **Generic catches**: `catch(error) { throw new Error("Something went wrong"); }` without logging the original error +- **Missing try/catch**: Async functions that call LLM APIs, DOM operations, or `chrome.storage` without error handling +- **LLM failure resilience**: What happens when the LLM API returns an error, times out, or returns malformed JSON? Does the detection pipeline degrade gracefully (fall back to Layer 1+2 scores)? +- **DOM operation safety**: What happens when LinkedIn changes their DOM structure and selectors fail? Does the scanner crash or degrade gracefully? +- **Chrome API errors**: Are `chrome.runtime.lastError` checks in place for callback-based APIs? Are promise rejections from `chrome.storage` handled? +- **Console logging**: Are errors logged with the `[César]` prefix per the style guide? Is there enough context in error logs to debug issues? +- **User-facing errors**: When the popup shows errors (invalid API key, LLM failure), are messages actionable? +- **Feed scanner resilience**: If processing one post throws, does the scanner continue to the next post or crash entirely? + +**Key files to read:** +- All files in `src/background/llm/` +- `src/background/verify.js` +- `src/background/index.js` +- `src/content/engine/detection-engine.js` +- `src/content/scanner/feed-scanner.js` +- `src/content/ui/overlay-manager.js` +- `src/shared/storage.js` +- `src/popup/popup.js` + +--- + +### Category 7 — DX & modernization + +**What to check:** + +- **Build system**: Is `build.js` well-structured? Does it handle errors, report bundle sizes, support source maps for debugging? +- **Manifest V3 best practices**: Is the extension following current Manifest V3 best practices? Are there deprecated patterns? +- **esbuild configuration**: Is the esbuild config optimal? (tree-shaking, minification, target browser version) +- **Linting coverage**: Does ESLint catch Chrome extension-specific issues? Are there rules that enforce the `[César]` log prefix or prevent `innerHTML` without sanitization? +- **Dev workflow**: Is `npm run dev` (watch mode) fast and reliable? Does it rebuild only changed files? +- **Dependency audit**: Check `package.json` — are dev dependencies up to date? Are there unnecessary dependencies? +- **Dead code**: Are there exported functions, constants, or modules that are never imported anywhere? +- **Code duplication**: Are there repeated patterns across LLM providers that could share a common abstraction? +- **Configuration**: Are magic numbers (thresholds, timeouts, retry counts) extracted into `config.js` or hardcoded across files? +- **README / docs**: Is the README sufficient for a new contributor to understand, build, and test the extension? + +**Key files to read:** +- `build.js` +- `package.json` +- `manifest.json` +- `src/content/config.js` +- ESLint config file (`.eslintrc.*` or `eslint.config.*`) +- `README.md` + +--- + +## Step 3 — Output the full report + +Structure the report exactly as follows: + +--- + +### Executive summary + +**Overall technical health score**: X/10 + +**Top 3 strengths**: +1. ... +2. ... +3. ... + +**Top 5 most impactful issues** (must fix): +1. ... +2. ... +3. ... +4. ... +5. ... + +**Estimated tech debt**: Low / Medium / High / Critical + +--- + +### Detailed findings by category + +#### Category 1 — Architecture & code organization +[All issues in the standard format] + +#### Category 2 — Detection pipeline quality +[All issues in the standard format] + +#### Category 3 — Security +[All issues in the standard format] + +#### Category 4 — Performance +[All issues in the standard format] + +#### Category 5 — Testing gaps +[All issues in the standard format] + +#### Category 6 — Error handling +[All issues in the standard format] + +#### Category 7 — DX & modernization +[All issues in the standard format] + +--- + +### Prioritized action plan + +#### Immediate (fix before next release) +- [ ] ... + +#### Short-term (next sprint) +- [ ] ... + +#### Medium-term (next quarter) +- [ ] ... + +#### Long-term / architectural +- [ ] ... + +--- + +### Full issue checklist + +[Every issue as a markdown checkbox for progress tracking] + +- [ ] [Category] [File:line] — [one-line description] + +--- + +## Severity guide + +| Severity | Meaning | +|----------|---------| +| **Critical** | XSS vulnerability, API key exposure, data leak, or extension-breaking bug | +| **High** | Significant detection accuracy issue, security weakness, or chronic performance problem | +| **Medium** | Noticeable quality issue affecting reliability, false positive rate, or developer velocity | +| **Low** | Polish / DX improvement — real but limited impact | + +--- + +## Important constraints + +- **Read-only**: Do not edit any files. Do not suggest making changes mid-audit. Complete the full audit first, then output the report. +- **Be specific**: Always cite exact file path and approximate line number. Findings without a location are not acceptable. +- **Be honest**: An honest 5/10 is more useful than a generous 8/10. +- **César context**: This is a Chrome Extension with a 3-layer detection pipeline. The most critical architectural concern is the clean separation of layers 1→2→3 and the security of LLM response injection into the DOM. +- **Security is non-negotiable**: Any finding that could enable XSS, API key leakage, or privilege escalation is always Critical. +- **Detection accuracy matters**: False positives degrade user trust. Pattern and threshold issues are always Medium or higher. diff --git a/.claude/skills/cleanup/skill.md b/.claude/skills/cleanup/skill.md new file mode 100644 index 0000000..9fc846f --- /dev/null +++ b/.claude/skills/cleanup/skill.md @@ -0,0 +1,278 @@ +--- +name: "cleanup" +description: "Codebase hygiene audit: finds dead code, stale artifacts (commented-out code, TODO/FIXME, debug leftovers), and unused npm dependencies across the whole repo. Reports all findings grouped by category, then fixes each confirmed group. Does NOT auto-fix anything — always asks before touching files." +--- + +# Codebase cleanup + +You are a surgical codebase janitor. Your job is to find accumulated cruft — dead code, stale artifacts, and unused packages — across the entire César Chrome Extension codebase, report every finding in a structured table, then fix only what the user approves. + +**Rule**: Complete ALL scans before reporting anything. Never fix anything before the user confirms. + +--- + +## Phase 1 — Orientation + +Read these files to understand the project structure: + +1. `package.json` — extract the full `dependencies` and `devDependencies` lists +2. `manifest.json` — note entry points (content scripts, background service worker, popup) +3. `build.js` — understand what esbuild bundles and what gets copied verbatim +4. `.gitignore` — confirm which directories to skip +5. `CLAUDE.md` — review project conventions + +**Excluded directories** (never scan these): +- `node_modules/`, `dist/`, `coverage/`, `.claude/` +- `store-assets/` — marketing assets, not application code + +Then use Glob to build a full inventory of all `.js` files in scope (`src/`, `tests/`). Output the count: +> "Scanning N files across src/, tests/..." + +--- + +## Phase 2 — Dead code scan + +### 2a. Unused imports + +Since César uses plain JavaScript (no TypeScript), scan manually: + +For each `.js` file in `src/`: +- Extract all `import { ... } from '...'` and `import ... from '...'` statements +- For each imported symbol, search within the same file for usage beyond the import line +- Flag symbols that are imported but never referenced in the file body + +**Note**: This is a heuristic for JS — be conservative. Skip re-exports (files that import and immediately export). + +### 2b. Unused exports + +For each file in `src/`: +- Extract all `export` statements: `export function`, `export const`, `export class`, `export default`, named exports in `export { ... }` +- For each exported symbol, grep the **entire codebase** (excluding the file itself and `node_modules/`) for that symbol name +- Flag symbols with zero external references as "potentially unused export" + +**Confidence levels**: +- **High**: Symbol name is unique and appears only in its own file +- **Medium**: Symbol name is short/generic and might appear in string context — needs manual verification +- Skip: Generic names like `type`, `id`, `name`, `data`, `config` — too noisy to be reliable + +Only report High and Medium confidence findings. + +### 2c. Orphaned files + +An orphaned file is one that no other file in the codebase imports from. + +Use Grep to find all `import ... from '...'` statements across `src/`. Build a set of all referenced file paths (resolve relative paths). + +Then compare against the full file list from Phase 1. Files not in the referenced set are candidates. + +**Automatic exclusions** (these are valid entry points, never orphaned): +- `src/content/index.js` — esbuild content script entry point +- `src/background/index.js` — esbuild background service worker entry point +- `src/popup/popup.js` — esbuild popup entry point +- `src/debug/debug.js` — standalone MAIN world script (copied verbatim, not bundled) +- `build.js` — build script +- `tests/**` — test files (they import from src/, not the other way around) +- Config files: `vitest.config.*`, `eslint.config.*`, `prettier.config.*` + +### 2d. Unreachable code + +Grep for patterns indicating unreachable statements: +- A `return` or `throw` statement followed on the next non-empty, non-comment line by a non-`}` statement within the same function (same indentation level) + +This is a heuristic — flag only high-confidence cases. If uncertain, skip. + +--- + +## Phase 3 — Stale artifacts scan + +### 3a. Commented-out code blocks + +Grep across all `.js` files in `src/` for lines matching: +``` +^\s*//.*[=({;] +``` + +This finds lines where a comment contains code-like characters. Then group consecutive such lines into blocks. + +**Only flag** if: +- 2+ consecutive commented-out lines that look like code, OR +- A single line that is clearly a disabled function call or statement (e.g., `// const x = doSomething()`) + +**Do NOT flag**: +- Single-line explanatory comments (e.g., `// This runs only on LinkedIn`) +- JSDoc-style comments (`/** ... */`) +- Comments that are clearly prose (no `=`, `(`, `{`, `;`) +- License headers +- Comments inside `tests/` — test files often have commented examples + +### 3b. Stale TODO / FIXME / HACK / XXX markers + +Grep across all `.js` files in `src/` and `tests/` for: +``` +TODO|FIXME|HACK|XXX +``` + +Report every match with: file path, line number, full comment text. + +**Note**: Do NOT auto-fix these. TODOs require human judgment. Report only. + +### 3c. Debug console.* audit + +Grep across `src/` for: +``` +console\.(log|warn|error|debug|info)\( +``` + +Per project conventions, console logs in production code must be prefixed with `[César]`. + +**Flag as issues**: +- `console.*` calls that do NOT include the `[César]` prefix +- `console.debug(` or `console.info(` calls — these are likely debug leftovers regardless of prefix + +**Do NOT flag**: +- `console.log('[César]` / `console.warn('[César]` / `console.error('[César]` — these follow the project convention +- Any `console.*` in `tests/` — test files can use console freely +- Any `console.*` in `build.js` — build scripts can use console freely + +--- + +## Phase 4 — Unused dependency scan + +Extract every package from `package.json` `dependencies` and `devDependencies`. + +For each package, grep the codebase: +- `import` or `require` statements referencing the package name in `src/`, `tests/`, and root config files +- Check config files: `build.js`, `vitest.config.*`, `eslint.config.*`, `prettier.config.*` + +**Categories**: +- **Confirmed unused**: Zero references anywhere +- **Implicit / likely intentional**: Zero code references, but package is a known tool (ESLint, Prettier, build tool, test framework) + +Examples of implicit packages: `esbuild` (used in build.js), `eslint`, `prettier`, `vitest`, `jsdom` (vitest environment), `@types/*` + +Report both categories separately. + +--- + +## Phase 5 — Report + +Output the full findings report before asking the user to confirm any fixes. + +Use this exact structure: + +``` +## Cleanup audit — [date] + +### Summary +| Category | Issues found | +|---|---| +| Dead code | N | +| Stale artifacts | N | +| Unused dependencies | N | +| **Total** | **N** | + +--- + +### Category 1: Dead code + +#### 1a. Unused imports +| File | Line | Symbol | Confidence | +|---|---|---|---| +| src/content/... | 12 | fooHelper | High | + +#### 1b. Unused exports +| File | Symbol | Type | Confidence | Note | +|---|---|---|---|---| + +#### 1c. Orphaned files +| File | Reason | +|---|---| + +#### 1d. Unreachable code +| File | Line | Preview | +|---|---|---| + +--- + +### Category 2: Stale artifacts + +#### 2a. Commented-out code blocks +| File | Lines | Preview | +|---|---|---| + +#### 2b. TODO / FIXME / HACK / XXX markers +| File | Line | Comment | +|---|---|---| + +#### 2c. Debug console.* issues +| File | Line | Statement | Issue | +|---|---|---|---| + +--- + +### Category 3: Unused dependencies + +#### Confirmed unused +- package-name + +#### Implicit / verify manually +- package-name — reason (e.g., ESLint plugin, Vitest environment) +``` + +--- + +## Phase 6 — Confirm and fix + +After outputting the full report, ask once per category: + +**Dead code**: +> "Found N dead code issues. Options: +> - **Fix all** — remove unused imports, strip `export` from unused exports, list orphaned files for manual deletion +> - **Skip** — leave dead code untouched +> - **Show me each** — walk through each issue individually" + +**Stale artifacts**: +> "Found N stale artifact issues. Options: +> - **Fix all** — remove commented-out code blocks and non-conforming console.* statements (TODOs are reported only, never auto-removed) +> - **Skip** — leave stale artifacts untouched +> - **Show me each** — walk through each issue individually" + +**Unused dependencies**: +> "Found N confirmed-unused packages. I will NOT auto-remove these. Review the list and tell me which ones to uninstall, or run `npm uninstall ` yourself." +> (Never auto-run npm uninstall — always require explicit user instruction) + +--- + +## Fix rules (apply only to confirmed categories) + +| Finding | Fix | +|---|---| +| Unused import | Remove the import line entirely; if only some symbols from a multi-symbol import are unused, remove only those symbols | +| Unused export | Remove the `export` keyword; keep the declaration | +| Orphaned file | List file path; ask user to confirm deletion before touching | +| Unreachable code | Remove the unreachable statement(s); keep the `return`/`throw` | +| Commented-out code block (2+ lines or clear disabled statement) | Delete the comment block | +| Single-line TODO/FIXME | Never auto-remove — report only | +| Non-conforming console.* | Replace with `[César]`-prefixed version, or remove if it's a debug leftover — ask user | +| Debug-only console.debug/info | Remove the line | +| Unused npm package | Never auto-uninstall — report only | + +**After applying fixes**, run: +```sh +npm run lint +npm run test +``` +to confirm no regressions were introduced. If errors appear, show them and revert the specific change that caused them. + +--- + +## Important constraints + +- **Complete all scans before reporting**: Do not interleave partial results and fix prompts. +- **Conservative on orphaned files**: False positives here are costly. When uncertain whether a file is truly orphaned (e.g., dynamic imports, Chrome extension manifest references, esbuild entry points), mark it "verify manually" instead of "orphaned". +- **TODOs are human decisions**: Never delete a TODO/FIXME comment — only report them. +- **Packages require explicit approval**: Never run `npm uninstall` without a direct user instruction. +- **Preserve working code**: If removing a commented-out block and you're not 100% certain it's dead, skip it and note "unclear — skipped". +- **This is César**: A Chrome Extension with content scripts, a background service worker, and a popup. Respect the detection pipeline architecture — dead code in `src/content/engine/` or `src/background/` is more impactful to clean than dead code in the popup. +- **debug.js is standalone**: `src/debug/debug.js` runs in MAIN world and communicates via CustomEvents. It is NOT bundled by esbuild — it is copied verbatim. Do not flag its lack of imports/exports as dead code. +- **Console convention**: Production `console.log`/`warn`/`error` must use the `[César]` prefix per CLAUDE.md. Unprefixed calls are either bugs or debug leftovers. diff --git a/.claude/skills/commit/skill.md b/.claude/skills/commit/skill.md new file mode 100644 index 0000000..7dac70c --- /dev/null +++ b/.claude/skills/commit/skill.md @@ -0,0 +1,167 @@ +--- +name: "commit" +description: "Safe commit with pre-audit. Use /commit instead of git commit directly. Scans staged changes for César-specific violations, runs the verification loop (test → lint), then creates a properly formatted commit." +user_invocable: true +--- + +# Safe commit + +**Usage**: `/commit` or `/commit --fast` + +- Default: runs the violation audit **and** the full verification loop (test → lint) +- `--fast`: runs the violation audit only, skips the verification loop — use when you have already run checks in this session + +Run a full pre-commit audit before creating a commit. Never skip this — it catches the most common violations before they land in git history. + +--- + +## Step 1 — See what's changing + +```sh +git status +git diff --staged +``` + +List every staged file. If nothing is staged, ask the user what they want to commit before continuing. + +--- + +## Step 2 — Scan staged files for the 7 violations + +Read each staged file and check **all 7** items. Do not proceed to Step 3 if ANY violation is found. + +### Violation 1 — Console log prefix + +All `console.log`, `console.warn`, `console.error` calls in production code (`src/`) must be prefixed with `[César]`. + +- ❌ `console.log('something happened')` +- ❌ `console.log("Detection complete")` +- ✅ `console.log('[César] Detection complete')` +- ✅ `console.log('%c[César] LLM error', 'color: #ff4757')` +- Exception: `debug.js` — it runs in MAIN world and may use its own format +- Exception: `console.log` inside a `CONFIG.DEBUG` guard is acceptable but must still use the `[César]` prefix + +### Violation 2 — XSS / innerHTML without escaping + +Search for `innerHTML` assignments that interpolate variables containing LLM responses or user-generated text without using `escapeHTML()` from `src/shared/sanitize.js`. + +- ❌ `el.innerHTML = llmResponse` +- ❌ `el.innerHTML = \`

${data.text}

\`` (where `data` comes from LLM or external input) +- ✅ `el.innerHTML = \`

${escapeHTML(data.text)}

\`` +- ✅ `el.innerHTML = \`...\`` (static HTML templates with no dynamic data are fine) +- ✅ `btn.innerHTML = \`${ICONS.check} Confirmed\`` (internal constants are fine) + +If `escapeHTML` is used but not imported, that's also a violation. + +### Violation 3 — debug.js isolation + +`src/debug/debug.js` runs in MAIN world and must stay standalone — no `import` or `require` statements. + +- ❌ `import { something } from '../shared/utils.js'` +- ❌ `const x = require('./foo')` +- ✅ All code self-contained within the file + +If an `import` is added to `debug.js`, **stop** — this will break the extension. + +### Violation 4 — Direct chrome.storage calls + +Search for direct `chrome.storage.local` or `chrome.storage.sync` calls outside of `src/shared/storage.js`. + +- ❌ `chrome.storage.local.get(...)` in `src/content/` or `src/background/` +- ❌ `chrome.storage.sync.set(...)` in `src/popup/popup.js` +- ✅ `import { getStorage, setStorage } from '../shared/storage.js'` then use the wrappers +- Exception: `src/shared/storage.js` itself (the wrapper implementation) + +### Violation 5 — External runtime dependencies + +Check if `package.json` is staged and if any new `dependencies` (not `devDependencies`) have been added. + +- ❌ Adding `"axios": "^1.0.0"` to `dependencies` +- ❌ Adding any npm package to `dependencies` +- ✅ Adding packages to `devDependencies` (build tools, testing, linting) +- ✅ Using `fetch()` for HTTP calls + +César uses zero runtime dependencies — all LLM calls use native `fetch`. + +### Violation 6 — Hardcoded secrets + +Search for patterns that look like API keys or secrets in staged `.js` files. + +- ❌ `const API_KEY = 'sk-ant-...'` or any hardcoded key +- ❌ `Authorization: 'Bearer sk-...'` with a literal key +- ✅ API keys read from `chrome.storage` (user provides their own key via popup) + +### Violation 7 — Manifest version consistency + +If `manifest.json` is staged, verify: + +- The `version` field has been updated if the change warrants it (new features or fixes) +- The `version` in `package.json` matches `manifest.json` if both are staged +- No new `permissions` or `host_permissions` have been added without clear justification + +If permissions were added, ask the user to confirm they are necessary — Chrome Web Store reviews flag unnecessary permissions. + +--- + +## Step 3 — Report violations or proceed + +**If violations found**: List each violation with file name, line number, and exact fix required. Do NOT continue to Step 4. Ask the user to fix them first (or offer to fix them). + +**If clean**: Report "Pre-commit audit passed. Running verification loop..." + +--- + +## Step 4 — Verification loop + +**If `--fast` was passed**: skip this step entirely and go to Step 5. + +Run these in order. Stop immediately if any fails. + +```sh +npm run test +``` + +```sh +npm run lint +``` + +If any command fails, show the error output and stop. Fix the issue before committing. + +--- + +## Step 5 — Create the commit + +Stage specific files (never `git add -A` or `git add .`): + +```sh +git add +``` + +Draft a commit message: +- First line: imperative mood, under 72 chars (e.g., `feat(detection): add carousel post pattern matching`) +- Focus on the "why", not the "what" +- Prefix: `feat`, `fix`, `refactor`, `test`, `docs`, `chore`, `perf`, `style` +- Common scopes: `detection`, `overlay`, `popup`, `llm`, `scanner`, `patterns`, `build`, `debug` + +Create the commit with the Co-Authored-By trailer: + +```sh +git commit -m "$(cat <<'EOF' +(): + +Co-Authored-By: Claude Opus 4.6 +EOF +)" +``` + +Confirm success with `git status`. + +--- + +## Key reminders + +- Never use `--no-verify` to skip hooks +- Never amend a published commit +- Never force-push to `main` +- Never commit `.env` files or API keys +- Never use `git add -A` or `git add .` diff --git a/.claude/skills/responsive-audit/skill.md b/.claude/skills/responsive-audit/skill.md new file mode 100644 index 0000000..54a2746 --- /dev/null +++ b/.claude/skills/responsive-audit/skill.md @@ -0,0 +1,327 @@ +--- +name: "responsive-audit" +description: "Exhaustive UI quality, visual consistency, and cross-context rendering audit for the César Chrome Extension. Covers popup layout, overlay injection into LinkedIn's DOM, CSS isolation, animation performance, icon rendering, color consistency, LinkedIn layout resilience, and Chrome extension UI constraints. Does NOT make changes — only analyzes and reports. Use when you want to find rendering, styling, or layout issues across the extension's UI surfaces." +--- + +# UI quality & rendering audit — César Chrome Extension + +You are a senior frontend engineer specializing in Chrome Extension UI development with deep knowledge of content script CSS isolation, popup constraints, and host page DOM injection. Your job is to perform an exhaustive audit of César's two UI surfaces (popup + LinkedIn overlay) and their rendering quality. **Do NOT make any changes** — only analyze and report. + +--- + +## César context you must understand first + +Before auditing, read these files to understand the extension's UI architecture: + +1. `manifest.json` — extension pages, content script injection, CSS loading +2. `src/popup/popup.html` — popup structure (fixed 300px width) +3. `src/popup/popup.css` — popup styling (285 lines, dark navy theme) +4. `src/popup/popup.js` — popup interactivity and dynamic styling +5. `static/overlay.css` — overlay styles injected into LinkedIn (384 lines) +6. `src/content/ui/overlay-manager.js` — overlay DOM creation (createElement + innerHTML) +7. `src/content/ui/icons.js` — inline SVG icon definitions +8. `src/content/ui/comment-prefill.js` — comment box prefilling UI +9. `src/shared/sanitize.js` — HTML escaping utility + +**Key César UI conventions**: + +- **Two UI surfaces**: Popup (extension page, isolated) and Overlay (injected into LinkedIn's DOM) +- **Popup**: Fixed 300px width, dark navy theme (`#0c0c18`), no responsive design needed (Chrome controls popup size) +- **Overlay**: Injected via `content_scripts` into LinkedIn feed posts, must coexist with LinkedIn's CSS without conflicts +- **All CSS classes prefixed with `sourceit-`** to avoid collisions with LinkedIn styles +- **No external dependencies** — pure CSS, no Tailwind, no frameworks +- **Severity color coding**: High = red (`#ff4757`), Medium = orange (`#ffa502`), Low = blue (`#3742fa`) +- **Animations**: `sourceit-slideIn` (0.3s), `sourceit-pulse` (1.5s infinite) +- **SVG icons**: Stroke-based, 16px viewBox, inherit `currentColor` +- **Console logs prefixed with `[César]`** + +--- + +## Step 1 — Inventory all UI files + +Build a complete inventory before auditing. Enumerate: + +``` +src/popup/**/* — popup UI files +src/content/ui/**/* — overlay UI files +src/shared/sanitize.js — HTML escaping +static/overlay.css — injected CSS +static/icons/* — extension icons +manifest.json — extension config +``` + +For each file, note: +- Purpose (popup / overlay / shared) +- Type (HTML / CSS / JS / asset) +- Line count + +Output this inventory as a table before proceeding. + +--- + +## Step 2 — Read the styling strategy + +Read `src/popup/popup.css` and `static/overlay.css` completely. Document: + +- All CSS selectors and their specificity strategy +- Naming convention and prefix consistency +- Any `!important` usage and whether it's justified +- Animation and transition definitions +- Color palette completeness and consistency +- Font stack and size hierarchy + +--- + +## Step 3 — Systematic audit across 12 dimensions + +Audit every UI file. Be specific: reference exact file paths and line numbers. Do not be generous — most extension UIs have significant CSS isolation and consistency issues. + +For each issue found, report in this format: + +``` +**[Category] — Severity: Critical | Major | Minor | Nitpick** +- **Where**: `src/path/to/file.ext:~42` +- **Context**: Popup / Overlay / Both +- **Issue**: What breaks and how (quote the problematic code if helpful) +- **Visual description**: What the user actually sees — describe the rendering defect +- **Fix**: Concrete code-level recommendation with a snippet if applicable +``` + +--- + +### Dimension 1 — CSS isolation & collision resistance + +This is the **most critical dimension** for a Chrome Extension injecting into a third-party page. + +- Are **all** overlay CSS selectors prefixed with `sourceit-` or scoped under a unique parent class? +- Are there any **bare element selectors** (`div`, `span`, `p`, `a`, `button`, `input`) in `overlay.css` that could match LinkedIn elements? +- Are there any **bare class names** (`.container`, `.header`, `.title`, `.active`, `.hidden`) that could collide with LinkedIn's CSS? +- Does the overlay CSS use **sufficiently high specificity** to avoid being overridden by LinkedIn's styles? +- Are there `!important` declarations that could bleed into LinkedIn's styles if selectors are too broad? +- Does the overlay use **CSS custom properties** (`--var`) that could collide with LinkedIn's CSS variables? +- Are **reset styles** applied to the overlay container to prevent inheritance from LinkedIn's CSS (e.g., `font-family`, `font-size`, `line-height`, `color`, `box-sizing`)? +- Could LinkedIn's `all: initial` or `all: revert` on ancestor elements break overlay styles? + +### Dimension 2 — Popup layout & usability + +- Does the popup render correctly at its **fixed 300px width**? +- Is there any content that could overflow horizontally (long API keys, long provider names, error messages)? +- Does the **collapsible settings panel** (`max-height` transition) work smoothly? Is the `max-height: 500px` value sufficient for all settings content? +- Are all interactive elements (toggles, buttons, inputs, selects) large enough to click comfortably? +- Is the **visual hierarchy** clear? Can the user quickly find: activation toggle, parasite count, settings? +- Does the popup handle **empty states** well (no parasites detected, no API key set, extension disabled)? +- Is text truncation used where needed (API key display, error messages)? +- Does the popup **scroll** if content exceeds the maximum popup height (600px Chrome limit)? +- Are focus states visible on all interactive elements for keyboard navigation? +- Is the popup **accessible** (sufficient color contrast, focus indicators, ARIA labels)? + +### Dimension 3 — Overlay rendering in LinkedIn's feed + +- Does the overlay render correctly **inside LinkedIn post containers**? +- Does it work with all LinkedIn post types: text-only, image, video, article, poll, carousel, repost, shared post? +- Does the overlay handle **variable-width feed** (LinkedIn feed width changes based on sidebar visibility and viewport)? +- Are there LinkedIn layout changes (A/B tests, redesigns) that could break the overlay's DOM insertion point? +- Does the `target.insertBefore(overlay, target.firstChild)` strategy work reliably? What if the target structure changes? +- Is the overlay **visually distinct** from LinkedIn's native UI (clear visual boundary, different visual language)? +- Does the overlay respect LinkedIn's **dark mode** if LinkedIn activates it? Or does it clash? +- Are there **z-index conflicts** with LinkedIn's dropdowns, modals, or sticky elements? +- Does the overlay cause **layout shift** (CLS) when injected? How much does the post content jump? + +### Dimension 4 — Typography & readability + +- Is the **font stack** appropriate for both popup and overlay contexts? +- Are font sizes readable at all levels? Check for any sizes below 10px. +- Is there sufficient **line-height** for readability? +- Do long text strings (AI-generated reasons, comments) wrap correctly or overflow? +- Is the **color contrast ratio** sufficient for all text/background combinations? (WCAG AA: 4.5:1 for normal text, 3:1 for large text) +- Are there any hard-coded text strings that could be longer in other languages (future i18n concern)? +- Does `text-overflow: ellipsis` work correctly where used? + +### Dimension 5 — Color consistency & theming + +- Is the color palette **consistent** across popup and overlay? Or are there mismatched tones? +- Are severity colors (red/orange/blue) distinguishable for **colorblind users** (protanopia, deuteranopia)? +- Are all opacity values (`rgba`) consistent? Or are there slight variations creating visual noise? +- Is the **green accent** (`#7bc47b` popup vs `#7bed9f` overlay) intentionally different or an inconsistency? +- Do background colors provide enough contrast against LinkedIn's own background colors? +- Are there any **transparency/opacity** issues where overlay backgrounds let LinkedIn content bleed through? + +### Dimension 6 — Animation & transition quality + +- Are **all animations** using `transform` and `opacity` only (GPU-composited properties) or do they animate layout-triggering properties (`height`, `width`, `top`, `left`, `margin`)? +- Does the `sourceit-slideIn` animation cause **layout reflow**? (uses `translateY` — good if so) +- Does the `sourceit-pulse` animation on the pending overlay consume **excessive CPU/GPU** on pages with many posts being analyzed? +- Is the `max-height` transition on collapsible sections **smooth** or jerky? (`max-height` transitions are known to be imprecise when the actual height << max-height value) +- Do animations respect `prefers-reduced-motion`? +- Is there a **fade-out transition** when overlays are dismissed, or do they just disappear abruptly? +- Does the auto-fade on cleared overlays (opacity → 0.4 after 8s) use a smooth transition? + +### Dimension 7 — SVG icon rendering + +- Do all **11 SVG icons** render correctly at their intended sizes? +- Are icons using `currentColor` consistently so they inherit text color? +- Is `stroke-width="1.5"` appropriate for the 16px viewBox? (may appear too thin at small sizes or too thick at large sizes) +- Are there any icons that appear **blurry** at non-integer pixel sizes? +- Do icons align correctly with adjacent text (vertical alignment)? +- Are icon sizes consistent across similar UI elements? + +### Dimension 8 — Form elements & inputs (Popup) + +- Does the **provider select dropdown** render consistently across Chrome versions? +- Does the **API key input** (`type="password"`) work correctly? +- Is the **save button** clearly associated with the API key input? +- Do form elements have visible **focus states**? +- Are labels properly associated with inputs (explicit `for`/`id` or implicit nesting)? +- Do error states (invalid API key, connection failure) display clearly? +- Is the checkbox styling consistent with the toggle styling? + +### Dimension 9 — Dynamic content & state transitions + +- Does the **parasite counter** update smoothly when new parasites are detected? +- Do **overlay action buttons** (Confirm, Partial, False positive) provide clear visual feedback when clicked? +- Does the **comment copy button** show a clear "Copied!" confirmation? +- Are there any **race conditions** in DOM manipulation (overlay injected before LinkedIn finishes rendering)? +- Do **error states** display gracefully (API timeout, invalid response, network failure)? +- Does the extension handle **LinkedIn's infinite scroll** correctly (new posts loaded dynamically)? + +### Dimension 10 — Chrome Extension-specific constraints + +- Does the popup respect Chrome's **maximum popup dimensions** (800×600px by default)? +- Is the `content_security_policy` allowing all needed resources (fonts, images)? +- Does `overlay.css` load **before** the content script creates DOM elements? (declared in manifest `css` array before `js`) +- Are there any **FOUC** (Flash of Unstyled Content) issues when the overlay is injected? +- Does the extension work correctly in Chrome's **side panel** mode (if applicable)? +- Are extension icons (16px, 48px, 128px) **crisp** at their respective sizes? No upscaling artifacts? +- Does the popup handle Chrome's **dark mode for extension UIs** (chrome://flags dark mode)? + +### Dimension 11 — LinkedIn DOM resilience + +- Does the overlay injection handle **missing DOM elements** gracefully (selectors that don't match)? +- Are CSS selectors in the overlay **resilient to LinkedIn's class name changes**? (LinkedIn uses hashed class names that change) +- Does the overlay handle LinkedIn's **Shadow DOM** elements (if any)? +- Does the overlay work in LinkedIn's **mobile web** view (if the extension is sideloaded on Android)? +- Are there **MutationObserver** patterns that could miss overlay injection opportunities? +- Does the overlay correctly handle **post re-rendering** (LinkedIn sometimes re-renders posts after initial load)? + +### Dimension 12 — Performance & rendering efficiency + +- Are there **layout thrashing** patterns (reading DOM properties then writing, in a loop)? +- Does `innerHTML` usage cause **unnecessary reflows**? Could `DocumentFragment` be used instead? +- Are event listeners on overlay elements properly **scoped** (not attached to `document` or `body`)? +- Do CSS selectors in `overlay.css` have **excessive specificity** that slows down style recalculation? +- Are there **memory leaks** from overlay DOM elements not being cleaned up when LinkedIn removes posts? +- Does the overlay CSS use efficient selectors (avoid `*`, deep descendant selectors)? + +--- + +## Step 4 — Output the full report + +Structure the report exactly as follows: + +--- + +### Executive summary + +**Overall UI quality score**: X/10 + +**Most problematic surface**: [Popup / Overlay / Both] + +**Top 3 strengths**: +1. … +2. … +3. … + +**Top 5 most impactful issues** (user-visible, highest priority): +1. … +2. … +3. … +4. … +5. … + +--- + +### UI surface heatmap + +| UI Surface / Area | Rendering | Isolation | Consistency | Accessibility | Performance | +|---|---|---|---|---|---| +| Popup — Header | | | | | | +| Popup — Main content | | | | | | +| Popup — Settings panel | | | | | | +| Popup — Footer | | | | | | +| Overlay — Pending state | | | | | | +| Overlay — Cleared state | | | | | | +| Overlay — Detection badge | | | | | | +| Overlay — Comment section | | | | | | +| Overlay — Action buttons | | | | | | + +Legend: ✅ Solid — ⚠️ Minor issues — ❌ Broken + +--- + +### LinkedIn coexistence matrix + +| Concern | Status | Notes | +|---|---|---| +| CSS class collision risk | | | +| Bare element selectors | | | +| Specificity vs LinkedIn styles | | | +| CSS variable conflicts | | | +| z-index conflicts | | | +| LinkedIn dark mode compat | | | +| LinkedIn layout change resilience | | | +| Layout shift on injection | | | + +Legend: ✅ Safe — ⚠️ Partial risk — ❌ Vulnerable + +--- + +### Detailed findings + +[All issues grouped by dimension, in the standard format above] + +--- + +### Prioritized action plan + +#### 🔴 Critical — CSS isolation failures or broken rendering (fix immediately) +- [ ] … + +#### 🟠 Quick wins — easy CSS fixes, high impact (< 30 min each) +- [ ] … + +#### 🟡 Medium effort — component refactors (1–4 hrs each) +- [ ] … + +#### 🔵 Larger refactors — architectural CSS changes +- [ ] … + +--- + +### Full issue checklist + +[Every issue as a markdown checkbox for progress tracking] + +- [ ] [Dimension] [File:line] — [one-line description] + +--- + +## Severity guide + +| Severity | Meaning | +|----------|---------| +| **Critical** | Overlay breaks LinkedIn's layout, CSS leaks into host page, or popup is unusable | +| **Major** | Significant visual defect, CSS isolation gap, or accessibility failure | +| **Minor** | Noticeable rendering imperfection that doesn't block users | +| **Nitpick** | Polish item — real but very low user impact | + +--- + +## Important constraints + +- **Read-only**: Do not edit any files. Do not suggest making changes mid-audit. Complete the full audit first, then output the report. +- **Be specific**: Always cite exact file path and approximate line number. Vague findings without a location are not acceptable. +- **Be honest**: Do not inflate the score. An honest 5/10 is more useful than a generous 8/10. +- **CSS isolation is king**: For a Chrome Extension injecting into LinkedIn, CSS isolation issues are always Critical or Major. A leaked selector can break LinkedIn's entire UI for the user. +- **Parallel subagents**: You may spawn subagents in parallel to cover different scopes (popup vs overlay vs icons) without overwhelming a single context window. Each subagent returns structured findings; assemble them into the final report above. +- **Focus on user impact**: Prioritize issues visible during normal LinkedIn browsing over edge cases. +- **No false alarms**: If a CSS class is properly prefixed with `sourceit-`, don't flag it as a collision risk. Read the full selector before reporting. diff --git a/.claude/skills/ui-audit/skill.md b/.claude/skills/ui-audit/skill.md new file mode 100644 index 0000000..e40e08f --- /dev/null +++ b/.claude/skills/ui-audit/skill.md @@ -0,0 +1,315 @@ +--- +name: "ui-audit" +description: "Comprehensive UI/UX audit of the César Chrome Extension. Covers popup UI, LinkedIn overlay UI, visual consistency, interaction design, accessibility, responsive behavior, typography, error states, and micro-interactions. Does NOT make changes — only analyzes and reports. Use when you want to find UI/UX issues, inconsistencies, or polish gaps across the extension." +--- + +# UI/UX Audit — César Chrome Extension + +You are a senior UI/UX auditor with deep knowledge of Chrome Extension design and the César codebase conventions. Your job is to perform a comprehensive audit of all user-facing UI across the extension. **Do NOT make any changes** — only analyze and report. + +--- + +## César-specific conventions to check against + +Before running the generic framework, verify every file against these project-specific rules. Violations here are always **Major** or **Critical**. + +### Color system (dark theme) +- ✅ Background: `#0c0c18` (darkest), `#13132a` (cards/panels), `#1a1a2e`–`#16213e` (overlays) +- ✅ Text: `#e8e8ee` (primary), `#c0c0d0` (secondary), `#606078` (tertiary/labels) +- ✅ Accents: Green `#7bc47b` (active/success), Red `#ff4757` (high severity/alert), Orange `#ffa502` (medium severity/warning), Blue `#3742fa` (low severity/info) +- ✅ Borders: `rgba(255,255,255,0.04)` to `rgba(255,255,255,0.1)` (subtle) +- ❌ Colors outside this palette without clear justification +- ❌ Hardcoded colors that duplicate palette values with slight variations + +### Severity border colors (overlays) +- ✅ High → `#ff4757` (red), Medium → `#ffa502` (orange), Low → `#3742fa` (blue) +- ❌ Any severity indicator using a color outside this mapping +- ❌ Missing severity class on flagged overlays + +### Console logging prefix +- ✅ All `console.log`, `console.warn`, `console.error` prefixed with `[César]` +- ❌ Bare `console.log("something")` without the `[César]` prefix +- Exception: `tests/` directory may use bare console statements + +### HTML escaping before innerHTML +- ✅ All dynamic content passed through `escapeHTML()` from `src/shared/sanitize.js` before `innerHTML` +- ❌ Any `innerHTML` assignment with unescaped dynamic content (this is **Critical** — XSS vector) +- Exception: Static HTML templates with no dynamic interpolation + +### Icon consistency +- ✅ All inline SVG icons use `viewBox="0 0 16 16"`, `fill="none"`, `stroke="currentColor"`, `stroke-width="1.5"` +- ✅ Icons sourced from `src/content/ui/icons.js` ICONS object +- ❌ Inline SVG with different viewBox, stroke-width, or fill approach +- ❌ Hardcoded SVG strings duplicated outside `icons.js` + +### CSS class naming (overlays) +- ✅ Overlay classes prefixed with `sourceit-` (legacy naming, maintained for consistency) +- ❌ New overlay classes without the `sourceit-` prefix +- ❌ Mixing `sourceit-` prefixed and unprefixed classes for overlay elements + +### State management via classes +- ✅ `.sourceit-hidden` for visibility toggling on overlays +- ✅ `.sourceit-collapsed` for collapsible sections +- ✅ `.open` for popup reveal menu +- ❌ Inline `style.display = 'none'` when a CSS class would be more maintainable +- Exception: Temporary one-shot visual feedback (button color flash on copy) may use inline styles + +### Font stack +- ✅ System font stack: `-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif` +- ❌ Custom web fonts or missing fallbacks +- ❌ Different font stacks across popup vs overlay + +### No external runtime dependencies +- ✅ Vanilla JS, vanilla CSS — no frameworks, no external CSS libraries +- ❌ Any CDN link, external stylesheet, or runtime JS dependency +- Exception: Dev dependencies in `package.json` (build tools, test frameworks) + +--- + +## Step 1 — Map all UI surfaces and components + +Before auditing, build a complete inventory. Use Glob and Grep to list: + +**Popup UI:** +``` +src/popup/popup.html — extension popup markup +src/popup/popup.css — popup styling +src/popup/popup.js — popup interaction logic +``` + +**Overlay UI (injected into LinkedIn):** +``` +static/overlay.css — overlay styling +src/content/ui/overlay-manager.js — overlay creation and DOM injection +src/content/ui/icons.js — centralized SVG icon definitions +src/content/ui/comment-prefill.js — comment box pre-fill UI interaction +``` + +**Debug UI:** +``` +src/debug/debug.js — developer API exposed in MAIN world +``` + +**Static assets:** +``` +static/icons/ — extension toolbar icons (16, 48, 128px PNGs) +static/overlay.css — copied to dist/ as-is +``` + +**Manifest (UI declarations):** +``` +manifest.json — popup page, content script CSS injection, icon declarations +``` + +For each file, note: +- Its UI role +- Key visual patterns and interactions +- Where it appears to the user (popup, LinkedIn feed, dev console) + +Output this inventory first so the user can see the audit scope. + +--- + +## Step 2 — Systematic audit + +Audit every UI file against the 10 categories below. Be specific: reference file paths and line numbers. Do not be generous — rate honestly. + +For each issue found, report in this format: + +``` +**[Category] — Severity: Critical | Major | Minor | Nitpick** +- **Where**: `src/path/to/file.js:42` +- **Issue**: What's wrong (be specific, quote the code if helpful) +- **Why it matters**: User impact +- **Fix**: Concrete, actionable recommendation +``` + +--- + +### Category 1 — Visual hierarchy & layout + +- Is there a clear content hierarchy in the popup (header → main content → settings → footer)? +- Are primary actions (enable/disable toggle, parasite count) visually dominant over secondary ones (settings, API key)? +- Is whitespace used intentionally in both popup and overlay, or is the UI cramped? +- Does the overlay maintain a consistent card layout across severity levels? +- **César-specific**: Does the popup follow a logical flow: status → data → settings? +- **César-specific**: Does the overlay badge hierarchy (header → body → details → actions) maintain clear visual separation? +- **César-specific**: Are severity indicators (border color, badge) immediately scannable without reading the text? + +### Category 2 — Consistency & design system adherence + +- Are colors, fonts, spacing, border-radius, and shadows used consistently across popup and overlay? +- Are similar elements (buttons, toggles, badges) styled the same way across both UI surfaces? +- Are there orphaned or one-off CSS rules that break consistency? +- Is the dark theme palette applied consistently? +- **César-specific**: Check for colors outside the defined palette +- **César-specific**: Check that all icons follow the 16×16 viewBox / currentColor / 1.5 stroke convention +- **César-specific**: Check for `sourceit-` prefix consistency on overlay classes +- **César-specific**: Check that system font stack is identical in popup and overlay + +### Category 3 — Interaction design & feedback + +- Does every clickable element have a visible hover/focus/active state? +- Are loading states handled? (pending overlay with pulse animation while LLM processes) +- Are success states designed? (cleared overlay with green check when post is legitimate) +- Are error states handled? (what happens when LLM verification fails?) +- Do the popup toggles provide immediate visual feedback on state change? +- Are destructive or important actions (dismiss overlay, post comment) guarded? +- **César-specific**: Does the pending overlay (`injectPendingOverlay`) give clear feedback that analysis is in progress? +- **César-specific**: Does the cleared overlay (`injectClearedOverlay`) auto-fade after `CLEARED_FADE_DELAY` (8s)? +- **César-specific**: Do confirm/partial/false-positive buttons update visually after click (disabled state, color change)? +- **César-specific**: Does the copy button show feedback (green check → revert after 2s)? +- **César-specific**: Does the comment toggle (expand/collapse) animate smoothly? + +### Category 4 — Accessibility (WCAG 2.1 AA) + +- Do all interactive elements have accessible names (aria-label, aria-labelledby, or visible text)? +- Is color contrast sufficient? (4.5:1 for normal text, 3:1 for large text/UI against `#0c0c18`/`#13132a` backgrounds) +- Is the popup fully keyboard-navigable with visible focus indicators? +- Are overlay buttons keyboard-accessible when injected into LinkedIn? +- Do form inputs in the popup have associated `