@kaddo/mcp 3.60.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 +2336 -690
  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
697
1999
 
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
- }
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
2088
+
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,10 +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"),
2455
- ready_work_item_ids: wis.filter((w) => w.lifecycle === "ready").map((w) => w.id),
3836
+ ready_work_item_ids: wis.filter((w3) => w3.lifecycle === "ready").map((w3) => w3.id),
2456
3837
  in_progress_work_items: byState("in-progress"),
2457
3838
  blocked_work_items: byState("blocked"),
2458
3839
  total_work_items: total,
@@ -2482,17 +3863,17 @@ function roadmapSignal(dir) {
2482
3863
  const lines = md.replace(/^---[\s\S]*?---/m, "").split(/\r?\n/);
2483
3864
  let inOpenQuestions = false;
2484
3865
  let candidates = 0;
2485
- for (const l of lines) {
2486
- if (/^#{1,6}\s/.test(l)) inOpenQuestions = /open questions|preguntas abiertas/i.test(l);
2487
- 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;
2488
3869
  }
2489
3870
  return candidates > 0 ? "has-candidates" : "empty";
2490
3871
  }
2491
3872
  function workItemsSignal(dir) {
2492
3873
  const wis = discoverWorkItems(dir);
2493
3874
  if (wis.length === 0) return "none";
2494
- if (wis.some((w) => w.lifecycle === "in-progress")) return "in-progress";
2495
- 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";
2496
3877
  return "none-ready";
2497
3878
  }
2498
3879
  function installedAdapters(dir) {
@@ -2500,8 +3881,8 @@ function installedAdapters(dir) {
2500
3881
  (s) => s.state === "injected" || s.state === "legacy-injected" || s.state === "full-generated" && (s.originAdapter === s.id || s.originAdapter === null)
2501
3882
  ).map((s) => s.id);
2502
3883
  }
2503
- var B = "knowledge/business/business.md";
2504
- var P = "knowledge/product/product.md";
3884
+ var B2 = "knowledge/business/business.md";
3885
+ var P2 = "knowledge/product/product.md";
2505
3886
  var CAP = "knowledge/product/capabilities.md";
2506
3887
  var CS = "knowledge/tech/current-state.md";
2507
3888
  var CB = "knowledge/tech/codebase.md";
@@ -2511,8 +3892,61 @@ function resolveNextStep(dir, now = /* @__PURE__ */ new Date()) {
2511
3892
  return { id: "init", phase: "Setup", label: "Run `kaddo init` to initialize Kaddo.", command: "kaddo init", reason: "Kaddo is not initialized in this project." };
2512
3893
  }
2513
3894
  const state = config.project.state;
2514
- const q = (rel) => analyzeKnowledgeArtifact(dir, rel);
2515
- 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);
2516
3950
  if (qBusiness === "missing" || qProduct === "missing") {
2517
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." };
2518
3952
  }
@@ -2556,12 +3990,12 @@ function resolveNextStep(dir, now = /* @__PURE__ */ new Date()) {
2556
3990
  ]
2557
3991
  };
2558
3992
  };
2559
- if (qBusiness !== "useful") return refine("refine-business", "business-agent", B, qBusiness);
3993
+ if (qBusiness !== "useful") return refine("refine-business", "business-agent", B2, qBusiness);
2560
3994
  if (qProduct !== "useful" || qCap !== "useful") {
2561
3995
  if (qCap !== "useful") {
2562
3996
  return refine("refine-product", "capability-agent", CAP, qCap, discovery ? "discover and document existing system capabilities grouped by functional domains in" : "complete");
2563
3997
  }
2564
- return refine("refine-product", "capability-agent", P, qProduct);
3998
+ return refine("refine-product", "capability-agent", P2, qProduct);
2565
3999
  }
2566
4000
  if (qCurrentState !== "useful") return refine("refine-current-state", "architecture-agent", CS, qCurrentState);
2567
4001
  if (qCodebase !== "useful") {
@@ -2765,7 +4199,7 @@ function buildReadinessReport(dir, now = /* @__PURE__ */ new Date()) {
2765
4199
  if (config.project.state === "legacy") return stub("legacy-project", "Use the legacy project flow.");
2766
4200
  const scan = exists(join(dir, ".kaddo", "scan.json")) ? "available" : "missing";
2767
4201
  const understand = exists(join(dir, ".kaddo", "understand.md")) ? "available" : "missing";
2768
- 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)]));
2769
4203
  const ctx = buildCodexAdapterContext(dir);
2770
4204
  const agents = ctx.hasAgents ? "present" : "missing";
2771
4205
  const skills = ctx.hasSkills ? "present" : "missing";
@@ -2793,7 +4227,7 @@ function buildReadinessReport(dir, now = /* @__PURE__ */ new Date()) {
2793
4227
  resolved_questions: oq.summary.resolution.resolved,
2794
4228
  deferred_questions: oq.summary.resolution.deferred
2795
4229
  };
2796
- const firstWeak = KNOWLEDGE_FILES.find((f) => presence[f.key] !== "useful");
4230
+ const firstWeak = KNOWLEDGE_FILES.find((f3) => presence[f3.key] !== "useful");
2797
4231
  let overall;
2798
4232
  if (scan === "missing") overall = "initialized";
2799
4233
  else if (bootstrapBaseline2 === "incomplete") overall = "bootstrap-incomplete";
@@ -2852,7 +4286,7 @@ function skill(id, title, group, appliesTo, body) {
2852
4286
  `version: ${KADDO_VERSION}`,
2853
4287
  `group: ${group}`,
2854
4288
  "applies_to:",
2855
- ...appliesTo.map((a) => ` - ${a}`),
4289
+ ...appliesTo.map((a2) => ` - ${a2}`),
2856
4290
  "---",
2857
4291
  ""
2858
4292
  ].join("\n");
@@ -3207,6 +4641,58 @@ steps, and stop criteria (when to pause and ask).
3207
4641
  A numbered plan covering the sections above, ending with a request to confirm before coding.
3208
4642
  `
3209
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
+ );
3210
4696
  var SKILLS = [
3211
4697
  ADR_WRITING,
3212
4698
  WORK_ITEM_REFINEMENT,
@@ -3214,11 +4700,12 @@ var SKILLS = [
3214
4700
  GRAPH_METADATA_REVIEW,
3215
4701
  CAPSULE_WRITING,
3216
4702
  LEARNING_CAPTURE,
3217
- IMPLEMENTATION_PLANNING
4703
+ IMPLEMENTATION_PLANNING,
4704
+ MODULE_CONTEXT_REFINEMENT
3218
4705
  ];
3219
4706
  var SKILL_GROUPS = {
3220
4707
  delivery: ["work-item-refinement", "implementation-planning", "learning-capture"],
3221
- tech: ["adr-writing", "ownership-suggestion", "graph-metadata-review"],
4708
+ tech: ["adr-writing", "ownership-suggestion", "graph-metadata-review", "module-context-refinement"],
3222
4709
  integration: ["capsule-writing"]
3223
4710
  };
3224
4711
  var SKILL_GROUP_NAMES = Object.keys(SKILL_GROUPS);
@@ -3305,6 +4792,14 @@ var RESPONSIBILITY_MATRIX = {
3305
4792
  cannotSuggest: ["Git", "branches", "code"],
3306
4793
  next: ["architecture-agent"]
3307
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
+ },
3308
4803
  "architecture-agent": {
3309
4804
  agent: "architecture-agent",
3310
4805
  responsibleFor: ["Architecture", "Technical state", "Risks"],
@@ -3448,25 +4943,25 @@ function list(items) {
3448
4943
  return items.length > 0 ? items.join(", ") : "\u2014";
3449
4944
  }
3450
4945
  function renderAgentBoundaries(agent) {
3451
- const r = RESPONSIBILITY_MATRIX[agent];
3452
- if (!r) return "";
4946
+ const r2 = RESPONSIBILITY_MATRIX[agent];
4947
+ if (!r2) return "";
3453
4948
  return [
3454
4949
  "## Responsibility & Boundaries",
3455
4950
  "",
3456
- `**Responsible for:** ${list(r.responsibleFor)}`,
3457
- `**Produces:** ${list(r.produces)}`,
3458
- `**May suggest:** ${list(r.canSuggest)}`,
3459
- `**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)}`,
3460
4955
  "",
3461
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.",
3462
4957
  ""
3463
4958
  ].join("\n");
3464
4959
  }
3465
4960
  function renderAgentTrace(agent) {
3466
- const r = RESPONSIBILITY_MATRIX[agent];
3467
- if (!r) return "";
3468
- const produced = r.produces.length > 0 ? r.produces.join("\n") : "(none)";
3469
- 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)";
3470
4965
  return [
3471
4966
  "## Agent Trace",
3472
4967
  "",
@@ -3474,7 +4969,7 @@ function renderAgentTrace(agent) {
3474
4969
  "",
3475
4970
  "```text",
3476
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",
3477
- `Agent: ${r.agent}`,
4972
+ `Agent: ${r2.agent}`,
3478
4973
  "",
3479
4974
  "Produced:",
3480
4975
  produced,
@@ -3522,7 +5017,8 @@ var KNOWLEDGE_REFINING_AGENTS = {
3522
5017
  "work-item-agent": "work-item-agent",
3523
5018
  "backlog-agent": "backlog-agent",
3524
5019
  "adr-agent": "adr-agent",
3525
- "implementation-agent": "implementation-agent"
5020
+ "implementation-agent": "implementation-agent",
5021
+ "module-context-agent": "module-context-agent"
3526
5022
  };
