@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.
Files changed (127) hide show
  1. package/AGENTS.md +56 -4
  2. package/README.md +28 -1
  3. package/dist/cli/index.js +2 -0
  4. package/dist/cli/index.js.map +1 -1
  5. package/dist/commands/check.js +1 -1
  6. package/dist/commands/check.js.map +1 -1
  7. package/dist/commands/configure.d.ts +3 -0
  8. package/dist/commands/configure.d.ts.map +1 -0
  9. package/dist/commands/configure.js +19 -0
  10. package/dist/commands/configure.js.map +1 -0
  11. package/dist/commands/init.d.ts.map +1 -1
  12. package/dist/commands/init.js +2 -0
  13. package/dist/commands/init.js.map +1 -1
  14. package/dist/commands/map.d.ts.map +1 -1
  15. package/dist/commands/map.js +10 -11
  16. package/dist/commands/map.js.map +1 -1
  17. package/dist/core/archive.d.ts.map +1 -1
  18. package/dist/core/archive.js +32 -43
  19. package/dist/core/archive.js.map +1 -1
  20. package/dist/core/check.d.ts.map +1 -1
  21. package/dist/core/check.js +115 -104
  22. package/dist/core/check.js.map +1 -1
  23. package/dist/core/ci.d.ts.map +1 -1
  24. package/dist/core/ci.js +50 -69
  25. package/dist/core/ci.js.map +1 -1
  26. package/dist/core/configure.d.ts +14 -0
  27. package/dist/core/configure.d.ts.map +1 -0
  28. package/dist/core/configure.js +434 -0
  29. package/dist/core/configure.js.map +1 -0
  30. package/dist/core/detect.d.ts.map +1 -1
  31. package/dist/core/detect.js +153 -26
  32. package/dist/core/detect.js.map +1 -1
  33. package/dist/core/diff.d.ts.map +1 -1
  34. package/dist/core/diff.js +62 -93
  35. package/dist/core/diff.js.map +1 -1
  36. package/dist/core/doc-style.d.ts +0 -4
  37. package/dist/core/doc-style.d.ts.map +1 -1
  38. package/dist/core/doc-style.js +28 -23
  39. package/dist/core/doc-style.js.map +1 -1
  40. package/dist/core/docs.js +106 -100
  41. package/dist/core/docs.js.map +1 -1
  42. package/dist/core/health.js +55 -77
  43. package/dist/core/health.js.map +1 -1
  44. package/dist/core/hooks.d.ts +0 -3
  45. package/dist/core/hooks.d.ts.map +1 -1
  46. package/dist/core/hooks.js +0 -11
  47. package/dist/core/hooks.js.map +1 -1
  48. package/dist/core/init.d.ts +2 -0
  49. package/dist/core/init.d.ts.map +1 -1
  50. package/dist/core/init.js +230 -406
  51. package/dist/core/init.js.map +1 -1
  52. package/dist/core/list.d.ts.map +1 -1
  53. package/dist/core/list.js +55 -65
  54. package/dist/core/list.js.map +1 -1
  55. package/dist/core/log.d.ts.map +1 -1
  56. package/dist/core/log.js +23 -33
  57. package/dist/core/log.js.map +1 -1
  58. package/dist/core/map.d.ts +15 -2
  59. package/dist/core/map.d.ts.map +1 -1
  60. package/dist/core/map.js +257 -194
  61. package/dist/core/map.js.map +1 -1
  62. package/dist/core/shared-setup.d.ts +0 -40
  63. package/dist/core/shared-setup.d.ts.map +1 -1
  64. package/dist/core/shared-setup.js +87 -52
  65. package/dist/core/shared-setup.js.map +1 -1
  66. package/dist/core/status.d.ts.map +1 -1
  67. package/dist/core/status.js +42 -52
  68. package/dist/core/status.js.map +1 -1
  69. package/dist/core/test-quality.d.ts +0 -8
  70. package/dist/core/test-quality.d.ts.map +1 -1
  71. package/dist/core/test-quality.js +24 -30
  72. package/dist/core/test-quality.js.map +1 -1
  73. package/dist/core/trace.d.ts.map +1 -1
  74. package/dist/core/trace.js +31 -41
  75. package/dist/core/trace.js.map +1 -1
  76. package/dist/core/update.d.ts.map +1 -1
  77. package/dist/core/update.js +61 -11
  78. package/dist/core/update.js.map +1 -1
  79. package/dist/core/validate.d.ts +1 -4
  80. package/dist/core/validate.d.ts.map +1 -1
  81. package/dist/core/validate.js +126 -148
  82. package/dist/core/validate.js.map +1 -1
  83. package/dist/utils/config.d.ts +15 -5
  84. package/dist/utils/config.d.ts.map +1 -1
  85. package/dist/utils/config.js +63 -42
  86. package/dist/utils/config.js.map +1 -1
  87. package/dist/utils/fs.d.ts +0 -12
  88. package/dist/utils/fs.d.ts.map +1 -1
  89. package/dist/utils/fs.js +0 -12
  90. package/dist/utils/fs.js.map +1 -1
  91. package/dist/utils/paths.d.ts +0 -6
  92. package/dist/utils/paths.d.ts.map +1 -1
  93. package/dist/utils/paths.js +0 -6
  94. package/dist/utils/paths.js.map +1 -1
  95. package/dist/utils/spawn.d.ts +0 -3
  96. package/dist/utils/spawn.d.ts.map +1 -1
  97. package/dist/utils/spawn.js +0 -3
  98. package/dist/utils/spawn.js.map +1 -1
  99. package/package.json +1 -1
  100. package/skills/grimoire-apply/SKILL.md +84 -16
  101. package/skills/grimoire-audit/SKILL.md +21 -1
  102. package/skills/grimoire-bug/SKILL.md +48 -9
  103. package/skills/grimoire-commit/SKILL.md +2 -1
  104. package/skills/grimoire-design/SKILL.md +259 -0
  105. package/skills/grimoire-design-consult/SKILL.md +200 -0
  106. package/skills/grimoire-discover/SKILL.md +65 -2
  107. package/skills/grimoire-draft/SKILL.md +85 -2
  108. package/skills/grimoire-plan/SKILL.md +61 -18
  109. package/skills/grimoire-pr/SKILL.md +4 -6
  110. package/skills/grimoire-pr-review/SKILL.md +45 -114
  111. package/skills/grimoire-precommit-review/SKILL.md +205 -0
  112. package/skills/grimoire-refactor/SKILL.md +5 -5
  113. package/skills/grimoire-review/SKILL.md +74 -147
  114. package/skills/grimoire-verify/SKILL.md +33 -0
  115. package/skills/references/adversarial-personas.md +225 -0
  116. package/skills/references/brand-tokens-format.md +186 -0
  117. package/skills/references/code-quality.md +140 -0
  118. package/skills/references/design-heuristics.md +138 -0
  119. package/skills/references/design-input-formats.md +190 -0
  120. package/skills/references/pattern-guard.md +180 -0
  121. package/skills/references/refactor-scan-categories.md +152 -0
  122. package/skills/references/review-personas.md +405 -0
  123. package/skills/references/security-compliance.md +22 -1
  124. package/skills/references/visual-fidelity.md +206 -0
  125. package/templates/brand-tokens-example.json +13 -0
  126. package/templates/brand-voice-example.md +22 -0
  127. package/templates/design-tool-setup-stub.md +59 -0
