@kaddo/mcp 3.48.0 → 3.49.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 +142 -21
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -384,6 +384,7 @@ function parseArtifact(filePath, raw) {
384
384
  initiative: String(data.initiative ?? data.source_initiative ?? ""),
385
385
  source: data.source ? String(data.source) : "",
386
386
  sourceId: String(data.source_id ?? ""),
387
+ rawFrontmatter: data,
387
388
  decisions: Array.isArray(data.decisions) ? data.decisions.map(String).filter(Boolean) : [],
388
389
  capsules: Array.isArray(data.capsules) ? data.capsules.map(String).filter(Boolean) : []
389
390
  };
@@ -5553,6 +5554,84 @@ function renderSignalsCompact(signals) {
5553
5554
  return lines.length > 0 ? lines.join("\n") + "\n" : "No signals detected.\n";
5554
5555
  }
5555
5556
 
5557
+ // ../cli/src/core/work-item-source.ts
5558
+ var VALID_SOURCES = [
5559
+ "manual",
5560
+ "roadmap",
5561
+ "jira",
5562
+ "github",
5563
+ "notion",
5564
+ "xlsx",
5565
+ "csv",
5566
+ "api",
5567
+ "external",
5568
+ "unknown"
5569
+ ];
5570
+ function isValidSource(s) {
5571
+ return VALID_SOURCES.includes(s);
5572
+ }
5573
+ function parseWorkItemSource(frontmatter) {
5574
+ const raw = frontmatter.source ? String(frontmatter.source) : "";
5575
+ if (raw && isValidSource(raw)) {
5576
+ return {
5577
+ type: raw,
5578
+ id: optStr(frontmatter.source_id),
5579
+ title: optStr(frontmatter.source_title),
5580
+ context: optStr(frontmatter.source_context),
5581
+ provider: optStr(frontmatter.source_provider),
5582
+ url: optStr(frontmatter.source_url),
5583
+ imported_at: optStr(frontmatter.source_imported_at),
5584
+ synced_at: optStr(frontmatter.source_synced_at),
5585
+ inferred: false
5586
+ };
5587
+ }
5588
+ if (raw && !isValidSource(raw)) {
5589
+ return {
5590
+ type: "unknown",
5591
+ id: optStr(frontmatter.source_id),
5592
+ title: optStr(frontmatter.source_title),
5593
+ context: optStr(frontmatter.source_context),
5594
+ provider: optStr(frontmatter.source_provider),
5595
+ url: optStr(frontmatter.source_url),
5596
+ imported_at: optStr(frontmatter.source_imported_at),
5597
+ synced_at: optStr(frontmatter.source_synced_at),
5598
+ inferred: true,
5599
+ reason: `Invalid source value: "${raw}".`
5600
+ };
5601
+ }
5602
+ if (frontmatter.source_work_item_candidate || frontmatter.source_roadmap_initiative) {
5603
+ return {
5604
+ type: "roadmap",
5605
+ id: optStr(frontmatter.source_id) ?? optStr(frontmatter.source_work_item_candidate),
5606
+ title: optStr(frontmatter.source_initiative_title),
5607
+ inferred: true,
5608
+ reason: "Inferred from legacy roadmap fields."
5609
+ };
5610
+ }
5611
+ if (frontmatter.source_id) {
5612
+ return {
5613
+ type: "unknown",
5614
+ id: optStr(frontmatter.source_id),
5615
+ inferred: true,
5616
+ reason: "Has source_id but no source type."
5617
+ };
5618
+ }
5619
+ return {
5620
+ type: "unknown",
5621
+ inferred: true,
5622
+ reason: "No source metadata found."
5623
+ };
5624
+ }
5625
+ function renderSourceCompact(source) {
5626
+ const parts = [source.type];
5627
+ if (source.id) parts.push(source.id);
5628
+ return parts.join(" \xB7 ");
5629
+ }
5630
+ function optStr(v) {
5631
+ if (typeof v === "string" && v.trim()) return v.trim();
5632
+ return void 0;
5633
+ }
5634
+
5556
5635
  // ../cli/src/core/project-route.ts
