@kaddo/mcp 3.21.0 → 3.22.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 +65 -11
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -504,8 +504,12 @@ function projectStatus(root) {
504
504
  withOwnership: explain.ownership?.workItemsWithOwnership ?? 0,
505
505
  total: explain.ownership?.workItemsTotal ?? 0
506
506
  },
507
- graphQuality: hints?.quality ?? "unknown (run `kaddo graph export`)",
508
- graphHints: hints?.summary?.hints ?? 0,
507
+ graph: {
508
+ scope: hints?.scope ?? "unknown (run `kaddo graph export`)",
509
+ scope_reason: hints?.scope_reason ?? "",
510
+ quality: hints?.quality ?? "unknown (run `kaddo graph export`)",
511
+ hints: hints?.summary?.hints ?? 0
512
+ },
509
513
  capsules: capsules.length
510
514
  });
511
515
  }
@@ -553,7 +557,13 @@ function listGraphHints(root, filter = {}) {
553
557
  if (filter.artifact_type) hints = hints.filter((h) => h.artifact_type === filter.artifact_type);
554
558
  if (filter.severity) hints = hints.filter((h) => h.severity === filter.severity);
555
559
  if (filter.active_only) hints = hints.filter((h) => h.artifact_type === "work-item");
556
- return ok({ quality: report.quality ?? "unknown", count: hints.length, hints });
560
+ return ok({
561
+ scope: report.scope ?? "active",
562
+ scope_reason: report.scope_reason ?? "",
563
+ quality: report.quality ?? "unknown",
564
+ count: hints.length,
565
+ hints
566
+ });
557
567
  }
558
568
 
559
569
  // ../cli/src/core/config.ts
@@ -1521,6 +1531,11 @@ function loadExternalCapsules(dir) {
1521
1531
 
1522
1532
  // ../cli/src/core/graph.ts
1523
1533
  var KNOWLEDGE3 = "knowledge";
1534
+ var ACTIVE_STATUSES = ["draft", "ready", "in-progress", "blocked"];
1535
+ var ALL_STATUSES = ["draft", "ready", "in-progress", "blocked", "completed"];
1536
+ function scopeStatuses(scope) {
1537
+ return scope === "all" ? { included: ALL_STATUSES, excluded: ["archived"] } : { included: ACTIVE_STATUSES, excluded: ["completed", "archived"] };
1538
+ }
1524
1539
  function toPosix3(p) {
1525
1540
  return p.replace(/\\/g, "/");
1526
1541
  }
@@ -1563,7 +1578,10 @@ function buildGraph(dir, config, opts = {}, now = /* @__PURE__ */ new Date()) {
1563
1578
  }
1564
1579
  const all = discoverKnowledge(dir);
1565
1580
  const workItems = all.filter((a) => a.isWorkItem);
1566
- const selectedWIs = scope === "active" ? workItems.filter((a) => a.lifecycle && isActiveState(a.lifecycle)) : workItems;
1581
+ const { included, excluded } = scopeStatuses(scope);
1582
+ const includedSet = new Set(included);
1583
+ const activeWICount = workItems.filter((a) => a.lifecycle && isActiveState(a.lifecycle)).length;
1584
+ const selectedWIs = workItems.filter((a) => a.lifecycle && includedSet.has(a.lifecycle));
1567
1585
  for (const wi of selectedWIs) {
1568
1586
  const id = wi.id || wi.title;
1569
1587
  const wiNodeId = `wi:${id}`;
@@ -1633,6 +1651,7 @@ function buildGraph(dir, config, opts = {}, now = /* @__PURE__ */ new Date()) {
1633
1651
  }
1634
1652
  }
1635
1653
  }