3527
5023
  function renderFrontmatterRules(agent) {
3528
5024
  if (!KNOWLEDGE_REFINING_AGENTS[agent]) return "";
@@ -4742,6 +6238,92 @@ Save as \`knowledge/tech/modules/<module-name>/module-design.md\`.
4742
6238
  - Diagrams are suggested, not generated.
4743
6239
  - Assumptions and risks are explicit.
4744
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
+ `;
4745
6327
  var BUSINESS_AGENT = `# Business Agent
4746
6328
 
4747
6329
  ## Role
@@ -5339,6 +6921,7 @@ var AGENT_PROMPTS = [
5339
6921
  { fileName: "standards-agent.md", content: STANDARDS_AGENT },
5340
6922
  { fileName: "stack-agent.md", content: STACK_AGENT },
5341
6923
  { fileName: "module-design-agent.md", content: MODULE_DESIGN_AGENT },
6924
+ { fileName: "module-context-agent.md", content: MODULE_CONTEXT_AGENT },
5342
6925
  // Bootstrap agents (new projects)
5343
6926
  { fileName: "business-agent.md", content: BUSINESS_AGENT },
5344
6927
  { fileName: "bootstrap-agent.md", content: BOOTSTRAP_AGENT },
@@ -5439,9 +7022,9 @@ var agentReadme = {
5439
7022
  "- `graph-agent.md` \u2014 review `kaddo graph export` hints and propose precise relationship front matter."
5440
7023
  ].join("\n")
5441
7024
  };
5442
- var agentFiles = AGENT_PROMPTS.map((a) => ({
5443
- path: agentInstallPath(a.fileName),
5444
- 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)
5445
7028
  }));
5446
7029
  var agentsModule = {
5447
7030
  name: "agents",
@@ -5493,10 +7076,10 @@ var agentsModule = {
5493
7076
 
5494
7077
  // ../cli/src/core/assets.ts
5495
7078
  function canonicalAgents() {
5496
- return AGENT_PROMPTS.map((a) => ({
5497
- name: a.fileName.replace(/\.md$/, ""),
5498
- path: agentInstallPath(a.fileName),
5499
- 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)
5500
7083
  }));
5501
7084
  }
5502
7085
  function canonicalSkills() {
@@ -5510,12 +7093,12 @@ function versionOf(content) {
5510
7093
  return null;
5511
7094
  }
5512
7095
  }
5513
- function cmpVersion(a, b) {
5514
- const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
5515
- 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);
5516
7099
  for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
5517
- const d = (pa[i] ?? 0) - (pb[i] ?? 0);
5518
- 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;
5519
7102
  }
5520
7103
  return 0;
5521
7104
  }
@@ -5550,7 +7133,7 @@ function summarize(items) {
5550
7133
  }
5551
7134
  function assetStatus(dir, kind) {
5552
7135
  const catalog = kind === "agent" ? canonicalAgents() : canonicalSkills();
5553
- return summarize(catalog.map((a) => classify(dir, a)));
7136
+ return summarize(catalog.map((a2) => classify(dir, a2)));
5554
7137
  }
5555
7138
  function installedAssetsSummary(dir) {
5556
7139
  return { version: KADDO_VERSION, agents: assetStatus(dir, "agent"), skills: assetStatus(dir, "skill") };
@@ -5561,14 +7144,14 @@ var ROADMAP_PATH = "knowledge/delivery/roadmap.md";
5561
7144
  var INITIATIVE_RE2 = /^#{2,4}\s+(RM-[\w.-]+)\s*[:\-–]?\s*(.*)$/;
5562
7145
  function fieldPresent(lines, label) {
5563
7146
  for (let i = 0; i < lines.length; i++) {
5564
- const m = lines[i].match(new RegExp(`^\\s*[-*]?\\s*(?:\\*\\*)?\\s*(${label.source})\\s*(?:\\*\\*)?\\s*:\\s*(.*)$`, "i"));
5565
- if (!m) continue;
5566
- 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();
5567
7150
  if (inline) return true;
5568
- for (let j = i + 1; j < lines.length; j++) {
5569
- if (/^\s{2,}[-*]\s+\S/.test(lines[j])) return true;
5570
- if (/^\S/.test(lines[j]) || /^#{2,4}\s/.test(lines[j])) break;
5571
- 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;
5572
7155
  }
5573
7156
  }
5574
7157
  return false;
@@ -5593,10 +7176,10 @@ function parseRoadmapCandidateQuality(md) {
5593
7176
  cur = null;
5594
7177
  };
5595
7178
  for (const line of lines) {
5596
- const m = line.match(INITIATIVE_RE2);
5597
- if (m) {
7179
+ const m2 = line.match(INITIATIVE_RE2);
7180
+ if (m2) {
5598
7181
  flush();
5599
- cur = { id: m[1], title: m[2].trim(), lines: [] };
7182
+ cur = { id: m2[1], title: m2[2].trim(), lines: [] };
5600
7183
  continue;
5601
7184
  }
5602
7185
  if (cur) cur.lines.push(line);
@@ -5772,8 +7355,8 @@ function optStr(v) {
5772
7355
  }
5773
7356
 
5774
7357
  // ../cli/src/core/project-route.ts
5775
- function isUseful(q) {
5776
- return q === "useful";
7358
+ function isUseful(q3) {
7359
+ return q3 === "useful";
5777
7360
  }
5778
7361
  var enableKaddo = {
5779
7362
  id: "enable-kaddo",
@@ -6058,9 +7641,9 @@ function buildRouteContext(dir) {
6058
7641
  }
6059
7642
  }
6060
7643
  const stats = roadmapStats(roadmapMd, wis.length);
6061
- const byState = (s) => wis.filter((w) => w.lifecycle === s).length;
7644
+ const byState = (s) => wis.filter((w3) => w3.lifecycle === s).length;
6062
7645
  const total = wis.length;
6063
- const withOwnership = wis.filter((w) => w.codeGlobs.length > 0).length;
7646
+ const withOwnership = wis.filter((w3) => w3.codeGlobs.length > 0).length;
6064
7647
  const adapters = installedAdapters(dir);
6065
7648
  const nextStep = resolveNextStep(dir);
6066
7649
  return {
@@ -6089,8 +7672,8 @@ function buildRouteContext(dir) {
6089
7672
  adaptersInstalled: adapters.length,
6090
7673
  hasGuardHistory: exists(join(dir, ".kaddo", "history", "guard-runs.jsonl")),
6091
7674
  hasScanWarnings: hasScan ? loadScanWarnings(dir) : false,
6092
- hasUnknownSources: wis.some((w) => {
6093
- const src = parseWorkItemSource(w.rawFrontmatter);
7675
+ hasUnknownSources: wis.some((w3) => {
7676
+ const src = parseWorkItemSource(w3.rawFrontmatter);
6094
7677
  return src.type === "unknown" && src.inferred;
6095
7678
  }),
6096
7679
  nextStepId: mapNextStepId(nextStep.id)
@@ -6119,7 +7702,10 @@ function mapNextStepId(id) {
6119
7702
  "refine-codebase": "describe-architecture",
6120
7703
  "review-work-item": "refine-work-item",
6121
7704
  "prepare-implementation": "prepare-implementation",
6122
- "implement-work-item": "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"
6123
7709
  };
6124
7710
  return MAP[id] ?? id;
6125
7711
  }
@@ -6128,9 +7714,9 @@ function buildProjectRoute(dir) {
6128
7714
  const state = config?.project.state ?? "pre-ai";
6129
7715
  const defs = stepsForState(state);
6130
7716
  const ctx = buildRouteContext(dir);
6131
- const steps = defs.map((d) => {
6132
- const result = d.evaluate(ctx);
6133
- 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 };
6134
7720
  });
6135
7721
  for (const s of steps) {
6136
7722
  if (s.id === ctx.nextStepId && s.status !== "done") {
@@ -6194,8 +7780,8 @@ function renderRouteCompact(route) {
6194
7780
  const warnings = route.steps.filter((s) => s.status === "warning");
6195
7781
  if (warnings.length > 0) {
6196
7782
  lines.push("Warnings:");
6197
- for (const w of warnings) {
6198
- 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}` : ""}`);
6199
7785
  }
6200
7786
  lines.push("");
6201
7787
  }
@@ -6261,10 +7847,10 @@ function findDuplicateWorkItems(items) {
6261
7847
  const bucket = (key, reason, pred) => {
6262
7848
  const matched = items.filter(pred);
6263
7849
  if (matched.length > 1) {
6264
- const id = `${reason}:${key}:${matched.map((m) => m.id).sort().join(",")}`;
7850
+ const id = `${reason}:${key}:${matched.map((m2) => m2.id).sort().join(",")}`;
6265
7851
  if (!seen.has(id)) {
6266
7852
  seen.add(id);
6267
- 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 })) });
6268
7854
  }
6269
7855
  }
6270
7856
  };
@@ -6278,7 +7864,7 @@ function findDuplicateWorkItems(items) {
6278
7864
  }
6279
7865
  function first(values) {
6280
7866
  if (Array.isArray(values)) {
6281
- const v = values.find((x) => typeof x === "string" && x);
7867
+ const v = values.find((x2) => typeof x2 === "string" && x2);
6282
7868
  return v ? String(v) : void 0;
6283
7869
  }
6284
7870
  return typeof values === "string" && values ? values : void 0;
@@ -6318,9 +7904,9 @@ function loadScanSignals(dir) {
6318
7904
  function hasAgents(dir) {
6319
7905
  const agentsDir = join(dir, ARCH_DIR2, "agents");
6320
7906
  if (!exists(agentsDir)) return false;
6321
- function hasAgentMd(d) {
6322
- for (const e of readDir(d)) {
6323
- const full = join(d, e);
7907
+ function hasAgentMd(d3) {
7908
+ for (const e of readDir(d3)) {
7909
+ const full = join(d3, e);
6324
7910
  if (isFile(full)) {
6325
7911
  if (e.endsWith("-agent.md")) return true;
6326
7912
  } else if (hasAgentMd(full)) {
@@ -6360,7 +7946,7 @@ function buildProjectExplanation(dir) {
6360
7946
  infrastructureFiles: scan.infrastructureFiles
6361
7947
  } : null;
6362
7948
  const layers = knowledgeLayers(dir);
6363
- const layerStatus = (name) => layers.find((l) => l.layer === name)?.status ?? "Missing";
7949
+ const layerStatus = (name) => layers.find((l2) => l2.layer === name)?.status ?? "Missing";
6364
7950
  const knowledge = {
6365
7951
  hasScan: scan !== null,
6366
7952
  hasInventory: exists(join(dir, ARCH_DIR2, "inventory.md")),
@@ -6375,18 +7961,18 @@ function buildProjectExplanation(dir) {
6375
7961
  hasSkills: hasSkills(dir)
6376
7962
  };
6377
7963
  const workItemArtifacts = discoverWorkItems(dir);
6378
- const items = workItemArtifacts.map((a) => {
6379
- const src = parseWorkItemSource(a.rawFrontmatter);
7964
+ const items = workItemArtifacts.map((a2) => {
7965
+ const src = parseWorkItemSource(a2.rawFrontmatter);
6380
7966
  return {
6381
- id: a.id || a.title,
6382
- title: a.title,
6383
- type: a.type,
6384
- status: a.status,
6385
- lifecycle: lifecycleStateOf({ status: a.status, filePath: a.filePath }),
6386
- initiative: a.initiative,
6387
- knowledgeLevel: a.knowledgeLevel,
6388
- hasOwnership: a.codeGlobs.length > 0,
6389
- 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,
6390
7976
  source: { type: src.type, ...src.id ? { id: src.id } : {}, inferred: src.inferred }
6391
7977
  };
6392
7978
  });
@@ -6402,7 +7988,7 @@ function buildProjectExplanation(dir) {
6402
7988
  if (!initiativeMap.has(name)) initiativeMap.set(name, emptyLifecycleCounts());
6403
7989
  initiativeMap.get(name)[i.lifecycle]++;
6404
7990
  }
6405
- 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));
6406
7992
  const workItems = {
6407
7993
  total: items.length,
6408
7994
  inProgress: items.filter((i) => i.lifecycle === "in-progress").length,
@@ -6419,9 +8005,9 @@ function buildProjectExplanation(dir) {
6419
8005
  workItemsWithOwnership: withOwnership,
6420
8006
  workItemsMissingOwnership: items.length - withOwnership
6421
8007
  };
6422
- const domains = [...new Set(workItemArtifacts.flatMap((a) => a.domains))].filter(Boolean);
8008
+ const domains = [...new Set(workItemArtifacts.flatMap((a2) => a2.domains))].filter(Boolean);
6423
8009
  const duplicateWorkItems = findDuplicateWorkItems(
6424
- 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 }))
6425
8011
  );
6426
8012
  const roadmapPath = join(dir, ARCH_DIR2, "delivery", "roadmap.md");
6427
8013
  const roadmapMd = exists(roadmapPath) ? readFile(roadmapPath) : null;
@@ -6562,7 +8148,7 @@ function renderExplanationHuman(exp) {
6562
8148
  lines.push("## Scan Signals");
6563
8149
  lines.push(renderSignalsCompact(exp.scanSignals));
6564
8150
  }
6565
- 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";
6566
8152
  lines.push("## Knowledge Status");
6567
8153
  lines.push(`- Inventory: ${exp.knowledge.hasInventory ? "available" : "missing"}`);
6568
8154
  lines.push(`- Context pack: ${exp.knowledge.hasContextPack ? "available" : "missing"}`);
@@ -6590,7 +8176,7 @@ function renderExplanationHuman(exp) {
6590
8176
  lines.push(`- ${LIFECYCLE_LABEL[s2]}: ${exp.workItems.byState[s2]}`);
6591
8177
  }
6592
8178
  lines.push("");
6593
- 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]);
6594
8180
  if (typeEntries.length > 0) {
6595
8181
  lines.push("## Work Items by Type");
6596
8182
  for (const [t, n] of typeEntries) lines.push(`- ${typeLabel(t)}: ${n}`);
@@ -6638,15 +8224,15 @@ function renderExplanationHuman(exp) {
6638
8224
  }
6639
8225
  lines.push("## Mapped Modules");
6640
8226
  if (exp.mappedModules.length > 0) {
6641
- for (const m of exp.mappedModules) {
6642
- const owner = m.owner ? ` \u2014 owner: ${m.owner}` : "";
6643
- 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}`);
6644
8230
  }
6645
8231
  lines.push("");
6646
8232
  lines.push("## Module Artifact Coverage");
6647
- for (const m of exp.mappedModules) {
6648
- const present = presentArtifacts(m.artifacts);
6649
- 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"}`);
6650
8236
  }
6651
8237
  lines.push("");
