@kaddo/mcp 3.37.0 → 3.38.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 -85
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1916,10 +1916,10 @@ function extractFromMarkdown(md) {
1916
1916
  }
1917
1917
  const m = line.match(/^\s*(?:[-*]|\d+\.)\s+(.+?)\s*$/);
1918
1918
  if (m) {
1919
- const raw = m[1].trim();
1920
- if (!raw || /^_.*_$/.test(raw)) continue;
1921
- const { text: text2, resolution_status } = parseResolution(raw);
1922
- if (text2) out.push({ text: text2, resolution_status });
1919
+ const bullet = m[1].trim();
1920
+ if (!bullet || /^_.*_$/.test(bullet)) continue;
1921
+ const { text: text2, resolution_status } = parseResolution(bullet);
1922
+ if (text2) out.push({ text: text2, resolution_status, line: i + 1, raw: line.trim() });
1923
1923
  }
1924
1924
  }
1925
1925
  return out;
@@ -1959,12 +1959,15 @@ function buildOpenQuestionsReport(dir, now = /* @__PURE__ */ new Date()) {
1959
1959
  questions.push({
1960
1960
  id: `OQ-${String(seq).padStart(3, "0")}`,
1961
1961
  source,
1962
+ sourcePath: source,
1963
+ line: eq.line,
1964
+ raw: eq.raw,
1962
1965
  section: "Open Questions",
1963
1966
  question: eq.text,
1964
1967
  classification,
1965
1968
  resolution_status: eq.resolution_status,
1966
1969
  reason,
1967
- ...eq.resolution_note ? { resolution_note: eq.resolution_note } : {},
1970
+ ...eq.resolution_note ? { resolution_note: eq.resolution_note, note: eq.resolution_note } : {},
1968
1971
  ...classification === "blocking" && eq.resolution_status === "open" ? { suggested_assumption: suggestedAssumption(eq.text) } : {}
1969
1972
  });
1970
1973
  }
@@ -2034,17 +2037,23 @@ function renderOpenQuestionsMarkdown(r) {
2034
2037
  L.push("## Blocking Open Questions", "");
2035
2038
  if (blockingOpen.length === 0) L.push("_None \u2014 nothing blocks readiness._", "");
2036
2039
  for (const q of blockingOpen) {
2037
- L.push(`### ${q.id}`, "");
2038
- L.push(`- Source: \`${q.source}\``);
2039
- L.push(`- Question: ${q.question}`);
2040
+ L.push(`### ${q.question}`, "");
2041
+ L.push(`- Status: ${q.resolution_status}`);
2042
+ L.push(`- Severity: ${q.classification}`);
2043
+ L.push(`- Source: \`${q.sourcePath}:${q.line}\``);
2040
2044
  L.push(`- Reason: ${q.reason}`);
2041
- if (q.suggested_assumption) L.push(`- Suggested assumption: ${q.suggested_assumption}`);
2045
+ L.push("");
2046
+ L.push("Suggested action:", "");
2047
+ L.push("```md");
2048
+ L.push(`- [assumed] ${q.question}`);
2049
+ L.push(` - note: ${q.suggested_assumption ?? "<editable assumption for the MVP>"}`);
2050
+ L.push("```");
2042
2051
  L.push("");
2043
2052
  }
2044
2053
  const renderStatusList = (title, items) => {
2045
2054
  L.push(`## ${title}`, "");
2046
2055
  if (items.length === 0) L.push("_None._");
2047
- for (const q of items) L.push(`- ${q.question}${q.resolution_note ? ` \u2014 _${q.resolution_note}_` : ""}`);
2056
+ for (const q of items) L.push(`- ${q.question} \u2014 \`${q.sourcePath}:${q.line}\`${q.note ? ` \u2014 _${q.note}_` : ""}`);
2048
2057
  L.push("");
2049
2058
  };
2050
2059
  renderStatusList("Resolved", r.resolved_questions);
@@ -2218,14 +2227,7 @@ function buildAdapterStatuses(dir) {
2218
2227
  });
2219
2228
  }
2220
2229
 
