@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.
- package/.claude-plugin/plugin.json +8 -0
- package/AGENTS.md +217 -0
- package/README.md +748 -0
- package/bin/grimoire.js +2 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +42 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/commands/archive.d.ts +3 -0
- package/dist/commands/archive.d.ts.map +1 -0
- package/dist/commands/archive.js +22 -0
- package/dist/commands/archive.js.map +1 -0
- package/dist/commands/branch-check.d.ts +3 -0
- package/dist/commands/branch-check.d.ts.map +1 -0
- package/dist/commands/branch-check.js +16 -0
- package/dist/commands/branch-check.js.map +1 -0
- package/dist/commands/check.d.ts +3 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +22 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/ci.d.ts +3 -0
- package/dist/commands/ci.d.ts.map +1 -0
- package/dist/commands/ci.js +18 -0
- package/dist/commands/ci.js.map +1 -0
- package/dist/commands/diff.d.ts +3 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +10 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/docs.d.ts +3 -0
- package/dist/commands/docs.d.ts.map +1 -0
- package/dist/commands/docs.js +11 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/commands/health.d.ts +3 -0
- package/dist/commands/health.d.ts.map +1 -0
- package/dist/commands/health.js +13 -0
- package/dist/commands/health.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +21 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +3 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +22 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/log.d.ts +3 -0
- package/dist/commands/log.d.ts.map +1 -0
- package/dist/commands/log.js +15 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/map.d.ts +3 -0
- package/dist/commands/map.d.ts.map +1 -0
- package/dist/commands/map.js +17 -0
- package/dist/commands/map.js.map +1 -0
- package/dist/commands/pr.d.ts +3 -0
- package/dist/commands/pr.d.ts.map +1 -0
- package/dist/commands/pr.js +17 -0
- package/dist/commands/pr.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +12 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/test-quality.d.ts +3 -0
- package/dist/commands/test-quality.d.ts.map +1 -0
- package/dist/commands/test-quality.js +37 -0
- package/dist/commands/test-quality.js.map +1 -0
- package/dist/commands/trace.d.ts +3 -0
- package/dist/commands/trace.d.ts.map +1 -0
- package/dist/commands/trace.js +12 -0
- package/dist/commands/trace.js.map +1 -0
- package/dist/commands/update.d.ts +3 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +22 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate.d.ts +3 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +17 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/core/archive.d.ts +9 -0
- package/dist/core/archive.d.ts.map +1 -0
- package/dist/core/archive.js +92 -0
- package/dist/core/archive.js.map +1 -0
- package/dist/core/branch-check.d.ts +27 -0
- package/dist/core/branch-check.d.ts.map +1 -0
- package/dist/core/branch-check.js +205 -0
- package/dist/core/branch-check.js.map +1 -0
- package/dist/core/check.d.ts +24 -0
- package/dist/core/check.d.ts.map +1 -0
- package/dist/core/check.js +372 -0
- package/dist/core/check.js.map +1 -0
- package/dist/core/ci.d.ts +24 -0
- package/dist/core/ci.d.ts.map +1 -0
- package/dist/core/ci.js +162 -0
- package/dist/core/ci.js.map +1 -0
- package/dist/core/detect.d.ts +10 -0
- package/dist/core/detect.d.ts.map +1 -0
- package/dist/core/detect.js +368 -0
- package/dist/core/detect.js.map +1 -0
- package/dist/core/diff.d.ts +29 -0
- package/dist/core/diff.d.ts.map +1 -0
- package/dist/core/diff.js +197 -0
- package/dist/core/diff.js.map +1 -0
- package/dist/core/doc-style.d.ts +16 -0
- package/dist/core/doc-style.d.ts.map +1 -0
- package/dist/core/doc-style.js +192 -0
- package/dist/core/doc-style.js.map +1 -0
- package/dist/core/docs.d.ts +6 -0
- package/dist/core/docs.d.ts.map +1 -0
- package/dist/core/docs.js +478 -0
- package/dist/core/docs.js.map +1 -0
- package/dist/core/health.d.ts +7 -0
- package/dist/core/health.d.ts.map +1 -0
- package/dist/core/health.js +489 -0
- package/dist/core/health.js.map +1 -0
- package/dist/core/hooks.d.ts +5 -0
- package/dist/core/hooks.d.ts.map +1 -0
- package/dist/core/hooks.js +168 -0
- package/dist/core/hooks.js.map +1 -0
- package/dist/core/init.d.ts +9 -0
- package/dist/core/init.d.ts.map +1 -0
- package/dist/core/init.js +563 -0
- package/dist/core/init.js.map +1 -0
- package/dist/core/list.d.ts +4 -0
- package/dist/core/list.d.ts.map +1 -0
- package/dist/core/list.js +170 -0
- package/dist/core/list.js.map +1 -0
- package/dist/core/log.d.ts +8 -0
- package/dist/core/log.d.ts.map +1 -0
- package/dist/core/log.js +150 -0
- package/dist/core/log.js.map +1 -0
- package/dist/core/map.d.ts +9 -0
- package/dist/core/map.d.ts.map +1 -0
- package/dist/core/map.js +302 -0
- package/dist/core/map.js.map +1 -0
- package/dist/core/pr.d.ts +9 -0
- package/dist/core/pr.d.ts.map +1 -0
- package/dist/core/pr.js +273 -0
- package/dist/core/pr.js.map +1 -0
- package/dist/core/shared-setup.d.ts +52 -0
- package/dist/core/shared-setup.d.ts.map +1 -0
- package/dist/core/shared-setup.js +221 -0
- package/dist/core/shared-setup.js.map +1 -0
- package/dist/core/status.d.ts +6 -0
- package/dist/core/status.d.ts.map +1 -0
- package/dist/core/status.js +114 -0
- package/dist/core/status.js.map +1 -0
- package/dist/core/test-quality.d.ts +33 -0
- package/dist/core/test-quality.d.ts.map +1 -0
- package/dist/core/test-quality.js +378 -0
- package/dist/core/test-quality.js.map +1 -0
- package/dist/core/trace.d.ts +6 -0
- package/dist/core/trace.d.ts.map +1 -0
- package/dist/core/trace.js +211 -0
- package/dist/core/trace.js.map +1 -0
- package/dist/core/update.d.ts +10 -0
- package/dist/core/update.d.ts.map +1 -0
- package/dist/core/update.js +149 -0
- package/dist/core/update.js.map +1 -0
- package/dist/core/validate.d.ts +20 -0
- package/dist/core/validate.d.ts.map +1 -0
- package/dist/core/validate.js +275 -0
- package/dist/core/validate.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/config.d.ts +61 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +172 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/fs.d.ts +17 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +38 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/paths.d.ts +10 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +35 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/spawn.d.ts +5 -0
- package/dist/utils/spawn.d.ts.map +1 -0
- package/dist/utils/spawn.js +34 -0
- package/dist/utils/spawn.js.map +1 -0
- package/package.json +68 -0
- package/skills/grimoire-apply/SKILL.md +274 -0
- package/skills/grimoire-audit/SKILL.md +129 -0
- package/skills/grimoire-branch-guard/SKILL.md +111 -0
- package/skills/grimoire-bug/SKILL.md +160 -0
- package/skills/grimoire-bug-explore/SKILL.md +242 -0
- package/skills/grimoire-bug-report/SKILL.md +237 -0
- package/skills/grimoire-bug-session/SKILL.md +222 -0
- package/skills/grimoire-bug-triage/SKILL.md +274 -0
- package/skills/grimoire-commit/SKILL.md +150 -0
- package/skills/grimoire-discover/SKILL.md +297 -0
- package/skills/grimoire-draft/SKILL.md +202 -0
- package/skills/grimoire-plan/SKILL.md +329 -0
- package/skills/grimoire-pr/SKILL.md +134 -0
- package/skills/grimoire-pr-review/SKILL.md +240 -0
- package/skills/grimoire-refactor/SKILL.md +251 -0
- package/skills/grimoire-remove/SKILL.md +112 -0
- package/skills/grimoire-review/SKILL.md +247 -0
- package/skills/grimoire-verify/SKILL.md +223 -0
- package/skills/references/bug-classification.md +154 -0
- package/skills/references/build-vs-buy.md +77 -0
- package/skills/references/elicitation-personas.md +118 -0
- package/skills/references/refactor-register-format.md +88 -0
- package/skills/references/refactor-scan-categories.md +102 -0
- package/skills/references/schema-format.md +68 -0
- package/skills/references/security-compliance.md +110 -0
- package/skills/references/testing-contracts.md +93 -0
- package/templates/context.yml +110 -0
- package/templates/debt-exceptions.yml +61 -0
- package/templates/decision.md +50 -0
- package/templates/dupignore +93 -0
- package/templates/example.feature +24 -0
- package/templates/manifest.md +29 -0
- package/templates/mapignore +58 -0
- 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 @@
|
|
|
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.
|