6652
8238
  } else {
@@ -6682,7 +8268,7 @@ function renderExplanationHuman(exp) {
6682
8268
  }
6683
8269
  if (exp.skills.total > 0) {
6684
8270
  lines.push(`## Skills installed: ${exp.skills.total}`);
6685
- 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]));
6686
8272
  if (groups.length > 0) {
6687
8273
  lines.push("Groups:");
6688
8274
  for (const [g, n] of groups) lines.push(`- ${g}: ${n}`);
@@ -6691,7 +8277,7 @@ function renderExplanationHuman(exp) {
6691
8277
  }
6692
8278
  if (exp.missingKnowledge.length > 0) {
6693
8279
  lines.push("## Missing Knowledge");
6694
- for (const m of exp.missingKnowledge) lines.push(`- ${m}`);
8280
+ for (const m2 of exp.missingKnowledge) lines.push(`- ${m2}`);
6695
8281
  lines.push("");
6696
8282
  }
6697
8283
  if (exp.duplicateWorkItems.length > 0) {
@@ -6709,7 +8295,7 @@ function renderExplanationHuman(exp) {
6709
8295
  lines.push(`- Phase: ${assessment.phase}`);
6710
8296
  if (assessment.reasons.length > 0) {
6711
8297
  lines.push("- Reason:");
6712
- for (const r2 of assessment.reasons) lines.push(` - ${r2}`);
8298
+ for (const r3 of assessment.reasons) lines.push(` - ${r3}`);
6713
8299
  }
6714
8300
  lines.push(`- Next step: ${exp.readiness.recommended_next_step.label}`);
6715
8301
  lines.push("");
@@ -6721,11 +8307,11 @@ function renderExplanationHuman(exp) {
6721
8307
  steps.forEach((s2, i) => lines.push(`${i + 1}. ${s2}`));
6722
8308
  lines.push("");
6723
8309
  }
6724
- const r = exp.readiness;
6725
- const s = r.signals;
8310
+ const r2 = exp.readiness;
8311
+ const s = r2.signals;
6726
8312
  lines.push("## Project Readiness");
6727
- lines.push(`- overall: ${r.overall}`);
6728
- 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") {
6729
8315
  lines.push(`- bootstrap baseline: ${s.bootstrap_baseline}`);
6730
8316
  lines.push(`- scan: ${s.scan}`);
6731
8317
  lines.push(`- understand: ${s.understand}`);
@@ -6745,11 +8331,11 @@ function renderExplanationHuman(exp) {
6745
8331
  }
6746
8332
  lines.push("");
6747
8333
  lines.push("### Recommended next step");
6748
- lines.push(r.recommended_next_step.label);
8334
+ lines.push(r2.recommended_next_step.label);
6749
8335
  lines.push("");
6750
8336
  const td = exp.techDecisions;
6751
8337
  const tk = exp.techKnowledge;
6752
- const mark = (b) => b ? "\u2713" : "\u2717";
8338
+ const mark = (b2) => b2 ? "\u2713" : "\u2717";
6753
8339
  lines.push("## Tech Knowledge");
6754
8340
  lines.push("Core:");
6755
8341
  lines.push(`- ${mark(tk.core.currentState)} current-state.md`);
@@ -6824,8 +8410,8 @@ function renderExplanationHuman(exp) {
6824
8410
  }
6825
8411
  if (exp.metadataHealth.findings.length > 0) {
6826
8412
  lines.push("## Metadata Health");
6827
- for (const f of exp.metadataHealth.findings) {
6828
- lines.push(`- \`${f.file}\`: ${f.detail}`);
8413
+ for (const f3 of exp.metadataHealth.findings) {
8414
+ lines.push(`- \`${f3.file}\`: ${f3.detail}`);
6829
8415
  }
6830
8416
  lines.push("");
6831
8417
  }
@@ -6858,30 +8444,30 @@ function loadGuardRuns(dir) {
6858
8444
  return out;
6859
8445
  }
6860
8446
  function resolveDriftThreads(runs) {
6861
- 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));
6862
8448
  const paths = /* @__PURE__ */ new Set();
6863
- 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);
6864
8450
  const threads = [];
6865
8451
  for (const codePath of paths) {
6866
8452
  const related = /* @__PURE__ */ new Set();
6867
8453
  let firstDetected = "";
6868
8454
  let lastWarn = "";
6869
- for (const r of sorted) {
6870
- const w = r.warnings.find((x) => x.code_path === codePath);
6871
- if (w) {
6872
- if (!firstDetected) firstDetected = r.generated_at;
6873
- lastWarn = r.generated_at;
6874
- 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);
6875
8461
  }
6876
8462
  }
6877
8463
  let resolvedAt;
6878
- for (const r of sorted) {
6879
- if (r.generated_at <= lastWarn) continue;
6880
- const touched = r.touched_files.some((f) => toPosix5(f) === codePath);
6881
- const warnedHere = r.warnings.some((x) => x.code_path === codePath);
6882
- 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));
6883
8469
  if (touched && updatedRelated && !warnedHere) {
6884
- resolvedAt = r.generated_at;
8470
+ resolvedAt = r2.generated_at;
6885
8471
  break;
6886
8472
  }
6887
8473
  }
@@ -6902,9 +8488,9 @@ function hotspotDir(codePath) {
6902
8488
  }
6903
8489
  function computeTrend(runs) {
6904
8490
  if (runs.length < 2) return { direction: "unknown", reason: "Not enough recorded runs to detect a trend." };
6905
- 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));
6906
8492
  const mid = Math.floor(sorted.length / 2);
6907
- 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;
6908
8494
  const earlier = avg(sorted.slice(0, mid));
6909
8495
  const recent = avg(sorted.slice(mid));
6910
8496
  if (recent < earlier) return { direction: "improving", reason: "Fewer warnings in the last recorded runs." };
@@ -6930,18 +8516,18 @@ function buildGuardHistory(dir) {
6930
8516
  trend: { direction: "unknown", reason: "No guard history recorded yet." }
6931
8517
  };
6932
8518
  }
6933
- 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));
6934
8520
  const threads = resolveDriftThreads(sorted);
6935
8521
  const open = threads.filter((t) => t.status === "open").length;
6936
8522
  const resolved = threads.filter((t) => t.status === "resolved").length;
6937
8523
  const detected = threads.length;
6938
- const runsWithWarnings = sorted.filter((r) => r.warnings.length > 0).length;
8524
+ const runsWithWarnings = sorted.filter((r2) => r2.warnings.length > 0).length;
6939
8525
  const hotspotMap = /* @__PURE__ */ new Map();
6940
8526
  for (const t of threads) {
6941
- const d = hotspotDir(t.code_path);
6942
- hotspotMap.set(d, (hotspotMap.get(d) ?? 0) + 1);
8527
+ const d3 = hotspotDir(t.code_path);
8528
+ hotspotMap.set(d3, (hotspotMap.get(d3) ?? 0) + 1);
6943
8529
  }
6944
- 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);
6945
8531
  return {
6946
8532
  available: true,
6947
8533
  total_runs: sorted.length,
@@ -6965,14 +8551,14 @@ function isBroadGlob(glob) {
6965
8551
  const prefix = glob.slice(0, -3);
6966
8552
  return prefix.length > 0 && prefix.split("/").length <= 2;
6967
8553
  }
6968
- function levelFromRatio(r) {
6969
- if (r >= 0.9) return "Very High";
6970
- if (r >= 0.7) return "High";
6971
- 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";
6972
8558
  return "Low";
6973
8559
  }
6974
8560
  function hasSection(body, re) {
6975
- 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));
6976
8562
  }
6977
8563
  function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
6978
8564
  const resolvedScope = opts.scope ?? "all";
@@ -7038,7 +8624,7 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7038
8624
  } catch {
7039
8625
  }
7040
8626
  }
7041
- const ownedCodePaths = [...globCounts.values()].reduce((a, b) => a + b, 0);
8627
+ const ownedCodePaths = [...globCounts.values()].reduce((a2, b2) => a2 + b2, 0);
7042
8628
  const broadGlobs = [...globCounts.keys()].filter((g2) => isBroadGlob(g2)).length;
