nexus-prime 7.9.14 → 7.9.16

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.
Files changed (43) hide show
  1. package/README.md +22 -21
  2. package/dist/agents/adapters/mcp/handlers/runtime.js +12 -0
  3. package/dist/agents/adapters/mcp.d.ts +2 -0
  4. package/dist/agents/adapters/mcp.js +58 -6
  5. package/dist/cli/install-wizard.js +19 -0
  6. package/dist/cli.js +37 -6
  7. package/dist/dashboard/app/index.html +8 -0
  8. package/dist/dashboard/app/main.js +7 -0
  9. package/dist/dashboard/app/state.js +5 -0
  10. package/dist/dashboard/app/styles/board.css +163 -2
  11. package/dist/dashboard/app/styles/context-log.css +167 -0
  12. package/dist/dashboard/app/styles/memory.css +63 -0
  13. package/dist/dashboard/app/styles/workforce.css +21 -0
  14. package/dist/dashboard/app/views/board.js +145 -7
  15. package/dist/dashboard/app/views/context-log.js +158 -0
  16. package/dist/dashboard/app/views/license.js +36 -0
  17. package/dist/dashboard/app/views/memory.js +87 -3
  18. package/dist/dashboard/app/views/workforce.js +22 -6
  19. package/dist/dashboard/routes/events.js +80 -3
  20. package/dist/dashboard/stream/sse-broker.js +25 -13
  21. package/dist/engines/client-bootstrap.js +66 -20
  22. package/dist/engines/code-review-graph-client.d.ts +11 -3
  23. package/dist/engines/code-review-graph-client.js +151 -24
  24. package/dist/engines/instruction-gateway.js +6 -0
  25. package/dist/engines/mcp-entrypoint.js +3 -1
  26. package/dist/engines/orchestrator/decision-spine.d.ts +170 -0
  27. package/dist/engines/orchestrator/decision-spine.js +424 -0
  28. package/dist/engines/orchestrator/selection-policy.d.ts +39 -0
  29. package/dist/engines/orchestrator/selection-policy.js +32 -0
  30. package/dist/engines/orchestrator.js +19 -33
  31. package/dist/licensing/enforcement.js +25 -5
  32. package/dist/licensing/index.d.ts +1 -1
  33. package/dist/licensing/license-manager.js +110 -4
  34. package/dist/licensing/license-sync.js +4 -3
  35. package/dist/licensing/types.d.ts +19 -3
  36. package/dist/licensing/upgrade-prompts.d.ts +2 -2
  37. package/dist/licensing/upgrade-prompts.js +30 -9
  38. package/dist/licensing/web-auth.d.ts +2 -2
  39. package/dist/licensing/web-auth.js +6 -6
  40. package/dist/phantom/runtime.d.ts +16 -0
  41. package/dist/phantom/runtime.js +158 -20
  42. package/dist/postinstall-bootstrap.js +6 -4
  43. package/package.json +2 -2
package/README.md CHANGED
@@ -16,8 +16,8 @@
16
16
  <p>
17
17
  <img src="https://img.shields.io/badge/Protocol-MCP-4285F4?style=for-the-badge" alt="MCP Protocol">
18
18
  <img src="https://img.shields.io/badge/license-Commercial-6f42c1?style=for-the-badge" alt="Commercial License">
19
- <a href="https://nexus-prime.cfd/pricing"><img src="https://img.shields.io/badge/30--day-free%20trial-00ff88?style=for-the-badge" alt="30-day free trial"></a>
20
- <img src="https://img.shields.io/badge/independent%20creators-free%20forever-ff69b4?style=for-the-badge" alt="Free for IC creators">
19
+ <a href="https://nexus-prime.cfd/pricing"><img src="https://img.shields.io/badge/3--day-grace%20then%20license-00ff88?style=for-the-badge" alt="3-day grace then license"></a>
20
+ <img src="https://img.shields.io/badge/licenses-reviewed%20within%2024h-ff69b4?style=for-the-badge" alt="Licenses reviewed within 24 hours">
21
21
  <img src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-444?style=for-the-badge" alt="Cross-platform">
22
22
  </p>
23
23
 
@@ -305,7 +305,7 @@ If any of that sounds like you — keep reading.
305
305
 
306
306
  <div align="center">
307
307
 
