@neurcode-ai/cli 0.9.65 → 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 (260) hide show
  1. package/dist/commands/bootstrap-policy.d.ts +29 -0
  2. package/dist/commands/bootstrap-policy.d.ts.map +1 -0
  3. package/dist/commands/bootstrap-policy.js +334 -0
  4. package/dist/commands/bootstrap-policy.js.map +1 -0
  5. package/dist/commands/doctor.d.ts.map +1 -1
  6. package/dist/commands/doctor.js +82 -0
  7. package/dist/commands/doctor.js.map +1 -1
  8. package/dist/commands/governance.d.ts +3 -0
  9. package/dist/commands/governance.d.ts.map +1 -0
  10. package/dist/commands/governance.js +390 -0
  11. package/dist/commands/governance.js.map +1 -0
  12. package/dist/commands/quickstart.d.ts +21 -0
  13. package/dist/commands/quickstart.d.ts.map +1 -0
  14. package/dist/commands/quickstart.js +178 -0
  15. package/dist/commands/quickstart.js.map +1 -0
  16. package/dist/commands/remediate-export.d.ts +36 -0
  17. package/dist/commands/remediate-export.d.ts.map +1 -0
  18. package/dist/commands/remediate-export.js +1072 -0
  19. package/dist/commands/remediate-export.js.map +1 -0
  20. package/dist/commands/replay.d.ts.map +1 -1
  21. package/dist/commands/replay.js +14 -0
  22. package/dist/commands/replay.js.map +1 -1
  23. package/dist/commands/session.d.ts +7 -0
  24. package/dist/commands/session.d.ts.map +1 -1
  25. package/dist/commands/session.js +156 -0
  26. package/dist/commands/session.js.map +1 -1
  27. package/dist/commands/start-intent.d.ts.map +1 -1
  28. package/dist/commands/start-intent.js +61 -11
  29. package/dist/commands/start-intent.js.map +1 -1
  30. package/dist/commands/verify-guidance.d.ts +5 -0
  31. package/dist/commands/verify-guidance.d.ts.map +1 -0
  32. package/dist/commands/verify-guidance.js +49 -0
  33. package/dist/commands/verify-guidance.js.map +1 -0
  34. package/dist/commands/verify-output.d.ts +37 -0
  35. package/dist/commands/verify-output.d.ts.map +1 -0
  36. package/dist/commands/verify-output.js +572 -0
  37. package/dist/commands/verify-output.js.map +1 -0
  38. package/dist/commands/verify-render.d.ts +41 -0
  39. package/dist/commands/verify-render.d.ts.map +1 -0
  40. package/dist/commands/verify-render.js +457 -0
  41. package/dist/commands/verify-render.js.map +1 -0
  42. package/dist/commands/verify.d.ts.map +1 -1
  43. package/dist/commands/verify.js +384 -1091
  44. package/dist/commands/verify.js.map +1 -1
  45. package/dist/commands/workspace.d.ts.map +1 -1
  46. package/dist/commands/workspace.js +3 -14
  47. package/dist/commands/workspace.js.map +1 -1
  48. package/dist/context-engine/graph.d.ts.map +1 -1
  49. package/dist/context-engine/graph.js +69 -7
  50. package/dist/context-engine/graph.js.map +1 -1
  51. package/dist/context-engine/scanner.d.ts.map +1 -1
  52. package/dist/context-engine/scanner.js +9 -2
  53. package/dist/context-engine/scanner.js.map +1 -1
  54. package/dist/daemon/compatibility/execution.d.ts +42 -0
  55. package/dist/daemon/compatibility/execution.d.ts.map +1 -0
  56. package/dist/daemon/compatibility/execution.js +183 -0
  57. package/dist/daemon/compatibility/execution.js.map +1 -0
  58. package/dist/daemon/compatibility/mutation.d.ts +24 -0
  59. package/dist/daemon/compatibility/mutation.d.ts.map +1 -0
  60. package/dist/daemon/compatibility/mutation.js +724 -0
  61. package/dist/daemon/compatibility/mutation.js.map +1 -0
  62. package/dist/daemon/routes.d.ts +19 -0
  63. package/dist/daemon/routes.d.ts.map +1 -0
  64. package/dist/daemon/routes.js +123 -0
  65. package/dist/daemon/routes.js.map +1 -0
  66. package/dist/daemon/runtime/execution-bus.d.ts +217 -0
  67. package/dist/daemon/runtime/execution-bus.d.ts.map +1 -0
  68. package/dist/daemon/runtime/execution-bus.js +1420 -0
  69. package/dist/daemon/runtime/execution-bus.js.map +1 -0
  70. package/dist/daemon/runtime/workspace-runtime.d.ts +280 -0
  71. package/dist/daemon/runtime/workspace-runtime.d.ts.map +1 -0
  72. package/dist/daemon/runtime/workspace-runtime.js +1473 -0
  73. package/dist/daemon/runtime/workspace-runtime.js.map +1 -0
  74. package/dist/daemon/server.d.ts.map +1 -1
  75. package/dist/daemon/server.js +171 -874
  76. package/dist/daemon/server.js.map +1 -1
  77. package/dist/daemon/shaping.d.ts +11 -0
  78. package/dist/daemon/shaping.d.ts.map +1 -0
  79. package/dist/daemon/shaping.js +240 -0
  80. package/dist/daemon/shaping.js.map +1 -0
  81. package/dist/governance/canonical-invariants.d.ts +88 -0
  82. package/dist/governance/canonical-invariants.d.ts.map +1 -0
  83. package/dist/governance/canonical-invariants.js +197 -0
  84. package/dist/governance/canonical-invariants.js.map +1 -0
  85. package/dist/governance/canonical-ordering.d.ts +76 -0
  86. package/dist/governance/canonical-ordering.d.ts.map +1 -0
  87. package/dist/governance/canonical-ordering.js +189 -0
  88. package/dist/governance/canonical-ordering.js.map +1 -0
  89. package/dist/governance/canonical-pipeline.d.ts +9 -1
  90. package/dist/governance/canonical-pipeline.d.ts.map +1 -1
  91. package/dist/governance/canonical-pipeline.js +367 -24
  92. package/dist/governance/canonical-pipeline.js.map +1 -1
  93. package/dist/governance/diff-line-provenance.d.ts +59 -0
  94. package/dist/governance/diff-line-provenance.d.ts.map +1 -0
  95. package/dist/governance/diff-line-provenance.js +118 -0
  96. package/dist/governance/diff-line-provenance.js.map +1 -0
  97. package/dist/governance/pilot-readiness.d.ts +34 -0
  98. package/dist/governance/pilot-readiness.d.ts.map +1 -0
  99. package/dist/governance/pilot-readiness.js +226 -0
  100. package/dist/governance/pilot-readiness.js.map +1 -0
  101. package/dist/governance/policy-parity-validator.d.ts +62 -0
  102. package/dist/governance/policy-parity-validator.d.ts.map +1 -0
  103. package/dist/governance/policy-parity-validator.js +137 -0
  104. package/dist/governance/policy-parity-validator.js.map +1 -0
  105. package/dist/governance/remediation-boundary.d.ts +55 -0
  106. package/dist/governance/remediation-boundary.d.ts.map +1 -0
  107. package/dist/governance/remediation-boundary.js +120 -0
  108. package/dist/governance/remediation-boundary.js.map +1 -0
  109. package/dist/governance/structural-cache.d.ts +103 -0
  110. package/dist/governance/structural-cache.d.ts.map +1 -0
  111. package/dist/governance/structural-cache.js +235 -0
  112. package/dist/governance/structural-cache.js.map +1 -0
  113. package/dist/governance/structural-on-diff.d.ts +22 -2
  114. package/dist/governance/structural-on-diff.d.ts.map +1 -1
  115. package/dist/governance/structural-on-diff.js +36 -4
  116. package/dist/governance/structural-on-diff.js.map +1 -1
  117. package/dist/governance/structural-policy-merge.d.ts +8 -0
  118. package/dist/governance/structural-policy-merge.d.ts.map +1 -1
  119. package/dist/governance/structural-policy-merge.js +7 -0
  120. package/dist/governance/structural-policy-merge.js.map +1 -1
  121. package/dist/governance/verify-runtime-guard.d.ts +99 -0
  122. package/dist/governance/verify-runtime-guard.d.ts.map +1 -0
  123. package/dist/governance/verify-runtime-guard.js +129 -0
  124. package/dist/governance/verify-runtime-guard.js.map +1 -0
  125. package/dist/index.js +277 -77
  126. package/dist/index.js.map +1 -1
  127. package/dist/intent-engine/repo-classifier.d.ts +64 -0
  128. package/dist/intent-engine/repo-classifier.d.ts.map +1 -0
  129. package/dist/intent-engine/repo-classifier.js +178 -0
  130. package/dist/intent-engine/repo-classifier.js.map +1 -0
  131. package/dist/structural-rules/index.d.ts +4 -0
  132. package/dist/structural-rules/index.d.ts.map +1 -1
  133. package/dist/structural-rules/index.js +18 -1
  134. package/dist/structural-rules/index.js.map +1 -1
  135. package/dist/structural-rules/python/PY003-broad-except-clause.d.ts +21 -0
  136. package/dist/structural-rules/python/PY003-broad-except-clause.d.ts.map +1 -1
  137. package/dist/structural-rules/python/PY003-broad-except-clause.js +212 -21
  138. package/dist/structural-rules/python/PY003-broad-except-clause.js.map +1 -1
  139. package/dist/structural-rules/python/PY011-thread-lifecycle.d.ts +11 -0
  140. package/dist/structural-rules/python/PY011-thread-lifecycle.d.ts.map +1 -0
  141. package/dist/structural-rules/python/PY011-thread-lifecycle.js +97 -0
  142. package/dist/structural-rules/python/PY011-thread-lifecycle.js.map +1 -0
  143. package/dist/structural-rules/python/PY012-asyncio-run-misuse.d.ts +11 -0
  144. package/dist/structural-rules/python/PY012-asyncio-run-misuse.d.ts.map +1 -0
  145. package/dist/structural-rules/python/PY012-asyncio-run-misuse.js +83 -0
  146. package/dist/structural-rules/python/PY012-asyncio-run-misuse.js.map +1 -0
  147. package/dist/structural-rules/python/PY013-mutable-default-arg.d.ts +11 -0
  148. package/dist/structural-rules/python/PY013-mutable-default-arg.d.ts.map +1 -0
  149. package/dist/structural-rules/python/PY013-mutable-default-arg.js +73 -0
  150. package/dist/structural-rules/python/PY013-mutable-default-arg.js.map +1 -0
  151. package/dist/structural-rules/python/PY014-fixed-sleep-retry.d.ts +11 -0
  152. package/dist/structural-rules/python/PY014-fixed-sleep-retry.d.ts.map +1 -0
  153. package/dist/structural-rules/python/PY014-fixed-sleep-retry.js +115 -0
  154. package/dist/structural-rules/python/PY014-fixed-sleep-retry.js.map +1 -0
  155. package/dist/structural-rules/types.d.ts +12 -0
  156. package/dist/structural-rules/types.d.ts.map +1 -1
  157. package/dist/utils/active-engineering-context.d.ts +12 -0
  158. package/dist/utils/active-engineering-context.d.ts.map +1 -0
  159. package/dist/utils/active-engineering-context.js +67 -0
  160. package/dist/utils/active-engineering-context.js.map +1 -0
  161. package/dist/utils/artifact-io.d.ts +33 -0
  162. package/dist/utils/artifact-io.d.ts.map +1 -0
  163. package/dist/utils/artifact-io.js +183 -0
  164. package/dist/utils/artifact-io.js.map +1 -0
  165. package/dist/utils/change-contract.d.ts +6 -2
  166. package/dist/utils/change-contract.d.ts.map +1 -1
  167. package/dist/utils/change-contract.js +175 -0
  168. package/dist/utils/change-contract.js.map +1 -1
  169. package/dist/utils/context-pack.d.ts +12 -0
  170. package/dist/utils/context-pack.d.ts.map +1 -0
  171. package/dist/utils/context-pack.js +147 -0
  172. package/dist/utils/context-pack.js.map +1 -0
  173. package/dist/utils/control-plane.d.ts +18 -0
  174. package/dist/utils/control-plane.d.ts.map +1 -1
  175. package/dist/utils/control-plane.js +31 -4
  176. package/dist/utils/control-plane.js.map +1 -1
  177. package/dist/utils/drift-intelligence.d.ts +47 -0
  178. package/dist/utils/drift-intelligence.d.ts.map +1 -0
  179. package/dist/utils/drift-intelligence.js +2099 -0
  180. package/dist/utils/drift-intelligence.js.map +1 -0
  181. package/dist/utils/execution-actions.d.ts +22 -0
  182. package/dist/utils/execution-actions.d.ts.map +1 -0
  183. package/dist/utils/execution-actions.js +103 -0
  184. package/dist/utils/execution-actions.js.map +1 -0
  185. package/dist/utils/execution-bus.d.ts +1 -214
  186. package/dist/utils/execution-bus.d.ts.map +1 -1
  187. package/dist/utils/execution-bus.js +15 -1359
  188. package/dist/utils/execution-bus.js.map +1 -1
  189. package/dist/utils/git.d.ts +1 -0
  190. package/dist/utils/git.d.ts.map +1 -1
  191. package/dist/utils/git.js +13 -3
  192. package/dist/utils/git.js.map +1 -1
  193. package/dist/utils/governance-decisions.d.ts +75 -0
  194. package/dist/utils/governance-decisions.d.ts.map +1 -0
  195. package/dist/utils/governance-decisions.js +412 -0
  196. package/dist/utils/governance-decisions.js.map +1 -0
  197. package/dist/utils/governance-provenance.d.ts +1 -1
  198. package/dist/utils/governance-provenance.d.ts.map +1 -1
  199. package/dist/utils/governance-provenance.js +5 -7
  200. package/dist/utils/governance-provenance.js.map +1 -1
  201. package/dist/utils/governance.d.ts +108 -0
  202. package/dist/utils/governance.d.ts.map +1 -1
  203. package/dist/utils/governance.js +209 -7
  204. package/dist/utils/governance.js.map +1 -1
  205. package/dist/utils/intelligence-runtime-common.d.ts +30 -0
  206. package/dist/utils/intelligence-runtime-common.d.ts.map +1 -0
  207. package/dist/utils/intelligence-runtime-common.js +156 -0
  208. package/dist/utils/intelligence-runtime-common.js.map +1 -0
  209. package/dist/utils/intent-contract-diagnostics.d.ts +9 -0
  210. package/dist/utils/intent-contract-diagnostics.d.ts.map +1 -0
  211. package/dist/utils/intent-contract-diagnostics.js +322 -0
  212. package/dist/utils/intent-contract-diagnostics.js.map +1 -0
  213. package/dist/utils/intent-pack.d.ts +15 -0
  214. package/dist/utils/intent-pack.d.ts.map +1 -0
  215. package/dist/utils/intent-pack.js +196 -0
  216. package/dist/utils/intent-pack.js.map +1 -0
  217. package/dist/utils/plan-sync.d.ts +1 -0
  218. package/dist/utils/plan-sync.d.ts.map +1 -1
  219. package/dist/utils/plan-sync.js +23 -0
  220. package/dist/utils/plan-sync.js.map +1 -1
  221. package/dist/utils/policy-decision.d.ts +5 -0
  222. package/dist/utils/policy-decision.d.ts.map +1 -0
  223. package/dist/utils/policy-decision.js +17 -0
  224. package/dist/utils/policy-decision.js.map +1 -0
  225. package/dist/utils/replay-custody.d.ts +43 -0
  226. package/dist/utils/replay-custody.d.ts.map +1 -0
  227. package/dist/utils/replay-custody.js +168 -0
  228. package/dist/utils/replay-custody.js.map +1 -0
  229. package/dist/utils/replay-runtime.d.ts +13 -0
  230. package/dist/utils/replay-runtime.d.ts.map +1 -1
  231. package/dist/utils/replay-runtime.js +96 -9
  232. package/dist/utils/replay-runtime.js.map +1 -1
  233. package/dist/utils/repository-intelligence.d.ts +9 -0
  234. package/dist/utils/repository-intelligence.d.ts.map +1 -0
  235. package/dist/utils/repository-intelligence.js +372 -0
  236. package/dist/utils/repository-intelligence.js.map +1 -0
  237. package/dist/utils/runtime-events.d.ts.map +1 -1
  238. package/dist/utils/runtime-events.js +25 -6
  239. package/dist/utils/runtime-events.js.map +1 -1
  240. package/dist/utils/semantic-contract-intelligence.d.ts +20 -0
  241. package/dist/utils/semantic-contract-intelligence.d.ts.map +1 -0
  242. package/dist/utils/semantic-contract-intelligence.js +825 -0
  243. package/dist/utils/semantic-contract-intelligence.js.map +1 -0
  244. package/dist/utils/session-continuity.d.ts +56 -0
  245. package/dist/utils/session-continuity.d.ts.map +1 -0
  246. package/dist/utils/session-continuity.js +318 -0
  247. package/dist/utils/session-continuity.js.map +1 -0
  248. package/dist/utils/verification-evidence.d.ts.map +1 -1
  249. package/dist/utils/verification-evidence.js +4 -1
  250. package/dist/utils/verification-evidence.js.map +1 -1
  251. package/dist/utils/verify-runtime-stability.d.ts +142 -0
  252. package/dist/utils/verify-runtime-stability.d.ts.map +1 -0
  253. package/dist/utils/verify-runtime-stability.js +230 -0
  254. package/dist/utils/verify-runtime-stability.js.map +1 -0
  255. package/dist/utils/workspace-runtime.d.ts +1 -266
  256. package/dist/utils/workspace-runtime.d.ts.map +1 -1
  257. package/dist/utils/workspace-runtime.js +15 -1412
  258. package/dist/utils/workspace-runtime.js.map +1 -1
  259. package/package.json +11 -10
  260. package/LICENSE +0 -201
