@kaddo/cli 3.46.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 +415 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8680,6 +8680,407 @@ function buildRoadmapQuality(dir) {
8680
8680
  return { initiatives, work_item_candidates };
8681
8681
  }
8682
8682
 
8683
+ // src/core/project-route.ts
8684
+ function isUseful(q) {
8685
+ return q === "useful";
8686
+ }
8687
+ var enableKaddo = {
8688
+ id: "enable-kaddo",
8689
+ label: "Enable Kaddo",
8690
+ evaluate: (ctx) => ({
8691
+ status: ctx.hasConfig ? "done" : "current",
8692
+ evidence: ctx.hasConfig ? [".kaddo/config.yml"] : void 0,
8693
+ command: ctx.hasConfig ? void 0 : "kaddo init"
8694
+ })
8695
+ };
8696
+ var scanRepository = {
8697
+ id: "scan-repository",
8698
+ label: "Scan repository",
8699
+ evaluate: (ctx) => ({
8700
+ status: ctx.hasScan ? "done" : ctx.hasConfig ? "pending" : "pending",
8701
+ evidence: ctx.hasScan ? [".kaddo/scan.json"] : void 0,
8702
+ command: ctx.hasScan ? void 0 : "kaddo scan"
8703
+ })
8704
+ };
8705
+ var defineBusiness = {
8706
+ id: "define-business",
8707
+ label: "Define business context",
8708
+ evaluate: (ctx) => ({
8709
+ status: isUseful(ctx.qBusiness) ? "done" : ctx.qBusiness === "missing" ? "pending" : "warning",
8710
+ evidence: isUseful(ctx.qBusiness) ? ["knowledge/business/business.md"] : void 0,
8711
+ reason: ctx.qBusiness === "placeholder" ? "Business context is still a bootstrap placeholder." : void 0,
8712
+ agent: isUseful(ctx.qBusiness) ? void 0 : "business-agent"
8713
+ })
8714
+ };
8715
+ var defineProduct = {
8716
+ id: "define-product",
8717
+ label: "Define product context",
8718
+ evaluate: (ctx) => ({
8719
+ status: isUseful(ctx.qProduct) ? "done" : ctx.qProduct === "missing" ? "pending" : "warning",
8720
+ evidence: isUseful(ctx.qProduct) ? ["knowledge/product/product.md"] : void 0,
8721
+ agent: isUseful(ctx.qProduct) ? void 0 : "capability-agent"
8722
+ })
8723
+ };
8724
+ var discoverCapabilities = {
8725
+ id: "discover-capabilities",
8726
+ label: "Discover capabilities",
8727
+ evaluate: (ctx) => ({
8728
+ status: isUseful(ctx.qCapabilities) ? "done" : ctx.qCapabilities === "missing" ? "pending" : "warning",
8729
+ evidence: isUseful(ctx.qCapabilities) ? ["knowledge/product/capabilities.md"] : void 0,
8730
+ agent: isUseful(ctx.qCapabilities) ? void 0 : "capability-agent"
8731
+ })
8732
+ };
8733
+ var describeArchitecture = {
8734
+ id: "describe-architecture",
8735
+ label: "Describe current architecture",
8736
+ evaluate: (ctx) => {
8737
+ const done = isUseful(ctx.qCurrentState) && isUseful(ctx.qCodebase);
8738
+ const evidence = [];
8739
+ if (isUseful(ctx.qCurrentState)) evidence.push("knowledge/tech/current-state.md");
8740
+ if (isUseful(ctx.qCodebase)) evidence.push("knowledge/tech/codebase.md");
8741
+ return {
8742
+ status: done ? "done" : "pending",
8743
+ evidence: evidence.length > 0 ? evidence : void 0,
8744
+ agent: done ? void 0 : "architecture-agent"
8745
+ };
8746
+ }
8747
+ };
8748
+ var captureTechDecisions = {
8749
+ id: "capture-technical-decisions",
8750
+ label: "Capture technical decisions",
8751
+ evaluate: (ctx) => {
8752
+ if (ctx.decisionCandidates === 0 && ctx.totalAdrs === 0) {
8753
+ return { status: "optional", reason: "No decision candidates found." };
8754
+ }
8755
+ if (ctx.totalAdrs > 0) {
8756
+ return { status: "done", evidence: ["knowledge/tech/decisions/"], reason: `${ctx.totalAdrs} ADR(s) exist.` };
8757
+ }
8758
+ return {
8759
+ status: "warning",
8760
+ reason: `${ctx.decisionCandidates} decision candidate(s) exist but no ADRs have been materialized.`,
8761
+ command: "kaddo adr",
8762
+ skill: "adr-writing"
8763
+ };
8764
+ }
8765
+ };
8766
+ var createWorkSource = {
8767
+ id: "create-work-source",
8768
+ label: "Create or connect work source",
8769
+ evaluate: (ctx) => ({
8770
+ status: ctx.hasRoadmap || ctx.totalWorkItems > 0 ? "done" : "pending",
8771
+ evidence: ctx.hasRoadmap ? ["knowledge/delivery/roadmap.md"] : void 0,
8772
+ command: ctx.hasRoadmap ? void 0 : "kaddo roadmap",
8773
+ agent: ctx.hasRoadmap ? void 0 : "roadmap-agent"
8774
+ })
8775
+ };
8776
+ var materializeWorkItem = {
8777
+ id: "materialize-work-item",
8778
+ label: "Materialize first Work Item",
8779
+ evaluate: (ctx) => {
8780
+ if (ctx.totalWorkItems > 0) {
8781
+ return { status: "done", evidence: ["knowledge/delivery/work-items/"] };
8782
+ }
8783
+ if (ctx.roadmapCandidates > 0) {
8784
+ return { status: "current", command: "kaddo create --from roadmap", reason: "Roadmap has candidates but no Work Item exists." };
8785
+ }
8786
+ return { status: "pending" };
8787
+ }
8788
+ };
8789
+ var refineWorkItem = {
8790
+ id: "refine-work-item",
8791
+ label: "Refine Work Item",
8792
+ evaluate: (ctx) => {
8793
+ if (ctx.readyWorkItems > 0 || ctx.inProgressWorkItems > 0) return { status: "done" };
8794
+ if (ctx.draftWorkItems > 0) {
8795
+ return {
8796
+ status: "current",
8797
+ reason: `There ${ctx.draftWorkItems === 1 ? "is" : "are"} ${ctx.draftWorkItems} draft Work Item${ctx.draftWorkItems === 1 ? "" : "s"} and no Work Item is ready.`,
8798
+ agent: "work-item-agent",
8799
+ skill: "work-item-refinement"
8800
+ };
8801
+ }
8802
+ return { status: "pending" };
8803
+ }
8804
+ };
8805
+ var suggestOwnership = {
8806
+ id: "suggest-ownership",
8807
+ label: "Suggest ownership",
8808
+ evaluate: (ctx) => {
8809
+ if (ctx.totalWorkItems === 0) return { status: "pending" };
8810
+ if (ctx.ownershipComplete) return { status: "done" };
8811
+ return {
8812
+ status: "next",
8813
+ reason: `Ownership coverage is ${ctx.ownershipCoverage}.`,
8814
+ command: "kaddo owners suggest"
8815
+ };
8816
+ }
8817
+ };
8818
+ var resolveAdrs = {
8819
+ id: "resolve-adrs",
8820
+ label: "Resolve ADRs if needed",
8821
+ evaluate: (ctx) => {
8822
+ if (ctx.decisionCandidates === 0 && ctx.totalAdrs === 0) return { status: "optional" };
8823
+ if (ctx.totalAdrs > 0) return { status: "done" };
8824
+ return {
8825
+ status: "warning",
8826
+ reason: `${ctx.decisionCandidates} decision candidate(s) without ADRs.`,
8827
+ command: "kaddo adr",
8828
+ skill: "adr-writing"
8829
+ };
8830
+ }
8831
+ };
8832
+ var prepareImplementation = {
8833
+ id: "prepare-implementation",
8834
+ label: "Prepare implementation",
8835
+ evaluate: (ctx) => {
8836
+ if (ctx.inProgressWorkItems > 0 || ctx.completedWorkItems > 0) return { status: "done" };
8837
+ if (ctx.readyWorkItems > 0) {
8838
+ if (ctx.adaptersInstalled === 0) {
8839
+ return { status: "current", reason: "Ready Work Items exist but no adapter is installed.", command: "kaddo adapters list" };
8840
+ }
8841
+ return { status: "current", agent: "implementation-agent" };
8842
+ }
8843
+ return { status: "pending" };
8844
+ }
8845
+ };
8846
+ var runGuard2 = {
8847
+ id: "run-guard",
8848
+ label: "Run guard",
8849
+ evaluate: (ctx) => {
8850
+ if (ctx.hasGuardHistory) return { status: "done", evidence: [".kaddo/history/guard-runs.jsonl"] };
8851
+ if (ctx.inProgressWorkItems > 0) return { status: "current", command: "kaddo guard" };
8852
+ return { status: "pending" };
8853
+ }
8854
+ };
8855
+ var captureLearning = {
8856
+ id: "capture-learning",
8857
+ label: "Capture learning",
8858
+ evaluate: (ctx) => {
8859
+ if (ctx.completedWorkItems > 0) return { status: "done" };
8860
+ if (ctx.totalWorkItems === 0) return { status: "optional", reason: "Project is still in early discovery." };
8861
+ return { status: "pending" };
8862
+ }
8863
+ };
8864
+ var identifyLegacyModules = {
8865
+ id: "identify-legacy-modules",
8866
+ label: "Identify legacy modules",
8867
+ evaluate: (ctx) => {
8868
+ const hasLegacy = exists(join(ctx.dir, "knowledge/legacy/risks.md"));
8869
+ return {
8870
+ status: hasLegacy ? "done" : "pending",
8871
+ evidence: hasLegacy ? ["knowledge/legacy/risks.md"] : void 0,
8872
+ agent: hasLegacy ? void 0 : "legacy-agent"
8873
+ };
8874
+ }
8875
+ };
8876
+ var identifyRisks = {
8877
+ id: "identify-risks",
8878
+ label: "Identify operational risks",
8879
+ evaluate: (ctx) => {
8880
+ const hasLegacy = exists(join(ctx.dir, "knowledge/legacy/risks.md"));
8881
+ return { status: hasLegacy ? "done" : "pending", agent: hasLegacy ? void 0 : "legacy-agent" };
8882
+ }
8883
+ };
8884
+ var NEW_STEPS = [
8885
+ enableKaddo,
8886
+ defineBusiness,
8887
+ defineProduct,
8888
+ { ...discoverCapabilities, label: "Define initial capabilities" },
8889
+ { ...describeArchitecture, label: "Define initial architecture" },
8890
+ { ...createWorkSource, label: "Create initial work source" },
8891
+ { ...materializeWorkItem, label: "Create first Work Item" },
8892
+ refineWorkItem,
8893
+ suggestOwnership,
8894
+ prepareImplementation,
8895
+ runGuard2,
8896
+ captureLearning
8897
+ ];
8898
+ var PRE_AI_STEPS = [
8899
+ enableKaddo,
8900
+ scanRepository,
8901
+ defineBusiness,
8902
+ defineProduct,
8903
+ discoverCapabilities,
8904
+ describeArchitecture,
8905
+ captureTechDecisions,
8906
+ createWorkSource,
8907
+ materializeWorkItem,
8908
+ refineWorkItem,
8909
+ suggestOwnership,
8910
+ resolveAdrs,
8911
+ prepareImplementation,
8912
+ runGuard2,
8913
+ captureLearning
8914
+ ];
8915
+ var LEGACY_STEPS = [
8916
+ enableKaddo,
8917
+ scanRepository,
8918
+ identifyLegacyModules,
8919
+ { ...discoverCapabilities, label: "Discover critical capabilities" },
8920
+ describeArchitecture,
8921
+ identifyRisks,
8922
+ captureTechDecisions,
8923
+ { ...createWorkSource, label: "Create modernization candidates" },
8924
+ { ...materializeWorkItem, label: "Materialize safe Work Item" },
8925
+ refineWorkItem,
8926
+ suggestOwnership,
8927
+ resolveAdrs,
8928
+ { ...prepareImplementation, label: "Prepare safe implementation" },
8929
+ runGuard2,
8930
+ captureLearning
8931
+ ];
8932
+ function stepsForState(state) {
8933
+ switch (state) {
8934
+ case "new":
8935
+ return NEW_STEPS;
8936
+ case "legacy":
8937
+ return LEGACY_STEPS;
8938
+ case "pre-ai":
8939
+ default:
8940
+ return PRE_AI_STEPS;
8941
+ }
8942
+ }
8943
+ function buildRouteContext(dir) {
8944
+ const config = loadConfig(dir);
8945
+ const hasScan = exists(join(dir, ".kaddo", "scan.json"));
8946
+ const hasInventory = exists(join(dir, "knowledge", "inventory.md"));
8947
+ const qa = (rel) => analyzeKnowledgeArtifact(dir, rel);
8948
+ const wis = discoverWorkItems(dir);
8949
+ const td = buildTechDecisions(dir);
8950
+ const roadmapPath = join(dir, "knowledge/delivery/roadmap.md");
8951
+ const hasRoadmap = exists(roadmapPath);
8952
+ let roadmapMd = null;
8953
+ if (hasRoadmap) {
8954
+ try {
8955
+ roadmapMd = readFile(roadmapPath);
8956
+ } catch {
8957
+ }
8958
+ }
8959
+ const stats = roadmapStats(roadmapMd, wis.length);
8960
+ const byState = (s) => wis.filter((w) => w.lifecycle === s).length;
8961
+ const total = wis.length;
8962
+ const withOwnership = wis.filter((w) => w.codeGlobs.length > 0).length;
8963
+ const adapters = installedAdapters(dir);
8964
+ const nextStep = resolveNextStep(dir);
8965
+ return {
8966
+ dir,
8967
+ hasConfig: config !== null,
8968
+ hasScan,
8969
+ hasInventory,
8970
+ qBusiness: qa("knowledge/business/business.md"),
8971
+ qProduct: qa("knowledge/product/product.md"),
8972
+ qCapabilities: qa("knowledge/product/capabilities.md"),
8973
+ qCurrentState: qa("knowledge/tech/current-state.md"),
8974
+ qCodebase: qa("knowledge/tech/codebase.md"),
8975
+ hasRoadmap,
8976
+ roadmapCandidates: stats.work_item_candidates,
8977
+ totalWorkItems: total,
8978
+ draftWorkItems: byState("draft"),
8979
+ readyWorkItems: byState("ready"),
8980
+ inProgressWorkItems: byState("in-progress"),
8981
+ completedWorkItems: byState("completed"),
8982
+ ownershipCoverage: `${withOwnership}/${total}`,
8983
+ ownershipComplete: total > 0 && withOwnership >= total,
8984
+ decisionCandidates: td.candidates,
8985
+ acceptedAdrs: td.accepted_adrs,
8986
+ draftAdrs: td.draft_adrs,
8987
+ totalAdrs: td.adrs,
8988
+ adaptersInstalled: adapters.length,
8989
+ hasGuardHistory: exists(join(dir, ".kaddo", "history", "guard-runs.jsonl")),
8990
+ nextStepId: mapNextStepId(nextStep.id)
8991
+ };
8992
+ }
8993
+ function mapNextStepId(id) {
8994
+ const MAP = {
8995
+ init: "enable-kaddo",
8996
+ bootstrap: "define-business",
8997
+ "add-agents": "enable-kaddo",
8998
+ "add-skills": "enable-kaddo",
8999
+ scan: "scan-repository",
9000
+ context: "scan-repository",
9001
+ understand: "scan-repository"
9002
+ };
9003
+ return MAP[id] ?? id;
9004
+ }
9005
+ function buildProjectRoute(dir) {
9006
+ const config = loadConfig(dir);
9007
+ const state = config?.project.state ?? "pre-ai";
9008
+ const defs = stepsForState(state);
9009
+ const ctx = buildRouteContext(dir);
9010
+ const steps = defs.map((d) => {
9011
+ const result = d.evaluate(ctx);
9012
+ return { id: d.id, label: d.label, ...result };
9013
+ });
9014
+ for (const s of steps) {
9015
+ if (s.id === ctx.nextStepId && s.status !== "done") {
9016
+ s.status = "current";
9017
+ }
9018
+ }
9019
+ let seenCurrent = false;
9020
+ for (const s of steps) {
9021
+ if (s.status === "current") seenCurrent = true;
9022
+ if (seenCurrent && s.status === "pending") {
9023
+ s.status = "next";
9024
+ break;
9025
+ }
9026
+ }
9027
+ const completed = steps.filter((s) => s.status === "done").length;
9028
+ const total = steps.length;
9029
+ const progressPercent = total > 0 ? Math.round(completed / total * 100) : 0;
9030
+ return {
9031
+ type: state,
9032
+ currentStep: steps.find((s) => s.status === "current")?.id ?? steps.find((s) => s.status !== "done")?.id ?? "complete",
9033
+ completed,
9034
+ total,
9035
+ progressPercent,
9036
+ steps
9037
+ };
9038
+ }
9039
+ var STATUS_MARKER = {
9040
+ done: "[x]",
9041
+ current: "[>]",
9042
+ next: "[ ]",
9043
+ pending: "[ ]",
9044
+ optional: "[o]",
9045
+ blocked: "[!]",
9046
+ warning: "[~]",
9047
+ skipped: "[-]"
9048
+ };
9049
+ function renderRouteMarkdown(route) {
9050
+ const lines = [];
9051
+ lines.push("## Project Route\n");
9052
+ lines.push(`Route: ${route.type}`);
9053
+ lines.push(`Progress: ${route.completed}/${route.total}
9054
+ `);
9055
+ for (const s of route.steps) {
9056
+ lines.push(`- ${STATUS_MARKER[s.status]} ${s.label}`);
9057
+ }
9058
+ lines.push("");
9059
+ return lines.join("\n");
9060
+ }
9061
+ function renderRouteCompact(route) {
9062
+ const lines = [];
9063
+ lines.push(`Route: ${route.type} \xB7 Progress: ${route.completed}/${route.total}
9064
+ `);
9065
+ const current = route.steps.find((s) => s.status === "current");
9066
+ if (current) {
9067
+ const agent = current.agent ? ` \u2014 ${current.agent}` : "";
9068
+ const skill2 = current.skill ? ` / ${current.skill}` : "";
9069
+ lines.push(`Current:
9070
+ - ${current.label}${agent}${skill2}
9071
+ `);
9072
+ }
9073
+ const warnings = route.steps.filter((s) => s.status === "warning");
9074
+ if (warnings.length > 0) {
9075
+ lines.push("Warnings:");
9076
+ for (const w of warnings) {
9077
+ lines.push(`- ${w.label}${w.reason ? ` \u2014 ${w.reason}` : ""}`);
9078
+ }
9079
+ lines.push("");
9080
+ }
9081
+ return lines.join("\n");
9082
+ }
9083
+
8683
9084
  // src/core/project-explain.ts
