@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,724 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createCompatibilityMutationHandlers = createCompatibilityMutationHandlers;
37
+ const fs = __importStar(require("node:fs"));
38
+ const path = __importStar(require("node:path"));
39
+ const node_crypto_1 = require("node:crypto");
40
+ const node_child_process_1 = require("node:child_process");
41
+ const contracts_1 = require("@neurcode-ai/contracts");
42
+ const patch_engine_1 = require("../../patch-engine");
43
+ const diff_1 = require("../../patch-engine/diff");
44
+ const execution_bus_1 = require("../runtime/execution-bus");
45
+ const shaping_1 = require("../shaping");
46
+ function resolveGitRoot(cwd) {
47
+ const result = (0, node_child_process_1.spawnSync)('git', ['-C', cwd, 'rev-parse', '--show-toplevel'], {
48
+ encoding: 'utf-8',
49
+ stdio: ['ignore', 'pipe', 'ignore'],
50
+ });
51
+ if (result.status !== 0)
52
+ return null;
53
+ const value = typeof result.stdout === 'string' ? result.stdout.trim() : '';
54
+ return value.length > 0 ? value : null;
55
+ }
56
+ function captureGitDirtyPaths(cwd) {
57
+ const gitRoot = resolveGitRoot(cwd);
58
+ if (!gitRoot)
59
+ return null;
60
+ const statusResult = (0, node_child_process_1.spawnSync)('git', ['-C', cwd, 'status', '--porcelain=1', '-z', '--untracked-files=all'], {
61
+ encoding: 'utf-8',
62
+ stdio: ['ignore', 'pipe', 'ignore'],
63
+ });
64
+ if (statusResult.status !== 0 || typeof statusResult.stdout !== 'string')
65
+ return null;
66
+ const tokens = statusResult.stdout.split('\0').filter((entry) => entry.length > 0);
67
+ const dirty = new Set();
68
+ for (let index = 0; index < tokens.length; index += 1) {
69
+ const token = tokens[index];
70
+ if (token.length < 4)
71
+ continue;
72
+ const status = token.slice(0, 2);
73
+ const filePath = token.slice(3).trim();
74
+ if (filePath.length > 0) {
75
+ dirty.add(path.resolve(gitRoot, filePath));
76
+ }
77
+ const renamedOrCopied = status.includes('R') || status.includes('C');
78
+ if (renamedOrCopied && index + 1 < tokens.length) {
79
+ index += 1;
80
+ }
81
+ }
82
+ return dirty;
83
+ }
84
+ function hashFileForDiff(absPath) {
85
+ try {
86
+ const stat = fs.statSync(absPath);
87
+ if (!stat.isFile())
88
+ return '<non-file>';
89
+ const content = fs.readFileSync(absPath);
90
+ return (0, node_crypto_1.createHash)('sha256').update(content).digest('hex');
91
+ }
92
+ catch {
93
+ return '<missing>';
94
+ }
95
+ }
96
+ function captureDirtyFileFingerprints(cwd) {
97
+ const dirtyPaths = captureGitDirtyPaths(cwd);
98
+ if (!dirtyPaths)
99
+ return null;
100
+ const map = new Map();
101
+ for (const dirtyPath of dirtyPaths) {
102
+ map.set(dirtyPath, hashFileForDiff(dirtyPath));
103
+ }
104
+ return map;
105
+ }
106
+ function isAllowedPatchSideEffect(absPath, targetAbsPath, cwd) {
107
+ if (absPath === targetAbsPath)
108
+ return true;
109
+ const rel = path.relative(cwd, absPath);
110
+ if (!rel || rel.startsWith('..'))
111
+ return false;
112
+ if (rel === 'neurcode.policy.compiled.json')
113
+ return true;
114
+ return rel === '.neurcode' || rel.startsWith(`.neurcode${path.sep}`);
115
+ }
116
+ function collectUnexpectedPatchSideEffects(before, after, targetAbsPath, cwd) {
117
+ if (!before || !after)
118
+ return [];
119
+ return [...after]
120
+ .filter((entry) => !before.has(entry))
121
+ .filter((entry) => !isAllowedPatchSideEffect(entry, targetAbsPath, cwd))
122
+ .map((entry) => path.relative(cwd, entry).replace(/\\/g, '/'))
123
+ .filter((entry) => entry.length > 0)
124
+ .sort();
125
+ }
126
+ function collectUnexpectedPatchMutations(before, after, targetAbsPath, cwd) {
127
+ if (!before || !after)
128
+ return [];
129
+ const keys = new Set([...before.keys(), ...after.keys()]);
130
+ const unexpected = [];
131
+ for (const key of keys) {
132
+ const beforeHash = before.get(key) ?? '<missing>';
133
+ const afterHash = after.get(key) ?? '<missing>';
134
+ if (beforeHash === afterHash)
135
+ continue;
136
+ if (isAllowedPatchSideEffect(key, targetAbsPath, cwd))
137
+ continue;
138
+ const rel = path.relative(cwd, key).replace(/\\/g, '/');
139
+ if (rel.length > 0 && !rel.startsWith('..')) {
140
+ unexpected.push(rel);
141
+ }
142
+ }
143
+ return unexpected.sort();
144
+ }
145
+ function patternDescriptor(kind, confidence, manualReviewRequired) {
146
+ const labelByKind = {
147
+ missing_validation: 'API input validation guard',
148
+ missing_timeout_handling: 'Outbound request timeout guard',
149
+ unsafe_fetch_without_retries: 'Outbound request retry guard',
150
+ missing_idempotency_keys: 'Mutation idempotency-key guard',
151
+ unsafe_file_uploads: 'Upload MIME/size validation guard',
152
+ missing_auth_middleware: 'Route authentication middleware',
153
+ missing_rate_limiting: 'Route rate limiting middleware',
154
+ missing_token_expiry: 'JWT expiry enforcement',
155
+ unsafe_inner_html_usage: 'Unsafe DOM sink replacement',
156
+ unsafe_sensitive_logging: 'Sensitive log redaction',
157
+ db_in_ui: 'Service-layer boundary placeholder',
158
+ todo_fixme: 'TODO/FIXME debt marker removal',
159
+ };
160
+ const confidenceModel = confidence === 'high'
161
+ ? 'high'
162
+ : confidence === 'medium'
163
+ ? 'medium'
164
+ : 'low';
165
+ return {
166
+ kind,
167
+ label: labelByKind[kind] || kind,
168
+ deterministic: true,
169
+ confidenceModel,
170
+ advisoryOnly: confidenceModel === 'low',
171
+ manualReviewRequired,
172
+ };
173
+ }
174
+ function summarizeDiff(diff) {
175
+ let addedLines = 0;
176
+ let removedLines = 0;
177
+ for (const line of diff.split('\n')) {
178
+ if (line.startsWith('+++') || line.startsWith('---') || line.startsWith('@@'))
179
+ continue;
180
+ if (line.startsWith('+'))
181
+ addedLines += 1;
182
+ if (line.startsWith('-'))
183
+ removedLines += 1;
184
+ }
185
+ const changedLines = addedLines + removedLines;
186
+ return {
187
+ addedLines,
188
+ removedLines,
189
+ changedLines,
190
+ summary: `${changedLines} changed line(s): +${addedLines} / -${removedLines}`,
191
+ };
192
+ }
193
+ function extractRequestInputUsage(content) {
194
+ const accessMatch = content.match(/\b(req|request)\.(body|params|query)\b/);
195
+ if (!accessMatch)
196
+ return null;
197
+ const receiver = accessMatch[1];
198
+ const field = accessMatch[2];
199
+ const fieldRegex = new RegExp(`\\b${receiver}\\.${field}\\.([A-Za-z_$][\\w$]*)\\b`, 'g');
200
+ const fields = [];
201
+ const seen = new Set();
202
+ let match = fieldRegex.exec(content);
203
+ while (match) {
204
+ const fieldName = match[1];
205
+ if (!seen.has(fieldName)) {
206
+ seen.add(fieldName);
207
+ fields.push(fieldName);
208
+ }
209
+ match = fieldRegex.exec(content);
210
+ }
211
+ return { receiver, field, fields };
212
+ }
213
+ function buildPatchPreviewReasoning(patternKind, targetPath, beforeContent) {
214
+ if (!patternKind)
215
+ return null;
216
+ if (patternKind === 'missing_validation') {
217
+ const usage = extractRequestInputUsage(beforeContent);
218
+ if (!usage) {
219
+ return {
220
+ summary: 'Adds deterministic API input validation guard.',
221
+ why: 'This file accesses request input without a validation boundary check.',
222
+ risk: 'Malformed input can cause runtime errors or unsafe processing paths.',
223
+ expectedOutcome: 'Invalid requests fail fast and valid requests continue unchanged.',
224
+ };
225
+ }
226
+ const noun = usage.field === 'body' ? 'request body' : usage.field === 'params' ? 'route params' : 'query params';
227
+ const fieldSummary = usage.fields.length > 0 ? usage.fields.join(', ') : 'no explicit property access detected';
228
+ return {
229
+ summary: `Adds deterministic validation before reading ${usage.receiver}.${usage.field}.`,
230
+ why: `${targetPath} reads ${noun} fields (${fieldSummary}) before validation.`,
231
+ risk: `Without boundary validation, malformed ${noun} may propagate into handler logic.`,
232
+ expectedOutcome: `Invalid ${noun} returns HTTP 400 early; valid requests keep existing behavior.`,
233
+ fields: usage.fields,
234
+ };
235
+ }
236
+ if (patternKind === 'db_in_ui') {
237
+ return {
238
+ summary: 'Suggests moving direct DB access behind a service boundary.',
239
+ why: `${targetPath} appears to perform direct data access in a non-service layer.`,
240
+ risk: 'Layering violations increase coupling and make behavior harder to govern.',
241
+ expectedOutcome: 'Patch inserts a deterministic placeholder to redirect to service-layer logic.',
242
+ };
243
+ }
244
+ if (patternKind === 'missing_auth_middleware') {
245
+ return {
246
+ summary: 'Adds deterministic authentication middleware to the route definition.',
247
+ why: `${targetPath} appears to expose a request handler without an auth middleware guard.`,
248
+ risk: 'Unauthenticated routes can expose sensitive behavior to unauthorized clients.',
249
+ expectedOutcome: 'Route execution is gated by requireAuth before handler logic runs.',
250
+ };
251
+ }
252
+ if (patternKind === 'missing_rate_limiting') {
253
+ return {
254
+ summary: 'Adds deterministic rate-limit middleware to the route definition.',
255
+ why: `${targetPath} appears to expose a request handler without rate limiting controls.`,
256
+ risk: 'Unbounded request rates can increase abuse, cost, and availability risks.',
257
+ expectedOutcome: 'Route applies rateLimitGuard before handler execution.',
258
+ };
259
+ }
260
+ if (patternKind === 'missing_timeout_handling') {
261
+ return {
262
+ summary: 'Adds deterministic timeout guard to outbound fetch call.',
263
+ why: `${targetPath} issues a fetch request without timeout protection.`,
264
+ risk: 'Unbounded network calls can hang request execution and degrade reliability under upstream latency.',
265
+ expectedOutcome: 'Fetch call aborts after timeout and fails fast instead of hanging.',
266
+ };
267
+ }
268
+ if (patternKind === 'unsafe_fetch_without_retries') {
269
+ return {
270
+ summary: 'Wraps outbound fetch call in deterministic retry guard.',
271
+ why: `${targetPath} makes outbound network calls without transient failure retry handling.`,
272
+ risk: 'Single transient failures can become user-facing errors and increase instability.',
273
+ expectedOutcome: 'Transient upstream failures retry deterministically before failing.',
274
+ };
275
+ }
276
+ if (patternKind === 'missing_idempotency_keys') {
277
+ return {
278
+ summary: 'Adds deterministic idempotency-key guard for side-effecting requests.',
279
+ why: `${targetPath} appears to process payment/order-like mutations without idempotency key enforcement.`,
280
+ risk: 'Duplicate requests can cause repeated side effects (double charges/orders).',
281
+ expectedOutcome: 'Requests missing idempotency key fail early with explicit error.',
282
+ };
283
+ }
284
+ if (patternKind === 'unsafe_file_uploads') {
285
+ return {
286
+ summary: 'Adds deterministic MIME and size guards for uploaded files.',
287
+ why: `${targetPath} appears to process uploaded files without boundary checks.`,
288
+ risk: 'Unbounded or unsafe uploads increase security and stability risk.',
289
+ expectedOutcome: 'Invalid upload payloads are rejected before processing.',
290
+ };
291
+ }
292
+ if (patternKind === 'missing_token_expiry') {
293
+ return {
294
+ summary: 'Adds deterministic token expiry to JWT signing call.',
295
+ why: `${targetPath} signs JWT tokens without an expiresIn option.`,
296
+ risk: 'Long-lived tokens increase replay and account-compromise blast radius.',
297
+ expectedOutcome: 'Tokens gain explicit expiry to enforce credential rotation windows.',
298
+ };
299
+ }
300
+ if (patternKind === 'unsafe_inner_html_usage') {
301
+ return {
302
+ summary: 'Replaces unsafe innerHTML assignment with textContent.',
303
+ why: `${targetPath} writes HTML content directly into the DOM using innerHTML.`,
304
+ risk: 'innerHTML assignments can expose XSS vectors when input is not trusted.',
305
+ expectedOutcome: 'DOM assignment becomes text-only rendering with reduced injection risk.',
306
+ };
307
+ }
308
+ if (patternKind === 'unsafe_sensitive_logging') {
309
+ return {
310
+ summary: 'Removes deterministic sensitive logging line.',
311
+ why: `${targetPath} appears to log secret-bearing fields (token/authorization/password).`,
312
+ risk: 'Sensitive log content can leak credentials to observability or audit sinks.',
313
+ expectedOutcome: 'Sensitive logging path is replaced with a neutral warning placeholder.',
314
+ };
315
+ }
316
+ if (patternKind === 'todo_fixme') {
317
+ return {
318
+ summary: 'Removes TODO/FIXME marker matched by policy.',
319
+ why: `${targetPath} includes TODO/FIXME comments tracked as governance debt.`,
320
+ risk: 'Unresolved TODO markers can hide missing implementation or review debt.',
321
+ expectedOutcome: 'Patch removes the marker; implementation must still be verified separately.',
322
+ };
323
+ }
324
+ return null;
325
+ }
326
+ function createCompatibilityMutationHandlers(context) {
327
+ const { readBody, success, failure, toSource, toActor, recordPatchOutcome } = context;
328
+ async function handleFix(req, res) {
329
+ const run = await (0, execution_bus_1.runExecution)({
330
+ type: 'fix',
331
+ source: toSource(req),
332
+ actor: toActor(req),
333
+ cwd: process.cwd(),
334
+ reverify: true,
335
+ });
336
+ if (!run.primaryPayload) {
337
+ failure(res, run.execution.result?.message || 'fix execution produced no payload');
338
+ return;
339
+ }
340
+ const normalizedFixPayload = (0, shaping_1.normalizeFixPayloadForLegacyClients)(run.primaryPayload) ?? run.primaryPayload;
341
+ const normalizedVerifyAfter = (0, shaping_1.normalizeVerifyPayloadForLegacyClients)(run.verificationPayload);
342
+ success(res, {
343
+ ...normalizedFixPayload,
344
+ verifyAfter: normalizedVerifyAfter ?? null,
345
+ _execution: (0, shaping_1.buildExecutionResponseMeta)(run),
346
+ });
347
+ }
348
+ async function handleFixApplySafe(req, res) {
349
+ const run = await (0, execution_bus_1.runExecution)({
350
+ type: 'apply-safe',
351
+ source: toSource(req),
352
+ actor: toActor(req),
353
+ cwd: process.cwd(),
354
+ reverify: true,
355
+ });
356
+ if (!run.primaryPayload) {
357
+ failure(res, run.execution.result?.message || 'fix --apply-safe execution produced no payload');
358
+ return;
359
+ }
360
+ const normalizedFixPayload = (0, shaping_1.normalizeFixPayloadForLegacyClients)(run.primaryPayload) ?? run.primaryPayload;
361
+ const normalizedVerifyAfter = (0, shaping_1.normalizeVerifyPayloadForLegacyClients)(run.verificationPayload);
362
+ success(res, {
363
+ ...normalizedFixPayload,
364
+ verifyAfter: normalizedVerifyAfter ?? null,
365
+ execution: run.execution,
366
+ _execution: (0, shaping_1.buildExecutionResponseMeta)(run),
367
+ });
368
+ }
369
+ async function handlePatch(req, res) {
370
+ let body = {};
371
+ try {
372
+ body = JSON.parse(await readBody(req));
373
+ }
374
+ catch {
375
+ failure(res, 'Invalid JSON body', 400);
376
+ return;
377
+ }
378
+ const file = body.file;
379
+ if (!file || typeof file !== 'string' || file.includes('..')) {
380
+ failure(res, 'Missing or unsafe "file" field', 400);
381
+ return;
382
+ }
383
+ const previewToken = typeof body.previewToken === 'string' && body.previewToken.trim().length > 0
384
+ ? body.previewToken.trim()
385
+ : undefined;
386
+ const cwd = process.cwd();
387
+ const targetPath = file.trim();
388
+ const absPath = path.resolve(cwd, targetPath);
389
+ const beforeDirtyPaths = captureGitDirtyPaths(cwd);
390
+ const beforeDirtyFingerprints = captureDirtyFileFingerprints(cwd);
391
+ let contentBefore = null;
392
+ try {
393
+ contentBefore = fs.readFileSync(absPath, 'utf-8');
394
+ }
395
+ catch { /* file may not exist */ }
396
+ const primaryArgs = ['patch', '--file', targetPath];
397
+ if (previewToken) {
398
+ primaryArgs.push('--preview-token', previewToken);
399
+ }
400
+ const run = await (0, execution_bus_1.runExecution)({
401
+ type: 'patch',
402
+ source: toSource(req),
403
+ actor: toActor(req),
404
+ target: targetPath,
405
+ cwd,
406
+ reverify: true,
407
+ primaryArgs,
408
+ });
409
+ const patchData = run.primaryPayload ?? {
410
+ success: false,
411
+ file: targetPath,
412
+ message: run.execution.result?.message || 'No applicable patch found',
413
+ };
414
+ let changed = false;
415
+ if (patchData.success && contentBefore !== null) {
416
+ try {
417
+ const contentAfter = fs.readFileSync(absPath, 'utf-8');
418
+ changed = contentAfter !== contentBefore;
419
+ }
420
+ catch { /* ignore read error */ }
421
+ }
422
+ const afterDirtyPaths = captureGitDirtyPaths(cwd);
423
+ const afterDirtyFingerprints = captureDirtyFileFingerprints(cwd);
424
+ const sideEffects = collectUnexpectedPatchSideEffects(beforeDirtyPaths, afterDirtyPaths, absPath, cwd);
425
+ const mutatedSideEffects = collectUnexpectedPatchMutations(beforeDirtyFingerprints, afterDirtyFingerprints, absPath, cwd);
426
+ const combinedSideEffects = [...new Set([...sideEffects, ...mutatedSideEffects])].sort();
427
+ const payloadFile = typeof patchData.file === 'string' ? patchData.file : '';
428
+ const payloadTargetMatch = payloadFile.length > 0
429
+ ? path.resolve(cwd, payloadFile) === absPath
430
+ : true;
431
+ const patchSucceeded = patchData.success === true;
432
+ const rawPatchStatus = typeof patchData.status === 'string' ? patchData.status : '';
433
+ const patchStatus = rawPatchStatus === 'filesystem_changed_since_preview'
434
+ ? 'stale_preview'
435
+ : !patchSucceeded
436
+ ? 'rejected'
437
+ : changed && payloadTargetMatch && combinedSideEffects.length === 0
438
+ ? 'applied'
439
+ : changed
440
+ ? 'partial'
441
+ : 'rejected';
442
+ const patchMessage = (() => {
443
+ if (patchStatus === 'applied') {
444
+ return (typeof patchData.message === 'string' && patchData.message.trim().length > 0)
445
+ ? patchData.message
446
+ : `${contracts_1.STATUS_TERMS.safePatchApplied}`;
447
+ }
448
+ if (patchStatus === 'partial') {
449
+ if (!payloadTargetMatch) {
450
+ return `${contracts_1.STATUS_TERMS.patchRejected}: patch target mismatch detected between requested file and daemon payload file.`;
451
+ }
452
+ if (combinedSideEffects.length > 0) {
453
+ return `${contracts_1.STATUS_TERMS.patchRejected}: patch introduced side effects in ${combinedSideEffects.length} additional file(s).`;
454
+ }
455
+ return `${contracts_1.STATUS_TERMS.safePatchApplied}. ${contracts_1.STATUS_TERMS.manualReviewRecommended}.`;
456
+ }
457
+ if (patchStatus === 'stale_preview') {
458
+ return `${contracts_1.STATUS_TERMS.filesystemChangedSincePreview}. Regenerate patch preview and retry. ${contracts_1.STATUS_TERMS.retrySafe}.`;
459
+ }
460
+ return (typeof patchData.message === 'string' && patchData.message.trim().length > 0)
461
+ ? patchData.message
462
+ : `${contracts_1.STATUS_TERMS.patchRejected}; no deterministic file-scoped change applied`;
463
+ })();
464
+ const reverifyRequired = patchStatus === 'applied' || patchStatus === 'partial';
465
+ const stateLabel = patchStatus === 'stale_preview'
466
+ ? contracts_1.STATUS_TERMS.filesystemChangedSincePreview.toLowerCase()
467
+ : (0, contracts_1.toPatchStateLabel)(patchStatus).toLowerCase();
468
+ recordPatchOutcome(patchStatus);
469
+ const normalizedVerifyPayload = (0, shaping_1.normalizeVerifyPayloadForLegacyClients)(run.verificationPayload);
470
+ success(res, {
471
+ patch: {
472
+ ...patchData,
473
+ file: payloadFile || targetPath,
474
+ success: patchStatus === 'applied',
475
+ rawSuccess: patchData.success === true,
476
+ changed,
477
+ status: patchStatus,
478
+ targetMatch: payloadTargetMatch,
479
+ sideEffects: combinedSideEffects,
480
+ message: patchMessage,
481
+ reverifyRequired,
482
+ stateLabel,
483
+ previewTokenUsed: previewToken ? true : false,
484
+ },
485
+ verify: normalizedVerifyPayload ?? null,
486
+ execution: run.execution,
487
+ _execution: (0, shaping_1.buildExecutionResponseMeta)(run),
488
+ });
489
+ }
490
+ async function handlePatchRollback(req, res) {
491
+ let body = {};
492
+ try {
493
+ body = JSON.parse(await readBody(req));
494
+ }
495
+ catch {
496
+ failure(res, 'Invalid JSON body', 400);
497
+ return;
498
+ }
499
+ const file = body.file;
500
+ const receiptId = typeof body.receiptId === 'string' ? body.receiptId.trim() : '';
501
+ if (!file || typeof file !== 'string' || file.includes('..')) {
502
+ failure(res, 'Missing or unsafe "file" field', 400);
503
+ return;
504
+ }
505
+ if (!receiptId) {
506
+ failure(res, 'Missing "receiptId" field', 400);
507
+ return;
508
+ }
509
+ const cwd = process.cwd();
510
+ const targetPath = file.trim();
511
+ const absPath = path.resolve(cwd, targetPath);
512
+ const beforeDirtyPaths = captureGitDirtyPaths(cwd);
513
+ const beforeDirtyFingerprints = captureDirtyFileFingerprints(cwd);
514
+ let contentBefore = null;
515
+ try {
516
+ contentBefore = fs.readFileSync(absPath, 'utf-8');
517
+ }
518
+ catch { /* file may not exist */ }
519
+ const run = await (0, execution_bus_1.runExecution)({
520
+ type: 'patch',
521
+ source: toSource(req),
522
+ actor: toActor(req),
523
+ target: targetPath,
524
+ cwd,
525
+ reverify: true,
526
+ primaryArgs: ['patch', '--file', targetPath, '--rollback-receipt', receiptId, '--json'],
527
+ });
528
+ const patchData = run.primaryPayload ?? {
529
+ success: false,
530
+ file: targetPath,
531
+ message: run.execution.result?.message || 'No rollback receipt could be applied',
532
+ };
533
+ let changed = false;
534
+ if (patchData.success && contentBefore !== null) {
535
+ try {
536
+ const contentAfter = fs.readFileSync(absPath, 'utf-8');
537
+ changed = contentAfter !== contentBefore;
538
+ }
539
+ catch {
540
+ // ignore read error
541
+ }
542
+ }
543
+ const afterDirtyPaths = captureGitDirtyPaths(cwd);
544
+ const afterDirtyFingerprints = captureDirtyFileFingerprints(cwd);
545
+ const sideEffects = collectUnexpectedPatchSideEffects(beforeDirtyPaths, afterDirtyPaths, absPath, cwd);
546
+ const mutatedSideEffects = collectUnexpectedPatchMutations(beforeDirtyFingerprints, afterDirtyFingerprints, absPath, cwd);
547
+ const combinedSideEffects = [...new Set([...sideEffects, ...mutatedSideEffects])].sort();
548
+ const payloadFile = typeof patchData.file === 'string' ? patchData.file : '';
549
+ const payloadTargetMatch = payloadFile.length > 0
550
+ ? path.resolve(cwd, payloadFile) === absPath
551
+ : true;
552
+ const rawStatus = typeof patchData.status === 'string' ? patchData.status : '';
553
+ const rollbackStatus = rawStatus === 'rollback_applied'
554
+ ? 'rollback_applied'
555
+ : rawStatus === 'rollback_stale' || rawStatus === 'filesystem_changed_since_patch'
556
+ ? 'rollback_stale'
557
+ : 'rollback_rejected';
558
+ const rollbackSucceeded = patchData.success === true && rollbackStatus === 'rollback_applied' && payloadTargetMatch && combinedSideEffects.length === 0;
559
+ const rollbackMessage = (() => {
560
+ if (rollbackSucceeded) {
561
+ return (typeof patchData.message === 'string' && patchData.message.trim().length > 0)
562
+ ? patchData.message
563
+ : contracts_1.STATUS_TERMS.rollbackApplied;
564
+ }
565
+ if (!payloadTargetMatch) {
566
+ return `${contracts_1.STATUS_TERMS.patchRejected}: rollback receipt target mismatch detected.`;
567
+ }
568
+ if (combinedSideEffects.length > 0) {
569
+ return `${contracts_1.STATUS_TERMS.patchRejected}: rollback side effects detected in ${combinedSideEffects.length} additional file(s).`;
570
+ }
571
+ return (typeof patchData.message === 'string' && patchData.message.trim().length > 0)
572
+ ? patchData.message
573
+ : contracts_1.STATUS_TERMS.patchRejected;
574
+ })();
575
+ recordPatchOutcome(rollbackStatus);
576
+ success(res, {
577
+ patch: {
578
+ ...patchData,
579
+ file: payloadFile || targetPath,
580
+ success: rollbackSucceeded,
581
+ rawSuccess: patchData.success === true,
582
+ changed,
583
+ status: rollbackStatus,
584
+ targetMatch: payloadTargetMatch,
585
+ sideEffects: combinedSideEffects,
586
+ message: rollbackMessage,
587
+ reverifyRequired: rollbackSucceeded,
588
+ stateLabel: rollbackSucceeded
589
+ ? contracts_1.STATUS_TERMS.rollbackApplied.toLowerCase()
590
+ : rollbackStatus === 'rollback_stale'
591
+ ? contracts_1.STATUS_TERMS.filesystemChangedSincePreview.toLowerCase()
592
+ : contracts_1.STATUS_TERMS.patchRejected.toLowerCase(),
593
+ previewTokenUsed: false,
594
+ },
595
+ verify: (0, shaping_1.normalizeVerifyPayloadForLegacyClients)(run.verificationPayload) ?? null,
596
+ execution: run.execution,
597
+ _execution: (0, shaping_1.buildExecutionResponseMeta)(run),
598
+ });
599
+ }
600
+ async function handlePatchPreview(req, res) {
601
+ let body = {};
602
+ try {
603
+ body = JSON.parse(await readBody(req));
604
+ }
605
+ catch {
606
+ failure(res, 'Invalid JSON body', 400);
607
+ return;
608
+ }
609
+ const file = body.file;
610
+ if (!file || typeof file !== 'string' || file.includes('..')) {
611
+ failure(res, 'Missing or unsafe "file" field', 400);
612
+ return;
613
+ }
614
+ const cwd = process.cwd();
615
+ const targetPath = file.trim();
616
+ const absPath = path.resolve(cwd, targetPath);
617
+ let contentBefore = '';
618
+ try {
619
+ contentBefore = fs.readFileSync(absPath, 'utf-8');
620
+ }
621
+ catch {
622
+ failure(res, `File not found: ${targetPath}`, 404);
623
+ return;
624
+ }
625
+ const preview = (0, patch_engine_1.applyFirstMatchingPatch)(targetPath, contentBefore);
626
+ if (!preview) {
627
+ success(res, {
628
+ success: false,
629
+ file: targetPath,
630
+ status: 'rejected',
631
+ message: `No deterministic patch preview available for ${targetPath}`,
632
+ beforeContent: contentBefore,
633
+ afterContent: null,
634
+ diff: null,
635
+ changed: false,
636
+ patternKind: null,
637
+ patchConfidence: null,
638
+ patchHash: null,
639
+ previewToken: null,
640
+ validation: null,
641
+ recipe: null,
642
+ pattern: null,
643
+ whatChanges: null,
644
+ rollbackPreviewDiff: null,
645
+ whySafe: null,
646
+ manualReviewRequired: true,
647
+ supportedDeterministicPattern: false,
648
+ reasoning: null,
649
+ });
650
+ return;
651
+ }
652
+ const reasoning = buildPatchPreviewReasoning(preview.patternKind, targetPath, contentBefore);
653
+ const rollbackPreviewDiff = (0, diff_1.generateUnifiedDiff)(targetPath, preview.updatedContent, contentBefore);
654
+ const changeSummary = summarizeDiff(preview.diff);
655
+ const manualReviewRequired = preview.patchConfidence === 'low'
656
+ || preview.validation.safe !== true
657
+ || preview.recipe.requiresManualReview === true;
658
+ const pattern = patternDescriptor(preview.patternKind, preview.patchConfidence, manualReviewRequired);
659
+ const whySafe = {
660
+ deterministic: true,
661
+ validationPassed: preview.validation.safe === true,
662
+ confidence: preview.patchConfidence,
663
+ checks: preview.validation.checks,
664
+ reasonCodes: preview.validation.reasonCodes,
665
+ };
666
+ if (!preview.validation.safe) {
667
+ success(res, {
668
+ success: false,
669
+ file: targetPath,
670
+ status: 'rejected',
671
+ message: `Patch preview rejected by deterministic safety validation (${preview.validation.reasonCodes.join(', ') || 'unknown'}).`,
672
+ beforeContent: contentBefore,
673
+ afterContent: null,
674
+ diff: preview.diff,
675
+ changed: false,
676
+ patternKind: preview.patternKind,
677
+ patchConfidence: preview.patchConfidence,
678
+ patchHash: preview.patchHash,
679
+ previewToken: preview.previewToken,
680
+ validation: preview.validation,
681
+ recipe: preview.recipe,
682
+ pattern,
683
+ whatChanges: changeSummary,
684
+ rollbackPreviewDiff,
685
+ whySafe,
686
+ manualReviewRequired,
687
+ supportedDeterministicPattern: true,
688
+ reasoning,
689
+ });
690
+ return;
691
+ }
692
+ success(res, {
693
+ success: true,
694
+ file: targetPath,
695
+ status: 'preview',
696
+ message: 'Patch preview generated',
697
+ beforeContent: contentBefore,
698
+ afterContent: preview.updatedContent,
699
+ diff: preview.diff,
700
+ changed: contentBefore !== preview.updatedContent,
701
+ patternKind: preview.patternKind,
702
+ patchConfidence: preview.patchConfidence,
703
+ patchHash: preview.patchHash,
704
+ previewToken: preview.previewToken,
705
+ validation: preview.validation,
706
+ recipe: preview.recipe,
707
+ pattern,
708
+ whatChanges: changeSummary,
709
+ rollbackPreviewDiff,
710
+ whySafe,
711
+ manualReviewRequired,
712
+ supportedDeterministicPattern: true,
713
+ reasoning,
714
+ });
715
+ }
716
+ return {
717
+ handleFix,
718
+ handleFixApplySafe,
719
+ handlePatch,
720
+ handlePatchRollback,
721
+ handlePatchPreview,
722
+ };
723
+ }
724
+ //# sourceMappingURL=mutation.js.map