@kiwidata/grimoire 0.1.3 → 0.1.4
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/AGENTS.md +56 -4
- package/README.md +28 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/check.js +1 -1
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/configure.d.ts +3 -0
- package/dist/commands/configure.d.ts.map +1 -0
- package/dist/commands/configure.js +19 -0
- package/dist/commands/configure.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +2 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/map.d.ts.map +1 -1
- package/dist/commands/map.js +10 -11
- package/dist/commands/map.js.map +1 -1
- package/dist/core/archive.d.ts.map +1 -1
- package/dist/core/archive.js +32 -43
- package/dist/core/archive.js.map +1 -1
- package/dist/core/check.d.ts.map +1 -1
- package/dist/core/check.js +115 -104
- package/dist/core/check.js.map +1 -1
- package/dist/core/ci.d.ts.map +1 -1
- package/dist/core/ci.js +50 -69
- package/dist/core/ci.js.map +1 -1
- package/dist/core/configure.d.ts +14 -0
- package/dist/core/configure.d.ts.map +1 -0
- package/dist/core/configure.js +434 -0
- package/dist/core/configure.js.map +1 -0
- package/dist/core/detect.d.ts.map +1 -1
- package/dist/core/detect.js +153 -26
- package/dist/core/detect.js.map +1 -1
- package/dist/core/diff.d.ts.map +1 -1
- package/dist/core/diff.js +62 -93
- package/dist/core/diff.js.map +1 -1
- package/dist/core/doc-style.d.ts +0 -4
- package/dist/core/doc-style.d.ts.map +1 -1
- package/dist/core/doc-style.js +28 -23
- package/dist/core/doc-style.js.map +1 -1
- package/dist/core/docs.js +106 -100
- package/dist/core/docs.js.map +1 -1
- package/dist/core/health.js +55 -77
- package/dist/core/health.js.map +1 -1
- package/dist/core/hooks.d.ts +0 -3
- package/dist/core/hooks.d.ts.map +1 -1
- package/dist/core/hooks.js +0 -11
- package/dist/core/hooks.js.map +1 -1
- package/dist/core/init.d.ts +2 -0
- package/dist/core/init.d.ts.map +1 -1
- package/dist/core/init.js +230 -406
- package/dist/core/init.js.map +1 -1
- package/dist/core/list.d.ts.map +1 -1
- package/dist/core/list.js +55 -65
- package/dist/core/list.js.map +1 -1
- package/dist/core/log.d.ts.map +1 -1
- package/dist/core/log.js +23 -33
- package/dist/core/log.js.map +1 -1
- package/dist/core/map.d.ts +15 -2
- package/dist/core/map.d.ts.map +1 -1
- package/dist/core/map.js +257 -194
- package/dist/core/map.js.map +1 -1
- package/dist/core/shared-setup.d.ts +0 -40
- package/dist/core/shared-setup.d.ts.map +1 -1
- package/dist/core/shared-setup.js +87 -52
- package/dist/core/shared-setup.js.map +1 -1
- package/dist/core/status.d.ts.map +1 -1
- package/dist/core/status.js +42 -52
- package/dist/core/status.js.map +1 -1
- package/dist/core/test-quality.d.ts +0 -8
- package/dist/core/test-quality.d.ts.map +1 -1
- package/dist/core/test-quality.js +24 -30
- package/dist/core/test-quality.js.map +1 -1
- package/dist/core/trace.d.ts.map +1 -1
- package/dist/core/trace.js +31 -41
- package/dist/core/trace.js.map +1 -1
- package/dist/core/update.d.ts.map +1 -1
- package/dist/core/update.js +61 -11
- package/dist/core/update.js.map +1 -1
- package/dist/core/validate.d.ts +1 -4
- package/dist/core/validate.d.ts.map +1 -1
- package/dist/core/validate.js +126 -148
- package/dist/core/validate.js.map +1 -1
- package/dist/utils/config.d.ts +15 -5
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +63 -42
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/fs.d.ts +0 -12
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/fs.js +0 -12
- package/dist/utils/fs.js.map +1 -1
- package/dist/utils/paths.d.ts +0 -6
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +0 -6
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/spawn.d.ts +0 -3
- package/dist/utils/spawn.d.ts.map +1 -1
- package/dist/utils/spawn.js +0 -3
- package/dist/utils/spawn.js.map +1 -1
- package/package.json +1 -1
- package/skills/grimoire-apply/SKILL.md +84 -16
- package/skills/grimoire-audit/SKILL.md +21 -1
- package/skills/grimoire-bug/SKILL.md +48 -9
- package/skills/grimoire-commit/SKILL.md +2 -1
- package/skills/grimoire-design/SKILL.md +259 -0
- package/skills/grimoire-design-consult/SKILL.md +200 -0
- package/skills/grimoire-discover/SKILL.md +65 -2
- package/skills/grimoire-draft/SKILL.md +85 -2
- package/skills/grimoire-plan/SKILL.md +61 -18
- package/skills/grimoire-pr/SKILL.md +4 -6
- package/skills/grimoire-pr-review/SKILL.md +45 -114
- package/skills/grimoire-precommit-review/SKILL.md +205 -0
- package/skills/grimoire-refactor/SKILL.md +5 -5
- package/skills/grimoire-review/SKILL.md +74 -147
- package/skills/grimoire-verify/SKILL.md +33 -0
- package/skills/references/adversarial-personas.md +225 -0
- package/skills/references/brand-tokens-format.md +186 -0
- package/skills/references/code-quality.md +140 -0
- package/skills/references/design-heuristics.md +138 -0
- package/skills/references/design-input-formats.md +190 -0
- package/skills/references/pattern-guard.md +180 -0
- package/skills/references/refactor-scan-categories.md +152 -0
- package/skills/references/review-personas.md +405 -0
- package/skills/references/security-compliance.md +22 -1
- package/skills/references/visual-fidelity.md +206 -0
- package/templates/brand-tokens-example.json +13 -0
- package/templates/brand-voice-example.md +22 -0
- package/templates/design-tool-setup-stub.md +59 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Design Heuristics Reference
|
|
2
|
+
|
|
3
|
+
Loaded by `grimoire-design` (variant generation, state enumeration) and review skills running visual-fidelity checks. A compact checklist of the heuristics, laws, and minimum-viable rules an AI agent or reviewer should know before generating or critiquing UI.
|
|
4
|
+
|
|
5
|
+
The goal is **calibration**, not exhaustiveness. Every heuristic below has a trigger condition — if the trigger doesn't apply to the change under review, skip it. Heuristics fired indiscriminately become noise; the materiality gate from `./review-personas.md` §2 applies here too.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Nielsen's 10 Usability Heuristics
|
|
10
|
+
|
|
11
|
+
The classic baseline. Each line: heuristic, one-line definition, trigger.
|
|
12
|
+
|
|
13
|
+
| # | Heuristic | Trigger (when it applies) |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| 1 | **Visibility of system status** — keep users informed of what's happening | Any async action; loading > 1s; multi-step flows |
|
|
16
|
+
| 2 | **Match between system and real world** — speak the user's language | Naming any concept users will see; error messages |
|
|
17
|
+
| 3 | **User control and freedom** — escape hatches, undo, cancel | Any destructive action; multi-step wizards; modal dialogs |
|
|
18
|
+
| 4 | **Consistency and standards** — follow platform and product conventions | New component where a similar one exists; reinventing standard controls |
|
|
19
|
+
| 5 | **Error prevention** — design out errors before they happen | Forms; destructive actions; irreversible operations |
|
|
20
|
+
| 6 | **Recognition rather than recall** — show options, don't make users remember | Multi-step flows; command palettes; settings spread across pages |
|
|
21
|
+
| 7 | **Flexibility and efficiency of use** — accelerators for power users | Frequently-used flows; keyboard shortcuts; bulk operations |
|
|
22
|
+
| 8 | **Aesthetic and minimalist design** — every extra element competes for attention | Crowded UI; multiple CTAs; decorative elements without purpose |
|
|
23
|
+
| 9 | **Help users recognize, diagnose, and recover from errors** — plain language, named cause, suggested fix | Every error path; form validation; API failures |
|
|
24
|
+
| 10 | **Help and documentation** — searchable, task-focused, concrete steps | Onboarding; complex features; first-use moments |
|
|
25
|
+
|
|
26
|
+
Findings cite the heuristic by number: "Violates H#9 — error message names no recovery path."
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 2. WCAG 2.2 AA Quick Reference
|
|
31
|
+
|
|
32
|
+
The minimum bar for any web or mobile UI claiming accessibility. Numbers are AA-level; AAA is stricter and rarely required outside regulated domains.
|
|
33
|
+
|
|
34
|
+
### Contrast
|
|
35
|
+
|
|
36
|
+
- **Body text vs background**: 4.5:1 minimum
|
|
37
|
+
- **Large text** (≥18pt regular or ≥14pt bold) vs background: 3:1 minimum
|
|
38
|
+
- **UI components** (buttons, form borders, focus indicators, icons that convey meaning) vs adjacent colors: 3:1 minimum
|
|
39
|
+
- **Tools**: check contrast with a contrast checker; pseudo-disabled or low-emphasis text still must meet 3:1 if it carries meaning
|
|
40
|
+
|
|
41
|
+
### Target size
|
|
42
|
+
|
|
43
|
+
- **Minimum interactive target**: 24×24 CSS pixels (WCAG 2.2 added this — was 44×44 in iOS HIG, 48dp in Material)
|
|
44
|
+
- **Spacing**: targets smaller than 24×24 must have at least 24px of clear space around them
|
|
45
|
+
- **Exceptions**: inline links in body text; user-agent-controlled (native `<select>`); essential controls where size is dictated by the underlying content
|
|
46
|
+
|
|
47
|
+
### Focus
|
|
48
|
+
|
|
49
|
+
- Focus indicator must be **visible** on every interactive element
|
|
50
|
+
- Focus order must match visual reading order (left-to-right, top-to-bottom for LTR; reverse for RTL)
|
|
51
|
+
- No focus traps except in modal dialogs (where trap must be escapable via Esc)
|
|
52
|
+
|
|
53
|
+
### Forms
|
|
54
|
+
|
|
55
|
+
- Every input has a programmatically-associated `<label>`
|
|
56
|
+
- Required fields are marked beyond color (asterisk, "required" text)
|
|
57
|
+
- Errors are announced to screen readers (live region or focus shift) and named in text near the field
|
|
58
|
+
|
|
59
|
+
### Motion
|
|
60
|
+
|
|
61
|
+
- No content that flashes >3 times per second (seizure risk)
|
|
62
|
+
- Respect `prefers-reduced-motion`; provide a non-animated alternative for essential motion
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 3. Deceptive Patterns (Brignull Taxonomy)
|
|
67
|
+
|
|
68
|
+
Dark patterns to **avoid** in the design, and to **flag** during review. Source: deceptive.design (Harry Brignull's taxonomy). Findings here are usually blockers — the project's stage and audience determine severity, but never normalize them.
|
|
69
|
+
|
|
70
|
+
### Patterns
|
|
71
|
+
|
|
72
|
+
- **Roach motel** — easy to get into, hard to get out (e.g. one-click signup, multi-step cancel flow). Trigger: review any sign-up / subscription / account-deletion flow.
|
|
73
|
+
- **Confirmshaming** — guilt the user out of opting out (e.g. "No thanks, I hate saving money"). Trigger: any opt-out / decline button.
|
|
74
|
+
- **Sneak into basket** — adds items the user did not select (e.g. donation pre-checked, add-on default-enabled at checkout). Trigger: any cart / order-review flow.
|
|
75
|
+
- **Hidden costs** — final price revealed only at last step (fees, shipping, taxes appear at checkout). Trigger: any purchase / pricing flow.
|
|
76
|
+
- **Forced continuity** — free trial silently rolls to paid without notice. Trigger: any trial / subscription onboarding.
|
|
77
|
+
- **Disguised ads** — ads styled to look like content or controls. Trigger: any ad-supported UI.
|
|
78
|
+
- **Friend spam** — uses contact list to send unsolicited invites under the user's name. Trigger: any contact-import / referral flow.
|
|
79
|
+
- **Privacy zuckering** — tricks users into sharing more data than intended. Trigger: any consent flow, permission prompt, default privacy setting.
|
|
80
|
+
- **Misdirection** — uses visual emphasis to distract from a deceptive choice. Trigger: A/B-tested CTA layouts; "recommended" defaults.
|
|
81
|
+
- **Trick questions** — confusingly-worded questions where the obvious answer is the opposite of intent. Trigger: any settings toggle, consent checkbox.
|
|
82
|
+
|
|
83
|
+
### Reviewer rule
|
|
84
|
+
|
|
85
|
+
For each pattern, ask: "If a regulator (FTC, CMA, EU DSA enforcement) saw this flow tomorrow, would the company defend it or change it?" If the answer is "change it," the pattern is a blocker.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 4. Cognitive Laws (apply when relevant)
|
|
90
|
+
|
|
91
|
+
Named laws that compress empirical findings about human-UI interaction. Each one is a single sentence plus when to apply it.
|
|
92
|
+
|
|
93
|
+
- **Fitts's Law** — time to acquire a target is a function of distance and size. *Apply when*: placing primary actions (put them where the cursor / thumb already is, make them large); reviewing dense toolbars.
|
|
94
|
+
- **Hick's Law** — decision time grows with the log of the number of choices. *Apply when*: menus with >7 items; settings pages; onboarding step sequences. Reduce, group, or progressively disclose.
|
|
95
|
+
- **Miller's 7±2** — short-term memory holds roughly 7 items. *Apply when*: navigation breadth (top-level menu items), groups within a form, items shown without scrolling. Chunk when over the limit.
|
|
96
|
+
- **Jakob's Law** — users spend most of their time on other sites. *Apply when*: inventing a new pattern where a standard one exists. Most users expect the search box top-right, the logo top-left, the cart icon top-right, the sign-out under a profile menu. Deviate only with reason.
|
|
97
|
+
- **Doherty Threshold** — productivity soars when system response is under 400ms. *Apply when*: any interactive action — feedback within 100ms, completion under 400ms where possible, skeleton/loader for anything longer.
|
|
98
|
+
- **Tesler's Law** — every system has irreducible complexity; the question is who absorbs it (user, designer, engineer). *Apply when*: simplifying — never delete complexity, only shift it. Don't push to users what the system can decide.
|
|
99
|
+
- **Postel's Law (UI variant)** — be liberal in what you accept, conservative in what you produce. *Apply when*: form inputs (accept "(555) 123-4567" or "5551234567"); display formatting (canonicalize on output).
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 5. Empty / Error / Loading State Rules
|
|
104
|
+
|
|
105
|
+
For every interactive component, the design must address these states. Missing states are the single most common omission in AI-generated UI; treat them as a checklist.
|
|
106
|
+
|
|
107
|
+
### Required states (all interactive components)
|
|
108
|
+
|
|
109
|
+
| State | Minimum-viable handling |
|
|
110
|
+
|---|---|
|
|
111
|
+
| **Default** | The component at rest, ready for input or display. |
|
|
112
|
+
| **Loading** | Visible feedback if action takes >300ms. Skeleton, spinner, or progress bar. Never a blank screen. |
|
|
113
|
+
| **Empty** | Component is visible but holds no data. Show a brief explanation of what would normally appear and how to populate it (the "zero state"). Never silent. |
|
|
114
|
+
| **Error** | Component cannot fulfill its job. Show what went wrong in plain language, with a concrete recovery action (retry, contact, alternative path). Never just "An error occurred." |
|
|
115
|
+
|
|
116
|
+
### Conditional states (apply per component type)
|
|
117
|
+
|
|
118
|
+
| State | Applies when | Handling |
|
|
119
|
+
|---|---|---|
|
|
120
|
+
| **Success** | Action has a meaningful completed state (form submit, file upload) | Brief acknowledgement + next step. No celebration confetti unless the action genuinely warrants it. |
|
|
121
|
+
| **Disabled** | Action is unavailable in the current context | Visually muted; tooltip or label explains *why* it's disabled and what would enable it. Never disable without explanation. |
|
|
122
|
+
| **Read-only** | Component shows data the user can't edit | Visually distinct from editable (no input border, no cursor); copy-to-clipboard if data is referenceable. |
|
|
123
|
+
| **Over-limit** | Input has a max length, count, or quota | Live counter visible at ≥80% capacity; clear feedback when limit is hit and what the user can do (delete, upgrade). |
|
|
124
|
+
| **Partial / degraded** | Component depends on a service that's slow or down | Show what's available + named outage explanation; do not pretend everything is fine. |
|
|
125
|
+
|
|
126
|
+
### Reviewer rule
|
|
127
|
+
|
|
128
|
+
For each interactive component in the design, walk the four required states. If any is missing, that's a finding — severity depends on the criticality of the component. Login forms missing an error state = blocker. Footer-link list missing a loading state = drop (loading isn't a thing for static content).
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Notes for AI Agents Generating UI
|
|
133
|
+
|
|
134
|
+
- Default to **fewer choices** (Hick) and **standard patterns** (Jakob). The marginal cost of inventing a novel layout almost never beats the marginal cost of users not recognizing it.
|
|
135
|
+
- Default to **visible feedback within 100ms** for any interaction. Even a focus-ring change counts.
|
|
136
|
+
- Default to **calm, blameless error messages** with a named recovery path. "Couldn't reach the server. Retry?" beats "An error occurred."
|
|
137
|
+
- When in doubt about contrast, check; do not estimate. AI-generated palettes routinely miss 4.5:1.
|
|
138
|
+
- When in doubt about target size, go to 44×44. The 24×24 minimum is the floor, not the goal.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Design Input Formats Reference
|
|
2
|
+
|
|
3
|
+
Loaded by `grimoire-design` (variant generation) and `grimoire-draft` (Figma snapshot consumption). Defines the input sources grimoire-design can consume, in precedence order, and the fallbacks when none are available.
|
|
4
|
+
|
|
5
|
+
The precedence is **Figma MCP → other MCPs → static HTML → ASCII**. Higher-fidelity inputs win; lower-fidelity outputs are emitted only when nothing better is available. See ADR-0018 for the Figma-primary decision.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Figma MCP (primary)
|
|
10
|
+
|
|
11
|
+
When `project.design_tool.mcp` is configured with the Figma server, grimoire-design queries Figma directly for frame data and component metadata.
|
|
12
|
+
|
|
13
|
+
### Setup
|
|
14
|
+
|
|
15
|
+
Configured at `grimoire init` time. Stored as:
|
|
16
|
+
|
|
17
|
+
```yaml
|
|
18
|
+
project:
|
|
19
|
+
design_tool:
|
|
20
|
+
name: figma
|
|
21
|
+
mcp:
|
|
22
|
+
name: figma-developer
|
|
23
|
+
command: npx
|
|
24
|
+
args: ["-y", "figma-developer-mcp@latest"]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The access token is **never** written to config. The MCP server reads `FIGMA_ACCESS_TOKEN` from the shell environment.
|
|
28
|
+
|
|
29
|
+
### What to query
|
|
30
|
+
|
|
31
|
+
- **Frame data** — given a Figma URL or node ID, fetch frame structure (children, sizes, positions). Use for converting a designed screen into a Gherkin scenario set.
|
|
32
|
+
- **Variables** — Figma Variables → DTCG tokens. If the project's `.grimoire/brand/tokens.json` is missing and Figma Variables exist, offer to seed `tokens.json` from them via Tokens Studio export.
|
|
33
|
+
- **Components** — query the file's components inventory. Cross-reference with `.grimoire/docs/components.md` to detect drift or net-new components.
|
|
34
|
+
|
|
35
|
+
### Cache
|
|
36
|
+
|
|
37
|
+
When grimoire-design or grimoire-draft fetches frame data, cache the response at `.grimoire/changes/<change-id>/designs/figma-snapshot.json`. Reuse cache for subsequent skills on the same change-id; refresh on user request.
|
|
38
|
+
|
|
39
|
+
### Graceful degradation
|
|
40
|
+
|
|
41
|
+
If the MCP is configured but the call fails (network, expired token, missing file permission):
|
|
42
|
+
- Emit one-line "Figma MCP unreachable — `<error>`. Falling back to static HTML."
|
|
43
|
+
- Continue with HTML fallback (§4 below). Do not crash the workflow.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 2. shadcn-ui MCP (optional)
|
|
48
|
+
|
|
49
|
+
When the project uses shadcn-ui (detected via `components.json` or `@radix-ui/*` deps) and the shadcn MCP is installed, grimoire-design can fetch component source by name.
|
|
50
|
+
|
|
51
|
+
### What to query
|
|
52
|
+
|
|
53
|
+
- **Component fetch** — given a component name (e.g. `Button`, `DialogClose`), retrieve the canonical source. Use when generating variants to ensure they reference the actual project component shape, not a generic one.
|
|
54
|
+
- **Variants list** — enumerate variants the project's component library exposes (e.g. `Button` → `default`, `destructive`, `ghost`, `outline`).
|
|
55
|
+
|
|
56
|
+
### Activation
|
|
57
|
+
|
|
58
|
+
Only engaged when `.grimoire/docs/components.md` lists shadcn-ui as the component library. Otherwise skip.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 3. Storybook MCP (optional)
|
|
63
|
+
|
|
64
|
+
When the project has Storybook (`.storybook/` directory, `*.stories.*` files), the Storybook MCP can extract story metadata.
|
|
65
|
+
|
|
66
|
+
### What to query
|
|
67
|
+
|
|
68
|
+
- **Story enumeration** — list all stories with their args, controls, and parameters. Use to derive states per component (default / loading / empty / error).
|
|
69
|
+
- **Story rendering** — for a given story, fetch the rendered HTML snapshot (if Storybook is running locally with the addon installed).
|
|
70
|
+
|
|
71
|
+
### Use case
|
|
72
|
+
|
|
73
|
+
The richest source of per-component state coverage. When available, prefer over manually enumerating states in §9 of the grimoire-design workflow.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 4. design-extract (optional)
|
|
78
|
+
|
|
79
|
+
URL-to-tokens scraper. Given a live site URL, produces DTCG-format `tokens.json`.
|
|
80
|
+
|
|
81
|
+
### When to use
|
|
82
|
+
|
|
83
|
+
- Bootstrapping `tokens.json` from an existing site (e.g. migrating to grimoire mid-project)
|
|
84
|
+
- Sanity-checking that hand-edited tokens match what's actually on a deployed page
|
|
85
|
+
|
|
86
|
+
### Output
|
|
87
|
+
|
|
88
|
+
Writes to stdout or a path; pipe to `.grimoire/brand/tokens.json` (or to a temp file for diffing).
|
|
89
|
+
|
|
90
|
+
### Limitations
|
|
91
|
+
|
|
92
|
+
- Computed styles only — no semantic grouping. Output is flat; group manually.
|
|
93
|
+
- Misses tokens not present on the scanned page (e.g. error states never rendered).
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 5. HTML Fallback
|
|
98
|
+
|
|
99
|
+
When no MCP is available, grimoire-design emits self-contained static HTML files at `.grimoire/changes/<change-id>/designs/variant-{n}.html`.
|
|
100
|
+
|
|
101
|
+
### Structure
|
|
102
|
+
|
|
103
|
+
```html
|
|
104
|
+
<!DOCTYPE html>
|
|
105
|
+
<html>
|
|
106
|
+
<head>
|
|
107
|
+
<meta charset="utf-8" />
|
|
108
|
+
<title>Variant 1 — <change-id></title>
|
|
109
|
+
<style>
|
|
110
|
+
:root {
|
|
111
|
+
/* Brand tokens injected from .grimoire/brand/tokens.json */
|
|
112
|
+
--color-primary: #0066ff;
|
|
113
|
+
--color-text: #111827;
|
|
114
|
+
--spacing-base: 8px;
|
|
115
|
+
--font-family-base: Inter, sans-serif;
|
|
116
|
+
}
|
|
117
|
+
body { font-family: var(--font-family-base); color: var(--color-text); }
|
|
118
|
+
.button-primary { background: var(--color-primary); padding: var(--spacing-base); }
|
|
119
|
+
/* ... */
|
|
120
|
+
</style>
|
|
121
|
+
</head>
|
|
122
|
+
<body>
|
|
123
|
+
<main>
|
|
124
|
+
<!-- Variant markup -->
|
|
125
|
+
</main>
|
|
126
|
+
</body>
|
|
127
|
+
</html>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Rules
|
|
131
|
+
|
|
132
|
+
- **Self-contained** — no external CSS, no CDN scripts, no remote fonts. Designer opens the file directly; offline must work.
|
|
133
|
+
- **CSS variables only** — every color, spacing, font value must reference a `--token` CSS variable defined in `:root`. The `:root` block is the bridge between `tokens.json` and rendered output.
|
|
134
|
+
- **No JS** unless the variant is demonstrating an interaction that can't be shown statically. Prefer multiple HTML files showing each state over one file with JS state toggling.
|
|
135
|
+
- **One file per variant** — `variant-1.html`, `variant-2.html`, `variant-3.html` by default. A `preview.html` file at the same level renders all variants × all states in a grid for side-by-side review.
|
|
136
|
+
|
|
137
|
+
### Token referencing
|
|
138
|
+
|
|
139
|
+
Generate the `:root` block by reading `.grimoire/brand/tokens.json` and emitting one CSS custom property per token. Mapping rule: `color.primary` → `--color-primary`, `font.family.base` → `--font-family-base`. Dot becomes hyphen, kebab-case throughout.
|
|
140
|
+
|
|
141
|
+
If `tokens.json` is absent, emit neutral defaults (white background, system font, 8px spacing) and note in a top-of-file comment: `/* No brand tokens — using neutral defaults. Run grimoire-design --capture-brand. */`
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 6. ASCII Fallback
|
|
146
|
+
|
|
147
|
+
For trivial scope (level 1-2 changes touching a single existing component), ASCII art in a markdown table is the right tier. Faster to author and read than HTML for low-stakes layout changes.
|
|
148
|
+
|
|
149
|
+
### When to use
|
|
150
|
+
|
|
151
|
+
- Single component, single state change
|
|
152
|
+
- Pure layout reordering (no new visual treatment)
|
|
153
|
+
- TUI surface (where HTML preview is irrelevant)
|
|
154
|
+
- Quick sketch for a consult conversation, not a final spec
|
|
155
|
+
|
|
156
|
+
### Convention
|
|
157
|
+
|
|
158
|
+
```markdown
|
|
159
|
+
## Variant 1 — login form, error state
|
|
160
|
+
|
|
161
|
+
| Element | Layout |
|
|
162
|
+
|--- |--- |
|
|
163
|
+
| Header | [Logo] [Help link] |
|
|
164
|
+
| Form | Email: [____________________] |
|
|
165
|
+
| | Password: [____________________] |
|
|
166
|
+
| | [!] Invalid credentials |
|
|
167
|
+
| | [ Sign in ] Forgot password? |
|
|
168
|
+
| Footer | Terms · Privacy · v2.4 |
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Use `[Element]` for interactive controls, `[!]` for error states, plain text for static labels. Markdown tables keep the structure readable in any viewer.
|
|
172
|
+
|
|
173
|
+
### When NOT to use
|
|
174
|
+
|
|
175
|
+
- Web or mobile surface with new visual treatment → use HTML
|
|
176
|
+
- Multi-component or multi-state designs → ASCII collapses; use HTML grid
|
|
177
|
+
- Anything a designer needs to react to visually → ASCII underspecifies
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Selection Rule (precedence)
|
|
182
|
+
|
|
183
|
+
Grimoire-design picks the highest-fidelity output the environment supports:
|
|
184
|
+
|
|
185
|
+
1. Figma MCP configured → render in Figma (no local artifact written)
|
|
186
|
+
2. shadcn / Storybook MCP available + UI codebase detected → HTML using actual component source
|
|
187
|
+
3. Otherwise → static HTML with brand-token CSS variables
|
|
188
|
+
4. Override to ASCII only when scope is trivial OR surface is TUI
|
|
189
|
+
|
|
190
|
+
User can override via conversational invocation: "use HTML" or "give me ASCII". The selection is a default, not a lock.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Pattern Guard Reference
|
|
2
|
+
|
|
3
|
+
Loaded by `grimoire-apply` and `grimoire-bug`. Run **before writing the test** for each task — not after, not as a review pass. The goal is to write code that matches the codebase's established conventions the first time, rather than writing to generic patterns and fixing divergence later.
|
|
4
|
+
|
|
5
|
+
This is not a quality checklist. It is a reconnaissance step: find out how this codebase already solves this class of problem, then write to that pattern.
|
|
6
|
+
|
|
7
|
+
Requires `codebase-memory-mcp` indexed. If the graph is not available, skip this reference entirely and rely on `code-quality.md` alone.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Run Before Each Task
|
|
12
|
+
|
|
13
|
+
### Step 1 — Classify the code being written
|
|
14
|
+
|
|
15
|
+
From the task description and feature file, identify what category of code this task produces:
|
|
16
|
+
|
|
17
|
+
| Code type | Examples |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `api_handler` | Route handler, view, controller, endpoint function |
|
|
20
|
+
| `service` | Use case, interactor, domain service, business logic function |
|
|
21
|
+
| `repository` | Data access, ORM query, store method, DAO |
|
|
22
|
+
| `model` | ORM model, dataclass, schema, type definition |
|
|
23
|
+
| `utility` | Helper, formatter, validator, parser |
|
|
24
|
+
| `test` | Step definition, unit test, fixture, factory |
|
|
25
|
+
| `middleware` | Auth, logging, rate-limiting, request transform |
|
|
26
|
+
| `integration` | External API client, webhook handler, adapter |
|
|
27
|
+
|
|
28
|
+
A task may touch multiple types — classify the primary one.
|
|
29
|
+
|
|
30
|
+
### Step 1b — Reuse discovery
|
|
31
|
+
|
|
32
|
+
Before finding peer patterns, ask: **does what I'm about to write already exist?**
|
|
33
|
+
|
|
34
|
+
These are two different questions. Step 2 finds code to *pattern-match against*. This step finds code to *call instead of writing*.
|
|
35
|
+
|
|
36
|
+
For each function, helper, or class the task requires, run both searches:
|
|
37
|
+
|
|
38
|
+
**Semantic search** — find it by concept, not by name:
|
|
39
|
+
```
|
|
40
|
+
search_graph(semantic_query=["<primary_concept>", "<action_verb>", "<domain_noun>"])
|
|
41
|
+
```
|
|
42
|
+
Example: about to write something that formats a currency amount →
|
|
43
|
+
```
|
|
44
|
+
search_graph(semantic_query=["format", "currency", "amount"])
|
|
45
|
+
```
|
|
46
|
+
This finds `render_price`, `display_amount`, `format_currency` — whatever name the codebase already uses.
|
|
47
|
+
|
|
48
|
+
**Name-pattern search** — find it by likely prefix or suffix:
|
|
49
|
+
```
|
|
50
|
+
search_graph(name_pattern="(format_|_format|currency|amount|price)")
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Decision rules:**
|
|
54
|
+
- Result does the job → **call it**. Do not re-implement.
|
|
55
|
+
- Result almost fits → **use it directly**. Do not generalize it for a second case that doesn't exist yet.
|
|
56
|
+
- Both searches return nothing usable → write new code and proceed to Step 2.
|
|
57
|
+
|
|
58
|
+
**Log the outcome in the pattern brief** (Step 4): note which searches ran and what they found. If calling an existing function instead of writing new code, note it explicitly: `Reused format_currency from billing/utils.py — no new function needed.`
|
|
59
|
+
|
|
60
|
+
Do not skip this step. Writing new code without a reuse search is the primary source of duplication in LLM-generated codebases. The semantic_query mode bridges vocabulary gaps — it finds "publish" when you search "send".
|
|
61
|
+
|
|
62
|
+
### Step 2 — Find peer examples
|
|
63
|
+
|
|
64
|
+
Use `search_graph` to find 3–5 existing functions/classes of the same type. Prefer the most established (oldest, least recently changed) — these are the modal pattern, not the recent drift.
|
|
65
|
+
|
|
66
|
+
**Queries by code type:**
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
api_handler: search_graph(label="Function", name_pattern="(handle|view|endpoint|get_|post_|put_|delete_|patch_)")
|
|
70
|
+
service: search_graph(label="Function", name_pattern="(service|use_case|create_|update_|delete_|process_)")
|
|
71
|
+
repository: search_graph(label="Function", name_pattern="(repo|get_by|find_by|list_|save_|delete_)")
|
|
72
|
+
model: search_graph(label="Class", name_pattern="(Model|Schema|DTO|Type|Entity)")
|
|
73
|
+
utility: search_graph(label="Function", name_pattern="(parse_|format_|validate_|convert_|build_)")
|
|
74
|
+
test: search_graph(label="Module", name_pattern="(test_|_test|spec|_spec|conftest|fixture)")
|
|
75
|
+
middleware: search_graph(label="Function", name_pattern="(middleware|guard|interceptor|filter|auth)")
|
|
76
|
+
integration: search_graph(label="Class", name_pattern="(Client|Adapter|Gateway|Connector|Webhook)")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
If the query returns > 10 results, filter to the same area as the task's target file (check area docs or directory).
|
|
80
|
+
|
|
81
|
+
Exclude files changed in the last 60 days from your sample — those may already be drifted. Use `git log --since="60 days ago" --name-only --format=` to get the recent list.
|
|
82
|
+
|
|
83
|
+
If < 3 peers exist in the graph, skip the pattern brief — there's no established pattern yet. Write to `code-quality.md` rules and the feature spec only.
|
|
84
|
+
|
|
85
|
+
### Step 3 — Extract the modal pattern
|
|
86
|
+
|
|
87
|
+
`get_code_snippet(qualified_name)` for each peer. Read across all samples and identify:
|
|
88
|
+
|
|
89
|
+
**Four critical seams** (these are the ones that cause architectural drift if broken):
|
|
90
|
+
|
|
91
|
+
1. **Error handling** — Does this codebase raise exceptions or return result/error values at this layer? Do handlers catch specific exception types? Is there a central error handler or per-function handling?
|
|
92
|
+
|
|
93
|
+
2. **Dependency access** — Are dependencies injected (constructor, function arg) or imported directly? Is there an established pattern (DI container, FastAPI `Depends`, Django `self.repository`, etc.)?
|
|
94
|
+
|
|
95
|
+
3. **Abstraction depth** — Does this code type contain business logic, or does it delegate? (e.g., handlers should be thin, services should be thick — but check what *this* codebase actually does)
|
|
96
|
+
|
|
97
|
+
4. **Return shape** — Dict? Typed dataclass/schema? Model instance? Tuple `(result, error)`? Pydantic model? Match exactly.
|
|
98
|
+
|
|
99
|
+
**Three secondary seams** (style drift, not architecture):
|
|
100
|
+
|
|
101
|
+
5. **Naming** — snake_case vs camelCase beyond language default, verb-first vs noun-first for functions, consistent abbreviation patterns
|
|
102
|
+
|
|
103
|
+
6. **Test structure** — `pytest` fixtures vs factories vs inline setup? `unittest.mock` vs `pytest-mock`? Arrange/Act/Assert comments or no?
|
|
104
|
+
|
|
105
|
+
7. **Import order / grouping** — stdlib → third-party → local? Relative vs absolute imports?
|
|
106
|
+
|
|
107
|
+
### Step 4 — Write the pattern brief
|
|
108
|
+
|
|
109
|
+
Produce a short, concrete brief of 5–8 rules derived from the samples. Not generic rules — rules for *this task in this codebase*. Example:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
Pattern brief for: POST /invoices handler (api_handler)
|
|
113
|
+
|
|
114
|
+
From 4 peers (billing/views.py, orders/views.py, customers/views.py, auth/views.py):
|
|
115
|
+
|
|
116
|
+
1. Error handling: raise ValidationError / NotFound — do NOT return {"error": ...}.
|
|
117
|
+
Central handler in middleware/errors.py converts exceptions to HTTP responses.
|
|
118
|
+
2. Dependency: inject service via constructor arg — `def __init__(self, invoice_service: InvoiceService)`
|
|
119
|
+
Do NOT call InvoiceService() inline.
|
|
120
|
+
3. Abstraction: handler validates request, calls one service method, serializes response.
|
|
121
|
+
No business logic in the handler.
|
|
122
|
+
4. Return shape: return InvoiceSerializer(result).data with DRF Response — not a raw dict.
|
|
123
|
+
5. Naming: method names are HTTP verb — `def post(self, request)` not `def create_invoice`.
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
This brief is your constraint set for this task. Apply it while writing — not as a review after.
|
|
127
|
+
|
|
128
|
+
### Step 5 — Write to the brief
|
|
129
|
+
|
|
130
|
+
When writing the test and production code for this task:
|
|
131
|
+
|
|
132
|
+
- Apply the brief's rules as hard constraints, not suggestions
|
|
133
|
+
- If the task spec conflicts with the brief (e.g., feature file implies a return shape the codebase doesn't use), flag it to the user before writing — don't silently choose one
|
|
134
|
+
- If you must deviate from the brief (e.g., the brief's pattern won't work for this specific case), note the deviation inline with a comment explaining why, and add it to the handoff note
|
|
135
|
+
|
|
136
|
+
### Step 6 — Verify called functions exist
|
|
137
|
+
|
|
138
|
+
After writing production code, before running tests:
|
|
139
|
+
|
|
140
|
+
Extract every external function/method call your new code makes (exclude stdlib and known third-party packages). For each:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
search_graph(name_pattern="<function_name>")
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
If a called function is not found in the graph:
|
|
147
|
+
- Check the import — is it an alias or renamed import?
|
|
148
|
+
- Check for typos against similar names in the graph
|
|
149
|
+
- If genuinely missing: **stop**. Do not call a function that doesn't exist. Either find the correct function via `search_graph` or flag to the user.
|
|
150
|
+
|
|
151
|
+
This catches hallucinated API calls before they become broken tests.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Pattern Brief Template
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
Pattern brief for: <task title> (<code_type>)
|
|
159
|
+
|
|
160
|
+
From <N> peers (<file1>, <file2>, ...):
|
|
161
|
+
|
|
162
|
+
1. Error handling: <what the peers do>
|
|
163
|
+
2. Dependency: <injection pattern used>
|
|
164
|
+
3. Abstraction: <what this layer does vs delegates>
|
|
165
|
+
4. Return shape: <concrete type/shape>
|
|
166
|
+
5. Naming: <any non-obvious conventions>
|
|
167
|
+
[6. Test structure: <if this is a test task>]
|
|
168
|
+
[7. Deviation noted: <if you must deviate, why>]
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Write the brief into the task's handoff note in `tasks.md` so future sessions have it.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## When to Skip
|
|
176
|
+
|
|
177
|
+
- Graph not indexed → skip entirely, use `code-quality.md` only
|
|
178
|
+
- < 3 peers found → skip the brief, note "no established pattern yet"
|
|
179
|
+
- Task is adding a new code type with no prior examples → skip the brief, note "first of this type"
|
|
180
|
+
- Hotfix / bug task in `grimoire-bug` → run only Step 6 (hallucination check); skip the full brief to avoid over-constraining the fix
|