@bastani/atomic 0.8.20-0 → 0.8.21-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.
Files changed (127) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/builtin/intercom/package.json +1 -1
  3. package/dist/builtin/mcp/CHANGELOG.md +5 -0
  4. package/dist/builtin/mcp/package.json +1 -1
  5. package/dist/builtin/subagents/CHANGELOG.md +5 -0
  6. package/dist/builtin/subagents/agents/code-simplifier.md +78 -22
  7. package/dist/builtin/subagents/agents/debugger.md +4 -3
  8. package/dist/builtin/subagents/package.json +1 -1
  9. package/dist/builtin/web-access/CHANGELOG.md +5 -0
  10. package/dist/builtin/web-access/package.json +1 -1
  11. package/dist/builtin/workflows/CHANGELOG.md +25 -0
  12. package/dist/builtin/workflows/package.json +1 -1
  13. package/dist/builtin/workflows/skills/create-spec/SKILL.md +169 -125
  14. package/dist/builtin/workflows/skills/impeccable/SKILL.md +89 -80
  15. package/dist/builtin/workflows/skills/impeccable/agents/impeccable_asset_producer.toml +92 -0
  16. package/dist/builtin/workflows/skills/impeccable/agents/impeccable_manual_edit_applier.toml +95 -0
  17. package/dist/builtin/workflows/skills/impeccable/agents/openai.yaml +4 -0
  18. package/dist/builtin/workflows/skills/impeccable/reference/adapt.md +122 -1
  19. package/dist/builtin/workflows/skills/impeccable/reference/animate.md +38 -12
  20. package/dist/builtin/workflows/skills/impeccable/reference/audit.md +5 -5
  21. package/dist/builtin/workflows/skills/impeccable/reference/bolder.md +7 -7
  22. package/dist/builtin/workflows/skills/impeccable/reference/brand.md +4 -14
  23. package/dist/builtin/workflows/skills/impeccable/reference/clarify.md +115 -1
  24. package/dist/builtin/workflows/skills/impeccable/reference/codex.md +3 -3
  25. package/dist/builtin/workflows/skills/impeccable/reference/colorize.md +109 -6
  26. package/dist/builtin/workflows/skills/impeccable/reference/craft.md +7 -7
  27. package/dist/builtin/workflows/skills/impeccable/reference/critique.md +623 -94
  28. package/dist/builtin/workflows/skills/impeccable/reference/delight.md +2 -2
  29. package/dist/builtin/workflows/skills/impeccable/reference/distill.md +2 -2
  30. package/dist/builtin/workflows/skills/impeccable/reference/document.md +16 -14
  31. package/dist/builtin/workflows/skills/impeccable/reference/extract.md +1 -1
  32. package/dist/builtin/workflows/skills/impeccable/reference/harden.md +1 -1
  33. package/dist/builtin/workflows/skills/impeccable/reference/init.md +172 -0
  34. package/dist/builtin/workflows/skills/impeccable/reference/interaction-design.md +0 -6
  35. package/dist/builtin/workflows/skills/impeccable/reference/layout.md +33 -13
  36. package/dist/builtin/workflows/skills/impeccable/reference/live.md +96 -19
  37. package/dist/builtin/workflows/skills/impeccable/reference/onboard.md +1 -1
  38. package/dist/builtin/workflows/skills/impeccable/reference/optimize.md +1 -1
  39. package/dist/builtin/workflows/skills/impeccable/reference/overdrive.md +1 -1
  40. package/dist/builtin/workflows/skills/impeccable/reference/polish.md +3 -4
  41. package/dist/builtin/workflows/skills/impeccable/reference/product.md +1 -3
  42. package/dist/builtin/workflows/skills/impeccable/reference/quieter.md +2 -2
  43. package/dist/builtin/workflows/skills/impeccable/reference/shape.md +5 -5
  44. package/dist/builtin/workflows/skills/impeccable/reference/typeset.md +158 -3
  45. package/dist/builtin/workflows/skills/impeccable/scripts/cleanup-deprecated.mjs +1 -1
  46. package/dist/builtin/workflows/skills/impeccable/scripts/command-metadata.json +2 -2
  47. package/dist/builtin/workflows/skills/impeccable/scripts/context-signals.mjs +225 -0
  48. package/dist/builtin/workflows/skills/impeccable/scripts/context.mjs +266 -0
  49. package/dist/builtin/workflows/skills/impeccable/scripts/critique-storage.mjs +17 -1
  50. package/dist/builtin/workflows/skills/impeccable/scripts/design-parser.mjs +16 -1
  51. package/dist/builtin/workflows/skills/impeccable/scripts/detect.mjs +21 -0
  52. package/dist/builtin/workflows/skills/impeccable/scripts/detector/browser/injected/index.mjs +1725 -0
  53. package/dist/builtin/workflows/skills/impeccable/scripts/detector/cli/main.mjs +244 -0
  54. package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +4543 -0
  55. package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns.mjs +43 -0
  56. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +252 -0
  57. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +535 -0
  58. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +986 -0
  59. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +208 -0
  60. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs +189 -0
  61. package/dist/builtin/workflows/skills/impeccable/scripts/detector/findings.mjs +12 -0
  62. package/dist/builtin/workflows/skills/impeccable/scripts/detector/node/file-system.mjs +198 -0
  63. package/dist/builtin/workflows/skills/impeccable/scripts/detector/profile/profiler.mjs +166 -0
  64. package/dist/builtin/workflows/skills/impeccable/scripts/detector/registry/antipatterns.mjs +419 -0
  65. package/dist/builtin/workflows/skills/impeccable/scripts/detector/rules/checks.mjs +2316 -0
  66. package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/color.mjs +124 -0
  67. package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/constants.mjs +101 -0
  68. package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/page.mjs +7 -0
  69. package/dist/builtin/workflows/skills/impeccable/scripts/impeccable-paths.mjs +17 -1
  70. package/dist/builtin/workflows/skills/impeccable/scripts/is-generated.mjs +2 -2
  71. package/dist/builtin/workflows/skills/impeccable/scripts/live-accept.mjs +139 -96
  72. package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +4491 -526
  73. package/dist/builtin/workflows/skills/impeccable/scripts/live-commit-manual-edits.mjs +1241 -0
  74. package/dist/builtin/workflows/skills/impeccable/scripts/live-copy-edit-agent.mjs +683 -0
  75. package/dist/builtin/workflows/skills/impeccable/scripts/live-discard-manual-edits.mjs +51 -0
  76. package/dist/builtin/workflows/skills/impeccable/scripts/live-event-validation.mjs +136 -0
  77. package/dist/builtin/workflows/skills/impeccable/scripts/live-inject.mjs +22 -9
  78. package/dist/builtin/workflows/skills/impeccable/scripts/live-insert-ui.mjs +458 -0
  79. package/dist/builtin/workflows/skills/impeccable/scripts/live-insert.mjs +232 -0
  80. package/dist/builtin/workflows/skills/impeccable/scripts/live-manual-edit-evidence.mjs +363 -0
  81. package/dist/builtin/workflows/skills/impeccable/scripts/live-manual-edits-buffer.mjs +152 -0
  82. package/dist/builtin/workflows/skills/impeccable/scripts/live-poll.mjs +288 -110
  83. package/dist/builtin/workflows/skills/impeccable/scripts/live-resume.mjs +47 -1
  84. package/dist/builtin/workflows/skills/impeccable/scripts/live-server.mjs +1443 -100
  85. package/dist/builtin/workflows/skills/impeccable/scripts/live-session-store.mjs +17 -0
  86. package/dist/builtin/workflows/skills/impeccable/scripts/live-status.mjs +17 -3
  87. package/dist/builtin/workflows/skills/impeccable/scripts/live-wrap.mjs +216 -6
  88. package/dist/builtin/workflows/skills/impeccable/scripts/live.mjs +2 -3
  89. package/dist/builtin/workflows/skills/impeccable/scripts/palette.mjs +633 -0
  90. package/dist/builtin/workflows/skills/impeccable/scripts/pin.mjs +1 -1
  91. package/dist/builtin/workflows/src/extension/index.ts +67 -3
  92. package/dist/builtin/workflows/src/extension/render-result.ts +26 -1
  93. package/dist/builtin/workflows/src/runs/foreground/executor.ts +227 -3
  94. package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +94 -7
  95. package/dist/builtin/workflows/src/shared/stage-prompt.ts +326 -0
  96. package/dist/builtin/workflows/src/shared/stage-ui-broker.ts +62 -7
  97. package/dist/builtin/workflows/src/shared/store-types.ts +43 -0
  98. package/dist/builtin/workflows/src/shared/store.ts +37 -0
  99. package/dist/builtin/workflows/src/tui/chat-surface-message.ts +22 -4
  100. package/dist/builtin/workflows/src/tui/graph-view.ts +47 -0
  101. package/dist/builtin/workflows/src/tui/overlay-adapter.ts +43 -1
  102. package/dist/builtin/workflows/src/tui/run-detail.ts +10 -4
  103. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +117 -15
  104. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +9 -0
  105. package/dist/core/skills.d.ts.map +1 -1
  106. package/dist/core/skills.js +2 -5
  107. package/dist/core/skills.js.map +1 -1
  108. package/dist/core/system-prompt.d.ts.map +1 -1
  109. package/dist/core/system-prompt.js +11 -29
  110. package/dist/core/system-prompt.js.map +1 -1
  111. package/dist/index.d.ts +1 -0
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +3 -0
  114. package/dist/index.js.map +1 -1
  115. package/docs/quickstart.md +1 -2
  116. package/package.json +4 -4
  117. package/dist/builtin/workflows/skills/impeccable/reference/cognitive-load.md +0 -106
  118. package/dist/builtin/workflows/skills/impeccable/reference/color-and-contrast.md +0 -105
  119. package/dist/builtin/workflows/skills/impeccable/reference/heuristics-scoring.md +0 -234
  120. package/dist/builtin/workflows/skills/impeccable/reference/motion-design.md +0 -109
  121. package/dist/builtin/workflows/skills/impeccable/reference/personas.md +0 -179
  122. package/dist/builtin/workflows/skills/impeccable/reference/responsive-design.md +0 -114
  123. package/dist/builtin/workflows/skills/impeccable/reference/spatial-design.md +0 -100
  124. package/dist/builtin/workflows/skills/impeccable/reference/teach.md +0 -156
  125. package/dist/builtin/workflows/skills/impeccable/reference/typography.md +0 -159
  126. package/dist/builtin/workflows/skills/impeccable/reference/ux-writing.md +0 -107
  127. package/dist/builtin/workflows/skills/impeccable/scripts/load-context.mjs +0 -141
