nexus-prime 6.1.0 → 6.2.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.
@@ -333,6 +333,36 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
333
333
  const executionPreset = request.params.arguments?.executionPreset
334
334
  ? String(request.params.arguments.executionPreset)
335
335
  : undefined;
336
+ // Auto-apply token optimization when explicit files are provided.
337
+ // Gives agents an upfront reading plan before orchestrate runs.
338
+ // No-files path relies on knowledge fabric (handled inside orchestrate).
339
+ let upfrontTokenNote = '';
340
+ if (files && files.length > 3) {
341
+ try {
342
+ const statLimit = pLimit(8);
343
+ const fileRefs = await Promise.all(files.map((p) => statLimit(async () => {
344
+ const resolved = hctx.resolveToolPath(p, request.params.arguments ?? {});
345
+ try {
346
+ const stat = await fsPromises.stat(resolved);
347
+ return { path: resolved, sizeBytes: stat.size, lastModified: stat.mtimeMs };
348
+ }
349
+ catch {
350
+ return { path: resolved, sizeBytes: 0 };
351
+ }
352
+ })));
353
+ const upfrontPlan = await getTokenEngine().plan(prompt, fileRefs);
354
+ if (upfrontPlan.savings > 0) {
355
+ const pct = upfrontPlan.totalEstimatedTokens > 0
356
+ ? Math.round(upfrontPlan.savings / (upfrontPlan.totalEstimatedTokens + upfrontPlan.savings) * 100)
357
+ : 0;
358
+ upfrontTokenNote = `Token plan: ${upfrontPlan.files.filter(a => a.action === 'full').length} full reads, ${upfrontPlan.files.filter(a => a.action === 'outline').length} outlines, ${upfrontPlan.files.filter(a => a.action === 'skip').length} skipped. ~${upfrontPlan.savings.toLocaleString()} tokens saved (${pct}%). `;
359
+ nexusEventBus.emit('tokens.optimized', { savings: upfrontPlan.savings, pct, source: 'orchestrate-preflight' });
360
+ }
361
+ }
362
+ catch {
363
+ // Non-fatal: proceed without upfront plan
364
+ }
365
+ }
336
366
  try {
337
367
  const preset = resolveExecutionPreset(executionPreset);
338
368
  const execution = await hctx.nexusRef.orchestrate(prompt, applyExecutionPreset({
@@ -459,6 +489,7 @@ export async function handleOrchestrationGroup(toolName, hctx, request, args, ct
459
489
  content: [{
460
490
  type: 'text',
461
491
  text: [
492
+ upfrontTokenNote ? `[Token plan] ${upfrontTokenNote}` : '',
462
493
  `Orchestrated run ${execution.state}.`,
463
494
  formatBullets([
464
495
  `Workspace: ${workspace.repoName} (${workspace.workspaceSource})`,
@@ -913,9 +913,14 @@ export class MCPAdapter {
913
913
  const swarm = await this.getOrchestrator().induce(goal);
914
914
  nexusEventBus.emit('nexusnet.sync', { newItemsCount: swarm.length });
915
915
  }
916
- // v6: Lazy-init Synapse/Architects on first tool call if not yet initialized
916
+ // v6: Lazy-init Synapse/Architects on first tool call if not yet initialized.
917
+ // Mandate + hire tools need Architects live so coordination bridge is set before
918
+ // executeMandatePipeline runs (otherwise worklistId is null, orphaned teams).
917
919
  if (toolName.startsWith('nexus_synapse_')) {
918
920
  this.nexusRef.ensureSynapseInit();
921
+ if (toolName === 'nexus_synapse_mandate' || toolName === 'nexus_synapse_assign_mission' || toolName === 'nexus_synapse_hire') {
922
+ this.nexusRef.ensureArchitectsInit();
923
+ }
919
924
  }
920
925
  const synapseResponse = await handleSynapseToolCall(toolName, args, this.nexusRef.getSynapse?.() ?? null);
921
926
  if (synapseResponse) {
@@ -185,41 +185,65 @@ export function initArchitects(options) {
185
185
  if (hasOperative)
186
186
  ward.start();
187
187
  const onOperativeHired = ({ operativeId, strikeTeamId }) => {
188
- knownOperatives.add(operativeId);
189
- operativeActivity.set(operativeId, { strikeTeamId, lastSortieAt: null });
190
- ensureImplicitWorklist(strikeTeamId);
188
+ try {
189
+ knownOperatives.add(operativeId);
190
+ operativeActivity.set(operativeId, { strikeTeamId, lastSortieAt: null });
191
+ ensureImplicitWorklist(strikeTeamId);
192
+ }
193
+ catch (err) {
194
+ console.error('[Architects] onOperativeHired failed', operativeId, err);
195
+ nexusEventBus.emit('architects.event.failed', { event: 'operative.hired', operativeId, error: String(err) });
196
+ }
191
197
  };
192
198
  const onMissionAssigned = ({ operativeId, missionId, title }) => {
193
- const activity = operativeActivity.get(operativeId);
194
- const strikeTeamId = activity?.strikeTeamId ?? null;
195
- if (!strikeTeamId)
196
- return;
197
- const worklistId = ensureImplicitWorklist(strikeTeamId);
198
- upsertWorkItem(db, {
199
- id: missionId,
200
- worklistId,
201
- title,
202
- status: 'todo',
203
- assignedOperativeId: operativeId,
204
- constructionLockId: null,
205
- dependsOn: [],
206
- branch: null,
207
- mergedAt: null,
208
- createdAt: new Date().toISOString(),
209
- });
199
+ try {
200
+ const activity = operativeActivity.get(operativeId);
201
+ const strikeTeamId = activity?.strikeTeamId ?? null;
202
+ if (!strikeTeamId)
203
+ return;
204
+ const worklistId = ensureImplicitWorklist(strikeTeamId);
205
+ upsertWorkItem(db, {
206
+ id: missionId,
207
+ worklistId,
208
+ title,
209
+ status: 'todo',
210
+ assignedOperativeId: operativeId,
211
+ constructionLockId: null,
212
+ dependsOn: [],
213
+ branch: null,
214
+ mergedAt: null,
215
+ createdAt: new Date().toISOString(),
216
+ });
217
+ }
218
+ catch (err) {
219
+ console.error('[Architects] onMissionAssigned failed', missionId, err);
220
+ nexusEventBus.emit('architects.event.failed', { event: 'mission.assigned', operativeId, missionId, error: String(err) });
221
+ }
210
222
  };
211
223
  const onSortieCompleted = ({ operativeId, missionId, status }) => {
212
- const activity = operativeActivity.get(operativeId);
213
- if (activity) {
214
- activity.lastSortieAt = new Date().toISOString();
215
- operativeActivity.set(operativeId, activity);
224
+ try {
225
+ const activity = operativeActivity.get(operativeId);
226
+ if (activity) {
227
+ activity.lastSortieAt = new Date().toISOString();
228
+ operativeActivity.set(operativeId, activity);
229
+ }
230
+ if (!missionId)
231
+ return;
232
+ updateWorkItemStatus(db, missionId, status === 'completed' ? 'done' : status === 'failed' ? 'failed' : 'blocked');
233
+ }
234
+ catch (err) {
235
+ console.error('[Architects] onSortieCompleted failed', missionId, err);
236
+ nexusEventBus.emit('architects.event.failed', { event: 'sortie.completed', operativeId, missionId: missionId ?? undefined, error: String(err) });
216
237
  }
217
- if (!missionId)
218
- return;
219
- updateWorkItemStatus(db, missionId, status === 'completed' ? 'done' : status === 'failed' ? 'failed' : 'blocked');
220
238
  };
221
239
  const onStriketeamDeployed = ({ strikeTeamId }) => {
222
- ensureImplicitWorklist(strikeTeamId);
240
+ try {
241
+ ensureImplicitWorklist(strikeTeamId);
242
+ }
243
+ catch (err) {
244
+ console.error('[Architects] onStriketeamDeployed failed', strikeTeamId, err);
245
+ nexusEventBus.emit('architects.event.failed', { event: 'striketeam.deployed', strikeTeamId, error: String(err) });
246
+ }
223
247
  };
224
248
  const onStanddown = () => setConvergencePaused(true);
225
249
  const onResumed = () => setConvergencePaused(false);
@@ -120,6 +120,10 @@ export const handleGovernanceRoutes = async (ctx, req, res, url) => {
120
120
  return true;
121
121
  }
122
122
  if (req.method === 'POST' && url.pathname === '/api/synapse/deploy-crew') {
123
+ // Ensure Architects is live before mandate so coordination bridge is wired.
124
+ // getSynapse() triggers ensureSynapseInit(); getArchitects() triggers ensureArchitectsInit()
125
+ // + reconnectSynapseCoordination() so worklistId is non-null in the pipeline.
126
+ ctx.getArchitects();
123
127
  const synapse = ctx.getSynapse();
124
128
  if (!synapse) {
125
129
  const initErr = ctx.getSynapseInitError();
@@ -1,4 +1,4 @@
1
- export type NexusEventType = 'system.boot' | 'planner.stage' | 'memory.store' | 'memory.dedup' | 'memory.recall' | 'memory.flushed' | 'memory.health.tick' | 'memory.sqlite.retry' | 'pod.signal' | 'tokens.optimized' | 'tokens.searchSaved' | 'session.summaryBootstrap' | 'phantom.worker.start' | 'phantom.worker.complete' | 'phantom.merge.complete' | 'phantom.merge' | 'guardrail.check' | 'ghost.pass' | 'graph.query' | 'graph.sync.failed' | 'graph.coverage.low' | 'graph.cr.build.start' | 'graph.cr.build.complete' | 'graph.cr.build.failed' | 'darwin.cycle' | 'darwin.cycle.complete' | 'session.dna' | 'skill.register' | 'skill.deploy' | 'skill.revoke' | 'hook.deploy' | 'hook.revoke' | 'hook.fire' | 'hook.error' | 'workflow.deploy' | 'workflow.run' | 'automation.deploy' | 'automation.revoke' | 'automation.run' | 'shield.decision' | 'memory.audit' | 'federation.heartbeat' | 'client.heartbeat' | 'client.inferred' | 'client.status' | 'dashboard.action' | 'nexus.shutdown' | 'orchestrator.disposed' | 'orchestrator.funnel.stage' | 'nexusnet.publish' | 'nexusnet.sync' | 'mcp.call.start' | 'mcp.call.stream' | 'mcp.call.complete' | 'mcp.handler.complete' | 'mcp.handler.failed' | 'mcp.handler.retry' | 'mcp.handler.best-effort-failed' | 'tool.invocation' | 'memory.tier.promoted' | 'memory.tier.promoted.failed' | 'memory.pre-compaction' | 'memory.flush-requested' | 'entanglement.create' | 'entanglement.collapse' | 'entanglement.correlate' | 'cas.encode' | 'cas.decode' | 'cas.pattern_learned' | 'kv.merge' | 'kv.adapt' | 'kv.consensus' | 'byzantine.vote.started' | 'byzantine.vote.result' | 'synapse.ready' | 'synapse.operative.hired' | 'synapse.operative.retired' | 'synapse.operative.health.changed' | 'synapse.striketeam.deployed' | 'synapse.striketeam.completed' | 'synapse.mission.assigned' | 'synapse.mission.completed' | 'synapse.sortie.started' | 'synapse.sortie.completed' | 'synapse.sortie.failed' | 'synapse.fieldreport.submitted' | 'synapse.echo.fired' | 'synapse.budget.warning' | 'synapse.budget.exceeded' | 'synapse.approval.requested' | 'synapse.approval.resolved' | 'synapse.compaction.standdown' | 'synapse.compaction.resumed' | 'synapse.watchdog.stall' | 'synapse.watchdog.zombie' | 'architects.ready' | 'architects.blueprint.instantiated' | 'architects.worklist.created' | 'architects.workitem.claimed' | 'architects.workitem.completed' | 'architects.workitem.blocked' | 'architects.constructionlock.acquired' | 'architects.constructionlock.renewed' | 'architects.constructionlock.released' | 'architects.constructionlock.contested' | 'architects.relay.sent' | 'architects.relay.read' | 'architects.sentinel.patrol' | 'architects.sentinel.stall' | 'architects.sentinel.zombie' | 'architects.ward.patrol' | 'architects.ward.escalation' | 'architects.convergence.started' | 'architects.convergence.merged' | 'architects.convergence.failed' | 'architects.dispatch.go' | 'architects.dispatch.queued' | 'architects.relay.failed' | 'ledger.duplicate-prevented' | 'nexus.circuit-open' | 'nexus.circuit-tripped' | 'license.activated' | 'license.deactivated' | 'license.expired' | 'license.cap.warning' | 'license.cap.reached' | 'dispatch.started' | 'dispatch.event' | 'dispatch.token-usage' | 'dispatch.complete' | 'dispatch.failed' | 'dispatch.cancelled' | 'dispatch.budget-exceeded' | 'mcp.auto-memory.failed' | 'daemon.self-heal.db-corrupt' | 'feature.time_to_first_bootstrap' | 'feature.time_to_first_memory' | 'feature.time_to_first_interaction' | 'feature.time_to_first_mission_complete';
1
+ export type NexusEventType = 'system.boot' | 'planner.stage' | 'memory.store' | 'memory.dedup' | 'memory.recall' | 'memory.flushed' | 'memory.health.tick' | 'memory.sqlite.retry' | 'pod.signal' | 'tokens.optimized' | 'tokens.searchSaved' | 'session.summaryBootstrap' | 'phantom.worker.start' | 'phantom.worker.complete' | 'phantom.merge.complete' | 'phantom.merge' | 'guardrail.check' | 'ghost.pass' | 'graph.query' | 'graph.sync.failed' | 'graph.coverage.low' | 'graph.cr.build.start' | 'graph.cr.build.complete' | 'graph.cr.build.failed' | 'darwin.cycle' | 'darwin.cycle.complete' | 'session.dna' | 'skill.register' | 'skill.deploy' | 'skill.revoke' | 'hook.deploy' | 'hook.revoke' | 'hook.fire' | 'hook.error' | 'workflow.deploy' | 'workflow.run' | 'automation.deploy' | 'automation.revoke' | 'automation.run' | 'shield.decision' | 'memory.audit' | 'federation.heartbeat' | 'client.heartbeat' | 'client.inferred' | 'client.status' | 'dashboard.action' | 'nexus.shutdown' | 'orchestrator.disposed' | 'orchestrator.funnel.stage' | 'nexusnet.publish' | 'nexusnet.sync' | 'mcp.call.start' | 'mcp.call.stream' | 'mcp.call.complete' | 'mcp.handler.complete' | 'mcp.handler.failed' | 'mcp.handler.retry' | 'mcp.handler.best-effort-failed' | 'tool.invocation' | 'memory.tier.promoted' | 'memory.tier.promoted.failed' | 'memory.pre-compaction' | 'memory.flush-requested' | 'entanglement.create' | 'entanglement.collapse' | 'entanglement.correlate' | 'cas.encode' | 'cas.decode' | 'cas.pattern_learned' | 'kv.merge' | 'kv.adapt' | 'kv.consensus' | 'byzantine.vote.started' | 'byzantine.vote.result' | 'synapse.ready' | 'synapse.operative.hired' | 'synapse.operative.retired' | 'synapse.operative.health.changed' | 'synapse.striketeam.deployed' | 'synapse.striketeam.completed' | 'synapse.mission.assigned' | 'synapse.mission.completed' | 'synapse.sortie.started' | 'synapse.sortie.completed' | 'synapse.sortie.failed' | 'synapse.fieldreport.submitted' | 'synapse.echo.fired' | 'synapse.budget.warning' | 'synapse.budget.exceeded' | 'synapse.approval.requested' | 'synapse.approval.resolved' | 'synapse.compaction.standdown' | 'synapse.compaction.resumed' | 'synapse.watchdog.stall' | 'synapse.watchdog.zombie' | 'architects.ready' | 'architects.blueprint.instantiated' | 'architects.worklist.created' | 'architects.workitem.claimed' | 'architects.workitem.completed' | 'architects.workitem.blocked' | 'architects.constructionlock.acquired' | 'architects.constructionlock.renewed' | 'architects.constructionlock.released' | 'architects.constructionlock.contested' | 'architects.relay.sent' | 'architects.relay.read' | 'architects.sentinel.patrol' | 'architects.sentinel.stall' | 'architects.sentinel.zombie' | 'architects.ward.patrol' | 'architects.ward.escalation' | 'architects.convergence.started' | 'architects.convergence.merged' | 'architects.convergence.failed' | 'architects.dispatch.go' | 'architects.dispatch.queued' | 'architects.relay.failed' | 'architects.event.failed' | 'ledger.duplicate-prevented' | 'nexus.circuit-open' | 'nexus.circuit-tripped' | 'license.activated' | 'license.deactivated' | 'license.expired' | 'license.cap.warning' | 'license.cap.reached' | 'dispatch.started' | 'dispatch.event' | 'dispatch.token-usage' | 'dispatch.complete' | 'dispatch.failed' | 'dispatch.cancelled' | 'dispatch.budget-exceeded' | 'mcp.auto-memory.failed' | 'daemon.self-heal.db-corrupt' | 'feature.time_to_first_bootstrap' | 'feature.time_to_first_memory' | 'feature.time_to_first_interaction' | 'feature.time_to_first_mission_complete';
2
2
  export interface NexusEventPayloads {
3
3
  'system.boot': {
4
4
  version: string;
@@ -625,6 +625,13 @@ export interface NexusEventPayloads {
625
625
  subject: string;
626
626
  error: string;
627
627
  };
628
+ 'architects.event.failed': {
629
+ event: string;
630
+ operativeId?: string;
631
+ missionId?: string;
632
+ strikeTeamId?: string;
633
+ error: string;
634
+ };
628
635
  'ledger.duplicate-prevented': {
629
636
  fingerprint: string;
630
637
  existingId: string;
@@ -144,7 +144,7 @@ export function initSynapse(options) {
144
144
  if (payload.operativeId) {
145
145
  db.prepare('UPDATE synapse_operatives SET health_state=\'BLOCKED\', state=\'SUSPENDED\', suspend_reason=\'manual\' WHERE id=?').run(payload.operativeId);
146
146
  nexusEventBus.emit('synapse.operative.health.changed', { operativeId: payload.operativeId, healthState: 'BLOCKED' });
147
- providers.memory.store(`[Architects:Blocked] ${payload.operativeId} ${payload.reason ?? ''}`.trim(), 0.82, ['#synapse', '#blocked']);
147
+ providers.memory.store(`[Architects:Blocked] ${payload.operativeId} ${payload.reason ?? ''}`.trim(), 0.82, ['#synapse', '#blocked'], undefined, 0, { provenance: { agentId: payload.operativeId, source: 'system' } });
148
148
  }
149
149
  };
150
150
  const stallListener = ({ operativeId }) => {
@@ -157,7 +157,12 @@ export async function executeMandatePipeline(db, mandateText, providers, opts =
157
157
  correlationId: teamId,
158
158
  status: 'deployed',
159
159
  });
160
- providers.memory.store(`[Synapse:Mandate] ${mandateText}`, 0.85, ['#synapse', '#mandate', `#team:${teamId}`]);
160
+ providers.memory.store(`[Synapse:Mandate] ${mandateText}`, 0.85, ['#synapse', '#mandate', `#team:${teamId}`], undefined, 0, {
161
+ provenance: {
162
+ source: 'runtime',
163
+ containerTags: [`#team:${teamId}`, ...(worklistId ? [`#worklist:${worklistId}`] : [])],
164
+ },
165
+ });
161
166
  return getStrikeTeam(db, teamId);
162
167
  })();
163
168
  return team;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexus-prime",
3
- "version": "6.1.0",
3
+ "version": "6.2.0",
4
4
  "description": "Local-first MCP control plane for coding agents with bootstrap-orchestrate execution, memory fabric, token budgeting, and worktree-backed swarms",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -25,6 +25,7 @@
25
25
  "nexus-prime": "dist/cli.js"
26
26
  },
27
27
  "scripts": {
28
+ "prepare": "git config core.hooksPath .hooks || true",
28
29
  "nexus:dev": "node dev-orchestrator.mjs",
29
30
  "generate:competitive-landscape": "tsx scripts/generate-competitive-landscape.ts",
30
31
  "generate:readme-catalog": "tsx scripts/generate-readme-runtime-catalog.ts",