@kaddo/mcp 3.129.0 → 3.129.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 +133 -133
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25921,101 +25921,83 @@ 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
|
-
|
|
25929
|
-
|
|
25930
|
-
|
|
25931
|
-
|
|
25932
|
-
|
|
25933
|
-
|
|
25934
|
-
|
|
25935
|
-
|
|
25936
|
-
|
|
25937
|
-
|
|
25938
|
-
|
|
25939
|
-
|
|
25940
|
-
|
|
25941
|
-
|
|
25942
|
-
|
|
25943
|
-
|
|
25944
|
-
|
|
25945
|
-
|
|
25946
|
-
|
|
25947
|
-
|
|
25948
|
-
|
|
25949
|
-
|
|
25950
|
-
|
|
25951
|
-
|
|
25952
|
-
|
|
25953
|
-
|
|
25954
|
-
|
|
25955
|
-
|
|
25956
|
-
|
|
25957
|
-
|
|
25958
|
-
|
|
25959
|
-
|
|
25960
|
-
|
|
25961
|
-
|
|
25962
|
-
|
|
25963
|
-
|
|
25964
|
-
|
|
25965
|
-
|
|
25966
|
-
|
|
25967
|
-
|
|
25968
|
-
|
|
25969
|
-
|
|
25970
|
-
|
|
25971
|
-
|
|
25972
|
-
"
|
|
25973
|
-
"
|
|
25974
|
-
|
|
25975
|
-
|
|
25976
|
-
|
|
25977
|
-
|
|
25978
|
-
|
|
25979
|
-
|
|
25980
|
-
|
|
25981
|
-
|
|
25982
|
-
"
|
|
25983
|
-
|
|
25984
|
-
|
|
25985
|
-
|
|
25986
|
-
"
|
|
25987
|
-
|
|
25988
|
-
|
|
25989
|
-
"
|
|
25990
|
-
"
|
|
25991
|
-
"
|
|
25992
|
-
"
|
|
25993
|
-
"
|
|
25994
|
-
"
|
|
25995
|
-
|
|
25996
|
-
|
|
25997
|
-
|
|
25998
|
-
|
|
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, " ");
|
|
26008
|
-
}
|
|
26009
|
-
function distinctiveHeadings(body) {
|
|
26010
|
-
const out = [];
|
|
26011
|
-
for (const line of body.split(/\r?\n/)) {
|
|
26012
|
-
const m2 = line.match(/^#{2,3}\s+(.+?)\s*$/);
|
|
26013
|
-
if (!m2) continue;
|
|
26014
|
-
const norm = normalizeHeading(m2[1]);
|
|
26015
|
-
if (!norm || GENERIC_HEADINGS.has(norm)) continue;
|
|
26016
|
-
out.push(norm);
|
|
25924
|
+
var SHINGLE_SIZE = 6;
|
|
25925
|
+
var MIN_SHARED_RUN = 6;
|
|
25926
|
+
function contentWords(body) {
|
|
25927
|
+
const words = [];
|
|
25928
|
+
let inFence = false;
|
|
25929
|
+
for (const raw of body.split(/\r?\n/)) {
|
|
25930
|
+
const t = raw.trim();
|
|
25931
|
+
if (/^```/.test(t)) {
|
|
25932
|
+
inFence = !inFence;
|
|
25933
|
+
continue;
|
|
25934
|
+
}
|
|
25935
|
+
if (inFence) continue;
|
|
25936
|
+
if (/^#{1,6}\s/.test(t)) continue;
|
|
25937
|
+
if (/^>/.test(t)) continue;
|
|
25938
|
+
const text3 = t.replace(/^([-*+]\s+|\d+\.\s+)/, "");
|
|
25939
|
+
const matched = text3.toLowerCase().match(/[a-záéíóúñü0-9]+/gi);
|
|
25940
|
+
if (matched) words.push(...matched);
|
|
25941
|
+
}
|
|
25942
|
+
return words;
|
|
25943
|
+
}
|
|
25944
|
+
function buildShingles(body) {
|
|
25945
|
+
const words = contentWords(body);
|
|
25946
|
+
const keys = [];
|
|
25947
|
+
const set = /* @__PURE__ */ new Set();
|
|
25948
|
+
for (let i = 0; i + SHINGLE_SIZE <= words.length; i++) {
|
|
25949
|
+
const key = words.slice(i, i + SHINGLE_SIZE).join(" ");
|
|
25950
|
+
keys.push(key);
|
|
25951
|
+
set.add(key);
|
|
25952
|
+
}
|
|
25953
|
+
return { words, keys, set };
|
|
25954
|
+
}
|
|
25955
|
+
function longestSharedRun(a2, b2) {
|
|
25956
|
+
let best = 0;
|
|
25957
|
+
let bestStart = -1;
|
|
25958
|
+
let run = 0;
|
|
25959
|
+
let runStart = 0;
|
|
25960
|
+
for (let i = 0; i < a2.keys.length; i++) {
|
|
25961
|
+
if (b2.set.has(a2.keys[i])) {
|
|
25962
|
+
if (run === 0) runStart = i;
|
|
25963
|
+
run += 1;
|
|
25964
|
+
if (run > best) {
|
|
25965
|
+
best = run;
|
|
25966
|
+
bestStart = runStart;
|
|
25967
|
+
}
|
|
25968
|
+
} else {
|
|
25969
|
+
run = 0;
|
|
25970
|
+
}
|
|
25971
|
+
}
|
|
25972
|
+
if (best === 0) return { length: 0, snippet: "" };
|
|
25973
|
+
const snippet = a2.words.slice(bestStart, bestStart + SHINGLE_SIZE + best - 1).join(" ");
|
|
25974
|
+
return { length: best, snippet };
|
|
25975
|
+
}
|
|
25976
|
+
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;
|
|
25977
|
+
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;
|
|
25978
|
+
var TEST_RE = /(\btest\w*|\bpruebas?\b|coverage|cobertura|verde[s]?|green\b|assert\w*)/i;
|
|
25979
|
+
var BENCH_RE = /(benchmark\w*|ns\/op|µs\b|throughput|latenc\w*|ops\/s|\d+\s*%|faster|slower|baseline)/i;
|
|
25980
|
+
var EXPERIMENT_RE = /(experiment\w*|experiment[oa]\w*|prototyp\w*|prototip\w*|spike\b|probamos|probé|intentamos)/i;
|
|
25981
|
+
function splitSentences(text3) {
|
|
25982
|
+
return text3.replace(/\s+/g, " ").split(/(?<=[.!?;])\s+/).map((s) => s.trim()).filter(Boolean);
|
|
25983
|
+
}
|
|
25984
|
+
function classifyLearningSentence(sentence) {
|
|
25985
|
+
const s = sentence.trim();
|
|
25986
|
+
if (!s) return "none";
|
|
25987
|
+
const normative = NORMATIVE_RE.test(s);
|
|
25988
|
+
const pastResult = PAST_RESULT_RE.test(s);
|
|
25989
|
+
if (normative && !pastResult) return "durable-rule";
|
|
25990
|
+
if (BENCH_RE.test(s)) return "benchmark-evidence";
|
|
25991
|
+
if (pastResult) return "historical-result";
|
|
25992
|
+
if (TEST_RE.test(s)) return "test-observation";
|
|
25993
|
+
if (EXPERIMENT_RE.test(s)) return "experimental-result";
|
|
25994
|
+
return "none";
|
|
25995
|
+
}
|
|
25996
|
+
function firstRuleFragment(learning) {
|
|
25997
|
+
for (const sentence of splitSentences(learning)) {
|
|
25998
|
+
if (classifyLearningSentence(sentence) === "durable-rule") return sentence;
|
|
26017
25999
|
}
|
|
26018
|
-
return
|
|
26000
|
+
return null;
|
|
26019
26001
|
}
|
|
26020
26002
|
function sectionBody(body, titles) {
|
|
26021
26003
|
const lines = body.split(/\r?\n/);
|
|
@@ -26099,32 +26081,33 @@ function buildConsolidationPlan(dir, opts = {}) {
|
|
|
26099
26081
|
requires_semantic_review: false
|
|
26100
26082
|
});
|
|
26101
26083
|
}
|
|
26102
|
-
const
|
|
26103
|
-
|
|
26104
|
-
);
|
|
26105
|
-
const
|
|
26106
|
-
|
|
26107
|
-
|
|
26108
|
-
|
|
26084
|
+
const comparable = scoped.filter(isComparableKnowledge);
|
|
26085
|
+
const shingleIndex = /* @__PURE__ */ new Map();
|
|
26086
|
+
const shinglesByRel = /* @__PURE__ */ new Map();
|
|
26087
|
+
for (const la of comparable) {
|
|
26088
|
+
const shingles = buildShingles(la.body);
|
|
26089
|
+
shinglesByRel.set(la.rel, shingles);
|
|
26090
|
+
for (const key of shingles.set) {
|
|
26091
|
+
const arr = shingleIndex.get(key) ?? [];
|
|
26109
26092
|
arr.push(la);
|
|
26110
|
-
|
|
26093
|
+
shingleIndex.set(key, arr);
|
|
26111
26094
|
}
|
|
26112
26095
|
}
|
|
26113
|
-
const
|
|
26114
|
-
for (const
|
|
26096
|
+
const candidatePairs = /* @__PURE__ */ new Map();
|
|
26097
|
+
for (const arts of shingleIndex.values()) {
|
|
26115
26098
|
if (arts.length < 2) continue;
|
|
26116
26099
|
for (let i = 0; i < arts.length; i++) {
|
|
26117
26100
|
for (let j2 = i + 1; j2 < arts.length; j2++) {
|
|
26118
26101
|
if (arts[i].rel === arts[j2].rel) continue;
|
|
26119
26102
|
const key = [arts[i].rel, arts[j2].rel].sort().join("||");
|
|
26120
|
-
|
|
26121
|
-
entry.shared.add(heading);
|
|
26122
|
-
pairHeadings.set(key, entry);
|
|
26103
|
+
if (!candidatePairs.has(key)) candidatePairs.set(key, { a: arts[i], b: arts[j2] });
|
|
26123
26104
|
}
|
|
26124
26105
|
}
|
|
26125
26106
|
}
|
|
26126
|
-
for (const { a: a2, b: b2
|
|
26127
|
-
|
|
26107
|
+
for (const { a: a2, b: b2 } of candidatePairs.values()) {
|
|
26108
|
+
const run = longestSharedRun(shinglesByRel.get(a2.rel), shinglesByRel.get(b2.rel));
|
|
26109
|
+
if (run.length < MIN_SHARED_RUN) continue;
|
|
26110
|
+
const passageWords = SHINGLE_SIZE + run.length - 1;
|
|
26128
26111
|
opportunities.push({
|
|
26129
26112
|
id: stableOpportunityId("knowledge_redundancy", [label(a2), label(b2)]),
|
|
26130
26113
|
category: "knowledge_redundancy",
|
|
@@ -26133,10 +26116,12 @@ function buildConsolidationPlan(dir, opts = {}) {
|
|
|
26133
26116
|
title: `Possible overlapping content between ${label(a2)} and ${label(b2)}`,
|
|
26134
26117
|
source_artifacts: [label(a2), label(b2)],
|
|
26135
26118
|
target_artifacts: [label(a2), label(b2)],
|
|
26136
|
-
evidence: [
|
|
26137
|
-
|
|
26119
|
+
evidence: [
|
|
26120
|
+
`A ${passageWords}-word passage appears verbatim in both artifacts: "${redactSecrets3(run.snippet)}".`
|
|
26121
|
+
],
|
|
26122
|
+
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
26123
|
possible_impact: "If genuinely duplicated, the same fact can drift out of sync across files.",
|
|
26139
|
-
suggested_action: "Semantic review: compare the
|
|
26124
|
+
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
26125
|
requires_semantic_review: true
|
|
26141
26126
|
});
|
|
26142
26127
|
}
|
|
@@ -26144,7 +26129,8 @@ function buildConsolidationPlan(dir, opts = {}) {
|
|
|
26144
26129
|
if (!isCompletedWorkItem(la)) continue;
|
|
26145
26130
|
const learning = sectionBody(la.body, ["Learning", "Aprendizaje", "Aprendizajes", "Learnings"]);
|
|
26146
26131
|
if (!learning) continue;
|
|
26147
|
-
|
|
26132
|
+
const ruleFragment = firstRuleFragment(learning);
|
|
26133
|
+
if (!ruleFragment) continue;
|
|
26148
26134
|
opportunities.push({
|
|
26149
26135
|
id: stableOpportunityId("unincorporated_learning", [label(la)]),
|
|
26150
26136
|
category: "unincorporated_learning",
|
|
@@ -26152,16 +26138,18 @@ function buildConsolidationPlan(dir, opts = {}) {
|
|
|
26152
26138
|
confidence: "requires-review",
|
|
26153
26139
|
title: `${label(la)} captured a learning that may belong in current knowledge`,
|
|
26154
26140
|
source_artifacts: [label(la)],
|
|
26155
|
-
target_artifacts: [
|
|
26156
|
-
|
|
26157
|
-
|
|
26141
|
+
target_artifacts: [],
|
|
26142
|
+
// unresolved — determined in semantic review (never invent a destination)
|
|
26143
|
+
evidence: [`Completed Work Item records a rule-like learning (heuristic classification): "${redactSecrets3(ruleFragment)}"`],
|
|
26144
|
+
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
26145
|
possible_impact: "A relevant constraint stays buried in delivery history instead of informing current work.",
|
|
26159
|
-
suggested_action: "Semantic review:
|
|
26146
|
+
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
26147
|
requires_semantic_review: true
|
|
26161
26148
|
});
|
|
26162
26149
|
}
|
|
26163
26150
|
const weakByFolder = /* @__PURE__ */ new Map();
|
|
26164
26151
|
for (const la of scoped) {
|
|
26152
|
+
if (!isConsolidatableKnowledge(la)) continue;
|
|
26165
26153
|
const quality = safeQuality(dir, la.rel);
|
|
26166
26154
|
if (quality === "placeholder" || quality === "weak") {
|
|
26167
26155
|
opportunities.push({
|
|
@@ -26172,11 +26160,11 @@ function buildConsolidationPlan(dir, opts = {}) {
|
|
|
26172
26160
|
title: `${label(la)} is ${quality} and may need consolidation or expansion`,
|
|
26173
26161
|
source_artifacts: [label(la)],
|
|
26174
26162
|
target_artifacts: [label(la)],
|
|
26175
|
-
evidence: [`Artifact quality analysis classifies this artifact as "${quality}".`],
|
|
26176
|
-
rationale: "
|
|
26163
|
+
evidence: [`Artifact quality analysis classifies this canonical knowledge artifact as "${quality}".`],
|
|
26164
|
+
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
26165
|
possible_impact: "Readers must open more files to assemble a complete picture.",
|
|
26178
|
-
suggested_action: "
|
|
26179
|
-
requires_semantic_review:
|
|
26166
|
+
suggested_action: "Semantic review: decide whether to expand, merge into a stronger artifact, or cross-reference it.",
|
|
26167
|
+
requires_semantic_review: true
|
|
26180
26168
|
});
|
|
26181
26169
|
const folder = la.rel.split("/").slice(0, -1).join("/");
|
|
26182
26170
|
const arr = weakByFolder.get(folder) ?? [];
|
|
@@ -26191,11 +26179,11 @@ function buildConsolidationPlan(dir, opts = {}) {
|
|
|
26191
26179
|
category: "knowledge_fragmentation",
|
|
26192
26180
|
classification: "suggested",
|
|
26193
26181
|
confidence: "requires-review",
|
|
26194
|
-
title: `${folder}/ holds ${arts.length} low-signal artifacts \u2014 possible fragmentation`,
|
|
26182
|
+
title: `${folder}/ holds ${arts.length} low-signal canonical artifacts \u2014 possible fragmentation`,
|
|
26195
26183
|
source_artifacts: arts.map((a2) => label(a2)),
|
|
26196
26184
|
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.",
|
|
26185
|
+
evidence: [`${arts.length} placeholder/weak canonical knowledge artifacts in the same folder: ${arts.map((a2) => a2.rel.split("/").pop()).join(", ")}.`],
|
|
26186
|
+
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
26187
|
possible_impact: "Related knowledge is spread across too many files to follow.",
|
|
26200
26188
|
suggested_action: "Semantic review: evaluate whether cross-references or a consolidation would add clarity. Do not merge by file count alone.",
|
|
26201
26189
|
requires_semantic_review: true
|
|
@@ -26287,7 +26275,9 @@ function renderConsolidationMarkdown(plan) {
|
|
|
26287
26275
|
lines.push(`- Classification: **${o2.classification}**${o2.requires_semantic_review ? " (requires semantic review)" : ""}`);
|
|
26288
26276
|
lines.push(`- Confidence: ${o2.confidence}`);
|
|
26289
26277
|
lines.push(`- Source: ${o2.source_artifacts.join(", ") || "\u2014"}`);
|
|
26290
|
-
lines.push(
|
|
26278
|
+
lines.push(
|
|
26279
|
+
`- Suggested target: ${o2.target_artifacts.length > 0 ? o2.target_artifacts.join(", ") : "(unresolved \u2014 to be determined in semantic review)"}`
|
|
26280
|
+
);
|
|
26291
26281
|
lines.push(`- Evidence:`);
|
|
26292
26282
|
for (const e of o2.evidence) lines.push(` - ${e}`);
|
|
26293
26283
|
lines.push(`- Rationale: ${o2.rationale}`);
|
|
@@ -26312,15 +26302,25 @@ function isCompletedWorkItem(la) {
|
|
|
26312
26302
|
const p = toPosix8(la.artifact.filePath);
|
|
26313
26303
|
return p.includes("/delivery/work-items/completed/") || isWorkItem(la) && la.artifact.status === "completed";
|
|
26314
26304
|
}
|
|
26315
|
-
function
|
|
26316
|
-
const
|
|
26317
|
-
return
|
|
26305
|
+
function isScaffolding(la) {
|
|
26306
|
+
const p = toPosix8(la.artifact.filePath);
|
|
26307
|
+
return p.includes(`/${KNOWLEDGE7}/agents/`) || p.includes(`/${KNOWLEDGE7}/skills/`) || p.includes(`/${KNOWLEDGE7}/external/`) || la.artifact.type === "knowledge-capsule";
|
|
26308
|
+
}
|
|
26309
|
+
var NON_KNOWLEDGE_DOC_TYPES = /* @__PURE__ */ new Set([
|
|
26310
|
+
"roadmap",
|
|
26311
|
+
"initiative",
|
|
26312
|
+
"deprecation",
|
|
26313
|
+
"knowledge-capsule",
|
|
26314
|
+
"inventory",
|
|
26315
|
+
"project-resource"
|
|
26316
|
+
]);
|
|
26317
|
+
function isComparableKnowledge(la) {
|
|
26318
|
+
return !isWorkItem(la) && la.artifact.type !== "roadmap" && !isScaffolding(la);
|
|
26318
26319
|
}
|
|
26319
|
-
function
|
|
26320
|
-
|
|
26321
|
-
|
|
26322
|
-
|
|
26323
|
-
return redactSecrets3(s.trim());
|
|
26320
|
+
function isConsolidatableKnowledge(la) {
|
|
26321
|
+
if (isWorkItem(la) || isScaffolding(la)) return false;
|
|
26322
|
+
if (NON_KNOWLEDGE_DOC_TYPES.has(la.artifact.type)) return false;
|
|
26323
|
+
return la.layer === "Business" || la.layer === "Product" || la.layer === "Tech";
|
|
26324
26324
|
}
|
|
26325
26325
|
var SECRET_TOKEN_PATTERNS = [
|
|
26326
26326
|
/\bgh[pours]_[A-Za-z0-9]{16,}\b/g,
|
package/package.json
CHANGED