@kaddo/mcp 3.45.0 → 3.47.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 +569 -26
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5516,6 +5516,407 @@ function buildRoadmapQuality(dir) {
5516
5516
  return { initiatives, work_item_candidates };
5517
5517
  }
5518
5518
 
5519
+ // ../cli/src/core/project-route.ts
5520
+ function isUseful(q) {
5521
+ return q === "useful";
5522
+ }
5523
+ var enableKaddo = {
5524
+ id: "enable-kaddo",
5525
+ label: "Enable Kaddo",
5526
+ evaluate: (ctx) => ({
5527
+ status: ctx.hasConfig ? "done" : "current",
5528
+ evidence: ctx.hasConfig ? [".kaddo/config.yml"] : void 0,
5529
+ command: ctx.hasConfig ? void 0 : "kaddo init"
5530
+ })
5531
+ };
5532
+ var scanRepository = {
5533
+ id: "scan-repository",
5534
+ label: "Scan repository",
5535
+ evaluate: (ctx) => ({
5536
+ status: ctx.hasScan ? "done" : ctx.hasConfig ? "pending" : "pending",
5537
+ evidence: ctx.hasScan ? [".kaddo/scan.json"] : void 0,
5538
+ command: ctx.hasScan ? void 0 : "kaddo scan"
5539
+ })
5540
+ };
5541
+ var defineBusiness = {
5542
+ id: "define-business",
5543
+ label: "Define business context",
5544
+ evaluate: (ctx) => ({
5545
+ status: isUseful(ctx.qBusiness) ? "done" : ctx.qBusiness === "missing" ? "pending" : "warning",
5546
+ evidence: isUseful(ctx.qBusiness) ? ["knowledge/business/business.md"] : void 0,
5547
+ reason: ctx.qBusiness === "placeholder" ? "Business context is still a bootstrap placeholder." : void 0,
5548
+ agent: isUseful(ctx.qBusiness) ? void 0 : "business-agent"
5549
+ })
5550
+ };
5551
+ var defineProduct = {
5552
+ id: "define-product",
5553
+ label: "Define product context",
5554
+ evaluate: (ctx) => ({
5555
+ status: isUseful(ctx.qProduct) ? "done" : ctx.qProduct === "missing" ? "pending" : "warning",
5556
+ evidence: isUseful(ctx.qProduct) ? ["knowledge/product/product.md"] : void 0,
5557
+ agent: isUseful(ctx.qProduct) ? void 0 : "capability-agent"
5558
+ })
5559
+ };
5560
+ var discoverCapabilities = {
5561
+ id: "discover-capabilities",
5562
+ label: "Discover capabilities",
5563
+ evaluate: (ctx) => ({
5564
+ status: isUseful(ctx.qCapabilities) ? "done" : ctx.qCapabilities === "missing" ? "pending" : "warning",
5565
+ evidence: isUseful(ctx.qCapabilities) ? ["knowledge/product/capabilities.md"] : void 0,
5566
+ agent: isUseful(ctx.qCapabilities) ? void 0 : "capability-agent"
5567
+ })
5568
+ };
5569
+ var describeArchitecture = {
5570
+ id: "describe-architecture",
5571
+ label: "Describe current architecture",
5572
+ evaluate: (ctx) => {
5573
+ const done = isUseful(ctx.qCurrentState) && isUseful(ctx.qCodebase);
5574
+ const evidence = [];
5575
+ if (isUseful(ctx.qCurrentState)) evidence.push("knowledge/tech/current-state.md");
5576
+ if (isUseful(ctx.qCodebase)) evidence.push("knowledge/tech/codebase.md");
5577
+ return {
5578
+ status: done ? "done" : "pending",
5579
+ evidence: evidence.length > 0 ? evidence : void 0,
5580
+ agent: done ? void 0 : "architecture-agent"
5581
+ };
5582
+ }
5583
+ };
5584
+ var captureTechDecisions = {
5585
+ id: "capture-technical-decisions",
5586
+ label: "Capture technical decisions",
5587
+ evaluate: (ctx) => {
5588
+ if (ctx.decisionCandidates === 0 && ctx.totalAdrs === 0) {
5589
+ return { status: "optional", reason: "No decision candidates found." };
5590
+ }
5591
+ if (ctx.totalAdrs > 0) {
5592
+ return { status: "done", evidence: ["knowledge/tech/decisions/"], reason: `${ctx.totalAdrs} ADR(s) exist.` };
5593
+ }
5594
+ return {
5595
+ status: "warning",
5596
+ reason: `${ctx.decisionCandidates} decision candidate(s) exist but no ADRs have been materialized.`,
5597
+ command: "kaddo adr",
5598
+ skill: "adr-writing"
5599
+ };
5600
+ }
5601
+ };
5602
+ var createWorkSource = {
5603
+ id: "create-work-source",
5604
+ label: "Create or connect work source",
5605
+ evaluate: (ctx) => ({
5606
+ status: ctx.hasRoadmap || ctx.totalWorkItems > 0 ? "done" : "pending",
5607
+ evidence: ctx.hasRoadmap ? ["knowledge/delivery/roadmap.md"] : void 0,
5608
+ command: ctx.hasRoadmap ? void 0 : "kaddo roadmap",
5609
+ agent: ctx.hasRoadmap ? void 0 : "roadmap-agent"
5610
+ })
5611
+ };
5612
+ var materializeWorkItem = {
5613
+ id: "materialize-work-item",
5614
+ label: "Materialize first Work Item",
5615
+ evaluate: (ctx) => {
5616
+ if (ctx.totalWorkItems > 0) {
5617
+ return { status: "done", evidence: ["knowledge/delivery/work-items/"] };
5618
+ }
5619
+ if (ctx.roadmapCandidates > 0) {
5620
+ return { status: "current", command: "kaddo create --from roadmap", reason: "Roadmap has candidates but no Work Item exists." };
5621
+ }
5622
+ return { status: "pending" };
5623
+ }
5624
+ };
5625
+ var refineWorkItem = {
5626
+ id: "refine-work-item",
5627
+ label: "Refine Work Item",
5628
+ evaluate: (ctx) => {
5629
+ if (ctx.readyWorkItems > 0 || ctx.inProgressWorkItems > 0) return { status: "done" };
5630
+ if (ctx.draftWorkItems > 0) {
5631
+ return {
5632
+ status: "current",
5633
+ reason: `There ${ctx.draftWorkItems === 1 ? "is" : "are"} ${ctx.draftWorkItems} draft Work Item${ctx.draftWorkItems === 1 ? "" : "s"} and no Work Item is ready.`,
5634
+ agent: "work-item-agent",
5635
+ skill: "work-item-refinement"
5636
+ };
5637
+ }
5638
+ return { status: "pending" };
5639
+ }
5640
+ };
5641
+ var suggestOwnership = {
5642
+ id: "suggest-ownership",
5643
+ label: "Suggest ownership",
5644
+ evaluate: (ctx) => {
5645
+ if (ctx.totalWorkItems === 0) return { status: "pending" };
5646
+ if (ctx.ownershipComplete) return { status: "done" };
5647
+ return {
5648
+ status: "next",
5649
+ reason: `Ownership coverage is ${ctx.ownershipCoverage}.`,
5650
+ command: "kaddo owners suggest"
5651
+ };
5652
+ }
5653
+ };
5654
+ var resolveAdrs = {
5655
+ id: "resolve-adrs",
5656
+ label: "Resolve ADRs if needed",
5657
+ evaluate: (ctx) => {
5658
+ if (ctx.decisionCandidates === 0 && ctx.totalAdrs === 0) return { status: "optional" };
5659
+ if (ctx.totalAdrs > 0) return { status: "done" };
5660
+ return {
5661
+ status: "warning",
5662
+ reason: `${ctx.decisionCandidates} decision candidate(s) without ADRs.`,
5663
+ command: "kaddo adr",
5664
+ skill: "adr-writing"
5665
+ };
5666
+ }
5667
+ };
5668
+ var prepareImplementation = {
5669
+ id: "prepare-implementation",
5670
+ label: "Prepare implementation",
5671
+ evaluate: (ctx) => {
5672
+ if (ctx.inProgressWorkItems > 0 || ctx.completedWorkItems > 0) return { status: "done" };
5673
+ if (ctx.readyWorkItems > 0) {
5674
+ if (ctx.adaptersInstalled === 0) {
5675
+ return { status: "current", reason: "Ready Work Items exist but no adapter is installed.", command: "kaddo adapters list" };
5676
+ }
5677
+ return { status: "current", agent: "implementation-agent" };
5678
+ }
5679
+ return { status: "pending" };
5680
+ }
5681
+ };
5682
+ var runGuard = {
5683
+ id: "run-guard",
5684
+ label: "Run guard",
5685
+ evaluate: (ctx) => {
5686
+ if (ctx.hasGuardHistory) return { status: "done", evidence: [".kaddo/history/guard-runs.jsonl"] };
5687
+ if (ctx.inProgressWorkItems > 0) return { status: "current", command: "kaddo guard" };
5688
+ return { status: "pending" };
5689
+ }
5690
+ };
5691
+ var captureLearning = {
5692
+ id: "capture-learning",
5693
+ label: "Capture learning",
5694
+ evaluate: (ctx) => {
5695
+ if (ctx.completedWorkItems > 0) return { status: "done" };
5696
+ if (ctx.totalWorkItems === 0) return { status: "optional", reason: "Project is still in early discovery." };
5697
+ return { status: "pending" };
5698
+ }
5699
+ };
5700
+ var identifyLegacyModules = {
5701
+ id: "identify-legacy-modules",
5702
+ label: "Identify legacy modules",
5703
+ evaluate: (ctx) => {
5704
+ const hasLegacy = exists(join(ctx.dir, "knowledge/legacy/risks.md"));
5705
+ return {
5706
+ status: hasLegacy ? "done" : "pending",
5707
+ evidence: hasLegacy ? ["knowledge/legacy/risks.md"] : void 0,
5708
+ agent: hasLegacy ? void 0 : "legacy-agent"
5709
+ };
5710
+ }
5711
+ };
5712
+ var identifyRisks = {
5713
+ id: "identify-risks",
5714
+ label: "Identify operational risks",
5715
+ evaluate: (ctx) => {
5716
+ const hasLegacy = exists(join(ctx.dir, "knowledge/legacy/risks.md"));
5717
+ return { status: hasLegacy ? "done" : "pending", agent: hasLegacy ? void 0 : "legacy-agent" };
5718
+ }
5719
+ };
5720
+ var NEW_STEPS = [
5721
+ enableKaddo,
5722
+ defineBusiness,
5723
+ defineProduct,
5724
+ { ...discoverCapabilities, label: "Define initial capabilities" },
5725
+ { ...describeArchitecture, label: "Define initial architecture" },
5726
+ { ...createWorkSource, label: "Create initial work source" },
5727
+ { ...materializeWorkItem, label: "Create first Work Item" },
5728
+ refineWorkItem,
5729
+ suggestOwnership,
5730
+ prepareImplementation,
5731
+ runGuard,
5732
+ captureLearning
5733
+ ];
5734
+ var PRE_AI_STEPS = [
5735
+ enableKaddo,
5736
+ scanRepository,
5737
+ defineBusiness,
5738
+ defineProduct,
5739
+ discoverCapabilities,
5740
+ describeArchitecture,
5741
+ captureTechDecisions,
5742
+ createWorkSource,
5743
+ materializeWorkItem,
5744
+ refineWorkItem,
5745
+ suggestOwnership,
5746
+ resolveAdrs,
5747
+ prepareImplementation,
5748
+ runGuard,
5749
+ captureLearning
5750
+ ];
5751
+ var LEGACY_STEPS = [
5752
+ enableKaddo,
5753
+ scanRepository,
5754
+ identifyLegacyModules,
5755
+ { ...discoverCapabilities, label: "Discover critical capabilities" },
5756
+ describeArchitecture,
5757
+ identifyRisks,
5758
+ captureTechDecisions,
5759
+ { ...createWorkSource, label: "Create modernization candidates" },
5760
+ { ...materializeWorkItem, label: "Materialize safe Work Item" },
5761
+ refineWorkItem,
5762
+ suggestOwnership,
5763
+ resolveAdrs,
5764
+ { ...prepareImplementation, label: "Prepare safe implementation" },
5765
+ runGuard,
5766
+ captureLearning
5767
+ ];
5768
+ function stepsForState(state) {
5769
+ switch (state) {
5770
+ case "new":
5771
+ return NEW_STEPS;
5772
+ case "legacy":
5773
+ return LEGACY_STEPS;
5774
+ case "pre-ai":
5775
+ default:
5776
+ return PRE_AI_STEPS;
5777
+ }
5778
+ }
5779
+ function buildRouteContext(dir) {
5780
+ const config = loadConfig(dir);
5781
+ const hasScan = exists(join(dir, ".kaddo", "scan.json"));
5782
+ const hasInventory = exists(join(dir, "knowledge", "inventory.md"));
5783
+ const qa = (rel) => analyzeKnowledgeArtifact(dir, rel);
5784
+ const wis = discoverWorkItems(dir);
5785
+ const td = buildTechDecisions(dir);
5786
+ const roadmapPath = join(dir, "knowledge/delivery/roadmap.md");
5787
+ const hasRoadmap = exists(roadmapPath);
5788
+ let roadmapMd = null;
5789
+ if (hasRoadmap) {
5790
+ try {
5791
+ roadmapMd = readFile(roadmapPath);
5792
+ } catch {
5793
+ }
5794
+ }
5795
+ const stats = roadmapStats(roadmapMd, wis.length);
5796
+ const byState = (s) => wis.filter((w) => w.lifecycle === s).length;
5797
+ const total = wis.length;
5798
+ const withOwnership = wis.filter((w) => w.codeGlobs.length > 0).length;
5799
+ const adapters = installedAdapters(dir);
5800
+ const nextStep = resolveNextStep(dir);
5801
+ return {
5802
+ dir,
5803
+ hasConfig: config !== null,
5804
+ hasScan,
5805
+ hasInventory,
5806
+ qBusiness: qa("knowledge/business/business.md"),
5807
+ qProduct: qa("knowledge/product/product.md"),
5808
+ qCapabilities: qa("knowledge/product/capabilities.md"),
5809
+ qCurrentState: qa("knowledge/tech/current-state.md"),
5810
+ qCodebase: qa("knowledge/tech/codebase.md"),
5811
+ hasRoadmap,
5812
+ roadmapCandidates: stats.work_item_candidates,
5813
+ totalWorkItems: total,
5814
+ draftWorkItems: byState("draft"),
5815
+ readyWorkItems: byState("ready"),
5816
+ inProgressWorkItems: byState("in-progress"),
5817
+ completedWorkItems: byState("completed"),
5818
+ ownershipCoverage: `${withOwnership}/${total}`,
5819
+ ownershipComplete: total > 0 && withOwnership >= total,
5820
+ decisionCandidates: td.candidates,
5821
+ acceptedAdrs: td.accepted_adrs,
5822
+ draftAdrs: td.draft_adrs,
5823
+ totalAdrs: td.adrs,
5824
+ adaptersInstalled: adapters.length,
5825
+ hasGuardHistory: exists(join(dir, ".kaddo", "history", "guard-runs.jsonl")),
5826
+ nextStepId: mapNextStepId(nextStep.id)
5827
+ };
5828
+ }
5829
+ function mapNextStepId(id) {
5830
+ const MAP = {
5831
+ init: "enable-kaddo",
5832
+ bootstrap: "define-business",
5833
+ "add-agents": "enable-kaddo",
5834
+ "add-skills": "enable-kaddo",
5835
+ scan: "scan-repository",
5836
+ context: "scan-repository",
5837
+ understand: "scan-repository"
5838
+ };
5839
+ return MAP[id] ?? id;
5840
+ }
5841
+ function buildProjectRoute(dir) {
5842
+ const config = loadConfig(dir);
5843
+ const state = config?.project.state ?? "pre-ai";
5844
+ const defs = stepsForState(state);
5845
+ const ctx = buildRouteContext(dir);
5846
+ const steps = defs.map((d) => {
5847
+ const result = d.evaluate(ctx);
5848
+ return { id: d.id, label: d.label, ...result };
5849
+ });
5850
+ for (const s of steps) {
5851
+ if (s.id === ctx.nextStepId && s.status !== "done") {
5852
+ s.status = "current";
5853
+ }
5854
+ }
5855
+ let seenCurrent = false;
5856
+ for (const s of steps) {
5857
+ if (s.status === "current") seenCurrent = true;
5858
+ if (seenCurrent && s.status === "pending") {
5859
+ s.status = "next";
5860
+ break;
5861
+ }
5862
+ }
5863
+ const completed = steps.filter((s) => s.status === "done").length;
5864
+ const total = steps.length;
5865
+ const progressPercent = total > 0 ? Math.round(completed / total * 100) : 0;
5866
+ return {
5867
+ type: state,
5868
+ currentStep: steps.find((s) => s.status === "current")?.id ?? steps.find((s) => s.status !== "done")?.id ?? "complete",
5869
+ completed,
5870
+ total,
5871
+ progressPercent,
5872
+ steps
5873
+ };
5874
+ }
5875
+ var STATUS_MARKER = {
5876
+ done: "[x]",
5877
+ current: "[>]",
5878
+ next: "[ ]",
5879
+ pending: "[ ]",
5880
+ optional: "[o]",
5881
+ blocked: "[!]",
5882
+ warning: "[~]",
5883
+ skipped: "[-]"
5884
+ };
5885
+ function renderRouteMarkdown(route) {
5886
+ const lines = [];
5887
+ lines.push("## Project Route\n");
5888
+ lines.push(`Route: ${route.type}`);
5889
+ lines.push(`Progress: ${route.completed}/${route.total}
5890
+ `);
5891
+ for (const s of route.steps) {
5892
+ lines.push(`- ${STATUS_MARKER[s.status]} ${s.label}`);
5893
+ }
5894
+ lines.push("");
5895
+ return lines.join("\n");
5896
+ }
5897
+ function renderRouteCompact(route) {
5898
+ const lines = [];
5899
+ lines.push(`Route: ${route.type} \xB7 Progress: ${route.completed}/${route.total}
5900
+ `);
5901
+ const current = route.steps.find((s) => s.status === "current");
5902
+ if (current) {
5903
+ const agent = current.agent ? ` \u2014 ${current.agent}` : "";
5904
+ const skill2 = current.skill ? ` / ${current.skill}` : "";
5905
+ lines.push(`Current:
5906
+ - ${current.label}${agent}${skill2}
5907
+ `);
5908
+ }
5909
+ const warnings = route.steps.filter((s) => s.status === "warning");
5910
+ if (warnings.length > 0) {
5911
+ lines.push("Warnings:");
5912
+ for (const w of warnings) {
5913
+ lines.push(`- ${w.label}${w.reason ? ` \u2014 ${w.reason}` : ""}`);
5914
+ }
5915
+ lines.push("");
5916
+ }
5917
+ return lines.join("\n");
5918
+ }
5919
+
5519
5920
  // ../cli/src/core/project-explain.ts
