@deksden-com/dd-flow-cli 0.9.0-beta.14 → 0.9.0-beta.141

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 (493) hide show
  1. package/CHANGELOG.md +740 -0
  2. package/README.md +143 -1
  3. package/dist/build-info.json +8 -8
  4. package/dist/cli/argument-values.js +38 -0
  5. package/dist/cli/command-inputs.js +376 -0
  6. package/dist/cli/command-metadata.js +197 -0
  7. package/dist/cli/command-option-descriptions.js +191 -0
  8. package/dist/cli/completion-cli.js +70 -0
  9. package/dist/cli/completion.js +57 -0
  10. package/dist/cli/error-output.js +52 -0
  11. package/dist/cli/executor-onboarding.js +76 -0
  12. package/dist/cli/flows.js +29 -0
  13. package/dist/cli/harnesses.js +84 -0
  14. package/dist/cli/help.js +328 -18
  15. package/dist/cli/hook-ingress.js +78 -0
  16. package/dist/cli/input-preparation.js +165 -0
  17. package/dist/cli/memory-flow-admission.js +44 -0
  18. package/dist/cli/memory-init-invocation.js +78 -0
  19. package/dist/cli/memory-init.js +240 -0
  20. package/dist/cli/memory-storage-admission.js +53 -0
  21. package/dist/cli/models.js +39 -0
  22. package/dist/cli/native-hook-ingress.js +80 -0
  23. package/dist/cli/operator-profiles.js +61 -0
  24. package/dist/cli/output-options.js +35 -0
  25. package/dist/cli/response-file.js +71 -0
  26. package/dist/cli/run-cli.js +1689 -545
  27. package/dist/cli/runtime-maintenance-diagnostics.js +46 -0
  28. package/dist/cli/runtime-maintenance-ingress.js +52 -0
  29. package/dist/cli/runtime-process.js +153 -0
  30. package/dist/cli/setup.js +149 -0
  31. package/dist/cli.js +71 -2
  32. package/dist/domain/stage-catalog.js +1 -1
  33. package/dist/domain/stage-handler-identities.js +20 -0
  34. package/dist/harness-runtime/DD-ZCODE.md +112 -0
  35. package/dist/harness-runtime/OPENCODE-LICENSE.txt +24 -0
  36. package/dist/harness-runtime/bin/dd-agy.mjs +56 -0
  37. package/dist/harness-runtime/bin/dd-codex.mjs +27 -0
  38. package/dist/harness-runtime/bin/dd-droid.mjs +34 -0
  39. package/dist/harness-runtime/bin/dd-grok.mjs +40 -0
  40. package/dist/harness-runtime/bin/dd-opencode.mjs +22 -0
  41. package/dist/harness-runtime/bin/dd-zcode.mjs +87 -0
  42. package/dist/harness-runtime/lib/adapter-timeouts.d.mts +5 -0
  43. package/dist/harness-runtime/lib/adapter-timeouts.mjs +34 -0
  44. package/dist/harness-runtime/lib/agy-hooks.d.mts +1 -0
  45. package/dist/harness-runtime/lib/agy-hooks.mjs +9 -0
  46. package/dist/harness-runtime/lib/daemon-observation.d.mts +2 -0
  47. package/dist/harness-runtime/lib/daemon-observation.mjs +163 -0
  48. package/dist/harness-runtime/lib/daemon-operations.d.mts +1 -0
  49. package/dist/harness-runtime/lib/daemon-operations.mjs +371 -0
  50. package/dist/harness-runtime/lib/dd-agy-daemon.d.mts +6 -0
  51. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +728 -0
  52. package/dist/harness-runtime/lib/dd-agy.mjs +70 -0
  53. package/dist/harness-runtime/lib/dd-codex-daemon.d.mts +1 -0
  54. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +196 -0
  55. package/dist/harness-runtime/lib/dd-codex.d.mts +1 -0
  56. package/dist/harness-runtime/lib/dd-codex.mjs +817 -0
  57. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +140 -0
  58. package/dist/harness-runtime/lib/dd-droid.mjs +584 -0
  59. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +498 -0
  60. package/dist/harness-runtime/lib/dd-grok.mjs +177 -0
  61. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +557 -0
  62. package/dist/harness-runtime/lib/dd-opencode.mjs +363 -0
  63. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +751 -0
  64. package/dist/harness-runtime/lib/dd-zcode.mjs +1145 -0
  65. package/dist/harness-runtime/lib/delegation-instructions.d.mts +14 -0
  66. package/dist/harness-runtime/lib/delegation-instructions.mjs +157 -0
  67. package/dist/harness-runtime/lib/dispatch-fence.mjs +14 -0
  68. package/dist/harness-runtime/lib/driver-recovery.mjs +139 -0
  69. package/dist/harness-runtime/lib/droid-observation.mjs +66 -0
  70. package/dist/harness-runtime/lib/lease-renewal.d.mts +8 -0
  71. package/dist/harness-runtime/lib/lease-renewal.mjs +37 -0
  72. package/dist/harness-runtime/lib/lifecycle-command.d.mts +20 -0
  73. package/dist/harness-runtime/lib/lifecycle-command.mjs +273 -0
  74. package/dist/harness-runtime/lib/lifecycle-contract.d.mts +10 -0
  75. package/dist/harness-runtime/lib/lifecycle-contract.mjs +19 -0
  76. package/dist/harness-runtime/lib/managed-daemon.d.mts +16 -0
  77. package/dist/harness-runtime/lib/managed-daemon.mjs +683 -0
  78. package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
  79. package/dist/harness-runtime/lib/model-observations.mjs +101 -0
  80. package/dist/harness-runtime/lib/native-children.d.mts +16 -0
  81. package/dist/harness-runtime/lib/native-children.mjs +113 -0
  82. package/dist/harness-runtime/lib/native-hook-command.d.mts +7 -0
  83. package/dist/harness-runtime/lib/native-hook-command.mjs +251 -0
  84. package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
  85. package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
  86. package/dist/harness-runtime/lib/native-streams.mjs +45 -0
  87. package/dist/harness-runtime/lib/observation-clock.d.mts +18 -0
  88. package/dist/harness-runtime/lib/observation-clock.mjs +92 -0
  89. package/dist/harness-runtime/lib/opencode-plugin.mjs +85 -0
  90. package/dist/harness-runtime/lib/operation-context.mjs +5 -0
  91. package/dist/harness-runtime/lib/operation-errors.d.mts +16 -0
  92. package/dist/harness-runtime/lib/operation-errors.mjs +127 -0
  93. package/dist/harness-runtime/lib/operation-progress.d.mts +7 -0
  94. package/dist/harness-runtime/lib/operation-progress.mjs +114 -0
  95. package/dist/harness-runtime/lib/process-json.d.mts +5 -0
  96. package/dist/harness-runtime/lib/process-json.mjs +201 -0
  97. package/dist/harness-runtime/lib/process-snapshot.mjs +10 -0
  98. package/dist/harness-runtime/lib/provider-overload-policy.d.mts +13 -0
  99. package/dist/harness-runtime/lib/provider-overload-policy.mjs +138 -0
  100. package/dist/harness-runtime/lib/runner-events.mjs +200 -0
  101. package/dist/harness-runtime/lib/runner-lock.mjs +42 -0
  102. package/dist/harness-runtime/lib/session-settlement.mjs +30 -0
  103. package/dist/harness-runtime/lib/setup-progress.d.mts +9 -0
  104. package/dist/harness-runtime/lib/setup-progress.mjs +51 -0
  105. package/dist/harness-runtime/lib/tool-observations.d.mts +21 -0
  106. package/dist/harness-runtime/lib/tool-observations.mjs +228 -0
  107. package/dist/harness-runtime/lib/zcode-usage.mjs +55 -0
  108. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-1y4a697q.js +81 -0
  109. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-2ny4vxct.js +92 -0
  110. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-6mptkzbc.js +0 -0
  111. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-7x67cf1q.js +52 -0
  112. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9rqn6x4v.js +16 -0
  113. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9vdz0zwn.js +1661 -0
  114. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ecs5ftka.js +1466 -0
  115. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-frbwqjmf.js +145 -0
  116. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gne7h7mq.js +50 -0
  117. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gx9wnkzr.js +105 -0
  118. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-m2eywc8w.js +0 -0
  119. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-nwcpakzx.js +12 -0
  120. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-q4g3afnw.js +623 -0
  121. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-qav6mfdz.js +0 -0
  122. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-sxt88q69.js +12 -0
  123. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-t1xa31vm.js +39 -0
  124. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ve4aws36.js +103 -0
  125. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vmytr4q8.js +4 -0
  126. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vt9jbch8.js +36 -0
  127. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vyas3vgt.js +0 -0
  128. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-wjyeq25y.js +30 -0
  129. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-xgnj2w4v.js +20 -0
  130. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-y2etg5bs.js +9 -0
  131. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ydhz1zrh.js +238 -0
  132. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-z6qdwcsf.js +62 -0
  133. package/dist/harness-runtime/vendor/opencode-client/contract.d.ts +1 -0
  134. package/dist/harness-runtime/vendor/opencode-client/contract.js +12 -0
  135. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.d.ts +2806 -0
  136. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.js +0 -0
  137. package/dist/harness-runtime/vendor/opencode-client/effect/api.d.ts +4 -0
  138. package/dist/harness-runtime/vendor/opencode-client/effect/api.js +0 -0
  139. package/dist/harness-runtime/vendor/opencode-client/effect/client.d.ts +2530 -0
  140. package/dist/harness-runtime/vendor/opencode-client/effect/client.js +15 -0
  141. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.d.ts +7 -0
  142. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.js +6 -0
  143. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.d.ts +2529 -0
  144. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.js +8 -0
  145. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.d.ts +2 -0
  146. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.js +12 -0
  147. package/dist/harness-runtime/vendor/opencode-client/effect/index.d.ts +35 -0
  148. package/dist/harness-runtime/vendor/opencode-client/effect/index.js +75 -0
  149. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.d.ts +20 -0
  150. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.js +11 -0
  151. package/dist/harness-runtime/vendor/opencode-client/effect/service.d.ts +90 -0
  152. package/dist/harness-runtime/vendor/opencode-client/effect/service.js +187 -0
  153. package/dist/harness-runtime/vendor/opencode-client/package.json +84 -0
  154. package/dist/harness-runtime/vendor/opencode-client/promise/api.d.ts +21 -0
  155. package/dist/harness-runtime/vendor/opencode-client/promise/api.js +0 -0
  156. package/dist/harness-runtime/vendor/opencode-client/promise/client.d.ts +252 -0
  157. package/dist/harness-runtime/vendor/opencode-client/promise/client.js +14 -0
  158. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.d.ts +8 -0
  159. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.js +6 -0
  160. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.d.ts +259 -0
  161. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.js +7 -0
  162. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.d.ts +3 -0
  163. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.js +79 -0
  164. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.d.ts +8932 -0
  165. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.js +70 -0
  166. package/dist/harness-runtime/vendor/opencode-client/promise/index.d.ts +6 -0
  167. package/dist/harness-runtime/vendor/opencode-client/promise/index.js +83 -0
  168. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.d.ts +32 -0
  169. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.js +7 -0
  170. package/dist/harness-runtime/vendor/opencode-client/promise/service.d.ts +24 -0
  171. package/dist/harness-runtime/vendor/opencode-client/promise/service.js +187 -0
  172. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.d.ts +12 -0
  173. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.js +14 -0
  174. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.d.ts +20 -0
  175. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.js +14 -0
  176. package/dist/harness-runtime/vendor/opencode-client/service-contender.d.ts +37 -0
  177. package/dist/harness-runtime/vendor/opencode-client/service-contender.js +10 -0
  178. package/dist/harness-runtime/vendor/opencode-client/service-probe.d.ts +70 -0
  179. package/dist/harness-runtime/vendor/opencode-client/service-probe.js +16 -0
  180. package/dist/harness-runtime/vendor/opencode-client/service-timing.d.ts +12 -0
  181. package/dist/harness-runtime/vendor/opencode-client/service-timing.js +10 -0
  182. package/dist/harness-runtime/vendor/opencode-client/service-version.d.ts +2 -0
  183. package/dist/harness-runtime/vendor/opencode-client/service-version.js +6 -0
  184. package/dist/harness-runtime/vendor/opencode-client/service.d.ts +52 -0
  185. package/dist/harness-runtime/vendor/opencode-client/service.js +1 -0
  186. package/dist/harness-runtime/vendor/opencode-client/shared-events.d.ts +11 -0
  187. package/dist/harness-runtime/vendor/opencode-client/shared-events.js +8 -0
  188. package/dist/harness-runtime/vendor/opencode-client/solid/connection.d.ts +37 -0
  189. package/dist/harness-runtime/vendor/opencode-client/solid/connection.js +10 -0
  190. package/dist/harness-runtime/vendor/opencode-client/solid/data.d.ts +211 -0
  191. package/dist/harness-runtime/vendor/opencode-client/solid/data.js +18 -0
  192. package/dist/harness-runtime/vendor/opencode-client/solid/index.d.ts +3 -0
  193. package/dist/harness-runtime/vendor/opencode-client/solid/index.js +32 -0
  194. package/dist/harness-runtime/vendor/opencode-client/solid/pty.d.ts +22 -0
  195. package/dist/harness-runtime/vendor/opencode-client/solid/pty.js +8 -0
  196. package/dist/harness-runtime/vendor/opencode-plugin.mjs +3 -0
  197. package/dist/protocol/local-files.js +18 -9
  198. package/dist/runtime/context.js +8 -4
  199. package/dist/schemas/agent-profile.schema.json +1 -1
  200. package/dist/schemas/code-review-result.schema.json +1 -1
  201. package/dist/schemas/code-verification.schema.json +7 -5
  202. package/dist/schemas/code-work-batch.schema.json +2 -2
  203. package/dist/schemas/discovery-result.schema.json +184 -0
  204. package/dist/schemas/execution-bundle.schema.json +205 -0
  205. package/dist/schemas/execution-settings.schema.json +162 -0
  206. package/dist/schemas/flow-descriptor.schema.json +54 -0
  207. package/dist/schemas/flow-run.schema.json +28 -0
  208. package/dist/schemas/harness-catalog.schema.json +80 -0
  209. package/dist/schemas/mb-init-compose-result.schema.json +457 -0
  210. package/dist/schemas/mb-init-discover-result.schema.json +500 -0
  211. package/dist/schemas/mb-init-finish-result.schema.json +422 -0
  212. package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
  213. package/dist/schemas/mb-init-review-result.schema.json +396 -0
  214. package/dist/schemas/mb-init-verify-result.schema.json +391 -0
  215. package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
  216. package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
  217. package/dist/schemas/memory-composition-work-result.schema.json +38 -0
  218. package/dist/schemas/memory-repair-work-result.schema.json +49 -0
  219. package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
  220. package/dist/schemas/memory-review-work-result.schema.json +43 -0
  221. package/dist/schemas/model-catalog.schema.json +153 -0
  222. package/dist/schemas/plan-review-decision.schema.json +3 -3
  223. package/dist/schemas/plan-review-result.schema.json +2 -2
  224. package/dist/schemas/profile-settings.schema.json +122 -0
  225. package/dist/schemas/release-manifest.schema.json +291 -0
  226. package/dist/schemas/run-control-receipt.schema.json +118 -0
  227. package/dist/schemas/run-control-request.schema.json +36 -0
  228. package/dist/schemas/run-engine-binding.schema.json +1 -1
  229. package/dist/schemas/vnext-protocol-plan.schema.json +2 -2
  230. package/dist/services/branch-context.js +3 -3
  231. package/dist/services/canon.js +11 -8
  232. package/dist/services/check-runner-evidence.js +250 -0
  233. package/dist/services/cleanup.js +133 -40
  234. package/dist/services/cli-operation-classifier.js +25 -62
  235. package/dist/services/cli-upgrade-allowlist.js +27 -0
  236. package/dist/services/code-checks.js +1168 -107
  237. package/dist/services/codex-hook-delivery.js +32 -0
  238. package/dist/services/command-context.js +80 -0
  239. package/dist/services/compatibility-preflight.js +13 -3
  240. package/dist/services/config.js +11 -8
  241. package/dist/services/continuation-outcome.js +20 -0
  242. package/dist/services/controller-child-capacity.js +13 -0
  243. package/dist/services/controller-child-observer.js +115 -0
  244. package/dist/services/controller-execution.js +88 -0
  245. package/dist/services/controller-fanout.js +202 -0
  246. package/dist/services/dashboard.js +143 -58
  247. package/dist/services/descriptor-coordinator-session.js +35 -0
  248. package/dist/services/descriptor-root-work.js +53 -0
  249. package/dist/services/descriptor-run-settlement.js +105 -0
  250. package/dist/services/descriptor-run-start.js +449 -0
  251. package/dist/services/descriptor-stage-coordinator.js +197 -0
  252. package/dist/services/descriptor-stage-settlement.js +222 -0
  253. package/dist/services/descriptor-stage-start.js +139 -0
  254. package/dist/services/discovery/agy-discovery.js +2 -0
  255. package/dist/services/discovery/codex-discovery.js +2 -0
  256. package/dist/services/discovery/droid-discovery.js +2 -0
  257. package/dist/services/discovery/grok-discovery.js +2 -0
  258. package/dist/services/discovery/opencode-discovery.js +2 -0
  259. package/dist/services/discovery/static.js +31 -0
  260. package/dist/services/discovery/zcode-discovery.js +2 -0
  261. package/dist/services/engines.js +294 -153
  262. package/dist/services/eval-snapshots.js +1215 -116
  263. package/dist/services/execution-bundles.js +263 -0
  264. package/dist/services/execution-policy.js +185 -0
  265. package/dist/services/executor-onboarding.js +56 -0
  266. package/dist/services/external-work-launch.js +308 -0
  267. package/dist/services/flow-catalog.js +21 -0
  268. package/dist/services/flow-descriptors.js +82 -0
  269. package/dist/services/frozen-engine.js +250 -0
  270. package/dist/services/generic-execution.js +164 -0
  271. package/dist/services/harness-adapter.js +355 -36
  272. package/dist/services/harness-config.js +2 -0
  273. package/dist/services/harness-discovery.js +29 -0
  274. package/dist/services/harness-doctor.js +75 -0
  275. package/dist/services/harness-probe-effects.js +51 -0
  276. package/dist/services/harness-version-probe.js +100 -0
  277. package/dist/services/hooks.js +771 -325
  278. package/dist/services/hybrid-contracts.js +483 -0
  279. package/dist/services/ids.js +29 -1
  280. package/dist/services/installation-lock.js +95 -0
  281. package/dist/services/installed-flow-source.js +183 -0
  282. package/dist/services/lanes.js +78 -65
  283. package/dist/services/lifecycle-command.js +1 -288
  284. package/dist/services/lifecycle-contract.js +1 -0
  285. package/dist/services/lifecycle-invocations.js +2007 -0
  286. package/dist/services/managed-daemon-binding.js +38 -0
  287. package/dist/services/managed-lease-monitor.js +133 -0
  288. package/dist/services/managed-processes.js +475 -55
  289. package/dist/services/memory-accepted-composition.js +77 -0
  290. package/dist/services/memory-baseline-preservation.js +65 -0
  291. package/dist/services/memory-completed-correction-wave.js +320 -0
  292. package/dist/services/memory-compose-handler.js +258 -0
  293. package/dist/services/memory-composition-acceptance.js +199 -0
  294. package/dist/services/memory-composition-graph.js +134 -0
  295. package/dist/services/memory-composition-registration.js +146 -0
  296. package/dist/services/memory-composition-work-custody.js +151 -0
  297. package/dist/services/memory-composition-work-results.js +96 -0
  298. package/dist/services/memory-corrected-review-acceptance.js +129 -0
  299. package/dist/services/memory-corrected-review-batch.js +30 -0
  300. package/dist/services/memory-corrected-review-findings.js +106 -0
  301. package/dist/services/memory-corrected-review-inputs.js +210 -0
  302. package/dist/services/memory-corrected-review-projection.js +78 -0
  303. package/dist/services/memory-corrected-review-receipt.js +170 -0
  304. package/dist/services/memory-corrected-review-registration.js +191 -0
  305. package/dist/services/memory-correction-check-receipt.js +219 -0
  306. package/dist/services/memory-correction-input-owner.js +6 -0
  307. package/dist/services/memory-discover-handler.js +104 -0
  308. package/dist/services/memory-finish-evidence.js +435 -0
  309. package/dist/services/memory-finish-handler.js +215 -0
  310. package/dist/services/memory-finish-integration.js +280 -0
  311. package/dist/services/memory-finish-readiness.js +122 -0
  312. package/dist/services/memory-git-integration.js +151 -0
  313. package/dist/services/memory-historical-corrected-review.js +206 -0
  314. package/dist/services/memory-historical-original-review.js +130 -0
  315. package/dist/services/memory-historical-repair-registration.js +99 -0
  316. package/dist/services/memory-historical-second-review.js +128 -0
  317. package/dist/services/memory-init-bootstrap-readiness.js +210 -0
  318. package/dist/services/memory-init-contexts.js +89 -0
  319. package/dist/services/memory-init-controller-start.js +84 -0
  320. package/dist/services/memory-init-engine-release.js +223 -0
  321. package/dist/services/memory-init-git-policy.js +136 -0
  322. package/dist/services/memory-init-lint-capability.js +185 -0
  323. package/dist/services/memory-init-native-capacity.js +296 -0
  324. package/dist/services/memory-init-preflight.js +330 -0
  325. package/dist/services/memory-init-project-bootstrap.js +599 -0
  326. package/dist/services/memory-init-request-candidate.js +157 -0
  327. package/dist/services/memory-init-request-input.js +66 -0
  328. package/dist/services/memory-init-resource-storage.js +125 -0
  329. package/dist/services/memory-init-run-allocation.js +81 -0
  330. package/dist/services/memory-init-run-bundle.js +98 -0
  331. package/dist/services/memory-init-start.js +181 -0
  332. package/dist/services/memory-init-startup-custody.js +80 -0
  333. package/dist/services/memory-init-startup-input.js +240 -0
  334. package/dist/services/memory-init-storage.js +81 -0
  335. package/dist/services/memory-init-stores.js +359 -0
  336. package/dist/services/memory-init-worktrunk-capability.js +178 -0
  337. package/dist/services/memory-layer-publication.js +611 -0
  338. package/dist/services/memory-layer.js +156 -0
  339. package/dist/services/memory-lint-config.js +85 -0
  340. package/dist/services/memory-native-review-copy.js +165 -0
  341. package/dist/services/memory-normal-flow-entry.js +75 -0
  342. package/dist/services/memory-ordinary-defaults.js +112 -0
  343. package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
  344. package/dist/services/memory-preflight-handler.js +259 -0
  345. package/dist/services/memory-repair-current-view.js +299 -0
  346. package/dist/services/memory-repair-document-delta.js +451 -0
  347. package/dist/services/memory-repair-history.js +491 -0
  348. package/dist/services/memory-repair-physical-binding.js +312 -0
  349. package/dist/services/memory-repair-publication-files.js +152 -0
  350. package/dist/services/memory-repair-publication-intent.js +27 -0
  351. package/dist/services/memory-repair-publication-plan.js +160 -0
  352. package/dist/services/memory-repair-publication-source.js +225 -0
  353. package/dist/services/memory-repair-publication.js +794 -0
  354. package/dist/services/memory-repair-registration.js +239 -0
  355. package/dist/services/memory-repair-work-baseline.js +413 -0
  356. package/dist/services/memory-repair-work-completion.js +97 -0
  357. package/dist/services/memory-repair-work-custody.js +73 -0
  358. package/dist/services/memory-repair-work-results.js +89 -0
  359. package/dist/services/memory-repair-workspace.js +252 -0
  360. package/dist/services/memory-repair-writer-copy.js +735 -0
  361. package/dist/services/memory-result-binding.js +173 -0
  362. package/dist/services/memory-retained-review-authority.js +129 -0
  363. package/dist/services/memory-retained-review-results.js +70 -0
  364. package/dist/services/memory-retained-second-baseline.js +102 -0
  365. package/dist/services/memory-retained-second-repairs.js +156 -0
  366. package/dist/services/memory-review-acceptance.js +214 -0
  367. package/dist/services/memory-review-correction-plan.js +171 -0
  368. package/dist/services/memory-review-handler.js +585 -0
  369. package/dist/services/memory-review-inputs.js +200 -0
  370. package/dist/services/memory-review-receipt.js +180 -0
  371. package/dist/services/memory-review-registration.js +108 -0
  372. package/dist/services/memory-review-work-custody.js +124 -0
  373. package/dist/services/memory-review-work-input.js +72 -0
  374. package/dist/services/memory-review-work-results.js +73 -0
  375. package/dist/services/memory-second-corrected-review-inputs.js +165 -0
  376. package/dist/services/memory-second-correction-plan.js +76 -0
  377. package/dist/services/memory-second-repair-baseline.js +91 -0
  378. package/dist/services/memory-second-repair-launch.js +614 -0
  379. package/dist/services/memory-second-repair-registration.js +88 -0
  380. package/dist/services/memory-second-repair-source.js +187 -0
  381. package/dist/services/memory-second-review-acceptance.js +115 -0
  382. package/dist/services/memory-source-observations.js +117 -0
  383. package/dist/services/memory-stage-dispatch.js +28 -0
  384. package/dist/services/memory-stage-results.js +199 -0
  385. package/dist/services/memory-verification-acceptance.js +135 -0
  386. package/dist/services/memory-verification-checks.js +252 -0
  387. package/dist/services/memory-verification-receipt.js +159 -0
  388. package/dist/services/memory-verify-handler.js +135 -0
  389. package/dist/services/memory-work-result-preparation.js +63 -0
  390. package/dist/services/merge-queue.js +228 -149
  391. package/dist/services/merge-server.js +161 -35
  392. package/dist/services/migrations.js +37 -16
  393. package/dist/services/model-catalog.js +109 -0
  394. package/dist/services/model-discovery.js +46 -0
  395. package/dist/services/native-daemon-history.js +49 -0
  396. package/dist/services/native-session-control.js +39 -0
  397. package/dist/services/operator-profiles.js +236 -0
  398. package/dist/services/plan-runtime.js +26 -11
  399. package/dist/services/plans.js +28 -25
  400. package/dist/services/projects.js +37 -17
  401. package/dist/services/prompts.js +28 -17
  402. package/dist/services/protocols.js +163 -87
  403. package/dist/services/provider-capacity.js +385 -0
  404. package/dist/services/recovery-observation-budget.js +121 -0
  405. package/dist/services/recovery-snapshot-database.js +560 -0
  406. package/dist/services/release-archive-producer.js +52 -0
  407. package/dist/services/release-archive.js +143 -0
  408. package/dist/services/release-cache.js +142 -0
  409. package/dist/services/release-compatibility.js +18 -0
  410. package/dist/services/release-download.js +67 -0
  411. package/dist/services/release-envelope.js +104 -0
  412. package/dist/services/release-manifest.js +45 -0
  413. package/dist/services/release-payload.js +114 -0
  414. package/dist/services/release-producer.js +63 -0
  415. package/dist/services/release-provenance.js +160 -0
  416. package/dist/services/release-registry.js +66 -0
  417. package/dist/services/release-source.js +194 -0
  418. package/dist/services/repair-intents.js +42 -0
  419. package/dist/services/review-copy.js +165 -0
  420. package/dist/services/review-deferral.js +23 -0
  421. package/dist/services/run-control-receipt.js +56 -0
  422. package/dist/services/run-control-worker.js +411 -0
  423. package/dist/services/run-control.js +1056 -0
  424. package/dist/services/run-controller-adapter.js +399 -0
  425. package/dist/services/run-controller-capture.js +186 -0
  426. package/dist/services/run-controller-process.js +208 -0
  427. package/dist/services/run-controller-recovery.js +289 -0
  428. package/dist/services/run-controller-state.js +97 -0
  429. package/dist/services/run-controller.js +1205 -0
  430. package/dist/services/run-engine-bindings.js +1 -1
  431. package/dist/services/run-fork.js +147 -0
  432. package/dist/services/run-health.js +149 -0
  433. package/dist/services/run-observations.js +152 -0
  434. package/dist/services/run-projection.js +22 -64
  435. package/dist/services/run-recovery-guard.js +77 -0
  436. package/dist/services/run-recovery-runtime.js +112 -0
  437. package/dist/services/run-recovery.js +489 -0
  438. package/dist/services/run-start-custody.js +177 -0
  439. package/dist/services/runs.js +1019 -247
  440. package/dist/services/runtime-budget.js +430 -0
  441. package/dist/services/runtime-command.js +43 -0
  442. package/dist/services/runtime-scope-capture.js +52 -0
  443. package/dist/services/runtime-scope-control.js +468 -0
  444. package/dist/services/runtime-scope-resume.js +599 -0
  445. package/dist/services/runtime-scope-stop.js +210 -0
  446. package/dist/services/runtime-scope-worker.js +287 -0
  447. package/dist/services/runtime-service.js +96 -0
  448. package/dist/services/schema-validation.js +10 -8
  449. package/dist/services/scope-writer-cleanup.js +27 -0
  450. package/dist/services/sessions.js +35 -69
  451. package/dist/services/setup.js +377 -0
  452. package/dist/services/stage-blocker.js +17 -7
  453. package/dist/services/stage-context.js +193 -19
  454. package/dist/services/stage-handlers.js +74 -0
  455. package/dist/services/stage-lifecycle.js +152 -116
  456. package/dist/services/stage-pause.js +89 -75
  457. package/dist/services/stage-report-renderer.js +234 -6
  458. package/dist/services/stage-work-graph.js +52 -0
  459. package/dist/services/tooling.js +41 -30
  460. package/dist/services/usage.js +49 -101
  461. package/dist/services/verification-matrix.js +375 -0
  462. package/dist/services/vnext-code-review.js +223 -88
  463. package/dist/services/vnext-code.js +327 -226
  464. package/dist/services/vnext-contracts.js +10 -1
  465. package/dist/services/vnext-execution-profile.js +80 -5
  466. package/dist/services/vnext-fanout.js +311 -19
  467. package/dist/services/vnext-merge.js +332 -111
  468. package/dist/services/vnext-plan-review.js +279 -127
  469. package/dist/services/vnext-plan.js +228 -104
  470. package/dist/services/vnext-protocolize.js +531 -95
  471. package/dist/services/vnext-specify.js +119 -81
  472. package/dist/services/vnext-workspace-policy.js +7 -2
  473. package/dist/services/work-registry.js +1627 -199
  474. package/dist/services/workspace-bootstrap.js +52 -15
  475. package/dist/services/workspace-files.js +85 -0
  476. package/dist/services/worktrees.js +105 -48
  477. package/dist/shared/entity-references.js +8 -0
  478. package/dist/shared/errors.js +27 -0
  479. package/dist/storage/agent-output.js +26 -0
  480. package/dist/storage/database.js +891 -39
  481. package/dist/storage/foreign-key-transaction.js +39 -0
  482. package/dist/storage/immutable-input.js +45 -0
  483. package/dist/storage/import-guard.js +102 -0
  484. package/dist/storage/native-cleanup.js +52 -0
  485. package/dist/storage/paths.js +17 -4
  486. package/dist/storage/projection-lock.js +73 -0
  487. package/dist/storage/work-references.js +23 -0
  488. package/dist/storage/writer-contract.js +89 -0
  489. package/dist/storage/writer-migration.js +85 -0
  490. package/package.json +43 -13
  491. package/tools/create-canon-release.mjs +33 -0
  492. package/tools/produce-hybrid-release.mjs +41 -0
  493. package/tools/repair-paused-run-status.mjs +84 -0
