@neurcode-ai/cli 0.14.0 → 0.15.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 (188) hide show
  1. package/README.md +60 -8
  2. package/dist/api-client.d.ts +284 -0
  3. package/dist/api-client.d.ts.map +1 -1
  4. package/dist/api-client.js +111 -0
  5. package/dist/api-client.js.map +1 -1
  6. package/dist/commands/activate.d.ts +82 -0
  7. package/dist/commands/activate.d.ts.map +1 -0
  8. package/dist/commands/activate.js +551 -0
  9. package/dist/commands/activate.js.map +1 -0
  10. package/dist/commands/admission.d.ts +67 -0
  11. package/dist/commands/admission.d.ts.map +1 -0
  12. package/dist/commands/admission.js +350 -0
  13. package/dist/commands/admission.js.map +1 -0
  14. package/dist/commands/agent.d.ts +3 -0
  15. package/dist/commands/agent.d.ts.map +1 -0
  16. package/dist/commands/agent.js +2045 -0
  17. package/dist/commands/agent.js.map +1 -0
  18. package/dist/commands/demo.d.ts +3 -0
  19. package/dist/commands/demo.d.ts.map +1 -0
  20. package/dist/commands/demo.js +102 -0
  21. package/dist/commands/demo.js.map +1 -0
  22. package/dist/commands/init.d.ts.map +1 -1
  23. package/dist/commands/init.js +58 -44
  24. package/dist/commands/init.js.map +1 -1
  25. package/dist/commands/login.d.ts +1 -1
  26. package/dist/commands/login.d.ts.map +1 -1
  27. package/dist/commands/login.js +44 -22
  28. package/dist/commands/login.js.map +1 -1
  29. package/dist/commands/profile.d.ts +14 -0
  30. package/dist/commands/profile.d.ts.map +1 -0
  31. package/dist/commands/profile.js +118 -0
  32. package/dist/commands/profile.js.map +1 -0
  33. package/dist/commands/quickstart.d.ts +2 -2
  34. package/dist/commands/quickstart.d.ts.map +1 -1
  35. package/dist/commands/quickstart.js +31 -30
  36. package/dist/commands/quickstart.js.map +1 -1
  37. package/dist/commands/remediate-export.d.ts +6 -1
  38. package/dist/commands/remediate-export.d.ts.map +1 -1
  39. package/dist/commands/remediate-export.js +359 -7
  40. package/dist/commands/remediate-export.js.map +1 -1
  41. package/dist/commands/replay.d.ts.map +1 -1
  42. package/dist/commands/replay.js +84 -0
  43. package/dist/commands/replay.js.map +1 -1
  44. package/dist/commands/run.d.ts +3 -0
  45. package/dist/commands/run.d.ts.map +1 -0
  46. package/dist/commands/run.js +98 -0
  47. package/dist/commands/run.js.map +1 -0
  48. package/dist/commands/runtime-adapter.d.ts +8 -0
  49. package/dist/commands/runtime-adapter.d.ts.map +1 -0
  50. package/dist/commands/runtime-adapter.js +375 -0
  51. package/dist/commands/runtime-adapter.js.map +1 -0
  52. package/dist/commands/runtime-doctor.d.ts +6 -0
  53. package/dist/commands/runtime-doctor.d.ts.map +1 -0
  54. package/dist/commands/runtime-doctor.js +478 -0
  55. package/dist/commands/runtime-doctor.js.map +1 -0
  56. package/dist/commands/runtime-report.d.ts +13 -0
  57. package/dist/commands/runtime-report.d.ts.map +1 -0
  58. package/dist/commands/runtime-report.js +81 -0
  59. package/dist/commands/runtime-report.js.map +1 -0
  60. package/dist/commands/runtime-sync.d.ts +17 -0
  61. package/dist/commands/runtime-sync.d.ts.map +1 -0
  62. package/dist/commands/runtime-sync.js +656 -0
  63. package/dist/commands/runtime-sync.js.map +1 -0
  64. package/dist/commands/runtime.d.ts +16 -0
  65. package/dist/commands/runtime.d.ts.map +1 -0
  66. package/dist/commands/runtime.js +380 -0
  67. package/dist/commands/runtime.js.map +1 -0
  68. package/dist/commands/session-hook.d.ts +35 -0
  69. package/dist/commands/session-hook.d.ts.map +1 -0
  70. package/dist/commands/session-hook.js +1297 -0
  71. package/dist/commands/session-hook.js.map +1 -0
  72. package/dist/commands/session.d.ts +91 -0
  73. package/dist/commands/session.d.ts.map +1 -1
  74. package/dist/commands/session.js +1226 -0
  75. package/dist/commands/session.js.map +1 -1
  76. package/dist/commands/whoami.d.ts +7 -4
  77. package/dist/commands/whoami.d.ts.map +1 -1
  78. package/dist/commands/whoami.js +59 -34
  79. package/dist/commands/whoami.js.map +1 -1
  80. package/dist/config.d.ts.map +1 -1
  81. package/dist/config.js +24 -5
  82. package/dist/config.js.map +1 -1
  83. package/dist/daemon/routes.d.ts.map +1 -1
  84. package/dist/daemon/routes.js +8 -0
  85. package/dist/daemon/routes.js.map +1 -1
  86. package/dist/daemon/server.d.ts.map +1 -1
  87. package/dist/daemon/server.js +88 -0
  88. package/dist/daemon/server.js.map +1 -1
  89. package/dist/governance/impact-analysis.d.ts +27 -0
  90. package/dist/governance/impact-analysis.d.ts.map +1 -0
  91. package/dist/governance/impact-analysis.js +274 -0
  92. package/dist/governance/impact-analysis.js.map +1 -0
  93. package/dist/index.js +472 -29
  94. package/dist/index.js.map +1 -1
  95. package/dist/intent-engine/matcher.d.ts.map +1 -1
  96. package/dist/intent-engine/matcher.js +3 -12
  97. package/dist/intent-engine/matcher.js.map +1 -1
  98. package/dist/utils/admission-artifact.d.ts +59 -0
  99. package/dist/utils/admission-artifact.d.ts.map +1 -0
  100. package/dist/utils/admission-artifact.js +410 -0
  101. package/dist/utils/admission-artifact.js.map +1 -0
  102. package/dist/utils/agent-adapter-setup.d.ts +80 -0
  103. package/dist/utils/agent-adapter-setup.d.ts.map +1 -0
  104. package/dist/utils/agent-adapter-setup.js +577 -0
  105. package/dist/utils/agent-adapter-setup.js.map +1 -0
  106. package/dist/utils/agent-guard-supervisor.d.ts +75 -0
  107. package/dist/utils/agent-guard-supervisor.d.ts.map +1 -0
  108. package/dist/utils/agent-guard-supervisor.js +388 -0
  109. package/dist/utils/agent-guard-supervisor.js.map +1 -0
  110. package/dist/utils/agent-guard.d.ts +92 -0
  111. package/dist/utils/agent-guard.d.ts.map +1 -0
  112. package/dist/utils/agent-guard.js +326 -0
  113. package/dist/utils/agent-guard.js.map +1 -0
  114. package/dist/utils/agent-session-launcher.d.ts +89 -0
  115. package/dist/utils/agent-session-launcher.d.ts.map +1 -0
  116. package/dist/utils/agent-session-launcher.js +308 -0
  117. package/dist/utils/agent-session-launcher.js.map +1 -0
  118. package/dist/utils/bash-command-analysis.d.ts +19 -0
  119. package/dist/utils/bash-command-analysis.d.ts.map +1 -0
  120. package/dist/utils/bash-command-analysis.js +295 -0
  121. package/dist/utils/bash-command-analysis.js.map +1 -0
  122. package/dist/utils/consequence-nudges.d.ts +30 -0
  123. package/dist/utils/consequence-nudges.d.ts.map +1 -0
  124. package/dist/utils/consequence-nudges.js +313 -0
  125. package/dist/utils/consequence-nudges.js.map +1 -0
  126. package/dist/utils/drift-intelligence.d.ts.map +1 -1
  127. package/dist/utils/drift-intelligence.js +29 -7
  128. package/dist/utils/drift-intelligence.js.map +1 -1
  129. package/dist/utils/git-coverage.d.ts +57 -0
  130. package/dist/utils/git-coverage.d.ts.map +1 -0
  131. package/dist/utils/git-coverage.js +302 -0
  132. package/dist/utils/git-coverage.js.map +1 -0
  133. package/dist/utils/gitignore.d.ts.map +1 -1
  134. package/dist/utils/gitignore.js +2 -1
  135. package/dist/utils/gitignore.js.map +1 -1
  136. package/dist/utils/governed-intent.d.ts +10 -0
  137. package/dist/utils/governed-intent.d.ts.map +1 -0
  138. package/dist/utils/governed-intent.js +108 -0
  139. package/dist/utils/governed-intent.js.map +1 -0
  140. package/dist/utils/hook-heartbeat.d.ts +55 -0
  141. package/dist/utils/hook-heartbeat.d.ts.map +1 -0
  142. package/dist/utils/hook-heartbeat.js +116 -0
  143. package/dist/utils/hook-heartbeat.js.map +1 -0
  144. package/dist/utils/intent-continuity.d.ts +21 -0
  145. package/dist/utils/intent-continuity.d.ts.map +1 -0
  146. package/dist/utils/intent-continuity.js +192 -0
  147. package/dist/utils/intent-continuity.js.map +1 -0
  148. package/dist/utils/messages.d.ts +1 -1
  149. package/dist/utils/messages.d.ts.map +1 -1
  150. package/dist/utils/messages.js +24 -21
  151. package/dist/utils/messages.js.map +1 -1
  152. package/dist/utils/runtime-companion.d.ts +137 -0
  153. package/dist/utils/runtime-companion.d.ts.map +1 -0
  154. package/dist/utils/runtime-companion.js +231 -0
  155. package/dist/utils/runtime-companion.js.map +1 -0
  156. package/dist/utils/runtime-connection.d.ts +46 -0
  157. package/dist/utils/runtime-connection.d.ts.map +1 -0
  158. package/dist/utils/runtime-connection.js +148 -0
  159. package/dist/utils/runtime-connection.js.map +1 -0
  160. package/dist/utils/runtime-evidence.d.ts +68 -0
  161. package/dist/utils/runtime-evidence.d.ts.map +1 -0
  162. package/dist/utils/runtime-evidence.js +248 -0
  163. package/dist/utils/runtime-evidence.js.map +1 -0
  164. package/dist/utils/runtime-live.d.ts +33 -0
  165. package/dist/utils/runtime-live.d.ts.map +1 -0
  166. package/dist/utils/runtime-live.js +361 -0
  167. package/dist/utils/runtime-live.js.map +1 -0
  168. package/dist/utils/runtime-outbox.d.ts +76 -0
  169. package/dist/utils/runtime-outbox.d.ts.map +1 -0
  170. package/dist/utils/runtime-outbox.js +410 -0
  171. package/dist/utils/runtime-outbox.js.map +1 -0
  172. package/dist/utils/runtime-receipt.d.ts +50 -0
  173. package/dist/utils/runtime-receipt.d.ts.map +1 -0
  174. package/dist/utils/runtime-receipt.js +223 -0
  175. package/dist/utils/runtime-receipt.js.map +1 -0
  176. package/dist/utils/state.d.ts +21 -0
  177. package/dist/utils/state.d.ts.map +1 -1
  178. package/dist/utils/state.js +30 -0
  179. package/dist/utils/state.js.map +1 -1
  180. package/dist/utils/structural-understanding.d.ts +334 -0
  181. package/dist/utils/structural-understanding.d.ts.map +1 -0
  182. package/dist/utils/structural-understanding.js +2316 -0
  183. package/dist/utils/structural-understanding.js.map +1 -0
  184. package/dist/utils/v0-governance.d.ts +197 -0
  185. package/dist/utils/v0-governance.d.ts.map +1 -0
  186. package/dist/utils/v0-governance.js +904 -0
  187. package/dist/utils/v0-governance.js.map +1 -0
  188. package/package.json +5 -5
