@neurcode-ai/cli 0.9.66 → 0.10.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 (180) hide show
  1. package/dist/commands/governance.d.ts +3 -0
  2. package/dist/commands/governance.d.ts.map +1 -0
  3. package/dist/commands/governance.js +390 -0
  4. package/dist/commands/governance.js.map +1 -0
  5. package/dist/commands/quickstart.js +3 -3
  6. package/dist/commands/quickstart.js.map +1 -1
  7. package/dist/commands/remediate-export.d.ts +5 -0
  8. package/dist/commands/remediate-export.d.ts.map +1 -1
  9. package/dist/commands/remediate-export.js +803 -14
  10. package/dist/commands/remediate-export.js.map +1 -1
  11. package/dist/commands/replay.d.ts.map +1 -1
  12. package/dist/commands/replay.js +14 -0
  13. package/dist/commands/replay.js.map +1 -1
  14. package/dist/commands/session.d.ts +7 -0
  15. package/dist/commands/session.d.ts.map +1 -1
  16. package/dist/commands/session.js +156 -0
  17. package/dist/commands/session.js.map +1 -1
  18. package/dist/commands/start-intent.d.ts.map +1 -1
  19. package/dist/commands/start-intent.js +61 -11
  20. package/dist/commands/start-intent.js.map +1 -1
  21. package/dist/commands/verify-guidance.d.ts +5 -0
  22. package/dist/commands/verify-guidance.d.ts.map +1 -0
  23. package/dist/commands/verify-guidance.js +49 -0
  24. package/dist/commands/verify-guidance.js.map +1 -0
  25. package/dist/commands/verify-output.d.ts +37 -0
  26. package/dist/commands/verify-output.d.ts.map +1 -0
  27. package/dist/commands/verify-output.js +572 -0
  28. package/dist/commands/verify-output.js.map +1 -0
  29. package/dist/commands/verify-render.d.ts +41 -0
  30. package/dist/commands/verify-render.d.ts.map +1 -0
  31. package/dist/commands/verify-render.js +457 -0
  32. package/dist/commands/verify-render.js.map +1 -0
  33. package/dist/commands/verify.d.ts.map +1 -1
  34. package/dist/commands/verify.js +278 -1081
  35. package/dist/commands/verify.js.map +1 -1
  36. package/dist/commands/workspace.d.ts.map +1 -1
  37. package/dist/commands/workspace.js +3 -14
  38. package/dist/commands/workspace.js.map +1 -1
  39. package/dist/context-engine/graph.d.ts.map +1 -1
  40. package/dist/context-engine/graph.js +69 -7
  41. package/dist/context-engine/graph.js.map +1 -1
  42. package/dist/context-engine/scanner.d.ts.map +1 -1
  43. package/dist/context-engine/scanner.js +9 -2
  44. package/dist/context-engine/scanner.js.map +1 -1
  45. package/dist/daemon/compatibility/execution.d.ts +42 -0
  46. package/dist/daemon/compatibility/execution.d.ts.map +1 -0
  47. package/dist/daemon/compatibility/execution.js +183 -0
  48. package/dist/daemon/compatibility/execution.js.map +1 -0
  49. package/dist/daemon/compatibility/mutation.d.ts +24 -0
  50. package/dist/daemon/compatibility/mutation.d.ts.map +1 -0
  51. package/dist/daemon/compatibility/mutation.js +724 -0
  52. package/dist/daemon/compatibility/mutation.js.map +1 -0
  53. package/dist/daemon/routes.d.ts +19 -0
  54. package/dist/daemon/routes.d.ts.map +1 -0
  55. package/dist/daemon/routes.js +123 -0
  56. package/dist/daemon/routes.js.map +1 -0
  57. package/dist/daemon/runtime/execution-bus.d.ts +217 -0
  58. package/dist/daemon/runtime/execution-bus.d.ts.map +1 -0
  59. package/dist/daemon/runtime/execution-bus.js +1420 -0
  60. package/dist/daemon/runtime/execution-bus.js.map +1 -0
  61. package/dist/daemon/runtime/workspace-runtime.d.ts +280 -0
  62. package/dist/daemon/runtime/workspace-runtime.d.ts.map +1 -0
  63. package/dist/daemon/runtime/workspace-runtime.js +1473 -0
  64. package/dist/daemon/runtime/workspace-runtime.js.map +1 -0
  65. package/dist/daemon/server.d.ts.map +1 -1
  66. package/dist/daemon/server.js +171 -874
  67. package/dist/daemon/server.js.map +1 -1
  68. package/dist/daemon/shaping.d.ts +11 -0
  69. package/dist/daemon/shaping.d.ts.map +1 -0
  70. package/dist/daemon/shaping.js +240 -0
  71. package/dist/daemon/shaping.js.map +1 -0
  72. package/dist/governance/canonical-pipeline.d.ts +2 -1
  73. package/dist/governance/canonical-pipeline.d.ts.map +1 -1
  74. package/dist/governance/canonical-pipeline.js +259 -84
  75. package/dist/governance/canonical-pipeline.js.map +1 -1
  76. package/dist/governance/structural-cache.d.ts.map +1 -1
  77. package/dist/governance/structural-cache.js +2 -7
  78. package/dist/governance/structural-cache.js.map +1 -1
  79. package/dist/index.js +230 -66
  80. package/dist/index.js.map +1 -1
  81. package/dist/utils/active-engineering-context.d.ts +12 -0
  82. package/dist/utils/active-engineering-context.d.ts.map +1 -0
  83. package/dist/utils/active-engineering-context.js +67 -0
  84. package/dist/utils/active-engineering-context.js.map +1 -0
  85. package/dist/utils/artifact-io.d.ts +33 -0
  86. package/dist/utils/artifact-io.d.ts.map +1 -0
  87. package/dist/utils/artifact-io.js +183 -0
  88. package/dist/utils/artifact-io.js.map +1 -0
  89. package/dist/utils/change-contract.d.ts +6 -2
  90. package/dist/utils/change-contract.d.ts.map +1 -1
  91. package/dist/utils/change-contract.js +175 -0
  92. package/dist/utils/change-contract.js.map +1 -1
  93. package/dist/utils/context-pack.d.ts +12 -0
  94. package/dist/utils/context-pack.d.ts.map +1 -0
  95. package/dist/utils/context-pack.js +147 -0
  96. package/dist/utils/context-pack.js.map +1 -0
  97. package/dist/utils/control-plane.d.ts +18 -0
  98. package/dist/utils/control-plane.d.ts.map +1 -1
  99. package/dist/utils/control-plane.js +31 -4
  100. package/dist/utils/control-plane.js.map +1 -1
  101. package/dist/utils/drift-intelligence.d.ts +47 -0
  102. package/dist/utils/drift-intelligence.d.ts.map +1 -0
  103. package/dist/utils/drift-intelligence.js +2099 -0
  104. package/dist/utils/drift-intelligence.js.map +1 -0
  105. package/dist/utils/execution-actions.d.ts +22 -0
  106. package/dist/utils/execution-actions.d.ts.map +1 -0
  107. package/dist/utils/execution-actions.js +103 -0
  108. package/dist/utils/execution-actions.js.map +1 -0
  109. package/dist/utils/execution-bus.d.ts +1 -214
  110. package/dist/utils/execution-bus.d.ts.map +1 -1
  111. package/dist/utils/execution-bus.js +15 -1359
  112. package/dist/utils/execution-bus.js.map +1 -1
  113. package/dist/utils/git.d.ts +1 -0
  114. package/dist/utils/git.d.ts.map +1 -1
  115. package/dist/utils/git.js +13 -3
  116. package/dist/utils/git.js.map +1 -1
  117. package/dist/utils/governance-decisions.d.ts +75 -0
  118. package/dist/utils/governance-decisions.d.ts.map +1 -0
  119. package/dist/utils/governance-decisions.js +412 -0
  120. package/dist/utils/governance-decisions.js.map +1 -0
  121. package/dist/utils/governance-provenance.d.ts +1 -1
  122. package/dist/utils/governance-provenance.d.ts.map +1 -1
  123. package/dist/utils/governance-provenance.js +5 -7
  124. package/dist/utils/governance-provenance.js.map +1 -1
  125. package/dist/utils/governance.d.ts +108 -0
  126. package/dist/utils/governance.d.ts.map +1 -1
  127. package/dist/utils/governance.js +209 -7
  128. package/dist/utils/governance.js.map +1 -1
  129. package/dist/utils/intelligence-runtime-common.d.ts +30 -0
  130. package/dist/utils/intelligence-runtime-common.d.ts.map +1 -0
  131. package/dist/utils/intelligence-runtime-common.js +156 -0
  132. package/dist/utils/intelligence-runtime-common.js.map +1 -0
  133. package/dist/utils/intent-contract-diagnostics.d.ts +9 -0
  134. package/dist/utils/intent-contract-diagnostics.d.ts.map +1 -0
  135. package/dist/utils/intent-contract-diagnostics.js +322 -0
  136. package/dist/utils/intent-contract-diagnostics.js.map +1 -0
  137. package/dist/utils/intent-pack.d.ts +15 -0
  138. package/dist/utils/intent-pack.d.ts.map +1 -0
  139. package/dist/utils/intent-pack.js +196 -0
  140. package/dist/utils/intent-pack.js.map +1 -0
  141. package/dist/utils/plan-sync.d.ts +1 -0
  142. package/dist/utils/plan-sync.d.ts.map +1 -1
  143. package/dist/utils/plan-sync.js +23 -0
  144. package/dist/utils/plan-sync.js.map +1 -1
  145. package/dist/utils/policy-decision.d.ts +5 -0
  146. package/dist/utils/policy-decision.d.ts.map +1 -0
  147. package/dist/utils/policy-decision.js +17 -0
  148. package/dist/utils/policy-decision.js.map +1 -0
  149. package/dist/utils/replay-custody.d.ts +43 -0
  150. package/dist/utils/replay-custody.d.ts.map +1 -0
  151. package/dist/utils/replay-custody.js +168 -0
  152. package/dist/utils/replay-custody.js.map +1 -0
  153. package/dist/utils/replay-runtime.d.ts +13 -0
  154. package/dist/utils/replay-runtime.d.ts.map +1 -1
  155. package/dist/utils/replay-runtime.js +96 -9
  156. package/dist/utils/replay-runtime.js.map +1 -1
  157. package/dist/utils/repository-intelligence.d.ts +9 -0
  158. package/dist/utils/repository-intelligence.d.ts.map +1 -0
  159. package/dist/utils/repository-intelligence.js +372 -0
  160. package/dist/utils/repository-intelligence.js.map +1 -0
  161. package/dist/utils/runtime-events.d.ts.map +1 -1
  162. package/dist/utils/runtime-events.js +25 -6
  163. package/dist/utils/runtime-events.js.map +1 -1
  164. package/dist/utils/semantic-contract-intelligence.d.ts +20 -0
  165. package/dist/utils/semantic-contract-intelligence.d.ts.map +1 -0
  166. package/dist/utils/semantic-contract-intelligence.js +825 -0
  167. package/dist/utils/semantic-contract-intelligence.js.map +1 -0
  168. package/dist/utils/session-continuity.d.ts +56 -0
  169. package/dist/utils/session-continuity.d.ts.map +1 -0
  170. package/dist/utils/session-continuity.js +318 -0
  171. package/dist/utils/session-continuity.js.map +1 -0
  172. package/dist/utils/verification-evidence.d.ts.map +1 -1
  173. package/dist/utils/verification-evidence.js +4 -1
  174. package/dist/utils/verification-evidence.js.map +1 -1
  175. package/dist/utils/workspace-runtime.d.ts +1 -266
  176. package/dist/utils/workspace-runtime.d.ts.map +1 -1
  177. package/dist/utils/workspace-runtime.js +15 -1412
  178. package/dist/utils/workspace-runtime.js.map +1 -1
  179. package/package.json +11 -10
  180. package/LICENSE +0 -201
