@kaddo/mcp 3.59.0 → 3.61.0

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 (2) hide show
  1. package/dist/index.js +2393 -738
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,4 +1,85 @@
1
1
  #!/usr/bin/env node
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+
28
+ // ../../node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js
29
+ var require_src = __commonJS({
30
+ "../../node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js"(exports, module) {
31
+ "use strict";
32
+ var ESC = "\x1B";
33
+ var CSI = `${ESC}[`;
34
+ var beep = "\x07";
35
+ var cursor = {
36
+ to(x2, y) {
37
+ if (!y) return `${CSI}${x2 + 1}G`;
38
+ return `${CSI}${y + 1};${x2 + 1}H`;
39
+ },
40
+ move(x2, y) {
41
+ let ret = "";
42
+ if (x2 < 0) ret += `${CSI}${-x2}D`;
43
+ else if (x2 > 0) ret += `${CSI}${x2}C`;
44
+ if (y < 0) ret += `${CSI}${-y}A`;
45
+ else if (y > 0) ret += `${CSI}${y}B`;
46
+ return ret;
47
+ },
48
+ up: (count = 1) => `${CSI}${count}A`,
49
+ down: (count = 1) => `${CSI}${count}B`,
50
+ forward: (count = 1) => `${CSI}${count}C`,
51
+ backward: (count = 1) => `${CSI}${count}D`,
52
+ nextLine: (count = 1) => `${CSI}E`.repeat(count),
53
+ prevLine: (count = 1) => `${CSI}F`.repeat(count),
54
+ left: `${CSI}G`,
55
+ hide: `${CSI}?25l`,
56
+ show: `${CSI}?25h`,
57
+ save: `${ESC}7`,
58
+ restore: `${ESC}8`
59
+ };
60
+ var scroll = {
61
+ up: (count = 1) => `${CSI}S`.repeat(count),
62
+ down: (count = 1) => `${CSI}T`.repeat(count)
63
+ };
64
+ var erase = {
65
+ screen: `${CSI}2J`,
66
+ up: (count = 1) => `${CSI}1J`.repeat(count),
67
+ down: (count = 1) => `${CSI}J`.repeat(count),
68
+ line: `${CSI}2K`,
69
+ lineEnd: `${CSI}K`,
70
+ lineStart: `${CSI}1K`,
71
+ lines(count) {
72
+ let clear = "";
73
+ for (let i = 0; i < count; i++)
74
+ clear += this.line + (i < count - 1 ? cursor.up() : "");
75
+ if (count)
76
+ clear += cursor.left;
77
+ return clear;
78
+ }
79
+ };
80
+ module.exports = { cursor, scroll, erase, beep };
81
+ }
82
+ });
2
83
 
3
84
  // src/index.ts
4
85
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -6,7 +87,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
6
87
  // src/server.ts
7
88
  import { createRequire } from "module";
8
89
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9
- import { z as z2 } from "zod";
90
+ import { z as z3 } from "zod";
10
91
 
11
92
  // src/catalog.ts
12
93
  import matter from "gray-matter";
