domain-knowledge-kit 0.2.16 → 0.2.19

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 (45) hide show
  1. package/dist/cli.js +4 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/features/agent/commands/init.d.ts +90 -1
  4. package/dist/features/agent/commands/init.d.ts.map +1 -1
  5. package/dist/features/agent/commands/init.js +206 -48
  6. package/dist/features/agent/commands/init.js.map +1 -1
  7. package/dist/features/agent/commands/prime.d.ts.map +1 -1
  8. package/dist/features/agent/commands/prime.js +2 -1
  9. package/dist/features/agent/commands/prime.js.map +1 -1
  10. package/dist/features/agent/commands/update.d.ts +27 -0
  11. package/dist/features/agent/commands/update.d.ts.map +1 -0
  12. package/dist/features/agent/commands/update.js +316 -0
  13. package/dist/features/agent/commands/update.js.map +1 -0
  14. package/dist/features/agent/dkk-artifacts.d.ts +76 -0
  15. package/dist/features/agent/dkk-artifacts.d.ts.map +1 -0
  16. package/dist/features/agent/dkk-artifacts.js +328 -0
  17. package/dist/features/agent/dkk-artifacts.js.map +1 -0
  18. package/dist/features/agent/install-mode.d.ts +34 -0
  19. package/dist/features/agent/install-mode.d.ts.map +1 -0
  20. package/dist/features/agent/install-mode.js +78 -0
  21. package/dist/features/agent/install-mode.js.map +1 -0
  22. package/dist/features/agent/mcp-register.d.ts +20 -0
  23. package/dist/features/agent/mcp-register.d.ts.map +1 -0
  24. package/dist/features/agent/mcp-register.js +116 -0
  25. package/dist/features/agent/mcp-register.js.map +1 -0
  26. package/dist/features/agent/settings-prune.d.ts +29 -0
  27. package/dist/features/agent/settings-prune.d.ts.map +1 -0
  28. package/dist/features/agent/settings-prune.js +70 -0
  29. package/dist/features/agent/settings-prune.js.map +1 -0
  30. package/dist/features/agent/tests/settings-prune.test.d.ts +2 -0
  31. package/dist/features/agent/tests/settings-prune.test.d.ts.map +1 -0
  32. package/dist/features/agent/tests/settings-prune.test.js +118 -0
  33. package/dist/features/agent/tests/settings-prune.test.js.map +1 -0
  34. package/dist/features/scaffold/commands/new-domain.d.ts +22 -0
  35. package/dist/features/scaffold/commands/new-domain.d.ts.map +1 -1
  36. package/dist/features/scaffold/commands/new-domain.js +44 -28
  37. package/dist/features/scaffold/commands/new-domain.js.map +1 -1
  38. package/dist/version.d.ts +4 -0
  39. package/dist/version.d.ts.map +1 -0
  40. package/dist/version.js +15 -0
  41. package/dist/version.js.map +1 -0
  42. package/package.json +3 -3
  43. package/tools/dkk/claude/hooks/post-edit-validate.mjs +25 -8
  44. package/tools/dkk/claude/hooks/session-start-prime.mjs +3 -16
  45. package/tools/dkk/claude/hooks/stop-validate.mjs +25 -6
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Prune DKK-owned entries from a Claude `settings.json` payload.
3
+ *
4
+ * Used by `dkk update` to clear stale entries (e.g. hooks for scripts that
5
+ * have been renamed or removed) before re-applying the additive merge with
6
+ * the new template. User-authored entries are preserved untouched.
7
+ *
8
+ * Decision boundaries (see [[dkk-artifacts]] for the predicate source of
9
+ * truth):
10
+ *
11
+ * - A `permissions.allow` entry is DKK-owned iff it appears verbatim in
12
+ * the bundled template's allow list. Exact string equality is the right
13
+ * bar because the template's allow patterns are stable identifiers.
14
+ * - A `hooks.<event>` sub-entry is DKK-owned iff **every** `hooks[].command`
15
+ * inside it resolves via {@link extractHookBasename} to a DKK basename.
16
+ * Mixed entries (some DKK, some user-authored) are left intact and
17
+ * reported as warnings — pruning them partially would mutate
18
+ * user-authored data.
19
+ */
20
+ import { extractHookBasename } from "./commands/init.js";
21
+ export function pruneDkkEntries(settings, dkkAllow, dkkHookBasenames) {
22
+ // Deep-clone so callers can compare before/after without surprise.
23
+ const pruned = JSON.parse(JSON.stringify(settings));
24
+ const removed = [];
25
+ const mixedHookWarnings = [];
26
+ // permissions.allow — drop exact-string matches.
27
+ if (Array.isArray(pruned.permissions?.allow)) {
28
+ const before = pruned.permissions.allow;
29
+ const kept = [];
30
+ for (const entry of before) {
31
+ if (dkkAllow.has(entry)) {
32
+ removed.push(`permissions.allow: ${entry}`);
33
+ }
34
+ else {
35
+ kept.push(entry);
36
+ }
37
+ }
38
+ pruned.permissions.allow = kept;
39
+ }
40
+ // hooks.* — drop entries whose every command resolves to a DKK basename.
41
+ if (pruned.hooks && typeof pruned.hooks === "object") {
42
+ for (const [event, entries] of Object.entries(pruned.hooks)) {
43
+ if (!Array.isArray(entries))
44
+ continue;
45
+ const kept = [];
46
+ for (const entry of entries) {
47
+ const commands = entry.hooks ?? [];
48
+ if (commands.length === 0) {
49
+ kept.push(entry);
50
+ continue;
51
+ }
52
+ const basenames = commands.map((h) => extractHookBasename(h.command));
53
+ const dkkOwned = basenames.filter((b) => b !== null && dkkHookBasenames.has(b));
54
+ const allDkk = basenames.every((b) => b !== null && dkkHookBasenames.has(b));
55
+ const someDkk = dkkOwned.length > 0;
56
+ if (allDkk) {
57
+ removed.push(`hooks.${event}: ${basenames.filter(Boolean).join(", ")}`);
58
+ continue;
59
+ }
60
+ if (someDkk) {
61
+ mixedHookWarnings.push(`hooks.${event}: mixed DKK/user commands left intact (DKK: ${dkkOwned.join(", ")})`);
62
+ }
63
+ kept.push(entry);
64
+ }
65
+ pruned.hooks[event] = kept;
66
+ }
67
+ }
68
+ return { pruned, removed, mixedHookWarnings };
69
+ }
70
+ //# sourceMappingURL=settings-prune.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-prune.js","sourceRoot":"","sources":["../../../src/features/agent/settings-prune.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=settings-prune.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-prune.test.d.ts","sourceRoot":"","sources":["../../../../src/features/agent/tests/settings-prune.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Tests for the settings.json prune logic used by `dkk update`.
3
+ *
4
+ * Covers the three scenarios the update flow cares about:
5
+ * 1. DKK-only `permissions.allow` entries are removed; user entries stay.
6
+ * 2. Hook entries whose every command is DKK-owned are removed; mixed
7
+ * entries (DKK + user) are kept with a warning.
8
+ * 3. Empty settings are handled without throwing.
9
+ */
10
+ import { pruneDkkEntries } from "../settings-prune.js";
11
+ let passed = 0;
12
+ let failed = 0;
13
+ function assert(label, condition, detail) {
14
+ if (condition) {
15
+ console.log(` OK: ${label}`);
16
+ passed++;
17
+ }
18
+ else {
19
+ console.error(`FAIL: ${label}${detail ? ` — ${detail}` : ""}`);
20
+ failed++;
21
+ }
22
+ }
23
+ // Canonical DKK identifiers (subset — enough to exercise the prune logic).
24
+ const DKK_ALLOW = new Set([
25
+ "Bash(dkk list:*)",
26
+ "Bash(dkk show:*)",
27
+ "Bash(dkk validate:*)",
28
+ ]);
29
+ const DKK_HOOKS = new Set([
30
+ "session-start-prime.mjs",
31
+ "post-edit-validate.mjs",
32
+ ]);
33
+ console.log("\n=== prune: removes only DKK-owned permissions.allow entries ===");
34
+ {
35
+ const input = {
36
+ permissions: {
37
+ allow: [
38
+ "Bash(dkk list:*)", // DKK-owned
39
+ "Bash(dkk show:*)", // DKK-owned
40
+ "Bash(myproject build:*)", // user-authored
41
+ "Bash(custom thing:*)", // user-authored
42
+ ],
43
+ },
44
+ };
45
+ const { pruned, removed } = pruneDkkEntries(input, DKK_ALLOW, DKK_HOOKS);
46
+ assert("user entries preserved", pruned.permissions?.allow?.includes("Bash(myproject build:*)") === true &&
47
+ pruned.permissions?.allow?.includes("Bash(custom thing:*)") === true);
48
+ assert("DKK entries removed from permissions.allow", pruned.permissions?.allow?.includes("Bash(dkk list:*)") === false &&
49
+ pruned.permissions?.allow?.includes("Bash(dkk show:*)") === false);
50
+ assert("removed list reports DKK entries", removed.length === 2);
51
+ }
52
+ console.log("\n=== prune: removes hook entries whose every command is DKK ===");
53
+ {
54
+ const input = {
55
+ hooks: {
56
+ SessionStart: [
57
+ {
58
+ // DKK-only entry — should be dropped.
59
+ hooks: [
60
+ { type: "command", command: 'node "$CLAUDE_PROJECT_DIR/.claude/hooks/session-start-prime.mjs"' },
61
+ ],
62
+ },
63
+ {
64
+ // User-only entry — should be preserved.
65
+ hooks: [{ type: "command", command: "echo user-hook" }],
66
+ },
67
+ ],
68
+ },
69
+ };
70
+ const { pruned } = pruneDkkEntries(input, DKK_ALLOW, DKK_HOOKS);
71
+ const remaining = pruned.hooks?.SessionStart ?? [];
72
+ assert("DKK-only hook entry removed", remaining.length === 1);
73
+ assert("user hook entry preserved", remaining[0]?.hooks?.[0]?.command === "echo user-hook");
74
+ }
75
+ console.log("\n=== prune: leaves mixed hook entries alone with a warning ===");
76
+ {
77
+ const input = {
78
+ hooks: {
79
+ SessionStart: [
80
+ {
81
+ hooks: [
82
+ { type: "command", command: 'node "$CLAUDE_PROJECT_DIR/.claude/hooks/session-start-prime.mjs"' },
83
+ { type: "command", command: "echo also-user-hook" },
84
+ ],
85
+ },
86
+ ],
87
+ },
88
+ };
89
+ const { pruned, mixedHookWarnings } = pruneDkkEntries(input, DKK_ALLOW, DKK_HOOKS);
90
+ assert("mixed entry preserved verbatim", pruned.hooks?.SessionStart?.length === 1);
91
+ assert("mixed warning emitted", mixedHookWarnings.length === 1);
92
+ assert("mixed warning names the DKK hook", mixedHookWarnings[0].includes("session-start-prime.mjs"));
93
+ }
94
+ console.log("\n=== prune: tolerates empty / missing fields ===");
95
+ {
96
+ const empty = {};
97
+ const { pruned, removed, mixedHookWarnings } = pruneDkkEntries(empty, DKK_ALLOW, DKK_HOOKS);
98
+ assert("empty settings → no removed entries", removed.length === 0);
99
+ assert("empty settings → no mixed warnings", mixedHookWarnings.length === 0);
100
+ // Deep clone returns an object that's structurally equivalent (also empty).
101
+ assert("empty settings round-trip", JSON.stringify(pruned) === "{}");
102
+ }
103
+ console.log("\n=== prune: drops empty allow list entries cleanly ===");
104
+ {
105
+ const input = {
106
+ permissions: {
107
+ allow: ["Bash(dkk list:*)", "Bash(dkk show:*)", "Bash(dkk validate:*)"],
108
+ },
109
+ };
110
+ const { pruned, removed } = pruneDkkEntries(input, DKK_ALLOW, DKK_HOOKS);
111
+ assert("all DKK entries removed", pruned.permissions?.allow?.length === 0);
112
+ assert("removed list has 3 entries", removed.length === 3);
113
+ }
114
+ // ── Summary ───────────────────────────────────────────────────────────
115
+ console.log(`\n${passed} passed, ${failed} failed`);
116
+ if (failed > 0)
117
+ process.exit(1);
118
+ //# sourceMappingURL=settings-prune.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-prune.test.js","sourceRoot":"","sources":["../../../../src/features/agent/tests/settings-prune.test.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,29 @@
8
8
  * context.yml, events/, commands/, aggregates/, policies/, read-models/
