klypix-mcp 1.65.0 → 1.66.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/README.md +49 -20
- package/bin/klypix-brain-deleted.mjs +6 -1
- package/bin/klypix-conformance.mjs +67 -31
- package/bin/klypix-git-tools.mjs +4 -4
- package/bin/klypix-install.mjs +2 -2
- package/bin/klypix-worker.mjs +115 -8
- package/package.json +4 -2
- package/src/agent-presence.mjs +377 -79
- package/src/brain-doctor.mjs +44 -9
- package/src/brain-graveyard.mjs +52 -3
- package/src/brain-note.mjs +3 -1
- package/src/codex-brain-hook.mjs +38 -8
- package/src/finding-routing.mjs +61 -22
- package/src/global-brain-hook.mjs +284 -121
- package/src/klypix-core.mjs +86 -87
- package/src/klypix-format.mjs +228 -5
- package/src/mcp-presence.mjs +355 -38
- package/src/mcp-supervisor.mjs +127 -15
- package/src/merge-brains.mjs +39 -6
- package/src/presence-relay.mjs +184 -32
- package/src/remote-client.mjs +158 -0
- package/src/result-reconcile.mjs +618 -0
- package/src/semantic-memory.mjs +48 -0
package/README.md
CHANGED
|
@@ -79,7 +79,7 @@ npx klypix-mcp conformance
|
|
|
79
79
|
|
|
80
80
|
It runs in a temporary fixture and touches nothing else. It checks tool discovery, task memory,
|
|
81
81
|
truthful peer reporting, overlap surfacing, proactive logging, and in-band delivery of a peer note.
|
|
82
|
-
It verifies
|
|
82
|
+
It verifies 15 required coordination behaviours — not the 21 tools, and not the retrieval engine.
|
|
83
83
|
|
|
84
84
|
---
|
|
85
85
|
|
|
@@ -150,7 +150,9 @@ not a filing convention.
|
|
|
150
150
|
|
|
151
151
|
- **Decisions have a lifecycle.** A new decision that contradicts an old one supersedes it. The
|
|
152
152
|
stale card is archived with an arrow and a date, never deleted, and later answers surface the
|
|
153
|
-
correction rather than the corpse.
|
|
153
|
+
correction rather than the corpse. If a later decision returns to an earlier superseded stance,
|
|
154
|
+
high-confidence lineage leaves a dated `re-adopts` stamp on the new card plus an earlier→current
|
|
155
|
+
edge; the original A→B→C history remains intact.
|
|
154
156
|
- **Corrections are explicit, not guessed.** Supersession fires on an UPPERCASE correction cue or
|
|
155
157
|
an explicit edge. `brain_reconcile` only *proposes* stale-vs-correction pairs for a human to
|
|
156
158
|
confirm.
|
|
@@ -274,7 +276,9 @@ the full brief written to disk for when broad history or status work needs it.
|
|
|
274
276
|
|
|
275
277
|
Every other host gets a bounded ~2.8KB task capsule from one `brain_sync` call, plus a compact
|
|
276
278
|
always-loaded `AGENTS.md` block that tells the agent to make that call at task start, when scope
|
|
277
|
-
changes, and on completion. The gateway capsule is lexical-fast by design.
|
|
279
|
+
changes, and on completion. The gateway capsule is lexical-fast by design. A newly captured open
|
|
280
|
+
gap can claim a labeled `RECENT OPEN` slot only after clearing the normal lexical-relevance floor,
|
|
281
|
+
so fresh relevant findings are not crowded out by older area vocabulary.
|
|
278
282
|
|
|
279
283
|
Briefs are **not** injected automatically on Cursor, Cline, Copilot, Gemini CLI or Antigravity —
|
|
280
284
|
there are no lifecycle hooks on those hosts.
|
|
@@ -285,9 +289,12 @@ On Claude Code, decisions are captured automatically at turn end from inline `
|
|
|
285
289
|
markers in the transcript, deduped, under a capture lock.
|
|
286
290
|
|
|
287
291
|
On every other host, capture is explicit: `brain_note` runs the same capture engine as the hooks —
|
|
288
|
-
dedup, supersession, `✓` resolve, `~` update in place, `+` skill,
|
|
289
|
-
|
|
290
|
-
|
|
292
|
+
dedup, supersession, round-trip re-adoption receipts, `✓` resolve, `~` update in place, `+` skill,
|
|
293
|
+
`closes:` — and stamps which agent wrote the card. A `✓` question preference ranks only candidates
|
|
294
|
+
that already clear raw lexical overlap and two subject-identity anchors; generic lifecycle wording
|
|
295
|
+
cannot turn weak overlap into a closure.
|
|
296
|
+
(If you install the git commit hook from the KLYPIX app, commit messages also capture automatically,
|
|
297
|
+
for any agent. That hook has no CLI installer.)
|
|
291
298
|
|
|
292
299
|
`brain_challenge` is the other direction: propose a decision and the brain answers with receipts —
|
|
293
300
|
prior decisions that deterministically contradict it, standing rules that dispute it, and
|
|
@@ -323,14 +330,30 @@ have to have declared their files for the overlap to be visible at all.
|
|
|
323
330
|
|
|
324
331
|
## Handoffs and messages
|
|
325
332
|
|
|
326
|
-
`brain_message` leaves one-time coordination notes for other sessions.
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
333
|
+
`brain_message` leaves one-time coordination notes for other sessions. A supported KLYPIX action
|
|
334
|
+
offers the note in model-visible context; the next independent supported action replays it and
|
|
335
|
+
records an acknowledgement. That acknowledgement proves only that a later action followed the
|
|
336
|
+
offer — never that a person read it or that an agent acted on it. Pending and offered notes survive
|
|
337
|
+
reconnects. Expiry or bounded-capacity eviction records a failed per-recipient receipt instead of
|
|
338
|
+
silently looking delivered. The core lane is machine-local, notes expire after 24 hours, and they
|
|
339
|
+
are never written into the brain.
|
|
330
340
|
|
|
331
341
|
Durable handoffs go in the brain itself — decisions, findings, open questions and skills captured
|
|
332
342
|
as cards, each stamped with the agent that wrote it.
|
|
333
343
|
|
|
344
|
+
## Evidence-gated completion
|
|
345
|
+
|
|
346
|
+
When a task publishes a quantified or otherwise machine-checkable claim, it can attach one or more
|
|
347
|
+
versioned result manifests to `brain_sync { phase: "complete" }`. Each manifest binds the claim to a
|
|
348
|
+
report hash, producer/run provenance, the exact input and configuration fingerprints, and named
|
|
349
|
+
metrics with counts and tolerances. Matching peer evidence is recorded as corroboration; conflicting
|
|
350
|
+
or incomparable evidence returns `needs-reconciliation` and keeps the task scope active.
|
|
351
|
+
|
|
352
|
+
The gate fails closed. Once a task submits result evidence, it cannot bypass an invalid or
|
|
353
|
+
conflicting result by retrying completion without the manifest, and that obligation survives worker
|
|
354
|
+
restart, hibernation, and transparent hot-swap. A fresh `phase: "start"` is the explicit boundary for
|
|
355
|
+
a new task. The strict schema and reusable validator are exported as `klypix-mcp/result-reconcile`.
|
|
356
|
+
|
|
334
357
|
## Human control in Klypix
|
|
335
358
|
|
|
336
359
|
> **Not a second brain. A shared one.**
|
|
@@ -471,14 +494,14 @@ The MCP verbs below are what agents call. These are what **you** call:
|
|
|
471
494
|
|---|---|
|
|
472
495
|
| `brain_ask` | Whole-brain question answering — correction-aware, `as_of` time travel |
|
|
473
496
|
| `brain_challenge` | The brain argues back: contradictions with receipts, tried-and-reversed chains, standing rules, other-agent provenance flags |
|
|
474
|
-
| `brain_note` | Capture with the full lifecycle — supersede / ✓ resolve / ~ update / 🛠 skill / `closes:` |
|
|
497
|
+
| `brain_note` | Capture with the full lifecycle — supersede / re-adopt / ✓ resolve / ~ update / 🛠 skill / `closes:` |
|
|
475
498
|
| `brain_reconcile` | Proposes stale-vs-correction pairs and unrecorded migrations for a human to confirm |
|
|
476
499
|
| `brain_insights` | Hubs, orphaned decisions, stale questions, area sizes |
|
|
477
500
|
| `brain_lens` | Machine-readable freshness, provenance, activity, timeline, orrery and unresolved views |
|
|
478
501
|
| `brain_garden` | Maintenance pass — proposes first, and cannot apply without an approval code the human generates |
|
|
479
502
|
| `brain_doctor` | Self-diagnosis: version, core/enhanced host adapters, active sessions, tool count, projection drift |
|
|
480
|
-
| `brain_message` | Session-to-session coordination notes (24h TTL, never written into the brain) |
|
|
481
|
-
| `brain_sync` | Context Gateway: task capsule, active-task peers, exact-file overlap, one-time alerts, timing |
|
|
503
|
+
| `brain_message` | Session-to-session coordination notes with per-recipient offer / later-action acknowledgement / failure receipts (24h TTL, never written into the brain) |
|
|
504
|
+
| `brain_sync` | Context Gateway: task capsule, active-task peers, exact-file overlap, one-time alerts, timing, and optional result-manifest reconciliation |
|
|
482
505
|
| `brain_connect` | Find and draw related-but-unlinked cards |
|
|
483
506
|
| `project_map_context` | Read-only, bounded code-graph evidence beside correction-aware brain context, with exact-path review proposals; external artifacts (e.g. Graphify) are supported but never installed or run locally |
|
|
484
507
|
| `project_map_scan` | KLYPIX's own zero-install scanner: gitignore-aware file inventory + file-level import edges (relative, tsconfig-alias, and monorepo-workspace imports resolved) written to `klypix-map/graph.json` — which then serves `project_map_context` automatically |
|
|
@@ -491,7 +514,7 @@ The MCP verbs below are what agents call. These are what **you** call:
|
|
|
491
514
|
| `add_to_canvas` | Append cards/connections (positions preserved) |
|
|
492
515
|
| `list_canvases` | List every `.klypix` in the vault |
|
|
493
516
|
|
|
494
|
-
Exactly
|
|
517
|
+
Exactly 21, machine-verifiable with `npx klypix-mcp doctor`.
|
|
495
518
|
|
|
496
519
|
> **`canvas_view`:** no MCP Apps host has been observed rendering the UI resource yet — there is no
|
|
497
520
|
> screenshot and no host-level test. Hosts without the extension get clean text, which is the path
|
|
@@ -570,7 +593,8 @@ replaceable worker runs the brain core. A staged update is hash-verified, initia
|
|
|
570
593
|
checked for backward-compatible tool schemas, and handed the current `brain_sync` task scope before
|
|
571
594
|
the supervisor switches between requests. Added tools use the standard
|
|
572
595
|
`notifications/tools/list_changed` signal. A failed or breaking candidate is rejected while the old
|
|
573
|
-
worker keeps serving.
|
|
596
|
+
worker keeps serving. A blocked result claim is kept in a durable per-project/session marker, so a
|
|
597
|
+
worker replacement cannot turn a failed evidence check into a result-less completion.
|
|
574
598
|
|
|
575
599
|
Compatible engine updates therefore activate behind the same live connection — no reconnect, no
|
|
576
600
|
host restart. Three cases still require a deliberate reconnect or manual install: the one-time
|
|
@@ -601,7 +625,11 @@ keep lazy first-use indexing instead.
|
|
|
601
625
|
- **Coordination state is local files.** The brain is a file in your repo; the presence lane is a
|
|
602
626
|
file under your home directory. Nothing is uploaded — with one explicit, default-OFF exception:
|
|
603
627
|
the cross-PC presence relay, which (only after per-brain consent in the KLYPIX desktop app)
|
|
604
|
-
shares
|
|
628
|
+
shares whitelisted presence fields and the text of one-time coordination notes over that
|
|
629
|
+
brain's cloud channel. KLYPIX does not automatically attach file/card contents, diffs, or screen
|
|
630
|
+
data, but a note relays whatever its sender typed (and automatic overlap alerts name the declared
|
|
631
|
+
file paths involved). The scope is versioned: an older metadata-only grant does not authorize note
|
|
632
|
+
text and must be granted again. No current consent, no frames.
|
|
605
633
|
- **`install` writes to your home directory:** `~/.claude/project-brain` (engine + runtime),
|
|
606
634
|
`~/.claude/settings.json` (four hooks — written even if Claude Code is not installed),
|
|
607
635
|
`~/.codex/AGENTS.md` (guidance block), and with `--codex-hooks`, `~/.codex/hooks.json`. It also
|
|
@@ -617,9 +645,10 @@ Read this section before you build on any of it.
|
|
|
617
645
|
- **Coordination is machine-local and OS-user-local.** The presence lane is a file in your home
|
|
618
646
|
directory. Two developers on two machines do not see each other's sessions, peers, overlaps or
|
|
619
647
|
messages. This package ships the cross-machine presence *core* (`./presence-relay` — versioned
|
|
620
|
-
metadata-
|
|
621
|
-
|
|
622
|
-
|
|
648
|
+
whitelisted presence metadata plus coordination-note text, a symmetric default-off consent gate,
|
|
649
|
+
loop prevention, stable message IDs and per-recipient-machine acknowledgement primitives), but no
|
|
650
|
+
transport: carrying frames between machines is the desktop app's job. With `klypix-mcp` alone,
|
|
651
|
+
coordination is machine-local.
|
|
623
652
|
- **Overlap matching is exact-path, and both sides must declare.** A session that never declares
|
|
624
653
|
its expected files is invisible to overlap detection, and `src/auth/token.ts` does not match a
|
|
625
654
|
rename or a parent directory.
|
|
@@ -685,7 +714,7 @@ Your `brain.klypix` is yours — it is a plain ZIP and stays readable with or wi
|
|
|
685
714
|
Issues and pull requests: [github.com/dahshanlabs/klypix-mcp](https://github.com/dahshanlabs/klypix-mcp).
|
|
686
715
|
Questions or feedback: [hello@klypix.com](mailto:hello@klypix.com).
|
|
687
716
|
|
|
688
|
-
The repository carries
|
|
717
|
+
The repository carries 59 test files, 54 of them in the `npm test` chain, covering the presence
|
|
689
718
|
lane and its cross-machine relay, the Context Gateway, supervisor hot-swap, auto-update, retrieval
|
|
690
719
|
quality, decay, challenge, lenses, the format guard, the git tools (including a real `git merge`
|
|
691
720
|
through the merge driver), uninstall, and conformance. Run them with `npm test` from a clone — they
|
|
@@ -37,8 +37,13 @@ if (action === 'list') {
|
|
|
37
37
|
console.log(`${entries.length} deleted card(s) in ${path.basename(brainPath)} — newest first\n`);
|
|
38
38
|
for (const e of entries) {
|
|
39
39
|
const full = ids.includes(e.id) ? await readGraveyardCard(buf, e.id) : null;
|
|
40
|
-
|
|
40
|
+
const label = e.summary?.label || e.preview || `(${e.summary?.type || 'unknown'} item)`;
|
|
41
|
+
const audit = e.deletion?.confidence === 'legacy'
|
|
42
|
+
? 'legacy source unverified'
|
|
43
|
+
: `${e.deletion?.initiator || 'unknown'} via ${e.deletion?.cause || 'unclassified'}`;
|
|
44
|
+
console.log(` ${e.id} ${ago(e.deletedAt).padEnd(9)} ${e.area ? `[${e.area}] ` : ''}${label} <${audit}>`);
|
|
41
45
|
if (full?.content) console.log(`\n${String(full.content).split('\n').map((l) => ` ${l}`).join('\n')}\n`);
|
|
46
|
+
else if (full) console.log(`\n ${JSON.stringify(e.summary || { type: full.type || 'unknown' })}\n`);
|
|
42
47
|
}
|
|
43
48
|
console.log(`\nFull text: npx klypix-mcp brain-deleted list <id> --brain "${brainPath}"`);
|
|
44
49
|
console.log(`Restore: npx klypix-mcp brain-deleted restore <id>`);
|
|
@@ -106,22 +106,32 @@ try {
|
|
|
106
106
|
const tools = await a.client.listTools();
|
|
107
107
|
checks.brainSyncDiscoverable = tools.tools?.some((tool) => tool.name === 'brain_sync') === true;
|
|
108
108
|
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
109
|
+
const syncStart = async (client, intent, expectedTasks) => {
|
|
110
|
+
let response;
|
|
111
|
+
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
112
|
+
response = await client.callTool({
|
|
113
|
+
name: 'brain_sync',
|
|
114
|
+
arguments: {
|
|
115
|
+
phase: 'start',
|
|
116
|
+
intent,
|
|
117
|
+
files: ['src/conformance-overlap.ts'],
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
const structured = response.structuredContent || {};
|
|
121
|
+
if (Number.isFinite(structured.timingMs?.total)
|
|
122
|
+
&& structured.counts?.activeTasks === expectedTasks) return { response, attempt };
|
|
123
|
+
await wait(75);
|
|
124
|
+
}
|
|
125
|
+
return { response, attempt: 3 };
|
|
126
|
+
};
|
|
127
|
+
// The lane is deliberately lock-protected and the two real clients heartbeat
|
|
128
|
+
// concurrently. A bounded retry proves convergence without turning one
|
|
129
|
+
// transient lock collision into a false product failure.
|
|
130
|
+
const aStarted = await syncStart(a.client, 'Validate automatic Codex Context Gateway coordination', 1);
|
|
131
|
+
const bStarted = await syncStart(b.client, 'Validate proactive overlap delivery from a second session', 2);
|
|
132
|
+
const aStart = aStarted.response;
|
|
133
|
+
const bStart = bStarted.response;
|
|
134
|
+
metrics.startAttempts = { first: aStarted.attempt, second: bStarted.attempt };
|
|
125
135
|
const aStructured = aStart.structuredContent || {};
|
|
126
136
|
const bStructured = bStart.structuredContent || {};
|
|
127
137
|
checks.taskMemory = Array.isArray(aStructured.context?.hits) && aStructured.context.hits.length > 0;
|
|
@@ -144,16 +154,25 @@ try {
|
|
|
144
154
|
metrics.firstClientLogCount = a.logs.length;
|
|
145
155
|
if (!checks.proactiveLogging && a.logs.length) metrics.firstClientLogs = a.logs.slice(-4);
|
|
146
156
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
+
let checkpointStructured = {};
|
|
158
|
+
let inBandAttempts = 0;
|
|
159
|
+
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
160
|
+
inBandAttempts = attempt;
|
|
161
|
+
const aCheckpoint = await a.client.callTool({
|
|
162
|
+
name: 'brain_sync',
|
|
163
|
+
arguments: {
|
|
164
|
+
phase: 'checkpoint',
|
|
165
|
+
intent: 'Validate automatic Codex Context Gateway coordination',
|
|
166
|
+
files: ['src/conformance-overlap.ts'],
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
checkpointStructured = aCheckpoint.structuredContent || {};
|
|
170
|
+
if (checkpointStructured.messages?.some((message) =>
|
|
171
|
+
String(message.text).includes('Automatic KLYPIX overlap alert'))) break;
|
|
172
|
+
await wait(75);
|
|
173
|
+
}
|
|
174
|
+
metrics.inBandAttempts = inBandAttempts;
|
|
175
|
+
checks.durableInBandOffer = checkpointStructured.messages?.some((message) =>
|
|
157
176
|
String(message.text).includes('Automatic KLYPIX overlap alert')) === true;
|
|
158
177
|
|
|
159
178
|
await Promise.all([
|
|
@@ -188,10 +207,26 @@ try {
|
|
|
188
207
|
&& /no live session declared docs\/unowned\.md/.test(nobody.reason);
|
|
189
208
|
|
|
190
209
|
const receipt = summarizeReceipts({
|
|
191
|
-
messages: [{
|
|
210
|
+
messages: [{
|
|
211
|
+
id: 'finding-note',
|
|
212
|
+
from: 'finding-sender',
|
|
213
|
+
to: 'all',
|
|
214
|
+
text: 'verified note',
|
|
215
|
+
ts: now - 1_000,
|
|
216
|
+
candidateIds: ['finding-owner'],
|
|
217
|
+
deliveryVersion: 2,
|
|
218
|
+
deliveries: [{
|
|
219
|
+
recipientId: 'finding-owner',
|
|
220
|
+
state: 'acknowledged',
|
|
221
|
+
attempts: 1,
|
|
222
|
+
offeredAt: now - 900,
|
|
223
|
+
acknowledgedAt: now - 500,
|
|
224
|
+
}],
|
|
225
|
+
seen: ['finding-owner'],
|
|
226
|
+
}],
|
|
192
227
|
sessions: lane, selfId: 'finding-sender', now,
|
|
193
228
|
});
|
|
194
|
-
checks.findingReceiptRendered = /
|
|
229
|
+
checks.findingReceiptRendered = /model-context delivery acknowledged by all 1 target peer\(s\) on a later action \(not human-read\)/.test(renderReceiptSummary(receipt));
|
|
195
230
|
}
|
|
196
231
|
|
|
197
232
|
// ── Cross-PC presence: simulated two-machine scenario ─────────────────────
|
|
@@ -305,7 +340,7 @@ const required = [
|
|
|
305
340
|
'exactBlockingOverlap',
|
|
306
341
|
'alertQueued',
|
|
307
342
|
'proactiveLogging',
|
|
308
|
-
'
|
|
343
|
+
'durableInBandOffer',
|
|
309
344
|
'findingRouteOwnerReason',
|
|
310
345
|
'findingRouteNobodyReason',
|
|
311
346
|
'findingReceiptRendered',
|
|
@@ -323,7 +358,8 @@ const result = {
|
|
|
323
358
|
metrics,
|
|
324
359
|
contract: {
|
|
325
360
|
proactive: 'best-effort MCP logging notification',
|
|
326
|
-
|
|
361
|
+
inBand: 'a retained machine-local note is offered on a supported model-context KLYPIX action, then acknowledged only by a later independent action; expiry/overflow are failed receipts',
|
|
362
|
+
crossMachine: 'relay primitives require caller-confirmed durable insertion and a per-recipient-machine acknowledgement; app bridge wiring is a separate conformance boundary',
|
|
327
363
|
},
|
|
328
364
|
};
|
|
329
365
|
|
|
@@ -336,6 +372,6 @@ if (jsonMode) {
|
|
|
336
372
|
}
|
|
337
373
|
if (checks.error) console.log(` error: ${checks.error}`);
|
|
338
374
|
console.log(` memory/coordination: ${metrics.firstClientMs ?? '?'}ms / ${metrics.secondClientMs ?? '?'}ms`);
|
|
339
|
-
console.log(' proactive notifications are best-effort;
|
|
375
|
+
console.log(' proactive notifications are best-effort; retained notes use offer → later-action acknowledgement, with explicit failure receipts.');
|
|
340
376
|
}
|
|
341
377
|
process.exit(ok ? 0 : 1);
|
package/bin/klypix-git-tools.mjs
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// • ONE merge engine — the driver rides src/merge-brains.mjs verbatim.
|
|
13
13
|
// • The registered driver path is the INSTALLED runtime
|
|
14
14
|
// (~/.claude/project-brain) — stable across npx cache evictions; this
|
|
15
|
-
// module self-provisions the
|
|
15
|
+
// module self-provisions the four engine files + their two deps there
|
|
16
16
|
// when missing, without running the full hook installer.
|
|
17
17
|
// • A truncated list must NEVER render as complete: every capped section
|
|
18
18
|
// emits its "…and N more" through an unguarded push.
|
|
@@ -85,11 +85,11 @@ async function loadEngine() {
|
|
|
85
85
|
|
|
86
86
|
// ── git-driver ──────────────────────────────────────────────────────────────
|
|
87
87
|
|
|
88
|
-
const ENGINE_FILES = ['klypix-merge-driver.mjs', 'merge-brains.mjs', 'klypix-format.mjs'];
|
|
88
|
+
const ENGINE_FILES = ['klypix-merge-driver.mjs', 'merge-brains.mjs', 'klypix-format.mjs', 'brain-graveyard.mjs'];
|
|
89
89
|
const ENGINE_DEPS = ['jszip', 'fractional-indexing'];
|
|
90
90
|
|
|
91
|
-
// Make sure the INSTALLED runtime can actually run the driver: the
|
|
92
|
-
// engine files plus their two
|
|
91
|
+
// Make sure the INSTALLED runtime can actually run the driver: the four
|
|
92
|
+
// engine files plus their two runtime deps. This is deliberately a
|
|
93
93
|
// light provision — it never touches hooks or servers; the full installer
|
|
94
94
|
// remains `npx klypix-mcp install`.
|
|
95
95
|
function ensureDriverRuntime() {
|
package/bin/klypix-install.mjs
CHANGED
|
@@ -226,7 +226,7 @@ const flatten = (code) => code
|
|
|
226
226
|
.replace(/\.\.\/src\/klypix-(core|format)\.mjs/g, './klypix-$1.mjs')
|
|
227
227
|
// brain-doctor + agent-rules (the server's lazy `import('../src/brain-doctor.mjs')`
|
|
228
228
|
// for the brain_doctor tool) → flat sibling refs in the runtime layout.
|
|
229
|
-
.replace(/\.\.\/src\/(brain-doctor|agent-rules|mcp-presence|mcp-supervisor|mcp-auto-update|semantic-memory|runtime-inspector|project-graph|git-capture-install)\.mjs/g, './$1.mjs')
|
|
229
|
+
.replace(/\.\.\/src\/(bench|brain-doctor|agent-presence|agent-rules|finding-routing|mcp-presence|mcp-supervisor|mcp-auto-update|presence-relay|semantic-memory|runtime-inspector|project-graph|git-capture-install|remote-client)\.mjs/g, './$1.mjs')
|
|
230
230
|
.replace(/klypix-worker\.mjs/g, 'klypix-mcp-worker.mjs')
|
|
231
231
|
.replace(/const PKG_VERSION = \(\(\) => \{[\s\S]*?\}\)\(\);/, `const PKG_VERSION = '${VERSION}'; // baked at install (flat layout has no package.json)`);
|
|
232
232
|
|
|
@@ -293,7 +293,7 @@ try {
|
|
|
293
293
|
// canvas-view-app.html is the canvas_view MCP App UI — staged raw (an HTML
|
|
294
294
|
// file must never get a JS-comment banner) beside the flat server, which
|
|
295
295
|
// resolves it via its ./canvas-view-app.html candidate path.
|
|
296
|
-
for (const f of ['global-brain-hook.mjs', 'brain-semantic.mjs', 'semantic-memory.mjs', 'brain-note.mjs', 'brain-git-hook.mjs', 'git-capture-install.mjs', 'brain-history.mjs', 'brain-graveyard.mjs', 'klypix-format.mjs', 'klypix-core.mjs', 'brain-write-lock.mjs', 'agent-rules.mjs', 'brain-doctor.mjs', 'agent-presence.mjs', 'mcp-presence.mjs', 'finding-routing.mjs', 'mcp-supervisor.mjs', 'mcp-auto-update.mjs', 'runtime-inspector.mjs', 'project-graph.mjs', 'bench.mjs', 'codex-brain-hook.mjs', 'codex-hooks.mjs', 'canvas-view-app.html']) {
|
|
296
|
+
for (const f of ['global-brain-hook.mjs', 'brain-semantic.mjs', 'semantic-memory.mjs', 'brain-note.mjs', 'brain-git-hook.mjs', 'git-capture-install.mjs', 'brain-history.mjs', 'brain-graveyard.mjs', 'klypix-format.mjs', 'klypix-core.mjs', 'brain-write-lock.mjs', 'agent-rules.mjs', 'brain-doctor.mjs', 'agent-presence.mjs', 'mcp-presence.mjs', 'result-reconcile.mjs', 'finding-routing.mjs', 'presence-relay.mjs', 'mcp-supervisor.mjs', 'mcp-auto-update.mjs', 'runtime-inspector.mjs', 'project-graph.mjs', 'remote-client.mjs', 'bench.mjs', 'codex-brain-hook.mjs', 'codex-hooks.mjs', 'canvas-view-app.html']) {
|
|
297
297
|
const s = path.join(SRC, f); if (exists(s)) staged.push({ dst: f, content: fs.readFileSync(s, 'utf8') });
|
|
298
298
|
}
|
|
299
299
|
for (const [src, dst] of [
|
package/bin/klypix-worker.mjs
CHANGED
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
registerProjectBrain,
|
|
39
39
|
spawnAutoUpdateHelper,
|
|
40
40
|
} from '../src/mcp-auto-update.mjs';
|
|
41
|
+
import { remoteActions, remoteCommand, remoteSessions, remoteStatus } from '../src/remote-client.mjs';
|
|
41
42
|
// Namespace import (already in-process via the klypix-core chain, so zero added
|
|
42
43
|
// load cost) so a bundle whose klypix-format predates classifyDecay degrades
|
|
43
44
|
// gracefully — a named import of a missing export would kill the whole server.
|
|
@@ -224,6 +225,85 @@ const toContent = (r) => {
|
|
|
224
225
|
return mcpPresence.decorateToolResult(result);
|
|
225
226
|
};
|
|
226
227
|
|
|
228
|
+
const remoteToolResult = (label, value) => mcpPresence.decorateToolResult({
|
|
229
|
+
content: [{ type: 'text', text: `${label}\n\n${JSON.stringify(value, null, 2)}` }],
|
|
230
|
+
structuredContent: { result: value },
|
|
231
|
+
});
|
|
232
|
+
const remoteToolError = (error) => {
|
|
233
|
+
const message = typeof error?.message === 'string' && /^KLYPIX_[A-Z0-9_]+$/.test(error.message)
|
|
234
|
+
? error.message : 'KLYPIX_REMOTE_REQUEST_REJECTED';
|
|
235
|
+
return mcpPresence.decorateToolResult({
|
|
236
|
+
content: [{ type: 'text', text: `${message}. The KLYPIX desktop window may be closed, but its tray relay must be running and Remote control must be enabled.` }],
|
|
237
|
+
isError: true,
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
server.registerTool('remote_status', {
|
|
242
|
+
title: 'Inspect the local KLYPIX Remote relay',
|
|
243
|
+
description: 'Reports whether the KLYPIX tray relay, discovery, provider hooks, verified controls, phone pairing, and encrypted network relay are active. The desktop WINDOW may be closed; KLYPIX must still be running in the tray and the PC must be awake.',
|
|
244
|
+
annotations: { destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
245
|
+
inputSchema: {},
|
|
246
|
+
}, async () => {
|
|
247
|
+
try { return remoteToolResult('KLYPIX Remote status', await remoteStatus()); }
|
|
248
|
+
catch (error) { return remoteToolError(error); }
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
server.registerTool('remote_sessions', {
|
|
252
|
+
title: 'List coding-agent sessions by KLYPIX project',
|
|
253
|
+
description: 'Lists local coding-agent sessions with their project/path binding, current state, active host binding, and exact capability receipts. Treat each receipt as the truth for that specific provider + version + live session; never infer a missing action. The KLYPIX tray relay must be running.',
|
|
254
|
+
annotations: { destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
255
|
+
inputSchema: {
|
|
256
|
+
project_id: z.string().max(2048).optional().describe('Optional exact KLYPIX project id from a prior session result.'),
|
|
257
|
+
},
|
|
258
|
+
}, async ({ project_id }) => {
|
|
259
|
+
try { return remoteToolResult('KLYPIX Remote sessions', await remoteSessions({ projectId: project_id })); }
|
|
260
|
+
catch (error) { return remoteToolError(error); }
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
server.registerTool('remote_actions', {
|
|
264
|
+
title: 'List pending coding-agent decisions',
|
|
265
|
+
description: 'Lists pending questions, permission requests, confirmations, failures, conflicts, and reviews reported by supported provider hooks. Approval/rejection still requires the exact session capability receipt and request digest. The KLYPIX tray relay must be running.',
|
|
266
|
+
annotations: { destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
267
|
+
inputSchema: {},
|
|
268
|
+
}, async () => {
|
|
269
|
+
try { return remoteToolResult('KLYPIX Remote actions', await remoteActions()); }
|
|
270
|
+
catch (error) { return remoteToolError(error); }
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
server.registerTool('remote_command', {
|
|
274
|
+
title: 'Control one verified coding-agent session',
|
|
275
|
+
description: 'Sends one command to the exact machine/provider/session and host binding named by a fresh remote_sessions capability receipt. Supports opening the exact provider session, messages, images/files, interrupt, approve/reject, close/archive/resume only when that exact receipt says the operation is available. File paths are local to this PC. The KLYPIX tray relay must be running and verified controls enabled.',
|
|
276
|
+
annotations: { destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
277
|
+
inputSchema: {
|
|
278
|
+
machine_id: z.string().min(1).max(256),
|
|
279
|
+
provider: z.enum(['antigravity-agent', 'claude-code', 'codex', 'cursor-agent', 'gemini-cli', 'grok-build', 'kimi-code', 'opencode', 'pi', 'qoder', 'mistral-vibe', 'unknown']),
|
|
280
|
+
external_session_id: z.string().min(1).max(512),
|
|
281
|
+
operation: z.enum(['send-text', 'send-message', 'attach-image', 'attach-file', 'interrupt', 'approve', 'reject', 'close', 'archive', 'resume', 'open-provider']),
|
|
282
|
+
capability_receipt_id: z.string().min(1).max(256).describe('Fresh receipt id for this exact operation from remote_sessions.'),
|
|
283
|
+
binding_id: z.string().min(1).max(256).describe('Fresh host binding id named by the receipt.'),
|
|
284
|
+
request_digest: z.string().regex(/^[0-9a-f]{64}$/).optional().describe('Required for approve/reject; copy it from the pending remote action.'),
|
|
285
|
+
text: z.string().min(1).max(20000).optional(),
|
|
286
|
+
replace_draft: z.boolean().optional(),
|
|
287
|
+
attachments: z.array(z.object({
|
|
288
|
+
path: z.string().min(1).max(2048).describe('Absolute local file path on this PC.'),
|
|
289
|
+
kind: z.enum(['image', 'video', 'audio', 'document', 'file']),
|
|
290
|
+
mime_type: z.string().min(1).max(128).optional(),
|
|
291
|
+
})).max(25).optional(),
|
|
292
|
+
},
|
|
293
|
+
}, async ({ machine_id, provider, external_session_id, operation, capability_receipt_id, binding_id, request_digest, text, replace_draft, attachments }) => {
|
|
294
|
+
try {
|
|
295
|
+
const receipt = await remoteCommand({
|
|
296
|
+
machineId: machine_id, provider, externalSessionId: external_session_id, operation,
|
|
297
|
+
capabilityReceiptId: capability_receipt_id, bindingId: binding_id,
|
|
298
|
+
requestDigest: request_digest, text, replaceDraft: replace_draft,
|
|
299
|
+
attachments: attachments?.map((attachment) => ({
|
|
300
|
+
path: attachment.path, kind: attachment.kind, mimeType: attachment.mime_type,
|
|
301
|
+
})),
|
|
302
|
+
});
|
|
303
|
+
return remoteToolResult('KLYPIX Remote command receipt', receipt);
|
|
304
|
+
} catch (error) { return remoteToolError(error); }
|
|
305
|
+
});
|
|
306
|
+
|
|
227
307
|
server.registerTool('list_canvases', {
|
|
228
308
|
title: 'List KLYPIX canvases',
|
|
229
309
|
description: 'List all .klypix / .any canvas files in the vault, with card and connection counts.',
|
|
@@ -413,8 +493,9 @@ server.registerTool('brain_insights', {
|
|
|
413
493
|
inputSchema: {
|
|
414
494
|
canvas: z.string().optional().describe('Canvas filename/path. Defaults to the project brain ("brain").'),
|
|
415
495
|
staleDays: z.number().optional().describe('Open questions older than this many days count as stale (default 21).'),
|
|
496
|
+
view: z.enum(['full', 'areas', 'status']).optional().describe('"areas" = a cheap category map (what sections exist + live counts) to orient BEFORE retrieving. "status" = where each active area stands (newest milestone + open count). "full" (default) = hubs, orphans, stale questions and areas.'),
|
|
416
497
|
},
|
|
417
|
-
}, async ({ canvas, staleDays }) => toContent(await opBrainInsights({ vault: mcpPresence.vault, canvas, staleDays })));
|
|
498
|
+
}, async ({ canvas, staleDays, view }) => toContent(await opBrainInsights({ vault: mcpPresence.vault, canvas, staleDays, view })));
|
|
418
499
|
|
|
419
500
|
server.registerTool('brain_lens', {
|
|
420
501
|
title: 'Brain lens — machine-readable views of a brain (freshness · provenance · activity · timeline · orrery · unresolved)',
|
|
@@ -425,8 +506,9 @@ server.registerTool('brain_lens', {
|
|
|
425
506
|
root: z.string().optional().describe('Orrery center: a card title prefix or id. Default: the most-connected hub card.'),
|
|
426
507
|
staleDays: z.number().optional().describe('Open questions older than this count as stale (default 21).'),
|
|
427
508
|
limit: z.number().optional().describe('Cap for recent-activity entries (default 30).'),
|
|
509
|
+
structured: z.boolean().optional().describe('Also return the full machine-readable lens object (large — tens of KB). Default false: the markdown answers the question, and the object was previously attached to every call whether or not anything read it.'),
|
|
428
510
|
},
|
|
429
|
-
}, async ({ canvas, view, root, staleDays, limit }) => toContent(await opBrainLens({ vault: mcpPresence.vault, canvas, view, root, staleDays, limit })));
|
|
511
|
+
}, async ({ canvas, view, root, staleDays, limit, structured }) => toContent(await opBrainLens({ vault: mcpPresence.vault, canvas, view, root, staleDays, limit, structured })));
|
|
430
512
|
|
|
431
513
|
server.registerTool('brain_connect', {
|
|
432
514
|
title: 'Connect related-but-unlinked brain cards (densify the graph)',
|
|
@@ -509,7 +591,7 @@ server.registerTool('brain_note', {
|
|
|
509
591
|
|
|
510
592
|
server.registerTool('brain_message', {
|
|
511
593
|
title: 'Message the other live agent sessions on this project (one-time note, not a brain card)',
|
|
512
|
-
description: 'Leave a DELIBERATE, targeted note for the OTHER active agent sessions working on this project right now ("merged the hook refactor — rebase before you commit", "don\'t touch canvasStore, mid-refactor"). Any MCP client can send and receive through the shared presence lane.
|
|
594
|
+
description: 'Leave a DELIBERATE, targeted note for the OTHER active agent sessions working on this project right now ("merged the hook refactor — rebase before you commit", "don\'t touch canvasStore, mid-refactor"). Any MCP client can send and receive through the shared machine-local presence lane. A supported lifecycle event or KLYPIX tool result offers the note into model-visible context; a later independent supported action acknowledges that offer. Pending/offered notes replay after reconnect, while expiry or capacity loss leaves a failed per-recipient receipt instead of silently disappearing. Acknowledged means a later action followed the offer — it is NOT proof a human read it. Delivery remains OS-user-local, machine-local, bounded by a 24h TTL, and unavailable to a peer that never takes a supported action. Ephemeral and NOT persisted to the brain — for a durable decision use brain_note instead.',
|
|
513
595
|
inputSchema: {
|
|
514
596
|
text: z.string().describe('The note to deliver (kept to 400 chars).'),
|
|
515
597
|
to: z.string().optional().describe('Target hint — a peer session id-prefix or branch name; omit or "all" for every live session.'),
|
|
@@ -518,12 +600,23 @@ server.registerTool('brain_message', {
|
|
|
518
600
|
}, async ({ text, to, canvas }) => {
|
|
519
601
|
let via; try { via = server.server.getClientVersion()?.name; } catch { /* optional */ }
|
|
520
602
|
mcpPresence.noteSent(text);
|
|
521
|
-
return toContent(await opBrainMessage({
|
|
603
|
+
return toContent(await opBrainMessage({
|
|
604
|
+
vault: mcpPresence.vault,
|
|
605
|
+
// Bind the default message lane to the brain this worker actually joined.
|
|
606
|
+
// The worker process can be launched from an IDE/install directory that has
|
|
607
|
+
// a different ancestor brain; falling back to process.cwd() would split the
|
|
608
|
+
// sender presence and its message across two unrelated project lanes.
|
|
609
|
+
canvas: canvas || mcpPresence.brainPath,
|
|
610
|
+
text,
|
|
611
|
+
to,
|
|
612
|
+
via,
|
|
613
|
+
from: mcpPresence.refreshIdentity(),
|
|
614
|
+
}));
|
|
522
615
|
});
|
|
523
616
|
|
|
524
617
|
server.registerTool('brain_sync', {
|
|
525
618
|
title: 'KLYPIX Context Gateway — synchronize task, peers, conflicts, and relevant memory',
|
|
526
|
-
description: 'APPROVAL-FREE task gateway over the authorized MCP connection. Call FIRST with a concise intent and expected files, again when scope changes, and with phase:"complete" before the final response. One bounded response returns compact task-relevant brain context, active TASK peers (idle connections hidden), one-time messages, structured exact-file conflicts, and late-arrival overlap alerts. Works on any MCP host — it needs only the authorized MCP connection, so native lifecycle hooks are optional. LIMITS: conflict matching is EXACT-PATH and both sessions must have declared their files, coordination is machine-local and OS-user-local (a teammate on another machine is invisible), and overlap
|
|
619
|
+
description: 'APPROVAL-FREE task gateway over the authorized MCP connection. Call FIRST with a concise intent and expected files, again when scope changes, and with phase:"complete" before the final response. One bounded response returns compact task-relevant brain context, active TASK peers (idle connections hidden), one-time messages, structured exact-file conflicts, and late-arrival overlap alerts. A completion that supplies machine-checkable result manifests is fail-closed: invalid, conflicting, or incomparable evidence returns needs-reconciliation and retains task scope. Works on any MCP host — it needs only the authorized MCP connection, so native lifecycle hooks are optional. LIMITS: conflict matching is EXACT-PATH and both sessions must have declared their files, coordination/result reconciliation is machine-local and OS-user-local (a teammate on another machine is invisible), and file overlap remains ADVISORY.',
|
|
527
620
|
annotations: {
|
|
528
621
|
destructiveHint: false,
|
|
529
622
|
idempotentHint: true,
|
|
@@ -534,11 +627,24 @@ server.registerTool('brain_sync', {
|
|
|
534
627
|
intent: z.string().max(160).optional().describe('One sentence describing the current task. Supply for start/checkpoint; completion clears it.'),
|
|
535
628
|
files: z.array(z.string()).max(20).optional().describe('Project-relative files you expect to touch or have touched. Exact overlaps with peers are flagged.'),
|
|
536
629
|
phase: z.enum(['start', 'checkpoint', 'complete']).optional().describe('start replaces prior task scope; checkpoint merges changed scope; complete clears task intent/files. Default: checkpoint.'),
|
|
537
|
-
include_context: z.boolean().optional().describe('Include fast task-relevant brain cards in the same response. Defaults true;
|
|
630
|
+
include_context: z.boolean().optional().describe('Include fast task-relevant brain cards and offer queued coordination notes in the same response. Defaults true; false also defers note delivery so internal supervisor probes cannot consume model-visible messages.'),
|
|
631
|
+
// Deliberately permissive at the MCP/Zod boundary. The authoritative,
|
|
632
|
+
// versioned fail-closed validator lives in result-reconcile.mjs and must see
|
|
633
|
+
// malformed/unknown nested fields so it can persist the evidence-required
|
|
634
|
+
// marker before rejecting them. A strict transport schema rejected first,
|
|
635
|
+
// allowing a later result-less completion to bypass that state entirely.
|
|
636
|
+
results: z.unknown().optional().describe('On phase complete, 1-8 result manifests for stable claim keys. The in-handler versioned validator rejects malformed, empty, unknown-field, or incomparable evidence and retains task scope.'),
|
|
538
637
|
},
|
|
539
|
-
}, async ({ project, intent, files, phase, include_context }) => {
|
|
638
|
+
}, async ({ project, intent, files, phase, include_context, results }) => {
|
|
540
639
|
const totalStartedAt = Date.now();
|
|
541
|
-
const report = mcpPresence.sync({
|
|
640
|
+
const report = mcpPresence.sync({
|
|
641
|
+
project,
|
|
642
|
+
intent,
|
|
643
|
+
files,
|
|
644
|
+
phase,
|
|
645
|
+
results,
|
|
646
|
+
deliverMessages: include_context !== false,
|
|
647
|
+
});
|
|
542
648
|
// Zero-manual harness convergence: brain_sync is the one project-aware
|
|
543
649
|
// gateway every MCP host can call. Register MCP-only projects here (Claude's
|
|
544
650
|
// lifecycle hook is no longer the sole registry writer), then reconcile only
|
|
@@ -624,6 +730,7 @@ server.registerTool('brain_sync', {
|
|
|
624
730
|
text: [report.text, harnessText, shipNotice, contextText, timingText].filter(Boolean).join('\n\n'),
|
|
625
731
|
}],
|
|
626
732
|
structuredContent,
|
|
733
|
+
...(report.isError ? { isError: true } : {}),
|
|
627
734
|
};
|
|
628
735
|
});
|
|
629
736
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "klypix-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.66.1",
|
|
4
4
|
"description": "Shared project brain and MCP coordination server for multi-agent coding.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"./core": "./src/klypix-core.mjs",
|
|
54
54
|
"./presence": "./src/agent-presence.mjs",
|
|
55
55
|
"./mcp-presence": "./src/mcp-presence.mjs",
|
|
56
|
+
"./result-reconcile": "./src/result-reconcile.mjs",
|
|
56
57
|
"./presence-relay": "./src/presence-relay.mjs",
|
|
57
58
|
"./supervisor": "./src/mcp-supervisor.mjs",
|
|
58
59
|
"./runtime-inspector": "./src/runtime-inspector.mjs",
|
|
@@ -76,10 +77,11 @@
|
|
|
76
77
|
"node": ">=18"
|
|
77
78
|
},
|
|
78
79
|
"scripts": {
|
|
80
|
+
"test:remote": "node test/remote-client.mjs",
|
|
79
81
|
"test:project-graph": "node test/project-graph.mjs",
|
|
80
82
|
"bench": "node bin/klypix-mcp.mjs bench",
|
|
81
83
|
"test:bench": "node test/bench.mjs",
|
|
82
|
-
"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/agent-presence.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/context-gateway.mjs && node test/conformance.mjs && node test/brain-doctor.mjs && node test/version-currency.mjs && node test/ship-capture.mjs && node test/lane-message.mjs && node test/brain-quality.mjs && node test/brain-connect-orphans.mjs && node test/brief-and-recall.mjs && node test/layout-cluster.mjs && node test/brain-ask.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/skill-staleness.mjs && node test/canvas-view.mjs && node test/status-completeness.mjs && node test/semantic-gate.mjs && node test/memory-runtime.mjs && node test/semantic-cache.mjs && node test/decay-status.mjs && node test/decay-hook.mjs && node test/evidence-anchors.mjs && node test/presence-visibility.mjs && node test/merge-brains.mjs && node test/concurrent-writes.mjs && node test/lock-interop.mjs && node test/a2a-smoke.mjs && node test/cli-args.mjs && node test/format-guard.mjs && node test/git-tools.mjs && node test/uninstall.mjs",
|
|
84
|
+
"test": "node test/publish-verdict.mjs && node test/remote-client.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/agent-presence.mjs && node test/result-reconcile.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/context-gateway.mjs && node test/conformance.mjs && node test/brain-doctor.mjs && node test/version-currency.mjs && node test/ship-capture.mjs && node test/lane-message.mjs && node test/brain-quality.mjs && node test/brain-connect-orphans.mjs && node test/brief-and-recall.mjs && node test/layout-cluster.mjs && node test/brain-ask.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/skill-staleness.mjs && node test/canvas-view.mjs && node test/status-completeness.mjs && node test/semantic-gate.mjs && node test/memory-runtime.mjs && node test/semantic-cache.mjs && node test/decay-status.mjs && node test/decay-hook.mjs && node test/evidence-anchors.mjs && node test/presence-visibility.mjs && node test/merge-brains.mjs && node test/concurrent-writes.mjs && node test/lock-interop.mjs && node test/a2a-smoke.mjs && node test/cli-args.mjs && node test/format-guard.mjs && node test/git-tools.mjs && node test/uninstall.mjs",
|
|
83
85
|
"test:memory": "node test/memory-runtime.mjs",
|
|
84
86
|
"test:memory:soak": "node --expose-gc test/memory-soak.mjs",
|
|
85
87
|
"runtime": "node bin/klypix-runtime.mjs"
|