@kaddo/mcp 3.129.0 → 3.129.2
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 +149 -134
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25921,101 +25921,97 @@ function relFromDir(dir, filePath) {
|
|
|
25921
25921
|
function sha256(content) {
|
|
25922
25922
|
return createHash3("sha256").update(content, "utf-8").digest("hex");
|
|
25923
25923
|
}
|
|
25924
|
-
var
|
|
25925
|
-
|
|
25926
|
-
|
|
25927
|
-
|
|
25928
|
-
"intent",
|
|
25929
|
-
"goal",
|
|
25930
|
-
"objetivo",
|
|
25931
|
-
"summary",
|
|
25932
|
-
"resumen",
|
|
25933
|
-
"overview",
|
|
25934
|
-
"context",
|
|
25935
|
-
"contexto",
|
|
25936
|
-
"scope",
|
|
25937
|
-
"alcance",
|
|
25938
|
-
"out of scope",
|
|
25939
|
-
"fuera de alcance",
|
|
25940
|
-
"acceptance criteria",
|
|
25941
|
-
"criterios de aceptacion",
|
|
25942
|
-
"criterios de aceptaci\xF3n",
|
|
25943
|
-
"validation",
|
|
25944
|
-
"validation scenarios",
|
|
25945
|
-
"validacion",
|
|
25946
|
-
"validaci\xF3n",
|
|
25947
|
-
"escenarios de validacion",
|
|
25948
|
-
"escenarios de validaci\xF3n",
|
|
25949
|
-
"notes",
|
|
25950
|
-
"notas",
|
|
25951
|
-
"references",
|
|
25952
|
-
"referencias",
|
|
25953
|
-
"examples",
|
|
25954
|
-
"ejemplos",
|
|
25955
|
-
"learning",
|
|
25956
|
-
"learnings",
|
|
25957
|
-
"aprendizaje",
|
|
25958
|
-
"aprendizajes",
|
|
25959
|
-
// Work Item template sections
|
|
25960
|
-
"problem",
|
|
25961
|
-
"problema",
|
|
25962
|
-
"expected result",
|
|
25963
|
-
"resultado esperado",
|
|
25964
|
-
"refinement",
|
|
25965
|
-
"refinamiento",
|
|
25966
|
-
"implementation guidance",
|
|
25967
|
-
"guia de implementacion",
|
|
25968
|
-
"gu\xEDa de implementaci\xF3n",
|
|
25969
|
-
"definition of done",
|
|
25970
|
-
"definicion de hecho",
|
|
25971
|
-
"definici\xF3n de hecho",
|
|
25972
|
-
"commit gate",
|
|
25973
|
-
"future evolution",
|
|
25974
|
-
"evolucion futura",
|
|
25975
|
-
"evoluci\xF3n futura",
|
|
25976
|
-
"guiding principle",
|
|
25977
|
-
"principio rector",
|
|
25978
|
-
"open questions",
|
|
25979
|
-
"preguntas abiertas",
|
|
25980
|
-
"dependencies",
|
|
25981
|
-
"dependencias",
|
|
25982
|
-
"conceptual model",
|
|
25983
|
-
"goal"
|
|
25984
|
-
]);
|
|
25985
|
-
var RULE_KEYWORDS = [
|
|
25986
|
-
"siempre",
|
|
25987
|
-
"nunca",
|
|
25988
|
-
"debe",
|
|
25989
|
-
"deben",
|
|
25990
|
-
"requiere",
|
|
25991
|
-
"requieren",
|
|
25992
|
-
"invariante",
|
|
25993
|
-
"restriccion",
|
|
25994
|
-
"restricci\xF3n",
|
|
25995
|
-
"regla",
|
|
25996
|
-
"obligatorio",
|
|
25997
|
-
"must",
|
|
25998
|
-
"always",
|
|
25999
|
-
"never",
|
|
26000
|
-
"require",
|
|
26001
|
-
"requires",
|
|
26002
|
-
"constraint",
|
|
26003
|
-
"invariant",
|
|
26004
|
-
"rule"
|
|
26005
|
-
];
|
|
26006
|
-
function normalizeHeading(h2) {
|
|
26007
|
-
return h2.trim().toLowerCase().replace(/\s+/g, " ");
|
|
25924
|
+
var SHINGLE_SIZE = 6;
|
|
25925
|
+
var MIN_SHARED_RUN = 6;
|
|
25926
|
+
function stripNoise(text3) {
|
|
25927
|
+
return text3.replace(/```[\s\S]*?```/g, " ").replace(/`[^`]*`/g, " ").replace(/https?:\/\/\S+|www\.\S+/gi, " ");
|
|
26008
25928
|
}
|
|
26009
|
-
function
|
|
26010
|
-
const
|
|
26011
|
-
|
|
26012
|
-
|
|
26013
|
-
|
|
26014
|
-
|
|
26015
|
-
|
|
26016
|
-
|
|
25929
|
+
function contentBlocks(body) {
|
|
25930
|
+
const blocks = [];
|
|
25931
|
+
let cur = [];
|
|
25932
|
+
let inFence = false;
|
|
25933
|
+
const flush = () => {
|
|
25934
|
+
if (cur.length) blocks.push(cur);
|
|
25935
|
+
cur = [];
|
|
25936
|
+
};
|
|
25937
|
+
for (const raw of body.split(/\r?\n/)) {
|
|
25938
|
+
const t = raw.trim();
|
|
25939
|
+
if (/^```/.test(t)) {
|
|
25940
|
+
inFence = !inFence;
|
|
25941
|
+
flush();
|
|
25942
|
+
continue;
|
|
25943
|
+
}
|
|
25944
|
+
if (inFence) continue;
|
|
25945
|
+
if (t === "" || /^#{1,6}\s/.test(t) || /^>/.test(t)) {
|
|
25946
|
+
flush();
|
|
25947
|
+
continue;
|
|
25948
|
+
}
|
|
25949
|
+
const isListItem = /^([-*+]\s+|\d+\.\s+)/.test(t);
|
|
25950
|
+
if (isListItem) flush();
|
|
25951
|
+
const text3 = stripNoise(t.replace(/^([-*+]\s+|\d+\.\s+)/, ""));
|
|
25952
|
+
const matched = text3.toLowerCase().match(/[a-záéíóúñü0-9]+/gi);
|
|
25953
|
+
if (matched) cur.push(...matched);
|
|
26017
25954
|
}
|
|
26018
|
-
|
|
25955
|
+
flush();
|
|
25956
|
+
return blocks;
|
|
25957
|
+
}
|
|
25958
|
+
function buildShingles(body) {
|
|
25959
|
+
const blocks = contentBlocks(body);
|
|
25960
|
+
const set = /* @__PURE__ */ new Set();
|
|
25961
|
+
for (const block of blocks) {
|
|
25962
|
+
for (let i = 0; i + SHINGLE_SIZE <= block.length; i++) {
|
|
25963
|
+
set.add(block.slice(i, i + SHINGLE_SIZE).join(" "));
|
|
25964
|
+
}
|
|
25965
|
+
}
|
|
25966
|
+
return { blocks, set };
|
|
25967
|
+
}
|
|
25968
|
+
function longestSharedRun(a2, b2) {
|
|
25969
|
+
let best = 0;
|
|
25970
|
+
let bestSnippet = "";
|
|
25971
|
+
for (const block of a2.blocks) {
|
|
25972
|
+
let run = 0;
|
|
25973
|
+
let runStart = 0;
|
|
25974
|
+
for (let i = 0; i + SHINGLE_SIZE <= block.length; i++) {
|
|
25975
|
+
const key = block.slice(i, i + SHINGLE_SIZE).join(" ");
|
|
25976
|
+
if (b2.set.has(key)) {
|
|
25977
|
+
if (run === 0) runStart = i;
|
|
25978
|
+
run += 1;
|
|
25979
|
+
if (run > best) {
|
|
25980
|
+
best = run;
|
|
25981
|
+
bestSnippet = block.slice(runStart, runStart + SHINGLE_SIZE + run - 1).join(" ");
|
|
25982
|
+
}
|
|
25983
|
+
} else {
|
|
25984
|
+
run = 0;
|
|
25985
|
+
}
|
|
25986
|
+
}
|
|
25987
|
+
}
|
|
25988
|
+
return { length: best, snippet: bestSnippet };
|
|
25989
|
+
}
|
|
25990
|
+
var NORMATIVE_RE = /(^|[^a-záéíóúñü])(must|should|shall|debe[ns]?|deber[ií]a[ns]?|se\s+debe|hay\s+que|requiere[ns]?|require[sd]?|no\s+debe|invariant[e]?|invariants|restricci[oó]n|constraint|regla|obligatori[oa])([^a-záéíóúñü]|$)/i;
|
|
25991
|
+
var PAST_RESULT_RE = /(compil[aoeéó]\w*|compiled|benchmark\w*|passed|succeed\w*|succeeded|ran\s+successfully|ejecut\w*|resultad\w*|crates?\b|ns\/op|µs\b|throughput|latenc\w*|baseline|measured|medid\w*|\d+\s*%|\bx\d|faster|slower)/i;
|
|
25992
|
+
var TEST_RE = /(\btest\w*|\bpruebas?\b|coverage|cobertura|verde[s]?|green\b|assert\w*)/i;
|
|
25993
|
+
var BENCH_RE = /(benchmark\w*|ns\/op|µs\b|throughput|latenc\w*|ops\/s|\d+\s*%|faster|slower|baseline)/i;
|
|
25994
|
+
var EXPERIMENT_RE = /(experiment\w*|experiment[oa]\w*|prototyp\w*|prototip\w*|spike\b|probamos|probé|intentamos)/i;
|
|
25995
|
+
function splitSentences(text3) {
|
|
25996
|
+
return text3.replace(/\s+/g, " ").split(/(?<=[.!?;])\s+/).map((s) => s.trim()).filter(Boolean);
|
|
25997
|
+
}
|
|
25998
|
+
function classifyLearningSentence(sentence) {
|
|
25999
|
+
const s = sentence.trim();
|
|
26000
|
+
if (!s) return "none";
|
|
26001
|
+
const normative = NORMATIVE_RE.test(s);
|
|
26002
|
+
const pastResult = PAST_RESULT_RE.test(s);
|
|
26003
|
+
if (normative && !pastResult) return "durable-rule";
|
|
26004
|
+
if (BENCH_RE.test(s)) return "benchmark-evidence";
|
|
26005
|
+
if (pastResult) return "historical-result";
|
|
26006
|
+
if (TEST_RE.test(s)) return "test-observation";
|
|
26007
|
+
if (EXPERIMENT_RE.test(s)) return "experimental-result";
|
|
26008
|
+
return "none";
|
|
26009
|
+
}
|
|
26010
|
+
function firstRuleFragment(learning) {
|
|
26011
|
+
for (const sentence of splitSentences(learning)) {
|
|
26012
|
+
if (classifyLearningSentence(sentence) === "durable-rule") return sentence;
|
|
26013
|
+
}
|
|
26014
|
+
return null;
|
|
26019
26015
|
}
|
|
26020
26016
|
function sectionBody(body, titles) {
|
|
26021
26017
|
const lines = body.split(/\r?\n/);
|
|
@@ -26099,32 +26095,33 @@ function buildConsolidationPlan(dir, opts = {}) {
|
|
|
26099
26095
|
requires_semantic_review: false
|
|
26100
26096
|
});
|
|
26101
26097
|
}
|
|
26102
|
-
const
|
|
26103
|
-
|
|
26104
|
-
);
|
|
26105
|
-
const
|
|
26106
|
-
|
|
26107
|
-
|
|
26108
|
-
|
|
26098
|
+
const comparable = scoped.filter(isComparableKnowledge);
|
|
26099
|
+
const shingleIndex = /* @__PURE__ */ new Map();
|
|
26100
|
+
const shinglesByRel = /* @__PURE__ */ new Map();
|
|
26101
|
+
for (const la of comparable) {
|
|
26102
|
+
const shingles = buildShingles(la.body);
|
|
26103
|
+
shinglesByRel.set(la.rel, shingles);
|
|
26104
|
+
for (const key of shingles.set) {
|
|
26105
|
+
const arr = shingleIndex.get(key) ?? [];
|
|
26109
26106
|
arr.push(la);
|
|
26110
|
-
|
|
26107
|
+
shingleIndex.set(key, arr);
|
|
26111
26108
|
}
|
|
26112
26109
|
}
|
|
26113
|
-
const
|
|
26114
|
-
for (const
|
|
26110
|
+
const candidatePairs = /* @__PURE__ */ new Map();
|
|
26111
|
+
for (const arts of shingleIndex.values()) {
|
|
26115
26112
|
if (arts.length < 2) continue;
|
|
26116
26113
|
for (let i = 0; i < arts.length; i++) {
|
|
26117
26114
|
for (let j2 = i + 1; j2 < arts.length; j2++) {
|
|
26118
26115
|
if (arts[i].rel === arts[j2].rel) continue;
|
|
26119
26116
|
const key = [arts[i].rel, arts[j2].rel].sort().join("||");
|
|
26120
|
-
|
|
26121
|
-
entry.shared.add(heading);
|
|
26122
|
-
pairHeadings.set(key, entry);
|
|
26117
|
+
if (!candidatePairs.has(key)) candidatePairs.set(key, { a: arts[i], b: arts[j2] });
|
|
26123
26118
|
}
|
|
26124
26119
|
}
|
|
26125
26120
|
}
|
|
26126
|
-
for (const { a: a2, b: b2
|
|
26127
|
-
|
|
26121
|
+
for (const { a: a2, b: b2 } of candidatePairs.values()) {
|
|
26122
|
+
const run = longestSharedRun(shinglesByRel.get(a2.rel), shinglesByRel.get(b2.rel));
|
|
26123
|
+
if (run.length < MIN_SHARED_RUN) continue;
|
|
26124
|
+
const passageWords = SHINGLE_SIZE + run.length - 1;
|
|
26128
26125
|
opportunities.push({
|
|
26129
26126
|
id: stableOpportunityId("knowledge_redundancy", [label(a2), label(b2)]),
|
|
26130
26127
|
category: "knowledge_redundancy",
|
|
@@ -26133,18 +26130,22 @@ function buildConsolidationPlan(dir, opts = {}) {
|
|
|
26133
26130
|
title: `Possible overlapping content between ${label(a2)} and ${label(b2)}`,
|
|
26134
26131
|
source_artifacts: [label(a2), label(b2)],
|
|
26135
26132
|
target_artifacts: [label(a2), label(b2)],
|
|
26136
|
-
evidence: [
|
|
26137
|
-
|
|
26133
|
+
evidence: [
|
|
26134
|
+
`A ${passageWords}-word passage appears verbatim in both artifacts: "${redactSecrets3(run.snippet)}".`
|
|
26135
|
+
],
|
|
26136
|
+
rationale: "A verbatim shared passage is a hint of potential duplication, NOT proof. Two documents can legitimately restate context from different layers/responsibilities; shared template structure alone was NOT used.",
|
|
26138
26137
|
possible_impact: "If genuinely duplicated, the same fact can drift out of sync across files.",
|
|
26139
|
-
suggested_action: "Semantic review: compare the
|
|
26138
|
+
suggested_action: "Semantic review: compare the overlapping passage; if one restates the other, keep a single reference location and link the rest. Preserve layer separation.",
|
|
26140
26139
|
requires_semantic_review: true
|
|
26141
26140
|
});
|
|
26142
26141
|
}
|
|
26143
26142
|
for (const la of scoped) {
|
|
26144
26143
|
if (!isCompletedWorkItem(la)) continue;
|
|
26145
|
-
const
|
|
26146
|
-
if (!
|
|
26147
|
-
|
|
26144
|
+
const learningRaw = sectionBody(la.body, ["Learning", "Aprendizaje", "Aprendizajes", "Learnings"]);
|
|
26145
|
+
if (!learningRaw) continue;
|
|
26146
|
+
const learning = stripNoise(learningRaw);
|
|
26147
|
+
const ruleFragment = firstRuleFragment(learning);
|
|
26148
|
+
if (!ruleFragment) continue;
|
|
26148
26149
|
opportunities.push({
|
|
26149
26150
|
id: stableOpportunityId("unincorporated_learning", [label(la)]),
|
|
26150
26151
|
category: "unincorporated_learning",
|
|
@@ -26152,16 +26153,18 @@ function buildConsolidationPlan(dir, opts = {}) {
|
|
|
26152
26153
|
confidence: "requires-review",
|
|
26153
26154
|
title: `${label(la)} captured a learning that may belong in current knowledge`,
|
|
26154
26155
|
source_artifacts: [label(la)],
|
|
26155
|
-
target_artifacts: [
|
|
26156
|
-
|
|
26157
|
-
|
|
26156
|
+
target_artifacts: [],
|
|
26157
|
+
// unresolved — determined in semantic review (never invent a destination)
|
|
26158
|
+
evidence: [`Completed Work Item records a rule-like learning (heuristic classification): "${redactSecrets3(ruleFragment)}"`],
|
|
26159
|
+
rationale: "A sentence phrased as a durable rule MAY represent live technical knowledge not yet reflected in current knowledge. The rule/result distinction is a heuristic, not a verified conclusion \u2014 this is a candidate, not a confirmed gap.",
|
|
26158
26160
|
possible_impact: "A relevant constraint stays buried in delivery history instead of informing current work.",
|
|
26159
|
-
suggested_action: "Semantic review:
|
|
26161
|
+
suggested_action: "Semantic review: confirm whether this is a live rule and determine the right destination artifact; if so, incorporate it WITH a reference back to the Work Item. Do not delete or summarize the Work Item.",
|
|
26160
26162
|
requires_semantic_review: true
|
|
26161
26163
|
});
|
|
26162
26164
|
}
|
|
26163
26165
|
const weakByFolder = /* @__PURE__ */ new Map();
|
|
26164
26166
|
for (const la of scoped) {
|
|
26167
|
+
if (!isConsolidatableKnowledge(la)) continue;
|
|
26165
26168
|
const quality = safeQuality(dir, la.rel);
|
|
26166
26169
|
if (quality === "placeholder" || quality === "weak") {
|
|
26167
26170
|
opportunities.push({
|
|
@@ -26172,11 +26175,11 @@ function buildConsolidationPlan(dir, opts = {}) {
|
|
|
26172
26175
|
title: `${label(la)} is ${quality} and may need consolidation or expansion`,
|
|
26173
26176
|
source_artifacts: [label(la)],
|
|
26174
26177
|
target_artifacts: [label(la)],
|
|
26175
|
-
evidence: [`Artifact quality analysis classifies this artifact as "${quality}".`],
|
|
26176
|
-
rationale: "
|
|
26178
|
+
evidence: [`Artifact quality analysis classifies this canonical knowledge artifact as "${quality}".`],
|
|
26179
|
+
rationale: "Observed: the quality heuristic rates this artifact low-signal. Whether it should be expanded, merged or cross-referenced is a judgement that needs semantic review \u2014 the quality signal alone does not decide it.",
|
|
26177
26180
|
possible_impact: "Readers must open more files to assemble a complete picture.",
|
|
26178
|
-
suggested_action: "
|
|
26179
|
-
requires_semantic_review:
|
|
26181
|
+
suggested_action: "Semantic review: decide whether to expand, merge into a stronger artifact, or cross-reference it.",
|
|
26182
|
+
requires_semantic_review: true
|
|
26180
26183
|
});
|
|
26181
26184
|
const folder = la.rel.split("/").slice(0, -1).join("/");
|
|
26182
26185
|
const arr = weakByFolder.get(folder) ?? [];
|
|
@@ -26191,11 +26194,11 @@ function buildConsolidationPlan(dir, opts = {}) {
|
|
|
26191
26194
|
category: "knowledge_fragmentation",
|
|
26192
26195
|
classification: "suggested",
|
|
26193
26196
|
confidence: "requires-review",
|
|
26194
|
-
title: `${folder}/ holds ${arts.length} low-signal artifacts \u2014 possible fragmentation`,
|
|
26197
|
+
title: `${folder}/ holds ${arts.length} low-signal canonical artifacts \u2014 possible fragmentation`,
|
|
26195
26198
|
source_artifacts: arts.map((a2) => label(a2)),
|
|
26196
26199
|
target_artifacts: [folder],
|
|
26197
|
-
evidence: [`${arts.length} placeholder/weak artifacts in the same folder: ${arts.map((a2) => a2.rel.split("/").pop()).join(", ")}.`],
|
|
26198
|
-
rationale: "Several thin artifacts in one folder MAY be easier to consume if consolidated or cross-linked. Consolidation must preserve each distinct responsibility.",
|
|
26200
|
+
evidence: [`${arts.length} placeholder/weak canonical knowledge artifacts in the same folder: ${arts.map((a2) => a2.rel.split("/").pop()).join(", ")}.`],
|
|
26201
|
+
rationale: "Several thin canonical artifacts in one folder MAY be easier to consume if consolidated or cross-linked. Consolidation must preserve each distinct responsibility; Work Items and generated/lifecycle artifacts are not considered here.",
|
|
26199
26202
|
possible_impact: "Related knowledge is spread across too many files to follow.",
|
|
26200
26203
|
suggested_action: "Semantic review: evaluate whether cross-references or a consolidation would add clarity. Do not merge by file count alone.",
|
|
26201
26204
|
requires_semantic_review: true
|
|
@@ -26287,7 +26290,9 @@ function renderConsolidationMarkdown(plan) {
|
|
|
26287
26290
|
lines.push(`- Classification: **${o2.classification}**${o2.requires_semantic_review ? " (requires semantic review)" : ""}`);
|
|
26288
26291
|
lines.push(`- Confidence: ${o2.confidence}`);
|
|
26289
26292
|
lines.push(`- Source: ${o2.source_artifacts.join(", ") || "\u2014"}`);
|
|
26290
|
-
lines.push(
|
|
26293
|
+
lines.push(
|
|
26294
|
+
`- Suggested target: ${o2.target_artifacts.length > 0 ? o2.target_artifacts.join(", ") : "(unresolved \u2014 to be determined in semantic review)"}`
|
|
26295
|
+
);
|
|
26291
26296
|
lines.push(`- Evidence:`);
|
|
26292
26297
|
for (const e of o2.evidence) lines.push(` - ${e}`);
|
|
26293
26298
|
lines.push(`- Rationale: ${o2.rationale}`);
|
|
@@ -26312,15 +26317,25 @@ function isCompletedWorkItem(la) {
|
|
|
26312
26317
|
const p = toPosix8(la.artifact.filePath);
|
|
26313
26318
|
return p.includes("/delivery/work-items/completed/") || isWorkItem(la) && la.artifact.status === "completed";
|
|
26314
26319
|
}
|
|
26315
|
-
function
|
|
26316
|
-
const
|
|
26317
|
-
return
|
|
26320
|
+
function isScaffolding(la) {
|
|
26321
|
+
const p = toPosix8(la.artifact.filePath);
|
|
26322
|
+
return p.includes(`/${KNOWLEDGE7}/agents/`) || p.includes(`/${KNOWLEDGE7}/skills/`) || p.includes(`/${KNOWLEDGE7}/external/`) || la.artifact.type === "knowledge-capsule";
|
|
26323
|
+
}
|
|
26324
|
+
var NON_KNOWLEDGE_DOC_TYPES = /* @__PURE__ */ new Set([
|
|
26325
|
+
"roadmap",
|
|
26326
|
+
"initiative",
|
|
26327
|
+
"deprecation",
|
|
26328
|
+
"knowledge-capsule",
|
|
26329
|
+
"inventory",
|
|
26330
|
+
"project-resource"
|
|
26331
|
+
]);
|
|
26332
|
+
function isComparableKnowledge(la) {
|
|
26333
|
+
return !isWorkItem(la) && la.artifact.type !== "roadmap" && !isScaffolding(la);
|
|
26318
26334
|
}
|
|
26319
|
-
function
|
|
26320
|
-
|
|
26321
|
-
|
|
26322
|
-
|
|
26323
|
-
return redactSecrets3(s.trim());
|
|
26335
|
+
function isConsolidatableKnowledge(la) {
|
|
26336
|
+
if (isWorkItem(la) || isScaffolding(la)) return false;
|
|
26337
|
+
if (NON_KNOWLEDGE_DOC_TYPES.has(la.artifact.type)) return false;
|
|
26338
|
+
return la.layer === "Business" || la.layer === "Product" || la.layer === "Tech";
|
|
26324
26339
|
}
|
|
26325
26340
|
var SECRET_TOKEN_PATTERNS = [
|
|
26326
26341
|
/\bgh[pours]_[A-Za-z0-9]{16,}\b/g,
|
package/package.json
CHANGED