9
9
  *
10
10
  * Errors if `.dkk/domain/` already exists (use `--force` to overwrite).
11
+ *
12
+ * The scaffold logic is also exported as `scaffoldDomain()` so `dkk init`
13
+ * can bootstrap the same structure during project initialization.
11
14
  */
12
15
  import type { Command as Cmd } from "commander";
16
+ export type ScaffoldDomainStatus = "created" | "skipped" | "replaced";
17
+ export interface ScaffoldDomainResult {
18
+ status: ScaffoldDomainStatus;
19
+ path: string;
20
+ }
21
+ /**
22
+ * Scaffold `.dkk/domain/` with sample content.
23
+ *
24
+ * - If the directory does not exist, creates it (`status: "created"`).
25
+ * - If it exists and `force` is false, leaves it untouched (`status: "skipped"`).
26
+ * - If it exists and `force` is true, removes it entirely first, then
27
+ * creates a fresh scaffold (`status: "replaced"`).
28
+ */
29
+ export declare function scaffoldDomain(opts?: {
30
+ root?: string;
31
+ force?: boolean;
32
+ }): ScaffoldDomainResult;
33
+ /** Files created by a successful scaffold — used by callers that print their own report. */
34
+ export declare const SCAFFOLD_DOMAIN_FILES: readonly string[];
13
35
  export declare function registerNewDomain(program: Cmd): void;
