@kaddo/mcp 3.106.0 → 3.107.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 +146 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19055,6 +19055,110 @@ function materializeCandidate(dir, id, candidateId) {
|
|
|
19055
19055
|
if (!updated) throw new InitiativeWriteError("Failed to parse the Initiative after materialization.");
|
|
19056
19056
|
return { workItemId: wiId, fileName, initiative: updated };
|
|
19057
19057
|
}
|
|
19058
|
+
var SUCCESS_HEADING_RE = /^#{1,6}\s*(success criteria|criterios de[ét]xito|criterios de éxito)\s*$/i;
|
|
19059
|
+
var HEADING_RE2 = /^#{1,6}\s+/;
|
|
19060
|
+
var CHECK_ITEM_RE = /^\s*[-*]\s+\[([ xX])\]\s+(.*)$/;
|
|
19061
|
+
var BULLET_RE2 = /^\s*[-*]\s+(.*)$/;
|
|
19062
|
+
var PLACEHOLDER_RE = /^_.*_$/;
|
|
19063
|
+
function parseSuccessCriteria(body) {
|
|
19064
|
+
const lines = body.split(/\r?\n/);
|
|
19065
|
+
const out = [];
|
|
19066
|
+
let capture = false;
|
|
19067
|
+
for (const line of lines) {
|
|
19068
|
+
if (capture && HEADING_RE2.test(line)) break;
|
|
19069
|
+
if (!capture) {
|
|
19070
|
+
if (SUCCESS_HEADING_RE.test(line.trim())) capture = true;
|
|
19071
|
+
continue;
|
|
19072
|
+
}
|
|
19073
|
+
const check = line.match(CHECK_ITEM_RE);
|
|
19074
|
+
if (check) {
|
|
19075
|
+
const text22 = check[2].trim();
|
|
19076
|
+
if (text22 && !PLACEHOLDER_RE.test(text22)) {
|
|
19077
|
+
out.push({ text: text22, checked: check[1].toLowerCase() === "x" });
|
|
19078
|
+
}
|
|
19079
|
+
continue;
|
|
19080
|
+
}
|
|
19081
|
+
const bullet = line.match(BULLET_RE2);
|
|
19082
|
+
if (bullet) {
|
|
19083
|
+
const text22 = bullet[1].trim();
|
|
19084
|
+
if (text22 && !PLACEHOLDER_RE.test(text22)) out.push({ text: text22, checked: null });
|
|
19085
|
+
}
|
|
19086
|
+
}
|
|
19087
|
+
return out;
|
|
19088
|
+
}
|
|
19089
|
+
function analyzeInitiative(dir, ini) {
|
|
19090
|
+
const progress = computeInitiativeProgress(dir, ini);
|
|
19091
|
+
const successCriteria = parseSuccessCriteria(ini.body);
|
|
19092
|
+
const pendingCandidates = ini.candidates.filter((c) => !c.materializedAs);
|
|
19093
|
+
const associated = associatedWorkItems(dir, ini.id);
|
|
19094
|
+
const findings = [];
|
|
19095
|
+
if (successCriteria.length === 0) {
|
|
19096
|
+
findings.push({
|
|
19097
|
+
code: "no-success-criteria",
|
|
19098
|
+
severity: "warning",
|
|
19099
|
+
message: "The Initiative has no explicit Success Criteria; completion cannot be judged by outcome, only by delivery."
|
|
19100
|
+
});
|
|
19101
|
+
} else {
|
|
19102
|
+
const uncovered = successCriteria.filter((c) => c.checked === false);
|
|
19103
|
+
if (uncovered.length > 0) {
|
|
19104
|
+
findings.push({
|
|
19105
|
+
code: "uncovered-success-criteria",
|
|
19106
|
+
severity: "blocking",
|
|
19107
|
+
message: `${uncovered.length} success criterion/criteria remain uncovered.`,
|
|
19108
|
+
items: uncovered.map((c) => c.text)
|
|
19109
|
+
});
|
|
19110
|
+
}
|
|
19111
|
+
}
|
|
19112
|
+
if (pendingCandidates.length > 0) {
|
|
19113
|
+
findings.push({
|
|
19114
|
+
code: "pending-candidates",
|
|
19115
|
+
severity: "blocking",
|
|
19116
|
+
message: `${pendingCandidates.length} committed candidate(s) not yet materialized into Work Items.`,
|
|
19117
|
+
items: pendingCandidates.map((c) => `${c.id}: ${c.title}`)
|
|
19118
|
+
});
|
|
19119
|
+
}
|
|
19120
|
+
const notCompleted = associated.filter((w3) => w3.status !== "completed" && w3.status !== "archived");
|
|
19121
|
+
if (associated.length === 0) {
|
|
19122
|
+
findings.push({
|
|
19123
|
+
code: "no-delivery",
|
|
19124
|
+
severity: "info",
|
|
19125
|
+
message: "No Work Items are associated with this Initiative yet."
|
|
19126
|
+
});
|
|
19127
|
+
} else if (notCompleted.length > 0) {
|
|
19128
|
+
findings.push({
|
|
19129
|
+
code: "incomplete-delivery",
|
|
19130
|
+
severity: "blocking",
|
|
19131
|
+
message: `${notCompleted.length} associated Work Item(s) are not completed.`,
|
|
19132
|
+
items: notCompleted.map((w3) => `${w3.id} (${w3.status})`)
|
|
19133
|
+
});
|
|
19134
|
+
}
|
|
19135
|
+
return {
|
|
19136
|
+
initiative: ini.id,
|
|
19137
|
+
status: ini.status,
|
|
19138
|
+
progress,
|
|
19139
|
+
successCriteria,
|
|
19140
|
+
pendingCandidates,
|
|
19141
|
+
findings,
|
|
19142
|
+
suggestedCandidates: pendingCandidates
|
|
19143
|
+
};
|
|
19144
|
+
}
|
|
19145
|
+
function evaluateInitiativeCompletion(dir, ini) {
|
|
19146
|
+
const analysis = analyzeInitiative(dir, ini);
|
|
19147
|
+
const reasons = [];
|
|
19148
|
+
for (const f3 of analysis.findings) {
|
|
19149
|
+
if (f3.severity === "blocking") reasons.push(f3.message);
|
|
19150
|
+
}
|
|
19151
|
+
if (analysis.progress.delivery.total === 0 && analysis.pendingCandidates.length === 0) {
|
|
19152
|
+
reasons.push("Nothing has been delivered or committed under this Initiative.");
|
|
19153
|
+
}
|
|
19154
|
+
const ready = reasons.length === 0;
|
|
19155
|
+
return {
|
|
19156
|
+
initiative: ini.id,
|
|
19157
|
+
ready,
|
|
19158
|
+
readiness: ready ? "ready" : "not-ready",
|
|
19159
|
+
reasons
|
|
19160
|
+
};
|
|
19161
|
+
}
|
|
19058
19162
|
|
|
19059
19163
|
// src/tools.ts
|
|
19060
19164
|
var ok = (data) => ({ ok: true, data });
|
|
@@ -22673,6 +22777,30 @@ function materializeInitiativeCandidateTool(root, args) {
|
|
|
22673
22777
|
() => materializeCandidate(root, args.id, args.candidateId)
|
|
22674
22778
|
);
|
|
22675
22779
|
}
|
|
22780
|
+
function analyzeInitiativeTool(root, id) {
|
|
22781
|
+
const ini = getInitiative(root, id);
|
|
22782
|
+
if (!ini) return fail4(`Initiative ${id} not found.`);
|
|
22783
|
+
return ok5(analyzeInitiative(root, ini));
|
|
22784
|
+
}
|
|
22785
|
+
function completeInitiativeTool(root, args) {
|
|
22786
|
+
const ini = getInitiative(root, args.id);
|
|
22787
|
+
if (!ini) return fail4(`Initiative ${args.id} not found.`);
|
|
22788
|
+
const readiness = evaluateInitiativeCompletion(root, ini);
|
|
22789
|
+
if (!args.confirm) {
|
|
22790
|
+
return ok5({
|
|
22791
|
+
action: "complete-initiative",
|
|
22792
|
+
readiness,
|
|
22793
|
+
instruction: readiness.ready ? "Initiative looks ready. Call again with confirm=true to complete (human decision)." : "Initiative is NOT ready (see readiness.reasons). Completion requires an explicit human decision: call again with confirm=true only if the human chooses to complete anyway."
|
|
22794
|
+
});
|
|
22795
|
+
}
|
|
22796
|
+
try {
|
|
22797
|
+
const done = transitionInitiative(root, args.id, "completed");
|
|
22798
|
+
return ok5({ applied: true, readiness, result: { id: done.id, status: done.status } });
|
|
22799
|
+
} catch (err) {
|
|
22800
|
+
if (err instanceof InitiativeWriteError) return fail4(err.message);
|
|
22801
|
+
throw err;
|
|
22802
|
+
}
|
|
22803
|
+
}
|
|
22676
22804
|
|
|
22677
22805
|
// src/server.ts
|
|
22678
22806
|
var SERVER_NAME = "kaddo";
|
|
@@ -23156,6 +23284,24 @@ function createServer(root) {
|
|
|
23156
23284
|
},
|
|
23157
23285
|
async (args) => toolText(guarded(root, () => materializeInitiativeCandidateTool(root, args)))
|
|
23158
23286
|
);
|
|
23287
|
+
server.registerTool(
|
|
23288
|
+
"kaddo_analyze_initiative",
|
|
23289
|
+
{
|
|
23290
|
+
title: "Analyze initiative",
|
|
23291
|
+
description: `Read-only gap analysis: success-criteria coverage, pending candidates, delivery status, grounded findings, and the Initiative's own pending candidates as suggestions. Never invents work. ${INITIATIVE_READ_NOTE}`,
|
|
23292
|
+
inputSchema: { id: z4.string() }
|
|
23293
|
+
},
|
|
23294
|
+
async (args) => toolText(guarded(root, () => analyzeInitiativeTool(root, args.id)))
|
|
23295
|
+
);
|
|
23296
|
+
server.registerTool(
|
|
23297
|
+
"kaddo_complete_initiative",
|
|
23298
|
+
{
|
|
23299
|
+
title: "Complete initiative",
|
|
23300
|
+
description: "Human-gated completion. Without confirm returns completion readiness (does NOT complete). With confirm=true transitions the Initiative to completed; readiness findings are returned either way so uncovered scope stays visible. Never completes autonomously.",
|
|
23301
|
+
inputSchema: { id: z4.string(), confirm: z4.boolean().optional() }
|
|
23302
|
+
},
|
|
23303
|
+
async (args) => toolText(guarded(root, () => completeInitiativeTool(root, args)))
|
|
23304
|
+
);
|
|
23159
23305
|
server.registerTool(
|
|
23160
23306
|
"kaddo_telemetry_status",
|
|
23161
23307
|
{
|
package/package.json
CHANGED