@kiwidata/grimoire 0.1.1

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 (215) hide show
  1. package/.claude-plugin/plugin.json +8 -0
  2. package/AGENTS.md +217 -0
  3. package/README.md +748 -0
  4. package/bin/grimoire.js +2 -0
  5. package/dist/cli/index.d.ts +2 -0
  6. package/dist/cli/index.d.ts.map +1 -0
  7. package/dist/cli/index.js +42 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/commands/archive.d.ts +3 -0
  10. package/dist/commands/archive.d.ts.map +1 -0
  11. package/dist/commands/archive.js +22 -0
  12. package/dist/commands/archive.js.map +1 -0
  13. package/dist/commands/branch-check.d.ts +3 -0
  14. package/dist/commands/branch-check.d.ts.map +1 -0
  15. package/dist/commands/branch-check.js +16 -0
  16. package/dist/commands/branch-check.js.map +1 -0
  17. package/dist/commands/check.d.ts +3 -0
  18. package/dist/commands/check.d.ts.map +1 -0
  19. package/dist/commands/check.js +22 -0
  20. package/dist/commands/check.js.map +1 -0
  21. package/dist/commands/ci.d.ts +3 -0
  22. package/dist/commands/ci.d.ts.map +1 -0
  23. package/dist/commands/ci.js +18 -0
  24. package/dist/commands/ci.js.map +1 -0
  25. package/dist/commands/diff.d.ts +3 -0
  26. package/dist/commands/diff.d.ts.map +1 -0
  27. package/dist/commands/diff.js +10 -0
  28. package/dist/commands/diff.js.map +1 -0
  29. package/dist/commands/docs.d.ts +3 -0
  30. package/dist/commands/docs.d.ts.map +1 -0
  31. package/dist/commands/docs.js +11 -0
  32. package/dist/commands/docs.js.map +1 -0
  33. package/dist/commands/health.d.ts +3 -0
  34. package/dist/commands/health.d.ts.map +1 -0
  35. package/dist/commands/health.js +13 -0
  36. package/dist/commands/health.js.map +1 -0
  37. package/dist/commands/init.d.ts +3 -0
  38. package/dist/commands/init.d.ts.map +1 -0
  39. package/dist/commands/init.js +21 -0
  40. package/dist/commands/init.js.map +1 -0
  41. package/dist/commands/list.d.ts +3 -0
  42. package/dist/commands/list.d.ts.map +1 -0
  43. package/dist/commands/list.js +22 -0
  44. package/dist/commands/list.js.map +1 -0
  45. package/dist/commands/log.d.ts +3 -0
  46. package/dist/commands/log.d.ts.map +1 -0
  47. package/dist/commands/log.js +15 -0
  48. package/dist/commands/log.js.map +1 -0
  49. package/dist/commands/map.d.ts +3 -0
  50. package/dist/commands/map.d.ts.map +1 -0
  51. package/dist/commands/map.js +17 -0
  52. package/dist/commands/map.js.map +1 -0
  53. package/dist/commands/pr.d.ts +3 -0
  54. package/dist/commands/pr.d.ts.map +1 -0
  55. package/dist/commands/pr.js +17 -0
  56. package/dist/commands/pr.js.map +1 -0
  57. package/dist/commands/status.d.ts +3 -0
  58. package/dist/commands/status.d.ts.map +1 -0
  59. package/dist/commands/status.js +12 -0
  60. package/dist/commands/status.js.map +1 -0
  61. package/dist/commands/test-quality.d.ts +3 -0
  62. package/dist/commands/test-quality.d.ts.map +1 -0
  63. package/dist/commands/test-quality.js +37 -0
  64. package/dist/commands/test-quality.js.map +1 -0
  65. package/dist/commands/trace.d.ts +3 -0
  66. package/dist/commands/trace.d.ts.map +1 -0
  67. package/dist/commands/trace.js +12 -0
  68. package/dist/commands/trace.js.map +1 -0
  69. package/dist/commands/update.d.ts +3 -0
  70. package/dist/commands/update.d.ts.map +1 -0
  71. package/dist/commands/update.js +22 -0
  72. package/dist/commands/update.js.map +1 -0
  73. package/dist/commands/validate.d.ts +3 -0
  74. package/dist/commands/validate.d.ts.map +1 -0
  75. package/dist/commands/validate.js +17 -0
  76. package/dist/commands/validate.js.map +1 -0
  77. package/dist/core/archive.d.ts +9 -0
  78. package/dist/core/archive.d.ts.map +1 -0
  79. package/dist/core/archive.js +92 -0
  80. package/dist/core/archive.js.map +1 -0
  81. package/dist/core/branch-check.d.ts +27 -0
  82. package/dist/core/branch-check.d.ts.map +1 -0
  83. package/dist/core/branch-check.js +205 -0
  84. package/dist/core/branch-check.js.map +1 -0
  85. package/dist/core/check.d.ts +24 -0
  86. package/dist/core/check.d.ts.map +1 -0
  87. package/dist/core/check.js +372 -0
  88. package/dist/core/check.js.map +1 -0
  89. package/dist/core/ci.d.ts +24 -0
  90. package/dist/core/ci.d.ts.map +1 -0
  91. package/dist/core/ci.js +162 -0
  92. package/dist/core/ci.js.map +1 -0
  93. package/dist/core/detect.d.ts +10 -0
  94. package/dist/core/detect.d.ts.map +1 -0
  95. package/dist/core/detect.js +368 -0
  96. package/dist/core/detect.js.map +1 -0
  97. package/dist/core/diff.d.ts +29 -0
  98. package/dist/core/diff.d.ts.map +1 -0
  99. package/dist/core/diff.js +197 -0
  100. package/dist/core/diff.js.map +1 -0
  101. package/dist/core/doc-style.d.ts +16 -0
  102. package/dist/core/doc-style.d.ts.map +1 -0
  103. package/dist/core/doc-style.js +192 -0
  104. package/dist/core/doc-style.js.map +1 -0
  105. package/dist/core/docs.d.ts +6 -0
  106. package/dist/core/docs.d.ts.map +1 -0
  107. package/dist/core/docs.js +478 -0
  108. package/dist/core/docs.js.map +1 -0
  109. package/dist/core/health.d.ts +7 -0
  110. package/dist/core/health.d.ts.map +1 -0
  111. package/dist/core/health.js +489 -0
  112. package/dist/core/health.js.map +1 -0
  113. package/dist/core/hooks.d.ts +5 -0
  114. package/dist/core/hooks.d.ts.map +1 -0
  115. package/dist/core/hooks.js +168 -0
  116. package/dist/core/hooks.js.map +1 -0
  117. package/dist/core/init.d.ts +9 -0
  118. package/dist/core/init.d.ts.map +1 -0
  119. package/dist/core/init.js +563 -0
  120. package/dist/core/init.js.map +1 -0
  121. package/dist/core/list.d.ts +4 -0
  122. package/dist/core/list.d.ts.map +1 -0
  123. package/dist/core/list.js +170 -0
  124. package/dist/core/list.js.map +1 -0
  125. package/dist/core/log.d.ts +8 -0
  126. package/dist/core/log.d.ts.map +1 -0
  127. package/dist/core/log.js +150 -0
  128. package/dist/core/log.js.map +1 -0
  129. package/dist/core/map.d.ts +9 -0
  130. package/dist/core/map.d.ts.map +1 -0
  131. package/dist/core/map.js +302 -0
  132. package/dist/core/map.js.map +1 -0
  133. package/dist/core/pr.d.ts +9 -0
  134. package/dist/core/pr.d.ts.map +1 -0
  135. package/dist/core/pr.js +273 -0
  136. package/dist/core/pr.js.map +1 -0
  137. package/dist/core/shared-setup.d.ts +52 -0
  138. package/dist/core/shared-setup.d.ts.map +1 -0
  139. package/dist/core/shared-setup.js +221 -0
  140. package/dist/core/shared-setup.js.map +1 -0
  141. package/dist/core/status.d.ts +6 -0
  142. package/dist/core/status.d.ts.map +1 -0
  143. package/dist/core/status.js +114 -0
  144. package/dist/core/status.js.map +1 -0
  145. package/dist/core/test-quality.d.ts +33 -0
  146. package/dist/core/test-quality.d.ts.map +1 -0
  147. package/dist/core/test-quality.js +378 -0
  148. package/dist/core/test-quality.js.map +1 -0
  149. package/dist/core/trace.d.ts +6 -0
  150. package/dist/core/trace.d.ts.map +1 -0
  151. package/dist/core/trace.js +211 -0
  152. package/dist/core/trace.js.map +1 -0
  153. package/dist/core/update.d.ts +10 -0
  154. package/dist/core/update.d.ts.map +1 -0
  155. package/dist/core/update.js +149 -0
  156. package/dist/core/update.js.map +1 -0
  157. package/dist/core/validate.d.ts +20 -0
  158. package/dist/core/validate.d.ts.map +1 -0
  159. package/dist/core/validate.js +275 -0
  160. package/dist/core/validate.js.map +1 -0
  161. package/dist/index.d.ts +19 -0
  162. package/dist/index.d.ts.map +1 -0
  163. package/dist/index.js +20 -0
  164. package/dist/index.js.map +1 -0
  165. package/dist/utils/config.d.ts +61 -0
  166. package/dist/utils/config.d.ts.map +1 -0
  167. package/dist/utils/config.js +172 -0
  168. package/dist/utils/config.js.map +1 -0
  169. package/dist/utils/fs.d.ts +17 -0
  170. package/dist/utils/fs.d.ts.map +1 -0
  171. package/dist/utils/fs.js +38 -0
  172. package/dist/utils/fs.js.map +1 -0
  173. package/dist/utils/paths.d.ts +10 -0
  174. package/dist/utils/paths.d.ts.map +1 -0
  175. package/dist/utils/paths.js +35 -0
  176. package/dist/utils/paths.js.map +1 -0
  177. package/dist/utils/spawn.d.ts +5 -0
  178. package/dist/utils/spawn.d.ts.map +1 -0
  179. package/dist/utils/spawn.js +34 -0
  180. package/dist/utils/spawn.js.map +1 -0
  181. package/package.json +68 -0
  182. package/skills/grimoire-apply/SKILL.md +274 -0
  183. package/skills/grimoire-audit/SKILL.md +129 -0
  184. package/skills/grimoire-branch-guard/SKILL.md +111 -0
  185. package/skills/grimoire-bug/SKILL.md +160 -0
  186. package/skills/grimoire-bug-explore/SKILL.md +242 -0
  187. package/skills/grimoire-bug-report/SKILL.md +237 -0
  188. package/skills/grimoire-bug-session/SKILL.md +222 -0
  189. package/skills/grimoire-bug-triage/SKILL.md +274 -0
  190. package/skills/grimoire-commit/SKILL.md +150 -0
  191. package/skills/grimoire-discover/SKILL.md +297 -0
  192. package/skills/grimoire-draft/SKILL.md +202 -0
  193. package/skills/grimoire-plan/SKILL.md +329 -0
  194. package/skills/grimoire-pr/SKILL.md +134 -0
  195. package/skills/grimoire-pr-review/SKILL.md +240 -0
  196. package/skills/grimoire-refactor/SKILL.md +251 -0
  197. package/skills/grimoire-remove/SKILL.md +112 -0
  198. package/skills/grimoire-review/SKILL.md +247 -0
  199. package/skills/grimoire-verify/SKILL.md +223 -0
  200. package/skills/references/bug-classification.md +154 -0
  201. package/skills/references/build-vs-buy.md +77 -0
  202. package/skills/references/elicitation-personas.md +118 -0
  203. package/skills/references/refactor-register-format.md +88 -0
  204. package/skills/references/refactor-scan-categories.md +102 -0
  205. package/skills/references/schema-format.md +68 -0
  206. package/skills/references/security-compliance.md +110 -0
  207. package/skills/references/testing-contracts.md +93 -0
  208. package/templates/context.yml +110 -0
  209. package/templates/debt-exceptions.yml +61 -0
  210. package/templates/decision.md +50 -0
  211. package/templates/dupignore +93 -0
  212. package/templates/example.feature +24 -0
  213. package/templates/manifest.md +29 -0
  214. package/templates/mapignore +58 -0
  215. package/templates/mapkeys +65 -0
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Walk up from cwd to find a directory containing .grimoire/ or features/
3
+ */
4
+ export declare function findProjectRoot(): Promise<string>;
5
+ export declare function resolveChangePath(root: string, changeId: string): string;
6
+ /**
7
+ * Resolve a path and verify it stays within the project root.
8
+ */
9
+ export declare function safePath(root: string, filePath: string): string;
10
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC,CAgBvD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKxE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAM/D"}
@@ -0,0 +1,35 @@
1
+ import { join, resolve } from "node:path";
2
+ import { fileExists } from "./fs.js";
3
+ /**
4
+ * Walk up from cwd to find a directory containing .grimoire/ or features/
5
+ */
6
+ export async function findProjectRoot() {
7
+ let dir = process.cwd();
8
+ const root = resolve("/");
9
+ while (dir !== root) {
10
+ if ((await fileExists(join(dir, ".grimoire"))) ||
11
+ (await fileExists(join(dir, "features")))) {
12
+ return dir;
13
+ }
14
+ dir = resolve(dir, "..");
15
+ }
16
+ // Fall back to cwd
17
+ return process.cwd();
18
+ }
19
+ export function resolveChangePath(root, changeId) {
20
+ if (/[/\\]/.test(changeId) || changeId === ".." || changeId.includes("..")) {
21
+ throw new Error(`Invalid change ID: ${changeId}`);
22
+ }
23
+ return join(root, ".grimoire", "changes", changeId);
24
+ }
25
+ /**
26
+ * Resolve a path and verify it stays within the project root.
27
+ */
28
+ export function safePath(root, filePath) {
29
+ const resolved = resolve(root, filePath);
30
+ if (!resolved.startsWith(root + "/") && resolved !== root) {
31
+ throw new Error(`Path escapes project root: ${filePath}`);
32
+ }
33
+ return resolved;
34
+ }
35
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACxB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAE1B,OAAO,GAAG,KAAK,IAAI,EAAE,CAAC;QACpB,IACE,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC;YAC1C,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,EACzC,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;QACD,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,mBAAmB;IACnB,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,QAAgB;IAC9D,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,QAAgB;IACrD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Spawn a command with stdin piped, avoiding sh -c shell interpretation.
3
+ */
4
+ export declare function spawnWithStdin(command: string, args: string[], input: string, cwd: string): Promise<string>;
5
+ //# sourceMappingURL=spawn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../src/utils/spawn.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,CA+BjB"}
@@ -0,0 +1,34 @@
1
+ import { spawn } from "node:child_process";
2
+ /**
3
+ * Spawn a command with stdin piped, avoiding sh -c shell interpretation.
4
+ */
5
+ export function spawnWithStdin(command, args, input, cwd) {
6
+ return new Promise((resolve, reject) => {
7
+ const parts = command.split(/\s+/);
8
+ const proc = spawn(parts[0], [...parts.slice(1), ...args], {
9
+ cwd,
10
+ stdio: ["pipe", "pipe", "pipe"],
11
+ timeout: 120_000,
12
+ });
13
+ let stdout = "";
14
+ let stderr = "";
15
+ proc.stdout.on("data", (data) => {
16
+ stdout += data.toString();
17
+ });
18
+ proc.stderr.on("data", (data) => {
19
+ stderr += data.toString();
20
+ });
21
+ proc.on("error", reject);
22
+ proc.on("close", (code) => {
23
+ if (code === 0 || stdout.trim()) {
24
+ resolve(stdout.trim());
25
+ }
26
+ else {
27
+ reject(new Error(stderr.trim() || `Command exited with code ${code}`));
28
+ }
29
+ });
30
+ proc.stdin.write(input);
31
+ proc.stdin.end();
32
+ });
33
+ }
34
+ //# sourceMappingURL=spawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.js","sourceRoot":"","sources":["../../src/utils/spawn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAe,EACf,IAAc,EACd,KAAa,EACb,GAAW;IAEX,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE;YACzD,GAAG;YACH,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,OAAO,EAAE,OAAO;SACjB,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YACtC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YACtC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACzB,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,IAAI,IAAI,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;gBAChC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,4BAA4B,IAAI,EAAE,CAAC,CAAC,CAAC;YACzE,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;AACL,CAAC"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@kiwidata/grimoire",
3
+ "version": "0.1.1",
4
+ "description": "Gherkin + MADR spec-driven development for AI coding assistants",
5
+ "type": "module",
6
+ "bin": {
7
+ "grimoire": "./bin/grimoire.js"
8
+ },
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "dev": "tsc --watch",
18
+ "test": "vitest",
19
+ "lint": "eslint src/",
20
+ "clean": "rm -rf dist/",
21
+ "prepublishOnly": "npm run clean && npm run build"
22
+ },
23
+ "files": [
24
+ ".claude-plugin/",
25
+ "dist/",
26
+ "bin/",
27
+ "templates/",
28
+ "skills/",
29
+ "AGENTS.md",
30
+ "README.md"
31
+ ],
32
+ "keywords": [
33
+ "gherkin",
34
+ "bdd",
35
+ "madr",
36
+ "adr",
37
+ "spec-driven",
38
+ "ai",
39
+ "claude",
40
+ "codex",
41
+ "cursor"
42
+ ],
43
+ "author": "Kiwi Data",
44
+ "license": "MIT",
45
+ "engines": {
46
+ "node": ">=20.0.0"
47
+ },
48
+ "dependencies": {
49
+ "@cucumber/gherkin": "^39.0.0",
50
+ "@cucumber/messages": "^32.2.0",
51
+ "chalk": "^5.5.0",
52
+ "commander": "^14.0.0",
53
+ "fast-glob": "^3.3.0",
54
+ "gray-matter": "^4.0.3",
55
+ "simple-git": "^3.33.0",
56
+ "yaml": "^2.8.0"
57
+ },
58
+ "devDependencies": {
59
+ "@types/node": "^22.0.0",
60
+ "@typescript-eslint/eslint-plugin": "^8.58.1",
61
+ "@typescript-eslint/parser": "^8.58.1",
62
+ "@vitest/coverage-v8": "^3.2.4",
63
+ "eslint": "^9.0.0",
64
+ "jscpd": "^4.0.9",
65
+ "typescript": "^5.7.0",
66
+ "vitest": "^3.0.0"
67
+ }
68
+ }
@@ -0,0 +1,274 @@
1
+ ---
2
+ name: grimoire-apply
3
+ description: Implement tasks from a planned grimoire change with strict red-green BDD. Use when tasks.md exists and is ready for implementation.
4
+ compatibility: Designed for Claude Code (or similar products)
5
+ metadata:
6
+ author: kiwi-data
7
+ version: "0.1"
8
+ ---
9
+
10
+ # grimoire-apply
11
+
12
+ Implement tasks from a planned grimoire change. Write production code AND tests. A task is not complete until its scenarios pass.
13
+
14
+ ## CRITICAL: Two Rules That Must Not Be Broken
15
+
16
+ ### 1. Do Not Re-Plan
17
+
18
+ **`tasks.md` IS the plan. Do not enter plan mode. Do not create your own plan. Do not reorganize, re-derive, or "think through" the tasks before starting.**
19
+
20
+ ### 2. Do Not Implement All Tasks In One Context
21
+
22
+ **Spawn a fresh subagent (or start a fresh session) for each task section.** The parent/orchestrator reads `tasks.md` and delegates — it does NOT write code itself. Context degrades after 3-4 tasks and the LLM starts making mistakes based on stale file contents. See "Session Management" below for the exact workflow.
23
+
24
+ The plan was already created in the plan stage, reviewed by the user, and approved. Your job is to EXECUTE it, not to re-evaluate it. Read `tasks.md`, find the first unchecked task, and start working.
25
+
26
+ If you believe a task is wrong, incomplete, or impossible — flag it to the user. Do not silently re-plan. Do not skip tasks. Do not reorder tasks unless the user asks.
27
+
28
+ This applies to all LLMs: Claude, Codex, Cursor, Copilot, etc. The task list is the authority.
29
+
30
+ ## Triggers
31
+ - User wants to implement a planned grimoire change
32
+ - User asks to apply, implement, or build a grimoire change
33
+ - Loose match: "apply", "implement", "build" with a change reference
34
+
35
+ ## Routing
36
+ - No tasks.md exists → `grimoire-plan` first
37
+ - Task seems wrong or impossible → flag to user; do NOT silently re-plan or skip
38
+ - Implementation reveals the spec is wrong → STOP. Go back to `grimoire-draft`.
39
+ - Fix is needed (not a planned change) → `grimoire-bug`
40
+
41
+ ## Prerequisites
42
+ - A change exists in `.grimoire/changes/<change-id>/` with:
43
+ - `manifest.md`
44
+ - `tasks.md` (from plan stage)
45
+ - At least one `.feature` file or decision record
46
+
47
+ ## Workflow
48
+
49
+ ### 1. Select Change
50
+ - List active changes in `.grimoire/changes/` that have `tasks.md`
51
+ - If multiple, ask user which one to apply
52
+ - If only one, confirm it
53
+ - Read `tasks.md` and find the first unchecked `- [ ]` task — that's where you start
54
+ - Skip any tasks already marked `- [x]` (resume from where a previous session left off)
55
+
56
+ ### 2. Choose Execution Mode
57
+ Ask the user how they want to work through the task list:
58
+
59
+ **Review mode (default):** Before each task, present what you plan to implement and which files you'll touch. Then for each file change:
60
+ 1. Show the proposed change (what you plan to write/edit and why)
61
+ 2. Wait for user approval before writing to that file
62
+ 3. If the user requests modifications, revise and re-present before writing
63
+
64
+ After all file changes for a task are approved and written, run the tests and show results. Wait for user approval before moving to the next task. The user can request changes, ask questions, reorder, or skip tasks at any point.
65
+
66
+ **Autonomous mode:** Work through the entire task list without pausing between tasks. Only stop if:
67
+ - A test won't go green after reasonable attempts (you're stuck)
68
+ - Implementation reveals the spec is wrong (needs to go back to draft)
69
+ - You hit an external blocker (missing dependency, permissions, etc.)
70
+
71
+ If the user doesn't specify, default to review mode.
72
+
73
+ **Both modes:** Update `tasks.md` in real time as work progresses. Mark tasks `- [x]` the moment they pass. If a task is split, reordered, or new tasks are discovered during implementation, update `tasks.md` immediately so it always reflects the current state. The task list is the source of truth for progress — if the session is interrupted, the next agent should be able to read `tasks.md` and know exactly where to resume.
74
+
75
+ ### Stuck Detection & Recovery
76
+
77
+ **You MUST track failed attempts per task.** If a test won't go green, count your attempts:
78
+
79
+ - **Attempt 1:** Try the straightforward implementation from the task description.
80
+ - **Attempt 2:** If attempt 1 failed, re-read the error carefully. Try a *different* approach — not the same code with minor tweaks. State what you're doing differently and why.
81
+ - **Attempt 3 (final):** If attempt 2 failed, try one more *fundamentally different* approach. If the same error recurs, the problem is likely not in your implementation.
82
+
83
+ **After 3 failed attempts on a single task, STOP.** Do not continue. Instead:
84
+ 1. Add a comment to `tasks.md` under the task: `<!-- BLOCKED: <summary of what was tried and what failed> -->`
85
+ 2. Present to the user:
86
+ - What the task requires
87
+ - What you tried (all 3 approaches, briefly)
88
+ - What error/failure persisted
89
+ - Your best guess at the root cause
90
+ 3. Wait for the user to decide: fix the task, provide guidance, skip it, or go back to plan.
91
+
92
+ **What counts as a "different approach":**
93
+ - Using a different library/API to achieve the same result
94
+ - Restructuring the code (different function signature, different data flow)
95
+ - Changing the test setup (different fixtures, different mocking strategy)
96
+
97
+ **What does NOT count:**
98
+ - Changing a variable name or adding a print statement
99
+ - Adding a try/catch around the same failing code
100
+ - Re-running the same code hoping for a different result
101
+
102
+ **In autonomous mode:** This rule is especially critical. Without it, the agent will loop until the token budget is exhausted. After 3 failed attempts, switch to review mode for that task and ask the user.
103
+
104
+ **Never silently retry the same approach.** If your implementation produced error X and you're about to write code that will produce error X again, stop and think about why. If you can't identify what would change the outcome, stop and ask.
105
+
106
+ ### Session Management — MANDATORY Fresh Context Per Section
107
+
108
+ **Do NOT implement all tasks in a single conversation context.** Context accumulates across tasks and degrades output quality — the LLM starts hallucinating based on stale file contents it read 5 tasks ago. This is not a suggestion. Fresh context per task section is required.
109
+
110
+ Each task section in `tasks.md` has a `<!-- context: ... -->` block listing the exact files needed. This is the loading list for that section's fresh context.
111
+
112
+ #### Claude Code: Subagent Per Section
113
+
114
+ The parent agent is the **orchestrator only** — it does NOT implement tasks itself. The workflow is:
115
+
116
+ 1. Parent reads `tasks.md`, finds the first unchecked section
117
+ 2. Parent spawns a **subagent** (Agent tool) with this prompt:
118
+ ```
119
+ You are implementing grimoire tasks. Read `.grimoire/changes/<change-id>/tasks.md`,
120
+ find section <N>, and implement all unchecked tasks in that section.
121
+ Follow the red-green BDD cycle for each task. Mark tasks [x] when done.
122
+ When the section is complete, write a <!-- SESSION: ... --> handoff note
123
+ under the last task and exit.
124
+ ```
125
+ 3. Subagent reads `tasks.md` and the context files for that section
126
+ 4. Subagent implements, marks tasks `[x]`, writes handoff note, exits
127
+ 5. Parent reads updated `tasks.md`, spawns next subagent for next section
128
+ 6. Repeat until all sections complete
129
+
130
+ **The parent agent MUST NOT write production code or test code.** Its only jobs are: read `tasks.md`, spawn subagents, and check completion between sections. If the parent starts implementing tasks directly, context will degrade by section 3-4 and output quality will drop.
131
+
132
+ #### Other Agents (Codex, Cursor, Windsurf, etc.)
133
+
134
+ Start a **fresh session** for each task section. The resume mechanism via `tasks.md` checkboxes makes this seamless:
135
+
136
+ 1. Open a new session
137
+ 2. Tell the agent: "Run `/grimoire:apply` on change `<change-id>`"
138
+ 3. The agent reads `tasks.md`, finds the first `- [ ]`, reads that section's context block
139
+ 4. When the section is complete, end the session
140
+ 5. Start a new session for the next section
141
+
142
+ This is the same pattern as the [Ralph Wiggum loop](https://ralph-wiggum.ai) — progress lives in files (`tasks.md` + git), not in the context window. Each session gets a clean slate and reads current file state.
143
+
144
+ #### Handoff Notes
145
+
146
+ Before exiting (subagent exit or session end), write a handoff note in `tasks.md`:
147
+
148
+ ```markdown
149
+ - [x] 1.3 Implement TOTP verification
150
+ <!-- SESSION: completed 1.1-1.3. auth middleware moved to middleware/auth.ts. pyotp added to requirements. Next section needs the new middleware import. -->
151
+ ```
152
+
153
+ This gives the next session critical context (architectural decisions made, files created/moved, gotchas discovered) without requiring it to re-read everything.
154
+
155
+ #### When to Force a Fresh Context Mid-Section
156
+
157
+ Even within a section, break early if:
158
+ - You needed 3 attempts on a task (stuck detection recovery)
159
+ - You notice degraded output (repeating yourself, forgetting earlier context, making mistakes on things you got right earlier)
160
+ - The section has more than 5 tasks
161
+
162
+ Write a handoff note at the break point and start fresh.
163
+
164
+ **Check `.grimoire/config.yaml`** for the configured coding agent — use `llm.coding.command` and `llm.coding.model` for implementation work.
165
+
166
+ ### 3. Create Feature Branch
167
+ Before writing any code, ensure you're on a feature branch for this change:
168
+
169
+ ```
170
+ git checkout -b <type>/<change-id>
171
+ ```
172
+
173
+ Where `<type>` is `feat`, `fix`, `refactor`, or `chore` based on the change. If a branch already exists (resuming work), switch to it. Update the manifest's `branch:` field with the branch name.
174
+
175
+ This links the git history to the grimoire change — `grimoire trace` and `grimoire log` depend on it.
176
+
177
+ ### 4. Load Context
178
+
179
+ **Use the context blocks in `tasks.md`.** Each task section has a `<!-- context: ... -->` comment listing the exact files to load for that section. This was computed during planning with full codebase knowledge. Load those files — they include the relevant feature files, area docs, and source files you'll need.
180
+
181
+ **Loading order:**
182
+ 1. `tasks.md` — your checklist (load once at start, find the current section)
183
+ 2. Read the `<!-- context: ... -->` block for the current section
184
+ 3. Load each file listed in the context block
185
+ 4. If a listed file doesn't exist, it may need to be created as part of the task — that's fine
186
+
187
+ **If the context window fills up** (degraded output quality, forgotten context, repeated mistakes):
188
+ 1. Finish or pause the current task
189
+ 2. Summarize progress in `tasks.md` (mark completed tasks, add handoff note)
190
+ 3. Tell the user: "Context is getting large. I've updated tasks.md with progress. A fresh session can resume from here."
191
+
192
+ ### 5. Implement Tasks
193
+ Work through `tasks.md` sequentially. **Every task follows the same cycle: code → test → green → next.**
194
+
195
+ **For each task:**
196
+ 1. Announce which task you're working on
197
+ 2. Write the step definitions FIRST (the test that will verify this task)
198
+ 3. Run the step definitions — **they MUST FAIL (red)**
199
+ 4. If the test passes immediately, STOP. The test is broken — it's not actually testing anything. Fix the step definition so it makes a real assertion that fails without production code. Common causes:
200
+ - Empty step definition body (passes by default)
201
+ - Assertion against a mock/fixture that already satisfies the condition
202
+ - Step wired to wrong function or missing the actual check
203
+ - Overly broad assertion that matches anything
204
+ 5. Once confirmed red: write the production code to make it pass
205
+ 6. Run the step definitions again — they should PASS (green)
206
+ 7. If still red, fix the production code (not the test)
207
+ 8. **Test quality check:** Before marking done, verify your step definitions have strong assertions:
208
+ - Every Then step has a specific `assert` or `expect` with an exact expected value (not `assert True`, not `toBeDefined()`)
209
+ - No empty function bodies (`pass`, `...`, or no-op)
210
+ - Assertions check behavior, not just types or existence — "response status is 302 and redirect URL is /dashboard/" not "response is not None"
211
+ - If you wrote a test that would pass against a null/trivial implementation, strengthen it
212
+ 9. Mark complete: `- [ ]` → `- [x]`
213
+ 10. Move to next task
214
+
215
+ **This is strict red-green BDD.** A test that has never been red has never proven it can catch a failure. The red step is NOT a formality — it is the proof that the test works. If you skip it or the test passes immediately, you have a false positive that provides zero safety.
216
+
217
+ **Step definition rules:**
218
+ - Organize by domain concept, not by feature file
219
+ - Shared steps go in the project's common step location (check existing test setup)
220
+ - Step definitions are the translation layer between Gherkin and code
221
+ - Keep them thin — delegate to helper/support code
222
+ - Every Given/When/Then step in a proposed `.feature` file MUST have a corresponding step definition
223
+
224
+ **Architecture tasks:**
225
+ - Follow the decision record's chosen option
226
+ - Implement consequences noted in the ADR
227
+ - If the ADR has a Confirmation section, write a test or check that validates it
228
+
229
+ ### 6. Verify
230
+ When all implementation tasks are complete:
231
+ - Run the BDD test suite (command from `config.tools.bdd_test`) — existing behavior must not break
232
+ - All scenarios should pass — new AND existing
233
+ - If new scenarios fail, fix the implementation (not the feature file — the feature is the spec)
234
+ - If existing scenarios break, you've introduced a regression — fix it before proceeding
235
+ - Check ADR confirmation criteria if applicable
236
+ - Run the project's full test suite (`config.tools.unit_test`) if configured — grimoire tests don't replace existing tests
237
+
238
+ **The verify step is not optional. Do not proceed to finalize with failing tests.**
239
+
240
+ ### 7. Finalize
241
+ When all tests are green:
242
+ 1. Copy proposed `.feature` files from `.grimoire/changes/<change-id>/features/` to `features/` (replacing baseline)
243
+ 2. Move new decision records to `.grimoire/decisions/` with proper sequential numbering
244
+ 3. Update MADR status from `proposed` to `accepted` and set the date
245
+ 4. If `data.yml` exists, merge the changes into `.grimoire/docs/data/schema.yml` — apply adds/modifies/removes so the baseline schema stays current
246
+ 5. Move `manifest.md` to `.grimoire/archive/YYYY-MM-DD-<change-id>/`
247
+ 6. Remove the change directory from `.grimoire/changes/`
248
+
249
+ ### 8. Summary
250
+ Present a brief summary:
251
+ - What was implemented
252
+ - Which features now pass (with test counts if available)
253
+ - Which decisions were accepted
254
+ - Any follow-up items
255
+
256
+ ## References
257
+
258
+ **Before writing code**, read `../references/testing-contracts.md` — covers: verify-before-using rules (imports, packages, APIs), mocking strategy (HTTP boundary not client), fixture management, contract tests, and step definition quality checks.
259
+
260
+ ## Important
261
+ - **Tests are not optional.** Every task produces both production code and passing step definitions. No exceptions.
262
+ - **Red-green is mandatory, not aspirational.** A test must fail before it passes. If it doesn't fail, it's not a real test. Fix it before moving on.
263
+ - **A test that always passes is worse than no test.** It gives false confidence. If you can't make a step definition fail, you don't understand what it's testing.
264
+ - The feature file is the spec. If a test fails, fix the code, not the feature.
265
+ - If implementation reveals that a scenario is wrong or missing, STOP and go back to draft. Don't silently change features.
266
+ - Keep changes minimal and focused — only implement what's in tasks.md
267
+ - If blocked, flag it rather than working around it
268
+ - Commit frequently — one commit per logical task is ideal. Every commit during apply **MUST** include a `Change: <change-id>` git trailer for audit traceability. Use `/grimoire:commit` or manually add the trailer.
269
+ - Existing tests must keep passing. A grimoire change that breaks existing behavior is not complete.
270
+
271
+ ## Done
272
+ When all tasks are complete, tests pass, and artifacts are finalized, the workflow is complete. Present the summary and suggest:
273
+ - `grimoire-verify` to confirm implementation matches specs
274
+ - `grimoire-commit` to commit the changes
@@ -0,0 +1,129 @@
1
+ ---
2
+ name: grimoire-audit
3
+ description: Audit an existing codebase to discover undocumented features and architecture decisions. Use when onboarding an existing project to grimoire.
4
+ compatibility: Designed for Claude Code (or similar products)
5
+ metadata:
6
+ author: kiwi-data
7
+ version: "0.1"
8
+ ---
9
+
10
+ # grimoire-audit
11
+
12
+ Audit an existing codebase to discover undocumented features and architecture decisions. Interview the user to collaboratively build out the grimoire baseline.
13
+
14
+ ## Triggers
15
+ - User wants to onboard grimoire into an existing project
16
+ - User asks to audit, discover, or document existing behavior
17
+ - User asks "what features do we have?" or "what's not documented?"
18
+ - Loose match: "audit", "discover", "onboard", "baseline", "inventory"
19
+
20
+ ## Routing
21
+ - Want to map codebase structure, utilities, and patterns → `grimoire-discover` first
22
+ - Want to add new functionality → `grimoire-draft`
23
+ - Want to find code quality issues → `grimoire-refactor`
24
+
25
+ ## Workflow
26
+
27
+ ### 1. Determine Audit Scope
28
+ Ask the user what to audit:
29
+ - **Features** — find behavioral functionality that has no `.feature` file
30
+ - **Decisions** — find implicit architecture decisions that have no ADR
31
+ - **Both** — full audit (default)
32
+
33
+ Check what's already documented:
34
+ - Read all files in `features/` for existing behavioral specs
35
+ - Read all files in `.grimoire/decisions/` for existing ADRs
36
+ - This is your "already known" set — don't re-propose these
37
+
38
+ ### 2. Feature Discovery
39
+ Scan the codebase for behavioral functionality. Look at:
40
+ - **Routes / URL patterns** — each route implies user-facing behavior
41
+ - **Views / Controllers** — what actions can users take?
42
+ - **API endpoints** — what does the system expose?
43
+ - **UI components / templates** — what do users see and interact with?
44
+ - **Background tasks / jobs** — what happens automatically?
45
+ - **Permissions / auth** — what access control exists?
46
+ - **Email / notifications** — what does the system communicate?
47
+
48
+ For each discovered behavior cluster, check if a corresponding `.feature` file exists. If not, note it as undocumented.
49
+
50
+ ### 3. Decision Discovery
51
+ Scan for implicit architecture decisions:
52
+ - **Dependencies** — what major libraries/frameworks are used and why? (requirements.txt, package.json, go.mod)
53
+ - **Database** — what database(s), why, any extensions?
54
+ - **Infrastructure patterns** — caching, queuing, search, file storage
55
+ - **Auth patterns** — how is authentication/authorization implemented?
56
+ - **API design** — REST? GraphQL? RPC? What conventions?
57
+ - **Testing patterns** — what framework, what strategy?
58
+ - **Deployment** — Docker, K8s, serverless? CI/CD pipeline?
59
+ - **Data model** — multi-tenant? event-sourced? CQRS?
60
+
61
+ For each pattern found, check if a corresponding ADR exists. If not, note it as undocumented.
62
+
63
+ ### 4. Interview the User
64
+ Do NOT dump a massive list. Present findings in batches of 3-5, grouped by area, and ask the user about each:
65
+
66
+ For features:
67
+ > "I found a document review workflow with routes for `/dais/review/document/<id>/`. There's tab switching, error modals, and tag editing. I don't see a feature file covering this. Should I draft one?"
68
+
69
+ For decisions:
70
+ > "You're using PostgreSQL with pgvector for embeddings and Redis with Huey for task queuing. These seem like deliberate choices but I don't see ADRs for them. Want me to capture these?"
71
+
72
+ Let the user:
73
+ - **Confirm** — yes, draft it
74
+ - **Skip** — not important enough to document
75
+ - **Clarify** — provide context the code doesn't show
76
+ - **Group** — "those three things are actually one feature"
77
+
78
+ ### 5. Draft Artifacts
79
+ For confirmed items, create a grimoire change:
80
+ - Change ID: `audit-<area>` (e.g., `audit-auth`, `audit-data-model`)
81
+ - Draft `.feature` files for confirmed behavioral specs
82
+ - Draft MADR records for confirmed decisions
83
+ - Write manifest summarizing what was discovered and documented
84
+
85
+ Group related items into single changes — don't create one change per discovery.
86
+
87
+ ### 6. Dead Feature Detection
88
+ Check for documented features and decisions that may no longer be accurate:
89
+
90
+ **Dead features** — feature files that describe behavior the code no longer implements:
91
+ - Feature files with no step definitions: for each `.feature` file, grep the test directory for its step text patterns
92
+ - Orphaned step definitions: grep step definition imports, check if referenced modules still exist on disk
93
+ - Stub step definitions: `grep -rn 'pass$\|NotImplementedError\|\.\.\.$$' <test-dir>` (empty bodies)
94
+ - Stale skips: `grep -rn '@skip\|@wip' features/` cross-referenced with `git blame` for age
95
+ - Deleted routes: for each feature's endpoint, grep the codebase for the route — missing = dead
96
+
97
+ **Stale decisions** — ADRs that describe choices no longer reflected in the code:
98
+ - ADR says "use library X" but library X is no longer in dependencies
99
+ - ADR is `accepted` but the pattern it describes isn't in the codebase
100
+ - ADR references files or modules that no longer exist
101
+
102
+ Present dead features and stale decisions to the user with the same interview approach — batches of 3-5:
103
+ > "I found `features/billing/invoice.feature` with 4 scenarios, but there are no step definitions and the `InvoiceView` it would test was deleted 3 months ago. Should I create a removal change for this?"
104
+
105
+ Options for the user:
106
+ - **Remove** — create a grimoire removal change to clean it up
107
+ - **Revive** — the feature should exist; create a change to re-implement it
108
+ - **Update** — the feature exists but the spec is outdated; create a change to fix the spec
109
+ - **Skip** — leave it for now
110
+
111
+ ### 7. Prioritize
112
+ After the interview, summarize:
113
+ - How many features are documented vs. undocumented
114
+ - How many features are dead or stale
115
+ - How many decisions are documented vs. undocumented
116
+ - How many decisions are stale
117
+ - Suggest which areas to address first (highest risk / most complex / most frequently changed)
118
+
119
+ ## Important
120
+ - This is a COLLABORATIVE process, not a dump. Interview, don't lecture.
121
+ - Present findings in small batches. Let the user guide priority.
122
+ - The user knows things the code doesn't show — ask about intent, not just structure.
123
+ - Some things legitimately don't need documentation. Respect "skip" answers.
124
+ - Don't try to document everything in one session. It's ok to do multiple audit passes.
125
+ - Features should describe WHAT the system does, not HOW the code works. Don't just translate code into Gherkin.
126
+ - For decisions, focus on choices that were non-obvious or have alternatives. "We use Python" doesn't need an ADR. "We use Huey instead of Celery" probably does.
127
+
128
+ ## Done
129
+ When the audit interview is complete and confirmed items are drafted as grimoire changes, the workflow is complete. Suggest next steps: `grimoire-plan` for approved changes, or another audit pass for uncovered areas.