@kaddo/cli 3.53.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.
- package/dist/index.js +148 -28
- 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
|
|
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
|
|
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 } =
|
|
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 } =
|
|
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
|
|
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 } =
|
|
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({
|
|
@@ -9021,7 +9110,7 @@ function buildSecondaryRecommendations(st) {
|
|
|
9021
9110
|
}
|
|
9022
9111
|
|
|
9023
9112
|
// src/core/readiness.ts
|
|
9024
|
-
var
|
|
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(
|
|
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 =
|
|
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
|
|
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 =
|
|
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;
|
|
@@ -10028,7 +10117,8 @@ function buildProjectExplanation(dir) {
|
|
|
10028
10117
|
installedAssets: installedAssetsSummary(dir),
|
|
10029
10118
|
roadmapQuality: buildRoadmapQuality(dir),
|
|
10030
10119
|
projectRoute: buildProjectRoute(dir),
|
|
10031
|
-
scanSignals: loadScanSignals(dir)
|
|
10120
|
+
scanSignals: loadScanSignals(dir),
|
|
10121
|
+
metadataHealth: analyzeMetadataHealth(dir)
|
|
10032
10122
|
};
|
|
10033
10123
|
}
|
|
10034
10124
|
function stateLabel(state) {
|
|
@@ -10337,6 +10427,13 @@ function renderExplanationHuman(exp) {
|
|
|
10337
10427
|
}
|
|
10338
10428
|
lines.push("");
|
|
10339
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
|
+
}
|
|
10340
10437
|
return lines.join("\n").trimEnd() + "\n";
|
|
10341
10438
|
}
|
|
10342
10439
|
function renderExplanationAgent(exp) {
|
|
@@ -10352,7 +10449,7 @@ function readKnowledge(dir) {
|
|
|
10352
10449
|
if (!exists(knowledgePath)) return null;
|
|
10353
10450
|
try {
|
|
10354
10451
|
const raw = readFile(knowledgePath);
|
|
10355
|
-
const { data, content } =
|
|
10452
|
+
const { data, content } = matter6(raw);
|
|
10356
10453
|
return { content, data };
|
|
10357
10454
|
} catch {
|
|
10358
10455
|
return null;
|
|
@@ -10363,7 +10460,7 @@ function readRoadmap(dir) {
|
|
|
10363
10460
|
if (!exists(roadmapPath)) return null;
|
|
10364
10461
|
try {
|
|
10365
10462
|
const raw = readFile(roadmapPath);
|
|
10366
|
-
const { content } =
|
|
10463
|
+
const { content } = matter6(raw);
|
|
10367
10464
|
return content.trim();
|
|
10368
10465
|
} catch {
|
|
10369
10466
|
return null;
|
|
@@ -10532,7 +10629,7 @@ function runExplain(opts) {
|
|
|
10532
10629
|
}
|
|
10533
10630
|
|
|
10534
10631
|
// src/core/context-pack.ts
|
|
10535
|
-
import
|
|
10632
|
+
import matter7 from "gray-matter";
|
|
10536
10633
|
var CONTEXT_PACK_VERSION = "1";
|
|
10537
10634
|
var ARCH_DIR6 = "knowledge";
|
|
10538
10635
|
function readScanJson(dir) {
|
|
@@ -10545,7 +10642,7 @@ function readScanJson(dir) {
|
|
|
10545
10642
|
}
|
|
10546
10643
|
}
|
|
10547
10644
|
function firstParagraph2(markdown) {
|
|
10548
|
-
const body =
|
|
10645
|
+
const body = matter7(markdown).content.trim();
|
|
10549
10646
|
const para = body.split("\n\n").map((p2) => p2.trim()).find((p2) => p2 && !p2.startsWith("#"));
|
|
10550
10647
|
return para ?? "";
|
|
10551
10648
|
}
|
|
@@ -10760,6 +10857,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
|
|
|
10760
10857
|
skills: discoverInstalledSkills(dir).map((s) => s.id),
|
|
10761
10858
|
scanSignals: scanJson?.signals ?? null,
|
|
10762
10859
|
projectRoute: buildProjectRoute(dir),
|
|
10860
|
+
metadataHealth: analyzeMetadataHealth(dir),
|
|
10763
10861
|
mappedModules,
|
|
10764
10862
|
missing,
|
|
10765
10863
|
// VS-052/VS-073.2: the handoff is driven by the unified next step, so the pack never contradicts
|
|
@@ -11048,6 +11146,13 @@ function renderContextPack(pack) {
|
|
|
11048
11146
|
} else {
|
|
11049
11147
|
parts.push("_None \u2014 all expected context is present._\n");
|
|
11050
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
|
+
}
|
|
11051
11156
|
parts.push("## Recommended Agent Handoff\n");
|
|
11052
11157
|
if (isBootstrapIncomplete) {
|
|
11053
11158
|
parts.push("No agent handoff yet.\n");
|
|
@@ -11179,7 +11284,8 @@ function enrichUnderstandPlan(plan, opts) {
|
|
|
11179
11284
|
activeWorkItems: opts.activeWorkItems,
|
|
11180
11285
|
recommendedPaths: opts.recommendedPaths,
|
|
11181
11286
|
recommendedSkillPaths: opts.recommendedSkillPaths,
|
|
11182
|
-
projectRoute: opts.projectRoute
|
|
11287
|
+
projectRoute: opts.projectRoute,
|
|
11288
|
+
metadataHealth: opts.metadataHealth
|
|
11183
11289
|
};
|
|
11184
11290
|
}
|
|
11185
11291
|
|
|
@@ -11407,6 +11513,13 @@ function renderUnderstand(plan) {
|
|
|
11407
11513
|
} else {
|
|
11408
11514
|
parts.push("Re-run `kaddo understand` any time to see this plan again.\n");
|
|
11409
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
|
+
}
|
|
11410
11523
|
return parts.join("\n");
|
|
11411
11524
|
}
|
|
11412
11525
|
function renderUnderstandTerminal(plan) {
|
|
@@ -11467,7 +11580,13 @@ function renderUnderstandTerminal(plan) {
|
|
|
11467
11580
|
}
|
|
11468
11581
|
}
|
|
11469
11582
|
}
|
|
11470
|
-
|
|
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
|
+
}
|
|
11471
11590
|
lines.push("Kaddo does not call an LLM. You stay in control of the interpretation.");
|
|
11472
11591
|
lines.push("");
|
|
11473
11592
|
return lines.join("\n");
|
|
@@ -11697,7 +11816,8 @@ function runUnderstand() {
|
|
|
11697
11816
|
recommendedPaths,
|
|
11698
11817
|
recommendedSkillPaths,
|
|
11699
11818
|
language: languageLabel(projectLanguage(config)),
|
|
11700
|
-
projectRoute: buildProjectRoute(dir)
|
|
11819
|
+
projectRoute: buildProjectRoute(dir),
|
|
11820
|
+
metadataHealth: analyzeMetadataHealth(dir)
|
|
11701
11821
|
});
|
|
11702
11822
|
writeFile(join(dir, ".kaddo", "understand.md"), renderUnderstand(enrichedPlan));
|
|
11703
11823
|
log2.success("Wrote .kaddo/understand.md");
|
|
@@ -11987,7 +12107,7 @@ function runStatus() {
|
|
|
11987
12107
|
}
|
|
11988
12108
|
|
|
11989
12109
|
// src/commands/learn.ts
|
|
11990
|
-
import
|
|
12110
|
+
import matter8 from "gray-matter";
|
|
11991
12111
|
var ARCH_DIR9 = "knowledge";
|
|
11992
12112
|
var WORK_ITEMS_DIR2 = "knowledge/delivery/work-items";
|
|
11993
12113
|
function findWorkItemFile(dir, id) {
|
|
@@ -11999,7 +12119,7 @@ function findWorkItemFile(dir, id) {
|
|
|
11999
12119
|
}
|
|
12000
12120
|
function updateWorkItemFile(filePath, learning) {
|
|
12001
12121
|
const raw = readFile(filePath);
|
|
12002
|
-
const { data, content } =
|
|
12122
|
+
const { data, content } = matter8(raw);
|
|
12003
12123
|
data.status = "done";
|
|
12004
12124
|
data.completed_at = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
12005
12125
|
let updatedContent = content;
|
|
@@ -12024,7 +12144,7 @@ ${learning.trim()}
|
|
|
12024
12144
|
${learning.trim()}
|
|
12025
12145
|
`;
|
|
12026
12146
|
}
|
|
12027
|
-
const newRaw =
|
|
12147
|
+
const newRaw = matter8.stringify(updatedContent, data);
|
|
12028
12148
|
writeFile(filePath, newRaw);
|
|
12029
12149
|
}
|
|
12030
12150
|
async function runLearn(artifactId) {
|
|
@@ -12274,7 +12394,7 @@ function runAdd(moduleName, opts = {}, dir = cwd()) {
|
|
|
12274
12394
|
}
|
|
12275
12395
|
|
|
12276
12396
|
// src/core/ownership-suggest.ts
|
|
12277
|
-
import
|
|
12397
|
+
import matter9 from "gray-matter";
|
|
12278
12398
|
var SCAN_PATH = ".kaddo/scan.json";
|
|
12279
12399
|
function normalizeGlob(input) {
|
|
12280
12400
|
let g = input.trim().replace(/\\/g, "/");
|
|
@@ -12396,11 +12516,11 @@ function suggestGlobs(artifact, signals) {
|
|
|
12396
12516
|
return [...new Set(out)];
|
|
12397
12517
|
}
|
|
12398
12518
|
function applyOwnership(raw, globs, mode = "replace") {
|
|
12399
|
-
const parsed =
|
|
12519
|
+
const parsed = matter9(raw);
|
|
12400
12520
|
const existing = toStringArray3(parsed.data.code);
|
|
12401
12521
|
const next = mode === "append" ? [.../* @__PURE__ */ new Set([...existing, ...globs])] : [...new Set(globs)];
|
|
12402
12522
|
const data = { ...parsed.data, code: next };
|
|
12403
|
-
return
|
|
12523
|
+
return matter9.stringify(parsed.content, data);
|
|
12404
12524
|
}
|
|
12405
12525
|
|
|
12406
12526
|
// src/commands/owners.ts
|
|
@@ -15012,7 +15132,7 @@ function runGraphExport(opts = {}) {
|
|
|
15012
15132
|
}
|
|
15013
15133
|
|
|
15014
15134
|
// src/core/impact-report.ts
|
|
15015
|
-
import
|
|
15135
|
+
import matter10 from "gray-matter";
|
|
15016
15136
|
function isBroadGlob(glob) {
|
|
15017
15137
|
if (!glob.endsWith("/**")) return false;
|
|
15018
15138
|
const prefix = glob.slice(0, -3);
|
|
@@ -15081,7 +15201,7 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
|
|
|
15081
15201
|
}
|
|
15082
15202
|
}
|
|
15083
15203
|
try {
|
|
15084
|
-
const body =
|
|
15204
|
+
const body = matter10(readFile(wi.filePath)).content;
|
|
15085
15205
|
if (hasSection(body, /acceptance|criterios de aceptaci/i)) withAcceptance++;
|
|
15086
15206
|
else gaps.missing_acceptance_criteria.push(gapItem(wi, "Add an `## Acceptance Criteria` section."));
|
|
15087
15207
|
if (hasSection(body, /definition of done|^#{1,6}\s*dod\b|definici[oó]n de (terminado|hecho)/i)) withDoD++;
|