@kaddo/mcp 3.39.1 → 3.40.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 +87 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2433,6 +2433,76 @@ 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 slugify(s) {
|
|
2440
|
+
return s.toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
|
|
2441
|
+
}
|
|
2442
|
+
function parseDecisionCandidates(md) {
|
|
2443
|
+
const out = [];
|
|
2444
|
+
for (const line of md.split(/\r?\n/)) {
|
|
2445
|
+
const m = line.match(/^##\s+(.+?)\s*$/);
|
|
2446
|
+
if (m) {
|
|
2447
|
+
const t = m[1].trim();
|
|
2448
|
+
if (t && !/^_.*_$/.test(t)) out.push(t);
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
return out;
|
|
2452
|
+
}
|
|
2453
|
+
function countAdrs(dir) {
|
|
2454
|
+
const base = join(dir, DECISIONS_DIR);
|
|
2455
|
+
if (!exists(base)) return { total: 0, draft: 0, accepted: 0 };
|
|
2456
|
+
let total = 0;
|
|
2457
|
+
let draft = 0;
|
|
2458
|
+
let accepted = 0;
|
|
2459
|
+
for (const entry of readDir(base)) {
|
|
2460
|
+
if (!entry.endsWith(".md") || entry === ".gitkeep") continue;
|
|
2461
|
+
const full = join(base, entry);
|
|
2462
|
+
if (!isFile(full)) continue;
|
|
2463
|
+
total += 1;
|
|
2464
|
+
let content = "";
|
|
2465
|
+
try {
|
|
2466
|
+
content = readFile(full);
|
|
2467
|
+
} catch {
|
|
2468
|
+
continue;
|
|
2469
|
+
}
|
|
2470
|
+
const status = content.match(/^\s*status:\s*([a-z-]+)/im)?.[1]?.toLowerCase();
|
|
2471
|
+
if (status === "accepted") accepted += 1;
|
|
2472
|
+
else draft += 1;
|
|
2473
|
+
}
|
|
2474
|
+
return { total, draft, accepted };
|
|
2475
|
+
}
|
|
2476
|
+
function buildTechDecisions(dir) {
|
|
2477
|
+
const candFile = join(dir, CANDIDATES_PATH);
|
|
2478
|
+
let titles = [];
|
|
2479
|
+
if (exists(candFile)) {
|
|
2480
|
+
try {
|
|
2481
|
+
titles = parseDecisionCandidates(readFile(candFile));
|
|
2482
|
+
} catch {
|
|
2483
|
+
titles = [];
|
|
2484
|
+
}
|
|
2485
|
+
}
|
|
2486
|
+
const { total, draft, accepted } = countAdrs(dir);
|
|
2487
|
+
const candidate_list = titles.map((title, i) => {
|
|
2488
|
+
const n = String(total + i + 1).padStart(3, "0");
|
|
2489
|
+
return { title, source: CANDIDATES_PATH, suggestedAdrFile: `${DECISIONS_DIR}/ADR-${n}-${slugify(title)}.md` };
|
|
2490
|
+
});
|
|
2491
|
+
let status;
|
|
2492
|
+
if (accepted > 0) status = "accepted-adrs";
|
|
2493
|
+
else if (total > 0) status = "draft-adrs";
|
|
2494
|
+
else if (titles.length > 0) status = "candidates";
|
|
2495
|
+
else status = "none";
|
|
2496
|
+
return {
|
|
2497
|
+
status,
|
|
2498
|
+
candidates: titles.length,
|
|
2499
|
+
adrs: total,
|
|
2500
|
+
draft_adrs: draft,
|
|
2501
|
+
accepted_adrs: accepted,
|
|
2502
|
+
candidate_list
|
|
2503
|
+
};
|
|
2504
|
+
}
|
|
2505
|
+
|
|
2436
2506
|
// ../cli/src/core/project-explain.ts
|
|
2437
2507
|
var ARCH_DIR2 = "knowledge";
|
|
2438
2508
|
function normalizeTitle(t) {
|
|
@@ -2644,7 +2714,8 @@ function buildProjectExplanation(dir) {
|
|
|
2644
2714
|
missingKnowledge,
|
|
2645
2715
|
suggestedNextSteps,
|
|
2646
2716
|
readiness,
|
|
2647
|
-
nextStepRecommendation: readiness.nextStepRecommendation
|
|
2717
|
+
nextStepRecommendation: readiness.nextStepRecommendation,
|
|
2718
|
+
techDecisions: buildTechDecisions(dir)
|
|
2648
2719
|
};
|
|
2649
2720
|
}
|
|
2650
2721
|
function stateLabel(state) {
|
|
@@ -2858,6 +2929,16 @@ function renderExplanationHuman(exp) {
|
|
|
2858
2929
|
lines.push("### Recommended next step");
|
|
2859
2930
|
lines.push(r.recommended_next_step.label);
|
|
2860
2931
|
lines.push("");
|
|
2932
|
+
const td = exp.techDecisions;
|
|
2933
|
+
lines.push("## Tech Decisions");
|
|
2934
|
+
lines.push(`- Decision candidates: ${td.candidates}`);
|
|
2935
|
+
lines.push(`- ADRs: ${td.adrs} (draft: ${td.draft_adrs}, accepted: ${td.accepted_adrs})`);
|
|
2936
|
+
lines.push(`- Status: ${td.status}`);
|
|
2937
|
+
if (td.candidates > 0 && td.adrs === 0) {
|
|
2938
|
+
lines.push("");
|
|
2939
|
+
lines.push("Use the adr-writing skill to materialize decision candidates into ADRs (`kaddo adr`) before implementing related technical Work Items.");
|
|
2940
|
+
}
|
|
2941
|
+
lines.push("");
|
|
2861
2942
|
return lines.join("\n").trimEnd() + "\n";
|
|
2862
2943
|
}
|
|
2863
2944
|
function renderExplanationAgent(exp) {
|
|
@@ -4313,6 +4394,10 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
|
|
|
4313
4394
|
}
|
|
4314
4395
|
});
|
|
4315
4396
|
const nextStepRecommendation = resolveNextStep(dir, now);
|
|
4397
|
+
const techDecisions = buildTechDecisions(dir);
|
|
4398
|
+
if (techDecisions.candidates > 0 && techDecisions.adrs === 0) {
|
|
4399
|
+
missing.push(`${techDecisions.candidates} technical decision candidate(s) not yet materialized as ADRs (run \`kaddo adr\`).`);
|
|
4400
|
+
}
|
|
4316
4401
|
const unifiedPhase = {
|
|
4317
4402
|
...phase,
|
|
4318
4403
|
nextStep: nextStepRecommendation.label,
|
|
@@ -4350,6 +4435,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
|
|
|
4350
4435
|
roadmap,
|
|
4351
4436
|
phase: unifiedPhase,
|
|
4352
4437
|
nextStepRecommendation,
|
|
4438
|
+
techDecisions,
|
|
4353
4439
|
deliveryMix,
|
|
4354
4440
|
external: loadExternalCapsules(dir),
|
|
4355
4441
|
graph: loadGraphSummary(dir),
|
package/package.json
CHANGED