@@ -4,33 +4,38 @@ Interactive live variant mode: select elements in the browser, pick a design act
4
4
 
5
5
  A running dev server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser.
6
6
 
7
+ Codex: run live helper commands, the app dev server, and any dependency-installing setup with `sandbox_permissions: "require_escalated"` from the start; live mode depends on localhost and package-manager network access that the sandbox blocks.
8
+
7
9
  ## The contract (read once)
8
10
 
9
11
  Execute in order. No step skipped, no step reordered.
10
12
 
11
13
  1. `live.mjs`: boot.
12
- 2. Navigate to the URL that serves `pageFile` (infer from `package.json`, docs, terminal output, or an open tab). If you can't infer it confidently, tell the user once to open their dev/preview URL. Never use `serverPort` as that URL; it's the helper, not the app.
14
+ 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
15
  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=`.
16
+
17
+ The global bar **Impeccable mark** dims and shows a pulsing amber dot when no agent is long-polling `/poll`. Hover the mark for the hint; restart `live-poll.mjs` to reconnect.
14
18
  4. On `generate`: read screenshot if present; load the action's reference; plan three distinct directions; write all variants in one edit; `--reply done`; poll again.
15
- 5. On `accept` / `discard`: the poll script runs `live-accept.mjs`, acknowledges the delivered event, and prints `_completionAck`. Plain accepts/discards are terminal immediately; carbonize accepts remain recoverable until you finish cleanup, run `live-complete.mjs --id EVENT_ID`, and only then poll again.
16
- 6. If interrupted, run `live-status.mjs` or `live-resume.mjs` before guessing. The durable journal replays unacknowledged work after helper restart.
17
- 7. On `exit`: run the cleanup at the bottom.
19
+ 5. On `steer`: read the message and `pageUrl`; do the work (page edits, navigation help, or a short reply in the `--reply` message); `--reply steer_done`; poll again. No pickup ack. The Steer bar unlocks when `steer_done` arrives over SSE.
20
+ 6. On `accept` / `discard`: the poll script runs `live-accept.mjs`, acknowledges the delivered event, and prints `_completionAck`. Plain accepts/discards are terminal immediately; carbonize accepts remain recoverable until you finish cleanup, run `live-complete.mjs --id EVENT_ID`, and only then poll again.
21
+ 7. If interrupted, run `live-status.mjs` or `live-resume.mjs` before guessing. The durable journal replays unacknowledged work after helper restart.
22
+ 8. On `exit`: run the cleanup at the bottom.
18
23
 
19
24
  Harness policy:
20
25
  - **Claude Code**: run the poll as a **background task** (no short timeout). The harness notifies you when it completes, so the main conversation stays free. Do not block the shell.
21
- - **Cursor**: run the poll in the **foreground** (blocking shell; not a background terminal, not a subagent). Cursor background terminals and subagents do not reliably resume the chat with poll stdout.
26
+ - **Cursor**: run **one-shot** poll in a **background terminal** with notify on `"type":"(steer|generate|accept|discard|exit)"`. After each event the poll exits; handle it, `--reply`, then start `live-poll.mjs` again. Do **not** use `--stream` on Cursor: incremental stdout notify is slower in practice than exit-based notify (~5s vs sub-second in testing).
22
27
  - **Codex**: run the poll in the **foreground** (blocking shell; not a background task, not a subagent). Codex background exec sessions do not reliably surface poll stdout back into the conversation at the moment events arrive, so a "fire-and-forget" background poll will stall live mode.
23
- - **Other harnesses**: foreground unless you know stdout reliably returns to this session.
28
+ - **Other harnesses**: one-shot foreground unless you know stdout reliably returns to this session when a shell exits.
24
29
 
25
30
  Chat is overhead. No recap, no tutorial output, no pasting PRODUCT / DESIGN bodies. Spend tokens on tools and edits; on failure, one or two short sentences.
26
31
 
27
32
  ## Start
28
33
 
29
34
  ```bash