8684
9085
  var ARCH_DIR4 = "knowledge";
8685
9086
  function normalizeTitle(t) {
@@ -8905,7 +9306,8 @@ function buildProjectExplanation(dir) {
8905
9306
  }
8906
9307
  },
8907
9308
  installedAssets: installedAssetsSummary(dir),
8908
- roadmapQuality: buildRoadmapQuality(dir)
9309
+ roadmapQuality: buildRoadmapQuality(dir),
9310
+ projectRoute: buildProjectRoute(dir)
8909
9311
  };
8910
9312
  }
8911
9313
  function stateLabel(state) {
@@ -9080,6 +9482,7 @@ function renderExplanationHuman(exp) {
9080
9482
  lines.push("Review before continuing (non-blocking).");
9081
9483
  lines.push("");
9082
9484
  }
9485
+ lines.push(renderRouteMarkdown(exp.projectRoute));
9083
9486
  const assessment = assessPhase(exp);
9084
9487
  lines.push("## Phase");
9085
9488
  lines.push(`- Phase: ${assessment.phase}`);
@@ -9614,6 +10017,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
9614
10017
  graph: loadGraphSummary(dir),
9615
10018
  graphHints: loadGraphHints(dir),
9616
10019
  skills: discoverInstalledSkills(dir).map((s) => s.id),
10020
+ projectRoute: buildProjectRoute(dir),
9617
10021
  mappedModules,
9618
10022
  missing,
9619
10023
  // VS-052/VS-073.2: the handoff is driven by the unified next step, so the pack never contradicts
@@ -9690,6 +10094,8 @@ function renderContextPack(pack) {
9690
10094
  parts.push(rec.secondary.map((s) => `- ${s.label}`).join("\n") + "\n");
9691
10095
  }
9692
10096
  }