5520
5921
  var ARCH_DIR2 = "knowledge";
5521
5922
  function normalizeTitle(t) {
@@ -5741,7 +6142,8 @@ function buildProjectExplanation(dir) {
5741
6142
  }
5742
6143
  },
5743
6144
  installedAssets: installedAssetsSummary(dir),
5744
- roadmapQuality: buildRoadmapQuality(dir)
6145
+ roadmapQuality: buildRoadmapQuality(dir),
6146
+ projectRoute: buildProjectRoute(dir)
5745
6147
  };
5746
6148
  }
5747
6149
  function stateLabel(state) {
@@ -5916,6 +6318,7 @@ function renderExplanationHuman(exp) {
5916
6318
  lines.push("Review before continuing (non-blocking).");
5917
6319
  lines.push("");
5918
6320
  }
6321
+ lines.push(renderRouteMarkdown(exp.projectRoute));
5919
6322
  const assessment = assessPhase(exp);
5920
6323
  lines.push("## Phase");
5921
6324
  lines.push(`- Phase: ${assessment.phase}`);
@@ -7284,6 +7687,18 @@ var RESOURCES = [
7284
7687
  const deliveryState = { ...buildDeliveryState(root), phase: nextStepRecommendation.phase };
7285
7688
  return [{ uri: "kaddo://next-step", text: JSON.stringify({ nextStepRecommendation, deliveryState }, null, 2), mimeType: "application/json" }];
7286
7689
  }
7690
+ },
7691
+ {
7692
+ uri: "kaddo://project-route",
7693
+ name: "Kaddo project route",
7694
+ description: "Project route progress map \u2014 where the project sits in its lifecycle (new/pre-ai/legacy), completed steps, current step, warnings (VS-080). Read-only.",
7695
+ mimeType: "application/json",
7696
+ read: (root) => {
7697
+ if (!hasKnowledge(root)) {
7698
+ return text("kaddo://project-route", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
7699
+ }
7700
+ return [{ uri: "kaddo://project-route", text: JSON.stringify(buildProjectRoute(root), null, 2), mimeType: "application/json" }];
7701
+ }
7287
7702
  }
7288
7703
  ];