2221
- // ../cli/src/core/readiness.ts
2222
- var KNOWLEDGE_FILES = [
2223
- { key: "current_state", path: "knowledge/tech/current-state.md", label: "knowledge/tech/current-state.md", agent: "architecture-agent" },
2224
- { key: "codebase", path: "knowledge/tech/codebase.md", label: "knowledge/tech/codebase.md", agent: "codebase-agent" },
2225
- { key: "capabilities", path: "knowledge/product/capabilities.md", label: "knowledge/product/capabilities.md", agent: "capability-agent" },
2226
- { key: "product", path: "knowledge/product/product.md", label: "knowledge/product/product.md", agent: "product-agent" },
2227
- { key: "business", path: "knowledge/business/business.md", label: "knowledge/business/business.md", agent: "business-agent" }
2228
- ];
2230
+ // ../cli/src/core/next-step.ts
2229
2231
  function roadmapSignal(dir) {
2230
2232
  const p = join(dir, "knowledge/delivery/roadmap.md");
2231
2233
  if (!exists(p)) return "missing";
@@ -2256,8 +2258,91 @@ function installedAdapters(dir) {
2256
2258
  (s) => s.state === "injected" || s.state === "legacy-injected" || s.state === "full-generated" && (s.originAdapter === s.id || s.originAdapter === null)
2257
2259
  ).map((s) => s.id);
2258
2260
  }
