nexus-prime 3.17.0 → 3.18.0
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 +26 -9
- package/dist/agents/adapters/mcp.d.ts +4 -0
- package/dist/agents/adapters/mcp.d.ts.map +1 -1
- package/dist/agents/adapters/mcp.js +221 -24
- package/dist/agents/adapters/mcp.js.map +1 -1
- package/dist/engines/feature-registry.js +3 -3
- package/dist/engines/feature-registry.js.map +1 -1
- package/dist/engines/instruction-gateway.d.ts.map +1 -1
- package/dist/engines/instruction-gateway.js +15 -7
- package/dist/engines/instruction-gateway.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -293,9 +293,9 @@ Read the full tiered market map: [Comparison](https://sir-ad.github.io/nexus-pri
|
|
|
293
293
|
<details>
|
|
294
294
|
<summary><b>🧭 Platform Feature Registry</b></summary>
|
|
295
295
|
|
|
296
|
-
Generated from shared feature metadata at 2026-03-
|
|
296
|
+
Generated from shared feature metadata at 2026-03-21T02:48:13.064Z.
|
|
297
297
|
|
|
298
|
-
Inventory Snapshot: 109 skills · 64 workflows ·
|
|
298
|
+
Inventory Snapshot: 109 skills · 64 workflows · 9 hooks · 5 automations · 7 crews · 139 specialists
|
|
299
299
|
|
|
300
300
|
Control Plane Snapshot: 9 MCP surfaces · 6 client targets · 5 dashboard capabilities · 6 runtime subsystems · 5 release gates
|
|
301
301
|
|
|
@@ -310,11 +310,11 @@ Operator-facing entrypoints and expert control surfaces.
|
|
|
310
310
|
| nexus_orchestrate | core MCP | Plan, select assets, execute through worktree-backed runtime, and persist truth. | Default raw-prompt execution path. |
|
|
311
311
|
| nexus_plan_execution | planning MCP | Inspect the planner ledger before mutation. | Used when operators want a pre-run ledger. |
|
|
312
312
|
| nexus_recall_memory / nexus_memory_stats / nexus_store_memory | memory MCP | Inspect and persist durable learnings. | Feeds the memory fabric and handoff flow. |
|
|
313
|
-
| nexus_optimize_tokens | optimization MCP |
|
|
314
|
-
| nexus_mindkit_check / nexus_ghost_pass / nexus_spawn_workers | safety + runtime MCP | Run governance preflight, pre-
|
|
313
|
+
| nexus_optimize_tokens | optimization MCP | Generate a token-saving reading plan before broad file inspection. | Mandatory before reading 3+ files from client-visible intent. |
|
|
314
|
+
| nexus_mindkit_check / nexus_ghost_pass / nexus_spawn_workers | safety + runtime MCP | Run governance preflight, refactor pre-flight analysis, and explicit swarm control. | Mindkit and ghost-pass are required lifecycle checks for risky or multi-file mutation. |
|
|
315
315
|
| nexus_memory_export / import / backup / maintain / trace | memory portability MCP | Export, restore, maintain, and inspect local-first memory bundles. | Supports backup/resume and OpenClaw-oriented bridge packs. |
|
|
316
316
|
| nexus_list_skills / workflows / hooks / automations / specialists / crews | catalog MCP | Expose what the runtime can activate. | Used for explicit operator control and diagnostics. |
|
|
317
|
-
| nexus_run_status / nexus_federation_status / nexus_session_dna | runtime truth MCP | Inspect persisted run state, federation status, and handoff DNA. |
|
|
317
|
+
| nexus_run_status / nexus_federation_status / nexus_session_dna | runtime truth MCP | Inspect persisted run state, federation status, and handoff DNA. | Session DNA generation is mandatory before ending a meaningful session. |
|
|
318
318
|
|
|
319
319
|
</details>
|
|
320
320
|
|
|
@@ -362,7 +362,7 @@ Core architecture layers that shape execution, memory, and visibility.
|
|
|
362
362
|
| Source-Aware Token Budget | runtime subsystem | Allocates token budget across repo, memory, RAG, patterns, and runtime traces. | Persists selected and dropped context. |
|
|
363
363
|
| Bootstrap Manifest Truth | runtime subsystem | Tracks configured client bootstrap artifacts independently from active heartbeats. | Supports installed vs active truth in the dashboard. |
|
|
364
364
|
| Artifact Selection Audit | runtime subsystem | Explains why skills/workflows/crews/specialists were selected or rejected. | Persists auditable selection rationale. |
|
|
365
|
-
| Bundled assets: 109 skills · 64 workflows ·
|
|
365
|
+
| Bundled assets: 109 skills · 64 workflows · 9 hooks · 5 automations · 7 crews · 139 specialists | runtime subsystem | Summarizes the current bundled runtime inventory. | Detailed lists live in the runtime catalog section and dashboard catalog view. |
|
|
366
366
|
|
|
367
367
|
</details>
|
|
368
368
|
|
|
@@ -390,7 +390,7 @@ Quality and security checks required before release.
|
|
|
390
390
|
|
|
391
391
|
Generated from bundled runtime catalogs plus repo-local overrides via `npm run generate:readme-catalog`.
|
|
392
392
|
|
|
393
|
-
Inventory Snapshot: 109 skills · 64 workflows ·
|
|
393
|
+
Inventory Snapshot: 109 skills · 64 workflows · 9 hooks · 5 automations · 7 crews
|
|
394
394
|
|
|
395
395
|
<details>
|
|
396
396
|
<summary><b>Skills</b> (109)</summary>
|
|
@@ -582,12 +582,16 @@ Inventory Snapshot: 109 skills · 64 workflows · 5 hooks · 3 automations · 7
|
|
|
582
582
|
</details>
|
|
583
583
|
|
|
584
584
|
<details>
|
|
585
|
-
<summary><b>Hooks</b> (
|
|
585
|
+
<summary><b>Hooks</b> (9)</summary>
|
|
586
586
|
|
|
587
587
|
| Name | Type/Scope | Purpose | Trigger / When used |
|
|
588
588
|
| --- | --- | --- | --- |
|
|
589
|
+
| before-compaction-flush | read · base | Flush memory prefrontal to SQLite before context compaction. | before-compaction · context budget nearing limit |
|
|
590
|
+
| before-mutate-guard | read · base | Local checkpoint before bounded file mutation. | before-mutate |
|
|
589
591
|
| before-verify-approval | orchestrate · base | Attach approval-loop workflows before verification for domain work. | before-verify · verification checkpoint |
|
|
592
|
+
| failure-summary | read · base | Local failure checkpoint for recovery notes and retry scope. | run.failed |
|
|
590
593
|
| memory-shield-escalation | read · base | Flag stored memories for shield review when policy risk is detected. | memory.stored · high priority memory stored |
|
|
594
|
+
| memory-stored-review | read · base | Local review hook for important stored memories. | memory.stored |
|
|
591
595
|
| promotion-audit | read · base | Require a security-oriented audit note on promotion approval. | promotion.approved · promotion approved |
|
|
592
596
|
| retry-narrow-scope | orchestrate · base | Focus retries on the failing surface after an error cluster. | retry · retry requested |
|
|
593
597
|
| run-created-brief | read · base | Attach planning context and default orchestration on run creation. | run.created · run created |
|
|
@@ -595,12 +599,14 @@ Inventory Snapshot: 109 skills · 64 workflows · 5 hooks · 3 automations · 7
|
|
|
595
599
|
</details>
|
|
596
600
|
|
|
597
601
|
<details>
|
|
598
|
-
<summary><b>Automations</b> (
|
|
602
|
+
<summary><b>Automations</b> (5)</summary>
|
|
599
603
|
|
|
600
604
|
| Name | Type/Scope | Purpose | Trigger / When used |
|
|
601
605
|
| --- | --- | --- | --- |
|
|
606
|
+
| failure-followup | event · base | Queue a bounded retry follow-up after a failed run. | event:run.failed |
|
|
602
607
|
| failure-recovery-automation | event · base | Queue retry and review workflows after a failed run. | event:run.failed |
|
|
603
608
|
| memory-governance-automation | event · base | Attach memory and security review after memory storage events. | event:memory.stored |
|
|
609
|
+
| session-close-followup | event · base | Queue a bounded approval follow-up after a verified run. | event:run.verified |
|
|
604
610
|
| verified-followup-automation | event · base | Queue a bounded approval workflow after a verified run. | event:run.verified |
|
|
605
611
|
|
|
606
612
|
</details>
|
|
@@ -626,6 +632,17 @@ Inventory Snapshot: 109 skills · 64 workflows · 5 hooks · 3 automations · 7
|
|
|
626
632
|
## 📜 Release History
|
|
627
633
|
|
|
628
634
|
<details open>
|
|
635
|
+
<summary><b>v3.18.0</b> · 2026-03-21 · Lifecycle hardening across MCP, bootstrap artifacts, and release surfaces</summary>
|
|
636
|
+
|
|
637
|
+
- **Lifecycle checklists and footers**: `nexus_session_bootstrap` now appends a mandatory protocol checklist, and `nexus_orchestrate` now appends a mandatory remaining-steps footer.
|
|
638
|
+
- **Lifecycle warnings**: MCP responses now warn when 15+ post-orchestrate tool calls happen without `nexus_store_memory`, and when Nexus-visible 3+ file intent appears without `nexus_optimize_tokens`.
|
|
639
|
+
- **Shared instruction closure**: `CLAUDE.md`, `AGENTS.md`, client bootstrap artifacts, and the feature registry now agree that `nexus_orchestrate` does not replace during-work or end-of-session lifecycle steps.
|
|
640
|
+
- **Release-surface alignment**: Protocol, integrations, knowledge-base, README, and generated bootstrap surfaces now use the same mandatory lifecycle wording.
|
|
641
|
+
|
|
642
|
+
Full notes: [releases/v3.18.0.md](./releases/v3.18.0.md) · Full history: [CHANGELOG.md](./CHANGELOG.md)
|
|
643
|
+
</details>
|
|
644
|
+
|
|
645
|
+
<details>
|
|
629
646
|
<summary><b>v3.17.0</b> · 2026-03-20 · Agent adoption hardening, memory readability, atlas code intelligence peer</summary>
|
|
630
647
|
|
|
631
648
|
- **Hard bootstrap enforcement**: Non-bootstrap MCP tool calls return a structured `blocked` response with next-step guidance instead of a soft warning agents ignored. Read-only tools remain exempt.
|
|
@@ -24,6 +24,10 @@ export declare class MCPAdapter implements Adapter {
|
|
|
24
24
|
private getRuntime;
|
|
25
25
|
private getOrchestrator;
|
|
26
26
|
private getToolProfile;
|
|
27
|
+
private formatProtocolChecklist;
|
|
28
|
+
private formatRemainingProtocolSteps;
|
|
29
|
+
private prependTextToResponse;
|
|
30
|
+
private decorateLifecycleResponse;
|
|
27
31
|
private describeClientInstructionStatus;
|
|
28
32
|
private finalizeToolDefinitions;
|
|
29
33
|
private decorateToolDescription;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../../src/agents/adapters/mcp.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAiE5C,KAAK,cAAc,GAAG,YAAY,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../../src/agents/adapters/mcp.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAiE5C,KAAK,cAAc,GAAG,YAAY,GAAG,MAAM,CAAC;AAE5C,KAAK,iBAAiB,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC,CAAC;AA4SF,qBAAa,UAAW,YAAW,OAAO;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAG,KAAK,CAAU;IACtB,SAAS,UAAS;IAClB,MAAM,EAAE,MAAM,EAAE,CAAM;IAEtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,CAAa;IAC9B,OAAO,CAAC,SAAS,CAA4C;IAC7D,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,OAAO,CAAC,CAAkB;IAElC,OAAO,CAAC,cAAc;IA6BtB,OAAO,CAAC,GAAG;;IAmBX,OAAO,CAAC,gBAAgB;IA4BxB,WAAW,CAAC,KAAK,EAAE,UAAU;IAI7B,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,4BAA4B;IAWpC,OAAO,CAAC,qBAAqB;IAiB7B,OAAO,CAAC,yBAAyB;IA8BjC,OAAO,CAAC,+BAA+B;IAMvC,OAAO,CAAC,uBAAuB;IAqB/B,OAAO,CAAC,uBAAuB;IAkC/B,cAAc,CAAC,OAAO,GAAE,cAAsC,GAAG,iBAAiB,EAAE;IAIpF,OAAO,CAAC,oBAAoB;IA8yB5B,OAAO,CAAC,iBAAiB;YA4FX,cAAc;IA01D5B,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE;IAItC,OAAO,CAAC,IAAI;IAmBN,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAOxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB3B,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAClD,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;CACzC"}
|
|
@@ -130,11 +130,122 @@ class SessionTelemetry {
|
|
|
130
130
|
tokensOptimized = 0;
|
|
131
131
|
memoriesStored = 0;
|
|
132
132
|
memoriesRecalled = 0;
|
|
133
|
+
lifecyclePhase = 'pre-bootstrap';
|
|
134
|
+
optimizeTokensCalled = false;
|
|
135
|
+
mindkitCheckCalled = false;
|
|
136
|
+
storeMemoryCalledPostOrchestrate = false;
|
|
137
|
+
sessionDnaCalled = false;
|
|
138
|
+
fileReadIntentCount = 0;
|
|
139
|
+
callsSinceOrchestrate = 0;
|
|
140
|
+
fileIntentPaths = new Set();
|
|
133
141
|
bootstrapped = false;
|
|
134
|
-
recordCall() {
|
|
142
|
+
recordCall() {
|
|
143
|
+
this.callCount++;
|
|
144
|
+
if (this.isPostOrchestratePhase()) {
|
|
145
|
+
this.callsSinceOrchestrate++;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
135
148
|
recordTokens(saved) { this.tokensOptimized += saved; }
|
|
136
149
|
recordStore() { this.memoriesStored++; }
|
|
137
150
|
recordRecall(count) { this.memoriesRecalled += count; }
|
|
151
|
+
snapshot() {
|
|
152
|
+
return {
|
|
153
|
+
callCount: this.callCount,
|
|
154
|
+
tokensOptimized: this.tokensOptimized,
|
|
155
|
+
memoriesStored: this.memoriesStored,
|
|
156
|
+
memoriesRecalled: this.memoriesRecalled,
|
|
157
|
+
lifecyclePhase: this.lifecyclePhase,
|
|
158
|
+
optimizeTokensCalled: this.optimizeTokensCalled,
|
|
159
|
+
mindkitCheckCalled: this.mindkitCheckCalled,
|
|
160
|
+
storeMemoryCalledPostOrchestrate: this.storeMemoryCalledPostOrchestrate,
|
|
161
|
+
sessionDnaCalled: this.sessionDnaCalled,
|
|
162
|
+
fileReadIntentCount: this.fileReadIntentCount,
|
|
163
|
+
callsSinceOrchestrate: this.callsSinceOrchestrate,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
advancePhase(nextPhase) {
|
|
167
|
+
if (this.lifecyclePhase === nextPhase)
|
|
168
|
+
return;
|
|
169
|
+
this.lifecyclePhase = nextPhase;
|
|
170
|
+
if (nextPhase === 'bootstrapped' || nextPhase === 'orchestrated') {
|
|
171
|
+
this.resetFileIntentTracking();
|
|
172
|
+
this.optimizeTokensCalled = false;
|
|
173
|
+
}
|
|
174
|
+
if (nextPhase === 'orchestrated') {
|
|
175
|
+
this.mindkitCheckCalled = false;
|
|
176
|
+
this.storeMemoryCalledPostOrchestrate = false;
|
|
177
|
+
this.sessionDnaCalled = false;
|
|
178
|
+
this.callsSinceOrchestrate = 0;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
observeSuccessfulToolCall(toolName, args) {
|
|
182
|
+
if (toolName === 'nexus_session_bootstrap') {
|
|
183
|
+
this.bootstrapped = true;
|
|
184
|
+
this.advancePhase('bootstrapped');
|
|
185
|
+
this.noteFileIntent(args.files);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
if (toolName === 'nexus_orchestrate') {
|
|
189
|
+
this.advancePhase('orchestrated');
|
|
190
|
+
this.noteFileIntent(args.files);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (toolName === 'nexus_optimize_tokens') {
|
|
194
|
+
this.optimizeTokensCalled = true;
|
|
195
|
+
if (this.lifecyclePhase === 'orchestrated')
|
|
196
|
+
this.advancePhase('working');
|
|
197
|
+
this.noteFileIntent(args.files);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (toolName === 'nexus_mindkit_check') {
|
|
201
|
+
this.mindkitCheckCalled = true;
|
|
202
|
+
if (this.lifecyclePhase === 'orchestrated')
|
|
203
|
+
this.advancePhase('working');
|
|
204
|
+
this.noteFileIntent(args.filesToModify);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (toolName === 'nexus_ghost_pass') {
|
|
208
|
+
if (this.lifecyclePhase === 'orchestrated')
|
|
209
|
+
this.advancePhase('working');
|
|
210
|
+
this.noteFileIntent(args.files);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (toolName === 'nexus_store_memory') {
|
|
214
|
+
if (this.isPostOrchestratePhase()) {
|
|
215
|
+
this.storeMemoryCalledPostOrchestrate = true;
|
|
216
|
+
}
|
|
217
|
+
if (this.lifecyclePhase === 'orchestrated')
|
|
218
|
+
this.advancePhase('working');
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (toolName === 'nexus_session_dna' && String(args.action ?? 'load') === 'generate') {
|
|
222
|
+
this.sessionDnaCalled = true;
|
|
223
|
+
this.advancePhase('closing');
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (this.lifecyclePhase === 'orchestrated') {
|
|
227
|
+
this.advancePhase('working');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
needsOptimizeTokens(currentToolName) {
|
|
231
|
+
if (currentToolName === 'nexus_optimize_tokens')
|
|
232
|
+
return false;
|
|
233
|
+
if (this.lifecyclePhase === 'pre-bootstrap')
|
|
234
|
+
return false;
|
|
235
|
+
return this.fileReadIntentCount >= 3 && !this.optimizeTokensCalled;
|
|
236
|
+
}
|
|
237
|
+
needsStoreMemory(currentToolName) {
|
|
238
|
+
if (currentToolName === 'nexus_store_memory')
|
|
239
|
+
return false;
|
|
240
|
+
return this.isPostOrchestratePhase()
|
|
241
|
+
&& this.callsSinceOrchestrate >= 15
|
|
242
|
+
&& !this.storeMemoryCalledPostOrchestrate;
|
|
243
|
+
}
|
|
244
|
+
needsSessionDna(currentToolName) {
|
|
245
|
+
if (currentToolName === 'nexus_session_dna')
|
|
246
|
+
return false;
|
|
247
|
+
return this.isPostOrchestratePhase() && !this.sessionDnaCalled;
|
|
248
|
+
}
|
|
138
249
|
notifyStore(priority, tags, memStats) {
|
|
139
250
|
return `\nMemory telemetry: priority ${priority.toFixed(2)} · tags ${tags.join(', ') || 'none'} · cortex ${memStats.cortex} · zettel ${memStats.totalLinks}`;
|
|
140
251
|
}
|
|
@@ -175,14 +286,14 @@ class SessionTelemetry {
|
|
|
175
286
|
nudges.push('Guardrail FAILED. Do NOT proceed. Re-scope the task or call nexus_ghost_pass for a safer approach.');
|
|
176
287
|
break;
|
|
177
288
|
case 'high_call_count':
|
|
178
|
-
if (this.
|
|
179
|
-
nudges.push('
|
|
289
|
+
if (this.callsSinceOrchestrate >= 15 && !this.storeMemoryCalledPostOrchestrate) {
|
|
290
|
+
nudges.push('15+ post-orchestrate tool calls reached. Next: call nexus_store_memory with a session summary.');
|
|
180
291
|
}
|
|
181
292
|
break;
|
|
182
293
|
}
|
|
183
294
|
if (nudges.length === 0)
|
|
184
295
|
return '';
|
|
185
|
-
return `\n
|
|
296
|
+
return `\n\nMANDATORY NEXT STEPS:\n${nudges.map((n) => `- ${n}`).join('\n')}\nDo NOT proceed without completing these steps.`;
|
|
186
297
|
}
|
|
187
298
|
format(memStats) {
|
|
188
299
|
const uptime = Math.round((Date.now() - this.startTime) / 1000);
|
|
@@ -190,9 +301,30 @@ class SessionTelemetry {
|
|
|
190
301
|
const parts = [
|
|
191
302
|
`${this.callCount} calls`,
|
|
192
303
|
memStats ? `${memStats.totalLinks} Zettel links` : null,
|
|
304
|
+
`phase ${this.lifecyclePhase}`,
|
|
193
305
|
].filter(Boolean);
|
|
194
306
|
return `\nSession telemetry (${uptimeStr}): ${parts.join(' · ')}`;
|
|
195
307
|
}
|
|
308
|
+
noteFileIntent(rawPaths) {
|
|
309
|
+
if (!Array.isArray(rawPaths))
|
|
310
|
+
return;
|
|
311
|
+
for (const rawPath of rawPaths) {
|
|
312
|
+
const normalized = String(rawPath || '').trim();
|
|
313
|
+
if (!normalized)
|
|
314
|
+
continue;
|
|
315
|
+
this.fileIntentPaths.add(normalized);
|
|
316
|
+
}
|
|
317
|
+
this.fileReadIntentCount = this.fileIntentPaths.size;
|
|
318
|
+
}
|
|
319
|
+
resetFileIntentTracking() {
|
|
320
|
+
this.fileIntentPaths.clear();
|
|
321
|
+
this.fileReadIntentCount = 0;
|
|
322
|
+
}
|
|
323
|
+
isPostOrchestratePhase() {
|
|
324
|
+
return this.lifecyclePhase === 'orchestrated'
|
|
325
|
+
|| this.lifecyclePhase === 'working'
|
|
326
|
+
|| this.lifecyclePhase === 'closing';
|
|
327
|
+
}
|
|
196
328
|
}
|
|
197
329
|
function formatBullets(lines) {
|
|
198
330
|
return lines.filter(Boolean).map((line) => `- ${line}`).join('\n');
|
|
@@ -223,11 +355,9 @@ export class MCPAdapter {
|
|
|
223
355
|
for (let i = 0; i < keys.length; i += 2) {
|
|
224
356
|
const k1 = keys[i];
|
|
225
357
|
const v1 = String(metrics[k1]).substring(0, 20);
|
|
226
|
-
const p1 = `\x1b[33m${k1}:\x1b[0m ${v1}`.padEnd(42, ' ');
|
|
227
358
|
if (i + 1 < keys.length) {
|
|
228
359
|
const k2 = keys[i + 1];
|
|
229
360
|
const v2 = String(metrics[k2]).substring(0, 20);
|
|
230
|
-
const p2 = `\x1b[33m${k2}:\x1b[0m ${v2}`.padEnd(42, ' ');
|
|
231
361
|
// We have to hardcode padding because ansi escape codes mess with .padEnd length
|
|
232
362
|
console.error(`\x1b[36m║ \x1b[33m${k1}:\x1b[37m ${v1.padEnd(20, ' ')} │ \x1b[33m${k2}:\x1b[37m ${v2.padEnd(19, ' ')} \x1b[36m║\x1b[0m`);
|
|
233
363
|
}
|
|
@@ -312,9 +442,60 @@ export class MCPAdapter {
|
|
|
312
442
|
? 'full'
|
|
313
443
|
: 'autonomous';
|
|
314
444
|
}
|
|
445
|
+
formatProtocolChecklist() {
|
|
446
|
+
return [
|
|
447
|
+
'PROTOCOL CHECKLIST (follow every step):',
|
|
448
|
+
'[x] nexus_session_bootstrap — DONE',
|
|
449
|
+
'[ ] nexus_orchestrate — Call NOW with the user\'s request',
|
|
450
|
+
'[ ] nexus_optimize_tokens — Call BEFORE reading 3+ files',
|
|
451
|
+
'[ ] nexus_mindkit_check — Call BEFORE any file modifications',
|
|
452
|
+
'[ ] nexus_store_memory — Call AFTER significant findings AND at session end',
|
|
453
|
+
'[ ] nexus_session_dna — Call BEFORE ending this session',
|
|
454
|
+
].join('\n');
|
|
455
|
+
}
|
|
456
|
+
formatRemainingProtocolSteps() {
|
|
457
|
+
return [
|
|
458
|
+
'REMAINING PROTOCOL STEPS (MANDATORY):',
|
|
459
|
+
'- Call nexus_optimize_tokens(goal, files) BEFORE reading 3+ files',
|
|
460
|
+
'- Call nexus_mindkit_check(action, filesToModify) BEFORE modifying any files',
|
|
461
|
+
'- Call nexus_store_memory(content, priority, tags) with key findings from this work',
|
|
462
|
+
'- Call nexus_session_dna(action="generate") BEFORE ending this session',
|
|
463
|
+
'Do NOT skip these steps. The orchestrate call handled planning and execution, but these lifecycle steps are your responsibility.',
|
|
464
|
+
].join('\n');
|
|
465
|
+
}
|
|
466
|
+
prependTextToResponse(result, text) {
|
|
467
|
+
if (!text.trim())
|
|
468
|
+
return result;
|
|
469
|
+
const content = result.content.map((item, index) => {
|
|
470
|
+
if (index === 0 && item.type === 'text') {
|
|
471
|
+
return {
|
|
472
|
+
...item,
|
|
473
|
+
text: `${text}\n\n${item.text}`,
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
return item;
|
|
477
|
+
});
|
|
478
|
+
return { ...result, content };
|
|
479
|
+
}
|
|
480
|
+
decorateLifecycleResponse(toolName, result) {
|
|
481
|
+
const telemetry = this.telemetry.snapshot();
|
|
482
|
+
const warnings = [];
|
|
483
|
+
if (this.telemetry.needsOptimizeTokens(toolName)) {
|
|
484
|
+
warnings.push(`Nexus only sees best-effort file intent from tool arguments. Current intent references ${telemetry.fileReadIntentCount} file(s), and nexus_optimize_tokens has not been called in this phase. Call nexus_optimize_tokens(goal, files) before broad reading.`);
|
|
485
|
+
}
|
|
486
|
+
if (this.telemetry.needsStoreMemory(toolName)) {
|
|
487
|
+
warnings.push(`${telemetry.callsSinceOrchestrate} post-orchestrate tool calls have happened without nexus_store_memory. Store the key findings before continuing.`);
|
|
488
|
+
}
|
|
489
|
+
if (warnings.length === 0)
|
|
490
|
+
return result;
|
|
491
|
+
return this.prependTextToResponse(result, [
|
|
492
|
+
'LIFECYCLE WARNING:',
|
|
493
|
+
...warnings.map((warning) => `- ${warning}`),
|
|
494
|
+
].join('\n'));
|
|
495
|
+
}
|
|
315
496
|
describeClientInstructionStatus(profile) {
|
|
316
497
|
return profile === 'autonomous'
|
|
317
|
-
? 'Autonomous MCP profile active.
|
|
498
|
+
? 'Autonomous MCP profile active. REQUIRED start: nexus_session_bootstrap, then nexus_orchestrate. During-work and session-close lifecycle tools remain mandatory.'
|
|
318
499
|
: 'Full MCP profile active. Low-level and authoring tools are exposed.';
|
|
319
500
|
}
|
|
320
501
|
finalizeToolDefinitions(tools, profile = this.getToolProfile()) {
|
|
@@ -347,7 +528,19 @@ export class MCPAdapter {
|
|
|
347
528
|
return 'Optional: Inspect the execution ledger before calling nexus_orchestrate. Skip unless you need pre-run visibility into what Nexus will choose.';
|
|
348
529
|
}
|
|
349
530
|
if (name === 'nexus_optimize_tokens') {
|
|
350
|
-
return '
|
|
531
|
+
return 'MANDATORY before reading 3+ files. Returns a token-saving reading plan. Follow it exactly and do not bulk-read the repo.';
|
|
532
|
+
}
|
|
533
|
+
if (name === 'nexus_mindkit_check') {
|
|
534
|
+
return 'MANDATORY before any file modification or destructive operation. Returns PASS/FAIL. Do NOT proceed if it returns FAIL.';
|
|
535
|
+
}
|
|
536
|
+
if (name === 'nexus_store_memory') {
|
|
537
|
+
return 'MANDATORY after significant findings and at session end. Store root causes, architecture decisions, and reusable patterns.';
|
|
538
|
+
}
|
|
539
|
+
if (name === 'nexus_session_dna') {
|
|
540
|
+
return 'MANDATORY at session end. Generates the handover snapshot for this session. Never skip this step.';
|
|
541
|
+
}
|
|
542
|
+
if (name === 'nexus_ghost_pass') {
|
|
543
|
+
return 'MANDATORY before refactoring 3+ files. Provides a safe execution plan, risk map, and worker guidance.';
|
|
351
544
|
}
|
|
352
545
|
if (name === 'nexus_spawn_workers') {
|
|
353
546
|
return 'Call when modifying 3+ interrelated files or when nexus_ghost_pass recommends parallel execution. Prefer nexus_orchestrate for automatic worker management.';
|
|
@@ -365,7 +558,7 @@ export class MCPAdapter {
|
|
|
365
558
|
// ── Memory ────────────────────────────────────────────────────────
|
|
366
559
|
{
|
|
367
560
|
name: 'nexus_store_memory',
|
|
368
|
-
description: 'Store a finding, insight, or memory into Nexus Prime.
|
|
561
|
+
description: 'Store a finding, insight, or memory into Nexus Prime. MANDATORY after significant findings and at session end. Priority 0-1 (1.0 = critical). High-priority items auto-fission to long-term memory.',
|
|
369
562
|
inputSchema: {
|
|
370
563
|
type: 'object',
|
|
371
564
|
properties: {
|
|
@@ -616,7 +809,7 @@ export class MCPAdapter {
|
|
|
616
809
|
},
|
|
617
810
|
{
|
|
618
811
|
name: 'nexus_session_dna',
|
|
619
|
-
description: 'Generate or load a Session DNA snapshot. Captures files accessed/modified, decisions made, skills used, and recommended next steps for perfect session handover.
|
|
812
|
+
description: 'Generate or load a Session DNA snapshot. MANDATORY at session end when using "generate". Captures files accessed/modified, decisions made, skills used, and recommended next steps for perfect session handover.',
|
|
620
813
|
inputSchema: {
|
|
621
814
|
type: 'object',
|
|
622
815
|
properties: {
|
|
@@ -1196,13 +1389,14 @@ export class MCPAdapter {
|
|
|
1196
1389
|
if (toolName === 'nexus_session_bootstrap') {
|
|
1197
1390
|
this.telemetry.bootstrapped = true;
|
|
1198
1391
|
}
|
|
1392
|
+
const args = request.params?.arguments ?? {};
|
|
1199
1393
|
const callId = `mcp_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
1200
1394
|
const startTimeMs = Date.now();
|
|
1201
1395
|
nexusEventBus.emit('mcp.call.start', {
|
|
1202
1396
|
callId,
|
|
1203
1397
|
serverName: 'nexus-prime',
|
|
1204
1398
|
toolName,
|
|
1205
|
-
args
|
|
1399
|
+
args,
|
|
1206
1400
|
});
|
|
1207
1401
|
let result;
|
|
1208
1402
|
try {
|
|
@@ -1228,6 +1422,7 @@ export class MCPAdapter {
|
|
|
1228
1422
|
});
|
|
1229
1423
|
throw error;
|
|
1230
1424
|
}
|
|
1425
|
+
this.telemetry.observeSuccessfulToolCall(toolName, args);
|
|
1231
1426
|
if (!this.telemetry.bootstrapped &&
|
|
1232
1427
|
toolName !== 'nexus_session_bootstrap' &&
|
|
1233
1428
|
toolName !== 'nexus_memory_stats' &&
|
|
@@ -1246,7 +1441,7 @@ export class MCPAdapter {
|
|
|
1246
1441
|
}]
|
|
1247
1442
|
};
|
|
1248
1443
|
}
|
|
1249
|
-
return result;
|
|
1444
|
+
return this.decorateLifecycleResponse(toolName, result);
|
|
1250
1445
|
});
|
|
1251
1446
|
}
|
|
1252
1447
|
async handleToolCall(request) {
|
|
@@ -1329,6 +1524,7 @@ export class MCPAdapter {
|
|
|
1329
1524
|
`Bootstrap status: ${bootstrap.clientBootstrapStatus?.clients?.length || 0} client manifests tracked`,
|
|
1330
1525
|
]),
|
|
1331
1526
|
formatJsonDetails('Structured details', payload),
|
|
1527
|
+
this.formatProtocolChecklist(),
|
|
1332
1528
|
].join('\n\n'),
|
|
1333
1529
|
}],
|
|
1334
1530
|
};
|
|
@@ -1432,6 +1628,7 @@ export class MCPAdapter {
|
|
|
1432
1628
|
]),
|
|
1433
1629
|
execution.result ? `Result\n\`\`\`\n${execution.result}\n\`\`\`` : '',
|
|
1434
1630
|
formatJsonDetails('Structured details', payload),
|
|
1631
|
+
this.formatRemainingProtocolSteps(),
|
|
1435
1632
|
].filter(Boolean).join('\n\n'),
|
|
1436
1633
|
}],
|
|
1437
1634
|
};
|
|
@@ -1461,6 +1658,7 @@ export class MCPAdapter {
|
|
|
1461
1658
|
runtimeUsage?.skipReasons?.length ? `Skipped stages: ${runtimeUsage.skipReasons.join(' · ')}` : 'Skipped stages: not recorded',
|
|
1462
1659
|
]),
|
|
1463
1660
|
formatJsonDetails('Structured details', payload),
|
|
1661
|
+
this.formatRemainingProtocolSteps(),
|
|
1464
1662
|
].join('\n\n'),
|
|
1465
1663
|
}],
|
|
1466
1664
|
};
|
|
@@ -1486,8 +1684,6 @@ export class MCPAdapter {
|
|
|
1486
1684
|
const id = this.nexusRef.storeMemory(content, priority, tags);
|
|
1487
1685
|
this.telemetry.recordStore();
|
|
1488
1686
|
this.sessionDNA.recordMemoryStore();
|
|
1489
|
-
const memStats = this.nexusRef.getMemoryStats();
|
|
1490
|
-
const notification = this.telemetry.notifyStore(priority, tags, memStats);
|
|
1491
1687
|
const nudge = this.telemetry.planningNudge('store', { priority });
|
|
1492
1688
|
// Auto-Gist Publish Phase 8
|
|
1493
1689
|
let autoGistNote = '';
|
|
@@ -1526,8 +1722,6 @@ export class MCPAdapter {
|
|
|
1526
1722
|
nexusEventBus.emit('memory.recall', { query, count: memories.length });
|
|
1527
1723
|
this.telemetry.recordRecall(memories.length);
|
|
1528
1724
|
this.sessionDNA.recordMemoryRecall();
|
|
1529
|
-
const memStats = this.nexusRef.getMemoryStats();
|
|
1530
|
-
const notification = this.telemetry.notifyRecall(memories.length, query, memStats);
|
|
1531
1725
|
const nudge = this.telemetry.planningNudge('recall', { count: memories.length });
|
|
1532
1726
|
// Console ASCII UI
|
|
1533
1727
|
this.box('🔍 CORTEX MEMORY RECALL', [
|
|
@@ -2078,12 +2272,14 @@ export class MCPAdapter {
|
|
|
2078
2272
|
? String(request.params.arguments.sessionId)
|
|
2079
2273
|
: undefined;
|
|
2080
2274
|
if (action === 'generate') {
|
|
2275
|
+
this.telemetry.observeSuccessfulToolCall('nexus_session_dna', { action });
|
|
2081
2276
|
// Sync counters from telemetry before generating
|
|
2277
|
+
const telemetry = this.telemetry.snapshot();
|
|
2082
2278
|
this.sessionDNA.syncFromTelemetry({
|
|
2083
|
-
callCount:
|
|
2084
|
-
memoriesStored:
|
|
2085
|
-
memoriesRecalled:
|
|
2086
|
-
tokensOptimized:
|
|
2279
|
+
callCount: telemetry.callCount,
|
|
2280
|
+
memoriesStored: telemetry.memoriesStored,
|
|
2281
|
+
memoriesRecalled: telemetry.memoriesRecalled,
|
|
2282
|
+
tokensOptimized: telemetry.tokensOptimized,
|
|
2087
2283
|
});
|
|
2088
2284
|
const dna = this.sessionDNA.flush();
|
|
2089
2285
|
const formatted = SessionDNAManager.format(dna);
|
|
@@ -2995,11 +3191,12 @@ export class MCPAdapter {
|
|
|
2995
3191
|
async disconnect() {
|
|
2996
3192
|
// Auto-flush Session DNA on disconnect
|
|
2997
3193
|
try {
|
|
3194
|
+
const telemetry = this.telemetry.snapshot();
|
|
2998
3195
|
this.sessionDNA.syncFromTelemetry({
|
|
2999
|
-
callCount:
|
|
3000
|
-
memoriesStored:
|
|
3001
|
-
memoriesRecalled:
|
|
3002
|
-
tokensOptimized:
|
|
3196
|
+
callCount: telemetry.callCount,
|
|
3197
|
+
memoriesStored: telemetry.memoriesStored,
|
|
3198
|
+
memoriesRecalled: telemetry.memoriesRecalled,
|
|
3199
|
+
tokensOptimized: telemetry.tokensOptimized,
|
|
3003
3200
|
});
|
|
3004
3201
|
this.sessionDNA.flush();
|
|
3005
3202
|
console.error('[MCP Adapter] Session DNA flushed');
|