@@ -17,6 +17,7 @@
17
17
  * neurcode remediate-export --finding <id> --format mcp
18
18
  * neurcode remediate-export --finding <id> --out ./payload.json
19
19
  * neurcode remediate-export --finding <id> --copy
20
+ * neurcode remediate-export --verify-output-file ./verify.json --project-root ./repo
20
21
  */
21
22
  Object.defineProperty(exports, "__esModule", { value: true });
22
23
  exports.remediateExportCommand = remediateExportCommand;
@@ -53,6 +54,35 @@ const REMEDIATION_CATEGORY = {
53
54
  DS001: 'distributed-consistency',
54
55
  'potential-secret-default': 'security',
55
56
  'potential-secret-high': 'security',
57
+ governance_decision_block: 'governance-boundary',
58
+ scope_guard: 'governance-boundary',
59
+ 'drift_narrative:service-boundary-escape': 'governance-boundary',
60
+ 'drift_narrative:dependency-expansion': 'governance-boundary',
61
+ 'drift_narrative:forbidden-boundary-breach': 'governance-boundary',
62
+ 'drift_narrative:semantic-coupling': 'governance-boundary',
63
+ 'drift_narrative:blast-radius-expansion': 'governance-boundary',
64
+ 'drift_narrative:localized-scope-drift': 'governance-boundary',
65
+ 'drift_narrative:ownership-boundary-breach': 'governance-boundary',
66
+ 'drift_narrative:architectural-invariant-erosion': 'governance-boundary',
67
+ 'drift_narrative:runtime-behavior-shift': 'governance-boundary',
68
+ 'drift_narrative:deployment-semantics-breach': 'governance-boundary',
69
+ 'drift_narrative:state-ownership-erosion': 'governance-boundary',
70
+ 'drift_intelligence:cross-service': 'governance-boundary',
71
+ 'drift_intelligence:dependency-spread': 'governance-boundary',
72
+ 'drift_intelligence:infra-leakage': 'governance-boundary',
73
+ 'drift_intelligence:sensitive-boundary': 'governance-boundary',
74
+ 'drift_intelligence:blast-radius': 'governance-boundary',
75
+ 'drift_intelligence:rollout-risk': 'governance-boundary',
76
+ 'drift_intelligence:runtime-coupling': 'governance-boundary',
77
+ 'drift_intelligence:architectural-leakage': 'governance-boundary',
78
+ 'drift_intelligence:layer-violation': 'governance-boundary',
79
+ 'drift_intelligence:contract-misuse': 'governance-boundary',
80
+ 'drift_intelligence:ownership-inversion': 'governance-boundary',
81
+ 'drift_intelligence:responsibility-drift': 'governance-boundary',
82
+ 'drift_intelligence:invariant-violation': 'governance-boundary',
83
+ 'drift_intelligence:behavioral-drift': 'governance-boundary',
84
+ 'drift_intelligence:deployment-coupling': 'governance-boundary',
85
+ 'drift_intelligence:state-ownership-risk': 'governance-boundary',
56
86
  };
57
87
  // ── Suggested prompt hint per category — advisory, never prescriptive ─────────