7289
7704
 
@@ -7625,6 +8040,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
7625
8040
  graph: loadGraphSummary(dir),
7626
8041
  graphHints: loadGraphHints(dir),
7627
8042
  skills: discoverInstalledSkills(dir).map((s) => s.id),
8043
+ projectRoute: buildProjectRoute(dir),
7628
8044
  mappedModules,
7629
8045
  missing,
7630
8046
  // VS-052/VS-073.2: the handoff is driven by the unified next step, so the pack never contradicts
@@ -7701,6 +8117,8 @@ function renderContextPack(pack) {
7701
8117
  parts.push(rec.secondary.map((s) => `- ${s.label}`).join("\n") + "\n");
7702
8118
  }
7703
8119
  }
8120
+ parts.push("## Project Route\n");
8121
+ parts.push(renderRouteCompact(pack.projectRoute));
7704
8122
  parts.push("## Knowledge Layers\n");
7705
8123
  parts.push(
7706
8124
  "Project knowledge is organized in four layers: **Business \u2192 Product \u2192 Tech \u2192 Delivery**.\n"
@@ -7947,7 +8365,8 @@ function buildUnderstandPlan(dir, config) {
7947
8365
  name: config.project.name,
7948
8366
  state,
7949
8367
  teamSize: config.team.size,
7950
- structure: config.project.structure
8368
+ structure: config.project.structure,
8369
+ language: "English"
7951
8370
  },
7952
8371
  scanAvailable: exists(join(dir, ".kaddo", "scan.json")),
7953
8372
  contextPackPath: ".kaddo/context-pack.md",
@@ -7966,42 +8385,144 @@ function agentName(file) {
7966
8385
  }
7967
8386
  function renderUnderstand(plan) {
7968
8387
  const { project, steps } = plan;
8388
+ const rec = plan.nextStepRecommendation;
8389
+ const ds = plan.deliveryState;
7969
8390
  const parts = [];
7970
8391
  parts.push("# Kaddo Understand Handoff\n");
7971
8392
  parts.push(
7972
8393
  "> Generated by `kaddo understand`. Kaddo does not call an LLM \u2014 you stay in control of the interpretation.\n"
7973
8394
  );
7974
8395
  parts.push("## Project\n");
7975
- parts.push(
7976
- [
7977
- `- Name: ${project.name}`,
7978
- `- State: ${project.state}`,
7979
- `- Team: ${project.teamSize}`,
7980
- `- Structure: ${project.structure}`
7981
- ].join("\n") + "\n"
7982
- );
7983
- parts.push("## Recommended Agent Flow\n");
7984
- parts.push(`Recommended order for a ${stateLabel2(project.state)} project:
8396
+ const projectLines = [
8397
+ `- Name: ${project.name}`,
8398
+ `- State: ${project.state}`,
8399
+ `- Team: ${project.teamSize}`,
8400
+ `- Structure: ${project.structure}`
8401
+ ];
8402
+ if (project.language) projectLines.push(`- Language: ${project.language}`);
8403
+ parts.push(projectLines.join("\n") + "\n");
8404
+ if (plan.phase && rec) {
8405
+ parts.push("## Current Phase\n");
8406
+ const phaseLines = [`- Phase: ${plan.phase}`];
8407
+ if (rec.agent) phaseLines.push(`- Recommended agent: ${agentName(rec.agent)}`);
8408
+ if (rec.skill) phaseLines.push(`- Recommended skill: ${rec.skill}`);
8409
+ phaseLines.push(`- Next step: ${rec.label}`);
8410
+ if (rec.reason) phaseLines.push(`- Reason: ${rec.reason}`);
8411
+ parts.push(phaseLines.join("\n") + "\n");
8412
+ }
8413
+ if (ds && ds.total_work_items > 0) {
8414
+ parts.push("## Delivery State\n");
8415
+ parts.push(
8416
+ [
8417
+ `- Draft Work Items: ${ds.draft_work_items}`,
8418
+ `- Ready Work Items: ${ds.ready_work_items}`,
8419
+ `- In-progress Work Items: ${ds.in_progress_work_items}`,
8420
+ `- Blocked Work Items: ${ds.blocked_work_items}`,
8421
+ `- Ownership coverage: ${ds.ownership_coverage}`,
8422
+ `- Remaining Work Item candidates: ${ds.remaining_work_item_candidates}`,
8423
+ `- Technical decision candidates: ${ds.decision_candidates}`,
8424
+ `- Accepted ADRs: ${ds.accepted_adrs}`,
8425
+ `- Installed adapters: ${ds.adapters_installed}`
8426
+ ].join("\n") + "\n"
8427
+ );
8428
+ }
8429
+ if (plan.projectRoute) {
8430
+ parts.push("## Project Route\n");
8431
+ parts.push(renderRouteCompact(plan.projectRoute));
8432
+ }
8433
+ if (steps.length > 0) {
8434
+ parts.push("## Recommended Agent Flow\n");
8435
+ parts.push(`Recommended order for a ${stateLabel2(project.state)} project:
7985
8436
  `);
7986
- parts.push(
7987
- steps.map((s, i) => {
7988
- const flag = s.installed ? "" : " _(not installed \u2014 run `kaddo add agents`)_";
7989
- return `${i + 1}. ${agentName(s.agent)} \u2192 \`${s.output}\`${flag}`;
7990
- }).join("\n") + "\n"
7991
- );
8437
+ parts.push(
8438
+ steps.map((s, i) => {
8439
+ const flag = s.installed ? "" : " _(not installed \u2014 run `kaddo add agents`)_";
8440
+ return `${i + 1}. ${agentName(s.agent)} \u2192 \`${s.output}\`${flag}`;
8441
+ }).join("\n") + "\n"
8442
+ );
8443
+ } else if (rec) {
8444
+ parts.push("## Recommended Agent Flow\n");
8445
+ const flowSteps = [];
8446
+ if (rec.agent) flowSteps.push(agentName(rec.agent));
8447
+ if (rec.secondary) {
8448
+ for (const s of rec.secondary) {
8449
+ if (s.agent) flowSteps.push(agentName(s.agent));
8450
+ else if (s.skill) flowSteps.push(`${s.skill} skill`);
8451
+ else if (s.command) flowSteps.push(`\`${s.command}\``);
8452
+ }
8453
+ }
8454
+ if (flowSteps.length > 0) {
8455
+ parts.push(flowSteps.map((f, i) => `${i + 1}. ${f}`).join("\n") + "\n");
8456
+ }
8457
+ }
8458
+ if (rec) {
8459
+ parts.push("## Primary Recommendation\n");
8460
+ const recLines = [`- id: ${rec.id}`];
8461
+ if (rec.agent) recLines.push(`- agent: ${agentName(rec.agent)}`);
8462
+ if (rec.skill) recLines.push(`- skill: ${rec.skill}`);
8463
+ if (rec.command) recLines.push(`- command: \`${rec.command}\``);
8464
+ recLines.push(`- reason: ${rec.reason}`);
8465
+ parts.push(recLines.join("\n") + "\n");
8466
+ }
8467
+ if (rec?.secondary && rec.secondary.length > 0) {
8468
+ parts.push("## Secondary Recommendations\n");
8469
+ parts.push(rec.secondary.map((s, i) => `${i + 1}. ${s.label}`).join("\n") + "\n");
8470
+ }
8471
+ if (plan.activeWorkItems && plan.activeWorkItems.length > 0) {
8472
+ parts.push("## Active Work Items\n");
8473
+ parts.push(
8474
+ plan.activeWorkItems.map((w) => `- ${w.id} [${w.type}] ${w.lifecycle} \u2014 ${w.title}`).join("\n") + "\n"
8475
+ );
8476
+ }
7992
8477
  parts.push("## Context Pack\n");