2261
+ var B = "knowledge/business/business.md";
2262
+ var P = "knowledge/product/product.md";
2263
+ var CAP = "knowledge/product/capabilities.md";
2264
+ var CS = "knowledge/tech/current-state.md";
2265
+ var CB = "knowledge/tech/codebase.md";
2266
+ function resolveNextStep(dir, now = /* @__PURE__ */ new Date()) {
2267
+ const config = loadConfig(dir);
2268
+ if (!config) {
2269
+ return { id: "init", phase: "Setup", label: "Run `kaddo init` to initialize Kaddo.", command: "kaddo init", reason: "Kaddo is not initialized in this project." };
2270
+ }
2271
+ const state = config.project.state;
2272
+ const q = (rel) => analyzeKnowledgeArtifact(dir, rel);
2273
+ const qBusiness = q(B), qProduct = q(P), qCap = q(CAP), qCurrentState = q(CS), qCodebase = q(CB);
2274
+ if (qBusiness === "missing" || qProduct === "missing") {
2275
+ return { id: "bootstrap", phase: "Setup", label: "Run `kaddo bootstrap` to create the project knowledge baseline.", command: "kaddo bootstrap", reason: "The knowledge baseline is incomplete." };
2276
+ }
2277
+ const ctx = buildCodexAdapterContext(dir);
2278
+ if (!ctx.hasAgents) {
2279
+ return { id: "add-agents", phase: "Setup", label: "Run `kaddo add agents` to install the Kaddo agent prompt packs.", command: "kaddo add agents", reason: "No Kaddo agents are installed yet." };
2280
+ }
2281
+ if (!ctx.hasSkills) {
2282
+ return { id: "add-skills", phase: "Setup", label: "Run `kaddo add skills` to install reusable Kaddo skills.", command: "kaddo add skills", reason: "No Kaddo skills are installed yet." };
2283
+ }
2284
+ if ((state === "pre-ai" || state === "legacy") && !exists(join(dir, ".kaddo", "scan.json"))) {
2285
+ 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." };
2286
+ }
2287
+ if (!exists(join(dir, ".kaddo", "context-pack.md"))) {
2288
+ 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." };
2289
+ }
2290
+ if (!exists(join(dir, ".kaddo", "understand.md"))) {
2291
+ 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." };
2292
+ }
2293
+ const refine = (id, agent, target, quality) => ({
2294
+ id,
2295
+ phase: "Knowledge Refinement",
2296
+ label: `Use ${agent} to complete \`${target}\`.`,
2297
+ agent,
2298
+ target,
2299
+ reason: `${target} is ${quality === "missing" ? "missing" : "still a bootstrap placeholder or too thin"}.`,
2300
+ instructions: [
2301
+ "The baseline file exists but does not yet hold real, project-specific knowledge.",
2302
+ `Use the ${agent} to replace the placeholders with real knowledge.`,
2303
+ "Do not write code."
2304
+ ]
2305
+ });
2306
+ if (qBusiness !== "useful") return refine("refine-business", "business-agent", B, qBusiness);
2307
+ if (qProduct !== "useful" || qCap !== "useful") {
2308
+ const target = qCap !== "useful" ? CAP : P;
2309
+ return refine("refine-product", "capability-agent", target, qCap !== "useful" ? qCap : qProduct);
2310
+ }
2311
+ if (qCurrentState !== "useful") return refine("refine-current-state", "architecture-agent", CS, qCurrentState);
2312
+ if (qCodebase !== "useful") {
2313
+ const agent = ctx.agents.includes("codebase-agent") ? "codebase-agent" : "architecture-agent";
2314
+ return refine("refine-codebase", agent, CB, qCodebase);
2315
+ }
2316
+ const oq = buildOpenQuestionsReport(dir, now);
2317
+ if (oq.summary.blocking_open > 0) {
2318
+ return { id: "questions", phase: "Knowledge Refinement", label: "Run `kaddo questions` to see source locations and resolution guidance, then resolve, assume or defer the blocking open questions.", command: "kaddo questions", reason: `${oq.summary.blocking_open} blocking open question(s) remain.` };
2319
+ }
2320
+ const roadmap = roadmapSignal(dir);
2321
+ if (roadmap !== "has-candidates") {
2322
+ return { id: "roadmap", phase: "Planning", label: "Use roadmap-agent to define roadmap candidates (`kaddo roadmap`).", command: "kaddo roadmap", agent: "roadmap-agent", target: "knowledge/delivery/roadmap.md", reason: "The roadmap has no candidates yet." };
2323
+ }
2324
+ const wi = workItemsSignal(dir);
2325
+ if (wi === "none" || wi === "none-ready") {
2326
+ return { id: "create-work-item", phase: "Delivery Preparation", label: "Run `kaddo create --from roadmap` to materialize the first Work Item.", command: "kaddo create --from roadmap", reason: "The roadmap has candidates but no Work Item is ready." };
2327
+ }
2328
+ const adapters = installedAdapters(dir);
2329
+ if (adapters.length === 0) {
2330
+ return { id: "install-adapter", phase: "Active Delivery", label: "Run `kaddo adapters list` and install the adapter for your preferred agent.", command: "kaddo adapters list", reason: "A Work Item is ready but no adapter is installed." };
2331
+ }
2332
+ return { id: "implement", phase: "Active Delivery", label: "Implement the ready Work Item and run `kaddo guard`.", reason: "A Work Item is ready and an adapter is installed." };
2333
+ }
2334
+
2335
+ // ../cli/src/core/readiness.ts
2336
+ var KNOWLEDGE_FILES = [
2337
+ { key: "current_state", path: "knowledge/tech/current-state.md", label: "knowledge/tech/current-state.md", agent: "architecture-agent" },
2338
+ { key: "codebase", path: "knowledge/tech/codebase.md", label: "knowledge/tech/codebase.md", agent: "codebase-agent" },
2339
+ { key: "capabilities", path: "knowledge/product/capabilities.md", label: "knowledge/product/capabilities.md", agent: "capability-agent" },
2340
+ { key: "product", path: "knowledge/product/product.md", label: "knowledge/product/product.md", agent: "product-agent" },
2341
+ { key: "business", path: "knowledge/business/business.md", label: "knowledge/business/business.md", agent: "business-agent" }
2342
+ ];
2259
2343
  function buildReadinessReport(dir, now = /* @__PURE__ */ new Date()) {
2260
2344
  const config = loadConfig(dir);
2345
+ const rec = resolveNextStep(dir, now);
2261
2346
  const stub = (overall2, label, command) => ({
2262
2347
  project_name: config?.project.name ?? "unknown",
2263
2348
  project_type: config?.project.state ?? "unknown",
@@ -2281,9 +2366,10 @@ function buildReadinessReport(dir, now = /* @__PURE__ */ new Date()) {
2281
2366
  resolved_questions: 0,
2282
2367
  deferred_questions: 0
2283
2368
  },
2284
- recommended_next_step: { label, ...command ? { command } : {} }
2369
+ recommended_next_step: { label, ...command ? { command } : {} },
2370
+ nextStepRecommendation: rec
2285
2371
  });
2286
- if (!config) return stub("not-initialized", "Run `kaddo init` to initialize Kaddo.", "kaddo init");
2372
+ if (!config) return stub("not-initialized", rec.label, rec.command);
2287
2373
  if (config.project.state === "new") return stub("not-applicable", "This project uses the standard new-project Kaddo flow.");
2288
2374
  if (config.project.state === "legacy") return stub("legacy-project", "Use the legacy project flow.");
2289
2375
  const scan = exists(join(dir, ".kaddo", "scan.json")) ? "available" : "missing";
@@ -2316,41 +2402,26 @@ function buildReadinessReport(dir, now = /* @__PURE__ */ new Date()) {
2316
2402
  resolved_questions: oq.summary.resolution.resolved,
2317
2403
  deferred_questions: oq.summary.resolution.deferred
2318
2404
  };
2319
- let overall;
2320
- let next;
2321
2405
  const firstWeak = KNOWLEDGE_FILES.find((f) => presence[f.key] !== "useful");
2322
- if (scan === "missing") {
2323
- overall = "initialized";
2324
- next = { label: "Run `kaddo scan` to capture deterministic signals from the existing code.", command: "kaddo scan" };
2325
- } else if (bootstrapBaseline === "incomplete") {
2326
- overall = "bootstrap-incomplete";
2327
- next = { label: "Run `kaddo bootstrap` to create the project knowledge baseline.", command: "kaddo bootstrap" };
2328
- } else if (agents === "missing") {
2329
- overall = "agents-missing";
2330
- next = { label: "Run `kaddo add agents` to install the Kaddo agent prompt packs.", command: "kaddo add agents" };
2331
- } else if (skills === "missing") {
2332
- overall = "skills-missing";
2333
- next = { label: "Run `kaddo add skills` to install reusable Kaddo skills.", command: "kaddo add skills" };
2334
- } else if (understand === "missing") {
2335
- overall = "scanned";
2336
- next = { label: "Run `kaddo understand` to summarize the project context.", command: "kaddo understand" };
2337
- } else if (firstWeak) {
2338
- overall = "knowledge-incomplete";
2339
- next = { label: `Use ${firstWeak.agent} to complete \`${firstWeak.label}\` (it is ${presence[firstWeak.key]}).` };
2340
- } else if (oq.summary.blocking_open > 0) {
2341
- overall = "needs-decisions";
2342
- next = { label: "Resolve, assume or defer the blocking open questions (`kaddo questions`).", command: "kaddo questions" };
2343
- } else if (roadmap !== "has-candidates") {
2344
- overall = "ready-for-roadmap";
2345
- next = { label: "Run `kaddo roadmap` to draft the roadmap from the current knowledge.", command: "kaddo roadmap" };
2346
- } else if (work_items === "none" || work_items === "none-ready") {
2347
- overall = "ready-for-work-item";
2348
- next = { label: "Run `kaddo create --from roadmap` to materialize the first Work Item.", command: "kaddo create --from roadmap" };
2349
- } else {
2350
- overall = "ready-for-implementation";
2351
- next = adapters.length > 0 ? { label: "Implement the ready Work Item and run `kaddo guard`." } : { label: "Run `kaddo adapters list` and install the adapter for your preferred agent.", command: "kaddo adapters list" };
2352
- }
2353
- return { project_name: config.project.name, project_type: config.project.state, overall, signals, recommended_next_step: next };
2406
+ let overall;
2407
+ if (scan === "missing") overall = "initialized";
2408
+ else if (bootstrapBaseline === "incomplete") overall = "bootstrap-incomplete";
2409
+ else if (agents === "missing") overall = "agents-missing";
2410
+ else if (skills === "missing") overall = "skills-missing";
2411
+ else if (understand === "missing") overall = "scanned";
2412
+ else if (firstWeak) overall = "knowledge-incomplete";
2413
+ else if (oq.summary.blocking_open > 0) overall = "needs-decisions";
2414
+ else if (roadmap !== "has-candidates") overall = "ready-for-roadmap";
2415
+ else if (work_items === "none" || work_items === "none-ready") overall = "ready-for-work-item";
2416
+ else overall = "ready-for-implementation";
2417
+ return {
2418
+ project_name: config.project.name,
2419
+ project_type: config.project.state,
2420
+ overall,
2421
+ signals,
2422
+ recommended_next_step: { label: rec.label, ...rec.command ? { command: rec.command } : {} },
2423
+ nextStepRecommendation: rec
2424
+ };
2354
2425
  }
