@kaddo/mcp 3.39.1 → 3.40.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.
- package/dist/index.js +104 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2433,6 +2433,81 @@ function buildReadinessReport(dir, now = /* @__PURE__ */ new Date()) {
|
|
|
2433
2433
|
};
|
|
2434
2434
|
}
|
|
2435
2435
|
|
|
2436
|
+
// ../cli/src/core/decisions.ts
|
|
2437
|
+
var CANDIDATES_PATH = "knowledge/tech/decision-candidates.md";
|
|
2438
|
+
var DECISIONS_DIR = "knowledge/tech/decisions";
|
|
2439
|
+
function cleanCandidateTitle(title) {
|
|
2440
|
+
return title.replace(/^\s*#{1,6}\s+/, "").replace(/^\s*[-*]\s+/, "").replace(/^\s*\(?\d+\)?[.):]\s+/, "").trim();
|
|
2441
|
+
}
|
|
2442
|
+
function slugify(s) {
|
|
2443
|
+
return cleanCandidateTitle(s).toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "").slice(0, 70).replace(/-+$/g, "");
|
|
2444
|
+
}
|
|
2445
|
+
function parseDecisionCandidates(md) {
|
|
2446
|
+
const out = [];
|
|
2447
|
+
for (const line of md.split(/\r?\n/)) {
|
|
2448
|
+
const m = line.match(/^##\s+(.+?)\s*$/);
|
|
2449
|
+
if (m) {
|
|
2450
|
+
const raw = m[1].trim();
|
|
2451
|
+
if (!raw || /^_.*_$/.test(raw)) continue;
|
|
2452
|
+
const t = cleanCandidateTitle(raw);
|
|
2453
|
+
if (t) out.push(t);
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
return out;
|
|
2457
|
+
}
|
|
2458
|
+
function countAdrs(dir) {
|
|
2459
|
+
const base = join(dir, DECISIONS_DIR);
|
|
2460
|
+
if (!exists(base)) return { total: 0, draft: 0, accepted: 0 };
|
|
2461
|
+
let total = 0;
|
|
2462
|
+
let draft = 0;
|
|
2463
|
+
let accepted = 0;
|
|
2464
|
+
for (const entry of readDir(base)) {
|
|
2465
|
+
if (!entry.endsWith(".md") || entry === ".gitkeep") continue;
|
|
2466
|
+
const full = join(base, entry);
|
|
2467
|
+
if (!isFile(full)) continue;
|
|
2468
|
+
total += 1;
|
|
2469
|
+
let content = "";
|
|
2470
|
+
try {
|
|
2471
|
+
content = readFile(full);
|
|
2472
|
+
} catch {
|
|
2473
|
+
continue;
|
|
2474
|
+
}
|
|
2475
|
+
const status = content.match(/^\s*status:\s*([a-z-]+)/im)?.[1]?.toLowerCase();
|
|
2476
|
+
if (status === "accepted") accepted += 1;
|
|
2477
|
+
else draft += 1;
|
|
2478
|
+
}
|
|
2479
|
+
return { total, draft, accepted };
|
|
2480
|
+
}
|
|
2481
|
+
function buildTechDecisions(dir) {
|
|
2482
|
+
const candFile = join(dir, CANDIDATES_PATH);
|
|
2483
|
+
let titles = [];
|
|
2484
|
+
if (exists(candFile)) {
|
|
2485
|
+
try {
|
|
2486
|
+
titles = parseDecisionCandidates(readFile(candFile));
|
|
2487
|
+
} catch {
|
|
2488
|
+
titles = [];
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
const { total, draft, accepted } = countAdrs(dir);
|
|
2492
|
+
const candidate_list = titles.map((title, i) => {
|
|
2493
|
+
const n = String(total + i + 1).padStart(3, "0");
|
|
2494
|
+
return { title, source: CANDIDATES_PATH, suggestedAdrFile: `${DECISIONS_DIR}/ADR-${n}-${slugify(title)}.md` };
|
|
2495
|
+
});
|
|
2496
|
+
let status;
|
|
2497
|
+
if (accepted > 0) status = "accepted-adrs";
|
|
2498
|
+
else if (total > 0) status = "draft-adrs";
|
|
2499
|
+
else if (titles.length > 0) status = "candidates";
|
|
2500
|
+
else status = "none";
|
|
2501
|
+
return {
|
|
2502
|
+
status,
|
|
2503
|
+
candidates: titles.length,
|
|
2504
|
+
adrs: total,
|
|
2505
|
+
draft_adrs: draft,
|
|
2506
|
+
accepted_adrs: accepted,
|
|
2507
|
+
candidate_list
|
|
2508
|
+
};
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2436
2511
|
// ../cli/src/core/project-explain.ts
|
|
2437
2512
|
var ARCH_DIR2 = "knowledge";
|
|
2438
2513
|
function normalizeTitle(t) {
|
|
@@ -2644,7 +2719,8 @@ function buildProjectExplanation(dir) {
|
|
|
2644
2719
|
missingKnowledge,
|
|
2645
2720
|
suggestedNextSteps,
|
|
2646
2721
|
readiness,
|
|
2647
|
-
nextStepRecommendation: readiness.nextStepRecommendation
|
|
2722
|
+
nextStepRecommendation: readiness.nextStepRecommendation,
|
|
2723
|
+
techDecisions: buildTechDecisions(dir)
|
|
2648
2724
|
};
|
|
2649
2725
|
}
|
|
2650
2726
|
function stateLabel(state) {
|
|
@@ -2858,6 +2934,16 @@ function renderExplanationHuman(exp) {
|
|
|
2858
2934
|
lines.push("### Recommended next step");
|
|
2859
2935
|
lines.push(r.recommended_next_step.label);
|
|
2860
2936
|
lines.push("");
|
|
2937
|
+
const td = exp.techDecisions;
|
|
2938
|
+
lines.push("## Tech Decisions");
|
|
2939
|
+
lines.push(`- Decision candidates: ${td.candidates}`);
|
|
2940
|
+
lines.push(`- ADRs: ${td.adrs} (draft: ${td.draft_adrs}, accepted: ${td.accepted_adrs})`);
|
|
2941
|
+
lines.push(`- Status: ${td.status}`);
|
|
2942
|
+
if (td.candidates > 0 && td.adrs === 0) {
|
|
2943
|
+
lines.push("");
|
|
2944
|
+
lines.push("Use the adr-writing skill to materialize decision candidates into ADRs (`kaddo adr`) before implementing related technical Work Items.");
|
|
2945
|
+
}
|
|
2946
|
+
lines.push("");
|
|
2861
2947
|
return lines.join("\n").trimEnd() + "\n";
|
|
2862
2948
|
}
|
|
2863
2949
|
function renderExplanationAgent(exp) {
|
|
@@ -4044,6 +4130,18 @@ var RESOURCES = [
|
|
|
4044
4130
|
}
|
|
4045
4131
|
return [{ uri: "kaddo://roadmap-readiness", text: JSON.stringify(roadmapReadinessSummary(root), null, 2), mimeType: "application/json" }];
|
|
4046
4132
|
}
|
|
4133
|
+
},
|
|
4134
|
+
{
|
|
4135
|
+
uri: "kaddo://tech-decisions",
|
|
4136
|
+
name: "Kaddo tech decisions",
|
|
4137
|
+
description: "Technical decision candidates vs materialized ADRs (status, counts, candidate list with suggested ADR filenames). Read-only; shares buildTechDecisions with `kaddo adr`.",
|
|
4138
|
+
mimeType: "application/json",
|
|
4139
|
+
read: (root) => {
|
|
4140
|
+
if (!hasKnowledge(root)) {
|
|
4141
|
+
return text("kaddo://tech-decisions", "Knowledge repository not found. Run `kaddo bootstrap` first.", "text/plain");
|
|
4142
|
+
}
|
|
4143
|
+
return [{ uri: "kaddo://tech-decisions", text: JSON.stringify(buildTechDecisions(root), null, 2), mimeType: "application/json" }];
|
|
4144
|
+
}
|
|
4047
4145
|
}
|
|
4048
4146
|
];
|
|
4049
4147
|
|
|
@@ -4313,6 +4411,10 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
|
|
|
4313
4411
|
}
|
|
4314
4412
|
});
|
|
4315
4413
|
const nextStepRecommendation = resolveNextStep(dir, now);
|
|
4414
|
+
const techDecisions = buildTechDecisions(dir);
|
|
4415
|
+
if (techDecisions.candidates > 0 && techDecisions.adrs === 0) {
|
|
4416
|
+
missing.push(`${techDecisions.candidates} technical decision candidate(s) not yet materialized as ADRs (run \`kaddo adr\`).`);
|
|
4417
|
+
}
|
|
4316
4418
|
const unifiedPhase = {
|
|
4317
4419
|
...phase,
|
|
4318
4420
|
nextStep: nextStepRecommendation.label,
|
|
@@ -4350,6 +4452,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
|
|
|
4350
4452
|
roadmap,
|
|
4351
4453
|
phase: unifiedPhase,
|
|
4352
4454
|
nextStepRecommendation,
|
|
4455
|
+
techDecisions,
|
|
4353
4456
|
deliveryMix,
|
|
4354
4457
|
external: loadExternalCapsules(dir),
|
|
4355
4458
|
graph: loadGraphSummary(dir),
|
package/package.json
CHANGED