30
- node .claude/skills/impeccable/scripts/live.mjs
35
+ node .agents/skills/impeccable/scripts/live.mjs
31
36
  ```
32
37
 
33
- Output JSON: `{ ok, serverPort, serverToken, pageFiles, hasProduct, product, productPath, hasDesign, design, designPath, migrated }`. `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. If `migrated: true`, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md`; mention this once and suggest `/impeccable document` for the matching DESIGN.md.
38
+ 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.
34
39
 
35
40
  `serverPort` and `serverToken` belong to the small **Impeccable live helper** HTTP server (serves `/live.js`, SSE, and `/poll`). That port is **not** your dev server and is usually not the URL you open to view the app. The browser page is whatever origin serves one of the `pageFiles` entries (Vite / Next / Bun / tunnel / LAN hostname).
36
41
 
@@ -38,19 +43,33 @@ If output is `{ ok: false, error: "config_missing" | "config_invalid", path }`,
38
43
 
39
44
  ## Poll loop
40
45
 
46
+ **Default (portable, all harnesses):**
47
+
41
48
  ```
42
49
  LOOP:
43
- node .claude/skills/impeccable/scripts/live-poll.mjs # default long timeout; no --timeout=
50
+ node .agents/skills/impeccable/scripts/live-poll.mjs # default long timeout; no --timeout=
44
51
  Read JSON; dispatch on "type"
45
52
 
46
53
  "generate" → Handle Generate; reply done; LOOP
54
+ "steer" → Handle Steer; reply steer_done; LOOP
47
55
  "accept" → Handle Accept; complete carbonize cleanup if required; LOOP
48
56
  "discard" → Handle Discard; LOOP
49
57
  "prefetch" → Handle Prefetch; LOOP
58
+ "manual_edit_apply" → Handle Manual Edit Apply; reply done|partial|error; LOOP
50
59
  "timeout" → LOOP
51
60
  "exit" → break → Cleanup
52
61
  ```
53
62
 
63
+ **Stream mode (experimental, not for Cursor):**
64
+
65
+ ```
66
+ node .agents/skills/impeccable/scripts/live-poll.mjs --stream # stays running; one JSON line per event
67
+ Handle event; run --reply in a separate command
68
+ Repeat until "exit" line → Cleanup
69
+ ```
70
+
71
+ Stream keeps one process alive and waits for `--reply` ack before polling again. Useful only when the harness reads incremental stdout reliably and quickly. **Cursor is not one of those:** background pattern notify on a long-running shell was ~5s to pick up events vs sub-second for one-shot exit notify. Default to one-shot everywhere unless you have measured otherwise.
72
+
54
73
  ## Recovery commands
55
74
 
56
75
  The live helper persists an append-only journal under `.impeccable/live/sessions/`. Browser checkpoints are advisory but durable; the journal is canonical. This is local durable recovery state, not project source.
@@ -58,9 +77,9 @@ The live helper persists an append-only journal under `.impeccable/live/sessions
58
77
  Use these commands when the chat was interrupted, polling was missed, the helper restarted, or the browser reloaded:
