CodeVetter · Repo Unpack · Contributor handoff
nextlevelbuilder/ui-ux-pro-max-skill
Read CLAUDE.md first — it documents the src/ source-of-truth rule and the sync contract. Edit data/scripts/templates only under src/ui-ux-pro-max/, then run `cd cli && npm run sync:assets && npm run check:assets`. Never edit cli/assets/ or .claude/skills/ui-ux-pro-max/{data,scripts} directly (mirrored), but DO edit .claude/skills/ui-ux-pro-max/SKILL.md by hand (it is not generated). The Python layer is stdlib-only — no pip installs. Gate everything through `npm --prefix cli run verify:data` which runs both validators, unittest discovery, the relevance evaluator, both smoke suites, and the asset-sync check.
- Canonical edit boundary: modify CSVs under src/ui-ux-pro-max/data/, Python under src/ui-ux-pro-max/scripts/, templates under src/ui-ux-pro-max/templates/ — then `npm run sync:assets`; the two mirror trees (cli/assets/, .claude/skills/ui-ux-pro-max/{data,scripts}) are regenerated, never hand-edited.
- Exception to the mirror rule: .claude/skills/ui-ux-pro-max/SKILL.md is hand-authored and NOT synced — edit it directly; sync-assets.mjs only mirrors its data/ and scripts/ subdirs.
- Verify loop for any data/script change: `npm --prefix cli run verify:data` = validate:csv + validate:semantic + validate:agent-guide + validate:catalog-summary + unittest discovery + evaluate:relevance + smoke:domains + smoke:stacks + check:assets.
- When changing CSV row counts or advertised numbers (styles, palettes, fonts, stacks), regenerate catalog-summary.json via scripts/generate-catalog-summary.py and expect validate-agent-guide.py to recompute the SKILL.md/template description string — stale counts fail CI.
- Git workflow: never push to main; branch feat/... or fix/..., PR via gh; commits use Conventional Commits because release.yml runs semantic-release (conventionalcommits preset) that versions and publishes the CLI automatically.
- Known trap — path contract: skill docs must use skill-relative script paths ('scripts/search.py', '../<skill>/scripts/...'); ~/.claude/skills/, .claude/skills/, $HOME/, and ${CLAUDE_PLUGIN_ROOT} forms are grep-rejected by CI except in the core SKILL.md.
- Known trap — Windows/cp1252: search.py and design_system.py rewrap stdout/stderr to UTF-8 at import because emoji/box-drawing output crashes on the Windows default encoding; preserve that block when editing.
- Known trap — line endings: catalog-summary.json pins sha256 hashes of LF-normalized data and .gitattributes forces eol=lf on data files; committing CRLF data or bypassing .gitattributes breaks the hash check on other platforms.
- Known trap — abstention is intentional: a 0-result search is a feature (calibrated thresholds + suggestions), so don't 'fix' empty results by lowering thresholds without updating the relevance baseline and thresholds fixture.
- Files to read first for search changes: core.py (engine + registries), design_system.py (aggregator + persistence), reasoning_contract.py (rule grammar), then test_core.py + test_data_contracts.py to see the locked invariants; for installer changes: template.ts, types/index.ts, detect.ts, one platform JSON.
- cli/assets/ is .gitignore-adjacent generated output bundled into the npm package ('files': ['dist','assets']); the dry-run e2e specs import TS directly from src/, so CLI tests run without building dist first.
- CLI dev workflow: `npm run dev` runs via bun, `npm run build` prefers `bun build --target node` and falls back to node_modules tsc; `npm run typecheck` is tsc --noEmit; Playwright e2e needs `npx playwright install --with-deps chromium`.