7043
8629
  for (const [glob, owners] of globOwners) {
7044
8630
  if (owners.length > 1) {
@@ -7055,7 +8641,7 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7055
8641
  } else {
7056
8642
  g = { available: false, scope: resolvedScope, scopeReason: "", nodes: 0, edges: 0, quality: "unknown", hints: 0, generatedAt: "" };
7057
8643
  }
7058
- 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";
7059
8645
  const byState = exp.workItems.byState;
7060
8646
  const skills = discoverInstalledSkills(dir);
7061
8647
  const knowledge_health = {
@@ -7125,7 +8711,7 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7125
8711
  let score_breakdown = null;
7126
8712
  if (total > 0) {
7127
8713
  const healthPts = [layerStatus("Business"), layerStatus("Product"), layerStatus("Tech"), layerStatus("Delivery")].filter((s) => s !== "Missing").length / 4 * 20;
7128
- 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;
7129
8715
  const coveragePts = covAvg * 20;
7130
8716
  const ownPts = coverageRatio(withOwnership) * 15;
7131
8717
  const traceBlend = (exp.roadmap.candidates > 0 ? exp.roadmap.materialized / exp.roadmap.candidates : 1) * 0.5 + coverageRatio(withOwnership) * 0.5;
@@ -7153,14 +8739,14 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7153
8739
  if (!g.available) actions.push("Run `kaddo graph export --scope all` to inspect full traceability.");
7154
8740
  else if (g.scope === "active" && g.quality === "empty") actions.push("Run `kaddo impact --scope all` to measure accumulated knowledge impact.");
7155
8741
  if (exp.roadmap.remaining > 0) actions.push(`Materialize the ${exp.roadmap.remaining} remaining roadmap candidate(s) with \`kaddo create --from roadmap\`.`);
7156
- for (const a of [
8742
+ for (const a2 of [
7157
8743
  groupedAction(gaps.missing_code_ownership, "Add `code:` ownership to"),
7158
8744
  groupedAction(gaps.missing_source, "Add `source`/`source_id` to"),
7159
8745
  groupedAction(gaps.missing_initiative, "Add an `initiative` to"),
7160
8746
  groupedAction(gaps.missing_acceptance_criteria, "Add Acceptance Criteria to"),
7161
8747
  groupedAction(gaps.missing_definition_of_done, "Add a Definition of Done to"),
7162
8748
  groupedAction(gaps.missing_validation, "Add a validation (How to test it) section to")
7163
- ]) if (a) actions.push(a);
8749
+ ]) if (a2) actions.push(a2);
7164
8750
  if (gaps.broad_ownership_globs.length > 0) actions.push(`Narrow ${gaps.broad_ownership_globs.length} broad ownership glob(s) into specific paths.`);
7165
8751
  if (g.available && g.hints > 0) actions.push("Review graph hints (`kaddo://graph-hints` or `.kaddo/graph-hints.md`).");
7166
8752
  if (skills.length === 0) actions.push("Install reusable skills with `kaddo add skills`.");
@@ -7224,38 +8810,38 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7224
8810
  function ratio(have, total) {
7225
8811
  return `${have}/${total}`;
7226
8812
  }
7227
- function renderImpactMarkdown(r) {
8813
+ function renderImpactMarkdown(r2) {
7228
8814
  const L = [];
7229
8815
  L.push("# Kaddo Knowledge Impact Report", "");
7230
- L.push(`Generated at: ${r.generated_at}`);
7231
- L.push(`Project: ${r.project}`);
7232
- L.push(`Scope: ${r.scope}`);
7233
- 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`);
7234
8820
  else L.push("Knowledge Impact Score: not available");
7235
- if (r.scope_source === "default") {
8821
+ if (r2.scope_source === "default") {
7236
8822
  L.push("Scope note: Impact reports use `all` by default to measure accumulated knowledge impact.");
7237
- } else if (r.scope === "active" && r.graph_quality.available === false) {
8823
+ } else if (r2.scope === "active" && r2.graph_quality.available === false) {
7238
8824
  L.push("Tip: Run `kaddo impact --scope all` to inspect accumulated knowledge impact.");
7239
8825
  }
7240
8826
  L.push("");
7241
8827
  L.push("## Executive Summary", "");
7242
- for (const s2 of r.executive_summary) L.push(`- ${s2}`);
8828
+ for (const s2 of r2.executive_summary) L.push(`- ${s2}`);
7243
8829
  L.push("");
7244
8830
  L.push("## Knowledge Health", "");
7245
- 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}`);
7246
8832
  L.push("");
7247
8833
  L.push("## Knowledge Coverage", "");
7248
- 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)}`);
7249
8835
  L.push("");
7250
8836
  L.push("## Ownership Coverage", "");
7251
- L.push(`- Coverage: ${r.ownership_coverage.coverage_percent}%`);
7252
- L.push(`- Work Items with code ownership: ${r.ownership_coverage.work_items_with_ownership}`);
7253
- L.push(`- Owned code paths: ${r.ownership_coverage.owned_code_paths}`);
7254
- L.push(`- Broad globs detected: ${r.ownership_coverage.broad_globs}`);
7255
- 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}`);
7256
8842
  L.push("");
7257
8843
  L.push("## Traceability", "");
7258
- const t = r.traceability;
8844
+ const t = r2.traceability;
7259
8845
  L.push(`- Roadmap candidates: ${t.roadmap_candidates}`);
7260
8846
  L.push(`- Materialized Work Items: ${t.materialized_work_items}`);
7261
8847
  L.push(`- Remaining candidates: ${t.remaining_candidates}`);
@@ -7268,24 +8854,24 @@ function renderImpactMarkdown(r) {
7268
8854
  if (t.graph_hints !== null) L.push(`- Graph hints: ${t.graph_hints}`);
7269
8855
  L.push("");
7270
8856
  L.push("## Context Readiness", "");
7271
- L.push(`Context Readiness: ${r.context_readiness.level}`);
7272
- if (r.context_readiness.reasons.length > 0) {
8857
+ L.push(`Context Readiness: ${r2.context_readiness.level}`);
8858
+ if (r2.context_readiness.reasons.length > 0) {
7273
8859
  L.push("", "Reason:");
7274
- for (const reason of r.context_readiness.reasons) L.push(`- ${reason}`);
8860
+ for (const reason of r2.context_readiness.reasons) L.push(`- ${reason}`);
7275
8861
  }
7276
8862
  L.push("");
7277
8863
  L.push("## Work Item Readiness", "");
7278
- const w = r.work_item_readiness;
7279
- L.push(`- Draft: ${w.draft}`);
7280
- L.push(`- Ready: ${w.ready}`);
7281
- L.push(`- In Progress: ${w.in_progress}`);
7282
- L.push(`- Blocked: ${w.blocked}`);
7283
- L.push(`- Completed: ${w.completed}`);
7284
- 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}`);
7285
8871
  L.push("");
7286
8872
  L.push("## Graph Quality", "");
7287
- if (r.graph_quality.available) {
7288
- const gq = r.graph_quality;
8873
+ if (r2.graph_quality.available) {
8874
+ const gq = r2.graph_quality;
7289
8875
  L.push(`- Scope: ${gq.scope}`);
7290
8876
  L.push(`- Quality: ${gq.quality}`);
7291
8877
  L.push(`- Nodes: ${gq.nodes}`);
@@ -7298,12 +8884,12 @@ function renderImpactMarkdown(r) {
7298
8884
  }
7299
8885
  } else {
7300
8886
  L.push("- Graph data not available.");
7301
- L.push(`- Tip: ${r.graph_quality.suggestion}`);
8887
+ L.push(`- Tip: ${r2.graph_quality.suggestion}`);
7302
8888
  }
7303
8889
  L.push("");
7304
8890
  L.push("## Guard Activity", "");
7305
- if (r.guard_activity.available) {
7306
- const ga = r.guard_activity;
8891
+ if (r2.guard_activity.available) {
8892
+ const ga = r2.guard_activity;
7307
8893
  L.push("- Guard history: available");
7308
8894
  L.push(`- Guard runs recorded: ${ga.runs_recorded}`);
7309
8895
  L.push(`- Drift warnings detected: ${ga.detected}`);
@@ -7312,11 +8898,11 @@ function renderImpactMarkdown(r) {
7312
8898
  L.push(`- Resolution rate: ${ga.resolution_rate}%`);
7313
8899
  } else {
7314
8900
  L.push("- Guard history: not available");
7315
- L.push(`- Note: ${r.guard_activity.note}`);
8901
+ L.push(`- Note: ${r2.guard_activity.note}`);
7316
8902
  }
7317
8903
  L.push("");
7318
8904
  L.push("## Impact Signals", "");
7319
- const s = r.impact_signals;
8905
+ const s = r2.impact_signals;
7320
8906
  L.push(`- Ambiguity reduction: ${s.ambiguity_reduction}`);
7321
8907
  L.push(`- Drift prevention: ${s.drift_prevention}`);
7322
8908
  L.push(`- Onboarding support: ${s.onboarding_support}`);
@@ -7325,7 +8911,7 @@ function renderImpactMarkdown(r) {
7325
8911
  L.push(`- Maintenance readiness: ${s.maintenance_readiness}`);
7326
8912
  L.push("");
7327
8913
  L.push("## Actionable Gaps", "");
7328
- const gp = r.actionable_gaps;
8914
+ const gp = r2.actionable_gaps;
7329
8915
  const gapSection = (title, items) => {
7330
8916
  if (items.length === 0) return;
7331
8917
  L.push(`### ${title}`, "");
@@ -7345,19 +8931,19 @@ function renderImpactMarkdown(r) {
7345
8931
  gapSection("Work Items missing validation", gp.missing_validation);
7346
8932
  if (gp.broad_ownership_globs.length > 0) {
7347
8933
  L.push("### Broad ownership globs", "");
7348
- for (const b of gp.broad_ownership_globs) {
7349
- L.push(`- ${b.id} \u2014 ${b.title}`);
7350
- L.push(` - Glob: \`${b.glob}\``);
7351
- 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}`);
7352
8938
  }
7353
8939
  L.push("");
7354
8940
  }
7355
8941
  if (gp.ownership_overlaps.length > 0) {
7356
8942
  L.push("### Ownership overlaps", "");
7357
- for (const o of gp.ownership_overlaps) {
7358
- L.push(`- \`${o.code_path}\``);
7359
- L.push(` - Owned by: ${o.work_items.join(", ")}`);
7360
- 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}`);
7361
8947
  }
7362
8948
  L.push("");
7363
8949
  }
@@ -7365,28 +8951,28 @@ function renderImpactMarkdown(r) {
7365
8951
  if (anyGaps === 0) {
7366
8952
  L.push("No actionable knowledge gaps detected. \u{1F389}", "");
7367
8953
  }
7368
- if (r.score_breakdown) {
8954
+ if (r2.score_breakdown) {
7369
8955
  L.push("## Score Breakdown", "");
7370
- const b = r.score_breakdown;
7371
- L.push(`- Knowledge Health: ${b.knowledge_health.points}/${b.knowledge_health.max}`);
7372
- L.push(`- Knowledge Coverage: ${b.knowledge_coverage.points}/${b.knowledge_coverage.max}`);
7373
- L.push(`- Ownership Coverage: ${b.ownership_coverage.points}/${b.ownership_coverage.max}`);
7374
- L.push(`- Traceability: ${b.traceability.points}/${b.traceability.max}`);
7375
- L.push(`- Graph Quality: ${b.graph_quality.points}/${b.graph_quality.max}`);
7376
- 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}`);
7377
8963
  L.push("");
7378
8964
  }
7379
8965
  L.push("## Suggested Actions", "");
7380
- r.suggested_actions.forEach((a, i) => L.push(`${i + 1}. ${a}`));
8966
+ r2.suggested_actions.forEach((a2, i) => L.push(`${i + 1}. ${a2}`));
7381
8967
  L.push("");
7382
8968
  return L.join("\n");
7383
8969
  }
7384
- function serializeImpactJson(r) {
7385
- return JSON.stringify(r, null, 2) + "\n";
8970
+ function serializeImpactJson(r2) {
8971
+ return JSON.stringify(r2, null, 2) + "\n";
7386
8972
  }
7387
8973
 
7388
8974
  // ../cli/src/core/savings.ts
7389
- import { parse as parseYaml6 } from "yaml";
8975
+ import { parse as parseYaml7 } from "yaml";
7390
8976
  var DEFAULT_ASSUMPTIONS = {
7391
8977
  currency: "USD",
7392
8978
  hourly_cost: 40,
@@ -7404,21 +8990,21 @@ function loadAssumptions(dir) {
7404
8990
  const p = join(dir, SAVINGS_PATH);
7405
8991
  if (!exists(p)) return { assumptions: { ...DEFAULT_ASSUMPTIONS }, source: "default" };
7406
8992
  try {
7407
- const raw = parseYaml6(readFile(p));
7408
- const a = raw?.assumptions ?? {};
8993
+ const raw = parseYaml7(readFile(p));
8994
+ const a2 = raw?.assumptions ?? {};
7409
8995
  const t = raw?.team ?? {};
7410
- 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;
7411
8997
  return {
7412
8998
  source: "file",
7413
8999
  assumptions: {
7414
9000
  currency: raw?.currency ?? DEFAULT_ASSUMPTIONS.currency,
7415
9001
  hourly_cost: num(raw?.hourly_cost, DEFAULT_ASSUMPTIONS.hourly_cost),
7416
- 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),
7417
- rework_hours_avoided_per_resolved_drift: num(a.rework_hours_avoided_per_resolved_drift, DEFAULT_ASSUMPTIONS.rework_hours_avoided_per_resolved_drift),
7418
- onboarding_hours_saved_per_new_contributor: num(a.onboarding_hours_saved_per_new_contributor, DEFAULT_ASSUMPTIONS.onboarding_hours_saved_per_new_contributor),
7419
- 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),
7420
- 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),
7421
- 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),
7422
9008
  expected_new_contributors_per_month: num(t.expected_new_contributors_per_month, DEFAULT_ASSUMPTIONS.expected_new_contributors_per_month),
7423
9009
  expected_work_items_per_month: num(t.expected_work_items_per_month, DEFAULT_ASSUMPTIONS.expected_work_items_per_month)
7424
9010
  }
@@ -7431,12 +9017,12 @@ var READINESS_MULT = { Low: 0.25, Medium: 0.5, High: 0.75, "Very High": 1 };
7431
9017
  var GRAPH_MULT = { empty: 0, sparse: 0.25, partial: 0.6, good: 1, unknown: 0 };
7432
9018
  var round2 = (n) => Math.round(n * 100) / 100;
7433
9019
  function parseRatioNumerator(s) {
7434
- const m = s.match(/^(\d+)/);
7435
- return m ? Number(m[1]) : 0;
9020
+ const m2 = s.match(/^(\d+)/);
9021
+ return m2 ? Number(m2[1]) : 0;
7436
9022
  }
7437
9023
  var SAVINGS_DISCLAIMER = "These are evidence-based estimates, not exact ROI. Adjust assumptions with real team data.";
7438
9024
  function buildSavingsReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7439
- const { assumptions: a, source } = loadAssumptions(dir);
9025
+ const { assumptions: a2, source } = loadAssumptions(dir);
7440
9026
  const impact = buildImpactReport(dir, { scope: opts.scope, scopeSource: opts.scopeSource }, now);
7441
9027
  const completed = impact.traceability.completed_work_items;
7442
9028
  const wiWithOwnership = parseRatioNumerator(impact.traceability.work_items_connected_to_code);
@@ -7444,13 +9030,13 @@ function buildSavingsReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7444
9030
  const wiWithAcceptance = acceptanceCov?.have ?? 0;
7445
9031
  const graphQuality = impact.graph_quality.available ? impact.graph_quality.quality : "unknown";
7446
9032
  const readiness = impact.context_readiness.level;
7447
- const ctxPrepH = round2(completed * a.context_preparation_minutes_saved_per_work_item / 60);
7448
- const reviewH = round2(wiWithOwnership * a.review_minutes_saved_per_work_item_with_ownership / 60);
7449
- 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);
7450
9036
  const readinessMult = READINESS_MULT[readiness] ?? 0.5;
7451
- 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);
7452
9038
  const graphMult = GRAPH_MULT[graphQuality] ?? 0;
7453
- 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);
7454
9040
  const guard = buildGuardHistory(dir);
7455
9041
  let driftSavings;
