@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.
- package/dist/index.js +415 -3
- 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");
|