308
- **Free for 30 days. No credit card. No feature gating.**
308
+ **3-day no-license grace. Request a license before day 4. Manual approvals within 24 hours.**
309
309
 
310
310
  </div>
311
311
 
@@ -317,16 +317,16 @@ If any of that sounds like you — keep reading.
317
317
  <th>Caps</th>
318
318
  </tr>
319
319
  <tr>
320
- <td><b>🎁 Free Trial</b></td>
321
- <td>Everyone — try it risk-free</td>
322
- <td>Free for 30 days</td>
323
- <td>All Pro features</td>
320
+ <td><b>🎁 Local Grace</b></td>
321
+ <td>Everyone — install and verify locally</td>
322
+ <td>3 days without a license</td>
323
+ <td>Runtime available during grace; license required after day 3</td>
324
324
  </tr>
325
325
  <tr>
326
326
  <td><b>💎 Independent Creators</b></td>
327
327
  <td>Indie builders, solo engineers, students, OSS maintainers</td>
328
- <td><b>Free forever</b></td>
329
- <td>Unlimited usage on personal projects</td>
328
+ <td>Request access</td>
329
+ <td>Manual creator licenses reviewed by the team</td>
330
330
  </tr>
331
331
  <tr>
332
332
  <td><b>🚀 Pilot Program</b></td>
@@ -356,10 +356,10 @@ If any of that sounds like you — keep reading.
356
356
 
357
357
  ```bash
358
358
  nexus-prime license status # check your plan
359
- nexus-prime license activate <key> # activate any paid tier
359
+ nexus-prime license activate <key> # activate the key shared by the team
360
360
  ```
361
361
 