7456
9042
  if (!guard.available) {
@@ -7458,19 +9044,19 @@ function buildSavingsReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7458
9044
  } else if (guard.resolved > 0) {
7459
9045
  driftSavings = {
7460
9046
  available: true,
7461
- hours: round2(guard.resolved * a.rework_hours_avoided_per_resolved_drift),
7462
- 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`
7463
9049
  };
7464
9050
  } else {
7465
9051
  driftSavings = {
7466
9052
  available: true,
7467
9053
  hours: 0,
7468
- 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`,
7469
9055
  reason: "Guard history exists, but no resolved drift warnings have been recorded yet."
7470
9056
  };
7471
9057
  }
7472
9058
  const totalHours = round2(ctxPrepH + reviewH + clarH + onboardH + archH + driftSavings.hours);
7473
- const totalValue = Math.round(totalHours * a.hourly_cost);
9059
+ const totalValue = Math.round(totalHours * a2.hourly_cost);
7474
9060
  const reasons = [];
7475
9061
  let level;
7476
9062
  if (impact.score === null || impact.score < 60 || graphQuality === "empty") {
@@ -7508,17 +9094,17 @@ function buildSavingsReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7508
9094
  generated_at: now.toISOString(),
7509
9095
  project: impact.project,
7510
9096
  scope: impact.scope,
7511
- currency: a.currency,
9097
+ currency: a2.currency,
7512
9098
  disclaimer: SAVINGS_DISCLAIMER,
7513
9099
  assumptions_source: source,
7514
9100
  assumptions: {
7515
- hourly_cost: a.hourly_cost,
7516
- context_preparation_minutes_saved_per_work_item: a.context_preparation_minutes_saved_per_work_item,
7517
- review_minutes_saved_per_work_item_with_ownership: a.review_minutes_saved_per_work_item_with_ownership,
7518
- clarification_minutes_saved_per_ready_work_item: a.clarification_minutes_saved_per_ready_work_item,
7519
- onboarding_hours_saved_per_new_contributor: a.onboarding_hours_saved_per_new_contributor,
7520
- expected_new_contributors_per_month: a.expected_new_contributors_per_month,
7521
- 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
7522
9108
  },
7523
9109
  evidence: {
7524
9110
  knowledge_impact_score: impact.score,
@@ -7534,45 +9120,45 @@ function buildSavingsReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
7534
9120
  resolved_drift_warnings: guard.resolved
7535
9121
  },
7536
9122
  estimated_savings: {
7537
- context_preparation: { hours: ctxPrepH, formula: `${completed} Work Items \xD7 ${a.context_preparation_minutes_saved_per_work_item} min` },
7538
- review_effort: { hours: reviewH, formula: `${wiWithOwnership} Work Items with ownership \xD7 ${a.review_minutes_saved_per_work_item_with_ownership} min` },
7539
- clarification_reduction: { hours: clarH, formula: `${wiWithAcceptance} Work Items with Acceptance Criteria \xD7 ${a.clarification_minutes_saved_per_ready_work_item} min` },
7540
- 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` },
7541
- 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` },
7542
9128
  drift_prevention: driftSavings
7543
9129
  },
7544
- total: { estimated_hours_saved: totalHours, estimated_value: totalValue, currency: a.currency },
9130
+ total: { estimated_hours_saved: totalHours, estimated_value: totalValue, currency: a2.currency },
7545
9131
  confidence: { level, reasons },
7546
9132
  suggested_actions: actions
7547
9133
  };
7548
9134
  }
7549
- function renderSavingsMarkdown(r) {
9135
+ function renderSavingsMarkdown(r2) {
7550
9136
  const L = [];
7551
9137
  L.push("# Kaddo Estimated Savings Report", "");
7552
- L.push(`Generated at: ${r.generated_at}`);
7553
- L.push(`Project: ${r.project}`);
7554
- L.push(`Scope: ${r.scope}`);
7555
- 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}`);
7556
9142
  L.push("");
7557
9143
  L.push("## Disclaimer", "");
7558
- L.push(r.disclaimer, "");
9144
+ L.push(r2.disclaimer, "");
7559
9145
  L.push("## Executive Summary", "");
7560
- L.push(`- Estimated time saved: ${r.total.estimated_hours_saved} hours`);
7561
- L.push(`- Estimated value: ${r.total.estimated_value} ${r.currency}`);
7562
- L.push(`- Confidence: ${r.confidence.level}`);
7563
- 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.");
7564
9150
  L.push("");
7565
9151
  L.push("## Assumptions", "");
7566
- L.push(`- Hourly cost: ${r.assumptions.hourly_cost} ${r.currency}`);
7567
- L.push(`- Context preparation saved per Work Item: ${r.assumptions.context_preparation_minutes_saved_per_work_item} min`);
7568
- L.push(`- Review saved per Work Item with ownership: ${r.assumptions.review_minutes_saved_per_work_item_with_ownership} min`);
7569
- L.push(`- Clarification saved per Work Item with acceptance criteria: ${r.assumptions.clarification_minutes_saved_per_ready_work_item} min`);
7570
- L.push(`- Onboarding saved per new contributor: ${r.assumptions.onboarding_hours_saved_per_new_contributor} h`);
7571
- L.push(`- Expected new contributors per month: ${r.assumptions.expected_new_contributors_per_month}`);
7572
- 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`);
7573
9159
  L.push("");
7574
9160
  L.push("## Evidence Used", "");
7575
- const e = r.evidence;
9161
+ const e = r2.evidence;
7576
9162
  L.push(`- Knowledge Impact Score: ${e.knowledge_impact_score ?? "not available"}${e.knowledge_impact_score !== null ? "/100" : ""}`);
7577
9163
  L.push(`- Completed Work Items: ${e.completed_work_items}`);
7578
9164
  L.push(`- Ownership coverage: ${e.ownership_coverage_percent}%`);
@@ -7590,11 +9176,11 @@ function renderSavingsMarkdown(r) {
7590
9176
  }
7591
9177
  L.push("");
7592
9178
  L.push("## Estimated Savings", "");
7593
- const s = r.estimated_savings;
7594
- const line = (title, l) => {
9179
+ const s = r2.estimated_savings;
9180
+ const line = (title, l2) => {
7595
9181
  L.push(`### ${title}`, "");
7596
- L.push(`- Formula: ${l.formula}`);
7597
- L.push(`- Estimated: ${l.hours} h`, "");
9182
+ L.push(`- Formula: ${l2.formula}`);
9183
+ L.push(`- Estimated: ${l2.hours} h`, "");
7598
9184
  };
7599
9185
  line("Context Preparation", s.context_preparation);
7600
9186
  line("Review Effort", s.review_effort);
@@ -7612,31 +9198,31 @@ function renderSavingsMarkdown(r) {
7612
9198
  L.push(`- Reason: ${s.drift_prevention.reason}`, "");
7613
9199
  }
7614
9200
  L.push("## Total", "");
7615
- L.push(`- Estimated time saved: ${r.total.estimated_hours_saved} h`);
7616
- 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}`);
7617
9203
  L.push("");
7618
9204
  L.push("## Confidence", "");
7619
- L.push(`Confidence: ${r.confidence.level}`, "", "Reason:");
7620
- 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}`);
7621
9207
  L.push("");
7622
9208
  L.push("## Suggested Actions", "");
7623
- r.suggested_actions.forEach((act, i) => L.push(`${i + 1}. ${act}`));
9209
+ r2.suggested_actions.forEach((act, i) => L.push(`${i + 1}. ${act}`));
7624
9210
  L.push("");
7625
9211
  return L.join("\n");
7626
9212
  }
