@kaddo/cli 3.52.0 → 3.54.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 (2) hide show
  1. package/dist/index.js +151 -32
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2791,16 +2791,49 @@ function renderSkillsSection(agent) {
2791
2791
  ""
2792
2792
  ].join("\n");
2793
2793
  }
2794
+ var KNOWLEDGE_REFINING_AGENTS = {
2795
+ "business-agent": "business-agent",
2796
+ "capability-agent": "capability-agent",
2797
+ "bootstrap-agent": "bootstrap-agent",
2798
+ "codebase-agent": "codebase-agent",
2799
+ "architecture-agent": "architecture-agent",
2800
+ "roadmap-agent": "roadmap-agent",
2801
+ "legacy-agent": "legacy-agent",
2802
+ "work-item-agent": "work-item-agent",
2803
+ "backlog-agent": "backlog-agent",
2804
+ "adr-agent": "adr-agent",
2805
+ "implementation-agent": "implementation-agent"
2806
+ };
2807
+ function renderFrontmatterRules(agent) {
2808
+ if (!KNOWLEDGE_REFINING_AGENTS[agent]) return "";
2809
+ return [
2810
+ "## Frontmatter Rules",
2811
+ "",
2812
+ "When rewriting an existing Kaddo knowledge file:",
2813
+ "",
2814
+ "- Preserve the existing YAML frontmatter.",
2815
+ "- Do not remove `type`, `generated_by`, or `template_version`.",
2816
+ "- If the document is no longer a placeholder, set `project_state: ai-assisted`.",
2817
+ `- Add or update \`refined_by: ${agent}\`.`,
2818
+ "- Preserve unknown frontmatter keys \u2014 do not strip fields you do not recognize.",
2819
+ "- Only rewrite the markdown body unless metadata changes are explicitly required by these rules.",
2820
+ "- Preserve structural sections like `## Open Questions` \u2014 leave them empty rather than removing them.",
2821
+ ""
2822
+ ].join("\n");
2823
+ }
2794
2824
  function withResponsibilityTrace(fileName, content) {
2795
2825
  const agent = fileName.replace(/\.md$/, "");
2796
2826
  if (!RESPONSIBILITY_MATRIX[agent]) return content;
2797
2827
  const skills = renderSkillsSection(agent);
2798
2828
  const skillsBlock = skills ? `${skills}
2829
+ ` : "";
2830
+ const frontmatter = renderFrontmatterRules(agent);
2831
+ const frontmatterBlock = frontmatter ? `${frontmatter}
2799
2832
  ` : "";
2800
2833
  return `${content.trimEnd()}
2801
2834
 
2802
2835
  ${renderLanguageRule()}
2803
- ${renderAgentBoundaries(agent)}
2836
+ ${frontmatterBlock}${renderAgentBoundaries(agent)}
2804
2837
  ${skillsBlock}${renderAgentTrace(agent)}`;
2805
2838
  }
2806
2839
 
@@ -6271,6 +6304,54 @@ async function collectWorkspaceChanges(dir, mode = "head", deps = defaultDeps) {
6271
6304
  };
6272
6305
  }
6273
6306
 
6307
+ // src/core/metadata-health.ts
6308
+ import matter2 from "gray-matter";
6309
+ var KNOWLEDGE_FILES = [
6310
+ "knowledge/business/business.md",
6311
+ "knowledge/product/product.md",
6312
+ "knowledge/product/capabilities.md",
6313
+ "knowledge/tech/codebase.md",
6314
+ "knowledge/tech/current-state.md",
6315
+ "knowledge/delivery/roadmap.md"
6316
+ ];
6317
+ var REQUIRED_FIELDS = ["type", "generated_by", "template_version"];
6318
+ function analyzeMetadataHealth(dir) {
6319
+ const findings = [];
6320
+ let healthy = 0;
6321
+ let drifted = 0;
6322
+ for (const rel of KNOWLEDGE_FILES) {
6323
+ const p2 = join(dir, rel);
6324
+ if (!exists(p2)) continue;
6325
+ let data;
6326
+ try {
6327
+ const raw = readFile(p2);
6328
+ data = matter2(raw).data;
6329
+ } catch {
6330
+ continue;
6331
+ }
6332
+ if (Object.keys(data).length === 0) continue;
6333
+ let fileDrifted = false;
6334
+ for (const field of REQUIRED_FIELDS) {
6335
+ if (data[field] === void 0 || data[field] === null || data[field] === "") {
6336
+ findings.push({ file: rel, field, issue: "missing", detail: `Missing \`${field}\` in frontmatter.` });
6337
+ fileDrifted = true;
6338
+ }
6339
+ }
6340
+ if (data.refined_by && data.project_state && data.project_state !== "ai-assisted") {
6341
+ findings.push({
6342
+ file: rel,
6343
+ field: "project_state",
6344
+ issue: "inconsistent",
6345
+ detail: `File has \`refined_by: ${data.refined_by}\` but \`project_state\` is \`${data.project_state}\`, expected \`ai-assisted\`.`
6346
+ });
6347
+ fileDrifted = true;
6348
+ }
6349
+ if (fileDrifted) drifted++;
6350
+ else healthy++;
6351
+ }
6352
+ return { findings, healthy, drifted };
6353
+ }
6354
+
6274
6355
  // src/commands/guard.ts