1654
+ const scopeReason = scope === "all" ? "All supported Work Item statuses are included." : activeWICount === 0 ? "No active Work Items found. Completed Work Items are excluded from active scope." : "Active Work Items only; completed and archived are excluded.";
1636
1655
  return {
1637
1656
  generated_at: now.toISOString(),
1638
1657
  project: {
@@ -1640,6 +1659,10 @@ function buildGraph(dir, config, opts = {}, now = /* @__PURE__ */ new Date()) {
1640
1659
  state: config.project.state,
1641
1660
  structure: config.project.structure
1642
1661
  },
1662
+ scope,
1663
+ scope_reason: scopeReason,
1664
+ included_statuses: included,
1665
+ excluded_statuses: excluded,
1643
1666
  nodes: [...nodes.values()],
1644
1667
  edges
1645
1668
  };
@@ -1687,8 +1710,13 @@ function loadGraphSummary(dir) {
1687
1710
  const connected = new Set(
1688
1711
  edges.filter((e) => e.type === "owns" && activeWiIds.has(e.from)).map((e) => e.from)
1689
1712
  );
1713
+ const scope = graph.scope === "all" ? "all" : "active";
1690
1714
  return {
1691
1715
  generatedAt: String(graph.generated_at ?? ""),
1716
+ scope,
1717
+ scopeReason: String(graph.scope_reason ?? ""),
1718
+ includedStatuses: Array.isArray(graph.included_statuses) ? graph.included_statuses : [],
1719
+ excludedStatuses: Array.isArray(graph.excluded_statuses) ? graph.excluded_statuses : [],
1692
1720
  nodes: nodes.length,
1693
1721
  edges: edges.length,
1694
1722
  activeWorkItemsConnectedToCode: connected.size
@@ -1840,6 +1868,8 @@ function buildGraphHints(dir, graph, now = /* @__PURE__ */ new Date()) {
1840
1868
  const quality = assessQuality(nodes, relationshipEdges, hints.length);
1841
1869
  return {
1842
1870
  generated_at: now.toISOString(),
1871
+ scope: graph.scope,
1872
+ scope_reason: graph.scope_reason,
1843
1873
  quality,
1844
1874
  summary: { nodes, edges: graph.edges.length, hints: hints.length },
1845
1875
  metrics,
@@ -1875,13 +1905,23 @@ function renderGraphHintsMarkdown(report) {
1875
1905
  lines.push("");
1876
1906
  lines.push("## Summary");
1877
1907
  lines.push("");
1908
+ lines.push(`- Scope: ${report.scope} \u2014 ${report.scope_reason}`);
1878
1909
  lines.push(`- Relationship quality: ${report.quality} \u2014 ${QUALITY_NOTE[report.quality]}`);
1879
1910
  lines.push(`- Nodes: ${report.summary.nodes}`);
1880
1911
  lines.push(`- Edges: ${report.summary.edges}`);
1881
1912
  lines.push(`- Hints: ${report.summary.hints}`);
1882
1913
  lines.push("");
1883
1914
  if (report.hints.length === 0) {
1884
- lines.push("No hints \u2014 the declared relationships look healthy. \u{1F389}");
1915
+ if (report.quality === "empty") {
1916
+ lines.push("No active relationship hints were generated.");
1917
+ lines.push("");
1918
+ lines.push(`The graph is ${report.quality} for the **${report.scope}** scope \u2014 ${report.scope_reason}`);
1919
+ if (report.scope !== "all") {
1920
+ lines.push("Run `kaddo graph export --scope all` to inspect completed Work Items and historical relationships.");
1921
+ }
1922
+ } else {
1923
+ lines.push("No hints \u2014 the declared relationships look healthy. \u{1F389}");
1924
+ }
1885
1925
  lines.push("");
1886
1926
  return lines.join("\n");
1887
1927
  }
@@ -1917,6 +1957,8 @@ function loadGraphHints(dir) {
1917
1957
  const report = JSON.parse(readFile(p));
1918
1958
  const hints = Array.isArray(report.hints) ? report.hints : [];
1919
1959
  return {
1960
+ scope: String(report.scope ?? "active"),
1961
+ scopeReason: String(report.scope_reason ?? ""),
1920
1962
  quality: report.quality ?? "empty",
1921
1963
  totalHints: hints.length,
1922
1964
  activeWorkItemHints: hints.filter((h) => h.artifact_type === "work-item").length,
@@ -2316,9 +2358,12 @@ function renderContextPack(pack) {
2316
2358
  parts.push(
2317
2359
  [
2318
2360
  "- Available: yes",
2361
+ `- Scope: ${pack.graph.scope}`,
2319
2362
  `- Nodes: ${pack.graph.nodes}`,
2320
2363
  `- Edges: ${pack.graph.edges}`,
2321
- `- Active Work Items connected to code: ${pack.graph.activeWorkItemsConnectedToCode}`
2364
+ ...pack.graphHints ? [`- Quality: ${pack.graphHints.quality}`] : [],
2365
+ `- Active Work Items connected to code: ${pack.graph.activeWorkItemsConnectedToCode}`,
2366
+ ...pack.graph.scopeReason ? [`- Reason: ${pack.graph.scopeReason}`] : []
2322
2367
  ].join("\n") + "\n"
2323
2368
  );
2324
2369
  parts.push("Full graph: `.kaddo/graph.json` / `.kaddo/graph.mmd` (run `kaddo graph export` to refresh).\n");
@@ -2709,13 +2754,18 @@ function renderExplanationHuman(exp) {
2709
2754
  }
2710
2755
  if (exp.graph) {
2711
2756
  lines.push("## Knowledge Graph");
2757
+ lines.push(`- Scope: ${exp.graph.scope}`);
2712
2758
  lines.push(`- Nodes: ${exp.graph.nodes}`);
2713
2759
  lines.push(`- Edges: ${exp.graph.edges}`);
2714
2760
  if (exp.graphHints) {
2715
2761
  lines.push(`- Quality: ${exp.graphHints.quality}`);
2716
2762
  lines.push(`- Hints: ${exp.graphHints.totalHints}`);
2717
2763
  }
2764
+ if (exp.graph.scopeReason) lines.push(`- Reason: ${exp.graph.scopeReason}`);
2718
2765
  if (exp.graph.generatedAt) lines.push(`- Last exported: ${exp.graph.generatedAt}`);
2766
+ if (exp.graph.scope === "active" && exp.graphHints?.quality === "empty") {
2767
+ lines.push("- Tip: Run `kaddo graph export --scope all` to include completed Work Items");
2768
+ }
2719
2769
  lines.push("");
2720
2770
  }
2721
2771
  if (exp.skills.total > 0) {
@@ -2973,10 +3023,10 @@ function generateUnderstand(root) {
2973
3023
  next_suggested_resources: ["kaddo://understand"]
2974
3024
  };
2975
3025
  }
2976
- function generateGraph(root) {
3026
+ function generateGraph(root, scope = "active") {
2977
3027
  const config = requireConfig(root);
2978
3028
  requireKnowledge(root);
2979
- const graph = buildGraph(root, config, { scope: "active" });
3029
+ const graph = buildGraph(root, config, { scope });
2980
3030
  const hints = buildGraphHints(root, graph);
2981
3031
  writeDerived(root, ".kaddo/graph.json", serializeGraphJson(graph));
2982
3032
  writeDerived(root, ".kaddo/graph.mmd", renderGraphMermaid(graph));
@@ -2991,7 +3041,7 @@ function generateGraph(root) {
2991
3041
  ".kaddo/graph-hints.md",
2992
3042
  ".kaddo/graph-hints.json"
2993
3043
  ],
2994
- summary: "Knowledge graph and hints generated successfully.",
3044
+ summary: `Knowledge graph and hints generated successfully (${scope} scope).`,
2995
3045
  warnings,
2996
3046
  next_suggested_resources: ["kaddo://graph", "kaddo://graph-hints"]
2997
3047
  };
@@ -3172,8 +3222,12 @@ function createServer(root) {
3172
3222
  );
3173
3223
  server.registerTool(
3174
3224
  "kaddo_generate_graph",
3175
- { title: "Generate knowledge graph", description: `Regenerate .kaddo/graph.json/.mmd + graph-hints.md/.json. ${DERIVED_NOTE}`, inputSchema: {} },
3176
- async () => generated(root, "generate knowledge graph", () => generateGraph(root))
3225
+ {
3226
+ title: "Generate knowledge graph",
3227
+ description: `Regenerate .kaddo/graph.json/.mmd + graph-hints.md/.json. scope: active (default) or all. ${DERIVED_NOTE}`,
3228
+ inputSchema: { scope: z2.enum(["active", "all"]).optional() }
3229
+ },
3230
+ async (args) => generated(root, "generate knowledge graph", () => generateGraph(root, args.scope ?? "active"))
3177
3231
  );
3178
3232
  server.registerTool(
3179
3233
  "kaddo_generate_capsule_draft",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/mcp",
3
- "version": "3.21.0",
3
+ "version": "3.22.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": {