14
36
  //# sourceMappingURL=new-domain.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"new-domain.d.ts","sourceRoot":"","sources":["../../../../src/features/scaffold/commands/new-domain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AA0DhD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CA6DpD"}
1
+ {"version":3,"file":"new-domain.d.ts","sourceRoot":"","sources":["../../../../src/features/scaffold/commands/new-domain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AA0DhD,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAEtE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,oBAAoB,CA0BlG;AAED,4FAA4F;AAC5F,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAOlD,CAAC;AAIF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CAmCpD"}
@@ -45,6 +45,45 @@ emits:
45
45
  events:
46
46
  - SampleCreated
47
47
  `;
48
+ /**
49
+ * Scaffold `.dkk/domain/` with sample content.
50
+ *
51
+ * - If the directory does not exist, creates it (`status: "created"`).
52
+ * - If it exists and `force` is false, leaves it untouched (`status: "skipped"`).
53
+ * - If it exists and `force` is true, removes it entirely first, then
54
+ * creates a fresh scaffold (`status: "replaced"`).
55
+ */
56
+ export function scaffoldDomain(opts = {}) {
57
+ const dir = domainDir(opts.root);
58
+ if (existsSync(dir) && !opts.force) {
59
+ return { status: "skipped", path: dir };
60
+ }
61
+ const replaced = existsSync(dir) && (opts.force ?? false);
62
+ if (replaced) {
63
+ rmSync(dir, { recursive: true, force: true });
64
+ }
65
+ const contextsBase = join(dir, "contexts", "sample");
66
+ const subDirs = ["events", "commands", "aggregates", "policies", "read-models"];
67
+ for (const sub of subDirs) {
68
+ mkdirSync(join(contextsBase, sub), { recursive: true });
69
+ }
70
+ writeFileSync(join(dir, "index.yml"), INDEX_YML, "utf-8");
71
+ writeFileSync(join(dir, "actors.yml"), ACTORS_YML, "utf-8");
72
+ writeFileSync(join(contextsBase, "context.yml"), CONTEXT_YML, "utf-8");
73
+ writeFileSync(join(contextsBase, "events", "SampleCreated.yml"), SAMPLE_EVENT, "utf-8");
74
+ writeFileSync(join(contextsBase, "commands", "CreateSample.yml"), SAMPLE_COMMAND, "utf-8");
75
+ writeFileSync(join(contextsBase, "aggregates", "Sample.yml"), SAMPLE_AGGREGATE, "utf-8");
76
+ return { status: replaced ? "replaced" : "created", path: dir };
77
+ }
78
+ /** Files created by a successful scaffold — used by callers that print their own report. */
79
+ export const SCAFFOLD_DOMAIN_FILES = [
80
+ "index.yml",
81
+ "actors.yml",
82
+ "contexts/sample/context.yml",
83
+ "contexts/sample/events/SampleCreated.yml",
84
+ "contexts/sample/commands/CreateSample.yml",
85
+ "contexts/sample/aggregates/Sample.yml",
86
+ ];
48
87
  // ── Registration ──────────────────────────────────────────────────────
49
88
  export function registerNewDomain(program) {
50
89
  program
@@ -56,44 +95,21 @@ export function registerNewDomain(program) {
56
95
  .option("--minify", "Minify JSON")
57
96
  .action((opts) => {
58
97
  const dir = domainDir(opts.root);
59
- // Guard: refuse to overwrite unless --force
60
98
  if (existsSync(dir) && !opts.force) {
61
99
  console.error(`Error: ${dir} already exists. Use --force to replace it entirely.`);
62
100
  process.exit(1);
63
101
  }
64
- // --force: remove the entire domain directory so the scaffold is applied
65
- // to a clean slate (no silent merging of pre-existing content).
66
- if (existsSync(dir) && opts.force) {
67
- rmSync(dir, { recursive: true, force: true });
68
- }
69
- // Create directory structure
70
- const contextsBase = join(dir, "contexts", "sample");
71
- const subDirs = ["events", "commands", "aggregates", "policies", "read-models"];
72
- for (const sub of subDirs) {
73
- mkdirSync(join(contextsBase, sub), { recursive: true });
74
- }
75
- // Write files
76
- writeFileSync(join(dir, "index.yml"), INDEX_YML, "utf-8");
77
- writeFileSync(join(dir, "actors.yml"), ACTORS_YML, "utf-8");
78
- writeFileSync(join(contextsBase, "context.yml"), CONTEXT_YML, "utf-8");
79
- writeFileSync(join(contextsBase, "events", "SampleCreated.yml"), SAMPLE_EVENT, "utf-8");
80
- writeFileSync(join(contextsBase, "commands", "CreateSample.yml"), SAMPLE_COMMAND, "utf-8");
81
- writeFileSync(join(contextsBase, "aggregates", "Sample.yml"), SAMPLE_AGGREGATE, "utf-8");
102
+ const result = scaffoldDomain({ root: opts.root, force: opts.force });
82
103
  if (opts.json) {
83
104
  console.log(JSON.stringify({
84
- path: dir,
85
- success: true
105
+ path: result.path,
106
+ success: true,
86
107
  }, null, opts.minify ? 0 : 2));
87
108
  return;
88
109
  }
89
110
  console.log("Created .dkk/domain/ with sample content:");
90
- console.log(" index.yml");
91
- console.log(" actors.yml");
92
- console.log(" contexts/sample/");
93
- console.log(" context.yml");
94
- console.log(" events/SampleCreated.yml");
95
- console.log(" commands/CreateSample.yml");
96
- console.log(" aggregates/Sample.yml");
111
+ for (const f of SCAFFOLD_DOMAIN_FILES)
112
+ console.log(` ${f}`);
97
113
  console.log("\nRun `dkk render` to validate and generate documentation.");
98
114
  });
99
115
  }
@@ -1 +1 @@
1
- {"version":3,"file":"new-domain.js","sourceRoot":"","sources":["../../../../src/features/scaffold/commands/new-domain.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,yEAAyE;AAEzE,MAAM,SAAS,GAAG;;;;;CAKjB,CAAC;AAEF,MAAM,UAAU,GAAG;;;;;CAKlB,CAAC;AAEF,MAAM,WAAW,GAAG;;;;;;CAMnB,CAAC;AAEF,MAAM,YAAY,GAAG;;;;;;;CAOpB,CAAC;AAEF,MAAM,cAAc,GAAG;;;;;CAKtB,CAAC;AAEF,MAAM,gBAAgB,GAAG;;;;;;;;;CASxB,CAAC;AAEF,yEAAyE;AAEzE,MAAM,UAAU,iBAAiB,CAAC,OAAY;IAC5C,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,gEAAgE,CAAC;SAC7E,MAAM,CAAC,mBAAmB,EAAE,0BAA0B,CAAC;SACvD,MAAM,CACL,SAAS,EACT,sGAAsG,CACvG;SACA,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC;SACjC,MAAM,CAAC,CAAC,IAA0E,EAAE,EAAE;QACrF,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEjC,4CAA4C;QAC5C,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,CACX,UAAU,GAAG,sDAAsD,CACpE,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,yEAAyE;QACzE,gEAAgE;QAChE,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAClC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;QAED,6BAA6B;QAC7B,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;QAChF,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,SAAS,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,cAAc;QACd,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAC1D,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QAC5D,aAAa,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QACvE,aAAa,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,mBAAmB,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;QACxF,aAAa,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,EAAE,kBAAkB,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAC3F,aAAa,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,EAAE,YAAY,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC;QAEzF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;gBACxB,IAAI,EAAE,GAAG;gBACT,OAAO,EAAE,IAAI;aACf,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/B,OAAO;QACV,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"new-domain.js","sourceRoot":"","sources":["../../../../src/features/scaffold/commands/new-domain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare const pkgVersion: string;
2
+ /** Name of the package on the npm registry. Used by `dkk update`. */
3
+ export declare const pkgName = "domain-knowledge-kit";
4
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,UAAU,QAEd,CAAC;AAEV,qEAAqE;AACrE,eAAO,MAAM,OAAO,yBAAyB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Package version, read at runtime from `package.json`.
3
+ *
4
+ * Works in both dev (`src/version.ts`) and build (`dist/version.js`) because
5
+ * `package.json` is one level above either entrypoint. Computed once at
6
+ * module load.
7
+ */
8
+ import { readFileSync } from "node:fs";
9
+ import { fileURLToPath } from "node:url";
10
+ import { dirname, resolve } from "node:path";
11
+ const pkgPath = resolve(dirname(fileURLToPath(import.meta.url)), "../package.json");
12
+ export const pkgVersion = JSON.parse(readFileSync(pkgPath, "utf8")).version;
13
+ /** Name of the package on the npm registry. Used by `dkk update`. */
14
+ export const pkgName = "domain-knowledge-kit";
15
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,OAAO,GAAG,OAAO,CACrB,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EACvC,iBAAiB,CAClB,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GACrB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CACzC,CAAC,OAAO,CAAC;AAEV,qEAAqE;AACrE,MAAM,CAAC,MAAM,OAAO,GAAG,sBAAsB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domain-knowledge-kit",
3
- "version": "0.2.16",
3
+ "version": "0.2.19",
4
4
  "description": "Domain Knowledge Pack — YAML + ADR links + deterministic search + generated docs",
5
5
  "type": "module",
6
6
  "repository": {
@@ -39,7 +39,6 @@
39
39
  "keywords": [],
40
40
  "license": "Elastic-2.0",
41
41
  "devDependencies": {
42
- "@types/better-sqlite3": "^7.6.13",
43
42
  "@types/js-yaml": "^4.0.9",
44
43
  "eslint": "^10.0.1",
45
44
  "tsx": "^4.7.0",
@@ -49,9 +48,10 @@
49
48
  },
50
49
  "dependencies": {
51
50
  "@modelcontextprotocol/sdk": "^1.29.0",
51
+ "@types/better-sqlite3": "^7.6.13",
52
52
  "ajv": "^8.12.0",
53
53
  "ajv-formats": "^3.0.1",
54
- "better-sqlite3": "^11.0.0",
54
+ "better-sqlite3": "^12.10.0",
55
55
  "commander": "^12.0.0",
56
56
  "fast-glob": "^3.3.2",
57
57
  "handlebars": "^4.7.8",
@@ -9,8 +9,6 @@
9
9
  * Stays silent for unrelated edits (no-op, exit 0).
10
10
  */
11
11
  import { spawnSync } from "node:child_process";
12
- import { existsSync } from "node:fs";
13
- import { resolve } from "node:path";
14
12
 
15
13
  let raw = "";
16
14
  process.stdin.on("data", (d) => (raw += d));
@@ -32,18 +30,37 @@ process.stdin.on("end", () => {
32
30
  if (!isDomainYaml) process.exit(0);
33
31
 
34
32
  const repoRoot = process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
35
- const cliEntry = resolve(repoRoot, "src/cli.ts");
36
33
 
37
- const [cmd, args] = existsSync(cliEntry)
38
- ? ["npx", ["tsx", cliEntry, "validate", "--json", "--minify"]]
39
- : ["dkk", ["validate", "--json", "--minify"]];
34
+ const res = spawnSync("dkk", ["validate", "--json", "--minify"], {
35
+ cwd: repoRoot,
36
+ encoding: "utf8",
37
+ });
38
+
39
+ // Tooling problem (dkk not on PATH, spawn error, etc.) — surface a clear
40
+ // setup error to the user, but don't block the agent with a phantom
41
+ // "validation failure" it has no way to fix.
42
+ if (res.error?.code === "ENOENT") {
43
+ process.stderr.write(
44
+ "dkk post-edit hook: 'dkk' CLI not found on PATH — install with `npm i -g domain-knowledge-kit` to enable auto-validation.\n",
45
+ );
46
+ process.exit(1);
47
+ }
48
+ if (res.error) {
49
+ process.stderr.write(
50
+ `dkk post-edit hook: failed to invoke validator — ${res.error.message}\n`,
51
+ );
52
+ process.exit(1);
53
+ }
40
54
 
41
- const res = spawnSync(cmd, args, { cwd: repoRoot, encoding: "utf8" });
42
55
  // If validate fails, surface the JSON output to the model via stderr (exit 2
43
56
  // makes Claude Code feed stderr back as a tool-result correction signal).
44
57
  if (res.status !== 0) {
58
+ const body =
59
+ res.stdout ||
60
+ res.stderr ||
61
+ "(validator exited non-zero with no output — likely a tooling/wiring problem, not a domain issue)";
45
62
  process.stderr.write(
46
- `dkk validate failed after edit to ${filePath}:\n${res.stdout || res.stderr || ""}\n`,
63
+ `dkk validate failed after edit to ${filePath}:\n${body}\n`,
47
64
  );
48
65
  process.exit(2);
49
66
  }
@@ -8,26 +8,13 @@
8
8
  * so a missing domain model never blocks session start.
9
9
  */
10
10
  import { spawnSync } from "node:child_process";
11
- import { existsSync } from "node:fs";
12
- import { resolve } from "node:path";
13
11
 
14
12
  const repoRoot = process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
15
- const cliEntry = resolve(repoRoot, "src/cli.ts");
16
13
 
17
- let cmd, args;
18
- if (existsSync(cliEntry)) {
19
- // Local DKK development: run via tsx.
20
- cmd = "npx";
21
- args = ["tsx", cliEntry, "prime"];
22
- } else {
23
- // Downstream consumer: rely on the published `dkk` binary.
24
- cmd = "dkk";
25
- args = ["prime"];
26
- }
27
-
28
- const res = spawnSync(cmd, args, { cwd: repoRoot, encoding: "utf8" });
14
+ const res = spawnSync("dkk", ["prime"], { cwd: repoRoot, encoding: "utf8" });
29
15
  if (res.status === 0 && res.stdout) {
30
16
  process.stdout.write(res.stdout);
31
17
  }
32
- // Always exit 0 — never block session start over a missing/empty model.
18
+ // Always exit 0 — never block session start over a missing `dkk` binary or
19
+ // an empty/absent domain model. Priming is a best-effort context boost.
33
20
  process.exit(0);
@@ -28,19 +28,38 @@ process.stdin.on("end", () => {
28
28
  }
29
29
 
30
30
  const repoRoot = process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
31
- const cliEntry = resolve(repoRoot, "src/cli.ts");
32
31
 
33
32
  // No domain model? Nothing to gate on.
34
33
  if (!existsSync(resolve(repoRoot, ".dkk/domain"))) process.exit(0);
35
34
 
36
- const [cmd, args] = existsSync(cliEntry)
37
- ? ["npx", ["tsx", cliEntry, "validate", "--json", "--minify"]]
38
- : ["dkk", ["validate", "--json", "--minify"]];
35
+ const res = spawnSync("dkk", ["validate", "--json", "--minify"], {
36
+ cwd: repoRoot,
37
+ encoding: "utf8",
38
+ });
39
+
40
+ // Tooling problem (dkk not on PATH, spawn error, etc.) — surface a clear
41
+ // setup error to the user, but don't block the agent with a phantom
42
+ // "domain failure" it has no way to fix.
43
+ if (res.error?.code === "ENOENT") {
44
+ process.stderr.write(
45
+ "dkk stop hook: 'dkk' CLI not found on PATH — install with `npm i -g domain-knowledge-kit` to enable the domain validation gate.\n",
46
+ );
47
+ process.exit(1);
48
+ }
49
+ if (res.error) {
50
+ process.stderr.write(
51
+ `dkk stop hook: failed to invoke validator — ${res.error.message}\n`,
52
+ );
53
+ process.exit(1);
54
+ }
39
55
 
40
- const res = spawnSync(cmd, args, { cwd: repoRoot, encoding: "utf8" });
41
56
  if (res.status !== 0) {
57
+ const body =
58
+ res.stdout ||
59
+ res.stderr ||
60
+ "(validator exited non-zero with no output — likely a tooling/wiring problem, not a domain issue)";
42
61
  process.stderr.write(
43
- `Domain validation failed — fix these before ending the turn:\n${res.stdout || res.stderr || ""}\n`,
62
+ `Domain validation failed — fix these before ending the turn:\n${body}\n`,
44
63
  );
45
64
  process.exit(2);
46
65
  }