7627
- function serializeSavingsJson(r) {
7628
- return JSON.stringify(r, null, 2) + "\n";
9213
+ function serializeSavingsJson(r2) {
9214
+ return JSON.stringify(r2, null, 2) + "\n";
7629
9215
  }
7630
9216
 
7631
9217
  // ../cli/src/core/drift-report.ts
7632
9218
  function buildDriftReport(dir, now = /* @__PURE__ */ new Date()) {
7633
- const h = buildGuardHistory(dir);
9219
+ const h2 = buildGuardHistory(dir);
7634
9220
  const project = loadConfig(dir)?.project.name ?? "unknown";
7635
9221
  const actions = [];
7636
- if (!h.available) {
9222
+ if (!h2.available) {
7637
9223
  actions.push("Run `kaddo guard --record` to start recording guard history.");
7638
9224
  } else {
7639
- 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.");
7640
9226
  actions.push("Run `kaddo guard --record` before important commits.");
7641
9227
  actions.push("Use this report to calibrate estimated drift-prevention savings.");
7642
9228
  }
@@ -7644,55 +9230,55 @@ function buildDriftReport(dir, now = /* @__PURE__ */ new Date()) {
7644
9230
  generated_at: now.toISOString(),
7645
9231
  project,
7646
9232
  guard_history: {
7647
- available: h.available,
7648
- total_runs: h.total_runs,
7649
- first_run: h.first_run,
7650
- last_run: h.last_run,
7651
- runs_with_warnings: h.runs_with_warnings,
7652
- 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
7653
9239
  },
7654
- drift_warnings: { detected: h.detected, open: h.open, resolved: h.resolved, resolution_rate: h.resolution_rate },
7655
- hotspots: h.hotspots,
7656
- trend: h.trend,
7657
- 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,
7658
9244
  suggested_actions: actions
7659
9245
  };
7660
9246
  }
7661
- function renderDriftMarkdown(r) {
9247
+ function renderDriftMarkdown(r2) {
7662
9248
  const L = [];
7663
9249
  L.push("# Kaddo Drift Trend Report", "");
7664
- L.push(`Generated at: ${r.generated_at}`);
7665
- L.push(`Project: ${r.project}`);
9250
+ L.push(`Generated at: ${r2.generated_at}`);
9251
+ L.push(`Project: ${r2.project}`);
7666
9252
  L.push("");
7667
- if (!r.guard_history.available) {
9253
+ if (!r2.guard_history.available) {
7668
9254
  L.push("## Guard History", "");
7669
9255
  L.push("No guard history recorded yet.");
7670
9256
  L.push("");
7671
9257
  L.push("Run `kaddo guard --record` to start recording drift evidence.");
7672
9258
  L.push("");
7673
9259
  L.push("## Suggested Actions", "");
7674
- r.suggested_actions.forEach((a, i) => L.push(`${i + 1}. ${a}`));
9260
+ r2.suggested_actions.forEach((a2, i) => L.push(`${i + 1}. ${a2}`));
7675
9261
  L.push("");
7676
9262
  return L.join("\n");
7677
9263
  }
7678
- const w = r.drift_warnings;
9264
+ const w3 = r2.drift_warnings;
7679
9265
  L.push("## Executive Summary", "");
7680
- L.push(`- Guard runs recorded: ${r.guard_history.total_runs}`);
7681
- L.push(`- Drift warnings detected: ${w.detected}`);
7682
- L.push(`- Open warnings: ${w.open}`);
7683
- L.push(`- Resolved warnings: ${w.resolved}`);
7684
- L.push(`- Resolution rate: ${w.resolution_rate}%`);
7685
- 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}`);
7686
9272
  L.push("");
7687
9273
  L.push("## Guard History", "");
7688
- L.push(`- First run: ${r.guard_history.first_run}`);
7689
- L.push(`- Last run: ${r.guard_history.last_run}`);
7690
- L.push(`- Runs with warnings: ${r.guard_history.runs_with_warnings}/${r.guard_history.total_runs}`);
7691
- 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}`);
7692
9278
  L.push("");
7693
9279
  L.push("## Drift Warnings", "");
7694
- const open = r.threads.filter((t) => t.status === "open");
7695
- 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");
7696
9282
  L.push("### Open", "");
7697
9283
  if (open.length === 0) L.push("_None._", "");
7698
9284
  for (const t of open) {
@@ -7714,28 +9300,28 @@ function renderDriftMarkdown(r) {
7714
9300
  }
7715
9301
  L.push("");
7716
9302
  L.push("## Hotspots", "");
7717
- if (r.hotspots.length === 0) L.push("_None._");
7718
- 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)`);
7719
9305
  L.push("");
7720
9306
  L.push("## Trend", "");
7721
- L.push(`- Recent direction: ${r.trend.direction}`);
7722
- L.push(`- Reason: ${r.trend.reason}`);
9307
+ L.push(`- Recent direction: ${r2.trend.direction}`);
9308
+ L.push(`- Reason: ${r2.trend.reason}`);
7723
9309
  L.push("");
7724
9310
  L.push("## Suggested Actions", "");
7725
- r.suggested_actions.forEach((a, i) => L.push(`${i + 1}. ${a}`));
9311
+ r2.suggested_actions.forEach((a2, i) => L.push(`${i + 1}. ${a2}`));
7726
9312
  L.push("");
7727
9313
  return L.join("\n");
7728
9314
  }
7729
- function serializeDriftJson(r) {
9315
+ function serializeDriftJson(r2) {
7730
9316
  const out = {
7731
- generated_at: r.generated_at,
7732
- project: r.project,
7733
- guard_history: r.guard_history,
7734
- drift_warnings: r.drift_warnings,
7735
- hotspots: r.hotspots,
7736
- trend: r.trend,
7737
- threads: r.threads,
7738
- 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
7739
9325
  };
7740
9326
  return JSON.stringify(out, null, 2) + "\n";
7741
9327
  }
@@ -7765,7 +9351,7 @@ function parseSource(data) {
7765
9351
  }
7766
9352
  var ACTIVE_STATES2 = /* @__PURE__ */ new Set(["draft", "ready", "in-progress", "blocked"]);
7767
9353
  function strArray(v) {
7768
- return Array.isArray(v) ? v.map((x) => String(x)).filter(Boolean) : [];
9354
+ return Array.isArray(v) ? v.map((x2) => String(x2)).filter(Boolean) : [];
7769
9355
  }
7770
9356
  function lifecycleOf(data, relPath) {
7771
9357
  const status = String(data.status ?? "").trim();
@@ -7817,7 +9403,7 @@ function listWorkItems(root) {
7817
9403
  readiness
7818
9404
  });
7819
9405
  }
7820
- return items.sort((a, b) => a.id.localeCompare(b.id));
9406
+ return items.sort((a2, b2) => a2.id.localeCompare(b2.id));
7821
9407
  }
7822
9408
  function assessReadiness(data, content, code, domains, source) {
7823
9409
  const body = content.trim();
@@ -7844,12 +9430,12 @@ function assessReadiness(data, content, code, domains, source) {
7844
9430
  }
7845
9431
 
7846
9432
  // src/resources.ts
7847
- function text(uri, body, mimeType = "text/markdown") {
9433
+ function text2(uri, body, mimeType = "text/markdown") {
7848
9434
  return [{ uri, text: body, mimeType }];
7849
9435
  }
7850
9436
  function fileOrHint(root, uri, rel, hint, mimeType = "text/markdown") {
7851
9437
  const body = readText(root, rel);
7852
- return text(uri, body ?? hint, body ? mimeType : "text/plain");
9438
+ return text2(uri, body ?? hint, body ? mimeType : "text/plain");
7853
9439
  }
7854
9440
  var RESOURCES = [
7855
9441
  {
@@ -7897,7 +9483,7 @@ var RESOURCES = [
7897
9483
  const json = readText(root, ".kaddo/graph.json");
7898
9484
  const mmd = readText(root, ".kaddo/graph.mmd");
7899
9485
  if (!json && !mmd) {
7900
- 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");
7901
9487
  }
7902
9488
  const parts = [];
7903
9489
  if (json) parts.push({ uri: "kaddo://graph", text: json, mimeType: "application/json" });
@@ -7914,7 +9500,7 @@ var RESOURCES = [
7914
9500
  const md = readText(root, ".kaddo/graph-hints.md");
7915
9501
  const json = readText(root, ".kaddo/graph-hints.json");
7916
9502
  if (!md && !json) {
7917
- 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");
7918
9504
  }
7919
9505
  const parts = [];
7920
9506
  if (md) parts.push({ uri: "kaddo://graph-hints", text: md, mimeType: "text/markdown" });
@@ -7929,7 +9515,7 @@ var RESOURCES = [
7929
9515
  mimeType: "application/json",
7930
9516
  read: (root) => {
7931
9517
  if (!hasKnowledge(root)) {
7932
- 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");
7933
9519
  }
7934
9520
  return [
7935
9521
  {
@@ -8000,7 +9586,7 @@ var RESOURCES = [
8000
9586
  const saved = readText(root, ".kaddo/reports/impact-report.md");
8001
9587
  if (saved) return [{ uri: "kaddo://impact-report", text: saved, mimeType: "text/markdown" }];
8002
9588
  if (!hasKnowledge(root)) {
8003
- 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");
8004
9590
  }
8005
9591
  return [{ uri: "kaddo://impact-report", text: renderImpactMarkdown(buildImpactReport(root, { scope: "all", scopeSource: "default" })), mimeType: "text/markdown" }];
8006
9592
  }
@@ -8014,7 +9600,7 @@ var RESOURCES = [
8014
9600
  const saved = readText(root, ".kaddo/reports/savings-report.md");
8015
9601
  if (saved) return [{ uri: "kaddo://savings-report", text: saved, mimeType: "text/markdown" }];
8016
9602
  if (!hasKnowledge(root)) {
8017
- 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");
8018
9604
  }
8019
9605
  return [{ uri: "kaddo://savings-report", text: renderSavingsMarkdown(buildSavingsReport(root, { scope: "all", scopeSource: "default" })), mimeType: "text/markdown" }];
8020
9606
  }
@@ -8038,7 +9624,7 @@ var RESOURCES = [
8038
9624
  read: (root) => {
8039
9625
  const runs = readText(root, ".kaddo/history/guard-runs.jsonl");
8040
9626
  if (runs === null) {
8041
- 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");
8042
9628
  }
8043
9629
  return [{ uri: "kaddo://guard-history", text: runs, mimeType: "application/jsonl" }];
8044
9630
  }
@@ -8050,10 +9636,10 @@ var RESOURCES = [
8050
9636
  mimeType: "application/json",
8051
9637
  read: (root) => {
8052
9638
  if (!hasKnowledge(root)) {
8053
- 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");
8054
9640
  }
8055
- const r = buildOpenQuestionsReport(root);
8056
- 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" }];
8057
9643
  }
8058
9644
  },
8059
9645
  {
@@ -8063,7 +9649,7 @@ var RESOURCES = [
8063
9649
  mimeType: "application/json",
8064
9650
  read: (root) => {
8065
9651
  if (!hasKnowledge(root)) {
8066
- 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");
8067
9653
  }
8068
9654
  return [{ uri: "kaddo://roadmap-readiness", text: JSON.stringify(roadmapReadinessSummary(root), null, 2), mimeType: "application/json" }];
8069
9655
  }
@@ -8075,7 +9661,7 @@ var RESOURCES = [
8075
9661
  mimeType: "application/json",
8076
9662
  read: (root) => {
8077
9663
  if (!hasKnowledge(root)) {
8078
- 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");
8079
9665
  }
8080
9666
  return [{ uri: "kaddo://tech-decisions", text: JSON.stringify(buildTechDecisions(root), null, 2), mimeType: "application/json" }];
8081
9667
  }
@@ -8087,7 +9673,7 @@ var RESOURCES = [
8087
9673
  mimeType: "application/json",
8088
9674
  read: (root) => {
8089
9675
  if (!hasKnowledge(root)) {
8090
- 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");
8091
9677
  }
8092
9678
  return [{ uri: "kaddo://installed-assets", text: JSON.stringify(installedAssetsSummary(root), null, 2), mimeType: "application/json" }];
8093
9679
  }
@@ -8099,7 +9685,7 @@ var RESOURCES = [
8099
9685
  mimeType: "application/json",
8100
9686
  read: (root) => {
8101
9687
  if (!hasKnowledge(root)) {
8102
- 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");
8103
9689
  }
8104
9690
  return [{ uri: "kaddo://roadmap-quality", text: JSON.stringify(buildRoadmapQuality(root), null, 2), mimeType: "application/json" }];
8105
9691
  }
@@ -8111,7 +9697,7 @@ var RESOURCES = [
8111
9697
  mimeType: "application/json",
8112
9698
  read: (root) => {
8113
9699
  if (!hasKnowledge(root)) {
8114
- 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");
8115
9701
  }
8116
9702
  const md = readText(root, "knowledge/delivery/roadmap.md");
8117
9703
  const candidates = md ? parseRoadmapCandidates(md) : [];
@@ -8125,7 +9711,7 @@ var RESOURCES = [
8125
9711
  mimeType: "application/json",
8126
9712
  read: (root) => {
8127
9713
  if (!hasKnowledge(root)) {
8128
- 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");
8129
9715
  }
8130
9716
  const nextStepRecommendation = resolveNextStep(root);
8131
9717
  const deliveryState = { ...buildDeliveryState(root), phase: nextStepRecommendation.phase };
@@ -8139,7 +9725,7 @@ var RESOURCES = [
8139
9725
  mimeType: "application/json",
8140
9726
  read: (root) => {
8141
9727
  if (!hasKnowledge(root)) {
8142
- 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");
8143
9729
  }
8144
9730
  return [{ uri: "kaddo://project-route", text: JSON.stringify(buildProjectRoute(root), null, 2), mimeType: "application/json" }];
8145
9731
  }
@@ -8160,7 +9746,7 @@ var RESOURCES = [
8160
9746
  } catch {
8161
9747
  }
8162
9748
  }
8163
- 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");
8164
9750
  }
8165
9751
  }
8166
9752
  ];
@@ -8177,11 +9763,11 @@ function recommendedInputs(name) {
8177
9763
  return [".kaddo/context-pack.md", ...EXTRA_INPUTS[name] ?? []];
8178
9764
  }
8179
9765
  function listPrompts(root) {
8180
- return listAgents(root).map((a) => ({
8181
- name: a.name,
8182
- description: a.description || `Kaddo ${a.name}`,
9766
+ return listAgents(root).map((a2) => ({
9767
+ name: a2.name,
9768
+ description: a2.description || `Kaddo ${a2.name}`,
8183
9769
  content: "",
8184
- recommended_inputs: recommendedInputs(a.name)
9770
+ recommended_inputs: recommendedInputs(a2.name)
8185
9771
  }));
8186
9772
  }
8187
9773
  function getPrompt(root, name) {
@@ -8206,7 +9792,7 @@ function projectStatus(root) {
8206
9792
  if (!explain) {
8207
9793
  return fail("Project status needs `.kaddo/explain.json`. Run `kaddo explain` first.");
8208
9794
  }
8209
- const maturity = (explain.layers ?? []).map((l) => `${l.layer}: ${l.status}`);
9795
+ const maturity = (explain.layers ?? []).map((l2) => `${l2.layer}: ${l2.status}`);
8210
9796
  return ok({
8211
9797
  project: explain.project?.name ?? "unknown",
8212
9798
  state: explain.project?.state ?? "unknown",
@@ -8231,19 +9817,19 @@ function projectStatus(root) {
8231
9817
  }
8232
9818
  function listWorkItemsTool(root, filter = {}) {
8233
9819
  let items = listWorkItems(root);
8234
- if (filter.status) items = items.filter((w) => w.status === filter.status);
8235
- if (filter.type) items = items.filter((w) => w.type === filter.type);
8236
- 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);
8237
9823
  return ok(items);
8238
9824
  }
8239
9825
  function getWorkItem(root, id) {
8240
- const item = listWorkItems(root).find((w) => w.id === id);
9826
+ const item = listWorkItems(root).find((w3) => w3.id === id);
8241
9827
  if (!item) return fail(`Work Item "${id}" not found.`);
8242
9828
  const content = readText(root, item.path);
8243
9829
  return ok({ ...item, content: content ?? "" });
8244
9830
  }
8245
9831
  function markWorkItemReady(root, id, confirm) {
8246
- const item = listWorkItems(root).find((w) => w.id === id);
9832
+ const item = listWorkItems(root).find((w3) => w3.id === id);
8247
9833
  if (!item) return fail(`Work Item "${id}" not found.`);
8248
9834
  if (item.status === "ready") {
8249
9835
  return ok({ status: "already_ready", id: item.id, message: `Work Item ${item.id} is already ready.` });
@@ -8326,9 +9912,9 @@ function listGraphHints(root, filter = {}) {
8326
9912
  const report = readJson(root, ".kaddo/graph-hints.json");
8327
9913
  if (!report) return fail("Graph hints not found. Run `kaddo graph export` first.");
8328
9914
  let hints = Array.isArray(report.hints) ? report.hints : [];
8329
- if (filter.artifact_type) hints = hints.filter((h) => h.artifact_type === filter.artifact_type);
8330
- if (filter.severity) hints = hints.filter((h) => h.severity === filter.severity);
8331
- 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");
8332
9918
  return ok({
8333
9919
  scope: report.scope ?? "active",
8334
9920
  scope_reason: report.scope_reason ?? "",
@@ -8389,23 +9975,23 @@ var OPERATING_RULES = [
8389
9975
  "After significant changes run `kaddo scan`, `kaddo owners suggest` and `kaddo guard`, and update the affected knowledge (ADR / capabilities / current-state).",
8390
9976
  "Kaddo itself never calls an LLM and never runs git \u2014 every git action is the human\u2019s."
8391
9977
  ];
8392
- function toContextWorkItem(a) {
9978
+ function toContextWorkItem(a2) {
8393
9979
  return {
8394
- id: a.id,
8395
- type: a.type,
8396
- title: a.title,
8397
- status: a.status,
8398
- lifecycle: lifecycleStateOf({ status: a.status, filePath: a.filePath }),
8399
- knowledgeLevel: a.knowledgeLevel,
8400
- domains: a.domains,
8401
- 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)
8402
9988
  };
8403
9989
  }
8404
- function toContextArtifact(a) {
8405
- 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 };
8406
9992
  }
8407
- function isDeliveryWorkItem(a) {
8408
- 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);
8409
9995
  }
8410
9996
  function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8411
9997
  const missing = [];
@@ -8428,7 +10014,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8428
10014
  }
8429
10015
  const allArtifacts = discoverKnowledge(dir);
8430
10016
  const workItems = allArtifacts.filter(
8431
- (a) => isDeliveryWorkItem(a) && isActiveState(lifecycleStateOf({ status: a.status, filePath: a.filePath }))
10017
+ (a2) => isDeliveryWorkItem(a2) && isActiveState(lifecycleStateOf({ status: a2.status, filePath: a2.filePath }))
8432
10018
  );
8433
10019
  if (workItems.length === 0) {
8434
10020
  missing.push("No work items found.");
@@ -8436,15 +10022,15 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8436
10022
  const state = config.project.state;
8437
10023
  const roadmapPath = join(dir, ARCH_DIR3, "delivery", "roadmap.md");
8438
10024
  const materialized = allArtifacts.filter(
8439
- (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)
8440
10026
  ).length;
8441
10027
  const roadmap = roadmapStats(exists(roadmapPath) ? readFile(roadmapPath) : null, materialized);
8442
10028
  const deliveryMix = {};
8443
- for (const a of allArtifacts) {
8444
- const p = a.filePath.replace(/\\/g, "/");
8445
- if (!a.type || !p.includes("/delivery/work-items/")) continue;
8446
- if (!isActiveState(lifecycleStateOf({ status: a.status, filePath: a.filePath }))) continue;
8447
- 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;
8448
10034
  }
8449
10035
  const mappedModules = loadMappedModules(dir);
8450
10036
  const layers = knowledgeLayers(dir);
@@ -8455,7 +10041,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8455
10041
  const qCodebase = qa("knowledge/tech/codebase.md");
8456
10042
  const qCurrentState = qa("knowledge/tech/current-state.md");
8457
10043
  const qRoadmap = qa("knowledge/delivery/roadmap.md");
8458
- const layerStatusOf = (name) => layers.find((l) => l.layer === name)?.status ?? "Missing";
10044
+ const layerStatusOf = (name) => layers.find((l2) => l2.layer === name)?.status ?? "Missing";
8459
10045
  const knowledgeQuality = {
8460
10046
  business: { status: layerStatusOf("Business"), artifacts: { "knowledge/business/business.md": qBusiness } },
8461
10047
  product: { status: layerStatusOf("Product"), artifacts: { "knowledge/product/product.md": qProduct, "knowledge/product/capabilities.md": qCapabilities } },
@@ -8466,20 +10052,20 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8466
10052
  if (qProduct === "placeholder" || qCapabilities === "placeholder") missing.push("Product capabilities exist but still look like a bootstrap placeholder.");
8467
10053
  if (qCurrentState === "placeholder") missing.push("Current state exists but still looks like a bootstrap placeholder.");
8468
10054
  if (qCodebase === "placeholder") missing.push("Codebase map exists but still looks like a bootstrap placeholder.");
8469
- const allWorkItems = allArtifacts.filter((a) => a.isWorkItem);
8470
- 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;
8471
10057
  const phase = assessPhase({
8472
10058
  layers,
8473
10059
  roadmap,
8474
10060
  workItems: {
8475
10061
  total: allWorkItems.length,
8476
10062
  byState: lifecycleCounts(
8477
- allWorkItems.map((a) => lifecycleStateOf({ status: a.status, filePath: a.filePath }))
10063
+ allWorkItems.map((a2) => lifecycleStateOf({ status: a2.status, filePath: a2.filePath }))
8478
10064
  ),
8479
- items: allWorkItems.map((a) => ({
8480
- id: a.id || a.title,
8481
- title: a.title,
8482
- 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 })
8483
10069
  }))
8484
10070
  },
8485
10071
  ownership: {
@@ -8544,7 +10130,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8544
10130
  roadmapSummary,
8545
10131
  inventoryAvailable,
8546
10132
  workItems: workItems.map(toContextWorkItem),
8547
- artifacts: allArtifacts.filter((a) => a.codeGlobs.length > 0).map(toContextArtifact)
10133
+ artifacts: allArtifacts.filter((a2) => a2.codeGlobs.length > 0).map(toContextArtifact)
8548
10134
  },
8549
10135
  layers,
8550
10136
  knowledgeQuality,
@@ -8557,7 +10143,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8557
10143
  roadmapQuality: buildRoadmapQuality(dir),
8558
10144
  installedAssets: (() => {
8559
10145
  const s = installedAssetsSummary(dir);
8560
- 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 });
8561
10147
  return { version: s.version, agents: compact(s.agents), skills: compact(s.skills) };
8562
10148
  })(),
8563
10149
  deliveryMix,
@@ -8569,6 +10155,31 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
8569
10155
  projectRoute: buildProjectRoute(dir),
8570
10156
  metadataHealth: analyzeMetadataHealth(dir),
8571
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
+ })(),
8572
10183
  missing,
8573
10184
  // VS-052/VS-073.2: the handoff is driven by the unified next step, so the pack never contradicts
8574
10185
  // the Current Phase block above it.
@@ -8593,7 +10204,7 @@ function renderContextPack(pack) {
8593
10204
  "> Generated by `kaddo context`. Deterministic CLI output \u2014 not an interpretation of the system.\n"
8594
10205
  );
8595
10206
  parts.push("## Operating Rules (read first)\n");
8596
- parts.push(handoff.operatingRules.map((r) => `- ${r}`).join("\n") + "\n");
10207
+ parts.push(handoff.operatingRules.map((r2) => `- ${r2}`).join("\n") + "\n");
8597
10208
  parts.push("## Project Metadata\n");
8598
10209
  parts.push(
8599
10210
  [
@@ -8609,7 +10220,7 @@ function renderContextPack(pack) {
8609
10220
  `);
8610
10221
  if (pack.phase.reasons.length > 0) {
8611
10222
  parts.push("Reason:\n");
8612
- parts.push(pack.phase.reasons.map((r) => `- ${r}`).join("\n") + "\n");
10223
+ parts.push(pack.phase.reasons.map((r2) => `- ${r2}`).join("\n") + "\n");
8613
10224
  }
8614
10225
  if (pack.phase.recommendedAgents.length > 0) {
8615
10226
  parts.push(`Recommended next: ${pack.phase.recommendedAgents.join(", ")}
@@ -8650,7 +10261,7 @@ function renderContextPack(pack) {
8650
10261
  parts.push(
8651
10262
  "Project knowledge is organized in four layers: **Business \u2192 Product \u2192 Tech \u2192 Delivery**.\n"
8652
10263
  );
8653
- 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 ");
8654
10265
  parts.push(`Knowledge maturity \u2014 ${maturity}
8655
10266
  `);
8656
10267
  parts.push(renderLayersMarkdown(pack.layers) + "\n");
@@ -8663,19 +10274,19 @@ function renderContextPack(pack) {
8663
10274
  ];
8664
10275
  if (scan.sourceDirectories.length > 0) {
8665
10276
  lines.push("- Source directories:");
8666
- scan.sourceDirectories.forEach((d) => lines.push(` - ${d}`));
10277
+ scan.sourceDirectories.forEach((d3) => lines.push(` - ${d3}`));
8667
10278
  }
8668
10279
  if (scan.migrationDirectories.length > 0) {
8669
10280
  lines.push("- Migration directories:");
8670
- scan.migrationDirectories.forEach((d) => lines.push(` - ${d}`));
10281
+ scan.migrationDirectories.forEach((d3) => lines.push(` - ${d3}`));
8671
10282
  }
8672
10283
  if (scan.contractFiles.length > 0) {
8673
10284
  lines.push("- Contracts:");
8674
- scan.contractFiles.forEach((f) => lines.push(` - ${f}`));
10285
+ scan.contractFiles.forEach((f3) => lines.push(` - ${f3}`));
8675
10286
  }
8676
10287
  if (scan.infrastructureFiles.length > 0) {
8677
10288
  lines.push("- Infrastructure:");
8678
- scan.infrastructureFiles.forEach((f) => lines.push(` - ${f}`));
10289
+ scan.infrastructureFiles.forEach((f3) => lines.push(` - ${f3}`));
8679
10290
  }
8680
10291
  parts.push(lines.join("\n") + "\n");
8681
10292
  } else {
@@ -8753,7 +10364,7 @@ function renderContextPack(pack) {
8753
10364
  } else {
8754
10365
  parts.push("No active work items found.\n");
8755
10366
  }
8756
- 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]);
8757
10368
  if (mixEntries.length > 0) {
8758
10369
  parts.push("## Delivery Mix\n");
8759
10370
  parts.push("Active Work Items by type:\n");
@@ -8766,7 +10377,7 @@ function renderContextPack(pack) {
8766
10377
  parts.push("## Artifacts and Ownership\n");
8767
10378
  if (knowledge.artifacts.length > 0) {
8768
10379
  const lines = knowledge.artifacts.map(
8769
- (a) => `- ${a.id || a.title} [${a.type}] owns: ${a.codeGlobs.join(", ")}`
10380
+ (a2) => `- ${a2.id || a2.title} [${a2.type}] owns: ${a2.codeGlobs.join(", ")}`
8770
10381
  );
8771
10382
  parts.push(lines.join("\n") + "\n");
8772
10383
  } else {
@@ -8777,15 +10388,35 @@ function renderContextPack(pack) {
8777
10388
  parts.push("This project has mapped modules registered in `.kaddo/modules.yml`.\n");
8778
10389
  const header = "| Module | Type | Repo path | Owner | Capabilities | Artifacts |";
8779
10390
  const sep = "|---|---|---|---|---|---|";
8780
- const rows = pack.mappedModules.map((m) => {
8781
- const caps = m.capabilities.length > 0 ? m.capabilities.join(", ") : "\u2014";
8782
- const arts = presentArtifacts(m.artifacts);
8783
- 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"} |`;
8784
10395
  });
8785
10396
  parts.push([header, sep, ...rows].join("\n") + "\n");
8786
10397
  parts.push(
8787
10398
  "Note: Kaddo does not scan secondary repositories during `context`. Mapped modules come from `.kaddo/modules.yml` and module artifacts only.\n"
8788
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
+ }
8789
10420
  }
8790
10421
  if (pack.external.length > 0) {
8791
10422
  parts.push("## External Knowledge\n");
@@ -8827,7 +10458,7 @@ function renderContextPack(pack) {
8827
10458
  ].join("\n") + "\n"
8828
10459
  );
8829
10460
  const shown = pack.graphHints.messages.slice(0, 3);
8830
- parts.push(shown.map((m) => `- ${m}`).join("\n") + "\n");
10461
+ parts.push(shown.map((m2) => `- ${m2}`).join("\n") + "\n");
8831
10462
  if (pack.graphHints.totalHints > shown.length) {
8832
10463
  parts.push(`(+${pack.graphHints.totalHints - shown.length} more in \`.kaddo/graph-hints.md\`)
8833
10464
  `);
@@ -8848,18 +10479,18 @@ function renderContextPack(pack) {
8848
10479
  ...!pack.knowledgeQuality.product || pack.knowledgeQuality.product.status === "Missing" ? ["- Missing product knowledge."] : []
8849
10480
  ];
8850
10481
  if (missing.length > 0) {
8851
- baselineMissing.push(...missing.filter((m) => !baselineMissing.some((b) => b.includes(m))));
10482
+ baselineMissing.push(...missing.filter((m2) => !baselineMissing.some((b2) => b2.includes(m2))));
8852
10483
  }
8853
10484
  parts.push(baselineMissing.join("\n") + "\n");
8854
10485
  } else if (missing.length > 0) {
8855
- parts.push(missing.map((m) => `- ${m}`).join("\n") + "\n");
10486
+ parts.push(missing.map((m2) => `- ${m2}`).join("\n") + "\n");
8856
10487
  } else {
8857
10488
  parts.push("_None \u2014 all expected context is present._\n");
8858
10489
  }
8859
10490
  if (pack.metadataHealth.findings.length > 0) {
8860
10491
  parts.push("\n### Metadata Health\n");
8861
- for (const f of pack.metadataHealth.findings) {
8862
- parts.push(`- \`${f.file}\`: ${f.detail}
10492
+ for (const f3 of pack.metadataHealth.findings) {
10493
+ parts.push(`- \`${f3.file}\`: ${f3.detail}
8863
10494
  `);
8864
10495
  }
8865
10496
  }
@@ -8883,7 +10514,7 @@ function renderContextPack(pack) {
8883
10514
  parts.push(`Agent prompt: \`${rec.agentPath}\`
8884
10515
  `);
8885
10516
  }
8886
- 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");
8887
10518
  if (handoff.nextSteps.length > 0) {
8888
10519
  parts.push("Next step:\n");
8889
10520
  parts.push(handoff.nextSteps.map((s) => `- ${s}`).join("\n") + "\n");
@@ -9027,7 +10658,7 @@ function renderUnderstand(plan) {
9027
10658
  }
9028
10659
  }
9029
10660
  if (flowSteps.length > 0) {
9030
- 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");
9031
10662
  }
9032
10663
  }