5557
5636
  function isUseful(q) {
5558
5637
  return q === "useful";
@@ -5639,12 +5718,12 @@ var captureTechDecisions = {
5639
5718
  var createWorkSource = {
5640
5719
  id: "create-work-source",
5641
5720
  label: "Create or connect work source",
5642
- evaluate: (ctx) => ({
5643
- status: ctx.hasRoadmap || ctx.totalWorkItems > 0 ? "done" : "pending",
5644
- evidence: ctx.hasRoadmap ? ["knowledge/delivery/roadmap.md"] : void 0,
5645
- command: ctx.hasRoadmap ? void 0 : "kaddo roadmap",
5646
- agent: ctx.hasRoadmap ? void 0 : "roadmap-agent"
5647
- })
5721
+ evaluate: (ctx) => {
5722
+ if (!ctx.hasRoadmap && ctx.totalWorkItems === 0) return { status: "pending", command: "kaddo roadmap", agent: "roadmap-agent" };
5723
+ if (ctx.hasUnknownSources) return { status: "warning", evidence: ["Work Items with unknown source"], reason: "Some Work Items have no source metadata." };
5724
+ const evidence = ctx.hasRoadmap ? ["knowledge/delivery/roadmap.md"] : void 0;
5725
+ return { status: "done", evidence };
5726
+ }
5648
5727
  };
5649
5728
  var materializeWorkItem = {
5650
5729
  id: "materialize-work-item",
@@ -5861,6 +5940,10 @@ function buildRouteContext(dir) {
5861
5940
  adaptersInstalled: adapters.length,
5862
5941
  hasGuardHistory: exists(join(dir, ".kaddo", "history", "guard-runs.jsonl")),
5863
5942
  hasScanWarnings: hasScan ? loadScanWarnings(dir) : false,
5943
+ hasUnknownSources: wis.some((w) => {
5944
+ const src = parseWorkItemSource(w.rawFrontmatter);
5945
+ return src.type === "unknown" && src.inferred;
5946
+ }),
5864
5947
  nextStepId: mapNextStepId(nextStep.id)
5865
5948
  };
5866
5949
  }
@@ -6076,17 +6159,21 @@ function buildProjectExplanation(dir) {
6076
6159
  hasAgents: hasAgents(dir)
6077
6160
  };
6078
6161
  const workItemArtifacts = discoverWorkItems(dir);
6079
- const items = workItemArtifacts.map((a) => ({
6080
- id: a.id || a.title,
6081
- title: a.title,
6082
- type: a.type,
6083
- status: a.status,
6084
- lifecycle: lifecycleStateOf({ status: a.status, filePath: a.filePath }),
6085
- initiative: a.initiative,
6086
- knowledgeLevel: a.knowledgeLevel,
6087
- hasOwnership: a.codeGlobs.length > 0,
6088
- domains: a.domains
6089
- }));
6162
+ const items = workItemArtifacts.map((a) => {
6163
+ const src = parseWorkItemSource(a.rawFrontmatter);
6164
+ return {
6165
+ id: a.id || a.title,
6166
+ title: a.title,
6167
+ type: a.type,
6168
+ status: a.status,
6169
+ lifecycle: lifecycleStateOf({ status: a.status, filePath: a.filePath }),
6170
+ initiative: a.initiative,
6171
+ knowledgeLevel: a.knowledgeLevel,
6172
+ hasOwnership: a.codeGlobs.length > 0,
6173
+ domains: a.domains,
6174
+ source: { type: src.type, ...src.id ? { id: src.id } : {}, inferred: src.inferred }
6175
+ };
6176
+ });
6090
6177
  const byState = lifecycleCounts(items.map((i) => i.lifecycle));
6091
6178
  const byType = {};
6092
6179
  for (const i of items) {
@@ -6283,6 +6370,17 @@ function renderExplanationHuman(exp) {
6283
6370
  for (const [t, n] of typeEntries) lines.push(`- ${typeLabel(t)}: ${n}`);
6284
6371
  lines.push("");
6285
6372
  }
6373
+ const sourceCounts = {};
6374
+ for (const i of exp.workItems.items) {
6375
+ const t = i.source?.type ?? "unknown";
6376
+ sourceCounts[t] = (sourceCounts[t] ?? 0) + 1;
6377
+ }
6378
+ const sourceEntries = Object.entries(sourceCounts).filter(([, n]) => n > 0);
6379
+ if (sourceEntries.length > 0) {
6380
+ lines.push("## Work Item Sources");
6381
+ for (const [t, n] of sourceEntries) lines.push(`- ${t.charAt(0).toUpperCase() + t.slice(1)}: ${n}`);
6382
+ lines.push("");
6383
+ }
6286
6384
  const grouped = exp.workItems.initiatives.filter(
6287
6385
  (g) => LIFECYCLE_STATES.some((s2) => g.states[s2] > 0)
6288
6386
  );
@@ -7411,6 +7509,20 @@ function serializeDriftJson(r) {
7411
7509
 
7412
7510
  // src/workitems.ts
7413
7511
  import matter8 from "gray-matter";
7512
+ var VALID_SOURCES2 = /* @__PURE__ */ new Set(["manual", "roadmap", "jira", "github", "notion", "xlsx", "csv", "api", "external", "unknown"]);
7513
+ function optStr2(v) {
7514
+ return typeof v === "string" && v.trim() ? v.trim() : void 0;
7515
+ }
7516
+ function parseSource(data) {
7517
+ const raw = data.source ? String(data.source) : "";
7518
+ if (raw && VALID_SOURCES2.has(raw)) {
7519
+ return { type: raw, id: optStr2(data.source_id), title: optStr2(data.source_title), url: optStr2(data.source_url), provider: optStr2(data.source_provider), inferred: false };
7520
+ }
7521
+ if (data.source_work_item_candidate || data.source_roadmap_initiative) {
7522
+ return { type: "roadmap", id: optStr2(data.source_id) ?? optStr2(data.source_work_item_candidate), title: optStr2(data.source_initiative_title), inferred: true };
7523
+ }
7524
+ return { type: "unknown", inferred: true };
7525
+ }
7414
7526
  var ACTIVE_STATES2 = /* @__PURE__ */ new Set(["draft", "ready", "in-progress", "blocked"]);
7415
7527
  function strArray(v) {
7416
7528
  return Array.isArray(v) ? v.map((x) => String(x)).filter(Boolean) : [];
@@ -7454,7 +7566,8 @@ function listWorkItems(root) {
7454
7566
  code: strArray(data.code),
7455
7567
  capabilities: strArray(data.capabilities),
7456
7568
  decisions: strArray(data.decisions),
7457
- capsules: strArray(data.capsules)
7569
+ capsules: strArray(data.capsules),
7570
+ source: parseSource(data)
7458
7571
  });
7459
7572
  }
7460
7573
  return items.sort((a, b) => a.id.localeCompare(b.id));
@@ -7957,7 +8070,8 @@ function toContextWorkItem(a) {
7957
8070
  status: a.status,
7958
8071
  lifecycle: lifecycleStateOf({ status: a.status, filePath: a.filePath }),
7959
8072
  knowledgeLevel: a.knowledgeLevel,
7960
- domains: a.domains
8073
+ domains: a.domains,
8074
+ source: parseWorkItemSource(a.rawFrontmatter)
7961
8075
  };
7962
8076
  }
7963
8077
  function toContextArtifact(a) {
@@ -8298,7 +8412,10 @@ function renderContextPack(pack) {
8298
8412
  const level = wi.knowledgeLevel ? ` [${wi.knowledgeLevel}]` : "";
8299
8413
  const status = wi.lifecycle ? ` (${wi.lifecycle})` : wi.status ? ` (${wi.status})` : "";
8300
8414
  const domains = wi.domains.length > 0 ? ` \xB7 domains: ${wi.domains.join(", ")}` : "";
8301
- return `- ${wi.id || wi.title} [${wi.type}]${level}${status} \u2014 ${wi.title}${domains}`;
8415
+ const line = `- ${wi.id || wi.title} [${wi.type}]${level}${status} \u2014 ${wi.title}${domains}`;
8416
+ const src = wi.source && wi.source.type !== "unknown" ? `
8417
+ - Source: ${renderSourceCompact(wi.source)}` : "";
8418
+ return `${line}${src}`;
8302
8419
  });
8303
8420
  parts.push(lines.join("\n") + "\n");
8304
8421
  } else {
@@ -8556,7 +8673,11 @@ function renderUnderstand(plan) {
8556
8673
  if (plan.activeWorkItems && plan.activeWorkItems.length > 0) {
8557
8674
  parts.push("## Active Work Items\n");
8558
8675
  parts.push(
8559
- plan.activeWorkItems.map((w) => `- ${w.id} [${w.type}] ${w.lifecycle} \u2014 ${w.title}`).join("\n") + "\n"
8676
+ plan.activeWorkItems.map((w) => {
8677
+ const src = w.source && w.source.type !== "unknown" ? `
8678
+ - Source: ${w.source.type}${w.source.id ? ` \xB7 ${w.source.id}` : ""}` : "";
8679
+ return `- ${w.id} [${w.type}] ${w.lifecycle} \u2014 ${w.title}${src}`;
8680
+ }).join("\n") + "\n"
8560
8681
  );
8561
8682
  }
8562
8683
  parts.push("## Context Pack\n");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/mcp",
3
- "version": "3.48.0",
3
+ "version": "3.49.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": {