7993
8478
  const scanNote = plan.scanAvailable ? "" : " (incomplete \u2014 run `kaddo scan` first for a richer baseline)";
7994
8479
  parts.push(`Use \`${plan.contextPackPath}\` as the primary input${scanNote}.
7995
8480
  `);
8481
+ const agentPaths = [];
8482
+ if (plan.recommendedPaths && plan.recommendedPaths.length > 0) {
8483
+ agentPaths.push(...plan.recommendedPaths);
8484
+ } else if (steps.length > 0) {
8485
+ agentPaths.push(...steps.map((s) => agentInstallPath(s.agent)));
8486
+ }
8487
+ if (plan.recommendedSkillPaths && plan.recommendedSkillPaths.length > 0) {
8488
+ agentPaths.push(...plan.recommendedSkillPaths);
8489
+ }
8490
+ agentPaths.push(plan.contextPackPath);
7996
8491
  parts.push("## Agent Prompts\n");
7997
- parts.push(
7998
- steps.map((s) => `- \`${agentInstallPath(s.agent)}\``).join("\n") + "\n"
7999
- );
8000
- parts.push("## Expected Outputs\n");
8001
- parts.push(steps.map((s) => `- \`${s.output}\``).join("\n") + "\n");
8492
+ if (agentPaths.length > 1) {
8493
+ parts.push("Use:\n");
8494
+ parts.push(agentPaths.map((p) => `- \`${p}\``).join("\n") + "\n");
8495
+ } else {
8496
+ parts.push(`- \`${plan.contextPackPath}\`
8497
+ `);
8498
+ }
8499
+ if (steps.length > 0) {
8500
+ parts.push("## Expected Outputs\n");
8501
+ parts.push(steps.map((s) => `- \`${s.output}\``).join("\n") + "\n");
8502
+ } else if (rec) {
8503
+ parts.push("## Expected Outputs\n");
8504
+ const outputs = [];
8505
+ if (rec.target) outputs.push(`- \`${rec.target}\``);
8506
+ if (rec.id === "refine-work-item" || rec.id === "resolve-blocker")
8507
+ outputs.push("- Refined Work Item content.");
8508
+ if (rec.id === "create-work-item")
8509
+ outputs.push("- A new Work Item under `knowledge/delivery/work-items/`.");
8510
+ if (rec.id === "implement")
8511
+ outputs.push("- Implementation plan or code changes guided by the Work Item.");
8512
+ if (rec.id === "guard")
8513
+ outputs.push("- Updated knowledge artifacts reflecting recent code changes.");
8514
+ if (rec.id === "install-adapter")
8515
+ outputs.push("- An adapter configured and injected (`kaddo adapters list`).");
8516
+ if (outputs.length > 0) {
8517
+ parts.push("The LLM should produce:\n");
8518
+ parts.push(outputs.join("\n") + "\n");
8519
+ } else {
8520
+ parts.push("_See the primary recommendation above._\n");
8521
+ }
8522
+ }
8002
8523
  parts.push("## Copy/Paste Instructions\n");
