nexus-prime 7.9.25 → 7.9.27

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 CHANGED
@@ -74,6 +74,17 @@ Agents should start with `nexus_session_bootstrap`, then route the raw request t
74
74
 
75
75
  ---
76
76
 
77
+ ## Provenance and social proof
78
+
79
+ Nexus Prime now treats provenance as a product surface, not a footer afterthought.
80
+
81
+ - Every Nexus-enabled PR can carry a **Nexus Prime Presence** block that links back to https://nexus-prime.cfd/ and states whether Nexus observed, verified, assisted, authored, or published the change.
82
+ - Nexus-generated commits use the repo-local Git-native `Co-Authored-By` trailer for the Nexus Prime GitHub identity; human-only commits are not falsely claimed.
83
+ - Generated artifacts can include a Nexus Prime signature with run ID, verification state, human-review state, and website proof.
84
+ - Opt-in telemetry can send privacy-safe PLG events such as `pr_presence_added`, `commit_attributed`, `document_signed`, `release_verified`, and `proof_badge_viewed` to the configured Supabase endpoint. Raw prompts, code, repo names, branch names, file paths, secrets, and tokens are redacted by default.
85
+
86
+ ---
87
+
77
88
  ## The problem
78
89
 
79
90
  Every coding agent you use starts every session cold.
package/dist/cli.js CHANGED
@@ -40,6 +40,7 @@ import { runReset } from './cli/reset.js';
40
40
  import { runUninstall } from './cli/uninstall.js';
41
41
  import { runCleanup } from './cli/cleanup.js';
42
42
  import { runDoctorStorage } from './cli/doctor-storage.js';
43
+ import { formatNexusProofReport, verifyNexusProof } from './engines/nexus-proof.js';
43
44
  const tokenEngine = new TokenSupremacyEngine();
44
45
  import { getNexusHookSpec, writeNexusClaudeCodeHooks, } from './install/claude-code-hooks.js';
45
46
  /**
@@ -1886,6 +1887,34 @@ program
1886
1887
  nexus = null;
1887
1888
  }
1888
1889
  });
1890
+ program
1891
+ .command('proof')
1892
+ .description('Inspect Nexus Prime provenance, signatures, and opt-in proof telemetry')
1893
+ .addCommand(new Command('verify')
1894
+ .description('Verify Nexus Prime PR presence, generated commit trailers, artifact signatures, and telemetry redaction')
1895
+ .option('--repo-root <path>', 'Repo root to verify (default: cwd)')
1896
+ .option('--pr-body <path>', 'Generated pull request body markdown to verify')
1897
+ .option('--commit-message <path>', 'Generated commit message file to verify')
1898
+ .option('--artifact <path...>', 'Generated artifact/document files to verify')
1899
+ .option('--strict', 'Treat warnings as failures')
1900
+ .option('--json', 'Output raw JSON')
1901
+ .action(async (options) => {
1902
+ const summary = await verifyNexusProof({
1903
+ repoRoot: options.repoRoot ? path.resolve(options.repoRoot) : getWorkspaceRoot(),
1904
+ prBodyPath: options.prBody ? path.resolve(options.prBody) : undefined,
1905
+ commitMessagePath: options.commitMessage ? path.resolve(options.commitMessage) : undefined,
1906
+ artifactPaths: (options.artifact ?? []).map((artifactPath) => path.resolve(artifactPath)),
1907
+ });
1908
+ if (options.json) {
1909
+ console.log(JSON.stringify(summary, null, 2));
1910
+ }
1911
+ else {
1912
+ console.log(formatNexusProofReport(summary));
1913
+ }
1914
+ if (summary.failed > 0 || (options.strict && summary.warnings > 0)) {
1915
+ process.exitCode = 1;
1916
+ }
1917
+ }));
1889
1918
  program
1890
1919
  .command('memory-hygiene')
1891
1920
  .description('Inspect or apply memory hygiene to reduce duplicate and low-signal memories')
@@ -479,6 +479,38 @@
479
479
  color: var(--text-main); margin-bottom: 4px;
480
480
  }
481
481
  .frh-sub { font-size: var(--text-sm); color: var(--text-dim); }
482
+ .frh-steps {
483
+ display: grid;
484
+ grid-template-columns: repeat(3, minmax(0, 1fr));
485
+ gap: 8px;
486
+ margin-bottom: 14px;
487
+ }
488
+ .frh-step {
489
+ display: grid;
490
+ grid-template-columns: auto 1fr;
491
+ grid-template-rows: auto auto;
492
+ gap: 1px 8px;
493
+ align-items: center;
494
+ padding: 9px 10px;
495
+ border: 1px solid color-mix(in oklch, var(--accent) 24%, var(--border));
496
+ border-radius: var(--radius);
497
+ background: color-mix(in oklch, var(--accent) 4%, var(--bg-panel));
498
+ min-width: 0;
499
+ }
500
+ .frh-step span {
501
+ grid-row: 1 / span 2;
502
+ display: inline-grid;
503
+ place-items: center;
504
+ width: 22px;
505
+ height: 22px;
506
+ border-radius: 50%;
507
+ background: color-mix(in oklch, var(--accent) 18%, transparent);
508
+ color: var(--accent);
509
+ font-family: var(--font-mono);
510
+ font-size: 0.72rem;
511
+ }
512
+ .frh-step strong { font-size: 0.78rem; color: var(--text-main); min-width: 0; }
513
+ .frh-step small { font-size: 0.72rem; color: var(--text-dim); min-width: 0; }
482
514
  .frh-command {
483
515
  display: grid;
484
516
  grid-template-columns: minmax(220px, 1fr) auto auto;
@@ -492,6 +524,7 @@
492
524
  transition: border-color 0.15s;
493
525
  }
494
526
  .frh-pick:hover { border-color: var(--accent); }
527
+ .frh-pick-loading { border-style: dashed; }
495
528
  .frh-pick-name { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text-main); }
496
529
  .frh-pick-desc { font-size: 0.78rem; color: var(--text-dim); flex: 1; }
497
530
  .frh-pick-cost { font-family: var(--font-mono); font-size: 0.75rem; color: var(--accent); margin-top: 2px; }
@@ -507,6 +540,7 @@
507
540
  }
508
541
  @media (max-width: 768px) {
509
542
  #kanban-board { grid-template-columns: repeat(2, 1fr); }
543
+ .frh-steps,
510
544
  .frh-command,
511
545
  .frh-picks { grid-template-columns: 1fr; }
512
546
  }
@@ -376,7 +376,6 @@ function renderFirstRunHero() {
376
376
  if (hasOps || (alreadySeen && hasRuns)) return;
377
377
 
378
378
  const specs = (S.curatedSpecialists || []).slice(0, 3);
379
- if (!specs.length) return; // Still loading — will re-render when prefetch resolves
380
379
  const readiness = getHireReadiness();
381
380
  const noticesHtml = readiness.notes.length
382
381
  ? `<div class="frh-notices" style="display:flex;flex-direction:column;gap:8px;margin-bottom:12px">
@@ -389,23 +388,33 @@ function renderFirstRunHero() {
389
388
  card.className = 'first-run-hero card';
390
389
  card.innerHTML = `
391
390
  <div class="frh-header">
392
- <div class="frh-title">${hasRuns ? 'Your next hire' : 'Start the first real run'}</div>
393
- <div class="frh-sub">${hasRuns ? 'Hire a specialist to start running tasks autonomously.' : 'Run a goal from the dashboard or hire a specialist. The run will appear in Board and Context Log.'}</div>
391
+ <div class="frh-title">${hasRuns ? 'Choose the next worker' : 'Start the first real run'}</div>
392
+ <div class="frh-sub">${hasRuns ? 'Hire a specialist or queue a goal. Nexus will show the route, budget, workers, and verification here.' : 'Queue one goal from the dashboard. Nexus will route it, show who gets hired, and write the run trail into Board and Context Log.'}</div>
394
393
  </div>
395
394
  ${noticesHtml}
395
+ <div class="frh-steps" aria-label="Onboarding steps">
396
+ <div class="frh-step"><span>1</span><strong>Describe goal</strong><small>Run or hire from here.</small></div>
397
+ <div class="frh-step"><span>2</span><strong>Watch route</strong><small>Board shows workers and budget.</small></div>
398
+ <div class="frh-step"><span>3</span><strong>Verify proof</strong><small>Context Log keeps artifacts.</small></div>
399
+ </div>
396
400
  <div class="frh-command">
397
401
  <input id="frh-goal-input" class="form-input" type="text" placeholder="Inspect this repo and suggest the next fix" autocomplete="off">
398
- <button class="btn btn-primary btn-sm" id="frh-run-btn">Run goal</button>
402
+ <button class="btn btn-primary btn-sm" id="frh-run-btn">Run first goal</button>
399
403
  <button class="btn btn-sm" id="frh-context-btn">Open context</button>
400
404
  </div>
401
405
  <div class="frh-picks">
402
- ${specs.map(s => `
406
+ ${specs.length ? specs.map(s => `
403
407
  <div class="frh-pick" data-specid="${esc(s.specialistId)}" data-specname="${esc(s.name)}">
404
408
  <div class="frh-pick-name">${esc(s.name)}</div>
405
409
  <div class="frh-pick-desc">${esc((s.description||'').slice(0, 72))}${(s.description||'').length > 72 ? '…' : ''}</div>
406
410
  <div class="frh-pick-cost">~$${esc(String(s.pricing?.typical ?? '?'))}/sortie</div>
407
411
  <button class="btn btn-primary btn-sm frh-hire-btn" data-specid="${esc(s.specialistId)}" data-specname="${esc(s.name)}" ${readiness.unavailable ? 'disabled title="Synapse is not ready"' : ''}>Hire</button>
408
- </div>`).join('')}
412
+ </div>`).join('') : `
413
+ <div class="frh-pick frh-pick-loading">
414
+ <div class="frh-pick-name">Specialists loading</div>
415
+ <div class="frh-pick-desc">You can run a goal immediately. Hiring picks will appear when the catalog responds.</div>
416
+ <div class="frh-pick-cost">route first, hire second</div>
417
+ </div>`}
409
418
  </div>
410
419
  <div id="frh-status" style="display:none;margin-top:12px;font-size:var(--text-sm)"></div>
411
420
  <button class="btn btn-ghost btn-sm frh-dismiss" style="margin-top:var(--space-3)">Dismiss</button>`;
@@ -424,6 +433,7 @@ function renderFirstRunHero() {
424
433
  const result = await post('/api/orchestrate', { goal, source: 'dashboard-onboarding' });
425
434
  if (result.ok) {
426
435
  setFirstRunStatus('Run queued. Board and Context Log will update as Nexus writes artifacts.');
436
+ try { localStorage.setItem(FIRST_RUN_KEY, '1'); } catch { /* ignore */ }
427
437
  bustCache('/api/runs?limit=12');
