klypix-mcp 1.86.1 → 1.86.3
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/README.md +2 -2
- package/bin/klypix-install.mjs +3 -1
- package/bin/klypix-worker.mjs +3 -1
- package/package.json +2 -2
- package/src/agent-rules.mjs +2 -2
- package/src/brain-doctor.mjs +10 -1
- package/src/brain-semantic.mjs +32 -4
- package/src/global-brain-hook.mjs +457 -102
- package/src/klypix-core.mjs +5 -2
- package/src/klypix-format.mjs +163 -37
- package/src/semantic-memory.mjs +117 -18
package/README.md
CHANGED
|
@@ -290,7 +290,7 @@ For a reproducible map artifact on every pull request and main-branch push, inst
|
|
|
290
290
|
read-only workflow into a Git checkout:
|
|
291
291
|
|
|
292
292
|
```bash
|
|
293
|
-
npx klypix-project-map setup-github /path/to/project
|
|
293
|
+
npx -y -p klypix-mcp klypix-project-map setup-github /path/to/project
|
|
294
294
|
```
|
|
295
295
|
|
|
296
296
|
The command refuses to overwrite an existing workflow unless `--force` is explicit. The installed
|
|
@@ -314,7 +314,7 @@ behaviour is unverified.
|
|
|
314
314
|
| **VS Code (Copilot / Continue)** | MCP config + instructions file | `link` | Model must call `brain_sync` | Model must call `brain_note` | For the MCP connection |
|
|
315
315
|
| **Gemini CLI / Antigravity** | MCP config + always-on rules file | `link` | Model must call `brain_sync` | Model must call `brain_note` | For the MCP connection |
|
|
316
316
|
| **Windsurf** | Rules file only | `link` | Reaches the tools through Windsurf's own global MCP config | Model must call `brain_note` | Via its own MCP config |
|
|
317
|
-
| **Aider** | Rules file only (no MCP) | `link` | CLI path: `npx klypix-read` | CLI path: `npx klypix-append` | — |
|
|
317
|
+
| **Aider** | Rules file only (no MCP) | `link` | CLI path: `npx -y -p klypix-mcp klypix-read` | CLI path: `npx -y -p klypix-mcp klypix-append` | — |
|
|
318
318
|
| **Claude Desktop** | One-time manual config edit | you | Model must call `brain_sync` | Model must call `brain_note` | For the MCP connection |
|
|
319
319
|
|
|
320
320
|
`install` and `link` are different things and are not interchangeable: `install` sets up the
|
package/bin/klypix-install.mjs
CHANGED
|
@@ -436,7 +436,9 @@ try {
|
|
|
436
436
|
// deliberately preserving every host/project config byte.
|
|
437
437
|
const brainCmd = (arg) => `node "${fwd(path.join(BRAIN_DIR, 'global-brain-hook.mjs'))}"${arg ? ' ' + arg : ''}`;
|
|
438
438
|
const GROUPS = [
|
|
439
|
-
|
|
439
|
+
// "clear" (1.86.2): a /clear starts a new conversation that needs the
|
|
440
|
+
// brief as much as a fresh one does.
|
|
441
|
+
['SessionStart', { matcher: 'startup|resume|clear', hooks: [{ type: 'command', command: brainCmd('') }] }],
|
|
440
442
|
['UserPromptSubmit', { hooks: [{ type: 'command', command: brainCmd('--prompt'), timeout: 10 }] }],
|
|
441
443
|
['Stop', { hooks: [{ type: 'command', command: brainCmd('--capture') }] }],
|
|
442
444
|
['PostToolUse', { matcher: 'Bash|PowerShell|Edit|Write', hooks: [{ type: 'command', command: brainCmd('--live'), timeout: 10 }] }],
|
package/bin/klypix-worker.mjs
CHANGED
|
@@ -94,7 +94,9 @@ const runVerb = async (verb, moduleId) => {
|
|
|
94
94
|
// into ~/.claude/project-brain and wire the Claude Code hooks. This is the single
|
|
95
95
|
// agent-neutral installer, so a brain release reaches every machine via one npm
|
|
96
96
|
// publish + this command (the global brain serves every project). Runs before any
|
|
97
|
-
// server setup; delegates to the dedicated bin so `npx klypix-install`
|
|
97
|
+
// server setup; delegates to the dedicated bin so `npx -p klypix-mcp klypix-install`
|
|
98
|
+
// also works (the bin name on its own is not an npm package we own — see
|
|
99
|
+
// test/npx-owned-names.mjs).
|
|
98
100
|
await runVerb('install', './klypix-install.mjs');
|
|
99
101
|
|
|
100
102
|
// `npx klypix-mcp link` — make THIS project's brain automatic for EVERY agent tool,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "klypix-mcp",
|
|
3
|
-
"version": "1.86.
|
|
3
|
+
"version": "1.86.3",
|
|
4
4
|
"mcpName": "io.github.dahshanlabs/klypix-mcp",
|
|
5
5
|
"description": "Active state management for multi-agent coding: a shared, versioned project brain over MCP.",
|
|
6
6
|
"type": "module",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"bench": "node bin/klypix-mcp.mjs bench",
|
|
85
85
|
"test:bench": "node test/bench.mjs",
|
|
86
86
|
"pretest": "node test/publish-workflow.mjs",
|
|
87
|
-
"test": "node test/publish-verdict.mjs && node test/project-graph.mjs &&
|
|
87
|
+
"test": "node test/publish-verdict.mjs && node test/npx-owned-names.mjs && node test/project-graph.mjs &&node test/project-map-cli.mjs && node test/mcp-auto-update.mjs && node test/mcp-supervisor.mjs && node test/runtime-inspector.mjs && node test/codex-hooks.mjs && node test/request-identity.mjs && node test/session-identity-core.mjs && node test/agent-presence.mjs && node test/message-delivery-v3.mjs && node test/claude-message-delivery-v3.mjs && node test/result-reconcile.mjs && node test/evidence-publication-gate.mjs && node test/release-evidence-cli.mjs && node test/intent-guard.mjs && node test/git-capture-install.mjs && node test/brain-history.mjs && node test/brain-graveyard.mjs && node test/archived-visibility.mjs && node test/finding-routing.mjs && node test/finding-routing-hook.mjs && node test/presence-relay.mjs && node test/install-version.mjs && node test/install-rename-backoff.mjs && node test/project-binding-rebind.mjs && node test/context-gateway.mjs && node test/repo-state.mjs && node test/released-tag-guard.mjs && node test/conformance.mjs && node test/brain-doctor.mjs && node test/version-currency.mjs && node test/ship-capture.mjs && node test/capture-gap.mjs && node test/lane-message.mjs && node test/brain-quality.mjs && node test/brain-connect-orphans.mjs && node test/orphan-gardener.mjs && node test/brief-and-recall.mjs && node test/guard-cards.mjs && node test/layout-cluster.mjs && node test/brain-ask.mjs && node test/retrieval-fusion.mjs && node test/eval-retrieval.mjs && node test/field-report-2026-07-04.mjs && node test/autoprop.mjs && node test/overlay-recency-2026-07-12.mjs && node test/brain-challenge.mjs && node test/brain-lens.mjs && node test/brain-kind.mjs && node test/rule-drafts.mjs && node test/claim-engine.mjs && node test/partial-notes.mjs && node test/lifecycle-prefix.mjs && node test/close-link-safety.mjs && node test/resolve-ledger.mjs && node test/plan-fulfillment.mjs && node test/skill-staleness.mjs && node test/canvas-view.mjs && node test/status-completeness.mjs && node test/semantic-security.mjs && node test/semantic-gate.mjs && node test/memory-runtime.mjs && node test/semantic-cache.mjs && node test/semantic-hash-parity.mjs && node test/enrichment.mjs && node test/hook-fallback.mjs && node test/eval-hook-lane.mjs && node test/decay-status.mjs && node test/decay-hook.mjs && node test/marker-suffix-grammar.mjs && node test/evidence-anchors.mjs && node test/brain-evidence.mjs && node test/presence-visibility.mjs && node test/undeclared-active.mjs && node test/presence-liveness.mjs && node test/observed-scope.mjs && node test/release-lease.mjs && node test/release-reconcile.mjs && node test/release-ancestry.mjs && node test/release-claim-join.mjs && node test/release-claims.mjs && node test/release-handshake.mjs && node test/completion-guard.mjs && node test/merge-brains.mjs && node test/concurrent-writes.mjs && node test/lock-interop.mjs && node test/capture-write-failure.mjs && node test/a2a-smoke.mjs && node test/one-command-setup.mjs && node test/cli-args.mjs && node test/format-guard.mjs && node test/canvas-groups.mjs && node test/git-tools.mjs && node test/uninstall.mjs && node test/current-guidance.mjs && node test/status-shape.mjs && node test/status-hook.mjs",
|
|
88
88
|
"test:memory": "node test/memory-runtime.mjs",
|
|
89
89
|
"test:memory:soak": "node --expose-gc test/memory-soak.mjs",
|
|
90
90
|
"runtime": "node bin/klypix-runtime.mjs",
|
package/src/agent-rules.mjs
CHANGED
|
@@ -444,12 +444,12 @@ survives across sessions, agents, and context resets.
|
|
|
444
444
|
- do NOT automatically read the full \`.claude/brain-brief.md\`; open it only when \`brain_sync\`
|
|
445
445
|
says its compact context is insufficient or the task asks for broad project history/status.
|
|
446
446
|
- with the \`klypix-canvas\` MCP server: to **answer a question** from the brain ("what did we decide about X?", "where did Y land?"), call \`brain_ask\` — it ranks the whole brain, includes superseded history, and surfaces the current truth for any corrected card. Use \`search_canvases\` for a raw keyword lookup, \`read_canvas\` (canvas: \`"brain"\`) for the whole thing, or \`brain_insights\` for the load-bearing cards.
|
|
447
|
-
- or via CLI: \`npx klypix-read brain.klypix\`
|
|
447
|
+
- or via CLI: \`npx -y -p klypix-mcp klypix-read brain.klypix\`
|
|
448
448
|
|
|
449
449
|
**When you make a real decision, finding, or milestone — capture it HERE** so it persists for the next session/agent:
|
|
450
450
|
- with MCP: call \`brain_note\` with a one-line decision, or
|
|
451
451
|
- emit a marker line in your output: \`🧠 BRAIN [Area]: <one-line decision>\`, or
|
|
452
|
-
- via CLI: \`echo "🧠 BRAIN [Area]: <decision>" | npx klypix-append brain.klypix\`
|
|
452
|
+
- via CLI: \`echo "🧠 BRAIN [Area]: <decision>" | npx -y -p klypix-mcp klypix-append brain.klypix\`
|
|
453
453
|
|
|
454
454
|
Capture **sparingly** — real decisions / milestones / open questions / reusable gotchas, not routine
|
|
455
455
|
steps — and capture it **at the moment you decide** (a one-line marker inline), not batched or left in
|
package/src/brain-doctor.mjs
CHANGED
|
@@ -111,7 +111,15 @@ function inspectHooks(home) {
|
|
|
111
111
|
const present = !!settings;
|
|
112
112
|
const wired = present ? HOOK_EVENTS.filter(wiredFor) : [];
|
|
113
113
|
const missing = present ? HOOK_EVENTS.filter(e => !wired.includes(e)) : HOOK_EVENTS.slice();
|
|
114
|
-
|
|
114
|
+
// Informational (never a verdict): installs before 1.86.2 wired SessionStart
|
|
115
|
+
// for "startup|resume" only, so /clear starts a conversation with no brain
|
|
116
|
+
// brief. A runtime-only update never rewrites settings.json; a full
|
|
117
|
+
// `npx klypix-mcp install` does. An empty/absent matcher means every source.
|
|
118
|
+
const ours = (Array.isArray(settings?.hooks?.SessionStart) ? settings.hooks.SessionStart : [])
|
|
119
|
+
.filter(g => Array.isArray(g?.hooks) && g.hooks.some(h => typeof h?.command === 'string' && h.command.includes(HOOK_MARK)));
|
|
120
|
+
const coversClear = (g) => !g.matcher || String(g.matcher).split('|').map(x => x.trim()).some(x => x === 'clear' || x === '*');
|
|
121
|
+
const sessionStartMissesClear = ours.length > 0 && !ours.some(coversClear);
|
|
122
|
+
return { settingsPresent: present, wired, missing, sessionStartMissesClear };
|
|
115
123
|
}
|
|
116
124
|
|
|
117
125
|
// ── TOOLS (discoverable manifest) layer ──────────────────────────────────────
|
|
@@ -788,6 +796,7 @@ export function render(r, opts = {}) {
|
|
|
788
796
|
else if (r.hooks.missing.length === 1 && r.hooks.missing[0] === 'PreToolUse') L.push(`${hmark} ${c.bold}CLAUDE${c.rst} capture path intact; ${c.yel}guard lane not wired yet${c.rst} — \`npx klypix-mcp install\` adds the PreToolUse hook (guard cards)`);
|
|
789
797
|
else if (r.hooks.missing.length) L.push(`${hmark} ${c.bold}CLAUDE${c.rst} half-wired — missing: ${c.yel}${r.hooks.missing.join(', ')}${c.rst} ${c.dim}(liveness up, readiness no)${c.rst}`);
|
|
790
798
|
else L.push(`${hmark} ${c.bold}CLAUDE${c.rst} existing 5-hook capture path intact: ${r.hooks.wired.join(', ')}`);
|
|
799
|
+
if (r.hooks.sessionStartMissesClear) L.push(` ${c.dim}note: SessionStart is not wired for /clear — a cleared conversation starts without the brain brief; "npx klypix-mcp install" adds "clear" to its matcher${c.rst}`);
|
|
791
800
|
const chmark = r.layers.codexHooks === 'warning' ? warn : ok;
|
|
792
801
|
const smart = r.codexSmart?.globalInstructions
|
|
793
802
|
? 'approval-free Context Gateway active (task memory + clean peers + proactive/guaranteed alerts)'
|
package/src/brain-semantic.mjs
CHANGED
|
@@ -118,6 +118,21 @@ async function embedQueries(pipe, texts) {
|
|
|
118
118
|
// Vectors are unit-normalized, so dot == cosine.
|
|
119
119
|
export const dot = (a, b) => { let s = 0; const n = Math.min(a.length, b.length); for (let i = 0; i < n; i++) s += a[i] * b[i]; return s; };
|
|
120
120
|
|
|
121
|
+
// Copy of vectorEntryMatchesText in semantic-memory.mjs, where the rule is
|
|
122
|
+
// explained (this one-shot module cannot import the long-lived runtime). It
|
|
123
|
+
// takes precomputed hashes and references nothing outside itself. Keep the two
|
|
124
|
+
// identical: test/semantic-hash-parity.mjs compares them.
|
|
125
|
+
export function vectorEntryMatchesText(entry, fullHash, truncatedHash) {
|
|
126
|
+
try {
|
|
127
|
+
if (!entry || !entry.v || typeof fullHash !== 'string' || !fullHash) return false;
|
|
128
|
+
if (typeof entry.t === 'string' && entry.t === fullHash) return true;
|
|
129
|
+
if (typeof entry.h !== 'string' || !entry.h) return false;
|
|
130
|
+
if (entry.h === fullHash) return true;
|
|
131
|
+
const truncated = typeof truncatedHash === 'function' ? truncatedHash() : null;
|
|
132
|
+
return typeof truncated === 'string' && truncated !== '' && entry.h === truncated;
|
|
133
|
+
} catch { return false; }
|
|
134
|
+
}
|
|
135
|
+
|
|
121
136
|
// READ-ONLY card-vector cache — NEVER embeds or writes (embedding all cards in the
|
|
122
137
|
// per-prompt process is the multi-second stall we forbid). Reuses the SAME warm
|
|
123
138
|
// cache the MCP host fills. Current workers canonicalize absolute Windows paths
|
|
@@ -141,10 +156,23 @@ function readCachedVecs(brainPath, cards) {
|
|
|
141
156
|
} catch { /* try next variant */ }
|
|
142
157
|
}
|
|
143
158
|
const map = new Map();
|
|
144
|
-
// A vector is accepted only
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
|
|
159
|
+
// A vector is accepted only when its entry proves it was embedded from the
|
|
160
|
+
// card's current text: the full-text fingerprint `t`, or for an entry written
|
|
161
|
+
// before `t` existed its `h` against the full or the truncated text (`h` is
|
|
162
|
+
// the hash of the EMBED INPUT: the first 1,500 characters plus enrichment).
|
|
163
|
+
// An edited card must fall back to lexical, never pair on a stale embedding.
|
|
164
|
+
// Same card filter and same acceptance rule as
|
|
165
|
+
// semantic-memory.cachedVectorsForBrain, on ONE cache file: this reader
|
|
166
|
+
// stops at the first variant carrying the current modelKey, the server
|
|
167
|
+
// reader merges every alias file, so the two can differ until a writer run
|
|
168
|
+
// folds the aliases into the canonical file. The entry lookup comes first
|
|
169
|
+
// so a card with no cached vector costs no hash.
|
|
170
|
+
if (cache && cache.cards) for (const c of cards) {
|
|
171
|
+
if (!c || c.type === 'container' || typeof c.text !== 'string' || !c.text.trim()) continue;
|
|
172
|
+
const e = cache.cards[c.id];
|
|
173
|
+
if (!e || !e.v) continue;
|
|
174
|
+
if (vectorEntryMatchesText(e, sha1(c.text), () => (c.text.length > 1500 ? sha1(c.text.slice(0, 1500)) : null))) map.set(c.id, e.v);
|
|
175
|
+
}
|
|
148
176
|
return map;
|
|
149
177
|
}
|
|
150
178
|
|