@kaddo/cli 3.43.0 → 3.44.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/README.md +1 -0
- package/dist/index.js +232 -85
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -542,6 +542,7 @@ create --from roadmap → owners → guard → explain`.
|
|
|
542
542
|
| v3.41 | Tech knowledge structure: `knowledge/tech/discovery/` for architecture-notes/decision-candidates (core vs decisions vs discovery); `kaddo adr` reads discovery-first with legacy fallback; `kaddo tech organize` migrates safely; `explain` shows `## Tech Knowledge` |
|
|
543
543
|
| v3.42 | Agent & skill version metadata: installed agents/skills carry a `version:`; `kaddo agents status` / `kaddo skills status` classify up-to-date/outdated/unknown-version/modified/missing; `agents update` / `skills update` refresh outdated safely (never overwrite edits without `--force`); MCP `kaddo://installed-assets` |
|
|
544
544
|
| v3.43 | Capability-grounded roadmap: each `RM-xxx` candidate is graded on related domain / capability / source signals; `roadmap_quality` surfaced in `explain`/`context`/`understand`; `create --from roadmap` preserves `source_roadmap_candidate` + related metadata into the Work Item; roadmap-agent emits grounded fields (never materializes Work Items); MCP `kaddo://roadmap-quality` |
|
|
545
|
+
| v3.44 | Roadmap counting alignment + materialization quality: `explain`/`context` separate **Roadmap initiatives** from **Work Item candidates** (`## Roadmap Status`); two-level `roadmapQuality` (initiatives + work_item_candidates); `create --from roadmap` normalizes metadata — fills `domains` from `related_domain`, splits comma-joined `related_capabilities` into a real list, carries `source_roadmap_initiative`/`source_work_item_candidate`/`source_signals`/`decision_candidates`, improved Source + Context-From-Roadmap body + ADR warning; MCP `kaddo://work-item-candidates` |
|
|
545
546
|
|
|
546
547
|
**Optional modules (installed with `kaddo add`):**
|
|
547
548
|
|
package/dist/index.js
CHANGED
|
@@ -3032,13 +3032,22 @@ that it should be materialized first (\`kaddo adr\` + the adr-writing skill) and
|
|
|
3032
3032
|
without surfacing it. -->
|
|
3033
3033
|
\`\`\`
|
|
3034
3034
|
|
|
3035
|
-
### Preserve roadmap metadata (VS-077)
|
|
3035
|
+
### Preserve roadmap metadata (VS-077 / VS-078)
|
|
3036
3036
|
|
|
3037
|
-
When a Work Item comes from \`kaddo create --from roadmap\`, the front matter already carries
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3037
|
+
When a Work Item comes from \`kaddo create --from roadmap\`, the front matter already carries the trace
|
|
3038
|
+
back to the roadmap. **Keep and refine \u2014 never delete** these fields:
|
|
3039
|
+
|
|
3040
|
+
- \`source_roadmap_initiative\` and \`source_work_item_candidate\` (the RM-xxx initiative and the
|
|
3041
|
+
WI-CANDIDATE-xxx it was materialized from)
|
|
3042
|
+
- \`related_domain\` and \`domains\` (keep them consistent \u2014 \`domains\` must not be empty when
|
|
3043
|
+
\`related_domain\` exists)
|
|
3044
|
+
- \`related_capabilities\` (a real list, one capability per item \u2014 never a single comma-joined string)
|
|
3045
|
+
- \`expected_value\`, \`risks\`, \`dependencies\`
|
|
3046
|
+
- \`source_signals\` (do **not** invent them \u2014 if absent, leave them absent)
|
|
3047
|
+
- \`decision_candidates\` and \`related_decisions\` (when the work depends on a technical decision)
|
|
3048
|
+
|
|
3049
|
+
Do not drop the trace back to the capability domain and source signals. If a Work Item depends on a
|
|
3050
|
+
tech decision candidate with no ADR yet, keep the warning surfaced in the body.
|
|
3042
3051
|
|
|
3043
3052
|
## Where to Save the Result
|
|
3044
3053
|
|
|
@@ -4530,7 +4539,12 @@ function splitInitiatives(markdown) {
|
|
|
4530
4539
|
return blocks;
|
|
4531
4540
|
}
|
|
4532
4541
|
function parseBlock(block) {
|
|
4533
|
-
const meta = {
|
|
4542
|
+
const meta = {
|
|
4543
|
+
relatedCapabilities: [],
|
|
4544
|
+
dependencies: [],
|
|
4545
|
+
openQuestions: [],
|
|
4546
|
+
sourceSignals: []
|
|
4547
|
+
};
|
|
4534
4548
|
const rawCandidates = [];
|
|
4535
4549
|
let listField = null;
|
|
4536
4550
|
let inCandidateSection = false;
|
|
@@ -4580,7 +4594,7 @@ function parseBlock(block) {
|
|
|
4580
4594
|
meta.impact = value || void 0;
|
|
4581
4595
|
} else if (key === "risk") {
|
|
4582
4596
|
meta.risk = value || void 0;
|
|
4583
|
-
} else if (key === "project area / domain" || key === "domain" || key === "project area") {
|
|
4597
|
+
} else if (key === "project area / domain" || key === "domain" || key === "project area" || key === "related domain") {
|
|
4584
4598
|
meta.domain = value || void 0;
|
|
4585
4599
|
} else if (key === "related capabilities") {
|
|
4586
4600
|
listField = "relatedCapabilities";
|
|
@@ -4591,6 +4605,9 @@ function parseBlock(block) {
|
|
|
4591
4605
|
} else if (key === "open questions") {
|
|
4592
4606
|
listField = "openQuestions";
|
|
4593
4607
|
if (value) meta.openQuestions.push(value);
|
|
4608
|
+
} else if (key === "source signals" || key === "source signal") {
|
|
4609
|
+
listField = "sourceSignals";
|
|
4610
|
+
if (value) meta.sourceSignals.push(value);
|
|
4594
4611
|
}
|
|
4595
4612
|
continue;
|
|
4596
4613
|
}
|
|
@@ -4608,6 +4625,7 @@ function parseBlock(block) {
|
|
|
4608
4625
|
}
|
|
4609
4626
|
}
|
|
4610
4627
|
flush();
|
|
4628
|
+
const decisionCandidates = decisionCandidatesFromSignals(meta.sourceSignals);
|
|
4611
4629
|
return rawCandidates.map((c) => ({
|
|
4612
4630
|
...c,
|
|
4613
4631
|
initiative: block.initiative.id || block.initiative.title ? { ...block.initiative } : void 0,
|
|
@@ -4616,9 +4634,23 @@ function parseBlock(block) {
|
|
|
4616
4634
|
impact: meta.impact,
|
|
4617
4635
|
risk: meta.risk,
|
|
4618
4636
|
dependencies: meta.dependencies.length ? [...meta.dependencies] : void 0,
|
|
4619
|
-
openQuestions: meta.openQuestions.length ? [...meta.openQuestions] : void 0
|
|
4637
|
+
openQuestions: meta.openQuestions.length ? [...meta.openQuestions] : void 0,
|
|
4638
|
+
sourceSignals: meta.sourceSignals.length ? [...meta.sourceSignals] : void 0,
|
|
4639
|
+
decisionCandidates: decisionCandidates.length ? decisionCandidates : void 0
|
|
4620
4640
|
}));
|
|
4621
4641
|
}
|
|
4642
|
+
function decisionCandidatesFromSignals(signals) {
|
|
4643
|
+
const out = [];
|
|
4644
|
+
for (const sig of signals) {
|
|
4645
|
+
const m = sig.match(/decision candidate\s*:?\s*(.+)$/i);
|
|
4646
|
+
if (!m) continue;
|
|
4647
|
+
const rest = m[1].trim();
|
|
4648
|
+
const token = rest.match(/\b[A-Z][A-Z0-9_]{2,}\b/);
|
|
4649
|
+
const value = token ? token[0] : rest.replace(/[.。]+$/, "").trim();
|
|
4650
|
+
if (value && !out.includes(value)) out.push(value);
|
|
4651
|
+
}
|
|
4652
|
+
return out;
|
|
4653
|
+
}
|
|
4622
4654
|
var WI_ID_RE = /\bWI-[A-Za-z0-9-]*\d/;
|
|
4623
4655
|
var HEADING_RE = /^#{2,4}\s+(.*)$/;
|
|
4624
4656
|
var FLEX_BULLET_RE = /^\s*[-*]\s+(?:\[[ xX]?\]\s+)?(WI-[A-Za-z0-9-]*\d)\b[\s:.\-–)]*\s*(.*)$/;
|
|
@@ -4700,10 +4732,51 @@ function parseRoadmapCandidates(markdown) {
|
|
|
4700
4732
|
if (strict.length > 0) return strict;
|
|
4701
4733
|
return parseFlexible(markdown);
|
|
4702
4734
|
}
|
|
4735
|
+
function countRoadmapInitiatives(markdown) {
|
|
4736
|
+
if (markdown == null) return 0;
|
|
4737
|
+
let n = 0;
|
|
4738
|
+
for (const line of markdown.split(/\r?\n/)) if (INITIATIVE_RE.test(line)) n++;
|
|
4739
|
+
return n;
|
|
4740
|
+
}
|
|
4703
4741
|
function roadmapStats(markdown, materialized) {
|
|
4704
|
-
if (markdown == null)
|
|
4742
|
+
if (markdown == null)
|
|
4743
|
+
return {
|
|
4744
|
+
present: false,
|
|
4745
|
+
initiatives: 0,
|
|
4746
|
+
work_item_candidates: 0,
|
|
4747
|
+
materialized_work_items: materialized,
|
|
4748
|
+
remaining_work_item_candidates: 0,
|
|
4749
|
+
candidates: 0,
|
|
4750
|
+
materialized,
|
|
4751
|
+
remaining: 0
|
|
4752
|
+
};
|
|
4705
4753
|
const candidates = parseRoadmapCandidates(markdown).length;
|
|
4706
|
-
|
|
4754
|
+
const remaining = Math.max(0, candidates - materialized);
|
|
4755
|
+
return {
|
|
4756
|
+
present: true,
|
|
4757
|
+
initiatives: countRoadmapInitiatives(markdown),
|
|
4758
|
+
work_item_candidates: candidates,
|
|
4759
|
+
materialized_work_items: materialized,
|
|
4760
|
+
remaining_work_item_candidates: remaining,
|
|
4761
|
+
candidates,
|
|
4762
|
+
materialized,
|
|
4763
|
+
remaining
|
|
4764
|
+
};
|
|
4765
|
+
}
|
|
4766
|
+
function normalizeCapabilityList(raw) {
|
|
4767
|
+
if (!raw || raw.length === 0) return [];
|
|
4768
|
+
const out = [];
|
|
4769
|
+
for (const entry of raw) {
|
|
4770
|
+
for (const part of entry.split(/[,;]/)) {
|
|
4771
|
+
const cap = part.replace(/[.。]+\s*$/, "").trim();
|
|
4772
|
+
if (cap && !out.includes(cap)) out.push(cap);
|
|
4773
|
+
}
|
|
4774
|
+
}
|
|
4775
|
+
return out;
|
|
4776
|
+
}
|
|
4777
|
+
function domainsFromRelated(domain) {
|
|
4778
|
+
const d = domain?.trim();
|
|
4779
|
+
return d ? [d] : [];
|
|
4707
4780
|
}
|
|
4708
4781
|
|
|
4709
4782
|
// src/commands/create.ts
|
|
@@ -4999,32 +5072,44 @@ function buildRoadmapFrontMatter(id, type, level, title, candidate, answers) {
|
|
|
4999
5072
|
const today2 = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
5000
5073
|
const summary = (answers.problem?.split(".")[0] ?? candidate.expectedValue ?? title).trim();
|
|
5001
5074
|
const initiative = candidate.initiative?.title ?? candidate.initiative?.id ?? "";
|
|
5075
|
+
const q = (s) => s.replace(/"/g, "'");
|
|
5076
|
+
const domains = domainsFromRelated(candidate.domain);
|
|
5077
|
+
const relatedCapabilities = normalizeCapabilityList(candidate.relatedCapabilities);
|
|
5078
|
+
const risks = candidate.risk ? [candidate.risk] : [];
|
|
5079
|
+
const dependencies = candidate.dependencies ?? [];
|
|
5080
|
+
const sourceSignals = candidate.sourceSignals ?? [];
|
|
5081
|
+
const decisionCandidates = candidate.decisionCandidates ?? [];
|
|
5082
|
+
const yamlList2 = (key, items) => items.length === 0 ? [] : [`${key}:`, ...items.map((i) => ` - "${q(i)}"`)];
|
|
5002
5083
|
const lines = [
|
|
5003
5084
|
"---",
|
|
5004
5085
|
`type: ${type}`,
|
|
5005
5086
|
`id: ${id}`,
|
|
5006
|
-
`title: "${title}"`,
|
|
5087
|
+
`title: "${q(title)}"`,
|
|
5007
5088
|
`knowledge_level: ${level}`,
|
|
5008
5089
|
`status: draft`,
|
|
5009
5090
|
`phase: now`,
|
|
5010
|
-
`initiative: "${initiative
|
|
5011
|
-
|
|
5091
|
+
`initiative: "${q(initiative)}"`,
|
|
5092
|
+
...yamlList2("domains", domains),
|
|
5093
|
+
...domains.length === 0 ? ["domains: []"] : [],
|
|
5012
5094
|
`code: []`,
|
|
5013
5095
|
`created_at: ${today2}`,
|
|
5014
5096
|
`source: roadmap`,
|
|
5015
5097
|
`source_id: ${candidate.id}`,
|
|
5016
5098
|
`source_initiative: ${candidate.initiative?.id ?? "unknown"}`,
|
|
5017
|
-
// Capability-grounded traceability (VS-077):
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
...candidate.expectedValue ? [`expected_value: "${candidate.expectedValue
|
|
5025
|
-
...
|
|
5026
|
-
...
|
|
5027
|
-
|
|
5099
|
+
// Capability-grounded traceability (VS-077 / VS-078): distinguish the parent roadmap initiative
|
|
5100
|
+
// from the specific Work Item candidate it was materialized from.
|
|
5101
|
+
`source_roadmap_initiative: ${candidate.initiative?.id ?? "unknown"}`,
|
|
5102
|
+
`source_work_item_candidate: ${candidate.id}`,
|
|
5103
|
+
...candidate.initiative?.title ? [`source_initiative_title: "${q(candidate.initiative.title)}"`] : [],
|
|
5104
|
+
...candidate.domain ? [`related_domain: "${q(candidate.domain)}"`] : [],
|
|
5105
|
+
...yamlList2("related_capabilities", relatedCapabilities),
|
|
5106
|
+
...candidate.expectedValue ? [`expected_value: "${q(candidate.expectedValue)}"`] : [],
|
|
5107
|
+
...yamlList2("risks", risks),
|
|
5108
|
+
...yamlList2("dependencies", dependencies),
|
|
5109
|
+
...yamlList2("source_signals", sourceSignals),
|
|
5110
|
+
...yamlList2("decision_candidates", decisionCandidates),
|
|
5111
|
+
...decisionCandidates.length > 0 ? ["related_decisions: []"] : [],
|
|
5112
|
+
`summary: "${q(summary)}"`,
|
|
5028
5113
|
"---"
|
|
5029
5114
|
];
|
|
5030
5115
|
return lines.join("\n");
|
|
@@ -5036,14 +5121,24 @@ function buildRoadmapBody(type, level, title, candidate, answers, qualityGate) {
|
|
|
5036
5121
|
sections.push(`> Type: ${type} \xB7 Level: ${level}
|
|
5037
5122
|
`);
|
|
5038
5123
|
const initiativeLabel = candidate.initiative ? `${candidate.initiative.id ?? ""}${candidate.initiative.title ? ` \u2014 ${candidate.initiative.title}` : ""}`.trim() : "unknown";
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
);
|
|
5124
|
+
const relatedCapabilities = normalizeCapabilityList(candidate.relatedCapabilities);
|
|
5125
|
+
const sourceLines = [
|
|
5126
|
+
"## Source\n",
|
|
5127
|
+
`- Source: roadmap`,
|
|
5128
|
+
`- Roadmap Initiative: ${initiativeLabel || "unknown"}`,
|
|
5129
|
+
`- Work Item Candidate: ${candidate.id}`
|
|
5130
|
+
];
|
|
5131
|
+
if (candidate.domain) sourceLines.push(`- Related domain: ${candidate.domain}`);
|
|
5132
|
+
if (relatedCapabilities.length) {
|
|
5133
|
+
sourceLines.push("- Related capabilities:");
|
|
5134
|
+
relatedCapabilities.forEach((c) => sourceLines.push(` - ${c}`));
|
|
5135
|
+
}
|
|
5136
|
+
sections.push(sourceLines.join("\n") + "\n");
|
|
5137
|
+
if (candidate.decisionCandidates?.length) {
|
|
5138
|
+
sections.push(
|
|
5139
|
+
"> Warning: This Work Item is related to technical decision candidates that have not been materialized as ADRs.\n"
|
|
5140
|
+
);
|
|
5141
|
+
}
|
|
5047
5142
|
if (answers.problem) sections.push(`## Problem
|
|
5048
5143
|
|
|
5049
5144
|
${answers.problem}
|
|
@@ -5053,22 +5148,22 @@ ${answers.problem}
|
|
|
5053
5148
|
|
|
5054
5149
|
${expectedValue}
|
|
5055
5150
|
`);
|
|
5056
|
-
const
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
if (candidate.
|
|
5060
|
-
if (candidate.impact) ctx.push(`**Impact:** ${candidate.impact}`);
|
|
5061
|
-
if (candidate.risk) ctx.push(`**Risk:** ${candidate.risk}`);
|
|
5151
|
+
const initiativeRef = candidate.initiative?.id ? `roadmap initiative ${candidate.initiative.id}` : "a roadmap candidate";
|
|
5152
|
+
const ctx = [`This Work Item was materialized from ${initiativeRef}.`, ""];
|
|
5153
|
+
if (candidate.expectedValue) ctx.push(`**Expected value:** ${candidate.expectedValue}`);
|
|
5154
|
+
if (candidate.risk) ctx.push(`**Risks:** ${candidate.risk}`);
|
|
5062
5155
|
if (candidate.dependencies?.length)
|
|
5063
|
-
ctx.push(`**Dependencies:**
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5156
|
+
ctx.push(`**Dependencies:** ${candidate.dependencies.join("; ")}`);
|
|
5157
|
+
if (candidate.sourceSignals?.length) {
|
|
5158
|
+
ctx.push(`**Source signals:**
|
|
5159
|
+
${formatList(candidate.sourceSignals)}`);
|
|
5160
|
+
} else {
|
|
5161
|
+
ctx.push("**Source signals:** _Not provided in roadmap._");
|
|
5162
|
+
}
|
|
5163
|
+
sections.push(`## Context From Roadmap
|
|
5068
5164
|
|
|
5069
|
-
${
|
|
5070
|
-
`
|
|
5071
|
-
);
|
|
5165
|
+
${ctx.join("\n\n")}
|
|
5166
|
+
`);
|
|
5072
5167
|
if (answers.acceptance_criteria) {
|
|
5073
5168
|
const items = answers.acceptance_criteria.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
5074
5169
|
sections.push(`## Acceptance Criteria
|
|
@@ -8431,16 +8526,25 @@ function buildRoadmapQuality(dir) {
|
|
|
8431
8526
|
const items = parseRoadmapCandidateQuality(md);
|
|
8432
8527
|
const count = (pred) => items.filter(pred).length;
|
|
8433
8528
|
const grounded = count((i) => i.grounded);
|
|
8434
|
-
|
|
8435
|
-
|
|
8529
|
+
const initiatives = {
|
|
8530
|
+
total: items.length,
|
|
8436
8531
|
grounded,
|
|
8437
8532
|
with_related_domain: count((i) => i.hasRelatedDomain),
|
|
8438
8533
|
with_related_capability: count((i) => i.hasRelatedCapability),
|
|
8439
8534
|
with_source_signals: count((i) => i.hasSourceSignals),
|
|
8440
|
-
// Only "needs refinement" when there are
|
|
8535
|
+
// Only "needs refinement" when there are initiatives and at least one isn't grounded.
|
|
8441
8536
|
needs_refinement: items.length > 0 && grounded < items.length,
|
|
8442
8537
|
items
|
|
8443
8538
|
};
|
|
8539
|
+
const wiCandidates = md ? parseRoadmapCandidates(md) : [];
|
|
8540
|
+
const wcount = (pred) => wiCandidates.filter(pred).length;
|
|
8541
|
+
const work_item_candidates = {
|
|
8542
|
+
total: wiCandidates.length,
|
|
8543
|
+
with_source_initiative: wcount((c) => Boolean(c.initiative?.id || c.initiative?.title)),
|
|
8544
|
+
with_related_domain: wcount((c) => Boolean(c.domain)),
|
|
8545
|
+
with_related_capability: wcount((c) => Boolean(c.relatedCapabilities?.length))
|
|
8546
|
+
};
|
|
8547
|
+
return { initiatives, work_item_candidates };
|
|
8444
8548
|
}
|
|
8445
8549
|
|
|
8446
8550
|
// src/core/project-explain.ts
|
|
@@ -8723,10 +8827,11 @@ function renderExplanationHuman(exp) {
|
|
|
8723
8827
|
lines.push(`- Delivery: ${ls("Delivery")}`);
|
|
8724
8828
|
lines.push(`- Agents: ${exp.knowledge.hasAgents ? "available" : "missing"}`);
|
|
8725
8829
|
if (exp.roadmap.present) {
|
|
8726
|
-
lines.push(`- Roadmap
|
|
8727
|
-
lines.push(`-
|
|
8728
|
-
|
|
8729
|
-
|
|
8830
|
+
lines.push(`- Roadmap initiatives: ${exp.roadmap.initiatives}`);
|
|
8831
|
+
lines.push(`- Work Item candidates: ${exp.roadmap.work_item_candidates}`);
|
|
8832
|
+
lines.push(`- Materialized Work Items: ${exp.roadmap.materialized_work_items}`);
|
|
8833
|
+
if (exp.roadmap.remaining_work_item_candidates > 0)
|
|
8834
|
+
lines.push(`- Remaining Work Item candidates: ${exp.roadmap.remaining_work_item_candidates}`);
|
|
8730
8835
|
} else {
|
|
8731
8836
|
lines.push(`- Work items: ${exp.workItems.total}`);
|
|
8732
8837
|
}
|
|
@@ -8903,17 +9008,42 @@ function renderExplanationHuman(exp) {
|
|
|
8903
9008
|
lines.push("Tech discovery files are in the legacy `knowledge/tech/` root. Suggested cleanup: run `kaddo tech organize`.");
|
|
8904
9009
|
lines.push("");
|
|
8905
9010
|
}
|
|
9011
|
+
if (exp.roadmap.present) {
|
|
9012
|
+
lines.push("## Roadmap Status");
|
|
9013
|
+
lines.push(`- Initiatives: ${exp.roadmap.initiatives}`);
|
|
9014
|
+
lines.push(`- Work Item candidates: ${exp.roadmap.work_item_candidates}`);
|
|
9015
|
+
lines.push(`- Materialized Work Items: ${exp.roadmap.materialized_work_items}`);
|
|
9016
|
+
lines.push(`- Remaining Work Item candidates: ${exp.roadmap.remaining_work_item_candidates}`);
|
|
9017
|
+
lines.push("");
|
|
9018
|
+
}
|
|
8906
9019
|
const rq = exp.roadmapQuality;
|
|
8907
|
-
|
|
9020
|
+
const rqi = rq.initiatives;
|
|
9021
|
+
const rqw = rq.work_item_candidates;
|
|
9022
|
+
if (rqi.total > 0 || rqw.total > 0) {
|
|
8908
9023
|
lines.push("## Roadmap Quality");
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
|
|
9024
|
+
if (rqi.total > 0) {
|
|
9025
|
+
lines.push("Initiatives:");
|
|
9026
|
+
lines.push(`- Candidates evaluated: ${rqi.total}`);
|
|
9027
|
+
lines.push(`- Grounded: ${rqi.grounded}/${rqi.total}`);
|
|
9028
|
+
lines.push(`- With related domain: ${rqi.with_related_domain}/${rqi.total}`);
|
|
9029
|
+
lines.push(`- With related capability: ${rqi.with_related_capability}/${rqi.total}`);
|
|
9030
|
+
lines.push(`- With source signals: ${rqi.with_source_signals}/${rqi.total}`);
|
|
9031
|
+
}
|
|
9032
|
+
if (rqw.total > 0) {
|
|
8915
9033
|
lines.push("");
|
|
8916
|
-
lines.push("
|
|
9034
|
+
lines.push("Work Item Candidates:");
|
|
9035
|
+
lines.push(`- Candidates: ${rqw.total}`);
|
|
9036
|
+
lines.push(`- With source initiative: ${rqw.with_source_initiative}/${rqw.total}`);
|
|
9037
|
+
lines.push(`- With related domain: ${rqw.with_related_domain}/${rqw.total}`);
|
|
9038
|
+
lines.push(`- With related capability: ${rqw.with_related_capability}/${rqw.total}`);
|
|
9039
|
+
}
|
|
9040
|
+
if (rqi.needs_refinement) {
|
|
9041
|
+
lines.push("");
|
|
9042
|
+
lines.push("Roadmap quality: needs refinement.");
|
|
9043
|
+
lines.push("Suggested: use roadmap-agent to add domain / capability / source signals.");
|
|
9044
|
+
} else if (rqw.total > 0) {
|
|
9045
|
+
lines.push("");
|
|
9046
|
+
lines.push("Work Item candidate quality: good.");
|
|
8917
9047
|
}
|
|
8918
9048
|
lines.push("");
|
|
8919
9049
|
}
|
|
@@ -9434,35 +9564,52 @@ function renderContextPack(pack) {
|
|
|
9434
9564
|
}
|
|
9435
9565
|
parts.push("## Current Knowledge\n");
|
|
9436
9566
|
parts.push((knowledge.summary || "No project knowledge summary found yet.") + "\n");
|
|
9437
|
-
parts.push("## Roadmap\n");
|
|
9567
|
+
parts.push("## Roadmap Status\n");
|
|
9438
9568
|
if (pack.roadmap.present) {
|
|
9439
9569
|
parts.push(
|
|
9440
9570
|
[
|
|
9441
|
-
`-
|
|
9442
|
-
`-
|
|
9443
|
-
`-
|
|
9571
|
+
`- Initiatives: ${pack.roadmap.initiatives}`,
|
|
9572
|
+
`- Work Item candidates: ${pack.roadmap.work_item_candidates}`,
|
|
9573
|
+
`- Materialized Work Items: ${pack.roadmap.materialized_work_items}`,
|
|
9574
|
+
`- Remaining Work Item candidates: ${pack.roadmap.remaining_work_item_candidates}`
|
|
9444
9575
|
].join("\n") + "\n"
|
|
9445
9576
|
);
|
|
9446
|
-
if (pack.roadmap.
|
|
9577
|
+
if (pack.roadmap.remaining_work_item_candidates > 0) {
|
|
9447
9578
|
parts.push(
|
|
9448
|
-
"
|
|
9579
|
+
"Work Item candidates are not yet Work Items. Materialize them with `kaddo create --from roadmap`.\n"
|
|
9449
9580
|
);
|
|
9450
9581
|
}
|
|
9451
9582
|
}
|
|
9452
9583
|
parts.push((knowledge.roadmapSummary || "No roadmap baseline found.") + "\n");
|
|
9453
9584
|
const rq = pack.roadmapQuality;
|
|
9454
|
-
|
|
9585
|
+
const rqi = rq.initiatives;
|
|
9586
|
+
const rqw = rq.work_item_candidates;
|
|
9587
|
+
if (rqi.total > 0 || rqw.total > 0) {
|
|
9455
9588
|
parts.push("## Roadmap Quality\n");
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9589
|
+
if (rqi.total > 0) {
|
|
9590
|
+
parts.push(
|
|
9591
|
+
[
|
|
9592
|
+
"Initiatives:",
|
|
9593
|
+
`- Candidates evaluated: ${rqi.total}`,
|
|
9594
|
+
`- Grounded: ${rqi.grounded}/${rqi.total}`,
|
|
9595
|
+
`- With related domain: ${rqi.with_related_domain}/${rqi.total}`,
|
|
9596
|
+
`- With related capability: ${rqi.with_related_capability}/${rqi.total}`,
|
|
9597
|
+
`- With source signals: ${rqi.with_source_signals}/${rqi.total}`
|
|
9598
|
+
].join("\n") + "\n"
|
|
9599
|
+
);
|
|
9600
|
+
}
|
|
9601
|
+
if (rqw.total > 0) {
|
|
9602
|
+
parts.push(
|
|
9603
|
+
[
|
|
9604
|
+
"Work Item Candidates:",
|
|
9605
|
+
`- Candidates: ${rqw.total}`,
|
|
9606
|
+
`- With source initiative: ${rqw.with_source_initiative}/${rqw.total}`,
|
|
9607
|
+
`- With related domain: ${rqw.with_related_domain}/${rqw.total}`,
|
|
9608
|
+
`- With related capability: ${rqw.with_related_capability}/${rqw.total}`
|
|
9609
|
+
].join("\n") + "\n"
|
|
9610
|
+
);
|
|
9611
|
+
}
|
|
9612
|
+
if (rqi.needs_refinement) {
|
|
9466
9613
|
parts.push(
|
|
9467
9614
|
"Roadmap quality: needs refinement. Use the roadmap-agent to add domain / capability / source signals.\n"
|
|
9468
9615
|
);
|
|
@@ -9900,15 +10047,15 @@ function runUnderstand() {
|
|
|
9900
10047
|
console.log(" \u2192 Use the adr-writing skill to create ADR drafts from `knowledge/tech/decision-candidates.md`");
|
|
9901
10048
|
console.log(" into `knowledge/tech/decisions/` before implementing affected technical Work Items (`kaddo adr`).");
|
|
9902
10049
|
}
|
|
9903
|
-
const
|
|
9904
|
-
if (
|
|
10050
|
+
const rqi = exp.roadmapQuality.initiatives;
|
|
10051
|
+
if (rqi.needs_refinement) {
|
|
9905
10052
|
console.log("");
|
|
9906
|
-
console.log(`Roadmap quality: ${
|
|
9907
|
-
console.log(" \u2192 Use roadmap-agent to ground roadmap
|
|
10053
|
+
console.log(`Roadmap quality: ${rqi.grounded}/${rqi.total} initiatives grounded.`);
|
|
10054
|
+
console.log(" \u2192 Use roadmap-agent to ground roadmap initiatives in capability domains, gaps and source signals");
|
|
9908
10055
|
console.log(" before `kaddo create --from roadmap`.");
|
|
9909
|
-
} else if (
|
|
10056
|
+
} else if (rqi.total > 0 && rqi.grounded === rqi.total) {
|
|
9910
10057
|
console.log("");
|
|
9911
|
-
console.log("Roadmap
|
|
10058
|
+
console.log("Roadmap initiatives are grounded. \u2192 Run `kaddo create --from roadmap` to materialize the first Work Item.");
|
|
9912
10059
|
}
|
|
9913
10060
|
const ia = exp.installedAssets;
|
|
9914
10061
|
const outdatedRecommended = ia.agents.items.filter(
|