@@ -0,0 +1,1072 @@
1
+ "use strict";
2
+ /**
3
+ * neurcode remediate-export
4
+ *
5
+ * Exports a structured, deterministic remediation payload for a governance finding.
6
+ * The payload is designed to be passed to an external AI coding assistant
7
+ * (Cursor, Claude, Codex, GitHub Copilot) for remediation.
8
+ *
9
+ * TRUST BOUNDARY:
10
+ * Neurcode detects and exports. Your AI assistant remediates.
11
+ * This command never modifies any file.
12
+ *
13
+ * Usage:
14
+ * neurcode remediate-export --finding <id>
15
+ * neurcode remediate-export --finding-index 0
16
+ * neurcode remediate-export --all
17
+ * neurcode remediate-export --finding <id> --format mcp
18
+ * neurcode remediate-export --finding <id> --out ./payload.json
19
+ * neurcode remediate-export --finding <id> --copy
20
+ * neurcode remediate-export --verify-output-file ./verify.json --project-root ./repo
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.remediateExportCommand = remediateExportCommand;
24
+ const fs_1 = require("fs");
25
+ const path_1 = require("path");
26
+ const crypto_1 = require("crypto");
27
+ const child_process_1 = require("child_process");
28
+ const cli_json_1 = require("../utils/cli-json");
29
+ const chalk = (0, cli_json_1.loadChalk)();
30
+ // ── Trust boundary statement — fixed, never changes ──────────────────────────
31
+ const TRUST_BOUNDARY_STATEMENT = 'Neurcode deterministically detects and governs. ' +
32
+ 'Your AI coding assistant (Cursor, Claude, Codex, GitHub Copilot) performs remediation. ' +
33
+ 'Neurcode never autonomously modifies production code.';
34
+ // ── Remediation category map — deterministic, ruleId-keyed ───────────────────
35
+ const REMEDIATION_CATEGORY = {
36
+ PY003: 'exception-handling',
37
+ PY005: 'input-validation',
38
+ PY001: 'async-lifecycle',
39
+ PY006: 'async-lifecycle',
40
+ PY007: 'resource-lifecycle',
41
+ PY008: 'retry-resilience',
42
+ PY009: 'security',
43
+ PY010: 'resource-lifecycle',
44
+ PY011: 'thread-lifecycle',
45
+ PY012: 'async-lifecycle',
46
+ PY013: 'correctness',
47
+ PY014: 'retry-resilience',
48
+ SR001: 'exception-handling',
49
+ SR002: 'data-flow',
50
+ SR003: 'resource-lifecycle',
51
+ SR004: 'input-validation',
52
+ SR009: 'retry-resilience',
53
+ SR010: 'retry-resilience',
54
+ DS001: 'distributed-consistency',
55
+ 'potential-secret-default': 'security',
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',
86
+ };
87
+ // ── Suggested prompt hint per category — advisory, never prescriptive ─────────
88
+ const PROMPT_HINT = {
89
+ 'exception-handling': 'The finding identifies an exception handling pattern that silently swallows errors. ' +
90
+ 'Remediation should ensure exceptions are re-raised or converted to structured error responses.',
91
+ 'input-validation': 'The finding identifies a missing input validation boundary. ' +
92
+ 'Remediation should add schema validation (e.g., Pydantic model) before processing the input.',
93
+ 'async-lifecycle': 'The finding identifies an async pattern that may cause silent failures or event loop blocking. ' +
94
+ 'Remediation should ensure async tasks are tracked and exceptions are handled.',
95
+ 'resource-lifecycle': 'The finding identifies a resource (session, connection, thread) that may not be properly closed. ' +
96
+ 'Remediation should use context managers or explicit cleanup in finally blocks.',
97
+ 'thread-lifecycle': 'The finding identifies a thread created without daemon=True or without a stored reference. ' +
98
+ 'Remediation should set daemon=True and store the thread reference for join() on shutdown.',
99
+ 'retry-resilience': 'The finding identifies a retry pattern without exponential backoff or a thundering-herd risk. ' +
100
+ 'Remediation should implement exponential backoff with jitter.',
101
+ 'security': 'The finding identifies a security-sensitive pattern (hardcoded credential, unsafe deserialization). ' +
102
+ 'Remediation must use environment variables, secret managers, or safe alternatives.',
103
+ 'correctness': 'The finding identifies a correctness issue (e.g., mutable default argument). ' +
104
+ 'Remediation should follow standard Python idioms to avoid shared mutable state.',
105
+ 'distributed-consistency': 'The finding identifies a distributed consistency issue. ' +
106
+ 'Remediation should add compensating logic, idempotency, or saga rollback.',
107
+ 'data-flow': 'The finding identifies a data flow issue (unbounded collection, leaking state). ' +
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.',
111
+ };
112
+ async function remediateExportCommand(options) {
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)) {
118
+ console.error(chalk.red('✗ No verify output found.'));
119
+ console.error(chalk.dim(` Expected: ${verifyPath}`));
120
+ console.error(chalk.dim(' Run: neurcode verify --policy-only --json'));
121
+ console.error(chalk.dim(' Or pass: neurcode remediate-export --verify-output-file <path-to-verify.json>'));
122
+ process.exit(1);
123
+ }
124
+ let verifyOutput;
125
+ try {
126
+ verifyOutput = JSON.parse((0, fs_1.readFileSync)(verifyPath, 'utf-8'));
127
+ }
128
+ catch {
129
+ console.error(chalk.red(`✗ Could not parse verify output: ${verifyPath}`));
130
+ process.exit(1);
131
+ }
132
+ // Collect findings from verify output
133
+ const findings = collectFindings(verifyOutput);
134
+ if (findings.length === 0) {
135
+ console.log(chalk.green('✅ No findings in last verify run. Nothing to export.'));
136
+ return;
137
+ }
138
+ // Select which findings to export
139
+ let selected = [];
140
+ if (options.all) {
141
+ selected = findings;
142
+ }
143
+ else if (options.findingIndex !== undefined) {
144
+ const idx = parseInt(options.findingIndex, 10);
145
+ if (isNaN(idx) || idx < 0 || idx >= findings.length) {
146
+ console.error(chalk.red(`✗ --finding-index ${options.findingIndex} out of range. ${findings.length} findings available.`));
147
+ process.exit(1);
148
+ }
149
+ selected = [findings[idx]];
150
+ }
151
+ else if (options.finding) {
152
+ const found = findings.filter((f) => (f.id ?? f.findingId ?? '') === options.finding ||
153
+ String(f.findingId ?? f.id ?? '').startsWith(options.finding));
154
+ if (found.length === 0) {
155
+ console.error(chalk.red(`✗ Finding "${options.finding}" not found in last verify output.`));
156
+ console.error(chalk.dim(` Available IDs:`));
157
+ findings.slice(0, 10).forEach((f) => console.error(chalk.dim(` ${f.id ?? f.findingId ?? '(no id)'} — ${f.ruleId ?? f.rule ?? '?'} @ ${f.file ?? f.filePath ?? '?'}`)));
158
+ process.exit(1);
159
+ }
160
+ selected = found;
161
+ }
162
+ else {
163
+ // Default: export index 0 with a prompt
164
+ console.log(chalk.dim(`No finding specified. Exporting finding at index 0. Use --finding-index N or --all.\n`));
165
+ selected = [findings[0]];
166
+ }
167
+ const format = options.format ?? 'json';
168
+ const replayChecksum = resolveReplayChecksum(verifyOutput);
169
+ const replayMode = resolveReplayMode(verifyOutput);
170
+ const payloads = selected.map((finding) => buildPayload(finding, verifyOutput, projectRoot, replayChecksum, replayMode, format));
171
+ const output = payloads.length === 1
172
+ ? JSON.stringify(format === 'mcp' ? payloads[0].mcpEnvelope : payloads[0], null, 2)
173
+ : JSON.stringify(format === 'mcp' ? payloads.map(p => p.mcpEnvelope) : payloads, null, 2);
174
+ // Write to file or stdout
175
+ if (options.out) {
176
+ const outPath = (0, path_1.resolve)(projectRoot, options.out);
177
+ (0, fs_1.writeFileSync)(outPath, output, 'utf-8');
178
+ console.log(chalk.green(`✅ Remediation export written to ${outPath}`));
179
+ }
180
+ else {
181
+ console.log(output);
182
+ }
183
+ // Copy to clipboard
184
+ if (options.copy) {
185
+ try {
186
+ (0, child_process_1.execSync)('pbcopy', { input: output });
187
+ console.error(chalk.green('\n✅ Remediation payload copied to clipboard.'));
188
+ }
189
+ catch {
190
+ console.error(chalk.yellow('\n⚠ --copy failed (pbcopy not available on this system).'));
191
+ }
192
+ }
193
+ // Print trust boundary reminder
194
+ if (!options.json) {
195
+ console.error(chalk.dim('\n─────────────────────────────────────────────────────────'));
196
+ console.error(chalk.cyan(' Trust Boundary'));
197
+ console.error(chalk.dim(' Neurcode detects. Your AI assistant remediates.'));
198
+ console.error(chalk.dim(' Pass this payload to Cursor, Claude, Codex, or any provider.'));
199
+ console.error(chalk.dim(' Neurcode will re-verify after remediation.'));
200
+ console.error(chalk.dim('─────────────────────────────────────────────────────────\n'));
201
+ }
202
+ }
203
+ // ── Builders ──────────────────────────────────────────────────────────────────
204
+ function collectFindings(verifyOutput) {
205
+ // Try multiple possible locations in verify output shape
206
+ const govEnvelope = verifyOutput.governanceVerification?.findings ?? [];
207
+ const violations = verifyOutput.violations ?? [];
208
+ const blockingItems = verifyOutput.blockingItems ?? [];
209
+ const advisoryItems = verifyOutput.advisoryItems ?? [];
210
+ if (govEnvelope.length > 0)
211
+ return govEnvelope;
212
+ return [...violations, ...blockingItems, ...advisoryItems];
213
+ }
214
+ function buildPayload(finding, verifyOutput, projectRoot, replayChecksum, replayMode, format) {
215
+ const ruleId = resolveFindingRuleId(finding);
216
+ const filePath = finding.filePath ?? finding.file ?? finding.evidence?.filePath ?? '';
217
+ const line = finding.line ?? finding.evidence?.line ?? null;
218
+ const column = finding.column ?? finding.evidence?.column ?? null;
219
+ const severity = finding.severity ?? 'BLOCKING';
220
+ const determinismClass = finding.determinismClassification ?? finding.determinism ?? 'deterministic-structural';
221
+ const findingId = finding.id ?? finding.findingId ?? '';
222
+ const ruleName = finding.title ?? finding.ruleName ?? finding.name ?? ruleId;
223
+ const operationalExplanation = finding.operationalImplication ?? finding.message ?? finding.explanation ?? '';
224
+ // Extract code span from file if it exists
225
+ const { codeSpan, surroundingContext } = extractCodeSpan(projectRoot, filePath, line);
226
+ // Deterministic export ID
227
+ const exportId = (0, crypto_1.createHash)('sha256')
228
+ .update(`${findingId}|${filePath}|${line ?? 0}|${ruleId}`)
229
+ .digest('hex')
230
+ .slice(0, 32);
231
+ // Finding graph hash (deterministic over finding identity fields)
232
+ const findingGraphHash = (0, crypto_1.createHash)('sha256')
233
+ .update(`${ruleId}|${filePath}|${line ?? 0}|${severity}|${determinismClass}`)
234
+ .digest('hex')
235
+ .slice(0, 16);
236
+ const remediationCategory = REMEDIATION_CATEGORY[ruleId] ?? 'general';
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;
247
+ const policyViolations = [];
248
+ if (finding.structuralMetadata?.policyRef)
249
+ policyViolations.push(finding.structuralMetadata.policyRef);
250
+ if (finding.policy)
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);
283
+ const payload = {
284
+ exportId,
285
+ exportedAt: new Date().toISOString(),
286
+ neurcodeVersion: '0.10.0',
287
+ schemaVersion: '2026-05-14',
288
+ findingId,
289
+ ruleId,
290
+ ruleName,
291
+ severity,
292
+ determinismClass,
293
+ filePath,
294
+ line,
295
+ column,
296
+ codeSpan,
297
+ surroundingContext,
298
+ policyViolations,
299
+ operationalExplanation,
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,
310
+ trustBoundaryStatement: TRUST_BOUNDARY_STATEMENT,
311
+ replayChecksum,
312
+ replayMode,
313
+ findingGraphHash,
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,
325
+ suggestedPromptHint,
326
+ };
327
+ if (format === 'mcp') {
328
+ payload.mcpEnvelope = {
329
+ type: 'neurcode/remediation-request',
330
+ version: '1.0',
331
+ trust: 'deterministic-governance',
332
+ finding: {
333
+ id: findingId,
334
+ ruleId,
335
+ severity,
336
+ file: filePath,
337
+ line,
338
+ codeSpan,
339
+ },
340
+ context: buildMcpContext(surroundingContext, engineeringContext, driftIntelligence, graphImpact, relevantNarratives, semanticInsights, intentGovernance),
341
+ constraint: TRUST_BOUNDARY_STATEMENT,
342
+ promptHint: suggestedPromptHint,
343
+ };
344
+ }
345
+ return payload;
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
+ }
1043
+ function extractCodeSpan(projectRoot, filePath, line) {
1044
+ if (!filePath || line === null) {
1045
+ return { codeSpan: '(file or line not available)', surroundingContext: '' };
1046
+ }
1047
+ const fullPath = (0, path_1.resolve)(projectRoot, filePath);
1048
+ if (!(0, fs_1.existsSync)(fullPath)) {
1049
+ return { codeSpan: `(file not found: ${filePath})`, surroundingContext: '' };
1050
+ }
1051
+ try {
1052
+ const content = (0, fs_1.readFileSync)(fullPath, 'utf-8');
1053
+ const lines = content.split('\n');
1054
+ const zeroIdx = line - 1;
1055
+ const targetLine = lines[zeroIdx] ?? '';
1056
+ const contextStart = Math.max(0, zeroIdx - 5);
1057
+ const contextEnd = Math.min(lines.length - 1, zeroIdx + 5);
1058
+ const contextLines = [];
1059
+ for (let i = contextStart; i <= contextEnd; i++) {
1060
+ const prefix = i === zeroIdx ? '→ ' : ' ';
1061
+ contextLines.push(`${String(i + 1).padStart(4)} ${prefix}${lines[i]}`);
1062
+ }
1063
+ return {
1064
+ codeSpan: targetLine.trim(),
1065
+ surroundingContext: contextLines.join('\n'),
1066
+ };
1067
+ }
1068
+ catch {
1069
+ return { codeSpan: '(could not read file)', surroundingContext: '' };
1070
+ }
1071
+ }
1072
+ //# sourceMappingURL=remediate-export.js.map