@@ -2,40 +2,75 @@ import crypto from "node:crypto";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { spawn, spawnSync } from "node:child_process";
5
+ import { spawn } from "node:child_process";
6
+ import { commandText } from '../harness-runtime/lib/process-json.mjs';
7
+ import { SETUP_STARTUP_MS, publishSetup } from '../harness-runtime/lib/setup-progress.mjs';
6
8
  import { createRequire } from "node:module";
9
+ import { valid } from "semver";
7
10
  import { getCliBuildInfo } from "./build-info.js";
8
11
  import { AppError } from "../shared/errors.js";
9
12
  import { ensureDir, engineStoreRoot, engineVersionRoot, resolveProjectRoot } from "../storage/paths.js";
10
- import { classifyCliOperation } from "./cli-operation-classifier.js";
13
+ import { classifyCliOperation, isRouterNative } from "./cli-operation-classifier.js";
11
14
  import { requireProtocol } from "./protocols.js";
12
15
  import { resolveCanonRootBeforeContext } from "./canon.js";
13
16
  import { appendAudit } from "./audit.js";
17
+ import { readBoundedReleaseFile } from "./release-source.js";
14
18
  import { findProjectByRoot } from "./projects.js";
19
+ import { parseCommandArgs } from "./lifecycle-command.js";
15
20
  import { allRunEngineBindings, locateRunRoot, readRunEngineBinding, runEngineBindingSchemaId, writeRunEngineBinding } from "./run-engine-bindings.js";
