@kaddo/cli 3.9.0 → 3.9.1

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 +142 -122
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4044,9 +4044,11 @@ function parseArtifact(filePath, raw) {
4044
4044
  knowledgeLevel: String(data.knowledge_level ?? ""),
4045
4045
  codeGlobs: globs,
4046
4046
  domains: Array.isArray(data.domains) ? data.domains : [],
4047
+ capabilities: Array.isArray(data.capabilities) ? data.capabilities.map(String).filter(Boolean) : [],
4047
4048
  status: String(data.status ?? ""),
4048
4049
  phase: String(data.phase ?? ""),
4049
- initiative: String(data.initiative ?? data.source_initiative ?? "")
4050
+ initiative: String(data.initiative ?? data.source_initiative ?? ""),
4051
+ source: data.source ? String(data.source) : ""
4050
4052
  };
4051
4053
  } catch {
4052
4054
  return null;
@@ -4071,6 +4073,94 @@ function readArtifacts(archDir) {
4071
4073
  return artifacts;
4072
4074
  }
4073
4075
 
4076
+ // src/core/lifecycle.ts
4077
+ var LIFECYCLE_STATES = [
4078
+ "draft",
4079
+ "ready",
4080
+ "in-progress",
4081
+ "blocked",
4082
+ "completed",
4083
+ "archived"
4084
+ ];
4085
+ var ACTIVE_STATES = ["draft", "ready", "in-progress", "blocked"];
4086
+ var LEGACY_STATUS_MAP = {
4087
+ done: "completed",
4088
+ cancelled: "archived",
4089
+ canceled: "archived",
4090
+ "in-progress": "in-progress"
4091
+ };
4092
+ var STATE_SET = new Set(LIFECYCLE_STATES);
4093
+ function isLifecycleState(s) {
4094
+ return STATE_SET.has(s);
4095
+ }
4096
+ function isActiveState(s) {
4097
+ return ACTIVE_STATES.includes(s);
4098
+ }
4099
+ function lifecycleFolderOf(filePath) {
4100
+ const p2 = filePath.replace(/\\/g, "/");
4101
+ const m = p2.match(/\/delivery\/work-items\/([^/]+)\//);
4102
+ if (m && isLifecycleState(m[1])) return m[1];
4103
+ return null;
4104
+ }
4105
+ function lifecycleStateOf(item) {
4106
+ const status = (item.status ?? "").trim().toLowerCase();
4107
+ if (isLifecycleState(status)) return status;
4108
+ if (status && LEGACY_STATUS_MAP[status]) return LEGACY_STATUS_MAP[status];
4109
+ const folder = lifecycleFolderOf(item.filePath ?? "");
4110
+ if (folder) return folder;
4111
+ return "ready";
4112
+ }
4113
+ function emptyLifecycleCounts() {
4114
+ return Object.fromEntries(LIFECYCLE_STATES.map((s) => [s, 0]));
4115
+ }
4116
+ function lifecycleCounts(states) {
4117
+ const counts = emptyLifecycleCounts();
4118
+ for (const s of states) counts[s]++;
4119
+ return counts;
4120
+ }
4121
+
4122
+ // src/services/knowledge-artifacts.ts
4123
+ var ARCH_DIR2 = "knowledge";
4124
+ function toPosix(p2) {
4125
+ return p2.replace(/\\/g, "/");
4126
+ }
4127
+ function relativeTo(dir, filePath) {
4128
+ const base = toPosix(dir).replace(/\/+$/, "");
4129
+ const full = toPosix(filePath);
4130
+ return full.startsWith(base + "/") ? full.slice(base.length + 1) : full;
4131
+ }
4132
+ function isWorkItemArtifact(a) {
4133
+ return toPosix(a.filePath).includes("/delivery/work-items/") && Boolean(a.type);
4134
+ }
4135
+ function classifyLayer(posixPath) {
4136
+ if (posixPath.includes("/knowledge/business/")) return "business";
4137
+ if (posixPath.includes("/knowledge/product/")) return "product";
4138
+ if (posixPath.includes("/knowledge/tech/modules/") || posixPath.includes("/knowledge/modules/"))
4139
+ return "module";
4140
+ if (posixPath.includes("/knowledge/tech/")) return "tech";
4141
+ if (posixPath.includes("/knowledge/delivery/")) return "delivery";
4142
+ return "unknown";
4143
+ }
4144
+ function enrich(dir, a) {
4145
+ const posix = toPosix(a.filePath);
4146
+ const isWi = isWorkItemArtifact(a);
4147
+ return {
4148
+ ...a,
4149
+ relPath: relativeTo(dir, a.filePath),
4150
+ layer: classifyLayer(posix),
4151
+ isWorkItem: isWi,
4152
+ lifecycle: isWi ? lifecycleStateOf({ status: a.status, filePath: a.filePath }) : void 0
4153
+ };
4154
+ }
4155
+ function discoverKnowledge(dir) {
4156
+ const archDir = join(dir, ARCH_DIR2);
4157
+ if (!exists(archDir)) return [];
4158
+ return readArtifacts(archDir).map((a) => enrich(dir, a));
4159
+ }
4160
+ function discoverWorkItems(dir) {
4161
+ return discoverKnowledge(dir).filter((a) => a.isWorkItem);
4162
+ }
4163
+
4074
4164
  // src/core/diff-analysis.ts
4075
4165
  import { minimatch } from "minimatch";
4076
4166
  function normalizePath(p2) {
@@ -4463,7 +4553,7 @@ function collectMatchedDomains(matchedArtifactDomains) {
4463
4553
  }
4464
4554
 
4465
4555
  // src/commands/guard.ts
4466
- var ARCH_DIR2 = "knowledge";
4556
+ var ARCH_DIR3 = "knowledge";
4467
4557
  var CONFIG_PATH2 = ".kaddo/config.yml";
4468
4558
  function loadConfig2(dir) {
4469
4559
  const configPath = join(dir, CONFIG_PATH2);
@@ -4607,12 +4697,12 @@ async function runGuard(opts = {}) {
4607
4697
  console.log("kaddo guard: no modified files detected.");
4608
4698
  return;
4609
4699
  }
4610
- const archDir = join(dir, ARCH_DIR2);
4700
+ const archDir = join(dir, ARCH_DIR3);
4611
4701
  if (!exists(archDir)) {
4612
4702
  console.log("kaddo guard: no knowledge/ directory found. Run `kaddo init` first.");
4613
4703
  return;
4614
4704
  }
4615
- const artifacts = readArtifacts(archDir);
4705
+ const artifacts = discoverKnowledge(dir);
4616
4706
  const result = analyzeGuard(touchedFiles, artifacts, silentWithoutOwnership);
4617
4707
  const pluginSignals = runPlugins(plugins, currentFiles, (filePath) => {
4618
4708
  const abs = join(dir, filePath);
@@ -4881,54 +4971,8 @@ function renderLayersMarkdown(layers) {
4881
4971
  return lines.join("\n").trimEnd();
4882
4972
  }
4883
4973
 
4884
- // src/core/lifecycle.ts
4885
- var LIFECYCLE_STATES = [
4886
- "draft",
4887
- "ready",
4888
- "in-progress",
4889
- "blocked",
4890
- "completed",
4891
- "archived"
4892
- ];
4893
- var ACTIVE_STATES = ["draft", "ready", "in-progress", "blocked"];
4894
- var LEGACY_STATUS_MAP = {
4895
- done: "completed",
4896
- cancelled: "archived",
4897
- canceled: "archived",
4898
- "in-progress": "in-progress"
4899
- };
4900
- var STATE_SET = new Set(LIFECYCLE_STATES);
4901
- function isLifecycleState(s) {
4902
- return STATE_SET.has(s);
4903
- }
4904
- function isActiveState(s) {
4905
- return ACTIVE_STATES.includes(s);
4906
- }
4907
- function lifecycleFolderOf(filePath) {
4908
- const p2 = filePath.replace(/\\/g, "/");
4909
- const m = p2.match(/\/delivery\/work-items\/([^/]+)\//);
4910
- if (m && isLifecycleState(m[1])) return m[1];
4911
- return null;
4912
- }
4913
- function lifecycleStateOf(item) {
4914
- const status = (item.status ?? "").trim().toLowerCase();
4915
- if (isLifecycleState(status)) return status;
4916
- if (status && LEGACY_STATUS_MAP[status]) return LEGACY_STATUS_MAP[status];
4917
- const folder = lifecycleFolderOf(item.filePath ?? "");
4918
- if (folder) return folder;
4919
- return "ready";
4920
- }
4921
- function emptyLifecycleCounts() {
4922
- return Object.fromEntries(LIFECYCLE_STATES.map((s) => [s, 0]));
4923
- }
4924
- function lifecycleCounts(states) {
4925
- const counts = emptyLifecycleCounts();
4926
- for (const s of states) counts[s]++;
4927
- return counts;
4928
- }
4929
-
4930
4974
  // src/core/project-explain.ts
4931
- var ARCH_DIR3 = "knowledge";
4975
+ var ARCH_DIR4 = "knowledge";
4932
4976
  function first(values) {
4933
4977
  if (Array.isArray(values)) {
4934
4978
  const v = values.find((x) => typeof x === "string" && x);
@@ -4959,7 +5003,7 @@ function loadScan(dir) {
4959
5003
  }
4960
5004
  }
4961
5005
  function hasAgents(dir) {
4962
- const agentsDir = join(dir, ARCH_DIR3, "agents");
5006
+ const agentsDir = join(dir, ARCH_DIR4, "agents");
4963
5007
  if (!exists(agentsDir)) return false;
4964
5008
  function hasAgentMd(d) {
4965
5009
  for (const e of readDir(d)) {
@@ -4996,7 +5040,7 @@ function buildProjectExplanation(dir) {
4996
5040
  const layerStatus = (name) => layers.find((l) => l.layer === name)?.status ?? "Missing";
4997
5041
  const knowledge = {
4998
5042
  hasScan: scan2 !== null,
4999
- hasInventory: exists(join(dir, ARCH_DIR3, "inventory.md")),
5043
+ hasInventory: exists(join(dir, ARCH_DIR4, "inventory.md")),
5000
5044
  hasContextPack: exists(join(dir, ".kaddo", "context-pack.md")),
5001
5045
  hasUnderstand: exists(join(dir, ".kaddo", "understand.md")),
5002
5046
  hasCapabilities: layerStatus("Product") !== "Missing",
@@ -5004,12 +5048,7 @@ function buildProjectExplanation(dir) {
5004
5048
  hasRoadmap: layerStatus("Delivery") !== "Missing",
5005
5049
  hasAgents: hasAgents(dir)
5006
5050
  };
5007
- const archDir = join(dir, ARCH_DIR3);
5008
- const allArtifacts = exists(archDir) ? readArtifacts(archDir) : [];
5009
- const workItemArtifacts = allArtifacts.filter((a) => {
5010
- const p2 = a.filePath.replace(/\\/g, "/");
5011
- return p2.includes("/delivery/work-items/") && Boolean(a.type);
5012
- });
5051
+ const workItemArtifacts = discoverWorkItems(dir);
5013
5052
  const items = workItemArtifacts.map((a) => ({
5014
5053
  id: a.id || a.title,
5015
5054
  title: a.title,
@@ -5051,7 +5090,7 @@ function buildProjectExplanation(dir) {
5051
5090
  workItemsMissingOwnership: items.length - withOwnership
5052
5091
  };
5053
5092
  const domains = [...new Set(workItemArtifacts.flatMap((a) => a.domains))].filter(Boolean);
5054
- const roadmapPath = join(dir, ARCH_DIR3, "delivery", "roadmap.md");
5093
+ const roadmapPath = join(dir, ARCH_DIR4, "delivery", "roadmap.md");
5055
5094
  const roadmapMd = exists(roadmapPath) ? readFile(roadmapPath) : null;
5056
5095
  const roadmap = roadmapStats(roadmapMd, items.length);
5057
5096
  const mappedModules = loadMappedModules(dir);
@@ -5245,10 +5284,10 @@ function renderExplanationAgent(exp) {
5245
5284
  }
5246
5285
 
5247
5286
  // src/commands/explain.ts
5248
- var ARCH_DIR4 = "knowledge";
5287
+ var ARCH_DIR5 = "knowledge";
5249
5288
  var CONFIG_PATH3 = ".kaddo/config.yml";
5250
5289
  function readKnowledge(dir) {
5251
- const knowledgePath = join(dir, ARCH_DIR4, "knowledge.md");
5290
+ const knowledgePath = join(dir, ARCH_DIR5, "knowledge.md");
5252
5291
  if (!exists(knowledgePath)) return null;
5253
5292
  try {
5254
5293
  const raw = readFile(knowledgePath);
@@ -5259,7 +5298,7 @@ function readKnowledge(dir) {
5259
5298
  }
5260
5299
  }
5261
5300
  function readRoadmap(dir) {
5262
- const roadmapPath = join(dir, ARCH_DIR4, "roadmap.md");
5301
+ const roadmapPath = join(dir, ARCH_DIR5, "roadmap.md");
5263
5302
  if (!exists(roadmapPath)) return null;
5264
5303
  try {
5265
5304
  const raw = readFile(roadmapPath);
@@ -5408,7 +5447,7 @@ function runExplain(opts) {
5408
5447
  explainProject(dir, mode);
5409
5448
  return;
5410
5449
  }
5411
- const archDir = join(dir, ARCH_DIR4);
5450
+ const archDir = join(dir, ARCH_DIR5);
5412
5451
  if (!exists(archDir)) {
5413
5452
  console.error("No knowledge/ directory found. Run `kaddo init` first.");
5414
5453
  process.exit(1);
@@ -5433,7 +5472,7 @@ function runExplain(opts) {
5433
5472
  // src/core/context-pack.ts
5434
5473
  import matter3 from "gray-matter";
5435
5474
  var CONTEXT_PACK_VERSION = "1";
5436
- var ARCH_DIR5 = "knowledge";
5475
+ var ARCH_DIR6 = "knowledge";
5437
5476
  function readScanJson(dir) {
5438
5477
  const scanPath = join(dir, ".kaddo", "scan.json");
5439
5478
  if (!exists(scanPath)) return null;
@@ -5449,7 +5488,7 @@ function firstParagraph(markdown) {
5449
5488
  return para ?? "";
5450
5489
  }
5451
5490
  function readMarkdownSummary(dir, file) {
5452
- const p2 = join(dir, ARCH_DIR5, file);
5491
+ const p2 = join(dir, ARCH_DIR6, file);
5453
5492
  if (!exists(p2)) return null;
5454
5493
  try {
5455
5494
  return firstParagraph(readFile(p2));
@@ -5527,7 +5566,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
5527
5566
  missing.push("Scan baseline missing. Run `kaddo scan` for better context.");
5528
5567
  }
5529
5568
  const detected = scanJson?.detected ?? {};
5530
- const inventoryAvailable = exists(join(dir, ARCH_DIR5, "inventory.md"));
5569
+ const inventoryAvailable = exists(join(dir, ARCH_DIR6, "inventory.md"));
5531
5570
  if (!inventoryAvailable) {
5532
5571
  missing.push("No technical inventory found. Run `kaddo scan` to generate it.");
5533
5572
  }
@@ -5539,8 +5578,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
5539
5578
  if (!roadmapSummary) {
5540
5579
  missing.push("No roadmap baseline found.");
5541
5580
  }
5542
- const archPath = join(dir, ARCH_DIR5);
5543
- const allArtifacts = exists(archPath) ? readArtifacts(archPath) : [];
5581
+ const allArtifacts = discoverKnowledge(dir);
5544
5582
  const workItems = allArtifacts.filter(
5545
5583
  (a) => isDeliveryWorkItem(a) && isActiveState(lifecycleStateOf({ status: a.status, filePath: a.filePath }))
5546
5584
  );
@@ -5548,7 +5586,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
5548
5586
  missing.push("No work items found.");
5549
5587
  }
5550
5588
  const state = config.project.state;
5551
- const roadmapPath = join(dir, ARCH_DIR5, "delivery", "roadmap.md");
5589
+ const roadmapPath = join(dir, ARCH_DIR6, "delivery", "roadmap.md");
5552
5590
  const materialized = allArtifacts.filter(
5553
5591
  (a) => a.filePath.replace(/\\/g, "/").includes("/delivery/work-items/") && Boolean(a.type)
5554
5592
  ).length;
@@ -5942,19 +5980,12 @@ import { parse as parseYaml9 } from "yaml";
5942
5980
  function slugify2(s) {
5943
5981
  return s.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
5944
5982
  }
5945
- function isWorkItem(a) {
5946
- return a.filePath.replace(/\\/g, "/").includes("/delivery/work-items/") && Boolean(a.type);
5947
- }
5948
5983
  function toActive(a) {
5949
5984
  const id = a.id || a.title || "WI";
5950
5985
  return { id, title: a.title || id, type: a.type, slug: slugify2(a.title || id) };
5951
5986
  }
5952
5987
  function activeWorkItems(dir) {
5953
- const archDir = join(dir, "knowledge");
5954
- if (!exists(archDir)) return [];
5955
- return readArtifacts(archDir).filter(
5956
- (a) => isWorkItem(a) && lifecycleStateOf({ status: a.status, filePath: a.filePath }) === "in-progress"
5957
- ).map(toActive);
5988
+ return discoverWorkItems(dir).filter((a) => a.lifecycle === "in-progress").map(toActive);
5958
5989
  }
5959
5990
  function branchPrefix(type) {
5960
5991
  switch (type) {
@@ -6257,9 +6288,9 @@ function classify(declaredType, declaredLevel, touchedFiles) {
6257
6288
  }
6258
6289
 
6259
6290
  // src/commands/classify.ts
6260
- var ARCH_DIR6 = "knowledge";
6291
+ var ARCH_DIR7 = "knowledge";
6261
6292
  function findActiveWorkItem(dir) {
6262
- const archDir = join(dir, ARCH_DIR6);
6293
+ const archDir = join(dir, ARCH_DIR7);
6263
6294
  if (!exists(archDir)) return null;
6264
6295
  const artifacts = readArtifacts(archDir);
6265
6296
  return artifacts.filter((a) => a.status === "in-progress" && a.type !== "current-state" && a.type !== "roadmap").sort((a, b) => {
@@ -6325,7 +6356,7 @@ async function runClassify(opts = {}) {
6325
6356
 
6326
6357
  // src/commands/status.ts
6327
6358
  import { parse as parseYaml10 } from "yaml";
6328
- var ARCH_DIR7 = "knowledge";
6359
+ var ARCH_DIR8 = "knowledge";
6329
6360
  var CONFIG_PATH4 = ".kaddo/config.yml";
6330
6361
  function loadConfig3(dir) {
6331
6362
  const p2 = join(dir, CONFIG_PATH4);
@@ -6338,12 +6369,12 @@ function loadConfig3(dir) {
6338
6369
  }
6339
6370
  function runStatus() {
6340
6371
  const dir = cwd();
6341
- if (!exists(join(dir, ARCH_DIR7))) {
6372
+ if (!exists(join(dir, ARCH_DIR8))) {
6342
6373
  console.error("No knowledge/ directory found. Run `kaddo init` first.");
6343
6374
  process.exit(1);
6344
6375
  }
6345
6376
  const config = loadConfig3(dir);
6346
- const artifacts = readArtifacts(join(dir, ARCH_DIR7));
6377
+ const artifacts = readArtifacts(join(dir, ARCH_DIR8));
6347
6378
  const ignores = loadIgnores(dir);
6348
6379
  const workItems = artifacts.filter(
6349
6380
  (a) => a.type !== "current-state" && a.type !== "roadmap"
@@ -6389,7 +6420,7 @@ function runStatus() {
6389
6420
 
6390
6421
  // src/commands/learn.ts
6391
6422
  import matter4 from "gray-matter";
6392
- var ARCH_DIR8 = "knowledge";
6423
+ var ARCH_DIR9 = "knowledge";
6393
6424
  var WORK_ITEMS_DIR2 = "knowledge/delivery/work-items";
6394
6425
  function findWorkItemFile(dir, id) {
6395
6426
  const wiDir = join(dir, WORK_ITEMS_DIR2);
@@ -6430,12 +6461,12 @@ ${learning.trim()}
6430
6461
  }
6431
6462
  async function runLearn(artifactId) {
6432
6463
  const dir = cwd();
6433
- if (!exists(join(dir, ARCH_DIR8))) {
6464
+ if (!exists(join(dir, ARCH_DIR9))) {
6434
6465
  console.error("No knowledge/ directory found. Run `kaddo init` first.");
6435
6466
  process.exit(1);
6436
6467
  }
6437
6468
  intro2("kaddo learn");
6438
- const artifacts = readArtifacts(join(dir, ARCH_DIR8));
6469
+ const artifacts = readArtifacts(join(dir, ARCH_DIR9));
6439
6470
  const inProgress = artifacts.filter(
6440
6471
  (a) => a.status === "in-progress" && a.type !== "current-state" && a.type !== "roadmap"
6441
6472
  );
@@ -6478,7 +6509,7 @@ async function runLearn(artifactId) {
6478
6509
  }
6479
6510
 
6480
6511
  // src/commands/history.ts
6481
- var ARCH_DIR9 = "knowledge";
6512
+ var ARCH_DIR10 = "knowledge";
6482
6513
  function formatRow(a) {
6483
6514
  const id = (a.id || "").padEnd(8);
6484
6515
  const type = a.type.padEnd(18);
@@ -6489,11 +6520,11 @@ function formatRow(a) {
6489
6520
  }
6490
6521
  function runHistory(opts = {}) {
6491
6522
  const dir = cwd();
6492
- if (!exists(join(dir, ARCH_DIR9))) {
6523
+ if (!exists(join(dir, ARCH_DIR10))) {
6493
6524
  console.error("No knowledge/ directory found. Run `kaddo init` first.");
6494
6525
  process.exit(1);
6495
6526
  }
6496
- let artifacts = readArtifacts(join(dir, ARCH_DIR9)).filter(
6527
+ let artifacts = readArtifacts(join(dir, ARCH_DIR10)).filter(
6497
6528
  (a) => a.type !== "current-state" && a.type !== "roadmap"
6498
6529
  );
6499
6530
  if (opts.domain) {
@@ -6654,42 +6685,23 @@ function runAdd(moduleName, opts = {}, dir = cwd()) {
6654
6685
 
6655
6686
  // src/core/ownership-suggest.ts
6656
6687
  import matter5 from "gray-matter";
6657
- var WORK_ITEMS_DIR3 = "knowledge/delivery/work-items";
6658
6688
  var SCAN_PATH = ".kaddo/scan.json";
6659
6689
  function toStringArray3(value) {
6660
6690
  return Array.isArray(value) ? value.map((v) => String(v)).filter(Boolean) : [];
6661
6691
  }
6662
- function parseOwnershipArtifact(filePath, relPath, raw) {
6663
- try {
6664
- const { data } = matter5(raw);
6665
- const codeGlobs = toStringArray3(data.code);
6666
- return {
6667
- filePath,
6668
- relPath: relPath.split("\\").join("/"),
6669
- id: String(data.id ?? ""),
6670
- title: String(data.title ?? ""),
6671
- type: String(data.type ?? ""),
6672
- domains: toStringArray3(data.domains),
6673
- capabilities: toStringArray3(data.capabilities),
6674
- codeGlobs,
6675
- source: data.source ? String(data.source) : void 0,
6676
- hasOwnership: codeGlobs.length > 0
6677
- };
6678
- } catch {
6679
- return null;
6680
- }
6681
- }
6682
6692
  function findWorkItemArtifacts(dir) {
6683
- const wiDir = join(dir, WORK_ITEMS_DIR3);
6684
- if (!exists(wiDir)) return [];
6685
- const artifacts = [];
6686
- for (const entry of readDir(wiDir)) {
6687
- const full = join(wiDir, entry);
6688
- if (!isFile(full) || !entry.endsWith(".md")) continue;
6689
- const parsed = parseOwnershipArtifact(full, `${WORK_ITEMS_DIR3}/${entry}`, readFile(full));
6690
- if (parsed) artifacts.push(parsed);
6691
- }
6692
- return artifacts;
6693
+ return discoverWorkItems(dir).map((a) => ({
6694
+ filePath: a.filePath,
6695
+ relPath: a.relPath,
6696
+ id: a.id,
6697
+ title: a.title,
6698
+ type: a.type,
6699
+ domains: a.domains,
6700
+ capabilities: a.capabilities,
6701
+ codeGlobs: a.codeGlobs,
6702
+ source: a.source || void 0,
6703
+ hasOwnership: a.codeGlobs.length > 0
6704
+ }));
6693
6705
  }
6694
6706
  function artifactsMissingOwnership(artifacts) {
6695
6707
  return artifacts.filter((a) => !a.hasOwnership);
@@ -6833,16 +6845,24 @@ async function runOwnersSuggest() {
6833
6845
  intro2("kaddo owners suggest");
6834
6846
  const artifacts = findWorkItemArtifacts(dir);
6835
6847
  if (artifacts.length === 0) {
6836
- log2.warn("No knowledge artifacts found. Create a Work Item first.");
6848
+ log2.warn(
6849
+ "No Work Items found under knowledge/delivery/work-items/ (searched recursively, including draft/ ready/ in-progress/ \u2026)."
6850
+ );
6851
+ log2.info("Create one with `kaddo create` or `kaddo create --from roadmap`.");
6837
6852
  outro2("Nothing to do.");
6838
6853
  return;
6839
6854
  }
6840
6855
  const missing = artifactsMissingOwnership(artifacts);
6841
6856
  if (missing.length === 0) {
6842
- log2.info("All detected artifacts already declare code ownership.");
6857
+ log2.success(
6858
+ `Found ${artifacts.length} Work Item${artifacts.length === 1 ? "" : "s"}; all already declare code ownership.`
6859
+ );
6843
6860
  outro2("Nothing to do.");
6844
6861
  return;
6845
6862
  }
6863
+ log2.info(
6864
+ `Found ${artifacts.length} Work Item${artifacts.length === 1 ? "" : "s"}; ${missing.length} missing code ownership.`
6865
+ );
6846
6866
  const relPath = missing.length === 1 ? missing[0].relPath : await select2({
6847
6867
  message: "Which artifact needs ownership?",
6848
6868
  options: missing.map((a) => ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/cli",
3
- "version": "3.9.0",
3
+ "version": "3.9.1",
4
4
  "description": "Knowledge Driven Development toolkit",
5
5
  "license": "MIT",
6
6
  "repository": {