58
88
  const PROMPT_HINT = {
@@ -76,22 +106,27 @@ const PROMPT_HINT = {
76
106
  'Remediation should add compensating logic, idempotency, or saga rollback.',
77
107
  'data-flow': 'The finding identifies a data flow issue (unbounded collection, leaking state). ' +
78
108
  'Remediation should add bounds or explicit cleanup.',
109
+ 'governance-boundary': 'The finding identifies engineering drift outside the approved intent envelope. ' +
110
+ 'Remediation should pull the change back inside the declared service, dependency, and rollout boundary before re-verification.',
79
111
  };
80
112
  async function remediateExportCommand(options) {
81
- const projectRoot = process.cwd();
82
- const lastVerifyPath = (0, path_1.join)(projectRoot, '.neurcode', 'last-verify-output.json');
83
- if (!(0, fs_1.existsSync)(lastVerifyPath)) {
113
+ const projectRoot = options.projectRoot ? (0, path_1.resolve)(options.projectRoot) : process.cwd();
114
+ const verifyPath = options.verifyOutputFile
115
+ ? (0, path_1.resolve)(options.verifyOutputFile)
116
+ : (0, path_1.join)(projectRoot, '.neurcode', 'last-verify-output.json');
117
+ if (!(0, fs_1.existsSync)(verifyPath)) {
84
118
  console.error(chalk.red('✗ No verify output found.'));
119
+ console.error(chalk.dim(` Expected: ${verifyPath}`));
85
120
  console.error(chalk.dim(' Run: neurcode verify --policy-only --json'));
86
- console.error(chalk.dim(' The last verify output must exist at .neurcode/last-verify-output.json'));
121
+ console.error(chalk.dim(' Or pass: neurcode remediate-export --verify-output-file <path-to-verify.json>'));
87
122
  process.exit(1);
88
123
  }
89
124
  let verifyOutput;
90
125
  try {
91
- verifyOutput = JSON.parse((0, fs_1.readFileSync)(lastVerifyPath, 'utf-8'));
126
+ verifyOutput = JSON.parse((0, fs_1.readFileSync)(verifyPath, 'utf-8'));
92
127
  }
93
128
  catch {
94
- console.error(chalk.red('✗ Could not parse .neurcode/last-verify-output.json'));
129
+ console.error(chalk.red(`✗ Could not parse verify output: ${verifyPath}`));
95
130
  process.exit(1);
96
131
  }
97
132
  // Collect findings from verify output
@@ -130,8 +165,8 @@ async function remediateExportCommand(options) {
130
165
  selected = [findings[0]];
131
166
  }
132
167
  const format = options.format ?? 'json';
133
- const replayChecksum = verifyOutput.replayChecksum ?? null;
134
- const replayMode = verifyOutput.replayMode ?? null;
168
+ const replayChecksum = resolveReplayChecksum(verifyOutput);
169
+ const replayMode = resolveReplayMode(verifyOutput);
135
170
  const payloads = selected.map((finding) => buildPayload(finding, verifyOutput, projectRoot, replayChecksum, replayMode, format));
136
171
  const output = payloads.length === 1
137
172
  ? JSON.stringify(format === 'mcp' ? payloads[0].mcpEnvelope : payloads[0], null, 2)
@@ -177,7 +212,7 @@ function collectFindings(verifyOutput) {
177
212
  return [...violations, ...blockingItems, ...advisoryItems];
178
213
  }
179
214
  function buildPayload(finding, verifyOutput, projectRoot, replayChecksum, replayMode, format) {
180
- const ruleId = finding.ruleId ?? finding.rule ?? finding.structuralMetadata?.ruleId ?? 'UNKNOWN';
215
+ const ruleId = resolveFindingRuleId(finding);
181
216
  const filePath = finding.filePath ?? finding.file ?? finding.evidence?.filePath ?? '';
182
217
  const line = finding.line ?? finding.evidence?.line ?? null;
183
218
  const column = finding.column ?? finding.evidence?.column ?? null;
@@ -200,16 +235,56 @@ function buildPayload(finding, verifyOutput, projectRoot, replayChecksum, replay
200
235
  .slice(0, 16);
201
236
  const remediationCategory = REMEDIATION_CATEGORY[ruleId] ?? 'general';
202
237
  const suggestedPromptHint = PROMPT_HINT[remediationCategory] ?? PROMPT_HINT['correctness'];
238
+ const snapshotIds = Array.isArray(finding.replayMetadata?.snapshotIds)
239
+ ? finding.replayMetadata.snapshotIds.filter((entry) => typeof entry === 'string' && entry.trim().length > 0)
240
+ : [];
241
+ const controlPlaneSnapshotId = typeof verifyOutput.controlPlaneSnapshotId === 'string'
242
+ ? verifyOutput.controlPlaneSnapshotId
243
+ : snapshotIds.find((entry) => entry.startsWith('cps-')) ?? null;
244
+ const workspaceSnapshotId = typeof verifyOutput.workspaceSnapshotId === 'string'
245
+ ? verifyOutput.workspaceSnapshotId
246
+ : snapshotIds.find((entry) => entry.startsWith('wss-')) ?? null;
203
247
  const policyViolations = [];
204
248
  if (finding.structuralMetadata?.policyRef)
205
249
  policyViolations.push(finding.structuralMetadata.policyRef);
206
250
  if (finding.policy)
207
251
  policyViolations.push(finding.policy);
252
+ const blastRadiusRisk = typeof verifyOutput.blastRadius === 'object'
253
+ && verifyOutput.blastRadius
254
+ && typeof verifyOutput.blastRadius.riskScore === 'string'
255
+ ? verifyOutput.blastRadius.riskScore
256
+ : null;
257
+ const scopeReason = typeof verifyOutput.suspiciousChange === 'object'
258
+ && verifyOutput.suspiciousChange
259
+ && typeof verifyOutput.suspiciousChange.reason === 'string'
260
+ ? verifyOutput.suspiciousChange.reason
261
+ : null;
262
+ const scopeUnexpectedFiles = typeof verifyOutput.suspiciousChange === 'object'
263
+ && verifyOutput.suspiciousChange
264
+ && Array.isArray(verifyOutput.suspiciousChange.unexpectedFiles)
265
+ ? verifyOutput.suspiciousChange.unexpectedFiles
266
+ .filter((entry) => typeof entry === 'string' && entry.trim().length > 0)
267
+ .slice(0, 12)
268
+ : [];
269
+ const contractViolationSummary = typeof verifyOutput.changeContract === 'object'
270
+ && verifyOutput.changeContract
271
+ && Array.isArray(verifyOutput.changeContract.violations)
272
+ ? verifyOutput.changeContract.violations
273
+ .map((entry) => typeof entry.message === 'string' ? entry.message.trim() : '')
274
+ .filter((entry) => entry.length > 0)
275
+ .slice(0, 12)
276
+ : [];
277
+ const engineeringContext = extractEngineeringContext(verifyOutput);
278
+ const intentGovernance = extractIntentGovernance(verifyOutput);
279
+ const driftIntelligence = extractDriftIntelligence(verifyOutput);
280
+ const graphImpact = extractGraphImpact(verifyOutput);
281
+ const relevantNarratives = selectRelevantNarratives(driftIntelligence, filePath, ruleId);
282
+ const semanticInsights = deriveSemanticExportInsights(engineeringContext, driftIntelligence, relevantNarratives, filePath);
208
283
  const payload = {
209
284
  exportId,
210
285
  exportedAt: new Date().toISOString(),
211
- neurcodeVersion: '0.9.66',
212
- schemaVersion: '2026-05-12',
286
+ neurcodeVersion: '0.10.0',
287
+ schemaVersion: '2026-05-14',
213
288
  findingId,
214
289
  ruleId,
215
290
  ruleName,
@@ -223,12 +298,30 @@ function buildPayload(finding, verifyOutput, projectRoot, replayChecksum, replay
223
298
  policyViolations,
224
299
  operationalExplanation,
225
300
  remediationCategory,
301
+ blastRadiusRisk,
302
+ scopeReason,
303
+ scopeUnexpectedFiles,
304
+ contractViolationSummary,
305
+ violatedContracts: semanticInsights.violatedContracts,
306
+ ownershipBoundaryCrossed: semanticInsights.ownershipBoundaryCrossed,
307
+ invariantSummaries: semanticInsights.invariantSummaries,
308
+ semanticRiskSummary: semanticInsights.semanticRiskSummary,
309
+ intentGovernance,
226
310
  trustBoundaryStatement: TRUST_BOUNDARY_STATEMENT,
227
311
  replayChecksum,
228
312
  replayMode,
229
313
  findingGraphHash,
230
- provenanceRunId: finding.provenanceMetadata?.planId ?? null,
231
- provenanceAt: finding.provenanceMetadata?.generatedAt ?? null,
314
+ provenanceRunId: finding.provenanceMetadata?.runId ?? verifyOutput.provenanceRunId ?? null,
315
+ provenanceAt: finding.provenanceMetadata?.generatedAt ?? verifyOutput.provenanceRunAt ?? null,
316
+ planId: finding.provenanceMetadata?.planId ?? verifyOutput.planId ?? null,
317
+ policyLockFingerprint: finding.provenanceMetadata?.policyLockFingerprint ?? verifyOutput.policyLockFingerprint ?? null,
318
+ compiledPolicyFingerprint: finding.provenanceMetadata?.compiledPolicyFingerprint ?? verifyOutput.compiledPolicyFingerprint ?? null,
319
+ controlPlaneSnapshotId,
320
+ workspaceSnapshotId,
321
+ engineeringContext,
322
+ driftIntelligence,
323
+ graphImpact,
324
+ relevantNarratives,
232
325
  suggestedPromptHint,
233
326
  };
234
327
  if (format === 'mcp') {
@@ -244,13 +337,709 @@ function buildPayload(finding, verifyOutput, projectRoot, replayChecksum, replay
244
337
  line,
245
338
  codeSpan,
246
339
  },
247
- context: surroundingContext,
340
+ context: buildMcpContext(surroundingContext, engineeringContext, driftIntelligence, graphImpact, relevantNarratives, semanticInsights, intentGovernance),
248
341
  constraint: TRUST_BOUNDARY_STATEMENT,
249
342
  promptHint: suggestedPromptHint,
250
343
  };
251
344
  }
252
345
  return payload;
253
346
  }
347
+ function resolveFindingRuleId(finding) {
348
+ const direct = finding.ruleId
349
+ ?? finding.rule
350
+ ?? finding.structuralMetadata?.ruleId
351
+ ?? null;
352
+ if (typeof direct === 'string' && direct.trim().length > 0) {
353
+ return direct.trim();
354
+ }
355
+ const title = typeof finding.title === 'string' ? finding.title.trim() : '';
356
+ const titleMatch = title.match(/·\s*([A-Za-z0-9:_-]+)/);
357
+ if (titleMatch?.[1]) {
358
+ return titleMatch[1];
359
+ }
360
+ return 'UNKNOWN';
361
+ }
362
+ function asRecord(value) {
363
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
364
+ return null;
365
+ }
366
+ return value;
367
+ }
368
+ function asStringArray(value, limit = 12) {
369
+ if (!Array.isArray(value)) {
370
+ return [];
371
+ }
372
+ return value
373
+ .filter((entry) => typeof entry === 'string' && entry.trim().length > 0)
374
+ .slice(0, limit);
375
+ }
376
+ function extractGovernanceDecisionLineage(value) {
377
+ const record = asRecord(value);
378
+ if (!record)
379
+ return null;
380
+ return {
381
+ decisionId: typeof record.decisionId === 'string' ? record.decisionId : 'unknown',
382
+ state: typeof record.state === 'string' ? record.state : 'acknowledged',
383
+ findingId: typeof record.findingId === 'string' ? record.findingId : null,
384
+ category: typeof record.category === 'string' ? record.category : null,
385
+ reason: typeof record.reason === 'string' ? record.reason : 'Governance decision reason unavailable.',
386
+ actor: typeof record.actor === 'string' ? record.actor : 'unknown',
387
+ decidedAt: typeof record.decidedAt === 'string' ? record.decidedAt : '',
388
+ expiresAt: typeof record.expiresAt === 'string' ? record.expiresAt : null,
389
+ temporary: record.temporary === true,
390
+ expired: record.expired === true,
391
+ previousGate: typeof record.previousGate === 'string' ? record.previousGate : null,
392
+ resultingGate: typeof record.resultingGate === 'string' ? record.resultingGate : null,
393
+ previousRolloutTrust: typeof record.previousRolloutTrust === 'string' ? record.previousRolloutTrust : null,
394
+ resultingRolloutTrust: typeof record.resultingRolloutTrust === 'string' ? record.resultingRolloutTrust : null,
395
+ sourcePath: typeof record.sourcePath === 'string' ? record.sourcePath : null,
396
+ lineageHash: typeof record.lineageHash === 'string' ? record.lineageHash : 'unknown',
397
+ };
398
+ }
399
+ function asBoundaryArray(value) {
400
+ if (!Array.isArray(value)) {
401
+ return [];
402
+ }
403
+ return value
404
+ .map((entry) => asRecord(entry))
405
+ .filter((entry) => entry !== null)
406
+ .map((entry) => ({
407
+ type: typeof entry.type === 'string' ? entry.type : 'unknown',
408
+ path: typeof entry.path === 'string' ? entry.path : '',
409
+ policy: typeof entry.policy === 'string' ? entry.policy : 'review-required',
410
+ reason: typeof entry.reason === 'string' ? entry.reason : '',
411
+ }))
412
+ .filter((entry) => entry.path.trim().length > 0)
413
+ .slice(0, 12);
414
+ }
415
+ function extractEngineeringContext(verifyOutput) {
416
+ const context = asRecord(verifyOutput.engineeringContext);
417
+ if (!context) {
418
+ return null;
419
+ }
420
+ const approvedScope = asRecord(context.approvedScope);
421
+ const semanticExpectations = asRecord(context.semanticExpectations);
422
+ return {
423
+ source: typeof context.source === 'string' ? context.source : null,
424
+ sessionId: typeof context.sessionId === 'string' ? context.sessionId : null,
425
+ intentPackId: typeof context.intentPackId === 'string' ? context.intentPackId : null,
426
+ contextPackId: typeof context.contextPackId === 'string' ? context.contextPackId : null,
427
+ repositoryGraphId: typeof context.repositoryGraphId === 'string' ? context.repositoryGraphId : null,
428
+ intentSummary: typeof context.intentSummary === 'string' ? context.intentSummary : null,
429
+ approvedScope: {
430
+ files: asStringArray(approvedScope?.files, 20),
431
+ modules: asStringArray(approvedScope?.modules, 20),
432
+ services: asStringArray(approvedScope?.services, 20),
433
+ },
434
+ expectedDependencies: asStringArray(context.expectedDependencies, 20),
435
+ expectedInfrastructure: asStringArray(context.expectedInfrastructure, 20),
436
+ rolloutExpectations: asStringArray(context.rolloutExpectations, 12),
437
+ forbiddenBoundaries: asBoundaryArray(context.forbiddenBoundaries),
438
+ semanticExpectations: semanticExpectations
439
+ ? {
440
+ ownershipBoundaries: asStringArray(semanticExpectations.ownershipBoundaries, 16),
441
+ contractIds: asStringArray(semanticExpectations.contractIds, 20),
442
+ invariantIds: asStringArray(semanticExpectations.invariantIds, 20),
443
+ expectedResponsibilities: asStringArray(semanticExpectations.expectedResponsibilities, 20),
444
+ expectedBehaviorKinds: asStringArray(semanticExpectations.expectedBehaviorKinds, 20),
445
+ expectedRuntimeFlows: asStringArray(semanticExpectations.expectedRuntimeFlows, 20),
446
+ expectedRolloutUnits: asStringArray(semanticExpectations.expectedRolloutUnits, 20),
447
+ }
448
+ : null,
449
+ contextFiles: Array.isArray(context.contextFiles)
450
+ ? context.contextFiles
451
+ .map((entry) => asRecord(entry))
452
+ .filter((entry) => entry !== null)
453
+ .map((entry) => (typeof entry.path === 'string' ? entry.path : ''))
454
+ .filter((entry) => entry.length > 0)
455
+ .slice(0, 16)
456
+ : [],
457
+ relatedModules: asStringArray(context.relatedModules, 20),
458
+ serviceBoundaries: Array.isArray(context.serviceBoundaries)
459
+ ? context.serviceBoundaries
460
+ .map((entry) => asRecord(entry))
461
+ .filter((entry) => entry !== null)
462
+ .map((entry) => `${typeof entry.name === 'string' ? entry.name : 'unknown'}:${typeof entry.path === 'string' ? entry.path : ''}`)
463
+ .filter((entry) => !entry.endsWith(':'))
464
+ .slice(0, 16)
465
+ : [],
466
+ ownershipBoundaries: Array.isArray(context.ownershipBoundaries)
467
+ ? context.ownershipBoundaries
468
+ .map((entry) => asRecord(entry))
469
+ .filter((entry) => entry !== null)
470
+ .map((entry) => ({
471
+ name: typeof entry.name === 'string' ? entry.name : 'unknown',
472
+ domain: typeof entry.domain === 'string' ? entry.domain : 'unknown',
473
+ kind: typeof entry.kind === 'string' ? entry.kind : 'unknown',
474
+ primaryOwner: typeof entry.primaryOwner === 'string' ? entry.primaryOwner : 'unknown',
475
+ responsibilities: asStringArray(entry.responsibilities, 12),
476
+ forbiddenResponsibilities: asStringArray(entry.forbiddenResponsibilities, 12),
477
+ criticality: typeof entry.criticality === 'string' ? entry.criticality : 'standard',
478
+ }))
479
+ .slice(0, 16)
480
+ : [],
481
+ invariants: Array.isArray(context.invariants)
482
+ ? context.invariants
483
+ .map((entry) => asRecord(entry))
484
+ .filter((entry) => entry !== null)
485
+ .map((entry) => ({
486
+ id: typeof entry.id === 'string' ? entry.id : 'unknown',
487
+ name: typeof entry.name === 'string' ? entry.name : 'Invariant',
488
+ category: typeof entry.category === 'string' ? entry.category : 'unknown',
489
+ expectation: typeof entry.expectation === 'string' ? entry.expectation : 'Expectation unavailable.',
490
+ impact: typeof entry.impact === 'string' ? entry.impact : 'unknown',
491
+ boundaryName: typeof entry.boundaryName === 'string' ? entry.boundaryName : null,
492
+ }))
493
+ .slice(0, 20)
494
+ : [],
495
+ invariantMemory: (() => {
496
+ const memory = asRecord(context.invariantMemory);
497
+ if (!memory)
498
+ return null;
499
+ return {
500
+ invariantMemoryId: typeof memory.invariantMemoryId === 'string' ? memory.invariantMemoryId : null,
501
+ historicalDriftPatterns: Array.isArray(memory.historicalDriftPatterns)
502
+ ? memory.historicalDriftPatterns
503
+ .map((entry) => asRecord(entry))
504
+ .filter((entry) => entry !== null)
505
+ .map((entry) => ({
506
+ category: typeof entry.category === 'string' ? entry.category : 'unknown',
507
+ count: typeof entry.count === 'number' ? entry.count : 0,
508
+ latestSummary: typeof entry.latestSummary === 'string' ? entry.latestSummary : '',
509
+ }))
510
+ .slice(0, 12)
511
+ : [],
512
+ };
513
+ })(),
514
+ runtimeBehaviors: Array.isArray(context.runtimeBehaviors)
515
+ ? context.runtimeBehaviors
516
+ .map((entry) => asRecord(entry))
517
+ .filter((entry) => entry !== null)
518
+ .map((entry) => ({
519
+ boundaryName: typeof entry.boundaryName === 'string' ? entry.boundaryName : 'unknown',
520
+ behaviorKinds: asStringArray(entry.behaviorKinds, 12),
521
+ sideEffectKinds: asStringArray(entry.sideEffectKinds, 12),
522
+ stateSurfaces: asStringArray(entry.stateSurfaces, 12),
523
+ rolloutUnits: asStringArray(entry.rolloutUnits, 12),
524
+ runtimeEnvironments: asStringArray(entry.runtimeEnvironments, 8),
525
+ criticalFlows: asStringArray(entry.criticalFlows, 12),
526
+ }))
527
+ .slice(0, 20)
528
+ : [],
529
+ runtimeInteractions: Array.isArray(context.runtimeInteractions)
530
+ ? context.runtimeInteractions
531
+ .map((entry) => asRecord(entry))
532
+ .filter((entry) => entry !== null)
533
+ .map((entry) => ({
534
+ kind: typeof entry.kind === 'string' ? entry.kind : 'unknown',
535
+ fromBoundaryName: typeof entry.fromBoundaryName === 'string' ? entry.fromBoundaryName : 'unknown',
536
+ toBoundaryName: typeof entry.toBoundaryName === 'string' ? entry.toBoundaryName : null,
537
+ subject: typeof entry.subject === 'string' ? entry.subject : 'unknown',
538
+ rationale: typeof entry.rationale === 'string' ? entry.rationale : '',
539
+ }))
540
+ .slice(0, 24)
541
+ : [],
542
+ deploymentBoundaries: Array.isArray(context.deploymentBoundaries)
543
+ ? context.deploymentBoundaries
544
+ .map((entry) => asRecord(entry))
545
+ .filter((entry) => entry !== null)
546
+ .map((entry) => ({
547
+ name: typeof entry.name === 'string' ? entry.name : 'unknown',
548
+ type: typeof entry.type === 'string' ? entry.type : 'unknown',
549
+ rolloutUnits: asStringArray(entry.rolloutUnits, 12),
550
+ runtimeEnvironments: asStringArray(entry.runtimeEnvironments, 8),
551
+ dependentBoundaryNames: asStringArray(entry.dependentBoundaryNames, 12),
552
+ }))
553
+ .slice(0, 16)
554
+ : [],
555
+ sessionLineage: asStringArray(context.sessionLineage, 12),
556
+ };
557
+ }
558
+ function extractDriftIntelligence(verifyOutput) {
559
+ const drift = asRecord(verifyOutput.driftIntelligence);
560
+ if (!drift) {
561
+ return null;
562
+ }
563
+ const findings = Array.isArray(drift.findings)
564
+ ? drift.findings
565
+ .map((entry) => asRecord(entry))
566
+ .filter((entry) => entry !== null)
567
+ .map((entry) => {
568
+ const evidence = asRecord(entry.evidence);
569
+ const remediationGuidance = asRecord(entry.remediationGuidance);
570
+ return {
571
+ category: typeof entry.category === 'string' ? entry.category : 'unknown',
572
+ severity: typeof entry.severity === 'string' ? entry.severity : 'unknown',
573
+ message: typeof entry.message === 'string' ? entry.message : 'Drift signal detected.',
574
+ rationale: typeof entry.rationale === 'string' ? entry.rationale : null,
575
+ file: typeof entry.file === 'string' ? entry.file : null,
576
+ module: typeof entry.module === 'string' ? entry.module : null,
577
+ service: typeof entry.service === 'string' ? entry.service : null,
578
+ evidenceTier: typeof entry.evidenceTier === 'string' ? entry.evidenceTier : null,
579
+ actionability: typeof entry.actionability === 'string' ? entry.actionability : null,
580
+ priority: typeof entry.priority === 'string' ? entry.priority : null,
581
+ governanceGate: typeof entry.governanceGate === 'string' ? entry.governanceGate : null,
582
+ rolloutTrust: typeof entry.rolloutTrust === 'string' ? entry.rolloutTrust : null,
583
+ relationships: Array.isArray(entry.relationships)
584
+ ? entry.relationships
585
+ .map((relationship) => asRecord(relationship))
586
+ .filter((relationship) => relationship !== null)
587
+ .map((relationship) => ({
588
+ type: typeof relationship.type === 'string' ? relationship.type : 'derived-from',
589
+ targetFindingId: typeof relationship.targetFindingId === 'string'
590
+ ? relationship.targetFindingId
591
+ : '',
592
+ rationale: typeof relationship.rationale === 'string'
593
+ ? relationship.rationale
594
+ : 'Finding relationship rationale unavailable.',
595
+ }))
596
+ .filter((relationship) => relationship.targetFindingId.length > 0)
597
+ .slice(0, 4)
598
+ : [],
599
+ governanceDecision: extractGovernanceDecisionLineage(entry.governanceDecision),
600
+ evidence: evidence
601
+ ? {
602
+ tier: typeof evidence.tier === 'string' ? evidence.tier : null,
603
+ changedFiles: asStringArray(evidence.changedFiles, 8),
604
+ changedLines: Array.isArray(evidence.changedLines)
605
+ ? evidence.changedLines
606
+ .map((line) => asRecord(line))
607
+ .filter((line) => line !== null)
608
+ .map((line) => ({
609
+ file: typeof line.file === 'string' ? line.file : 'unknown',
610
+ line: typeof line.line === 'number' ? line.line : 0,
611
+ text: typeof line.text === 'string' ? line.text : '',
612
+ }))
613
+ .filter((line) => line.line > 0 || line.text.length > 0)
614
+ .slice(0, 8)
615
+ : [],
616
+ dependencyEdges: asStringArray(evidence.dependencyEdges, 8),
617
+ boundary: typeof evidence.boundary === 'string' ? evidence.boundary : null,
618
+ explanation: typeof evidence.explanation === 'string' ? evidence.explanation : null,
619
+ }
620
+ : null,
621
+ remediationGuidance: remediationGuidance
622
+ ? {
623
+ actionability: typeof remediationGuidance.actionability === 'string'
624
+ ? remediationGuidance.actionability
625
+ : null,
626
+ evidenceTier: typeof remediationGuidance.evidenceTier === 'string'
627
+ ? remediationGuidance.evidenceTier
628
+ : null,
629
+ minimalCorrection: typeof remediationGuidance.minimalCorrection === 'string'
630
+ ? remediationGuidance.minimalCorrection
631
+ : null,
632
+ boundaryToPreserve: typeof remediationGuidance.boundaryToPreserve === 'string'
633
+ ? remediationGuidance.boundaryToPreserve
634
+ : null,
635
+ verifyAfterRemediation: typeof remediationGuidance.verifyAfterRemediation === 'string'
636
+ ? remediationGuidance.verifyAfterRemediation
637
+ : null,
638
+ uncertainty: asStringArray(remediationGuidance.uncertainty, 6),
639
+ }
640
+ : null,
641
+ };
642
+ })
643
+ .slice(0, 8)
644
+ : [];
645
+ const narratives = Array.isArray(drift.narratives)
646
+ ? drift.narratives
647
+ .map((entry) => asRecord(entry))
648
+ .filter((entry) => entry !== null)
649
+ .map((entry) => ({
650
+ category: typeof entry.category === 'string' ? entry.category : 'unknown',
651
+ severity: typeof entry.severity === 'string' ? entry.severity : 'unknown',
652
+ summary: typeof entry.summary === 'string' ? entry.summary : 'Compressed governance narrative detected.',
653
+ rootCause: typeof entry.rootCause === 'string' ? entry.rootCause : 'Root cause unavailable.',
654
+ operationalRisk: typeof entry.operationalRisk === 'string' ? entry.operationalRisk : 'Operational risk unavailable.',
655
+ remediationBoundary: typeof entry.remediationBoundary === 'string' ? entry.remediationBoundary : 'Keep remediation inside the approved scope.',
656
+ causalChain: asStringArray(entry.causalChain, 8),
657
+ affectedFiles: asStringArray(entry.affectedFiles, 16),
658
+ affectedModules: asStringArray(entry.affectedModules, 16),
659
+ affectedServices: asStringArray(entry.affectedServices, 16),
660
+ }))
661
+ .slice(0, 6)
662
+ : [];
663
+ const riskSynthesisRecord = asRecord(drift.riskSynthesis);
664
+ const priorityCountsRecord = asRecord(riskSynthesisRecord?.priorityCounts);
665
+ const governancePostureRecord = asRecord(drift.governancePosture);
666
+ const posturePriorityCountsRecord = asRecord(governancePostureRecord?.priorityCounts);
667
+ const governanceDecisionsRecord = asRecord(drift.governanceDecisions);
668
+ return {
669
+ source: typeof drift.source === 'string' ? drift.source : null,
670
+ confidence: typeof drift.confidence === 'string' ? drift.confidence : null,
671
+ rolloutRisk: typeof drift.rolloutRisk === 'string' ? drift.rolloutRisk : null,
672
+ unexpectedFiles: asStringArray(drift.unexpectedFiles, 20),
673
+ unexpectedModules: asStringArray(drift.unexpectedModules, 20),
674
+ unexpectedServices: asStringArray(drift.unexpectedServices, 20),
675
+ impactedModules: asStringArray(drift.impactedModules, 20),
676
+ impactedServices: asStringArray(drift.impactedServices, 20),
677
+ impactedRuntimeFlows: asStringArray(drift.impactedRuntimeFlows, 20),
678
+ affectedRolloutUnits: asStringArray(drift.affectedRolloutUnits, 20),
679
+ findings,
680
+ narratives,
681
+ riskSynthesis: riskSynthesisRecord
682
+ ? {
683
+ overallRisk: typeof riskSynthesisRecord.overallRisk === 'string' ? riskSynthesisRecord.overallRisk : null,
684
+ summary: typeof riskSynthesisRecord.summary === 'string' ? riskSynthesisRecord.summary : null,
685
+ primaryNarratives: asStringArray(riskSynthesisRecord.primaryNarratives, 6),
686
+ rawFindingCount: typeof riskSynthesisRecord.rawFindingCount === 'number' ? riskSynthesisRecord.rawFindingCount : null,
687
+ compressedNarrativeCount: typeof riskSynthesisRecord.compressedNarrativeCount === 'number'
688
+ ? riskSynthesisRecord.compressedNarrativeCount
689
+ : null,
690
+ authExposure: riskSynthesisRecord.authExposure === true,
691
+ infraExposure: riskSynthesisRecord.infraExposure === true,
692
+ deploymentExposure: riskSynthesisRecord.deploymentExposure === true,
693
+ dependencyExposure: riskSynthesisRecord.dependencyExposure === true,
694
+ transitiveImpactCount: typeof riskSynthesisRecord.transitiveImpactCount === 'number'
695
+ ? riskSynthesisRecord.transitiveImpactCount
696
+ : null,
697
+ runtimeFlowExposure: riskSynthesisRecord.runtimeFlowExposure === true,
698
+ externalSideEffectExposure: riskSynthesisRecord.externalSideEffectExposure === true,
699
+ stateOwnershipExposure: riskSynthesisRecord.stateOwnershipExposure === true,
700
+ affectedRolloutUnits: asStringArray(riskSynthesisRecord.affectedRolloutUnits, 12),
701
+ cascadingRisk: typeof riskSynthesisRecord.cascadingRisk === 'string'
702
+ ? riskSynthesisRecord.cascadingRisk
703
+ : null,
704
+ rolloutTrust: typeof riskSynthesisRecord.rolloutTrust === 'string'
705
+ ? riskSynthesisRecord.rolloutTrust
706
+ : null,
707
+ governanceGate: typeof riskSynthesisRecord.governanceGate === 'string'
708
+ ? riskSynthesisRecord.governanceGate
709
+ : null,
710
+ postureSummary: typeof riskSynthesisRecord.postureSummary === 'string'
711
+ ? riskSynthesisRecord.postureSummary
712
+ : null,
713
+ priorityCounts: priorityCountsRecord
714
+ ? {
715
+ p0RolloutBlockers: typeof priorityCountsRecord.p0RolloutBlockers === 'number'
716
+ ? priorityCountsRecord.p0RolloutBlockers
717
+ : 0,
718
+ p1ArchitectureBlockers: typeof priorityCountsRecord.p1ArchitectureBlockers === 'number'
719
+ ? priorityCountsRecord.p1ArchitectureBlockers
720
+ : 0,
721
+ p2ReviewRequired: typeof priorityCountsRecord.p2ReviewRequired === 'number'
722
+ ? priorityCountsRecord.p2ReviewRequired
723
+ : 0,
724
+ p3Advisory: typeof priorityCountsRecord.p3Advisory === 'number'
725
+ ? priorityCountsRecord.p3Advisory
726
+ : 0,
727
+ }
728
+ : null,
729
+ remediationOrder: asStringArray(riskSynthesisRecord.remediationOrder, 12),
730
+ }
731
+ : null,
732
+ governancePosture: governancePostureRecord
733
+ ? {
734
+ rolloutTrust: typeof governancePostureRecord.rolloutTrust === 'string'
735
+ ? governancePostureRecord.rolloutTrust
736
+ : null,
737
+ governanceGate: typeof governancePostureRecord.governanceGate === 'string'
738
+ ? governancePostureRecord.governanceGate
739
+ : null,
740
+ summary: typeof governancePostureRecord.summary === 'string'
741
+ ? governancePostureRecord.summary
742
+ : null,
743
+ reasons: asStringArray(governancePostureRecord.reasons, 6),
744
+ priorityCounts: posturePriorityCountsRecord
745
+ ? {
746
+ p0RolloutBlockers: typeof posturePriorityCountsRecord.p0RolloutBlockers === 'number'
747
+ ? posturePriorityCountsRecord.p0RolloutBlockers
748
+ : 0,
749
+ p1ArchitectureBlockers: typeof posturePriorityCountsRecord.p1ArchitectureBlockers === 'number'
750
+ ? posturePriorityCountsRecord.p1ArchitectureBlockers
751
+ : 0,
752
+ p2ReviewRequired: typeof posturePriorityCountsRecord.p2ReviewRequired === 'number'
753
+ ? posturePriorityCountsRecord.p2ReviewRequired
754
+ : 0,
755
+ p3Advisory: typeof posturePriorityCountsRecord.p3Advisory === 'number'
756
+ ? posturePriorityCountsRecord.p3Advisory
757
+ : 0,
758
+ }
759
+ : null,
760
+ remediationOrder: asStringArray(governancePostureRecord.remediationOrder, 12),
761
+ }
762
+ : null,
763
+ governanceDecisions: governanceDecisionsRecord
764
+ ? {
765
+ sourcePath: typeof governanceDecisionsRecord.sourcePath === 'string'
766
+ ? governanceDecisionsRecord.sourcePath
767
+ : null,
768
+ decisionsApplied: typeof governanceDecisionsRecord.decisionsApplied === 'number'
769
+ ? governanceDecisionsRecord.decisionsApplied
770
+ : 0,
771
+ activeOverrides: typeof governanceDecisionsRecord.activeOverrides === 'number'
772
+ ? governanceDecisionsRecord.activeOverrides
773
+ : 0,
774
+ expiredOverrides: typeof governanceDecisionsRecord.expiredOverrides === 'number'
775
+ ? governanceDecisionsRecord.expiredOverrides
776
+ : 0,
777
+ findingsChanged: typeof governanceDecisionsRecord.findingsChanged === 'number'
778
+ ? governanceDecisionsRecord.findingsChanged
779
+ : 0,
780
+ lineage: Array.isArray(governanceDecisionsRecord.lineage)
781
+ ? governanceDecisionsRecord.lineage
782
+ .map((entry) => extractGovernanceDecisionLineage(entry))
783
+ .filter((entry) => entry !== null)
784
+ .slice(0, 12)
785
+ : [],
786
+ }
787
+ : null,
788
+ };
789
+ }
790
+ function extractIntentGovernance(verifyOutput) {
791
+ const intentGovernance = asRecord(verifyOutput.intentGovernance);
792
+ if (!intentGovernance) {
793
+ return null;
794
+ }
795
+ return {
796
+ source: typeof intentGovernance.source === 'string' ? intentGovernance.source : null,
797
+ deterministic: intentGovernance.deterministic === true,
798
+ flagged: intentGovernance.flagged === true,
799
+ confidence: typeof intentGovernance.confidence === 'string' ? intentGovernance.confidence : null,
800
+ rolloutRisk: typeof intentGovernance.rolloutRisk === 'string' ? intentGovernance.rolloutRisk : null,
801
+ canonicalFindingCount: typeof intentGovernance.canonicalFindingCount === 'number' ? intentGovernance.canonicalFindingCount : null,
802
+ blockingFindingCount: typeof intentGovernance.blockingFindingCount === 'number' ? intentGovernance.blockingFindingCount : null,
803
+ advisoryFindingCount: typeof intentGovernance.advisoryFindingCount === 'number' ? intentGovernance.advisoryFindingCount : null,
804
+ riskSummary: typeof intentGovernance.riskSummary === 'string' ? intentGovernance.riskSummary : null,
805
+ };
806
+ }
807
+ function extractGraphImpact(verifyOutput) {
808
+ const blastRadius = asRecord(verifyOutput.blastRadius);
809
+ if (!blastRadius) {
810
+ return null;
811
+ }
812
+ return {
813
+ affectedServices: asStringArray(blastRadius.affectedServices, 20),
814
+ impactedModules: asStringArray(blastRadius.impactedModules, 20),
815
+ impactedServices: asStringArray(blastRadius.impactedServices, 20),
816
+ transitiveImpactCount: typeof blastRadius.transitiveImpactCount === 'number' ? blastRadius.transitiveImpactCount : null,
817
+ rolloutComplexity: typeof blastRadius.rolloutComplexity === 'string' ? blastRadius.rolloutComplexity : null,
818
+ affectedRuntimeFlows: asStringArray(blastRadius.affectedRuntimeFlows, 20),
819
+ affectedRolloutUnits: asStringArray(blastRadius.affectedRolloutUnits, 20),
820
+ cascadingRisk: typeof blastRadius.cascadingRisk === 'string' ? blastRadius.cascadingRisk : null,
821
+ stateOwnershipExposure: blastRadius.stateOwnershipExposure === true,
822
+ externalSideEffectExposure: blastRadius.externalSideEffectExposure === true,
823
+ authTouched: blastRadius.authTouched === true,
824
+ apiTouched: blastRadius.apiTouched === true,
825
+ infraTouched: blastRadius.infraTouched === true,
826
+ deploymentTouched: blastRadius.deploymentTouched === true,
827
+ dependencyManifestTouched: blastRadius.dependencyManifestTouched === true,
828
+ };
829
+ }
830
+ function deriveModulePathForExport(filePath) {
831
+ const normalized = filePath.replace(/\\/g, '/').replace(/^\.\//, '').trim();
832
+ const parts = normalized.split('/').filter(Boolean);
833
+ if (parts.length <= 1)
834
+ return parts[0] || normalized;
835
+ if (['src', 'app', 'apps', 'services', 'packages', 'libs', 'lib', 'web'].includes(parts[0]) && parts.length >= 2) {
836
+ return `${parts[0]}/${parts[1]}`;
837
+ }
838
+ return parts[0];
839
+ }
840
+ function selectRelevantNarratives(driftIntelligence, filePath, ruleId) {
841
+ if (!driftIntelligence || driftIntelligence.narratives.length === 0) {
842
+ return [];
843
+ }
844
+ const moduleName = deriveModulePathForExport(filePath);
845
+ const driftRuleCategory = ruleId.startsWith('drift_') && ruleId.includes(':')
846
+ ? ruleId.split(':').slice(1).join(':')
847
+ : null;
848
+ const matched = driftIntelligence.narratives.filter((entry) => entry.affectedFiles.includes(filePath)
849
+ || entry.affectedModules.includes(moduleName)
850
+ || (driftRuleCategory ? entry.category.includes(driftRuleCategory.replace('drift_intelligence:', '')) : false));
851
+ const selected = matched.length > 0 ? matched : driftIntelligence.narratives.slice(0, 3);
852
+ return selected.slice(0, 3).map((entry) => ({
853
+ category: entry.category,
854
+ severity: entry.severity,
855
+ summary: entry.summary,
856
+ rootCause: entry.rootCause,
857
+ operationalRisk: entry.operationalRisk,
858
+ remediationBoundary: entry.remediationBoundary,
859
+ causalChain: entry.causalChain.slice(0, 5),
860
+ }));
861
+ }
862
+ function dedupeStrings(values, limit = 12) {
863
+ return [...new Set(values.map((value) => value.trim()).filter(Boolean))].slice(0, limit);
864
+ }
865
+ function deriveSemanticExportInsights(engineeringContext, driftIntelligence, relevantNarratives, filePath) {
866
+ const moduleName = deriveModulePathForExport(filePath);
867
+ const touchedOwnership = engineeringContext?.ownershipBoundaries.filter((boundary) => boundary.name === moduleName
868
+ || driftIntelligence?.unexpectedModules.includes(boundary.name)
869
+ || driftIntelligence?.unexpectedServices.includes(boundary.name)
870
+ || relevantNarratives.some((entry) => entry.summary.includes(boundary.name))) || [];
871
+ const violatedContracts = dedupeStrings([
872
+ ...(engineeringContext?.semanticExpectations?.contractIds || []),
873
+ ...touchedOwnership.flatMap((boundary) => boundary.forbiddenResponsibilities.map((item) => `${boundary.name}:${item}`)),
874
+ ], 16);
875
+ const ownershipBoundaryCrossed = dedupeStrings(touchedOwnership.map((boundary) => `${boundary.name} (${boundary.primaryOwner})`), 12);
876
+ const invariantSummaries = dedupeStrings([
877
+ ...(engineeringContext?.invariants
878
+ .filter((invariant) => !invariant.boundaryName
879
+ || touchedOwnership.some((boundary) => boundary.name === invariant.boundaryName)
880
+ || relevantNarratives.some((entry) => entry.summary.includes(invariant.boundaryName || ''))
881
+ || invariant.expectation.includes(moduleName))
882
+ .map((invariant) => invariant.expectation) || []),
883
+ ...relevantNarratives
884
+ .filter((entry) => entry.category === 'ownership-boundary-breach'
885
+ || entry.category === 'architectural-invariant-erosion'
886
+ || entry.category === 'semantic-coupling')
887
+ .map((entry) => entry.rootCause),
888
+ ], 12);
889
+ const semanticRiskSummary = relevantNarratives[0]?.operationalRisk
890
+ || driftIntelligence?.riskSynthesis?.summary
891
+ || null;
892
+ return {
893
+ violatedContracts,
894
+ ownershipBoundaryCrossed,
895
+ invariantSummaries,
896
+ semanticRiskSummary,
897
+ };
898
+ }
899
+ function buildMcpContext(surroundingContext, engineeringContext, driftIntelligence, graphImpact, relevantNarratives, semanticInsights, intentGovernance) {
900
+ const lines = [];
901
+ if (engineeringContext?.intentSummary) {
902
+ lines.push(`Intent: ${engineeringContext.intentSummary}`);
903
+ }
904
+ if (engineeringContext) {
905
+ lines.push(`Approved scope: files=${engineeringContext.approvedScope.files.slice(0, 6).join(', ') || 'none'}; modules=${engineeringContext.approvedScope.modules.slice(0, 6).join(', ') || 'none'}; services=${engineeringContext.approvedScope.services.slice(0, 6).join(', ') || 'none'}`);
906
+ }
907
+ if (driftIntelligence?.riskSynthesis?.summary) {
908
+ lines.push(`Risk synthesis: ${driftIntelligence.riskSynthesis.summary}`);
909
+ }
910
+ if (driftIntelligence?.governancePosture?.summary) {
911
+ lines.push(`Governance posture: ${driftIntelligence.governancePosture.governanceGate || 'advisory'} / ${driftIntelligence.governancePosture.rolloutTrust || 'rollout-safe'} — ${driftIntelligence.governancePosture.summary}`);
912
+ }
913
+ if (driftIntelligence?.governanceDecisions && driftIntelligence.governanceDecisions.decisionsApplied > 0) {
914
+ lines.push(`Governance decisions: ${driftIntelligence.governanceDecisions.activeOverrides} active, ${driftIntelligence.governanceDecisions.expiredOverrides} expired/invalid, ${driftIntelligence.governanceDecisions.findingsChanged} changed finding posture.`);
915
+ }
916
+ if (driftIntelligence?.findings.length) {
917
+ driftIntelligence.findings.slice(0, 3).forEach((finding, index) => {
918
+ lines.push(`Drift evidence ${index + 1}: [${finding.priority || 'p2-review-required'} / ${finding.governanceGate || 'review-blocker'} / ${finding.actionability || 'review-required'} / ${finding.evidenceTier || 'unknown-evidence'}] ${finding.message}`);
919
+ if (finding.rolloutTrust) {
920
+ lines.push(`Rollout posture ${index + 1}: ${finding.rolloutTrust}`);
921
+ }
922
+ if (finding.evidence?.explanation) {
923
+ lines.push(`Evidence basis ${index + 1}: ${finding.evidence.explanation}`);
924
+ }
925
+ if (finding.evidence?.changedLines.length) {
926
+ const lineRefs = finding.evidence.changedLines
927
+ .slice(0, 3)
928
+ .map((line) => `${line.file}:${line.line}`)
929
+ .join(', ');
930
+ lines.push(`Changed-line evidence ${index + 1}: ${lineRefs}`);
931
+ }
932
+ if (finding.evidence?.dependencyEdges.length) {
933
+ lines.push(`Dependency edge evidence ${index + 1}: ${finding.evidence.dependencyEdges.slice(0, 4).join(' | ')}`);
934
+ }
935
+ if (finding.relationships.length) {
936
+ lines.push(`Finding relationship ${index + 1}: ${finding.relationships
937
+ .slice(0, 2)
938
+ .map((relationship) => `${relationship.type}->${relationship.targetFindingId}`)
939
+ .join(' | ')}`);
940
+ }
941
+ if (finding.governanceDecision) {
942
+ lines.push(`Governance decision ${index + 1}: ${finding.governanceDecision.state} by ${finding.governanceDecision.actor}; reason=${finding.governanceDecision.reason}; lineage=${finding.governanceDecision.lineageHash}`);
943
+ }
944
+ if (finding.remediationGuidance?.minimalCorrection) {
945
+ lines.push(`Bounded correction ${index + 1}: ${finding.remediationGuidance.minimalCorrection}`);
946
+ }
947
+ if (finding.remediationGuidance?.uncertainty.length) {
948
+ lines.push(`Uncertainty ${index + 1}: ${finding.remediationGuidance.uncertainty.slice(0, 2).join(' | ')}`);
949
+ }
950
+ });
951
+ }
952
+ if (intentGovernance) {
953
+ lines.push(`Intent governance: source=${intentGovernance.source || 'unknown'}; deterministic=${intentGovernance.deterministic ? 'yes' : 'no'}; findings=${intentGovernance.canonicalFindingCount ?? 0}; blocking=${intentGovernance.blockingFindingCount ?? 0}; rollout=${intentGovernance.rolloutRisk || 'unknown'}`);
954
+ }
955
+ if (semanticInsights.ownershipBoundaryCrossed.length > 0) {
956
+ lines.push(`Ownership boundary: ${semanticInsights.ownershipBoundaryCrossed.join(' | ')}`);
957
+ }
958
+ if (semanticInsights.violatedContracts.length > 0) {
959
+ lines.push(`Violated contracts: ${semanticInsights.violatedContracts.slice(0, 6).join(' | ')}`);
960
+ }
961
+ if (semanticInsights.invariantSummaries.length > 0) {
962
+ lines.push(`Invariant expectations: ${semanticInsights.invariantSummaries.slice(0, 3).join(' | ')}`);
963
+ }
964
+ if (semanticInsights.semanticRiskSummary) {
965
+ lines.push(`Semantic risk: ${semanticInsights.semanticRiskSummary}`);
966
+ }
967
+ if (engineeringContext?.semanticExpectations?.expectedBehaviorKinds.length) {
968
+ lines.push(`Expected runtime behaviors: ${engineeringContext.semanticExpectations.expectedBehaviorKinds.slice(0, 6).join(' | ')}`);
969
+ }
970
+ if (engineeringContext?.semanticExpectations?.expectedRuntimeFlows.length) {
971
+ lines.push(`Expected runtime flows: ${engineeringContext.semanticExpectations.expectedRuntimeFlows.slice(0, 6).join(' | ')}`);
972
+ }
973
+ if (engineeringContext?.semanticExpectations?.expectedRolloutUnits.length) {
974
+ lines.push(`Expected rollout units: ${engineeringContext.semanticExpectations.expectedRolloutUnits.slice(0, 6).join(' | ')}`);
975
+ }
976
+ if (engineeringContext?.runtimeBehaviors.length) {
977
+ const summaries = engineeringContext.runtimeBehaviors
978
+ .slice(0, 4)
979
+ .map((entry) => `${entry.boundaryName}:${entry.behaviorKinds.slice(0, 3).join('/') || 'unknown'}`);
980
+ lines.push(`Runtime behaviors: ${summaries.join(' | ')}`);
981
+ }
982
+ if (engineeringContext?.deploymentBoundaries.length) {
983
+ const summaries = engineeringContext.deploymentBoundaries
984
+ .slice(0, 4)
985
+ .map((entry) => `${entry.name}:${entry.type}:${entry.rolloutUnits.slice(0, 2).join('/') || 'default'}`);
986
+ lines.push(`Deployment boundaries: ${summaries.join(' | ')}`);
987
+ }
988
+ if (relevantNarratives.length > 0) {
989
+ relevantNarratives.forEach((narrative, index) => {
990
+ lines.push(`Narrative ${index + 1}: ${narrative.summary}`);
991
+ lines.push(`Root cause ${index + 1}: ${narrative.rootCause}`);
992
+ });
993
+ }
994
+ else if (driftIntelligence?.findings.length) {
995
+ lines.push(`Drift: ${driftIntelligence.findings.slice(0, 3).map((entry) => entry.message).join(' | ')}`);
996
+ }
997
+ if (graphImpact) {
998
+ lines.push(`Graph impact: services=${graphImpact.impactedServices.slice(0, 6).join(', ') || 'none'}; modules=${graphImpact.impactedModules.slice(0, 6).join(', ') || 'none'}; rollout=${graphImpact.rolloutComplexity || 'unknown'}`);
999
+ if (graphImpact.affectedRuntimeFlows.length > 0) {
1000
+ lines.push(`Runtime flows impacted: ${graphImpact.affectedRuntimeFlows.slice(0, 6).join(' | ')}`);
1001
+ }
1002
+ if (graphImpact.affectedRolloutUnits.length > 0) {
1003
+ lines.push(`Rollout units impacted: ${graphImpact.affectedRolloutUnits.slice(0, 6).join(' | ')}`);
1004
+ }
1005
+ if (graphImpact.cascadingRisk) {
1006
+ lines.push(`Cascading risk: ${graphImpact.cascadingRisk}`);
1007
+ }
1008
+ if (graphImpact.stateOwnershipExposure) {
1009
+ lines.push('State ownership risk: runtime state mutation spans multiple boundaries.');
1010
+ }
1011
+ if (graphImpact.externalSideEffectExposure) {
1012
+ lines.push('External side effects detected in the affected runtime path.');
1013
+ }
1014
+ }
1015
+ if (surroundingContext.trim().length > 0) {
1016
+ lines.push('Code context:');
1017
+ lines.push(surroundingContext);
1018
+ }
1019
+ return lines.join('\n');
1020
+ }
1021
+ function resolveReplayChecksum(verifyOutput) {
1022
+ const direct = typeof verifyOutput.replayChecksum === 'string' && verifyOutput.replayChecksum.trim().length > 0
1023
+ ? verifyOutput.replayChecksum.trim()
1024
+ : null;
1025
+ if (direct)
1026
+ return direct;
1027
+ const nested = verifyOutput.governanceVerification?.replayChecksum;
1028
+ return typeof nested === 'string' && nested.trim().length > 0 ? nested.trim() : null;
1029
+ }
1030
+ function resolveReplayMode(verifyOutput) {
1031
+ const direct = typeof verifyOutput.replayMode === 'string' && verifyOutput.replayMode.trim().length > 0
1032
+ ? verifyOutput.replayMode.trim()
1033
+ : null;
1034
+ if (direct)
1035
+ return direct;
1036
+ const policyOnly = verifyOutput.policyOnly === true;
1037
+ const mode = typeof verifyOutput.mode === 'string' ? verifyOutput.mode : '';
1038
+ if (policyOnly || mode === 'policy_only') {
1039
+ return 'local-structural';
1040
+ }
1041
+ return null;
1042
+ }
254
1043
  function extractCodeSpan(projectRoot, filePath, line) {
255
1044
  if (!filePath || line === null) {
256
1045
  return { codeSpan: '(file or line not available)', surroundingContext: '' };