@kaddo/mcp 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.
- package/dist/index.js +115 -12
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -274,7 +274,7 @@ function join(...parts) {
|
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
// ../cli/src/core/impact-report.ts
|
|
277
|
-
import
|
|
277
|
+
import matter8 from "gray-matter";
|
|
278
278
|
|
|
279
279
|
// ../cli/src/core/config.ts
|
|
280
280
|
import { z } from "zod";
|
|
@@ -2496,9 +2496,6 @@ function resolveNextStep(dir, now = /* @__PURE__ */ new Date()) {
|
|
|
2496
2496
|
if (!exists(join(dir, ".kaddo", "context-pack.md"))) {
|
|
2497
2497
|
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." };
|
|
2498
2498
|
}
|
|
2499
|
-
if (!exists(join(dir, ".kaddo", "understand.md"))) {
|
|
2500
|
-
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." };
|
|
2501
|
-
}
|
|
2502
2499
|
const discovery = state === "pre-ai" || state === "legacy";
|
|
2503
2500
|
const resolveAgent = (agent) => {
|
|
2504
2501
|
const file = agent.endsWith(".md") ? agent : `${agent}.md`;
|
|
@@ -2538,6 +2535,9 @@ function resolveNextStep(dir, now = /* @__PURE__ */ new Date()) {
|
|
|
2538
2535
|
const agent = ctx.agents.includes("codebase-agent") ? "codebase-agent" : "architecture-agent";
|
|
2539
2536
|
return refine("refine-codebase", agent, CB, qCodebase);
|
|
2540
2537
|
}
|
|
2538
|
+
if (!exists(join(dir, ".kaddo", "understand.md"))) {
|
|
2539
|
+
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." };
|
|
2540
|
+
}
|
|
2541
2541
|
const oq = buildOpenQuestionsReport(dir, now);
|
|
2542
2542
|
if (oq.summary.blocking_open > 0) {
|
|
2543
2543
|
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.` };
|
|
@@ -3445,16 +3445,49 @@ function renderSkillsSection(agent) {
|
|
|
3445
3445
|
""
|
|
3446
3446
|
].join("\n");
|
|
3447
3447
|
}
|
|
3448
|
+
var KNOWLEDGE_REFINING_AGENTS = {
|
|
3449
|
+
"business-agent": "business-agent",
|
|
3450
|
+
"capability-agent": "capability-agent",
|
|
3451
|
+
"bootstrap-agent": "bootstrap-agent",
|
|
3452
|
+
"codebase-agent": "codebase-agent",
|
|
3453
|
+
"architecture-agent": "architecture-agent",
|
|
3454
|
+
"roadmap-agent": "roadmap-agent",
|
|
3455
|
+
"legacy-agent": "legacy-agent",
|
|
3456
|
+
"work-item-agent": "work-item-agent",
|
|
3457
|
+
"backlog-agent": "backlog-agent",
|
|
3458
|
+
"adr-agent": "adr-agent",
|
|
3459
|
+
"implementation-agent": "implementation-agent"
|
|
3460
|
+
};
|
|
3461
|
+
function renderFrontmatterRules(agent) {
|
|
3462
|
+
if (!KNOWLEDGE_REFINING_AGENTS[agent]) return "";
|
|
3463
|
+
return [
|
|
3464
|
+
"## Frontmatter Rules",
|
|
3465
|
+
"",
|
|
3466
|
+
"When rewriting an existing Kaddo knowledge file:",
|
|
3467
|
+
"",
|
|
3468
|
+
"- Preserve the existing YAML frontmatter.",
|
|
3469
|
+
"- Do not remove `type`, `generated_by`, or `template_version`.",
|
|
3470
|
+
"- If the document is no longer a placeholder, set `project_state: ai-assisted`.",
|
|
3471
|
+
`- Add or update \`refined_by: ${agent}\`.`,
|
|
3472
|
+
"- Preserve unknown frontmatter keys \u2014 do not strip fields you do not recognize.",
|
|
3473
|
+
"- Only rewrite the markdown body unless metadata changes are explicitly required by these rules.",
|
|
3474
|
+
"- Preserve structural sections like `## Open Questions` \u2014 leave them empty rather than removing them.",
|
|
3475
|
+
""
|
|
3476
|
+
].join("\n");
|
|
3477
|
+
}
|
|
3448
3478
|
function withResponsibilityTrace(fileName, content) {
|
|
3449
3479
|
const agent = fileName.replace(/\.md$/, "");
|
|
3450
3480
|
if (!RESPONSIBILITY_MATRIX[agent]) return content;
|
|
3451
3481
|
const skills = renderSkillsSection(agent);
|
|
3452
3482
|
const skillsBlock = skills ? `${skills}
|
|
3483
|
+
` : "";
|
|
3484
|
+
const frontmatter = renderFrontmatterRules(agent);
|
|
3485
|
+
const frontmatterBlock = frontmatter ? `${frontmatter}
|
|
3453
3486
|
` : "";
|
|
3454
3487
|
return `${content.trimEnd()}
|
|
3455
3488
|
|
|
3456
3489
|
${renderLanguageRule()}
|
|
3457
|
-
${renderAgentBoundaries(agent)}
|
|
3490
|
+
${frontmatterBlock}${renderAgentBoundaries(agent)}
|
|
3458
3491
|
${skillsBlock}${renderAgentTrace(agent)}`;
|
|
3459
3492
|
}
|
|
3460
3493
|
|
|
@@ -5986,7 +6019,6 @@ function mapNextStepId(id) {
|
|
|
5986
6019
|
"add-skills": "enable-kaddo",
|
|
5987
6020
|
scan: "scan-repository",
|
|
5988
6021
|
context: "scan-repository",
|
|
5989
|
-
understand: "scan-repository",
|
|
5990
6022
|
"refine-business": "define-business",
|
|
5991
6023
|
"refine-product": "define-product",
|
|
5992
6024
|
"refine-capabilities": "discover-capabilities",
|
|
@@ -6074,6 +6106,54 @@ function renderRouteCompact(route) {
|
|
|
6074
6106
|
return lines.join("\n");
|
|
6075
6107
|
}
|
|
6076
6108
|
|
|
6109
|
+
// ../cli/src/core/metadata-health.ts
|
|
6110
|
+
import matter7 from "gray-matter";
|
|
6111
|
+
var KNOWLEDGE_FILES2 = [
|
|
6112
|
+
"knowledge/business/business.md",
|
|
6113
|
+
"knowledge/product/product.md",
|
|
6114
|
+
"knowledge/product/capabilities.md",
|
|
6115
|
+
"knowledge/tech/codebase.md",
|
|
6116
|
+
"knowledge/tech/current-state.md",
|
|
6117
|
+
"knowledge/delivery/roadmap.md"
|
|
6118
|
+
];
|
|
6119
|
+
var REQUIRED_FIELDS = ["type", "generated_by", "template_version"];
|
|
6120
|
+
function analyzeMetadataHealth(dir) {
|
|
6121
|
+
const findings = [];
|
|
6122
|
+
let healthy = 0;
|
|
6123
|
+
let drifted = 0;
|
|
6124
|
+
for (const rel of KNOWLEDGE_FILES2) {
|
|
6125
|
+
const p = join(dir, rel);
|
|
6126
|
+
if (!exists(p)) continue;
|
|
6127
|
+
let data;
|
|
6128
|
+
try {
|
|
6129
|
+
const raw = readFile(p);
|
|
6130
|
+
data = matter7(raw).data;
|
|
6131
|
+
} catch {
|
|
6132
|
+
continue;
|
|
6133
|
+
}
|
|
6134
|
+
if (Object.keys(data).length === 0) continue;
|
|
6135
|
+
let fileDrifted = false;
|
|
6136
|
+
for (const field of REQUIRED_FIELDS) {
|
|
6137
|
+
if (data[field] === void 0 || data[field] === null || data[field] === "") {
|
|
6138
|
+
findings.push({ file: rel, field, issue: "missing", detail: `Missing \`${field}\` in frontmatter.` });
|
|
6139
|
+
fileDrifted = true;
|
|
6140
|
+
}
|
|
6141
|
+
}
|
|
6142
|
+
if (data.refined_by && data.project_state && data.project_state !== "ai-assisted") {
|
|
6143
|
+
findings.push({
|
|
6144
|
+
file: rel,
|
|
6145
|
+
field: "project_state",
|
|
6146
|
+
issue: "inconsistent",
|
|
6147
|
+
detail: `File has \`refined_by: ${data.refined_by}\` but \`project_state\` is \`${data.project_state}\`, expected \`ai-assisted\`.`
|
|
6148
|
+
});
|
|
6149
|
+
fileDrifted = true;
|
|
6150
|
+
}
|
|
6151
|
+
if (fileDrifted) drifted++;
|
|
6152
|
+
else healthy++;
|
|
6153
|
+
}
|
|
6154
|
+
return { findings, healthy, drifted };
|
|
6155
|
+
}
|
|
6156
|
+
|
|
6077
6157
|
// ../cli/src/core/project-explain.ts
|
|
6078
6158
|
var ARCH_DIR2 = "knowledge";
|
|
6079
6159
|
function normalizeTitle(t) {
|
|
@@ -6336,7 +6416,8 @@ function buildProjectExplanation(dir) {
|
|
|
6336
6416
|
installedAssets: installedAssetsSummary(dir),
|
|
6337
6417
|
roadmapQuality: buildRoadmapQuality(dir),
|
|
6338
6418
|
projectRoute: buildProjectRoute(dir),
|
|
6339
|
-
scanSignals: loadScanSignals(dir)
|
|
6419
|
+
scanSignals: loadScanSignals(dir),
|
|
6420
|
+
metadataHealth: analyzeMetadataHealth(dir)
|
|
6340
6421
|
};
|
|
6341
6422
|
}
|
|
6342
6423
|
function stateLabel(state) {
|
|
@@ -6645,6 +6726,13 @@ function renderExplanationHuman(exp) {
|
|
|
6645
6726
|
}
|
|
6646
6727
|
lines.push("");
|
|
6647
6728
|
}
|
|
6729
|
+
if (exp.metadataHealth.findings.length > 0) {
|
|
6730
|
+
lines.push("## Metadata Health");
|
|
6731
|
+
for (const f of exp.metadataHealth.findings) {
|
|
6732
|
+
lines.push(`- \`${f.file}\`: ${f.detail}`);
|
|
6733
|
+
}
|
|
6734
|
+
lines.push("");
|
|
6735
|
+
}
|
|
6648
6736
|
return lines.join("\n").trimEnd() + "\n";
|
|
6649
6737
|
}
|
|
6650
6738
|
function renderExplanationAgent(exp) {
|
|
@@ -6844,7 +6932,7 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
|
|
|
6844
6932
|
}
|
|
6845
6933
|
}
|
|
6846
6934
|
try {
|
|
6847
|
-
const body =
|
|
6935
|
+
const body = matter8(readFile(wi.filePath)).content;
|
|
6848
6936
|
if (hasSection(body, /acceptance|criterios de aceptaci/i)) withAcceptance++;
|
|
6849
6937
|
else gaps.missing_acceptance_criteria.push(gapItem(wi, "Add an `## Acceptance Criteria` section."));
|
|
6850
6938
|
if (hasSection(body, /definition of done|^#{1,6}\s*dod\b|definici[oó]n de (terminado|hecho)/i)) withDoD++;
|
|
@@ -7557,7 +7645,7 @@ function serializeDriftJson(r) {
|
|
|
7557
7645
|
}
|
|
7558
7646
|
|
|
7559
7647
|
// src/workitems.ts
|
|
7560
|
-
import
|
|
7648
|
+
import matter9 from "gray-matter";
|
|
7561
7649
|
var VALID_SOURCES2 = /* @__PURE__ */ new Set(["manual", "roadmap", "jira", "github", "notion", "xlsx", "csv", "api", "external", "unknown"]);
|
|
7562
7650
|
function optStr2(v) {
|
|
7563
7651
|
return typeof v === "string" && v.trim() ? v.trim() : void 0;
|
|
@@ -7598,7 +7686,7 @@ function listWorkItems(root) {
|
|
|
7598
7686
|
if (raw === null) continue;
|
|
7599
7687
|
let parsed;
|
|
7600
7688
|
try {
|
|
7601
|
-
parsed =
|
|
7689
|
+
parsed = matter9(raw);
|
|
7602
7690
|
} catch {
|
|
7603
7691
|
continue;
|
|
7604
7692
|
}
|
|
@@ -8061,7 +8149,7 @@ function listGraphHints(root, filter = {}) {
|
|
|
8061
8149
|
}
|
|
8062
8150
|
|
|
8063
8151
|
// ../cli/src/core/context-pack.ts
|
|
8064
|
-
import
|
|
8152
|
+
import matter10 from "gray-matter";
|
|
8065
8153
|
var CONTEXT_PACK_VERSION = "1";
|
|
8066
8154
|
var ARCH_DIR3 = "knowledge";
|
|
8067
8155
|
function readScanJson(dir) {
|
|
@@ -8074,7 +8162,7 @@ function readScanJson(dir) {
|
|
|
8074
8162
|
}
|
|
8075
8163
|
}
|
|
8076
8164
|
function firstParagraph3(markdown) {
|
|
8077
|
-
const body =
|
|
8165
|
+
const body = matter10(markdown).content.trim();
|
|
8078
8166
|
const para = body.split("\n\n").map((p) => p.trim()).find((p) => p && !p.startsWith("#"));
|
|
8079
8167
|
return para ?? "";
|
|
8080
8168
|
}
|
|
@@ -8289,6 +8377,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
|
|
|
8289
8377
|
skills: discoverInstalledSkills(dir).map((s) => s.id),
|
|
8290
8378
|
scanSignals: scanJson?.signals ?? null,
|
|
8291
8379
|
projectRoute: buildProjectRoute(dir),
|
|
8380
|
+
metadataHealth: analyzeMetadataHealth(dir),
|
|
8292
8381
|
mappedModules,
|
|
8293
8382
|
missing,
|
|
8294
8383
|
// VS-052/VS-073.2: the handoff is driven by the unified next step, so the pack never contradicts
|
|
@@ -8577,6 +8666,13 @@ function renderContextPack(pack) {
|
|
|
8577
8666
|
} else {
|
|
8578
8667
|
parts.push("_None \u2014 all expected context is present._\n");
|
|
8579
8668
|
}
|
|
8669
|
+
if (pack.metadataHealth.findings.length > 0) {
|
|
8670
|
+
parts.push("\n### Metadata Health\n");
|
|
8671
|
+
for (const f of pack.metadataHealth.findings) {
|
|
8672
|
+
parts.push(`- \`${f.file}\`: ${f.detail}
|
|
8673
|
+
`);
|
|
8674
|
+
}
|
|
8675
|
+
}
|
|
8580
8676
|
parts.push("## Recommended Agent Handoff\n");
|
|
8581
8677
|
if (isBootstrapIncomplete) {
|
|
8582
8678
|
parts.push("No agent handoff yet.\n");
|
|
@@ -8884,6 +8980,13 @@ function renderUnderstand(plan) {
|
|
|
8884
8980
|
} else {
|
|
8885
8981
|
parts.push("Re-run `kaddo understand` any time to see this plan again.\n");
|
|
8886
8982
|
}
|
|
8983
|
+
if (plan.metadataHealth && plan.metadataHealth.findings.length > 0) {
|
|
8984
|
+
parts.push("## Metadata Health\n");
|
|
8985
|
+
for (const f of plan.metadataHealth.findings) {
|
|
8986
|
+
parts.push(`- \`${f.file}\`: ${f.detail}
|
|
8987
|
+
`);
|
|
8988
|
+
}
|
|
8989
|
+
}
|
|
8887
8990
|
return parts.join("\n");
|
|
8888
8991
|
}
|
|
8889
8992
|
|
package/package.json
CHANGED