9033
10664
  if (rec) {
@@ -9046,10 +10677,10 @@ function renderUnderstand(plan) {
9046
10677
  if (plan.activeWorkItems && plan.activeWorkItems.length > 0) {
9047
10678
  parts.push("## Active Work Items\n");
9048
10679
  parts.push(
9049
- plan.activeWorkItems.map((w) => {
9050
- const src = w.source && w.source.type !== "unknown" ? `
9051
- - Source: ${w.source.type}${w.source.id ? ` \xB7 ${w.source.id}` : ""}` : "";
9052
- 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}`;
9053
10684
  }).join("\n") + "\n"
9054
10685
  );
9055
10686
  }
@@ -9101,6 +10732,8 @@ function renderUnderstand(plan) {
9101
10732
  outputs.push("- A new Work Item under `knowledge/delivery/work-items/`.");
9102
10733
  if (rec.id === "implement" || rec.id === "implement-work-item")
9103
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.");
9104
10737
  if (rec.id === "guard")
9105
10738
  outputs.push("- Updated knowledge artifacts reflecting recent code changes.");
9106
10739
  if (rec.id === "install-adapter" || rec.id === "prepare-implementation")
@@ -9170,10 +10803,23 @@ function renderUnderstand(plan) {
9170
10803
  } else {
9171
10804
  parts.push("Re-run `kaddo understand` any time to see this plan again.\n");
9172
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
+ }
9173
10819
  if (plan.metadataHealth && plan.metadataHealth.findings.length > 0) {
9174
10820
  parts.push("## Metadata Health\n");
9175
- for (const f of plan.metadataHealth.findings) {
9176
- parts.push(`- \`${f.file}\`: ${f.detail}
10821
+ for (const f3 of plan.metadataHealth.findings) {
10822
+ parts.push(`- \`${f3.file}\`: ${f3.detail}
9177
10823
  `);
9178
10824
  }
9179
10825
  }
@@ -9349,8 +10995,8 @@ function toolText(result) {
9349
10995
  if (!result.ok) {
9350
10996
  return { content: [{ type: "text", text: result.message }], isError: true };
9351
10997
  }
9352
- const text2 = typeof result.data === "string" ? result.data : JSON.stringify(result.data, null, 2);
9353
- 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 }] };
9354
11000
  }