6275
6356
  import path4 from "path";
6276
6357
  import { parse as parseYaml7 } from "yaml";
@@ -6893,6 +6974,14 @@ async function runGuard(opts = {}) {
6893
6974
  console.log("");
6894
6975
  }
6895
6976
  printPluginSignals(pluginSignals);
6977
+ const mh = analyzeMetadataHealth(dir);
6978
+ if (mh.findings.length > 0) {
6979
+ console.log("Metadata health:");
6980
+ for (const f of mh.findings) {
6981
+ console.log(` \u26A0 ${f.file}: ${f.detail}`);
6982
+ }
6983
+ console.log("");
6984
+ }
6896
6985
  const ownerMap = loadOwners(dir);
6897
6986
  const matchedDomains = collectMatchedDomains(activeMatches.map((m) => m.artifact.domains));
6898
6987
  const affectedOwners = resolveAffectedOwners(matchedDomains, ownerMap);
@@ -6954,7 +7043,7 @@ function runIgnoreRemove(artifactId) {
6954
7043
  }
6955
7044
 
6956
7045
  // src/commands/explain.ts
6957
- import matter5 from "gray-matter";
7046
+ import matter6 from "gray-matter";
6958
7047
  import { parse as parseYaml9 } from "yaml";
6959
7048
 
6960
7049
  // src/core/delivery-phase.ts
@@ -7120,7 +7209,7 @@ function assessPhase(input) {
7120
7209
  }
7121
7210
 
7122
7211
  // src/core/capsule.ts
7123
- import matter2 from "gray-matter";
7212
+ import matter3 from "gray-matter";
7124
7213
  import { parse as parseYaml8, stringify as stringifyYaml3 } from "yaml";
7125
7214
  var KNOWLEDGE = "knowledge";
