@kaddo/cli 3.5.1 → 3.6.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 +126 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3093,8 +3093,91 @@ function parseBlock(block) {
|
|
|
3093
3093
|
openQuestions: meta.openQuestions.length ? [...meta.openQuestions] : void 0
|
|
3094
3094
|
}));
|
|
3095
3095
|
}
|
|
3096
|
+
var WI_ID_RE = /\bWI-[A-Za-z0-9-]*\d/;
|
|
3097
|
+
var HEADING_RE = /^#{2,4}\s+(.*)$/;
|
|
3098
|
+
var FLEX_BULLET_RE = /^\s*[-*]\s+(?:\[[ xX]?\]\s+)?(WI-[A-Za-z0-9-]*\d)\b[\s:.\-–)]*\s*(.*)$/;
|
|
3099
|
+
var SEPARATOR_CELL_RE = /^:?-{2,}:?$/;
|
|
3100
|
+
function splitRow(line) {
|
|
3101
|
+
return line.replace(/^\s*\|/, "").replace(/\|\s*$/, "").split("|").map((c) => c.trim());
|
|
3102
|
+
}
|
|
3103
|
+
function isSeparatorRow(cells) {
|
|
3104
|
+
return cells.length > 0 && cells.every((c) => SEPARATOR_CELL_RE.test(c) || c === "");
|
|
3105
|
+
}
|
|
3106
|
+
function initiativeFromHeading(text3) {
|
|
3107
|
+
const rm = text3.match(/^(RM-[\w.-]+)\s*[:\-–]?\s*(.*)$/);
|
|
3108
|
+
if (rm) return { id: rm[1], title: rm[2].trim() || void 0 };
|
|
3109
|
+
return { title: text3.trim() || void 0 };
|
|
3110
|
+
}
|
|
3111
|
+
function extractDeps(cell) {
|
|
3112
|
+
if (!cell) return void 0;
|
|
3113
|
+
const ids = cell.match(/WI-[A-Za-z0-9-]*\d/g);
|
|
3114
|
+
return ids && ids.length ? [...new Set(ids)] : void 0;
|
|
3115
|
+
}
|
|
3116
|
+
function parseFlexible(markdown) {
|
|
3117
|
+
const out = [];
|
|
3118
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3119
|
+
let initiative;
|
|
3120
|
+
let cols = null;
|
|
3121
|
+
const push = (id, title, deps, raw) => {
|
|
3122
|
+
if (seen.has(id)) return;
|
|
3123
|
+
seen.add(id);
|
|
3124
|
+
out.push({
|
|
3125
|
+
id,
|
|
3126
|
+
title: title.trim() || id,
|
|
3127
|
+
dependencies: deps,
|
|
3128
|
+
initiative: initiative?.id || initiative?.title ? { ...initiative } : void 0,
|
|
3129
|
+
rawMarkdown: raw.trim()
|
|
3130
|
+
});
|
|
3131
|
+
};
|
|
3132
|
+
for (const line of markdown.split(/\r?\n/)) {
|
|
3133
|
+
const h = line.match(HEADING_RE);
|
|
3134
|
+
if (h) {
|
|
3135
|
+
initiative = initiativeFromHeading(h[1]);
|
|
3136
|
+
cols = null;
|
|
3137
|
+
continue;
|
|
3138
|
+
}
|
|
3139
|
+
if (line.includes("|")) {
|
|
3140
|
+
const cells = splitRow(line);
|
|
3141
|
+
if (isSeparatorRow(cells)) continue;
|
|
3142
|
+
const lower = cells.map((c) => c.toLowerCase());
|
|
3143
|
+
const idIdx = lower.findIndex((c) => c === "id" || c === "wi" || c === "work item id");
|
|
3144
|
+
if (idIdx >= 0 && !WI_ID_RE.test(line)) {
|
|
3145
|
+
cols = {
|
|
3146
|
+
id: idIdx,
|
|
3147
|
+
title: lower.findIndex((c) => /work item|title|item|name|description/.test(c)),
|
|
3148
|
+
deps: lower.findIndex((c) => /depend/.test(c))
|
|
3149
|
+
};
|
|
3150
|
+
continue;
|
|
3151
|
+
}
|
|
3152
|
+
if (WI_ID_RE.test(line)) {
|
|
3153
|
+
let idCell = cols && cols.id >= 0 ? cells[cols.id] : cells.find((c) => /^WI-/.test(c));
|
|
3154
|
+
const idMatch = (idCell ?? line).match(/WI-[A-Za-z0-9-]*\d/);
|
|
3155
|
+
if (!idMatch) continue;
|
|
3156
|
+
const id = idMatch[0];
|
|
3157
|
+
const title = cols && cols.title >= 0 ? cells[cols.title] ?? "" : cells.find((c) => !/^WI-/.test(c) && c) ?? "";
|
|
3158
|
+
const deps = cols && cols.deps >= 0 ? extractDeps(cells[cols.deps]) : void 0;
|
|
3159
|
+
push(id, title, deps, line);
|
|
3160
|
+
continue;
|
|
3161
|
+
}
|
|
3162
|
+
continue;
|
|
3163
|
+
}
|
|
3164
|
+
const b = line.match(FLEX_BULLET_RE);
|
|
3165
|
+
if (b) {
|
|
3166
|
+
push(b[1], b[2] ?? "", void 0, line);
|
|
3167
|
+
continue;
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3170
|
+
return out;
|
|
3171
|
+
}
|
|
3096
3172
|
function parseRoadmapCandidates(markdown) {
|
|
3097
|
-
|
|
3173
|
+
const strict = splitInitiatives(markdown).flatMap(parseBlock);
|
|
3174
|
+
if (strict.length > 0) return strict;
|
|
3175
|
+
return parseFlexible(markdown);
|
|
3176
|
+
}
|
|
3177
|
+
function roadmapStats(markdown, materialized) {
|
|
3178
|
+
if (markdown == null) return { present: false, candidates: 0, materialized, remaining: 0 };
|
|
3179
|
+
const candidates = parseRoadmapCandidates(markdown).length;
|
|
3180
|
+
return { present: true, candidates, materialized, remaining: Math.max(0, candidates - materialized) };
|
|
3098
3181
|
}
|
|
3099
3182
|
|
|
3100
3183
|
// src/commands/create.ts
|
|
@@ -4533,6 +4616,9 @@ function buildProjectExplanation(dir) {
|
|
|
4533
4616
|
workItemsMissingOwnership: items.length - withOwnership
|
|
4534
4617
|
};
|
|
4535
4618
|
const domains = [...new Set(workItemArtifacts.flatMap((a) => a.domains))].filter(Boolean);
|
|
4619
|
+
const roadmapPath = join(dir, ARCH_DIR3, "delivery", "roadmap.md");
|
|
4620
|
+
const roadmapMd = exists(roadmapPath) ? readFile(roadmapPath) : null;
|
|
4621
|
+
const roadmap = roadmapStats(roadmapMd, items.length);
|
|
4536
4622
|
const mappedModules = loadMappedModules(dir);
|
|
4537
4623
|
const missingKnowledge = [];
|
|
4538
4624
|
if (!knowledge.hasScan) missingKnowledge.push("Scan baseline (.kaddo/scan.json)");
|
|
@@ -4560,8 +4646,12 @@ function buildProjectExplanation(dir) {
|
|
|
4560
4646
|
}
|
|
4561
4647
|
if (!knowledge.hasRoadmap) {
|
|
4562
4648
|
suggestedNextSteps.push("Use roadmap-agent to generate knowledge/delivery/roadmap.md.");
|
|
4649
|
+
} else if (roadmap.remaining > 0) {
|
|
4650
|
+
suggestedNextSteps.push(
|
|
4651
|
+
`Materialize ${roadmap.remaining} roadmap candidate(s) with \`kaddo create --from roadmap\`.`
|
|
4652
|
+
);
|
|
4563
4653
|
}
|
|
4564
|
-
if (items.length === 0) {
|
|
4654
|
+
if (items.length === 0 && !roadmap.present) {
|
|
4565
4655
|
suggestedNextSteps.push("Create your first Work Item with `kaddo create`.");
|
|
4566
4656
|
} else if (ownership.workItemsMissingOwnership > 0) {
|
|
4567
4657
|
suggestedNextSteps.push(
|
|
@@ -4576,6 +4666,7 @@ function buildProjectExplanation(dir) {
|
|
|
4576
4666
|
ownership,
|
|
4577
4667
|
domains,
|
|
4578
4668
|
layers,
|
|
4669
|
+
roadmap,
|
|
4579
4670
|
mappedModules,
|
|
4580
4671
|
missingKnowledge,
|
|
4581
4672
|
suggestedNextSteps
|
|
@@ -4619,7 +4710,14 @@ function renderExplanationHuman(exp) {
|
|
|
4619
4710
|
lines.push(`- Tech: ${ls("Tech")}`);
|
|
4620
4711
|
lines.push(`- Delivery: ${ls("Delivery")}`);
|
|
4621
4712
|
lines.push(`- Agents: ${exp.knowledge.hasAgents ? "available" : "missing"}`);
|
|
4622
|
-
|
|
4713
|
+
if (exp.roadmap.present) {
|
|
4714
|
+
lines.push(`- Roadmap candidates: ${exp.roadmap.candidates}`);
|
|
4715
|
+
lines.push(`- Materialized work items: ${exp.roadmap.materialized}`);
|
|
4716
|
+
if (exp.roadmap.remaining > 0)
|
|
4717
|
+
lines.push(`- Remaining candidates: ${exp.roadmap.remaining}`);
|
|
4718
|
+
} else {
|
|
4719
|
+
lines.push(`- Work items: ${exp.workItems.total}`);
|
|
4720
|
+
}
|
|
4623
4721
|
lines.push(
|
|
4624
4722
|
`- Ownership coverage: ${exp.ownership.workItemsWithOwnership}/${exp.ownership.workItemsTotal} work items`
|
|
4625
4723
|
);
|
|
@@ -4973,6 +5071,11 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
|
|
|
4973
5071
|
missing.push("No work items found.");
|
|
4974
5072
|
}
|
|
4975
5073
|
const state = config.project.state;
|
|
5074
|
+
const roadmapPath = join(dir, ARCH_DIR5, "delivery", "roadmap.md");
|
|
5075
|
+
const materialized = allArtifacts.filter(
|
|
5076
|
+
(a) => a.filePath.replace(/\\/g, "/").includes("/delivery/work-items/") && Boolean(a.type)
|
|
5077
|
+
).length;
|
|
5078
|
+
const roadmap = roadmapStats(exists(roadmapPath) ? readFile(roadmapPath) : null, materialized);
|
|
4976
5079
|
const mappedModules = loadMappedModules(dir);
|
|
4977
5080
|
const layers = knowledgeLayers(dir);
|
|
4978
5081
|
return {
|
|
@@ -5002,6 +5105,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
|
|
|
5002
5105
|
artifacts: workItems.filter((a) => a.codeGlobs.length > 0).map(toContextArtifact)
|
|
5003
5106
|
},
|
|
5004
5107
|
layers,
|
|
5108
|
+
roadmap,
|
|
5005
5109
|
mappedModules,
|
|
5006
5110
|
missing,
|
|
5007
5111
|
handoff: {
|
|
@@ -5076,6 +5180,20 @@ function renderContextPack(pack) {
|
|
|
5076
5180
|
parts.push("## Current Knowledge\n");
|
|
5077
5181
|
parts.push((knowledge.summary || "No project knowledge summary found yet.") + "\n");
|
|
5078
5182
|
parts.push("## Roadmap\n");
|
|
5183
|
+
if (pack.roadmap.present) {
|
|
5184
|
+
parts.push(
|
|
5185
|
+
[
|
|
5186
|
+
`- Roadmap candidates: ${pack.roadmap.candidates}`,
|
|
5187
|
+
`- Materialized work items: ${pack.roadmap.materialized}`,
|
|
5188
|
+
`- Remaining candidates: ${pack.roadmap.remaining}`
|
|
5189
|
+
].join("\n") + "\n"
|
|
5190
|
+
);
|
|
5191
|
+
if (pack.roadmap.remaining > 0) {
|
|
5192
|
+
parts.push(
|
|
5193
|
+
"Candidates are not yet Work Items. Materialize them with `kaddo create --from roadmap`.\n"
|
|
5194
|
+
);
|
|
5195
|
+
}
|
|
5196
|
+
}
|
|
5079
5197
|
parts.push((knowledge.roadmapSummary || "No roadmap baseline found.") + "\n");
|
|
5080
5198
|
parts.push("## Existing Work Items\n");
|
|
5081
5199
|
if (knowledge.workItems.length > 0) {
|
|
@@ -5439,8 +5557,11 @@ function runUnderstand() {
|
|
|
5439
5557
|
utilities: ["Use legacy-agent to surface risks and unknowns"]
|
|
5440
5558
|
};
|
|
5441
5559
|
if (roadmapHasUnmaterializedCandidates(dir)) {
|
|
5560
|
+
const { candidates, materialized, remaining } = pack.roadmap;
|
|
5442
5561
|
console.log("");
|
|
5443
|
-
console.log(
|
|
5562
|
+
console.log(
|
|
5563
|
+
`The roadmap has ${remaining} unmaterialized Work Item candidate(s) (${candidates} candidate(s), ${materialized} materialized).`
|
|
5564
|
+
);
|
|
5444
5565
|
console.log(" \u2192 Run `kaddo create --from roadmap`, or use the work-item-agent to");
|
|
5445
5566
|
console.log(" materialize them into knowledge/delivery/work-items/.");
|
|
5446
5567
|
}
|
|
@@ -8145,7 +8266,7 @@ async function runBootstrap(dir = cwd()) {
|
|
|
8145
8266
|
|
|
8146
8267
|
// src/index.ts
|
|
8147
8268
|
var program = new Command();
|
|
8148
|
-
program.name("kaddo").description("Knowledge Driven Development toolkit").version("3.
|
|
8269
|
+
program.name("kaddo").description("Knowledge Driven Development toolkit").version("3.6.0");
|
|
8149
8270
|
program.command("init").description("Initialize Kaddo in the current project").action(async () => {
|
|
8150
8271
|
await runInit();
|
|
8151
8272
|
});
|