59
78
 
60
79
  ```bash
61
- node .claude/skills/impeccable/scripts/live-status.mjs
62
- node .claude/skills/impeccable/scripts/live-resume.mjs --id SESSION_ID
63
- node .claude/skills/impeccable/scripts/live-complete.mjs --id SESSION_ID
80
+ node .agents/skills/impeccable/scripts/live-status.mjs
81
+ node .agents/skills/impeccable/scripts/live-resume.mjs --id SESSION_ID
82
+ node .agents/skills/impeccable/scripts/live-complete.mjs --id SESSION_ID
64
83
  ```
65
84
 
66
85
  - `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.
@@ -71,9 +90,32 @@ Server restart rule: start `live-server.mjs` again, then poll. Startup requeues
71
90
 
72
91
  ## Handle `generate`
73
92
 
74
- Event: `{id, action, freeformPrompt?, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
93
+ **Replace mode** (default): `{id, action, freeformPrompt?, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
94
+
95
+ **Insert mode** (`event.mode === "insert"`): `{id, mode: "insert", count, pageUrl, insert: { position, anchor }, placeholder: { width, height }, freeformPrompt?, screenshotPath?, comments?, strokes?}`. No `action`. Requires a non-empty `freeformPrompt` **or** annotations. Screenshot is sent only when annotations exist (same rule as replace). Use `placeholder` dimensions as a soft size hint for net-new content.
96
+
97
+ Speed matters; the user is watching a spinner. Minimize tool calls by using the wrap/insert helper and writing all variants in a single edit.
98
+
99
+ ### Insert mode branch
100
+
101
+ When `event.mode === "insert"`:
102
+
103
+ 1. Read the screenshot if `event.screenshotPath` is present (annotations only).
104
+ 2. Run the insert helper instead of wrap:
105
+
106
+ ```bash
107
+ node .agents/skills/impeccable/scripts/live-insert.mjs --id EVENT_ID --count EVENT_COUNT --position after \
108
+ --element-id "ANCHOR_ID" --classes "class1,class2" --tag "section" --text "ANCHOR_TEXT"
109
+ ```
110
+
111
+ - `--position` ← `event.insert.position` (`before` | `after`)
112
+ - Anchor flags ← `event.insert.anchor` (same mapping as wrap: id, classes, tag, text)
113
+
114
+ The scaffold has **no** `data-impeccable-variant="original"`. Variants are net-new HTML+CSS inserted at `insertLine`. Load `brand.md` or `product.md` (freeform only, no action sub-command). Write all variants in one edit, then `--reply done`.
115
+
116
+ On accept/discard, `live-accept.mjs` removes the wrapper block; the anchor element is untouched.
75
117
 
76
- Speed matters; the user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
118
+ ### Replace mode (default)
77
119
 
78
120
  ### 1. Read the screenshot (if present)
79
121
 
@@ -93,7 +135,7 @@ Reading annotations precisely:
93
135
  ### 2. Wrap the element
94
136
 
95
137
  ```bash
96
- node .claude/skills/impeccable/scripts/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div" --text "TEXT_SNIPPET"
138
+ node .agents/skills/impeccable/scripts/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div" --text "TEXT_SNIPPET"
97
139
  ```
98
140
 
99
141
  Flag mapping. Keep them separate, don't collapse into `--query`:
@@ -337,7 +379,7 @@ The carbonize cleanup step (see below) reads that comment and bakes the chosen v
337
379
  ### 8. Signal done
338
380
 
339
381
  ```bash
340
- node .claude/skills/impeccable/scripts/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
382
+ node .agents/skills/impeccable/scripts/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
341
383
  ```
342
384
 
343
385
  `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.
@@ -349,7 +391,7 @@ Then run `live-poll.mjs` again immediately.
349
391
  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:
350
392
 
351
393
  ```bash
352
- node .claude/skills/impeccable/scripts/live-poll.mjs --reply EVENT_ID error "Short reason"
394
+ node .agents/skills/impeccable/scripts/live-poll.mjs --reply EVENT_ID error "Short reason"
353
395
  ```
354
396
 
355
397
  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.
@@ -398,6 +440,7 @@ Remove the wrapper you inserted in Step 2. Nothing else to do.
398
440
 
399
441
  Event: `{id, variantId, _acceptResult, _completionAck}`. The poll script already ran `live-accept.mjs` to handle the file operation deterministically, then acknowledged event delivery to the helper. The browser DOM is already updated.
400
442
 
443
+ - The accept event includes `pageUrl`; the poll script must forward it to `live-accept.mjs --page-url PAGE_URL` so accept-time cleanup only scrubs staged copy edits for the current page.
401
444
  - `_completionAck.ok !== true`: do not poll yet. Run `live-status.mjs` / `live-resume.mjs`, complete the cleanup manually if needed, then run `live-complete.mjs --id EVENT_ID`.
402
445
  - `_acceptResult.handled: true` and `carbonize: false`: nothing to do. Poll again.
403
446
  - `_acceptResult.handled: true` and `carbonize: true`: **post-accept cleanup is required before the next poll.** See the "Required after accept (carbonize)" section below. The `event._acceptResult.todo` field, `_completionAck.requiresComplete`, and a stderr banner all point at this required follow-up; none are decorative. After cleanup, run `live-complete.mjs --id EVENT_ID`, then poll again.
@@ -424,6 +467,28 @@ A background agent may be used for the rewrite, but the current thread is respon
424
467
 
425
468
  Event: `{id, _acceptResult, _completionAck}`. The poll script already restored the original, removed all variant markers, and acknowledged `discarded` durable completion. Nothing to do unless `_completionAck.ok !== true`; in that case run `live-complete.mjs --id EVENT_ID --discarded`, then poll again.
426
469
 
470
+ ## Handle `steer`
471
+
472
+ Event: `{id, message, pageUrl}`. The user typed or spoke into the global bar **Steer** control: page-level direction without picking an element or launching variant generation.
473
+
474
+ The mic button uses the browser **Web Speech API** (MVP): click to start, speak, stop automatically when the utterance ends, then the transcript submits as a steer event. Click again while listening to cancel without submitting.
475
+
476
+ This is lighter than `generate`: no screenshot, no element context, no variant cycling. Read `message` and inspect the live page or project files as needed, then either make edits or answer in prose.
477
+
478
+ When finished:
479
+
480
+ ```bash
481
+ node .agents/skills/impeccable/scripts/live-poll.mjs --reply EVENT_ID steer_done ["Optional short note for a browser toast"]
482
+ ```
483
+
484
+ On failure:
485
+
486
+ ```bash
487
+ node .agents/skills/impeccable/scripts/live-poll.mjs --reply EVENT_ID error "Short reason"
488
+ ```
489
+
490
+ 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.
491
+
427
492
  ## Handle `prefetch`
428
493
 
429
494
  Event: `{pageUrl}`. The browser fires this the first time the user selects an element on a given route, as a latency shortcut; it signals the user is likely about to Go on a page you haven't read yet.
@@ -437,6 +502,18 @@ Read the file into context, then poll again. No `--reply`: this is speculative p
437
502
 
438
503
  Dedupe is the browser's job (one prefetch per unique pathname per session); trust it. If the same file shows up twice from different routes mapping to the same file, the second Read is cached anyway.
439
504
 
505
+ ## Handle `manual_edit_apply`
506
+
507
+ Event: `{id, pageUrl, batch: {entries}, evidencePath?, chunk?, repair?, deadlineMs}`.
508
+
509
+ The user already clicked Apply. Do not ask what to do, discard, or redirect to Go. The parent live thread keeps the foreground poll loop and sends the final `/poll --reply --data`.
510
+
511
+ When native subagents are available, delegate source edits to `impeccable_manual_edit_applier` / `impeccable-manual-edit-applier`. Pass cwd, scripts path, event id, page URL, chunk/deadline, `batch`, `evidencePath`, and the canonical JSON result schema. The subagent must not poll or reply. If unavailable, apply inline with the same contract.
512
+
513
+ 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.
514
+
515
+ After source edits finish, reply exactly once with `node .agents/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.
516
+
440
517
  ## Exit
441
518
 
442
519
  The user can stop live mode by:
@@ -449,7 +526,7 @@ When the poll returns `exit`, proceed to cleanup. If the poll is still running a
449
526
  ## Cleanup
450
527
 
451
528
  ```bash
452
- node .claude/skills/impeccable/scripts/live-server.mjs stop
529
+ node .agents/skills/impeccable/scripts/live-server.mjs stop
453
530
  ```
454
531
 
455
532
  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.
@@ -535,7 +612,7 @@ If `config.cspChecked === true`, skip this entire section. You already asked thi
535
612
  Otherwise, run the detection helper:
536
613
 
537
614
  ```bash
538
- node .claude/skills/impeccable/scripts/detect-csp.mjs
615
+ node .agents/skills/impeccable/scripts/detect-csp.mjs
539
616
  ```
540
617
 
541
618
  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.
@@ -231,4 +231,4 @@ Test with real users:
231
231
  - **Completion rate**: Are users completing? (If low, simplify)
232
232
  - **Time to value**: How long until users get first value?
233
233
 
234
- When users hit the aha moment fast and don't drop off, hand off to `/impeccable polish` for the final pass.
234
+ When users hit the aha moment fast and don't drop off, hand off to `$impeccable polish` for the final pass.
@@ -255,4 +255,4 @@ Test that optimizations worked:
255
255
  - **No regressions**: Ensure functionality still works
256
256
  - **User perception**: Does it *feel* faster?
257
257
 
258
- When the user-facing numbers move, hand off to `/impeccable polish` for the final pass.
258
+ When the user-facing numbers move, hand off to `$impeccable polish` for the final pass.
@@ -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. **STOP and call the AskUserQuestion tool to clarify.** to present these directions and get the user's pick before writing any code. Explain trade-offs (browser support, performance cost, complexity).
17
+ 2. **STOP and use Codex's structured user-input/question tool when available; if unavailable, ask directly in chat 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.
@@ -35,10 +35,10 @@ Understand the current state and goals before touching anything:
35
35
  - Loading and transition smoothness
36
36
  - Information architecture and flow drift (does this feature reveal complexity the way neighboring features do?)
37
37
 
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:
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 .claude/skills/impeccable/scripts/critique-storage.mjs slug "<resolved>")
41
- node .claude/skills/impeccable/scripts/critique-storage.mjs latest "$slug"
40
+ slug=$(node .agents/skills/impeccable/scripts/critique-storage.mjs slug "<resolved>")
41
+ node .agents/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
 
@@ -91,7 +91,6 @@ Visual polish on a misshapen flow is wasted work. Match the *shape* of the exper
91
91
  - **Theme consistency**: Works in all theme variants
92
92
  - **Color meaning**: Same colors mean same things throughout
93
93
  - **Accessible focus**: Focus indicators visible with sufficient contrast
94
- - **Tinted neutrals**: No pure gray or pure black; add subtle color tint (0.01 chroma)
95
94
  - **Gray on color**: Never put gray text on colored backgrounds; use a shade of that color or transparency
96
95
 
97
96
  ### Interaction States
@@ -10,7 +10,6 @@ Product UI's failure mode isn't flatness, it's strangeness without purpose: over
10
10
 
11
11
  ## Typography
12
12
 
13
- - **System fonts are legitimate.** `-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif` gives you native feel on every platform. Inter is the common cross-platform default for a reason.
14
13
  - **One family is often right.** Product UIs don't need display/body pairing. A well-tuned sans carries headings, buttons, labels, body, data.
15
14
  - **Fixed rem scale, not fluid.** Clamp-sized headings don't serve product UI. Users view at consistent DPI, and a fluid h1 that shrinks in a sidebar looks worse, not better.
16
15
  - **Tighter scale ratio.** 1.125–1.2 between steps is typical. More type elements here than on brand surfaces; exaggerated contrast creates noise.
@@ -26,8 +25,6 @@ Product defaults to Restrained. A single surface can earn Committed (a dashboard
26
25
 
27
26
  ## Layout
28
27
 
29
- - Predictable grids. Consistency IS an affordance; users navigate faster when the structure is expected.
30
- - Familiar patterns are features. Standard navigation (top bar, side nav), breadcrumbs, tabs, and form layouts have established user expectations. Don't reinvent for flavor.
31
28
  - Responsive behavior is structural (collapse sidebar, responsive table, breakpoint-driven columns), not fluid typography.
32
29
 
33
30
  ## Components
@@ -51,6 +48,7 @@ Every interactive component has: default, hover, focus, active, disabled, loadin
51
48
  - Display fonts in UI labels, buttons, data.
52
49
  - Reinventing standard affordances for flavor (custom scrollbars, weird form controls, non-standard modals).
53
50
  - Heavy color or full-saturation accents on inactive states.
51
+ - Modal as first thought. Modals are usually laziness. Exhaust inline / progressive alternatives first.
54
52
 
55
53
  ## Product permissions
56
54
 
@@ -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, STOP and call the AskUserQuestion tool to clarify.
31
+ If any of these are unclear from the codebase, STOP and use Codex's structured user-input/question tool when available; if unavailable, ask directly in chat 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
 
@@ -96,4 +96,4 @@ Ensure refinement maintains quality:
96
96
  - **Better reading**: Is text easier to read for extended periods?
97
97
  - **Restrained, not absent**: Does the POV survive the cuts?
98
98
 
99
- When the result feels right, hand off to `/impeccable polish` for the final pass.
99
+ When the result feels right, hand off to `$impeccable polish` for the final pass.
@@ -2,7 +2,7 @@ Shape the UX and UI for a feature before any code is written. This command produ
2
2
 
3
3
  **Scope**: Design planning only. This command does NOT write code. It produces the thinking that makes code good.
4
4
 
5
- **Output**: A design brief that can be handed off to /impeccable craft, or directly to /impeccable for freeform implementation. When visual direction probes are used, the images are supporting artifacts, not the primary output.
5
+ **Output**: A design brief that can be handed off to $impeccable craft, or directly to $impeccable for freeform implementation. When visual direction probes are used, the images are supporting artifacts, not the primary output.
6
6
 
7
7
  ## Philosophy
8
8
 
@@ -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. STOP and call the AskUserQuestion tool to clarify.
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. STOP and use Codex's structured user-input/question tool when available; if unavailable, ask directly in chat to clarify what you cannot infer.
16
16
 
17
17
  ### Interview cadence
18
18
 
@@ -151,15 +151,15 @@ How users interact with this feature. What happens on click, hover, scroll? What
151
151
  What copy, labels, empty state messages, error messages, and microcopy are needed. Note any dynamic content and its realistic ranges. For image-led surfaces, also list the required image/media roles and their likely source (project asset, generated raster, semantic SVG/CSS, canvas/WebGL, icon library, or accepted omission).
152
152
 
153
153
  **9. Recommended References**
154
- Based on the brief, list which impeccable reference files would be most valuable during implementation (e.g., spatial-design.md for complex layouts, motion-design.md for animated features, interaction-design.md for form-heavy features).
154
+ Based on the brief, list which impeccable reference files would be most valuable during implementation (e.g., layout.md for complex layouts, animate.md for animated features, interaction-design.md for form-heavy features, typeset.md for typography-driven pages, colorize.md for color-led brands).
155
155
 
156
156
  **10. Open Questions**
157
157
  Anything genuinely unresolved. Don't list "open questions" you've already recommended a default for; assert the default and move on. If you'd write `Recommend: X` next to a question, just decide X.
158
158
 
159
159
  ---
160
160
 
161
- STOP and call the AskUserQuestion tool to clarify. Ask for explicit confirmation of the brief before finishing.
161
+ STOP and use Codex's structured user-input/question tool when available; if unavailable, ask directly in chat 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
 
165
- Once confirmed, the brief is complete. The user can now hand it to /impeccable, or use it to guide any other implementation approach. (If the user wants the full discovery-then-build flow in one step, they should use /impeccable craft instead, which runs this command internally.)
165
+ Once confirmed, the brief is complete. The user can now hand it to $impeccable, or use it to guide any other implementation approach. (If the user wants the full discovery-then-build flow in one step, they should use $impeccable craft instead, which runs this command internally.)
@@ -4,7 +4,7 @@ Typography carries most of the information on the page. Replace generic defaults
4
4
 
5
5
  ## Register
6
6
 
7
- Brand: run the font selection procedure in [brand.md](brand.md). Pairing follows the brand's lane (display serif + sans body for editorial/luxury, one committed sans for tech, etc.). Fluid `clamp()` scale, ≥1.25 ratio between steps.
7
+ Brand: run the font selection procedure in [brand.md](brand.md). Fluid `clamp()` scale, ≥1.25 ratio between steps.
8
8
 
9
9
  Product: system fonts and familiar sans stacks are legitimate here. One well-tuned family typically carries the whole UI. Fixed `rem` scale, 1.125–1.2 ratio between more closely-spaced steps.
10
10
 
@@ -43,7 +43,7 @@ Analyze what's weak or generic about the current type:
43
43
 
44
44
  ## Plan Typography Improvements
45
45
 
46
- Consult the [typography reference](typography.md) for detailed guidance on scales, pairing, and loading strategies.
46
+ Consult the [Reference Material](#reference-material) section below for detailed guidance on scales, pairing, and loading strategies.
47
47
 
48
48
  Create a systematic plan:
49
49
 
@@ -109,7 +109,7 @@ Build a clear type scale:
109
109
  - **Performance**: Are web fonts loading efficiently without layout shift?
110
110
  - **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
111
111
 
112
- When the type carries the hierarchy on its own, hand off to `/impeccable polish` for the final pass.
112
+ When the type carries the hierarchy on its own, hand off to `$impeccable polish` for the final pass.
113
113
 
114
114
  ## Live-mode signature params
115
115
 
@@ -122,3 +122,158 @@ Each variant MUST declare a `scale` param controlling the hierarchy ratio. Expre
122
122
  Where the variant riffs on a specific pairing, expose the pairing choice as a `steps` param (e.g. "serif display + sans body" vs. "mono display + sans body" vs. "all-sans"). Each branch routes through `:scope[data-p-pairing="X"]` selectors in scoped CSS.
123
123
 
124
124
  See `reference/live.md` for the full params contract.
125
+
126
+ ---
127
+
128
+ ## Reference Material
129
+
130
+ The sections below were previously `typography.md` and live inline now so the typeset flow has its deep typography reference in one place. `bolder.md` also references this section.
131
+
132
+ ### Typography
133
+
134
+ #### Classic Typography Principles
135
+
136
+ ##### Vertical Rhythm
137
+
138
+ Your line-height should be the base unit for ALL vertical spacing. If body text has `line-height: 1.5` on `16px` type (= 24px), spacing values should be multiples of 24px. This creates subconscious harmony; text and space share a mathematical foundation.
139
+
140
+ ##### Modular Scale & Hierarchy
141
+
142
+ The common mistake: too many font sizes that are too close together (14px, 15px, 16px, 18px...). This creates muddy hierarchy.
143
+
144
+ **Use fewer sizes with more contrast.** A 5-size system covers most needs:
145
+
146
+ | Role | Typical Ratio | Use Case |
147
+ |------|---------------|----------|
148
+ | xs | 0.75rem | Captions, legal |
149
+ | sm | 0.875rem | Secondary UI, metadata |
150
+ | base | 1rem | Body text |
151
+ | lg | 1.25-1.5rem | Subheadings, lead text |
152
+ | xl+ | 2-4rem | Headlines, hero text |
153
+
154
+ Popular ratios: 1.25 (major third), 1.333 (perfect fourth), 1.5 (perfect fifth). Pick one and commit.
155
+
156
+ ##### Readability & Measure
157
+
158
+ Use `ch` units for character-based measure (`max-width: 65ch`). Line-height scales inversely with line length: narrow columns need tighter leading, wide columns need more.
159
+
160
+ **Non-obvious**: Light text on dark backgrounds needs compensation on three axes, not just one. Bump line-height by 0.05–0.1, add a touch of letter-spacing (0.01–0.02em), and optionally step the body weight up one notch (regular → medium). The perceived weight drops across all three; fix all three.
161
+
162
+ **Paragraph rhythm**: Pick either space between paragraphs OR first-line indentation. Never both. Digital usually wants space; editorial/long-form can justify indent-only.
163
+
164
+ #### Font Selection & Pairing
165
+
166
+ The tactical selection procedure and the reflex-reject list live in [reference/brand.md](brand.md) under **Font selection procedure** and **Reflex-reject list** (loaded for brand-register tasks). The rest of this section covers the adjacent knowledge: anti-reflex corrections, system font use, and pairing rules.
167
+
168
+ ##### Anti-reflexes worth defending against
169
+
170
+ - A technical/utilitarian brief does NOT need a serif "for warmth." Most tech tools should look like tech tools.
171
+ - An editorial/premium brief does NOT need the same expressive serif everyone is using right now. Premium can be Swiss-modern, can be neo-grotesque, can be a literal monospace, can be a quiet humanist sans.
172
+ - A children's product does NOT need a rounded display font. Kids' books use real type.
173
+ - A "modern" brief does NOT need a geometric sans. The most modern thing you can do is not use the font everyone else is using.
174
+
175
+ **System fonts are underrated**: `-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui` looks native, loads instantly, and is highly readable. Consider this for apps where performance > personality.
176
+
177
+ ##### Pairing Principles
178
+
179
+ **The non-obvious truth**: You often don't need a second font. One well-chosen font family in multiple weights creates cleaner hierarchy than two competing typefaces. Only add a second font when you need genuine contrast (e.g., display headlines + body serif).
180
+
181
+ When pairing, contrast on multiple axes:
182
+ - Serif + Sans (structure contrast)
183
+ - Geometric + Humanist (personality contrast)
184
+ - Condensed display + Wide body (proportion contrast)
185
+
186
+ ##### Web Font Loading
187
+
188
+ The layout shift problem: fonts load late, text reflows, and users see content jump. Here's the fix:
189
+
190
+ ```css
191
+ /* 1. Use font-display: swap for visibility */
192
+ @font-face {
193
+ font-family: 'CustomFont';
194
+ src: url('font.woff2') format('woff2');
195
+ font-display: swap;
196
+ }
197
+
198
+ /* 2. Match fallback metrics to minimize shift */
199
+ @font-face {
200
+ font-family: 'CustomFont-Fallback';
201
+ src: local('Arial');
202
+ size-adjust: 105%; /* Scale to match x-height */
203
+ ascent-override: 90%; /* Match ascender height */
204
+ descent-override: 20%; /* Match descender depth */
205
+ line-gap-override: 10%; /* Match line spacing */
206
+ }
207
+
208
+ body {
209
+ font-family: 'CustomFont', 'CustomFont-Fallback', sans-serif;
210
+ }
211
+ ```
212
+
213
+ Tools like [Fontaine](https://github.com/unjs/fontaine) calculate these overrides automatically.
214
+
215
+ **`swap` vs `optional`**: `swap` shows fallback text immediately and FOUT-swaps when the web font arrives. `optional` uses the fallback if the web font misses a small load budget (~100ms) and avoids the shift entirely. Pick `optional` when zero layout shift matters more than seeing the branded font on slow networks.
216
+
217
+ **Preload the critical weight only**: typically the regular-weight body font used above the fold. Preloading every weight costs more bandwidth than it saves.
218
+
219
+ **Variable fonts for 3+ weights or styles**: a single variable font file is usually smaller than three static weight files, gives fractional weight control, and pairs well with `font-optical-sizing: auto`. For 1–2 weights, static is fine.
220
+
221
+ #### Modern Web Typography
222
+
223
+ ##### Fluid Type
224
+
225
+ Fluid typography via `clamp(min, preferred, max)` scales text smoothly with the viewport. The middle value (e.g., `5vw + 1rem`) controls scaling rate (higher vw = faster scaling). Add a rem offset so it doesn't collapse to 0 on small screens.
226
+
227
+ **Use fluid type for**: Headings and display text on marketing/content pages where text dominates the layout and needs to breathe across viewport sizes.
228
+
229
+ **Use fixed `rem` scales for**: App UIs, dashboards, and data-dense interfaces. No major app design system (Material, Polaris, Primer, Carbon) uses fluid type in product UI; fixed scales with optional breakpoint adjustments give the spatial predictability that container-based layouts need. Body text should also be fixed even on marketing pages, since the size difference across viewports is too small to warrant it.
230
+
231
+ **Bound your clamp()**: keep `max-size ≤ ~2.5 × min-size`. Wider ratios break the browser's zoom and reflow behaviour and make large viewports feel like the page is shouting.
232
+
233
+ **Scale container width and font-size together** so effective character measure stays in the 45–75ch band at every viewport. A heading that widens faster than its container drifts out of the comfortable measure at the top end.
234
+
235
+ ##### OpenType Features
236
+
237
+ Most developers don't know these exist. Use them for polish:
238
+
239
+ ```css
240
+ /* Proper fractions */
241
+ .recipe-amount { font-variant-numeric: diagonal-fractions; }
242
+
243
+ /* Small caps for abbreviations */
244
+ abbr { font-variant-caps: all-small-caps; }
245
+
246
+ /* Disable ligatures in code */
247
+ code { font-variant-ligatures: none; }
248
+
249
+ /* Enable kerning (usually on by default, but be explicit) */
250
+ body { font-kerning: normal; }
251
+ ```
252
+
253
+ Check what features your font supports at [Wakamai Fondue](https://wakamaifondue.com/).
254
+
255
+ ##### Rendering polish
256
+
257
+ ```css
258
+ /* Variable fonts: pick the right optical-size master automatically */
259
+ body { font-optical-sizing: auto; }
260
+ ```
261
+
262
+ **ALL-CAPS tracking**: capitals sit too close at default spacing. Add 5–12% letter-spacing (`letter-spacing: 0.05em` to `0.12em`) to short all-caps labels, eyebrows, and small headings. Real small caps (via `font-variant-caps`) need the same treatment, slightly gentler.
263
+
264
+ #### Typography System Architecture
265
+
266
+ Name tokens semantically (`--text-body`, `--text-heading`), not by value (`--font-size-16`). Include font stacks, size scale, weights, line-heights, and letter-spacing in your token system.
267
+
268
+ #### Accessibility Considerations
269
+
270
+ Beyond contrast ratios (which are well-documented), consider:
271
+
272
+ - **Never disable zoom**: `user-scalable=no` breaks accessibility. If your layout breaks at 200% zoom, fix the layout.
273
+ - **Use rem/em for font sizes**: This respects user browser settings. Never `px` for body text.
274
+ - **Minimum 16px body text**: Smaller than this strains eyes and fails WCAG on mobile.
275
+ - **Adequate touch targets**: Text links need padding or line-height that creates 44px+ tap targets.
276
+
277
+ ---
278
+
279
+ **Avoid**: More than 2-3 font families per project. Skipping fallback font definitions. Ignoring font loading performance (FOUT/FOIT). Using decorative fonts for body text.
@@ -25,7 +25,7 @@ import { join, resolve } from 'node:path';
25
25
  const DEPRECATED_NAMES = [
26
26
  // v2.0 renames
27
27
  'frontend-design', // renamed to impeccable
28
- 'teach-impeccable', // folded into /impeccable teach
28
+ 'teach-impeccable', // folded into /impeccable init
29
29
  // v2.1 merges
30
30
  'arrange', // renamed to layout
31
31
  'normalize', // merged into polish
@@ -3,8 +3,8 @@
3
3
  "description": "Full confirmed-brief-then-build flow. Runs multi-round shape discovery first, resolves visual probe and north-star mock gates when available, then builds and visually iterates. Use when building a new feature end-to-end.",
4
4
  "argumentHint": "[feature description]"
5
5
  },
6
- "teach": {
7
- "description": "Gathers design context for a project. Runs a multi-round discovery interview when context is missing and writes PRODUCT.md (strategic: users, brand, principles) and, when code exists to analyze, DESIGN.md (visual: colors, typography, components). Every other command reads these files before doing work. Use once per project.",
6
+ "init": {
7
+ "description": "Sets up a project for impeccable. Runs a multi-round discovery interview when context is missing and writes PRODUCT.md (strategic: users, brand, principles); offers DESIGN.md (visual: colors, typography, components) when code exists; pre-configures live mode; then recommends the best commands to run next. Every other command reads these files before doing work. Use once per project.",
8
8
  "argumentHint": ""
9
9
  },
10
10
  "document": {