nexus-prime 7.3.1 → 7.5.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.
Files changed (50) hide show
  1. package/README.md +18 -0
  2. package/dist/adapters/hooks/context.d.ts +2 -2
  3. package/dist/adapters/hooks/index.d.ts +2 -2
  4. package/dist/agents/adapters/ide-compat.js +4 -1
  5. package/dist/agents/adapters/mcp/definitions.d.ts +3 -0
  6. package/dist/agents/adapters/mcp/definitions.js +83 -1
  7. package/dist/agents/adapters/mcp/handlers/governance.js +3 -2
  8. package/dist/agents/adapters/mcp/handlers/memory.js +8 -3
  9. package/dist/agents/adapters/mcp/handlers/orchestration.js +27 -11
  10. package/dist/agents/adapters/mcp/helpers.d.ts +0 -2
  11. package/dist/agents/adapters/mcp/helpers.js +0 -7
  12. package/dist/agents/adapters/mcp/util/token-engine.d.ts +2 -0
  13. package/dist/agents/adapters/mcp/util/token-engine.js +7 -0
  14. package/dist/agents/adapters/mcp.js +13 -12
  15. package/dist/cli/hook.d.ts +9 -1
  16. package/dist/cli/hook.js +11 -2
  17. package/dist/cli/install-wizard.js +4 -1
  18. package/dist/cli.js +8 -0
  19. package/dist/daemon/server.js +7 -8
  20. package/dist/dashboard/app/index.html +4 -1
  21. package/dist/dashboard/app/main.js +11 -0
  22. package/dist/dashboard/app/state.js +4 -0
  23. package/dist/dashboard/app/styles/tokens.css +5 -9
  24. package/dist/dashboard/app/views/board.js +65 -0
  25. package/dist/dashboard/app/views/knowledge.js +8 -4
  26. package/dist/dashboard/app/views/repo.js +113 -24
  27. package/dist/dashboard/routes/graph.js +218 -88
  28. package/dist/dashboard/server.js +6 -1
  29. package/dist/dashboard/stream/sse-broker.js +21 -15
  30. package/dist/engines/client-bootstrap.js +27 -3
  31. package/dist/engines/context-assembler.d.ts +1 -1
  32. package/dist/engines/context-assembler.js +12 -7
  33. package/dist/engines/event-bus.d.ts +29 -1
  34. package/dist/engines/generated-specialist-loader.js +25 -3
  35. package/dist/engines/instruction-gateway.js +9 -5
  36. package/dist/engines/machine-efficiency/types.js +5 -1
  37. package/dist/engines/memory.d.ts +6 -0
  38. package/dist/engines/memory.js +32 -16
  39. package/dist/engines/orchestrator.js +54 -25
  40. package/dist/engines/token-supremacy.d.ts +2 -2
  41. package/dist/engines/token-supremacy.js +4 -4
  42. package/dist/engines/workspace-resolver.js +6 -10
  43. package/dist/index.js +62 -35
  44. package/dist/kernel/context/service.d.ts +2 -2
  45. package/dist/kernel/index.d.ts +2 -2
  46. package/dist/phantom/runtime.d.ts +1 -1
  47. package/dist/phantom/runtime.js +83 -7
  48. package/package.json +4 -3
  49. package/dist/agents/adapters/mcp/util/auto-memory.d.ts +0 -15
  50. package/dist/agents/adapters/mcp/util/auto-memory.js +0 -23