9355
11001
  function guarded(root, fn) {
9356
11002
  try {
@@ -9374,11 +11020,11 @@ function generated(root, label, fn) {
9374
11020
  var DERIVED_NOTE = "Writes only derived files under .kaddo/. Does not modify knowledge, source code, external context or git.";
9375
11021
  function createServer(root) {
9376
11022
  const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION });
9377
- for (const r of RESOURCES) {
11023
+ for (const r2 of RESOURCES) {
9378
11024
  server.registerResource(
9379
- r.name,
9380
- r.uri,
9381
- { 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 },
9382
11028
  async (uri) => {
9383
11029
  try {
9384
11030
  assertKaddoProject(root);
@@ -9386,7 +11032,7 @@ function createServer(root) {
9386
11032
  const message = err instanceof KaddoMcpError ? err.message : String(err);
9387
11033
  return { contents: [{ uri: uri.href, text: message, mimeType: "text/plain" }] };
9388
11034
  }
9389
- const parts = r.read(root);
11035
+ const parts = r2.read(root);
9390
11036
  return { contents: parts.map((p) => ({ uri: p.uri, text: p.text, mimeType: p.mimeType })) };
9391
11037
  }
9392
11038
  );
@@ -9402,16 +11048,16 @@ function createServer(root) {
9402
11048
  title: "List Work Items",
9403
11049
  description: "List Work Items with optional status/type/knowledge_level filters.",
9404
11050
  inputSchema: {
9405
- status: z2.string().optional(),
9406
- type: z2.string().optional(),
9407
- knowledge_level: z2.string().optional()
11051
+ status: z3.string().optional(),
11052
+ type: z3.string().optional(),
11053
+ knowledge_level: z3.string().optional()
9408
11054
  }
9409
11055
  },
9410
11056
  async (args) => toolText(guarded(root, () => listWorkItemsTool(root, args)))
9411
11057
  );
9412
11058
  server.registerTool(
9413
11059
  "kaddo_get_work_item",
9414
- { 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() } },
9415
11061
  async (args) => toolText(guarded(root, () => getWorkItem(root, args.id)))
9416
11062
  );
9417
11063
  server.registerTool(
@@ -9419,7 +11065,7 @@ function createServer(root) {
9419
11065
  {
9420
11066
  title: "Mark Work Item ready",
9421
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.",
9422
- inputSchema: { id: z2.string(), confirm: z2.boolean().optional() }
11068
+ inputSchema: { id: z3.string(), confirm: z3.boolean().optional() }
9423
11069
  },
9424
11070
  async (args) => toolText(guarded(root, () => markWorkItemReady(root, args.id, args.confirm)))
9425
11071
  );
@@ -9430,7 +11076,7 @@ function createServer(root) {
9430
11076
  );
9431
11077
  server.registerTool(
9432
11078
  "kaddo_get_capsule",
9433
- { 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() } },
9434
11080
  async (args) => toolText(guarded(root, () => getCapsuleTool(root, args.id)))
9435
11081
  );
9436
11082
  server.registerTool(
@@ -9440,7 +11086,7 @@ function createServer(root) {
9440
11086
  );
9441
11087
  server.registerTool(
9442
11088
  "kaddo_get_agent_prompt",
9443
- { 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() } },
9444
11090
  async (args) => toolText(guarded(root, () => getAgentPromptTool(root, args.name)))
9445
11091
  );
9446
11092
  server.registerTool(
@@ -9449,9 +11095,9 @@ function createServer(root) {
9449
11095
  title: "List graph hints",
9450
11096
  description: "List knowledge-graph relationship hints with optional filters.",
9451
11097
  inputSchema: {
9452
- artifact_type: z2.string().optional(),
9453
- severity: z2.string().optional(),
9454
- active_only: z2.boolean().optional()
11098
+ artifact_type: z3.string().optional(),
11099
+ severity: z3.string().optional(),
11100
+ active_only: z3.boolean().optional()
9455
11101
  }
9456
11102
  },
9457
11103
  async (args) => toolText(guarded(root, () => listGraphHints(root, args)))
@@ -9463,7 +11109,7 @@ function createServer(root) {
9463
11109
  );
9464
11110
  server.registerTool(
9465
11111
  "kaddo_get_skill",
9466
- { 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() } },
9467
11113
  async (args) => toolText(guarded(root, () => getSkillTool(root, args.id)))
9468
11114
  );
9469
11115
  let installedSkills = [];
@@ -9508,7 +11154,7 @@ function createServer(root) {
9508
11154
  {
9509
11155
  title: "Generate knowledge graph",
9510
11156
  description: `Regenerate .kaddo/graph.json/.mmd + graph-hints.md/.json. scope: active (default) or all. ${DERIVED_NOTE}`,
9511
- inputSchema: { scope: z2.enum(["active", "all"]).optional() }
11157
+ inputSchema: { scope: z3.enum(["active", "all"]).optional() }
9512
11158
  },
9513
11159
  async (args) => generated(root, "generate knowledge graph", () => generateGraph(root, args.scope ?? "active"))
9514
11160
  );
@@ -9518,9 +11164,9 @@ function createServer(root) {
9518
11164
  title: "Generate impact report",
9519
11165
  description: `Write the Knowledge Impact Report under .kaddo/reports/. format: markdown (default) or json; scope: active or all (default all). ${DERIVED_NOTE}`,
9520
11166
  inputSchema: {
9521
- format: z2.enum(["markdown", "json"]).optional(),
9522
- scope: z2.enum(["active", "all"]).optional(),
9523
- output: z2.string().optional()
11167
+ format: z3.enum(["markdown", "json"]).optional(),
11168
+ scope: z3.enum(["active", "all"]).optional(),
11169
+ output: z3.string().optional()
9524
11170
  }
9525
11171
  },
9526
11172
  async (args) => generated(
@@ -9535,9 +11181,9 @@ function createServer(root) {
9535
11181
  title: "Generate savings report",
9536
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}`,
9537
11183
  inputSchema: {
9538
- format: z2.enum(["markdown", "json"]).optional(),
9539
- scope: z2.enum(["active", "all"]).optional(),
9540
- output: z2.string().optional()
11184
+ format: z3.enum(["markdown", "json"]).optional(),
11185
+ scope: z3.enum(["active", "all"]).optional(),
11186
+ output: z3.string().optional()
9541
11187
  }
9542
11188
  },
9543
11189
  async (args) => generated(
@@ -9552,8 +11198,8 @@ function createServer(root) {
9552
11198
  title: "Generate drift report",
9553
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}`,
9554
11200
  inputSchema: {
9555
- format: z2.enum(["markdown", "json"]).optional(),
9556
- output: z2.string().optional()
11201
+ format: z3.enum(["markdown", "json"]).optional(),
11202
+ output: z3.string().optional()
9557
11203
  }
9558
11204
  },
9559
11205
  async (args) => generated(
@@ -9568,8 +11214,8 @@ function createServer(root) {
9568
11214
  title: "Generate open-questions report",
9569
11215
  description: `Write the Open Questions readiness report under .kaddo/reports/ (classifies blocking/important/deferred). Does NOT resolve questions. ${DERIVED_NOTE}`,
9570
11216
  inputSchema: {
9571
- format: z2.enum(["markdown", "json"]).optional(),
9572
- output: z2.string().optional()
11217
+ format: z3.enum(["markdown", "json"]).optional(),
11218
+ output: z3.string().optional()
9573
11219
  }
9574
11220
  },
9575
11221
  async (args) => generated(