2355
2426
 
2356
2427
  // ../cli/src/core/project-explain.ts
@@ -2542,6 +2613,7 @@ function buildProjectExplanation(dir) {
2542
2613
  "Run `kaddo owners suggest` for Work Items without code ownership."
2543
2614
  );
2544
2615
  }
2616
+ const readiness = buildReadinessReport(dir);
2545
2617
  return {
2546
2618
  project,
2547
2619
  stack,
@@ -2562,7 +2634,8 @@ function buildProjectExplanation(dir) {
2562
2634
  mappedModules,
2563
2635
  missingKnowledge,
2564
2636
  suggestedNextSteps,
2565
- readiness: buildReadinessReport(dir)
2637
+ readiness,
2638
+ nextStepRecommendation: readiness.nextStepRecommendation
2566
2639
  };
2567
2640
  }
2568
2641
  function stateLabel(state) {
@@ -2743,7 +2816,7 @@ function renderExplanationHuman(exp) {
2743
2816
  lines.push("- Reason:");
2744
2817
  for (const r2 of assessment.reasons) lines.push(` - ${r2}`);
2745
2818
  }
2746
- if (assessment.nextStep) lines.push(`- Next step: ${assessment.nextStep}`);
2819
+ lines.push(`- Next step: ${exp.readiness.recommended_next_step.label}`);
2747
2820
  lines.push("");
2748
2821
  if (exp.suggestedNextSteps.length > 0) {
2749
2822
  lines.push("## Suggested Next Steps");
@@ -2765,7 +2838,6 @@ function renderExplanationHuman(exp) {
2765
2838
  lines.push(`- capabilities: ${s.capabilities}`);
2766
2839
  lines.push(`- current-state: ${s.current_state}`);
2767
2840
  lines.push(`- codebase: ${s.codebase}`);
2768
- lines.push(`- capabilities: ${s.capabilities}`);
2769
2841
  lines.push(`- roadmap: ${s.roadmap}`);
2770
2842
  lines.push(`- work-items: ${s.work_items}`);
2771
2843
  lines.push(`- adapters: ${s.adapters.length > 0 ? s.adapters.join(", ") + " installed" : "none installed"}`);
@@ -4120,28 +4192,6 @@ function recommendedAgentsForState(state) {
4120
4192
  return ["capability-agent", "architecture-agent", "roadmap-agent"];
4121
4193
  }
4122
4194
  }
4123
- function nextStepsForState(state) {
4124
- switch (state) {
4125
- case "new":
4126
- return [
4127
- "Use roadmap-agent to shape an initial roadmap.",
4128
- "Use architecture-agent to outline the intended architecture."
4129
- ];
4130
- case "legacy":
4131
- return [
4132
- "Use legacy-agent to surface risks and unknowns before changing code.",
4133
- "Use architecture-agent to reconstruct the current architecture.",
4134
- "Use capability-agent to map existing capabilities."
4135
- ];
4136
- case "pre-ai":
4137
- default:
4138
- return [
4139
- "Use capability-agent to extract system capabilities.",
4140
- "Use architecture-agent to reconstruct the current architecture.",
4141
- "Use roadmap-agent to propose roadmap candidates."
4142
- ];
4143
- }
4144
- }
4145
4195
  var LLM_INSTRUCTIONS = [
4146
4196
  "Use this context pack as the project baseline.",
4147
4197
  "Do not write code yet.",
@@ -4253,6 +4303,12 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
4253
4303
  workItemsMissingOwnership: allWorkItems.length - wiWithOwnership
4254
4304
  }
4255
4305
  });