@@ -0,0 +1,206 @@
1
+ # Visual Fidelity Reference
2
+
3
+ Shared visual-fidelity check engine used by `grimoire-review` (design-phase HTML previews), `grimoire-pr-review` (PR diff), and `grimoire-precommit-review` (staged diff).
4
+
5
+ The calling skill is responsible for:
6
+ - Resolving the **scope** (HTML preview files in `.grimoire/changes/<id>/designs/` vs changed CSS/markup in a diff)
7
+ - Invoking this engine at the appropriate workflow step (§5.5 in all three review skills)
8
+ - Folding the engine's report under the "Visual Fidelity" section of the final review report
9
+
10
+ This reference defines: when to run, scope per phase, the token-compliance lint algorithm, axe-core invocation, report format, gating rules, and edge-case handling.
11
+
12
+ ---
13
+
14
+ ## 1. When to Run
15
+
16
+ Engage the visual-fidelity engine when **either** is true:
17
+
18
+ - `.grimoire/brand/tokens.json` exists (brand tokens are defined; drift is checkable)
19
+ - The change has design artifacts: any file under `.grimoire/changes/<id>/designs/` (HTML preview, ASCII variants, problem.md, etc.)
20
+
21
+ If neither holds, skip silently — no report section, no noise. This is not an error state; it is a project that has not opted into brand tokens or generated designs.
22
+
23
+ ---
24
+
25
+ ## 2. Scope per Phase
26
+
27
+ The scope changes by which skill invokes the engine.
28
+
29
+ ### Design phase (`grimoire-review`)
30
+
31
+ - **Target**: HTML preview files in `.grimoire/changes/<id>/designs/preview.html` (and any `variant-{n}.html`)
32
+ - **Rationale**: No code exists yet — the design is the artifact under review. Token compliance and a11y are evaluated against the rendered HTML preview.
33
+ - **Skip when**: No `designs/*.html` files exist (e.g., ASCII-only or Figma-only variants — token compliance still runs against the variants markdown if hex values appear; a11y is N/A).
34
+
35
+ ### Code phase (`grimoire-precommit-review`, `grimoire-pr-review`)
36
+
37
+ - **Target**: Staged diff (precommit) or PR diff (pr-review) — specifically the hunks touching CSS files, SCSS, CSS-in-JS strings, inline `style=` attributes, and HTML/JSX with `class` or `style` content.
38
+ - **Rationale**: Brand drift is a code-time concern once implementation begins. Catch it before merge, not at design re-review.
39
+ - **Skip when**: Diff touches no styling surface (e.g., pure backend / config / docs change).
40
+
41
+ ---
42
+
43
+ ## 3. Token-Compliance Lint Algorithm
44
+
45
+ The algorithm is the same as `grimoire-design --lint`. The reference here is the canonical source — the design skill's lint mode and all three review skills run identical logic.
46
+
47
+ ### 3.1 Load tokens
48
+
49
+ 1. Read `.grimoire/brand/tokens.json`.
50
+ 2. Parse as DTCG (see `./brand-tokens-format.md`).
51
+ 3. Build a lookup index: `{ "#0066ff" → "color.primary", "Inter, sans-serif" → "font.family.base", "8px" → "spacing.base", ... }`. Normalize hex to lowercase, six-digit form; normalize px-as-integer where possible.
52
+ 4. On parse failure or any token missing `$value`: emit the malformed-token report (§6 Gating) and exit the engine. Do not proceed to scan.
53
+
54
+ ### 3.2 Scan target files
55
+
56
+ For each file in scope (per §2):
57
+
58
+ - **Hex colors**: regex `#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})\b` — capture every match with file path + line number.
59
+ - **px values**: regex `\b\d+(\.\d+)?px\b` — capture font-size, spacing, border, etc.
60
+ - **font-family strings**: parse CSS `font-family:` declarations and JSX `fontFamily:` props; capture the quoted family list.
61
+
62
+ ### 3.3 Edge-case suppression (false-positive prevention)
63
+
64
+ Skip the following matches — they are token-referencing CSS, not drift:
65
+
66
+ - Inside `var(--...)` — e.g., `color: var(--color-primary)` does not contain a literal hex.
67
+ - Inside an SCSS variable declaration that itself is the token source — e.g., `$color-primary: #0066ff;` in a generated tokens file. Detect: file path matches `**/tokens.{scss,css}` or `**/_tokens.scss`, or the file is the generated output of Style Dictionary.
68
+ - Inside a comment (`//`, `/* */`, `<!-- -->`) — the lint targets active rules, not annotations.
69
+ - Inside a string in a non-style context — e.g., a JS string literal `"see #0066ff for an example"` in a Markdown blockquote within JSX. Heuristic: skip matches whose surrounding context is not a CSS rule, inline `style=`, or known styling prop name (`color`, `background`, `borderColor`, `fill`, `stroke`, `fontFamily`, `fontSize`).
70
+ - Already-token CSS custom properties: `--color-primary: #0066ff;` in a stylesheet that defines the tokens is the source of truth, not drift. Same file-path heuristic as the SCSS variable case.
71
+
72
+ When in doubt, prefer false-negative over false-positive. A noisy lint gets disabled; a quiet one stays on.
73
+
74
+ ### 3.4 Suggestion synthesis
75
+
76
+ For each surviving hardcoded value, find the nearest token in the index:
77
+
78
+ - **Exact match**: `#0066ff` matches `color.primary` exactly → suggest `var(--color-primary)`.
79
+ - **Near match** (color): compute ΔE76 (Euclidean distance in Lab space) or a cheap Euclidean in sRGB; if any token is within 5% → suggest with a "near match" note ("`#0066fe` ~ `var(--color-primary)` (#0066ff)").
80
+ - **Px values**: nearest spacing or font-size token; suggest with the token name.
81
+ - **font-family**: substring match against any font-family token's value.
82
+ - **No match**: emit the finding but suggest "add a new token in `tokens.json` or pick the closest existing token manually" — do not invent a token name.
83
+
84
+ ### 3.5 Output format per finding
85
+
86
+ ```
87
+ - **[suggestion]** `<file>:<line>` hardcoded `<value>` — replace with `var(--<token-path>)` (<note if near match or no match>)
88
+ ```
89
+
90
+ Severity is **suggestion** by default. Promote to **blocker** only when the project's `tokens.json` is referenced by an active ADR as the canonical source (briefing axis — brand-system enforcement) AND the value appears in a primary surface (not a one-off test fixture or sandbox).
91
+
92
+ ### 3.6 Clean state
93
+
94
+ If zero drift findings: emit `No brand drift detected across N files scanned.` Do not emit an empty section header — keep the report clean.
95
+
96
+ ---
97
+
98
+ ## 4. axe-core Invocation
99
+
100
+ axe-core runs accessibility checks against rendered HTML. It is **opt-in** — never auto-installed by this engine.
101
+
102
+ ### 4.1 Availability check
103
+
104
+ Before invoking, check (in order):
105
+
106
+ 1. `npx --no-install axe-core --version` exits 0 → axe-core resolvable in the local `node_modules` or up the tree.
107
+ 2. `axe-core` listed in `package.json` `devDependencies` or `dependencies`.
108
+ 3. `@axe-core/cli` listed in `package.json`.
109
+
110
+ If none: emit a single line under the Visual Fidelity section and skip the a11y portion entirely:
111
+
112
+ ```
113
+ axe-core not installed — install `@axe-core/cli` for accessibility checks.
114
+ ```
115
+
116
+ Do NOT run `npm install`, do NOT prompt the user to install, do NOT fall back to a hosted service. The engine respects the user's tooling choices.
117
+
118
+ ### 4.2 Invocation
119
+
120
+ When axe-core is available and the scope includes HTML files:
121
+
122
+ - Design phase: `npx axe <designs/preview.html>` (and per-variant if multiple)
123
+ - Code phase: skip axe-core unless the diff modified a rendered preview file the project already maintains. Do not spin up a headless browser to render JSX from a diff — that is out of scope for the cheap tier.
124
+
125
+ ### 4.3 Output format per finding
126
+
127
+ Map axe-core's JSON output to the same finding shape:
128
+
129
+ ```
130
+ - **[<severity>]** [axe-<rule-id>] <file> — <description>. Impact: <minor|moderate|serious|critical>.
131
+ ```
132
+
133
+ axe-core severity maps directly: `minor`/`moderate` → suggestion; `serious`/`critical` → suggestion by default, blocker if `project.compliance` lists WCAG / ADA / EAA / Section 508 (regulator anchor — same rule as `./adversarial-personas.md` §Severity Calibration).
134
+
135
+ ### 4.4 Clean state
136
+
137
+ If axe-core ran and found nothing: `axe-core: no violations.`
138
+
139
+ ---
140
+
141
+ ## 5. Report-Section Format
142
+
143
+ The engine returns a single Markdown block the calling skill folds into the report under `## Visual Fidelity`:
144
+
145
+ ```markdown
146
+ ## Visual Fidelity
147
+
148
+ ### Token Compliance
149
+ - **[suggestion]** `src/components/Header.tsx:42` hardcoded `#0066ff` — replace with `var(--color-primary)`.
150
+ - **[suggestion]** `src/components/Header.tsx:58` hardcoded `16px` — replace with `var(--spacing-base-2x)`.
151
+ (or: "No brand drift detected across 12 files scanned.")
152
+
153
+ ### Accessibility (axe-core)
154
+ - **[suggestion]** [axe-color-contrast] `designs/preview.html` — Element has insufficient color contrast of 3.8 (foreground color: #888888, background color: #ffffff). Impact: serious.
155
+ (or: "axe-core: no violations.")
156
+ (or: "axe-core not installed — install `@axe-core/cli` for accessibility checks.")
157
+ ```
158
+
159
+ Omit subsections that have nothing to report (no findings + skip-state). If the entire section has nothing to report (clean tokens + axe-core unavailable + nothing in scope), omit the `## Visual Fidelity` header from the report entirely.
160
+
161
+ ---
162
+
163
+ ## 6. Gating Rules
164
+
165
+ ### 6.1 Absent tokens.json
166
+
167
+ If `.grimoire/brand/tokens.json` does not exist AND the change has design artifacts:
168
+
169
+ - Token-compliance section: skip silently. Do not emit "no tokens — skipped" noise.
170
+ - Accessibility section: still runs (axe-core works without tokens).
171
+ - This is the standard greenfield-design state.
172
+
173
+ If `.grimoire/brand/tokens.json` does not exist AND there are no design artifacts: the engine should not have been invoked at all (per §1). The calling skill is responsible for the gate; the engine assumes the gate already passed.
174
+
175
+ ### 6.2 Malformed tokens.json
176
+
177
+ If `tokens.json` exists but fails to parse, or any token is missing `$value`:
178
+
179
+ ```markdown
180
+ ## Visual Fidelity
181
+
182
+ tokens.json malformed at `.grimoire/brand/tokens.json` — <parse error description>. Fix or remove to enable visual-fidelity checks.
183
+ ```
184
+
185
+ Exit the engine for the code-phase invocations (this is a misconfiguration the user must fix; downstream lint cannot proceed). For the design-phase invocation, continue with the accessibility section only — a malformed tokens file should not block reviewing a freshly generated design.
186
+
187
+ This mirrors `grimoire-design --lint` malformed-token behavior (one-line error + parse description, suggest fix). Single source of truth — same behavior in all four invocation sites (design --lint, review §5.5, precommit-review §5.5, pr-review §5.5).
188
+
189
+ ### 6.3 Empty tokens.json
190
+
191
+ A valid-JSON but token-less file (`{}`) is treated as "no tokens defined" — token-compliance section emits `No brand tokens defined in tokens.json — token compliance skipped.` and proceeds to accessibility.
192
+
193
+ ### 6.4 Surface gating
194
+
195
+ This engine does NOT consult `project.surface`. Surface gating belongs to the adversarial personas (`./adversarial-personas.md` activation matrix). Visual fidelity runs whenever the §1 conditions hold — a TUI project that has somehow generated an HTML preview will still get linted. The user can skip via the standard "skip visual-fidelity" conversational override.
196
+
197
+ ---
198
+
199
+ ## 7. Edge Cases
200
+
201
+ - **Multiple preview files**: lint each independently; merge findings into one section, group by file in the report.
202
+ - **Tokens defined but no styling files in scope**: emit `No styling files in scope for token compliance.` Do not pretend to have scanned.
203
+ - **Generated stylesheet committed in the diff** (e.g., a Tailwind-built CSS file): include in scan only when the file is hand-authored. Auto-detect generated files via standard banner comments (`/* Generated by Tailwind */`, `/* Generated by Style Dictionary */`) and skip; note skipped count in the report.
204
+ - **Color in image asset (SVG)**: out of scope for the cheap tier — do not parse SVGs for fill/stroke hex values. The premium tier (future) may add this; v1 documents the gap and moves on.
205
+ - **CSS custom property defined in a non-tokens file**: e.g., `--local-padding: 4px` in a component-local stylesheet. Lint the value (`4px` here) against tokens; suggest replacing the local declaration with a token reference if a match exists.
206
+ - **Theme variants (light/dark)**: if `tokens.json` defines mode variants per DTCG, the lookup index includes both; a hardcoded value matching either mode is accepted.
@@ -0,0 +1,13 @@
1
+ {
2
+ "color": {
3
+ "primary": { "$value": "#0066ff", "$type": "color" }
4
+ },
5
+ "font": {
6
+ "family": {
7
+ "base": { "$value": "Inter, sans-serif", "$type": "fontFamily" }
8
+ }
9
+ },
10
+ "spacing": {
11
+ "base": { "$value": "8px", "$type": "dimension" }
12
+ }
13
+ }
@@ -0,0 +1,22 @@
1
+ # Brand Voice & Tone
2
+
3
+ One-line summary of your brand voice (e.g., "Confident, direct, and human — never corporate.").
4
+
5
+ ## Do
6
+
7
+ - Speak plainly. Short sentences. Active voice.
8
+ - Lead with the user's goal, not the product's feature.
9
+ - Use specific numbers and concrete examples over vague claims.
10
+
11
+ ## Don't
12
+
13
+ - Don't hedge ("might", "perhaps", "we think") when stating capability.
14
+ - Don't use jargon or acronyms without a one-line gloss on first use.
15
+ - Don't write like a press release — no "world-class", "best-in-class", "synergies".
16
+
17
+ ## Examples
18
+
19
+ | Context | Do | Don't |
20
+ | --- | --- | --- |
21
+ | Empty state | "No invoices yet. Create one to get started." | "Your invoice journey awaits!" |
22
+ | Error | "Couldn't reach the server. Retry in 30 seconds." | "Oops! Something went wrong." |
@@ -0,0 +1,59 @@
1
+ # Design Tool MCP Setup ({{tool}})
2
+
3
+ `{{tool}}` does not currently have a first-class MCP server in the grimoire registry.
4
+ Use this checklist to wire one up manually so AI agents can read your designs.
5
+
6
+ ## 1. Install an MCP server for your tool
7
+
8
+ Search for an MCP server compatible with `{{tool}}` (e.g., `mcp-{{tool}}` on
9
+ npm, GitHub, or the MCP server registry at https://github.com/modelcontextprotocol).
10
+
11
+ If none exists, fall back to the HTML/ASCII path: `grimoire-design` will render
12
+ previews from a textual description and lint them against `.grimoire/brand/tokens.json`.
13
+
14
+ ## 2. Set environment variables
15
+
16
+ Most design-tool MCPs require an API token. Export it in your shell, never in
17
+ `.grimoire/config.yaml`:
18
+
19
+ ```bash
20
+ export {{tool}}_ACCESS_TOKEN=...
21
+ ```
22
+
23
+ ## 3. Register the server in your agent config
24
+
25
+ For Claude Code, add to `.mcp.json` at the repo root:
26
+
27
+ ```json
28
+ {
29
+ "mcpServers": {
30
+ "{{tool}}": {
31
+ "command": "npx",
32
+ "args": ["-y", "<mcp-package-name>"]
33
+ }
34
+ }
35
+ }
36
+ ```
37
+
38
+ For other agents, see their MCP documentation.
39
+
40
+ ## 4. Restart your agent and verify
41
+
42
+ Restart the agent. In `grimoire-design`, run a small request like "fetch the
43
+ homepage frame" to confirm the MCP responds.
44
+
45
+ ## 5. Update `.grimoire/config.yaml`
46
+
47
+ Once the MCP is working, add it under `project.design_tool.mcp`:
48
+
49
+ ```yaml
50
+ project:
51
+ design_tool:
52
+ name: {{tool}}
53
+ mcp:
54
+ name: {{tool}}-mcp
55
+ command: npx
56
+ args: ["-y", "<mcp-package-name>"]
57
+ ```
58
+
59
+ Re-run `grimoire init` is not necessary — just save the file.