quiver-cli 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/cli.js +125 -43
- package/package.json +1 -1
- package/template/.agents/skills/agent-browser/SKILL.md +4 -9
- package/template/.agents/skills/apps/skybridge/SKILL.md +1 -1
- package/template/.agents/skills/code/improve/SKILL.md +9 -5
- package/template/.agents/skills/code/improve/references/audit-playbook.md +10 -10
- package/template/.agents/skills/code/improve/references/closing-the-loop.md +4 -3
- package/template/.agents/skills/code/improve/references/plan-template.md +5 -0
- package/template/.agents/skills/design/impeccable/SKILL.md +14 -24
- package/template/.agents/skills/design/impeccable/reference/animate.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/bolder.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/brand.md +2 -2
- package/template/.agents/skills/design/impeccable/reference/colorize.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/critique.md +6 -6
- package/template/.agents/skills/design/impeccable/reference/delight.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/distill.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/document.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/extract.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/hooks.md +90 -0
- package/template/.agents/skills/design/impeccable/reference/init.md +5 -5
- package/template/.agents/skills/design/impeccable/reference/live.md +16 -16
- package/template/.agents/skills/design/impeccable/reference/overdrive.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/polish.md +2 -2
- package/template/.agents/skills/design/impeccable/reference/quieter.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/shape.md +2 -2
- package/template/.agents/skills/design/impeccable/scripts/context-signals.mjs +1 -1
- package/template/.agents/skills/design/impeccable/scripts/context.mjs +724 -33
- package/template/.agents/skills/design/impeccable/scripts/critique-storage.mjs +1 -1
- package/template/.agents/skills/design/impeccable/scripts/detector/browser/injected/index.mjs +204 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/cli/main.mjs +57 -11
- package/template/.agents/skills/design/impeccable/scripts/detector/design-system.mjs +750 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/detect-antipatterns-browser.js +633 -46
- package/template/.agents/skills/design/impeccable/scripts/detector/detect-antipatterns.mjs +7 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/browser/detect-url.mjs +29 -4
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/regex/detect-text.mjs +43 -10
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +29 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/detect-html.mjs +27 -1
- package/template/.agents/skills/design/impeccable/scripts/detector/node/file-system.mjs +1 -1
- package/template/.agents/skills/design/impeccable/scripts/detector/registry/antipatterns.mjs +29 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/rules/checks.mjs +401 -46
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/inline-ignores.mjs +148 -0
- package/template/.agents/skills/design/impeccable/scripts/hook-admin.mjs +661 -0
- package/template/.agents/skills/design/impeccable/scripts/hook-before-edit.mjs +476 -0
- package/template/.agents/skills/design/impeccable/scripts/hook-lib.mjs +1632 -0
- package/template/.agents/skills/design/impeccable/scripts/hook.mjs +61 -0
- package/template/.agents/skills/design/impeccable/scripts/{design-parser.mjs → lib/design-parser.mjs} +8 -1
- package/template/.agents/skills/design/impeccable/scripts/lib/impeccable-config.mjs +638 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/impeccable-paths.mjs +128 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/target-args.mjs +42 -0
- package/template/.agents/skills/design/impeccable/scripts/live/browser-script-parts.mjs +49 -0
- package/template/.agents/skills/design/impeccable/scripts/{live-event-validation.mjs → live/event-validation.mjs} +6 -5
- package/template/.agents/skills/design/impeccable/scripts/live/manual-apply.mjs +939 -0
- package/template/.agents/skills/design/impeccable/scripts/live/manual-edit-routes.mjs +357 -0
- package/template/.agents/skills/design/impeccable/scripts/{live-manual-edits-buffer.mjs → live/manual-edits-buffer.mjs} +1 -1
- package/template/.agents/skills/design/impeccable/scripts/{live-session-store.mjs → live/session-store.mjs} +1 -1
- package/template/.agents/skills/design/impeccable/scripts/{live-ui-core.mjs → live/ui-core.mjs} +2 -1
- package/template/.agents/skills/design/impeccable/scripts/live/vocabulary.mjs +36 -0
- package/template/.agents/skills/design/impeccable/scripts/live-accept.mjs +3 -3
- package/template/.agents/skills/design/impeccable/scripts/live-browser-dom.js +146 -0
- package/template/.agents/skills/design/impeccable/scripts/live-browser.js +1456 -599
- package/template/.agents/skills/design/impeccable/scripts/live-commit-manual-edits.mjs +2 -2
- package/template/.agents/skills/design/impeccable/scripts/live-complete.mjs +2 -2
- package/template/.agents/skills/design/impeccable/scripts/live-discard-manual-edits.mjs +1 -1
- package/template/.agents/skills/design/impeccable/scripts/live-inject.mjs +35 -9
- package/template/.agents/skills/design/impeccable/scripts/live-insert.mjs +2 -2
- package/template/.agents/skills/design/impeccable/scripts/live-manual-edit-evidence.mjs +2 -2
- package/template/.agents/skills/design/impeccable/scripts/live-poll.mjs +18 -13
- package/template/.agents/skills/design/impeccable/scripts/live-resume.mjs +1 -1
- package/template/.agents/skills/design/impeccable/scripts/live-server.mjs +77 -1264
- package/template/.agents/skills/design/impeccable/scripts/live-status.mjs +2 -2
- package/template/.agents/skills/design/impeccable/scripts/live-target.mjs +30 -0
- package/template/.agents/skills/design/impeccable/scripts/live-wrap.mjs +4 -4
- package/template/.agents/skills/design/impeccable/scripts/live.mjs +73 -22
- package/template/.agents/skills/writing/humanizer/SKILL.md +621 -0
- package/template/.agents/upstreams.json +17 -8
- package/template/.agents/skills/apps/skybridge/references/architecture.md +0 -175
- package/template/.agents/skills/apps/skybridge/references/copy-template.md +0 -24
- package/template/.agents/skills/apps/skybridge/references/csp.md +0 -33
- package/template/.agents/skills/apps/skybridge/references/deploy.md +0 -33
- package/template/.agents/skills/apps/skybridge/references/discover.md +0 -84
- package/template/.agents/skills/apps/skybridge/references/download-file.md +0 -77
- package/template/.agents/skills/apps/skybridge/references/fetch-and-render-data.md +0 -151
- package/template/.agents/skills/apps/skybridge/references/oauth.md +0 -115
- package/template/.agents/skills/apps/skybridge/references/open-external-links.md +0 -71
- package/template/.agents/skills/apps/skybridge/references/prompt-llm.md +0 -20
- package/template/.agents/skills/apps/skybridge/references/publish.md +0 -19
- package/template/.agents/skills/apps/skybridge/references/run-locally.md +0 -51
- package/template/.agents/skills/apps/skybridge/references/state-and-context.md +0 -151
- package/template/.agents/skills/apps/skybridge/references/ui-guidelines.md +0 -205
- package/template/.agents/skills/design/impeccable/scripts/cleanup-deprecated.mjs +0 -284
- package/template/.agents/skills/design/impeccable/scripts/impeccable-paths.mjs +0 -126
- /package/template/.agents/skills/design/impeccable/scripts/{is-generated.mjs → lib/is-generated.mjs} +0 -0
- /package/template/.agents/skills/design/impeccable/scripts/{live-completion.mjs → live/completion.mjs} +0 -0
- /package/template/.agents/skills/design/impeccable/scripts/{live-insert-ui.mjs → live/insert-ui.mjs} +0 -0
- /package/template/.agents/skills/design/impeccable/scripts/{live-svelte-component.mjs → live/svelte-component.mjs} +0 -0
- /package/template/.agents/skills/design/impeccable/scripts/{live-sveltekit-adapter.mjs → live/sveltekit-adapter.mjs} +0 -0
|
@@ -60,7 +60,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
|
|
|
60
60
|
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
|
|
61
61
|
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
|
|
62
62
|
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
|
|
63
|
-
- Don't converge across projects.
|
|
63
|
+
- Don't converge across projects. Each brand surface differentiates from the last.
|
|
64
64
|
- When a cultural-symbol palette is the obvious pull, reach past it. Let the cultural reading come from typography, imagery, and copy, not the palette.
|
|
65
65
|
|
|
66
66
|
## Layout
|
|
@@ -74,7 +74,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
|
|
|
74
74
|
|
|
75
75
|
Brand surfaces lean on imagery. A restaurant, hotel, magazine, or product landing page without any imagery reads as incomplete, not as restrained. A solid-color rectangle where a hero image should go is worse than a representative stock photo.
|
|
76
76
|
|
|
77
|
-
**When the brief implies imagery
|
|
77
|
+
**When the brief implies imagery, you must ship imagery.** Zero images is a bug, not a design choice. "Restraint" is not an excuse. If the approved comp or brief is image-led, ship real project assets, generated raster assets, or a credible canvas/SVG/WebGL scene. Do not replace photographic, architectural, product, or place imagery with generic CSS panels, decorative diagrams, cards, bullets, or copy.
|
|
78
78
|
|
|
79
79
|
- **For greenfield work without local assets, use stock imagery.** Unsplash is the default. The URL shape is `https://images.unsplash.com/photo-{id}?auto=format&fit=crop&w=1600&q=80`. **Verify the URLs before referencing them.** If you have an image-search MCP, web-fetch tool, or browser access, use it to find real photo IDs and confirm they resolve. Guessed IDs (even ones that look real) often 404 and ship as broken-image placeholders. Without a verification path, pick fewer photos you're confident exist over more that you guessed; never substitute colored `<div>` placeholders.
|
|
80
80
|
- **Search for the brand's physical object**, not the generic category: "handmade pasta on a scratched wooden table" beats "Italian food"; "cypress trees above a limestone hotel facade at dusk" beats "luxury hotel".
|
|
@@ -30,7 +30,7 @@ Analyze the current state and identify opportunities:
|
|
|
30
30
|
- **Wayfinding**: Helping users navigate and understand structure
|
|
31
31
|
- **Delight**: Moments of visual interest and personality
|
|
32
32
|
|
|
33
|
-
If any of these are unclear from the codebase,
|
|
33
|
+
If any of these are unclear from the codebase, ask the user directly to clarify what you cannot infer.
|
|
34
34
|
|
|
35
35
|
**CRITICAL**: More color ≠ better. Strategic color beats rainbow vomit every time. Every color should have a purpose.
|
|
36
36
|
|
|
@@ -20,7 +20,7 @@ Resolve one stable target, run two independent assessments, synthesize a design
|
|
|
20
20
|
- "this page" -> the current URL or source file
|
|
21
21
|
2. **Compute the slug**:
|
|
22
22
|
```bash
|
|
23
|
-
node .
|
|
23
|
+
node .pi/skills/impeccable/scripts/critique-storage.mjs slug "<resolved-path-or-url>"
|
|
24
24
|
```
|
|
25
25
|
Keep it. If the command exits non-zero, skip persistence and trend for this run, but continue the critique.
|
|
26
26
|
3. **Read `.impeccable/critique/ignore.md`** if it exists. Drop matching findings silently; it is the only prior-run input critique consumes.
|
|
@@ -50,7 +50,7 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|
|
50
50
|
|
|
51
51
|
CLI scan:
|
|
52
52
|
```bash
|
|
53
|
-
node .
|
|
53
|
+
node .pi/skills/impeccable/scripts/detect.mjs --json [target]
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
|
@@ -64,7 +64,7 @@ Browser visualization is required for a viewable target when browser automation
|
|
|
64
64
|
1. Create a fresh tab and navigate.
|
|
65
65
|
2. Preflight mutable injection by setting `document.title` and appending a `<script>` tag. Read-only evaluate APIs do not count.
|
|
66
66
|
3. If mutation is unavailable, skip live server, browser presentation, and injection; report fallback signal.
|
|
67
|
-
4. If mutation is available, start `node .
|
|
67
|
+
4. If mutation is available, start `node .pi/skills/impeccable/scripts/live-server.mjs --background`, present the browser if supported, label `[Human]`, scroll top, inject `http://localhost:PORT/detect.js`, wait 2-3 seconds, read `impeccable` console messages, then stop the live server.
|
|
68
68
|
5. For multi-view targets, inject on 3-5 representative pages.
|
|
69
69
|
|
|
70
70
|
Return: CLI findings JSON/counts, browser console findings if applicable, false positives, and skipped/failed browser steps with concrete reasons.
|
|
@@ -166,7 +166,7 @@ Skip this step if the Setup slug was null (vague or root-level target).
|
|
|
166
166
|
2. **Pass the structured metadata** through `IMPECCABLE_CRITIQUE_META` (JSON), then run the write command:
|
|
167
167
|
```bash
|
|
168
168
|
IMPECCABLE_CRITIQUE_META='{"target":"<user phrasing>","total_score":<n>,"p0_count":<n>,"p1_count":<n>}' \
|
|
169
|
-
node .
|
|
169
|
+
node .pi/skills/impeccable/scripts/critique-storage.mjs write <slug> <body-file>
|
|
170
170
|
```
|
|
171
171
|
The helper prints the absolute path it wrote.
|
|
172
172
|
|
|
@@ -174,7 +174,7 @@ Skip this step if the Setup slug was null (vague or root-level target).
|
|
|
174
174
|
|
|
175
175
|
4. **Read the trend** for context:
|
|
176
176
|
```bash
|
|
177
|
-
node .
|
|
177
|
+
node .pi/skills/impeccable/scripts/critique-storage.mjs trend <slug> 5
|
|
178
178
|
```
|
|
179
179
|
This returns a JSON array of the last 5 frontmatter entries (including the one you just wrote).
|
|
180
180
|
|
|
@@ -189,7 +189,7 @@ This is fire-and-forget. Do not show the user the helper's JSON output; only the
|
|
|
189
189
|
|
|
190
190
|
### Ask the User
|
|
191
191
|
|
|
192
|
-
**After presenting findings**, use targeted questions based on what was actually found.
|
|
192
|
+
**After presenting findings**, use targeted questions based on what was actually found. ask the user directly to clarify what you cannot infer. These answers will shape the action plan.
|
|
193
193
|
|
|
194
194
|
Ask questions along these lines (adapt to the specific findings; do NOT ask generic questions):
|
|
195
195
|
|
|
@@ -37,7 +37,7 @@ Identify where delight would enhance (not distract from) the experience:
|
|
|
37
37
|
- **Helpful surprises**: Anticipating needs before users ask (productivity tools)
|
|
38
38
|
- **Sensory richness**: Satisfying sounds, smooth animations (creative tools)
|
|
39
39
|
|
|
40
|
-
If any of these are unclear from the codebase,
|
|
40
|
+
If any of these are unclear from the codebase, ask the user directly to clarify what you cannot infer.
|
|
41
41
|
|
|
42
42
|
**CRITICAL**: Delight should enhance usability, never obscure it. If users notice the delight more than accomplishing their goal, you've gone too far.
|
|
43
43
|
|
|
@@ -21,7 +21,7 @@ Analyze what makes the design feel complex or cluttered:
|
|
|
21
21
|
- What can be removed, hidden, or combined?
|
|
22
22
|
- What's the 20% that delivers 80% of value?
|
|
23
23
|
|
|
24
|
-
If any of these are unclear from the codebase,
|
|
24
|
+
If any of these are unclear from the codebase, ask the user directly to clarify what you cannot infer.
|
|
25
25
|
|
|
26
26
|
**CRITICAL**: Simplicity is not about removing features. It's about removing obstacles between users and their goals. Every element should justify its existence.
|
|
27
27
|
|
|
@@ -66,7 +66,7 @@ Optional evocative subtitles are allowed in the form `## 2. Colors: The [Name] P
|
|
|
66
66
|
- An existing `DESIGN.md` is stale (the design has drifted).
|
|
67
67
|
- Before a large redesign, to capture the current state as a reference.
|
|
68
68
|
|
|
69
|
-
If a `DESIGN.md` already exists, **do not silently overwrite it**. Show the user the existing file and
|
|
69
|
+
If a `DESIGN.md` already exists, **do not silently overwrite it**. Show the user the existing file and ask the user directly to clarify what you cannot infer. whether to refresh, overwrite, or merge.
|
|
70
70
|
|
|
71
71
|
## Two paths
|
|
72
72
|
|
|
@@ -6,7 +6,7 @@ Identify reusable patterns, components, and design tokens, then extract and cons
|
|
|
6
6
|
|
|
7
7
|
Find the design system, component library, or shared UI directory. Understand its structure: component organization, naming conventions, design token structure, import/export conventions.
|
|
8
8
|
|
|
9
|
-
**CRITICAL**: If no design system exists,
|
|
9
|
+
**CRITICAL**: If no design system exists, ask the user directly to clarify what you cannot infer. before creating one. Understand the preferred location and structure first.
|
|
10
10
|
|
|
11
11
|
## Step 2: Identify Patterns
|
|
12
12
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# /impeccable hooks
|
|
2
|
+
|
|
3
|
+
Manage the **design detector hook** for the current project.
|
|
4
|
+
|
|
5
|
+
The hook runs the impeccable design detector on direct file edits to design-relevant files (`.tsx`, `.jsx`, `.html`, `.vue`, `.svelte`, `.astro`, `.css`, `.scss`, `.sass`, `.less`, `.ts`, `.js`). Claude Code, Codex, and GitHub Copilot use a post-tool-use hook and push a short system reminder into the agent's context after the edit; findings get a correction prompt, pending issues get a re-nudge, and clean UI-ish files get a short ack unless quiet mode is on (`hook.quiet` in config). Plain `.ts` and `.js` files are still scanned, but stay quiet unless the detector finds something. Cursor uses `preToolUse` to block bad proposed writes before they land and stays silent when it allows a clean write.
|
|
6
|
+
|
|
7
|
+
This command toggles the hook **per project** by editing `.impeccable/config.json` (the unified Impeccable config; hook runtime settings live under its `hook` key, and shared detector ignores live under `detector`). Per-developer overrides, including the install consent decision (`hook.consent`) the CLI records, live in the gitignored `.impeccable/config.local.json`. Set `hook.enabled: false` to turn the hook off, `hook.quiet: true` to silence the clean/pending acks, or `hook.auditLog` to a file path for an NDJSON log. The legacy `IMPECCABLE_HOOK_DISABLED`, `IMPECCABLE_HOOK_QUIET`, and `IMPECCABLE_HOOK_LOG` env vars are still honored and override these config values when set.
|
|
8
|
+
|
|
9
|
+
Manual `npx impeccable detect` scans use the same project filter config by default: `detector.ignoreRules`, `detector.ignoreFiles`, `detector.ignoreValues`, and `detector.designSystem.enabled`. `hook.enabled` only controls automatic hook execution, not manual CLI scans. Use `npx impeccable detect --no-config ...` for a raw detector run that ignores project config/context. Use `npx impeccable ignores ...` for direct CLI CRUD on the same detector ignores.
|
|
10
|
+
|
|
11
|
+
Supported harnesses: Claude Code (`.claude/settings.local.json` in the project, which is gitignored so the hook stays machine-local; a hook you move into the shared `settings.json` is honored in place too), Codex (`.codex/hooks.json` in the project), Cursor (`.cursor/hooks.json` in the project), and GitHub Copilot (`.github/hooks/impeccable.json` in the project, a team-shared committed file that both the Copilot CLI and the cloud agent read). For the Copilot CLI, repo-level hooks fire once `.github/hooks/impeccable.json` is committed to the repository's default branch.
|
|
12
|
+
|
|
13
|
+
On **Cursor**, `preToolUse` checks proposed Write/Edit/Shell write content and denies only when the real detector finds an issue. The denial message is visible to the agent as the tool error, so the agent can reconsider before the bad write lands.
|
|
14
|
+
|
|
15
|
+
## Routing
|
|
16
|
+
|
|
17
|
+
The first argument is the action. Defaults to `status`.
|
|
18
|
+
|
|
19
|
+
| Action | What it does |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `status` | Print current state, shared/local config paths, ignored rules / files / values, env override. |
|
|
22
|
+
| `on` | Set `enabled: true` in `.impeccable/config.json`, record local hook consent as accepted, and install/repair provider hook manifests when the skill is installed. |
|
|
23
|
+
| `off` | Set `enabled: false` in `.impeccable/config.json`. |
|
|
24
|
+
| `ignore-rule <id>` | Append `<id>` to `detector.ignoreRules`; for `overused-font`, requires `--all-values`. |
|
|
25
|
+
| `ignore-file <glob>` | Append `<glob>` to `detector.ignoreFiles`. |
|
|
26
|
+
| `ignore-value <id> <value> [--shared] [--reason "..."]` | Append a rule/value suppression to shared `.impeccable/config.json`. |
|
|
27
|
+
| `ignore-value <id> <value> --local [--reason "..."]` | Append a private rule/value suppression to `.impeccable/config.local.json`. |
|
|
28
|
+
| `reset` | Delete the project config, dedup cache, and Cursor pending queue. |
|
|
29
|
+
|
|
30
|
+
## Flow
|
|
31
|
+
|
|
32
|
+
1. Resolve the action from the user's argument. If no action was given, default to `status`.
|
|
33
|
+
2. Invoke the admin script and pass the user's output through verbatim:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
node .pi/skills/impeccable/scripts/hook-admin.mjs <action> [args...]
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
3. If `<action>` is `off`, follow up with a one-line note: "Done. New edits will not trigger the design hook in this project until you run `/impeccable hooks on`."
|
|
40
|
+
4. If `<action>` is `on`, follow up with: "Done. The design hook will fire after the next Edit/Write/MultiEdit on a UI file."
|
|
41
|
+
5. If `<action>` is `ignore-value`, `ignore-file`, or `ignore-rule`, just print the script output. The default scope is shared `.impeccable/config.json`; add `--local` only when the user explicitly asks for a private exception.
|
|
42
|
+
6. If `<action>` is `status`, just print the script output. Do not add commentary unless the user asked a follow-up question.
|
|
43
|
+
|
|
44
|
+
## Intentional findings
|
|
45
|
+
|
|
46
|
+
The hook itself never writes ignore config. Persist an exception only after the user explicitly confirms the flagged issue is intentional, and always go through `hook-admin.mjs`.
|
|
47
|
+
|
|
48
|
+
Prefer the narrowest exception:
|
|
49
|
+
|
|
50
|
+
- If the finding line shows an exact `ignore-value` command, run that command. This writes shared `.impeccable/config.json` by default.
|
|
51
|
+
- For value-specific findings such as `overused-font` and `bounce-easing`, use `ignore-value` when the user confirms the specific value. Do not use `ignore-rule overused-font` for a specific font.
|
|
52
|
+
- If the finding has no value-specific command, such as `side-tab`, prefer `ignore-file <path>` for the current file.
|
|
53
|
+
- Use `ignore-rule <id>` only when the user asks to suppress that whole rule across the project. For broad overused-font suppression, use `ignore-rule overused-font --all-values` only when the user asks to ignore overused fonts generally.
|
|
54
|
+
- Prefer config ignores (the commands above) by default; they keep suppressions in one reviewable place. Reach for an inline comment only when the waiver must travel with a single file that leaves the repo (a generated/exported standalone document, an emailed HTML file). The supported marker is `impeccable-disable <rule>` (whole file) or `impeccable-disable-line` / `impeccable-disable-next-line` (one line), in any comment syntax, with an optional reason after `:` or `--`. The detector honors it by default; `--no-inline-ignores` or `--no-config` bypasses it.
|
|
55
|
+
|
|
56
|
+
Example value-specific exception:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
node .pi/skills/impeccable/scripts/hook-admin.mjs ignore-value overused-font Inter --shared --reason "User confirmed Inter is intentional"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Example intentional motion exception:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
node .pi/skills/impeccable/scripts/hook-admin.mjs ignore-value bounce-easing bounce-ball --shared --reason "User confirmed ball bounce animation is intentional"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Example whole-rule font exception:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
node .pi/skills/impeccable/scripts/hook-admin.mjs ignore-rule overused-font --all-values --reason "User asked to ignore overused fonts generally"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Example file-scoped exception:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
node .pi/skills/impeccable/scripts/hook-admin.mjs ignore-file "src/legacy/Card.tsx"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Constraints
|
|
81
|
+
|
|
82
|
+
- Never modify `.impeccable/config.json` or `.impeccable/config.local.json` by hand from this command. Always go through `hook-admin.mjs` so writes stay validated and the file shape stays consistent.
|
|
83
|
+
- Do not edit the hook scripts themselves (`hook.mjs`, `hook-lib.mjs`, `hook-before-edit.mjs`) from this flow. Those are skill plumbing.
|
|
84
|
+
- Cursor can block a proposed write when the detector finds a real issue. Claude Code, Codex, and GitHub Copilot do not block the edit; they emit a post-edit reminder instead. Disabling stops both blocking and reminders.
|
|
85
|
+
- The hook is bundled with the Impeccable skill and installed through project-local manifests: `.claude/settings.local.json`, `.codex/hooks.json`, `.cursor/hooks.json`, and `.github/hooks/impeccable.json`. On Codex, the user must approve the hook via `/hooks` the first time. On Cursor, confirm hooks are enabled under Settings -> Hooks. On GitHub Copilot, the CLI loads `.github/hooks/impeccable.json` once it is committed to the repository's default branch, and the cloud agent reads it from the repo directly.
|
|
86
|
+
|
|
87
|
+
## Failure modes
|
|
88
|
+
|
|
89
|
+
- If `.impeccable/config.json` or `.impeccable/config.local.json` is unreadable or malformed, the hook ignores that file and uses the remaining valid config/defaults. `hook-admin.mjs status` will show malformed files as ignored.
|
|
90
|
+
- If the user asks to "disable the hook" globally, lead with `/impeccable hooks off` (persistent for this project; writes `hook.enabled: false` to config). The legacy `IMPECCABLE_HOOK_DISABLED=1` env var also works as a one-shot override that follows the shell.
|
|
@@ -16,7 +16,7 @@ Decision tree:
|
|
|
16
16
|
- **Neither file exists (empty project or no context yet)**: do Steps 2-4 (write PRODUCT.md), then decide on DESIGN.md based on whether there's code to analyze.
|
|
17
17
|
- **PRODUCT.md exists, DESIGN.md missing**: skip to Step 5 and offer to run `/impeccable document` for DESIGN.md.
|
|
18
18
|
- **PRODUCT.md exists but has no `## Register` section (legacy)**: add it. Infer a hypothesis from the codebase (see Step 2), confirm with the user, write the field.
|
|
19
|
-
- **Both exist**:
|
|
19
|
+
- **Both exist**: ask the user directly to clarify what you cannot infer. Ask which file to refresh. Skip the one the user doesn't want changed.
|
|
20
20
|
- **Just DESIGN.md exists (unusual)**: do Steps 2-4 to produce PRODUCT.md.
|
|
21
21
|
|
|
22
22
|
Never silently overwrite an existing file. Always confirm first.
|
|
@@ -45,7 +45,7 @@ Note what you've learned and what remains unclear. Also note any rough edges wor
|
|
|
45
45
|
|
|
46
46
|
## Step 3: Ask strategic questions (for PRODUCT.md)
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
ask the user directly to clarify what you cannot infer. Ask only about what you couldn't infer from the codebase.
|
|
49
49
|
|
|
50
50
|
### Interview mode, not confirmation mode
|
|
51
51
|
|
|
@@ -68,7 +68,7 @@ Every design task is either **brand** (marketing, landing, campaign, long-form c
|
|
|
68
68
|
|
|
69
69
|
If Step 2 produced a clear hypothesis, lead with it: *"From the codebase, this looks like a [brand / product] surface. Does that match your intent, or should we treat it differently?"*
|
|
70
70
|
|
|
71
|
-
If the signal is genuinely split (e.g. a product with a big marketing landing),
|
|
71
|
+
If the signal is genuinely split (e.g. a product with a big marketing landing), ask the user directly to clarify what you cannot infer. Ask which register describes the **primary** surface. The register can be overridden per task later, but PRODUCT.md carries one default.
|
|
72
72
|
|
|
73
73
|
### Users & Purpose
|
|
74
74
|
- Who uses this? What's their context when using it?
|
|
@@ -146,7 +146,7 @@ If the project has code with HTML entries and a dev server (the same "code exist
|
|
|
146
146
|
Otherwise:
|
|
147
147
|
|
|
148
148
|
1. Write `.impeccable/live/config.json`. Choose `files` (the HTML entries the browser actually loads), `insertBefore`, and `commentSyntax` from the framework table in [live.md](live.md)'s **First-time setup** section, using the framework you found in Step 2. That table is canonical; do not restate it here. For multi-page static sites, prefer a glob (`["public/**/*.html"]`) over a literal list.
|
|
149
|
-
2. Run `node .
|
|
149
|
+
2. Run `node .pi/skills/impeccable/scripts/detect-csp.mjs`. If it reports a patchable shape (`append-arrays` / `append-string`), use the **consent prompt template** from live.md before editing any source file. On decline, skip the patch. For `middleware` / `meta-tag` shapes, surface the detected files and ask the user to add `http://localhost:8400` to `script-src` and `connect-src` manually. For `null`, there's nothing to do.
|
|
150
150
|
3. Set `cspChecked: true` in the config once CSP is handled (patched, declined, manual, or not needed). The schema and per-shape patch details live in live.md's First-time setup; follow it rather than duplicating.
|
|
151
151
|
|
|
152
152
|
Writing the config file is harmless and needs no consent; only the CSP **source-file patch** requires a yes.
|
|
@@ -169,4 +169,4 @@ The full command menu is one bare `/impeccable` away; keep this list short and p
|
|
|
169
169
|
|
|
170
170
|
If init was invoked as a blocker by another impeccable command (e.g. the user ran `/impeccable polish` with no PRODUCT.md), resume that original task now. Your own writes are the freshest source; no reload needed.
|
|
171
171
|
|
|
172
|
-
Optionally
|
|
172
|
+
Optionally ask the user directly to clarify what you cannot infer. Ask whether they'd like a brief summary of PRODUCT.md appended to AGENTS.md for easier agent reference. If yes, append a short **Design Context** pointer section there.
|
|
@@ -8,7 +8,7 @@ A running dev server with hot module replacement (Vite, Next.js, Bun, etc.), OR
|
|
|
8
8
|
|
|
9
9
|
Execute in order. No step skipped, no step reordered.
|
|
10
10
|
|
|
11
|
-
1. `live.mjs`: boot.
|
|
11
|
+
1. `live.mjs`: boot. If the request names or implies a file, route, or app inside a monorepo, infer the concrete path and run `node .pi/skills/impeccable/scripts/live.mjs --target <path>` instead; then run the rest of this live session from the returned `projectRoot`.
|
|
12
12
|
2. Open the app URL that serves `pageFile` (infer from `package.json`, docs, terminal output, or an open tab). Never use `serverPort`; it's the helper, not the app. **Cursor:** `browser_navigate` to that URL before polling; do not skip. **Other harnesses:** use the available browser tool; if the URL is uncertain, ask the user once.
|
|
13
13
|
3. Poll loop with the default long timeout (600000 ms). After every event or `--reply`, run `live-poll.mjs` again immediately. Never pass a short `--timeout=`.
|
|
14
14
|
|
|
@@ -30,7 +30,7 @@ Chat is overhead. No recap, no tutorial output, no pasting PRODUCT / DESIGN bodi
|
|
|
30
30
|
## Start
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
node .
|
|
33
|
+
node .pi/skills/impeccable/scripts/live.mjs
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
Output JSON: `{ ok, serverPort, serverToken, pageFiles, hasProduct, product, productPath, hasDesign, design, designPath }`. `pageFiles` is the list of HTML entries the live script was injected into. Keep PRODUCT.md and DESIGN.md in mind for variant generation; **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.** When DESIGN.md is missing, identity is **not** absent; extract it from CSS variables, computed styles, and sibling components on the page (see Step 4 Phase A). Identity preservation is the default; departure from existing identity requires an explicit trigger from PRODUCT.md anti-references or the user's freeform prompt.
|
|
@@ -45,7 +45,7 @@ If output is `{ ok: false, error: "config_missing" | "config_invalid", path }`,
|
|
|
45
45
|
|
|
46
46
|
```
|
|
47
47
|
LOOP:
|
|
48
|
-
node .
|
|
48
|
+
node .pi/skills/impeccable/scripts/live-poll.mjs # default long timeout; no --timeout=
|
|
49
49
|
Read JSON; dispatch on "type"
|
|
50
50
|
|
|
51
51
|
"generate" → Handle Generate; reply done; LOOP
|
|
@@ -61,7 +61,7 @@ LOOP:
|
|
|
61
61
|
**Stream mode (experimental, not for Cursor):**
|
|
62
62
|
|
|
63
63
|
```
|
|
64
|
-
node .
|
|
64
|
+
node .pi/skills/impeccable/scripts/live-poll.mjs --stream # stays running; one JSON line per event
|
|
65
65
|
Handle event; run --reply in a separate command
|
|
66
66
|
Repeat until "exit" line → Cleanup
|
|
67
67
|
```
|
|
@@ -75,9 +75,9 @@ The live helper persists an append-only journal under `.impeccable/live/sessions
|
|
|
75
75
|
Use these commands when the chat was interrupted, polling was missed, the helper restarted, or the browser reloaded:
|
|
76
76
|
|
|
77
77
|
```bash
|
|
78
|
-
node .
|
|
79
|
-
node .
|
|
80
|
-
node .
|
|
78
|
+
node .pi/skills/impeccable/scripts/live-status.mjs
|
|
79
|
+
node .pi/skills/impeccable/scripts/live-resume.mjs --id SESSION_ID
|
|
80
|
+
node .pi/skills/impeccable/scripts/live-complete.mjs --id SESSION_ID
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
- `live-status.mjs` prints connected helper state, active durable sessions, and queued pending events. It works even when the helper is down by reading the journal directly.
|
|
@@ -102,7 +102,7 @@ When `event.mode === "insert"`:
|
|
|
102
102
|
2. Run the insert helper instead of wrap:
|
|
103
103
|
|
|
104
104
|
```bash
|
|
105
|
-
node .
|
|
105
|
+
node .pi/skills/impeccable/scripts/live-insert.mjs --id EVENT_ID --count EVENT_COUNT --position after \
|
|
106
106
|
--element-id "ANCHOR_ID" --classes "class1,class2" --tag "section" --text "ANCHOR_TEXT"
|
|
107
107
|
```
|
|
108
108
|
|
|
@@ -135,7 +135,7 @@ Reading annotations precisely:
|
|
|
135
135
|
### 2. Wrap the element
|
|
136
136
|
|
|
137
137
|
```bash
|
|
138
|
-
node .
|
|
138
|
+
node .pi/skills/impeccable/scripts/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div" --text "TEXT_SNIPPET"
|
|
139
139
|
```
|
|
140
140
|
|
|
141
141
|
Flag mapping. Keep them separate, don't collapse into `--query`:
|
|
@@ -398,7 +398,7 @@ The carbonize cleanup step (see below) reads that comment and bakes the chosen v
|
|
|
398
398
|
### 8. Signal done
|
|
399
399
|
|
|
400
400
|
```bash
|
|
401
|
-
node .
|
|
401
|
+
node .pi/skills/impeccable/scripts/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
|
402
402
|
```
|
|
403
403
|
|
|
404
404
|
`RELATIVE_PATH` is relative to project root (`public/index.html`, `src/App.tsx`, etc.); the browser fetches source directly if the dev server lacks HMR.
|
|
@@ -410,7 +410,7 @@ Then run `live-poll.mjs` again immediately.
|
|
|
410
410
|
If wrap or generation fails after the browser has flipped to GENERATING (e.g. wrap landed on the wrong source branch and you've already reverted it, or generation hit an unrecoverable error), tell the **browser** so its bar resets to PICKING:
|
|
411
411
|
|
|
412
412
|
```bash
|
|
413
|
-
node .
|
|
413
|
+
node .pi/skills/impeccable/scripts/live-poll.mjs --reply EVENT_ID error "Short reason"
|
|
414
414
|
```
|
|
415
415
|
|
|
416
416
|
Don't run `live-accept --discard` for this; that's a pure file mutator, the browser doesn't see it, and the bar gets stuck on the GENERATING dots forever (the user has to refresh). `--discard` is only correct when the **browser** initiated the discard (user clicked ✕ during CYCLING) and the agent is just running source-side cleanup the browser already triggered.
|
|
@@ -497,13 +497,13 @@ This is lighter than `generate`: no screenshot, no element context, no variant c
|
|
|
497
497
|
When finished:
|
|
498
498
|
|
|
499
499
|
```bash
|
|
500
|
-
node .
|
|
500
|
+
node .pi/skills/impeccable/scripts/live-poll.mjs --reply EVENT_ID steer_done ["Optional short note for a browser toast"]
|
|
501
501
|
```
|
|
502
502
|
|
|
503
503
|
On failure:
|
|
504
504
|
|
|
505
505
|
```bash
|
|
506
|
-
node .
|
|
506
|
+
node .pi/skills/impeccable/scripts/live-poll.mjs --reply EVENT_ID error "Short reason"
|
|
507
507
|
```
|
|
508
508
|
|
|
509
509
|
Then poll again immediately. Do not send a separate "picked up" reply. The Steer bar stays locked until `steer_done` or `error` arrives over SSE.
|
|
@@ -531,7 +531,7 @@ When native subagents are available, delegate source edits to `impeccable_manual
|
|
|
531
531
|
|
|
532
532
|
If `repair` is present, the previous Apply changed source but final validation failed. Fix the current source and return the same canonical JSON result; do not roll files back yourself. The browser will ask the user before any rollback.
|
|
533
533
|
|
|
534
|
-
After source edits finish, reply exactly once with `node .
|
|
534
|
+
After source edits finish, reply exactly once with `node .pi/skills/impeccable/scripts/live-poll.mjs --reply EVENT_ID done --data '{"status":"done","appliedEntryIds":["8hexid"],"failed":[],"files":["src/page.html"],"notes":[]}'`. Use `status:"partial"` or `status:"error"` with `failed[]` when not every entry applied. Then poll again. Never reply without the event id; `--reply done --file ...` is invalid for manual Apply.
|
|
535
535
|
|
|
536
536
|
## Exit
|
|
537
537
|
|
|
@@ -545,7 +545,7 @@ When the poll returns `exit`, proceed to cleanup. If the poll is still running a
|
|
|
545
545
|
## Cleanup
|
|
546
546
|
|
|
547
547
|
```bash
|
|
548
|
-
node .
|
|
548
|
+
node .pi/skills/impeccable/scripts/live-server.mjs stop
|
|
549
549
|
```
|
|
550
550
|
|
|
551
551
|
Stops the HTTP server and runs `live-inject.mjs --remove` to strip `localhost:…/live.js` from the HTML entry. To stop the server but keep the inject tag (for a quick restart), use `stop --keep-inject`. `.impeccable/live/config.json` persists as project config for future sessions.
|
|
@@ -631,7 +631,7 @@ If `config.cspChecked === true`, skip this entire section. You already asked thi
|
|
|
631
631
|
Otherwise, run the detection helper:
|
|
632
632
|
|
|
633
633
|
```bash
|
|
634
|
-
node .
|
|
634
|
+
node .pi/skills/impeccable/scripts/detect-csp.mjs
|
|
635
635
|
```
|
|
636
636
|
|
|
637
637
|
Output: `{ shape, signals }` where `shape` is one of `append-arrays`, `append-string`, `middleware`, `meta-tag`, or `null`. The shape is named by *patch mechanism*, so one template covers many frameworks.
|
|
@@ -14,7 +14,7 @@ Push an interface past conventional limits. This isn't just about visual effects
|
|
|
14
14
|
This command has the highest potential to misfire. Do NOT jump straight into implementation. You MUST:
|
|
15
15
|
|
|
16
16
|
1. **Think through 2-3 different directions**: consider different techniques, levels of ambition, and aesthetic approaches. For each direction, briefly describe what the result would look and feel like.
|
|
17
|
-
2. **
|
|
17
|
+
2. **ask the user directly to clarify what you cannot infer.** to present these directions and get the user's pick before writing any code. Explain trade-offs (browser support, performance cost, complexity).
|
|
18
18
|
3. Only proceed with the direction the user confirms.
|
|
19
19
|
|
|
20
20
|
Skipping this step risks building something embarrassing that needs to be thrown away.
|
|
@@ -37,8 +37,8 @@ Understand the current state and goals before touching anything:
|
|
|
37
37
|
|
|
38
38
|
4. **Pull in any prior critique** (optional signal): If `/impeccable critique` has been run on the same target, its priority issues are a useful prior for what to address first. Resolve the target to a file path or URL, then:
|
|
39
39
|
```bash
|
|
40
|
-
slug=$(node .
|
|
41
|
-
node .
|
|
40
|
+
slug=$(node .pi/skills/impeccable/scripts/critique-storage.mjs slug "<resolved>")
|
|
41
|
+
node .pi/skills/impeccable/scripts/critique-storage.mjs latest "$slug"
|
|
42
42
|
```
|
|
43
43
|
Exit 0 with body = found; fold the P0/P1 items into your polish list and mention the snapshot path so the user sees what you read. Exit 2 = no snapshot, continue without it. The critique is one input among many. Do your own pass either way.
|
|
44
44
|
|
|
@@ -28,7 +28,7 @@ Analyze what makes the design feel too intense:
|
|
|
28
28
|
- What's working? (Don't throw away good ideas)
|
|
29
29
|
- What's the core message? (Preserve what matters)
|
|
30
30
|
|
|
31
|
-
If any of these are unclear from the codebase,
|
|
31
|
+
If any of these are unclear from the codebase, ask the user directly to clarify what you cannot infer.
|
|
32
32
|
|
|
33
33
|
**CRITICAL**: "Quieter" doesn't mean boring or generic. It means refined and easier on the eyes. Think luxury, not laziness.
|
|
34
34
|
|
|
@@ -12,7 +12,7 @@ Most AI-generated UIs fail not because of bad code, but because of skipped think
|
|
|
12
12
|
|
|
13
13
|
**Do NOT write any code or make any design decisions during this phase.** Your only job is to understand the feature deeply enough to make excellent design decisions later.
|
|
14
14
|
|
|
15
|
-
This is a required interaction, not optional guidance. Ask these questions in conversation, adapting based on answers. Don't dump them all at once; have a natural dialogue.
|
|
15
|
+
This is a required interaction, not optional guidance. Ask these questions in conversation, adapting based on answers. Don't dump them all at once; have a natural dialogue. ask the user directly to clarify what you cannot infer.
|
|
16
16
|
|
|
17
17
|
### Interview cadence
|
|
18
18
|
|
|
@@ -158,7 +158,7 @@ Anything genuinely unresolved. Don't list "open questions" you've already recomm
|
|
|
158
158
|
|
|
159
159
|
---
|
|
160
160
|
|
|
161
|
-
|
|
161
|
+
ask the user directly to clarify what you cannot infer. Ask for explicit confirmation of the brief before finishing.
|
|
162
162
|
|
|
163
163
|
If the user disagrees with any part, revisit the relevant discovery questions. A shape run is incomplete until the user confirms direction.
|
|
164
164
|
|
|
@@ -22,7 +22,7 @@ import path from 'node:path';
|
|
|
22
22
|
import { fileURLToPath } from 'node:url';
|
|
23
23
|
import { execFileSync } from 'node:child_process';
|
|
24
24
|
import { loadContext, extractRegister } from './context.mjs';
|
|
25
|
-
import { getCritiqueDir } from './impeccable-paths.mjs';
|
|
25
|
+
import { getCritiqueDir } from './lib/impeccable-paths.mjs';
|
|
26
26
|
|
|
27
27
|
/** Is there code here at all, or just context files / an empty repo? */
|
|
28
28
|
function hasCode(cwd) {
|