@kaddo/cli 3.5.0 → 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.
Files changed (3) hide show
  1. package/README.md +1 -0
  2. package/dist/index.js +126 -5
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -437,6 +437,7 @@ create --from roadmap → owners → guard → explain`.
437
437
  | v3.3 | Work Item delivery lifecycle: `understand` shows branch → scan → ownership → guard → knowledge → commit for active Work Items (suggestions only; Kaddo never runs git) |
438
438
  | v3.4 | Delivery protocol in the `work-item-agent`: branch first per the Git strategy, commit only with human confirmation (CLI never touches git) |
439
439
  | v3.5 | Knowledge discovery by front-matter type with per-layer maturity (explain/understand/context); context pack carries Operating Rules so agents never commit without confirmation |
440
+ | v3.5.1 | Author attribution & knowledge identity: Kaddo as a practical implementation of KDD for AI-assisted development (docs/README) |
440
441
 
441
442
  **Optional modules (installed with `kaddo add`):**
442
443
 
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
- return splitInitiatives(markdown).flatMap(parseBlock);
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
- lines.push(`- Work items: ${exp.workItems.total}`);
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("The roadmap has Work Item candidates that are not materialized yet.");
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.5.0");
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
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/cli",
3
- "version": "3.5.0",
3
+ "version": "3.6.0",
4
4
  "description": "Knowledge Driven Development toolkit",
5
5
  "license": "MIT",
6
6
  "repository": {