@@ -27,11 +27,14 @@ const crypto_1 = require("crypto");
27
27
  const child_process_1 = require("child_process");
28
28
  const runtime_state_1 = require("../utils/runtime-state");
29
29
  const cli_json_1 = require("../utils/cli-json");
30
+ const plan_cache_1 = require("../utils/plan-cache");
30
31
  const chalk = (0, cli_json_1.loadChalk)();
31
32
  // ── Trust boundary statement — fixed, never changes ──────────────────────────
32
33
  const TRUST_BOUNDARY_STATEMENT = 'Neurcode deterministically detects and governs. ' +
33
- 'Your AI coding assistant (Cursor, Claude, Codex, GitHub Copilot) performs remediation. ' +
34
+ 'Your AI coding assistant (Claude, Codex, Cursor, Gemini, GitHub Copilot) performs remediation. ' +
34
35
  'Neurcode never autonomously modifies production code.';
36
+ const REMEDIATION_HANDOFF_SCHEMA = 'neurcode.remediation-handoff.v1';
37
+ const PROVIDERS = ['claude', 'codex', 'cursor', 'gemini'];
35
38
  // ── Remediation category map — deterministic, ruleId-keyed ───────────────────
36
39
  const REMEDIATION_CATEGORY = {
37
40
  PY003: 'exception-handling',
@@ -179,13 +182,17 @@ async function remediateExportCommand(options) {
179
182
  console.log(chalk.dim(`No finding specified. Exporting finding at index 0. Use --finding-index N or --all.\n`));
180
183
  selected = [findings[0]];
181
184
  }
182
- const format = options.format ?? 'json';
185
+ const format = normalizeOutputFormat(options.format);
186
+ const provider = normalizeProvider(options.provider);
187
+ if ((format === 'prompt' || options.open) && !provider) {
188
+ console.error(chalk.red('✗ A provider is required for provider-specific handoff output.'));
189
+ console.error(chalk.dim(` Use: --provider ${PROVIDERS.join('|')}`));
190
+ process.exit(1);
191
+ }
183
192
  const replayChecksum = resolveReplayChecksum(verifyOutput);
184
193
  const replayMode = resolveReplayMode(verifyOutput);
185
194
  const payloads = selected.map((finding) => buildPayload(finding, verifyOutput, projectRoot, replayChecksum, replayMode, format));
186
- const output = payloads.length === 1
187
- ? JSON.stringify(format === 'mcp' ? payloads[0].mcpEnvelope : payloads[0], null, 2)
188
- : JSON.stringify(format === 'mcp' ? payloads.map(p => p.mcpEnvelope) : payloads, null, 2);
195
+ const output = renderRemediationOutput(payloads, format, provider);
189
196
  // Write to file or stdout
190
197
  if (options.out) {
191
198
  const outPath = (0, path_1.resolve)(projectRoot, options.out);
@@ -205,8 +212,16 @@ async function remediateExportCommand(options) {
205
212
  console.error(chalk.yellow('\n⚠ --copy failed (pbcopy not available on this system).'));
206
213
  }
207
214
  }
215
+ if (options.open) {
216
+ if (payloads.length !== 1) {
217
+ console.error(chalk.yellow('\n⚠ --open supports one finding at a time. Re-run without --all.'));
218
+ }
219
+ else if (provider) {
220
+ openProviderHandoff(payloads[0], provider);
221
+ }
222
+ }
208
223
  // Print trust boundary reminder
209
- if (!options.json) {
224
+ if (!options.json && format === 'json') {
210
225
  console.error(chalk.dim('\n─────────────────────────────────────────────────────────'));
211
226
  console.error(chalk.cyan(' Trust Boundary'));
212
227
  console.error(chalk.dim(' Neurcode detects. Your AI assistant remediates.'));
@@ -298,7 +313,7 @@ function buildPayload(finding, verifyOutput, projectRoot, replayChecksum, replay
298
313
  const payload = {
299
314
  exportId,
300
315
  exportedAt: new Date().toISOString(),
301
- neurcodeVersion: '0.14.0',
316
+ neurcodeVersion: (0, plan_cache_1.getNeurcodeVersion)(),
302
317
  schemaVersion: '2026-05-14',
303
318
  findingId,
304
319
  ruleId,
@@ -338,7 +353,9 @@ function buildPayload(finding, verifyOutput, projectRoot, replayChecksum, replay
338
353
  graphImpact,
339
354
  relevantNarratives,
340
355
  suggestedPromptHint,
356
+ agentHandoff: undefined,
341
357
  };
358
+ payload.agentHandoff = buildAgentHandoff(payload, projectRoot);
342
359
  if (format === 'mcp') {
343
360
  payload.mcpEnvelope = {
344
361
  type: 'neurcode/remediation-request',
@@ -388,6 +405,341 @@ function asStringArray(value, limit = 12) {
388
405
  .filter((entry) => typeof entry === 'string' && entry.trim().length > 0)
389
406
  .slice(0, limit);
390
407
  }
408
+ function normalizeProvider(value) {
409
+ if (typeof value !== 'string' || value.trim().length === 0)
410
+ return undefined;
411
+ const normalized = value.trim().toLowerCase();
412
+ return PROVIDERS.includes(normalized)
413
+ ? normalized
414
+ : undefined;
415
+ }
416
+ function normalizeOutputFormat(value) {
417
+ if (typeof value !== 'string')
418
+ return 'json';
419
+ const normalized = value.trim().toLowerCase();
420
+ return ['json', 'mcp', 'prompt', 'markdown'].includes(normalized)
421
+ ? normalized
422
+ : 'json';
423
+ }
424
+ function shellQuote(value) {
425
+ return `'${value.replace(/'/g, `'\\''`)}'`;
426
+ }
427
+ function uniqueNonEmpty(values, limit = 20) {
428
+ return [...new Set(values.map((value) => value?.trim() || '').filter(Boolean))].slice(0, limit);
429
+ }
430
+ function buildAgentHandoff(payload, projectRoot) {
431
+ const context = payload.engineeringContext;
432
+ const drift = payload.driftIntelligence;
433
+ const allowedFiles = uniqueNonEmpty([
434
+ payload.filePath,
435
+ ...(context?.approvedScope.files || []),
436
+ ...(context?.contextFiles || []),
437
+ ], 24);
438
+ const forbiddenBoundaries = uniqueNonEmpty([
439
+ ...((context?.forbiddenBoundaries || []).map((entry) => `${entry.policy}:${entry.type}:${entry.path}${entry.reason ? ` — ${entry.reason}` : ''}`)),
440
+ ...payload.scopeUnexpectedFiles.map((file) => `out-of-scope:${file}`),
441
+ ...(drift?.unexpectedFiles || []).map((file) => `unexpected-file:${file}`),
442
+ ...(payload.ownershipBoundaryCrossed || []).map((entry) => `ownership-boundary:${entry}`),
443
+ ], 24);
444
+ const currentFailure = [
445
+ `${payload.severity} ${payload.ruleId} in ${payload.filePath}${payload.line ? `:${payload.line}` : ''}`,
446
+ payload.operationalExplanation || payload.suggestedPromptHint,
447
+ ].filter(Boolean).join(' — ');
448
+ const handoffBase = {
449
+ schemaVersion: REMEDIATION_HANDOFF_SCHEMA,
450
+ purpose: 'bounded-operational-remediation',
451
+ runtimeIdentity: {
452
+ name: 'Neurcode',
453
+ role: 'Deterministic operational governance runtime for AI-assisted engineering.',
454
+ notRole: [
455
+ 'autonomous coding agent',
456
+ 'code generator',
457
+ 'scanner-only tool',
458
+ 'probabilistic reviewer',
459
+ ],
460
+ trustBoundary: payload.trustBoundaryStatement,
461
+ },
462
+ lifecycle: {
463
+ currentStage: 'verify-failed-remediation-handoff',
464
+ direction: 'deterministic verify failure -> bounded external AI remediation -> deterministic re-verify',
465
+ closureCommand: 'neurcode verify --evidence',
466
+ replayContinuity: payload.replayChecksum
467
+ ? `Preserve replay continuity from checksum ${payload.replayChecksum}.`
468
+ : 'Re-run verify after remediation so replay continuity can be reconstructed.',
469
+ },
470
+ continuity: {
471
+ exportId: payload.exportId,
472
+ findingId: payload.findingId,
473
+ findingGraphHash: payload.findingGraphHash,
474
+ replayChecksum: payload.replayChecksum,
475
+ replayMode: payload.replayMode,
476
+ provenanceRunId: payload.provenanceRunId,
477
+ planId: payload.planId,
478
+ },
479
+ objective: {
480
+ intentSummary: context?.intentSummary || payload.intentGovernance?.riskSummary || 'No authored intent summary was present in the verify payload.',
481
+ governanceObjective: 'Resolve the blocking finding while preserving the declared intent, approved scope, dependency boundary, generated-code policy, and replay expectations.',
482
+ currentFailure,
483
+ remediationCategory: payload.remediationCategory,
484
+ },
485
+ scope: {
486
+ targetFile: payload.filePath,
487
+ targetLine: payload.line,
488
+ allowedFiles,
489
+ approvedModules: context?.approvedScope.modules || [],
490
+ approvedServices: context?.approvedScope.services || [],
491
+ forbiddenBoundaries,
492
+ generatedCodePolicy: 'Do not edit generated-code surfaces directly. Regenerate from source or stop and report if the target is generated.',
493
+ },
494
+ behaviorContract: {
495
+ do: [
496
+ 'Minimally resolve the blocking governance finding.',
497
+ 'Inspect the cited code and nearby context before editing.',
498
+ 'Keep changes inside the allowed file, module, service, and intent boundary.',
499
+ 'Preserve architectural intent, ownership boundaries, and existing style.',
500
+ 'Run or recommend the deterministic verification loop after edits.',
501
+ ],
502
+ doNot: [
503
+ 'Do not broaden implementation scope.',
504
+ 'Do not perform unrelated refactors, formatting sweeps, dependency upgrades, or architecture changes.',
505
+ 'Do not touch generated-code surfaces directly.',
506
+ 'Do not widen dependency, import, infrastructure, CI, or rollout boundaries.',
507
+ 'Do not treat Neurcode findings as suggestions to debate away.',
508
+ ],
509
+ constraints: [
510
+ 'No autonomous governance decisions.',
511
+ 'No policy exception creation.',
512
+ 'No suppression unless explicitly requested by a human through governed workflow.',
513
+ 'Stop and explain if the requested remediation cannot be completed inside the boundary.',
514
+ ],
515
+ minimalityExpectations: [
516
+ 'Prefer the smallest code change that clears the finding.',
517
+ 'Avoid new abstractions unless required to satisfy the rule safely.',
518
+ 'Preserve public APIs unless the finding explicitly concerns the public API.',
519
+ 'Keep tests focused on the changed behavior when tests are needed.',
520
+ ],
521
+ },
522
+ successCriteria: [
523
+ 'The cited finding is resolved in the target file.',
524
+ 'No new blocking or advisory Neurcode findings are introduced.',
525
+ 'Approved scope, forbidden boundaries, generated-code policy, and import-edge governance remain intact.',
526
+ 'The engineer can run `neurcode verify --evidence` and get a PASS or a narrower, explainable remaining finding.',
527
+ ],
528
+ verificationLoop: {
529
+ required: true,
530
+ command: 'neurcode verify --evidence',
531
+ expectation: 'Re-run deterministic verify after the external AI edit. Do not claim closure before verify passes.',
532
+ },
533
+ outputExpectations: [
534
+ 'State the files changed and why each change was necessary.',
535
+ 'Call out any boundary uncertainty instead of guessing.',
536
+ 'Do not claim Neurcode approval; only Neurcode verify can close the loop.',
537
+ ],
538
+ };
539
+ const handoff = handoffBase;
540
+ handoff.providerHandoffs = {
541
+ claude: buildProviderHandoff('claude', handoffBase, payload, projectRoot),
542
+ codex: buildProviderHandoff('codex', handoffBase, payload, projectRoot),
543
+ cursor: buildProviderHandoff('cursor', handoffBase, payload, projectRoot),
544
+ gemini: buildProviderHandoff('gemini', handoffBase, payload, projectRoot),
545
+ };
546
+ return handoff;
547
+ }
548
+ function buildProviderHandoff(provider, handoff, payload, projectRoot) {
549
+ const prompt = buildProviderPrompt(provider, handoff, payload);
550
+ const compactPrompt = buildProviderPrompt(provider, handoff, payload, { compact: true });
551
+ const encodedPrompt = encodeURIComponent(compactPrompt);
552
+ const cwd = encodeURIComponent(projectRoot);
553
+ const label = provider === 'claude'
554
+ ? 'Claude Code'
555
+ : provider === 'codex'
556
+ ? 'Codex'
557
+ : provider === 'cursor'
558
+ ? 'Cursor'
559
+ : 'Gemini CLI';
560
+ const command = provider === 'codex'
561
+ ? `codex --cd ${shellQuote(projectRoot)} ${shellQuote(prompt)}`
562
+ : provider === 'cursor'
563
+ ? `cursor-agent ${shellQuote(prompt)}`
564
+ : provider === 'gemini'
565
+ ? `gemini -p ${shellQuote(prompt)}`
566
+ : null;
567
+ const claudeLink = provider === 'claude' && compactPrompt.length <= 5000
568
+ ? `claude-cli://open?cwd=${cwd}&q=${encodedPrompt}`
569
+ : null;
570
+ return {
571
+ provider,
572
+ label,
573
+ optimizedFor: providerOptimizations(provider),
574
+ clipboardTitle: `Remediate in ${label}`,
575
+ prompt,
576
+ launch: {
577
+ mode: provider === 'claude' ? 'deep-link' : command ? 'cli-command' : 'clipboard',
578
+ available: provider === 'claude' ? Boolean(claudeLink) : Boolean(command),
579
+ deepLink: claudeLink,
580
+ command,
581
+ limitation: provider === 'claude'
582
+ ? claudeLink
583
+ ? null
584
+ : 'Claude Code deep links accept prompts up to 5,000 characters; use the clipboard prompt for this larger handoff.'
585
+ : `${label} does not expose a documented universal prompt-prefill deep link in the audited docs; use the CLI command or clipboard prompt.`,
586
+ },
587
+ };
588
+ }
589
+ function providerOptimizations(provider) {
590
+ switch (provider) {
591
+ case 'claude':
592
+ return ['Claude Code deep-link prefill', 'explicit contract tags', 'long-context boundary retention'];
593
+ case 'codex':
594
+ return ['local workspace execution', 'reviewable patch workflow', 'approval-aware command execution'];
595
+ case 'cursor':
596
+ return ['IDE agent/composer workflow', 'file-local context anchoring', 'rule-aware editing'];
597
+ case 'gemini':
598
+ return ['CLI prompt mode', 'checklist-style boundaries', 'explicit anti-broadening constraints'];
599
+ }
600
+ }
601
+ function buildProviderPrompt(provider, handoff, payload, options = {}) {
602
+ const providerDirective = {
603
+ claude: 'Claude Code: read this as an operational contract before editing. Keep a short plan, then implement only the bounded fix.',
604
+ codex: 'Codex: operate as a local coding agent under strict governance constraints. Inspect first, edit narrowly, then summarize verification.',
605
+ cursor: 'Cursor: use Agent/Composer with this file as the anchor. Do not fan out across the codebase unless the allowed scope below requires it.',
606
+ gemini: 'Gemini CLI: follow the checklist exactly. Avoid broad rewrites; stop if the fix requires scope expansion.',
607
+ }[provider];
608
+ const allowed = handoff.scope.allowedFiles.slice(0, options.compact ? 8 : 18);
609
+ const forbidden = handoff.scope.forbiddenBoundaries.slice(0, options.compact ? 6 : 14);
610
+ const lines = [
611
+ '# Neurcode Remediation Handoff',
612
+ '',
613
+ providerDirective,
614
+ '',
615
+ '## Runtime Identity',
616
+ `${handoff.runtimeIdentity.name} is a deterministic operational governance runtime for AI-assisted engineering.`,
617
+ `It is not: ${handoff.runtimeIdentity.notRole.join(', ')}.`,
618
+ handoff.runtimeIdentity.trustBoundary,
619
+ '',
620
+ '## Governance Objective',
621
+ handoff.objective.governanceObjective,
622
+ '',
623
+ '## Current Deterministic Failure',
624
+ `Finding: ${handoff.objective.currentFailure}`,
625
+ `Category: ${handoff.objective.remediationCategory}`,
626
+ `Target: ${handoff.scope.targetFile}${handoff.scope.targetLine ? `:${handoff.scope.targetLine}` : ''}`,
627
+ payload.codeSpan ? `Code span: ${payload.codeSpan}` : '',
628
+ '',
629
+ '## Intent And Scope',
630
+ `Intent summary: ${handoff.objective.intentSummary}`,
631
+ `Allowed files: ${allowed.length ? allowed.join(', ') : handoff.scope.targetFile}`,
632
+ handoff.scope.approvedModules.length ? `Approved modules: ${handoff.scope.approvedModules.join(', ')}` : '',
633
+ handoff.scope.approvedServices.length ? `Approved services: ${handoff.scope.approvedServices.join(', ')}` : '',
634
+ forbidden.length ? `Forbidden boundaries: ${forbidden.join(' | ')}` : 'Forbidden boundaries: do not expand dependencies, imports, generated-code, infra, CI, rollout, or ownership scope.',
635
+ handoff.scope.generatedCodePolicy,
636
+ '',
637
+ '## Required Behavior',
638
+ ...handoff.behaviorContract.do.map((entry) => `DO: ${entry}`),
639
+ ...handoff.behaviorContract.doNot.map((entry) => `DO NOT: ${entry}`),
640
+ '',
641
+ '## Minimality Constraints',
642
+ ...handoff.behaviorContract.minimalityExpectations.map((entry) => `- ${entry}`),
643
+ '',
644
+ '## Success Criteria',
645
+ ...handoff.successCriteria.map((entry) => `- ${entry}`),
646
+ '',
647
+ '## Verification Loop',
648
+ `After remediation, run: ${handoff.verificationLoop.command}`,
649
+ handoff.verificationLoop.expectation,
650
+ '',
651
+ '## Continuity',
652
+ `Export ID: ${handoff.continuity.exportId}`,
653
+ `Finding graph hash: ${handoff.continuity.findingGraphHash}`,
654
+ handoff.continuity.replayChecksum ? `Replay checksum: ${handoff.continuity.replayChecksum}` : 'Replay checksum: unavailable in source verify payload',
655
+ ].filter((line) => line !== '');
656
+ if (!options.compact && payload.surroundingContext.trim().length > 0) {
657
+ lines.push('', '## Local Code Context', '```', payload.surroundingContext, '```');
658
+ }
659
+ if (!options.compact && payload.relevantNarratives.length > 0) {
660
+ lines.push('', '## Relevant Governance Narrative');
661
+ payload.relevantNarratives.slice(0, 3).forEach((entry, index) => {
662
+ lines.push(`${index + 1}. ${entry.summary}`);
663
+ lines.push(`Root cause: ${entry.rootCause}`);
664
+ lines.push(`Boundary: ${entry.remediationBoundary}`);
665
+ });
666
+ }
667
+ lines.push('', '## Output Expectations', ...handoff.outputExpectations.map((entry) => `- ${entry}`));
668
+ return lines.join('\n');
669
+ }
670
+ function renderRemediationOutput(payloads, format, provider) {
671
+ if (format === 'prompt' && provider) {
672
+ return payloads.map((payload) => payload.agentHandoff.providerHandoffs[provider].prompt).join('\n\n---\n\n');
673
+ }
674
+ if (format === 'markdown') {
675
+ return payloads.map((payload) => renderMarkdownHandoff(payload, provider)).join('\n\n---\n\n');
676
+ }
677
+ if (format === 'mcp') {
678
+ return payloads.length === 1
679
+ ? JSON.stringify(payloads[0].mcpEnvelope, null, 2)
680
+ : JSON.stringify(payloads.map((payload) => payload.mcpEnvelope), null, 2);
681
+ }
682
+ return payloads.length === 1
683
+ ? JSON.stringify(payloads[0], null, 2)
684
+ : JSON.stringify(payloads, null, 2);
685
+ }
686
+ function renderMarkdownHandoff(payload, provider) {
687
+ const selected = provider ? [payload.agentHandoff.providerHandoffs[provider]] : PROVIDERS.map((entry) => payload.agentHandoff.providerHandoffs[entry]);
688
+ const lines = [
689
+ '# Neurcode Remediation Handoff',
690
+ '',
691
+ `Export: \`${payload.exportId}\``,
692
+ `Finding: \`${payload.ruleId}\` in \`${payload.filePath}${payload.line ? `:${payload.line}` : ''}\``,
693
+ `Replay: \`${payload.replayChecksum || 'unavailable'}\``,
694
+ '',
695
+ payload.agentHandoff.objective.governanceObjective,
696
+ '',
697
+ ];
698
+ selected.forEach((handoff) => {
699
+ lines.push(`## ${handoff.clipboardTitle}`);
700
+ if (handoff.launch.deepLink)
701
+ lines.push(`[Open ${handoff.label}](${handoff.launch.deepLink})`);
702
+ if (handoff.launch.command) {
703
+ lines.push('```bash');
704
+ lines.push(handoff.launch.command);
705
+ lines.push('```');
706
+ }
707
+ if (handoff.launch.limitation)
708
+ lines.push(`Note: ${handoff.launch.limitation}`);
709
+ lines.push('');
710
+ lines.push('```text');
711
+ lines.push(handoff.prompt);
712
+ lines.push('```');
713
+ lines.push('');
714
+ });
715
+ return lines.join('\n');
716
+ }
717
+ function openProviderHandoff(payload, provider) {
718
+ const handoff = payload.agentHandoff.providerHandoffs[provider];
719
+ if (!handoff.launch.deepLink) {
720
+ console.error(chalk.yellow(`\n⚠ ${handoff.label} does not have an available documented deep-link for this payload.`));
721
+ if (handoff.launch.command) {
722
+ console.error(chalk.dim(' Use this command instead:'));
723
+ console.error(chalk.cyan(` ${handoff.launch.command}`));
724
+ }
725
+ return;
726
+ }
727
+ try {
728
+ if (process.platform === 'darwin') {
729
+ (0, child_process_1.execFileSync)('open', [handoff.launch.deepLink], { stdio: 'ignore' });
730
+ }
731
+ else if (process.platform === 'win32') {
732
+ (0, child_process_1.execFileSync)('cmd', ['/c', 'start', '', handoff.launch.deepLink], { stdio: 'ignore' });
733
+ }
734
+ else {
735
+ (0, child_process_1.execFileSync)('xdg-open', [handoff.launch.deepLink], { stdio: 'ignore' });
736
+ }
737
+ console.error(chalk.green(`\n✅ Opened ${handoff.label} handoff.`));
738
+ }
739
+ catch {
740
+ console.error(chalk.yellow(`\n⚠ Could not open ${handoff.label}. Copy the deep link or prompt from the export instead.`));
741
+ }
742
+ }
391
743
  function extractGovernanceDecisionLineage(value) {
392
744
  const record = asRecord(value);
393
745
  if (!record)