4306
+ const nextStepRecommendation = resolveNextStep(dir, now);
4307
+ const unifiedPhase = {
4308
+ ...phase,
4309
+ nextStep: nextStepRecommendation.label,
4310
+ recommendedAgents: nextStepRecommendation.agent ? [nextStepRecommendation.agent] : phase.recommendedAgents
4311
+ };
4256
4312
  return {
4257
4313
  version: CONTEXT_PACK_VERSION,
4258
4314
  generatedAt: now.toISOString(),
@@ -4283,7 +4339,8 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
4283
4339
  layers,
4284
4340
  knowledgeQuality,
4285
4341
  roadmap,
4286
- phase,
4342
+ phase: unifiedPhase,
4343
+ nextStepRecommendation,
4287
4344
  deliveryMix,
4288
4345
  external: loadExternalCapsules(dir),
4289
4346
  graph: loadGraphSummary(dir),
@@ -4291,12 +4348,12 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
4291
4348
  skills: discoverInstalledSkills(dir).map((s) => s.id),
4292
4349
  mappedModules,
4293
4350
  missing,
4294
- // VS-052: the handoff is driven by the REAL phase, not project.state, so the pack never
4295
- // contradicts the Current Phase block above it.
4351
+ // VS-052/VS-073.2: the handoff is driven by the unified next step, so the pack never contradicts
4352
+ // the Current Phase block above it.
4296
4353
  handoff: {
4297
- recommendedAgents: phase.recommendedAgents.length > 0 ? phase.recommendedAgents : recommendedAgentsForState(state),
4298
- nextSteps: phase.nextStep ? [phase.nextStep] : nextStepsForState(state),
4299
- instructions: phase.llmInstructions.length > 0 ? phase.llmInstructions : LLM_INSTRUCTIONS,
4354
+ recommendedAgents: unifiedPhase.recommendedAgents.length > 0 ? unifiedPhase.recommendedAgents : recommendedAgentsForState(state),
4355
+ nextSteps: [nextStepRecommendation.label],
4356
+ instructions: unifiedPhase.llmInstructions.length > 0 ? unifiedPhase.llmInstructions : LLM_INSTRUCTIONS,
4300
4357
  operatingRules: OPERATING_RULES
4301
4358
  }
4302
4359
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/mcp",
3
- "version": "3.37.0",
3
+ "version": "3.38.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": {