362
- → **[nexus-prime.cfd/pricing](https://nexus-prime.cfd/pricing)** · **[Apply to the pilot program](mailto:hello@nexus-prime.cfd?subject=Pilot%20Program)**
362
+ → **[nexus-prime.cfd/account](https://nexus-prime.cfd/account)** · **[Request by email](mailto:adarsh@nexus-prime.cfd?subject=Nexus%20Prime%20license%20request)**
363
363
 
364
364
  ---
365
365
 
@@ -380,19 +380,19 @@ No — it supercharges them. Keep the agents you already love. Nexus Prime adds
380
380
  <details>
381
381
  <summary><b>What happens after the 30-day trial ends?</b></summary>
382
382
  <br>
383
- You're never locked out. You can keep using a free tier, pick a paid plan, or if you're an independent creator apply for free-forever access. Your memory, data, and projects stay yours either way.
383
+ The local trial window ends and paid-tier work requires an active license. Your local memory and data stay on your machine; activate a license or request renewal from the account page to continue.
384
384
  </details>
385
385
 
386
386
  <details>
387
387
  <summary><b>Is it free for indie developers and creators?</b></summary>
388
388
  <br>
389
- Yes. If you build independently — solo founder, indie dev, content creator, student, OSS maintainer — you qualify for unlimited free usage. Just <a href="mailto:hello@nexus-prime.cfd?subject=Creator%20Program">email us</a> and we'll sort it.
389
+ Creator access is reviewed manually. If you build independently — solo founder, indie dev, content creator, student, OSS maintainer — request a creator license from the account page or email <a href="mailto:adarsh@nexus-prime.cfd?subject=Creator%20Program">adarsh@nexus-prime.cfd</a>.
390
390
  </details>
391
391
 
392
392
  <details>
393
393
  <summary><b>My team wants to try this across the whole engineering org. What's the pilot?</b></summary>
394
394
  <br>
395
- We're taking <b>10 companies</b> into our pilot program — full Team features free, white-glove onboarding, direct access to the team building it. First come, first served. <a href="mailto:hello@nexus-prime.cfd?subject=Pilot%20Program">Reach out</a>.
395
+ We're taking <b>10 companies</b> into our pilot program — white-glove onboarding, direct access to the team building it, and team licenses issued after review. <a href="mailto:adarsh@nexus-prime.cfd?subject=Pilot%20Program">Reach out</a>.
396
396
  </details>
397
397
 
398
398
  <details>
@@ -416,7 +416,7 @@ Each engineer runs their own local instance — nothing is shared across machine
416
416
  <details>
417
417
  <summary><b>What if I hit my plan's cap?</b></summary>
418
418
  <br>
419
- Nothing stops working. You get a gentle in-app nudge and a link to upgrade. Your data is never held hostage.
419
+ The app shows an upgrade request path and keeps your local data intact. Features above your licensed tier require an approved upgrade.
420
420
  </details>
421
421
 
422
422
  <details>
@@ -433,7 +433,7 @@ Nexus Prime was designed privacy-first, because the code on your machine is your
433
433
 
434
434
  - 🏠 **100% local.** All data lives on your disk, in your home directory.
435
435
  - 🚫 **No cloud sync.** Your code, your memory, your logs — never uploaded.
436
- - 🔐 **No required account.** You can run the free trial without signing up for anything.
436
+ - 🔐 **Short no-account grace.** You can run locally for 3 days without signing up; a license is required after that grace period.
437
437
  - 📊 **Telemetry is opt-in.** Off by default. When on, only aggregate, anonymous event counts are sent — never source code, never memory contents.
438
438
  - 🗑️ **Uninstall is clean.** Everything lives in one directory you can delete.
439
439
 
@@ -448,7 +448,8 @@ Nexus Prime was designed privacy-first, because the code on your machine is your
448
448
  | 💬 [**Discord**](https://discord.gg/tByGZgk5gS) | Real-time help, show-and-tell, feature ideas |
449
449
  | 🔴 [**Reddit — r/Nexus_Prime**](https://www.reddit.com/r/Nexus_Prime/) | Long-form posts, releases, community wins |
450
450
  | 🐦 [**X / Twitter**](https://x.com/nexusprime_ai) | Launch announcements, tips, updates |
451
- | 📧 [**hello@nexus-prime.cfd**](mailto:hello@nexus-prime.cfd) | Pilot program, creator program, enterprise, press |
451
+ | 📧 [**adarsh@nexus-prime.cfd**](mailto:adarsh@nexus-prime.cfd) | License requests, upgrades, pilots, enterprise |
452
+ | 📧 [**hello@nexus-prime.cfd**](mailto:hello@nexus-prime.cfd) | General support, press, community |
452
453
  | 🌐 [**nexus-prime.cfd**](https://nexus-prime.cfd) | Product site, demos, pricing, setup guides |
453
454
 
454
455
  </div>
@@ -457,11 +458,11 @@ Nexus Prime was designed privacy-first, because the code on your machine is your
457
458
 
458
459
  ## License
459
460
 
460
- Nexus Prime is a **commercial product** with generous free tiers:
461
+ Nexus Prime is a **commercial product** with manual license issuance:
461
462
 
462
- - ✅ Free for 30 days, for everyone
463
- - ✅ Free forever for independent creators
464
- - ✅ Free pilot for the first 10 partner companies
463
+ - ✅ 3-day local no-license grace, for everyone
464
+ - ✅ Manual creator, pilot, team, and enterprise license review
465
+ - ✅ License and upgrade requests reviewed within 24 hours
465
466
  - 💳 Paid plans for professional, team, and enterprise usage
466
467
 
467
468
  Commercial use without a valid license is prohibited. See [nexus-prime.cfd/pricing](https://nexus-prime.cfd/pricing) for current plans and terms.
@@ -38,11 +38,21 @@ export async function handleRuntimeGroup(toolName, hctx, request, args, ctx) {
38
38
  }
39
39
  // summary (default)
40
40
  const licStatus = getSharedLicenseManager().getStatus();
41
+ const trialLines = licStatus.trialPhase ? [
42
+ `- **Trial phase**: ${licStatus.trialPhase}`,
43
+ typeof licStatus.trialDaysRemaining === 'number'
44
+ ? `- **Trial remaining**: ${licStatus.trialDaysRemaining} day${licStatus.trialDaysRemaining === 1 ? '' : 's'}`
45
+ : '',
46
+ licStatus.activationRequired
47
+ ? `- **Agent motion**: Stop paid-tier work and ask the user to request or activate a Nexus Prime license now.`
48
+ : `- **Agent motion**: 3-day no-license grace is active; ask the user to request a license before day 4.`,
49
+ ].filter((line) => Boolean(line)) : [];
41
50
  const lines = [
42
51
  `## License Status`,
43
52
  `- **Plan**: ${pcu.tier.toUpperCase()}`,
44
53
  `- **Status**: ${licStatus.valid ? 'Active' : licStatus.degradedReason ?? 'Inactive'}`,
45
54
  licStatus.expiresAt ? `- **Expires**: ${new Date(licStatus.expiresAt).toISOString().split('T')[0]}` : '- **Expires**: Never',
55
+ ...trialLines,
46
56
  '',
47
57
  `## Resource Usage`,
48
58
  `- Memory: ${pcu.memory.current.toLocaleString()} / ${Number.isFinite(pcu.memory.limit) ? pcu.memory.limit.toLocaleString() : '∞'} (${pcu.memory.pct}%)`,
@@ -54,6 +64,8 @@ export async function handleRuntimeGroup(toolName, hctx, request, args, ctx) {
54
64
  `## Upgrade`,
55
65
  `- Dashboard: http://127.0.0.1:3377 → License tab`,
56
66
  `- Web: https://nexus-prime.cfd/account`,
67
+ `- Email: adarsh@nexus-prime.cfd`,
68
+ `- SLA: team will share licenses within 24 hours`,
57
69
  `- CLI: nexus-prime license sync`,
58
70
  ];
59
71
  return { content: [{ type: 'text', text: lines.join('\n') }] };
@@ -20,6 +20,7 @@ export declare class MCPAdapter implements Adapter {
20
20
  private currentTask;
21
21
  private middlewarePipeline;
22
22
  private scanCache;
23
+ private sessionLifecycleFinalized;
23
24
  private sciFiMatrixLog;
24
25
  private classifyToolCategory;
25
26
  private sciFiToolHeader;
@@ -83,6 +84,7 @@ export declare class MCPAdapter implements Adapter {
83
84
  private extractFileRefsFromArgs;
84
85
  scanSourceFiles(cwd: string): Promise<string[]>;
85
86
  connect(): Promise<void>;
87
+ private finalizeSessionLifecycle;
86
88
  disconnect(): Promise<void>;
87
89
  send(message: NetworkMessage): Promise<void>;
88
90
  receive(message: NetworkMessage): void;
@@ -160,6 +160,7 @@ export class MCPAdapter {
160
160
  currentTask = '';
161
161
  middlewarePipeline;
162
162
  scanCache = new Map();
163
+ sessionLifecycleFinalized = false;
163
164
  sciFiMatrixLog(title, metrics, intent) {
164
165
  const width = 76;
165
166
  console.error(`\n\x1b[36m╔═══ [ \x1b[37m\x1b[1mNEXUS PRIME · ORCHESTRATION MATRIX\x1b[0m\x1b[36m ] ${'═'.repeat(Math.max(0, width - 48))}╗\x1b[0m`);
@@ -876,6 +877,9 @@ export class MCPAdapter {
876
877
  }
877
878
  else {
878
879
  this.telemetry.observeSuccessfulToolCall(toolName, args);
880
+ if (toolName === 'nexus_session_dna' && String(args.action ?? 'load') === 'generate') {
881
+ this.sessionLifecycleFinalized = true;
882
+ }
879
883
  }
880
884
  }
881
885
  // Surface meaningful tool calls on the SSE feed; persist only high-signal outcomes.
@@ -1159,22 +1163,70 @@ export class MCPAdapter {
1159
1163
  startWatchdog();
1160
1164
  console.error('[MCP Adapter] Connected — runtime tools active');
1161
1165
  }
1162
- async disconnect() {
1163
- // Auto-flush Session DNA on disconnect
1166
+ async finalizeSessionLifecycle(reason) {
1167
+ if (this.sessionLifecycleFinalized && reason !== 'explicit')
1168
+ return;
1169
+ const telemetry = this.telemetry.snapshot();
1170
+ try {
1171
+ const promoted = this.nexusRef?.runTierPromotion?.();
1172
+ if (promoted)
1173
+ nexusEventBus.emit('memory.tier.promoted', promoted);
1174
+ }
1175
+ catch (e) {
1176
+ nexusEventBus.emit('mcp.handler.failed', {
1177
+ toolName: 'nexus_session_dna.disconnect.tierPromotion',
1178
+ code: 'internal',
1179
+ attempts: 1,
1180
+ durationMs: 0,
1181
+ });
1182
+ console.error('[MCP Adapter] Failed to run Session DNA tier promotion:', e);
1183
+ }
1164
1184
  try {
1165
- const telemetry = this.telemetry.snapshot();
1166
1185
  this.sessionDNA.syncFromTelemetry({
1167
1186
  callCount: telemetry.callCount,
1168
1187
  memoriesStored: telemetry.memoriesStored,
1169
1188
  memoriesRecalled: telemetry.memoriesRecalled,
1170
1189
  tokensOptimized: telemetry.tokensOptimized,
1171
1190
  });
1172
- this.sessionDNA.flush();
1173
- console.error('[MCP Adapter] Session DNA flushed');
1191
+ const dna = this.sessionDNA.flush();
1192
+ this.sessionLifecycleFinalized = true;
1193
+ try {
1194
+ const runtimeTokens = this.runtime?.getUsageSnapshot().tokens?.grossInputTokens ?? 0;
1195
+ this.getOrchestrator({}).persistSessionSummary(telemetry.tokensOptimized || runtimeTokens || 0);
1196
+ }
1197
+ catch (e) {
1198
+ nexusEventBus.emit('mcp.handler.failed', {
1199
+ toolName: 'nexus_session_dna.disconnect.persistSessionSummary',
1200
+ code: 'internal',
1201
+ attempts: 1,
1202
+ durationMs: 0,
1203
+ });
1204
+ console.error('[MCP Adapter] Failed to persist Session DNA summary:', e);
1205
+ }
1206
+ await getSharedTelemetry().trackSessionEnd(this.telemetry.elapsedMs(), {
1207
+ projectId: this.nexusRef?.getWorkspaceContext?.()?.repoRoot ?? '',
1208
+ tokensSaved: telemetry.tokensOptimized,
1209
+ memoriesCreated: telemetry.memoriesStored,
1210
+ memoriesRecalled: telemetry.memoriesRecalled,
1211
+ toolsUsed: telemetry.callCount,
1212
+ sessionId: dna.sessionId,
1213
+ }).catch((e) => {
1214
+ nexusEventBus.emit('mcp.handler.failed', {
1215
+ toolName: 'nexus_session_dna.disconnect.trackSessionEnd',
1216
+ code: 'internal',
1217
+ attempts: 1,
1218
+ durationMs: 0,
1219
+ });
1220
+ console.error('[MCP Adapter] Failed to track Session DNA session end:', e);
1221
+ });
1222
+ console.error(`[MCP Adapter] Session DNA finalized on ${reason}`);
1174
1223
  }
1175
1224
  catch (e) {
1176
- console.error('[MCP Adapter] Failed to flush Session DNA:', e);
1225
+ console.error('[MCP Adapter] Failed to finalize Session DNA:', e);
1177
1226
  }
1227
+ }
1228
+ async disconnect() {
1229
+ await this.finalizeSessionLifecycle('disconnect');
1178
1230
  await this.server.close();
1179
1231
  this.connected = false;
1180
1232
  console.error('[MCP Adapter] Disconnected');
@@ -159,6 +159,21 @@ function _writeClaudeCodeHooks(workspaceRoot) {
159
159
  });
160
160
  });
161
161
  }
162
+ function _isManagedGraphPeer(server) {
163
+ if (!server || typeof server !== 'object' || Array.isArray(server))
164
+ return false;
165
+ const record = server;
166
+ const args = Array.isArray(record.args) ? record.args.map(String) : [];
167
+ return record.command === 'goatlas' && args.length === 1 && args[0] === 'mcp';
168
+ }
169
+ function _stripInternalGraphPeers(mcpServers) {
170
+ if (!mcpServers)
171
+ return;
172
+ delete mcpServers['code-review-graph'];
173
+ if (_isManagedGraphPeer(mcpServers['atlas'])) {
174
+ delete mcpServers['atlas'];
175
+ }
176
+ }
162
177
  /**
163
178
  * Write workspace-local MCP config files for IDEs whose workspace directories
164
179
  * already exist (`.vscode/`, `.cursor/`). Non-fatal; errors are swallowed.
@@ -181,6 +196,7 @@ function _writeWorkspaceLocalConfigs(callerIde, workspaceRoot) {
181
196
  ? settings.mcpServers
182
197
  : {};
183
198
  servers['nexus-prime'] = entry;
199
+ _stripInternalGraphPeers(servers);
184
200
  settings.mcpServers = servers;
185
201
  writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
186
202
  appendToManifest((m) => {
@@ -212,6 +228,7 @@ function _writeWorkspaceLocalConfigs(callerIde, workspaceRoot) {
212
228
  ? mcp.mcpServers
213
229
  : {};
214
230
  servers['nexus-prime'] = entry;
231
+ _stripInternalGraphPeers(servers);
215
232
  mcp.mcpServers = servers;
216
233
  writeFileSync(mcpPath, JSON.stringify(mcp, null, 2), 'utf8');
217
234
  appendToManifest((m) => {
@@ -347,6 +364,7 @@ function mergeIntoExistingConfig(configPath, newContent, ide) {
347
364
  ...(existing.mcpServers ?? {}),
348
365
  ...(incoming.mcpServers ?? {}),
349
366
  };
367
+ _stripInternalGraphPeers(existing.mcpServers);
350
368
  return JSON.stringify(existing, null, 2);
351
369
  }
352
370
  if (ide === 'claude-code') {
@@ -362,6 +380,7 @@ function mergeIntoExistingConfig(configPath, newContent, ide) {
362
380
  ...(existing.mcpServers ?? {}),
363
381
  ...(incoming.mcpServers ?? {}),
364
382
  };
383
+ _stripInternalGraphPeers(existing.mcpServers);
365
384
  }
366
385
  return JSON.stringify(existing, null, 2);
367
386
  }
package/dist/cli.js CHANGED
@@ -197,9 +197,25 @@ function writeStandardMcpConfig(targetPath, workspaceRoot) {
197
197
  const existing = readJson(targetPath);
198
198
  existing.mcpServers = existing.mcpServers ?? {};
199
199
  existing.mcpServers['nexus-prime'] = buildStandardMcpServerConfig(workspaceRoot);
200
+ delete existing.mcpServers['code-review-graph'];
201
+ if (isNexusManagedGraphPeer(existing.mcpServers['atlas'])) {
202
+ delete existing.mcpServers['atlas'];
203
+ }
200
204
  ensureParentDir(targetPath);
201
205
  writeFileSync(targetPath, JSON.stringify(existing, null, 2));
202
206
  }
207
+ function isNexusManagedGraphPeer(server) {
208
+ if (!server || typeof server !== 'object' || Array.isArray(server))
209
+ return false;
210
+ const record = server;
211
+ const args = Array.isArray(record['args']) ? record['args'].map(String) : [];
212
+ return record['command'] === 'goatlas' && args.length === 1 && args[0] === 'mcp';
213
+ }
214
+ function jsonExposesInternalGraphPeer(parsed) {
215
+ const servers = parsed?.mcpServers ?? parsed?.mcp ?? {};
216
+ return Boolean(servers?.['code-review-graph']
217
+ || isNexusManagedGraphPeer(servers?.['atlas']));
218
+ }
203
219
  function writeOpencodeConfig(targetPath, workspaceRoot) {
204
220
  const existing = readJson(targetPath);
205
221
  const mcpConfig = buildStandardMcpServerConfig(workspaceRoot);
@@ -428,6 +444,15 @@ function buildInstructionFiles(clientId) {
428
444
  content: artifact.content,
429
445
  }));
430
446
  }
447
+ function resolveClaudeDesktopConfigPath() {
448
+ if (process.platform === 'darwin') {
449
+ return join(homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
450
+ }
451
+ if (process.platform === 'win32') {
452
+ return join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'Claude', 'claude_desktop_config.json');
453
+ }
454
+ return join(homedir(), '.claude', 'claude_desktop_config.json');
455
+ }
431
456
  function getSetupDefinition(clientId) {
432
457
  const instructionFiles = buildInstructionFiles(clientId);
433
458
  if (clientId === 'codex') {
@@ -458,7 +483,7 @@ function getSetupDefinition(clientId) {
458
483
  return {
459
484
  id: clientId,
460
485
  label: 'Claude Desktop',
461
- configPath: join(homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'),
486
+ configPath: resolveClaudeDesktopConfigPath(),
462
487
  instructionFiles,
463
488
  };
464
489
  }
@@ -583,6 +608,8 @@ function hasExpectedConfig(definition) {
583
608
  }
584
609
  try {
585
610
  const parsed = JSON.parse(readFileSync(definition.configPath, 'utf8'));
611
+ if (jsonExposesInternalGraphPeer(parsed))
612
+ return false;
586
613
  if (definition.id === 'opencode') {
587
614
  const server = parsed?.mcp?.['nexus-prime'];
588
615
  return Boolean(server && isStableNexusMcpServerConfig(server, 'environment'));
@@ -1724,7 +1751,7 @@ program
1724
1751
  .description('Manage your Nexus Prime license')
1725
1752
  .addCommand(new Command('activate')
1726
1753
  .description('Activate a license key')
1727
- .argument('<key>', 'License key from nexus-prime.cfd/signup or account page')
1754
+ .argument('<key>', 'License key from the Nexus account page or license team')
1728
1755
  .action((key) => {
1729
1756
  const mgr = getSharedLicenseManager();
1730
1757
  const status = mgr.activate(key);
@@ -1737,7 +1764,8 @@ program
1737
1764
  }
1738
1765
  else {
1739
1766
  console.error(`\u2717 License invalid: ${status.degradedReason ?? 'unknown'}`);
1740
- console.error(' Get a valid key at https://nexus-prime.cfd/signup');
1767
+ console.error(' Request a valid key at https://nexus-prime.cfd/account');
1768
+ console.error(' Or email adarsh@nexus-prime.cfd — licenses are shared within 24 hours.');
1741
1769
  process.exit(1);
1742
1770
  }
1743
1771
  }))
@@ -1765,7 +1793,8 @@ program
1765
1793
  .action(() => {
1766
1794
  getSharedLicenseManager().deactivate();
1767
1795
  console.log('\u2713 License removed. Reverted to Free plan.');
1768
- console.log(' Sign up again at https://nexus-prime.cfd/signup');
1796
+ console.log(' Request a new key at https://nexus-prime.cfd/account');
1797
+ console.log(' Or email adarsh@nexus-prime.cfd — licenses are shared within 24 hours.');
1769
1798
  }))
1770
1799
  .addCommand(new Command('login')
1771
1800
  .description('Login to nexus-prime.cfd for license sync')
@@ -1794,7 +1823,8 @@ program
1794
1823
  }
1795
1824
  catch {
1796
1825
  console.log(' License sync skipped (no license found yet).');
1797
- console.log(' Your free license is generated on signup at nexus-prime.cfd/signup');
1826
+ console.log(' Request a license at https://nexus-prime.cfd/account');
1827
+ console.log(' Or email adarsh@nexus-prime.cfd — licenses are shared within 24 hours.');
1798
1828
  }
1799
1829
  }
1800
1830
  catch (err) {
@@ -1848,12 +1878,13 @@ program
1848
1878
  try {
1849
1879
  const result = await requestUpgrade(plan);
1850
1880
  console.log(`\u2713 Upgrade request submitted (${result.status})`);
1851
- console.log(' We will review your request and notify you when approved.');
1881
+ console.log(' The Nexus Prime team will review it and share licenses within 24 hours.');
1852
1882
  console.log(' Once approved, run: nexus-prime license sync');
1853
1883
  }
1854
1884
  catch (err) {
1855
1885
  console.error(`\u2717 Request failed: ${err instanceof Error ? err.message : String(err)}`);
1856
1886
  console.log(' Visit https://nexus-prime.cfd/account to request an upgrade.');
1887
+ console.log(' Or email adarsh@nexus-prime.cfd with your account email and target plan.');
1857
1888
  process.exit(1);
1858
1889
  }
1859
1890
  }));
@@ -11,6 +11,7 @@
11
11
  <link rel="stylesheet" href="./styles/board.css">
12
12
  <link rel="stylesheet" href="./styles/workforce.css">
13
13
  <link rel="stylesheet" href="./styles/memory.css">
14
+ <link rel="stylesheet" href="./styles/context-log.css">
14
15
  <link rel="stylesheet" href="./styles/governance.css">
15
16
  <link rel="stylesheet" href="./styles/trust.css">
16
17
  <link rel="stylesheet" href="./styles/animation.css">
@@ -55,6 +56,7 @@ if(location.protocol==='file:'){
55
56
  <a class="nav-item" data-nav="runtime" href="#runtime">⚡ Runtime</a>
56
57
  <a class="nav-item" data-nav="workforce" href="#workforce">Workforce</a>
57
58
  <a class="nav-item" data-nav="memory" href="#memory">Memory</a>
59
+ <a class="nav-item" data-nav="context-log" href="#context-log">Context Log</a>
58
60
  <a class="nav-item" data-nav="repo" href="#repo">Repo</a>
59
61
  <a class="nav-item" data-nav="knowledge" href="#knowledge">Knowledge</a>
60
62
  <a class="nav-item" data-nav="governance" href="#governance">Governance</a>
@@ -214,12 +216,18 @@ if(location.protocol==='file:'){
214
216
  <input id="mem-search" type="text" placeholder="Search memories…" aria-label="Search memories">
215
217
  <button class="btn btn-sm" id="mem-list-browse-btn">Browse</button>
216
218
  </div>
219
+ <div id="memory-selection-panel" class="memory-selection-panel"></div>
217
220
  <div id="mem-list"></div>
218
221
  </div>
219
222
  <div class="card"><div id="mem-stats"></div></div>
220
223
  </div>
221
224
  </section>
222
225
 
226
+ <!-- CONTEXT LOG ────────────────────────────────────────────── -->
227
+ <section class="view-panel" data-view="context-log" aria-label="Context log">
228
+ <div id="context-log-view"></div>
229
+ </section>
230
+
223
231
  <!-- REPO ───────────────────────────────────────────────────── -->
224
232
  <section class="view-panel" data-view="repo" aria-label="Repo graph">
225
233
  <div class="shd">Repo knowledge graph</div>
@@ -15,6 +15,7 @@ import { init as initCmdBar } from './widgets/command-bar.js';
15
15
  import * as Board from './views/board.js';
16
16
  import * as Workforce from './views/workforce.js';
17
17
  import * as Memory from './views/memory.js';
18
+ import * as ContextLog from './views/context-log.js';
18
19
  import * as Knowledge from './views/knowledge.js';
19
20
  import * as Repo from './views/repo.js';
20
21
  import * as Governance from './views/governance.js';
@@ -53,6 +54,7 @@ navRegister('board', Board.load);
53
54
  navRegister('runtime', Runtime.load);
54
55
  navRegister('workforce', Workforce.load);
55
56
  navRegister('memory', Memory.load);
57
+ navRegister('context-log', ContextLog.load);
56
58
  navRegister('repo', Repo.load);
57
59
  navRegister('knowledge', Knowledge.load);
58
60
  navRegister('governance', Governance.load);
@@ -113,10 +115,14 @@ setOnEvent(evt => {
113
115
  // here we just refresh the surface payload so kanban + KPIs reflect the new run.
114
116
  if (String(evt.type||'').startsWith('orchestration.')) {
115
117
  bustCache('/api/dashboard/surface/operate');
118
+ bustCache('/api/runs');
116
119
  if (tab === 'board') {
117
120
  Board.handleOrchestrationEvent?.(evt);
118
121
  Board.render();
119
122
  }
123
+ if (tab === 'context-log') {
124
+ ContextLog.load();
125
+ }
120
126
  }
121
127
  // Workspace root promoted (e.g. from bootstrap hint) — refresh header immediately.
122
128
  if (String(evt.type||'') === 'workspace.changed') {
@@ -300,6 +306,7 @@ function _reloadTab(tab) {
300
306
  if (tab === 'board') Board.load();
301
307
  if (tab === 'workforce') Workforce.load();
302
308
  if (tab === 'memory') Memory.load();
309
+ if (tab === 'context-log') ContextLog.load();
303
310
  if (tab === 'knowledge') Knowledge.load();
304
311
  }
305
312
 
@@ -65,6 +65,7 @@ export const S = {
65
65
  memQuery: '',
66
66
  graphSim: null,
67
67
  memLane: 'all',
68
+ selectedMemoryIds: [],
68
69
  memorySurface: null,
69
70
  topology: null,
70
71
 
@@ -81,6 +82,10 @@ export const S = {
81
82
  // Orchestration pipeline (live decomposition + completion from SSE)
82
83
  lastDecomposition: null,
83
84
  lastCompletion: null,
85
+ lastDecisionSpine: null,
86
+ contextLogRuns: [],
87
+ contextLogSelectedRunId: null,
88
+ contextLogSpine: null,
84
89
 
85
90
  // Neural Stream HUD ring buffer (latest SSE events, restored from v3.8.0)
86
91
  neuralStream: [],