@kage-core/kage-graph-mcp 2.5.5 → 2.5.6
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/kernel.js +35 -41
- package/package.json +1 -1
package/dist/kernel.js
CHANGED
|
@@ -7015,10 +7015,11 @@ function gcProject(projectDir, options = {}) {
|
|
|
7015
7015
|
skipped.push({ id: packet.id, title: packet.title, reason: "already deprecated" });
|
|
7016
7016
|
continue;
|
|
7017
7017
|
}
|
|
7018
|
-
// Serialized transcript / tool-output / file-content dumps
|
|
7019
|
-
//
|
|
7020
|
-
//
|
|
7021
|
-
|
|
7018
|
+
// Serialized transcript / tool-output / file-content dumps and ungrounded conversational
|
|
7019
|
+
// chatter (a path-less rant at the assistant) carry no durable knowledge and bloat recall +
|
|
7020
|
+
// the digest. Always delete them (deprecating would leave the blob on disk) — this also
|
|
7021
|
+
// reclaims legacy junk written before the capture-time guards existed.
|
|
7022
|
+
if (isSerializedDumpTitle(packet.title) || isSerializedDumpBody(packet.body) || isUngroundedConversationalCapture(packet)) {
|
|
7022
7023
|
if (!options.dryRun)
|
|
7023
7024
|
(0, node_fs_1.unlinkSync)(path);
|
|
7024
7025
|
deleted.push({ id: packet.id, title: packet.title });
|
|
@@ -8012,6 +8013,14 @@ function hasRepoGroundingSignal(text) {
|
|
|
8012
8013
|
// punctuation, or one of a curated set of rhetorical / second-person-at-the-assistant
|
|
8013
8014
|
// phrases — so it stays clear of normal declarative learnings (which read as statements, not
|
|
8014
8015
|
// outbursts addressed to "you").
|
|
8016
|
+
// Phrases that rant AT the assistant ("why are you...", "it's your job", "don't stop"). These
|
|
8017
|
+
// never appear in a curated learning, so they mark chatter even when the outburst name-drops a
|
|
8018
|
+
// platform word (github, pr, x, linkedin) that the loose grounding matcher would otherwise
|
|
8019
|
+
// treat as a repo reference. This is the override that closes the leak where a frustrated
|
|
8020
|
+
// message peppered with nouns slipped through and was captured as approved memory.
|
|
8021
|
+
function looksFrustratedAtAssistant(text) {
|
|
8022
|
+
return /\b(why are you|why did you|why would you|why aren'?t you|are you (kidding|serious|even|really)|it'?s your job|that'?s your job|do your job|don'?t stop|stop asking|stop before you|keep going|hurry up|just do it|figure it out yourself|i (already )?told you)\b/i.test(text ?? "");
|
|
8023
|
+
}
|
|
8015
8024
|
function looksLikeRawUserUtterance(text) {
|
|
8016
8025
|
const t = (text ?? "").trim();
|
|
8017
8026
|
if (!t)
|
|
@@ -8021,18 +8030,21 @@ function looksLikeRawUserUtterance(text) {
|
|
|
8021
8030
|
if (/[!?]{2,}/.test(t))
|
|
8022
8031
|
return true;
|
|
8023
8032
|
// Rhetorical questions / second-person-imperative frustration directed at the assistant.
|
|
8024
|
-
return
|
|
8025
|
-
}
|
|
8026
|
-
// Capture-noise guard for ungrounded chat. A packet trips it
|
|
8027
|
-
//
|
|
8028
|
-
//
|
|
8029
|
-
//
|
|
8030
|
-
//
|
|
8031
|
-
//
|
|
8033
|
+
return looksFrustratedAtAssistant(t);
|
|
8034
|
+
}
|
|
8035
|
+
// Capture-noise guard for ungrounded chat. A packet trips it when it cites zero repo paths and
|
|
8036
|
+
// either (a) it rants at the assistant — which overrides incidental repo-ish words, since the
|
|
8037
|
+
// grounding matcher false-positives on bare platform names — or (b) it reads as a raw outburst
|
|
8038
|
+
// and carries no repo grounding signal at all. The override + conjunction keep it safe: a real
|
|
8039
|
+
// ungrounded decision or convention is declarative (no "why are you.../don't stop") and usually
|
|
8040
|
+
// names a symbol, file, command, or rule, so it is never caught. Such packets route to pending
|
|
8041
|
+
// (not auto-approved) at capture time and are withheld from recall, like serialized dumps.
|
|
8032
8042
|
function isUngroundedConversationalCapture(packet) {
|
|
8033
8043
|
if (packet.paths && packet.paths.length > 0)
|
|
8034
8044
|
return false;
|
|
8035
8045
|
const text = `${packet.title ?? ""}\n${packet.body ?? ""}`;
|
|
8046
|
+
if (looksFrustratedAtAssistant(text))
|
|
8047
|
+
return true;
|
|
8036
8048
|
if (hasRepoGroundingSignal(text))
|
|
8037
8049
|
return false;
|
|
8038
8050
|
return looksLikeRawUserUtterance(text);
|
|
@@ -15615,20 +15627,17 @@ function kageResume(projectDir) {
|
|
|
15615
15627
|
updated_at: packetRecency(packet),
|
|
15616
15628
|
age: humanPacketAge(packetRecency(packet)),
|
|
15617
15629
|
}));
|
|
15618
|
-
|
|
15619
|
-
|
|
15630
|
+
// A new session starts on a fresh task, so SessionStart does NOT replay last session's files,
|
|
15631
|
+
// commands, or a recency-ranked memory list — that was pre-task noise (it fires before the
|
|
15632
|
+
// first prompt, so it can't be task-targeted) and the surface that leaked raw command dumps and
|
|
15633
|
+
// junk packets. Task-relevant memory is pulled on the first prompt via prompt-context; recall
|
|
15634
|
+
// at the moment a file is read via file-context. SessionStart carries only always-on curated
|
|
15635
|
+
// repo facts (the pinned block, below) plus a few actionable open-thread pointers.
|
|
15636
|
+
const hasSessionContent = Boolean(lastChangeMemory || pendingAutoDistilled || reconciliation.unresolved_count);
|
|
15637
|
+
const hasContent = hasSessionContent;
|
|
15620
15638
|
const lines = [];
|
|
15621
|
-
if (
|
|
15622
|
-
lines.push("#
|
|
15623
|
-
if (lastSession) {
|
|
15624
|
-
lines.push(`Last session ${lastSession.session_id} (${lastSession.observations} observation${lastSession.observations === 1 ? "" : "s"}, ended ${lastSession.last_at}).`);
|
|
15625
|
-
if (lastSession.paths.length)
|
|
15626
|
-
lines.push(`Worked on: ${lastSession.paths.join(", ")}`);
|
|
15627
|
-
if (lastSession.commands.length)
|
|
15628
|
-
lines.push(`Commands: ${lastSession.commands.join("; ")}`);
|
|
15629
|
-
if (lastSession.distilled_titles.length)
|
|
15630
|
-
lines.push(`Learned: ${lastSession.distilled_titles.join("; ")}`);
|
|
15631
|
-
}
|
|
15639
|
+
if (hasSessionContent) {
|
|
15640
|
+
lines.push("# Open threads (Kage)");
|
|
15632
15641
|
if (lastChangeMemory) {
|
|
15633
15642
|
lines.push(`Change memory: ${lastChangeMemory.title} — ${lastChangeMemory.summary}`);
|
|
15634
15643
|
}
|
|
@@ -15641,22 +15650,7 @@ function kageResume(projectDir) {
|
|
|
15641
15650
|
lines.push(` - ${item.packet_id}: ${item.title}`);
|
|
15642
15651
|
}
|
|
15643
15652
|
}
|
|
15644
|
-
|
|
15645
|
-
// only for the newest few, hard-capped to the resume token budget.
|
|
15646
|
-
const block = lines.slice(0, 15);
|
|
15647
|
-
if (recentPackets.length) {
|
|
15648
|
-
block.push("", "## Recent memory");
|
|
15649
|
-
recentPackets.forEach((packet, position) => {
|
|
15650
|
-
const entry = `[${packet.id.slice(0, 12)}] ${packet.type} ${packet.title} (${humanPacketAge(packetRecency(packet))})`;
|
|
15651
|
-
const candidate = [entry];
|
|
15652
|
-
if (position < RESUME_TIMELINE_DETAILED && packet.summary) {
|
|
15653
|
-
const summary = packet.summary.replace(/\s+/g, " ").trim();
|
|
15654
|
-
candidate.push(` ${summary.length > 160 ? `${summary.slice(0, 157)}...` : summary}`);
|
|
15655
|
-
}
|
|
15656
|
-
if (estimateTokens([...block, ...candidate].join("\n")) <= RESUME_CONTEXT_TOKEN_BUDGET)
|
|
15657
|
-
block.push(...candidate);
|
|
15658
|
-
});
|
|
15659
|
-
}
|
|
15653
|
+
const block = lines.slice(0, 12);
|
|
15660
15654
|
// Lead the SessionStart injection with the team's pinned, always-on repo memory (the
|
|
15661
15655
|
// curated high-signal facts), not just the recent-timeline digest — parity with recall's
|
|
15662
15656
|
// context block, so a new session starts already holding the key knowledge, not only a
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kage-core/kage-graph-mcp",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.6",
|
|
4
4
|
"description": "Team memory for coding agents: captures the decisions, runbooks, and bug fixes that get lost, verified against your code and shared via git. MCP server, zero deps, no account.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"files": [
|