@kaddo/mcp 3.64.0 → 3.66.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 +279 -65
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -521,7 +521,14 @@ function parseArtifact(filePath, raw) {
521
521
  sourceId: String(data.source_id ?? ""),
522
522
  rawFrontmatter: data,
523
523
  decisions: Array.isArray(data.decisions) ? data.decisions.map(String).filter(Boolean) : [],
524
- capsules: Array.isArray(data.capsules) ? data.capsules.map(String).filter(Boolean) : []
524
+ capsules: Array.isArray(data.capsules) ? data.capsules.map(String).filter(Boolean) : [],
525
+ implementationStatus: String(data.implementation_status ?? ""),
526
+ validationStatus: String(data.validation_status ?? ""),
527
+ releaseStatus: String(data.release_status ?? ""),
528
+ affectedModules: Array.isArray(data.affected_modules) ? data.affected_modules.map(String).filter(Boolean) : [],
529
+ refinedBy: String(data.refined_by ?? ""),
530
+ implementedBy: String(data.implemented_by ?? ""),
531
+ closedBy: String(data.closed_by ?? "")
525
532
  };
526
533
  } catch {
527
534
  return null;
@@ -698,7 +705,7 @@ function assessPhase(input) {
698
705
  const techReady = !NOT_READY_LAYER.includes(techStatus);
699
706
  if (techReady) {
700
707
  return {
701
- phase: "Active Delivery",
708
+ phase: "Ready for Core Orchestration",
702
709
  reasons: ["Module repo \u2014 Tech layer ready", "Business/Product managed by core"],
703
710
  recommendedAgents: [],
704
711
  nextStep: "Module knowledge is ready for core orchestration.",
@@ -2413,6 +2420,7 @@ function buildGraph(dir, config, opts = {}, now = /* @__PURE__ */ new Date()) {
2413
2420
  const selectedWIs = workItems.filter((a2) => a2.lifecycle && includedSet.has(a2.lifecycle));
2414
2421
  for (const wi of selectedWIs) {
2415
2422
  const id = wi.id || wi.title;
2423
+ if (!id || !id.trim()) continue;
2416
2424
  const wiNodeId = `wi:${id}`;
2417
2425
  addNode({
2418
2426
  id: wiNodeId,
@@ -2423,16 +2431,19 @@ function buildGraph(dir, config, opts = {}, now = /* @__PURE__ */ new Date()) {
2423
2431
  knowledge_level: wi.knowledgeLevel || void 0
2424
2432
  });
2425
2433
  for (const glob of wi.codeGlobs) {
2434
+ if (!glob || !glob.trim()) continue;
2426
2435
  const codeId = `code:${glob}`;
2427
2436
  addNode({ id: codeId, type: "code-glob", label: glob });
2428
2437
  addEdge(wiNodeId, codeId, "owns");
2429
2438
  }
2430
2439
  for (const cap of wi.capabilities) {
2440
+ if (!cap || !cap.trim()) continue;
2431
2441
  const capId = `capability:${slug(cap) || cap}`;
2432
2442
  addNode({ id: capId, type: "capability", label: cap });
2433
2443
  addEdge(wiNodeId, capId, "implements");
2434
2444
  }
2435
2445
  for (const dec of wi.decisions) {
2446
+ if (!dec || !dec.trim()) continue;
2436
2447
  const adrId = `adr:${dec}`;
2437
2448
  addNode({ id: adrId, type: "decision", label: dec });
2438
2449
  addEdge(wiNodeId, adrId, "depends_on");
@@ -2449,16 +2460,19 @@ function buildGraph(dir, config, opts = {}, now = /* @__PURE__ */ new Date()) {
2449
2460
  }
2450
2461
  }
2451
2462
  for (const adr of all.filter(isAdr)) {
2452
- const adrId = `adr:${adr.id || adr.title}`;
2463
+ const adrLabel = adr.id || adr.title;
2464
+ if (!adrLabel || !adrLabel.trim()) continue;
2465
+ const adrId = `adr:${adrLabel}`;
2453
2466
  const referenced = nodes.has(adrId);
2454
2467
  if (scope === "all" || referenced) {
2455
2468
  nodes.set(adrId, {
2456
2469
  id: adrId,
2457
2470
  type: "decision",
2458
- label: `${adr.id} ${adr.title}`.trim() || adr.id || adr.title,
2471
+ label: `${adr.id} ${adr.title}`.trim() || adrLabel,
2459
2472
  path: adr.relPath
2460
2473
  });
2461
2474
  for (const glob of adr.codeGlobs) {
2475
+ if (!glob || !glob.trim()) continue;
2462
2476
  const codeId = `code:${glob}`;
2463
2477
  addNode({ id: codeId, type: "code-glob", label: glob });
2464
2478
  addEdge(adrId, codeId, "governs");
@@ -2514,13 +2528,20 @@ function renderGraphMermaid(graph) {
2514
2528
  safeIds.set(id, candidate);
2515
2529
  return candidate;
2516
2530
  };
2517
- const escapeLabel = (s) => s.replace(/"/g, "'");
2531
+ const escapeLabel = (s) => s.replace(/"/g, "'").replace(/\[/g, "(").replace(/\]/g, ")").replace(/\n/g, " ");
2532
+ const validNodes = graph.nodes.filter(
2533
+ (n) => n.id && n.id.trim() !== "" && n.label && n.label.trim() !== ""
2534
+ );
2535
+ const validNodeIds = new Set(validNodes.map((n) => n.id));
2518
2536
  const lines = ["flowchart LR"];
2519
- for (const node of graph.nodes) {
2537
+ for (const node of validNodes) {
2520
2538
  lines.push(` ${safe(node.id)}["${escapeLabel(node.label)}"]`);
2521
2539
  }
2522
- if (graph.edges.length > 0) lines.push("");
2523
- for (const edge of graph.edges) {
2540
+ const validEdges = graph.edges.filter(
2541
+ (e) => validNodeIds.has(e.from) && validNodeIds.has(e.to)
2542
+ );
2543
+ if (validEdges.length > 0) lines.push("");
2544
+ for (const edge of validEdges) {
2524
2545
  lines.push(` ${safe(edge.from)} -->|${edge.type}| ${safe(edge.to)}`);
2525
2546
  }
2526
2547
  return lines.join("\n") + "\n";
@@ -4290,6 +4311,47 @@ function buildReadinessReport(dir, now = /* @__PURE__ */ new Date()) {
4290
4311
  if (!config) return stub("not-initialized", rec.label, rec.command);
4291
4312
  if (config.project.state === "new") return stub("not-applicable", "This project uses the standard new-project Kaddo flow.");
4292
4313
  if (config.project.state === "legacy") return stub("legacy-project", "Use the legacy project flow.");
4314
+ if (isModule(config)) {
4315
+ const scan2 = exists(join(dir, ".kaddo", "scan.json")) ? "available" : "missing";
4316
+ const understand2 = exists(join(dir, ".kaddo", "understand.md")) ? "available" : "missing";
4317
+ const mcNew = "knowledge/tech/module/module-context.md";
4318
+ const mcLegacy = "knowledge/module/module-context.md";
4319
+ const mcPath = exists(join(dir, mcNew)) ? mcNew : mcLegacy;
4320
+ const qMC = analyzeKnowledgeArtifact(dir, mcPath);
4321
+ const qCS = analyzeKnowledgeArtifact(dir, "knowledge/tech/current-state.md");
4322
+ const qCB = analyzeKnowledgeArtifact(dir, "knowledge/tech/codebase.md");
4323
+ const moduleBaseline = qMC !== "missing" && qCS !== "missing" && qCB !== "missing" ? "complete" : "incomplete";
4324
+ const moduleReady = qMC === "useful" && qCS === "useful" && qCB === "useful";
4325
+ const overall2 = moduleReady ? "ready-for-core-orchestration" : moduleBaseline === "incomplete" ? "bootstrap-incomplete" : "knowledge-incomplete";
4326
+ return {
4327
+ project_name: config.project.name,
4328
+ project_type: config.project.state,
4329
+ project_role: "module",
4330
+ overall: overall2,
4331
+ signals: {
4332
+ scan: scan2,
4333
+ understand: understand2,
4334
+ bootstrap_baseline: moduleBaseline,
4335
+ agents: "managed-by-core",
4336
+ skills: "managed-by-core",
4337
+ current_state: qCS,
4338
+ codebase: qCB,
4339
+ module_context: qMC,
4340
+ capabilities: "managed-by-core",
4341
+ product: "not-applicable",
4342
+ business: "not-applicable",
4343
+ roadmap: "managed-by-core",
4344
+ work_items: "managed-by-core",
4345
+ adapters: [],
4346
+ blocking_open_questions: 0,
4347
+ assumed_questions: 0,
4348
+ resolved_questions: 0,
4349
+ deferred_questions: 0
4350
+ },
4351
+ recommended_next_step: { label: rec.label, ...rec.command ? { command: rec.command } : {} },
4352
+ nextStepRecommendation: rec
4353
+ };
4354
+ }
4293
4355
  const scan = exists(join(dir, ".kaddo", "scan.json")) ? "available" : "missing";
4294
4356
  const understand = exists(join(dir, ".kaddo", "understand.md")) ? "available" : "missing";
4295
4357
  const presence = Object.fromEntries(KNOWLEDGE_FILES.map((f3) => [f3.key, analyzeKnowledgeArtifact(dir, f3.path)]));
@@ -7989,6 +8051,33 @@ function analyzeMetadataHealth(dir) {
7989
8051
  if (fileDrifted) drifted++;
7990
8052
  else healthy++;
7991
8053
  }
8054
+ const wiDir = join(dir, "knowledge/delivery/work-items");
8055
+ if (exists(wiDir)) {
8056
+ const walkWIs = (d3) => {
8057
+ for (const entry of readDir(d3)) {
8058
+ const p = join(d3, entry);
8059
+ if (isFile(p) && entry.endsWith(".md")) {
8060
+ try {
8061
+ const raw = readFile(p);
8062
+ const fm = matter7(raw).data;
8063
+ if (fm.status === "done") {
8064
+ const rel = p.replace(dir + "/", "").replace(dir + "\\", "").replace(/\\/g, "/");
8065
+ findings.push({
8066
+ file: rel,
8067
+ field: "status",
8068
+ issue: "inconsistent",
8069
+ detail: "Legacy status `done` detected. Canonical status is `completed`."
8070
+ });
8071
+ }
8072
+ } catch {
8073
+ }
8074
+ } else if (!isFile(p) && !entry.startsWith(".")) {
8075
+ walkWIs(p);
8076
+ }
8077
+ }
8078
+ };
8079
+ walkWIs(wiDir);
8080
+ }
7992
8081
  return { findings, healthy, drifted };
7993
8082
  }
7994
8083
 
@@ -8169,51 +8258,73 @@ function buildProjectExplanation(dir) {
8169
8258
  const roadmapMd = exists(roadmapPath) ? readFile(roadmapPath) : null;
8170
8259
  const roadmap = roadmapStats(roadmapMd, items.length);
8171
8260
  const mappedModules = loadMappedModules(dir);
8261
+ const moduleRepo = config != null && isModule(config);
8172
8262
  const missingKnowledge = [];
8173
- if (!knowledge.hasScan) missingKnowledge.push("Scan baseline (.kaddo/scan.json)");
8174
- if (!knowledge.hasContextPack) missingKnowledge.push("Context pack (.kaddo/context-pack.md)");
8175
- if (!knowledge.hasInventory) missingKnowledge.push("Inventory (knowledge/inventory.md)");
8176
- if (!knowledge.hasCapabilities) missingKnowledge.push("Product knowledge (knowledge/product/)");
8177
- if (!knowledge.hasArchitecture) missingKnowledge.push("Tech knowledge (knowledge/tech/)");
8178
- if (!knowledge.hasRoadmap) missingKnowledge.push("Roadmap (knowledge/delivery/roadmap.md)");
8179
- if (!knowledge.hasAgents) missingKnowledge.push("Agents (knowledge/agents/)");
8180
- if (items.length === 0) missingKnowledge.push("Work items (knowledge/delivery/work-items/)");
8181
- const suggestedNextSteps = [];
8182
- const baselineIncomplete = !knowledge.hasBusiness || !knowledge.hasProduct;
8183
- if (baselineIncomplete) {
8184
- suggestedNextSteps.push("Run `kaddo bootstrap` to create the project knowledge baseline.");
8185
- if (!knowledge.hasAgents) suggestedNextSteps.push("Then run `kaddo add agents`.");
8186
- if (!knowledge.hasSkills) suggestedNextSteps.push("Then run `kaddo add skills`.");
8187
- suggestedNextSteps.push("Then run `kaddo context`.");
8188
- suggestedNextSteps.push("Then run `kaddo understand`.");
8263
+ if (moduleRepo) {
8264
+ if (!knowledge.hasScan) missingKnowledge.push("Scan baseline (.kaddo/scan.json)");
8265
+ if (!knowledge.hasContextPack) missingKnowledge.push("Context pack (.kaddo/context-pack.md)");
8266
+ if (!knowledge.hasArchitecture) missingKnowledge.push("Tech knowledge (knowledge/tech/)");
8189
8267
  } else {
8268
+ if (!knowledge.hasScan) missingKnowledge.push("Scan baseline (.kaddo/scan.json)");
8269
+ if (!knowledge.hasContextPack) missingKnowledge.push("Context pack (.kaddo/context-pack.md)");
8270
+ if (!knowledge.hasInventory) missingKnowledge.push("Inventory (knowledge/inventory.md)");
8271
+ if (!knowledge.hasCapabilities) missingKnowledge.push("Product knowledge (knowledge/product/)");
8272
+ if (!knowledge.hasArchitecture) missingKnowledge.push("Tech knowledge (knowledge/tech/)");
8273
+ if (!knowledge.hasRoadmap) missingKnowledge.push("Roadmap (knowledge/delivery/roadmap.md)");
8274
+ if (!knowledge.hasAgents) missingKnowledge.push("Agents (knowledge/agents/)");
8275
+ if (items.length === 0) missingKnowledge.push("Work items (knowledge/delivery/work-items/)");
8276
+ }
8277
+ const suggestedNextSteps = [];
8278
+ if (moduleRepo) {
8190
8279
  if (!knowledge.hasScan) {
8191
8280
  suggestedNextSteps.push("Run `kaddo scan` to detect the technical stack.");
8192
8281
  } else if (!knowledge.hasContextPack) {
8193
8282
  suggestedNextSteps.push("Run `kaddo context` to prepare an LLM context pack.");
8283
+ } else if (!knowledge.hasArchitecture) {
8284
+ suggestedNextSteps.push("Use module-context-agent to refine knowledge/tech/module/module-context.md.");
8285
+ } else {
8286
+ suggestedNextSteps.push("Return to the core repository.");
8287
+ suggestedNextSteps.push("Create or continue the Work Item from the core.");
8288
+ suggestedNextSteps.push("Add this module to `affected_modules` when the change touches it.");
8289
+ suggestedNextSteps.push("Re-run `kaddo context` and `kaddo understand` from the core.");
8194
8290
  }
8195
- if (!knowledge.hasAgents) {
8196
- suggestedNextSteps.push("Run `kaddo add agents` to install knowledge agents.");
8197
- }
8198
- if (!knowledge.hasCapabilities) {
8199
- suggestedNextSteps.push("Use capability-agent to generate knowledge/product/capabilities.md.");
8200
- }
8201
- if (!knowledge.hasArchitecture) {
8202
- suggestedNextSteps.push("Use architecture-agent to generate knowledge/tech/current-state.md.");
8203
- }
8204
- if (!knowledge.hasRoadmap) {
8205
- suggestedNextSteps.push("Use roadmap-agent to generate knowledge/delivery/roadmap.md.");
8206
- } else if (roadmap.remaining > 0) {
8207
- suggestedNextSteps.push(
8208
- `Materialize ${roadmap.remaining} roadmap candidate(s) with \`kaddo create --from roadmap\`.`
8209
- );
8210
- }
8211
- if (items.length === 0 && !roadmap.present) {
8212
- suggestedNextSteps.push("Create your first Work Item with `kaddo create`.");
8213
- } else if (ownership.workItemsMissingOwnership > 0) {
8214
- suggestedNextSteps.push(
8215
- "Run `kaddo owners suggest` for Work Items without code ownership."
8216
- );
8291
+ } else {
8292
+ const baselineIncomplete = !knowledge.hasBusiness || !knowledge.hasProduct;
8293
+ if (baselineIncomplete) {
8294
+ suggestedNextSteps.push("Run `kaddo bootstrap` to create the project knowledge baseline.");
8295
+ if (!knowledge.hasAgents) suggestedNextSteps.push("Then run `kaddo add agents`.");
8296
+ if (!knowledge.hasSkills) suggestedNextSteps.push("Then run `kaddo add skills`.");
8297
+ suggestedNextSteps.push("Then run `kaddo context`.");
8298
+ suggestedNextSteps.push("Then run `kaddo understand`.");
8299
+ } else {
8300
+ if (!knowledge.hasScan) {
8301
+ suggestedNextSteps.push("Run `kaddo scan` to detect the technical stack.");
8302
+ } else if (!knowledge.hasContextPack) {
8303
+ suggestedNextSteps.push("Run `kaddo context` to prepare an LLM context pack.");
8304
+ }
8305
+ if (!knowledge.hasAgents) {
8306
+ suggestedNextSteps.push("Run `kaddo add agents` to install knowledge agents.");
8307
+ }
8308
+ if (!knowledge.hasCapabilities) {
8309
+ suggestedNextSteps.push("Use capability-agent to generate knowledge/product/capabilities.md.");
8310
+ }
8311
+ if (!knowledge.hasArchitecture) {
8312
+ suggestedNextSteps.push("Use architecture-agent to generate knowledge/tech/current-state.md.");
8313
+ }
8314
+ if (!knowledge.hasRoadmap) {
8315
+ suggestedNextSteps.push("Use roadmap-agent to generate knowledge/delivery/roadmap.md.");
8316
+ } else if (roadmap.remaining > 0) {
8317
+ suggestedNextSteps.push(
8318
+ `Materialize ${roadmap.remaining} roadmap candidate(s) with \`kaddo create --from roadmap\`.`
8319
+ );
8320
+ }
8321
+ if (items.length === 0 && !roadmap.present) {
8322
+ suggestedNextSteps.push("Create your first Work Item with `kaddo create`.");
8323
+ } else if (ownership.workItemsMissingOwnership > 0) {
8324
+ suggestedNextSteps.push(
8325
+ "Run `kaddo owners suggest` for Work Items without code ownership."
8326
+ );
8327
+ }
8217
8328
  }
8218
8329
  }
8219
8330
  const readiness = buildReadinessReport(dir);
@@ -8256,7 +8367,30 @@ function buildProjectExplanation(dir) {
8256
8367
  projectRoute: buildProjectRoute(dir),
8257
8368
  scanSignals: loadScanSignals(dir),
8258
8369
  metadataHealth: analyzeMetadataHealth(dir),
8259
- isModuleRepo: config != null && isModule(config)
8370
+ isModuleRepo: config != null && isModule(config),
8371
+ implementationEvidence: workItemArtifacts.filter((a2) => a2.affectedModules.length > 0).map((a2) => {
8372
+ const fm = a2.rawFrontmatter;
8373
+ const evidence = fm.implementation_evidence;
8374
+ const repos = evidence?.repositories ?? {};
8375
+ const repoEvidence = {};
8376
+ for (const [repoId, data] of Object.entries(repos)) {
8377
+ repoEvidence[repoId] = {
8378
+ role: String(data.role ?? (repoId === "core" ? "core" : "module")),
8379
+ status: String(data.status ?? "unknown")
8380
+ };
8381
+ }
8382
+ return {
8383
+ id: a2.id || a2.title,
8384
+ lifecycle: lifecycleStateOf({ status: a2.status, filePath: a2.filePath }),
8385
+ implementationStatus: a2.implementationStatus || "not-started",
8386
+ validationStatus: a2.validationStatus || "not-started",
8387
+ releaseStatus: a2.releaseStatus || "not-assessed",
8388
+ affectedModules: a2.affectedModules,
8389
+ releaseGates: Array.isArray(fm.release_gates) ? fm.release_gates : [],
8390
+ completionExceptions: Array.isArray(fm.completion_exceptions) ? fm.completion_exceptions : [],
8391
+ repoEvidence
8392
+ };
8393
+ })
8260
8394
  };
8261
8395
  }
8262
8396
  function stateLabel(state) {
@@ -8309,11 +8443,19 @@ function renderExplanationHuman(exp) {
8309
8443
  lines.push("## Knowledge Status");
8310
8444
  lines.push(`- Inventory: ${exp.knowledge.hasInventory ? "available" : "missing"}`);
8311
8445
  lines.push(`- Context pack: ${exp.knowledge.hasContextPack ? "available" : "missing"}`);
8312
- lines.push(`- Business: ${ls("Business")}`);
8313
- lines.push(`- Product: ${ls("Product")}`);
8314
- lines.push(`- Tech: ${ls("Tech")}`);
8315
- lines.push(`- Delivery: ${ls("Delivery")}`);
8316
- lines.push(`- Agents: ${exp.knowledge.hasAgents ? "available" : "missing"}`);
8446
+ if (exp.isModuleRepo) {
8447
+ lines.push("- Business: Not applicable");
8448
+ lines.push("- Product: Not applicable");
8449
+ lines.push(`- Tech: ${ls("Tech")}`);
8450
+ lines.push("- Delivery: Managed by core");
8451
+ lines.push("- Agents: Managed by core");
8452
+ } else {
8453
+ lines.push(`- Business: ${ls("Business")}`);
8454
+ lines.push(`- Product: ${ls("Product")}`);
8455
+ lines.push(`- Tech: ${ls("Tech")}`);
8456
+ lines.push(`- Delivery: ${ls("Delivery")}`);
8457
+ lines.push(`- Agents: ${exp.knowledge.hasAgents ? "available" : "missing"}`);
8458
+ }
8317
8459
  if (exp.roadmap.present) {
8318
8460
  lines.push(`- Roadmap initiatives: ${exp.roadmap.initiatives}`);
8319
8461
  lines.push(`- Work Item candidates: ${exp.roadmap.work_item_candidates}`);
@@ -8374,6 +8516,36 @@ function renderExplanationHuman(exp) {
8374
8516
  }
8375
8517
  lines.push("");
8376
8518
  }
8519
+ if (exp.implementationEvidence.length > 0) {
8520
+ lines.push("## Implementation Evidence");
8521
+ for (const ev of exp.implementationEvidence) {
8522
+ lines.push("");
8523
+ lines.push(`### ${ev.id}`);
8524
+ lines.push(`- Lifecycle: ${ev.lifecycle.charAt(0).toUpperCase() + ev.lifecycle.slice(1)}`);
8525
+ lines.push(`- Implementation: ${ev.implementationStatus}`);
8526
+ lines.push(`- Validation: ${ev.validationStatus}`);
8527
+ lines.push(`- Release: ${ev.releaseStatus}`);
8528
+ if (Object.keys(ev.repoEvidence).length > 0) {
8529
+ lines.push("Repositories:");
8530
+ for (const [repoId, info] of Object.entries(ev.repoEvidence)) {
8531
+ lines.push(`- ${repoId} \u2014 ${info.status}`);
8532
+ }
8533
+ } else if (ev.affectedModules.length > 0) {
8534
+ lines.push(`Affected modules: ${ev.affectedModules.join(", ")}`);
8535
+ }
8536
+ const pendingGates = ev.releaseGates.filter((g) => g.status === "blocked" || g.status === "pending");
8537
+ if (pendingGates.length > 0) {
8538
+ lines.push("Pending release gates:");
8539
+ for (const g of pendingGates) lines.push(`- ${g.id}${g.reason ? ` \u2014 ${g.reason}` : ""}`);
8540
+ }
8541
+ const acceptedExceptions = ev.completionExceptions.filter((e) => e.status === "accepted" || e.status === "deferred");
8542
+ if (acceptedExceptions.length > 0) {
8543
+ lines.push("Completion exceptions:");
8544
+ for (const e of acceptedExceptions) lines.push(`- ${e.id}: ${e.status}${e.reason ? ` \u2014 ${e.reason}` : ""}`);
8545
+ }
8546
+ }
8547
+ lines.push("");
8548
+ }
8377
8549
  if (exp.domains.length > 0) {
8378
8550
  lines.push("## Domains");
8379
8551
  lines.push(`- ${exp.domains.join(", ")}`);
@@ -8474,14 +8646,27 @@ function renderExplanationHuman(exp) {
8474
8646
  lines.push(`- understand: ${s.understand}`);
8475
8647
  lines.push(`- agents: ${s.agents}`);
8476
8648
  lines.push(`- skills: ${s.skills}`);
8477
- lines.push(`- business: ${s.business}`);
8478
- lines.push(`- product: ${s.product}`);
8649
+ if (exp.isModuleRepo) {
8650
+ lines.push("- business: not-applicable");
8651
+ lines.push("- product: not-applicable");
8652
+ } else {
8653
+ lines.push(`- business: ${s.business}`);
8654
+ lines.push(`- product: ${s.product}`);
8655
+ }
8479
8656
  lines.push(`- capabilities: ${s.capabilities}`);
8480
8657
  lines.push(`- current-state: ${s.current_state}`);
8481
8658
  lines.push(`- codebase: ${s.codebase}`);
8482
- lines.push(`- roadmap: ${s.roadmap}`);
8483
- lines.push(`- work-items: ${s.work_items}`);
8484
- lines.push(`- adapters: ${s.adapters.length > 0 ? s.adapters.join(", ") + " installed" : "none installed"}`);
8659
+ if (s.module_context != null) {
8660
+ lines.push(`- module-context: ${s.module_context}`);
8661
+ }
8662
+ if (!exp.isModuleRepo) {
8663
+ lines.push(`- roadmap: ${s.roadmap}`);
8664
+ lines.push(`- work-items: ${s.work_items}`);
8665
+ lines.push(`- adapters: ${s.adapters.length > 0 ? s.adapters.join(", ") + " installed" : "none installed"}`);
8666
+ } else {
8667
+ lines.push("- roadmap: managed-by-core");
8668
+ lines.push("- work-items: managed-by-core");
8669
+ }
8485
8670
  lines.push(`- blocking open questions: ${s.blocking_open_questions}`);
8486
8671
  lines.push(`- assumptions: ${s.assumed_questions}`);
8487
8672
  lines.push(`- deferred: ${s.deferred_questions}`);
@@ -9557,7 +9742,16 @@ function listWorkItems(root) {
9557
9742
  capsules: strArray(data.capsules),
9558
9743
  source,
9559
9744
  domains,
9560
- readiness
9745
+ readiness,
9746
+ ...data.implementation_status ? { implementation_status: String(data.implementation_status) } : {},
9747
+ ...data.validation_status ? { validation_status: String(data.validation_status) } : {},
9748
+ ...data.release_status ? { release_status: String(data.release_status) } : {},
9749
+ ...Array.isArray(data.affected_modules) && data.affected_modules.length > 0 ? { affected_modules: data.affected_modules.map(String) } : {},
9750
+ ...data.refined_by ? { refined_by: String(data.refined_by) } : {},
9751
+ ...data.implemented_by ? { implemented_by: String(data.implemented_by) } : {},
9752
+ ...data.closed_by ? { closed_by: String(data.closed_by) } : {},
9753
+ ...Array.isArray(data.release_gates) && data.release_gates.length > 0 ? { release_gates: data.release_gates } : {},
9754
+ ...Array.isArray(data.completion_exceptions) && data.completion_exceptions.length > 0 ? { completion_exceptions: data.completion_exceptions } : {}
9561
9755
  });
9562
9756
  }
9563
9757
  return items.sort((a2, b2) => a2.id.localeCompare(b2.id));
@@ -9950,7 +10144,7 @@ function projectStatus(root) {
9950
10144
  return fail("Project status needs `.kaddo/explain.json`. Run `kaddo explain` first.");
9951
10145
  }
9952
10146
  const maturity = (explain.layers ?? []).map((l2) => `${l2.layer}: ${l2.status}`);
9953
- return ok({
10147
+ const result = {
9954
10148
  project: explain.project?.name ?? "unknown",
9955
10149
  state: explain.project?.state ?? "unknown",
9956
10150
  knowledgeMaturity: maturity,
@@ -9970,7 +10164,17 @@ function projectStatus(root) {
9970
10164
  hints: hints?.summary?.hints ?? 0
9971
10165
  },
9972
10166
  capsules: capsules.length
9973
- });
10167
+ };
10168
+ if (explain.isModuleRepo) {
10169
+ result.isModuleRepo = true;
10170
+ result.readiness = {
10171
+ overall: explain.readiness?.overall ?? "unknown",
10172
+ project_role: explain.readiness?.project_role ?? "module",
10173
+ agents: "managed-by-core",
10174
+ skills: "managed-by-core"
10175
+ };
10176
+ }
10177
+ return ok(result);
9974
10178
  }
9975
10179
  function listWorkItemsTool(root, filter = {}) {
9976
10180
  let items = listWorkItems(root);
@@ -10672,7 +10876,7 @@ var OPERATING_RULES = [
10672
10876
  "Kaddo itself never calls an LLM and never runs git \u2014 every git action is the human\u2019s."
10673
10877
  ];
10674
10878
  function toContextWorkItem(a2) {
10675
- return {
10879
+ const wi = {
10676
10880
  id: a2.id,
10677
10881
  type: a2.type,
10678
10882
  title: a2.title,
@@ -10682,6 +10886,11 @@ function toContextWorkItem(a2) {
10682
10886
  domains: a2.domains,
10683
10887
  source: parseWorkItemSource(a2.rawFrontmatter)
10684
10888
  };
10889
+ if (a2.implementationStatus) wi.implementationStatus = a2.implementationStatus;
10890
+ if (a2.validationStatus) wi.validationStatus = a2.validationStatus;
10891
+ if (a2.releaseStatus) wi.releaseStatus = a2.releaseStatus;
10892
+ if (a2.affectedModules.length > 0) wi.affectedModules = a2.affectedModules;
10893
+ return wi;
10685
10894
  }
10686
10895
  function toContextArtifact(a2) {
10687
10896
  return { id: a2.id, type: a2.type, title: a2.title, summary: a2.summary, codeGlobs: a2.codeGlobs };
@@ -10700,11 +10909,11 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
10700
10909
  if (!inventoryAvailable) {
10701
10910
  missing.push("No technical inventory found. Run `kaddo scan` to generate it.");
10702
10911
  }
10912
+ const moduleRepo = config != null && isModule(config);
10703
10913
  const knowledgeSummary = readMarkdownSummary(dir, "knowledge.md") ?? "";
10704
- if (!knowledgeSummary) {
10914
+ if (!knowledgeSummary && !moduleRepo) {
10705
10915
  missing.push("No project knowledge summary found yet.");
10706
10916
  }
10707
- const moduleRepo = config != null && isModule(config);
10708
10917
  const roadmapSummary = readMarkdownSummary(dir, "delivery/roadmap.md") ?? "";
10709
10918
  if (!roadmapSummary && !moduleRepo) {
10710
10919
  missing.push("No roadmap baseline found.");
@@ -10878,11 +11087,12 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
10878
11087
  }
10879
11088
  return contexts;
10880
11089
  })(),
11090
+ isModuleRepo: moduleRepo,
10881
11091
  missing,
10882
11092
  // VS-052/VS-073.2: the handoff is driven by the unified next step, so the pack never contradicts
10883
11093
  // the Current Phase block above it.
10884
11094
  handoff: {
10885
- recommendedAgents: isBootstrap ? [] : unifiedPhase.recommendedAgents.length > 0 ? unifiedPhase.recommendedAgents : recommendedAgentsForState(state),
11095
+ recommendedAgents: isBootstrap ? [] : unifiedPhase.recommendedAgents.length > 0 ? unifiedPhase.recommendedAgents : moduleRepo ? [] : recommendedAgentsForState(state),
10886
11096
  nextSteps: [nextStepRecommendation.label],
10887
11097
  instructions: isBootstrap ? ["No agent handoff yet.", "Run `kaddo bootstrap` first to create the baseline files."] : unifiedPhase.llmInstructions.length > 0 ? unifiedPhase.llmInstructions : LLM_INSTRUCTIONS,
10888
11098
  operatingRules: OPERATING_RULES
@@ -11193,7 +11403,11 @@ function renderContextPack(pack) {
11193
11403
  }
11194
11404
  }
11195
11405
  parts.push("## Recommended Agent Handoff\n");
11196
- if (isBootstrapIncomplete) {
11406
+ if (pack.isModuleRepo && handoff.recommendedAgents.length === 0) {
11407
+ parts.push("No local agent action is required.\n");
11408
+ parts.push("This module is ready for core orchestration.\n");
11409
+ parts.push("Business, Product, Delivery, Agents and Skills are managed by the core repository.\n");
11410
+ } else if (isBootstrapIncomplete) {
11197
11411
  parts.push("No agent handoff yet.\n");
11198
11412
  parts.push("Run `kaddo bootstrap` first to create the baseline files.\n");
11199
11413
  } else if (rec.agent && rec.agentInstalled === false) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/mcp",
3
- "version": "3.64.0",
3
+ "version": "3.66.0",
4
4
  "description": "MCP server for Kaddo project knowledge: read-only resources/tools/prompts plus safe derived generation under .kaddo/.",
5
5
  "license": "MIT",
6
6
  "repository": {