Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Phase 5 is complete — updates and distribution. See `dev_docs/MASTER-PLAN.md`
- **Installer** — `npx pixelslop install` is interactive by default. It detects Claude Code and Codex CLI, lets the user pick runtimes and scope, supports project-local Codex installs in `.codex/`, rewrites paths, configures MCP, and installs skills via symlink or copy. `npx pixelslop@latest update` upgrades the installed runtime set with backup + diff.
- **CI/CD** — GitHub Actions for CI (Node 18/20/22) and automated releases via release-please + npm publish with OIDC provenance.
- **Orchestrator** — coordinates the full scan→fix→verify workflow. Spawns subagents, manages user interaction, groups findings by category, handles PARTIAL results. Supports `--personas` and `--thorough` flags.
- **Scanner** — evaluates pages across 3 viewports, scores 5 pillars, detects 25 slop patterns, runs persona evaluation from 8 user perspectives. Tested on 7 pages, scores stable within ±1.
- **Scanner** — evaluates pages across 3 viewports, scores 5 pillars, detects 26 slop patterns, runs vision-first persona evaluation (the page-relevant subset of 8 built-ins, plus any project persona). Tested on 7 pages, scores stable within ±1.
- **Persona evaluation** — 8 built-in personas (screen-reader-user, low-vision-user, keyboard-user, rushed-mobile-user, slow-connection-user, non-native-english, design-critic, first-time-visitor). Extensible JSON format supports custom personas.
- **Fixer** — takes a scanner finding, locates the source code, creates a checkpoint via `pixelslop-tools`, applies the smallest viable fix.
- **Checker** — re-measures the targeted metric after a fix, compares before/after, returns PASS/FAIL/PARTIAL. Updates plan via `pixelslop-tools`.
Expand Down Expand Up @@ -137,7 +137,7 @@ Agents use `pixelslop-tools` (bin/pixelslop-tools.cjs) for all state operations.
- **`scan trend`** reports the score progression across runs. `scan save-results` now appends each run's /20 total (plus per-pillar scores) to `.pixelslop/scan-history.json`; `scan trend [--target <url>] [--last <n>]` reads it back (`11 -> 13 -> 14 (+3)`). History is best-effort — a corrupt history file self-heals and never blocks the actual save. The orchestrator surfaces the trend in its scan summary.
- **`personas write` / `personas list`** manage project-specific personas. `write --json '<persona>'` validates (required fields, slug-only id, no built-in collision, no path traversal) and saves to `.pixelslop/personas/<id>.json`; `list` returns the 8 built-ins plus any custom ones. The orchestrator generates 1-2 personas from the project's audience/brand and evaluates them alongside the built-ins, so persona findings fit the real users instead of only the generic profiles.
- **`doctor`** self-checks the install: reports the version, confirms `pixelslop-tools.cjs` is reachable, and flags when a newer version is published (a throttled npm check, cached 24h in `.pixelslop-doctor-cache.json`, fail-soft offline). The skill runs it at preflight — if it can't run, the install is broken/stale and the skill tells the user to `npx pixelslop@latest update`; if it reports `stale`, the skill surfaces the update once and continues. This is what makes a stale/broken install self-diagnose instead of failing opaquely.
- **`config write --register brand|product`** stores the project's **register** — a `## Register` section in `.pixelslop.md`. Register frames the whole review: a `brand` surface (landing, marketing, campaign) is judged on distinctiveness and emotional pull; a `product` surface (app, dashboard, tool) on clarity and low friction. `config write` validates it (bare `brand`/`product`, junk is dropped) and `config read` round-trips it. It calibrates **only** the design-director's judgment pass — the 6 measured pillars stay register-blind, because a 90-char line or a 3:1 contrast ratio is a defect on any surface. The setup agent forms a register hypothesis from route/component signals and confirms it with a leading question.
- **`config write --register brand|product`** stores the project's **register** — a `## Register` section in `.pixelslop.md`. Register frames the whole review: a `brand` surface (landing, marketing, campaign) is judged on distinctiveness and emotional pull; a `product` surface (app, dashboard, tool) on clarity and low friction. `config write` validates it (bare `brand`/`product`, junk is dropped) and `config read` round-trips it. It calibrates **only** the design-director's judgment pass — the 5 measured pillars stay register-blind, because a 90-char line or a 3:1 contrast ratio is a defect on any surface. The setup agent forms a register hypothesis from route/component signals and confirms it with a leading question.

## Design Detectors & Report Provenance

Expand All @@ -153,7 +153,7 @@ The measured /20 is the objective backbone; the perceptual layer is how the page
- **Personas ground in behavior, not just the still.** Beyond the three above-fold viewport shots, the persona evaluator reads `scroll.foldScreenshots` (the whole scrolled page) and the interaction evidence the collector already captured — `interactivePromises.results` (did the mobile menu open, did the anchor jump), `focusPass` (keyboard reachability + focus rings), `viewports.mobile.touchTargets`, `hoverStates`. So "would I bounce" is grounded in whether the flow *works*, not only how the hero looks. Each persona pulls the evidence its `designPriorities` care about; a null pass means it didn't run and must not be invented. All deterministic — it's evidence collected once, not the persona re-driving the browser.
- **Project persona sourcing (in priority order).** The tailored persona comes from the best available signal: (1) an explicit audience/brand description in `.pixelslop.md` (setup) — always wins; (2) failing that, a **hero-inference fallback** in Step 6a — if the desktop hero pitches a specific, nameable audience ("The product development system for teams and agents"), infer one persona from it, tagged as an unconfirmed hypothesis; (3) failing that, the built-ins. The fallback self-gates: a bare search box, app shell, or generic splash produces nothing (verified against Linear/Stripe/Airbnb heroes — sharp on the first two, correctly silent on Airbnb's search box). Text about the audience always beats a guess from pixels, so the fallback only fires when there was no text to begin with.
- **The Read co-headlines.** The design-director's verdict + the sharpest persona reactions lead the report: a `### The Read` section above the Scores, a `Reads as:` header line, a co-led scan summary (`Measured: X/20` **and** `Reads as: …`), and an HTML card next to the /20 (`{{PERCEPTUAL_READ}}`, from `scan.perceptualRead`). It's prose grounded in what was seen — **never a competing number.** A second "/10" would be judgment masquerading as measurement, the exact failure the measured/judgment split prevents.
- **The internal evaluator count is now 8** (6 pillars + design-director + persona). `evaluator.test.js` pins it.
- **The internal evaluator count is now 8** (5 measured pillars + slop classifier + design-director + persona). `evaluator.test.js` pins it. The slop evaluator returns a severity band, not a pillar score, so it never counts toward the /20 — that stays 5 pillars × 4.

## Voice & Persona

Expand Down
Loading