7126
7215
  function today() {
@@ -7255,7 +7344,7 @@ function sectionParagraph(md, title) {
7255
7344
  return "";
7256
7345
  }
7257
7346
  function parseCapsule(id, path6, md) {
7258
- const { data } = matter2(md);
7347
+ const { data } = matter3(md);
7259
7348
  const updatedAt = data.updated_at ? String(data.updated_at) : void 0;
7260
7349
  let ageDays = null;
7261
7350
  if (updatedAt) {
@@ -7281,7 +7370,7 @@ function slugId(s) {
7281
7370
  function addExternalCapsule(dir, sourceFile) {
7282
7371
  if (!exists(sourceFile)) throw new Error(`Capsule not found: ${sourceFile}`);
7283
7372
  const raw = readFile(sourceFile);
7284
- const { data } = matter2(raw);
7373
+ const { data } = matter3(raw);
7285
7374
  const isCapsuleType = data.type === "knowledge-capsule";
7286
7375
  const fallbackName = sourceFile.split(/[\\/]/).pop()?.replace(/\.capsule\.md$/, "") ?? "external";
7287
7376
  const id = slugId(String(data.system ?? fallbackName));
@@ -7753,7 +7842,7 @@ function loadGraphHints(dir) {
7753
7842
  }
7754
7843
 
7755
7844
  // src/services/installed-skills.ts
7756
- import matter3 from "gray-matter";
7845
+ import matter4 from "gray-matter";
7757
7846
  var SKILLS_DIR = join("knowledge", "skills");
7758
7847
  function discoverInstalledSkills(dir) {
7759
7848
  const base = join(dir, SKILLS_DIR);
@@ -7763,7 +7852,7 @@ function discoverInstalledSkills(dir) {
7763
7852
  const skillFile = join(base, entry, "skill.md");
7764
7853
  if (!isFile(skillFile)) continue;
7765
7854
  try {
7766
- const { data } = matter3(readFile(skillFile));
7855
+ const { data } = matter4(readFile(skillFile));
7767
7856
  if (data.type && String(data.type) !== "skill") continue;
7768
7857
  const id = String(data.id ?? entry);
7769
7858
  out.push({
@@ -8857,9 +8946,6 @@ function resolveNextStep(dir, now = /* @__PURE__ */ new Date()) {
8857
8946
  if (!exists(join(dir, ".kaddo", "context-pack.md"))) {
8858
8947
  return { id: "context", phase: "Discovery", label: "Run `kaddo context` to prepare the LLM context pack.", command: "kaddo context", reason: "No context pack has been generated yet." };
8859
8948
  }
8860
- if (!exists(join(dir, ".kaddo", "understand.md"))) {
8861
- return { id: "understand", phase: "Discovery", label: "Run `kaddo understand` to summarize the project context.", command: "kaddo understand", reason: "No understand handoff has been generated yet." };
8862
- }
8863
8949
  const discovery = state === "pre-ai" || state === "legacy";
8864
8950
  const resolveAgent = (agent) => {
8865
8951
  const file = agent.endsWith(".md") ? agent : `${agent}.md`;
@@ -8899,6 +8985,9 @@ function resolveNextStep(dir, now = /* @__PURE__ */ new Date()) {
8899
8985
  const agent = ctx.agents.includes("codebase-agent") ? "codebase-agent" : "architecture-agent";
8900
8986
  return refine("refine-codebase", agent, CB, qCodebase);
8901
8987
  }
8988
+ if (!exists(join(dir, ".kaddo", "understand.md"))) {
8989
+ return { id: "understand", phase: "Discovery", label: "Run `kaddo understand` to summarize the project context.", command: "kaddo understand", reason: "No understand handoff has been generated yet." };
8990
+ }
8902
8991
  const oq = buildOpenQuestionsReport(dir, now);
8903
8992
  if (oq.summary.blocking_open > 0) {
8904
8993
  return { id: "questions", phase: "Knowledge Refinement", label: "Run `kaddo questions` to see source locations and resolution guidance, then resolve, assume or defer the blocking open questions.", command: "kaddo questions", reason: `${oq.summary.blocking_open} blocking open question(s) remain.` };
@@ -9021,7 +9110,7 @@ function buildSecondaryRecommendations(st) {
9021
9110
  }
9022
9111
 
9023
9112
  // src/core/readiness.ts
9024
- var KNOWLEDGE_FILES = [
9113
+ var KNOWLEDGE_FILES2 = [
9025
9114
  { key: "current_state", path: "knowledge/tech/current-state.md", label: "knowledge/tech/current-state.md", agent: "architecture-agent" },
9026
9115
  { key: "codebase", path: "knowledge/tech/codebase.md", label: "knowledge/tech/codebase.md", agent: "codebase-agent" },
9027
9116
  { key: "capabilities", path: "knowledge/product/capabilities.md", label: "knowledge/product/capabilities.md", agent: "capability-agent" },
@@ -9062,7 +9151,7 @@ function buildReadinessReport(dir, now = /* @__PURE__ */ new Date()) {
9062
9151
  if (config.project.state === "legacy") return stub("legacy-project", "Use the legacy project flow.");
9063
9152
  const scan2 = exists(join(dir, ".kaddo", "scan.json")) ? "available" : "missing";
9064
9153
  const understand = exists(join(dir, ".kaddo", "understand.md")) ? "available" : "missing";
9065
- const presence = Object.fromEntries(KNOWLEDGE_FILES.map((f) => [f.key, analyzeKnowledgeArtifact(dir, f.path)]));
9154
+ const presence = Object.fromEntries(KNOWLEDGE_FILES2.map((f) => [f.key, analyzeKnowledgeArtifact(dir, f.path)]));
9066
9155
  const ctx = buildCodexAdapterContext(dir);
9067
9156
  const agents = ctx.hasAgents ? "present" : "missing";
9068
9157
  const skills = ctx.hasSkills ? "present" : "missing";
@@ -9090,7 +9179,7 @@ function buildReadinessReport(dir, now = /* @__PURE__ */ new Date()) {
9090
9179
  resolved_questions: oq.summary.resolution.resolved,
9091
9180
  deferred_questions: oq.summary.resolution.deferred
9092
9181
  };
9093
- const firstWeak = KNOWLEDGE_FILES.find((f) => presence[f.key] !== "useful");
9182
+ const firstWeak = KNOWLEDGE_FILES2.find((f) => presence[f.key] !== "useful");
9094
9183
  let overall;
9095
9184
  if (scan2 === "missing") overall = "initialized";
9096
9185
  else if (bootstrapBaseline2 === "incomplete") overall = "bootstrap-incomplete";
@@ -9113,7 +9202,7 @@ function buildReadinessReport(dir, now = /* @__PURE__ */ new Date()) {
9113
9202
  }
9114
9203
 
9115
9204
  // src/core/assets.ts
9116
- import matter4 from "gray-matter";
9205
+ import matter5 from "gray-matter";
9117
9206
  function canonicalAgents() {
9118
9207
  return AGENT_PROMPTS.map((a) => ({
9119
9208
  name: a.fileName.replace(/\.md$/, ""),
@@ -9126,7 +9215,7 @@ function canonicalSkills() {
9126
9215
  }
9127
9216
  function versionOf(content) {
9128
9217
  try {
9129
- const v = matter4(content).data.version;
9218
+ const v = matter5(content).data.version;
9130
9219
  return v === void 0 || v === null ? null : String(v);
9131
9220
  } catch {
9132
9221
  return null;
@@ -9679,7 +9768,6 @@ function mapNextStepId(id) {
9679
9768
  "add-skills": "enable-kaddo",
9680
9769
  scan: "scan-repository",
9681
9770
  context: "scan-repository",
9682
- understand: "scan-repository",
9683
9771
  "refine-business": "define-business",
9684
9772
  "refine-product": "define-product",
9685
9773
  "refine-capabilities": "discover-capabilities",
@@ -10029,7 +10117,8 @@ function buildProjectExplanation(dir) {
10029
10117
  installedAssets: installedAssetsSummary(dir),
10030
10118
  roadmapQuality: buildRoadmapQuality(dir),
10031
10119
  projectRoute: buildProjectRoute(dir),
10032
- scanSignals: loadScanSignals(dir)
10120
+ scanSignals: loadScanSignals(dir),
10121
+ metadataHealth: analyzeMetadataHealth(dir)
10033
10122
  };
10034
10123
  }
10035
10124
  function stateLabel(state) {
@@ -10338,6 +10427,13 @@ function renderExplanationHuman(exp) {
10338
10427
  }
10339
10428
  lines.push("");
10340
10429
  }
10430
+ if (exp.metadataHealth.findings.length > 0) {
10431
+ lines.push("## Metadata Health");
10432
+ for (const f of exp.metadataHealth.findings) {
10433
+ lines.push(`- \`${f.file}\`: ${f.detail}`);
10434
+ }
10435
+ lines.push("");
10436
+ }
10341
10437
  return lines.join("\n").trimEnd() + "\n";
10342
10438
  }
10343
10439
  function renderExplanationAgent(exp) {
@@ -10353,7 +10449,7 @@ function readKnowledge(dir) {
10353
10449
  if (!exists(knowledgePath)) return null;
10354
10450
  try {
10355
10451
  const raw = readFile(knowledgePath);
10356
- const { data, content } = matter5(raw);
10452
+ const { data, content } = matter6(raw);
10357
10453
  return { content, data };
10358
10454
  } catch {
10359
10455
  return null;
@@ -10364,7 +10460,7 @@ function readRoadmap(dir) {
10364
10460
  if (!exists(roadmapPath)) return null;
10365
10461
  try {
10366
10462
  const raw = readFile(roadmapPath);
10367
- const { content } = matter5(raw);
10463
+ const { content } = matter6(raw);
10368
10464
  return content.trim();
10369
10465
  } catch {
10370
10466
  return null;
@@ -10533,7 +10629,7 @@ function runExplain(opts) {
10533
10629
  }
10534
10630
 
10535
10631
  // src/core/context-pack.ts
10536
- import matter6 from "gray-matter";
10632
+ import matter7 from "gray-matter";
10537
10633
  var CONTEXT_PACK_VERSION = "1";
10538
10634
  var ARCH_DIR6 = "knowledge";
10539
10635
  function readScanJson(dir) {
@@ -10546,7 +10642,7 @@ function readScanJson(dir) {
10546
10642
  }
10547
10643
  }
10548
10644
  function firstParagraph2(markdown) {
10549
- const body = matter6(markdown).content.trim();
10645
+ const body = matter7(markdown).content.trim();
10550
10646
  const para = body.split("\n\n").map((p2) => p2.trim()).find((p2) => p2 && !p2.startsWith("#"));
10551
10647
  return para ?? "";
10552
10648
  }
@@ -10761,6 +10857,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
10761
10857
  skills: discoverInstalledSkills(dir).map((s) => s.id),
10762
10858
  scanSignals: scanJson?.signals ?? null,
10763
10859
  projectRoute: buildProjectRoute(dir),
10860
+ metadataHealth: analyzeMetadataHealth(dir),
10764
10861
  mappedModules,
10765
10862
  missing,
10766
10863
  // VS-052/VS-073.2: the handoff is driven by the unified next step, so the pack never contradicts
@@ -11049,6 +11146,13 @@ function renderContextPack(pack) {
11049
11146
  } else {
11050
11147
  parts.push("_None \u2014 all expected context is present._\n");
11051
11148
  }
11149
+ if (pack.metadataHealth.findings.length > 0) {
11150
+ parts.push("\n### Metadata Health\n");
11151
+ for (const f of pack.metadataHealth.findings) {
11152
+ parts.push(`- \`${f.file}\`: ${f.detail}
11153
+ `);
11154
+ }
11155
+ }
11052
11156
  parts.push("## Recommended Agent Handoff\n");
11053
11157
  if (isBootstrapIncomplete) {
11054
11158
  parts.push("No agent handoff yet.\n");
@@ -11180,7 +11284,8 @@ function enrichUnderstandPlan(plan, opts) {
11180
11284
  activeWorkItems: opts.activeWorkItems,
11181
11285
  recommendedPaths: opts.recommendedPaths,
11182
11286
  recommendedSkillPaths: opts.recommendedSkillPaths,
11183
- projectRoute: opts.projectRoute
11287
+ projectRoute: opts.projectRoute,
11288
+ metadataHealth: opts.metadataHealth
11184
11289
  };
11185
11290
  }
11186
11291
 
@@ -11408,6 +11513,13 @@ function renderUnderstand(plan) {
11408
11513
  } else {
11409
11514
  parts.push("Re-run `kaddo understand` any time to see this plan again.\n");
11410
11515
  }
11516
+ if (plan.metadataHealth && plan.metadataHealth.findings.length > 0) {
11517
+ parts.push("## Metadata Health\n");
11518
+ for (const f of plan.metadataHealth.findings) {
11519
+ parts.push(`- \`${f.file}\`: ${f.detail}
11520
+ `);
11521
+ }
11522
+ }
11411
11523
  return parts.join("\n");
11412
11524
  }
11413
11525
  function renderUnderstandTerminal(plan) {
@@ -11468,7 +11580,13 @@ function renderUnderstandTerminal(plan) {
11468
11580
  }
11469
11581
  }
11470
11582
  }
11471
- lines.push("");
11583
+ if (plan.metadataHealth && plan.metadataHealth.findings.length > 0) {
11584
+ lines.push("Metadata health:");
11585
+ for (const f of plan.metadataHealth.findings) {
11586
+ lines.push(` \u26A0 ${f.file}: ${f.detail}`);
11587
+ }
11588
+ lines.push("");
11589
+ }
11472
11590
  lines.push("Kaddo does not call an LLM. You stay in control of the interpretation.");
11473
11591
  lines.push("");
11474
11592
  return lines.join("\n");
@@ -11698,7 +11816,8 @@ function runUnderstand() {
11698
11816
  recommendedPaths,
11699
11817
  recommendedSkillPaths,
11700
11818
  language: languageLabel(projectLanguage(config)),
11701
- projectRoute: buildProjectRoute(dir)
11819
+ projectRoute: buildProjectRoute(dir),
11820
+ metadataHealth: analyzeMetadataHealth(dir)
11702
11821
  });
11703
11822
  writeFile(join(dir, ".kaddo", "understand.md"), renderUnderstand(enrichedPlan));
11704
11823
  log2.success("Wrote .kaddo/understand.md");
@@ -11988,7 +12107,7 @@ function runStatus() {
11988
12107
  }
11989
12108
 
11990
12109
  // src/commands/learn.ts
11991
- import matter7 from "gray-matter";
12110
+ import matter8 from "gray-matter";
11992
12111
  var ARCH_DIR9 = "knowledge";
11993
12112
  var WORK_ITEMS_DIR2 = "knowledge/delivery/work-items";
11994
12113
  function findWorkItemFile(dir, id) {
@@ -12000,7 +12119,7 @@ function findWorkItemFile(dir, id) {
12000
12119
  }
12001
12120
  function updateWorkItemFile(filePath, learning) {
12002
12121
  const raw = readFile(filePath);
12003
- const { data, content } = matter7(raw);
12122
+ const { data, content } = matter8(raw);
12004
12123
  data.status = "done";
12005
12124
  data.completed_at = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
12006
12125
  let updatedContent = content;
@@ -12025,7 +12144,7 @@ ${learning.trim()}
12025
12144
  ${learning.trim()}
12026
12145
  `;
12027
12146
  }
12028
- const newRaw = matter7.stringify(updatedContent, data);
12147
+ const newRaw = matter8.stringify(updatedContent, data);
12029
12148
  writeFile(filePath, newRaw);
12030
12149
  }
12031
12150
  async function runLearn(artifactId) {
@@ -12275,7 +12394,7 @@ function runAdd(moduleName, opts = {}, dir = cwd()) {
12275
12394
  }
12276
12395
 
12277
12396
  // src/core/ownership-suggest.ts
12278
- import matter8 from "gray-matter";
12397
+ import matter9 from "gray-matter";
12279
12398
  var SCAN_PATH = ".kaddo/scan.json";
12280
12399
  function normalizeGlob(input) {
12281
12400
  let g = input.trim().replace(/\\/g, "/");
@@ -12397,11 +12516,11 @@ function suggestGlobs(artifact, signals) {
12397
12516
  return [...new Set(out)];
12398
12517
  }
12399
12518
  function applyOwnership(raw, globs, mode = "replace") {
12400
- const parsed = matter8(raw);
12519
+ const parsed = matter9(raw);
12401
12520
  const existing = toStringArray3(parsed.data.code);
12402
12521
  const next = mode === "append" ? [.../* @__PURE__ */ new Set([...existing, ...globs])] : [...new Set(globs)];
12403
12522
  const data = { ...parsed.data, code: next };
12404
- return matter8.stringify(parsed.content, data);
12523
+ return matter9.stringify(parsed.content, data);
12405
12524
  }
12406
12525
 
12407
12526
  // src/commands/owners.ts
@@ -15013,7 +15132,7 @@ function runGraphExport(opts = {}) {
15013
15132
  }
15014
15133
 
15015
15134
  // src/core/impact-report.ts
15016
- import matter9 from "gray-matter";
15135
+ import matter10 from "gray-matter";
15017
15136
  function isBroadGlob(glob) {
15018
15137
  if (!glob.endsWith("/**")) return false;
15019
15138
  const prefix = glob.slice(0, -3);
@@ -15082,7 +15201,7 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
15082
15201
  }
15083
15202
  }
15084
15203
  try {
15085
- const body = matter9(readFile(wi.filePath)).content;
15204
+ const body = matter10(readFile(wi.filePath)).content;
15086
15205
  if (hasSection(body, /acceptance|criterios de aceptaci/i)) withAcceptance++;
15087
15206
  else gaps.missing_acceptance_criteria.push(gapItem(wi, "Add an `## Acceptance Criteria` section."));
15088
15207
  if (hasSection(body, /definition of done|^#{1,6}\s*dod\b|definici[oó]n de (terminado|hecho)/i)) withDoD++;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/cli",
3
- "version": "3.52.0",
3
+ "version": "3.54.0",
4
4
  "description": "Knowledge Driven Development toolkit",
5
5
  "license": "MIT",
6
6
  "repository": {