package/README.md CHANGED
@@ -49,8 +49,10 @@
49
49
  - [The problem](#the-problem)
50
50
  - [What changes when you install](#what-changes-when-you-install)
51
51
  - [Quick start](#quick-start)
52
+ - [Docs and comparison](#docs-and-comparison)
52
53
  - [Features](#features)
53
54
  - [See it in action](#see-it-in-action)
55
+ - [Competitive position](#competitive-position)
54
56
  - [Works with](#works-with)
55
57
  - [What users see](#what-users-see)
56
58
  - [Who it's for](#who-its-for)
@@ -62,6 +64,16 @@
62
64
 
63
65
  ---
64
66
 
67
+ ## Docs and comparison
68
+
69
+ - Website: https://nexus-prime.cfd/
70
+ - Comparison: https://nexus-prime.cfd/comparison.html
71
+ - Knowledge base: https://nexus-prime.cfd/knowledge-base.html
72
+
73
+ Agents should start with `nexus_session_bootstrap`, then route the raw request through `nexus_orchestrate`. Auto-bootstrap runs on first non-bootstrap call for compatible clients, but the explicit bootstrap-first path remains the safest integration contract.
74
+
75
+ ---
76
+
65
77
  ## The problem
66
78
 
67
79
  Every coding agent you use starts every session cold.
@@ -269,6 +281,12 @@ No benchmarks from a press release — this is what the dashboard shows you, on
269
281
 
270
282
  ---
271
283
 
284
+ ## Competitive position
285
+
286
+ Nexus Prime is a local-first control plane for coding agents: persistent memory, workspace-scoped runtime state, dashboard observability, and MCP-native orchestration in one install. The public comparison page tracks where it differs from other agent frameworks and developer orchestrators: https://nexus-prime.cfd/comparison.html
287
+
288
+ ---
289
+
272
290
  ## Who it's for
273
291
 
274
292
  Nexus Prime is for people who take AI-assisted coding seriously:
@@ -12,11 +12,11 @@ export declare const ContextHooks: {
12
12
  readonly hypertuneMax: (task: string, files: FileRef[], graphConnectivity?: (chunk: {
13
13
  source: string;
14
14
  label: string;
15
- }) => number) => {
15
+ }) => number) => Promise<{
16
16
  plan: ReadingPlan;
17
17
  assembly: AssemblyResult;
18
18
  budgetConfig: BudgetConfig;
19
- };
19
+ }>;
20
20
  readonly differential: (prev: SessionSummary, curr: FileRef[]) => ContextDelta;
21
21
  readonly loadLatestSessionSummary: () => Promise<SessionSummary | null>;
22
22
  readonly allocateBudget: (workers: Array<{
@@ -37,11 +37,11 @@ export declare const Hooks: {
37
37
  readonly hypertuneMax: (task: string, files: FileRef[], graphConnectivity?: (chunk: {
38
38
  source: string;
39
39
  label: string;
40
- }) => number) => {
40
+ }) => number) => Promise<{
41
41
  plan: import("../../engines/token-supremacy.js").ReadingPlan;
42
42
  assembly: import("../../engines/context-assembler.js").AssemblyResult;
43
43
  budgetConfig: import("../../engines/context-assembler.js").BudgetConfig;
44
- };
44
+ }>;
45
45
  readonly differential: (prev: import("../../engines/token-supremacy.js").SessionSummary, curr: FileRef[]) => import("../../engines/token-supremacy.js").ContextDelta;
46
46
  readonly loadLatestSessionSummary: () => Promise<import("../../engines/token-supremacy.js").SessionSummary | null>;
47
47
  readonly allocateBudget: (workers: Array<{
@@ -13,7 +13,10 @@ function nexusMcpServerEntry(workspaceRoot) {
13
13
  return {
14
14
  command: 'node',
15
15
  args: [join(workspaceRoot, 'node_modules', 'nexus-prime', 'dist', 'cli.js'), 'mcp'],
16
- env: {},
16
+ env: {
17
+ NEXUS_MCP_TOOL_PROFILE: 'autonomous',
18
+ NEXUS_WORKSPACE_ROOT: workspaceRoot,
19
+ },
17
20
  };
18
21
  }
19
22
  function hasAnyEnvPrefix(prefix) {
@@ -2,5 +2,8 @@ export type McpToolDefinition = {
2
2
  name: string;
3
3
  description: string;
4
4
  inputSchema: Record<string, unknown>;
5
+ deprecated?: true;
6
+ deprecatedReplacement?: string;
5
7
  };
8
+ export declare const FIRST_CLASS_TOOLS: Set<string>;
6
9
  export declare function buildMcpToolDefinitions(): McpToolDefinition[];
@@ -1,8 +1,26 @@
1
1
  import { synapseToolDefinitions } from '../../../synapse/index.js';
2
2
  import { architectsToolDefinitions } from '../../../architects/index.js';
3
3
  import { getGstackBridge } from '../../../engines/gstack-bridge.js';
4
+ export const FIRST_CLASS_TOOLS = new Set([
5
+ 'nexus_session_bootstrap',
6
+ 'nexus_orchestrate',
7
+ 'nexus_session_dna',
8
+ 'nexus_store_memory',
9
+ 'nexus_recall_memory',
10
+ 'nexus_memory_stats',
11
+ 'nexus_optimize_tokens',
12
+ 'nexus_mindkit_check',
13
+ 'nexus_ghost_pass',
14
+ 'nexus_describe_tool',
15
+ 'nexus_search',
16
+ 'nexus_runtime_health',
17
+ 'nexus_run_status',
18
+ 'kernel_run_step',
19
+ 'kernel_run_verify',
20
+ 'kernel_run_merge',
21
+ ]);
4
22
  export function buildMcpToolDefinitions() {
5
- return [
23
+ const tools = [
6
24
  // ── Memory ────────────────────────────────────────────────────────
7
25
  {
8
26
  name: 'nexus_store_memory',
@@ -1048,7 +1066,71 @@ export function buildMcpToolDefinitions() {
1048
1066
  },
1049
1067
  },
1050
1068
  },
1069
+ {
1070
+ name: 'kernel_run_step',
1071
+ description: 'Run a mutation step inside an isolated git worktree and record it in the kernel ledger. Returns worktreeRef, commitSha, changedFiles. Merge requires a subsequent kernel_run_verify.',
1072
+ inputSchema: {
1073
+ type: 'object',
1074
+ properties: {
1075
+ runId: { type: 'string' },
1076
+ stepId: { type: 'string' },
1077
+ task: { type: 'string' },
1078
+ intent: { type: 'string' },
1079
+ baseRef: { type: 'string', description: 'Ref/branch/sha to branch off. Defaults to HEAD.' },
1080
+ worktreeHintRef: { type: 'string', description: 'Optional branch label override.' },
1081
+ mutations: {
1082
+ type: 'array',
1083
+ items: {
1084
+ type: 'object',
1085
+ properties: {
1086
+ kind: { type: 'string', enum: ['write_file', 'append_file', 'delete_file', 'run_command'] },
1087
+ path: { type: 'string' },
1088
+ content: { type: 'string' },
1089
+ command: { type: 'string' },
1090
+ cwd: { type: 'string' },
1091
+ },
1092
+ required: ['kind'],
1093
+ },
1094
+ },
1095
+ metadata: { type: 'object' },
1096
+ },
1097
+ required: ['runId', 'stepId', 'task'],
1098
+ },
1099
+ },
1100
+ {
1101
+ name: 'kernel_run_verify',
1102
+ description: 'Hash the files changed by a kernel step and optionally run registered verifiers. Records the snapshot used to detect stale-verify at merge time.',
1103
+ inputSchema: {
1104
+ type: 'object',
1105
+ properties: {
1106
+ runId: { type: 'string' },
1107
+ stepId: { type: 'string' },
1108
+ verifierIds: { type: 'array', items: { type: 'string' } },
1109
+ metadata: { type: 'object' },
1110
+ },
1111
+ required: ['runId', 'stepId'],
1112
+ },
1113
+ },
1114
+ {
1115
+ name: 'kernel_run_merge',
1116
+ description: 'Fast-forward targetRef to a verified kernel step. Rejects when verify is missing, failed, or stale.',
1117
+ inputSchema: {
1118
+ type: 'object',
1119
+ properties: {
1120
+ runId: { type: 'string' },
1121
+ stepId: { type: 'string' },
1122
+ verifyId: { type: 'string', description: 'Explicit verify pin. If omitted, latest passed verify is used.' },
1123
+ targetRef: { type: 'string' },
1124
+ reason: { type: 'string' },
1125
+ metadata: { type: 'object' },
1126
+ },
1127
+ required: ['runId', 'stepId', 'targetRef'],
1128
+ },
1129
+ },
1051
1130
  // ── Embedded capabilities (auto-detected from installed skills) ──
1052
1131
  ...getGstackBridge().getToolDefinitions(),
1053
1132
  ];
1133
+ return tools.map((tool) => FIRST_CLASS_TOOLS.has(tool.name)
1134
+ ? tool
1135
+ : { ...tool, deprecated: true, deprecatedReplacement: tool.deprecatedReplacement ?? 'nexus_orchestrate' });
1054
1136
  }
@@ -3,7 +3,8 @@
3
3
  * graph_query, hypertune_max.
4
4
  * Extracted from mcp.ts (Phase 3 split).
5
5
  */
6
- import { formatBullets, formatJsonDetails, getTokenEngine, getGraphEngine, getTraversalEngine, getHybridRetriever, } from '../helpers.js';
6
+ import { formatBullets, formatJsonDetails, getGraphEngine, getTraversalEngine, getHybridRetriever, } from '../helpers.js';
7
+ import { getTokenEngine } from '../util/token-engine.js';
7
8
  import { nexusEventBus } from '../../../../engines/event-bus.js';
8
9
  import { formatBrandedResponse } from '../../../../engines/nexus-brand.js';
9
10
  import { formatReadingPlan } from '../../../../engines/token-supremacy.js';
@@ -289,7 +290,7 @@ export async function handleGovernanceGroup(toolName, hctx, request, args, ctx)
289
290
  return { path: resolved, sizeBytes: 0 };
290
291
  }
291
292
  })))).filter((f) => f.sizeBytes > 0);
292
- const { plan, assembly, budgetConfig } = getTokenEngine().hypertuneMax(task, files);
293
+ const { plan, assembly, budgetConfig } = await getTokenEngine().hypertuneMax(task, files);
293
294
  const planText = formatReadingPlan(plan);
294
295
  const assemblyText = ContextAssembler.format(assembly, budgetConfig);
295
296
  const savings = plan.savings;
@@ -7,7 +7,6 @@
7
7
  import { formatBullets, formatJsonDetails } from '../helpers.js';
8
8
  import { nexusEventBus } from '../../../../engines/event-bus.js';
9
9
  import { getOperativeJournal } from '../../../../engines/operative-journal.js';
10
- import { storeToolSummary } from '../util/auto-memory.js';
11
10
  import { requireRuntime } from '../util/require-runtime.js';
12
11
  import { nxlResult } from '../../../../nxl/index.js';
13
12
  import { consolidateMemory } from '../../../../engines/memory-consolidator.js';
@@ -368,9 +367,15 @@ export async function handleMemoryGroup(toolName, hctx, request, args, ctx) {
368
367
  states,
369
368
  auditLimit: limit,
370
369
  });
371
- // Record hygiene sweep so dashboard memory view shows recent housekeeping.
370
+ // Surface hygiene-sweep on the SSE feed; do not persist as a memory.
372
371
  try {
373
- storeToolSummary(hctx, 'nexus_memory_hygiene', `Hygiene sweep (${mode}): scanned ${result.audit.scanned}, purge-eligible ${result.health.purgeEligible}, quarantined ${result.health.quarantineBacklog}.`);
372
+ nexusEventBus.emit('memory.snapshot', {
373
+ kind: 'hygiene-sweep',
374
+ mode,
375
+ scanned: result.audit.scanned,
376
+ purgeEligible: result.health.purgeEligible,
377
+ quarantineBacklog: result.health.quarantineBacklog,
378
+ });
374
379
  }
375
380
  catch { /* best-effort */ }
376
381
  return {
@@ -3,7 +3,8 @@
3
3
  * mindkit_check, ghost_pass, spawn_workers, session_dna, plan_execution.
4
4
  * Extracted from mcp.ts (Phase 3 split).
5
5
  */
6
- import { normalizeDetailLevel, normalizeBootstrapDepth, normalizeResponseIntent, normalizeResponseTopology, buildWorkspaceEnvelope, formatBullets, formatJsonDetails, getTokenEngine, getGuardrailEngine, truncateText, } from '../helpers.js';
6
+ import { normalizeDetailLevel, normalizeBootstrapDepth, normalizeResponseIntent, normalizeResponseTopology, buildWorkspaceEnvelope, formatBullets, formatJsonDetails, getGuardrailEngine, truncateText, } from '../helpers.js';
7
+ import { getTokenEngine } from '../util/token-engine.js';
7
8
  import { nexusEventBus } from '../../../../engines/event-bus.js';
8
9
  import { formatBrandedResponse, getRandomQuote } from '../../../../engines/nexus-brand.js';
9
10
  import { hasValidBootstrapReceipt } from '../../../../engines/bootstrap/index.js';
@@ -16,7 +17,6 @@ import { promises as fsPromises } from 'fs';
16
17
  import { getSharedLicenseManager } from '../../../../licensing/index.js';
17
18
  import { SessionDNAManager } from '../../../../engines/session-dna.js';
18
19
  import { getSharedTelemetry } from '../../../../engines/telemetry-remote.js';
19
- import { storeToolSummary } from '../util/auto-memory.js';
20
20
  import { requireRuntime } from '../util/require-runtime.js';
21
21
  import { ensureCrGraphBuilt } from '../../../../engines/code-review-graph-client.js';
22
22
  import { recordFirstBootstrap } from '../../../../engines/telemetry.js';
@@ -136,10 +136,16 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
136
136
  ctx.meta.repoRoot = workspace.repoRoot;
137
137
  ctx.meta.repoName = workspace.repoName;
138
138
  }
139
- // Auto-generate a project-scoped memory on bootstrap so dashboard always has something to show.
140
- // Priority 0.4 (via storeToolSummary) ensures it passes the SSE noise filter (threshold: 0.3).
139
+ // Surface a session-bootstrap signal on the SSE feed without polluting persistent
140
+ // memory. Audit-log content like "Session bootstrap: ..." was previously stored as
141
+ // a real memory (priority 0.4) which dominated recall results and forced low-signal
142
+ // memories into hippocampus.
141
143
  try {
142
- storeToolSummary(hctx, 'nexus_session_bootstrap', `Session bootstrap: ${bootstrapGoal || 'interactive session'}. Memory: prefrontal=${bootstrap.memoryStats?.prefrontal ?? 0}, hippocampus=${bootstrap.memoryStats?.hippocampus ?? 0}, cortex=${bootstrap.memoryStats?.cortex ?? 0}.`);
144
+ nexusEventBus.emit('memory.snapshot', {
145
+ kind: 'session-bootstrap',
146
+ goal: bootstrapGoal || 'interactive session',
147
+ memoryStats: bootstrap.memoryStats,
148
+ });
143
149
  }
144
150
  catch (err) {
145
151
  nexusEventBus.emit('mcp.handler.best-effort-failed', { toolName, stage: 'persist-session-summary', error: err instanceof Error ? err.message : String(err) });
@@ -411,7 +417,10 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
411
417
  result.modifiedFiles.forEach((file) => hctx.sessionDNA.recordFileModified(file));
412
418
  });
413
419
  const runtimeUsage = hctx.getRuntime().getUsageSnapshot();
414
- hctx.sessionDNA.recordDecision('Orchestrated autonomous run completed', execution.result || summarizeExecution(execution), execution.state === 'merged' ? 0.95 : execution.state === 'rolled_back' ? 0.55 : 0.3);
420
+ hctx.sessionDNA.recordDecision('Orchestrated autonomous run completed', execution.result || summarizeExecution(execution), execution.state === 'merged' ? 0.95
421
+ : execution.state === 'inspected' ? 0.85
422
+ : execution.state === 'rolled_back' ? 0.55
423
+ : 0.3);
415
424
  const timings = {
416
425
  totalMs: Date.now() - callStartedAt,
417
426
  };
@@ -738,10 +747,14 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
738
747
  ? String(request.params.arguments.executionPreset)
739
748
  : undefined;
740
749
  const preset = resolveExecutionPreset(executionPreset);
741
- // Record worker plan intent before execution so the dashboard memory view
742
- // shows something even if the run is still in progress.
750
+ // Surface worker-plan intent on the SSE feed without persisting it as a memory.
743
751
  try {
744
- storeToolSummary(hctx, 'nexus_spawn_workers', `Worker plan: "${goal.slice(0, 100)}" — ${workersCount} workers, ${rawFiles.length} files.`);
752
+ nexusEventBus.emit('memory.snapshot', {
753
+ kind: 'worker-plan',
754
+ goal: goal.slice(0, 100),
755
+ workers: workersCount,
756
+ files: rawFiles.length,
757
+ });
745
758
  }
746
759
  catch (err) {
747
760
  nexusEventBus.emit('mcp.handler.best-effort-failed', { toolName, stage: 'worker-plan-summary', error: err instanceof Error ? err.message : String(err) });
@@ -775,7 +788,10 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
775
788
  execution.workerResults.forEach(result => {
776
789
  result.modifiedFiles.forEach(file => hctx.sessionDNA.recordFileModified(file));
777
790
  });
778
- hctx.sessionDNA.recordDecision('Runtime swarm execution completed', execution.result || summarizeExecution(execution), execution.state === 'merged' ? 0.94 : execution.state === 'rolled_back' ? 0.45 : 0.3);
791
+ hctx.sessionDNA.recordDecision('Runtime swarm execution completed', execution.result || summarizeExecution(execution), execution.state === 'merged' ? 0.94
792
+ : execution.state === 'inspected' ? 0.85
793
+ : execution.state === 'rolled_back' ? 0.45
794
+ : 0.3);
779
795
  hctx.nexusRef.storeMemory(`Runtime swarm: state=${execution.state}, workers=${execution.workerResults.length}, verified=${verifiedWorkers}, decision=${execution.finalDecision?.action ?? 'none'}`, execution.state === 'merged' ? 0.92 : 0.72, ['#phantom', '#decision', execution.state]);
780
796
  if (execution.finalDecision) {
781
797
  nexusEventBus.emit('phantom.merge', {
@@ -789,7 +805,7 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
789
805
  `Workers: ${execution.workerResults.length.toString().padEnd(5, ' ')} Verified: ${verifiedWorkers.toString().padEnd(10, ' ')} Files: ${String(modifiedFiles).padEnd(12, ' ')}`,
790
806
  `${`Preset: ${preset?.name ?? 'manual'}`.padEnd(61, ' ')}`,
791
807
  `Decision: ${(execution.finalDecision?.action ?? 'none').padEnd(52, ' ')}`
792
- ], execution.state === 'merged' ? '32' : execution.state === 'rolled_back' ? '33' : '31');
808
+ ], execution.state === 'merged' || execution.state === 'inspected' ? '32' : execution.state === 'rolled_back' ? '33' : '31');
793
809
  return {
794
810
  content: [{
795
811
  type: 'text',
@@ -5,7 +5,6 @@
5
5
  * These are pure functions and lazy-singleton getters shared by the
6
6
  * handler files and by MCPAdapter itself.
7
7
  */
8
- import { TokenSupremacyEngine } from '../../../engines/token-supremacy.js';
9
8
  import { GuardrailEngine } from '../../../engines/guardrails-bridge.js';
10
9
  import { ContinuousAttentionStream, createKVBridge, OrchestratorEngine } from '../../../engines/index.js';
11
10
  import { FederationEngine } from '../../../engines/federation.js';
@@ -14,7 +13,6 @@ import { GraphTraversalEngine } from '../../../engines/graph-traversal.js';
14
13
  import { HybridRetriever } from '../../../engines/hybrid-retriever.js';
15
14
  import type { WorkspaceContext } from '../../../engines/workspace-resolver.js';
16
15
  import type { SubAgentRuntime } from '../../../phantom/index.js';
17
- export declare function getTokenEngine(): TokenSupremacyEngine;
18
16
  export declare function getGuardrailEngine(): GuardrailEngine;
19
17
  export declare function getCasEngine(): ContinuousAttentionStream;
20
18
  export declare function getKvBridge(): ReturnType<typeof createKVBridge>;
@@ -7,7 +7,6 @@
7
7
  */
8
8
  import { statSync, readdirSync } from 'fs';
9
9
  import * as path from 'path';
10
- import { TokenSupremacyEngine } from '../../../engines/token-supremacy.js';
11
10
  import { GuardrailEngine } from '../../../engines/guardrails-bridge.js';
12
11
  import { ContinuousAttentionStream, createKVBridge, OrchestratorEngine, } from '../../../engines/index.js';
13
12
  import { FederationEngine } from '../../../engines/federation.js';
@@ -16,7 +15,6 @@ import { GraphTraversalEngine } from '../../../engines/graph-traversal.js';
16
15
  import { HybridRetriever } from '../../../engines/hybrid-retriever.js';
17
16
  import { createSubAgentRuntime } from '../../../phantom/index.js';
18
17
  // ─── Lazy-init engine singletons ─────────────────────────────────────────────
19
- let _tokenEngine;
20
18
  let _guardrailEngine;
21
19
  let _casEngine;
22
20
  let _kvBridge;
@@ -24,11 +22,6 @@ let _federation;
24
22
  let _graphEngine = null;
25
23
  let _traversalEngine = null;
26
24
  let _hybridRetriever = null;
27
- export function getTokenEngine() {
28
- if (!_tokenEngine)
29
- _tokenEngine = new TokenSupremacyEngine();
30
- return _tokenEngine;
31
- }
32
25
  export function getGuardrailEngine() {
33
26
  if (!_guardrailEngine)
34
27
  _guardrailEngine = new GuardrailEngine();
@@ -0,0 +1,2 @@
1
+ import { TokenSupremacyEngine } from '../../../../engines/token-supremacy.js';
2
+ export declare function getTokenEngine(): TokenSupremacyEngine;
@@ -0,0 +1,7 @@
1
+ import { TokenSupremacyEngine } from '../../../../engines/token-supremacy.js';
2
+ let tokenEngine;
3
+ export function getTokenEngine() {
4
+ if (!tokenEngine)
5
+ tokenEngine = new TokenSupremacyEngine();
6
+ return tokenEngine;
7
+ }
@@ -830,21 +830,22 @@ export class MCPAdapter {
830
830
  : { error: envelope.error.message }),
831
831
  });
832
832
  this.telemetry.observeSuccessfulToolCall(toolName, args);
833
- // Server-side auto-memory: write a low-priority tagged memory after every
834
- // meaningful tool call so MCP clients without hooks (Codex, Cursor) still
835
- // accumulate context automatically. Fire-and-forget never delays response.
836
- // The isNoiseEvent filter in sse-broker.ts drops auto-memories (priority < 0.3)
837
- // from the live SSE feed, so the dashboard event stream stays clean.
833
+ // Surface meaningful tool calls on the SSE feed without persisting them as memories.
834
+ // Previously a low-priority memory was auto-stored on every non-read-only tool call,
835
+ // which polluted recall with audit-log entries like "nexus_store_memory: priority=0.85,
836
+ // tags=...". Recall now stays focused on user-stored knowledge.
838
837
  if (this.nexusRef && !isReadOnlyMcpTool(toolName)) {
839
838
  const repoRoot = this.nexusRef.getWorkspaceContext?.()?.repoRoot ?? '';
840
839
  const repoName = repoRoot ? path.basename(repoRoot) : '';
841
- const summary = buildAutoMemorySummary(toolName, args);
842
- setImmediate(() => {
843
- try {
844
- this.nexusRef.storeMemory(summary, 0.2, ['#auto', `tool:${toolName}`, ...(repoName ? [`repo:${repoName}`] : [])], undefined, undefined, { verbatim: false });
845
- }
846
- catch { /* best-effort; memory engine may not be ready */ }
847
- });
840
+ try {
841
+ nexusEventBus.emit('memory.snapshot', {
842
+ kind: 'tool-invocation',
843
+ toolName,
844
+ repo: repoName,
845
+ summary: buildAutoMemorySummary(toolName, args),
846
+ });
847
+ }
848
+ catch { /* best-effort */ }
848
849
  }
849
850
  const decorated = this.decorateLifecycleResponse(toolName, result);
850
851
  return this.injectMemoryContext(toolName, args, decorated);
@@ -16,7 +16,15 @@
16
16
  */
17
17
  /** UserPromptSubmit — call nexus_session_bootstrap so the model never has to. */
18
18
  export declare function runHookBootstrap(): Promise<void>;
19
- /** PostToolUse (Edit|Write|MultiEdit|Bash) — auto-write low-priority memory. */
19
+ /**
20
+ * PostToolUse (Edit|Write|MultiEdit|Bash) — opt-in audit memory.
21
+ *
22
+ * Disabled by default because every Edit/Write/Bash was being stored as a
23
+ * low-priority memory, which polluted recall results with audit-log entries
24
+ * like "Edit: file_path=src/foo.ts". Real findings should be stored via
25
+ * nexus_store_memory by the agent itself. To opt back in, set
26
+ * NEXUS_HOOK_AUTO_MEMORY=1.
27
+ */
20
28
  export declare function runHookMemory(): Promise<void>;
21
29
  /**
22
30
  * PreToolUse (Edit|Write|MultiEdit) — governance check.
package/dist/cli/hook.js CHANGED
@@ -149,8 +149,18 @@ export async function runHookBootstrap() {
149
149
  goal: goal.slice(0, 500),
150
150
  }, 10_000);
151
151
  }
152
- /** PostToolUse (Edit|Write|MultiEdit|Bash) — auto-write low-priority memory. */
152
+ /**
153
+ * PostToolUse (Edit|Write|MultiEdit|Bash) — opt-in audit memory.
154
+ *
155
+ * Disabled by default because every Edit/Write/Bash was being stored as a
156
+ * low-priority memory, which polluted recall results with audit-log entries
157
+ * like "Edit: file_path=src/foo.ts". Real findings should be stored via
158
+ * nexus_store_memory by the agent itself. To opt back in, set
159
+ * NEXUS_HOOK_AUTO_MEMORY=1.
160
+ */
153
161
  export async function runHookMemory() {
162
+ if (process.env.NEXUS_HOOK_AUTO_MEMORY !== '1')
163
+ return;
154
164
  const data = await readStdinJson();
155
165
  const cwd = String(data.cwd ?? process.cwd());
156
166
  const toolName = String(data.tool_name ?? '');
@@ -163,7 +173,6 @@ export async function runHookMemory() {
163
173
  if (!lock)
164
174
  return;
165
175
  const input = (data.tool_input ?? {});
166
- // Summarize input without large content blobs
167
176
  const inputSummary = Object.entries(input)
168
177
  .filter(([k]) => !['content', 'new_string', 'old_string', 'result', 'command_result'].includes(k))
169
178
  .map(([k, v]) => `${k}=${String(v).slice(0, 80)}`)
@@ -139,7 +139,10 @@ function _nexusMcpEntry(workspaceRoot) {
139
139
  return {
140
140
  command: 'node',
141
141
  args: [join(workspaceRoot, 'node_modules', 'nexus-prime', 'dist', 'cli.js'), 'mcp'],
142
- env: {},
142
+ env: {
143
+ NEXUS_MCP_TOOL_PROFILE: 'autonomous',
144
+ NEXUS_WORKSPACE_ROOT: workspaceRoot,
145
+ },
143
146
  };
144
147
  }
145
148
  /**
package/dist/cli.js CHANGED
@@ -780,6 +780,14 @@ program
780
780
  .addCommand(new Command('__serve')
781
781
  .description('Internal: run the daemon server process (do not call directly)')
782
782
  .action(async () => {
783
+ // Opt the daemon into the deferred-bootstrap fast-start path so the
784
+ // dashboard port listens before the (3+ second) workspace bootstrap
785
+ // file I/O completes. Tests that construct NexusPrime directly do not
786
+ // set this flag, so their synchronous workspace-file assertions still
787
+ // see a fully-initialized state by the time start() resolves.
788
+ if (process.env.NEXUS_DAEMON_FAST_START === undefined) {
789
+ process.env.NEXUS_DAEMON_FAST_START = '1';
790
+ }
783
791
  const workspaceContext = resolveWorkspaceContext({ workspaceRoot: getWorkspaceRoot() });
784
792
  const daemon = new NexusDaemonServer(workspaceContext);
785
793
  const { started, record } = await daemon.start();
@@ -185,14 +185,13 @@ export class NexusDaemonServer {
185
185
  },
186
186
  });
187
187
  await this.nexus.start();
188
- // Pre-warm the n-gram repo-search index so the first nexus_orchestrate
189
- // / nexus_optimize_tokens call doesn't pay the cold-build cost (Codex
190
- // hard-codes a 120s tool-call timeout). setImmediate keeps it off the
191
- // accept loop. Failures are deliberately swallowed — the on-demand path
192
- // will rebuild the index if pre-warm fails.
193
- setImmediate(() => {
194
- void this.nexus?.getOrchestrator().warmRepoSearchIndex().catch(() => { });
195
- });
188
+ // Optional repo-search prewarm. It can be CPU-heavy in large workspaces, so
189
+ // keep daemon startup and dashboard responsiveness as the default behavior.
190
+ if (process.env.NEXUS_PREWARM_REPO_SEARCH === '1' && this.workspace.gitRoot) {
191
+ setImmediate(() => {
192
+ void this.nexus?.getOrchestrator().warmRepoSearchIndex().catch(() => { });
193
+ });
194
+ }
196
195
  // Warm the invoker availability cache so /api/runtimes returns fast and
197
196
  // the dashboard runtime badges render immediately on first load.
198
197
  setImmediate(() => { invokerRegistry.warmCache(); });
@@ -6,7 +6,7 @@
6
6
  <title>Nexus Prime</title>
7
7
 
8
8
  <!-- Design system -->
9
- <link rel="stylesheet" href="./styles/tokens.css">
9
+ <link rel="stylesheet" href="./styles/tokens.css?v=4">
10
10
  <link rel="stylesheet" href="./styles/shell.css">
11
11
  <link rel="stylesheet" href="./styles/board.css">
12
12
  <link rel="stylesheet" href="./styles/workforce.css">
@@ -113,6 +113,9 @@ if(location.protocol==='file:'){
113
113
  <div><div class="kb-col-hd"><span class="kb-col-title">Done</span><span class="kb-count" id="kc-done">0</span></div><div class="kb-body" id="kb-done"></div></div>
114
114
  </div>
115
115
 
116
+ <!-- Orchestration pipeline (live decomposition + completion) -->
117
+ <div id="orchestration-pipeline" class="card" style="margin-bottom:16px;display:none"></div>
118
+
116
119
  <!-- Tool health strip -->
117
120
  <div id="tool-health-card" class="card" style="margin-bottom:16px;display:none">
118
121
  <div class="shd" style="margin-bottom:8px">Tool Health <span id="tool-health-stamp" style="font-size:11px;opacity:.5;font-weight:400"></span></div>
@@ -80,6 +80,17 @@ setOnEvent(evt => {
80
80
  if (String(evt.type||'').startsWith('dispatch.')) {
81
81
  Workforce.handleDispatchEvent(evt);
82
82
  }
83
+
84
+ // Orchestration pipeline events — keep board fresh as decomposition / completion fires.
85
+ // The board's own SSE listener (board.js:loadOrchestrationPipeline) renders the detail card;
86
+ // here we just refresh the surface payload so kanban + KPIs reflect the new run.
87
+ if (String(evt.type||'').startsWith('orchestration.')) {
88
+ bustCache('/api/dashboard/surface/operate');
89
+ if (tab === 'board') {
90
+ Board.handleOrchestrationEvent?.(evt);
91
+ Board.render();
92
+ }
93
+ }
83
94
  // Workspace root promoted (e.g. from bootstrap hint) — refresh header immediately.
84
95
  if (String(evt.type||'') === 'workspace.changed') {
85
96
  bustCache('/api/workspace');
@@ -78,6 +78,10 @@ export const S = {
78
78
  ledger: null,
79
79
  workerPlan: null,
80
80
 
81
+ // Orchestration pipeline (live decomposition + completion from SSE)
82
+ lastDecomposition: null,
83
+ lastCompletion: null,
84
+
81
85
  // Assets sub-tabs
82
86
  assetsSubTab: 'skills',
83
87
 
@@ -2,7 +2,7 @@
2
2
  * tokens.css — OKLCh design tokens, LATTICE typography scale, spacing, and reset.
3
3
  * Lifted from index.html inline styles and kept as the single source of truth.
4
4
  * Fonts: Instrument Serif (display/title), Geist (body/label), Geist Mono (data/caption).
5
- * Place .woff2 subsets in ./assets/fonts/ for offline-first serving.
5
+ * Local-first declarations avoid network/font 404s when optional subsets are absent.
6
6
  */
7
7
 
8
8
  /* ── @font-face declarations (local-first; graceful system fallback) ── */
@@ -11,8 +11,7 @@
11
11
  font-style: normal;
12
12
  font-weight: 400;
13
13
  font-display: swap;
14
- src: local('Instrument Serif'),
15
- url('../assets/fonts/InstrumentSerif-Regular.woff2') format('woff2');
14
+ src: local('Instrument Serif');
16
15
  }
17
16
 
18
17
  @font-face {
@@ -20,8 +19,7 @@
20
19
  font-style: italic;
21
20
  font-weight: 400;
22
21
  font-display: swap;
23
- src: local('Instrument Serif Italic'),
24
- url('../assets/fonts/InstrumentSerif-Italic.woff2') format('woff2');
22
+ src: local('Instrument Serif Italic');
25
23
  }
26
24
 
27
25
  @font-face {
@@ -29,8 +27,7 @@
29
27
  font-style: normal;
30
28
  font-weight: 400 600;
31
29
  font-display: swap;
32
- src: local('Geist'),
33
- url('../assets/fonts/Geist-Regular.woff2') format('woff2');
30
+ src: local('Geist');
34
31
  }
35
32
 
36
33
  @font-face {
@@ -38,8 +35,7 @@
38
35
  font-style: normal;
39
36
  font-weight: 400 600;
40
37
  font-display: swap;
41
- src: local('Geist Mono'),
42
- url('../assets/fonts/GeistMono-Regular.woff2') format('woff2');
38
+ src: local('Geist Mono');
43
39
  }
44
40
 
45
41
  :root {