@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
@@ -1,159 +0,0 @@
1
- # Typography
2
-
3
- ## Classic Typography Principles
4
-
5
- ### Vertical Rhythm
6
-
7
- 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.
8
-
9
- ### Modular Scale & Hierarchy
10
-
11
- The common mistake: too many font sizes that are too close together (14px, 15px, 16px, 18px...). This creates muddy hierarchy.
12
-
13
- **Use fewer sizes with more contrast.** A 5-size system covers most needs:
14
-
15
- | Role | Typical Ratio | Use Case |
16
- |------|---------------|----------|
17
- | xs | 0.75rem | Captions, legal |
18
- | sm | 0.875rem | Secondary UI, metadata |
19
- | base | 1rem | Body text |
20
- | lg | 1.25-1.5rem | Subheadings, lead text |
21
- | xl+ | 2-4rem | Headlines, hero text |
22
-
23
- Popular ratios: 1.25 (major third), 1.333 (perfect fourth), 1.5 (perfect fifth). Pick one and commit.
24
-
25
- ### Readability & Measure
26
-
27
- 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.
28
-
29
- **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.
30
-
31
- **Paragraph rhythm**: Pick either space between paragraphs OR first-line indentation. Never both. Digital usually wants space; editorial/long-form can justify indent-only.
32
-
33
- ## Font Selection & Pairing
34
-
35
- 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.
36
-
37
- ### Anti-reflexes worth defending against
38
-
39
- - A technical/utilitarian brief does NOT need a serif "for warmth." Most tech tools should look like tech tools.
40
- - 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.
41
- - A children's product does NOT need a rounded display font. Kids' books use real type.
42
- - 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.
43
-
44
- **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.
45
-
46
- ### Pairing Principles
47
-
48
- **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).
49
-
50
- When pairing, contrast on multiple axes:
51
- - Serif + Sans (structure contrast)
52
- - Geometric + Humanist (personality contrast)
53
- - Condensed display + Wide body (proportion contrast)
54
-
55
- **Never pair fonts that are similar but not identical** (e.g., two geometric sans-serifs). They create visual tension without clear hierarchy.
56
-
57
- ### Web Font Loading
58
-
59
- The layout shift problem: fonts load late, text reflows, and users see content jump. Here's the fix:
60
-
61
- ```css
62
- /* 1. Use font-display: swap for visibility */
63
- @font-face {
64
- font-family: 'CustomFont';
65
- src: url('font.woff2') format('woff2');
66
- font-display: swap;
67
- }
68
-
69
- /* 2. Match fallback metrics to minimize shift */
70
- @font-face {
71
- font-family: 'CustomFont-Fallback';
72
- src: local('Arial');
73
- size-adjust: 105%; /* Scale to match x-height */
74
- ascent-override: 90%; /* Match ascender height */
75
- descent-override: 20%; /* Match descender depth */
76
- line-gap-override: 10%; /* Match line spacing */
77
- }
78
-
79
- body {
80
- font-family: 'CustomFont', 'CustomFont-Fallback', sans-serif;
81
- }
82
- ```
83
-
84
- Tools like [Fontaine](https://github.com/unjs/fontaine) calculate these overrides automatically.
85
-
86
- **`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.
87
-
88
- **Preload the critical weight only**: typically the regular-weight body font used above the fold. Preloading every weight costs more bandwidth than it saves.
89
-
90
- **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.
91
-
92
- ## Modern Web Typography
93
-
94
- ### Fluid Type
95
-
96
- 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.
97
-
98
- **Use fluid type for**: Headings and display text on marketing/content pages where text dominates the layout and needs to breathe across viewport sizes.
99
-
100
- **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.
101
-
102
- **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.
103
-
104
- **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.
105
-
106
- ### OpenType Features
107
-
108
- Most developers don't know these exist. Use them for polish:
109
-
110
- ```css
111
- /* Tabular numbers for data alignment */
112
- .data-table { font-variant-numeric: tabular-nums; }
113
-
114
- /* Proper fractions */
115
- .recipe-amount { font-variant-numeric: diagonal-fractions; }
116
-
117
- /* Small caps for abbreviations */
118
- abbr { font-variant-caps: all-small-caps; }
119
-
120
- /* Disable ligatures in code */
121
- code { font-variant-ligatures: none; }
122
-
123
- /* Enable kerning (usually on by default, but be explicit) */
124
- body { font-kerning: normal; }
125
- ```
126
-
127
- Check what features your font supports at [Wakamai Fondue](https://wakamaifondue.com/).
128
-
129
- ### Rendering polish
130
-
131
- ```css
132
- /* Even out heading line lengths (browser picks better break points) */
133
- h1, h2, h3 { text-wrap: balance; }
134
-
135
- /* Reduce orphans and ragged endings in long prose */
136
- article p { text-wrap: pretty; }
137
-
138
- /* Variable fonts: pick the right optical-size master automatically */
139
- body { font-optical-sizing: auto; }
140
- ```
141
-
142
- **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.
143
-
144
- ## Typography System Architecture
145
-
146
- 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.
147
-
148
- ## Accessibility Considerations
149
-
150
- Beyond contrast ratios (which are well-documented), consider:
151
-
152
- - **Never disable zoom**: `user-scalable=no` breaks accessibility. If your layout breaks at 200% zoom, fix the layout.
153
- - **Use rem/em for font sizes**: This respects user browser settings. Never `px` for body text.
154
- - **Minimum 16px body text**: Smaller than this strains eyes and fails WCAG on mobile.
155
- - **Adequate touch targets**: Text links need padding or line-height that creates 44px+ tap targets.
156
-
157
- ---
158
-
159
- **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.
@@ -1,107 +0,0 @@
1
- # UX Writing
2
-
3
- ## The Button Label Problem
4
-
5
- **Never use "OK", "Submit", or "Yes/No".** These are lazy and ambiguous. Use specific verb + object patterns:
6
-
7
- | Bad | Good | Why |
8
- |-----|------|-----|
9
- | OK | Save changes | Says what will happen |
10
- | Submit | Create account | Outcome-focused |
11
- | Yes | Delete message | Confirms the action |
12
- | Cancel | Keep editing | Clarifies what "cancel" means |
13
- | Click here | Download PDF | Describes the destination |
14
-
15
- **For destructive actions**, name the destruction:
16
- - "Delete" not "Remove" (delete is permanent, remove implies recoverable)
17
- - "Delete 5 items" not "Delete selected" (show the count)
18
-
19
- ## Error Messages: The Formula
20
-
21
- Every error message should answer: (1) What happened? (2) Why? (3) How to fix it? Example: "Email address isn't valid. Please include an @ symbol." not "Invalid input".
22
-
23
- ### Error Message Templates
24
-
25
- | Situation | Template |
26
- |-----------|----------|
27
- | **Format error** | "[Field] needs to be [format]. Example: [example]" |
28
- | **Missing required** | "Please enter [what's missing]" |
29
- | **Permission denied** | "You don't have access to [thing]. [What to do instead]" |
30
- | **Network error** | "We couldn't reach [thing]. Check your connection and [action]." |
31
- | **Server error** | "Something went wrong on our end. We're looking into it. [Alternative action]" |
32
-
33
- ### Don't Blame the User
34
-
35
- Reframe errors: "Please enter a date in MM/DD/YYYY format" not "You entered an invalid date".
36
-
37
- ## Empty States Are Opportunities
38
-
39
- Empty states are onboarding moments: (1) Acknowledge briefly, (2) Explain the value of filling it, (3) Provide a clear action. "No projects yet. Create your first one to get started." not just "No items".
40
-
41
- ## Voice vs Tone
42
-
43
- **Voice** is your brand's personality, consistent everywhere.
44
- **Tone** adapts to the moment.
45
-
46
- | Moment | Tone Shift |
47
- |--------|------------|
48
- | Success | Celebratory, brief: "Done! Your changes are live." |
49
- | Error | Empathetic, helpful: "That didn't work. Here's what to try..." |
50
- | Loading | Reassuring: "Saving your work..." |
51
- | Destructive confirm | Serious, clear: "Delete this project? This can't be undone." |
52
-
53
- **Never use humor for errors.** Users are already frustrated. Be helpful, not cute.
54
-
55
- ## Writing for Accessibility
56
-
57
- **Link text** must have standalone meaning: "View pricing plans" not "Click here". **Alt text** describes information, not the image: "Revenue increased 40% in Q4" not "Chart". Use `alt=""` for decorative images. **Icon buttons** need `aria-label` for screen reader context.
58
-
59
- ## Writing for Translation
60
-
61
- ### Plan for Expansion
62
-
63
- German text is ~30% longer than English. Allocate space:
64
-
65
- | Language | Expansion |
66
- |----------|-----------|
67
- | German | +30% |
68
- | French | +20% |
69
- | Finnish | +30-40% |
70
- | Chinese | -30% (fewer chars, but same width) |
71
-
72
- ### Translation-Friendly Patterns
73
-
74
- Keep numbers separate ("New messages: 3" not "You have 3 new messages"). Use full sentences as single strings (word order varies by language). Avoid abbreviations ("5 minutes ago" not "5 mins ago"). Give translators context about where strings appear.
75
-
76
- ## Consistency: The Terminology Problem
77
-
78
- Pick one term and stick with it:
79
-
80
- | Inconsistent | Consistent |
81
- |--------------|------------|
82
- | Delete / Remove / Trash | Delete |
83
- | Settings / Preferences / Options | Settings |
84
- | Sign in / Log in / Enter | Sign in |
85
- | Create / Add / New | Create |
86
-
87
- Build a terminology glossary and enforce it. Variety creates confusion.
88
-
89
- ## Avoid Redundant Copy
90
-
91
- If the heading explains it, the intro is redundant. If the button is clear, don't explain it again. Say it once, say it well.
92
-
93
- ## Loading States
94
-
95
- Be specific: "Saving your draft..." not "Loading...". For long waits, set expectations ("This usually takes 30 seconds") or show progress.
96
-
97
- ## Confirmation Dialogs: Use Sparingly
98
-
99
- Most confirmation dialogs are design failures; consider undo instead. When you must confirm: name the action, explain consequences, use specific button labels ("Delete project" / "Keep project", not "Yes" / "No").
100
-
101
- ## Form Instructions
102
-
103
- Show format with placeholders, not instructions. For non-obvious fields, explain why you're asking.
104
-
105
- ---
106
-
107
- **Avoid**: Jargon without explanation. Blaming users ("You made an error" → "This field is required"). Vague errors ("Something went wrong"). Varying terminology for variety. Humor for errors.
@@ -1,141 +0,0 @@
1
- /**
2
- * Shared context loader for every impeccable command that needs to know
3
- * "who is this for" and "what does this look like".
4
- *
5
- * Input: project root (process.cwd()).
6
- *
7
- * Output (JSON to stdout):
8
- * {
9
- * hasProduct: boolean, // PRODUCT.md found (or auto-migrated)
10
- * product: string | null, // PRODUCT.md contents
11
- * productPath: string | null, // relative path
12
- * hasDesign: boolean, // DESIGN.md found
13
- * design: string | null, // DESIGN.md contents
14
- * designPath: string | null,
15
- * migrated: boolean, // true if we auto-renamed .impeccable.md -> PRODUCT.md
16
- * contextDir: string, // absolute path of the directory the files were found in
17
- * }
18
- *
19
- * Filename matching is case-insensitive for PRODUCT.md and DESIGN.md. The
20
- * Google DESIGN.md convention is uppercase at repo root; Kiro-style and
21
- * lowercase variants are also matched so users don't get punished for case.
22
- *
23
- * Lookup directory resolution (first match wins):
24
- * 1. process.env.IMPECCABLE_CONTEXT_DIR (absolute or relative to cwd)
25
- * 2. cwd, if PRODUCT.md / DESIGN.md / .impeccable.md is there (back-compat)
26
- * 3. Auto-fallback subdirectories of cwd: .agents/context/, then docs/
27
- * 4. cwd as a default "no context found" location
28
- *
29
- * Legacy `.impeccable.md` -> PRODUCT.md migration only fires at cwd root;
30
- * fallback directories are read-only as far as auto-rename is concerned.
31
- */
32
-
33
- import fs from 'node:fs';
34
- import path from 'node:path';
35
-
36
- const PRODUCT_NAMES = ['PRODUCT.md', 'Product.md', 'product.md'];
37
- const DESIGN_NAMES = ['DESIGN.md', 'Design.md', 'design.md'];
38
- const LEGACY_NAMES = ['.impeccable.md'];
39
- const FALLBACK_DIRS = ['.agents/context', 'docs'];
40
-
41
- /**
42
- * Resolve the directory that holds PRODUCT.md / DESIGN.md for
43
- * this project. Exported so other scripts (e.g. live-server.mjs) can read the
44
- * design files from the same location the loader uses.
45
- */
46
- export function resolveContextDir(cwd = process.cwd()) {
47
- // 1. Explicit override
48
- const envDir = process.env.IMPECCABLE_CONTEXT_DIR;
49
- if (envDir && envDir.trim()) {
50
- const trimmed = envDir.trim();
51
- return path.isAbsolute(trimmed) ? trimmed : path.resolve(cwd, trimmed);
52
- }
53
-
54
- // 2. cwd wins if any canonical or legacy file is there. We check legacy too
55
- // so the auto-migration path in loadContext stays predictable.
56
- if (firstExisting(cwd, [...PRODUCT_NAMES, ...DESIGN_NAMES, ...LEGACY_NAMES])) {
57
- return cwd;
58
- }
59
-
60
- // 3. Auto-fallback subdirs. Match if PRODUCT.md or DESIGN.md is present;
61
- // legacy `.impeccable.md` does not pull the lookup into a fallback dir.
62
- for (const rel of FALLBACK_DIRS) {
63
- const candidate = path.resolve(cwd, rel);
64
- if (firstExisting(candidate, [...PRODUCT_NAMES, ...DESIGN_NAMES])) {
65
- return candidate;
66
- }
67
- }
68
-
69
- // 4. Nothing found — keep the historical "default to cwd" behaviour so the
70
- // caller's `hasProduct === false` branch still fires the same way.
71
- return cwd;
72
- }
73
-
74
- export function loadContext(cwd = process.cwd()) {
75
- let migrated = false;
76
- const contextDir = resolveContextDir(cwd);
77
-
78
- // 1. Look for PRODUCT.md (case-insensitive) in the resolved dir
79
- let productPath = firstExisting(contextDir, PRODUCT_NAMES);
80
-
81
- // 2. Legacy: if no PRODUCT.md but .impeccable.md exists at cwd root, rename
82
- // it in place. We only migrate at the root — fallback dirs are read-only
83
- // so we don't surprise users by mutating files under docs/ or .agents/.
84
- if (!productPath && contextDir === cwd) {
85
- const legacyPath = firstExisting(cwd, LEGACY_NAMES);
86
- if (legacyPath) {
87
- const newPath = path.join(cwd, 'PRODUCT.md');
88
- try {
89
- fs.renameSync(legacyPath, newPath);
90
- productPath = newPath;
91
- migrated = true;
92
- } catch {
93
- // Rename failed (permissions, etc.) — fall back to reading legacy in place
94
- productPath = legacyPath;
95
- }
96
- }
97
- }
98
-
99
- // 3. DESIGN.md (case-insensitive)
100
- const designPath = firstExisting(contextDir, DESIGN_NAMES);
101
-
102
- const product = productPath ? safeRead(productPath) : null;
103
- const design = designPath ? safeRead(designPath) : null;
104
-
105
- return {
106
- hasProduct: !!product,
107
- product,
108
- productPath: productPath ? path.relative(cwd, productPath) : null,
109
- hasDesign: !!design,
110
- design,
111
- designPath: designPath ? path.relative(cwd, designPath) : null,
112
- migrated,
113
- contextDir,
114
- };
115
- }
116
-
117
- function firstExisting(dir, names) {
118
- for (const name of names) {
119
- const abs = path.join(dir, name);
120
- if (fs.existsSync(abs)) return abs;
121
- }
122
- return null;
123
- }
124
-
125
- function safeRead(p) {
126
- try { return fs.readFileSync(p, 'utf-8'); } catch { return null; }
127
- }
128
-
129
- // ---------------------------------------------------------------------------
130
- // CLI mode — print the context as JSON
131
- // ---------------------------------------------------------------------------
132
-
133
- function cli() {
134
- const result = loadContext(process.cwd());
135
- console.log(JSON.stringify(result, null, 2));
136
- }
137
-
138
- const _running = process.argv[1];
139
- if (_running?.endsWith('load-context.mjs') || _running?.endsWith('load-context.mjs/')) {
140
- cli();
141
- }