8003
- const first2 = steps[0];
8004
- if (first2) {
8524
+ if (steps.length > 0) {
8525
+ const first2 = steps[0];
8005
8526
  parts.push(
8006
8527
  [
8007
8528
  `Start with **${agentName(first2.agent)}**:`,
@@ -8013,9 +8534,31 @@ function renderUnderstand(plan) {
8013
8534
  `5. Save the result in: \`${first2.output}\``
8014
8535
  ].join("\n") + "\n"
8015
8536
  );
8537
+ } else if (agentPaths.length > 1) {
8538
+ parts.push("Paste the following into your LLM chat:\n");
8539
+ parts.push(agentPaths.map((p, i) => `${i + 1}. \`${p}\``).join("\n") + "\n");
8540
+ if (rec?.agent) {
8541
+ parts.push(`Ask the LLM to follow the ${agentName(rec.agent)} instructions.
8542
+ `);
8543
+ }
8544
+ } else {
8545
+ parts.push(`Paste \`${plan.contextPackPath}\` into your LLM chat.
8546
+ `);
8016
8547
  }
8017
8548
  parts.push("## Next Steps\n");
8018
- if (steps.length > 1) {
8549
+ if (rec) {
8550
+ const nextLines = [];
8551
+ nextLines.push(`1. ${rec.label}`);
8552
+ let n = 2;
8553
+ if (rec.secondary) {
8554
+ for (const s of rec.secondary) {
8555
+ nextLines.push(`${n}. ${s.label}`);
8556
+ n++;
8557
+ }
8558
+ }
8559
+ nextLines.push(`${n}. Re-run \`kaddo explain\`.`);
8560
+ parts.push(nextLines.join("\n") + "\n");
8561
+ } else if (steps.length > 1) {
8019
8562
  parts.push(
8020
8563
  `After saving \`${steps[0].output}\`, continue with **${agentName(steps[1].agent)}** (feed it the context pack plus the artifacts you already produced). Re-run \`kaddo understand\` any time to see this plan again.
8021
8564
  `
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/mcp",
3
- "version": "3.45.0",
3
+ "version": "3.47.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": {