16
21
  export const engineManifestSchemaId = "dd-flow/engine-manifest@1";
17
- const routerNativeFamilies = new Set(["engine", "version", "schema"]);
18
22
  const sourceFile = fileURLToPath(import.meta.url);
19
- const packageRequire = createRequire(sourceFile);
20
23
  export function isEngineMode(env) {
21
24
  return env.DD_FLOW_ENGINE_MODE === "1";
22
25
  }
23
26
  export function isRouterNativeCommand(args) {
24
- const first = args[0];
25
- if (!first || first === "--version")
26
- return true;
27
- if (first === "--help" || first === "-h")
28
- return true;
29
- if (args.includes("--help") || args.includes("-h"))
30
- return true;
31
- return routerNativeFamilies.has(first) || first === "codex" && args[1] === "hook" && args[2] === "handle";
27
+ return isRouterNative(args);
32
28
  }
33
29
  export function installCurrentEngine(context, input = {}) {
30
+ const installation = prepareInstallation(context, input);
31
+ const first = installation.next();
32
+ if (first.done && input.forRouting)
33
+ return first.value;
34
+ const manifest = first.done ? requireManifest(path.join(String(first.value.path), 'engine.json')) : first.value;
35
+ return probeEntrypoint(manifest, undefined, context.ddFlowHome, process.env).then(() => first.done ? first.value : installation.next().value)
36
+ .catch(error => {
37
+ let cleanup_error;
38
+ try {
39
+ installation.return({});
40
+ }
41
+ catch (cleanup) {
42
+ cleanup_error = { message: String(cleanup).slice(0, 2000) };
43
+ }
44
+ throw new AppError('engine_install_failed', 'Staged engine admission failed', 1, { ...error.details, cause: error.code, probe_error: { code: error.code, details: error.details }, ...(cleanup_error ? { cleanup_error } : {}) });
45
+ });
46
+ }
47
+ function* prepareInstallation(context, input) {
34
48
  const build = getCliBuildInfo();
35
49
  const packageRoot = findPackageRoot(path.dirname(sourceFile));
36
50
  if (!packageRoot) {
37
51
  throw new AppError("engine_install_failed", "Cannot locate package root for current dd-flow engine", 1);
38
52
  }
53
+ return yield* installPackageSnapshot(context, packageRoot, build.package_name, build.version, input);
54
+ }
55
+ /** Delivery from an independently selected package, not the invoking CLI.
56
+ * The caller owns release/dependency qualification of expectedChecksum.
57
+ * Existing snapshots are preserved even when not yet bound to a RUN. */
58
+ export function installPackageEngine(context, input) {
59
+ if (!path.isAbsolute(input.packageRoot) || fs.realpathSync(input.packageRoot) !== input.packageRoot
60
+ || !/^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/.test(input.packageName)
61
+ || valid(input.version) !== input.version
62
+ || !/^[a-f0-9]{64}$/.test(input.expectedChecksum)) {
63
+ throw new AppError("engine_install_failed", "Selected package requires a canonical root and independent content checksum", 1, { effect: "no_effect" });
64
+ }
65
+ const metadata = JSON.parse(readBoundedReleaseFile(path.join(input.packageRoot, "package.json"), 1024 * 1024).toString("utf8"));
66
+ if (metadata.name !== input.packageName || metadata.version !== input.version
67
+ || snapshotFilesChecksum(packageSnapshotFiles(input.packageRoot)) !== input.expectedChecksum) {
68
+ throw new AppError("engine_install_failed", "Selected package identity or contents changed before delivery", 1, { effect: "no_effect" });
69
+ }
70
+ return installPackageSnapshot(context, input.packageRoot, input.packageName, input.version, { force: true, forRouting: true }, input.expectedChecksum, input.validateStaged).next().value;
71
+ }
72
+ function* installPackageSnapshot(context, packageRoot, packageName, version, input, expectedChecksum, validateStaged) {
73
+ const build = { package_name: packageName, version };
39
74
  const target = engineVersionRoot(context.ddFlowHome, build.package_name, build.version);
40
75
  const manifestPath = path.join(target, "engine.json");
41
76
  const existing = readManifest(manifestPath);
@@ -66,14 +101,24 @@ export function installCurrentEngine(context, input = {}) {
66
101
  const tmp = path.join(parent, `.${path.basename(target)}.tmp-${process.pid}-${Date.now()}`);
67
102
  fs.rmSync(tmp, { recursive: true, force: true });
68
103
  ensureDir(tmp);
104
+ publishSetup('probe_started', `engine-staging:${tmp}`);
69
105
  copyPackageSnapshot(packageRoot, tmp);
70
106
  const stagedManifest = buildManifest(context, build.package_name, build.version, packageRoot, target, tmp);
71
107
  const stagedChecksum = stagedManifest.integrity.checksum;
108
+ if (expectedChecksum !== undefined && stagedChecksum !== expectedChecksum) {
109
+ throw new AppError("engine_install_failed", "Selected package changed during delivery", 1, { effect: "partial", path: tmp });
110
+ }
111
+ try {
112
+ validateStaged?.(tmp);
113
+ }
114
+ catch (error) {
115
+ throw new AppError("engine_install_failed", "Staged package no longer matches its selected release", 1, { effect: "partial", path: tmp, reason: error instanceof AppError ? error.details.reason ?? error.code : "staged_selection_changed" });
116
+ }
72
117
  const activationTarget = input.force
73
118
  && existing
74
119
  && stagedChecksum
75
120
  && stagedChecksum !== existing.integrity.checksum
76
- && engineIsBound(context.ddFlowHome, existing)
121
+ && (expectedChecksum !== undefined || engineIsBound(context.ddFlowHome, existing))
77
122
  ? `${target}--${stagedChecksum}`
78
123
  : target;
79
124
  const duplicate = stagedChecksum ? findInstalledManifest(context.ddFlowHome, {
@@ -81,7 +126,7 @@ export function installCurrentEngine(context, input = {}) {
81
126
  packageVersion: build.version,
82
127
  integrityChecksum: stagedChecksum
83
128
  }) : null;
84
- if (duplicate) {
129
+ if (duplicate && manifestDiagnostics(duplicate, { checkEntrypoint: false }).length === 0) {
85
130
  fs.rmSync(tmp, { recursive: true, force: true });
86
131
  return {
87
132
  ok: true,
@@ -94,13 +139,15 @@ export function installCurrentEngine(context, input = {}) {
94
139
  const manifest = { ...stagedManifest, package_root: activationTarget, snapshot_root: activationTarget };
95
140
  fs.writeFileSync(path.join(tmp, "engine.json"), `${JSON.stringify(manifest, null, 2)}\n`);
96
141
  const checkedManifest = requireManifest(path.join(tmp, "engine.json"));
97
- const stagedDiagnostics = manifestDiagnostics({ ...checkedManifest, package_root: tmp, snapshot_root: tmp }, { checkEntrypoint: !input.forRouting });
142
+ const stagedDiagnostics = manifestDiagnostics({ ...checkedManifest, package_root: tmp, snapshot_root: tmp }, { checkEntrypoint: false });
98
143
  if (stagedDiagnostics.length > 0) {
99
144
  throw new AppError("engine_install_failed", "Staged dd-flow engine failed its integrity or dependency health check", 1, {
100
145
  diagnostics: stagedDiagnostics,
101
146
  path: tmp
102
147
  });
103
148
  }
149
+ if (!input.forRouting)
150
+ yield { ...checkedManifest, package_root: tmp, snapshot_root: tmp };
104
151
  activateEngineAtomically(tmp, activationTarget);
105
152
  const installed = requireManifest(path.join(activationTarget, "engine.json"));
106
153
  return {
@@ -117,7 +164,7 @@ export function installCurrentEngine(context, input = {}) {
117
164
  }
118
165
  export function listEngines(context) {
119
166
  const root = engineStoreRoot(context.ddFlowHome);
120
- const engines = readInstalledManifests(root).map(manifestSummary);
167
+ const engines = readInstalledManifests(root).map(manifest => manifestSummary(manifest));
121
168
  return { ok: true, schema_id: "dd-flow/engine-list@1", engine_store: root, engines };
122
169
  }
123
170
  export function engineInfo(context, input) {
@@ -135,14 +182,23 @@ export function resolveEngine(context, input = {}) {
135
182
  }
136
183
  return { ok: true, schema_id: "dd-flow/engine-resolve@1", selection, contexts: compatibilityContexts(context, { ...input, classification }) };
137
184
  }
138
- export function doctorEngines(context, input = {}) {
185
+ export async function doctorEngines(context, input = {}) {
139
186
  const root = engineStoreRoot(context.ddFlowHome);
140
187
  const installed = readInstalledManifests(root);
141
- const checks = installed.map((manifest) => ({
142
- engine: manifestSummary(manifest),
143
- status: manifestHealthy(manifest) ? "ok" : "corrupt",
144
- diagnostics: manifestDiagnostics(manifest)
145
- }));
188
+ const checks = [];
189
+ for (const manifest of installed) {
190
+ const diagnostics = manifestDiagnostics(manifest);
191
+ let probe_error;
192
+ if (!diagnostics.length)
193
+ try {
194
+ await probeEntrypoint(manifest, undefined, context.ddFlowHome, context.env);
195
+ }
196
+ catch (error) {
197
+ probe_error = error instanceof AppError ? error.details : { message: String(error) };
198
+ diagnostics.push(error instanceof AppError && error.code === 'engine_probe_failed' ? 'entrypoint_dependency_load_failed' : 'entrypoint_probe_unavailable');
199
+ }
200
+ checks.push({ engine: manifestSummary(manifest, diagnostics), status: diagnostics.includes("entrypoint_probe_unavailable") ? "unverified" : diagnostics.length ? "corrupt" : "ok", diagnostics, ...(probe_error ? { probe_error } : {}) });
201
+ }
146
202
  const classification = input.classification ?? classifyCliOperation(["engine", "doctor"], input.env ?? context.env);
147
203
  const selection = selectEngine(context, input, {}, classification);
148
204
  return {
@@ -155,7 +211,7 @@ export function doctorEngines(context, input = {}) {
155
211
  exit_code: checks.every((check) => check.status === "ok") && selection.status === "selected" ? 0 : 1
156
212
  };
157
213
  }
158
- export function routeArgsThroughEngine(context, args, io, stdin, env, resolvedProjectRoot) {
214
+ export async function routeArgsThroughEngine(context, args, io, stdin, env, resolvedProjectRoot) {
159
215
  if (isEngineMode(env) || isRouterNativeCommand(args))
160
216
  return Promise.resolve(null);
161
217
  const classification = classifyCliOperation(args, env);
@@ -174,13 +230,18 @@ export function routeArgsThroughEngine(context, args, io, stdin, env, resolvedPr
174
230
  if (!selection.selected)
175
231
  return Promise.resolve(null);
176
232
  const current = getCliBuildInfo();
177
- if (selection.selected.package_name === current.package_name && selection.selected.package_version === current.version) {
233
+ const currentRoot = findPackageRoot(path.dirname(sourceFile));
234
+ if (selection.selected.package_name === current.package_name && selection.selected.package_version === current.version
235
+ && currentRoot !== null && fs.realpathSync(selection.selected.snapshot_root) === fs.realpathSync(currentRoot)) {
178
236
  return Promise.resolve({ routed: true, exitCode: 0, inProcess: true });
179
237
  }
180
238
  const entrypoint = resolveManifestEntrypoint(selection.selected);
239
+ // The admitted immutable entrypoint executes the requested operation itself.
240
+ // A separate --version process adds no operation-specific admission.
181
241
  return spawnEngine(selection.selected, entrypoint, args, io, stdin, env, current.version);
182
242
  }
183
- export function bindRunEngine(context, input) {
243
+ export async function prepareRunEngineBind(context, input) {
244
+ const reason = requiredText(input.reason, "reason");
184
245
  const projectRoot = resolveProjectRoot(input.projectRoot);
185
246
  const located = locateRunRoot(context.db, projectRoot, input.runId);
186
247
  if (!located)
@@ -190,40 +251,43 @@ export function bindRunEngine(context, input) {
190
251
  packageName: input.packageName ?? getCliBuildInfo().package_name,
191
252
  packageVersion: input.engineVersion,
192
253
  ...(input.integrityChecksum ? { integrityChecksum: input.integrityChecksum } : {})
193
- });
254
+ }, { checkEntrypoint: false });
194
255
  const requested = engineIdentity(manifest);
195
256
  if (existing) {
196
257
  if (sameEngineIdentity(existing.engine, requested))
197
- return { ok: true, action: "run_engine_bind", changed: false, binding: existing };
258
+ return { kind: "replay", binding: existing };
198
259
  throw new AppError("run_engine_binding_immutable", "RUN engine binding cannot be changed", 1, {
199
260
  run_id: located.run_id,
200
261
  current: existing.engine,
201
262
  requested
202
263
  });
203
264
  }
204
- const probeArgs = ["run", "status", located.run_id, "--project-root", projectRoot, "--json"];
205
- const probe = spawnSync(process.execPath, [resolveManifestEntrypoint(manifest), ...probeArgs], {
206
- cwd: manifest.snapshot_root,
207
- env: { ...process.env, ...context.env, DD_FLOW_HOME: context.ddFlowHome, DD_FLOW_ENGINE_MODE: "1", DD_FLOW_ENGINE_HOME: manifest.snapshot_root },
208
- encoding: "utf8",
209
- timeout: 30_000
210
- });
211
- if (probe.status !== 0) {
212
- throw new AppError("run_engine_probe_failed", "Selected engine cannot read the RUN authority", 1, {
213
- run_id: located.run_id,
214
- engine: manifestSummary(manifest),
215
- command: `dd-flow ${probeArgs.join(" ")}`,
216
- exit_code: probe.status,
217
- stderr: probe.stderr.slice(0, 2000)
218
- });
265
+ await probeEntrypoint(manifest, ['run', 'status', located.run_id, '--project-root', projectRoot, '--json'], context.ddFlowHome, context.env, 'run_engine');
266
+ return { kind: "create", projectRoot, located, manifest, requested, reason, entrypoint: resolveManifestEntrypoint(manifest) };
267
+ }
268
+ export async function bindRunEngine(context, input, supplied) {
269
+ const prepared = supplied ?? await prepareRunEngineBind(context, input);
270
+ if (prepared.kind === "replay")
271
+ return { ok: true, action: "run_engine_bind", changed: false, binding: prepared.binding };
272
+ const { projectRoot, located, manifest, requested, reason } = prepared;
273
+ const current = locateRunRoot(context.db, projectRoot, input.runId);
274
+ if (!current || current.run_root !== located.run_root)
275
+ throw new AppError('run_engine_binding_conflict', 'RUN identity changed during probe', 1);
276
+ requireBoundManifest(context.ddFlowHome, { packageName: manifest.package_name, packageVersion: manifest.package_version, integrityChecksum: requested.integrity_checksum });
277
+ const existing = readRunEngineBinding(located.binding_path, { allowMissing: true });
278
+ if (existing) {
279
+ if (sameEngineIdentity(existing.engine, requested))
280
+ return { ok: true, action: "run_engine_bind", changed: false, binding: existing };
281
+ throw new AppError("run_engine_binding_immutable", "RUN engine binding cannot be changed", 1, { run_id: located.run_id, current: existing.engine, requested });
219
282
  }
283
+ const probeArgs = ["run", "status", located.run_id, "--project-root", projectRoot, "--json"];
220
284
  const binding = {
221
285
  schema_id: runEngineBindingSchemaId,
222
286
  run_id: located.run_id,
223
287
  project_root: projectRoot,
224
288
  bound_at: context.now(),
225
289
  source: "legacy_recovery",
226
- reason: requiredText(input.reason, "reason"),
290
+ reason,
227
291
  engine: requested,
228
292
  probe: { status: "passed", command: `dd-flow ${probeArgs.join(" ")}` }
229
293
  };
@@ -252,6 +316,36 @@ export function bindCurrentEngineToRun(context, input) {
252
316
  };
253
317
  return writeRunEngineBinding(path.join(input.runRoot, "engine-binding.json"), binding).binding;
254
318
  }
319
+ /** Forks are a new execution authority. The source binding stays immutable;
320
+ * this replaces only the copied binding after proving the selected engine can
321
+ * read the copied RUN. */
322
+ export async function upgradeForkedRunEngine(context, input) {
323
+ const projectRoot = resolveProjectRoot(input.projectRoot);
324
+ const located = locateRunRoot(context.db, projectRoot, input.runId);
325
+ if (!located)
326
+ throw new AppError("not_found", `Forked RUN is not registered: ${input.runId}`, 1);
327
+ const manifest = requireBoundManifest(context.ddFlowHome, {
328
+ packageName: getCliBuildInfo().package_name,
329
+ packageVersion: input.engineVersion,
330
+ ...(input.integrityChecksum ? { integrityChecksum: input.integrityChecksum } : {})
331
+ });
332
+ const requested = engineIdentity(manifest);
333
+ const priorBinding = fs.readFileSync(located.binding_path, 'utf8');
334
+ const lineage = path.join(located.run_root, "fork-lineage.json");
335
+ if (!fs.existsSync(lineage))
336
+ throw new AppError("fork_lineage_missing", "Engine upgrade is permitted only for a derived RUN", 1, { run_id: located.run_id });
337
+ const probeArgs = ["run", "status", located.run_id, "--project-root", projectRoot, "--json"];
338
+ const priorLineage = fs.readFileSync(lineage, 'utf8');
339
+ await probeEntrypoint(manifest, probeArgs, context.ddFlowHome, context.env, 'fork_engine');
340
+ if (fs.readFileSync(located.binding_path, 'utf8') !== priorBinding || fs.readFileSync(lineage, 'utf8') !== priorLineage)
341
+ throw new AppError('fork_engine_binding_conflict', 'Fork identity changed during probe', 1);
342
+ requireBoundManifest(context.ddFlowHome, { packageName: manifest.package_name, packageVersion: manifest.package_version, integrityChecksum: manifest.integrity.checksum });
343
+ const binding = { schema_id: runEngineBindingSchemaId, run_id: located.run_id, project_root: projectRoot, bound_at: context.now(), source: "fork_upgrade", reason: requiredText(input.reason, "reason"), engine: requested, probe: { status: "passed", command: `dd-flow ${probeArgs.join(" ")}` } };
344
+ const temporary = `${located.binding_path}.fork-${process.pid}-${Date.now()}.tmp`;
345
+ fs.writeFileSync(temporary, `${JSON.stringify(binding, null, 2)}\n`);
346
+ fs.renameSync(temporary, located.binding_path);
347
+ return binding;
348
+ }
255
349
  function boundRunEngineForArgs(context, args, projectRoot) {
256
350
  const runId = runIdForArgs(args);
257
351
  if (!runId || !projectRoot)
@@ -274,6 +368,8 @@ function runIdForArgs(args) {
274
368
  const [family, command, ...rest] = args;
275
369
  const parsed = parseLightArgs(rest);
276
370
  if (family === "run" && command !== "start" && command !== "list") {
371
+ if (["drive", "control", "recovery", "capacity"].includes(command ?? ""))
372
+ return option(parsed, "run");
277
373
  if (command === "flags")
278
374
  return positional(parsed, 1);
279
375
  return positional(parsed, 0);
@@ -290,7 +386,7 @@ function runIdForArgs(args) {
290
386
  return option(parsed, "run");
291
387
  return null;
292
388
  }
293
- function requireBoundManifest(ddFlowHome, input) {
389
+ function requireBoundManifest(ddFlowHome, input, options = {}) {
294
390
  const manifest = input.snapshotRoot
295
391
  ? requireManifest(path.join(input.snapshotRoot, "engine.json"))
296
392
  : findInstalledManifest(ddFlowHome, {
@@ -303,7 +399,7 @@ function requireBoundManifest(ddFlowHome, input) {
303
399
  || manifest.package_version !== input.packageVersion
304
400
  || input.integrityChecksum !== undefined && manifest.integrity.checksum !== input.integrityChecksum
305
401
  || input.snapshotRoot !== undefined && path.resolve(manifest.snapshot_root) !== path.resolve(input.snapshotRoot)
306
- || !manifestHealthy(manifest)) {
402
+ || manifestDiagnostics(manifest, options).length !== 0) {
307
403
  throw new AppError("run_engine_binding_invalid", "RUN engine binding points to a missing or unhealthy engine snapshot", 1, {
308
404
  package_name: input.packageName,
309
405
  package_version: input.packageVersion,
@@ -344,7 +440,7 @@ function executionManifest(context) {
344
440
  return requireManifest(path.join(String(installed.path), "engine.json"));
345
441
  }
346
442
  function requiredText(value, label) {
347
- const normalized = value.trim();
443
+ const normalized = typeof value === "string" ? value.trim() : "";
348
444
  if (!normalized)
349
445
  throw new AppError("usage", `Missing required value: ${label}`, 2);
350
446
  return normalized;
@@ -380,14 +476,14 @@ export function selectEngine(context, input, options = {}, classification = inpu
380
476
  const requiredRange = stringValue(compatibility?.engine?.version_range) ?? (classification.mode === "mb_upgrade" ? null : `>=${build.version} <9999.0.0`);
381
477
  const recommended = stringValue(compatibility?.engine?.recommended_version) ?? build.version;
382
478
  const installHintTemplate = stringValue(compatibility?.engine?.old_engine_install_hint) ?? `npx ${packageName}@<version> engine install`;
383
- const manifests = readInstalledManifests(engineStoreRoot(context.ddFlowHome))
479
+ // An engine-mode caller already executes this module's build. Another
480
+ // installed engine cannot establish compatibility for its current writes.
481
+ // Keep full snapshot validation in routing/binding, not lease maintenance.
482
+ const executingCurrent = options.allowCurrentInProcess && isEngineMode(input.env ?? process.env);
483
+ const manifests = executingCurrent ? [] : readInstalledManifests(engineStoreRoot(context.ddFlowHome))
384
484
  .filter((manifest) => manifest.package_name === packageName)
385
485
  .filter((manifest) => requiredRange !== null && satisfiesRange(manifest.package_version, requiredRange))
386
- .filter((manifest) => options.allowCurrentInProcess
387
- && manifest.package_name === build.package_name
388
- && manifest.package_version === build.version
389
- ? true
390
- : manifestHealthy(manifest))
486
+ .filter((manifest) => manifestHealthy(manifest))
391
487
  .sort((a, b) => {
392
488
  const versionOrder = compareSemverStrings(b.package_version, a.package_version);
393
489
  if (versionOrder !== 0)
@@ -402,7 +498,7 @@ export function selectEngine(context, input, options = {}, classification = inpu
402
498
  requiredRange !== null &&
403
499
  packageName === build.package_name &&
404
500
  satisfiesRange(build.version, requiredRange)
405
- ? currentBuildManifest(context, build)
501
+ ? currentBuildManifest(context, build, options.verifyCurrentContent !== false)
406
502
  : null);
407
503
  const diagnostics = [
408
504
  ...targetBlockers,
@@ -420,9 +516,38 @@ export function selectEngine(context, input, options = {}, classification = inpu
420
516
  diagnostics
421
517
  };
422
518
  }
423
- function currentBuildManifest(context, build) {
519
+ function currentBuildManifest(context, build, verifyContent) {
424
520
  const packageRoot = findPackageRoot(path.dirname(sourceFile)) ?? process.cwd();
425
- return buildManifest(context, build.package_name, build.version, packageRoot, packageRoot, packageRoot);
521
+ const manifestFile = path.join(packageRoot, "engine.json");
522
+ const installedLayout = path.basename(path.dirname(path.dirname(packageRoot))) === "engines"
523
+ && path.basename(path.dirname(packageRoot)) === path.basename(path.dirname(engineVersionRoot(context.ddFlowHome, build.package_name, build.version)));
524
+ if (fs.existsSync(manifestFile) || installedLayout) {
525
+ const installed = readManifest(manifestFile);
526
+ // Use the executing module's physical root, never an environment alias.
527
+ // A damaged installed manifest must not become a development fallback.
528
+ if (!installed || installed.package_name !== build.package_name || installed.package_version !== build.version
529
+ || installed.engine_version !== build.version || installed.engine_id !== "dd-flow-engine"
530
+ || typeof installed.snapshot_root !== "string" || !fs.existsSync(installed.snapshot_root)
531
+ || fs.realpathSync(installed.snapshot_root) !== fs.realpathSync(packageRoot)
532
+ || typeof installed.entrypoint !== "string" || installed.integrity?.source !== "package_snapshot"
533
+ || typeof installed.integrity?.checksum !== "string" || !/^[a-f0-9]{64}$/.test(installed.integrity.checksum)
534
+ || (installed.schema_registry && (!Array.isArray(installed.schema_registry.entries)
535
+ || installed.schema_registry.entries.some(entry => !entry || typeof entry.path !== "string"
536
+ || typeof entry.id !== "string" || typeof entry.name !== "string" || !/^[a-f0-9]{64}$/.test(entry.checksum ?? ""))))) {
537
+ throw new AppError("unhealthy_engine", "Executing engine snapshot manifest does not match its build", 1, { manifest: manifestFile });
538
+ }
539
+ const diagnostics = manifestDiagnostics(installed, { checkEntrypoint: false, verifyContent });
540
+ if (diagnostics.length)
541
+ throw new AppError("unhealthy_engine", "Executing engine snapshot is unhealthy", 1, { manifest: manifestFile, diagnostics });
542
+ return installed;
543
+ }
544
+ // Only an unmaterialized package has no snapshot proof. Canon and
545
+ // package-manager aliases are expected in development checkouts.
546
+ const manifest = buildManifest(context, build.package_name, build.version, packageRoot, packageRoot, packageRoot, null);
547
+ // An ephemeral routing choice has no snapshot proof. Hash bytes only when
548
+ // materializing/validating an installed snapshot, never on every CLI call.
549
+ manifest.integrity.mode = "degraded_local_development";
550
+ return manifest;
426
551
  }
427
552
  export function compatibilityContexts(context, input = {}) {
428
553
  const env = input.env ?? process.env;
@@ -560,40 +685,16 @@ function canonCompatibilitySha(memorybankRoot) {
560
685
  return null;
561
686
  }
562
687
  }
563
- function parseLightArgs(args) {
564
- const positional = [];
565
- const options = new Map();
566
- for (let index = 0; index < args.length; index += 1) {
567
- const value = args[index];
568
- if (value?.startsWith("--")) {
569
- const equal = value.indexOf("=");
570
- if (equal > 2) {
571
- const key = value.slice(2, equal);
572
- options.set(key, [...(options.get(key) ?? []), value.slice(equal + 1)]);
573
- continue;
574
- }
575
- const key = value.slice(2);
576
- const next = args[index + 1];
577
- if (!next || next.startsWith("--"))
578
- options.set(key, [...(options.get(key) ?? []), ""]);
579
- else {
580
- options.set(key, [...(options.get(key) ?? []), next]);
581
- index += 1;
582
- }
583
- }
584
- else if (value)
585
- positional.push(value);
586
- }
587
- return { positional, options };
588
- }
688
+ const parseLightArgs = parseCommandArgs;
589
689
  function option(parsed, key) {
590
690
  const values = parsed.options.get(key);
591
- return values?.[values.length - 1] || null;
691
+ const value = values?.[values.length - 1];
692
+ return value && value !== "__dd_flow_flag__" ? value : null;
592
693
  }
593
694
  function positional(parsed, index) {
594
695
  return parsed.positional[index] ?? null;
595
696
  }
596
- function buildManifest(context, packageName, version, packageRoot, snapshotRoot, checksumRoot) {
697
+ function buildManifest(context, packageName, version, packageRoot, snapshotRoot, checksumRoot, checksum = engineSnapshotChecksum(checksumRoot)) {
597
698
  return {
598
699
  schema_id: engineManifestSchemaId,
599
700
  package_name: packageName,
@@ -609,35 +710,54 @@ function buildManifest(context, packageName, version, packageRoot, snapshotRoot,
609
710
  supports_contracts: {
610
711
  compatibility: ["dd-flow/compatibility@1"],
611
712
  version: ["dd-flow/version-report@1"],
612
- status: ["dd-flow/status-report@1"]
713
+ status: ["dd-flow/status-report@1"],
714
+ hybrid: ["dd-flow/flow-descriptor@1", "dd-flow/execution-settings@1", "dd-flow/execution-bundle@1", "dd-flow/memory-bootstrap-receipt@2"]
613
715
  },
614
716
  schema_registry: buildSchemaRegistry(checksumRoot),
615
717
  integrity: {
616
718
  source: "package_snapshot",
617
- checksum: engineSnapshotChecksum(checksumRoot),
719
+ checksum,
618
720
  mode: "full_content"
619
721
  }
620
722
  };
621
723
  }
622
724
  function copyPackageSnapshot(packageRoot, target) {
725
+ let copied = 0;
726
+ for (const [relative, source] of packageSnapshotFiles(packageRoot)) {
727
+ const destination = path.join(target, relative);
728
+ ensureDir(path.dirname(destination));
729
+ fs.copyFileSync(source, destination);
730
+ if (++copied % 64 === 0)
731
+ publishSetup('transfer_progress', `${target}:${copied}`);
732
+ }
733
+ }
734
+ /** The same source inventory drives validation and copying; no staging writes. */
735
+ export function packageSnapshotFiles(packageRoot) {
736
+ const files = new Map();
737
+ const collect = (source, relative, skipNodeModules = false) => {
738
+ if (!fs.statSync(source).isDirectory()) {
739
+ files.set(relative, source);
740
+ return;
741
+ }
742
+ for (const entry of fs.readdirSync(source, { withFileTypes: true })) {
743
+ if (skipNodeModules && entry.name === "node_modules")
744
+ continue;
745
+ const child = path.join(source, entry.name), name = path.join(relative, entry.name);
746
+ if (entry.isDirectory())
747
+ collect(child, name, skipNodeModules);
748
+ else if (entry.isFile())
749
+ files.set(name, child);
750
+ }
751
+ };
623
752
  for (const item of ["dist", "package.json", "README.md", "CHANGELOG.md", "tools"]) {
624
753
  const from = path.join(packageRoot, item);
625
754
  if (!fs.existsSync(from))
626
755
  continue;
627
- const to = path.join(target, item);
628
- const stat = fs.statSync(from);
629
- if (stat.isDirectory())
630
- copyDir(from, to);
631
- else {
632
- ensureDir(path.dirname(to));
633
- fs.copyFileSync(from, to);
634
- }
756
+ collect(from, item);
635
757
  }
636
- copyProductionDependencies(packageRoot, target);
637
- }
638
- function copyProductionDependencies(packageRoot, target) {
639
- const queue = [{ sourceRoot: packageRoot, targetRoot: target, ancestors: new Set() }];
640
- const copied = new Set();
758
+ const queue = [{ sourceRoot: packageRoot, targetRoot: "" }];
759
+ const placed = new Map();
760
+ const virtualRoot = path.resolve(path.sep, "dd-flow-snapshot");
641
761
  while (queue.length > 0) {
642
762
  const current = queue.shift();
643
763
  if (!current)
@@ -646,17 +766,48 @@ function copyProductionDependencies(packageRoot, target) {
646
766
  const sourceRoot = resolvePackageRoot(dependency, current.sourceRoot);
647
767
  if (!sourceRoot)
648
768
  throw new AppError("engine_install_failed", `Cannot resolve runtime dependency: ${dependency}`, 1);
649
- const targetRoot = path.join(current.targetRoot, "node_modules", dependency);
650
- const copyKey = `${sourceRoot}\n${targetRoot}`;
651
- if (copied.has(copyKey))
769
+ // Standard Node lookup permits hoisting identical selected packages.
770
+ // Copying a shared DAG under every parent makes SDK snapshots grow
771
+ // exponentially; conflicting versions still need their own local slot.
772
+ const search = createRequire(path.join(virtualRoot, current.targetRoot, "package.json")).resolve.paths(dependency) ?? [];
773
+ const candidates = search.filter(directory => directory.startsWith(`${virtualRoot}${path.sep}`))
774
+ .map(directory => path.relative(virtualRoot, path.join(directory, dependency)));
775
+ const existing = candidates.find(candidate => placed.has(candidate));
776
+ if (existing && placed.get(existing) === sourceRoot)
652
777
  continue;
653
- copied.add(copyKey);
654
- copyDir(sourceRoot, targetRoot, true);
655
- if (current.ancestors.has(sourceRoot))
656
- continue;
657
- queue.push({ sourceRoot, targetRoot, ancestors: new Set([...current.ancestors, sourceRoot]) });
778
+ const targetRoot = existing ? path.join(current.targetRoot, "node_modules", dependency) : path.join("node_modules", dependency);
779
+ placed.set(targetRoot, sourceRoot);
780
+ collect(sourceRoot, targetRoot, true);
781
+ queue.push({ sourceRoot, targetRoot });
658
782
  }
659
783
  }
784
+ return files;
785
+ }
786
+ export function prepareForkEngine(engineVersion, integrityChecksum) {
787
+ const build = getCliBuildInfo();
788
+ if (engineVersion !== build.version)
789
+ throw new AppError("fork_engine_unavailable", "Fork installs the invoking CLI engine; invoke the requested version to upgrade the fork", 2, { requested: engineVersion, available: build.version });
790
+ const packageRoot = findPackageRoot(path.dirname(sourceFile));
791
+ if (!packageRoot || !fs.existsSync(path.join(packageRoot, "dist", "cli.js")))
792
+ throw new AppError("harness_runtime_unbuilt", "Build the CLI before preparing a fork", 1);
793
+ const files = packageSnapshotFiles(packageRoot);
794
+ if (integrityChecksum !== undefined) {
795
+ const checksum = snapshotFilesChecksum(files);
796
+ if (checksum !== integrityChecksum)
797
+ throw new AppError("fork_engine_unavailable", "Requested engine checksum differs from the invoking CLI artifact", 2, { requested: integrityChecksum });
798
+ }
799
+ }
800
+ function snapshotFilesChecksum(files) {
801
+ const checksum = crypto.createHash("sha256");
802
+ for (const [relative, source] of [...files].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) {
803
+ if (path.basename(relative) === "engine.json")
804
+ continue;
805
+ checksum.update(relative);
806
+ checksum.update("\0");
807
+ checksum.update(fs.readFileSync(source));
808
+ checksum.update("\0");
809
+ }
810
+ return checksum.digest("hex");
660
811
  }
661
812
  function readProductionDependencies(packageRoot) {
662
813
  try {
@@ -676,20 +827,14 @@ function readProductionDependencies(packageRoot) {
676
827
  }
677
828
  }
678
829
  function resolvePackageRoot(name, from) {
679
- try {
680
- let current = path.dirname(packageRequire.resolve(name, { paths: [from] }));
681
- while (true) {
682
- if (fs.existsSync(path.join(current, "package.json")))
683
- return fs.realpathSync(current);
684
- const parent = path.dirname(current);
685
- if (parent === current)
686
- return null;
687
- current = parent;
688
- }
689
- }
690
- catch {
691
- return null;
830
+ // Inspect package roots through Node's lookup paths, not the require entry:
831
+ // production dependencies can expose only an ESM import condition.
832
+ for (const directory of createRequire(path.join(from, "package.json")).resolve.paths(name) ?? []) {
833
+ const candidate = path.join(directory, name);
834
+ if (fs.existsSync(path.join(candidate, "package.json")))
835
+ return fs.realpathSync(candidate);
692
836
  }
837
+ return null;
693
838
  }
694
839
  function inferInstallSource(packageRoot, ddFlowHome) {
695
840
  const normalized = path.resolve(packageRoot);
@@ -713,19 +858,6 @@ function hasAncestorFile(start, name) {
713
858
  current = parent;
714
859
  }
715
860
  }
716
- function copyDir(from, to, skipNodeModules = false) {
717
- ensureDir(to);
718
- for (const entry of fs.readdirSync(from, { withFileTypes: true })) {
719
- if (skipNodeModules && entry.name === "node_modules")
720
- continue;
721
- const source = path.join(from, entry.name);
722
- const target = path.join(to, entry.name);
723
- if (entry.isDirectory())
724
- copyDir(source, target, skipNodeModules);
725
- else if (entry.isFile())
726
- fs.copyFileSync(source, target);
727
- }
728
- }
729
861
  function acquireInstallLock(lockDir) {
730
862
  ensureDir(path.dirname(lockDir));
731
863
  try {
@@ -750,6 +882,9 @@ function readInstalledManifests(root) {
750
882
  if (!fs.statSync(packageRoot).isDirectory())
751
883
  continue;
752
884
  for (const versionDir of fs.readdirSync(packageRoot)) {
885
+ // Failed staging, activation backups and locks are not installations.
886
+ if (versionDir.startsWith(".") || /\.previous-\d+-\d+$/.test(versionDir) || versionDir.endsWith(".lock"))
887
+ continue;
753
888
  const manifest = readManifest(path.join(packageRoot, versionDir, "engine.json"));
754
889
  if (manifest)
755
890
  manifests.push(manifest);
@@ -802,7 +937,7 @@ function manifestDiagnostics(manifest, options = {}) {
802
937
  if (!manifest.integrity || manifest.integrity.mode !== "full_content" || !manifest.integrity.checksum) {
803
938
  diagnostics.push("content_checksum_missing");
804
939
  }
805
- else if (fs.existsSync(snapshotRoot)) {
940
+ else if (options.verifyContent !== false && fs.existsSync(snapshotRoot)) {
806
941
  try {
807
942
  if (engineSnapshotChecksum(snapshotRoot) !== manifest.integrity.checksum)
808
943
  diagnostics.push("content_checksum_mismatch");
@@ -816,6 +951,8 @@ function manifestDiagnostics(manifest, options = {}) {
816
951
  const schemaPath = safeResolveSnapshotPath(manifest, entry.path);
817
952
  if (!schemaPath || !fs.existsSync(schemaPath))
818
953
  diagnostics.push(`schema_registry_missing:${entry.name}`);
954
+ else if (options.verifyContent === false)
955
+ continue;
819
956
  else if (fileChecksum(schemaPath) !== entry.checksum)
820
957
  diagnostics.push(`schema_registry_checksum_mismatch:${entry.name}`);
821
958
  else {
@@ -829,25 +966,21 @@ function manifestDiagnostics(manifest, options = {}) {
829
966
  }
830
967
  }
831
968
  }
832
- if (options.checkEntrypoint !== false && entrypoint && fs.existsSync(entrypoint) && !diagnostics.includes("entrypoint_outside_snapshot")) {
833
- const health = spawnSync(process.execPath, [entrypoint, "--version", "--json"], {
834
- cwd: snapshotRoot,
835
- env: {
836
- ...process.env,
837
- DD_FLOW_ENGINE_MODE: "1",
838
- DD_FLOW_ENGINE_HOME: snapshotRoot,
839
- DD_FLOW_ENGINE_HEALTHCHECK: "1"
840
- },
841
- encoding: "utf8",
842
- stdio: ["ignore", "pipe", "pipe"],
843
- timeout: 15_000
844
- });
845
- if (health.status !== 0)
846
- diagnostics.push("entrypoint_dependency_load_failed");
847
- }
848
969
  return diagnostics;
849
970
  }
850
- function manifestSummary(manifest) {
971
+ async function probeEntrypoint(manifest, args = ['--version', '--json'], runtimeHome, env = {}, purpose = 'engine') {
972
+ publishSetup('probe_started', manifest.snapshot_root);
973
+ try {
974
+ await commandText(resolveManifestEntrypoint(manifest), args, { cwd: manifest.snapshot_root,
975
+ env: { ...env, DD_FLOW_ENGINE_MODE: '1', DD_FLOW_ENGINE_HOME: manifest.snapshot_root, ...(runtimeHome ? { DD_FLOW_HOME: runtimeHome } : {}), ...(args[0] === '--version' ? { DD_FLOW_ENGINE_HEALTHCHECK: '1' } : {}) }, startupMs: SETUP_STARTUP_MS, phase: 'engine-probe' });
976
+ publishSetup('probe_completed', manifest.snapshot_root);
977
+ }
978
+ catch (cause) {
979
+ const error = cause;
980
+ throw new AppError(error.details?.reason === 'child_exit' && error.details?.signal === null && error.details?.exit_code !== null ? `${purpose}_probe_failed` : `${purpose}_probe_unavailable`, 'Selected engine probe did not complete successfully', 1, { cause: error.code, message: error.message, ...error.details });
981
+ }
982
+ }
983
+ function manifestSummary(manifest, diagnostics = manifestDiagnostics(manifest, { checkEntrypoint: false })) {
851
984
  return {
852
985
  schema_id: manifest.schema_id,
853
986
  package_name: manifest.package_name,
@@ -859,8 +992,8 @@ function manifestSummary(manifest) {
859
992
  snapshot_root: manifest.snapshot_root,
860
993
  resolved_entrypoint: safeResolveManifestEntrypoint(manifest),
861
994
  installed_at: manifest.installed_at,
862
- healthy: manifestHealthy(manifest),
863
- diagnostics: manifestDiagnostics(manifest)
995
+ healthy: diagnostics.length === 0,
996
+ diagnostics
864
997
  };
865
998
  }
866
999
  function resolveManifestEntrypoint(manifest) {
@@ -1011,22 +1144,30 @@ function findPackageRoot(start) {
1011
1144
  }
1012
1145
  }
1013
1146
  export function engineSnapshotChecksum(root) {
1147
+ publishSetup('probe_started', `engine-digest:${root}`);
1014
1148
  const files = [];
1015
1149
  collectFiles(root, root, files);
1016
1150
  const checksum = crypto.createHash("sha256");
1151
+ let checked = 0;
1017
1152
  for (const file of files.sort()) {
1018
1153
  checksum.update(file);
1019
1154
  checksum.update("\0");
1020
1155
  checksum.update(fs.readFileSync(path.join(root, file)));
1156
+ if (++checked % 64 === 0)
1157
+ publishSetup('identity_digest_progress', `${root}:${checked}`);
1021
1158
  checksum.update("\0");
1022
1159
  }
1023
- return checksum.digest("hex");
1160
+ const result = checksum.digest("hex");
1161
+ publishSetup('identity_digest_completed', root);
1162
+ return result;
1024
1163
  }
1025
1164
  function collectFiles(root, current, files) {
1026
1165
  for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
1027
1166
  if (entry.name === "engine.json")
1028
1167
  continue;
1029
1168
  const full = path.join(current, entry.name);
1169
+ if (entry.isSymbolicLink())
1170
+ throw new AppError("engine_integrity_symlink", "Pinned engine snapshot contains an unhashed symbolic link", 1, { path: path.relative(root, full) });
1030
1171
  if (entry.isDirectory())
1031
1172
  collectFiles(root, full, files);
1032
1173
  else if (entry.isFile())