@deksden-com/dd-flow-cli 0.9.0-beta.15 → 0.9.0-beta.151

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