428
438
  bustCache('/api/events');
429
439
  setTimeout(load, 900);
@@ -431,7 +441,7 @@ function renderFirstRunHero() {
431
441
  setFirstRunStatus(result.error || 'Run failed to queue.', 'bad');
432
442
  if (button) {
433
443
  button.disabled = false;
434
- button.textContent = 'Run goal';
444
+ button.textContent = 'Run first goal';
435
445
  }
436
446
  }
437
447
  });
@@ -508,6 +518,21 @@ function buildKanbanCols() {
508
518
  if (sg) cols[sg].push({id:w.id||w.workerId||w.goal,goal:w.goal||w.task||w.approach||'(worker)',status:st,tokens:w.tokensUsed||w.budget,time:w.startedAt||w.createdAt,role:w.role});
509
519
  }
510
520
  }
521
+ const ghost = S.lastDecomposition?.autoGhostPass || S.lastCompletion?.autoGhostPass || op?.orchestration?.autoGhostPass || op?.autoGhostPass;
522
+ if (ghost && (ghost.applied || ghost.policy?.reason)) {
523
+ const risks = Array.isArray(ghost.riskAreas) ? ghost.riskAreas.length : 0;
524
+ const reason = ghost.policy?.reason ? ` · ${ghost.policy.reason}` : '';
525
+ cols.ghostpass.push({
526
+ id: 'auto-ghostpass',
527
+ goal: ghost.applied
528
+ ? `Auto Ghost Pass: ${risks} risk area${risks === 1 ? '' : 's'}, ${ghost.workerApproaches || 0} approach${ghost.workerApproaches === 1 ? '' : 'es'}`
529
+ : `Auto Ghost Pass skipped${reason}`,
530
+ status: ghost.applied ? 'reviewing' : 'skipped',
531
+ tokens: ghost.estimatedTokens,
532
+ time: S.lastDecomposition?.ts || S.lastCompletion?.ts,
533
+ role: 'ghost-pass',
534
+ });
535
+ }
511
536
  for (const r of (S.runs||[]).slice(0,8)) {
512
537
  const runId = r.runId || r.id;
513
538
  if (!runId) continue;
@@ -874,11 +899,16 @@ function renderOrchestrationPipeline() {
874
899
  const more = arr.length > 6 ? ` <span style="color:var(--muted)">+${arr.length - 6}</span>` : '';
875
900
  return `<div style="margin:4px 0"><span style="color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:0.5px">${esc(label)}</span> <span style="font-family:var(--font-mono);font-size:12px">${head}${more}</span></div>`;
876
901
  };
902
+ const ghostChip = (ghost) => ghost
903
+ ? chip('ghost-pass', ghost.applied
904
+ ? `${ghost.riskAreas?.length ?? 0} risks · ${ghost.workerApproaches ?? 0} approaches`
905
+ : `skipped${ghost.policy?.reason ? ` · ${ghost.policy.reason}` : ''}`)
906
+ : '';
877
907
  const decBlock = dec ? `
878
908
  <div style="border-left:3px solid var(--accent);padding:8px 12px;margin-bottom:8px">
879
909
  <div style="font-size:13px;font-weight:600;margin-bottom:4px">Decomposition · run ${esc((dec.runId || '').slice(-8))}</div>
880
910
  <div style="font-size:12px;color:var(--muted);margin-bottom:6px">${esc(dec.goal || '')}</div>
881
- <div>${chip('intent', dec.intent || 'auto')}${chip('crew', dec.crew || 'baseline')}${chip('workers', dec.workers ?? 0)}${chip('phases', dec.phases ?? 0)}</div>
911
+ <div>${chip('intent', dec.intent || 'auto')}${chip('crew', dec.crew || 'baseline')}${chip('workers', dec.workers ?? 0)}${chip('phases', dec.phases ?? 0)}${ghostChip(dec.autoGhostPass)}</div>
882
912
  ${chipList('specialists', dec.specialists)}
883
913
  ${chipList('skills', dec.skills)}
884
914
  ${chipList('files', dec.files)}
@@ -888,7 +918,7 @@ function renderOrchestrationPipeline() {
888
918
  <div style="border-left:3px solid ${stateColor(cmpState)};padding:8px 12px">
889
919
  <div style="font-size:13px;font-weight:600;margin-bottom:4px">Completion · run ${esc((cmp.runId || '').slice(-8))} · <span style="color:${stateColor(cmpState)}">${esc(cmpState || '')}</span></div>
890
920
  <div style="font-size:12px;color:var(--muted);margin-bottom:6px">${esc(cmp.result || '')}</div>
891
- <div>${chip('verified', `${cmp.verifiedWorkers ?? 0}/${cmp.totalWorkers ?? 0}`)}${chip('saved', `${fmtNum(cmp.savedTokens ?? 0)} t`)}${chip('compression', `${cmp.compressionPct ?? 0}%`)}${chip('duration', `${Math.round((cmp.durationMs ?? 0) / 100) / 10}s`)}</div>
921
+ <div>${chip('verified', `${cmp.verifiedWorkers ?? 0}/${cmp.totalWorkers ?? 0}`)}${chip('saved', `${fmtNum(cmp.savedTokens ?? 0)} t`)}${chip('compression', `${cmp.compressionPct ?? 0}%`)}${chip('duration', `${Math.round((cmp.durationMs ?? 0) / 100) / 10}s`)}${ghostChip(cmp.autoGhostPass)}</div>
892
922
  </div>` : '';
893
923
  const spineBlock = spine ? _buildDecisionSpineMiniHtml(spine) : '';
894
924
  const headerNote = same ? '' : (dec && cmp ? '<div style="font-size:11px;color:var(--muted);margin-bottom:6px">Showing latest decomposition + most recent completion (different runs)</div>' : '');
@@ -57,10 +57,20 @@ export function render(data) {
57
57
  const synapseHealth = Array.isArray(data.synapseHealth) ? data.synapseHealth : [];
58
58
  const approvals = Array.isArray(data.synapseApprovals) ? data.synapseApprovals : [];
59
59
  const escalations = Array.isArray(data.architectsEscalations) ? data.architectsEscalations : [];
60
+ const nexusProof = data.nexusProof ?? {};
60
61
 
61
62
  container.innerHTML = `
62
63
  <div class="trust-grid">
63
64
 
65
+ <!-- Nexus Prime proof card -->
66
+ <div class="card trust-card trust-card-wide">
67
+ <div class="trust-card-hd">
68
+ <span class="trust-card-title">Nexus Prime proof</span>
69
+ <span class="chip ${nexusProof.status === 'verified' ? 'chip-ok' : nexusProof.status === 'failed' ? 'chip-bad' : 'chip-warn'}">${esc(nexusProof.status ?? 'unknown')}</span>
70
+ </div>
71
+ ${_nexusProofSection(nexusProof)}
72
+ </div>
73
+
64
74
  <!-- Security posture card -->
65
75
  <div class="card trust-card">
66
76
  <div class="trust-card-hd">
@@ -188,6 +198,37 @@ function _postureRows(gov) {
188
198
  ).join('');
189
199
  }
190
200
 
201
+ function _nexusProofSection(proof) {
202
+ const telemetry = proof.telemetry ?? {};
203
+ const totals = telemetry.localTotals ?? {};
204
+ const checks = Array.isArray(proof.checks) ? proof.checks : [];
205
+ const events = Array.isArray(proof.proofEvents) ? proof.proofEvents : [];
206
+ return `
207
+ <div class="trust-posture-body">
208
+ <div class="trust-row"><span class="trust-row-k">Website</span><span class="trust-row-v">${esc(proof.website ?? 'https://nexus-prime.cfd/')}</span></div>
209
+ <div class="trust-row"><span class="trust-row-k">Checks</span><span class="trust-row-v">${esc(`${proof.passed ?? 0} passed · ${proof.warnings ?? 0} warning(s) · ${proof.failed ?? 0} failed`)}</span></div>
210
+ <div class="trust-row"><span class="trust-row-k">Telemetry</span><span class="trust-row-v">${telemetry.optedIn ? 'opted in' : 'off'} · ${telemetry.endpointConfigured ? 'endpoint ready' : 'local only'}</span></div>
211
+ <div class="trust-row"><span class="trust-row-k">Proof events</span><span class="trust-row-v">${esc(`${totals.prPresence ?? 0} PR · ${totals.commitAttributions ?? 0} commit · ${totals.documentsSigned ?? 0} doc · ${totals.releasesVerified ?? 0} release`)}</span></div>
212
+ </div>
213
+ <div class="trust-event-list" style="margin-top:10px">
214
+ ${checks.slice(0, 6).map(check => _proofCheckRow(check)).join('')}
215
+ </div>
216
+ <div class="empty-sub" style="margin-top:8px">${esc(events.slice(0, 6).join(' · '))}</div>
217
+ `;
218
+ }
219
+
220
+ function _proofCheckRow(check) {
221
+ const chip = check.status === 'pass' ? 'chip-ok' : check.status === 'fail' ? 'chip-bad' : 'chip-warn';
222
+ return `
223
+ <div class="trust-event-row">
224
+ <div class="trust-event-main">
225
+ <span class="chip ${chip}">${esc(check.status ?? 'unknown')}</span>
226
+ <span class="trust-event-type">${esc(check.label ?? check.id ?? 'proof check')}</span>
227
+ ${check.detail ? `<span style="color:var(--text-muted);font-size:var(--text-sm)">${esc(String(check.detail).slice(0, 110))}</span>` : ''}
228
+ </div>
229
+ </div>`;
230
+ }
231
+
191
232
  function _auditRow(e, idx) {
192
233
  return `
193
234
  <div class="trust-event-row">
@@ -1,4 +1,6 @@
1
1
  import { getSharedGovernor } from '../../engines/machine-efficiency/index.js';
2
+ import { verifyNexusProof } from '../../engines/nexus-proof.js';
3
+ import { getSharedTelemetry } from '../../engines/telemetry-remote.js';
2
4
  import { serializeMemoryAudit, serializeMemoryQuarantine } from '../serializers/memory-serializer.js';
3
5
  import { collectDashboardBaseState } from './summary-selector.js';
4
6
  export async function buildTrustSurface(ctx, url) {
@@ -7,6 +9,8 @@ export async function buildTrustSurface(ctx, url) {
7
9
  const governorState = governor.getState();
8
10
  const synapseTeams = ctx.getSynapse()?.getStrikeTeamStatus?.();
9
11
  const synapseHealth = ctx.getSynapse()?.getOperativeHealth?.();
12
+ const telemetryStats = getSharedTelemetry().getStats();
13
+ const proofSummary = await verifyNexusProof({ repoRoot: ctx.repoRoot });
10
14
  return {
11
15
  repoIdentity: state.snapshot?.repoIdentity ?? ctx.getSelectedRepoIdentity(url),
12
16
  usage: state.usage,
@@ -29,6 +33,22 @@ export async function buildTrustSurface(ctx, url) {
29
33
  : ctx.getClientRegistry()?.listClients(ctx.getAdapters()) ?? [],
30
34
  primaryClient: state.snapshot?.clients?.primary ?? ctx.getClientRegistry()?.getPrimaryClient(ctx.getAdapters()) ?? null,
31
35
  nexusLayer: state.layer?.getSummary(state.snapshot?.orchestration?.sessionId) ?? null,
36
+ nexusProof: {
37
+ ...proofSummary,
38
+ telemetry: {
39
+ optedIn: telemetryStats.optedIn,
40
+ queuedEvents: telemetryStats.queuedEvents,
41
+ endpointConfigured: telemetryStats.endpointConfigured,
42
+ remoteStatsConfigured: telemetryStats.remoteStatsConfigured,
43
+ localTotals: {
44
+ prPresence: telemetryStats.totalPrPresence,
45
+ commitAttributions: telemetryStats.totalCommitAttributions,
46
+ documentsSigned: telemetryStats.totalDocumentsSigned,
47
+ releasesVerified: telemetryStats.totalReleasesVerified,
48
+ proofBadgeViews: telemetryStats.totalProofBadgeViews,
49
+ },
50
+ },
51
+ },
32
52
  machinePressure: governorState.pressureLevel,
33
53
  activeWorktrees: governorState.activeWorktrees,
34
54
  governor: governorState,
@@ -268,6 +268,7 @@ export interface TrustSurfaceDTO {
268
268
  clients: unknown[];
269
269
  primaryClient: unknown;
270
270
  nexusLayer: unknown;
271
+ nexusProof: unknown;
271
272
  machinePressure: PressureLevel;
272
273
  activeWorktrees: number;
273
274
  governor: GovernorState;
@@ -93,6 +93,16 @@ export interface NexusEventPayloads {
93
93
  files: string[];
94
94
  workers: number;
95
95
  phases: number;
96
+ autoGhostPass?: {
97
+ applied: boolean;
98
+ riskAreas: string[];
99
+ workerApproaches: number;
100
+ estimatedTokens: number;
101
+ policy?: {
102
+ enabled?: boolean;
103
+ reason?: string;
104
+ };
105
+ };
96
106
  };
97
107
  'orchestration.completed': {
98
108
  runId: string;
@@ -104,6 +114,12 @@ export interface NexusEventPayloads {
104
114
  compressionPct: number;
105
115
  durationMs: number;
106
116
  result: string;
117
+ autoGhostPass?: {
118
+ applied: boolean;
119
+ riskAreas: string[];
120
+ workerApproaches: number;
121
+ estimatedTokens: number;
122
+ };
107
123
  };
108
124
  'session.summaryBootstrap': {
109
125
  originalTokens: number;
@@ -1,3 +1,4 @@
1
+ import { type RemoteTelemetry } from './telemetry-remote.js';
1
2
  export interface GithubBridgeDetection {
2
3
  available: boolean;
3
4
  method: 'gh-cli' | 'token' | 'none';
@@ -21,7 +22,8 @@ export interface GithubPromotionResult {
21
22
  }
22
23
  export declare class GithubBridge {
23
24
  private readonly defaultCwd;
24
- constructor(defaultCwd?: string);
25
+ private readonly telemetry?;
26
+ constructor(defaultCwd?: string, telemetry?: Pick<RemoteTelemetry, 'trackProductEvent'>);
25
27
  detect(cwd?: string): GithubBridgeDetection;
26
28
  promoteToPR(input: GithubPromotionInput): Promise<GithubPromotionResult>;
27
29
  private createPullRequestViaApi;
@@ -29,6 +31,7 @@ export declare class GithubBridge {
29
31
  private resolveRepo;
30
32
  private detectBaseBranch;
31
33
  private buildBranchName;
34
+ private renderCommitBody;
32
35
  private renderPrBody;
33
36
  private safeExec;
34
37
  shareAsGist(pattern: {
@@ -40,5 +43,7 @@ export declare class GithubBridge {
40
43
  localPath?: string;
41
44
  }>;
42
45
  private shellQuote;
46
+ private telemetryConsentLabel;
47
+ private trackProductEvent;
43
48
  }
44
49
  export declare function getSharedGithubBridge(cwd?: string): GithubBridge;
@@ -3,10 +3,14 @@ import * as path from 'path';
3
3
  import { execSync } from 'child_process';
4
4
  import { createHash } from 'crypto';
5
5
  import { resolveNexusStateDir } from './runtime-registry.js';
6
+ import { appendOrReplaceNexusPrPresenceBlock, buildNexusProofMetadata, ensureNexusCoauthorTrailer, NEXUS_PRIME_COAUTHOR_TRAILER, NEXUS_PRIME_WEBSITE, renderNexusDocumentSignature, renderNexusPrPresenceBlock, } from './nexus-signature.js';
7
+ import { getSharedTelemetry } from './telemetry-remote.js';
6
8
  export class GithubBridge {
7
9
  defaultCwd;
8
- constructor(defaultCwd = process.cwd()) {
10
+ telemetry;
11
+ constructor(defaultCwd = process.cwd(), telemetry) {
9
12
  this.defaultCwd = defaultCwd;
13
+ this.telemetry = telemetry;
10
14
  }
11
15
  detect(cwd = this.defaultCwd) {
12
16
  try {
@@ -42,20 +46,34 @@ export class GithubBridge {
42
46
  this.safeExec(`git checkout -b ${this.shellQuote(branch)}`, cwd, true);
43
47
  this.safeExec('git add -A', cwd, true);
44
48
  const subject = `[NOVA] Promote Darwin cycle ${input.cycleId ?? 'candidate'} to the fleet`;
45
- const body = [
46
- 'The autonomous engine marked this bounded improvement worthy of review.',
47
- `Hypothesis: ${input.hypothesis}`,
48
- ...(input.learnings?.length ? [`Learnings: ${input.learnings.join('; ')}`] : []),
49
- ].join('\n\n');
49
+ const body = ensureNexusCoauthorTrailer(this.renderCommitBody(input), true);
50
50
  this.safeExec(`git commit -m ${this.shellQuote(subject)} -m ${this.shellQuote(body)}`, cwd, true);
51
+ this.trackProductEvent('commit_attributed', {
52
+ surface: 'git_commit',
53
+ role: 'published',
54
+ method: detection.method,
55
+ attribution: 'coauthor_trailer',
56
+ });
51
57
  this.safeExec(`git push -u origin ${this.shellQuote(branch)}`, cwd, true);
52
58
  if (detection.method === 'gh-cli') {
53
59
  const title = `Darwin: ${input.hypothesis}`.slice(0, 72);
54
60
  const prBody = this.renderPrBody(input, diffSummary, baseBranch);
55
61
  const url = this.safeExec(`gh pr create --base ${this.shellQuote(baseBranch)} --head ${this.shellQuote(branch)} --title ${this.shellQuote(title)} --body ${this.shellQuote(prBody)}`, cwd, true).trim();
62
+ this.trackProductEvent('pr_presence_added', {
63
+ surface: 'pull_request',
64
+ role: 'published',
65
+ method: detection.method,
66
+ verification: 'local_diff_captured',
67
+ });
56
68
  return { status: 'pr_created', method: detection.method, branch, url };
57
69
  }
58
70
  const url = await this.createPullRequestViaApi(repo.owner, repo.name, branch, baseBranch, input, diffSummary);
71
+ this.trackProductEvent('pr_presence_added', {
72
+ surface: 'pull_request',
73
+ role: 'published',
74
+ method: detection.method,
75
+ verification: 'local_diff_captured',
76
+ });
59
77
  return { status: 'pr_created', method: detection.method, branch, url };
60
78
  }
61
79
  catch (error) {
@@ -100,6 +118,21 @@ export class GithubBridge {
100
118
  .slice(0, 10);
101
119
  const patchPath = path.join(stateDir, `darwin-${slug}.patch`);
102
120
  const artifactPath = path.join(stateDir, `darwin-${slug}.json`);
121
+ const signatureInput = {
122
+ source: 'github-bridge',
123
+ role: 'observed',
124
+ runId: input.cycleId,
125
+ cycleId: input.cycleId,
126
+ verificationState: diffPatch.trim() ? 'advisory' : 'not-run',
127
+ hooksState: 'not-applicable',
128
+ telemetryConsent: this.telemetryConsentLabel(),
129
+ humanReviewState: 'required',
130
+ coauthorState: 'Not claimed because no GitHub PR was created.',
131
+ };
132
+ const documentSignature = renderNexusDocumentSignature({
133
+ ...signatureInput,
134
+ artifactKind: 'GitHub promotion artifact',
135
+ });
103
136
  fs.writeFileSync(patchPath, diffPatch, 'utf8');
104
137
  fs.writeFileSync(artifactPath, JSON.stringify({
105
138
  createdAt: new Date().toISOString(),
@@ -111,7 +144,20 @@ export class GithubBridge {
111
144
  learnings: input.learnings ?? [],
112
145
  diffSummary,
113
146
  patchPath,
147
+ nexusPrime: {
148
+ website: NEXUS_PRIME_WEBSITE,
149
+ coauthorTrailer: NEXUS_PRIME_COAUTHOR_TRAILER,
150
+ prPresence: renderNexusPrPresenceBlock(signatureInput),
151
+ documentSignature,
152
+ metadata: buildNexusProofMetadata(signatureInput),
153
+ },
114
154
  }, null, 2), 'utf8');
155
+ this.trackProductEvent('document_signed', {
156
+ surface: 'github_promotion_artifact',
157
+ role: 'observed',
158
+ method,
159
+ status: 'artifact_saved',
160
+ });
115
161
  return {
116
162
  status: 'artifact_saved',
117
163
  method,
@@ -140,8 +186,15 @@ export class GithubBridge {
140
186
  .slice(0, 48);
141
187
  return `ad/${seed || 'darwin-candidate'}`;
142
188
  }
143
- renderPrBody(input, diffSummary, baseBranch) {
189
+ renderCommitBody(input) {
144
190
  return [
191
+ 'The autonomous engine marked this bounded improvement worthy of review.',
192
+ `Hypothesis: ${input.hypothesis}`,
193
+ ...(input.learnings?.length ? [`Learnings: ${input.learnings.join('; ')}`] : []),
194
+ ].join('\n\n');
195
+ }
196
+ renderPrBody(input, diffSummary, baseBranch) {
197
+ const body = [
145
198
  '### Mission Briefing',
146
199
  'A bounded Darwin candidate completed local validation and now seeks human review through the standard GitHub path.',
147
200
  '',
@@ -159,6 +212,17 @@ export class GithubBridge {
159
212
  diffSummary.trim() || 'No diff summary available.',
160
213
  '```',
161
214
  ].join('\n');
215
+ return appendOrReplaceNexusPrPresenceBlock(body, {
216
+ source: 'github-bridge',
217
+ role: 'published',
218
+ runId: input.cycleId,
219
+ cycleId: input.cycleId,
220
+ verificationState: diffSummary.trim() ? 'advisory' : 'unknown',
221
+ hooksState: 'unknown',
222
+ telemetryConsent: this.telemetryConsentLabel(),
223
+ humanReviewState: 'required',
224
+ coauthorState: 'Required on the Nexus-generated promotion commit.',
225
+ });
162
226
  }
163
227
  safeExec(command, cwd, throwOnError = false) {
164
228
  try {
@@ -233,6 +297,26 @@ export class GithubBridge {
233
297
  shellQuote(value) {
234
298
  return `'${value.replace(/'/g, `'\\''`)}'`;
235
299
  }
300
+ telemetryConsentLabel() {
301
+ try {
302
+ const telemetry = this.telemetry ?? getSharedTelemetry();
303
+ return telemetry instanceof Object && 'isOptedIn' in telemetry && typeof telemetry.isOptedIn === 'function'
304
+ ? (telemetry.isOptedIn() ? 'opted-in' : 'disabled')
305
+ : 'unknown';
306
+ }
307
+ catch {
308
+ return 'unknown';
309
+ }
310
+ }
311
+ trackProductEvent(type, metadata) {
312
+ try {
313
+ const telemetry = this.telemetry ?? getSharedTelemetry();
314
+ telemetry.trackProductEvent(type, metadata);
315
+ }
316
+ catch {
317
+ // Telemetry must never block promotion or artifact persistence.
318
+ }
319
+ }
236
320
  }
237
321
  let _sharedGithubBridge = null;
238
322
  export function getSharedGithubBridge(cwd) {
@@ -0,0 +1,26 @@
1
+ export type NexusProofCheckStatus = 'pass' | 'warn' | 'fail';
2
+ export interface NexusProofCheck {
3
+ id: string;
4
+ label: string;
5
+ status: NexusProofCheckStatus;
6
+ detail: string;
7
+ evidence?: string;
8
+ }
9
+ export interface NexusProofVerifyOptions {
10
+ repoRoot?: string;
11
+ prBodyPath?: string;
12
+ commitMessagePath?: string;
13
+ artifactPaths?: string[];
14
+ }
15
+ export interface NexusProofSummary {
16
+ generatedAt: number;
17
+ website: string;
18
+ status: 'verified' | 'attention' | 'failed';
19
+ passed: number;
20
+ warnings: number;
21
+ failed: number;
22
+ checks: NexusProofCheck[];
23
+ proofEvents: readonly string[];
24
+ }
25
+ export declare function verifyNexusProof(options?: NexusProofVerifyOptions): Promise<NexusProofSummary>;
26
+ export declare function formatNexusProofReport(summary: NexusProofSummary): string;
@@ -0,0 +1,118 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import { NEXUS_PLG_EVENT_TYPES, NEXUS_PRIME_COAUTHOR_TRAILER, NEXUS_PRIME_PRESENCE_END, NEXUS_PRIME_PRESENCE_START, NEXUS_PRIME_WEBSITE, } from './nexus-signature.js';
4
+ async function readOptional(filePath) {
5
+ if (!filePath)
6
+ return null;
7
+ try {
8
+ return await fs.readFile(filePath, 'utf8');
9
+ }
10
+ catch {
11
+ return null;
12
+ }
13
+ }
14
+ function addCheck(checks, id, label, status, detail, evidence) {
15
+ checks.push({ id, label, status, detail, evidence });
16
+ }
17
+ function hasPresenceBlock(value) {
18
+ return value.includes(NEXUS_PRIME_PRESENCE_START) && value.includes(NEXUS_PRIME_PRESENCE_END);
19
+ }
20
+ export async function verifyNexusProof(options = {}) {
21
+ const repoRoot = options.repoRoot ?? process.cwd();
22
+ const checks = [];
23
+ const prTemplatePath = path.join(repoRoot, '.github', 'pull_request_template.md');
24
+ const readmePath = path.join(repoRoot, 'README.md');
25
+ const telemetryPath = path.join(repoRoot, 'src', 'engines', 'telemetry-remote.ts');
26
+ addCheck(checks, 'website.identity', 'Website identity', NEXUS_PRIME_WEBSITE === 'https://nexus-prime.cfd/' ? 'pass' : 'fail', `Expected canonical website https://nexus-prime.cfd/, got ${NEXUS_PRIME_WEBSITE}`, NEXUS_PRIME_WEBSITE);
27
+ const prTemplate = await readOptional(prTemplatePath);
28
+ if (!prTemplate) {
29
+ addCheck(checks, 'pr.template', 'PR template presence', 'warn', 'No .github/pull_request_template.md found.');
30
+ }
31
+ else {
32
+ const ok = hasPresenceBlock(prTemplate) && prTemplate.includes(NEXUS_PRIME_WEBSITE);
33
+ addCheck(checks, 'pr.template', 'PR template presence', ok ? 'pass' : 'fail', ok
34
+ ? 'Pull request template contains Nexus Prime Presence and website identity.'
35
+ : 'Pull request template must include Nexus Prime Presence markers and website identity.', prTemplatePath);
36
+ }
37
+ const readme = await readOptional(readmePath);
38
+ if (!readme) {
39
+ addCheck(checks, 'docs.provenance', 'README provenance copy', 'warn', 'No README.md found.');
40
+ }
41
+ else {
42
+ const ok = readme.includes('Provenance and social proof')
43
+ && readme.includes('Nexus Prime Presence')
44
+ && readme.includes('privacy-safe PLG events')
45
+ && readme.includes(NEXUS_PRIME_WEBSITE);
46
+ addCheck(checks, 'docs.provenance', 'README provenance copy', ok ? 'pass' : 'fail', ok
47
+ ? 'README explains Nexus Prime signatures, attribution, telemetry, and social proof.'
48
+ : 'README must explain Nexus Prime Presence, attribution, privacy-safe PLG events, and the website.', readmePath);
49
+ }
50
+ const telemetry = await readOptional(telemetryPath);
51
+ if (!telemetry) {
52
+ addCheck(checks, 'telemetry.redaction', 'Telemetry redaction guard', 'warn', 'Telemetry source was not found.');
53
+ }
54
+ else {
55
+ const redactionPattern = String.raw `prompt|content|code|path|repo|branch|secret|token|file`;
56
+ const hasRedaction = telemetry.includes(redactionPattern)
57
+ && telemetry.includes('sanitizeEventData')
58
+ && telemetry.includes('trackProductEvent');
59
+ addCheck(checks, 'telemetry.redaction', 'Telemetry redaction guard', hasRedaction ? 'pass' : 'fail', hasRedaction
60
+ ? 'Proof telemetry is routed through the sanitizer and blocks sensitive key classes.'
61
+ : 'Proof telemetry must keep using sanitizeEventData and block prompt/code/path/repo/branch/secret/token/file keys.', telemetryPath);
62
+ }
63
+ const prBody = await readOptional(options.prBodyPath);
64
+ if (options.prBodyPath) {
65
+ const ok = Boolean(prBody && hasPresenceBlock(prBody) && prBody.includes(NEXUS_PRIME_WEBSITE));
66
+ addCheck(checks, 'pr.body', 'PR body proof', ok ? 'pass' : 'fail', ok ? 'PR body contains Nexus Prime Presence.' : 'PR body is missing Nexus Prime Presence.', options.prBodyPath);
67
+ }
68
+ else {
69
+ addCheck(checks, 'pr.body', 'PR body proof', 'warn', 'No PR body path supplied; skipping generated PR body verification.');
70
+ }
71
+ const commitMessage = await readOptional(options.commitMessagePath);
72
+ if (options.commitMessagePath) {
73
+ const ok = Boolean(commitMessage && commitMessage.includes(NEXUS_PRIME_COAUTHOR_TRAILER));
74
+ addCheck(checks, 'commit.coauthor', 'Generated commit co-author trailer', ok ? 'pass' : 'fail', ok ? 'Commit message contains the Nexus Prime co-author trailer.' : 'Generated commit message is missing the Nexus Prime co-author trailer.', options.commitMessagePath);
75
+ }
76
+ else {
77
+ addCheck(checks, 'commit.coauthor', 'Generated commit co-author trailer', 'warn', 'No commit message path supplied; skipping generated commit verification.');
78
+ }
79
+ const artifactPaths = options.artifactPaths ?? [];
80
+ if (artifactPaths.length === 0) {
81
+ addCheck(checks, 'artifact.signature', 'Generated artifact signatures', 'warn', 'No artifact paths supplied; skipping artifact signature verification.');
82
+ }
83
+ else {
84
+ for (const artifactPath of artifactPaths) {
85
+ const artifact = await readOptional(artifactPath);
86
+ const ok = Boolean(artifact && artifact.includes('signed by Nexus Prime') && artifact.includes(NEXUS_PRIME_WEBSITE));
87
+ addCheck(checks, `artifact.signature:${path.basename(artifactPath)}`, 'Generated artifact signature', ok ? 'pass' : 'fail', ok ? 'Artifact contains a Nexus Prime document signature.' : 'Artifact is missing a Nexus Prime document signature.', artifactPath);
88
+ }
89
+ }
90
+ const passed = checks.filter((check) => check.status === 'pass').length;
91
+ const warnings = checks.filter((check) => check.status === 'warn').length;
92
+ const failed = checks.filter((check) => check.status === 'fail').length;
93
+ const status = failed > 0 ? 'failed' : warnings > 0 ? 'attention' : 'verified';
94
+ return {
95
+ generatedAt: Date.now(),
96
+ website: NEXUS_PRIME_WEBSITE,
97
+ status,
98
+ passed,
99
+ warnings,
100
+ failed,
101
+ checks,
102
+ proofEvents: NEXUS_PLG_EVENT_TYPES,
103
+ };
104
+ }
105
+ export function formatNexusProofReport(summary) {
106
+ const lines = [
107
+ 'Nexus Prime proof verification',
108
+ `Website: ${summary.website}`,
109
+ `Status: ${summary.status}`,
110
+ `Checks: ${summary.passed} passed, ${summary.warnings} warning(s), ${summary.failed} failed`,
111
+ '',
112
+ ];
113
+ for (const check of summary.checks) {
114
+ const marker = check.status === 'pass' ? 'PASS' : check.status === 'warn' ? 'WARN' : 'FAIL';
115
+ lines.push(`[${marker}] ${check.label}: ${check.detail}`);
116
+ }
117
+ return lines.join('\n');
118
+ }
@@ -0,0 +1,33 @@
1
+ export declare const NEXUS_PRIME_WEBSITE = "https://nexus-prime.cfd/";
2
+ export declare const NEXUS_PRIME_GENERATOR = "Nexus Prime";
3
+ export declare const NEXUS_PRIME_COAUTHOR_TRAILER = "Co-Authored-By: nexus-prime <33547839+sir-ad@users.noreply.github.com>";
4
+ export declare const NEXUS_PRIME_PRESENCE_START = "<!-- nexus-prime:presence:start -->";
5
+ export declare const NEXUS_PRIME_PRESENCE_END = "<!-- nexus-prime:presence:end -->";
6
+ export type NexusPresenceRole = 'observed' | 'verified' | 'assisted' | 'authored' | 'published';
7
+ export type NexusVerificationState = 'unknown' | 'not-run' | 'advisory' | 'verified' | 'failed';
8
+ export type NexusHumanReviewState = 'required' | 'pending' | 'completed' | 'not-required';
9
+ export type NexusPlgEventType = 'pr_presence_added' | 'commit_attributed' | 'document_signed' | 'release_verified' | 'proof_badge_viewed' | 'website_proof_viewed' | 'telemetry_batch_sent';
10
+ export declare const NEXUS_PLG_EVENT_TYPES: readonly NexusPlgEventType[];
11
+ export interface NexusPresenceInput {
12
+ role: NexusPresenceRole;
13
+ source: string;
14
+ runId?: string;
15
+ cycleId?: string;
16
+ verificationState?: NexusVerificationState | string;
17
+ hooksState?: string;
18
+ telemetryConsent?: string;
19
+ humanReviewState?: NexusHumanReviewState | string;
20
+ coauthorState?: string;
21
+ website?: string;
22
+ generatedAt?: Date | string;
23
+ }
24
+ export interface NexusDocumentSignatureInput extends NexusPresenceInput {
25
+ artifactKind?: string;
26
+ reviewer?: string;
27
+ }
28
+ export declare function renderNexusPrPresenceBlock(input: NexusPresenceInput): string;
29
+ export declare function appendOrReplaceNexusPrPresenceBlock(body: string, input: NexusPresenceInput): string;
30
+ export declare function ensureNexusCoauthorTrailer(message: string, shouldAttribute: boolean): string;
31
+ export declare function renderNexusDocumentSignature(input: NexusDocumentSignatureInput): string;
32
+ export declare function buildNexusProofMetadata(input: NexusPresenceInput): Record<string, string>;
33
+ export declare function renderNexusWebsiteMetadata(input: NexusPresenceInput): string;
@@ -0,0 +1,127 @@
1
+ export const NEXUS_PRIME_WEBSITE = 'https://nexus-prime.cfd/';
2
+ export const NEXUS_PRIME_GENERATOR = 'Nexus Prime';
3
+ export const NEXUS_PRIME_COAUTHOR_TRAILER = 'Co-Authored-By: nexus-prime <33547839+sir-ad@users.noreply.github.com>';
4
+ export const NEXUS_PRIME_PRESENCE_START = '<!-- nexus-prime:presence:start -->';
5
+ export const NEXUS_PRIME_PRESENCE_END = '<!-- nexus-prime:presence:end -->';
6
+ export const NEXUS_PLG_EVENT_TYPES = [
7
+ 'pr_presence_added',
8
+ 'commit_attributed',
9
+ 'document_signed',
10
+ 'release_verified',
11
+ 'proof_badge_viewed',
12
+ 'website_proof_viewed',
13
+ 'telemetry_batch_sent',
14
+ ];
15
+ function clean(value, fallback) {
16
+ const normalized = String(value ?? '').trim();
17
+ return normalized || fallback;
18
+ }
19
+ function isoStamp(value) {
20
+ if (value instanceof Date)
21
+ return value.toISOString();
22
+ if (typeof value === 'string' && value.trim())
23
+ return value.trim();
24
+ return new Date().toISOString();
25
+ }
26
+ export function renderNexusPrPresenceBlock(input) {
27
+ const website = clean(input.website, NEXUS_PRIME_WEBSITE);
28
+ const runId = clean(input.runId ?? input.cycleId, 'no-run detected');
29
+ const verification = clean(input.verificationState, 'unknown');
30
+ const hooks = clean(input.hooksState, 'unknown');
31
+ const telemetry = clean(input.telemetryConsent, 'unknown');
32
+ const humanReview = clean(input.humanReviewState, 'required');
33
+ const coauthor = clean(input.coauthorState, 'Not claimed unless a Nexus-generated commit includes the co-author trailer.');
34
+ return [
35
+ NEXUS_PRIME_PRESENCE_START,
36
+ '## Nexus Prime Presence',
37
+ '',
38
+ `- Website: ${website}`,
39
+ `- Role: ${input.role}`,
40
+ `- Source: ${clean(input.source, 'unknown')}`,
41
+ `- Run ID: ${runId}`,
42
+ `- Verification: ${verification}`,
43
+ `- Hooks: ${hooks}`,
44
+ `- Telemetry consent: ${telemetry}`,
45
+ `- Human review: ${humanReview}`,
46
+ `- Co-authorship: ${coauthor}`,
47
+ `- Generated at: ${isoStamp(input.generatedAt)}`,
48
+ '',
49
+ 'Presence is not blanket authorship. Git co-authorship is only asserted for commits Nexus Prime generated, materially assisted, or published.',
50
+ NEXUS_PRIME_PRESENCE_END,
51
+ ].join('\n');
52
+ }
53
+ export function appendOrReplaceNexusPrPresenceBlock(body, input) {
54
+ const block = renderNexusPrPresenceBlock(input);
55
+ const pattern = new RegExp(`${escapeRegExp(NEXUS_PRIME_PRESENCE_START)}[\\s\\S]*?${escapeRegExp(NEXUS_PRIME_PRESENCE_END)}`, 'm');
56
+ const existing = String(body ?? '').trim();
57
+ if (pattern.test(existing))
58
+ return existing.replace(pattern, block);
59
+ return [existing, block].filter(Boolean).join('\n\n');
60
+ }
61
+ export function ensureNexusCoauthorTrailer(message, shouldAttribute) {
62
+ const normalized = String(message ?? '').trimEnd();
63
+ if (!shouldAttribute)
64
+ return normalized;
65
+ if (normalized.includes(NEXUS_PRIME_COAUTHOR_TRAILER))
66
+ return normalized;
67
+ return [normalized, NEXUS_PRIME_COAUTHOR_TRAILER].filter(Boolean).join('\n\n');
68
+ }
69
+ export function renderNexusDocumentSignature(input) {
70
+ return [
71
+ '---',
72
+ `${clean(input.artifactKind, 'Artifact')} signed by ${NEXUS_PRIME_GENERATOR}`,
73
+ `Website: ${clean(input.website, NEXUS_PRIME_WEBSITE)}`,
74
+ `Role: ${input.role}`,
75
+ `Source: ${clean(input.source, 'unknown')}`,
76
+ `Run ID: ${clean(input.runId ?? input.cycleId, 'no-run detected')}`,
77
+ `Verification: ${clean(input.verificationState, 'unknown')}`,
78
+ `Human review: ${clean(input.humanReviewState, 'required')}`,
79
+ `Reviewer: ${clean(input.reviewer, 'not recorded')}`,
80
+ `Generated at: ${isoStamp(input.generatedAt)}`,
81
+ '---',
82
+ ].join('\n');
83
+ }
84
+ export function buildNexusProofMetadata(input) {
85
+ return {
86
+ generator: NEXUS_PRIME_GENERATOR,
87
+ website: clean(input.website, NEXUS_PRIME_WEBSITE),
88
+ role: input.role,
89
+ source: clean(input.source, 'unknown'),
90
+ runId: clean(input.runId ?? input.cycleId, 'no-run detected'),
91
+ verificationState: clean(input.verificationState, 'unknown'),
92
+ humanReviewState: clean(input.humanReviewState, 'required'),
93
+ generatedAt: isoStamp(input.generatedAt),
94
+ };
95
+ }
96
+ export function renderNexusWebsiteMetadata(input) {
97
+ const metadata = buildNexusProofMetadata(input);
98
+ const jsonLd = {
99
+ '@context': 'https://schema.org',
100
+ '@type': 'SoftwareApplication',
101
+ name: NEXUS_PRIME_GENERATOR,
102
+ url: metadata.website,
103
+ applicationCategory: 'DeveloperApplication',
104
+ creator: {
105
+ '@type': 'Organization',
106
+ name: NEXUS_PRIME_GENERATOR,
107
+ url: metadata.website,
108
+ },
109
+ };
110
+ return [
111
+ '<meta name="generator" content="Nexus Prime">',
112
+ `<meta name="nexus-prime:role" content="${escapeHtml(metadata.role)}">`,
113
+ `<meta name="nexus-prime:verification" content="${escapeHtml(metadata.verificationState)}">`,
114
+ `<link rel="author" href="${escapeHtml(metadata.website)}">`,
115
+ `<script type="application/ld+json">${JSON.stringify(jsonLd)}</script>`,
116
+ ].join('\n');
117
+ }
118
+ function escapeRegExp(value) {
119
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
120
+ }
121
+ function escapeHtml(value) {
122
+ return value
123
+ .replace(/&/g, '&amp;')
124
+ .replace(/"/g, '&quot;')
125
+ .replace(/</g, '&lt;')
126
+ .replace(/>/g, '&gt;');
127
+ }
@@ -1036,7 +1036,7 @@ export class OrchestratorEngine {
1036
1036
  // Non-fatal: bootstrap receipt is a safety net, not a hard dependency
1037
1037
  }
1038
1038
  const [army, prepared] = await this.runParallelPhases(this.induce(task), this._prepareExecution(task, options));
1039
- const { intent, phases, primaryClient, bootstrapManifest, latestDNA, memoryMatches, memoryStats, candidateFiles, knowledgeFabric, plannedFiles, planner, selections, catalogHealth, tokenBudget, workerCount, mode, taskGraph, workerPlan, autoGhostPass, crSignals, } = prepared;
1039
+ const { intent, phases, primaryClient, bootstrapManifest, latestDNA, memoryMatches, memoryStats, candidateFiles, knowledgeFabric, plannedFiles, planner, selections, catalogHealth, tokenBudget, workerCount, mode, taskGraph, workerPlan, autoGhostPass, autoGhostPassDecision, crSignals, } = prepared;
1040
1040
  this.runtime.recordClientToolCall('nexus_orchestrate', {
1041
1041
  orchestrateCalled: true,
1042
1042
  plannerCalled: true,
@@ -1314,6 +1314,8 @@ export class OrchestratorEngine {
1314
1314
  instructionPacket,
1315
1315
  executionLedger: ledger,
1316
1316
  knowledgeFabric,
1317
+ autoGhostPass,
1318
+ autoGhostPassDecision,
1317
1319
  });
1318
1320
  this.executionDedupeStore.set(fingerprint, {
1319
1321
  id: ledger.runId,
@@ -5,7 +5,8 @@
5
5
  * Sends pseudonymous install + project activity to a Supabase REST endpoint
6
6
  * only after explicit opt-in or `NEXUS_TELEMETRY=on`.
7
7
  */
8
- export type TelemetryEventType = 'install' | 'session_start' | 'session_end' | 'feature_use' | 'token_savings' | 'memory_created' | 'memory_recalled' | 'autonomy_candidate' | 'autonomy_candidate_suppressed' | 'autonomy_apply_started' | 'autonomy_apply_finished' | 'autonomy_apply_blocked';
8
+ import { type NexusPlgEventType } from './nexus-signature.js';
9
+ export type TelemetryEventType = 'install' | 'session_start' | 'session_end' | 'feature_use' | 'token_savings' | 'memory_created' | 'memory_recalled' | 'autonomy_candidate' | 'autonomy_candidate_suppressed' | 'autonomy_apply_started' | 'autonomy_apply_finished' | 'autonomy_apply_blocked' | NexusPlgEventType;
9
10
  export interface TelemetryEvent {
10
11
  type: TelemetryEventType;
11
12
  timestamp: number;
@@ -26,6 +27,11 @@ export interface TelemetryStats {
26
27
  totalFeatureUses: number;
27
28
  totalMemoriesCreated: number;
28
29
  totalMemoriesRecalled: number;
30
+ totalPrPresence: number;
31
+ totalCommitAttributions: number;
32
+ totalDocumentsSigned: number;
33
+ totalReleasesVerified: number;
34
+ totalProofBadgeViews: number;
29
35
  endpointConfigured: boolean;
30
36
  remoteStatsConfigured: boolean;
31
37
  lastFlushAt?: number;
@@ -39,6 +45,7 @@ export interface RemoteInstallDrilldown {
39
45
  memoriesRecalled: number;
40
46
  featureUses: number;
41
47
  autonomyEvents: number;
48
+ proofEvents: number;
42
49
  recentProjects: string[];
43
50
  }
44
51
  export interface RemoteTelemetryStats {
@@ -49,6 +56,11 @@ export interface RemoteTelemetryStats {
49
56
  totalTokenSavings: number;
50
57
  totalMemoriesCreated: number;
51
58
  totalMemoriesRecalled: number;
59
+ totalPrPresence: number;
60
+ totalCommitAttributions: number;
61
+ totalDocumentsSigned: number;
62
+ totalReleasesVerified: number;
63
+ totalProofBadgeViews: number;
52
64
  installs: RemoteInstallDrilldown[];
53
65
  }
54
66
  export declare class RemoteTelemetry {
@@ -86,6 +98,7 @@ export declare class RemoteTelemetry {
86
98
  trackMemoryCreated(scope: string, metadata?: Record<string, unknown>): void;
87
99
  trackMemoryRecalled(hitCount: number, metadata?: Record<string, unknown>): void;
88
100
  trackAutonomyEvent(type: Extract<TelemetryEventType, 'autonomy_candidate' | 'autonomy_candidate_suppressed' | 'autonomy_apply_started' | 'autonomy_apply_finished' | 'autonomy_apply_blocked'>, metadata?: Record<string, unknown>): void;
101
+ trackProductEvent(type: NexusPlgEventType, metadata?: Record<string, unknown>): void;
89
102
  private enqueue;
90
103
  private persistQueue;
91
104
  private loadQueue;
@@ -100,6 +113,7 @@ export declare class RemoteTelemetry {
100
113
  getStats(): TelemetryStats;
101
114
  private getNexusVersion;
102
115
  private hashIdentifier;
116
+ private incrementProductCounter;
103
117
  destroy(): void;
104
118
  }
105
119
  export declare function getSharedTelemetry(options?: {
@@ -10,6 +10,7 @@ import * as path from 'path';
10
10
  import * as os from 'os';
11
11
  import * as crypto from 'crypto';
12
12
  import { fileURLToPath } from 'url';
13
+ import { NEXUS_PLG_EVENT_TYPES } from './nexus-signature.js';
13
14
  const __filename = fileURLToPath(import.meta.url);
14
15
  const __dirname = path.dirname(__filename);
15
16
  const NEXUS_STATE_DIR = path.join(os.homedir(), '.nexus-prime');
@@ -68,6 +69,11 @@ function createEmptyState() {
68
69
  totalFeatureUses: 0,
69
70
  totalMemoriesCreated: 0,
70
71
  totalMemoriesRecalled: 0,
72
+ totalPrPresence: 0,
73
+ totalCommitAttributions: 0,
74
+ totalDocumentsSigned: 0,
75
+ totalReleasesVerified: 0,
76
+ totalProofBadgeViews: 0,
71
77
  };
72
78
  }
73
79
  export class RemoteTelemetry {
@@ -267,6 +273,19 @@ export class RemoteTelemetry {
267
273
  data: sanitizeEventData(metadata ?? {}),
268
274
  });
269
275
  }
276
+ trackProductEvent(type, metadata) {
277
+ this.incrementProductCounter(type);
278
+ this.persistState();
279
+ this.enqueue({
280
+ type,
281
+ timestamp: Date.now(),
282
+ installId: this.installId,
283
+ data: sanitizeEventData({
284
+ eventFamily: 'nexus_prime_proof',
285
+ ...metadata,
286
+ }),
287
+ });
288
+ }
270
289
  enqueue(event) {
271
290
  if (!this.isOptedIn())
272
291
  return;
@@ -381,6 +400,11 @@ export class RemoteTelemetry {
381
400
  totalTokenSavings: 0,
382
401
  totalMemoriesCreated: 0,
383
402
  totalMemoriesRecalled: 0,
403
+ totalPrPresence: 0,
404
+ totalCommitAttributions: 0,
405
+ totalDocumentsSigned: 0,
406
+ totalReleasesVerified: 0,
407
+ totalProofBadgeViews: 0,
384
408
  installs: [],
385
409
  };
386
410
  }
@@ -406,6 +430,11 @@ export class RemoteTelemetry {
406
430
  let totalTokenSavings = 0;
407
431
  let totalMemoriesCreated = 0;
408
432
  let totalMemoriesRecalled = 0;
433
+ let totalPrPresence = 0;
434
+ let totalCommitAttributions = 0;
435
+ let totalDocumentsSigned = 0;
436
+ let totalReleasesVerified = 0;
437
+ let totalProofBadgeViews = 0;
409
438
  const activeCutoff = Date.now() - ACTIVE_INSTALL_WINDOW_MS;
410
439
  for (const row of rows) {
411
440
  const installId = String(row.install_id ?? '').trim();
@@ -425,6 +454,7 @@ export class RemoteTelemetry {
425
454
  memoriesRecalled: 0,
426
455
  featureUses: 0,
427
456
  autonomyEvents: 0,
457
+ proofEvents: 0,
428
458
  recentProjects: [],
429
459
  };
430
460
  if (!bucket.lastSeenAt || (sentAt && Date.parse(bucket.lastSeenAt) < sentAtMs)) {
@@ -459,6 +489,30 @@ export class RemoteTelemetry {
459
489
  case 'feature_use':
460
490
  bucket.featureUses += 1;
461
491
  break;
492
+ case 'pr_presence_added':
493
+ totalPrPresence += 1;
494
+ bucket.proofEvents += 1;
495
+ break;
496
+ case 'commit_attributed':
497
+ totalCommitAttributions += 1;
498
+ bucket.proofEvents += 1;
499
+ break;
500
+ case 'document_signed':
501
+ totalDocumentsSigned += 1;
502
+ bucket.proofEvents += 1;
503
+ break;
504
+ case 'release_verified':
505
+ totalReleasesVerified += 1;
506
+ bucket.proofEvents += 1;
507
+ break;
508
+ case 'proof_badge_viewed':
509
+ case 'website_proof_viewed':
510
+ totalProofBadgeViews += 1;
511
+ bucket.proofEvents += 1;
512
+ break;
513
+ case 'telemetry_batch_sent':
514
+ bucket.proofEvents += 1;
515
+ break;
462
516
  case 'autonomy_candidate':
463
517
  case 'autonomy_candidate_suppressed':
464
518
  case 'autonomy_apply_started':
@@ -479,6 +533,11 @@ export class RemoteTelemetry {
479
533
  totalTokenSavings,
480
534
  totalMemoriesCreated,
481
535
  totalMemoriesRecalled,
536
+ totalPrPresence,
537
+ totalCommitAttributions,
538
+ totalDocumentsSigned,
539
+ totalReleasesVerified,
540
+ totalProofBadgeViews,
482
541
  installs: [...installs.values()]
483
542
  .sort((a, b) => (b.tokenSavings - a.tokenSavings) || (b.sessions - a.sessions))
484
543
  .slice(0, 25),
@@ -493,6 +552,11 @@ export class RemoteTelemetry {
493
552
  totalTokenSavings: 0,
494
553
  totalMemoriesCreated: 0,
495
554
  totalMemoriesRecalled: 0,
555
+ totalPrPresence: 0,
556
+ totalCommitAttributions: 0,
557
+ totalDocumentsSigned: 0,
558
+ totalReleasesVerified: 0,
559
+ totalProofBadgeViews: 0,
496
560
  installs: [],
497
561
  };
498
562
  }
@@ -519,6 +583,11 @@ export class RemoteTelemetry {
519
583
  totalFeatureUses: this.state.totalFeatureUses,
520
584
  totalMemoriesCreated: this.state.totalMemoriesCreated,
521
585
  totalMemoriesRecalled: this.state.totalMemoriesRecalled,
586
+ totalPrPresence: this.state.totalPrPresence,
587
+ totalCommitAttributions: this.state.totalCommitAttributions,
588
+ totalDocumentsSigned: this.state.totalDocumentsSigned,
589
+ totalReleasesVerified: this.state.totalReleasesVerified,
590
+ totalProofBadgeViews: this.state.totalProofBadgeViews,
522
591
  endpointConfigured: Boolean(this.endpoint && this.apiKey),
523
592
  remoteStatsConfigured: Boolean(this.endpoint && process.env.NEXUS_TELEMETRY_SERVICE_KEY),
524
593
  lastFlushAt: this.state.lastFlushAt,
@@ -537,6 +606,30 @@ export class RemoteTelemetry {
537
606
  hashIdentifier(value) {
538
607
  return crypto.createHash('sha256').update(String(value)).digest('hex').slice(0, 12);
539
608
  }
609
+ incrementProductCounter(type) {
610
+ if (!NEXUS_PLG_EVENT_TYPES.includes(type))
611
+ return;
612
+ switch (type) {
613
+ case 'pr_presence_added':
614
+ this.state.totalPrPresence += 1;
615
+ break;
616
+ case 'commit_attributed':
617
+ this.state.totalCommitAttributions += 1;
618
+ break;
619
+ case 'document_signed':
620
+ this.state.totalDocumentsSigned += 1;
621
+ break;
622
+ case 'release_verified':
623
+ this.state.totalReleasesVerified += 1;
624
+ break;
625
+ case 'proof_badge_viewed':
626
+ case 'website_proof_viewed':
627
+ this.state.totalProofBadgeViews += 1;
628
+ break;
629
+ case 'telemetry_batch_sent':
630
+ break;
631
+ }
632
+ }
540
633
  destroy() {
541
634
  if (this.flushTimer) {
542
635
  clearInterval(this.flushTimer);
package/dist/index.d.ts CHANGED
@@ -289,3 +289,7 @@ export { SessionDNAManager } from './engines/session-dna.js';
289
289
  export type { SessionDNA } from './engines/session-dna.js';
290
290
  export { GithubBridge, getSharedGithubBridge } from './engines/github-bridge.js';
291
291
  export type { GithubPromotionInput, GithubPromotionResult } from './engines/github-bridge.js';
292
+ export { appendOrReplaceNexusPrPresenceBlock, buildNexusProofMetadata, ensureNexusCoauthorTrailer, NEXUS_PLG_EVENT_TYPES, NEXUS_PRIME_COAUTHOR_TRAILER, NEXUS_PRIME_GENERATOR, NEXUS_PRIME_WEBSITE, renderNexusDocumentSignature, renderNexusPrPresenceBlock, renderNexusWebsiteMetadata, } from './engines/nexus-signature.js';
293
+ export type { NexusDocumentSignatureInput, NexusHumanReviewState, NexusPlgEventType, NexusPresenceInput, NexusPresenceRole, NexusVerificationState, } from './engines/nexus-signature.js';
294
+ export { formatNexusProofReport, verifyNexusProof, } from './engines/nexus-proof.js';
295
+ export type { NexusProofCheck, NexusProofCheckStatus, NexusProofSummary, NexusProofVerifyOptions, } from './engines/nexus-proof.js';
package/dist/index.js CHANGED
@@ -1211,3 +1211,5 @@ export { GhostPass, PhantomOrchestrator, PhantomWorker } from './phantom/index.j
1211
1211
  export { MemoryEngine, createMemoryEngine } from './engines/memory.js';
1212
1212
  export { SessionDNAManager } from './engines/session-dna.js';
1213
1213
  export { GithubBridge, getSharedGithubBridge } from './engines/github-bridge.js';
1214
+ export { appendOrReplaceNexusPrPresenceBlock, buildNexusProofMetadata, ensureNexusCoauthorTrailer, NEXUS_PLG_EVENT_TYPES, NEXUS_PRIME_COAUTHOR_TRAILER, NEXUS_PRIME_GENERATOR, NEXUS_PRIME_WEBSITE, renderNexusDocumentSignature, renderNexusPrPresenceBlock, renderNexusWebsiteMetadata, } from './engines/nexus-signature.js';
1215
+ export { formatNexusProofReport, verifyNexusProof, } from './engines/nexus-proof.js';
@@ -24,6 +24,10 @@ export function getNexusHookSpec() {
24
24
  matcher: 'Edit|Write|MultiEdit',
25
25
  hooks: [{ type: 'command', command: 'nexus-prime hook mindkit', timeout: 10 }],
26
26
  },
27
+ {
28
+ matcher: 'MultiEdit',
29
+ hooks: [{ type: 'command', command: 'nexus-prime hook ghost-pass', timeout: 15 }],
30
+ },
27
31
  ],
28
32
  PostToolUse: [
29
33
  {
@@ -101,6 +101,12 @@ export interface ExecutionTask {
101
101
  instructionPacket?: InstructionPacket;
102
102
  executionLedger?: ExecutionLedger;
103
103
  knowledgeFabric?: KnowledgeFabricBundle;
104
+ autoGhostPass?: GhostReport;
105
+ autoGhostPassDecision?: {
106
+ enabled: boolean;
107
+ reason: string;
108
+ contextHash?: string;
109
+ };
104
110
  }
105
111
  export interface WorkerSkillOverlay {
106
112
  base: string[];
@@ -225,6 +225,16 @@ export class SubAgentRuntime {
225
225
  files: (task.files ?? []).slice(0, 24),
226
226
  workers: planner.plannerState.selectedSpecialists.length || 1,
227
227
  phases: planner.plannerState.ledger.length,
228
+ autoGhostPass: {
229
+ applied: Boolean(task.autoGhostPass),
230
+ riskAreas: task.autoGhostPass?.riskAreas ?? [],
231
+ workerApproaches: task.autoGhostPass?.workerAssignments?.length ?? 0,
232
+ estimatedTokens: task.autoGhostPass?.totalEstimatedTokens ?? 0,
233
+ policy: task.autoGhostPassDecision ? {
234
+ enabled: task.autoGhostPassDecision.enabled,
235
+ reason: task.autoGhostPassDecision.reason,
236
+ } : undefined,
237
+ },
228
238
  });
229
239
  }
230
240
  catch { /* best-effort */ }
@@ -765,6 +775,12 @@ export class SubAgentRuntime {
765
775
  compressionPct: Number(tt?.compressionPct ?? 0),
766
776
  durationMs: Date.now() - runStartedAt,
767
777
  result: String(applied.summary ?? '').slice(0, 280),
778
+ autoGhostPass: {
779
+ applied: Boolean(task.autoGhostPass),
780
+ riskAreas: task.autoGhostPass?.riskAreas ?? [],
781
+ workerApproaches: task.autoGhostPass?.workerAssignments?.length ?? 0,
782
+ estimatedTokens: task.autoGhostPass?.totalEstimatedTokens ?? 0,
783
+ },
768
784
  });
769
785
  }
770
786
  catch { /* best-effort */ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexus-prime",
3
- "version": "7.9.25",
3
+ "version": "7.9.27",
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",