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 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
@@ -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
- ['SessionStart', { matcher: 'startup|resume', hooks: [{ type: 'command', command: brainCmd('') }] }],
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 }] }],
@@ -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` also works.
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.1",
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 && 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/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",
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",
@@ -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
@@ -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
- return { settingsPresent: present, wired, missing };
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)'
@@ -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 for the text it was embedded from (the cache
145
- // stores sha1(text) as `h`) — an edited card must fall back to lexical, never
146
- // pair on a stale embedding (parity with semantic-memory.cachedVectorsForBrain).
147
- if (cache && cache.cards) for (const c of cards) { const e = cache.cards[c.id]; if (e && e.v && (!e.h || e.h === sha1(String(c.text)))) map.set(c.id, e.v); }
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