10097
+ parts.push("## Project Route\n");
10098
+ parts.push(renderRouteCompact(pack.projectRoute));
9693
10099
  parts.push("## Knowledge Layers\n");
9694
10100
  parts.push(
9695
10101
  "Project knowledge is organized in four layers: **Business \u2192 Product \u2192 Tech \u2192 Delivery**.\n"
@@ -9994,7 +10400,8 @@ function enrichUnderstandPlan(plan, opts) {
9994
10400
  deliveryState: opts.deliveryState,
9995
10401
  activeWorkItems: opts.activeWorkItems,
9996
10402
  recommendedPaths: opts.recommendedPaths,
9997
- recommendedSkillPaths: opts.recommendedSkillPaths
10403
+ recommendedSkillPaths: opts.recommendedSkillPaths,
10404
+ projectRoute: opts.projectRoute
9998
10405
  };
9999
10406
  }
10000
10407
 
@@ -10048,6 +10455,10 @@ function renderUnderstand(plan) {
10048
10455
  ].join("\n") + "\n"
10049
10456
  );
10050
10457
  }
10458
+ if (plan.projectRoute) {
10459
+ parts.push("## Project Route\n");
10460
+ parts.push(renderRouteCompact(plan.projectRoute));
10461
+ }
10051
10462
  if (steps.length > 0) {
10052
10463
  parts.push("## Recommended Agent Flow\n");
10053
10464
  parts.push(`Recommended order for a ${stateLabel2(project.state)} project:
@@ -10433,7 +10844,8 @@ function runUnderstand() {
10433
10844
  activeWorkItems: activeWis,
10434
10845
  recommendedPaths,
10435
10846
  recommendedSkillPaths,
10436
- language: languageLabel(projectLanguage(config))
10847
+ language: languageLabel(projectLanguage(config)),
10848
+ projectRoute: buildProjectRoute(dir)
10437
10849
  });
10438
10850
  writeFile(join(dir, ".kaddo", "understand.md"), renderUnderstand(enrichedPlan));
10439
10851
  log2.success("Wrote .kaddo/understand.md");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/cli",
3
- "version": "3.46.0",
3
+ "version": "3.47.0",
4
4
  "description": "Knowledge Driven Development toolkit",
5
5
  "license": "MIT",
6
6
  "repository": {