@@ -170,7 +251,7 @@ function listFiles(root, relDir, filterExt) {
170
251
  function sectionParagraph(md, title) {
171
252
  const lines = md.split(/\r?\n/);
172
253
  const re = new RegExp(`^##\\s+${title}\\s*$`, "i");
173
- const start = lines.findIndex((l) => re.test(l));
254
+ const start = lines.findIndex((l2) => re.test(l2));
174
255
  if (start < 0) return "";
175
256
  for (let i = start + 1; i < lines.length; i++) {
176
257
  if (/^##\s+/.test(lines[i])) break;
@@ -231,7 +312,7 @@ function listAgents(root) {
231
312
  }
232
313
  function getAgentPrompt(root, name) {
233
314
  const want = name.replace(/\.md$/, "");
234
- const info = listAgents(root).find((a) => a.name === want);
315
+ const info = listAgents(root).find((a2) => a2.name === want);
235
316
  if (!info) return null;
236
317
  const content = readText(root, info.path);
237
318
  if (content === null) return null;
@@ -269,7 +350,7 @@ function listSkills(root) {
269
350
  path: rel
270
351
  });
271
352
  }
272
- return out.sort((a, b) => a.id.localeCompare(b.id));
353
+ return out.sort((a2, b2) => a2.id.localeCompare(b2.id));
273
354
  }
274
355
  function getSkill(root, id) {
275
356
  const want = id.replace(/\.md$/, "");
@@ -352,6 +433,7 @@ var languageSchema = z.enum(["en", "es"], {
352
433
  message: `project.language must be one of: ${PROJECT_LANGUAGES.join(", ")}`
353
434
  })
354
435
  });
436
+ var multirepoRoleSchema = z.enum(["core", "module"]).optional();
355
437
  var configSchema = z.object({
356
438
  version: z.union([z.string(), z.number()]).optional(),
357
439
  project: z.object({
@@ -359,11 +441,20 @@ var configSchema = z.object({
359
441
  state: projectStateSchema.default(DEFAULTS.state),
360
442
  structure: structureSchema.default(DEFAULTS.structure),
361
443
  language: languageSchema.default(DEFAULTS.language),
444
+ role: multirepoRoleSchema,
362
445
  domains: z.array(z.string()).optional()
363
446
  }).passthrough().default({}),
364
447
  team: z.object({
365
448
  size: teamSizeSchema.default(DEFAULTS.teamSize)
366
449
  }).passthrough().default({}),
450
+ multirepo: z.object({
451
+ role: multirepoRoleSchema,
452
+ modules_file: z.string().optional(),
453
+ parent_system: z.string().optional()
454
+ }).passthrough().optional(),
455
+ module: z.object({
456
+ id: z.string().optional()
457
+ }).passthrough().optional(),
367
458
  knowledge: z.unknown().optional(),
368
459
  guard: z.unknown().optional(),
369
460
  scan: z.unknown().optional()
@@ -392,6 +483,12 @@ ${issues}`);
392
483
  }
393
484
  return parsed.data;
394
485
  }
486
+ function projectRole(config) {
487
+ return config.project.role ?? config.multirepo?.role;
488
+ }
489
+ function isModule(config) {
490
+ return projectRole(config) === "module";
491
+ }
395
492
 
396
493
  // ../cli/src/services/artifact-reader.ts
397
494
  import matter3 from "gray-matter";
@@ -466,8 +563,8 @@ function isActiveState(s) {
466
563
  }
467
564
  function lifecycleFolderOf(filePath) {
468
565
  const p = filePath.replace(/\\/g, "/");
469
- const m = p.match(/\/delivery\/work-items\/([^/]+)\//);
470
- if (m && isLifecycleState(m[1])) return m[1];
566
+ const m2 = p.match(/\/delivery\/work-items\/([^/]+)\//);
567
+ if (m2 && isLifecycleState(m2[1])) return m2[1];
471
568
  return null;
472
569
  }
473
570
  function lifecycleStateOf(item) {
@@ -497,8 +594,8 @@ function relativeTo(dir, filePath) {
497
594
  const full = toPosix2(filePath);
498
595
  return full.startsWith(base + "/") ? full.slice(base.length + 1) : full;
499
596
  }
500
- function isWorkItemArtifact(a) {
501
- return toPosix2(a.filePath).includes("/delivery/work-items/") && Boolean(a.type);
597
+ function isWorkItemArtifact(a2) {
598
+ return toPosix2(a2.filePath).includes("/delivery/work-items/") && Boolean(a2.type);
502
599
  }
503
600
  function classifyLayer(posixPath) {
504
601
  if (posixPath.includes("/knowledge/business/")) return "business";
@@ -509,29 +606,29 @@ function classifyLayer(posixPath) {
509
606
  if (posixPath.includes("/knowledge/delivery/")) return "delivery";
510
607
  return "unknown";
511
608
  }
512
- function enrich(dir, a) {
513
- const posix = toPosix2(a.filePath);
514
- const isWi = isWorkItemArtifact(a);
609
+ function enrich(dir, a2) {
610
+ const posix = toPosix2(a2.filePath);
611
+ const isWi = isWorkItemArtifact(a2);
515
612
  return {
516
- ...a,
517
- relPath: relativeTo(dir, a.filePath),
613
+ ...a2,
614
+ relPath: relativeTo(dir, a2.filePath),
518
615
  layer: classifyLayer(posix),
519
616
  isWorkItem: isWi,
520
- lifecycle: isWi ? lifecycleStateOf({ status: a.status, filePath: a.filePath }) : void 0
617
+ lifecycle: isWi ? lifecycleStateOf({ status: a2.status, filePath: a2.filePath }) : void 0
521
618
  };
522
619
  }
523
620
  function discoverKnowledge(dir) {
524
621
  const archDir = join(dir, ARCH_DIR);
525
622
  if (!exists(archDir)) return [];
526
- return readArtifacts(archDir).map((a) => enrich(dir, a));
623
+ return readArtifacts(archDir).map((a2) => enrich(dir, a2));
527
624
  }
528
625
  function discoverWorkItems(dir) {
529
- return discoverKnowledge(dir).filter((a) => a.isWorkItem);
626
+ return discoverKnowledge(dir).filter((a2) => a2.isWorkItem);
530
627
  }
531
628
 
532
629
  // ../cli/src/core/delivery-phase.ts
533
630
  function layer(layers, name) {
534
- return layers.find((l) => l.layer === name)?.status ?? "Missing";
631
+ return layers.find((l2) => l2.layer === name)?.status ?? "Missing";
535
632
  }
536
633
  var NOT_READY_LAYER = ["Missing", "Placeholder", "Weak"];
537
634
  function baseComplete(layers) {
@@ -554,9 +651,9 @@ function determinePhase(input) {
554
651
  if (active > 0) return "Active Delivery";
555
652
  return "Maintenance";
556
653
  }
557
- function ownershipPct(o) {
558
- if (o.workItemsTotal === 0) return 100;
559
- return Math.round(o.workItemsWithOwnership / o.workItemsTotal * 100);
654
+ function ownershipPct(o2) {
655
+ if (o2.workItemsTotal === 0) return 100;
656
+ return Math.round(o2.workItemsWithOwnership / o2.workItemsTotal * 100);
560
657
  }
561
658
  function buildReasons(input) {
562
659
  const reasons = [];
@@ -598,19 +695,19 @@ function assessPhase(input) {
598
695
  let llmInstructions = [];
599
696
  switch (phase) {
600
697
  case "Discovery": {
601
- const m = firstMissingLayerAgent(input.layers);
602
- recommendedAgents = [m.agent];
603
- nextStep = m.step;
604
- llmInstructions = [`Use the ${m.agent} to fill the missing base knowledge.`, "Do not write code."];
698
+ const m2 = firstMissingLayerAgent(input.layers);
699
+ recommendedAgents = [m2.agent];
700
+ nextStep = m2.step;
701
+ llmInstructions = [`Use the ${m2.agent} to fill the missing base knowledge.`, "Do not write code."];
605
702
  break;
606
703
  }
607
704
  case "Knowledge Refinement": {
608
- const m = firstUnrefinedLayerAgent(input.layers);
609
- recommendedAgents = [m.agent];
610
- nextStep = m.step;
705
+ const m2 = firstUnrefinedLayerAgent(input.layers);
706
+ recommendedAgents = [m2.agent];
707
+ nextStep = m2.step;
611
708
  llmInstructions = [
612
709
  "The baseline files exist but still look like bootstrap placeholders.",
613
- `Use the ${m.agent} to replace the placeholders with real, project-specific knowledge.`,
710
+ `Use the ${m2.agent} to replace the placeholders with real, project-specific knowledge.`,
614
711
  "Do not write code."
615
712
  ];
616
713
  break;
@@ -691,31 +788,1373 @@ function assessPhase(input) {
691
788
  return { phase, reasons, recommendedAgents, nextStep, llmInstructions };
692
789
  }
693
790
 
694
- // ../cli/src/core/capsule.ts
695
- import matter4 from "gray-matter";
696
- import { parse as parseYaml4, stringify as stringifyYaml } from "yaml";
791
+ // ../cli/src/core/capsule.ts
792
+ import matter4 from "gray-matter";
793
+ import { parse as parseYaml6, stringify as stringifyYaml2 } from "yaml";
794
+
795
+ // ../cli/src/services/owners.ts
796
+ import { parse as parseYaml3 } from "yaml";
797
+ var CONFIG_PATH = ".kaddo/config.yml";
798
+ function loadOwners(dir) {
799
+ const configPath = join(dir, CONFIG_PATH);
800
+ if (!exists(configPath)) return {};
801
+ try {
802
+ const config = parseYaml3(readFile(configPath));
803
+ const raw = config.owners ?? {};
804
+ const result = {};
805
+ for (const [domain, people] of Object.entries(raw)) {
806
+ result[domain] = Array.isArray(people) ? people.map(String) : [String(people)];
807
+ }
808
+ return result;
809
+ } catch {
810
+ return {};
811
+ }
812
+ }
813
+
814
+ // ../cli/src/services/mapped-modules.ts
815
+ import { parse as parseYaml4 } from "yaml";
816
+ var DESCRIPTOR_PATH = ".kaddo/modules.yml";
817
+ function toStringArray(value) {
818
+ return Array.isArray(value) ? value.map((v) => String(v)).filter(Boolean) : [];
819
+ }
820
+ function moduleArtifactCoverage(dir, id) {
821
+ const base = join(dir, "knowledge", "tech", "modules", id);
822
+ return {
823
+ moduleDesign: exists(join(base, "module-design.md")),
824
+ stack: exists(join(base, "stack.md")),
825
+ security: exists(join(base, "security.md")),
826
+ standards: exists(join(base, "standards.md")),
827
+ diagrams: exists(join(base, "diagrams")),
828
+ adrs: exists(join(base, "adrs"))
829
+ };
830
+ }
831
+ function loadMappedModules(dir) {
832
+ const path3 = join(dir, DESCRIPTOR_PATH);
833
+ if (!exists(path3)) return [];
834
+ let parsed;
835
+ try {
836
+ parsed = parseYaml4(readFile(path3));
837
+ } catch {
838
+ return [];
839
+ }
840
+ const raw = Array.isArray(parsed?.modules) ? parsed.modules : [];
841
+ const modules = [];
842
+ for (const entry of raw) {
843
+ if (!entry || typeof entry !== "object") continue;
844
+ const m2 = entry;
845
+ const id = typeof m2.id === "string" ? m2.id : "";
846
+ if (!id) continue;
847
+ modules.push({
848
+ id,
849
+ name: typeof m2.name === "string" ? m2.name : void 0,
850
+ repoPath: typeof m2.repoPath === "string" ? m2.repoPath : "",
851
+ type: typeof m2.type === "string" ? m2.type : void 0,
852
+ mainTechnology: typeof m2.mainTechnology === "string" ? m2.mainTechnology : void 0,
853
+ owner: typeof m2.owner === "string" ? m2.owner : void 0,
854
+ capabilities: toStringArray(m2.capabilities),
855
+ code: toStringArray(m2.code),
856
+ status: typeof m2.status === "string" ? m2.status : void 0,
857
+ artifacts: moduleArtifactCoverage(dir, id)
858
+ });
859
+ }
860
+ return modules;
861
+ }
862
+ function detectModuleStatus(coreDir, repoPath) {
863
+ const moduleDir = join(coreDir, repoPath);
864
+ const configPath = join(moduleDir, ".kaddo", "config.yml");
865
+ const hasConfig = exists(configPath);
866
+ if (!hasConfig) {
867
+ return {
868
+ status: "not_configured",
869
+ configured: false,
870
+ moduleContext: false,
871
+ currentState: false,
872
+ codebase: false,
873
+ warning: `Run \`kaddo init\` inside \`${repoPath}\` and select multirepo \u2192 module.`
874
+ };
875
+ }
876
+ let parsed = null;
877
+ try {
878
+ parsed = parseYaml4(readFile(configPath));
879
+ } catch {
880
+ }
881
+ const project = parsed?.project;
882
+ const multirepo = parsed?.multirepo;
883
+ const role = project?.role ?? multirepo?.role;
884
+ if (role !== "module") {
885
+ return {
886
+ status: "invalid",
887
+ configured: true,
888
+ role,
889
+ moduleContext: false,
890
+ currentState: false,
891
+ codebase: false,
892
+ warning: `Repository has Kaddo configured but project.role is not module.`
893
+ };
894
+ }
895
+ return {
896
+ status: "configured",
897
+ configured: true,
898
+ role: "module",
899
+ moduleContext: exists(join(moduleDir, "knowledge", "module", "module-context.md")),
900
+ currentState: exists(join(moduleDir, "knowledge", "tech", "current-state.md")),
901
+ codebase: exists(join(moduleDir, "knowledge", "tech", "codebase.md"))
902
+ };
903
+ }
904
+ function readModuleContext(coreDir, repoPath) {
905
+ const p = join(coreDir, repoPath, "knowledge", "module", "module-context.md");
906
+ if (!exists(p)) return null;
907
+ try {
908
+ return readFile(p);
909
+ } catch {
910
+ return null;
911
+ }
912
+ }
913
+ function presentArtifacts(coverage) {
914
+ const present = [];
915
+ if (coverage.moduleDesign) present.push("module-design");
916
+ if (coverage.stack) present.push("stack");
917
+ if (coverage.security) present.push("security");
918
+ if (coverage.standards) present.push("standards");
919
+ if (coverage.diagrams) present.push("diagrams");
920
+ if (coverage.adrs) present.push("adrs");
921
+ return present;
922
+ }
923
+
924
+ // ../../node_modules/.pnpm/@clack+core@0.3.5/node_modules/@clack/core/dist/index.mjs
925
+ var import_sisteransi = __toESM(require_src(), 1);
926
+ import { stdin as $, stdout as k } from "process";
927
+ import * as f from "readline";
928
+ import _ from "readline";
929
+ import { WriteStream as U } from "tty";
930
+ function q({ onlyFirst: e = false } = {}) {
931
+ const F = ["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))", "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|");
932
+ return new RegExp(F, e ? void 0 : "g");
933
+ }
934
+ var J = q();
935
+ function T(e) {
936
+ return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
937
+ }
938
+ var j = { exports: {} };
939
+ (function(e) {
940
+ var u = {};
941
+ e.exports = u, u.eastAsianWidth = function(t) {
942
+ var s = t.charCodeAt(0), C2 = t.length == 2 ? t.charCodeAt(1) : 0, D = s;
943
+ return 55296 <= s && s <= 56319 && 56320 <= C2 && C2 <= 57343 && (s &= 1023, C2 &= 1023, D = s << 10 | C2, D += 65536), D == 12288 || 65281 <= D && D <= 65376 || 65504 <= D && D <= 65510 ? "F" : D == 8361 || 65377 <= D && D <= 65470 || 65474 <= D && D <= 65479 || 65482 <= D && D <= 65487 || 65490 <= D && D <= 65495 || 65498 <= D && D <= 65500 || 65512 <= D && D <= 65518 ? "H" : 4352 <= D && D <= 4447 || 4515 <= D && D <= 4519 || 4602 <= D && D <= 4607 || 9001 <= D && D <= 9002 || 11904 <= D && D <= 11929 || 11931 <= D && D <= 12019 || 12032 <= D && D <= 12245 || 12272 <= D && D <= 12283 || 12289 <= D && D <= 12350 || 12353 <= D && D <= 12438 || 12441 <= D && D <= 12543 || 12549 <= D && D <= 12589 || 12593 <= D && D <= 12686 || 12688 <= D && D <= 12730 || 12736 <= D && D <= 12771 || 12784 <= D && D <= 12830 || 12832 <= D && D <= 12871 || 12880 <= D && D <= 13054 || 13056 <= D && D <= 19903 || 19968 <= D && D <= 42124 || 42128 <= D && D <= 42182 || 43360 <= D && D <= 43388 || 44032 <= D && D <= 55203 || 55216 <= D && D <= 55238 || 55243 <= D && D <= 55291 || 63744 <= D && D <= 64255 || 65040 <= D && D <= 65049 || 65072 <= D && D <= 65106 || 65108 <= D && D <= 65126 || 65128 <= D && D <= 65131 || 110592 <= D && D <= 110593 || 127488 <= D && D <= 127490 || 127504 <= D && D <= 127546 || 127552 <= D && D <= 127560 || 127568 <= D && D <= 127569 || 131072 <= D && D <= 194367 || 177984 <= D && D <= 196605 || 196608 <= D && D <= 262141 ? "W" : 32 <= D && D <= 126 || 162 <= D && D <= 163 || 165 <= D && D <= 166 || D == 172 || D == 175 || 10214 <= D && D <= 10221 || 10629 <= D && D <= 10630 ? "Na" : D == 161 || D == 164 || 167 <= D && D <= 168 || D == 170 || 173 <= D && D <= 174 || 176 <= D && D <= 180 || 182 <= D && D <= 186 || 188 <= D && D <= 191 || D == 198 || D == 208 || 215 <= D && D <= 216 || 222 <= D && D <= 225 || D == 230 || 232 <= D && D <= 234 || 236 <= D && D <= 237 || D == 240 || 242 <= D && D <= 243 || 247 <= D && D <= 250 || D == 252 || D == 254 || D == 257 || D == 273 || D == 275 || D == 283 || 294 <= D && D <= 295 || D == 299 || 305 <= D && D <= 307 || D == 312 || 319 <= D && D <= 322 || D == 324 || 328 <= D && D <= 331 || D == 333 || 338 <= D && D <= 339 || 358 <= D && D <= 359 || D == 363 || D == 462 || D == 464 || D == 466 || D == 468 || D == 470 || D == 472 || D == 474 || D == 476 || D == 593 || D == 609 || D == 708 || D == 711 || 713 <= D && D <= 715 || D == 717 || D == 720 || 728 <= D && D <= 731 || D == 733 || D == 735 || 768 <= D && D <= 879 || 913 <= D && D <= 929 || 931 <= D && D <= 937 || 945 <= D && D <= 961 || 963 <= D && D <= 969 || D == 1025 || 1040 <= D && D <= 1103 || D == 1105 || D == 8208 || 8211 <= D && D <= 8214 || 8216 <= D && D <= 8217 || 8220 <= D && D <= 8221 || 8224 <= D && D <= 8226 || 8228 <= D && D <= 8231 || D == 8240 || 8242 <= D && D <= 8243 || D == 8245 || D == 8251 || D == 8254 || D == 8308 || D == 8319 || 8321 <= D && D <= 8324 || D == 8364 || D == 8451 || D == 8453 || D == 8457 || D == 8467 || D == 8470 || 8481 <= D && D <= 8482 || D == 8486 || D == 8491 || 8531 <= D && D <= 8532 || 8539 <= D && D <= 8542 || 8544 <= D && D <= 8555 || 8560 <= D && D <= 8569 || D == 8585 || 8592 <= D && D <= 8601 || 8632 <= D && D <= 8633 || D == 8658 || D == 8660 || D == 8679 || D == 8704 || 8706 <= D && D <= 8707 || 8711 <= D && D <= 8712 || D == 8715 || D == 8719 || D == 8721 || D == 8725 || D == 8730 || 8733 <= D && D <= 8736 || D == 8739 || D == 8741 || 8743 <= D && D <= 8748 || D == 8750 || 8756 <= D && D <= 8759 || 8764 <= D && D <= 8765 || D == 8776 || D == 8780 || D == 8786 || 8800 <= D && D <= 8801 || 8804 <= D && D <= 8807 || 8810 <= D && D <= 8811 || 8814 <= D && D <= 8815 || 8834 <= D && D <= 8835 || 8838 <= D && D <= 8839 || D == 8853 || D == 8857 || D == 8869 || D == 8895 || D == 8978 || 9312 <= D && D <= 9449 || 9451 <= D && D <= 9547 || 9552 <= D && D <= 9587 || 9600 <= D && D <= 9615 || 9618 <= D && D <= 9621 || 9632 <= D && D <= 9633 || 9635 <= D && D <= 9641 || 9650 <= D && D <= 9651 || 9654 <= D && D <= 9655 || 9660 <= D && D <= 9661 || 9664 <= D && D <= 9665 || 9670 <= D && D <= 9672 || D == 9675 || 9678 <= D && D <= 9681 || 9698 <= D && D <= 9701 || D == 9711 || 9733 <= D && D <= 9734 || D == 9737 || 9742 <= D && D <= 9743 || 9748 <= D && D <= 9749 || D == 9756 || D == 9758 || D == 9792 || D == 9794 || 9824 <= D && D <= 9825 || 9827 <= D && D <= 9829 || 9831 <= D && D <= 9834 || 9836 <= D && D <= 9837 || D == 9839 || 9886 <= D && D <= 9887 || 9918 <= D && D <= 9919 || 9924 <= D && D <= 9933 || 9935 <= D && D <= 9953 || D == 9955 || 9960 <= D && D <= 9983 || D == 10045 || D == 10071 || 10102 <= D && D <= 10111 || 11093 <= D && D <= 11097 || 12872 <= D && D <= 12879 || 57344 <= D && D <= 63743 || 65024 <= D && D <= 65039 || D == 65533 || 127232 <= D && D <= 127242 || 127248 <= D && D <= 127277 || 127280 <= D && D <= 127337 || 127344 <= D && D <= 127386 || 917760 <= D && D <= 917999 || 983040 <= D && D <= 1048573 || 1048576 <= D && D <= 1114109 ? "A" : "N";
944
+ }, u.characterLength = function(t) {
945
+ var s = this.eastAsianWidth(t);
946
+ return s == "F" || s == "W" || s == "A" ? 2 : 1;
947
+ };
948
+ function F(t) {
949
+ return t.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g) || [];
950
+ }
951
+ u.length = function(t) {
952
+ for (var s = F(t), C2 = 0, D = 0; D < s.length; D++) C2 = C2 + this.characterLength(s[D]);
953
+ return C2;
954
+ }, u.slice = function(t, s, C2) {
955
+ textLen = u.length(t), s = s || 0, C2 = C2 || 1, s < 0 && (s = textLen + s), C2 < 0 && (C2 = textLen + C2);
956
+ for (var D = "", i = 0, n = F(t), E2 = 0; E2 < n.length; E2++) {
957
+ var h2 = n[E2], o2 = u.length(h2);
958
+ if (i >= s - (o2 == 2 ? 1 : 0)) if (i + o2 <= C2) D += h2;
959
+ else break;
960
+ i += o2;
961
+ }
962
+ return D;
963
+ };
964
+ })(j);
965
+ var Q = j.exports;
966
+ var X = T(Q);
967
+ var DD = function() {
968
+ return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|(?:\uD83E\uDDD1\uD83C\uDFFF\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFC-\uDFFF])|\uD83D\uDC68(?:\uD83C\uDFFB(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D[\uDC66\uDC67])|\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC)?|(?:\uD83D\uDC69(?:\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC69(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83E\uDDD1(?:\u200D(?:\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F\u200D\u26A7|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\uD83C\uDFF4\u200D\u2620|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u2600-\u2604\u260E\u2611\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26B0\u26B1\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0\u26F1\u26F4\u26F7\u26F8\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u3030\u303D\u3297\u3299]|\uD83C[\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3])\uFE0F|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDE35\u200D\uD83D\uDCAB|\uD83D\uDE2E\u200D\uD83D\uDCA8|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83E\uDDD1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC69(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83D\uDC08\u200D\u2B1B|\u2764\uFE0F\u200D(?:\uD83D\uDD25|\uD83E\uDE79)|\uD83D\uDC41\uFE0F|\uD83C\uDFF3\uFE0F|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|[#\*0-9]\uFE0F\u20E3|\u2764\uFE0F|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|\uD83C\uDFF4|(?:[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270C\u270D]|\uD83D[\uDD74\uDD90])(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC08\uDC15\uDC3B\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE2E\uDE35\uDE36\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5]|\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD]|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0D\uDD0E\uDD10-\uDD17\uDD1D\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78\uDD7A-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCB\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6]|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26A7\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5-\uDED7\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDD77\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g;
969
+ };
970
+ var uD = T(DD);
971
+ var d = 10;
972
+ var M = (e = 0) => (u) => `\x1B[${u + e}m`;
973
+ var P = (e = 0) => (u) => `\x1B[${38 + e};5;${u}m`;
974
+ var W = (e = 0) => (u, F, t) => `\x1B[${38 + e};2;${u};${F};${t}m`;
975
+ var r = { modifier: { reset: [0, 0], bold: [1, 22], dim: [2, 22], italic: [3, 23], underline: [4, 24], overline: [53, 55], inverse: [7, 27], hidden: [8, 28], strikethrough: [9, 29] }, color: { black: [30, 39], red: [31, 39], green: [32, 39], yellow: [33, 39], blue: [34, 39], magenta: [35, 39], cyan: [36, 39], white: [37, 39], blackBright: [90, 39], gray: [90, 39], grey: [90, 39], redBright: [91, 39], greenBright: [92, 39], yellowBright: [93, 39], blueBright: [94, 39], magentaBright: [95, 39], cyanBright: [96, 39], whiteBright: [97, 39] }, bgColor: { bgBlack: [40, 49], bgRed: [41, 49], bgGreen: [42, 49], bgYellow: [43, 49], bgBlue: [44, 49], bgMagenta: [45, 49], bgCyan: [46, 49], bgWhite: [47, 49], bgBlackBright: [100, 49], bgGray: [100, 49], bgGrey: [100, 49], bgRedBright: [101, 49], bgGreenBright: [102, 49], bgYellowBright: [103, 49], bgBlueBright: [104, 49], bgMagentaBright: [105, 49], bgCyanBright: [106, 49], bgWhiteBright: [107, 49] } };
976
+ Object.keys(r.modifier);
977
+ var FD = Object.keys(r.color);
978
+ var eD = Object.keys(r.bgColor);
979
+ [...FD, ...eD];
980
+ function tD() {
981
+ const e = /* @__PURE__ */ new Map();
982
+ for (const [u, F] of Object.entries(r)) {
983
+ for (const [t, s] of Object.entries(F)) r[t] = { open: `\x1B[${s[0]}m`, close: `\x1B[${s[1]}m` }, F[t] = r[t], e.set(s[0], s[1]);
984
+ Object.defineProperty(r, u, { value: F, enumerable: false });
985
+ }
986
+ return Object.defineProperty(r, "codes", { value: e, enumerable: false }), r.color.close = "\x1B[39m", r.bgColor.close = "\x1B[49m", r.color.ansi = M(), r.color.ansi256 = P(), r.color.ansi16m = W(), r.bgColor.ansi = M(d), r.bgColor.ansi256 = P(d), r.bgColor.ansi16m = W(d), Object.defineProperties(r, { rgbToAnsi256: { value: (u, F, t) => u === F && F === t ? u < 8 ? 16 : u > 248 ? 231 : Math.round((u - 8) / 247 * 24) + 232 : 16 + 36 * Math.round(u / 255 * 5) + 6 * Math.round(F / 255 * 5) + Math.round(t / 255 * 5), enumerable: false }, hexToRgb: { value: (u) => {
987
+ const F = /[a-f\d]{6}|[a-f\d]{3}/i.exec(u.toString(16));
988
+ if (!F) return [0, 0, 0];
989
+ let [t] = F;
990
+ t.length === 3 && (t = [...t].map((C2) => C2 + C2).join(""));
991
+ const s = Number.parseInt(t, 16);
992
+ return [s >> 16 & 255, s >> 8 & 255, s & 255];
993
+ }, enumerable: false }, hexToAnsi256: { value: (u) => r.rgbToAnsi256(...r.hexToRgb(u)), enumerable: false }, ansi256ToAnsi: { value: (u) => {
994
+ if (u < 8) return 30 + u;
995
+ if (u < 16) return 90 + (u - 8);
996
+ let F, t, s;
997
+ if (u >= 232) F = ((u - 232) * 10 + 8) / 255, t = F, s = F;
998
+ else {
999
+ u -= 16;
1000
+ const i = u % 36;
1001
+ F = Math.floor(u / 36) / 5, t = Math.floor(i / 6) / 5, s = i % 6 / 5;
1002
+ }
1003
+ const C2 = Math.max(F, t, s) * 2;
1004
+ if (C2 === 0) return 30;
1005
+ let D = 30 + (Math.round(s) << 2 | Math.round(t) << 1 | Math.round(F));
1006
+ return C2 === 2 && (D += 60), D;
1007
+ }, enumerable: false }, rgbToAnsi: { value: (u, F, t) => r.ansi256ToAnsi(r.rgbToAnsi256(u, F, t)), enumerable: false }, hexToAnsi: { value: (u) => r.ansi256ToAnsi(r.hexToAnsi256(u)), enumerable: false } }), r;
1008
+ }
1009
+ var sD = tD();
1010
+ var iD = "]";
1011
+ var w = `${iD}8;;`;
1012
+ var WD = globalThis.process.platform.startsWith("win");
1013
+
1014
+ // ../../node_modules/.pnpm/@clack+prompts@0.7.0/node_modules/@clack/prompts/dist/index.mjs
1015
+ import h from "process";
1016
+ var import_sisteransi2 = __toESM(require_src(), 1);
1017
+ function q2() {
1018
+ return h.platform !== "win32" ? h.env.TERM !== "linux" : Boolean(h.env.CI) || Boolean(h.env.WT_SESSION) || Boolean(h.env.TERMINUS_SUBLIME) || h.env.ConEmuTask === "{cmd::Cmder}" || h.env.TERM_PROGRAM === "Terminus-Sublime" || h.env.TERM_PROGRAM === "vscode" || h.env.TERM === "xterm-256color" || h.env.TERM === "alacritty" || h.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
1019
+ }
1020
+ var _2 = q2();
1021
+ var o = (r2, n) => _2 ? r2 : n;
1022
+ var H = o("\u25C6", "*");
1023
+ var I = o("\u25A0", "x");
1024
+ var x = o("\u25B2", "x");
1025
+ var S = o("\u25C7", "o");
1026
+ var K = o("\u250C", "T");
1027
+ var a = o("\u2502", "|");
1028
+ var d2 = o("\u2514", "\u2014");
1029
+ var b = o("\u25CF", ">");
1030
+ var E = o("\u25CB", " ");
1031
+ var C = o("\u25FB", "[\u2022]");
1032
+ var w2 = o("\u25FC", "[+]");
1033
+ var M2 = o("\u25FB", "[ ]");
1034
+ var U2 = o("\u25AA", "\u2022");
1035
+ var B = o("\u2500", "-");
1036
+ var Z = o("\u256E", "+");
1037
+ var z2 = o("\u251C", "+");
1038
+ var X2 = o("\u256F", "+");
1039
+ var J2 = o("\u25CF", "\u2022");
1040
+ var Y = o("\u25C6", "*");
1041
+ var Q2 = o("\u25B2", "!");
1042
+ var ee = o("\u25A0", "x");
1043
+
1044
+ // ../cli/src/commands/modules-map.ts
1045
+ import { parse as parseYaml5, stringify as stringifyYaml } from "yaml";
1046
+
1047
+ // ../cli/src/templates/registry.ts
1048
+ var QUALITY = "## Quality checklist";
1049
+ var WORK_ITEM = `---
1050
+ type: feature
1051
+ id: WI-001
1052
+ title: "Short, action-oriented title"
1053
+ status: draft
1054
+ knowledge_level: K2
1055
+ source: manual
1056
+ source_id:
1057
+ phase: now
1058
+ initiative:
1059
+ domains: []
1060
+ capabilities: []
1061
+ code: []
1062
+ created_at: YYYY-MM-DD
1063
+ ---
1064
+
1065
+ # <Title>
1066
+
1067
+ > Type: feature \xB7 Level: K2
1068
+
1069
+ ## Problem
1070
+
1071
+ _What problem or opportunity does this address?_
1072
+
1073
+ ## Expected result
1074
+
1075
+ _What should be true once this is done?_
1076
+
1077
+ ## Acceptance criteria
1078
+
1079
+ - [ ] ...
1080
+
1081
+ ## Design
1082
+
1083
+ _Optional. Key decisions or approach. Keep it minimal at low knowledge levels._
1084
+
1085
+ ## Risks
1086
+
1087
+ _Optional. What could go wrong?_
1088
+
1089
+ ## Out of scope
1090
+
1091
+ _What is intentionally not included in this Work Item?_
1092
+
1093
+ ## Validation
1094
+
1095
+ _How will this be validated?_
1096
+
1097
+ ## Definition of Done
1098
+
1099
+ - [ ] Code merged
1100
+ - [ ] Knowledge updated or intentionally unchanged
1101
+
1102
+ ## Learning
1103
+
1104
+ _What did we learn? Fill in after completion (\`kaddo learn\`)._
1105
+
1106
+ ${QUALITY}
1107
+
1108
+ - [ ] Title is specific and action-oriented.
1109
+ - [ ] \`code:\` globs declared so Guard can relate changes.
1110
+ - [ ] Knowledge level matches the real uncertainty.
1111
+ `;
1112
+ var ROADMAP = `---
1113
+ type: roadmap
1114
+ updated_at: YYYY-MM-DD
1115
+ ---
1116
+
1117
+ # <Project> \u2014 Roadmap
1118
+
1119
+ > Candidates for human review \u2014 not commitments. Generated with the roadmap-agent.
1120
+
1121
+ ## Initiatives
1122
+
1123
+ ### RM-001 \u2014 <Initiative title>
1124
+
1125
+ **Goal:** ...
1126
+ **Related capabilities:** ...
1127
+ **Impact:** ...
1128
+ **Risk:** ...
1129
+ **Suggested Knowledge Level:** K1 / K2 / K3 / K4
1130
+ **Dependencies:** ...
1131
+ **Why now:** ...
1132
+
1133
+ #### Candidate Work Items
1134
+
1135
+ - **WI-CANDIDATE-001** \u2014 <title> \xB7 type: feature \xB7 level: K2 \xB7 value: ... \xB7 notes: ...
1136
+
1137
+ ## Assumptions
1138
+
1139
+ - ...
1140
+
1141
+ **Open questions:**
1142
+
1143
+ - ...
1144
+
1145
+ ## Suggested execution order
1146
+
1147
+ 1. ...
1148
+
1149
+ ## Not now
1150
+
1151
+ - ...
1152
+
1153
+ ${QUALITY}
1154
+
1155
+ - [ ] Each initiative has a goal, impact and risk.
1156
+ - [ ] Candidates are marked as candidates, not decisions.
1157
+ - [ ] Priorities reflect the project state (new / pre-ai / legacy).
1158
+ `;
1159
+ var CAPABILITIES = `---
1160
+ type: capabilities
1161
+ updated_at: YYYY-MM-DD
1162
+ ---
1163
+
1164
+ # <Project> \u2014 Capabilities
1165
+
1166
+ > What the system can do, from the product's point of view. Refine with capability-agent.
1167
+
1168
+ ## CAP-001 \u2014 <Capability name>
1169
+
1170
+ **Description:** ...
1171
+ **Status:** existing / proposed
1172
+ **Related domains:** ...
1173
+ **Evidence:** _where in code/docs this is observed_
1174
+
1175
+ ## Assumptions
1176
+
1177
+ - ...
1178
+
1179
+ ## Open questions
1180
+
1181
+ - ...
1182
+
1183
+ ${QUALITY}
1184
+
1185
+ - [ ] Capabilities describe outcomes, not implementation.
1186
+ - [ ] Each capability cites evidence or is flagged as an assumption.
1187
+ `;
1188
+ var KNOWLEDGE = `---
1189
+ type: current-state
1190
+ updated_at: YYYY-MM-DD
1191
+ ---
1192
+
1193
+ # <Project> \u2014 Knowledge
1194
+
1195
+ > What is true about this product right now.
1196
+
1197
+ ## Purpose
1198
+
1199
+ _What this product does and who it serves._
1200
+
1201
+ ## Architecture overview
1202
+
1203
+ _High-level description of the main components._
1204
+
1205
+ ## Key domains
1206
+
1207
+ _Main domains or bounded contexts._
1208
+
1209
+ ## Active constraints
1210
+
1211
+ _Technical, regulatory or operational constraints that shape decisions._
1212
+
1213
+ ${QUALITY}
1214
+
1215
+ - [ ] Reflects the current reality, not aspirations.
1216
+ - [ ] Constraints are explicit.
1217
+ `;
1218
+ var CURRENT_STATE = `---
1219
+ type: current-state
1220
+ updated_at: YYYY-MM-DD
1221
+ ---
1222
+
1223
+ # <Project> \u2014 Current State (Architecture Baseline)
1224
+
1225
+ > Reconstructed baseline. Refine with architecture-agent using \`.kaddo/context-pack.md\`.
1226
+
1227
+ ## Components
1228
+
1229
+ _Main services / packages / modules and their responsibilities._
1230
+
1231
+ ## Data & integrations
1232
+
1233
+ _Datastores, queues, external APIs._
1234
+
1235
+ ## Cross-cutting concerns
1236
+
1237
+ _Auth, logging, config, error handling._
1238
+
1239
+ ## Known gaps
1240
+
1241
+ _What is unclear or undocumented._
1242
+
1243
+ ## Assumptions
1244
+
1245
+ - ...
1246
+
1247
+ ${QUALITY}
1248
+
1249
+ - [ ] Components map to real code areas.
1250
+ - [ ] Gaps and assumptions are explicit, not hidden.
1251
+ `;
1252
+ var ARCHITECTURE_NOTES = `---
1253
+ type: architecture-notes
1254
+ updated_at: YYYY-MM-DD
1255
+ ---
1256
+
1257
+ # Architecture Notes
1258
+
1259
+ > Working notes on architecture topics that are not yet ADRs.
1260
+
1261
+ ## Topic
1262
+
1263
+ _What is being explored._
1264
+
1265
+ ## Context
1266
+
1267
+ _Why it matters now._
1268
+
1269
+ ## Options
1270
+
1271
+ - Option A \u2014 ...
1272
+ - Option B \u2014 ...
1273
+
1274
+ ## Leaning towards
1275
+
1276
+ _Current inclination and why (not a decision yet)._
1277
+
1278
+ ## Open questions
1279
+
1280
+ - ...
1281
+
1282
+ ${QUALITY}
1283
+
1284
+ - [ ] Notes are clearly non-binding (not a decision).
1285
+ - [ ] Options capture real trade-offs.
1286
+ `;
1287
+ var DECISION_CANDIDATES = `---
1288
+ type: decision-candidates
1289
+ updated_at: YYYY-MM-DD
1290
+ ---
1291
+
1292
+ # Decision Candidates
1293
+
1294
+ > Candidate architecture decisions for human review. Refine with adr-agent.
1295
+ > Promote accepted candidates into individual ADRs.
1296
+
1297
+ ## DC-001 \u2014 <Decision title>
1298
+
1299
+ **Context:** ...
1300
+ **Options considered:** ...
1301
+ **Recommended option:** ...
1302
+ **Trade-offs:** ...
1303
+ **Status:** candidate
1304
+
1305
+ ${QUALITY}
1306
+
1307
+ - [ ] Each candidate states context and trade-offs.
1308
+ - [ ] Candidates are not presented as final decisions.
1309
+ `;
1310
+ var ADR = `---
1311
+ type: adr
1312
+ id: ADR-0001
1313
+ status: proposed
1314
+ date: YYYY-MM-DD
1315
+ domains: []
1316
+ capabilities: []
1317
+ code: []
1318
+ ---
1319
+
1320
+ # ADR-0001 \u2014 <Decision title>
1321
+
1322
+ ## Status
1323
+
1324
+ proposed | accepted | superseded
1325
+
1326
+ ## Context
1327
+
1328
+ _The forces and constraints that lead to this decision._
1329
+
1330
+ ## Decision
1331
+
1332
+ _The decision, stated clearly and in the present tense._
1333
+
1334
+ ## Consequences
1335
+
1336
+ _Positive and negative results of the decision._
1337
+
1338
+ ## Alternatives considered
1339
+
1340
+ - ...
1341
+
1342
+ ${QUALITY}
1343
+
1344
+ - [ ] The decision is unambiguous.
1345
+ - [ ] Consequences include the downsides, not only benefits.
1346
+ - [ ] Superseding ADRs are linked when status changes.
1347
+ `;
1348
+ var MODULE_DESIGN = `---
1349
+ type: module-design
1350
+ module: module-name
1351
+ status: draft
1352
+ owner: unknown
1353
+ repoPath: ../module-repo
1354
+ capabilities: []
1355
+ code: []
1356
+ ---
1357
+
1358
+ # <Module> \u2014 Design
1359
+
1360
+ > Refine with module-design-agent using \`.kaddo/context-pack.md\`.
1361
+
1362
+ **Type:** frontend / backend / worker / mobile / library / infrastructure / data
1363
+ **Repository:** ../module-repo
1364
+ **Main technology:** ...
1365
+ **Owner:** ...
1366
+
1367
+ ## Purpose
1368
+
1369
+ ## Boundaries
1370
+
1371
+ ## Inputs / Outputs
1372
+
1373
+ ## Dependencies
1374
+
1375
+ ## Related capabilities
1376
+
1377
+ - ...
1378
+
1379
+ ## Risks & open questions
1380
+
1381
+ ${QUALITY}
1382
+
1383
+ - [ ] Boundaries make clear what is in and out of the module.
1384
+ - [ ] Dependencies on other modules are listed.
1385
+ `;
1386
+ var MODULE_STACK = `# <Module> \u2014 Stack
1387
+
1388
+ > Refine with stack-agent.
1389
+
1390
+ **Main technology:** ...
1391
+
1392
+ ## Languages
1393
+
1394
+ ## Frameworks
1395
+
1396
+ ## Data
1397
+
1398
+ ## Infrastructure
1399
+
1400
+ ## Unknowns / needs confirmation
1401
+
1402
+ ${QUALITY}
1403
+
1404
+ - [ ] Reflects the module's actual stack, not the whole system.
1405
+ - [ ] Unknowns are listed rather than guessed.
1406
+ `;
1407
+ var MODULE_SECURITY = `# <Module> \u2014 Security Considerations
1408
+
1409
+ > Refine with security-agent. Kaddo does **not** perform security scanning.
1410
+
1411
+ ## Authentication & authorization
1412
+
1413
+ ## Data sensitivity
1414
+
1415
+ ## Secrets handling
1416
+
1417
+ ## Open questions
1418
+
1419
+ ${QUALITY}
1420
+
1421
+ - [ ] Documents concerns for humans \u2014 does not claim to audit code.
1422
+ - [ ] Data sensitivity is classified.
1423
+ `;
1424
+ var MODULE_STANDARDS = `# <Module> \u2014 Standards
1425
+
1426
+ > Refine with standards-agent. Keep it lightweight.
1427
+
1428
+ ## Coding standards
1429
+
1430
+ ## Testing expectations
1431
+
1432
+ ## PR checklist
1433
+
1434
+ ${QUALITY}
1435
+
1436
+ - [ ] A handful of high-value rules, not a long policy.
1437
+ - [ ] Standards are specific to this module where it differs from the system.
1438
+ `;
1439
+ var MODULE_ADR = `---
1440
+ type: adr
1441
+ id: ADR-0001
1442
+ module: module-name
1443
+ status: proposed
1444
+ date: YYYY-MM-DD
1445
+ code: []
1446
+ ---
1447
+
1448
+ # ADR-0001 \u2014 <Module decision title>
1449
+
1450
+ ## Status
1451
+
1452
+ proposed | accepted | superseded
1453
+
1454
+ ## Context
1455
+
1456
+ _Module-scoped forces and constraints._
1457
+
1458
+ ## Decision
1459
+
1460
+ ## Consequences
1461
+
1462
+ ## Alternatives considered
1463
+
1464
+ - ...
1465
+
1466
+ ${QUALITY}
1467
+
1468
+ - [ ] Scoped to this module; system-wide decisions go in the architecture repo.
1469
+ - [ ] Consequences include downsides.
1470
+ `;
1471
+ var SECURITY = `# Security Considerations
1472
+
1473
+ > Global. Install with \`kaddo add security\`. Refine with security-agent.
1474
+ > Kaddo does **not** perform security or vulnerability scanning.
1475
+
1476
+ ## Authentication & authorization
1477
+
1478
+ ## Data sensitivity
1479
+
1480
+ ## Secrets handling
1481
+
1482
+ ## Dependency risks
1483
+
1484
+ ## Deployment risks
1485
+
1486
+ ## Open questions
1487
+
1488
+ ${QUALITY}
1489
+
1490
+ - [ ] Documents concerns for humans and agents \u2014 it does not audit code.
1491
+ - [ ] Secrets handling describes where secrets live and how they rotate.
1492
+ `;
1493
+ var STANDARDS = `# Standards
1494
+
1495
+ > Global. Install with \`kaddo add standards\`. Refine with standards-agent.
1496
+ > Keep it lightweight \u2014 a handful of high-value rules beats a long policy.
1497
+
1498
+ ## Coding standards
1499
+
1500
+ ## Documentation standards
1501
+
1502
+ ## Testing expectations
1503
+
1504
+ ## PR checklist
1505
+
1506
+ - [ ] Linked to the right Work Item.
1507
+ - [ ] Knowledge updated or intentionally left unchanged.
1508
+
1509
+ ${QUALITY}
1510
+
1511
+ - [ ] Rules are high-value and enforceable.
1512
+ - [ ] No documentation theater.
1513
+ `;
1514
+ var STACK = `# Stack
1515
+
1516
+ > Global. Install with \`kaddo add stack\`. Refine with stack-agent.
1517
+
1518
+ ## Languages
1519
+
1520
+ ## Frameworks
1521
+
1522
+ ## Data
1523
+
1524
+ ## Infrastructure
1525
+
1526
+ ## Tooling
1527
+
1528
+ ## Unknowns / needs confirmation
1529
+
1530
+ ${QUALITY}
1531
+
1532
+ - [ ] Reflects the detected stack.
1533
+ - [ ] Unknowns are listed, not invented.
1534
+ `;
1535
+ var GIT_STRATEGY = `# Git Strategy
1536
+
1537
+ > Global. Install with \`kaddo add git-strategy\`. Refine with git-strategy-agent.
1538
+ > Kaddo recommends a default and does **not** enforce it in CI.
1539
+
1540
+ ## Default strategy
1541
+
1542
+ GitHub Flow + Conventional Commits + SemVer.
1543
+
1544
+ ## Branch naming
1545
+
1546
+ \`\`\`txt
1547
+ feature/<work-item-id>-<slug>
1548
+ bugfix/<work-item-id>-<slug>
1549
+ hotfix/<work-item-id>-<slug>
1550
+ \`\`\`
1551
+
1552
+ ## Commit convention
1553
+
1554
+ \`\`\`txt
1555
+ feat(scope): message
1556
+ fix(scope): message
1557
+ docs(scope): message
1558
+ \`\`\`
1559
+
1560
+ ## Tag strategy
1561
+
1562
+ \`\`\`txt
1563
+ vMAJOR.MINOR.PATCH
1564
+ \`\`\`
1565
+
1566
+ ## Customization
1567
+
1568
+ Edit \`.kaddo/git.yml\` to switch strategy: \`github-flow\`, \`gitflow\`,
1569
+ \`trunk-based\` or \`custom\`.
1570
+
1571
+ ${QUALITY}
1572
+
1573
+ - [ ] The chosen strategy matches how the team actually works.
1574
+ - [ ] Branch and commit conventions reference Work Items.
1575
+ `;
1576
+ var INCIDENT = `---
1577
+ type: incident
1578
+ id: INC-001
1579
+ status: open
1580
+ severity: SEV3
1581
+ date: YYYY-MM-DD
1582
+ code: []
1583
+ ---
1584
+
1585
+ # INC-001 \u2014 <Incident title>
1586
+
1587
+ ## Summary
1588
+
1589
+ _What happened, in one or two sentences._
1590
+
1591
+ ## Impact
1592
+
1593
+ _Who/what was affected and for how long._
1594
+
1595
+ ## Timeline
1596
+
1597
+ - HH:MM \u2014 ...
1598
+
1599
+ ## Root cause
1600
+
1601
+ _What actually caused it._
1602
+
1603
+ ## Resolution
1604
+
1605
+ _How it was mitigated and fixed._
1606
+
1607
+ ## Follow-up actions
1608
+
1609
+ - [ ] ...
1610
+
1611
+ ${QUALITY}
1612
+
1613
+ - [ ] Root cause is the real cause, not the trigger.
1614
+ - [ ] Follow-up actions are concrete and owned.
1615
+ `;
1616
+ var RUNBOOK = `---
1617
+ type: runbook
1618
+ title: "<Operation> runbook"
1619
+ updated_at: YYYY-MM-DD
1620
+ ---
1621
+
1622
+ # <Operation> \u2014 Runbook
1623
+
1624
+ > How to perform a recurring operational task safely.
1625
+
1626
+ ## When to use
1627
+
1628
+ _The situation that triggers this runbook._
1629
+
1630
+ ## Prerequisites
1631
+
1632
+ - ...
1633
+
1634
+ ## Steps
1635
+
1636
+ 1. ...
1637
+
1638
+ ## Verification
1639
+
1640
+ _How to confirm success._
1641
+
1642
+ ## Rollback
1643
+
1644
+ _How to undo if something goes wrong._
1645
+
1646
+ ${QUALITY}
1647
+
1648
+ - [ ] Steps are reproducible by someone who is not the author.
1649
+ - [ ] Rollback is defined.
1650
+ `;
1651
+ var LEGACY_RISKS = `---
1652
+ type: legacy-risks
1653
+ updated_at: YYYY-MM-DD
1654
+ ---
1655
+
1656
+ # Legacy Risks
1657
+
1658
+ > High-risk areas to know before changing legacy code. Refine with legacy-agent.
1659
+
1660
+ ## RISK-001 \u2014 <Area>
1661
+
1662
+ **What:** ...
1663
+ **Why risky:** ...
1664
+ **Blast radius:** ...
1665
+ **Mitigation:** ...
1666
+
1667
+ ${QUALITY}
1668
+
1669
+ - [ ] Risks are specific to code areas, not vague.
1670
+ - [ ] Blast radius is estimated.
1671
+ `;
1672
+ var LEGACY_UNKNOWNS = `---
1673
+ type: legacy-unknowns
1674
+ updated_at: YYYY-MM-DD
1675
+ ---
1676
+
1677
+ # Legacy Unknowns
1678
+
1679
+ > What we do not yet understand about the legacy system. Refine with legacy-agent.
1680
+
1681
+ ## UNK-001 \u2014 <Question>
1682
+
1683
+ **Question:** ...
1684
+ **Why it matters:** ...
1685
+ **How to find out:** ...
1686
+
1687
+ ${QUALITY}
1688
+
1689
+ - [ ] Each unknown has a way to resolve it.
1690
+ - [ ] Unknowns are not silently turned into assumptions.
1691
+ `;
1692
+ var MODERNIZATION_CANDIDATES = `---
1693
+ type: modernization-candidates
1694
+ updated_at: YYYY-MM-DD
1695
+ ---
1696
+
1697
+ # Modernization Candidates
1698
+
1699
+ > Candidate modernization efforts for human review. Not commitments.
1700
+
1701
+ ## MOD-001 \u2014 <Candidate>
1702
+
1703
+ **Current state:** ...
1704
+ **Target state:** ...
1705
+ **Value:** ...
1706
+ **Risk:** ...
1707
+ **Suggested Knowledge Level:** K1 / K2 / K3 / K4
1708
+
1709
+ ${QUALITY}
1710
+
1711
+ - [ ] Candidates state value and risk.
1712
+ - [ ] Marked as candidates, not decisions.
1713
+ `;
1714
+ var BUSINESS_PRODUCT_BRIEF = `---
1715
+ type: product-brief
1716
+ status: draft
1717
+ ---
1718
+
1719
+ # Product Brief
1720
+
1721
+ > Created by \`kaddo bootstrap\`. Refine with the business-agent. Mark unknowns as TBD.
1722
+
1723
+ ## What is this product?
1724
+
1725
+ TBD
1726
+
1727
+ ## Problem it solves
1728
+
1729
+ TBD
1730
+
1731
+ ## Target users
1732
+
1733
+ TBD
1734
+
1735
+ ## Value proposition
1736
+
1737
+ TBD
1738
+
1739
+ ## Out of scope (for the MVP)
1740
+
1741
+ - TBD
1742
+
1743
+ ## Assumptions
1744
+
1745
+ - ...
1746
+
1747
+ ## Open questions
1748
+
1749
+ - ...
1750
+
1751
+ ${QUALITY}
1752
+
1753
+ - [ ] The product can be described in one paragraph.
1754
+ - [ ] The MVP boundary is explicit.
1755
+ `;
1756
+ var BUSINESS_PROBLEM = `---
1757
+ type: problem
1758
+ status: draft
1759
+ ---
1760
+
1761
+ # Problem Statement
1762
+
1763
+ > Refine with the business-agent. Do not invent facts.
1764
+
1765
+ ## Problem
1766
+
1767
+ TBD
1768
+
1769
+ ## Who has it
1770
+
1771
+ TBD
1772
+
1773
+ ## Why it matters now
1774
+
1775
+ TBD
1776
+
1777
+ ## Current alternatives
1778
+
1779
+ - TBD
1780
+
1781
+ ## Assumptions
1782
+
1783
+ - ...
1784
+
1785
+ ## Open questions
1786
+
1787
+ - ...
1788
+
1789
+ ${QUALITY}
1790
+
1791
+ - [ ] The problem is stated without assuming the solution.
1792
+ - [ ] The affected users are named.
1793
+ `;
1794
+ var BUSINESS_USERS = `---
1795
+ type: users
1796
+ status: draft
1797
+ ---
1798
+
1799
+ # Users & Personas
1800
+
1801
+ > Refine with the business-agent.
1802
+
1803
+ ## Primary users
1804
+
1805
+ - TBD
1806
+
1807
+ ## Secondary users
1808
+
1809
+ - TBD
1810
+
1811
+ ## Needs & goals
1812
+
1813
+ - TBD
1814
+
1815
+ ## Assumptions
1816
+
1817
+ - ...
1818
+
1819
+ ## Open questions
1820
+
1821
+ - ...
1822
+
1823
+ ${QUALITY}
1824
+
1825
+ - [ ] Each persona has a goal, not just a label.
1826
+ - [ ] Primary vs secondary users are distinguished.
1827
+ `;
1828
+ var BUSINESS_VALUE_PROPOSITION = `---
1829
+ type: value-proposition
1830
+ status: draft
1831
+ ---
1832
+
1833
+ # Value Proposition
1834
+
1835
+ > Refine with the business-agent.
1836
+
1837
+ ## For whom
1838
+
1839
+ TBD
1840
+
1841
+ ## What we offer
1842
+
1843
+ TBD
1844
+
1845
+ ## Why it is better / different
1846
+
1847
+ TBD
1848
+
1849
+ ## Assumptions
1850
+
1851
+ - ...
1852
+
1853
+ ## Open questions
1854
+
1855
+ - ...
1856
+
1857
+ ${QUALITY}
1858
+
1859
+ - [ ] The value is specific, not generic.
1860
+ - [ ] It maps to a real user need.
1861
+ `;
1862
+ var BUSINESS_RULES = `---
1863
+ type: business-rules
1864
+ status: draft
1865
+ ---
1866
+
1867
+ # Business Rules
1868
+
1869
+ > Refine with the business-agent. These are product rules, not implementation details.
1870
+
1871
+ ## Core rules
1872
+
1873
+ - TBD
1874
+
1875
+ ## Edge cases
1876
+
1877
+ - TBD
1878
+
1879
+ ## Assumptions
1880
+
1881
+ - ...
1882
+
1883
+ ## Open questions
1884
+
1885
+ - ...
1886
+
1887
+ ${QUALITY}
1888
+
1889
+ - [ ] Rules are testable statements.
1890
+ - [ ] No implementation detail leaks in.
1891
+ `;
1892
+ var BUSINESS_CONSTRAINTS = `---
1893
+ type: constraints
1894
+ status: draft
1895
+ ---
1896
+
1897
+ # Constraints
1898
+
1899
+ > Refine with the business-agent.
1900
+
1901
+ ## Business constraints
1902
+
1903
+ - TBD
1904
+
1905
+ ## Regulatory / compliance
1906
+
1907
+ - TBD
1908
+
1909
+ ## Time / budget / team
1910
+
1911
+ - TBD
1912
+
1913
+ ## Assumptions
1914
+
1915
+ - ...
1916
+
1917
+ ## Open questions
1918
+
1919
+ - ...
1920
+
1921
+ ${QUALITY}
1922
+
1923
+ - [ ] Constraints are real, not aspirational.
1924
+ - [ ] Hard limits are separated from preferences.
1925
+ `;
1926
+ var BUSINESS_GLOSSARY = `---
1927
+ type: glossary
1928
+ status: draft
1929
+ ---
1930
+
1931
+ # Glossary
1932
+
1933
+ > Refine with the business-agent. One shared vocabulary avoids ambiguity.
1934
+
1935
+ | Term | Definition |
1936
+ |---|---|
1937
+ | TBD | TBD |
1938
+
1939
+ ## Open questions
1940
+
1941
+ - ...
1942
+
1943
+ ${QUALITY}
1944
+
1945
+ - [ ] Each term has a single agreed definition.
1946
+ - [ ] Ambiguous terms are flagged.
1947
+ `;
1948
+ var QUALITY_ATTRIBUTES = `---
1949
+ type: quality-attributes
1950
+ status: draft
1951
+ ---
1952
+
1953
+ # Quality Attributes
1954
+
1955
+ > Created by \`kaddo bootstrap\`. Refine with the bootstrap-agent. Prioritize honestly.
1956
+
1957
+ ## What matters most
1958
+
1959
+ - TBD (e.g. reliability, performance, security, maintainability, cost)
1960
+
1961
+ ## Trade-offs accepted
1962
+
1963
+ - TBD
1964
+
1965
+ ## Measurable targets (if known)
1966
+
1967
+ - TBD
1968
+
1969
+ ## Assumptions
1970
+
1971
+ - ...
1972
+
1973
+ ## Open questions
1974
+
1975
+ - ...
1976
+
1977
+ ${QUALITY}
1978
+
1979
+ - [ ] Attributes are prioritized, not all "high".
1980
+ - [ ] Trade-offs are explicit.
1981
+ `;
1982
+ var BUSINESS_CONSOLIDATED = `---
1983
+ type: business
1984
+ status: draft
1985
+ ---
1986
+
1987
+ # Business
1988
+
1989
+ > Created by \`kaddo bootstrap\`. The minimal **why** of the project. Refine with the
1990
+ > business-agent. As this matures it can split into problem.md, users.md, \u2026
1991
+
1992
+ ## Problem
1993
+
1994
+ TBD
1995
+
1996
+ ## Users
1997
+
1998
+ TBD
1999
+
2000
+ ## Value Proposition
2001
+
2002
+ TBD
2003
+
2004
+ ## Business Rules
2005
+
2006
+ - TBD
2007
+
2008
+ ## Constraints
2009
+
2010
+ - TBD
2011
+
2012
+ ## Assumptions
2013
+
2014
+ - ...
2015
+
2016
+ ## Open Questions
2017
+
2018
+ - ...
2019
+
2020
+ ${QUALITY}
2021
+
2022
+ - [ ] The problem is stated without assuming the solution.
2023
+ - [ ] Users have goals, not just labels.
2024
+ `;
2025
+ var PRODUCT_CONSOLIDATED = `---
2026
+ type: product
2027
+ status: draft
2028
+ ---
2029
+
2030
+ # Product
2031
+
2032
+ > Created by \`kaddo bootstrap\`. The minimal **what** of the project. Refine with the
2033
+ > bootstrap-agent / capability-agent. As this matures it can split into product-brief.md
2034
+ > and capabilities.md.
2035
+
2036
+ ## Product Brief
2037
+
2038
+ TBD
2039
+
2040
+ ## Capabilities
2041
+
2042
+ - TBD
2043
+
2044
+ ## Scope
2045
+
2046
+ - TBD
2047
+
2048
+ ## Out of Scope
2049
+
2050
+ - TBD
2051
+
2052
+ ## Success Criteria
2053
+
2054
+ - TBD
2055
+
2056
+ ## Assumptions
2057
+
2058
+ - ...
2059
+
2060
+ ## Open Questions
2061
+
2062
+ - ...
2063
+
2064
+ ${QUALITY}
2065
+
2066
+ - [ ] The product fits in one page.
2067
+ - [ ] Scope and out-of-scope are explicit.
2068
+ `;
2069
+ var CODEBASE_FOUNDATION = `---
2070
+ type: codebase
2071
+ status: draft
2072
+ ---
2073
+
2074
+ # Codebase
2075
+
2076
+ > Created by \`kaddo bootstrap\`. The minimal **how** of the project. Refine with the
2077
+ > codebase-agent. It describes the intended base \u2014 it does **not** generate code.
2078
+
2079
+ ## Repository Structure
2080
+
2081
+ TBD
2082
+
2083
+ ## Candidate Stack
2084
+
2085
+ - TBD
2086
+
2087
+ ## Quality Attributes
697
2088
 
698
- // ../cli/src/services/owners.ts
699
- import { parse as parseYaml3 } from "yaml";
700
- var CONFIG_PATH = ".kaddo/config.yml";
701
- function loadOwners(dir) {
702
- const configPath = join(dir, CONFIG_PATH);
703
- if (!exists(configPath)) return {};
704
- try {
705
- const config = parseYaml3(readFile(configPath));
706
- const raw = config.owners ?? {};
707
- const result = {};
708
- for (const [domain, people] of Object.entries(raw)) {
709
- result[domain] = Array.isArray(people) ? people.map(String) : [String(people)];
710
- }
711
- return result;
712
- } catch {
713
- return {};
714
- }
715
- }
2089
+ - TBD
2090
+
2091
+ ## Development Standards
2092
+
2093
+ - TBD
2094
+
2095
+ ## Git Strategy
2096
+
2097
+ GitHub Flow + Conventional Commits + SemVer (default). See \`kaddo add git-strategy\`.
2098
+
2099
+ ## Initial Modules
2100
+
2101
+ - TBD
2102
+
2103
+ ## Assumptions
2104
+
2105
+ - ...
2106
+
2107
+ ## Open Questions
2108
+
2109
+ - ...
2110
+
2111
+ ${QUALITY}
2112
+
2113
+ - [ ] Structure follows business and product, not a framework default.
2114
+ - [ ] No production code is described here \u2014 only the foundation.
2115
+ `;
2116
+ var BOOTSTRAP_SUMMARY = `---
2117
+ type: bootstrap-summary
2118
+ status: draft
2119
+ ---
2120
+
2121
+ # Bootstrap Summary
2122
+
2123
+ > Created by \`kaddo bootstrap\`. Index of the initial knowledge base and next steps.
2124
+
2125
+ ## Layers
2126
+
2127
+ - **Business** \u2014 \`knowledge/business/\`
2128
+ - **Architecture** \u2014 capabilities, quality-attributes, stack, current-state, decisions
2129
+ - **Codebase** \u2014 codebase-foundation, standards, git-strategy
2130
+ - **Development** \u2014 roadmap, work-items
2131
+
2132
+ ## Status
2133
+
2134
+ - [ ] Business defined
2135
+ - [ ] Initial architecture proposed
2136
+ - [ ] Codebase foundation drafted
2137
+ - [ ] Roadmap and first Work Items prepared
2138
+
2139
+ ## Next steps
2140
+
2141
+ 1. Run \`kaddo context\` and \`kaddo add agents\`.
2142
+ 2. Refine the artifacts with the business-agent, bootstrap-agent and
2143
+ codebase-agent in your LLM.
2144
+ 3. Run \`kaddo create --from roadmap\` to create the first Work Items.
2145
+
2146
+ ## Open questions
2147
+
2148
+ - ...
2149
+
2150
+ ${QUALITY}
2151
+
2152
+ - [ ] Every generated artifact is listed.
2153
+ - [ ] The next step is clear.
2154
+ `;
716
2155
 
717
2156
  // ../cli/src/core/capsule.ts
718
- var KNOWLEDGE = "knowledge";
2157
+ var KNOWLEDGE2 = "knowledge";
719
2158
  function today() {
720
2159
  return (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
721
2160
  }
@@ -732,16 +2171,16 @@ function readIf(dir, rel) {
732
2171
  return exists(p) ? readFile(p) : null;
733
2172
  }
734
2173
  function headings(md) {
735
- return md.split(/\r?\n/).map((l) => l.match(/^#{2,3}\s+(.+?)\s*$/)).filter((m) => Boolean(m)).map((m) => m[1].trim()).filter((h) => !/^(summary|resumen|overview|risks|owners|out of scope)$/i.test(h));
2174
+ return md.split(/\r?\n/).map((l2) => l2.match(/^#{2,3}\s+(.+?)\s*$/)).filter((m2) => Boolean(m2)).map((m2) => m2[1].trim()).filter((h2) => !/^(summary|resumen|overview|risks|owners|out of scope)$/i.test(h2));
736
2175
  }
737
2176
  function buildCapsule(dir, config) {
738
2177
  const ownerMap = loadOwners(dir);
739
2178
  const owners = [...new Set(Object.values(ownerMap).flat())];
740
2179
  const all = discoverKnowledge(dir);
741
- const purposeSrc = readIf(dir, `${KNOWLEDGE}/business/business.md`) ?? readIf(dir, `${KNOWLEDGE}/knowledge.md`) ?? "";
742
- const capsMd = readIf(dir, `${KNOWLEDGE}/product/capabilities.md`);
743
- const risksMd = readIf(dir, `${KNOWLEDGE}/legacy/risks.md`);
744
- const adrs = all.filter((a) => a.filePath.replace(/\\/g, "/").includes("/tech/decisions/") && Boolean(a.type)).map((a) => a.title || a.id).filter(Boolean);
2180
+ const purposeSrc = readIf(dir, `${KNOWLEDGE2}/business/business.md`) ?? readIf(dir, `${KNOWLEDGE2}/knowledge.md`) ?? "";
2181
+ const capsMd = readIf(dir, `${KNOWLEDGE2}/product/capabilities.md`);
2182
+ const risksMd = readIf(dir, `${KNOWLEDGE2}/legacy/risks.md`);
2183
+ const adrs = all.filter((a2) => a2.filePath.replace(/\\/g, "/").includes("/tech/decisions/") && Boolean(a2.type)).map((a2) => a2.title || a2.id).filter(Boolean);
745
2184
  return {
746
2185
  system: config.project.name,
747
2186
  version: 1,
@@ -813,7 +2252,7 @@ function loadExternalRegistry(dir) {
813
2252
  const p = join(dir, EXTERNAL_PATH);
814
2253
  if (!exists(p)) return [];
815
2254
  try {
816
- const parsed = parseYaml4(readFile(p));
2255
+ const parsed = parseYaml6(readFile(p));
817
2256
  return Array.isArray(parsed?.external) ? parsed.external : [];
818
2257
  } catch {
819
2258
  return [];
@@ -822,20 +2261,20 @@ function loadExternalRegistry(dir) {
822
2261
  function sectionList(md, title) {
823
2262
  const re = new RegExp(`^##\\s+${title}\\s*$`, "im");
824
2263
  const lines = md.split(/\r?\n/);
825
- const start = lines.findIndex((l) => re.test(l));
2264
+ const start = lines.findIndex((l2) => re.test(l2));
826
2265
  if (start < 0) return [];
827
2266
  const out = [];
828
2267
  for (let i = start + 1; i < lines.length; i++) {
829
2268
  if (/^##\s+/.test(lines[i])) break;
830
- const m = lines[i].match(/^\s*-\s+(.+?)\s*$/);
831
- if (m && !/^_.*_$/.test(m[1])) out.push(m[1].trim());
2269
+ const m2 = lines[i].match(/^\s*-\s+(.+?)\s*$/);
2270
+ if (m2 && !/^_.*_$/.test(m2[1])) out.push(m2[1].trim());
832
2271
  }
833
2272
  return out;
834
2273
  }
835
2274
  function sectionParagraph2(md, title) {
836
2275
  const re = new RegExp(`^##\\s+${title}\\s*$`, "im");
837
2276
  const lines = md.split(/\r?\n/);
838
- const start = lines.findIndex((l) => re.test(l));
2277
+ const start = lines.findIndex((l2) => re.test(l2));
839
2278
  if (start < 0) return "";
840
2279
  for (let i = start + 1; i < lines.length; i++) {
841
2280
  if (/^##\s+/.test(lines[i])) break;
@@ -849,8 +2288,8 @@ function parseCapsule(id, path3, md) {
849
2288
  const updatedAt = data.updated_at ? String(data.updated_at) : void 0;
850
2289
  let ageDays = null;
851
2290
  if (updatedAt) {
852
- const d = Date.parse(updatedAt);
853
- if (!Number.isNaN(d)) ageDays = Math.max(0, Math.floor((Date.now() - d) / 864e5));
2291
+ const d3 = Date.parse(updatedAt);
2292
+ if (!Number.isNaN(d3)) ageDays = Math.max(0, Math.floor((Date.now() - d3) / 864e5));
854
2293
  }
855
2294
  return {
856
2295
  id,
@@ -879,7 +2318,7 @@ function loadExternalCapsules(dir) {
879
2318
  }
880
2319
 
881
2320
  // ../cli/src/core/graph.ts
882
- var KNOWLEDGE2 = "knowledge";
2321
+ var KNOWLEDGE3 = "knowledge";
883
2322
  var ACTIVE_STATUSES = ["draft", "ready", "in-progress", "blocked"];
884
2323
  var ALL_STATUSES = ["draft", "ready", "in-progress", "blocked", "completed"];
885
2324
  function scopeStatuses(scope) {
@@ -891,8 +2330,8 @@ function toPosix3(p) {
891
2330
  function slug(s) {
892
2331
  return s.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
893
2332
  }
894
- function isAdr(a) {
895
- return toPosix3(a.filePath).includes("/tech/decisions/") && Boolean(a.type);
2333
+ function isAdr(a2) {
2334
+ return toPosix3(a2.filePath).includes("/tech/decisions/") && Boolean(a2.type);
896
2335
  }
897
2336
  function buildGraph(dir, config, opts = {}, now = /* @__PURE__ */ new Date()) {
898
2337
  const scope = opts.scope ?? "active";
@@ -916,7 +2355,7 @@ function buildGraph(dir, config, opts = {}, now = /* @__PURE__ */ new Date()) {
916
2355
  ];
917
2356
  const presentLayers = [];
918
2357
  for (const layer2 of layerDocs) {
919
- const path3 = layer2.files.map((f) => `${KNOWLEDGE2}/${f}`).find((rel) => exists(join(dir, rel)));
2358
+ const path3 = layer2.files.map((f3) => `${KNOWLEDGE3}/${f3}`).find((rel) => exists(join(dir, rel)));
920
2359
  if (path3) {
921
2360
  addNode({ id: layer2.id, type: layer2.type, label: layer2.label, path: path3 });
922
2361
  presentLayers.push(layer2.id);
@@ -926,11 +2365,11 @@ function buildGraph(dir, config, opts = {}, now = /* @__PURE__ */ new Date()) {
926
2365
  addEdge(presentLayers[i], presentLayers[i + 1], "informs");
927
2366
  }
928
2367
  const all = discoverKnowledge(dir);
929
- const workItems = all.filter((a) => a.isWorkItem);
2368
+ const workItems = all.filter((a2) => a2.isWorkItem);
930
2369
  const { included, excluded } = scopeStatuses(scope);
931
2370
  const includedSet = new Set(included);
932
- const activeWICount = workItems.filter((a) => a.lifecycle && isActiveState(a.lifecycle)).length;
933
- const selectedWIs = workItems.filter((a) => a.lifecycle && includedSet.has(a.lifecycle));
2371
+ const activeWICount = workItems.filter((a2) => a2.lifecycle && isActiveState(a2.lifecycle)).length;
2372
+ const selectedWIs = workItems.filter((a2) => a2.lifecycle && includedSet.has(a2.lifecycle));
934
2373
  for (const wi of selectedWIs) {
935
2374
  const id = wi.id || wi.title;
936
2375
  const wiNodeId = `wi:${id}`;
@@ -1076,20 +2515,20 @@ function loadGraphSummary(dir) {
1076
2515
  }
1077
2516
 
1078
2517
  // ../cli/src/core/graph-hints.ts
1079
- var KNOWLEDGE3 = "knowledge";
2518
+ var KNOWLEDGE4 = "knowledge";
1080
2519
  function toPosix4(p) {
1081
2520
  return p.replace(/\\/g, "/");
1082
2521
  }
1083
2522
  function slug2(s) {
1084
2523
  return s.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
1085
2524
  }
1086
- function isAdr2(a) {
1087
- return toPosix4(a.filePath).includes("/tech/decisions/") && Boolean(a.type);
2525
+ function isAdr2(a2) {
2526
+ return toPosix4(a2.filePath).includes("/tech/decisions/") && Boolean(a2.type);
1088
2527
  }
1089
2528
  function capabilityHeadings(dir) {
1090
- const p = join(dir, KNOWLEDGE3, "product", "capabilities.md");
2529
+ const p = join(dir, KNOWLEDGE4, "product", "capabilities.md");
1091
2530
  if (!exists(p)) return [];
1092
- return readFile(p).split(/\r?\n/).map((l) => l.match(/^#{2,3}\s+(.+?)\s*$/)).filter((m) => Boolean(m)).map((m) => m[1].trim()).filter((h) => !/^(summary|resumen|overview|capabilities|capacidades)$/i.test(h));
2531
+ return readFile(p).split(/\r?\n/).map((l2) => l2.match(/^#{2,3}\s+(.+?)\s*$/)).filter((m2) => Boolean(m2)).map((m2) => m2[1].trim()).filter((h2) => !/^(summary|resumen|overview|capabilities|capacidades)$/i.test(h2));
1093
2532
  }
1094
2533
  function humanMissing(field) {
1095
2534
  switch (field) {
@@ -1107,15 +2546,15 @@ function humanMissing(field) {
1107
2546
  }
1108
2547
  function buildGraphHints(dir, graph, now = /* @__PURE__ */ new Date()) {
1109
2548
  const artifacts = discoverKnowledge(dir);
1110
- const workItems = artifacts.filter((a) => a.isWorkItem);
1111
- const activeWIs = workItems.filter((a) => a.lifecycle && isActiveState(a.lifecycle));
2549
+ const workItems = artifacts.filter((a2) => a2.isWorkItem);
2550
+ const activeWIs = workItems.filter((a2) => a2.lifecycle && isActiveState(a2.lifecycle));
1112
2551
  const adrs = artifacts.filter(isAdr2);
1113
2552
  const capsules = loadExternalRegistry(dir);
1114
2553
  const hints = [];
1115
2554
  const referencedCapabilitySlugs = new Set(
1116
- workItems.flatMap((w) => w.capabilities.map((c) => slug2(c)))
2555
+ workItems.flatMap((w3) => w3.capabilities.map((c) => slug2(c)))
1117
2556
  );
1118
- const referencedCapsuleIds = new Set(workItems.flatMap((w) => w.capsules.map((c) => c)));
2557
+ const referencedCapsuleIds = new Set(workItems.flatMap((w3) => w3.capsules.map((c) => c)));
1119
2558
  let activeWithoutCode = 0;
1120
2559
  let activeWithoutCapabilities = 0;
1121
2560
  let wisWithoutSource = 0;
@@ -1239,8 +2678,8 @@ var QUALITY_NOTE = {
1239
2678
  };
1240
2679
  function yamlBlock(fm) {
1241
2680
  const lines = ["```yaml"];
1242
- for (const [k, vals] of Object.entries(fm)) {
1243
- lines.push(`${k}:`);
2681
+ for (const [k2, vals] of Object.entries(fm)) {
2682
+ lines.push(`${k2}:`);
1244
2683
  for (const v of vals) lines.push(` - ${v}`);
1245
2684
  }
1246
2685
  lines.push("```");
@@ -1276,20 +2715,20 @@ function renderGraphHintsMarkdown(report) {
1276
2715
  }
1277
2716
  lines.push("## Hints");
1278
2717
  lines.push("");
1279
- for (const h of report.hints) {
1280
- lines.push(`### ${h.artifact_id}${h.path ? ` \u2014 \`${h.path}\`` : ""}`);
2718
+ for (const h2 of report.hints) {
2719
+ lines.push(`### ${h2.artifact_id}${h2.path ? ` \u2014 \`${h2.path}\`` : ""}`);
1281
2720
  lines.push("");
1282
2721
  lines.push("Missing metadata:");
1283
2722
  lines.push("");
1284
- for (const m of h.missing) lines.push(`- \`${m}\``);
2723
+ for (const m2 of h2.missing) lines.push(`- \`${m2}\``);
1285
2724
  lines.push("");
1286
- if (h.suggested_front_matter) {
2725
+ if (h2.suggested_front_matter) {
1287
2726
  lines.push("Suggested front matter:");
1288
2727
  lines.push("");
1289
- lines.push(...yamlBlock(h.suggested_front_matter));
2728
+ lines.push(...yamlBlock(h2.suggested_front_matter));
1290
2729
  lines.push("");
1291
2730
  }
1292
- lines.push(`Reason: ${h.reason}`);
2731
+ lines.push(`Reason: ${h2.reason}`);
1293
2732
  lines.push("");
1294
2733
  }
1295
2734
  lines.push("> Use the `graph-agent` to turn these hints into precise front matter \u2014 you confirm and apply.");
@@ -1310,8 +2749,8 @@ function loadGraphHints(dir) {
1310
2749
  scopeReason: String(report.scope_reason ?? ""),
1311
2750
  quality: report.quality ?? "empty",
1312
2751
  totalHints: hints.length,
1313
- activeWorkItemHints: hints.filter((h) => h.artifact_type === "work-item").length,
1314
- messages: hints.map((h) => h.message).filter(Boolean)
2752
+ activeWorkItemHints: hints.filter((h2) => h2.artifact_type === "work-item").length,
2753
+ messages: hints.map((h2) => h2.message).filter(Boolean)
1315
2754
  };
1316
2755
  } catch {
1317
2756
  return null;
@@ -1342,7 +2781,7 @@ function discoverInstalledSkills(dir) {
1342
2781
  } catch {
1343
2782
  }
1344
2783
  }
1345
- return out.sort((a, b) => a.id.localeCompare(b.id));
2784
+ return out.sort((a2, b2) => a2.id.localeCompare(b2.id));
1346
2785
  }
1347
2786
  function skillGroupCounts(skills) {
1348
2787
  const counts = {};
@@ -1350,67 +2789,8 @@ function skillGroupCounts(skills) {
1350
2789
  return counts;
1351
2790
  }
1352
2791
 
1353
- // ../cli/src/services/mapped-modules.ts
1354
- import { parse as parseYaml5 } from "yaml";
1355
- var DESCRIPTOR_PATH = ".kaddo/modules.yml";
1356
- function toStringArray(value) {
1357
- return Array.isArray(value) ? value.map((v) => String(v)).filter(Boolean) : [];
1358
- }
1359
- function moduleArtifactCoverage(dir, id) {
1360
- const base = join(dir, "knowledge", "tech", "modules", id);
1361
- return {
1362
- moduleDesign: exists(join(base, "module-design.md")),
1363
- stack: exists(join(base, "stack.md")),
1364
- security: exists(join(base, "security.md")),
1365
- standards: exists(join(base, "standards.md")),
1366
- diagrams: exists(join(base, "diagrams")),
1367
- adrs: exists(join(base, "adrs"))
1368
- };
1369
- }
1370
- function loadMappedModules(dir) {
1371
- const path3 = join(dir, DESCRIPTOR_PATH);
1372
- if (!exists(path3)) return [];
1373
- let parsed;
1374
- try {
1375
- parsed = parseYaml5(readFile(path3));
1376
- } catch {
1377
- return [];
1378
- }
1379
- const raw = Array.isArray(parsed?.modules) ? parsed.modules : [];
1380
- const modules = [];
1381
- for (const entry of raw) {
1382
- if (!entry || typeof entry !== "object") continue;
1383
- const m = entry;
1384
- const id = typeof m.id === "string" ? m.id : "";
1385
- if (!id) continue;
1386
- modules.push({
1387
- id,
1388
- name: typeof m.name === "string" ? m.name : void 0,
1389
- repoPath: typeof m.repoPath === "string" ? m.repoPath : "",
1390
- type: typeof m.type === "string" ? m.type : void 0,
1391
- mainTechnology: typeof m.mainTechnology === "string" ? m.mainTechnology : void 0,
1392
- owner: typeof m.owner === "string" ? m.owner : void 0,
1393
- capabilities: toStringArray(m.capabilities),
1394
- code: toStringArray(m.code),
1395
- status: typeof m.status === "string" ? m.status : void 0,
1396
- artifacts: moduleArtifactCoverage(dir, id)
1397
- });
1398
- }
1399
- return modules;
1400
- }
1401
- function presentArtifacts(coverage) {
1402
- const present = [];
1403
- if (coverage.moduleDesign) present.push("module-design");
1404
- if (coverage.stack) present.push("stack");
1405
- if (coverage.security) present.push("security");
1406
- if (coverage.standards) present.push("standards");
1407
- if (coverage.diagrams) present.push("diagrams");
1408
- if (coverage.adrs) present.push("adrs");
1409
- return present;
1410
- }
1411
-
1412
2792
  // ../cli/src/core/knowledge-discovery.ts
1413
- var KNOWLEDGE4 = "knowledge";
2793
+ var KNOWLEDGE5 = "knowledge";
1414
2794
  var CONSOLIDATED_TYPE = {
1415
2795
  Business: "business",
1416
2796
  Product: "product",
@@ -1452,10 +2832,10 @@ function layerForType(type) {
1452
2832
  }
1453
2833
  function layerFromPath(filePath) {
1454
2834
  const p = filePath.replace(/\\/g, "/");
1455
- if (p.includes(`/${KNOWLEDGE4}/business/`)) return "Business";
1456
- if (p.includes(`/${KNOWLEDGE4}/product/`)) return "Product";
1457
- if (p.includes(`/${KNOWLEDGE4}/tech/`)) return "Tech";
1458
- if (p.includes(`/${KNOWLEDGE4}/delivery/`)) return "Delivery";
2835
+ if (p.includes(`/${KNOWLEDGE5}/business/`)) return "Business";
2836
+ if (p.includes(`/${KNOWLEDGE5}/product/`)) return "Product";
2837
+ if (p.includes(`/${KNOWLEDGE5}/tech/`)) return "Tech";
2838
+ if (p.includes(`/${KNOWLEDGE5}/delivery/`)) return "Delivery";
1459
2839
  return null;
1460
2840
  }
1461
2841
  function basename(p) {
@@ -1468,18 +2848,18 @@ function discoverLayers(dir) {
1468
2848
  Tech: blank(),
1469
2849
  Delivery: blank()
1470
2850
  };
1471
- const archDir = join(dir, KNOWLEDGE4);
2851
+ const archDir = join(dir, KNOWLEDGE5);
1472
2852
  const artifacts = exists(archDir) ? readArtifacts(archDir) : [];
1473
- for (const a of artifacts) {
1474
- const type = a.type;
1475
- const layer2 = layerForType(type) ?? layerFromPath(a.filePath);
2853
+ for (const a2 of artifacts) {
2854
+ const type = a2.type;
2855
+ const layer2 = layerForType(type) ?? layerFromPath(a2.filePath);
1476
2856
  if (!layer2) continue;
1477
2857
  const slot = acc[layer2];
1478
- slot.detected.add(basename(a.filePath));
2858
+ slot.detected.add(basename(a2.filePath));
1479
2859
  if (layer2 === "Delivery") {
1480
- if (type === "roadmap" || basename(a.filePath) === "roadmap.md") slot.hasRoadmap = true;
1481
- if (WORK_ITEM_TYPES.has(type) || a.filePath.replace(/\\/g, "/").includes("/delivery/work-items/")) {
1482
- if (a.filePath.replace(/\\/g, "/").includes("/delivery/work-items/")) slot.hasWorkItem = true;
2860
+ if (type === "roadmap" || basename(a2.filePath) === "roadmap.md") slot.hasRoadmap = true;
2861
+ if (WORK_ITEM_TYPES.has(type) || a2.filePath.replace(/\\/g, "/").includes("/delivery/work-items/")) {
2862
+ if (a2.filePath.replace(/\\/g, "/").includes("/delivery/work-items/")) slot.hasWorkItem = true;
1483
2863
  }
1484
2864
  continue;
1485
2865
  }
@@ -1490,7 +2870,7 @@ function discoverLayers(dir) {
1490
2870
  }
1491
2871
  if (type === "adr" || type === "decision") slot.hasDecision = true;
1492
2872
  }
1493
- if (existsDirWithMd(join(dir, KNOWLEDGE4, "tech", "decisions"))) acc.Tech.structured = true;
2873
+ if (existsDirWithMd(join(dir, KNOWLEDGE5, "tech", "decisions"))) acc.Tech.structured = true;
1494
2874
  return ["Business", "Product", "Tech", "Delivery"].map((layer2) => ({
1495
2875
  layer: layer2,
1496
2876
  status: statusFor(layer2, acc[layer2]),
@@ -1507,22 +2887,22 @@ function blank() {
1507
2887
  detected: /* @__PURE__ */ new Set()
1508
2888
  };
1509
2889
  }
1510
- function existsDirWithMd(d) {
1511
- if (!exists(d)) return false;
2890
+ function existsDirWithMd(d3) {
2891
+ if (!exists(d3)) return false;
1512
2892
  try {
1513
- return readDir(d).some((e) => e.endsWith(".md") && isFile(join(d, e)));
2893
+ return readDir(d3).some((e) => e.endsWith(".md") && isFile(join(d3, e)));
1514
2894
  } catch {
1515
2895
  return false;
1516
2896
  }
1517
2897
  }
1518
- function statusFor(layer2, a) {
2898
+ function statusFor(layer2, a2) {
1519
2899
  if (layer2 === "Delivery") {
1520
- if (a.hasWorkItem) return "Traceable";
1521
- if (a.hasRoadmap) return "Partial";
2900
+ if (a2.hasWorkItem) return "Traceable";
2901
+ if (a2.hasRoadmap) return "Partial";
1522
2902
  return "Missing";
1523
2903
  }
1524
- if (a.structured) return "Structured";
1525
- if (a.consolidated) return "Consolidated";
2904
+ if (a2.structured) return "Structured";
2905
+ if (a2.consolidated) return "Consolidated";
1526
2906
  return "Missing";
1527
2907
  }
1528
2908
 
@@ -1609,26 +2989,26 @@ function layerQuality(dir, layer2) {
1609
2989
  const order = ["missing", "placeholder", "weak", "useful"];
1610
2990
  let worst = null;
1611
2991
  for (const rel of LAYER_BASELINE[layer2]) {
1612
- const q = analyzeKnowledgeArtifact(dir, rel);
1613
- if (q === "missing") continue;
1614
- if (worst === null || order.indexOf(q) < order.indexOf(worst)) worst = q;
2992
+ const q3 = analyzeKnowledgeArtifact(dir, rel);
2993
+ if (q3 === "missing") continue;
2994
+ if (worst === null || order.indexOf(q3) < order.indexOf(worst)) worst = q3;
1615
2995
  }
1616
2996
  return worst;
1617
2997
  }
1618
2998
  function knowledgeLayers(dir) {
1619
- return discoverLayers(dir).map((l) => {
1620
- if (l.status !== "Consolidated" && l.status !== "Structured") return l;
1621
- const q = layerQuality(dir, l.layer);
1622
- if (q === "placeholder") return { ...l, status: "Placeholder" };
1623
- if (q === "weak") return { ...l, status: "Weak" };
1624
- return l;
2999
+ return discoverLayers(dir).map((l2) => {
3000
+ if (l2.status !== "Consolidated" && l2.status !== "Structured") return l2;
3001
+ const q3 = layerQuality(dir, l2.layer);
3002
+ if (q3 === "placeholder") return { ...l2, status: "Placeholder" };
3003
+ if (q3 === "weak") return { ...l2, status: "Weak" };
3004
+ return l2;
1625
3005
  });
1626
3006
  }
1627
3007
  function renderLayersMarkdown(layers) {
1628
3008
  const lines = [];
1629
3009
  for (const { layer: layer2, status, detected } of layers) {
1630
3010
  lines.push(`### ${layer2} \u2014 ${status}`);
1631
- if (detected.length > 0) for (const d of detected) lines.push(`- \u2713 ${d}`);
3011
+ if (detected.length > 0) for (const d3 of detected) lines.push(`- \u2713 ${d3}`);
1632
3012
  else lines.push("- \u2717 none");
1633
3013
  lines.push("");
1634
3014
  }
@@ -1648,10 +3028,10 @@ function splitInitiatives(markdown) {
1648
3028
  const blocks = [];
1649
3029
  let current = null;
1650
3030
  for (const line of markdown.split(/\r?\n/)) {
1651
- const m = line.match(INITIATIVE_RE);
1652
- if (m) {
3031
+ const m2 = line.match(INITIATIVE_RE);
3032
+ if (m2) {
1653
3033
  if (current) blocks.push(current);
1654
- current = { initiative: { id: m[1], title: m[2].trim() || void 0 }, lines: [] };
3034
+ current = { initiative: { id: m2[1], title: m2[2].trim() || void 0 }, lines: [] };
1655
3035
  continue;
1656
3036
  }
1657
3037
  if (current) current.lines.push(line);
@@ -1763,9 +3143,9 @@ function parseBlock(block) {
1763
3143
  function decisionCandidatesFromSignals(signals) {
1764
3144
  const out = [];
1765
3145
  for (const sig of signals) {
1766
- const m = sig.match(/decision candidate\s*:?\s*(.+)$/i);
1767
- if (!m) continue;
1768
- const rest = m[1].trim();
3146
+ const m2 = sig.match(/decision candidate\s*:?\s*(.+)$/i);
3147
+ if (!m2) continue;
3148
+ const rest = m2[1].trim();
1769
3149
  const token = rest.match(/\b[A-Z][A-Z0-9_]{2,}\b/);
1770
3150
  const value = token ? token[0] : rest.replace(/[.。]+$/, "").trim();
1771
3151
  if (value && !out.includes(value)) out.push(value);
@@ -1782,10 +3162,10 @@ function splitRow(line) {
1782
3162
  function isSeparatorRow(cells) {
1783
3163
  return cells.length > 0 && cells.every((c) => SEPARATOR_CELL_RE.test(c) || c === "");
1784
3164
  }
1785
- function initiativeFromHeading(text2) {
1786
- const rm = text2.match(/^(RM-[\w.-]+)\s*[:\-–]?\s*(.*)$/);
3165
+ function initiativeFromHeading(text3) {
3166
+ const rm = text3.match(/^(RM-[\w.-]+)\s*[:\-–]?\s*(.*)$/);
1787
3167
  if (rm) return { id: rm[1], title: rm[2].trim() || void 0 };
1788
- return { title: text2.trim() || void 0 };
3168
+ return { title: text3.trim() || void 0 };
1789
3169
  }
1790
3170
  function extractDeps(cell) {
1791
3171
  if (!cell) return void 0;
@@ -1809,9 +3189,9 @@ function parseFlexible(markdown) {
1809
3189
  });
1810
3190
  };
1811
3191
  for (const line of markdown.split(/\r?\n/)) {
1812
- const h = line.match(HEADING_RE);
1813
- if (h) {
1814
- initiative = initiativeFromHeading(h[1]);
3192
+ const h2 = line.match(HEADING_RE);
3193
+ if (h2) {
3194
+ initiative = initiativeFromHeading(h2[1]);
1815
3195
  cols = null;
1816
3196
  continue;
1817
3197
  }
@@ -1840,9 +3220,9 @@ function parseFlexible(markdown) {
1840
3220
  }
1841
3221
  continue;
1842
3222
  }
1843
- const b = line.match(FLEX_BULLET_RE);
1844
- if (b) {
1845
- push(b[1], b[2] ?? "", void 0, line);
3223
+ const b2 = line.match(FLEX_BULLET_RE);
3224
+ if (b2) {
3225
+ push(b2[1], b2[2] ?? "", void 0, line);
1846
3226
  continue;
1847
3227
  }
1848
3228
  }
@@ -1897,10 +3277,10 @@ var RESOLUTION_TOKENS = {
1897
3277
  diferida: "deferred"
1898
3278
  };
1899
3279
  function parseResolution(line) {
1900
- const m = line.match(/^\[([a-zA-Záéí]+)\]\s*(.*)$/);
1901
- if (m) {
1902
- const status = RESOLUTION_TOKENS[m[1].toLowerCase()];
1903
- if (status) return { text: m[2].trim(), resolution_status: status };
3280
+ const m2 = line.match(/^\[([a-zA-Záéí]+)\]\s*(.*)$/);
3281
+ if (m2) {
3282
+ const status = RESOLUTION_TOKENS[m2[1].toLowerCase()];
3283
+ if (status) return { text: m2[2].trim(), resolution_status: status };
1904
3284
  }
1905
3285
  return { text: line.trim(), resolution_status: "open" };
1906
3286
  }
@@ -1971,8 +3351,8 @@ var IMPORTANT = [
1971
3351
  "permis",
1972
3352
  "permission"
1973
3353
  ];
1974
- function matchesAny(text2, keywords) {
1975
- return keywords.some((k) => text2.includes(k));
3354
+ function matchesAny(text3, keywords) {
3355
+ return keywords.some((k2) => text3.includes(k2));
1976
3356
  }
1977
3357
  function classifyQuestion(question) {
1978
3358
  const t = question.toLowerCase();
@@ -1989,7 +3369,7 @@ function classifyQuestion(question) {
1989
3369
  }
1990
3370
  function extractFromMarkdown(md) {
1991
3371
  const lines = md.split(/\r?\n/);
1992
- const start = lines.findIndex((l) => /^#{1,6}\s+open questions\s*$/i.test(l.trim()) || /^#{1,6}\s+preguntas abiertas\s*$/i.test(l.trim()));
3372
+ const start = lines.findIndex((l2) => /^#{1,6}\s+open questions\s*$/i.test(l2.trim()) || /^#{1,6}\s+preguntas abiertas\s*$/i.test(l2.trim()));
1993
3373
  if (start < 0) return [];
1994
3374
  const out = [];
1995
3375
  for (let i = start + 1; i < lines.length; i++) {
@@ -2000,12 +3380,12 @@ function extractFromMarkdown(md) {
2000
3380
  if (meta[1].toLowerCase() === "note") out[out.length - 1].resolution_note = meta[2].trim();
2001
3381
  continue;
2002
3382
  }
2003
- const m = line.match(/^\s*(?:[-*]|\d+\.)\s+(.+?)\s*$/);
2004
- if (m) {
2005
- const bullet = m[1].trim();
3383
+ const m2 = line.match(/^\s*(?:[-*]|\d+\.)\s+(.+?)\s*$/);
3384
+ if (m2) {
3385
+ const bullet = m2[1].trim();
2006
3386
  if (!bullet || /^_.*_$/.test(bullet)) continue;
2007
- const { text: text2, resolution_status } = parseResolution(bullet);
2008
- if (text2) out.push({ text: text2, resolution_status, line: i + 1, raw: line.trim() });
3387
+ const { text: text3, resolution_status } = parseResolution(bullet);
3388
+ if (text3) out.push({ text: text3, resolution_status, line: i + 1, raw: line.trim() });
2009
3389
  }
2010
3390
  }
2011
3391
  return out;
@@ -2058,12 +3438,12 @@ function buildOpenQuestionsReport(dir, now = /* @__PURE__ */ new Date()) {
2058
3438
  });
2059
3439
  }
2060
3440
  }
2061
- const blocking = questions.filter((q) => q.classification === "blocking");
2062
- const important = questions.filter((q) => q.classification === "important");
2063
- const deferred = questions.filter((q) => q.classification === "deferred");
2064
- const blockingOpen = blocking.filter((q) => q.resolution_status === "open");
2065
- const importantOpen = important.filter((q) => q.resolution_status === "open");
2066
- const byStatus = (s) => questions.filter((q) => q.resolution_status === s);
3441
+ const blocking = questions.filter((q3) => q3.classification === "blocking");
3442
+ const important = questions.filter((q3) => q3.classification === "important");
3443
+ const deferred = questions.filter((q3) => q3.classification === "deferred");
3444
+ const blockingOpen = blocking.filter((q3) => q3.resolution_status === "open");
3445
+ const importantOpen = important.filter((q3) => q3.resolution_status === "open");
3446
+ const byStatus = (s) => questions.filter((q3) => q3.resolution_status === s);
2067
3447
  const resolved = byStatus("resolved");
2068
3448
  const assumed = byStatus("assumed");
2069
3449
  const deferredStatus = byStatus("deferred");
@@ -2071,7 +3451,7 @@ function buildOpenQuestionsReport(dir, now = /* @__PURE__ */ new Date()) {
2071
3451
  if (questions.length === 0) readiness = "unknown";
2072
3452
  else if (blockingOpen.length > 0) readiness = "needs_decisions";
2073
3453
  else readiness = "ready";
2074
- const suggested_assumptions = blockingOpen.map((q) => q.suggested_assumption).filter(Boolean);
3454
+ const suggested_assumptions = blockingOpen.map((q3) => q3.suggested_assumption).filter(Boolean);
2075
3455
  const recommended_next_step = readiness === "needs_decisions" ? "Confirm suggested assumptions with the user (resolve, assume or defer blocking open questions) before generating the roadmap." : readiness === "ready" ? "No blocking open questions \u2014 you can proceed to the roadmap. Surfaced assumptions/deferred items are informational." : "No open questions found. Run `kaddo bootstrap` to capture early questions, or proceed.";
2076
3456
  return {
2077
3457
  generated_at: now.toISOString(),
@@ -2102,75 +3482,75 @@ function buildOpenQuestionsReport(dir, now = /* @__PURE__ */ new Date()) {
2102
3482
  recommended_next_step
2103
3483
  };
2104
3484
  }
2105
- function renderOpenQuestionsMarkdown(r) {
3485
+ function renderOpenQuestionsMarkdown(r2) {
2106
3486
  const L = [];
2107
3487
  L.push("# Kaddo Open Questions Readiness Report", "");
2108
- L.push(`Generated at: ${r.generated_at}`);
2109
- L.push(`Project: ${r.project}`);
3488
+ L.push(`Generated at: ${r2.generated_at}`);
3489
+ L.push(`Project: ${r2.project}`);
2110
3490
  L.push("");
2111
3491
  L.push("## Summary", "");
2112
- L.push(`- Open questions found: ${r.summary.open_questions}`);
2113
- L.push(`- Roadmap readiness: ${r.summary.roadmap_readiness}`);
2114
- L.push(`- By resolution \u2014 open: ${r.summary.resolution.open}, resolved: ${r.summary.resolution.resolved}, assumed: ${r.summary.resolution.assumed}, deferred: ${r.summary.resolution.deferred}`);
2115
- L.push(`- Blocking open: ${r.summary.blocking_open}, important open: ${r.summary.important_open}`);
3492
+ L.push(`- Open questions found: ${r2.summary.open_questions}`);
3493
+ L.push(`- Roadmap readiness: ${r2.summary.roadmap_readiness}`);
3494
+ L.push(`- By resolution \u2014 open: ${r2.summary.resolution.open}, resolved: ${r2.summary.resolution.resolved}, assumed: ${r2.summary.resolution.assumed}, deferred: ${r2.summary.resolution.deferred}`);
3495
+ L.push(`- Blocking open: ${r2.summary.blocking_open}, important open: ${r2.summary.important_open}`);
2116
3496
  L.push("");
2117
- if (r.summary.open_questions === 0) {
3497
+ if (r2.summary.open_questions === 0) {
2118
3498
  L.push("No `## Open Questions` sections found in business / product / codebase / roadmap.", "");
2119
- L.push("## Recommended Next Step", "", r.recommended_next_step, "");
3499
+ L.push("## Recommended Next Step", "", r2.recommended_next_step, "");
2120
3500
  return L.join("\n");
2121
3501
  }
2122
- const blockingOpen = r.blocking_questions.filter((q) => q.resolution_status === "open");
3502
+ const blockingOpen = r2.blocking_questions.filter((q3) => q3.resolution_status === "open");
2123
3503
  L.push("## Blocking Open Questions", "");
2124
3504
  if (blockingOpen.length === 0) L.push("_None \u2014 nothing blocks readiness._", "");
2125
- for (const q of blockingOpen) {
2126
- L.push(`### ${q.question}`, "");
2127
- L.push(`- Status: ${q.resolution_status}`);
2128
- L.push(`- Severity: ${q.classification}`);
2129
- L.push(`- Source: \`${q.sourcePath}:${q.line}\``);
2130
- L.push(`- Reason: ${q.reason}`);
3505
+ for (const q3 of blockingOpen) {
3506
+ L.push(`### ${q3.question}`, "");
3507
+ L.push(`- Status: ${q3.resolution_status}`);
3508
+ L.push(`- Severity: ${q3.classification}`);
3509
+ L.push(`- Source: \`${q3.sourcePath}:${q3.line}\``);
3510
+ L.push(`- Reason: ${q3.reason}`);
2131
3511
  L.push("");
2132
3512
  L.push("Suggested action:", "");
2133
3513
  L.push("```md");
2134
- L.push(`- [assumed] ${q.question}`);
2135
- L.push(` - note: ${q.suggested_assumption ?? "<editable assumption for the MVP>"}`);
3514
+ L.push(`- [assumed] ${q3.question}`);
3515
+ L.push(` - note: ${q3.suggested_assumption ?? "<editable assumption for the MVP>"}`);
2136
3516
  L.push("```");
2137
3517
  L.push("");
2138
3518
  }
2139
3519
  const renderStatusList = (title, items) => {
2140
3520
  L.push(`## ${title}`, "");
2141
3521
  if (items.length === 0) L.push("_None._");
2142
- for (const q of items) L.push(`- ${q.question} \u2014 \`${q.sourcePath}:${q.line}\`${q.note ? ` \u2014 _${q.note}_` : ""}`);
3522
+ for (const q3 of items) L.push(`- ${q3.question} \u2014 \`${q3.sourcePath}:${q3.line}\`${q3.note ? ` \u2014 _${q3.note}_` : ""}`);
2143
3523
  L.push("");
2144
3524
  };
2145
- renderStatusList("Resolved", r.resolved_questions);
2146
- renderStatusList("Assumed (decisions to revisit)", r.assumed_questions);
2147
- renderStatusList("Deferred (out of current scope)", r.deferred_status_questions);
3525
+ renderStatusList("Resolved", r2.resolved_questions);
3526
+ renderStatusList("Assumed (decisions to revisit)", r2.assumed_questions);
3527
+ renderStatusList("Deferred (out of current scope)", r2.deferred_status_questions);
2148
3528
  L.push("## Important Questions", "");
2149
- if (r.important_questions.length === 0) L.push("_None._");
2150
- for (const q of r.important_questions) L.push(`- [${q.resolution_status}] ${q.question}`);
3529
+ if (r2.important_questions.length === 0) L.push("_None._");
3530
+ for (const q3 of r2.important_questions) L.push(`- [${q3.resolution_status}] ${q3.question}`);
2151
3531
  L.push("");
2152
- if (r.suggested_assumptions.length > 0) {
3532
+ if (r2.suggested_assumptions.length > 0) {
2153
3533
  L.push("## Suggested Assumptions", "");
2154
- for (const a of r.suggested_assumptions) L.push(`- ${a}`);
3534
+ for (const a2 of r2.suggested_assumptions) L.push(`- ${a2}`);
2155
3535
  L.push("");
2156
3536
  }
2157
- L.push("## Recommended Next Step", "", r.recommended_next_step, "");
3537
+ L.push("## Recommended Next Step", "", r2.recommended_next_step, "");
2158
3538
  return L.join("\n");
2159
3539
  }
2160
- function serializeOpenQuestionsJson(r) {
2161
- return JSON.stringify(r, null, 2) + "\n";
3540
+ function serializeOpenQuestionsJson(r2) {
3541
+ return JSON.stringify(r2, null, 2) + "\n";
2162
3542
  }
2163
3543
  function roadmapReadinessSummary(dir) {
2164
- const r = buildOpenQuestionsReport(dir);
3544
+ const r2 = buildOpenQuestionsReport(dir);
2165
3545
  return {
2166
- roadmap_readiness: r.summary.roadmap_readiness,
2167
- blocking_questions: r.summary.blocking,
2168
- blocking_open: r.summary.blocking_open,
2169
- important_questions: r.summary.important,
2170
- deferred_questions: r.summary.deferred,
2171
- resolution: r.summary.resolution,
2172
- suggested_assumptions: r.suggested_assumptions,
2173
- recommended_next_step: r.summary.roadmap_readiness === "needs_decisions" ? "Resolve, assume, or defer blocking open questions before generating roadmap." : r.recommended_next_step
3546
+ roadmap_readiness: r2.summary.roadmap_readiness,
3547
+ blocking_questions: r2.summary.blocking,
3548
+ blocking_open: r2.summary.blocking_open,
3549
+ important_questions: r2.summary.important,
3550
+ deferred_questions: r2.summary.deferred,
3551
+ resolution: r2.summary.resolution,
3552
+ suggested_assumptions: r2.suggested_assumptions,
3553
+ recommended_next_step: r2.summary.roadmap_readiness === "needs_decisions" ? "Resolve, assume, or defer blocking open questions before generating roadmap." : r2.recommended_next_step
2174
3554
  };
2175
3555
  }
2176
3556
 
@@ -2194,9 +3574,9 @@ function discoverAgents(dir) {
2194
3574
  const base = join(dir, "knowledge", "agents");
2195
3575
  if (!exists(base) || !isDir(base)) return [];
2196
3576
  const out = /* @__PURE__ */ new Set();
2197
- const walk = (d) => {
2198
- for (const e of readDir(d)) {
2199
- const full = join(d, e);
3577
+ const walk = (d3) => {
3578
+ for (const e of readDir(d3)) {
3579
+ const full = join(d3, e);
2200
3580
  if (isDir(full)) walk(full);
2201
3581
  else if (e.endsWith("-agent.md")) out.add(e.replace(/\.md$/, ""));
2202
3582
  }
@@ -2230,8 +3610,8 @@ function detectPackageManager(dir) {
2230
3610
  return void 0;
2231
3611
  }
2232
3612
  function detectMcpHint(dir) {
2233
- for (const f of [".mcp.json", "mcp.json", ".cursor/mcp.json"]) {
2234
- if (exists(join(dir, f))) return true;
3613
+ for (const f3 of [".mcp.json", "mcp.json", ".cursor/mcp.json"]) {
3614
+ if (exists(join(dir, f3))) return true;
2235
3615
  }
2236
3616
  return false;
2237
3617
  }
@@ -2257,11 +3637,11 @@ var ADAPTERS = [
2257
3637
  { id: "kiro", label: "Kiro", file: "AGENTS.md", supportsInject: true }
2258
3638
  ];
2259
3639
  function findAdapter(id) {
2260
- return ADAPTERS.find((a) => a.id === id);
3640
+ return ADAPTERS.find((a2) => a2.id === id);
2261
3641
  }
2262
3642
  function parseOriginAdapter(content) {
2263
- const m = content.match(/Generated by `kaddo adapters install (\w+)`/);
2264
- const id = m?.[1];
3643
+ const m2 = content.match(/Generated by `kaddo adapters install (\w+)`/);
3644
+ const id = m2?.[1];
2265
3645
  return id && findAdapter(id) ? id : null;
2266
3646
  }
2267
3647
  function classifyAdapterState(content) {
@@ -2279,8 +3659,8 @@ function classifyAdapterState(content) {
2279
3659
  return "team-owned";
2280
3660
  }
2281
3661
  }
2282
- function recommendedAction(a, state) {
2283
- const cmd = `kaddo adapters install ${a.id}`;
3662
+ function recommendedAction(a2, state) {
3663
+ const cmd = `kaddo adapters install ${a2.id}`;
2284
3664
  switch (state) {
2285
3665
  case "missing":
2286
3666
  return cmd;
@@ -2291,7 +3671,7 @@ function recommendedAction(a, state) {
2291
3671
  case "legacy-injected":
2292
3672
  return `${cmd} --inject (migrates legacy markers to neutral)`;
2293
3673
  case "full-generated":
2294
- return `No action needed. Use \`${cmd} --force\` only to regenerate for ${a.label}.`;
3674
+ return `No action needed. Use \`${cmd} --force\` only to regenerate for ${a2.label}.`;
2295
3675
  case "broken-markers":
2296
3676
  return "Fix the incomplete Kaddo adapter markers before running --inject.";
2297
3677
  }
@@ -2305,11 +3685,11 @@ function buildAdapterStatuses(dir) {
2305
3685
  }
2306
3686
  return cache.get(file);
2307
3687
  };
2308
- return ADAPTERS.map((a) => {
2309
- const content = read(a.file);
3688
+ return ADAPTERS.map((a2) => {
3689
+ const content = read(a2.file);
2310
3690
  const state = classifyAdapterState(content);
2311
3691
  const originAdapter = content ? parseOriginAdapter(content) : null;
2312
- return { ...a, state, originAdapter, recommendedAction: recommendedAction(a, state) };
3692
+ return { ...a2, state, originAdapter, recommendedAction: recommendedAction(a2, state) };
2313
3693
  });
2314
3694
  }
2315
3695
 
@@ -2324,6 +3704,7 @@ var AGENT_GROUPS = {
2324
3704
  "security-agent.md",
2325
3705
  "standards-agent.md",
2326
3706
  "module-design-agent.md",
3707
+ "module-context-agent.md",
2327
3708
  "adr-agent.md",
2328
3709
  "capsule-agent.md",
2329
3710
  "graph-agent.md"
@@ -2369,9 +3750,9 @@ function slugify(s) {
2369
3750
  function parseDecisionCandidates(md) {
2370
3751
  const out = [];
2371
3752
  for (const line of md.split(/\r?\n/)) {
2372
- const m = line.match(/^##\s+(.+?)\s*$/);
2373
- if (m) {
2374
- const raw = m[1].trim();
3753
+ const m2 = line.match(/^##\s+(.+?)\s*$/);
3754
+ if (m2) {
3755
+ const raw = m2[1].trim();
2375
3756
  if (!raw || /^_.*_$/.test(raw)) continue;
2376
3757
  const t = cleanCandidateTitle(raw);
2377
3758
  if (t) out.push(t);
@@ -2438,9 +3819,9 @@ function buildTechDecisions(dir) {
2438
3819
  // ../cli/src/core/next-step.ts
2439
3820
  function buildDeliveryState(dir) {
2440
3821
  const wis = discoverWorkItems(dir);
2441
- const byState = (s) => wis.filter((w) => w.lifecycle === s).length;
3822
+ const byState = (s) => wis.filter((w3) => w3.lifecycle === s).length;
2442
3823
  const total = wis.length;
2443
- const withOwnership = wis.filter((w) => w.codeGlobs.length > 0).length;
3824
+ const withOwnership = wis.filter((w3) => w3.codeGlobs.length > 0).length;
2444
3825
  const td = buildTechDecisions(dir);
2445
3826
  const roadmapPath = join(dir, "knowledge/delivery/roadmap.md");
2446
3827
  const roadmapMd = exists(roadmapPath) ? safeRead(roadmapPath) : null;
@@ -2449,9 +3830,10 @@ function buildDeliveryState(dir) {
2449
3830
  return {
2450
3831
  phase: "",
2451
3832
  draft_work_items: byState("draft"),
2452
- refined_draft_work_items: wis.filter((w) => w.lifecycle === "draft" && w.rawFrontmatter.refined_by).length,
2453
- refined_draft_ids: wis.filter((w) => w.lifecycle === "draft" && w.rawFrontmatter.refined_by).map((w) => w.id),
3833
+ refined_draft_work_items: wis.filter((w3) => w3.lifecycle === "draft" && w3.rawFrontmatter.refined_by).length,
3834
+ refined_draft_ids: wis.filter((w3) => w3.lifecycle === "draft" && w3.rawFrontmatter.refined_by).map((w3) => w3.id),
2454
3835
  ready_work_items: byState("ready"),
3836
+ ready_work_item_ids: wis.filter((w3) => w3.lifecycle === "ready").map((w3) => w3.id),
2455
3837
  in_progress_work_items: byState("in-progress"),
2456
3838
  blocked_work_items: byState("blocked"),
2457
3839
  total_work_items: total,
@@ -2481,17 +3863,17 @@ function roadmapSignal(dir) {
2481
3863
  const lines = md.replace(/^---[\s\S]*?---/m, "").split(/\r?\n/);
2482
3864
  let inOpenQuestions = false;
2483
3865
  let candidates = 0;
2484
- for (const l of lines) {
2485
- if (/^#{1,6}\s/.test(l)) inOpenQuestions = /open questions|preguntas abiertas/i.test(l);
2486
- else if (!inOpenQuestions && /^\s*(?:[-*]\s+|\|)/.test(l)) candidates += 1;
3866
+ for (const l2 of lines) {
3867
+ if (/^#{1,6}\s/.test(l2)) inOpenQuestions = /open questions|preguntas abiertas/i.test(l2);
3868
+ else if (!inOpenQuestions && /^\s*(?:[-*]\s+|\|)/.test(l2)) candidates += 1;
2487
3869
  }
2488
3870
  return candidates > 0 ? "has-candidates" : "empty";
2489
3871
  }
2490
3872
  function workItemsSignal(dir) {
2491
3873
  const wis = discoverWorkItems(dir);
2492
3874
  if (wis.length === 0) return "none";
2493
- if (wis.some((w) => w.lifecycle === "in-progress")) return "in-progress";
2494
- if (wis.some((w) => w.lifecycle === "ready")) return "ready";
3875
+ if (wis.some((w3) => w3.lifecycle === "in-progress")) return "in-progress";
3876
+ if (wis.some((w3) => w3.lifecycle === "ready")) return "ready";
2495
3877
  return "none-ready";
2496
3878
  }
2497
3879
  function installedAdapters(dir) {
@@ -2499,8 +3881,8 @@ function installedAdapters(dir) {
2499
3881
  (s) => s.state === "injected" || s.state === "legacy-injected" || s.state === "full-generated" && (s.originAdapter === s.id || s.originAdapter === null)
2500
3882
  ).map((s) => s.id);
2501
3883
  }
2502
- var B = "knowledge/business/business.md";
2503
- var P = "knowledge/product/product.md";
3884
+ var B2 = "knowledge/business/business.md";
3885
+ var P2 = "knowledge/product/product.md";
2504
3886
  var CAP = "knowledge/product/capabilities.md";
2505
3887
  var CS = "knowledge/tech/current-state.md";
2506
3888
  var CB = "knowledge/tech/codebase.md";
@@ -2510,8 +3892,61 @@ function resolveNextStep(dir, now = /* @__PURE__ */ new Date()) {
2510
3892
  return { id: "init", phase: "Setup", label: "Run `kaddo init` to initialize Kaddo.", command: "kaddo init", reason: "Kaddo is not initialized in this project." };
2511
3893
  }
2512
3894
  const state = config.project.state;
2513
- const q = (rel) => analyzeKnowledgeArtifact(dir, rel);
2514
- const qBusiness = q(B), qProduct = q(P), qCap = q(CAP), qCurrentState = q(CS), qCodebase = q(CB);
3895
+ const q3 = (rel) => analyzeKnowledgeArtifact(dir, rel);
3896
+ const moduleRepo = isModule(config);
3897
+ const MC = "knowledge/module/module-context.md";
3898
+ if (moduleRepo) {
3899
+ const qMC = q3(MC);
3900
+ if (qMC === "missing") {
3901
+ return { id: "init-module-context", phase: "Setup", label: "Create `knowledge/module/module-context.md` for this module.", command: "kaddo init", reason: "Module context file is missing. Re-run `kaddo init` as a multirepo module." };
3902
+ }
3903
+ if ((state === "pre-ai" || state === "legacy") && !exists(join(dir, ".kaddo", "scan.json"))) {
3904
+ return { id: "scan", phase: "Discovery", label: "Run `kaddo scan` to capture deterministic signals from the existing code.", command: "kaddo scan", reason: "No scan baseline exists for this existing project yet." };
3905
+ }
3906
+ if (!exists(join(dir, ".kaddo", "context-pack.md"))) {
3907
+ return { id: "context", phase: "Discovery", label: "Run `kaddo context` to prepare the LLM context pack.", command: "kaddo context", reason: "No context pack has been generated yet." };
3908
+ }
3909
+ if (qMC !== "useful") {
3910
+ return {
3911
+ id: "refine-module-context",
3912
+ phase: "Knowledge Refinement",
3913
+ label: "Use module-context-agent to refine `knowledge/module/module-context.md`.",
3914
+ agent: "module-context-agent",
3915
+ skill: "module-context-refinement",
3916
+ target: MC,
3917
+ reason: "Module context is still a placeholder.",
3918
+ instructions: ["Refine the module context with real knowledge about this module.", "Do not create business.md or product.md.", "Do not write code."]
3919
+ };
3920
+ }
3921
+ const qCurrentState2 = q3(CS), qCodebase2 = q3(CB);
3922
+ if (qCurrentState2 !== "useful") {
3923
+ return {
3924
+ id: "refine-current-state",
3925
+ phase: "Knowledge Refinement",
3926
+ label: "Use architecture-agent to complete `knowledge/tech/current-state.md`.",
3927
+ agent: "architecture-agent",
3928
+ target: CS,
3929
+ reason: `${CS} is still a bootstrap placeholder or too thin.`,
3930
+ instructions: ["Describe the module's local architecture.", "Do not write code."]
3931
+ };
3932
+ }
3933
+ if (qCodebase2 !== "useful") {
3934
+ return {
3935
+ id: "refine-codebase",
3936
+ phase: "Knowledge Refinement",
3937
+ label: "Use architecture-agent to complete `knowledge/tech/codebase.md`.",
3938
+ agent: "architecture-agent",
3939
+ target: CB,
3940
+ reason: `${CB} is still a bootstrap placeholder or too thin.`,
3941
+ instructions: ["Map the module's local codebase structure.", "Do not write code."]
3942
+ };
3943
+ }
3944
+ if (!exists(join(dir, ".kaddo", "understand.md"))) {
3945
+ return { id: "understand", phase: "Discovery", label: "Run `kaddo understand` to summarize the project context.", command: "kaddo understand", reason: "No understand handoff has been generated yet." };
3946
+ }
3947
+ return { id: "module-ready", phase: "Active Delivery", label: "Module context is complete. Create and manage Work Items from the core repository.", reason: "This module's knowledge is ready. Work Items are created and tracked in the core." };
3948
+ }
3949
+ const qBusiness = q3(B2), qProduct = q3(P2), qCap = q3(CAP), qCurrentState = q3(CS), qCodebase = q3(CB);
2515
3950
  if (qBusiness === "missing" || qProduct === "missing") {
2516
3951
  return { id: "bootstrap", phase: "Setup", label: "Run `kaddo bootstrap` to create the project knowledge baseline.", command: "kaddo bootstrap", reason: "The knowledge baseline is incomplete." };
2517
3952
  }
@@ -2555,12 +3990,12 @@ function resolveNextStep(dir, now = /* @__PURE__ */ new Date()) {
2555
3990
  ]
2556
3991
  };
2557
3992
  };
2558
- if (qBusiness !== "useful") return refine("refine-business", "business-agent", B, qBusiness);
3993
+ if (qBusiness !== "useful") return refine("refine-business", "business-agent", B2, qBusiness);
2559
3994
  if (qProduct !== "useful" || qCap !== "useful") {
2560
3995
  if (qCap !== "useful") {
2561
3996
  return refine("refine-product", "capability-agent", CAP, qCap, discovery ? "discover and document existing system capabilities grouped by functional domains in" : "complete");
2562
3997
  }
2563
- return refine("refine-product", "capability-agent", P, qProduct);
3998
+ return refine("refine-product", "capability-agent", P2, qProduct);
2564
3999
  }
2565
4000
  if (qCurrentState !== "useful") return refine("refine-current-state", "architecture-agent", CS, qCurrentState);
2566
4001
  if (qCodebase !== "useful") {
@@ -2577,63 +4012,42 @@ function resolveNextStep(dir, now = /* @__PURE__ */ new Date()) {
2577
4012
  const st = buildDeliveryState(dir);
2578
4013
  const secondary = buildSecondaryRecommendations(st);
2579
4014
  const roadmap = roadmapSignal(dir);
2580
- if (roadmap !== "has-candidates" && st.draft_work_items > 0) {
2581
- if (st.refined_draft_work_items > 0) {
2582
- const ids = st.refined_draft_ids;
2583
- const single = ids.length === 1;
2584
- return {
2585
- id: "review-work-item",
2586
- phase: "Active Delivery",
2587
- label: single ? `Review ${ids[0]} and mark it ready for implementation.` : "Review refined draft Work Items and mark one ready for implementation.",
2588
- command: single ? `kaddo ready ${ids[0]}` : "kaddo ready <WI-ID>",
2589
- mcpAction: "kaddo_mark_work_item_ready",
2590
- ...single ? { target: ids[0], mcpArgs: { id: ids[0] } } : { targets: ids },
2591
- reason: single ? `${ids[0]} is a refined draft Work Item awaiting human review.` : `There are ${ids.length} refined draft Work Items awaiting human review.`,
2592
- ...secondary.length ? { secondary } : {}
2593
- };
2594
- }
2595
- return {
2596
- id: "refine-work-item",
2597
- phase: "Active Delivery",
2598
- label: "Refine the existing draft Work Item with the work-item-agent.",
2599
- agent: "work-item-agent",
2600
- skill: "work-item-refinement",
2601
- reason: `There ${st.draft_work_items === 1 ? "is" : "are"} ${st.draft_work_items} draft Work Item${st.draft_work_items === 1 ? "" : "s"}. Refine before defining roadmap candidates.`,
2602
- ...secondary.length ? { secondary } : {}
2603
- };
2604
- }
2605
- if (roadmap !== "has-candidates") {
2606
- return { id: "roadmap", phase: "Planning", label: "Use roadmap-agent to define roadmap candidates (`kaddo roadmap`).", command: "kaddo roadmap", agent: "roadmap-agent", target: "knowledge/delivery/roadmap.md", reason: "The roadmap has no candidates yet." };
2607
- }
2608
- if (st.total_work_items === 0) {
2609
- return {
2610
- id: "create-work-item",
2611
- phase: "Delivery Preparation",
2612
- label: "Run `kaddo create --from roadmap` to materialize the first Work Item.",
2613
- command: "kaddo create --from roadmap",
2614
- reason: "The roadmap has candidates but no Work Item exists yet.",
2615
- ...secondary.length ? { secondary } : {}
2616
- };
2617
- }
2618
4015
  const adapters = st.adapters_installed;
2619
4016
  if (st.ready_work_items > 0) {
4017
+ const ids = st.ready_work_item_ids;
4018
+ const single = ids.length === 1;
4019
+ const sec = [...secondary];
4020
+ if (roadmap !== "has-candidates" && st.remaining_work_item_candidates === 0) {
4021
+ sec.push({
4022
+ id: "roadmap",
4023
+ label: "Roadmap has no candidates. Consider running `kaddo roadmap` after handling ready Work Items.",
4024
+ command: "kaddo roadmap",
4025
+ agent: "roadmap-agent",
4026
+ reason: "The roadmap has no candidates yet, but ready Work Items exist."
4027
+ });
4028
+ }
2620
4029
  if (adapters === 0) {
2621
4030
  return {
2622
- id: "install-adapter",
4031
+ id: "prepare-implementation",
2623
4032
  phase: "Active Delivery",
2624
- label: "Install or configure an adapter before implementation (`kaddo adapters list`).",
4033
+ label: single ? `Prepare implementation for ${ids[0]}.` : "Prepare implementation for ready Work Items.",
2625
4034
  command: "kaddo adapters list",
2626
- reason: `${st.ready_work_items} Work Item(s) are ready but no adapter is installed.`,
2627
- ...secondary.length ? { secondary } : {}
4035
+ agent: "implementation-agent",
4036
+ skill: "implementation-planning",
4037
+ ...single ? { target: ids[0] } : { targets: ids },
4038
+ reason: single ? `${ids[0]} is ready for implementation but no adapter is installed.` : `There are ${ids.length} ready Work Items awaiting implementation but no adapter is installed.`,
4039
+ ...sec.length ? { secondary: sec } : {}
2628
4040
  };
2629
4041
  }
2630
4042
  return {
2631
- id: "implement",
4043
+ id: "implement-work-item",
2632
4044
  phase: "Active Delivery",
2633
- label: "Use the implementation-agent or your installed adapter to plan implementation.",
4045
+ label: single ? `Use implementation-agent to implement ${ids[0]}.` : "Use implementation-agent to implement ready Work Items.",
2634
4046
  agent: "implementation-agent",
2635
- reason: `${st.ready_work_items} Work Item(s) are ready and an adapter is installed.`,
2636
- ...secondary.length ? { secondary } : {}
4047
+ skill: "implementation-planning",
4048
+ ...single ? { target: ids[0] } : { targets: ids },
4049
+ reason: single ? `${ids[0]} is ready for implementation.` : `There are ${ids.length} ready Work Items awaiting implementation.`,
4050
+ ...sec.length ? { secondary: sec } : {}
2637
4051
  };
2638
4052
  }
2639
4053
  if (st.in_progress_work_items > 0) {
@@ -2646,6 +4060,20 @@ function resolveNextStep(dir, now = /* @__PURE__ */ new Date()) {
2646
4060
  ...secondary.length ? { secondary } : {}
2647
4061
  };
2648
4062
  }
4063
+ if (st.refined_draft_work_items > 0) {
4064
+ const ids = st.refined_draft_ids;
4065
+ const single = ids.length === 1;
4066
+ return {
4067
+ id: "review-work-item",
4068
+ phase: "Active Delivery",
4069
+ label: single ? `Review ${ids[0]} and mark it ready for implementation.` : "Review refined draft Work Items and mark one ready for implementation.",
4070
+ command: single ? `kaddo ready ${ids[0]}` : "kaddo ready <WI-ID>",
4071
+ mcpAction: "kaddo_mark_work_item_ready",
4072
+ ...single ? { target: ids[0], mcpArgs: { id: ids[0] } } : { targets: ids },
4073
+ reason: single ? `${ids[0]} is a refined draft Work Item awaiting human review.` : `There are ${ids.length} refined draft Work Items awaiting human review.`,
4074
+ ...secondary.length ? { secondary } : {}
4075
+ };
4076
+ }
2649
4077
  if (st.draft_work_items > 0) {
2650
4078
  return {
2651
4079
  id: "refine-work-item",
@@ -2653,7 +4081,7 @@ function resolveNextStep(dir, now = /* @__PURE__ */ new Date()) {
2653
4081
  label: "Refine the existing draft Work Item with the work-item-agent.",
2654
4082
  agent: "work-item-agent",
2655
4083
  skill: "work-item-refinement",
2656
- reason: `There ${st.draft_work_items === 1 ? "is" : "are"} ${st.draft_work_items} draft Work Item${st.draft_work_items === 1 ? "" : "s"} and no Work Item is ready.`,
4084
+ reason: `There ${st.draft_work_items === 1 ? "is" : "are"} ${st.draft_work_items} draft Work Item${st.draft_work_items === 1 ? "" : "s"}. Refine before defining roadmap candidates.`,
2657
4085
  ...secondary.length ? { secondary } : {}
2658
4086
  };
2659
4087
  }
@@ -2667,6 +4095,19 @@ function resolveNextStep(dir, now = /* @__PURE__ */ new Date()) {
2667
4095
  ...secondary.length ? { secondary } : {}
2668
4096
  };
2669
4097
  }
4098
+ if (roadmap !== "has-candidates") {
4099
+ return { id: "roadmap", phase: "Planning", label: "Use roadmap-agent to define roadmap candidates (`kaddo roadmap`).", command: "kaddo roadmap", agent: "roadmap-agent", target: "knowledge/delivery/roadmap.md", reason: "The roadmap has no candidates yet." };
4100
+ }
4101
+ if (st.total_work_items === 0) {
4102
+ return {
4103
+ id: "create-work-item",
4104
+ phase: "Delivery Preparation",
4105
+ label: "Run `kaddo create --from roadmap` to materialize the first Work Item.",
4106
+ command: "kaddo create --from roadmap",
4107
+ reason: "The roadmap has candidates but no Work Item exists yet.",
4108
+ ...secondary.length ? { secondary } : {}
4109
+ };
4110
+ }
2670
4111
  if (st.remaining_work_item_candidates > 0) {
2671
4112
  return {
2672
4113
  id: "materialize-more-work-items",
@@ -2758,7 +4199,7 @@ function buildReadinessReport(dir, now = /* @__PURE__ */ new Date()) {
2758
4199
  if (config.project.state === "legacy") return stub("legacy-project", "Use the legacy project flow.");
2759
4200
  const scan = exists(join(dir, ".kaddo", "scan.json")) ? "available" : "missing";
2760
4201
  const understand = exists(join(dir, ".kaddo", "understand.md")) ? "available" : "missing";
2761
- const presence = Object.fromEntries(KNOWLEDGE_FILES.map((f) => [f.key, analyzeKnowledgeArtifact(dir, f.path)]));
4202
+ const presence = Object.fromEntries(KNOWLEDGE_FILES.map((f3) => [f3.key, analyzeKnowledgeArtifact(dir, f3.path)]));
2762
4203
  const ctx = buildCodexAdapterContext(dir);
2763
4204
  const agents = ctx.hasAgents ? "present" : "missing";
2764
4205
  const skills = ctx.hasSkills ? "present" : "missing";
@@ -2786,7 +4227,7 @@ function buildReadinessReport(dir, now = /* @__PURE__ */ new Date()) {
2786
4227
  resolved_questions: oq.summary.resolution.resolved,
2787
4228
  deferred_questions: oq.summary.resolution.deferred
2788
4229
  };
2789
- const firstWeak = KNOWLEDGE_FILES.find((f) => presence[f.key] !== "useful");
4230
+ const firstWeak = KNOWLEDGE_FILES.find((f3) => presence[f3.key] !== "useful");
2790
4231
  let overall;
2791
4232
  if (scan === "missing") overall = "initialized";
2792
4233
  else if (bootstrapBaseline2 === "incomplete") overall = "bootstrap-incomplete";
@@ -2845,7 +4286,7 @@ function skill(id, title, group, appliesTo, body) {
2845
4286
  `version: ${KADDO_VERSION}`,
2846
4287
  `group: ${group}`,
2847
4288
  "applies_to:",
2848
- ...appliesTo.map((a) => ` - ${a}`),
4289
+ ...appliesTo.map((a2) => ` - ${a2}`),
2849
4290
  "---",
2850
4291
  ""
2851
4292
  ].join("\n");
@@ -3200,6 +4641,58 @@ steps, and stop criteria (when to pause and ask).
3200
4641
  A numbered plan covering the sections above, ending with a request to confirm before coding.
3201
4642
  `
3202
4643
  );
4644
+ var MODULE_CONTEXT_REFINEMENT = skill(
4645
+ "module-context-refinement",
4646
+ "Module Context Refinement Skill",
4647
+ "tech",
4648
+ ["module-context-agent", "architecture-agent"],
4649
+ `
4650
+ # Module Context Refinement Skill
4651
+
4652
+ ## Purpose
4653
+
4654
+ Standardize how a multirepo module's context is refined without duplicating global knowledge.
4655
+
4656
+ ## When to use
4657
+
4658
+ When refining \`knowledge/module/module-context.md\` in a multirepo module repository.
4659
+
4660
+ ## Inputs
4661
+
4662
+ The module's \`module-context.md\`, local tech knowledge (\`current-state.md\`, \`codebase.md\`),
4663
+ and \u2014 optionally \u2014 the core system's context pack.
4664
+
4665
+ ## Output
4666
+
4667
+ A refined \`module-context.md\` with real, project-specific content in all sections.
4668
+
4669
+ ## Rules
4670
+
4671
+ - Use module responsibility, not full product strategy.
4672
+ - Identify boundaries and dependencies from the local code.
4673
+ - Keep business/product context in the core/system repository.
4674
+ - Document local risks and exposed interfaces.
4675
+ - Preserve frontmatter (\`type\`, \`module_id\`, \`parent_system\`).
4676
+ - Mark unknowns as open questions.
4677
+ - Do not create \`business.md\` or \`product.md\` in the module.
4678
+ - Do not install agents or skills in the module.
4679
+ - Do not create Work Items in the module.
4680
+
4681
+ ## Quality checklist
4682
+
4683
+ - Module identity and purpose are clear.
4684
+ - Responsibility and boundaries are non-overlapping with other modules.
4685
+ - Exposed interfaces are real, not invented.
4686
+ - Dependencies and consumers are listed.
4687
+ - Local rules are documented.
4688
+ - Risks are honest and specific.
4689
+ - Open questions are surfaced.
4690
+
4691
+ ## Example output
4692
+
4693
+ A \`module-context.md\` with all placeholder sections filled in.
4694
+ `
4695
+ );
3203
4696
  var SKILLS = [
3204
4697
  ADR_WRITING,
3205
4698
  WORK_ITEM_REFINEMENT,
@@ -3207,11 +4700,12 @@ var SKILLS = [
3207
4700
  GRAPH_METADATA_REVIEW,
3208
4701
  CAPSULE_WRITING,
3209
4702
  LEARNING_CAPTURE,
3210
- IMPLEMENTATION_PLANNING
4703
+ IMPLEMENTATION_PLANNING,
4704
+ MODULE_CONTEXT_REFINEMENT
3211
4705
  ];
3212
4706
  var SKILL_GROUPS = {
3213
4707
  delivery: ["work-item-refinement", "implementation-planning", "learning-capture"],
3214
- tech: ["adr-writing", "ownership-suggestion", "graph-metadata-review"],
4708
+ tech: ["adr-writing", "ownership-suggestion", "graph-metadata-review", "module-context-refinement"],
3215
4709
  integration: ["capsule-writing"]
3216
4710
  };
3217
4711
  var SKILL_GROUP_NAMES = Object.keys(SKILL_GROUPS);
@@ -3298,6 +4792,14 @@ var RESPONSIBILITY_MATRIX = {
3298
4792
  cannotSuggest: ["Git", "branches", "code"],
3299
4793
  next: ["architecture-agent"]
3300
4794
  },
4795
+ "module-context-agent": {
4796
+ agent: "module-context-agent",
4797
+ responsibleFor: ["Module context", "Responsibility", "Boundaries", "Interfaces", "Dependencies"],
4798
+ produces: ["knowledge/module/module-context.md"],
4799
+ canSuggest: ["architecture-agent"],
4800
+ cannotSuggest: ["Git", "branches", "code", "business.md", "product.md", "Work Items"],
4801
+ next: ["architecture-agent"]
4802
+ },
3301
4803
  "architecture-agent": {
3302
4804
  agent: "architecture-agent",
3303
4805
  responsibleFor: ["Architecture", "Technical state", "Risks"],
@@ -3441,25 +4943,25 @@ function list(items) {
3441
4943
  return items.length > 0 ? items.join(", ") : "\u2014";
3442
4944
  }
3443
4945
  function renderAgentBoundaries(agent) {
3444
- const r = RESPONSIBILITY_MATRIX[agent];
3445
- if (!r) return "";
4946
+ const r2 = RESPONSIBILITY_MATRIX[agent];
4947
+ if (!r2) return "";
3446
4948
  return [
3447
4949
  "## Responsibility & Boundaries",
3448
4950
  "",
3449
- `**Responsible for:** ${list(r.responsibleFor)}`,
3450
- `**Produces:** ${list(r.produces)}`,
3451
- `**May suggest:** ${list(r.canSuggest)}`,
3452
- `**Must NOT suggest:** ${list(r.cannotSuggest)}`,
4951
+ `**Responsible for:** ${list(r2.responsibleFor)}`,
4952
+ `**Produces:** ${list(r2.produces)}`,
4953
+ `**May suggest:** ${list(r2.canSuggest)}`,
4954
+ `**Must NOT suggest:** ${list(r2.cannotSuggest)}`,
3453
4955
  "",
3454
4956
  "This agent produces **knowledge only**. It never runs Git, never runs code and never runs commands. It may only suggest actions inside its own responsibility.",
3455
4957
  ""
3456
4958
  ].join("\n");
3457
4959
  }
3458
4960
  function renderAgentTrace(agent) {
3459
- const r = RESPONSIBILITY_MATRIX[agent];
3460
- if (!r) return "";
3461
- const produced = r.produces.length > 0 ? r.produces.join("\n") : "(none)";
3462
- const next = r.next.length > 0 ? r.next.join("\n") : "(end of flow)";
4961
+ const r2 = RESPONSIBILITY_MATRIX[agent];
4962
+ if (!r2) return "";
4963
+ const produced = r2.produces.length > 0 ? r2.produces.join("\n") : "(none)";
4964
+ const next = r2.next.length > 0 ? r2.next.join("\n") : "(end of flow)";
3463
4965
  return [
3464
4966
  "## Agent Trace",
3465
4967
  "",
@@ -3467,7 +4969,7 @@ function renderAgentTrace(agent) {
3467
4969
  "",
3468
4970
  "```text",
3469
4971
  "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
3470
- `Agent: ${r.agent}`,
4972
+ `Agent: ${r2.agent}`,
3471
4973
  "",
3472
4974
  "Produced:",
3473
4975
  produced,
@@ -3515,7 +5017,8 @@ var KNOWLEDGE_REFINING_AGENTS = {
3515
5017
  "work-item-agent": "work-item-agent",
3516
5018
  "backlog-agent": "backlog-agent",
3517
5019
  "adr-agent": "adr-agent",
3518
- "implementation-agent": "implementation-agent"
5020
+ "implementation-agent": "implementation-agent",
5021
+ "module-context-agent": "module-context-agent"
3519
5022
  };
3520
5023
  function renderFrontmatterRules(agent) {
3521
5024
  if (!KNOWLEDGE_REFINING_AGENTS[agent]) return "";
@@ -4735,6 +6238,92 @@ Save as \`knowledge/tech/modules/<module-name>/module-design.md\`.
4735
6238
  - Diagrams are suggested, not generated.
4736
6239
  - Assumptions and risks are explicit.
4737
6240
  `;
6241
+ var MODULE_CONTEXT_AGENT = `# Module Context Agent
6242
+
6243
+ ## Role
6244
+
6245
+ You are the Kaddo Module Context Agent. Your job is to refine the \`module-context.md\` file
6246
+ of a multirepo module from the available code and system context.
6247
+
6248
+ You do not write code. You describe the module's responsibility, boundaries, interfaces,
6249
+ dependencies, consumers, risks, and local rules. You never generate \`business.md\` or
6250
+ \`product.md\` \u2014 those belong to the core repository.
6251
+
6252
+ ## When to Use
6253
+
6254
+ Use this agent inside a multirepo **module** repository, after \`kaddo init\` has created the
6255
+ placeholder \`knowledge/module/module-context.md\`.
6256
+
6257
+ ## Input Required
6258
+
6259
+ Provide the module's \`knowledge/module/module-context.md\`, the local codebase context
6260
+ (\`knowledge/tech/current-state.md\`, \`knowledge/tech/codebase.md\`), and \u2014 if available \u2014
6261
+ the core system's \`.kaddo/context-pack.md\`.
6262
+
6263
+ ## Expected Output
6264
+
6265
+ A refined \`knowledge/module/module-context.md\` with all placeholder sections replaced by
6266
+ real, project-specific knowledge.
6267
+
6268
+ ## Instructions
6269
+
6270
+ 1. Describe the module's identity: name, purpose, and role inside the parent system.
6271
+ 2. Define responsibility: what this module owns.
6272
+ 3. Define boundaries: what belongs here and what does not.
6273
+ 4. List exposed interfaces: APIs, routes, events, tables, packages, contracts.
6274
+ 5. List dependencies: other modules, services, databases, queues, providers.
6275
+ 6. List consumers: who uses this module.
6276
+ 7. Document local rules: module-specific constraints agents must respect.
6277
+ 8. Document risks: what can go wrong when changing this module.
6278
+ 9. Surface open questions: what still needs confirmation.
6279
+
6280
+ ## Constraints
6281
+
6282
+ - Do not write code.
6283
+ - Do not generate \`business.md\` or \`product.md\` \u2014 those live in the core.
6284
+ - Do not install agents or skills \u2014 those live in the core.
6285
+ - Do not create Work Items \u2014 those live in the core.
6286
+ - Mark assumptions and unknowns clearly.
6287
+ - Preserve the existing frontmatter (\`type\`, \`module_id\`, \`parent_system\`).
6288
+
6289
+ ## Output Format
6290
+
6291
+ \`\`\`markdown
6292
+ # Module Context
6293
+
6294
+ ## Module identity
6295
+
6296
+ ## Responsibility
6297
+
6298
+ ## Boundaries
6299
+
6300
+ ## Exposed interfaces
6301
+
6302
+ ## Dependencies
6303
+
6304
+ ## Consumers
6305
+
6306
+ ## Local rules
6307
+
6308
+ ## Risks
6309
+
6310
+ ## Open questions
6311
+ \`\`\`
6312
+
6313
+ ## Where to Save the Result
6314
+
6315
+ Save as \`knowledge/module/module-context.md\`.
6316
+
6317
+ ## Quality Checklist
6318
+
6319
+ - Module identity and purpose are clear.
6320
+ - Responsibility and boundaries are explicit and non-overlapping.
6321
+ - Exposed interfaces are real, not invented.
6322
+ - Dependencies and consumers are listed.
6323
+ - Local rules are documented.
6324
+ - Risks are honest and specific.
6325
+ - Open questions are surfaced, not hidden.
6326
+ `;
4738
6327
  var BUSINESS_AGENT = `# Business Agent
4739
6328
 
4740
6329
  ## Role
@@ -5332,6 +6921,7 @@ var AGENT_PROMPTS = [
5332
6921
  { fileName: "standards-agent.md", content: STANDARDS_AGENT },
5333
6922
  { fileName: "stack-agent.md", content: STACK_AGENT },
5334
6923
  { fileName: "module-design-agent.md", content: MODULE_DESIGN_AGENT },
6924
+ { fileName: "module-context-agent.md", content: MODULE_CONTEXT_AGENT },
5335
6925
  // Bootstrap agents (new projects)
5336
6926
  { fileName: "business-agent.md", content: BUSINESS_AGENT },
5337
6927
  { fileName: "bootstrap-agent.md", content: BOOTSTRAP_AGENT },
@@ -5432,9 +7022,9 @@ var agentReadme = {
5432
7022
  "- `graph-agent.md` \u2014 review `kaddo graph export` hints and propose precise relationship front matter."
5433
7023
  ].join("\n")
5434
7024
  };
5435
- var agentFiles = AGENT_PROMPTS.map((a) => ({
5436
- path: agentInstallPath(a.fileName),
5437
- content: withAgentFrontMatter(a.fileName, a.content)
7025
+ var agentFiles = AGENT_PROMPTS.map((a2) => ({
7026
+ path: agentInstallPath(a2.fileName),
7027
+ content: withAgentFrontMatter(a2.fileName, a2.content)
5438
7028
  }));
5439
7029
  var agentsModule = {
5440
7030
  name: "agents",
@@ -5486,10 +7076,10 @@ var agentsModule = {
5486
7076
 
5487
7077
  // ../cli/src/core/assets.ts
5488
7078
  function canonicalAgents() {
5489
- return AGENT_PROMPTS.map((a) => ({
5490
- name: a.fileName.replace(/\.md$/, ""),
5491
- path: agentInstallPath(a.fileName),
5492
- content: withAgentFrontMatter(a.fileName, a.content)
7079
+ return AGENT_PROMPTS.map((a2) => ({
7080
+ name: a2.fileName.replace(/\.md$/, ""),
7081
+ path: agentInstallPath(a2.fileName),
7082
+ content: withAgentFrontMatter(a2.fileName, a2.content)
5493
7083
  }));
5494
7084
  }
5495
7085
  function canonicalSkills() {
@@ -5503,12 +7093,12 @@ function versionOf(content) {
5503
7093
  return null;
5504
7094
  }
5505
7095
  }
5506
- function cmpVersion(a, b) {
5507
- const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
5508
- const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
7096
+ function cmpVersion(a2, b2) {
7097
+ const pa = a2.split(".").map((n) => parseInt(n, 10) || 0);
7098
+ const pb = b2.split(".").map((n) => parseInt(n, 10) || 0);
5509
7099
  for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
5510
- const d = (pa[i] ?? 0) - (pb[i] ?? 0);
5511
- if (d !== 0) return d < 0 ? -1 : 1;
7100
+ const d3 = (pa[i] ?? 0) - (pb[i] ?? 0);
7101
+ if (d3 !== 0) return d3 < 0 ? -1 : 1;
5512
7102
  }
5513
7103
  return 0;
5514
7104
  }
@@ -5543,7 +7133,7 @@ function summarize(items) {
5543
7133
  }
5544
7134
  function assetStatus(dir, kind) {
5545
7135
  const catalog = kind === "agent" ? canonicalAgents() : canonicalSkills();
5546
- return summarize(catalog.map((a) => classify(dir, a)));
7136
+ return summarize(catalog.map((a2) => classify(dir, a2)));
5547
7137
  }
5548
7138
  function installedAssetsSummary(dir) {
5549
7139
  return { version: KADDO_VERSION, agents: assetStatus(dir, "agent"), skills: assetStatus(dir, "skill") };
@@ -5554,14 +7144,14 @@ var ROADMAP_PATH = "knowledge/delivery/roadmap.md";
5554
7144
  var INITIATIVE_RE2 = /^#{2,4}\s+(RM-[\w.-]+)\s*[:\-–]?\s*(.*)$/;
5555
7145
  function fieldPresent(lines, label) {
5556
7146
  for (let i = 0; i < lines.length; i++) {
5557
- const m = lines[i].match(new RegExp(`^\\s*[-*]?\\s*(?:\\*\\*)?\\s*(${label.source})\\s*(?:\\*\\*)?\\s*:\\s*(.*)$`, "i"));
5558
- if (!m) continue;
5559
- const inline = m[2].trim();
7147
+ const m2 = lines[i].match(new RegExp(`^\\s*[-*]?\\s*(?:\\*\\*)?\\s*(${label.source})\\s*(?:\\*\\*)?\\s*:\\s*(.*)$`, "i"));
7148
+ if (!m2) continue;
7149
+ const inline = m2[2].trim();
5560
7150
  if (inline) return true;
5561
- for (let j = i + 1; j < lines.length; j++) {
5562
- if (/^\s{2,}[-*]\s+\S/.test(lines[j])) return true;
5563
- if (/^\S/.test(lines[j]) || /^#{2,4}\s/.test(lines[j])) break;
5564
- if (/^\s*[-*]\s+\S/.test(lines[j]) && !/^\s{2,}/.test(lines[j])) break;
7151
+ for (let j2 = i + 1; j2 < lines.length; j2++) {
7152
+ if (/^\s{2,}[-*]\s+\S/.test(lines[j2])) return true;
7153
+ if (/^\S/.test(lines[j2]) || /^#{2,4}\s/.test(lines[j2])) break;
7154
+ if (/^\s*[-*]\s+\S/.test(lines[j2]) && !/^\s{2,}/.test(lines[j2])) break;
5565
7155
  }
5566
7156
  }
5567
7157
  return false;
@@ -5586,10 +7176,10 @@ function parseRoadmapCandidateQuality(md) {
5586
7176
  cur = null;
5587
7177
  };
5588
7178
  for (const line of lines) {
5589
- const m = line.match(INITIATIVE_RE2);
5590
- if (m) {
7179
+ const m2 = line.match(INITIATIVE_RE2);
7180
+ if (m2) {
5591
7181
  flush();
5592
- cur = { id: m[1], title: m[2].trim(), lines: [] };
7182
+ cur = { id: m2[1], title: m2[2].trim(), lines: [] };
5593
7183
  continue;
5594
7184
  }
5595
7185
  if (cur) cur.lines.push(line);
@@ -5765,8 +7355,8 @@ function optStr(v) {
5765
7355
  }
5766
7356
 
5767
7357
  // ../cli/src/core/project-route.ts
5768
- function isUseful(q) {
5769
- return q === "useful";
7358
+ function isUseful(q3) {
7359
+ return q3 === "useful";
5770
7360
  }
5771
7361
  var enableKaddo = {
5772
7362
  id: "enable-kaddo",
@@ -6051,9 +7641,9 @@ function buildRouteContext(dir) {
6051
7641
  }
6052
7642
  }
6053
7643
  const stats = roadmapStats(roadmapMd, wis.length);
6054
- const byState = (s) => wis.filter((w) => w.lifecycle === s).length;
7644
+ const byState = (s) => wis.filter((w3) => w3.lifecycle === s).length;
6055
7645
  const total = wis.length;
6056
- const withOwnership = wis.filter((w) => w.codeGlobs.length > 0).length;
7646
+ const withOwnership = wis.filter((w3) => w3.codeGlobs.length > 0).length;
6057
7647
  const adapters = installedAdapters(dir);
6058
7648
  const nextStep = resolveNextStep(dir);
6059
7649
  return {
@@ -6082,8 +7672,8 @@ function buildRouteContext(dir) {
6082
7672
  adaptersInstalled: adapters.length,
6083
7673
  hasGuardHistory: exists(join(dir, ".kaddo", "history", "guard-runs.jsonl")),
6084
7674
  hasScanWarnings: hasScan ? loadScanWarnings(dir) : false,
6085
- hasUnknownSources: wis.some((w) => {
6086
- const src = parseWorkItemSource(w.rawFrontmatter);
7675
+ hasUnknownSources: wis.some((w3) => {
7676
+ const src = parseWorkItemSource(w3.rawFrontmatter);
6087
7677
  return src.type === "unknown" && src.inferred;
6088
7678
  }),
6089
7679
  nextStepId: mapNextStepId(nextStep.id)
@@ -6110,7 +7700,12 @@ function mapNextStepId(id) {
6110
7700
  "refine-capabilities": "discover-capabilities",
6111
7701
  "refine-current-state": "describe-architecture",
6112
7702
  "refine-codebase": "describe-architecture",
6113
- "review-work-item": "refine-work-item"
7703
+ "review-work-item": "refine-work-item",
7704
+ "prepare-implementation": "prepare-implementation",
7705
+ "implement-work-item": "prepare-implementation",
7706
+ "refine-module-context": "refine-work-item",
7707
+ "init-module-context": "enable-kaddo",
7708
+ "module-ready": "prepare-implementation"
6114
7709
  };
6115
7710
  return MAP[id] ?? id;
6116
7711
  }
@@ -6119,9 +7714,9 @@ function buildProjectRoute(dir) {
6119
7714
  const state = config?.project.state ?? "pre-ai";
6120
7715
  const defs = stepsForState(state);
6121
7716
  const ctx = buildRouteContext(dir);
6122
- const steps = defs.map((d) => {
6123
- const result = d.evaluate(ctx);
6124
- return { id: d.id, label: d.label, ...result };
7717
+ const steps = defs.map((d3) => {
7718
+ const result = d3.evaluate(ctx);
7719
+ return { id: d3.id, label: d3.label, ...result };
6125
7720
  });
6126
7721
  for (const s of steps) {
6127
7722
  if (s.id === ctx.nextStepId && s.status !== "done") {
@@ -6185,8 +7780,8 @@ function renderRouteCompact(route) {
6185
7780
  const warnings = route.steps.filter((s) => s.status === "warning");
6186
7781
  if (warnings.length > 0) {
6187
7782
  lines.push("Warnings:");
6188
- for (const w of warnings) {
6189
- lines.push(`- ${w.label}${w.reason ? ` \u2014 ${w.reason}` : ""}`);
7783
+ for (const w3 of warnings) {
7784
+ lines.push(`- ${w3.label}${w3.reason ? ` \u2014 ${w3.reason}` : ""}`);
6190
7785
  }
6191
7786
  lines.push("");
6192
7787
  }
@@ -6252,10 +7847,10 @@ function findDuplicateWorkItems(items) {
6252
7847
  const bucket = (key, reason, pred) => {
6253
7848
  const matched = items.filter(pred);
6254
7849
  if (matched.length > 1) {
6255
- const id = `${reason}:${key}:${matched.map((m) => m.id).sort().join(",")}`;
7850
+ const id = `${reason}:${key}:${matched.map((m2) => m2.id).sort().join(",")}`;
6256
7851
  if (!seen.has(id)) {
6257
7852
  seen.add(id);
6258
- groups.push({ reason, items: matched.map((m) => ({ id: m.id, title: m.title })) });
7853
+ groups.push({ reason, items: matched.map((m2) => ({ id: m2.id, title: m2.title })) });
6259
7854
  }
6260
7855
  }
6261
7856
  };
@@ -6269,7 +7864,7 @@ function findDuplicateWorkItems(items) {
6269
7864
  }
6270
7865
  function first(values) {
6271
7866
  if (Array.isArray(values)) {
6272
- const v = values.find((x) => typeof x === "string" && x);
7867
+ const v = values.find((x2) => typeof x2 === "string" && x2);
6273
7868
  return v ? String(v) : void 0;
6274
7869
  }
6275
7870
  return typeof values === "string" && values ? values : void 0;
@@ -6309,9 +7904,9 @@ function loadScanSignals(dir) {
6309
7904
  function hasAgents(dir) {
6310
7905
  const agentsDir = join(dir, ARCH_DIR2, "agents");
6311
7906
  if (!exists(agentsDir)) return false;
6312
- function hasAgentMd(d) {
6313
- for (const e of readDir(d)) {
6314
- const full = join(d, e);
7907
+ function hasAgentMd(d3) {
7908
+ for (const e of readDir(d3)) {
7909
+ const full = join(d3, e);
6315
7910
  if (isFile(full)) {
6316
7911
  if (e.endsWith("-agent.md")) return true;
6317
7912
  } else if (hasAgentMd(full)) {
@@ -6351,7 +7946,7 @@ function buildProjectExplanation(dir) {
6351
7946
  infrastructureFiles: scan.infrastructureFiles
6352
7947
  } : null;
6353
7948
  const layers = knowledgeLayers(dir);
6354
- const layerStatus = (name) => layers.find((l) => l.layer === name)?.status ?? "Missing";
7949
+ const layerStatus = (name) => layers.find((l2) => l2.layer === name)?.status ?? "Missing";
6355
7950
  const knowledge = {
6356
7951
  hasScan: scan !== null,
6357
7952
  hasInventory: exists(join(dir, ARCH_DIR2, "inventory.md")),
@@ -6366,18 +7961,18 @@ function buildProjectExplanation(dir) {
6366
7961
  hasSkills: hasSkills(dir)
6367
7962
  };
6368
7963
  const workItemArtifacts = discoverWorkItems(dir);
6369
- const items = workItemArtifacts.map((a) => {
6370
- const src = parseWorkItemSource(a.rawFrontmatter);
7964
+ const items = workItemArtifacts.map((a2) => {
7965
+ const src = parseWorkItemSource(a2.rawFrontmatter);
6371
7966
  return {
6372
- id: a.id || a.title,
6373
- title: a.title,
6374
- type: a.type,
6375
- status: a.status,
6376
- lifecycle: lifecycleStateOf({ status: a.status, filePath: a.filePath }),
6377
- initiative: a.initiative,
6378
- knowledgeLevel: a.knowledgeLevel,
6379
- hasOwnership: a.codeGlobs.length > 0,
6380
- domains: a.domains,
7967
+ id: a2.id || a2.title,
7968
+ title: a2.title,
7969
+ type: a2.type,
7970
+ status: a2.status,
7971
+ lifecycle: lifecycleStateOf({ status: a2.status, filePath: a2.filePath }),
7972
+ initiative: a2.initiative,
7973
+ knowledgeLevel: a2.knowledgeLevel,
7974
+ hasOwnership: a2.codeGlobs.length > 0,
7975
+ domains: a2.domains,
6381
7976
  source: { type: src.type, ...src.id ? { id: src.id } : {}, inferred: src.inferred }
6382
7977
  };
6383
7978
  });
@@ -6393,7 +7988,7 @@ function buildProjectExplanation(dir) {
6393
7988
  if (!initiativeMap.has(name)) initiativeMap.set(name, emptyLifecycleCounts());
6394
7989
  initiativeMap.get(name)[i.lifecycle]++;
6395
7990
  }
6396
- const initiatives = [...initiativeMap.entries()].map(([name, states]) => ({ name, states })).sort((a, b) => a.name.localeCompare(b.name));
7991
+ const initiatives = [...initiativeMap.entries()].map(([name, states]) => ({ name, states })).sort((a2, b2) => a2.name.localeCompare(b2.name));
6397
7992
  const workItems = {
6398
7993
  total: items.length,
6399
7994
  inProgress: items.filter((i) => i.lifecycle === "in-progress").length,
@@ -6410,9 +8005,9 @@ function buildProjectExplanation(dir) {
6410
8005
  workItemsWithOwnership: withOwnership,
6411
8006
  workItemsMissingOwnership: items.length - withOwnership
6412
8007
  };
6413
- const domains = [...new Set(workItemArtifacts.flatMap((a) => a.domains))].filter(Boolean);
8008
+ const domains = [...new Set(workItemArtifacts.flatMap((a2) => a2.domains))].filter(Boolean);
6414
8009
  const duplicateWorkItems = findDuplicateWorkItems(
6415
- workItemArtifacts.map((a) => ({ id: a.id || a.title, title: a.title, sourceId: a.sourceId }))
8010
+ workItemArtifacts.map((a2) => ({ id: a2.id || a2.title, title: a2.title, sourceId: a2.sourceId }))
6416
8011
  );
6417
8012
  const roadmapPath = join(dir, ARCH_DIR2, "delivery", "roadmap.md");
6418
8013
  const roadmapMd = exists(roadmapPath) ? readFile(roadmapPath) : null;
@@ -6553,7 +8148,7 @@ function renderExplanationHuman(exp) {
6553
8148
  lines.push("## Scan Signals");
6554
8149
  lines.push(renderSignalsCompact(exp.scanSignals));
6555
8150
  }
6556
- const ls = (name) => exp.layers.find((l) => l.layer === name)?.status ?? "Missing";
8151
+ const ls = (name) => exp.layers.find((l2) => l2.layer === name)?.status ?? "Missing";
6557
8152
  lines.push("## Knowledge Status");
6558
8153
  lines.push(`- Inventory: ${exp.knowledge.hasInventory ? "available" : "missing"}`);
6559
8154
  lines.push(`- Context pack: ${exp.knowledge.hasContextPack ? "available" : "missing"}`);
@@ -6581,7 +8176,7 @@ function renderExplanationHuman(exp) {
6581
8176
  lines.push(`- ${LIFECYCLE_LABEL[s2]}: ${exp.workItems.byState[s2]}`);
6582
8177
  }
6583
8178
  lines.push("");
6584
- const typeEntries = Object.entries(exp.workItems.byType).sort((a, b) => b[1] - a[1]);
8179
+ const typeEntries = Object.entries(exp.workItems.byType).sort((a2, b2) => b2[1] - a2[1]);
6585
8180
  if (typeEntries.length > 0) {
6586
8181
  lines.push("## Work Items by Type");
6587
8182
  for (const [t, n] of typeEntries) lines.push(`- ${typeLabel(t)}: ${n}`);
@@ -6629,15 +8224,15 @@ function renderExplanationHuman(exp) {
6629
8224
  }
6630
8225
  lines.push("## Mapped Modules");
6631
8226
  if (exp.mappedModules.length > 0) {
6632
- for (const m of exp.mappedModules) {
6633
- const owner = m.owner ? ` \u2014 owner: ${m.owner}` : "";
6634
- lines.push(`- ${m.id} \u2014 ${m.type ?? "unknown"} \u2014 ${m.repoPath || "\u2014"}${owner}`);
8227
+ for (const m2 of exp.mappedModules) {
8228
+ const owner = m2.owner ? ` \u2014 owner: ${m2.owner}` : "";
8229
+ lines.push(`- ${m2.id} \u2014 ${m2.type ?? "unknown"} \u2014 ${m2.repoPath || "\u2014"}${owner}`);
6635
8230
  }
6636
8231
  lines.push("");
6637
8232
  lines.push("## Module Artifact Coverage");
6638
- for (const m of exp.mappedModules) {
6639
- const present = presentArtifacts(m.artifacts);
6640
- lines.push(`- ${m.id}: ${present.length > 0 ? present.join(", ") : "none"}`);
8233
+ for (const m2 of exp.mappedModules) {
8234
+ const present = presentArtifacts(m2.artifacts);
8235
+ lines.push(`- ${m2.id}: ${present.length > 0 ? present.join(", ") : "none"}`);
6641
8236
  }
6642
8237
  lines.push("");
6643
8238
  } else {
@@ -6673,7 +8268,7 @@ function renderExplanationHuman(exp) {
6673
8268
  }
6674
8269
  if (exp.skills.total > 0) {
6675
8270
  lines.push(`## Skills installed: ${exp.skills.total}`);
6676
- const groups = Object.entries(exp.skills.byGroup).sort((a, b) => a[0].localeCompare(b[0]));
8271
+ const groups = Object.entries(exp.skills.byGroup).sort((a2, b2) => a2[0].localeCompare(b2[0]));
6677
8272
  if (groups.length > 0) {
6678
8273
  lines.push("Groups:");
6679
8274
  for (const [g, n] of groups) lines.push(`- ${g}: ${n}`);
@@ -6682,7 +8277,7 @@ function renderExplanationHuman(exp) {
6682
8277
  }
6683
8278
  if (exp.missingKnowledge.length > 0) {
6684
8279
  lines.push("## Missing Knowledge");
6685
- for (const m of exp.missingKnowledge) lines.push(`- ${m}`);
8280
+ for (const m2 of exp.missingKnowledge) lines.push(`- ${m2}`);
6686
8281
  lines.push("");
6687
8282
  }
6688
8283
  if (exp.duplicateWorkItems.length > 0) {
@@ -6700,7 +8295,7 @@ function renderExplanationHuman(exp) {
6700
8295
  lines.push(`- Phase: ${assessment.phase}`);
6701
8296
  if (assessment.reasons.length > 0) {
6702
8297
  lines.push("- Reason:");
6703
- for (const r2 of assessment.reasons) lines.push(` - ${r2}`);
8298
+ for (const r3 of assessment.reasons) lines.push(` - ${r3}`);
6704
8299
  }
6705
8300
  lines.push(`- Next step: ${exp.readiness.recommended_next_step.label}`);
6706
8301
  lines.push("");
@@ -6712,11 +8307,11 @@ function renderExplanationHuman(exp) {
6712
8307
  steps.forEach((s2, i) => lines.push(`${i + 1}. ${s2}`));
6713
8308
  lines.push("");
6714
8309
  }
6715
- const r = exp.readiness;
6716
- const s = r.signals;
8310
+ const r2 = exp.readiness;
8311
+ const s = r2.signals;
6717
8312
  lines.push("## Project Readiness");
6718
- lines.push(`- overall: ${r.overall}`);
6719
- if (r.overall !== "not-initialized" && r.overall !== "not-applicable" && r.overall !== "legacy-project") {
8313
+ lines.push(`- overall: ${r2.overall}`);
8314
+ if (r2.overall !== "not-initialized" && r2.overall !== "not-applicable" && r2.overall !== "legacy-project") {
6720
8315
  lines.push(`- bootstrap baseline: ${s.bootstrap_baseline}`);
6721
8316
  lines.push(`- scan: ${s.scan}`);
6722
8317
  lines.push(`- understand: ${s.understand}`);
@@ -6736,11 +8331,11 @@ function renderExplanationHuman(exp) {
6736
8331
  }
6737
8332
  lines.push("");
6738
8333
  lines.push("### Recommended next step");
6739
- lines.push(r.recommended_next_step.label);
8334
+ lines.push(r2.recommended_next_step.label);
6740
8335
  lines.push("");
6741
8336
  const td = exp.techDecisions;
6742
8337
  const tk = exp.techKnowledge;
6743
- const mark = (b) => b ? "\u2713" : "\u2717";
8338
+ const mark = (b2) => b2 ? "\u2713" : "\u2717";
6744
8339
  lines.push("## Tech Knowledge");
6745
8340
  lines.push("Core:");
6746
8341
  lines.push(`- ${mark(tk.core.currentState)} current-state.md`);
@@ -6815,8 +8410,8 @@ function renderExplanationHuman(exp) {
6815
8410
  }
6816
8411
  if (exp.metadataHealth.findings.length > 0) {
6817
8412
  lines.push("## Metadata Health");
6818
- for (const f of exp.metadataHealth.findings) {
6819
- lines.push(`- \`${f.file}\`: ${f.detail}`);
8413
+ for (const f3 of exp.metadataHealth.findings) {
8414
+ lines.push(`- \`${f3.file}\`: ${f3.detail}`);
6820
8415
  }
6821
8416
  lines.push("");
6822
8417
  }
@@ -6849,30 +8444,30 @@ function loadGuardRuns(dir) {
6849
8444
  return out;
6850
8445
  }
6851
8446
  function resolveDriftThreads(runs) {
6852
- const sorted = [...runs].sort((a, b) => a.generated_at.localeCompare(b.generated_at));
8447
+ const sorted = [...runs].sort((a2, b2) => a2.generated_at.localeCompare(b2.generated_at));
6853
8448
  const paths = /* @__PURE__ */ new Set();
6854
- for (const r of sorted) for (const w of r.warnings) paths.add(w.code_path);
8449
+ for (const r2 of sorted) for (const w3 of r2.warnings) paths.add(w3.code_path);
6855
8450
  const threads = [];
6856
8451
  for (const codePath of paths) {
6857
8452
  const related = /* @__PURE__ */ new Set();
6858
8453
  let firstDetected = "";
6859
8454
  let lastWarn = "";
6860
- for (const r of sorted) {
6861
- const w = r.warnings.find((x) => x.code_path === codePath);
6862
- if (w) {
6863
- if (!firstDetected) firstDetected = r.generated_at;
6864
- lastWarn = r.generated_at;
6865
- for (const a of w.related_artifacts) related.add(a);
8455
+ for (const r2 of sorted) {
8456
+ const w3 = r2.warnings.find((x2) => x2.code_path === codePath);
8457
+ if (w3) {
8458
+ if (!firstDetected) firstDetected = r2.generated_at;
8459
+ lastWarn = r2.generated_at;
8460
+ for (const a2 of w3.related_artifacts) related.add(a2);
6866
8461
  }
6867
8462
  }
6868
8463
  let resolvedAt;
6869
- for (const r of sorted) {
6870
- if (r.generated_at <= lastWarn) continue;
6871
- const touched = r.touched_files.some((f) => toPosix5(f) === codePath);
6872
- const warnedHere = r.warnings.some((x) => x.code_path === codePath);
6873
- const updatedRelated = r.updated_artifacts.some((a) => related.has(a));
8464
+ for (const r2 of sorted) {
8465
+ if (r2.generated_at <= lastWarn) continue;
8466
+ const touched = r2.touched_files.some((f3) => toPosix5(f3) === codePath);
8467
+ const warnedHere = r2.warnings.some((x2) => x2.code_path === codePath);
8468
+ const updatedRelated = r2.updated_artifacts.some((a2) => related.has(a2));
6874
8469
  if (touched && updatedRelated && !warnedHere) {
6875
- resolvedAt = r.generated_at;
8470
+ resolvedAt = r2.generated_at;
6876
8471
  break;
6877
8472
  }
6878
8473
  }
@@ -6893,9 +8488,9 @@ function hotspotDir(codePath) {
6893
8488
  }
6894
8489
  function computeTrend(runs) {
6895
8490
  if (runs.length < 2) return { direction: "unknown", reason: "Not enough recorded runs to detect a trend." };
6896
- const sorted = [...runs].sort((a, b) => a.generated_at.localeCompare(b.generated_at));
8491
+ const sorted = [...runs].sort((a2, b2) => a2.generated_at.localeCompare(b2.generated_at));
6897
8492
  const mid = Math.floor(sorted.length / 2);
6898
- const avg = (arr) => arr.length ? arr.reduce((s, r) => s + r.warnings.length, 0) / arr.length : 0;
8493
+ const avg = (arr) => arr.length ? arr.reduce((s, r2) => s + r2.warnings.length, 0) / arr.length : 0;
6899
8494
  const earlier = avg(sorted.slice(0, mid));
6900
8495
  const recent = avg(sorted.slice(mid));
6901
8496
  if (recent < earlier) return { direction: "improving", reason: "Fewer warnings in the last recorded runs." };
@@ -6921,18 +8516,18 @@ function buildGuardHistory(dir) {
6921
8516
  trend: { direction: "unknown", reason: "No guard history recorded yet." }
6922
8517
  };
6923
8518
  }
6924
- const sorted = [...runs].sort((a, b) => a.generated_at.localeCompare(b.generated_at));
8519
+ const sorted = [...runs].sort((a2, b2) => a2.generated_at.localeCompare(b2.generated_at));
6925
8520
  const threads = resolveDriftThreads(sorted);
6926
8521
  const open = threads.filter((t) => t.status === "open").length;
6927
8522
  const resolved = threads.filter((t) => t.status === "resolved").length;
6928
8523
  const detected = threads.length;
6929
- const runsWithWarnings = sorted.filter((r) => r.warnings.length > 0).length;
8524
+ const runsWithWarnings = sorted.filter((r2) => r2.warnings.length > 0).length;
6930
8525
  const hotspotMap = /* @__PURE__ */ new Map();
6931
8526
  for (const t of threads) {
6932
- const d = hotspotDir(t.code_path);
6933
- hotspotMap.set(d, (hotspotMap.get(d) ?? 0) + 1);
8527
+ const d3 = hotspotDir(t.code_path);
8528
+ hotspotMap.set(d3, (hotspotMap.get(d3) ?? 0) + 1);
6934
8529
  }
6935
- const hotspots = [...hotspotMap.entries()].map(([path3, warnings]) => ({ path: path3, warnings })).sort((a, b) => b.warnings - a.warnings);
8530
+ const hotspots = [...hotspotMap.entries()].map(([path3, warnings]) => ({ path: path3, warnings })).sort((a2, b2) => b2.warnings - a2.warnings);
6936
8531
  return {
6937
8532
  available: true,
6938
8533
  total_runs: sorted.length,
@@ -6956,14 +8551,14 @@ function isBroadGlob(glob) {
6956
8551
  const prefix = glob.slice(0, -3);
6957
8552
  return prefix.length > 0 && prefix.split("/").length <= 2;
6958
8553
  }
6959
- function levelFromRatio(r) {
6960
- if (r >= 0.9) return "Very High";
6961
- if (r >= 0.7) return "High";
6962
- if (r >= 0.4) return "Medium";
8554
+ function levelFromRatio(r2) {
8555
+ if (r2 >= 0.9) return "Very High";
8556
+ if (r2 >= 0.7) return "High";
8557
+ if (r2 >= 0.4) return "Medium";
6963
8558
  return "Low";
6964
8559
  }
6965
8560
  function hasSection(body, re) {
6966
- return body.split(/\r?\n/).some((l) => /^#{1,6}\s+/.test(l) && re.test(l));
8561
+ return body.split(/\r?\n/).some((l2) => /^#{1,6}\s+/.test(l2) && re.test(l2));
6967
8562
  }
6968
8563
  function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
6969
8564
  const resolvedScope = opts.scope ?? "all";
@@ -7029,7 +8624,7 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7029
8624
  } catch {
7030
8625
  }
7031
8626
  }
7032
- const ownedCodePaths = [...globCounts.values()].reduce((a, b) => a + b, 0);
8627
+ const ownedCodePaths = [...globCounts.values()].reduce((a2, b2) => a2 + b2, 0);
7033
8628
  const broadGlobs = [...globCounts.keys()].filter((g2) => isBroadGlob(g2)).length;
7034
8629
  for (const [glob, owners] of globOwners) {
7035
8630
  if (owners.length > 1) {
@@ -7046,7 +8641,7 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7046
8641
  } else {
7047
8642
  g = { available: false, scope: resolvedScope, scopeReason: "", nodes: 0, edges: 0, quality: "unknown", hints: 0, generatedAt: "" };
7048
8643
  }
7049
- const layerStatus = (name) => exp.layers.find((l) => l.layer === name)?.status ?? "Missing";
8644
+ const layerStatus = (name) => exp.layers.find((l2) => l2.layer === name)?.status ?? "Missing";
7050
8645
  const byState = exp.workItems.byState;
7051
8646
  const skills = discoverInstalledSkills(dir);
7052
8647
  const knowledge_health = {
@@ -7116,7 +8711,7 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7116
8711
  let score_breakdown = null;
7117
8712
  if (total > 0) {
7118
8713
  const healthPts = [layerStatus("Business"), layerStatus("Product"), layerStatus("Tech"), layerStatus("Delivery")].filter((s) => s !== "Missing").length / 4 * 20;
7119
- const covAvg = knowledge_coverage.reduce((a, c) => a + coverageRatio(c.have), 0) / knowledge_coverage.length;
8714
+ const covAvg = knowledge_coverage.reduce((a2, c) => a2 + coverageRatio(c.have), 0) / knowledge_coverage.length;
7120
8715
  const coveragePts = covAvg * 20;
7121
8716
  const ownPts = coverageRatio(withOwnership) * 15;
7122
8717
  const traceBlend = (exp.roadmap.candidates > 0 ? exp.roadmap.materialized / exp.roadmap.candidates : 1) * 0.5 + coverageRatio(withOwnership) * 0.5;
@@ -7144,14 +8739,14 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7144
8739
  if (!g.available) actions.push("Run `kaddo graph export --scope all` to inspect full traceability.");
7145
8740
  else if (g.scope === "active" && g.quality === "empty") actions.push("Run `kaddo impact --scope all` to measure accumulated knowledge impact.");
7146
8741
  if (exp.roadmap.remaining > 0) actions.push(`Materialize the ${exp.roadmap.remaining} remaining roadmap candidate(s) with \`kaddo create --from roadmap\`.`);
7147
- for (const a of [
8742
+ for (const a2 of [
7148
8743
  groupedAction(gaps.missing_code_ownership, "Add `code:` ownership to"),
7149
8744
  groupedAction(gaps.missing_source, "Add `source`/`source_id` to"),
7150
8745
  groupedAction(gaps.missing_initiative, "Add an `initiative` to"),
7151
8746
  groupedAction(gaps.missing_acceptance_criteria, "Add Acceptance Criteria to"),
7152
8747
  groupedAction(gaps.missing_definition_of_done, "Add a Definition of Done to"),
7153
8748
  groupedAction(gaps.missing_validation, "Add a validation (How to test it) section to")
7154
- ]) if (a) actions.push(a);
8749
+ ]) if (a2) actions.push(a2);
7155
8750
  if (gaps.broad_ownership_globs.length > 0) actions.push(`Narrow ${gaps.broad_ownership_globs.length} broad ownership glob(s) into specific paths.`);
7156
8751
  if (g.available && g.hints > 0) actions.push("Review graph hints (`kaddo://graph-hints` or `.kaddo/graph-hints.md`).");
7157
8752
  if (skills.length === 0) actions.push("Install reusable skills with `kaddo add skills`.");
@@ -7215,38 +8810,38 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7215
8810
  function ratio(have, total) {
7216
8811
  return `${have}/${total}`;
7217
8812
  }
7218
- function renderImpactMarkdown(r) {
8813
+ function renderImpactMarkdown(r2) {
7219
8814
  const L = [];
7220
8815
  L.push("# Kaddo Knowledge Impact Report", "");
7221
- L.push(`Generated at: ${r.generated_at}`);
7222
- L.push(`Project: ${r.project}`);
7223
- L.push(`Scope: ${r.scope}`);
7224
- if (r.score !== null) L.push(`Knowledge Impact Score: ${r.score}/100`);
8816
+ L.push(`Generated at: ${r2.generated_at}`);
8817
+ L.push(`Project: ${r2.project}`);
8818
+ L.push(`Scope: ${r2.scope}`);
8819
+ if (r2.score !== null) L.push(`Knowledge Impact Score: ${r2.score}/100`);
7225
8820
  else L.push("Knowledge Impact Score: not available");
7226
- if (r.scope_source === "default") {
8821
+ if (r2.scope_source === "default") {
7227
8822
  L.push("Scope note: Impact reports use `all` by default to measure accumulated knowledge impact.");
7228
- } else if (r.scope === "active" && r.graph_quality.available === false) {
8823
+ } else if (r2.scope === "active" && r2.graph_quality.available === false) {
7229
8824
  L.push("Tip: Run `kaddo impact --scope all` to inspect accumulated knowledge impact.");
7230
8825
  }
7231
8826
  L.push("");
7232
8827
  L.push("## Executive Summary", "");
7233
- for (const s2 of r.executive_summary) L.push(`- ${s2}`);
8828
+ for (const s2 of r2.executive_summary) L.push(`- ${s2}`);
7234
8829
  L.push("");
7235
8830
  L.push("## Knowledge Health", "");
7236
- for (const [k, v] of Object.entries(r.knowledge_health)) L.push(`- ${k}: ${v}`);
8831
+ for (const [k2, v] of Object.entries(r2.knowledge_health)) L.push(`- ${k2}: ${v}`);
7237
8832
  L.push("");
7238
8833
  L.push("## Knowledge Coverage", "");
7239
- for (const c of r.knowledge_coverage) L.push(`- ${c.label}: ${ratio(c.have, c.total)}`);
8834
+ for (const c of r2.knowledge_coverage) L.push(`- ${c.label}: ${ratio(c.have, c.total)}`);
7240
8835
  L.push("");
7241
8836
  L.push("## Ownership Coverage", "");
7242
- L.push(`- Coverage: ${r.ownership_coverage.coverage_percent}%`);
7243
- L.push(`- Work Items with code ownership: ${r.ownership_coverage.work_items_with_ownership}`);
7244
- L.push(`- Owned code paths: ${r.ownership_coverage.owned_code_paths}`);
7245
- L.push(`- Broad globs detected: ${r.ownership_coverage.broad_globs}`);
7246
- L.push(`- Ownership overlaps: ${r.ownership_coverage.ownership_overlaps}`);
8837
+ L.push(`- Coverage: ${r2.ownership_coverage.coverage_percent}%`);
8838
+ L.push(`- Work Items with code ownership: ${r2.ownership_coverage.work_items_with_ownership}`);
8839
+ L.push(`- Owned code paths: ${r2.ownership_coverage.owned_code_paths}`);
8840
+ L.push(`- Broad globs detected: ${r2.ownership_coverage.broad_globs}`);
8841
+ L.push(`- Ownership overlaps: ${r2.ownership_coverage.ownership_overlaps}`);
7247
8842
  L.push("");
7248
8843
  L.push("## Traceability", "");
7249
- const t = r.traceability;
8844
+ const t = r2.traceability;
7250
8845
  L.push(`- Roadmap candidates: ${t.roadmap_candidates}`);
7251
8846
  L.push(`- Materialized Work Items: ${t.materialized_work_items}`);
7252
8847
  L.push(`- Remaining candidates: ${t.remaining_candidates}`);
@@ -7259,24 +8854,24 @@ function renderImpactMarkdown(r) {
7259
8854
  if (t.graph_hints !== null) L.push(`- Graph hints: ${t.graph_hints}`);
7260
8855
  L.push("");
7261
8856
  L.push("## Context Readiness", "");
7262
- L.push(`Context Readiness: ${r.context_readiness.level}`);
7263
- if (r.context_readiness.reasons.length > 0) {
8857
+ L.push(`Context Readiness: ${r2.context_readiness.level}`);
8858
+ if (r2.context_readiness.reasons.length > 0) {
7264
8859
  L.push("", "Reason:");
7265
- for (const reason of r.context_readiness.reasons) L.push(`- ${reason}`);
8860
+ for (const reason of r2.context_readiness.reasons) L.push(`- ${reason}`);
7266
8861
  }
7267
8862
  L.push("");
7268
8863
  L.push("## Work Item Readiness", "");
7269
- const w = r.work_item_readiness;
7270
- L.push(`- Draft: ${w.draft}`);
7271
- L.push(`- Ready: ${w.ready}`);
7272
- L.push(`- In Progress: ${w.in_progress}`);
7273
- L.push(`- Blocked: ${w.blocked}`);
7274
- L.push(`- Completed: ${w.completed}`);
7275
- L.push(`- Ready quality: ${w.ready_quality}`);
8864
+ const w3 = r2.work_item_readiness;
8865
+ L.push(`- Draft: ${w3.draft}`);
8866
+ L.push(`- Ready: ${w3.ready}`);
8867
+ L.push(`- In Progress: ${w3.in_progress}`);
8868
+ L.push(`- Blocked: ${w3.blocked}`);
8869
+ L.push(`- Completed: ${w3.completed}`);
8870
+ L.push(`- Ready quality: ${w3.ready_quality}`);
7276
8871
  L.push("");
7277
8872
  L.push("## Graph Quality", "");
7278
- if (r.graph_quality.available) {
7279
- const gq = r.graph_quality;
8873
+ if (r2.graph_quality.available) {
8874
+ const gq = r2.graph_quality;
7280
8875
  L.push(`- Scope: ${gq.scope}`);
7281
8876
  L.push(`- Quality: ${gq.quality}`);
7282
8877
  L.push(`- Nodes: ${gq.nodes}`);
@@ -7289,12 +8884,12 @@ function renderImpactMarkdown(r) {
7289
8884
  }
7290
8885
  } else {
7291
8886
  L.push("- Graph data not available.");
7292
- L.push(`- Tip: ${r.graph_quality.suggestion}`);
8887
+ L.push(`- Tip: ${r2.graph_quality.suggestion}`);
7293
8888
  }
7294
8889
  L.push("");
7295
8890
  L.push("## Guard Activity", "");
7296
- if (r.guard_activity.available) {
7297
- const ga = r.guard_activity;
8891
+ if (r2.guard_activity.available) {
8892
+ const ga = r2.guard_activity;
7298
8893
  L.push("- Guard history: available");
7299
8894
  L.push(`- Guard runs recorded: ${ga.runs_recorded}`);
7300
8895
  L.push(`- Drift warnings detected: ${ga.detected}`);
@@ -7303,11 +8898,11 @@ function renderImpactMarkdown(r) {
7303
8898
  L.push(`- Resolution rate: ${ga.resolution_rate}%`);
7304
8899
  } else {
7305
8900
  L.push("- Guard history: not available");
7306
- L.push(`- Note: ${r.guard_activity.note}`);
8901
+ L.push(`- Note: ${r2.guard_activity.note}`);
7307
8902
  }
7308
8903
  L.push("");
7309
8904
  L.push("## Impact Signals", "");
7310
- const s = r.impact_signals;
8905
+ const s = r2.impact_signals;
7311
8906
  L.push(`- Ambiguity reduction: ${s.ambiguity_reduction}`);
7312
8907
  L.push(`- Drift prevention: ${s.drift_prevention}`);
7313
8908
  L.push(`- Onboarding support: ${s.onboarding_support}`);
@@ -7316,7 +8911,7 @@ function renderImpactMarkdown(r) {
7316
8911
  L.push(`- Maintenance readiness: ${s.maintenance_readiness}`);
7317
8912
  L.push("");
7318
8913
  L.push("## Actionable Gaps", "");
7319
- const gp = r.actionable_gaps;
8914
+ const gp = r2.actionable_gaps;
7320
8915
  const gapSection = (title, items) => {
7321
8916
  if (items.length === 0) return;
7322
8917
  L.push(`### ${title}`, "");
@@ -7336,19 +8931,19 @@ function renderImpactMarkdown(r) {
7336
8931
  gapSection("Work Items missing validation", gp.missing_validation);
7337
8932
  if (gp.broad_ownership_globs.length > 0) {
7338
8933
  L.push("### Broad ownership globs", "");
7339
- for (const b of gp.broad_ownership_globs) {
7340
- L.push(`- ${b.id} \u2014 ${b.title}`);
7341
- L.push(` - Glob: \`${b.glob}\``);
7342
- L.push(` - Suggested action: ${b.suggested_action}`);
8934
+ for (const b2 of gp.broad_ownership_globs) {
8935
+ L.push(`- ${b2.id} \u2014 ${b2.title}`);
8936
+ L.push(` - Glob: \`${b2.glob}\``);
8937
+ L.push(` - Suggested action: ${b2.suggested_action}`);
7343
8938
  }
7344
8939
  L.push("");
7345
8940
  }
7346
8941
  if (gp.ownership_overlaps.length > 0) {
7347
8942
  L.push("### Ownership overlaps", "");
7348
- for (const o of gp.ownership_overlaps) {
7349
- L.push(`- \`${o.code_path}\``);
7350
- L.push(` - Owned by: ${o.work_items.join(", ")}`);
7351
- L.push(` - Suggested action: ${o.suggested_action}`);
8943
+ for (const o2 of gp.ownership_overlaps) {
8944
+ L.push(`- \`${o2.code_path}\``);
8945
+ L.push(` - Owned by: ${o2.work_items.join(", ")}`);
8946
+ L.push(` - Suggested action: ${o2.suggested_action}`);
7352
8947
  }
7353
8948
  L.push("");
7354
8949
  }
@@ -7356,28 +8951,28 @@ function renderImpactMarkdown(r) {
7356
8951
  if (anyGaps === 0) {
7357
8952
  L.push("No actionable knowledge gaps detected. \u{1F389}", "");
7358
8953
  }
7359
- if (r.score_breakdown) {
8954
+ if (r2.score_breakdown) {
7360
8955
  L.push("## Score Breakdown", "");
7361
- const b = r.score_breakdown;
7362
- L.push(`- Knowledge Health: ${b.knowledge_health.points}/${b.knowledge_health.max}`);
7363
- L.push(`- Knowledge Coverage: ${b.knowledge_coverage.points}/${b.knowledge_coverage.max}`);
7364
- L.push(`- Ownership Coverage: ${b.ownership_coverage.points}/${b.ownership_coverage.max}`);
7365
- L.push(`- Traceability: ${b.traceability.points}/${b.traceability.max}`);
7366
- L.push(`- Graph Quality: ${b.graph_quality.points}/${b.graph_quality.max}`);
7367
- L.push(`- Context Readiness: ${b.context_readiness.points}/${b.context_readiness.max}`);
8956
+ const b2 = r2.score_breakdown;
8957
+ L.push(`- Knowledge Health: ${b2.knowledge_health.points}/${b2.knowledge_health.max}`);
8958
+ L.push(`- Knowledge Coverage: ${b2.knowledge_coverage.points}/${b2.knowledge_coverage.max}`);
8959
+ L.push(`- Ownership Coverage: ${b2.ownership_coverage.points}/${b2.ownership_coverage.max}`);
8960
+ L.push(`- Traceability: ${b2.traceability.points}/${b2.traceability.max}`);
8961
+ L.push(`- Graph Quality: ${b2.graph_quality.points}/${b2.graph_quality.max}`);
8962
+ L.push(`- Context Readiness: ${b2.context_readiness.points}/${b2.context_readiness.max}`);
7368
8963
  L.push("");
7369
8964
  }
7370
8965
  L.push("## Suggested Actions", "");
7371
- r.suggested_actions.forEach((a, i) => L.push(`${i + 1}. ${a}`));
8966
+ r2.suggested_actions.forEach((a2, i) => L.push(`${i + 1}. ${a2}`));
7372
8967
  L.push("");
7373
8968
  return L.join("\n");
7374
8969
  }
7375
- function serializeImpactJson(r) {
7376
- return JSON.stringify(r, null, 2) + "\n";
8970
+ function serializeImpactJson(r2) {
8971
+ return JSON.stringify(r2, null, 2) + "\n";
7377
8972
  }
7378
8973
 
7379
8974
  // ../cli/src/core/savings.ts
7380
- import { parse as parseYaml6 } from "yaml";
8975
+ import { parse as parseYaml7 } from "yaml";
7381
8976
  var DEFAULT_ASSUMPTIONS = {
7382
8977
  currency: "USD",
7383
8978
  hourly_cost: 40,
@@ -7395,21 +8990,21 @@ function loadAssumptions(dir) {
7395
8990
  const p = join(dir, SAVINGS_PATH);
7396
8991
  if (!exists(p)) return { assumptions: { ...DEFAULT_ASSUMPTIONS }, source: "default" };
7397
8992
  try {
7398
- const raw = parseYaml6(readFile(p));
7399
- const a = raw?.assumptions ?? {};
8993
+ const raw = parseYaml7(readFile(p));
8994
+ const a2 = raw?.assumptions ?? {};
7400
8995
  const t = raw?.team ?? {};
7401
- const num = (v, d) => typeof v === "number" && Number.isFinite(v) ? v : d;
8996
+ const num = (v, d3) => typeof v === "number" && Number.isFinite(v) ? v : d3;
7402
8997
  return {
7403
8998
  source: "file",
7404
8999
  assumptions: {
7405
9000
  currency: raw?.currency ?? DEFAULT_ASSUMPTIONS.currency,
7406
9001
  hourly_cost: num(raw?.hourly_cost, DEFAULT_ASSUMPTIONS.hourly_cost),
7407
- context_preparation_minutes_saved_per_work_item: num(a.context_preparation_minutes_saved_per_work_item, DEFAULT_ASSUMPTIONS.context_preparation_minutes_saved_per_work_item),
7408
- rework_hours_avoided_per_resolved_drift: num(a.rework_hours_avoided_per_resolved_drift, DEFAULT_ASSUMPTIONS.rework_hours_avoided_per_resolved_drift),
7409
- onboarding_hours_saved_per_new_contributor: num(a.onboarding_hours_saved_per_new_contributor, DEFAULT_ASSUMPTIONS.onboarding_hours_saved_per_new_contributor),
7410
- review_minutes_saved_per_work_item_with_ownership: num(a.review_minutes_saved_per_work_item_with_ownership, DEFAULT_ASSUMPTIONS.review_minutes_saved_per_work_item_with_ownership),
7411
- clarification_minutes_saved_per_ready_work_item: num(a.clarification_minutes_saved_per_ready_work_item, DEFAULT_ASSUMPTIONS.clarification_minutes_saved_per_ready_work_item),
7412
- architecture_discovery_hours_saved_when_graph_good: num(a.architecture_discovery_hours_saved_when_graph_good, DEFAULT_ASSUMPTIONS.architecture_discovery_hours_saved_when_graph_good),
9002
+ context_preparation_minutes_saved_per_work_item: num(a2.context_preparation_minutes_saved_per_work_item, DEFAULT_ASSUMPTIONS.context_preparation_minutes_saved_per_work_item),
9003
+ rework_hours_avoided_per_resolved_drift: num(a2.rework_hours_avoided_per_resolved_drift, DEFAULT_ASSUMPTIONS.rework_hours_avoided_per_resolved_drift),
9004
+ onboarding_hours_saved_per_new_contributor: num(a2.onboarding_hours_saved_per_new_contributor, DEFAULT_ASSUMPTIONS.onboarding_hours_saved_per_new_contributor),
9005
+ review_minutes_saved_per_work_item_with_ownership: num(a2.review_minutes_saved_per_work_item_with_ownership, DEFAULT_ASSUMPTIONS.review_minutes_saved_per_work_item_with_ownership),
9006
+ clarification_minutes_saved_per_ready_work_item: num(a2.clarification_minutes_saved_per_ready_work_item, DEFAULT_ASSUMPTIONS.clarification_minutes_saved_per_ready_work_item),
9007
+ architecture_discovery_hours_saved_when_graph_good: num(a2.architecture_discovery_hours_saved_when_graph_good, DEFAULT_ASSUMPTIONS.architecture_discovery_hours_saved_when_graph_good),
7413
9008
  expected_new_contributors_per_month: num(t.expected_new_contributors_per_month, DEFAULT_ASSUMPTIONS.expected_new_contributors_per_month),
7414
9009
  expected_work_items_per_month: num(t.expected_work_items_per_month, DEFAULT_ASSUMPTIONS.expected_work_items_per_month)
7415
9010
  }
@@ -7422,12 +9017,12 @@ var READINESS_MULT = { Low: 0.25, Medium: 0.5, High: 0.75, "Very High": 1 };
7422
9017
  var GRAPH_MULT = { empty: 0, sparse: 0.25, partial: 0.6, good: 1, unknown: 0 };
7423
9018
  var round2 = (n) => Math.round(n * 100) / 100;
7424
9019
  function parseRatioNumerator(s) {
7425
- const m = s.match(/^(\d+)/);
7426
- return m ? Number(m[1]) : 0;
9020
+ const m2 = s.match(/^(\d+)/);
9021
+ return m2 ? Number(m2[1]) : 0;
7427
9022
  }
7428
9023
  var SAVINGS_DISCLAIMER = "These are evidence-based estimates, not exact ROI. Adjust assumptions with real team data.";
7429
9024
  function buildSavingsReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7430
- const { assumptions: a, source } = loadAssumptions(dir);
9025
+ const { assumptions: a2, source } = loadAssumptions(dir);
7431
9026
  const impact = buildImpactReport(dir, { scope: opts.scope, scopeSource: opts.scopeSource }, now);
7432
9027
  const completed = impact.traceability.completed_work_items;
7433
9028
  const wiWithOwnership = parseRatioNumerator(impact.traceability.work_items_connected_to_code);
@@ -7435,13 +9030,13 @@ function buildSavingsReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7435
9030
  const wiWithAcceptance = acceptanceCov?.have ?? 0;
7436
9031
  const graphQuality = impact.graph_quality.available ? impact.graph_quality.quality : "unknown";
7437
9032
  const readiness = impact.context_readiness.level;
7438
- const ctxPrepH = round2(completed * a.context_preparation_minutes_saved_per_work_item / 60);
7439
- const reviewH = round2(wiWithOwnership * a.review_minutes_saved_per_work_item_with_ownership / 60);
7440
- const clarH = round2(wiWithAcceptance * a.clarification_minutes_saved_per_ready_work_item / 60);
9033
+ const ctxPrepH = round2(completed * a2.context_preparation_minutes_saved_per_work_item / 60);
9034
+ const reviewH = round2(wiWithOwnership * a2.review_minutes_saved_per_work_item_with_ownership / 60);
9035
+ const clarH = round2(wiWithAcceptance * a2.clarification_minutes_saved_per_ready_work_item / 60);
7441
9036
  const readinessMult = READINESS_MULT[readiness] ?? 0.5;
7442
- const onboardH = round2(a.expected_new_contributors_per_month * a.onboarding_hours_saved_per_new_contributor * readinessMult);
9037
+ const onboardH = round2(a2.expected_new_contributors_per_month * a2.onboarding_hours_saved_per_new_contributor * readinessMult);
7443
9038
  const graphMult = GRAPH_MULT[graphQuality] ?? 0;
7444
- const archH = round2(a.architecture_discovery_hours_saved_when_graph_good * graphMult);
9039
+ const archH = round2(a2.architecture_discovery_hours_saved_when_graph_good * graphMult);
7445
9040
  const guard = buildGuardHistory(dir);
7446
9041
  let driftSavings;
7447
9042
  if (!guard.available) {
@@ -7449,19 +9044,19 @@ function buildSavingsReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7449
9044
  } else if (guard.resolved > 0) {
7450
9045
  driftSavings = {
7451
9046
  available: true,
7452
- hours: round2(guard.resolved * a.rework_hours_avoided_per_resolved_drift),
7453
- formula: `${guard.resolved} resolved drift warnings \xD7 ${a.rework_hours_avoided_per_resolved_drift} h`
9047
+ hours: round2(guard.resolved * a2.rework_hours_avoided_per_resolved_drift),
9048
+ formula: `${guard.resolved} resolved drift warnings \xD7 ${a2.rework_hours_avoided_per_resolved_drift} h`
7454
9049
  };
7455
9050
  } else {
7456
9051
  driftSavings = {
7457
9052
  available: true,
7458
9053
  hours: 0,
7459
- formula: `0 resolved drift warnings \xD7 ${a.rework_hours_avoided_per_resolved_drift} h`,
9054
+ formula: `0 resolved drift warnings \xD7 ${a2.rework_hours_avoided_per_resolved_drift} h`,
7460
9055
  reason: "Guard history exists, but no resolved drift warnings have been recorded yet."
7461
9056
  };
7462
9057
  }
7463
9058
  const totalHours = round2(ctxPrepH + reviewH + clarH + onboardH + archH + driftSavings.hours);
7464
- const totalValue = Math.round(totalHours * a.hourly_cost);
9059
+ const totalValue = Math.round(totalHours * a2.hourly_cost);
7465
9060
  const reasons = [];
7466
9061
  let level;
7467
9062
  if (impact.score === null || impact.score < 60 || graphQuality === "empty") {
@@ -7499,17 +9094,17 @@ function buildSavingsReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7499
9094
  generated_at: now.toISOString(),
7500
9095
  project: impact.project,
7501
9096
  scope: impact.scope,
7502
- currency: a.currency,
9097
+ currency: a2.currency,
7503
9098
  disclaimer: SAVINGS_DISCLAIMER,
7504
9099
  assumptions_source: source,
7505
9100
  assumptions: {
7506
- hourly_cost: a.hourly_cost,
7507
- context_preparation_minutes_saved_per_work_item: a.context_preparation_minutes_saved_per_work_item,
7508
- review_minutes_saved_per_work_item_with_ownership: a.review_minutes_saved_per_work_item_with_ownership,
7509
- clarification_minutes_saved_per_ready_work_item: a.clarification_minutes_saved_per_ready_work_item,
7510
- onboarding_hours_saved_per_new_contributor: a.onboarding_hours_saved_per_new_contributor,
7511
- expected_new_contributors_per_month: a.expected_new_contributors_per_month,
7512
- architecture_discovery_hours_saved_when_graph_good: a.architecture_discovery_hours_saved_when_graph_good
9101
+ hourly_cost: a2.hourly_cost,
9102
+ context_preparation_minutes_saved_per_work_item: a2.context_preparation_minutes_saved_per_work_item,
9103
+ review_minutes_saved_per_work_item_with_ownership: a2.review_minutes_saved_per_work_item_with_ownership,
9104
+ clarification_minutes_saved_per_ready_work_item: a2.clarification_minutes_saved_per_ready_work_item,
9105
+ onboarding_hours_saved_per_new_contributor: a2.onboarding_hours_saved_per_new_contributor,
9106
+ expected_new_contributors_per_month: a2.expected_new_contributors_per_month,
9107
+ architecture_discovery_hours_saved_when_graph_good: a2.architecture_discovery_hours_saved_when_graph_good
7513
9108
  },
7514
9109
  evidence: {
7515
9110
  knowledge_impact_score: impact.score,
@@ -7525,45 +9120,45 @@ function buildSavingsReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7525
9120
  resolved_drift_warnings: guard.resolved
7526
9121
  },
7527
9122
  estimated_savings: {
7528
- context_preparation: { hours: ctxPrepH, formula: `${completed} Work Items \xD7 ${a.context_preparation_minutes_saved_per_work_item} min` },
7529
- review_effort: { hours: reviewH, formula: `${wiWithOwnership} Work Items with ownership \xD7 ${a.review_minutes_saved_per_work_item_with_ownership} min` },
7530
- clarification_reduction: { hours: clarH, formula: `${wiWithAcceptance} Work Items with Acceptance Criteria \xD7 ${a.clarification_minutes_saved_per_ready_work_item} min` },
7531
- onboarding: { hours: onboardH, formula: `${a.expected_new_contributors_per_month} contributor \xD7 ${a.onboarding_hours_saved_per_new_contributor} h \xD7 ${readinessMult.toFixed(2)} readiness multiplier` },
7532
- architecture_discovery: { hours: archH, formula: `${a.architecture_discovery_hours_saved_when_graph_good} h \xD7 ${graphMult.toFixed(2)} graph multiplier` },
9123
+ context_preparation: { hours: ctxPrepH, formula: `${completed} Work Items \xD7 ${a2.context_preparation_minutes_saved_per_work_item} min` },
9124
+ review_effort: { hours: reviewH, formula: `${wiWithOwnership} Work Items with ownership \xD7 ${a2.review_minutes_saved_per_work_item_with_ownership} min` },
9125
+ clarification_reduction: { hours: clarH, formula: `${wiWithAcceptance} Work Items with Acceptance Criteria \xD7 ${a2.clarification_minutes_saved_per_ready_work_item} min` },
9126
+ onboarding: { hours: onboardH, formula: `${a2.expected_new_contributors_per_month} contributor \xD7 ${a2.onboarding_hours_saved_per_new_contributor} h \xD7 ${readinessMult.toFixed(2)} readiness multiplier` },
9127
+ architecture_discovery: { hours: archH, formula: `${a2.architecture_discovery_hours_saved_when_graph_good} h \xD7 ${graphMult.toFixed(2)} graph multiplier` },
7533
9128
  drift_prevention: driftSavings
7534
9129
  },
7535
- total: { estimated_hours_saved: totalHours, estimated_value: totalValue, currency: a.currency },
9130
+ total: { estimated_hours_saved: totalHours, estimated_value: totalValue, currency: a2.currency },
7536
9131
  confidence: { level, reasons },
7537
9132
  suggested_actions: actions
7538
9133
  };
7539
9134
  }
7540
- function renderSavingsMarkdown(r) {
9135
+ function renderSavingsMarkdown(r2) {
7541
9136
  const L = [];
7542
9137
  L.push("# Kaddo Estimated Savings Report", "");
7543
- L.push(`Generated at: ${r.generated_at}`);
7544
- L.push(`Project: ${r.project}`);
7545
- L.push(`Scope: ${r.scope}`);
7546
- L.push(`Currency: ${r.currency}`);
9138
+ L.push(`Generated at: ${r2.generated_at}`);
9139
+ L.push(`Project: ${r2.project}`);
9140
+ L.push(`Scope: ${r2.scope}`);
9141
+ L.push(`Currency: ${r2.currency}`);
7547
9142
  L.push("");
7548
9143
  L.push("## Disclaimer", "");
7549
- L.push(r.disclaimer, "");
9144
+ L.push(r2.disclaimer, "");
7550
9145
  L.push("## Executive Summary", "");
7551
- L.push(`- Estimated time saved: ${r.total.estimated_hours_saved} hours`);
7552
- L.push(`- Estimated value: ${r.total.estimated_value} ${r.currency}`);
7553
- L.push(`- Confidence: ${r.confidence.level}`);
7554
- if (r.assumptions_source === "default") L.push("- Using default assumptions. Run `kaddo savings init` to customize them.");
9146
+ L.push(`- Estimated time saved: ${r2.total.estimated_hours_saved} hours`);
9147
+ L.push(`- Estimated value: ${r2.total.estimated_value} ${r2.currency}`);
9148
+ L.push(`- Confidence: ${r2.confidence.level}`);
9149
+ if (r2.assumptions_source === "default") L.push("- Using default assumptions. Run `kaddo savings init` to customize them.");
7555
9150
  L.push("");
7556
9151
  L.push("## Assumptions", "");
7557
- L.push(`- Hourly cost: ${r.assumptions.hourly_cost} ${r.currency}`);
7558
- L.push(`- Context preparation saved per Work Item: ${r.assumptions.context_preparation_minutes_saved_per_work_item} min`);
7559
- L.push(`- Review saved per Work Item with ownership: ${r.assumptions.review_minutes_saved_per_work_item_with_ownership} min`);
7560
- L.push(`- Clarification saved per Work Item with acceptance criteria: ${r.assumptions.clarification_minutes_saved_per_ready_work_item} min`);
7561
- L.push(`- Onboarding saved per new contributor: ${r.assumptions.onboarding_hours_saved_per_new_contributor} h`);
7562
- L.push(`- Expected new contributors per month: ${r.assumptions.expected_new_contributors_per_month}`);
7563
- L.push(`- Architecture discovery saved when graph is good: ${r.assumptions.architecture_discovery_hours_saved_when_graph_good} h`);
9152
+ L.push(`- Hourly cost: ${r2.assumptions.hourly_cost} ${r2.currency}`);
9153
+ L.push(`- Context preparation saved per Work Item: ${r2.assumptions.context_preparation_minutes_saved_per_work_item} min`);
9154
+ L.push(`- Review saved per Work Item with ownership: ${r2.assumptions.review_minutes_saved_per_work_item_with_ownership} min`);
9155
+ L.push(`- Clarification saved per Work Item with acceptance criteria: ${r2.assumptions.clarification_minutes_saved_per_ready_work_item} min`);
9156
+ L.push(`- Onboarding saved per new contributor: ${r2.assumptions.onboarding_hours_saved_per_new_contributor} h`);
9157
+ L.push(`- Expected new contributors per month: ${r2.assumptions.expected_new_contributors_per_month}`);
9158
+ L.push(`- Architecture discovery saved when graph is good: ${r2.assumptions.architecture_discovery_hours_saved_when_graph_good} h`);
7564
9159
  L.push("");
7565
9160
  L.push("## Evidence Used", "");
7566
- const e = r.evidence;
9161
+ const e = r2.evidence;
7567
9162
  L.push(`- Knowledge Impact Score: ${e.knowledge_impact_score ?? "not available"}${e.knowledge_impact_score !== null ? "/100" : ""}`);
7568
9163
  L.push(`- Completed Work Items: ${e.completed_work_items}`);
7569
9164
  L.push(`- Ownership coverage: ${e.ownership_coverage_percent}%`);
@@ -7581,11 +9176,11 @@ function renderSavingsMarkdown(r) {
7581
9176
  }
7582
9177
  L.push("");
7583
9178
  L.push("## Estimated Savings", "");
7584
- const s = r.estimated_savings;
7585
- const line = (title, l) => {
9179
+ const s = r2.estimated_savings;
9180
+ const line = (title, l2) => {
7586
9181
  L.push(`### ${title}`, "");
7587
- L.push(`- Formula: ${l.formula}`);
7588
- L.push(`- Estimated: ${l.hours} h`, "");
9182
+ L.push(`- Formula: ${l2.formula}`);
9183
+ L.push(`- Estimated: ${l2.hours} h`, "");
7589
9184
  };
7590
9185
  line("Context Preparation", s.context_preparation);
7591
9186
  line("Review Effort", s.review_effort);
@@ -7603,31 +9198,31 @@ function renderSavingsMarkdown(r) {
7603
9198
  L.push(`- Reason: ${s.drift_prevention.reason}`, "");
7604
9199
  }
7605
9200
  L.push("## Total", "");
7606
- L.push(`- Estimated time saved: ${r.total.estimated_hours_saved} h`);
7607
- L.push(`- Estimated value: ${r.total.estimated_value} ${r.currency}`);
9201
+ L.push(`- Estimated time saved: ${r2.total.estimated_hours_saved} h`);
9202
+ L.push(`- Estimated value: ${r2.total.estimated_value} ${r2.currency}`);
7608
9203
  L.push("");
7609
9204
  L.push("## Confidence", "");
7610
- L.push(`Confidence: ${r.confidence.level}`, "", "Reason:");
7611
- for (const reason of r.confidence.reasons) L.push(`- ${reason}`);
9205
+ L.push(`Confidence: ${r2.confidence.level}`, "", "Reason:");
9206
+ for (const reason of r2.confidence.reasons) L.push(`- ${reason}`);
7612
9207
  L.push("");
7613
9208
  L.push("## Suggested Actions", "");
7614
- r.suggested_actions.forEach((act, i) => L.push(`${i + 1}. ${act}`));
9209
+ r2.suggested_actions.forEach((act, i) => L.push(`${i + 1}. ${act}`));
7615
9210
  L.push("");
7616
9211
  return L.join("\n");
7617
9212
  }
7618
- function serializeSavingsJson(r) {
7619
- return JSON.stringify(r, null, 2) + "\n";
9213
+ function serializeSavingsJson(r2) {
9214
+ return JSON.stringify(r2, null, 2) + "\n";
7620
9215
  }
7621
9216
 
7622
9217
  // ../cli/src/core/drift-report.ts
7623
9218
  function buildDriftReport(dir, now = /* @__PURE__ */ new Date()) {
7624
- const h = buildGuardHistory(dir);
9219
+ const h2 = buildGuardHistory(dir);
7625
9220
  const project = loadConfig(dir)?.project.name ?? "unknown";
7626
9221
  const actions = [];
7627
- if (!h.available) {
9222
+ if (!h2.available) {
7628
9223
  actions.push("Run `kaddo guard --record` to start recording guard history.");
7629
9224
  } else {
7630
- if (h.open > 0) actions.push("Review open drift warnings and update related Work Items or ownership.");
9225
+ if (h2.open > 0) actions.push("Review open drift warnings and update related Work Items or ownership.");
7631
9226
  actions.push("Run `kaddo guard --record` before important commits.");
7632
9227
  actions.push("Use this report to calibrate estimated drift-prevention savings.");
7633
9228
  }
@@ -7635,55 +9230,55 @@ function buildDriftReport(dir, now = /* @__PURE__ */ new Date()) {
7635
9230
  generated_at: now.toISOString(),
7636
9231
  project,
7637
9232
  guard_history: {
7638
- available: h.available,
7639
- total_runs: h.total_runs,
7640
- first_run: h.first_run,
7641
- last_run: h.last_run,
7642
- runs_with_warnings: h.runs_with_warnings,
7643
- runs_clean: h.runs_clean
9233
+ available: h2.available,
9234
+ total_runs: h2.total_runs,
9235
+ first_run: h2.first_run,
9236
+ last_run: h2.last_run,
9237
+ runs_with_warnings: h2.runs_with_warnings,
9238
+ runs_clean: h2.runs_clean
7644
9239
  },
7645
- drift_warnings: { detected: h.detected, open: h.open, resolved: h.resolved, resolution_rate: h.resolution_rate },
7646
- hotspots: h.hotspots,
7647
- trend: h.trend,
7648
- threads: h.threads,
9240
+ drift_warnings: { detected: h2.detected, open: h2.open, resolved: h2.resolved, resolution_rate: h2.resolution_rate },
9241
+ hotspots: h2.hotspots,
9242
+ trend: h2.trend,
9243
+ threads: h2.threads,
7649
9244
  suggested_actions: actions
7650
9245
  };
7651
9246
  }
7652
- function renderDriftMarkdown(r) {
9247
+ function renderDriftMarkdown(r2) {
7653
9248
  const L = [];
7654
9249
  L.push("# Kaddo Drift Trend Report", "");
7655
- L.push(`Generated at: ${r.generated_at}`);
7656
- L.push(`Project: ${r.project}`);
9250
+ L.push(`Generated at: ${r2.generated_at}`);
9251
+ L.push(`Project: ${r2.project}`);
7657
9252
  L.push("");
7658
- if (!r.guard_history.available) {
9253
+ if (!r2.guard_history.available) {
7659
9254
  L.push("## Guard History", "");
7660
9255
  L.push("No guard history recorded yet.");
7661
9256
  L.push("");
7662
9257
  L.push("Run `kaddo guard --record` to start recording drift evidence.");
7663
9258
  L.push("");
7664
9259
  L.push("## Suggested Actions", "");
7665
- r.suggested_actions.forEach((a, i) => L.push(`${i + 1}. ${a}`));
9260
+ r2.suggested_actions.forEach((a2, i) => L.push(`${i + 1}. ${a2}`));
7666
9261
  L.push("");
7667
9262
  return L.join("\n");
7668
9263
  }
7669
- const w = r.drift_warnings;
9264
+ const w3 = r2.drift_warnings;
7670
9265
  L.push("## Executive Summary", "");
7671
- L.push(`- Guard runs recorded: ${r.guard_history.total_runs}`);
7672
- L.push(`- Drift warnings detected: ${w.detected}`);
7673
- L.push(`- Open warnings: ${w.open}`);
7674
- L.push(`- Resolved warnings: ${w.resolved}`);
7675
- L.push(`- Resolution rate: ${w.resolution_rate}%`);
7676
- if (r.hotspots.length > 0) L.push(`- Most affected area: ${r.hotspots[0].path}`);
9266
+ L.push(`- Guard runs recorded: ${r2.guard_history.total_runs}`);
9267
+ L.push(`- Drift warnings detected: ${w3.detected}`);
9268
+ L.push(`- Open warnings: ${w3.open}`);
9269
+ L.push(`- Resolved warnings: ${w3.resolved}`);
9270
+ L.push(`- Resolution rate: ${w3.resolution_rate}%`);
9271
+ if (r2.hotspots.length > 0) L.push(`- Most affected area: ${r2.hotspots[0].path}`);
7677
9272
  L.push("");
7678
9273
  L.push("## Guard History", "");
7679
- L.push(`- First run: ${r.guard_history.first_run}`);
7680
- L.push(`- Last run: ${r.guard_history.last_run}`);
7681
- L.push(`- Runs with warnings: ${r.guard_history.runs_with_warnings}/${r.guard_history.total_runs}`);
7682
- L.push(`- Runs clean: ${r.guard_history.runs_clean}/${r.guard_history.total_runs}`);
9274
+ L.push(`- First run: ${r2.guard_history.first_run}`);
9275
+ L.push(`- Last run: ${r2.guard_history.last_run}`);
9276
+ L.push(`- Runs with warnings: ${r2.guard_history.runs_with_warnings}/${r2.guard_history.total_runs}`);
9277
+ L.push(`- Runs clean: ${r2.guard_history.runs_clean}/${r2.guard_history.total_runs}`);
7683
9278
  L.push("");
7684
9279
  L.push("## Drift Warnings", "");
7685
- const open = r.threads.filter((t) => t.status === "open");
7686
- const resolved = r.threads.filter((t) => t.status === "resolved");
9280
+ const open = r2.threads.filter((t) => t.status === "open");
9281
+ const resolved = r2.threads.filter((t) => t.status === "resolved");
7687
9282
  L.push("### Open", "");
7688
9283
  if (open.length === 0) L.push("_None._", "");
7689
9284
  for (const t of open) {
@@ -7705,28 +9300,28 @@ function renderDriftMarkdown(r) {
7705
9300
  }
7706
9301
  L.push("");
7707
9302
  L.push("## Hotspots", "");
7708
- if (r.hotspots.length === 0) L.push("_None._");
7709
- for (const h of r.hotspots) L.push(`- ${h.path}: ${h.warnings} warning(s)`);
9303
+ if (r2.hotspots.length === 0) L.push("_None._");
9304
+ for (const h2 of r2.hotspots) L.push(`- ${h2.path}: ${h2.warnings} warning(s)`);
7710
9305
  L.push("");
7711
9306
  L.push("## Trend", "");
7712
- L.push(`- Recent direction: ${r.trend.direction}`);
7713
- L.push(`- Reason: ${r.trend.reason}`);
9307
+ L.push(`- Recent direction: ${r2.trend.direction}`);
9308
+ L.push(`- Reason: ${r2.trend.reason}`);
7714
9309
  L.push("");
7715
9310
  L.push("## Suggested Actions", "");
7716
- r.suggested_actions.forEach((a, i) => L.push(`${i + 1}. ${a}`));
9311
+ r2.suggested_actions.forEach((a2, i) => L.push(`${i + 1}. ${a2}`));
7717
9312
  L.push("");
7718
9313
  return L.join("\n");
7719
9314
  }
7720
- function serializeDriftJson(r) {
9315
+ function serializeDriftJson(r2) {
7721
9316
  const out = {
7722
- generated_at: r.generated_at,
7723
- project: r.project,
7724
- guard_history: r.guard_history,
7725
- drift_warnings: r.drift_warnings,
7726
- hotspots: r.hotspots,
7727
- trend: r.trend,
7728
- threads: r.threads,
7729
- suggested_actions: r.suggested_actions
9317
+ generated_at: r2.generated_at,
9318
+ project: r2.project,
9319
+ guard_history: r2.guard_history,
9320
+ drift_warnings: r2.drift_warnings,
9321
+ hotspots: r2.hotspots,
9322
+ trend: r2.trend,
9323
+ threads: r2.threads,
9324
+ suggested_actions: r2.suggested_actions
7730
9325
  };
7731
9326
  return JSON.stringify(out, null, 2) + "\n";
7732
9327
  }
@@ -7756,7 +9351,7 @@ function parseSource(data) {
7756
9351
  }
7757
9352
  var ACTIVE_STATES2 = /* @__PURE__ */ new Set(["draft", "ready", "in-progress", "blocked"]);
7758
9353
  function strArray(v) {
7759
- return Array.isArray(v) ? v.map((x) => String(x)).filter(Boolean) : [];
9354
+ return Array.isArray(v) ? v.map((x2) => String(x2)).filter(Boolean) : [];
7760
9355
  }
7761
9356
  function lifecycleOf(data, relPath) {
7762
9357
  const status = String(data.status ?? "").trim();
@@ -7808,7 +9403,7 @@ function listWorkItems(root) {
7808
9403
  readiness
7809
9404
  });
7810
9405
  }
7811
- return items.sort((a, b) => a.id.localeCompare(b.id));
9406
+ return items.sort((a2, b2) => a2.id.localeCompare(b2.id));
7812
9407
  }
7813
9408
  function assessReadiness(data, content, code, domains, source) {
7814
9409
  const body = content.trim();
@@ -7835,12 +9430,12 @@ function assessReadiness(data, content, code, domains, source) {
7835
9430
  }
7836
9431
 
7837
9432
  // src/resources.ts
7838
- function text(uri, body, mimeType = "text/markdown") {
9433
+ function text2(uri, body, mimeType = "text/markdown") {
7839
9434
  return [{ uri, text: body, mimeType }];
7840
9435
  }
7841
9436
  function fileOrHint(root, uri, rel, hint, mimeType = "text/markdown") {
7842
9437
  const body = readText(root, rel);
7843
- return text(uri, body ?? hint, body ? mimeType : "text/plain");
9438
+ return text2(uri, body ?? hint, body ? mimeType : "text/plain");
7844
9439
  }
7845
9440
  var RESOURCES = [
7846
9441
  {
@@ -7888,7 +9483,7 @@ var RESOURCES = [
7888
9483
  const json = readText(root, ".kaddo/graph.json");
7889
9484
  const mmd = readText(root, ".kaddo/graph.mmd");
7890
9485
  if (!json && !mmd) {
7891
- return text("kaddo://graph", "Knowledge graph not found. Run `kaddo graph export` first.", "text/plain");
9486
+ return text2("kaddo://graph", "Knowledge graph not found. Run `kaddo graph export` first.", "text/plain");
7892
9487
  }
7893
9488
  const parts = [];
7894
9489
  if (json) parts.push({ uri: "kaddo://graph", text: json, mimeType: "application/json" });
@@ -7905,7 +9500,7 @@ var RESOURCES = [
7905
9500
  const md = readText(root, ".kaddo/graph-hints.md");
7906
9501
  const json = readText(root, ".kaddo/graph-hints.json");
7907
9502
  if (!md && !json) {
7908
- return text("kaddo://graph-hints", "Graph hints not found. Run `kaddo graph export` first.", "text/plain");
9503
+ return text2("kaddo://graph-hints", "Graph hints not found. Run `kaddo graph export` first.", "text/plain");
7909
9504
  }
7910
9505
  const parts = [];
7911
9506
  if (md) parts.push({ uri: "kaddo://graph-hints", text: md, mimeType: "text/markdown" });
@@ -7920,7 +9515,7 @@ var RESOURCES = [
7920
9515
  mimeType: "application/json",
7921
9516
  read: (root) => {
7922
9517
  if (!hasKnowledge(root)) {
7923
- return text("kaddo://work-items", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
9518
+ return text2("kaddo://work-items", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
7924
9519
  }
7925
9520
  return [
7926
9521
  {
@@ -7991,7 +9586,7 @@ var RESOURCES = [
7991
9586
  const saved = readText(root, ".kaddo/reports/impact-report.md");
7992
9587
  if (saved) return [{ uri: "kaddo://impact-report", text: saved, mimeType: "text/markdown" }];
7993
9588
  if (!hasKnowledge(root)) {
7994
- return text("kaddo://impact-report", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
9589
+ return text2("kaddo://impact-report", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
7995
9590
  }
7996
9591
  return [{ uri: "kaddo://impact-report", text: renderImpactMarkdown(buildImpactReport(root, { scope: "all", scopeSource: "default" })), mimeType: "text/markdown" }];
7997
9592
  }
@@ -8005,7 +9600,7 @@ var RESOURCES = [
8005
9600
  const saved = readText(root, ".kaddo/reports/savings-report.md");
8006
9601
  if (saved) return [{ uri: "kaddo://savings-report", text: saved, mimeType: "text/markdown" }];
8007
9602
  if (!hasKnowledge(root)) {
8008
- return text("kaddo://savings-report", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
9603
+ return text2("kaddo://savings-report", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
8009
9604
  }
8010
9605
  return [{ uri: "kaddo://savings-report", text: renderSavingsMarkdown(buildSavingsReport(root, { scope: "all", scopeSource: "default" })), mimeType: "text/markdown" }];
8011
9606
  }
@@ -8029,7 +9624,7 @@ var RESOURCES = [
8029
9624
  read: (root) => {
8030
9625
  const runs = readText(root, ".kaddo/history/guard-runs.jsonl");
8031
9626
  if (runs === null) {
8032
- return text("kaddo://guard-history", "No guard history recorded yet. Run `kaddo guard --record`.", "text/plain");
9627
+ return text2("kaddo://guard-history", "No guard history recorded yet. Run `kaddo guard --record`.", "text/plain");
8033
9628
  }
8034
9629
  return [{ uri: "kaddo://guard-history", text: runs, mimeType: "application/jsonl" }];
8035
9630
  }
@@ -8041,10 +9636,10 @@ var RESOURCES = [
8041
9636
  mimeType: "application/json",
8042
9637
  read: (root) => {
8043
9638
  if (!hasKnowledge(root)) {
8044
- return text("kaddo://open-questions", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
9639
+ return text2("kaddo://open-questions", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
8045
9640
  }
8046
- const r = buildOpenQuestionsReport(root);
8047
- return [{ uri: "kaddo://open-questions", text: JSON.stringify({ questions: r.questions }, null, 2), mimeType: "application/json" }];
9641
+ const r2 = buildOpenQuestionsReport(root);
9642
+ return [{ uri: "kaddo://open-questions", text: JSON.stringify({ questions: r2.questions }, null, 2), mimeType: "application/json" }];
8048
9643
  }
8049
9644
  },
8050
9645
  {
@@ -8054,7 +9649,7 @@ var RESOURCES = [
8054
9649
  mimeType: "application/json",
8055
9650
  read: (root) => {
8056
9651
  if (!hasKnowledge(root)) {
8057
- return text("kaddo://roadmap-readiness", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
9652
+ return text2("kaddo://roadmap-readiness", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
8058
9653
  }
8059
9654
  return [{ uri: "kaddo://roadmap-readiness", text: JSON.stringify(roadmapReadinessSummary(root), null, 2), mimeType: "application/json" }];
8060
9655
  }
@@ -8066,7 +9661,7 @@ var RESOURCES = [
8066
9661
  mimeType: "application/json",
8067
9662
  read: (root) => {
8068
9663
  if (!hasKnowledge(root)) {
8069
- return text("kaddo://tech-decisions", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
9664
+ return text2("kaddo://tech-decisions", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
8070
9665
  }
8071
9666
  return [{ uri: "kaddo://tech-decisions", text: JSON.stringify(buildTechDecisions(root), null, 2), mimeType: "application/json" }];
8072
9667
  }
@@ -8078,7 +9673,7 @@ var RESOURCES = [
8078
9673
  mimeType: "application/json",
8079
9674
  read: (root) => {
8080
9675
  if (!hasKnowledge(root)) {
8081
- return text("kaddo://installed-assets", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
9676
+ return text2("kaddo://installed-assets", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
8082
9677
  }
8083
9678
  return [{ uri: "kaddo://installed-assets", text: JSON.stringify(installedAssetsSummary(root), null, 2), mimeType: "application/json" }];
8084
9679
  }
@@ -8090,7 +9685,7 @@ var RESOURCES = [
8090
9685
  mimeType: "application/json",
8091
9686
  read: (root) => {
8092
9687
  if (!hasKnowledge(root)) {
8093
- return text("kaddo://roadmap-quality", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
9688
+ return text2("kaddo://roadmap-quality", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
8094
9689
  }
8095
9690
  return [{ uri: "kaddo://roadmap-quality", text: JSON.stringify(buildRoadmapQuality(root), null, 2), mimeType: "application/json" }];
8096
9691
  }
@@ -8102,7 +9697,7 @@ var RESOURCES = [
8102
9697
  mimeType: "application/json",
8103
9698
  read: (root) => {
8104
9699
  if (!hasKnowledge(root)) {
8105
- return text("kaddo://work-item-candidates", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
9700
+ return text2("kaddo://work-item-candidates", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
8106
9701
  }
8107
9702
  const md = readText(root, "knowledge/delivery/roadmap.md");
8108
9703
  const candidates = md ? parseRoadmapCandidates(md) : [];
@@ -8116,7 +9711,7 @@ var RESOURCES = [
8116
9711
  mimeType: "application/json",
8117
9712
  read: (root) => {
8118
9713
  if (!hasKnowledge(root)) {
8119
- return text("kaddo://next-step", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
9714
+ return text2("kaddo://next-step", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
8120
9715
  }
8121
9716
  const nextStepRecommendation = resolveNextStep(root);
8122
9717
  const deliveryState = { ...buildDeliveryState(root), phase: nextStepRecommendation.phase };
@@ -8130,7 +9725,7 @@ var RESOURCES = [
8130
9725
  mimeType: "application/json",
8131
9726
  read: (root) => {
8132
9727
  if (!hasKnowledge(root)) {
8133
- return text("kaddo://project-route", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
9728
+ return text2("kaddo://project-route", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
8134
9729
  }
8135
9730
  return [{ uri: "kaddo://project-route", text: JSON.stringify(buildProjectRoute(root), null, 2), mimeType: "application/json" }];
8136
9731
  }
@@ -8151,7 +9746,7 @@ var RESOURCES = [
8151
9746
  } catch {
8152
9747
  }
8153
9748
  }
8154
- return text("kaddo://scan-signals", "Scan signals not found. Run `kaddo scan` first.", "text/plain");
9749
+ return text2("kaddo://scan-signals", "Scan signals not found. Run `kaddo scan` first.", "text/plain");
8155
9750
  }
8156
9751
  }
8157
9752
  ];
@@ -8168,11 +9763,11 @@ function recommendedInputs(name) {
8168
9763
  return [".kaddo/context-pack.md", ...EXTRA_INPUTS[name] ?? []];
8169
9764
  }
8170
9765
  function listPrompts(root) {
8171
- return listAgents(root).map((a) => ({
8172
- name: a.name,
8173
- description: a.description || `Kaddo ${a.name}`,
9766
+ return listAgents(root).map((a2) => ({
9767
+ name: a2.name,
9768
+ description: a2.description || `Kaddo ${a2.name}`,
8174
9769
  content: "",
8175
- recommended_inputs: recommendedInputs(a.name)
9770
+ recommended_inputs: recommendedInputs(a2.name)
8176
9771
  }));
8177
9772
  }
8178
9773
  function getPrompt(root, name) {
@@ -8197,7 +9792,7 @@ function projectStatus(root) {
8197
9792
  if (!explain) {
8198
9793
  return fail("Project status needs `.kaddo/explain.json`. Run `kaddo explain` first.");
8199
9794
  }
8200
- const maturity = (explain.layers ?? []).map((l) => `${l.layer}: ${l.status}`);
9795
+ const maturity = (explain.layers ?? []).map((l2) => `${l2.layer}: ${l2.status}`);
8201
9796
  return ok({
8202
9797
  project: explain.project?.name ?? "unknown",
8203
9798
  state: explain.project?.state ?? "unknown",
@@ -8222,19 +9817,19 @@ function projectStatus(root) {
8222
9817
  }
8223
9818
  function listWorkItemsTool(root, filter = {}) {
8224
9819
  let items = listWorkItems(root);
8225
- if (filter.status) items = items.filter((w) => w.status === filter.status);
8226
- if (filter.type) items = items.filter((w) => w.type === filter.type);
8227
- if (filter.knowledge_level) items = items.filter((w) => w.knowledge_level === filter.knowledge_level);
9820
+ if (filter.status) items = items.filter((w3) => w3.status === filter.status);
9821
+ if (filter.type) items = items.filter((w3) => w3.type === filter.type);
9822
+ if (filter.knowledge_level) items = items.filter((w3) => w3.knowledge_level === filter.knowledge_level);
8228
9823
  return ok(items);
8229
9824
  }
8230
9825
  function getWorkItem(root, id) {
8231
- const item = listWorkItems(root).find((w) => w.id === id);
9826
+ const item = listWorkItems(root).find((w3) => w3.id === id);
8232
9827
  if (!item) return fail(`Work Item "${id}" not found.`);
8233
9828
  const content = readText(root, item.path);
8234
9829
  return ok({ ...item, content: content ?? "" });
8235
9830
  }
8236
9831
  function markWorkItemReady(root, id, confirm) {
8237
- const item = listWorkItems(root).find((w) => w.id === id);
9832
+ const item = listWorkItems(root).find((w3) => w3.id === id);
8238
9833
  if (!item) return fail(`Work Item "${id}" not found.`);
8239
9834
  if (item.status === "ready") {
8240
9835
  return ok({ status: "already_ready", id: item.id, message: `Work Item ${item.id} is already ready.` });
@@ -8317,9 +9912,9 @@ function listGraphHints(root, filter = {}) {
8317
9912
  const report = readJson(root, ".kaddo/graph-hints.json");
8318
9913
  if (!report) return fail("Graph hints not found. Run `kaddo graph export` first.");
8319
9914
  let hints = Array.isArray(report.hints) ? report.hints : [];
8320
- if (filter.artifact_type) hints = hints.filter((h) => h.artifact_type === filter.artifact_type);
8321
- if (filter.severity) hints = hints.filter((h) => h.severity === filter.severity);
8322
- if (filter.active_only) hints = hints.filter((h) => h.artifact_type === "work-item");
9915
+ if (filter.artifact_type) hints = hints.filter((h2) => h2.artifact_type === filter.artifact_type);
9916
+ if (filter.severity) hints = hints.filter((h2) => h2.severity === filter.severity);
9917
+ if (filter.active_only) hints = hints.filter((h2) => h2.artifact_type === "work-item");
8323
9918
  return ok({
8324
9919
  scope: report.scope ?? "active",
8325
9920
  scope_reason: report.scope_reason ?? "",
@@ -8380,23 +9975,23 @@ var OPERATING_RULES = [
8380
9975
  "After significant changes run `kaddo scan`, `kaddo owners suggest` and `kaddo guard`, and update the affected knowledge (ADR / capabilities / current-state).",
8381
9976
  "Kaddo itself never calls an LLM and never runs git \u2014 every git action is the human\u2019s."
8382
9977
  ];
8383
- function toContextWorkItem(a) {
9978
+ function toContextWorkItem(a2) {
8384
9979
  return {
8385
- id: a.id,
8386
- type: a.type,
8387
- title: a.title,
8388
- status: a.status,
8389
- lifecycle: lifecycleStateOf({ status: a.status, filePath: a.filePath }),
8390
- knowledgeLevel: a.knowledgeLevel,
8391
- domains: a.domains,
8392
- source: parseWorkItemSource(a.rawFrontmatter)
9980
+ id: a2.id,
9981
+ type: a2.type,
9982
+ title: a2.title,
9983
+ status: a2.status,
9984
+ lifecycle: lifecycleStateOf({ status: a2.status, filePath: a2.filePath }),
9985
+ knowledgeLevel: a2.knowledgeLevel,
9986
+ domains: a2.domains,
9987
+ source: parseWorkItemSource(a2.rawFrontmatter)
8393
9988
  };
8394
9989
  }
8395
- function toContextArtifact(a) {
8396
- return { id: a.id, type: a.type, title: a.title, summary: a.summary, codeGlobs: a.codeGlobs };
9990
+ function toContextArtifact(a2) {
9991
+ return { id: a2.id, type: a2.type, title: a2.title, summary: a2.summary, codeGlobs: a2.codeGlobs };
8397
9992
  }
8398
- function isDeliveryWorkItem(a) {
8399
- return a.filePath.replace(/\\/g, "/").includes("/delivery/work-items/") && Boolean(a.type);
9993
+ function isDeliveryWorkItem(a2) {
9994
+ return a2.filePath.replace(/\\/g, "/").includes("/delivery/work-items/") && Boolean(a2.type);
8400
9995
  }
8401
9996
  function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8402
9997
  const missing = [];
@@ -8419,7 +10014,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8419
10014
  }
8420
10015
  const allArtifacts = discoverKnowledge(dir);
8421
10016
  const workItems = allArtifacts.filter(
8422
- (a) => isDeliveryWorkItem(a) && isActiveState(lifecycleStateOf({ status: a.status, filePath: a.filePath }))
10017
+ (a2) => isDeliveryWorkItem(a2) && isActiveState(lifecycleStateOf({ status: a2.status, filePath: a2.filePath }))
8423
10018
  );
8424
10019
  if (workItems.length === 0) {
8425
10020
  missing.push("No work items found.");
@@ -8427,15 +10022,15 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8427
10022
  const state = config.project.state;
8428
10023
  const roadmapPath = join(dir, ARCH_DIR3, "delivery", "roadmap.md");
8429
10024
  const materialized = allArtifacts.filter(
8430
- (a) => a.filePath.replace(/\\/g, "/").includes("/delivery/work-items/") && Boolean(a.type)
10025
+ (a2) => a2.filePath.replace(/\\/g, "/").includes("/delivery/work-items/") && Boolean(a2.type)
8431
10026
  ).length;
8432
10027
  const roadmap = roadmapStats(exists(roadmapPath) ? readFile(roadmapPath) : null, materialized);
8433
10028
  const deliveryMix = {};
8434
- for (const a of allArtifacts) {
8435
- const p = a.filePath.replace(/\\/g, "/");
8436
- if (!a.type || !p.includes("/delivery/work-items/")) continue;
8437
- if (!isActiveState(lifecycleStateOf({ status: a.status, filePath: a.filePath }))) continue;
8438
- deliveryMix[a.type] = (deliveryMix[a.type] ?? 0) + 1;
10029
+ for (const a2 of allArtifacts) {
10030
+ const p = a2.filePath.replace(/\\/g, "/");
10031
+ if (!a2.type || !p.includes("/delivery/work-items/")) continue;
10032
+ if (!isActiveState(lifecycleStateOf({ status: a2.status, filePath: a2.filePath }))) continue;
10033
+ deliveryMix[a2.type] = (deliveryMix[a2.type] ?? 0) + 1;
8439
10034
  }
8440
10035
  const mappedModules = loadMappedModules(dir);
8441
10036
  const layers = knowledgeLayers(dir);
@@ -8446,7 +10041,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8446
10041
  const qCodebase = qa("knowledge/tech/codebase.md");
8447
10042
  const qCurrentState = qa("knowledge/tech/current-state.md");
8448
10043
  const qRoadmap = qa("knowledge/delivery/roadmap.md");
8449
- const layerStatusOf = (name) => layers.find((l) => l.layer === name)?.status ?? "Missing";
10044
+ const layerStatusOf = (name) => layers.find((l2) => l2.layer === name)?.status ?? "Missing";
8450
10045
  const knowledgeQuality = {
8451
10046
  business: { status: layerStatusOf("Business"), artifacts: { "knowledge/business/business.md": qBusiness } },
8452
10047
  product: { status: layerStatusOf("Product"), artifacts: { "knowledge/product/product.md": qProduct, "knowledge/product/capabilities.md": qCapabilities } },
@@ -8457,20 +10052,20 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8457
10052
  if (qProduct === "placeholder" || qCapabilities === "placeholder") missing.push("Product capabilities exist but still look like a bootstrap placeholder.");
8458
10053
  if (qCurrentState === "placeholder") missing.push("Current state exists but still looks like a bootstrap placeholder.");
8459
10054
  if (qCodebase === "placeholder") missing.push("Codebase map exists but still looks like a bootstrap placeholder.");
8460
- const allWorkItems = allArtifacts.filter((a) => a.isWorkItem);
8461
- const wiWithOwnership = allWorkItems.filter((a) => a.codeGlobs.length > 0).length;
10055
+ const allWorkItems = allArtifacts.filter((a2) => a2.isWorkItem);
10056
+ const wiWithOwnership = allWorkItems.filter((a2) => a2.codeGlobs.length > 0).length;
8462
10057
  const phase = assessPhase({
8463
10058
  layers,
8464
10059
  roadmap,
8465
10060
  workItems: {
8466
10061
  total: allWorkItems.length,
8467
10062
  byState: lifecycleCounts(
8468
- allWorkItems.map((a) => lifecycleStateOf({ status: a.status, filePath: a.filePath }))
10063
+ allWorkItems.map((a2) => lifecycleStateOf({ status: a2.status, filePath: a2.filePath }))
8469
10064
  ),
8470
- items: allWorkItems.map((a) => ({
8471
- id: a.id || a.title,
8472
- title: a.title,
8473
- lifecycle: lifecycleStateOf({ status: a.status, filePath: a.filePath })
10065
+ items: allWorkItems.map((a2) => ({
10066
+ id: a2.id || a2.title,
10067
+ title: a2.title,
10068
+ lifecycle: lifecycleStateOf({ status: a2.status, filePath: a2.filePath })
8474
10069
  }))
8475
10070
  },
8476
10071
  ownership: {
@@ -8535,7 +10130,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8535
10130
  roadmapSummary,
8536
10131
  inventoryAvailable,
8537
10132
  workItems: workItems.map(toContextWorkItem),
8538
- artifacts: allArtifacts.filter((a) => a.codeGlobs.length > 0).map(toContextArtifact)
10133
+ artifacts: allArtifacts.filter((a2) => a2.codeGlobs.length > 0).map(toContextArtifact)
8539
10134
  },
8540
10135
  layers,
8541
10136
  knowledgeQuality,
@@ -8548,7 +10143,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8548
10143
  roadmapQuality: buildRoadmapQuality(dir),
8549
10144
  installedAssets: (() => {
8550
10145
  const s = installedAssetsSummary(dir);
8551
- const compact = (a) => ({ total: a.total, installed: a.total - a.missing, outdated: a.outdated, unknown_version: a.unknown_version, modified: a.modified });
10146
+ const compact = (a2) => ({ total: a2.total, installed: a2.total - a2.missing, outdated: a2.outdated, unknown_version: a2.unknown_version, modified: a2.modified });
8552
10147
  return { version: s.version, agents: compact(s.agents), skills: compact(s.skills) };
8553
10148
  })(),
8554
10149
  deliveryMix,
@@ -8560,6 +10155,31 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8560
10155
  projectRoute: buildProjectRoute(dir),
8561
10156
  metadataHealth: analyzeMetadataHealth(dir),
8562
10157
  mappedModules,
10158
+ moduleStatuses: (() => {
10159
+ const statuses = {};
10160
+ for (const m2 of mappedModules) {
10161
+ if (m2.repoPath) statuses[m2.id] = detectModuleStatus(dir, m2.repoPath);
10162
+ }
10163
+ return statuses;
10164
+ })(),
10165
+ affectedModuleContexts: (() => {
10166
+ const contexts = {};
10167
+ const activeWIs = allArtifacts.filter(
10168
+ (a2) => a2.filePath.replace(/\\/g, "/").includes("/delivery/work-items/") && isActiveState(lifecycleStateOf({ status: a2.status, filePath: a2.filePath }))
10169
+ );
10170
+ const affectedIds = /* @__PURE__ */ new Set();
10171
+ for (const wi of activeWIs) {
10172
+ const am = wi.rawFrontmatter?.affected_modules;
10173
+ if (Array.isArray(am)) am.forEach((id) => affectedIds.add(String(id)));
10174
+ }
10175
+ for (const id of affectedIds) {
10176
+ const mod = mappedModules.find((m2) => m2.id === id);
10177
+ if (!mod?.repoPath) continue;
10178
+ const ctx = readModuleContext(dir, mod.repoPath);
10179
+ if (ctx) contexts[id] = ctx;
10180
+ }
10181
+ return contexts;
10182
+ })(),
8563
10183
  missing,
8564
10184
  // VS-052/VS-073.2: the handoff is driven by the unified next step, so the pack never contradicts
8565
10185
  // the Current Phase block above it.
@@ -8584,7 +10204,7 @@ function renderContextPack(pack) {
8584
10204
  "> Generated by `kaddo context`. Deterministic CLI output \u2014 not an interpretation of the system.\n"
8585
10205
  );
8586
10206
  parts.push("## Operating Rules (read first)\n");
8587
- parts.push(handoff.operatingRules.map((r) => `- ${r}`).join("\n") + "\n");
10207
+ parts.push(handoff.operatingRules.map((r2) => `- ${r2}`).join("\n") + "\n");
8588
10208
  parts.push("## Project Metadata\n");
8589
10209
  parts.push(
8590
10210
  [
@@ -8600,7 +10220,7 @@ function renderContextPack(pack) {
8600
10220
  `);
8601
10221
  if (pack.phase.reasons.length > 0) {
8602
10222
  parts.push("Reason:\n");
8603
- parts.push(pack.phase.reasons.map((r) => `- ${r}`).join("\n") + "\n");
10223
+ parts.push(pack.phase.reasons.map((r2) => `- ${r2}`).join("\n") + "\n");
8604
10224
  }
8605
10225
  if (pack.phase.recommendedAgents.length > 0) {
8606
10226
  parts.push(`Recommended next: ${pack.phase.recommendedAgents.join(", ")}
@@ -8641,7 +10261,7 @@ function renderContextPack(pack) {
8641
10261
  parts.push(
8642
10262
  "Project knowledge is organized in four layers: **Business \u2192 Product \u2192 Tech \u2192 Delivery**.\n"
8643
10263
  );
8644
- const maturity = pack.layers.map((l) => `${l.layer}: ${l.status}`).join(" \xB7 ");
10264
+ const maturity = pack.layers.map((l2) => `${l2.layer}: ${l2.status}`).join(" \xB7 ");
8645
10265
  parts.push(`Knowledge maturity \u2014 ${maturity}
8646
10266
  `);
8647
10267
  parts.push(renderLayersMarkdown(pack.layers) + "\n");
@@ -8654,19 +10274,19 @@ function renderContextPack(pack) {
8654
10274
  ];
8655
10275
  if (scan.sourceDirectories.length > 0) {
8656
10276
  lines.push("- Source directories:");
8657
- scan.sourceDirectories.forEach((d) => lines.push(` - ${d}`));
10277
+ scan.sourceDirectories.forEach((d3) => lines.push(` - ${d3}`));
8658
10278
  }
8659
10279
  if (scan.migrationDirectories.length > 0) {
8660
10280
  lines.push("- Migration directories:");
8661
- scan.migrationDirectories.forEach((d) => lines.push(` - ${d}`));
10281
+ scan.migrationDirectories.forEach((d3) => lines.push(` - ${d3}`));
8662
10282
  }
8663
10283
  if (scan.contractFiles.length > 0) {
8664
10284
  lines.push("- Contracts:");
8665
- scan.contractFiles.forEach((f) => lines.push(` - ${f}`));
10285
+ scan.contractFiles.forEach((f3) => lines.push(` - ${f3}`));
8666
10286
  }
8667
10287
  if (scan.infrastructureFiles.length > 0) {
8668
10288
  lines.push("- Infrastructure:");
8669
- scan.infrastructureFiles.forEach((f) => lines.push(` - ${f}`));
10289
+ scan.infrastructureFiles.forEach((f3) => lines.push(` - ${f3}`));
8670
10290
  }
8671
10291
  parts.push(lines.join("\n") + "\n");
8672
10292
  } else {
@@ -8744,7 +10364,7 @@ function renderContextPack(pack) {
8744
10364
  } else {
8745
10365
  parts.push("No active work items found.\n");
8746
10366
  }
8747
- const mixEntries = Object.entries(pack.deliveryMix).sort((a, b) => b[1] - a[1]);
10367
+ const mixEntries = Object.entries(pack.deliveryMix).sort((a2, b2) => b2[1] - a2[1]);
8748
10368
  if (mixEntries.length > 0) {
8749
10369
  parts.push("## Delivery Mix\n");
8750
10370
  parts.push("Active Work Items by type:\n");
@@ -8757,7 +10377,7 @@ function renderContextPack(pack) {
8757
10377
  parts.push("## Artifacts and Ownership\n");
8758
10378
  if (knowledge.artifacts.length > 0) {
8759
10379
  const lines = knowledge.artifacts.map(
8760
- (a) => `- ${a.id || a.title} [${a.type}] owns: ${a.codeGlobs.join(", ")}`
10380
+ (a2) => `- ${a2.id || a2.title} [${a2.type}] owns: ${a2.codeGlobs.join(", ")}`
8761
10381
  );
8762
10382
  parts.push(lines.join("\n") + "\n");
8763
10383
  } else {
@@ -8768,15 +10388,35 @@ function renderContextPack(pack) {
8768
10388
  parts.push("This project has mapped modules registered in `.kaddo/modules.yml`.\n");
8769
10389
  const header = "| Module | Type | Repo path | Owner | Capabilities | Artifacts |";
8770
10390
  const sep = "|---|---|---|---|---|---|";
8771
- const rows = pack.mappedModules.map((m) => {
8772
- const caps = m.capabilities.length > 0 ? m.capabilities.join(", ") : "\u2014";
8773
- const arts = presentArtifacts(m.artifacts);
8774
- return `| ${m.id} | ${m.type ?? "\u2014"} | ${m.repoPath || "\u2014"} | ${m.owner ?? "\u2014"} | ${caps} | ${arts.length > 0 ? arts.join(", ") : "none"} |`;
10391
+ const rows = pack.mappedModules.map((m2) => {
10392
+ const caps = m2.capabilities.length > 0 ? m2.capabilities.join(", ") : "\u2014";
10393
+ const arts = presentArtifacts(m2.artifacts);
10394
+ return `| ${m2.id} | ${m2.type ?? "\u2014"} | ${m2.repoPath || "\u2014"} | ${m2.owner ?? "\u2014"} | ${caps} | ${arts.length > 0 ? arts.join(", ") : "none"} |`;
8775
10395
  });
8776
10396
  parts.push([header, sep, ...rows].join("\n") + "\n");
8777
10397
  parts.push(
8778
10398
  "Note: Kaddo does not scan secondary repositories during `context`. Mapped modules come from `.kaddo/modules.yml` and module artifacts only.\n"
8779
10399
  );
10400
+ const statuses = pack.moduleStatuses ?? {};
10401
+ const warnings = Object.entries(statuses).filter(([, s]) => s.warning);
10402
+ if (warnings.length > 0) {
10403
+ parts.push("### Module Warnings\n");
10404
+ for (const [id, s] of warnings) {
10405
+ parts.push(`- **${id}** (${s.status}): ${s.warning}
10406
+ `);
10407
+ }
10408
+ }
10409
+ }
10410
+ const affectedCtx = pack.affectedModuleContexts ?? {};
10411
+ const affectedIds = Object.keys(affectedCtx);
10412
+ if (affectedIds.length > 0) {
10413
+ parts.push("## Affected Module Contexts\n");
10414
+ parts.push("The following module contexts are included because active Work Items reference them via `affected_modules`.\n");
10415
+ for (const id of affectedIds) {
10416
+ parts.push(`### Module: ${id}
10417
+ `);
10418
+ parts.push(affectedCtx[id] + "\n");
10419
+ }
8780
10420
  }
8781
10421
  if (pack.external.length > 0) {
8782
10422
  parts.push("## External Knowledge\n");
@@ -8818,7 +10458,7 @@ function renderContextPack(pack) {
8818
10458
  ].join("\n") + "\n"
8819
10459
  );
8820
10460
  const shown = pack.graphHints.messages.slice(0, 3);
8821
- parts.push(shown.map((m) => `- ${m}`).join("\n") + "\n");
10461
+ parts.push(shown.map((m2) => `- ${m2}`).join("\n") + "\n");
8822
10462
  if (pack.graphHints.totalHints > shown.length) {
8823
10463
  parts.push(`(+${pack.graphHints.totalHints - shown.length} more in \`.kaddo/graph-hints.md\`)
8824
10464
  `);
@@ -8839,18 +10479,18 @@ function renderContextPack(pack) {
8839
10479
  ...!pack.knowledgeQuality.product || pack.knowledgeQuality.product.status === "Missing" ? ["- Missing product knowledge."] : []
8840
10480
  ];
8841
10481
  if (missing.length > 0) {
8842
- baselineMissing.push(...missing.filter((m) => !baselineMissing.some((b) => b.includes(m))));
10482
+ baselineMissing.push(...missing.filter((m2) => !baselineMissing.some((b2) => b2.includes(m2))));
8843
10483
  }
8844
10484
  parts.push(baselineMissing.join("\n") + "\n");
8845
10485
  } else if (missing.length > 0) {
8846
- parts.push(missing.map((m) => `- ${m}`).join("\n") + "\n");
10486
+ parts.push(missing.map((m2) => `- ${m2}`).join("\n") + "\n");
8847
10487
  } else {
8848
10488
  parts.push("_None \u2014 all expected context is present._\n");
8849
10489
  }
8850
10490
  if (pack.metadataHealth.findings.length > 0) {
8851
10491
  parts.push("\n### Metadata Health\n");
8852
- for (const f of pack.metadataHealth.findings) {
8853
- parts.push(`- \`${f.file}\`: ${f.detail}
10492
+ for (const f3 of pack.metadataHealth.findings) {
10493
+ parts.push(`- \`${f3.file}\`: ${f3.detail}
8854
10494
  `);
8855
10495
  }
8856
10496
  }
@@ -8874,7 +10514,7 @@ function renderContextPack(pack) {
8874
10514
  parts.push(`Agent prompt: \`${rec.agentPath}\`
8875
10515
  `);
8876
10516
  }
8877
- parts.push(handoff.recommendedAgents.map((a, i) => `${i + 1}. ${a}`).join("\n") + "\n");
10517
+ parts.push(handoff.recommendedAgents.map((a2, i) => `${i + 1}. ${a2}`).join("\n") + "\n");
8878
10518
  if (handoff.nextSteps.length > 0) {
8879
10519
  parts.push("Next step:\n");
8880
10520
  parts.push(handoff.nextSteps.map((s) => `- ${s}`).join("\n") + "\n");
@@ -9018,7 +10658,7 @@ function renderUnderstand(plan) {
9018
10658
  }
9019
10659
  }
9020
10660
  if (flowSteps.length > 0) {
9021
- parts.push(flowSteps.map((f, i) => `${i + 1}. ${f}`).join("\n") + "\n");
10661
+ parts.push(flowSteps.map((f3, i) => `${i + 1}. ${f3}`).join("\n") + "\n");
9022
10662
  }
9023
10663
  }
9024
10664
  if (rec) {
@@ -9037,10 +10677,10 @@ function renderUnderstand(plan) {
9037
10677
  if (plan.activeWorkItems && plan.activeWorkItems.length > 0) {
9038
10678
  parts.push("## Active Work Items\n");
9039
10679
  parts.push(
9040
- plan.activeWorkItems.map((w) => {
9041
- const src = w.source && w.source.type !== "unknown" ? `
9042
- - Source: ${w.source.type}${w.source.id ? ` \xB7 ${w.source.id}` : ""}` : "";
9043
- return `- ${w.id} [${w.type}] ${w.lifecycle} \u2014 ${w.title}${src}`;
10680
+ plan.activeWorkItems.map((w3) => {
10681
+ const src = w3.source && w3.source.type !== "unknown" ? `
10682
+ - Source: ${w3.source.type}${w3.source.id ? ` \xB7 ${w3.source.id}` : ""}` : "";
10683
+ return `- ${w3.id} [${w3.type}] ${w3.lifecycle} \u2014 ${w3.title}${src}`;
9044
10684
  }).join("\n") + "\n"
9045
10685
  );
9046
10686
  }
@@ -9090,11 +10730,13 @@ function renderUnderstand(plan) {
9090
10730
  outputs.push("- Refined Work Item content.");
9091
10731
  if (rec.id === "create-work-item")
9092
10732
  outputs.push("- A new Work Item under `knowledge/delivery/work-items/`.");
9093
- if (rec.id === "implement")
10733
+ if (rec.id === "implement" || rec.id === "implement-work-item")
9094
10734
  outputs.push("- Implementation plan or code changes guided by the Work Item.");
10735
+ if (rec.id === "refine-module-context")
10736
+ outputs.push("- A refined `knowledge/module/module-context.md` with real, project-specific content.");
9095
10737
  if (rec.id === "guard")
9096
10738
  outputs.push("- Updated knowledge artifacts reflecting recent code changes.");
9097
- if (rec.id === "install-adapter")
10739
+ if (rec.id === "install-adapter" || rec.id === "prepare-implementation")
9098
10740
  outputs.push("- An adapter configured and injected (`kaddo adapters list`).");
9099
10741
  if (outputs.length > 0) {
9100
10742
  parts.push("The LLM should produce:\n");
@@ -9161,10 +10803,23 @@ function renderUnderstand(plan) {
9161
10803
  } else {
9162
10804
  parts.push("Re-run `kaddo understand` any time to see this plan again.\n");
9163
10805
  }
10806
+ const moduledWIs = (plan.activeWorkItems ?? []).filter((w3) => w3.affectedModules && w3.affectedModules.length > 0);
10807
+ if (moduledWIs.length > 0) {
10808
+ parts.push("## Branch Strategy\n");
10809
+ for (const w3 of moduledWIs) {
10810
+ const branch = `${w3.id.toLowerCase()}/${w3.title.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 40)}`;
10811
+ parts.push(`**${w3.id}** affects: ${w3.affectedModules.join(", ")}
10812
+ `);
10813
+ for (const mod of w3.affectedModules) {
10814
+ parts.push(`- \`${mod}\`: branch \`${branch}\``);
10815
+ }
10816
+ parts.push("");
10817
+ }
10818
+ }
9164
10819
  if (plan.metadataHealth && plan.metadataHealth.findings.length > 0) {
9165
10820
  parts.push("## Metadata Health\n");
9166
- for (const f of plan.metadataHealth.findings) {
9167
- parts.push(`- \`${f.file}\`: ${f.detail}
10821
+ for (const f3 of plan.metadataHealth.findings) {
10822
+ parts.push(`- \`${f3.file}\`: ${f3.detail}
9168
10823
  `);
9169
10824
  }
9170
10825
  }
@@ -9340,8 +10995,8 @@ function toolText(result) {
9340
10995
  if (!result.ok) {
9341
10996
  return { content: [{ type: "text", text: result.message }], isError: true };
9342
10997
  }
9343
- const text2 = typeof result.data === "string" ? result.data : JSON.stringify(result.data, null, 2);
9344
- return { content: [{ type: "text", text: text2 }] };
10998
+ const text3 = typeof result.data === "string" ? result.data : JSON.stringify(result.data, null, 2);
10999
+ return { content: [{ type: "text", text: text3 }] };
9345
11000
  }
9346
11001
  function guarded(root, fn) {
9347
11002
  try {
@@ -9365,11 +11020,11 @@ function generated(root, label, fn) {
9365
11020
  var DERIVED_NOTE = "Writes only derived files under .kaddo/. Does not modify knowledge, source code, external context or git.";
9366
11021
  function createServer(root) {
9367
11022
  const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION });
9368
- for (const r of RESOURCES) {
11023
+ for (const r2 of RESOURCES) {
9369
11024
  server.registerResource(
9370
- r.name,
9371
- r.uri,
9372
- { title: r.name, description: r.description, mimeType: r.mimeType },
11025
+ r2.name,
11026
+ r2.uri,
11027
+ { title: r2.name, description: r2.description, mimeType: r2.mimeType },
9373
11028
  async (uri) => {
9374
11029
  try {
9375
11030
  assertKaddoProject(root);
@@ -9377,7 +11032,7 @@ function createServer(root) {
9377
11032
  const message = err instanceof KaddoMcpError ? err.message : String(err);
9378
11033
  return { contents: [{ uri: uri.href, text: message, mimeType: "text/plain" }] };
9379
11034
  }
9380
- const parts = r.read(root);
11035
+ const parts = r2.read(root);
9381
11036
  return { contents: parts.map((p) => ({ uri: p.uri, text: p.text, mimeType: p.mimeType })) };
9382
11037
  }
9383
11038
  );
@@ -9393,16 +11048,16 @@ function createServer(root) {
9393
11048
  title: "List Work Items",
9394
11049
  description: "List Work Items with optional status/type/knowledge_level filters.",
9395
11050
  inputSchema: {
9396
- status: z2.string().optional(),
9397
- type: z2.string().optional(),
9398
- knowledge_level: z2.string().optional()
11051
+ status: z3.string().optional(),
11052
+ type: z3.string().optional(),
11053
+ knowledge_level: z3.string().optional()
9399
11054
  }
9400
11055
  },
9401
11056
  async (args) => toolText(guarded(root, () => listWorkItemsTool(root, args)))
9402
11057
  );
9403
11058
  server.registerTool(
9404
11059
  "kaddo_get_work_item",
9405
- { title: "Get Work Item", description: "Get a Work Item by ID (summary + full markdown).", inputSchema: { id: z2.string() } },
11060
+ { title: "Get Work Item", description: "Get a Work Item by ID (summary + full markdown).", inputSchema: { id: z3.string() } },
9406
11061
  async (args) => toolText(guarded(root, () => getWorkItem(root, args.id)))
9407
11062
  );
9408
11063
  server.registerTool(
@@ -9410,7 +11065,7 @@ function createServer(root) {
9410
11065
  {
9411
11066
  title: "Mark Work Item ready",
9412
11067
  description: "Assess whether a draft Work Item is ready for implementation. Without confirm, returns a preview with readiness warnings. With confirm=true, transitions the Work Item from draft to ready.",
9413
- inputSchema: { id: z2.string(), confirm: z2.boolean().optional() }
11068
+ inputSchema: { id: z3.string(), confirm: z3.boolean().optional() }
9414
11069
  },
9415
11070
  async (args) => toolText(guarded(root, () => markWorkItemReady(root, args.id, args.confirm)))
9416
11071
  );
@@ -9421,7 +11076,7 @@ function createServer(root) {
9421
11076
  );
9422
11077
  server.registerTool(
9423
11078
  "kaddo_get_capsule",
9424
- { title: "Get Knowledge Capsule", description: "Get an external Knowledge Capsule by ID.", inputSchema: { id: z2.string() } },
11079
+ { title: "Get Knowledge Capsule", description: "Get an external Knowledge Capsule by ID.", inputSchema: { id: z3.string() } },
9425
11080
  async (args) => toolText(guarded(root, () => getCapsuleTool(root, args.id)))
9426
11081
  );
9427
11082
  server.registerTool(
@@ -9431,7 +11086,7 @@ function createServer(root) {
9431
11086
  );
9432
11087
  server.registerTool(
9433
11088
  "kaddo_get_agent_prompt",
9434
- { title: "Get agent prompt", description: "Get an installed agent prompt by name.", inputSchema: { name: z2.string() } },
11089
+ { title: "Get agent prompt", description: "Get an installed agent prompt by name.", inputSchema: { name: z3.string() } },
9435
11090
  async (args) => toolText(guarded(root, () => getAgentPromptTool(root, args.name)))
9436
11091
  );
9437
11092
  server.registerTool(
@@ -9440,9 +11095,9 @@ function createServer(root) {
9440
11095
  title: "List graph hints",
9441
11096
  description: "List knowledge-graph relationship hints with optional filters.",
9442
11097
  inputSchema: {
9443
- artifact_type: z2.string().optional(),
9444
- severity: z2.string().optional(),
9445
- active_only: z2.boolean().optional()
11098
+ artifact_type: z3.string().optional(),
11099
+ severity: z3.string().optional(),
11100
+ active_only: z3.boolean().optional()
9446
11101
  }
9447
11102
  },
9448
11103
  async (args) => toolText(guarded(root, () => listGraphHints(root, args)))
@@ -9454,7 +11109,7 @@ function createServer(root) {
9454
11109
  );
9455
11110
  server.registerTool(
9456
11111
  "kaddo_get_skill",
9457
- { title: "Get skill", description: "Get an installed reusable skill by id.", inputSchema: { id: z2.string() } },
11112
+ { title: "Get skill", description: "Get an installed reusable skill by id.", inputSchema: { id: z3.string() } },
9458
11113
  async (args) => toolText(guarded(root, () => getSkillTool(root, args.id)))
9459
11114
  );
9460
11115
  let installedSkills = [];
@@ -9499,7 +11154,7 @@ function createServer(root) {
9499
11154
  {
9500
11155
  title: "Generate knowledge graph",
9501
11156
  description: `Regenerate .kaddo/graph.json/.mmd + graph-hints.md/.json. scope: active (default) or all. ${DERIVED_NOTE}`,
9502
- inputSchema: { scope: z2.enum(["active", "all"]).optional() }
11157
+ inputSchema: { scope: z3.enum(["active", "all"]).optional() }
9503
11158
  },
9504
11159
  async (args) => generated(root, "generate knowledge graph", () => generateGraph(root, args.scope ?? "active"))
9505
11160
  );
@@ -9509,9 +11164,9 @@ function createServer(root) {
9509
11164
  title: "Generate impact report",
9510
11165
  description: `Write the Knowledge Impact Report under .kaddo/reports/. format: markdown (default) or json; scope: active or all (default all). ${DERIVED_NOTE}`,
9511
11166
  inputSchema: {
9512
- format: z2.enum(["markdown", "json"]).optional(),
9513
- scope: z2.enum(["active", "all"]).optional(),
9514
- output: z2.string().optional()
11167
+ format: z3.enum(["markdown", "json"]).optional(),
11168
+ scope: z3.enum(["active", "all"]).optional(),
11169
+ output: z3.string().optional()
9515
11170
  }
9516
11171
  },
9517
11172
  async (args) => generated(
@@ -9526,9 +11181,9 @@ function createServer(root) {
9526
11181
  title: "Generate savings report",
9527
11182
  description: `Write the Estimated Savings Report under .kaddo/reports/. format: markdown (default) or json; scope: active or all (default all). Evidence-based estimates, not exact ROI. ${DERIVED_NOTE}`,
9528
11183
  inputSchema: {
9529
- format: z2.enum(["markdown", "json"]).optional(),
9530
- scope: z2.enum(["active", "all"]).optional(),
9531
- output: z2.string().optional()
11184
+ format: z3.enum(["markdown", "json"]).optional(),
11185
+ scope: z3.enum(["active", "all"]).optional(),
11186
+ output: z3.string().optional()
9532
11187
  }
9533
11188
  },
9534
11189
  async (args) => generated(
@@ -9543,8 +11198,8 @@ function createServer(root) {
9543
11198
  title: "Generate drift report",
9544
11199
  description: `Write the Drift Trend Report under .kaddo/reports/ from recorded guard history. format: markdown (default) or json. Does NOT record guard runs. ${DERIVED_NOTE}`,
9545
11200
  inputSchema: {
9546
- format: z2.enum(["markdown", "json"]).optional(),
9547
- output: z2.string().optional()
11201
+ format: z3.enum(["markdown", "json"]).optional(),
11202
+ output: z3.string().optional()
9548
11203
  }
9549
11204
  },
9550
11205
  async (args) => generated(
@@ -9559,8 +11214,8 @@ function createServer(root) {
9559
11214
  title: "Generate open-questions report",
9560
11215
  description: `Write the Open Questions readiness report under .kaddo/reports/ (classifies blocking/important/deferred). Does NOT resolve questions. ${DERIVED_NOTE}`,
9561
11216
  inputSchema: {
9562
- format: z2.enum(["markdown", "json"]).optional(),
9563
- output: z2.string().optional()
11217
+ format: z3.enum(["markdown", "json"]).optional(),
11218
+ output: z3.string().optional()
9564
11219
  }
9565
11220
  },
9566
11221
  async (args) => generated(