@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
@@ -39,14 +39,15 @@ exports.startDaemon = startDaemon;
39
39
  const http = __importStar(require("node:http"));
40
40
  const path = __importStar(require("node:path"));
41
41
  const fs = __importStar(require("node:fs"));
42
- const node_crypto_1 = require("node:crypto");
43
- const node_child_process_1 = require("node:child_process");
44
- const patch_engine_1 = require("../patch-engine");
45
- const diff_1 = require("../patch-engine/diff");
46
42
  const execution_bus_1 = require("../utils/execution-bus");
43
+ const execution_actions_1 = require("../utils/execution-actions");
47
44
  const runtime_events_1 = require("../utils/runtime-events");
48
45
  const control_plane_1 = require("../utils/control-plane");
49
46
  const workspace_runtime_1 = require("../utils/workspace-runtime");
47
+ const routes_1 = require("./routes");
48
+ const shaping_1 = require("./shaping");
49
+ const execution_1 = require("./compatibility/execution");
50
+ const mutation_1 = require("./compatibility/mutation");
50
51
  const workspace_1 = require("../workspace");
51
52
  const semantic_1 = require("../semantic");
52
53
  const intent_engine_1 = require("../intent-engine");
@@ -73,6 +74,16 @@ const daemonOpsMetrics = {
73
74
  requestsTotal: 0,
74
75
  requestsByMethod: {},
75
76
  requestsByRoute: {},
77
+ requestsBySubsystem: {
78
+ 'canonical-governance': 0,
79
+ 'compatibility-mutation': 0,
80
+ 'runtime-execution': 0,
81
+ 'workspace-orchestration': 0,
82
+ 'replay-evidence': 0,
83
+ 'operational-status': 0,
84
+ 'docs-transport': 0,
85
+ unknown: 0,
86
+ },
76
87
  failuresTotal: 0,
77
88
  retriableFailuresTotal: 0,
78
89
  stalePreviewRejections: 0,
@@ -84,18 +95,15 @@ const daemonOpsMetrics = {
84
95
  rollbackRejected: 0,
85
96
  recentErrors: [],
86
97
  };
87
- function normalizeRoutePath(url) {
88
- const pathOnly = url.split('?')[0]?.trim() || '/';
89
- return pathOnly.startsWith('/') ? pathOnly : `/${pathOnly}`;
90
- }
91
98
  function incrementMetricCounter(record, key) {
92
99
  record[key] = (record[key] || 0) + 1;
93
100
  }
94
101
  function recordDaemonRequest(url, method) {
95
102
  daemonOpsMetrics.requestsTotal += 1;
96
103
  incrementMetricCounter(daemonOpsMetrics.requestsByMethod, method.toUpperCase());
97
- const route = normalizeRoutePath(url);
104
+ const route = (0, routes_1.normalizeRoutePath)(url);
98
105
  incrementMetricCounter(daemonOpsMetrics.requestsByRoute, route);
106
+ incrementMetricCounter(daemonOpsMetrics.requestsBySubsystem, (0, routes_1.classifyDaemonRoute)(method, route));
99
107
  // Keep route cardinality bounded for long-lived daemon sessions.
100
108
  const routeKeys = Object.keys(daemonOpsMetrics.requestsByRoute);
101
109
  if (routeKeys.length > DAEMON_MAX_ROUTE_SAMPLE) {
@@ -191,6 +199,7 @@ function buildDaemonOperationalSummary(cwd) {
191
199
  failures: daemonOpsMetrics.failuresTotal,
192
200
  retriableFailures: daemonOpsMetrics.retriableFailuresTotal,
193
201
  byMethod: daemonOpsMetrics.requestsByMethod,
202
+ bySubsystem: daemonOpsMetrics.requestsBySubsystem,
194
203
  topRoutes: Object.entries(daemonOpsMetrics.requestsByRoute)
195
204
  .sort((left, right) => right[1] - left[1])
196
205
  .slice(0, 12)
@@ -313,408 +322,6 @@ function addCorsHeaders(res, req) {
313
322
  res.setHeader('Access-Control-Allow-Headers', [...allowedHeaders].join(', '));
314
323
  res.setHeader('Access-Control-Max-Age', '86400');
315
324
  }
316
- function resolveGitRoot(cwd) {
317
- const result = (0, node_child_process_1.spawnSync)('git', ['-C', cwd, 'rev-parse', '--show-toplevel'], {
318
- encoding: 'utf-8',
319
- stdio: ['ignore', 'pipe', 'ignore'],
320
- });
321
- if (result.status !== 0)
322
- return null;
323
- const value = typeof result.stdout === 'string' ? result.stdout.trim() : '';
324
- return value.length > 0 ? value : null;
325
- }
326
- function captureGitDirtyPaths(cwd) {
327
- const gitRoot = resolveGitRoot(cwd);
328
- if (!gitRoot)
329
- return null;
330
- const statusResult = (0, node_child_process_1.spawnSync)('git', ['-C', cwd, 'status', '--porcelain=1', '-z', '--untracked-files=all'], {
331
- encoding: 'utf-8',
332
- stdio: ['ignore', 'pipe', 'ignore'],
333
- });
334
- if (statusResult.status !== 0 || typeof statusResult.stdout !== 'string')
335
- return null;
336
- const tokens = statusResult.stdout.split('\0').filter((entry) => entry.length > 0);
337
- const dirty = new Set();
338
- for (let index = 0; index < tokens.length; index += 1) {
339
- const token = tokens[index];
340
- if (token.length < 4)
341
- continue;
342
- const status = token.slice(0, 2);
343
- const filePath = token.slice(3).trim();
344
- if (filePath.length > 0) {
345
- dirty.add(path.resolve(gitRoot, filePath));
346
- }
347
- const renamedOrCopied = status.includes('R') || status.includes('C');
348
- if (renamedOrCopied && index + 1 < tokens.length) {
349
- index += 1;
350
- }
351
- }
352
- return dirty;
353
- }
354
- function hashFileForDiff(absPath) {
355
- try {
356
- const stat = fs.statSync(absPath);
357
- if (!stat.isFile())
358
- return '<non-file>';
359
- const content = fs.readFileSync(absPath);
360
- return (0, node_crypto_1.createHash)('sha256').update(content).digest('hex');
361
- }
362
- catch {
363
- return '<missing>';
364
- }
365
- }
366
- function captureDirtyFileFingerprints(cwd) {
367
- const dirtyPaths = captureGitDirtyPaths(cwd);
368
- if (!dirtyPaths)
369
- return null;
370
- const map = new Map();
371
- for (const dirtyPath of dirtyPaths) {
372
- map.set(dirtyPath, hashFileForDiff(dirtyPath));
373
- }
374
- return map;
375
- }
376
- function isAllowedPatchSideEffect(absPath, targetAbsPath, cwd) {
377
- if (absPath === targetAbsPath)
378
- return true;
379
- const rel = path.relative(cwd, absPath);
380
- if (!rel || rel.startsWith('..'))
381
- return false;
382
- if (rel === 'neurcode.policy.compiled.json')
383
- return true;
384
- return rel === '.neurcode' || rel.startsWith(`.neurcode${path.sep}`);
385
- }
386
- function collectUnexpectedPatchSideEffects(before, after, targetAbsPath, cwd) {
387
- if (!before || !after)
388
- return [];
389
- const added = [...after].filter((entry) => !before.has(entry));
390
- const unexpected = added
391
- .filter((entry) => !isAllowedPatchSideEffect(entry, targetAbsPath, cwd))
392
- .map((entry) => path.relative(cwd, entry).replace(/\\/g, '/'))
393
- .filter((entry) => entry.length > 0)
394
- .sort();
395
- return unexpected;
396
- }
397
- function collectUnexpectedPatchMutations(before, after, targetAbsPath, cwd) {
398
- if (!before || !after)
399
- return [];
400
- const keys = new Set([...before.keys(), ...after.keys()]);
401
- const unexpected = [];
402
- for (const key of keys) {
403
- const beforeHash = before.get(key) ?? '<missing>';
404
- const afterHash = after.get(key) ?? '<missing>';
405
- if (beforeHash === afterHash)
406
- continue;
407
- if (isAllowedPatchSideEffect(key, targetAbsPath, cwd))
408
- continue;
409
- const rel = path.relative(cwd, key).replace(/\\/g, '/');
410
- if (rel.length > 0 && !rel.startsWith('..')) {
411
- unexpected.push(rel);
412
- }
413
- }
414
- return unexpected.sort();
415
- }
416
- function patternDescriptor(kind, confidence, manualReviewRequired) {
417
- const labelByKind = {
418
- missing_validation: 'API input validation guard',
419
- missing_timeout_handling: 'Outbound request timeout guard',
420
- unsafe_fetch_without_retries: 'Outbound request retry guard',
421
- missing_idempotency_keys: 'Mutation idempotency-key guard',
422
- unsafe_file_uploads: 'Upload MIME/size validation guard',
423
- missing_auth_middleware: 'Route authentication middleware',
424
- missing_rate_limiting: 'Route rate limiting middleware',
425
- missing_token_expiry: 'JWT expiry enforcement',
426
- unsafe_inner_html_usage: 'Unsafe DOM sink replacement',
427
- unsafe_sensitive_logging: 'Sensitive log redaction',
428
- db_in_ui: 'Service-layer boundary placeholder',
429
- todo_fixme: 'TODO/FIXME debt marker removal',
430
- };
431
- const confidenceModel = confidence === 'high'
432
- ? 'high'
433
- : confidence === 'medium'
434
- ? 'medium'
435
- : 'low';
436
- return {
437
- kind,
438
- label: labelByKind[kind] || kind,
439
- deterministic: true,
440
- confidenceModel,
441
- advisoryOnly: confidenceModel === 'low',
442
- manualReviewRequired,
443
- };
444
- }
445
- function summarizeDiff(diff) {
446
- let addedLines = 0;
447
- let removedLines = 0;
448
- for (const line of diff.split('\n')) {
449
- if (line.startsWith('+++') || line.startsWith('---') || line.startsWith('@@'))
450
- continue;
451
- if (line.startsWith('+'))
452
- addedLines += 1;
453
- if (line.startsWith('-'))
454
- removedLines += 1;
455
- }
456
- const changedLines = addedLines + removedLines;
457
- return {
458
- addedLines,
459
- removedLines,
460
- changedLines,
461
- summary: `${changedLines} changed line(s): +${addedLines} / -${removedLines}`,
462
- };
463
- }
464
- function extractRequestInputUsage(content) {
465
- const accessMatch = content.match(/\b(req|request)\.(body|params|query)\b/);
466
- if (!accessMatch)
467
- return null;
468
- const receiver = accessMatch[1];
469
- const field = accessMatch[2];
470
- const fieldRegex = new RegExp(`\\b${receiver}\\.${field}\\.([A-Za-z_$][\\w$]*)\\b`, 'g');
471
- const fields = [];
472
- const seen = new Set();
473
- let match = fieldRegex.exec(content);
474
- while (match) {
475
- const fieldName = match[1];
476
- if (!seen.has(fieldName)) {
477
- seen.add(fieldName);
478
- fields.push(fieldName);
479
- }
480
- match = fieldRegex.exec(content);
481
- }
482
- return { receiver, field, fields };
483
- }
484
- function buildPatchPreviewReasoning(patternKind, targetPath, beforeContent) {
485
- if (!patternKind)
486
- return null;
487
- if (patternKind === 'missing_validation') {
488
- const usage = extractRequestInputUsage(beforeContent);
489
- if (!usage) {
490
- return {
491
- summary: 'Adds deterministic API input validation guard.',
492
- why: `This file accesses request input without a validation boundary check.`,
493
- risk: 'Malformed input can cause runtime errors or unsafe processing paths.',
494
- expectedOutcome: 'Invalid requests fail fast and valid requests continue unchanged.',
495
- };
496
- }
497
- const noun = usage.field === 'body' ? 'request body' : usage.field === 'params' ? 'route params' : 'query params';
498
- const fieldSummary = usage.fields.length > 0 ? usage.fields.join(', ') : 'no explicit property access detected';
499
- return {
500
- summary: `Adds deterministic validation before reading ${usage.receiver}.${usage.field}.`,
501
- why: `${targetPath} reads ${noun} fields (${fieldSummary}) before validation.`,
502
- risk: `Without boundary validation, malformed ${noun} may propagate into handler logic.`,
503
- expectedOutcome: `Invalid ${noun} returns HTTP 400 early; valid requests keep existing behavior.`,
504
- fields: usage.fields,
505
- };
506
- }
507
- if (patternKind === 'db_in_ui') {
508
- return {
509
- summary: 'Suggests moving direct DB access behind a service boundary.',
510
- why: `${targetPath} appears to perform direct data access in a non-service layer.`,
511
- risk: 'Layering violations increase coupling and make behavior harder to govern.',
512
- expectedOutcome: 'Patch inserts a deterministic placeholder to redirect to service-layer logic.',
513
- };
514
- }
515
- if (patternKind === 'missing_auth_middleware') {
516
- return {
517
- summary: 'Adds deterministic authentication middleware to the route definition.',
518
- why: `${targetPath} appears to expose a request handler without an auth middleware guard.`,
519
- risk: 'Unauthenticated routes can expose sensitive behavior to unauthorized clients.',
520
- expectedOutcome: 'Route execution is gated by requireAuth before handler logic runs.',
521
- };
522
- }
523
- if (patternKind === 'missing_rate_limiting') {
524
- return {
525
- summary: 'Adds deterministic rate-limit middleware to the route definition.',
526
- why: `${targetPath} appears to expose a request handler without rate limiting controls.`,
527
- risk: 'Unbounded request rates can increase abuse, cost, and availability risks.',
528
- expectedOutcome: 'Route applies rateLimitGuard before handler execution.',
529
- };
530
- }
531
- if (patternKind === 'missing_timeout_handling') {
532
- return {
533
- summary: 'Adds deterministic timeout guard to outbound fetch call.',
534
- why: `${targetPath} issues a fetch request without timeout protection.`,
535
- risk: 'Unbounded network calls can hang request execution and degrade reliability under upstream latency.',
536
- expectedOutcome: 'Fetch call aborts after timeout and fails fast instead of hanging.',
537
- };
538
- }
539
- if (patternKind === 'unsafe_fetch_without_retries') {
540
- return {
541
- summary: 'Wraps outbound fetch call in deterministic retry guard.',
542
- why: `${targetPath} makes outbound network calls without transient failure retry handling.`,
543
- risk: 'Single transient failures can become user-facing errors and increase instability.',
544
- expectedOutcome: 'Transient upstream failures retry deterministically before failing.',
545
- };
546
- }
547
- if (patternKind === 'missing_idempotency_keys') {
548
- return {
549
- summary: 'Adds deterministic idempotency-key guard for side-effecting requests.',
550
- why: `${targetPath} appears to process payment/order-like mutations without idempotency key enforcement.`,
551
- risk: 'Duplicate requests can cause repeated side effects (double charges/orders).',
552
- expectedOutcome: 'Requests missing idempotency key fail early with explicit error.',
553
- };
554
- }
555
- if (patternKind === 'unsafe_file_uploads') {
556
- return {
557
- summary: 'Adds deterministic MIME and size guards for uploaded files.',
558
- why: `${targetPath} appears to process uploaded files without boundary checks.`,
559
- risk: 'Unbounded or unsafe uploads increase security and stability risk.',
560
- expectedOutcome: 'Invalid upload payloads are rejected before processing.',
561
- };
562
- }
563
- if (patternKind === 'missing_token_expiry') {
564
- return {
565
- summary: 'Adds deterministic token expiry to JWT signing call.',
566
- why: `${targetPath} signs JWT tokens without an expiresIn option.`,
567
- risk: 'Long-lived tokens increase replay and account-compromise blast radius.',
568
- expectedOutcome: 'Tokens gain explicit expiry to enforce credential rotation windows.',
569
- };
570
- }
571
- if (patternKind === 'unsafe_inner_html_usage') {
572
- return {
573
- summary: 'Replaces unsafe innerHTML assignment with textContent.',
574
- why: `${targetPath} writes HTML content directly into the DOM using innerHTML.`,
575
- risk: 'innerHTML assignments can expose XSS vectors when input is not trusted.',
576
- expectedOutcome: 'DOM assignment becomes text-only rendering with reduced injection risk.',
577
- };
578
- }
579
- if (patternKind === 'unsafe_sensitive_logging') {
580
- return {
581
- summary: 'Removes deterministic sensitive logging line.',
582
- why: `${targetPath} appears to log secret-bearing fields (token/authorization/password).`,
583
- risk: 'Sensitive log content can leak credentials to observability or audit sinks.',
584
- expectedOutcome: 'Sensitive logging path is replaced with a neutral warning placeholder.',
585
- };
586
- }
587
- if (patternKind === 'todo_fixme') {
588
- return {
589
- summary: 'Removes TODO/FIXME marker matched by policy.',
590
- why: `${targetPath} includes TODO/FIXME comments tracked as governance debt.`,
591
- risk: 'Unresolved TODO markers can hide missing implementation or review debt.',
592
- expectedOutcome: 'Patch removes the marker; implementation must still be verified separately.',
593
- };
594
- }
595
- return null;
596
- }
597
- function isExecutionActionType(value) {
598
- if (typeof value !== 'string')
599
- return false;
600
- return (value === 'verify'
601
- || value === 'fix'
602
- || value === 'patch'
603
- || value === 'apply-safe'
604
- || value === 'reverify'
605
- || value === 'policy-sync'
606
- || value === 'intent-update');
607
- }
608
- function asObjectRecord(value) {
609
- if (!value || typeof value !== 'object' || Array.isArray(value))
610
- return null;
611
- return value;
612
- }
613
- function asObjectArray(value) {
614
- if (!Array.isArray(value))
615
- return [];
616
- return value
617
- .map((entry) => asObjectRecord(entry))
618
- .filter((entry) => entry !== null);
619
- }
620
- function toLegacyViolation(entry, fallbackSeverity) {
621
- const file = typeof entry.file === 'string' && entry.file.trim().length > 0
622
- ? entry.file.trim()
623
- : '';
624
- const message = typeof entry.message === 'string' && entry.message.trim().length > 0
625
- ? entry.message.trim()
626
- : '';
627
- if (!file || !message)
628
- return null;
629
- const severity = typeof entry.severity === 'string' && entry.severity.trim().length > 0
630
- ? entry.severity.trim()
631
- : fallbackSeverity;
632
- const rule = typeof entry.rule === 'string' && entry.rule.trim().length > 0
633
- ? entry.rule.trim()
634
- : typeof entry.policy === 'string' && entry.policy.trim().length > 0
635
- ? entry.policy.trim()
636
- : '';
637
- return { file, message, severity, rule };
638
- }
639
- function normalizeVerifyPayloadForLegacyClients(payload) {
640
- if (!payload)
641
- return null;
642
- const existingViolations = asObjectArray(payload.violations)
643
- .map((entry) => toLegacyViolation(entry, 'warn'))
644
- .filter((entry) => entry !== null);
645
- const blockingItems = asObjectArray(payload.blockingItems)
646
- .map((entry) => toLegacyViolation(entry, 'block'))
647
- .filter((entry) => entry !== null);
648
- const advisoryItems = asObjectArray(payload.advisoryItems)
649
- .map((entry) => toLegacyViolation(entry, 'warn'))
650
- .filter((entry) => entry !== null);
651
- const warnings = asObjectArray(payload.warnings)
652
- .map((entry) => toLegacyViolation(entry, 'warn'))
653
- .filter((entry) => entry !== null);
654
- const merged = [...existingViolations];
655
- const canonicalSeverity = (value) => {
656
- const normalized = value.trim().toLowerCase();
657
- if (normalized === 'block' || normalized === 'critical' || normalized === 'high')
658
- return 'block';
659
- if (normalized === 'warn' || normalized === 'warning' || normalized === 'advisory' || normalized === 'medium' || normalized === 'low')
660
- return 'warn';
661
- return normalized;
662
- };
663
- const canonicalKey = (entry) => `${entry.file}::${entry.rule}::${entry.message}::${canonicalSeverity(entry.severity)}`;
664
- const seen = new Set(merged.map((entry) => canonicalKey(entry)));
665
- for (const item of [...blockingItems, ...advisoryItems, ...warnings]) {
666
- const key = canonicalKey(item);
667
- if (seen.has(key))
668
- continue;
669
- seen.add(key);
670
- merged.push(item);
671
- }
672
- if (merged.length === 0)
673
- return payload;
674
- return {
675
- ...payload,
676
- violations: merged,
677
- };
678
- }
679
- function normalizeFixPayloadForLegacyClients(payload) {
680
- if (!payload)
681
- return null;
682
- const suggestions = asObjectArray(payload.suggestions);
683
- if (suggestions.length === 0)
684
- return payload;
685
- const deduped = [];
686
- const seen = new Set();
687
- for (const suggestion of suggestions) {
688
- const file = typeof suggestion.file === 'string' ? suggestion.file.trim() : '';
689
- const line = typeof suggestion.line === 'number' && Number.isFinite(suggestion.line)
690
- ? String(Math.floor(suggestion.line))
691
- : '';
692
- const message = typeof suggestion.message === 'string' ? suggestion.message.trim() : '';
693
- const rule = typeof suggestion.rule === 'string'
694
- ? suggestion.rule.trim()
695
- : typeof suggestion.policy === 'string'
696
- ? suggestion.policy.trim()
697
- : '';
698
- const confidence = typeof suggestion.confidence === 'string' ? suggestion.confidence.trim().toLowerCase() : '';
699
- const patch = asObjectRecord(suggestion.patch);
700
- const patchDiff = patch && typeof patch.diff === 'string' ? patch.diff : '';
701
- const key = `${file}::${line}::${rule}::${message}::${confidence}::${(0, node_crypto_1.createHash)('sha1').update(patchDiff).digest('hex')}`;
702
- if (seen.has(key))
703
- continue;
704
- seen.add(key);
705
- deduped.push(suggestion);
706
- }
707
- if (deduped.length === suggestions.length)
708
- return payload;
709
- return {
710
- ...payload,
711
- suggestions: deduped,
712
- _normalization: {
713
- ...(asObjectRecord(payload._normalization) || {}),
714
- suggestionsDeduped: suggestions.length - deduped.length,
715
- },
716
- };
717
- }
718
325
  function isLoopback(req) {
719
326
  if (ALLOW_NON_LOOPBACK)
720
327
  return true;
@@ -965,71 +572,15 @@ async function handleVerify(req, res) {
965
572
  failure(res, run.execution.result?.message || 'verify execution produced no payload');
966
573
  return;
967
574
  }
968
- const normalizedPayload = normalizeVerifyPayloadForLegacyClients(run.primaryPayload ?? null) ?? run.primaryPayload;
575
+ const normalizedPayload = (0, shaping_1.normalizeVerifyPayloadForLegacyClients)(run.primaryPayload ?? null) ?? run.primaryPayload;
576
+ const governanceEnvelope = (0, shaping_1.buildGovernanceEnvelope)(run);
969
577
  success(res, {
970
578
  ...normalizedPayload,
971
- _execution: {
972
- id: run.execution.id,
973
- type: run.execution.type,
974
- source: run.execution.source,
975
- actor: run.execution.actor,
976
- status: run.execution.status,
977
- trend: run.execution.verification.diff.trend,
978
- evidence: run.execution.evidence.references,
979
- durationMs: run.execution.durationMs,
980
- },
981
- });
982
- }
983
- async function handleFix(req, res) {
984
- const run = await (0, execution_bus_1.runExecution)({
985
- type: 'fix',
986
- source: toSource(req),
987
- actor: toActor(req),
988
- cwd: process.cwd(),
989
- reverify: true,
990
- });
991
- if (!run.primaryPayload) {
992
- failure(res, run.execution.result?.message || 'fix execution produced no payload');
993
- return;
994
- }
995
- const normalizedFixPayload = normalizeFixPayloadForLegacyClients(run.primaryPayload) ?? run.primaryPayload;
996
- const normalizedVerifyAfter = normalizeVerifyPayloadForLegacyClients(run.verificationPayload);
997
- success(res, {
998
- ...normalizedFixPayload,
999
- verifyAfter: normalizedVerifyAfter ?? null,
1000
- _execution: {
1001
- id: run.execution.id,
1002
- type: run.execution.type,
1003
- source: run.execution.source,
1004
- actor: run.execution.actor,
1005
- status: run.execution.status,
1006
- trend: run.execution.verification.diff.trend,
1007
- evidence: run.execution.evidence.references,
1008
- durationMs: run.execution.durationMs,
1009
- },
1010
- });
1011
- }
1012
- async function handleFixApplySafe(req, res) {
1013
- const run = await (0, execution_bus_1.runExecution)({
1014
- type: 'apply-safe',
1015
- source: toSource(req),
1016
- actor: toActor(req),
1017
- cwd: process.cwd(),
1018
- reverify: true,
1019
- });
1020
- if (!run.primaryPayload) {
1021
- failure(res, run.execution.result?.message || 'fix --apply-safe execution produced no payload');
1022
- return;
1023
- }
1024
- const normalizedFixPayload = normalizeFixPayloadForLegacyClients(run.primaryPayload) ?? run.primaryPayload;
1025
- const normalizedVerifyAfter = normalizeVerifyPayloadForLegacyClients(run.verificationPayload);
1026
- success(res, {
1027
- ...normalizedFixPayload,
1028
- verifyAfter: normalizedVerifyAfter ?? null,
1029
- execution: run.execution,
579
+ governanceEnvelope,
580
+ _execution: (0, shaping_1.buildExecutionResponseMeta)(run),
1030
581
  });
1031
582
  }
1032
- async function handlePatch(req, res) {
583
+ async function handleExecute(req, res, compatibilityExecutionHandlers) {
1033
584
  let body = {};
1034
585
  try {
1035
586
  body = JSON.parse(await readBody(req));
@@ -1038,358 +589,18 @@ async function handlePatch(req, res) {
1038
589
  failure(res, 'Invalid JSON body', 400);
1039
590
  return;
1040
591
  }
1041
- const file = body.file;
1042
- if (!file || typeof file !== 'string' || file.includes('..')) {
1043
- failure(res, 'Missing or unsafe "file" field', 400);
1044
- return;
1045
- }
1046
- const previewToken = typeof body.previewToken === 'string' && body.previewToken.trim().length > 0
1047
- ? body.previewToken.trim()
1048
- : undefined;
1049
- const cwd = process.cwd();
1050
- const targetPath = file.trim();
1051
- const absPath = path.resolve(cwd, targetPath);
1052
- const beforeDirtyPaths = captureGitDirtyPaths(cwd);
1053
- const beforeDirtyFingerprints = captureDirtyFileFingerprints(cwd);
1054
- // Capture file content before patch to detect real change
1055
- let contentBefore = null;
1056
- try {
1057
- contentBefore = fs.readFileSync(absPath, 'utf-8');
1058
- }
1059
- catch { /* file may not exist */ }
1060
- const primaryArgs = ['patch', '--file', targetPath];
1061
- if (previewToken) {
1062
- primaryArgs.push('--preview-token', previewToken);
1063
- }
1064
- const run = await (0, execution_bus_1.runExecution)({
1065
- type: 'patch',
1066
- source: toSource(req),
1067
- actor: toActor(req),
1068
- target: targetPath,
1069
- cwd,
1070
- reverify: true,
1071
- primaryArgs,
1072
- });
1073
- const patchData = run.primaryPayload ?? {
1074
- success: false,
1075
- file: targetPath,
1076
- message: run.execution.result?.message || 'No applicable patch found',
1077
- };
1078
- // Validate that the file actually changed on disk
1079
- let changed = false;
1080
- if (patchData.success && contentBefore !== null) {
1081
- try {
1082
- const contentAfter = fs.readFileSync(absPath, 'utf-8');
1083
- changed = contentAfter !== contentBefore;
1084
- }
1085
- catch { /* ignore read error */ }
1086
- }
1087
- const afterDirtyPaths = captureGitDirtyPaths(cwd);
1088
- const afterDirtyFingerprints = captureDirtyFileFingerprints(cwd);
1089
- const sideEffects = collectUnexpectedPatchSideEffects(beforeDirtyPaths, afterDirtyPaths, absPath, cwd);
1090
- const mutatedSideEffects = collectUnexpectedPatchMutations(beforeDirtyFingerprints, afterDirtyFingerprints, absPath, cwd);
1091
- const combinedSideEffects = [...new Set([...sideEffects, ...mutatedSideEffects])].sort();
1092
- const payloadFile = typeof patchData.file === 'string' ? patchData.file : '';
1093
- const payloadTargetMatch = payloadFile.length > 0
1094
- ? path.resolve(cwd, payloadFile) === absPath
1095
- : true;
1096
- const patchSucceeded = patchData.success === true;
1097
- const rawPatchStatus = typeof patchData.status === 'string' ? patchData.status : '';
1098
- const patchStatus = rawPatchStatus === 'filesystem_changed_since_preview'
1099
- ? 'stale_preview'
1100
- : !patchSucceeded
1101
- ? 'rejected'
1102
- : changed && payloadTargetMatch && combinedSideEffects.length === 0
1103
- ? 'applied'
1104
- : changed
1105
- ? 'partial'
1106
- : 'rejected';
1107
- const patchMessage = (() => {
1108
- if (patchStatus === 'applied') {
1109
- return (typeof patchData.message === 'string' && patchData.message.trim().length > 0)
1110
- ? patchData.message
1111
- : `${contracts_1.STATUS_TERMS.safePatchApplied}`;
1112
- }
1113
- if (patchStatus === 'partial') {
1114
- if (!payloadTargetMatch) {
1115
- return `${contracts_1.STATUS_TERMS.patchRejected}: patch target mismatch detected between requested file and daemon payload file.`;
1116
- }
1117
- if (combinedSideEffects.length > 0) {
1118
- return `${contracts_1.STATUS_TERMS.patchRejected}: patch introduced side effects in ${combinedSideEffects.length} additional file(s).`;
1119
- }
1120
- return `${contracts_1.STATUS_TERMS.safePatchApplied}. ${contracts_1.STATUS_TERMS.manualReviewRecommended}.`;
1121
- }
1122
- if (patchStatus === 'stale_preview') {
1123
- return `${contracts_1.STATUS_TERMS.filesystemChangedSincePreview}. Regenerate patch preview and retry. ${contracts_1.STATUS_TERMS.retrySafe}.`;
1124
- }
1125
- return (typeof patchData.message === 'string' && patchData.message.trim().length > 0)
1126
- ? patchData.message
1127
- : `${contracts_1.STATUS_TERMS.patchRejected}; no deterministic file-scoped change applied`;
1128
- })();
1129
- const reverifyRequired = patchStatus === 'applied' || patchStatus === 'partial';
1130
- const stateLabel = patchStatus === 'stale_preview'
1131
- ? contracts_1.STATUS_TERMS.filesystemChangedSincePreview.toLowerCase()
1132
- : (0, contracts_1.toPatchStateLabel)(patchStatus).toLowerCase();
1133
- recordPatchOutcome(patchStatus);
1134
- const normalizedVerifyPayload = normalizeVerifyPayloadForLegacyClients(run.verificationPayload);
1135
- success(res, {
1136
- patch: {
1137
- ...patchData,
1138
- file: payloadFile || targetPath,
1139
- success: patchStatus === 'applied',
1140
- rawSuccess: patchData.success === true,
1141
- changed,
1142
- status: patchStatus,
1143
- targetMatch: payloadTargetMatch,
1144
- sideEffects: combinedSideEffects,
1145
- message: patchMessage,
1146
- reverifyRequired,
1147
- stateLabel,
1148
- previewTokenUsed: previewToken ? true : false,
1149
- },
1150
- verify: normalizedVerifyPayload ?? null,
1151
- execution: run.execution,
1152
- });
1153
- }
1154
- async function handlePatchRollback(req, res) {
1155
- let body = {};
1156
- try {
1157
- body = JSON.parse(await readBody(req));
1158
- }
1159
- catch {
1160
- failure(res, 'Invalid JSON body', 400);
1161
- return;
1162
- }
1163
- const file = body.file;
1164
- const receiptId = typeof body.receiptId === 'string' ? body.receiptId.trim() : '';
1165
- if (!file || typeof file !== 'string' || file.includes('..')) {
1166
- failure(res, 'Missing or unsafe "file" field', 400);
1167
- return;
1168
- }
1169
- if (!receiptId) {
1170
- failure(res, 'Missing "receiptId" field', 400);
1171
- return;
1172
- }
1173
- const cwd = process.cwd();
1174
- const targetPath = file.trim();
1175
- const absPath = path.resolve(cwd, targetPath);
1176
- const beforeDirtyPaths = captureGitDirtyPaths(cwd);
1177
- const beforeDirtyFingerprints = captureDirtyFileFingerprints(cwd);
1178
- let contentBefore = null;
1179
- try {
1180
- contentBefore = fs.readFileSync(absPath, 'utf-8');
1181
- }
1182
- catch { /* file may not exist */ }
1183
- const run = await (0, execution_bus_1.runExecution)({
1184
- type: 'patch',
1185
- source: toSource(req),
1186
- actor: toActor(req),
1187
- target: targetPath,
1188
- cwd,
1189
- reverify: true,
1190
- primaryArgs: ['patch', '--file', targetPath, '--rollback-receipt', receiptId, '--json'],
1191
- });
1192
- const patchData = run.primaryPayload ?? {
1193
- success: false,
1194
- file: targetPath,
1195
- message: run.execution.result?.message || 'No rollback receipt could be applied',
1196
- };
1197
- let changed = false;
1198
- if (patchData.success && contentBefore !== null) {
1199
- try {
1200
- const contentAfter = fs.readFileSync(absPath, 'utf-8');
1201
- changed = contentAfter !== contentBefore;
1202
- }
1203
- catch {
1204
- // ignore read error
1205
- }
1206
- }
1207
- const afterDirtyPaths = captureGitDirtyPaths(cwd);
1208
- const afterDirtyFingerprints = captureDirtyFileFingerprints(cwd);
1209
- const sideEffects = collectUnexpectedPatchSideEffects(beforeDirtyPaths, afterDirtyPaths, absPath, cwd);
1210
- const mutatedSideEffects = collectUnexpectedPatchMutations(beforeDirtyFingerprints, afterDirtyFingerprints, absPath, cwd);
1211
- const combinedSideEffects = [...new Set([...sideEffects, ...mutatedSideEffects])].sort();
1212
- const payloadFile = typeof patchData.file === 'string' ? patchData.file : '';
1213
- const payloadTargetMatch = payloadFile.length > 0
1214
- ? path.resolve(cwd, payloadFile) === absPath
1215
- : true;
1216
- const rawStatus = typeof patchData.status === 'string' ? patchData.status : '';
1217
- const rollbackStatus = rawStatus === 'rollback_applied'
1218
- ? 'rollback_applied'
1219
- : rawStatus === 'rollback_stale' || rawStatus === 'filesystem_changed_since_patch'
1220
- ? 'rollback_stale'
1221
- : 'rollback_rejected';
1222
- const rollbackSucceeded = patchData.success === true && rollbackStatus === 'rollback_applied' && payloadTargetMatch && combinedSideEffects.length === 0;
1223
- const rollbackMessage = (() => {
1224
- if (rollbackSucceeded) {
1225
- return (typeof patchData.message === 'string' && patchData.message.trim().length > 0)
1226
- ? patchData.message
1227
- : contracts_1.STATUS_TERMS.rollbackApplied;
1228
- }
1229
- if (!payloadTargetMatch) {
1230
- return `${contracts_1.STATUS_TERMS.patchRejected}: rollback receipt target mismatch detected.`;
1231
- }
1232
- if (combinedSideEffects.length > 0) {
1233
- return `${contracts_1.STATUS_TERMS.patchRejected}: rollback side effects detected in ${combinedSideEffects.length} additional file(s).`;
1234
- }
1235
- return (typeof patchData.message === 'string' && patchData.message.trim().length > 0)
1236
- ? patchData.message
1237
- : contracts_1.STATUS_TERMS.patchRejected;
1238
- })();
1239
- recordPatchOutcome(rollbackStatus);
1240
- success(res, {
1241
- patch: {
1242
- ...patchData,
1243
- file: payloadFile || targetPath,
1244
- success: rollbackSucceeded,
1245
- rawSuccess: patchData.success === true,
1246
- changed,
1247
- status: rollbackStatus,
1248
- targetMatch: payloadTargetMatch,
1249
- sideEffects: combinedSideEffects,
1250
- message: rollbackMessage,
1251
- reverifyRequired: rollbackSucceeded,
1252
- stateLabel: rollbackSucceeded
1253
- ? contracts_1.STATUS_TERMS.rollbackApplied.toLowerCase()
1254
- : rollbackStatus === 'rollback_stale'
1255
- ? contracts_1.STATUS_TERMS.filesystemChangedSincePreview.toLowerCase()
1256
- : contracts_1.STATUS_TERMS.patchRejected.toLowerCase(),
1257
- previewTokenUsed: false,
1258
- },
1259
- verify: normalizeVerifyPayloadForLegacyClients(run.verificationPayload) ?? null,
1260
- execution: run.execution,
1261
- });
1262
- }
1263
- async function handlePatchPreview(req, res) {
1264
- let body = {};
1265
- try {
1266
- body = JSON.parse(await readBody(req));
1267
- }
1268
- catch {
1269
- failure(res, 'Invalid JSON body', 400);
1270
- return;
1271
- }
1272
- const file = body.file;
1273
- if (!file || typeof file !== 'string' || file.includes('..')) {
1274
- failure(res, 'Missing or unsafe "file" field', 400);
1275
- return;
1276
- }
1277
- const cwd = process.cwd();
1278
- const targetPath = file.trim();
1279
- const absPath = path.resolve(cwd, targetPath);
1280
- let contentBefore = '';
1281
- try {
1282
- contentBefore = fs.readFileSync(absPath, 'utf-8');
1283
- }
1284
- catch {
1285
- failure(res, `File not found: ${targetPath}`, 404);
1286
- return;
1287
- }
1288
- const preview = (0, patch_engine_1.applyFirstMatchingPatch)(targetPath, contentBefore);
1289
- if (!preview) {
1290
- success(res, {
1291
- success: false,
1292
- file: targetPath,
1293
- status: 'rejected',
1294
- message: `No deterministic patch preview available for ${targetPath}`,
1295
- beforeContent: contentBefore,
1296
- afterContent: null,
1297
- diff: null,
1298
- changed: false,
1299
- patternKind: null,
1300
- patchConfidence: null,
1301
- patchHash: null,
1302
- previewToken: null,
1303
- validation: null,
1304
- recipe: null,
1305
- pattern: null,
1306
- whatChanges: null,
1307
- rollbackPreviewDiff: null,
1308
- whySafe: null,
1309
- manualReviewRequired: true,
1310
- supportedDeterministicPattern: false,
1311
- reasoning: null,
1312
- });
592
+ const type = body.type;
593
+ if (!(0, execution_actions_1.isExecutionActionType)(type)) {
594
+ failure(res, 'Invalid or missing "type" field', 400);
1313
595
  return;
1314
596
  }
1315
- const reasoning = buildPatchPreviewReasoning(preview.patternKind, targetPath, contentBefore);
1316
- const rollbackPreviewDiff = (0, diff_1.generateUnifiedDiff)(targetPath, preview.updatedContent, contentBefore);
1317
- const changeSummary = summarizeDiff(preview.diff);
1318
- const manualReviewRequired = preview.patchConfidence === 'low'
1319
- || preview.validation.safe !== true
1320
- || preview.recipe.requiresManualReview === true;
1321
- const pattern = patternDescriptor(preview.patternKind, preview.patchConfidence, manualReviewRequired);
1322
- const whySafe = {
1323
- deterministic: true,
1324
- validationPassed: preview.validation.safe === true,
1325
- confidence: preview.patchConfidence,
1326
- checks: preview.validation.checks,
1327
- reasonCodes: preview.validation.reasonCodes,
1328
- };
1329
- if (!preview.validation.safe) {
1330
- success(res, {
1331
- success: false,
1332
- file: targetPath,
1333
- status: 'rejected',
1334
- message: `Patch preview rejected by deterministic safety validation (${preview.validation.reasonCodes.join(', ') || 'unknown'}).`,
1335
- beforeContent: contentBefore,
1336
- afterContent: null,
1337
- diff: preview.diff,
1338
- changed: false,
1339
- patternKind: preview.patternKind,
1340
- patchConfidence: preview.patchConfidence,
1341
- patchHash: preview.patchHash,
1342
- previewToken: preview.previewToken,
1343
- validation: preview.validation,
1344
- recipe: preview.recipe,
1345
- pattern,
1346
- whatChanges: changeSummary,
1347
- rollbackPreviewDiff,
1348
- whySafe,
1349
- manualReviewRequired,
1350
- supportedDeterministicPattern: true,
1351
- reasoning,
597
+ const actionClass = (0, execution_actions_1.getExecutionActionClass)(type);
598
+ if ((0, execution_actions_1.isCompatibilityExecutionActionType)(type) && compatibilityExecutionHandlers) {
599
+ await compatibilityExecutionHandlers.handleExecuteBody(req, res, body, {
600
+ dispatchMode: 'legacy-generic-route',
1352
601
  });
1353
602
  return;
1354
603
  }
1355
- success(res, {
1356
- success: true,
1357
- file: targetPath,
1358
- status: 'preview',
1359
- message: 'Patch preview generated',
1360
- beforeContent: contentBefore,
1361
- afterContent: preview.updatedContent,
1362
- diff: preview.diff,
1363
- changed: contentBefore !== preview.updatedContent,
1364
- patternKind: preview.patternKind,
1365
- patchConfidence: preview.patchConfidence,
1366
- patchHash: preview.patchHash,
1367
- previewToken: preview.previewToken,
1368
- validation: preview.validation,
1369
- recipe: preview.recipe,
1370
- pattern,
1371
- whatChanges: changeSummary,
1372
- rollbackPreviewDiff,
1373
- whySafe,
1374
- manualReviewRequired,
1375
- supportedDeterministicPattern: true,
1376
- reasoning,
1377
- });
1378
- }
1379
- async function handleExecute(req, res) {
1380
- let body = {};
1381
- try {
1382
- body = JSON.parse(await readBody(req));
1383
- }
1384
- catch {
1385
- failure(res, 'Invalid JSON body', 400);
1386
- return;
1387
- }
1388
- const type = body.type;
1389
- if (!isExecutionActionType(type)) {
1390
- failure(res, 'Invalid or missing "type" field', 400);
1391
- return;
1392
- }
1393
604
  const run = await (0, execution_bus_1.runExecution)({
1394
605
  type,
1395
606
  source: toSource(req),
@@ -1397,13 +608,28 @@ async function handleExecute(req, res) {
1397
608
  target: body.target ?? null,
1398
609
  intentText: body.intentText ?? null,
1399
610
  cwd: process.cwd(),
1400
- reverify: body.reverify !== false,
611
+ reverify: typeof body.reverify === 'boolean'
612
+ ? body.reverify
613
+ : actionClass === 'compatibility-mutation',
1401
614
  ciMode: typeof body.ciMode === 'boolean' ? body.ciMode : undefined,
1402
615
  evidenceDir: typeof body.evidenceDir === 'string' ? body.evidenceDir : undefined,
1403
616
  dedupeWindowMs: typeof body.dedupeWindowMs === 'number' ? body.dedupeWindowMs : undefined,
1404
617
  });
618
+ const executionBoundary = {
619
+ routeScope: actionClass === 'canonical-governance' ? 'canonical-governance' : 'runtime-operation',
620
+ actionClass,
621
+ compatibilityAction: false,
622
+ canonicalRuntime: actionClass === 'canonical-governance',
623
+ genericExecution: true,
624
+ };
625
+ const governanceEnvelope = (0, shaping_1.buildGovernanceEnvelope)(run, { executionBoundary });
1405
626
  success(res, {
1406
627
  execution: run.execution,
628
+ _execution: (0, shaping_1.buildExecutionResponseMeta)(run, { executionBoundary }),
629
+ actionClass,
630
+ compatibilityAction: false,
631
+ executionBoundary,
632
+ governanceEnvelope,
1407
633
  payload: run.primaryPayload,
1408
634
  verification: run.verificationPayload,
1409
635
  });
@@ -1742,7 +968,7 @@ async function handleUpdateWorkspace(req, res, workspaceId) {
1742
968
  });
1743
969
  success(res, result);
1744
970
  }
1745
- async function handleExecuteWorkspace(req, res) {
971
+ async function handleExecuteWorkspace(req, res, compatibilityExecutionHandlers) {
1746
972
  let body = {};
1747
973
  try {
1748
974
  body = JSON.parse(await readBody(req));
@@ -1751,10 +977,16 @@ async function handleExecuteWorkspace(req, res) {
1751
977
  failure(res, 'Invalid JSON body', 400);
1752
978
  return;
1753
979
  }
1754
- if (!isExecutionActionType(body.type)) {
980
+ if (!(0, execution_actions_1.isExecutionActionType)(body.type)) {
1755
981
  failure(res, 'Invalid or missing execution type', 400);
1756
982
  return;
1757
983
  }
984
+ if ((0, execution_actions_1.isCompatibilityExecutionActionType)(body.type) && compatibilityExecutionHandlers) {
985
+ await compatibilityExecutionHandlers.handleWorkspaceExecuteBody(req, res, body, {
986
+ dispatchMode: 'legacy-generic-route',
987
+ });
988
+ return;
989
+ }
1758
990
  const request = {
1759
991
  workspaceId: asNonEmptyString(body.workspaceId),
1760
992
  repositoryIds: asStringArray(body.repositoryIds),
@@ -1763,7 +995,9 @@ async function handleExecuteWorkspace(req, res) {
1763
995
  actor: toActor(req),
1764
996
  target: body.target === null ? null : asNonEmptyString(body.target) || null,
1765
997
  intentText: body.intentText === null ? null : asNonEmptyString(body.intentText) || null,
1766
- reverify: typeof body.reverify === 'boolean' ? body.reverify : true,
998
+ reverify: typeof body.reverify === 'boolean'
999
+ ? body.reverify
1000
+ : (0, execution_actions_1.getExecutionActionClass)(body.type) === 'compatibility-mutation',
1767
1001
  ciMode: typeof body.ciMode === 'boolean' ? body.ciMode : undefined,
1768
1002
  evidenceDir: asNonEmptyString(body.evidenceDir),
1769
1003
  dedupeWindowMs: typeof body.dedupeWindowMs === 'number' ? body.dedupeWindowMs : undefined,
@@ -1771,7 +1005,54 @@ async function handleExecuteWorkspace(req, res) {
1771
1005
  const result = await (0, workspace_runtime_1.executeWorkspaceAction)(request, {
1772
1006
  cwd: process.cwd(),
1773
1007
  });
1774
- success(res, result);
1008
+ const workspaceActionClass = (0, execution_actions_1.getExecutionActionClass)(body.type);
1009
+ const executionBoundary = {
1010
+ routeScope: workspaceActionClass === 'canonical-governance'
1011
+ ? 'workspace-canonical-governance'
1012
+ : 'workspace-runtime-operation',
1013
+ actionClass: workspaceActionClass,
1014
+ compatibilityAction: false,
1015
+ canonicalRuntime: workspaceActionClass === 'canonical-governance',
1016
+ workspaceExecution: true,
1017
+ };
1018
+ success(res, {
1019
+ ...result,
1020
+ actionClass: workspaceActionClass,
1021
+ compatibilityAction: false,
1022
+ executionBoundary,
1023
+ governanceEnvelope: {
1024
+ schemaVersion: 'neurcode.governance-envelope.v1',
1025
+ identity: {
1026
+ executionId: result.executionId,
1027
+ executionType: result.type,
1028
+ source: result.source,
1029
+ actor: result.actor,
1030
+ completedAt: result.completedAt,
1031
+ },
1032
+ boundary: {
1033
+ actionClass: workspaceActionClass,
1034
+ runtimeBoundary: workspaceActionClass,
1035
+ mutatesCode: false,
1036
+ compatibilityAction: false,
1037
+ executionBoundary,
1038
+ compatibilityBoundary: null,
1039
+ },
1040
+ custody: {
1041
+ evidence: { generated: false, references: [], retentionLimit: null },
1042
+ replay: { checksum: null, mode: null, integrity: null },
1043
+ provenance: { runId: null, generatedAt: null },
1044
+ policy: { policyLockFingerprint: null, compiledPolicyFingerprint: null },
1045
+ receipts: { ids: [] },
1046
+ },
1047
+ lineage: {
1048
+ verificationTrend: result.totals.failed > 0 ? 'regressed' : 'unchanged',
1049
+ repositories: result.totals.repositories,
1050
+ attempted: result.totals.attempted,
1051
+ succeeded: result.totals.succeeded,
1052
+ failed: result.totals.failed,
1053
+ },
1054
+ },
1055
+ });
1775
1056
  }
1776
1057
  // ── Semantic Search Handlers ──────────────────────────────────────────────────
1777
1058
  /**
@@ -2213,7 +1494,10 @@ async function handleGovernanceFindings(req, res) {
2213
1494
  const parsed = JSON.parse(fs.readFileSync(candidate, 'utf8'));
2214
1495
  if (parsed && typeof parsed === 'object') {
2215
1496
  envelope = parsed;
2216
- const findings = parsed.findings;
1497
+ const governanceVerification = parsed.governanceVerification;
1498
+ const findings = parsed.governanceFindings
1499
+ || governanceVerification?.findings
1500
+ || parsed.findings;
2217
1501
  if (Array.isArray(findings)) {
2218
1502
  rawFindings = findings;
2219
1503
  }
@@ -2286,6 +1570,8 @@ async function handleGovernanceFindings(req, res) {
2286
1570
  advisoryCount,
2287
1571
  structuralCount: rawFindings.filter((f) => f.category === 'structural').length,
2288
1572
  semanticCount: rawFindings.filter((f) => f.category === 'semantic').length,
1573
+ intentGovernance: envelope.intentGovernance || null,
1574
+ intentGovernanceCount: rawFindings.filter((f) => f.sourceSystem === 'intent-engine').length,
2289
1575
  sourceFile: sourceFile || null,
2290
1576
  filtered: filtered.length,
2291
1577
  returned: paginated.length,
@@ -2884,6 +2170,21 @@ async function handlePilotReport(_req, res) {
2884
2170
  }
2885
2171
  // ── Server factory ─────────────────────────────────────────────────────────────
2886
2172
  function createDaemonServer() {
2173
+ const compatibilityExecutionHandlers = (0, execution_1.createCompatibilityExecutionHandlers)({
2174
+ readBody,
2175
+ success,
2176
+ failure,
2177
+ toSource,
2178
+ toActor,
2179
+ });
2180
+ const compatibilityMutationHandlers = (0, mutation_1.createCompatibilityMutationHandlers)({
2181
+ readBody,
2182
+ success,
2183
+ failure,
2184
+ toSource,
2185
+ toActor,
2186
+ recordPatchOutcome,
2187
+ });
2887
2188
  const server = http.createServer(async (req, res) => {
2888
2189
  const incomingRequestIdRaw = req.headers[REQUEST_ID_HEADER];
2889
2190
  const incomingRequestId = Array.isArray(incomingRequestIdRaw)
@@ -2906,7 +2207,7 @@ function createDaemonServer() {
2906
2207
  }
2907
2208
  const url = req.url ?? '/';
2908
2209
  const method = req.method ?? 'GET';
2909
- const normalizedRoutePath = normalizeRoutePath(url);
2210
+ const normalizedRoutePath = (0, routes_1.normalizeRoutePath)(url);
2910
2211
  recordDaemonRequest(normalizedRoutePath, method);
2911
2212
  res.__neurcodeRoutePath = normalizedRoutePath;
2912
2213
  try {
@@ -2925,7 +2226,19 @@ function createDaemonServer() {
2925
2226
  operational,
2926
2227
  executionBus: {
2927
2228
  schemaVersion: 'neurcode.execution.v1',
2928
- supportedActions: ['verify', 'fix', 'patch', 'apply-safe', 'reverify', 'policy-sync', 'intent-update'],
2229
+ supportedActions: execution_actions_1.EXECUTION_ACTION_TYPES,
2230
+ genericActions: [
2231
+ ...execution_actions_1.CANONICAL_EXECUTION_ACTION_TYPES,
2232
+ ...execution_actions_1.RUNTIME_OPERATION_EXECUTION_ACTION_TYPES,
2233
+ ],
2234
+ canonicalActions: execution_actions_1.CANONICAL_EXECUTION_ACTION_TYPES,
2235
+ runtimeOperationActions: execution_actions_1.RUNTIME_OPERATION_EXECUTION_ACTION_TYPES,
2236
+ compatibilityActions: execution_actions_1.COMPATIBILITY_EXECUTION_ACTION_TYPES,
2237
+ compatibilityBoundary: {
2238
+ explicitRoute: '/execute/compatibility',
2239
+ workspaceExplicitRoute: '/workspaces/execute/compatibility',
2240
+ legacyGenericDispatch: 'accepted-but-quarantined',
2241
+ },
2929
2242
  },
2930
2243
  runtimeEvents: {
2931
2244
  schemaVersion: 'neurcode.runtime-event.v1',
@@ -2948,6 +2261,15 @@ function createDaemonServer() {
2948
2261
  schemaVersion: 'neurcode.replay.state.v1',
2949
2262
  path: '/replay/state',
2950
2263
  },
2264
+ routeGroups: {
2265
+ canonicalGovernance: routes_1.CANONICAL_GOVERNANCE_ROUTE_DESCRIPTIONS,
2266
+ compatibilityMutation: routes_1.COMPATIBILITY_MUTATION_ROUTE_DESCRIPTIONS,
2267
+ runtimeExecution: routes_1.DAEMON_ROUTE_GROUPS['runtime-execution'],
2268
+ workspaceOrchestration: routes_1.DAEMON_ROUTE_GROUPS['workspace-orchestration'],
2269
+ replayEvidence: routes_1.DAEMON_ROUTE_GROUPS['replay-evidence'],
2270
+ operationalStatus: routes_1.DAEMON_ROUTE_GROUPS['operational-status'],
2271
+ docsTransport: routes_1.DAEMON_ROUTE_GROUPS['docs-transport'],
2272
+ },
2951
2273
  });
2952
2274
  return;
2953
2275
  }
@@ -3077,7 +2399,11 @@ function createDaemonServer() {
3077
2399
  return;
3078
2400
  }
3079
2401
  if (method === 'POST' && (url === '/workspaces/execute' || url.startsWith('/workspaces/execute?'))) {
3080
- await handleExecuteWorkspace(req, res);
2402
+ await handleExecuteWorkspace(req, res, compatibilityExecutionHandlers);
2403
+ return;
2404
+ }
2405
+ if (method === 'POST' && (url === '/workspaces/execute/compatibility' || url.startsWith('/workspaces/execute/compatibility?'))) {
2406
+ await compatibilityExecutionHandlers.handleWorkspaceExecute(req, res);
3081
2407
  return;
3082
2408
  }
3083
2409
  if (method === 'GET' && url.startsWith('/replay')) {
@@ -3135,8 +2461,12 @@ function createDaemonServer() {
3135
2461
  await handleDocsContent(res, decodeURIComponent(docsContentMatch[1]));
3136
2462
  return;
3137
2463
  }
2464
+ if (method === 'POST' && (url === '/execute/compatibility' || url.startsWith('/execute/compatibility?'))) {
2465
+ await compatibilityExecutionHandlers.handleExecute(req, res);
2466
+ return;
2467
+ }
3138
2468
  if (method === 'POST' && (url === '/execute' || url.startsWith('/execute?'))) {
3139
- await handleExecute(req, res);
2469
+ await handleExecute(req, res, compatibilityExecutionHandlers);
3140
2470
  return;
3141
2471
  }
3142
2472
  if (method === 'POST' && (url === '/verify' || url.startsWith('/verify?'))) {
@@ -3144,23 +2474,23 @@ function createDaemonServer() {
3144
2474
  return;
3145
2475
  }
3146
2476
  if (method === 'POST' && (url === '/fix' || url.startsWith('/fix?'))) {
3147
- await handleFix(req, res);
2477
+ await compatibilityMutationHandlers.handleFix(req, res);
3148
2478
  return;
3149
2479
  }
3150
2480
  if (method === 'POST' && (url === '/fix/apply-safe' || url.startsWith('/fix/apply-safe?'))) {
3151
- await handleFixApplySafe(req, res);
2481
+ await compatibilityMutationHandlers.handleFixApplySafe(req, res);
3152
2482
  return;
3153
2483
  }
3154
2484
  if (method === 'POST' && (url === '/patch/preview' || url.startsWith('/patch/preview?'))) {
3155
- await handlePatchPreview(req, res);
2485
+ await compatibilityMutationHandlers.handlePatchPreview(req, res);
3156
2486
  return;
3157
2487
  }
3158
2488
  if (method === 'POST' && (url === '/patch/rollback' || url.startsWith('/patch/rollback?'))) {
3159
- await handlePatchRollback(req, res);
2489
+ await compatibilityMutationHandlers.handlePatchRollback(req, res);
3160
2490
  return;
3161
2491
  }
3162
2492
  if (method === 'POST' && (url === '/patch' || url.startsWith('/patch?'))) {
3163
- await handlePatch(req, res);
2493
+ await compatibilityMutationHandlers.handlePatch(req, res);
3164
2494
  return;
3165
2495
  }
3166
2496
  failure(res, `No route for ${method} ${url}`, 404);
@@ -3246,46 +2576,13 @@ function startDaemon() {
3246
2576
  });
3247
2577
  server.listen(exports.DAEMON_PORT, exports.DAEMON_HOST, () => {
3248
2578
  console.log(`\nNeurcode daemon v2 running on http://localhost:${exports.DAEMON_PORT}`);
3249
- console.log(` POST /verify → execution bus: verify`);
3250
- console.log(` POST /fix → execution bus: fix + reverify`);
3251
- console.log(` POST /fix/apply-safe → execution bus: apply-safe + reverify`);
3252
- console.log(` POST /patch/preview → deterministic patch preview (before/after diff)`);
3253
- console.log(` POST /patch/rollback deterministic rollback apply by receipt`);
3254
- console.log(` POST /patch → execution bus: patch + reverify`);
3255
- console.log(` POST /execute → unified execution endpoint`);
3256
- console.log(` GET /executions → execution history`);
3257
- console.log(` GET /executions/:id → execution detail`);
3258
- console.log(` GET /executions/:id/timeline → phase timeline + durations`);
3259
- console.log(` GET /executions/:id/diff → verification + patch inspection`);
3260
- console.log(` GET /events → runtime event history`);
3261
- console.log(` GET /events/stream → SSE deterministic governance runtime`);
3262
- console.log(` GET /ops/summary → daemon operational health + reliability metrics`);
3263
- console.log(` GET /control-plane → governance control-plane state + snapshots`);
3264
- console.log(` POST /control-plane/preview → deterministic config impact preview`);
3265
- console.log(` PUT /control-plane → apply deterministic governance config update`);
3266
- console.log(` GET /workspaces → workspace catalog + active pointer`);
3267
- console.log(` GET /workspaces/runtime → workspace governance runtime snapshot`);
3268
- console.log(` GET /workspaces/:id/runtime → workspace-specific runtime snapshot`);
3269
- console.log(` GET /workspaces/:id → workspace definition`);
3270
- console.log(` POST /workspaces → create workspace`);
3271
- console.log(` PUT /workspaces/:id → update workspace`);
3272
- console.log(` POST /workspaces/:id/activate → set active workspace`);
3273
- console.log(` POST /workspaces/:id/repositories → add repository to workspace`);
3274
- console.log(` POST /workspaces/execute → workspace-scoped deterministic execution`);
3275
- console.log(` GET /workspaces/:id/cross-repo-graph → detected cross-repo dependency edges`);
3276
- console.log(` POST /workspaces/:id/federated-context → multi-repo blast radius analysis`);
3277
- console.log(` POST /workspaces/:id/semantic-search → TF-IDF vector similarity file search`);
3278
- console.log(` POST /workspaces/:id/semantic-index/build → rebuild semantic index from brain context`);
3279
- console.log(` POST /workspaces/:id/intent-expand → signed semantic intent governance artifact`);
3280
- console.log(` GET /replay/state → deterministic governance state replay`);
3281
- console.log(` GET /replay/execution/:id → deterministic execution replay`);
3282
- console.log(` GET /replay/workspace/:id → deterministic workspace replay`);
3283
- console.log(` GET /replay/timeline → deterministic governance timeline replay`);
3284
- console.log(` GET /governance/findings → canonical governance findings (last verify output)`);
3285
- console.log(` GET /governance/overview → governance posture summary`);
3286
- console.log(` GET /brain/cache-status → brain cache manifest and freshness`);
3287
- console.log(` GET /remediation/status → remediation artifacts and receipts`);
3288
- console.log(` GET /pilot-report → governance health metrics and trend`);
2579
+ (0, routes_1.logDaemonRouteGroup)('\nCanonical governance routes:', routes_1.CANONICAL_GOVERNANCE_ROUTE_DESCRIPTIONS);
2580
+ (0, routes_1.logDaemonRouteGroup)('\nCompatibility mutation routes (legacy):', routes_1.COMPATIBILITY_MUTATION_ROUTE_DESCRIPTIONS);
2581
+ (0, routes_1.logDaemonRouteGroup)('\nRuntime execution routes:', routes_1.DAEMON_ROUTE_GROUPS['runtime-execution']);
2582
+ (0, routes_1.logDaemonRouteGroup)('\nWorkspace orchestration routes:', routes_1.DAEMON_ROUTE_GROUPS['workspace-orchestration']);
2583
+ (0, routes_1.logDaemonRouteGroup)('\nReplay and evidence routes:', routes_1.DAEMON_ROUTE_GROUPS['replay-evidence']);
2584
+ (0, routes_1.logDaemonRouteGroup)('\nOperational status routes:', routes_1.DAEMON_ROUTE_GROUPS['operational-status']);
2585
+ (0, routes_1.logDaemonRouteGroup)('\nDocs transport routes:', routes_1.DAEMON_ROUTE_GROUPS['docs-transport']);
3289
2586
  console.log(`\n CWD: ${cwd}`);
3290
2587
  console.log(` Press Ctrl+C to stop.\n`);
3291
2588
  });