@kaddo/mcp 3.65.0 → 3.66.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 +125 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -521,7 +521,14 @@ function parseArtifact(filePath, raw) {
|
|
|
521
521
|
sourceId: String(data.source_id ?? ""),
|
|
522
522
|
rawFrontmatter: data,
|
|
523
523
|
decisions: Array.isArray(data.decisions) ? data.decisions.map(String).filter(Boolean) : [],
|
|
524
|
-
capsules: Array.isArray(data.capsules) ? data.capsules.map(String).filter(Boolean) : []
|
|
524
|
+
capsules: Array.isArray(data.capsules) ? data.capsules.map(String).filter(Boolean) : [],
|
|
525
|
+
implementationStatus: String(data.implementation_status ?? ""),
|
|
526
|
+
validationStatus: String(data.validation_status ?? ""),
|
|
527
|
+
releaseStatus: String(data.release_status ?? ""),
|
|
528
|
+
affectedModules: Array.isArray(data.affected_modules) ? data.affected_modules.map(String).filter(Boolean) : [],
|
|
529
|
+
refinedBy: String(data.refined_by ?? ""),
|
|
530
|
+
implementedBy: String(data.implemented_by ?? ""),
|
|
531
|
+
closedBy: String(data.closed_by ?? "")
|
|
525
532
|
};
|
|
526
533
|
} catch {
|
|
527
534
|
return null;
|
|
@@ -2413,6 +2420,7 @@ function buildGraph(dir, config, opts = {}, now = /* @__PURE__ */ new Date()) {
|
|
|
2413
2420
|
const selectedWIs = workItems.filter((a2) => a2.lifecycle && includedSet.has(a2.lifecycle));
|
|
2414
2421
|
for (const wi of selectedWIs) {
|
|
2415
2422
|
const id = wi.id || wi.title;
|
|
2423
|
+
if (!id || !id.trim()) continue;
|
|
2416
2424
|
const wiNodeId = `wi:${id}`;
|
|
2417
2425
|
addNode({
|
|
2418
2426
|
id: wiNodeId,
|
|
@@ -2423,16 +2431,19 @@ function buildGraph(dir, config, opts = {}, now = /* @__PURE__ */ new Date()) {
|
|
|
2423
2431
|
knowledge_level: wi.knowledgeLevel || void 0
|
|
2424
2432
|
});
|
|
2425
2433
|
for (const glob of wi.codeGlobs) {
|
|
2434
|
+
if (!glob || !glob.trim()) continue;
|
|
2426
2435
|
const codeId = `code:${glob}`;
|
|
2427
2436
|
addNode({ id: codeId, type: "code-glob", label: glob });
|
|
2428
2437
|
addEdge(wiNodeId, codeId, "owns");
|
|
2429
2438
|
}
|
|
2430
2439
|
for (const cap of wi.capabilities) {
|
|
2440
|
+
if (!cap || !cap.trim()) continue;
|
|
2431
2441
|
const capId = `capability:${slug(cap) || cap}`;
|
|
2432
2442
|
addNode({ id: capId, type: "capability", label: cap });
|
|
2433
2443
|
addEdge(wiNodeId, capId, "implements");
|
|
2434
2444
|
}
|
|
2435
2445
|
for (const dec of wi.decisions) {
|
|
2446
|
+
if (!dec || !dec.trim()) continue;
|
|
2436
2447
|
const adrId = `adr:${dec}`;
|
|
2437
2448
|
addNode({ id: adrId, type: "decision", label: dec });
|
|
2438
2449
|
addEdge(wiNodeId, adrId, "depends_on");
|
|
@@ -2449,16 +2460,19 @@ function buildGraph(dir, config, opts = {}, now = /* @__PURE__ */ new Date()) {
|
|
|
2449
2460
|
}
|
|
2450
2461
|
}
|
|
2451
2462
|
for (const adr of all.filter(isAdr)) {
|
|
2452
|
-
const
|
|
2463
|
+
const adrLabel = adr.id || adr.title;
|
|
2464
|
+
if (!adrLabel || !adrLabel.trim()) continue;
|
|
2465
|
+
const adrId = `adr:${adrLabel}`;
|
|
2453
2466
|
const referenced = nodes.has(adrId);
|
|
2454
2467
|
if (scope === "all" || referenced) {
|
|
2455
2468
|
nodes.set(adrId, {
|
|
2456
2469
|
id: adrId,
|
|
2457
2470
|
type: "decision",
|
|
2458
|
-
label: `${adr.id} ${adr.title}`.trim() ||
|
|
2471
|
+
label: `${adr.id} ${adr.title}`.trim() || adrLabel,
|
|
2459
2472
|
path: adr.relPath
|
|
2460
2473
|
});
|
|
2461
2474
|
for (const glob of adr.codeGlobs) {
|
|
2475
|
+
if (!glob || !glob.trim()) continue;
|
|
2462
2476
|
const codeId = `code:${glob}`;
|
|
2463
2477
|
addNode({ id: codeId, type: "code-glob", label: glob });
|
|
2464
2478
|
addEdge(adrId, codeId, "governs");
|
|
@@ -2514,13 +2528,20 @@ function renderGraphMermaid(graph) {
|
|
|
2514
2528
|
safeIds.set(id, candidate);
|
|
2515
2529
|
return candidate;
|
|
2516
2530
|
};
|
|
2517
|
-
const escapeLabel = (s) => s.replace(/"/g, "'");
|
|
2531
|
+
const escapeLabel = (s) => s.replace(/"/g, "'").replace(/\[/g, "(").replace(/\]/g, ")").replace(/\n/g, " ");
|
|
2532
|
+
const validNodes = graph.nodes.filter(
|
|
2533
|
+
(n) => n.id && n.id.trim() !== "" && n.label && n.label.trim() !== ""
|
|
2534
|
+
);
|
|
2535
|
+
const validNodeIds = new Set(validNodes.map((n) => n.id));
|
|
2518
2536
|
const lines = ["flowchart LR"];
|
|
2519
|
-
for (const node of
|
|
2537
|
+
for (const node of validNodes) {
|
|
2520
2538
|
lines.push(` ${safe(node.id)}["${escapeLabel(node.label)}"]`);
|
|
2521
2539
|
}
|
|
2522
|
-
|
|
2523
|
-
|
|
2540
|
+
const validEdges = graph.edges.filter(
|
|
2541
|
+
(e) => validNodeIds.has(e.from) && validNodeIds.has(e.to)
|
|
2542
|
+
);
|
|
2543
|
+
if (validEdges.length > 0) lines.push("");
|
|
2544
|
+
for (const edge of validEdges) {
|
|
2524
2545
|
lines.push(` ${safe(edge.from)} -->|${edge.type}| ${safe(edge.to)}`);
|
|
2525
2546
|
}
|
|
2526
2547
|
return lines.join("\n") + "\n";
|
|
@@ -8030,6 +8051,33 @@ function analyzeMetadataHealth(dir) {
|
|
|
8030
8051
|
if (fileDrifted) drifted++;
|
|
8031
8052
|
else healthy++;
|
|
8032
8053
|
}
|
|
8054
|
+
const wiDir = join(dir, "knowledge/delivery/work-items");
|
|
8055
|
+
if (exists(wiDir)) {
|
|
8056
|
+
const walkWIs = (d3) => {
|
|
8057
|
+
for (const entry of readDir(d3)) {
|
|
8058
|
+
const p = join(d3, entry);
|
|
8059
|
+
if (isFile(p) && entry.endsWith(".md")) {
|
|
8060
|
+
try {
|
|
8061
|
+
const raw = readFile(p);
|
|
8062
|
+
const fm = matter7(raw).data;
|
|
8063
|
+
if (fm.status === "done") {
|
|
8064
|
+
const rel = p.replace(dir + "/", "").replace(dir + "\\", "").replace(/\\/g, "/");
|
|
8065
|
+
findings.push({
|
|
8066
|
+
file: rel,
|
|
8067
|
+
field: "status",
|
|
8068
|
+
issue: "inconsistent",
|
|
8069
|
+
detail: "Legacy status `done` detected. Canonical status is `completed`."
|
|
8070
|
+
});
|
|
8071
|
+
}
|
|
8072
|
+
} catch {
|
|
8073
|
+
}
|
|
8074
|
+
} else if (!isFile(p) && !entry.startsWith(".")) {
|
|
8075
|
+
walkWIs(p);
|
|
8076
|
+
}
|
|
8077
|
+
}
|
|
8078
|
+
};
|
|
8079
|
+
walkWIs(wiDir);
|
|
8080
|
+
}
|
|
8033
8081
|
return { findings, healthy, drifted };
|
|
8034
8082
|
}
|
|
8035
8083
|
|
|
@@ -8319,7 +8367,30 @@ function buildProjectExplanation(dir) {
|
|
|
8319
8367
|
projectRoute: buildProjectRoute(dir),
|
|
8320
8368
|
scanSignals: loadScanSignals(dir),
|
|
8321
8369
|
metadataHealth: analyzeMetadataHealth(dir),
|
|
8322
|
-
isModuleRepo: config != null && isModule(config)
|
|
8370
|
+
isModuleRepo: config != null && isModule(config),
|
|
8371
|
+
implementationEvidence: workItemArtifacts.filter((a2) => a2.affectedModules.length > 0).map((a2) => {
|
|
8372
|
+
const fm = a2.rawFrontmatter;
|
|
8373
|
+
const evidence = fm.implementation_evidence;
|
|
8374
|
+
const repos = evidence?.repositories ?? {};
|
|
8375
|
+
const repoEvidence = {};
|
|
8376
|
+
for (const [repoId, data] of Object.entries(repos)) {
|
|
8377
|
+
repoEvidence[repoId] = {
|
|
8378
|
+
role: String(data.role ?? (repoId === "core" ? "core" : "module")),
|
|
8379
|
+
status: String(data.status ?? "unknown")
|
|
8380
|
+
};
|
|
8381
|
+
}
|
|
8382
|
+
return {
|
|
8383
|
+
id: a2.id || a2.title,
|
|
8384
|
+
lifecycle: lifecycleStateOf({ status: a2.status, filePath: a2.filePath }),
|
|
8385
|
+
implementationStatus: a2.implementationStatus || "not-started",
|
|
8386
|
+
validationStatus: a2.validationStatus || "not-started",
|
|
8387
|
+
releaseStatus: a2.releaseStatus || "not-assessed",
|
|
8388
|
+
affectedModules: a2.affectedModules,
|
|
8389
|
+
releaseGates: Array.isArray(fm.release_gates) ? fm.release_gates : [],
|
|
8390
|
+
completionExceptions: Array.isArray(fm.completion_exceptions) ? fm.completion_exceptions : [],
|
|
8391
|
+
repoEvidence
|
|
8392
|
+
};
|
|
8393
|
+
})
|
|
8323
8394
|
};
|
|
8324
8395
|
}
|
|
8325
8396
|
function stateLabel(state) {
|
|
@@ -8445,6 +8516,36 @@ function renderExplanationHuman(exp) {
|
|
|
8445
8516
|
}
|
|
8446
8517
|
lines.push("");
|
|
8447
8518
|
}
|
|
8519
|
+
if (exp.implementationEvidence.length > 0) {
|
|
8520
|
+
lines.push("## Implementation Evidence");
|
|
8521
|
+
for (const ev of exp.implementationEvidence) {
|
|
8522
|
+
lines.push("");
|
|
8523
|
+
lines.push(`### ${ev.id}`);
|
|
8524
|
+
lines.push(`- Lifecycle: ${ev.lifecycle.charAt(0).toUpperCase() + ev.lifecycle.slice(1)}`);
|
|
8525
|
+
lines.push(`- Implementation: ${ev.implementationStatus}`);
|
|
8526
|
+
lines.push(`- Validation: ${ev.validationStatus}`);
|
|
8527
|
+
lines.push(`- Release: ${ev.releaseStatus}`);
|
|
8528
|
+
if (Object.keys(ev.repoEvidence).length > 0) {
|
|
8529
|
+
lines.push("Repositories:");
|
|
8530
|
+
for (const [repoId, info] of Object.entries(ev.repoEvidence)) {
|
|
8531
|
+
lines.push(`- ${repoId} \u2014 ${info.status}`);
|
|
8532
|
+
}
|
|
8533
|
+
} else if (ev.affectedModules.length > 0) {
|
|
8534
|
+
lines.push(`Affected modules: ${ev.affectedModules.join(", ")}`);
|
|
8535
|
+
}
|
|
8536
|
+
const pendingGates = ev.releaseGates.filter((g) => g.status === "blocked" || g.status === "pending");
|
|
8537
|
+
if (pendingGates.length > 0) {
|
|
8538
|
+
lines.push("Pending release gates:");
|
|
8539
|
+
for (const g of pendingGates) lines.push(`- ${g.id}${g.reason ? ` \u2014 ${g.reason}` : ""}`);
|
|
8540
|
+
}
|
|
8541
|
+
const acceptedExceptions = ev.completionExceptions.filter((e) => e.status === "accepted" || e.status === "deferred");
|
|
8542
|
+
if (acceptedExceptions.length > 0) {
|
|
8543
|
+
lines.push("Completion exceptions:");
|
|
8544
|
+
for (const e of acceptedExceptions) lines.push(`- ${e.id}: ${e.status}${e.reason ? ` \u2014 ${e.reason}` : ""}`);
|
|
8545
|
+
}
|
|
8546
|
+
}
|
|
8547
|
+
lines.push("");
|
|
8548
|
+
}
|
|
8448
8549
|
if (exp.domains.length > 0) {
|
|
8449
8550
|
lines.push("## Domains");
|
|
8450
8551
|
lines.push(`- ${exp.domains.join(", ")}`);
|
|
@@ -9641,7 +9742,16 @@ function listWorkItems(root) {
|
|
|
9641
9742
|
capsules: strArray(data.capsules),
|
|
9642
9743
|
source,
|
|
9643
9744
|
domains,
|
|
9644
|
-
readiness
|
|
9745
|
+
readiness,
|
|
9746
|
+
...data.implementation_status ? { implementation_status: String(data.implementation_status) } : {},
|
|
9747
|
+
...data.validation_status ? { validation_status: String(data.validation_status) } : {},
|
|
9748
|
+
...data.release_status ? { release_status: String(data.release_status) } : {},
|
|
9749
|
+
...Array.isArray(data.affected_modules) && data.affected_modules.length > 0 ? { affected_modules: data.affected_modules.map(String) } : {},
|
|
9750
|
+
...data.refined_by ? { refined_by: String(data.refined_by) } : {},
|
|
9751
|
+
...data.implemented_by ? { implemented_by: String(data.implemented_by) } : {},
|
|
9752
|
+
...data.closed_by ? { closed_by: String(data.closed_by) } : {},
|
|
9753
|
+
...Array.isArray(data.release_gates) && data.release_gates.length > 0 ? { release_gates: data.release_gates } : {},
|
|
9754
|
+
...Array.isArray(data.completion_exceptions) && data.completion_exceptions.length > 0 ? { completion_exceptions: data.completion_exceptions } : {}
|
|
9645
9755
|
});
|
|
9646
9756
|
}
|
|
9647
9757
|
return items.sort((a2, b2) => a2.id.localeCompare(b2.id));
|
|
@@ -10766,7 +10876,7 @@ var OPERATING_RULES = [
|
|
|
10766
10876
|
"Kaddo itself never calls an LLM and never runs git \u2014 every git action is the human\u2019s."
|
|
10767
10877
|
];
|
|
10768
10878
|
function toContextWorkItem(a2) {
|
|
10769
|
-
|
|
10879
|
+
const wi = {
|
|
10770
10880
|
id: a2.id,
|
|
10771
10881
|
type: a2.type,
|
|
10772
10882
|
title: a2.title,
|
|
@@ -10776,6 +10886,11 @@ function toContextWorkItem(a2) {
|
|
|
10776
10886
|
domains: a2.domains,
|
|
10777
10887
|
source: parseWorkItemSource(a2.rawFrontmatter)
|
|
10778
10888
|
};
|
|
10889
|
+
if (a2.implementationStatus) wi.implementationStatus = a2.implementationStatus;
|
|
10890
|
+
if (a2.validationStatus) wi.validationStatus = a2.validationStatus;
|
|
10891
|
+
if (a2.releaseStatus) wi.releaseStatus = a2.releaseStatus;
|
|
10892
|
+
if (a2.affectedModules.length > 0) wi.affectedModules = a2.affectedModules;
|
|
10893
|
+
return wi;
|
|
10779
10894
|
}
|
|
10780
10895
|
function toContextArtifact(a2) {
|
|
10781
10896
|
return { id: a2.id, type: a2.type, title: a2.title, summary: a2.summary, codeGlobs: a2.codeGlobs };
|
package/package.json
CHANGED