@deksden-com/dd-flow-cli 0.9.0-beta.16 → 0.9.0-beta.160

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 (670) hide show
  1. package/CHANGELOG.md +959 -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 +417 -0
  6. package/dist/cli/command-metadata.js +303 -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/delivery.js +108 -0
  11. package/dist/cli/diagnostic-invocation.js +62 -0
  12. package/dist/cli/diagnostic.js +131 -0
  13. package/dist/cli/error-output.js +62 -0
  14. package/dist/cli/executor-onboarding.js +76 -0
  15. package/dist/cli/flows.js +29 -0
  16. package/dist/cli/harnesses.js +84 -0
  17. package/dist/cli/help.js +521 -19
  18. package/dist/cli/hook-ingress.js +89 -0
  19. package/dist/cli/input-preparation.js +193 -0
  20. package/dist/cli/interactive-invocation.js +33 -0
  21. package/dist/cli/interactive.js +114 -0
  22. package/dist/cli/memory-fix-invocation.js +52 -0
  23. package/dist/cli/memory-fix.js +100 -0
  24. package/dist/cli/memory-flow-admission.js +54 -0
  25. package/dist/cli/memory-init-invocation.js +85 -0
  26. package/dist/cli/memory-init.js +250 -0
  27. package/dist/cli/memory-storage-admission.js +54 -0
  28. package/dist/cli/memory-storage-qualification.js +105 -0
  29. package/dist/cli/memory-storage-transition.js +123 -0
  30. package/dist/cli/memory-upgrade.js +189 -0
  31. package/dist/cli/models.js +39 -0
  32. package/dist/cli/native-hook-ingress.js +94 -0
  33. package/dist/cli/native-hook-preparation.js +82 -0
  34. package/dist/cli/operator-profiles.js +61 -0
  35. package/dist/cli/output-options.js +35 -0
  36. package/dist/cli/response-file.js +72 -0
  37. package/dist/cli/run-cli.js +2020 -555
  38. package/dist/cli/runtime-maintenance-diagnostics.js +46 -0
  39. package/dist/cli/runtime-maintenance-ingress.js +52 -0
  40. package/dist/cli/runtime-process.js +153 -0
  41. package/dist/cli/setup.js +150 -0
  42. package/dist/cli.js +103 -2
  43. package/dist/domain/delivery-flows.js +8 -0
  44. package/dist/domain/diagnostic-aspects.js +103 -0
  45. package/dist/domain/diagnostic-flows.js +8 -0
  46. package/dist/domain/distill-flow.js +20 -0
  47. package/dist/domain/interactive-flow.js +1 -0
  48. package/dist/domain/memory-fix-flow.js +2 -0
  49. package/dist/domain/review-fix-flow.js +2 -0
  50. package/dist/domain/source-snapshot-flows.js +4 -0
  51. package/dist/domain/stage-catalog.js +1 -1
  52. package/dist/domain/stage-handler-identities.js +28 -0
  53. package/dist/harness-runtime/DD-ZCODE.md +112 -0
  54. package/dist/harness-runtime/OPENCODE-LICENSE.txt +24 -0
  55. package/dist/harness-runtime/bin/dd-agy.mjs +71 -0
  56. package/dist/harness-runtime/bin/dd-codex.mjs +27 -0
  57. package/dist/harness-runtime/bin/dd-droid.mjs +34 -0
  58. package/dist/harness-runtime/bin/dd-grok.mjs +50 -0
  59. package/dist/harness-runtime/bin/dd-opencode.mjs +22 -0
  60. package/dist/harness-runtime/bin/dd-zcode.mjs +95 -0
  61. package/dist/harness-runtime/lib/adapter-timeouts.d.mts +5 -0
  62. package/dist/harness-runtime/lib/adapter-timeouts.mjs +34 -0
  63. package/dist/harness-runtime/lib/agy-error-boundary.mjs +87 -0
  64. package/dist/harness-runtime/lib/agy-hooks.d.mts +1 -0
  65. package/dist/harness-runtime/lib/agy-hooks.mjs +9 -0
  66. package/dist/harness-runtime/lib/agy-native-inspection.mjs +225 -0
  67. package/dist/harness-runtime/lib/agy-native-inventory.mjs +19 -0
  68. package/dist/harness-runtime/lib/agy-native_pb.js +117 -0
  69. package/dist/harness-runtime/lib/agy-terminal-envelope.mjs +74 -0
  70. package/dist/harness-runtime/lib/agy-transcript-stream.mjs +54 -0
  71. package/dist/harness-runtime/lib/daemon-observation.d.mts +3 -0
  72. package/dist/harness-runtime/lib/daemon-observation.mjs +171 -0
  73. package/dist/harness-runtime/lib/daemon-operations.d.mts +2 -0
  74. package/dist/harness-runtime/lib/daemon-operations.mjs +512 -0
  75. package/dist/harness-runtime/lib/dd-agy-daemon.d.mts +7 -0
  76. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +1362 -0
  77. package/dist/harness-runtime/lib/dd-agy.mjs +105 -0
  78. package/dist/harness-runtime/lib/dd-codex-daemon.d.mts +1 -0
  79. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +271 -0
  80. package/dist/harness-runtime/lib/dd-codex.d.mts +1 -0
  81. package/dist/harness-runtime/lib/dd-codex.mjs +986 -0
  82. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +155 -0
  83. package/dist/harness-runtime/lib/dd-droid.mjs +739 -0
  84. package/dist/harness-runtime/lib/dd-grok-daemon.d.mts +1 -0
  85. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +667 -0
  86. package/dist/harness-runtime/lib/dd-grok.mjs +182 -0
  87. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +772 -0
  88. package/dist/harness-runtime/lib/dd-opencode.mjs +411 -0
  89. package/dist/harness-runtime/lib/dd-zcode-daemon.d.mts +1 -0
  90. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +845 -0
  91. package/dist/harness-runtime/lib/dd-zcode.mjs +1239 -0
  92. package/dist/harness-runtime/lib/delegation-instructions.d.mts +16 -0
  93. package/dist/harness-runtime/lib/delegation-instructions.mjs +179 -0
  94. package/dist/harness-runtime/lib/delivery-command.mjs +84 -0
  95. package/dist/harness-runtime/lib/dispatch-fence.mjs +14 -0
  96. package/dist/harness-runtime/lib/driver-recovery.mjs +121 -0
  97. package/dist/harness-runtime/lib/droid-observation.mjs +70 -0
  98. package/dist/harness-runtime/lib/entity-references.d.mts +2 -0
  99. package/dist/harness-runtime/lib/entity-references.mjs +9 -0
  100. package/dist/harness-runtime/lib/lease-renewal.d.mts +8 -0
  101. package/dist/harness-runtime/lib/lease-renewal.mjs +37 -0
  102. package/dist/harness-runtime/lib/lifecycle-command.d.mts +20 -0
  103. package/dist/harness-runtime/lib/lifecycle-command.mjs +273 -0
  104. package/dist/harness-runtime/lib/lifecycle-contract.d.mts +11 -0
  105. package/dist/harness-runtime/lib/lifecycle-contract.mjs +20 -0
  106. package/dist/harness-runtime/lib/managed-daemon.d.mts +16 -0
  107. package/dist/harness-runtime/lib/managed-daemon.mjs +698 -0
  108. package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
  109. package/dist/harness-runtime/lib/model-observations.mjs +113 -0
  110. package/dist/harness-runtime/lib/native-children.d.mts +34 -0
  111. package/dist/harness-runtime/lib/native-children.mjs +265 -0
  112. package/dist/harness-runtime/lib/native-hook-command.d.mts +8 -0
  113. package/dist/harness-runtime/lib/native-hook-command.mjs +306 -0
  114. package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
  115. package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
  116. package/dist/harness-runtime/lib/native-streams.mjs +38 -0
  117. package/dist/harness-runtime/lib/observation-clock.d.mts +18 -0
  118. package/dist/harness-runtime/lib/observation-clock.mjs +95 -0
  119. package/dist/harness-runtime/lib/opencode-plugin.mjs +112 -0
  120. package/dist/harness-runtime/lib/operation-context.mjs +5 -0
  121. package/dist/harness-runtime/lib/operation-errors.d.mts +16 -0
  122. package/dist/harness-runtime/lib/operation-errors.mjs +140 -0
  123. package/dist/harness-runtime/lib/operation-progress.d.mts +7 -0
  124. package/dist/harness-runtime/lib/operation-progress.mjs +118 -0
  125. package/dist/harness-runtime/lib/process-json.d.mts +5 -0
  126. package/dist/harness-runtime/lib/process-json.mjs +200 -0
  127. package/dist/harness-runtime/lib/process-snapshot.mjs +10 -0
  128. package/dist/harness-runtime/lib/provider-overload-policy.d.mts +23 -0
  129. package/dist/harness-runtime/lib/provider-overload-policy.mjs +242 -0
  130. package/dist/harness-runtime/lib/runner-events.mjs +202 -0
  131. package/dist/harness-runtime/lib/runner-lock.mjs +42 -0
  132. package/dist/harness-runtime/lib/session-settlement.mjs +30 -0
  133. package/dist/harness-runtime/lib/setup-progress.d.mts +9 -0
  134. package/dist/harness-runtime/lib/setup-progress.mjs +53 -0
  135. package/dist/harness-runtime/lib/tool-observations.d.mts +21 -0
  136. package/dist/harness-runtime/lib/tool-observations.mjs +238 -0
  137. package/dist/harness-runtime/lib/zcode-native-hook-ownership.mjs +109 -0
  138. package/dist/harness-runtime/lib/zcode-usage.mjs +55 -0
  139. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-1y4a697q.js +81 -0
  140. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-2ny4vxct.js +92 -0
  141. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-6mptkzbc.js +0 -0
  142. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-7x67cf1q.js +52 -0
  143. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9rqn6x4v.js +16 -0
  144. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9vdz0zwn.js +1661 -0
  145. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ecs5ftka.js +1466 -0
  146. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-frbwqjmf.js +145 -0
  147. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gne7h7mq.js +50 -0
  148. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gx9wnkzr.js +105 -0
  149. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-m2eywc8w.js +0 -0
  150. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-nwcpakzx.js +12 -0
  151. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-q4g3afnw.js +623 -0
  152. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-qav6mfdz.js +0 -0
  153. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-sxt88q69.js +12 -0
  154. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-t1xa31vm.js +39 -0
  155. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ve4aws36.js +103 -0
  156. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vmytr4q8.js +4 -0
  157. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vt9jbch8.js +36 -0
  158. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vyas3vgt.js +0 -0
  159. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-wjyeq25y.js +30 -0
  160. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-xgnj2w4v.js +20 -0
  161. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-y2etg5bs.js +9 -0
  162. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ydhz1zrh.js +238 -0
  163. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-z6qdwcsf.js +62 -0
  164. package/dist/harness-runtime/vendor/opencode-client/contract.d.ts +1 -0
  165. package/dist/harness-runtime/vendor/opencode-client/contract.js +12 -0
  166. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.d.ts +2806 -0
  167. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.js +0 -0
  168. package/dist/harness-runtime/vendor/opencode-client/effect/api.d.ts +4 -0
  169. package/dist/harness-runtime/vendor/opencode-client/effect/api.js +0 -0
  170. package/dist/harness-runtime/vendor/opencode-client/effect/client.d.ts +2530 -0
  171. package/dist/harness-runtime/vendor/opencode-client/effect/client.js +15 -0
  172. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.d.ts +7 -0
  173. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.js +6 -0
  174. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.d.ts +2529 -0
  175. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.js +8 -0
  176. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.d.ts +2 -0
  177. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.js +12 -0
  178. package/dist/harness-runtime/vendor/opencode-client/effect/index.d.ts +35 -0
  179. package/dist/harness-runtime/vendor/opencode-client/effect/index.js +75 -0
  180. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.d.ts +20 -0
  181. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.js +11 -0
  182. package/dist/harness-runtime/vendor/opencode-client/effect/service.d.ts +90 -0
  183. package/dist/harness-runtime/vendor/opencode-client/effect/service.js +187 -0
  184. package/dist/harness-runtime/vendor/opencode-client/package.json +84 -0
  185. package/dist/harness-runtime/vendor/opencode-client/promise/api.d.ts +21 -0
  186. package/dist/harness-runtime/vendor/opencode-client/promise/api.js +0 -0
  187. package/dist/harness-runtime/vendor/opencode-client/promise/client.d.ts +252 -0
  188. package/dist/harness-runtime/vendor/opencode-client/promise/client.js +14 -0
  189. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.d.ts +8 -0
  190. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.js +6 -0
  191. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.d.ts +259 -0
  192. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.js +7 -0
  193. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.d.ts +3 -0
  194. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.js +79 -0
  195. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.d.ts +8932 -0
  196. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.js +70 -0
  197. package/dist/harness-runtime/vendor/opencode-client/promise/index.d.ts +6 -0
  198. package/dist/harness-runtime/vendor/opencode-client/promise/index.js +83 -0
  199. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.d.ts +32 -0
  200. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.js +7 -0
  201. package/dist/harness-runtime/vendor/opencode-client/promise/service.d.ts +24 -0
  202. package/dist/harness-runtime/vendor/opencode-client/promise/service.js +187 -0
  203. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.d.ts +12 -0
  204. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.js +14 -0
  205. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.d.ts +20 -0
  206. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.js +14 -0
  207. package/dist/harness-runtime/vendor/opencode-client/service-contender.d.ts +37 -0
  208. package/dist/harness-runtime/vendor/opencode-client/service-contender.js +10 -0
  209. package/dist/harness-runtime/vendor/opencode-client/service-probe.d.ts +70 -0
  210. package/dist/harness-runtime/vendor/opencode-client/service-probe.js +16 -0
  211. package/dist/harness-runtime/vendor/opencode-client/service-timing.d.ts +12 -0
  212. package/dist/harness-runtime/vendor/opencode-client/service-timing.js +10 -0
  213. package/dist/harness-runtime/vendor/opencode-client/service-version.d.ts +2 -0
  214. package/dist/harness-runtime/vendor/opencode-client/service-version.js +6 -0
  215. package/dist/harness-runtime/vendor/opencode-client/service.d.ts +52 -0
  216. package/dist/harness-runtime/vendor/opencode-client/service.js +1 -0
  217. package/dist/harness-runtime/vendor/opencode-client/shared-events.d.ts +11 -0
  218. package/dist/harness-runtime/vendor/opencode-client/shared-events.js +8 -0
  219. package/dist/harness-runtime/vendor/opencode-client/solid/connection.d.ts +37 -0
  220. package/dist/harness-runtime/vendor/opencode-client/solid/connection.js +10 -0
  221. package/dist/harness-runtime/vendor/opencode-client/solid/data.d.ts +211 -0
  222. package/dist/harness-runtime/vendor/opencode-client/solid/data.js +18 -0
  223. package/dist/harness-runtime/vendor/opencode-client/solid/index.d.ts +3 -0
  224. package/dist/harness-runtime/vendor/opencode-client/solid/index.js +32 -0
  225. package/dist/harness-runtime/vendor/opencode-client/solid/pty.d.ts +22 -0
  226. package/dist/harness-runtime/vendor/opencode-client/solid/pty.js +8 -0
  227. package/dist/harness-runtime/vendor/opencode-plugin.mjs +3 -0
  228. package/dist/protocol/local-files.js +18 -9
  229. package/dist/runtime/context.js +8 -4
  230. package/dist/schemas/agent-profile.schema.json +1 -1
  231. package/dist/schemas/code-review-decision.schema.json +9 -0
  232. package/dist/schemas/code-review-result.schema.json +1 -1
  233. package/dist/schemas/code-verification.schema.json +7 -5
  234. package/dist/schemas/code-work-batch.schema.json +2 -2
  235. package/dist/schemas/code-work-result.schema.json +2 -1
  236. package/dist/schemas/delivery-stage-result.schema.json +286 -0
  237. package/dist/schemas/diagnostic-stage-result.schema.json +354 -0
  238. package/dist/schemas/diagnostic-work-result.schema.json +296 -0
  239. package/dist/schemas/discovery-result.schema.json +184 -0
  240. package/dist/schemas/distill-stage-result.schema.json +667 -0
  241. package/dist/schemas/distill-work-result.schema.json +428 -0
  242. package/dist/schemas/execution-bundle.schema.json +215 -0
  243. package/dist/schemas/execution-settings.schema.json +162 -0
  244. package/dist/schemas/flow-descriptor.schema.json +54 -0
  245. package/dist/schemas/flow-run.schema.json +29 -0
  246. package/dist/schemas/harness-catalog.schema.json +80 -0
  247. package/dist/schemas/interactive-stage-result.schema.json +47 -0
  248. package/dist/schemas/interactive-work-result.schema.json +63 -0
  249. package/dist/schemas/mb-fix-stage-result.schema.json +93 -0
  250. package/dist/schemas/mb-init-compose-result.schema.json +457 -0
  251. package/dist/schemas/mb-init-discover-result.schema.json +500 -0
  252. package/dist/schemas/mb-init-finish-result.schema.json +422 -0
  253. package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
  254. package/dist/schemas/mb-init-review-result.schema.json +396 -0
  255. package/dist/schemas/mb-init-verify-result.schema.json +391 -0
  256. package/dist/schemas/mb-upgrade-stage-result.schema.json +863 -0
  257. package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
  258. package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
  259. package/dist/schemas/memory-composition-work-result.schema.json +38 -0
  260. package/dist/schemas/memory-repair-work-result.schema.json +56 -0
  261. package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
  262. package/dist/schemas/memory-review-work-result.schema.json +43 -0
  263. package/dist/schemas/model-catalog.schema.json +153 -0
  264. package/dist/schemas/plan-review-decision.schema.json +12 -3
  265. package/dist/schemas/plan-review-result.schema.json +2 -2
  266. package/dist/schemas/profile-settings.schema.json +122 -0
  267. package/dist/schemas/project-flow-pack-manifest.schema.json +2 -2
  268. package/dist/schemas/release-impact.schema.json +3 -3
  269. package/dist/schemas/release-manifest.schema.json +291 -0
  270. package/dist/schemas/review-fix-stage-result.schema.json +210 -0
  271. package/dist/schemas/run-control-receipt.schema.json +119 -0
  272. package/dist/schemas/run-control-request.schema.json +36 -0
  273. package/dist/schemas/run-engine-binding.schema.json +1 -1
  274. package/dist/schemas/stage-start-response.schema.json +4 -0
  275. package/dist/schemas/vnext-protocol-plan.schema.json +3 -3
  276. package/dist/services/accepted-intent.js +139 -0
  277. package/dist/services/assigned-lifecycle.js +382 -0
  278. package/dist/services/branch-context.js +3 -3
  279. package/dist/services/canon.js +54 -15
  280. package/dist/services/check-environment.js +21 -0
  281. package/dist/services/check-runner-evidence.js +344 -0
  282. package/dist/services/check-runner-proof.js +373 -0
  283. package/dist/services/cleanup.js +133 -40
  284. package/dist/services/cli-operation-classifier.js +32 -64
  285. package/dist/services/cli-upgrade-allowlist.js +27 -0
  286. package/dist/services/code-checks.js +1426 -121
  287. package/dist/services/codex-capacity.js +367 -0
  288. package/dist/services/codex-hook-delivery.js +41 -0
  289. package/dist/services/command-context.js +80 -0
  290. package/dist/services/compatibility-preflight.js +16 -3
  291. package/dist/services/config.js +11 -8
  292. package/dist/services/continuation-outcome.js +25 -0
  293. package/dist/services/controller-child-capacity.js +71 -0
  294. package/dist/services/controller-child-observer.js +121 -0
  295. package/dist/services/controller-child-repair.js +117 -0
  296. package/dist/services/controller-execution.js +97 -0
  297. package/dist/services/controller-fanout.js +277 -0
  298. package/dist/services/controller-memory-task.js +45 -0
  299. package/dist/services/controller-memory-worker.js +51 -0
  300. package/dist/services/controller-result-authority.js +127 -0
  301. package/dist/services/controller-work-failure.js +198 -0
  302. package/dist/services/dashboard.js +145 -58
  303. package/dist/services/delivery-access.js +123 -0
  304. package/dist/services/delivery-approval.js +68 -0
  305. package/dist/services/delivery-artifact.js +86 -0
  306. package/dist/services/delivery-checks.js +178 -0
  307. package/dist/services/delivery-execution.js +181 -0
  308. package/dist/services/delivery-intents.js +212 -0
  309. package/dist/services/delivery-operation.js +81 -0
  310. package/dist/services/delivery-policy.js +91 -0
  311. package/dist/services/delivery-procedures.js +43 -0
  312. package/dist/services/delivery-request.js +99 -0
  313. package/dist/services/delivery-result.js +144 -0
  314. package/dist/services/delivery-stage-commands.js +26 -0
  315. package/dist/services/delivery-stage-entry.js +56 -0
  316. package/dist/services/delivery-stage-handlers.js +135 -0
  317. package/dist/services/delivery-stage-results.js +94 -0
  318. package/dist/services/descriptor-coordinator-session.js +37 -0
  319. package/dist/services/descriptor-root-work.js +53 -0
  320. package/dist/services/descriptor-run-settlement.js +107 -0
  321. package/dist/services/descriptor-run-start.js +495 -0
  322. package/dist/services/descriptor-stage-coordinator.js +318 -0
  323. package/dist/services/descriptor-stage-settlement.js +268 -0
  324. package/dist/services/descriptor-stage-start.js +175 -0
  325. package/dist/services/diagnostic-evidence.js +73 -0
  326. package/dist/services/diagnostic-repair-intake.js +123 -0
  327. package/dist/services/diagnostic-repair-source-intake.js +102 -0
  328. package/dist/services/diagnostic-report-publication.js +72 -0
  329. package/dist/services/diagnostic-report.js +97 -0
  330. package/dist/services/diagnostic-run-bundle.js +113 -0
  331. package/dist/services/diagnostic-snapshot.js +159 -0
  332. package/dist/services/diagnostic-stage-handlers.js +109 -0
  333. package/dist/services/diagnostic-stage-results.js +158 -0
  334. package/dist/services/diagnostic-start.js +134 -0
  335. package/dist/services/diagnostic-work-batch.js +34 -0
  336. package/dist/services/diagnostic-work-collection.js +97 -0
  337. package/dist/services/diagnostic-work-registration.js +101 -0
  338. package/dist/services/diagnostic-work-results.js +93 -0
  339. package/dist/services/discovery/agy-discovery.js +2 -0
  340. package/dist/services/discovery/codex-discovery.js +2 -0
  341. package/dist/services/discovery/droid-discovery.js +2 -0
  342. package/dist/services/discovery/grok-discovery.js +2 -0
  343. package/dist/services/discovery/opencode-discovery.js +2 -0
  344. package/dist/services/discovery/static.js +31 -0
  345. package/dist/services/discovery/zcode-discovery.js +2 -0
  346. package/dist/services/distill-document-publication.js +280 -0
  347. package/dist/services/distill-promotion.js +197 -0
  348. package/dist/services/distill-publication-custody.js +162 -0
  349. package/dist/services/distill-stage-handlers.js +249 -0
  350. package/dist/services/distill-stage-results.js +105 -0
  351. package/dist/services/distill-user-inputs.js +4 -0
  352. package/dist/services/distill-work-batch.js +42 -0
  353. package/dist/services/distill-work-collection.js +74 -0
  354. package/dist/services/distill-work-registration.js +93 -0
  355. package/dist/services/distill-work-results.js +98 -0
  356. package/dist/services/engines.js +354 -163
  357. package/dist/services/eval-snapshots.js +1326 -150
  358. package/dist/services/execution-bundles.js +275 -0
  359. package/dist/services/execution-policy.js +185 -0
  360. package/dist/services/executor-onboarding.js +56 -0
  361. package/dist/services/external-work-launch.js +316 -0
  362. package/dist/services/flow-catalog.js +54 -0
  363. package/dist/services/flow-descriptors.js +82 -0
  364. package/dist/services/frozen-engine.js +404 -0
  365. package/dist/services/generic-execution.js +165 -0
  366. package/dist/services/harness-adapter.js +342 -35
  367. package/dist/services/harness-config.js +2 -0
  368. package/dist/services/harness-discovery.js +29 -0
  369. package/dist/services/harness-doctor.js +75 -0
  370. package/dist/services/harness-probe-effects.js +51 -0
  371. package/dist/services/harness-version-probe.js +100 -0
  372. package/dist/services/hook-memory-routing.js +188 -0
  373. package/dist/services/hook-recovery-guard.js +14 -0
  374. package/dist/services/hook-session-observation.js +24 -0
  375. package/dist/services/hooks.js +813 -327
  376. package/dist/services/hybrid-contracts.js +479 -0
  377. package/dist/services/hybrid-digest.js +14 -0
  378. package/dist/services/ids.js +29 -1
  379. package/dist/services/installation-lock.js +95 -0
  380. package/dist/services/installed-flow-source.js +261 -0
  381. package/dist/services/interactive-attached-session.js +215 -0
  382. package/dist/services/interactive-baseline-custody.js +54 -0
  383. package/dist/services/interactive-before-versions.js +148 -0
  384. package/dist/services/interactive-bundle-data.js +85 -0
  385. package/dist/services/interactive-checks.js +179 -0
  386. package/dist/services/interactive-execution.js +33 -0
  387. package/dist/services/interactive-finish-integration.js +236 -0
  388. package/dist/services/interactive-git-baseline.js +230 -0
  389. package/dist/services/interactive-git-dispatch.js +278 -0
  390. package/dist/services/interactive-input-delivery.js +82 -0
  391. package/dist/services/interactive-mutation-scope.js +231 -0
  392. package/dist/services/interactive-request.js +287 -0
  393. package/dist/services/interactive-run-bundle.js +109 -0
  394. package/dist/services/interactive-stage-entry.js +41 -0
  395. package/dist/services/interactive-stage-handlers.js +289 -0
  396. package/dist/services/interactive-stage-observation.js +136 -0
  397. package/dist/services/interactive-stage-results.js +111 -0
  398. package/dist/services/interactive-user-inputs.js +142 -0
  399. package/dist/services/interactive-work-batch.js +43 -0
  400. package/dist/services/interactive-work-collection.js +119 -0
  401. package/dist/services/interactive-work-completion.js +180 -0
  402. package/dist/services/interactive-work-context.js +249 -0
  403. package/dist/services/interactive-work-history.js +112 -0
  404. package/dist/services/interactive-work-registration.js +124 -0
  405. package/dist/services/interactive-work-results.js +115 -0
  406. package/dist/services/interactive-work-start.js +155 -0
  407. package/dist/services/lanes.js +78 -65
  408. package/dist/services/lifecycle-command.js +1 -288
  409. package/dist/services/lifecycle-contract.js +1 -0
  410. package/dist/services/lifecycle-invocations.js +2549 -0
  411. package/dist/services/managed-daemon-binding.js +129 -0
  412. package/dist/services/managed-lease-monitor.js +133 -0
  413. package/dist/services/managed-processes.js +449 -69
  414. package/dist/services/memory-accepted-composition.js +78 -0
  415. package/dist/services/memory-baseline-preservation.js +65 -0
  416. package/dist/services/memory-completed-correction-wave.js +328 -0
  417. package/dist/services/memory-compose-handler.js +380 -0
  418. package/dist/services/memory-composition-acceptance.js +375 -0
  419. package/dist/services/memory-composition-graph.js +165 -0
  420. package/dist/services/memory-composition-registration.js +161 -0
  421. package/dist/services/memory-composition-work-custody.js +156 -0
  422. package/dist/services/memory-composition-work-results.js +108 -0
  423. package/dist/services/memory-corrected-review-acceptance.js +129 -0
  424. package/dist/services/memory-corrected-review-batch.js +37 -0
  425. package/dist/services/memory-corrected-review-findings.js +108 -0
  426. package/dist/services/memory-corrected-review-inputs.js +215 -0
  427. package/dist/services/memory-corrected-review-projection.js +78 -0
  428. package/dist/services/memory-corrected-review-receipt.js +178 -0
  429. package/dist/services/memory-corrected-review-registration.js +192 -0
  430. package/dist/services/memory-correction-check-receipt.js +235 -0
  431. package/dist/services/memory-correction-input-owner.js +6 -0
  432. package/dist/services/memory-custody-snapshot.js +36 -0
  433. package/dist/services/memory-discover-handler.js +104 -0
  434. package/dist/services/memory-finish-evidence.js +457 -0
  435. package/dist/services/memory-finish-handler.js +229 -0
  436. package/dist/services/memory-finish-integration.js +491 -0
  437. package/dist/services/memory-finish-readiness.js +169 -0
  438. package/dist/services/memory-fix-finish-integration.js +129 -0
  439. package/dist/services/memory-fix-git-dispatch.js +139 -0
  440. package/dist/services/memory-fix-intake-custody.js +11 -0
  441. package/dist/services/memory-fix-intake-settlement.js +127 -0
  442. package/dist/services/memory-fix-publication.js +196 -0
  443. package/dist/services/memory-fix-repair-admission.js +116 -0
  444. package/dist/services/memory-fix-request.js +141 -0
  445. package/dist/services/memory-fix-run-bundle.js +83 -0
  446. package/dist/services/memory-fix-scope.js +78 -0
  447. package/dist/services/memory-fix-sources.js +85 -0
  448. package/dist/services/memory-fix-stage-entry.js +24 -0
  449. package/dist/services/memory-fix-stage-handlers.js +282 -0
  450. package/dist/services/memory-fix-stage-results.js +106 -0
  451. package/dist/services/memory-fix-workspace.js +127 -0
  452. package/dist/services/memory-flow-user-inputs.js +88 -0
  453. package/dist/services/memory-git-integration.js +220 -0
  454. package/dist/services/memory-historical-corrected-review.js +212 -0
  455. package/dist/services/memory-historical-original-review.js +143 -0
  456. package/dist/services/memory-historical-repair-registration.js +105 -0
  457. package/dist/services/memory-historical-second-review.js +147 -0
  458. package/dist/services/memory-init-bootstrap-readiness.js +210 -0
  459. package/dist/services/memory-init-contexts.js +181 -0
  460. package/dist/services/memory-init-controller-start.js +119 -0
  461. package/dist/services/memory-init-engine-release.js +223 -0
  462. package/dist/services/memory-init-git-policy.js +165 -0
  463. package/dist/services/memory-init-lint-capability.js +203 -0
  464. package/dist/services/memory-init-native-capacity.js +309 -0
  465. package/dist/services/memory-init-preflight.js +334 -0
  466. package/dist/services/memory-init-project-bootstrap.js +599 -0
  467. package/dist/services/memory-init-request-candidate.js +213 -0
  468. package/dist/services/memory-init-request-input.js +82 -0
  469. package/dist/services/memory-init-resource-storage.js +125 -0
  470. package/dist/services/memory-init-run-allocation.js +81 -0
  471. package/dist/services/memory-init-run-bundle.js +135 -0
  472. package/dist/services/memory-init-start.js +181 -0
  473. package/dist/services/memory-init-startup-custody.js +80 -0
  474. package/dist/services/memory-init-startup-input.js +240 -0
  475. package/dist/services/memory-init-storage.js +91 -0
  476. package/dist/services/memory-init-stores.js +359 -0
  477. package/dist/services/memory-init-worktrunk-capability.js +174 -0
  478. package/dist/services/memory-layer-publication.js +611 -0
  479. package/dist/services/memory-layer.js +225 -0
  480. package/dist/services/memory-lint-config.js +194 -0
  481. package/dist/services/memory-native-review-copy.js +127 -0
  482. package/dist/services/memory-normal-flow-entry.js +87 -0
  483. package/dist/services/memory-ordinary-defaults.js +129 -0
  484. package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
  485. package/dist/services/memory-preflight-handler.js +274 -0
  486. package/dist/services/memory-repair-current-view.js +299 -0
  487. package/dist/services/memory-repair-document-delta.js +489 -0
  488. package/dist/services/memory-repair-history.js +496 -0
  489. package/dist/services/memory-repair-physical-binding.js +194 -0
  490. package/dist/services/memory-repair-publication-files.js +152 -0
  491. package/dist/services/memory-repair-publication-intent.js +27 -0
  492. package/dist/services/memory-repair-publication-plan.js +162 -0
  493. package/dist/services/memory-repair-publication-source.js +225 -0
  494. package/dist/services/memory-repair-publication.js +795 -0
  495. package/dist/services/memory-repair-registration.js +240 -0
  496. package/dist/services/memory-repair-work-baseline.js +415 -0
  497. package/dist/services/memory-repair-work-completion.js +117 -0
  498. package/dist/services/memory-repair-work-custody.js +73 -0
  499. package/dist/services/memory-repair-work-results.js +108 -0
  500. package/dist/services/memory-repair-workspace.js +261 -0
  501. package/dist/services/memory-repair-writer-copy.js +736 -0
  502. package/dist/services/memory-result-binding.js +239 -0
  503. package/dist/services/memory-retained-review-authority.js +138 -0
  504. package/dist/services/memory-retained-review-results.js +70 -0
  505. package/dist/services/memory-retained-second-baseline.js +102 -0
  506. package/dist/services/memory-retained-second-repairs.js +162 -0
  507. package/dist/services/memory-review-acceptance.js +214 -0
  508. package/dist/services/memory-review-correction-plan.js +206 -0
  509. package/dist/services/memory-review-handler.js +585 -0
  510. package/dist/services/memory-review-inputs.js +246 -0
  511. package/dist/services/memory-review-limits.js +10 -0
  512. package/dist/services/memory-review-receipt.js +180 -0
  513. package/dist/services/memory-review-registration.js +117 -0
  514. package/dist/services/memory-review-work-custody.js +126 -0
  515. package/dist/services/memory-review-work-input.js +91 -0
  516. package/dist/services/memory-review-work-results.js +95 -0
  517. package/dist/services/memory-second-corrected-review-inputs.js +167 -0
  518. package/dist/services/memory-second-correction-plan.js +77 -0
  519. package/dist/services/memory-second-repair-baseline.js +91 -0
  520. package/dist/services/memory-second-repair-launch.js +614 -0
  521. package/dist/services/memory-second-repair-registration.js +88 -0
  522. package/dist/services/memory-second-repair-source.js +187 -0
  523. package/dist/services/memory-second-review-acceptance.js +115 -0
  524. package/dist/services/memory-source-observations.js +117 -0
  525. package/dist/services/memory-stage-dispatch.js +65 -0
  526. package/dist/services/memory-stage-results.js +290 -0
  527. package/dist/services/memory-tool-probe.js +25 -0
  528. package/dist/services/memory-upgrade-analysis-handler.js +243 -0
  529. package/dist/services/memory-upgrade-bootstrap-readiness.js +251 -0
  530. package/dist/services/memory-upgrade-evidence.js +100 -0
  531. package/dist/services/memory-upgrade-inventory.js +442 -0
  532. package/dist/services/memory-upgrade-publication-custody.js +73 -0
  533. package/dist/services/memory-upgrade-publication.js +413 -0
  534. package/dist/services/memory-upgrade-selection.js +430 -0
  535. package/dist/services/memory-upgrade-start.js +60 -0
  536. package/dist/services/memory-upgrade-storage-readiness.js +340 -0
  537. package/dist/services/memory-verification-acceptance.js +156 -0
  538. package/dist/services/memory-verification-checks.js +317 -0
  539. package/dist/services/memory-verification-receipt.js +160 -0
  540. package/dist/services/memory-verify-handler.js +137 -0
  541. package/dist/services/memory-work-result-json.js +12 -0
  542. package/dist/services/memory-work-result-preparation.js +64 -0
  543. package/dist/services/merge-queue.js +228 -149
  544. package/dist/services/merge-server.js +163 -35
  545. package/dist/services/migrations.js +164 -114
  546. package/dist/services/model-catalog.js +109 -0
  547. package/dist/services/model-discovery.js +46 -0
  548. package/dist/services/native-daemon-history.js +50 -0
  549. package/dist/services/native-session-control.js +39 -0
  550. package/dist/services/operator-profiles.js +236 -0
  551. package/dist/services/physical-startup.js +45 -0
  552. package/dist/services/plan-runtime.js +26 -11
  553. package/dist/services/plans.js +28 -25
  554. package/dist/services/project-flow-source.js +195 -0
  555. package/dist/services/project-git-integration.js +92 -0
  556. package/dist/services/project-registry.js +97 -0
  557. package/dist/services/project-summary.js +1 -1
  558. package/dist/services/projects.js +17 -87
  559. package/dist/services/prompt-delivery.js +71 -0
  560. package/dist/services/prompts.js +28 -17
  561. package/dist/services/protocols.js +163 -87
  562. package/dist/services/provider-capacity.js +463 -0
  563. package/dist/services/recovery-observation-budget.js +121 -0
  564. package/dist/services/recovery-snapshot-database.js +588 -0
  565. package/dist/services/release-archive-producer.js +52 -0
  566. package/dist/services/release-archive.js +143 -0
  567. package/dist/services/release-cache.js +150 -0
  568. package/dist/services/release-compatibility.js +18 -0
  569. package/dist/services/release-download.js +67 -0
  570. package/dist/services/release-envelope.js +104 -0
  571. package/dist/services/release-manifest.js +45 -0
  572. package/dist/services/release-payload.js +114 -0
  573. package/dist/services/release-producer.js +63 -0
  574. package/dist/services/release-provenance.js +160 -0
  575. package/dist/services/release-registry.js +66 -0
  576. package/dist/services/release-source.js +194 -0
  577. package/dist/services/repair-intents.js +29 -0
  578. package/dist/services/repair-receipt.js +13 -0
  579. package/dist/services/retained-native-hook.js +274 -0
  580. package/dist/services/review-copy.js +165 -0
  581. package/dist/services/review-deferral.js +23 -0
  582. package/dist/services/review-fix-handoff.js +82 -0
  583. package/dist/services/review-fix-intake-custody.js +17 -0
  584. package/dist/services/review-fix-stage-entry.js +43 -0
  585. package/dist/services/review-fix-stage-handlers.js +176 -0
  586. package/dist/services/review-fix-stage-results.js +86 -0
  587. package/dist/services/run-control-receipt.js +56 -0
  588. package/dist/services/run-control-worker.js +469 -0
  589. package/dist/services/run-control.js +1109 -0
  590. package/dist/services/run-controller-adapter.js +434 -0
  591. package/dist/services/run-controller-capture.js +186 -0
  592. package/dist/services/run-controller-process.js +226 -0
  593. package/dist/services/run-controller-recovery.js +335 -0
  594. package/dist/services/run-controller-state.js +106 -0
  595. package/dist/services/run-controller.js +1717 -0
  596. package/dist/services/run-engine-bindings.js +1 -1
  597. package/dist/services/run-fork.js +147 -0
  598. package/dist/services/run-health.js +149 -0
  599. package/dist/services/run-observations.js +152 -0
  600. package/dist/services/run-projection.js +22 -64
  601. package/dist/services/run-recovery-guard.js +107 -0
  602. package/dist/services/run-recovery-runtime.js +112 -0
  603. package/dist/services/run-recovery.js +485 -0
  604. package/dist/services/run-start-custody.js +189 -0
  605. package/dist/services/run-timeline.js +59 -0
  606. package/dist/services/runs.js +996 -271
  607. package/dist/services/runtime-budget.js +446 -0
  608. package/dist/services/runtime-command.js +43 -0
  609. package/dist/services/runtime-scope-capture.js +52 -0
  610. package/dist/services/runtime-scope-control.js +468 -0
  611. package/dist/services/runtime-scope-resume.js +605 -0
  612. package/dist/services/runtime-scope-stop.js +211 -0
  613. package/dist/services/runtime-scope-worker.js +314 -0
  614. package/dist/services/runtime-service.js +19 -14
  615. package/dist/services/schema-validation.js +10 -8
  616. package/dist/services/scope-writer-cleanup.js +27 -0
  617. package/dist/services/sessions.js +37 -91
  618. package/dist/services/setup.js +427 -0
  619. package/dist/services/stage-blocker.js +17 -7
  620. package/dist/services/stage-context.js +240 -18
  621. package/dist/services/stage-handlers.js +141 -0
  622. package/dist/services/stage-lifecycle.js +156 -119
  623. package/dist/services/stage-pause.js +222 -94
  624. package/dist/services/stage-report-renderer.js +230 -6
  625. package/dist/services/stage-work-graph.js +52 -0
  626. package/dist/services/technical-notes.js +31 -0
  627. package/dist/services/tooling.js +111 -44
  628. package/dist/services/usage.js +49 -101
  629. package/dist/services/verification-matrix.js +393 -0
  630. package/dist/services/version-status.js +1 -1
  631. package/dist/services/vnext-code-review.js +302 -91
  632. package/dist/services/vnext-code.js +325 -251
  633. package/dist/services/vnext-contracts.js +10 -1
  634. package/dist/services/vnext-execution-profile.js +80 -5
  635. package/dist/services/vnext-fanout.js +399 -20
  636. package/dist/services/vnext-merge.js +336 -114
  637. package/dist/services/vnext-plan-review.js +288 -133
  638. package/dist/services/vnext-plan.js +230 -106
  639. package/dist/services/vnext-protocolize.js +534 -96
  640. package/dist/services/vnext-specify.js +131 -84
  641. package/dist/services/vnext-workspace-policy.js +7 -2
  642. package/dist/services/work-registry.js +1950 -215
  643. package/dist/services/work-retry-context.js +55 -0
  644. package/dist/services/workspace-bootstrap.js +53 -15
  645. package/dist/services/workspace-files.js +85 -0
  646. package/dist/services/worktrees.js +108 -48
  647. package/dist/shared/entity-references.js +1 -0
  648. package/dist/shared/errors.js +27 -0
  649. package/dist/storage/agent-output.js +26 -0
  650. package/dist/storage/data-preservation.js +65 -0
  651. package/dist/storage/database.js +931 -40
  652. package/dist/storage/foreign-key-transaction.js +39 -0
  653. package/dist/storage/immutable-input.js +45 -0
  654. package/dist/storage/import-guard.js +159 -0
  655. package/dist/storage/memory-upgrade-schema-bootstrap.js +38 -0
  656. package/dist/storage/native-cleanup.js +52 -0
  657. package/dist/storage/paired-writer-migration.js +424 -0
  658. package/dist/storage/paths.js +17 -4
  659. package/dist/storage/projection-lock.js +73 -0
  660. package/dist/storage/work-references.js +23 -0
  661. package/dist/storage/writer-contract.js +96 -0
  662. package/dist/storage/writer-migration.js +346 -0
  663. package/dist/storage/writer-restore.js +217 -0
  664. package/dist/verification-components.json +384 -0
  665. package/package.json +52 -13
  666. package/tools/create-canon-release.mjs +33 -0
  667. package/tools/probe-codex-history.mjs +37 -0
  668. package/tools/produce-hybrid-release.mjs +41 -0
  669. package/tools/repair-paused-run-status.mjs +84 -0
  670. package/tools/verification-jobs.mjs +342 -0
@@ -0,0 +1,382 @@
1
+ import crypto from "node:crypto";
2
+ import { AppError } from "../shared/errors.js";
3
+ import { storageSessionId } from "./session-identity.js";
4
+ import { runtimeHarness } from "./execution-policy.js";
5
+ import { requireManagedDaemonBinding } from "./managed-daemon-binding.js";
6
+ import { appendAudit } from "./audit.js";
7
+ import { commandOption, commandPosition, continuationCommand, parseLifecycleCommand } from "./lifecycle-command.js";
8
+ import { processStartedAt } from "./managed-processes.js";
9
+ import { stageGraphScope } from "./stage-work-graph.js";
10
+ import { hookSessionIdentity, assertStageStartHookEvent, claimStageStartHookEvent } from "./hooks.js";
11
+ const owned = new WeakMap();
12
+ const assignmentEvent = "lifecycle.controller_assignment";
13
+ function refuse(reason) { throw new AppError("invocation_assignment_unproven", "Managed command has no current assigned execution", 1, { reason, effect: "no_effect", recoverable: false, reconciliation_required: true }); }
14
+ function parsed(command) { const value = parseLifecycleCommand(command); return value.kind === "standalone" ? value.invocation : null; }
15
+ function stageEntryFence(context, scope, stage) {
16
+ const row = context.db.get("SELECT index_json FROM runs WHERE id=? AND project_root=?", [scope.runId, scope.projectRoot]);
17
+ const index = row ? JSON.parse(row.index_json) : null;
18
+ return JSON.stringify([index?.current_stage ?? null, index?.stage_runs?.find((item) => item.stage === stage) ?? null, index?.variables?.["merge.source_repair"]?.cycle ?? null]);
19
+ }
20
+ /** Called by the controller after native creation/resolution, before dispatch. */
21
+ export function retainControllerStageAssignment(context, command, input) {
22
+ const scope = JSON.parse(context.env.DD_FLOW_INVOCATION_SCOPE ?? "null");
23
+ const invocation = parsed(command);
24
+ if (!scope?.runId || !invocation || invocation.operation !== "stage_start" || commandOption(invocation, "stage") !== input.stage)
25
+ refuse("stage_issuance_scope");
26
+ const rows = context.db.all("SELECT * FROM lifecycle_invocations WHERE scope_json=? AND status='issued'", [JSON.stringify(scope)])
27
+ .filter(row => { const item = parsed(row.command); return item?.operation === "stage_start" && commandOption(item, "stage") === input.stage && commandOption(item, "context-sha256") === input.contextSha256; });
28
+ if (rows.length !== 1)
29
+ refuse("stage_issuance_ambiguous");
30
+ const controller = context.db.get("SELECT * FROM run_controllers WHERE controller_id=?", [input.controllerId]);
31
+ if (!controller || controller.run_id !== scope.runId || controller.generation !== scope.generation || ["completed", "cancelled", "superseded"].includes(controller.status))
32
+ refuse("controller_stale");
33
+ const state = JSON.parse(controller.state_json);
34
+ const session = state.current_session === null ? undefined : state.sessions[state.current_session];
35
+ if (!session || session.id !== input.sessionId || session.state_dir !== input.stateDir || session.stopped || session.retired)
36
+ refuse("controller_session_changed");
37
+ const binding = requireManagedDaemonBinding(context, { stateDir: input.stateDir, projectId: controller.project_id, runId: controller.run_id, ownerId: input.controllerId });
38
+ const native = binding.state.sessions?.find(item => typeof item === "string" ? item === input.sessionId : item.adapter_session_id === input.sessionId || item.provider_session_id === input.sessionId);
39
+ const nativeId = typeof native === "string" ? native : native?.provider_session_id;
40
+ const rootId = typeof native === "string" ? native : native?.root_provider_session_id ?? native?.provider_session_id;
41
+ if (!nativeId || rootId !== scope.rootSessionId || binding.state.daemon_id !== scope.daemonId)
42
+ refuse("native_create_mapping_unavailable");
43
+ const harness = runtimeHarness(session.profile);
44
+ const identity = { source: "controller_assignment", hookEventId: null, harness, providerSessionId: nativeId,
45
+ parentSessionId: null, daemonId: scope.daemonId, agentId: null, sessionId: storageSessionId({ harness_id: harness, session_id: nativeId }), nativeSessionId: nativeId,
46
+ turnId: null, transcriptPath: null, provider: session.profile.provider ?? null, model: null, reasoning: null, mode: null, agentType: null, cwd: session.cwd };
47
+ const payload = { invocation_id: rows[0].id, scope, controller_id: input.controllerId, owner_token: controller.owner_token,
48
+ stage_entry_fence: stageEntryFence(context, scope, input.stage), adapter_session_id: input.sessionId,
49
+ stage: input.stage, context_sha256: input.contextSha256, attempt: input.attempt ?? null, cycle: input.cycle ?? null, identity };
50
+ const prior = context.db.get("SELECT payload_json FROM audit_events WHERE project_id=? AND event_type=? AND json_extract(payload_json,'$.invocation_id')=?", [controller.project_id, assignmentEvent, rows[0].id]);
51
+ if (prior) {
52
+ if (prior.payload_json !== JSON.stringify(payload))
53
+ refuse("stage_assignment_changed");
54
+ return;
55
+ }
56
+ appendAudit(context, { projectId: controller.project_id, eventType: assignmentEvent, payload });
57
+ }
58
+ /** Resolve immutable packet membership; a readable UUID or env is not ownership. */
59
+ export function assignedLifecycleBinding(context, row) {
60
+ const scope = JSON.parse(row.scope_json);
61
+ const invocation = parsed(row.command);
62
+ if (!invocation || !scope.runId)
63
+ return null;
64
+ const operation = invocation.operation;
65
+ if (operation === "stage_start") {
66
+ const retained = context.db.get("SELECT payload_json FROM audit_events WHERE event_type=? AND json_extract(payload_json,'$.invocation_id')=?", [assignmentEvent, row.id]);
67
+ if (!retained)
68
+ return null;
69
+ const launch = JSON.parse(retained.payload_json);
70
+ if (JSON.stringify(launch.scope) !== row.scope_json || launch.stage !== commandOption(invocation, "stage") || launch.context_sha256 !== commandOption(invocation, "context-sha256"))
71
+ refuse("stage_packet_changed");
72
+ const owner = context.db.get("SELECT generation,owner_token,status,state_json FROM run_controllers WHERE controller_id=?", [launch.controller_id]);
73
+ const state = owner && JSON.parse(owner.state_json);
74
+ if (!owner || owner.owner_token !== launch.owner_token || stageEntryFence(context, scope, launch.stage) !== launch.stage_entry_fence || owner.generation !== scope.generation || ["completed", "cancelled", "superseded"].includes(owner.status) || !state || state.current_session === null || state.sessions[state.current_session]?.id !== launch.adapter_session_id || state.sessions[state.current_session]?.stopped || state.sessions[state.current_session]?.retired)
75
+ refuse("stage_owner_changed");
76
+ return { schema_id: "dd-flow/assigned-lifecycle-admission@1", kind: "managed_assignment", invocation_id: row.id, scope, operation,
77
+ work_id: null, work_session_id: null, controller_id: launch.controller_id, controller_owner: { token: launch.owner_token, session_id: launch.adapter_session_id }, stage: launch.stage, identity: launch.identity };
78
+ }
79
+ if (!["work_finish", "work_fail", "stage_finish", "stage_pause", "stage_resume"].includes(operation))
80
+ return null;
81
+ const stage = commandOption(invocation, "stage") ?? null;
82
+ const target = operation.startsWith("work_") ? commandPosition(invocation, 0) : commandOption(invocation, "work");
83
+ const matches = context.db.all(`SELECT DISTINCT ws.id,ws.work_id,ws.session_id,ws.start_receipt_json,s.harness,s.provider_session_id,s.parent_session_id,s.cwd,he.daemon_id
84
+ FROM lifecycle_packet_assignments pa JOIN work_sessions ws ON (pa.packet_sha256=json_extract(ws.start_receipt_json,'$.prompt_sha256')
85
+ OR EXISTS (SELECT 1 FROM audit_events a WHERE a.event_type='lifecycle.coordinator_packet'
86
+ AND json_extract(a.payload_json,'$.work_session_id')=ws.id AND json_extract(a.payload_json,'$.packet_sha256')=pa.packet_sha256))
87
+ JOIN works w ON w.work_id=ws.work_id JOIN projects p ON p.id=w.project_id
88
+ JOIN sessions s ON s.project_id=w.project_id AND s.session_id=ws.session_id
89
+ LEFT JOIN hook_events he ON he.project_id=w.project_id AND he.event_key=ws.hook_event_id
90
+ WHERE pa.invocation_id=? AND p.root=? AND w.run_id=? AND ws.status='running' AND ws.start_publication_status='published'
91
+ AND w.status IN ('running','paused')`, [row.id, scope.projectRoot, scope.runId])
92
+ .filter(item => (!target || item.work_id === target || item.work_id.match(/^WRK-\d+/)?.[0] === target));
93
+ if (!matches.length)
94
+ return null;
95
+ if (matches.length !== 1)
96
+ refuse("ambiguous_packet_owner");
97
+ const item = matches[0];
98
+ if (operation !== "stage_resume" && item.daemon_id && item.daemon_id !== scope.daemonId)
99
+ refuse("work_daemon_changed");
100
+ const projectId = context.db.get("SELECT id FROM projects WHERE root=?", [scope.projectRoot])?.id;
101
+ if (!projectId)
102
+ refuse("assignment_project_missing");
103
+ const owners = context.db.get("SELECT 1 FROM sqlite_master WHERE name='run_controllers'")
104
+ ? context.db.all("SELECT controller_id,owner_token,state_json FROM run_controllers WHERE project_id=? AND run_id=? AND generation=? AND status NOT IN ('completed','cancelled','superseded')", [projectId, scope.runId, scope.generation]) : [];
105
+ if (owners.length > 1)
106
+ refuse("controller_owner_ambiguous");
107
+ const controller = owners[0];
108
+ const controllerState = controller && JSON.parse(controller.state_json);
109
+ const current = controllerState && controllerState.current_session !== null ? controllerState.sessions[controllerState.current_session] : null;
110
+ if (controller && (!current || current.retired || current.stopped))
111
+ refuse("controller_session_retired");
112
+ if (stage && !context.db.get("SELECT 1 FROM sessions WHERE project_id=? AND session_id=? AND run_id=? AND current_stage=?", [projectId, item.session_id, scope.runId, stage]))
113
+ refuse("inactive_stage_assignment");
114
+ if (stage) {
115
+ const project = context.db.get("SELECT id FROM projects WHERE root=?", [scope.projectRoot]);
116
+ const graph = stageGraphScope(context, project.id, scope.runId, stage);
117
+ const packet = context.db.get(`SELECT a.payload_json FROM audit_events a JOIN lifecycle_packet_assignments pa
118
+ ON pa.packet_sha256=json_extract(a.payload_json,'$.packet_sha256') WHERE a.event_type='lifecycle.coordinator_packet'
119
+ AND pa.invocation_id=? AND json_extract(a.payload_json,'$.work_session_id')=? ORDER BY a.id DESC LIMIT 1`, [row.id, item.id]);
120
+ if (!packet || JSON.stringify(JSON.parse(packet.payload_json).stage_scope) !== JSON.stringify(graph))
121
+ refuse("stage_attempt_changed");
122
+ }
123
+ let identity = { source: "controller_assignment", hookEventId: null, harness: item.harness,
124
+ providerSessionId: item.provider_session_id, nativeSessionId: item.provider_session_id, sessionId: item.session_id,
125
+ parentSessionId: item.parent_session_id, daemonId: scope.daemonId, agentId: null, turnId: null, transcriptPath: null,
126
+ provider: null, model: null, reasoning: null, mode: null, agentType: null, cwd: item.cwd };
127
+ if (operation === "stage_resume") {
128
+ const retained = context.db.get("SELECT payload_json FROM audit_events WHERE project_id=? AND event_type='lifecycle.resume_assignment' AND json_extract(payload_json,'$.invocation_id')=?", [projectId, row.id]);
129
+ const run = context.db.get("SELECT index_json FROM runs WHERE project_id=? AND id=?", [projectId, scope.runId]);
130
+ const pause = run && JSON.parse(run.index_json).stage_runs.find((entry) => entry.stage === stage)?.pause;
131
+ if (!retained || JSON.parse(retained.payload_json).pause_id !== pause?.id)
132
+ refuse("resume_pause_changed");
133
+ const assignedSession = JSON.parse(retained.payload_json).work_session_id;
134
+ if (assignedSession !== item.id) {
135
+ const receipt = JSON.parse(item.start_receipt_json);
136
+ const recovered = receipt.recovered_from_work_session_id === assignedSession && receipt.recovery_id && context.db.get(`SELECT 1 FROM run_recovery_bindings b JOIN run_recovery_guards g ON g.recovery_id=b.recovery_id
137
+ WHERE g.project_id=? AND g.run_id=? AND g.generation=? AND g.status='recovered' AND b.status='accepted'
138
+ AND b.recovery_id=? AND b.prior_work_session_id=? AND b.work_id=? AND b.session_id=?`, [projectId, scope.runId, scope.generation, receipt.recovery_id, assignedSession, item.work_id, item.session_id]);
139
+ if (!recovered)
140
+ refuse("resume_session_changed");
141
+ }
142
+ if (controller && current) {
143
+ const harness = runtimeHarness(current.profile), nativeId = scope.rootSessionId;
144
+ identity = { ...identity, harness, nativeSessionId: nativeId, providerSessionId: nativeId,
145
+ sessionId: storageSessionId({ harness_id: harness, session_id: nativeId }), parentSessionId: null, cwd: current.cwd };
146
+ }
147
+ }
148
+ return { schema_id: "dd-flow/assigned-lifecycle-admission@1", kind: "managed_assignment", invocation_id: row.id, scope,
149
+ operation, work_id: item.work_id, work_session_id: item.id, controller_id: controller?.controller_id ?? null, stage, identity,
150
+ ...(controller && current ? { controller_owner: { token: controller.owner_token, session_id: current.id } } : {}) };
151
+ }
152
+ /** A pause and its current published coordinator packet authorize its exact answer command. */
153
+ export function bindAssignedStageResume(context, row) {
154
+ const command = parsed(row.command), scope = JSON.parse(row.scope_json);
155
+ if (command?.operation !== "stage_resume" || !scope.runId)
156
+ return;
157
+ const project = context.db.get("SELECT id FROM projects WHERE root=?", [scope.projectRoot]);
158
+ const stage = commandOption(command, "stage"), work = commandOption(command, "work");
159
+ const run = project && context.db.get("SELECT index_json FROM runs WHERE project_id=? AND id=?", [project.id, scope.runId]);
160
+ const entry = run && JSON.parse(run.index_json).stage_runs.find((item) => item.stage === stage);
161
+ if (!project || !entry?.pause || !work || ![entry.pause.work_id, entry.pause.work_id.match(/^WRK-\d+/)?.[0]].includes(work))
162
+ return;
163
+ const links = context.db.all("SELECT ws.id,ws.start_receipt_json FROM work_sessions ws JOIN works w ON w.work_id=ws.work_id WHERE w.project_id=? AND w.run_id=? AND w.work_id=? AND w.status='paused' AND ws.status='running' AND ws.start_publication_status='published'", [project.id, scope.runId, entry.pause.work_id]);
164
+ if (links.length !== 1)
165
+ return;
166
+ const link = links[0];
167
+ const hashes = context.db.all("SELECT json_extract(payload_json,'$.packet_sha256') AS packet FROM audit_events WHERE project_id=? AND event_type='lifecycle.coordinator_packet' AND json_extract(payload_json,'$.work_session_id')=? AND json_extract(payload_json,'$.stage')=?", [project.id, link.id, stage]);
168
+ const startHash = JSON.parse(link.start_receipt_json).prompt_sha256;
169
+ for (const hash of new Set([...hashes.map(item => item.packet), ...(startHash ? [startHash] : [])]))
170
+ context.db.run("INSERT OR IGNORE INTO lifecycle_packet_assignments(packet_sha256,invocation_id) VALUES (?,?)", [hash, row.id]);
171
+ appendAudit(context, { projectId: project.id, eventType: "lifecycle.resume_assignment", payload: { run_id: scope.runId,
172
+ invocation_id: row.id, work_session_id: link.id, stage, pause_id: entry.pause.id, answer_file: commandOption(command, "answer-file") ?? null, generation: scope.generation } });
173
+ }
174
+ export function claimAssignedLifecycle(context, row) {
175
+ const binding = assignedLifecycleBinding(context, row);
176
+ if (!binding)
177
+ return null;
178
+ // Physical observation can spawn ps; never hold the RUN writer while doing it.
179
+ const executor = { pid: process.pid, birth: processStartedAt(process.pid), cwd: process.cwd() };
180
+ return context.db.writeTransaction(() => {
181
+ const current = assignedLifecycleBinding(context, row);
182
+ if (!current || JSON.stringify(current) !== JSON.stringify(binding))
183
+ refuse("assignment_changed");
184
+ assertTerminalSettlementUnreserved(context, row, binding.work_session_id);
185
+ const admission = { ...binding, executor: { ...executor, admitted_at: context.now() } };
186
+ if (context.db.run("UPDATE lifecycle_invocations SET status='executing',admission_json=?,updated_at=? WHERE id=? AND status IN ('issued','observed')", [JSON.stringify(admission), admission.executor.admitted_at, row.id]).changes !== 1)
187
+ return null;
188
+ let map = owned.get(context.db);
189
+ if (!map) {
190
+ map = new Map();
191
+ owned.set(context.db, map);
192
+ }
193
+ map.set(row.id, admission);
194
+ return admission;
195
+ });
196
+ }
197
+ /** Both native and assigned claims reserve the same current WorkSession before checks. SQL-only. */
198
+ export function assertTerminalSettlementUnreserved(context, row, assignedSession) {
199
+ const sessions = (attempt) => {
200
+ const command = parsed(attempt.command), scope = JSON.parse(attempt.scope_json);
201
+ if (!command || !scope.runId || !["work_finish", "work_fail", "stage_finish", "stage_pause", "stage_resume"].includes(command.operation))
202
+ return [];
203
+ const retained = attempt.admission_json && JSON.parse(attempt.admission_json).work_session_id;
204
+ if (retained)
205
+ return [retained];
206
+ const target = command.operation.startsWith("work_") ? commandPosition(command, 0) : commandOption(command, "work");
207
+ const stage = commandOption(command, "stage");
208
+ const identity = context.db.get(`SELECT he.session_id FROM hook_events he JOIN projects p ON p.id=he.project_id
209
+ JOIN lifecycle_invocations li ON li.event_key=he.event_key WHERE li.id=? AND p.root=?`, [attempt.id, scope.projectRoot]);
210
+ return context.db.all(`SELECT ws.id,w.work_id,ws.session_id,w.parent_work_id,s.current_stage
211
+ FROM work_sessions ws JOIN works w ON w.work_id=ws.work_id JOIN projects p ON p.id=w.project_id
212
+ JOIN sessions s ON s.project_id=w.project_id AND s.session_id=ws.session_id
213
+ WHERE p.root=? AND w.run_id=? AND ws.status='running' AND w.status IN ('running','paused')`, [scope.projectRoot, scope.runId])
214
+ .filter(link => target ? link.work_id === target || link.work_id.match(/^WRK-\d+/)?.[0] === target
215
+ : Boolean(stage && link.current_stage === stage && (identity ? link.session_id === identity.session_id : link.parent_work_id === null)))
216
+ .map(link => link.id);
217
+ };
218
+ const scope = JSON.parse(row.scope_json);
219
+ const targets = assignedSession ? [assignedSession] : sessions(row);
220
+ if (!targets.length)
221
+ return;
222
+ const peers = context.db.all("SELECT * FROM lifecycle_invocations WHERE id<>? AND status='executing' AND json_extract(scope_json,'$.projectRoot')=? AND json_extract(scope_json,'$.runId')=?", [row.id, scope.projectRoot, scope.runId]);
223
+ const busy = peers.find(peer => sessions(peer).some(id => targets.includes(id)));
224
+ if (busy)
225
+ throw new AppError("invocation_outcome_pending", "Another settlement of this Work Session is executing; observe that attempt", 1, { invocation_id: busy.id, effect: "no_effect", recoverable: true, reconciliation_required: true });
226
+ }
227
+ export function currentAssignedLifecycle(context) {
228
+ const id = context.env?.DD_FLOW_CURRENT_INVOCATION;
229
+ if (!id)
230
+ return null;
231
+ const admission = owned.get(context.db)?.get(id);
232
+ if (!admission || admission.executor.pid !== process.pid || admission.executor.cwd !== process.cwd())
233
+ return null;
234
+ const row = context.db.get("SELECT status,admission_json FROM lifecycle_invocations WHERE id=?", [id]);
235
+ return row?.status === "executing" && row.admission_json === JSON.stringify(admission) ? admission : null;
236
+ }
237
+ /** Result consumers can use launch facts without manufacturing a native Hook. */
238
+ export function assignedSessionIdentity(context) { return currentAssignedLifecycle(context)?.identity ?? null; }
239
+ export function lifecycleSessionIdentity(context, projectId, eventKey) {
240
+ const assigned = assignedSessionIdentity(context);
241
+ if (assigned)
242
+ return assigned;
243
+ if (!eventKey)
244
+ refuse("native_or_assigned_identity_required");
245
+ return hookSessionIdentity(context, projectId, eventKey);
246
+ }
247
+ /** Historical launch custody remains readable without a fresh native event. */
248
+ export function hasAssignedCoordinatorLaunch(context, input) {
249
+ const rows = context.db.all("SELECT payload_json FROM audit_events WHERE project_id=? AND event_type='stage.coordinator_binding' AND json_extract(payload_json,'$.run_id')=? AND json_extract(payload_json,'$.scope.stage')=? AND json_extract(payload_json,'$.work_session_id')=?", [input.projectId, input.runId, input.stage, input.workSessionId]);
250
+ return rows.some(row => {
251
+ const payload = JSON.parse(row.payload_json);
252
+ if (!payload.launch_invocation_id || payload.session_id !== input.sessionId)
253
+ return false;
254
+ const invocation = context.db.get("SELECT admission_json,status FROM lifecycle_invocations WHERE id=?", [payload.launch_invocation_id]);
255
+ if (!invocation?.admission_json || !["executing", "settled"].includes(invocation.status))
256
+ return false;
257
+ const admission = JSON.parse(invocation.admission_json);
258
+ return admission.kind === "managed_assignment" && admission.operation === "stage_start" && admission.identity.sessionId === input.sessionId
259
+ && admission.scope.runId === input.runId && admission.stage === input.stage
260
+ && context.db.get("SELECT id FROM projects WHERE root=?", [admission.scope.projectRoot])?.id === input.projectId;
261
+ });
262
+ }
263
+ export function assertAssignedStageStart(context, input) {
264
+ const assigned = currentAssignedLifecycle(context);
265
+ if (assigned) {
266
+ if (assigned.operation !== "stage_start" || assigned.scope.runId !== input.runId || assigned.stage !== input.stage || assigned.scope.projectRoot !== input.projectRoot)
267
+ refuse("stage_launch_target");
268
+ return assigned.identity;
269
+ }
270
+ if (!input.eventKey)
271
+ refuse("stage_launch_identity_missing");
272
+ return assertStageStartHookEvent(context, { ...input, eventKey: input.eventKey });
273
+ }
274
+ export function claimAssignedStageStart(context, input) {
275
+ if (currentAssignedLifecycle(context))
276
+ return assertAssignedStageStart(context, input);
277
+ if (!input.eventKey)
278
+ refuse("stage_launch_identity_missing");
279
+ return claimStageStartHookEvent(context, { ...input, eventKey: input.eventKey });
280
+ }
281
+ export function bindAssignedCoordinatorPacket(context, prompt) {
282
+ const admitted = currentAssignedLifecycle(context);
283
+ if (!admitted || !["stage_start", "stage_resume"].includes(admitted.operation))
284
+ return;
285
+ const digest = crypto.createHash("sha256").update(prompt).digest("hex");
286
+ const projectId = context.db.get("SELECT id FROM projects WHERE root=?", [admitted.scope.projectRoot])?.id;
287
+ if (!projectId)
288
+ refuse("assignment_project_missing");
289
+ const links = context.db.all("SELECT ws.id,w.project_id,ws.start_receipt_json FROM work_sessions ws JOIN works w ON w.work_id=ws.work_id WHERE w.project_id=? AND w.run_id=? AND ws.session_id=? AND ws.status='running'", [projectId, admitted.scope.runId, admitted.identity.sessionId]);
290
+ if (links.length !== 1)
291
+ refuse("coordinator_packet_owner");
292
+ const link = links[0];
293
+ // Retain original launch bytes. Later stage/resume packets are independent
294
+ // immutable publications, not replacements of a Work start receipt.
295
+ if (!link.start_receipt_json)
296
+ context.db.run("UPDATE work_sessions SET start_receipt_json=?,start_publication_status='published' WHERE id=? AND status='running' AND start_receipt_json IS NULL", [JSON.stringify({ version: 3, prompt, prompt_sha256: digest, generation: admitted.scope.generation, invocation_id: admitted.invocation_id, source: "controller_assignment" }), link.id]);
297
+ const prior = context.db.get("SELECT 1 FROM audit_events WHERE project_id=? AND event_type='lifecycle.coordinator_packet' AND json_extract(payload_json,'$.work_session_id')=? AND json_extract(payload_json,'$.packet_sha256')=?", [link.project_id, link.id, digest]);
298
+ if (!prior)
299
+ appendAudit(context, { projectId: link.project_id, eventType: "lifecycle.coordinator_packet", payload: { run_id: admitted.scope.runId,
300
+ work_session_id: link.id, packet_sha256: digest, generation: admitted.scope.generation, invocation_id: admitted.invocation_id, stage: admitted.stage,
301
+ controller_id: admitted.controller_id, controller_owner: admitted.controller_owner ?? null,
302
+ daemon_id: admitted.scope.daemonId, root_session_id: admitted.scope.rootSessionId,
303
+ stage_scope: admitted.stage ? stageGraphScope(context, link.project_id, admitted.scope.runId, admitted.stage) : null,
304
+ auxiliary_operations: ["stage_block", ...(admitted.stage === "code" ? ["work_repair_add"] : [])], prompt } });
305
+ }
306
+ /** These two coordinator mutations are scoped permits, not generic shell authority. */
307
+ export function admitAssignedAuxiliary(context, command, scope, projectRoot) {
308
+ const operation = continuationCommand(command);
309
+ if (!operation || !scope.runId || projectRoot !== scope.projectRoot)
310
+ return false;
311
+ const runTarget = operation.args.options.get("run")?.[0] ?? operation.args.positional[2];
312
+ const stage = operation.args.options.get("stage")?.[0] ?? (operation.operation === "work_repair_add" ? "code" : undefined);
313
+ if (!runTarget || !stage)
314
+ refuse("auxiliary_target_missing");
315
+ const run = context.db.get("SELECT r.id,r.project_id FROM runs r JOIN projects p ON p.id=r.project_id WHERE p.root=? AND r.id=? AND (r.id=? OR r.short_id=?)", [scope.projectRoot, scope.runId, runTarget, runTarget]);
316
+ if (!run)
317
+ refuse("auxiliary_run_changed");
318
+ const links = context.db.all(`SELECT w.work_id,a.payload_json FROM audit_events a
319
+ JOIN work_sessions ws ON ws.id=json_extract(a.payload_json,'$.work_session_id') JOIN works w ON w.work_id=ws.work_id
320
+ JOIN sessions s ON s.project_id=w.project_id AND s.session_id=ws.session_id
321
+ WHERE a.event_type='lifecycle.coordinator_packet' AND w.project_id=? AND a.project_id=w.project_id AND w.run_id=? AND ws.status='running' AND ws.start_publication_status='published' AND w.status IN ('running','paused')
322
+ AND s.current_stage=? AND json_extract(a.payload_json,'$.generation')=?`, [run.project_id, scope.runId, stage, scope.generation]);
323
+ const work = operation.args.options.get("work")?.[0];
324
+ const matches = links.filter(link => {
325
+ const packet = JSON.parse(link.payload_json);
326
+ if (packet.daemon_id !== scope.daemonId || packet.root_session_id !== scope.rootSessionId
327
+ || JSON.stringify(packet.stage_scope) !== JSON.stringify(stageGraphScope(context, run.project_id, scope.runId, stage)))
328
+ return false;
329
+ if (!packet.controller_id || !packet.controller_owner)
330
+ return false;
331
+ const controller = context.db.get("SELECT owner_token,status,state_json,generation FROM run_controllers WHERE controller_id=? AND project_id=? AND run_id=?", [packet.controller_id, run.project_id, scope.runId]);
332
+ const state = controller && JSON.parse(controller.state_json);
333
+ const active = state && state.current_session !== null ? state.sessions[state.current_session] : null;
334
+ if (!controller || controller.owner_token !== packet.controller_owner.token || controller.generation !== scope.generation
335
+ || ["completed", "cancelled", "superseded"].includes(controller.status) || !active || active.id !== packet.controller_owner.session_id || active.retired || active.stopped)
336
+ return false;
337
+ return packet.auxiliary_operations?.includes(operation.operation) && (!work || link.work_id === work || link.work_id.match(/^WRK-\d+/)?.[0] === work);
338
+ });
339
+ if (new Set(matches.map(item => item.work_id)).size !== 1)
340
+ refuse("auxiliary_assignment_missing");
341
+ return true;
342
+ }
343
+ export function assertAssignedSettlementCurrent(context, workSessionId) {
344
+ const admission = currentAssignedLifecycle(context);
345
+ if (!admission)
346
+ return;
347
+ if (workSessionId && admission.work_session_id && admission.work_session_id !== workSessionId)
348
+ refuse("settlement_session_changed");
349
+ const guard = context.db.get("SELECT g.generation,g.status FROM run_recovery_guards g JOIN projects p ON p.id=g.project_id WHERE p.root=? AND g.run_id=? ORDER BY g.generation DESC LIMIT 1", [admission.scope.projectRoot, admission.scope.runId]);
350
+ if (guard && guard.generation !== admission.scope.generation && !(guard.status === "draining" && guard.generation === admission.scope.generation + 1))
351
+ refuse("settlement_generation_changed");
352
+ if (admission.controller_id && admission.controller_owner) {
353
+ const owner = context.db.get("SELECT owner_token,generation,state_json,status FROM run_controllers WHERE controller_id=?", [admission.controller_id]);
354
+ const state = owner && JSON.parse(owner.state_json);
355
+ if (!owner || owner.owner_token !== admission.controller_owner.token || owner.generation !== admission.scope.generation
356
+ || ["completed", "cancelled", "superseded"].includes(owner.status) || !state || state.current_session === null
357
+ || state.sessions[state.current_session]?.id !== admission.controller_owner.session_id || state.sessions[state.current_session]?.retired)
358
+ refuse("settlement_controller_changed");
359
+ }
360
+ }
361
+ export function inheritAssignedPackets(context, priorId, successorId) {
362
+ context.db.run("INSERT OR IGNORE INTO lifecycle_packet_assignments(packet_sha256,invocation_id) SELECT packet_sha256,? FROM lifecycle_packet_assignments WHERE invocation_id=?", [successorId, priorId]);
363
+ }
364
+ /** Exact SQL acceptance, independent of stdout or derivative result publication. */
365
+ export function readAcceptedAssignedWork(context, invocationId) {
366
+ const rows = context.db.all("SELECT project_id,payload_json FROM audit_events WHERE event_type='lifecycle.work_settlement' AND json_extract(payload_json,'$.invocation_id')=? LIMIT 2", [invocationId]);
367
+ if (!rows.length)
368
+ return null;
369
+ if (rows.length !== 1)
370
+ throw new AppError("invocation_outcome_pending", "Assigned Work has ambiguous settlement evidence", 1, { effect: "unknown" });
371
+ const invocation = context.db.get("SELECT admission_json FROM lifecycle_invocations WHERE id=?", [invocationId]);
372
+ if (!invocation?.admission_json)
373
+ return null;
374
+ const admission = JSON.parse(invocation.admission_json);
375
+ const retained = JSON.parse(rows[0].payload_json);
376
+ if (admission.work_id !== retained.work_id || admission.work_session_id !== retained.work_session_id || admission.scope.runId !== retained.run_id)
377
+ refuse("accepted_assignment_changed");
378
+ const accepted = context.db.get("SELECT w.result,w.status FROM works w JOIN work_sessions ws ON ws.work_id=w.work_id AND ws.status=w.status JOIN projects p ON p.id=w.project_id WHERE p.root=? AND w.project_id=? AND w.run_id=? AND w.work_id=? AND ws.id=?", [admission.scope.projectRoot, rows[0].project_id, retained.run_id, retained.work_id, retained.work_session_id]);
379
+ if (!accepted || crypto.createHash("sha256").update(accepted.result).digest("hex") !== retained.result_sha256 || accepted.status !== retained.response.status)
380
+ throw new AppError("invocation_outcome_pending", "Assigned Work settlement no longer matches retained result", 1, { effect: "unknown" });
381
+ return retained.response;
382
+ }
@@ -166,11 +166,11 @@ function gitFacts(workspacePath) {
166
166
  if (!fs.existsSync(workspacePath)) {
167
167
  return { status: "missing_workspace", actual_branch: null, dirty: null, path: workspacePath };
168
168
  }
169
- const branch = spawnSync("git", ["-C", workspacePath, "rev-parse", "--abbrev-ref", "HEAD"], { encoding: "utf8" });
169
+ const branch = spawnSync("git", ["-C", workspacePath, "rev-parse", "--abbrev-ref", "HEAD"], { encoding: "utf8", timeout: 5000 });
170
170
  if (branch.status !== 0) {
171
- return { status: "not_git_checkout", actual_branch: null, dirty: null, path: workspacePath };
171
+ return { status: branch.error || branch.signal ? "observation_unavailable" : "not_git_checkout", actual_branch: null, dirty: null, path: workspacePath };
172
172
  }
173
- const status = spawnSync("git", ["-C", workspacePath, "status", "--porcelain"], { encoding: "utf8" });
173
+ const status = spawnSync("git", ["-C", workspacePath, "status", "--porcelain"], { encoding: "utf8", timeout: 5000 });
174
174
  return {
175
175
  status: "ok",
176
176
  actual_branch: branch.stdout.trim() || null,
@@ -1,27 +1,32 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { spawnSync } from "node:child_process";
4
+ import { AppError } from "../shared/errors.js";
5
+ import { prepareError } from "../cli/input-preparation.js";
6
+ import { resolveDdFlowHome } from "../storage/paths.js";
7
+ import { readSetupStatus } from "./setup.js";
4
8
  const canonRootKey = "canon.root";
5
- export function registerCanonRoot(context, input) {
9
+ export function prepareCanonRegistration(context, input) {
10
+ if (typeof input.root !== "string" || !input.root.trim())
11
+ return prepareError(new AppError("validation", "Canon root must be a non-empty path", 2));
6
12
  const resolution = resolveCanonRoot(context, { explicitRoot: input.root, allowRegistered: false });
7
13
  if (!resolution.ok || !resolution.canon) {
8
- return {
9
- ...resolution,
10
- action: "register",
11
- exit_code: 1
12
- };
14
+ return prepareError(new AppError("validation", "Canon root cannot be registered", 2, { root: input.root, blockers: resolution.blockers, candidates: resolution.candidates, bootstrap: resolution.bootstrap }));
13
15
  }
16
+ return resolution.canon;
17
+ }
18
+ export function registerCanonRoot(context, input, canon = prepareCanonRegistration(context, input)) {
14
19
  const now = context.now();
15
20
  context.db.run(`INSERT INTO runtime_config (key, value_json, created_at, updated_at)
16
21
  VALUES (?, ?, ?, ?)
17
22
  ON CONFLICT(key) DO UPDATE SET
18
23
  value_json = excluded.value_json,
19
- updated_at = excluded.updated_at`, [canonRootKey, JSON.stringify({ root: resolution.canon.root }), now, now]);
24
+ updated_at = excluded.updated_at`, [canonRootKey, JSON.stringify({ root: canon.root }), now, now]);
20
25
  return {
21
26
  ok: true,
22
27
  action: "register",
23
28
  canon: {
24
- ...resolution.canon,
29
+ ...canon,
25
30
  source: "registered"
26
31
  },
27
32
  db_path: context.db.path
@@ -38,16 +43,21 @@ export function getCanonStatus(context, input = {}) {
38
43
  export function resolveCanonRoot(context, input = {}) {
39
44
  return resolveCanonCandidates(canonCandidates(context, input));
40
45
  }
41
- /** Read only: resolve an explicit/environment/nearby canon without opening DD_FLOW_HOME. */
46
+ /** Read only: resolve canonical data without opening SQLite or running migrations. */
42
47
  export function resolveCanonRootBeforeContext(env, input = {}) {
43
48
  const candidates = [];
44
49
  if (input.explicitRoot)
45
50
  candidates.push(validateCanonCandidate("explicit", input.explicitRoot));
46
51
  else if (env.DD_MEMORYBANK)
47
52
  candidates.push(validateCanonCandidate("env", env.DD_MEMORYBANK));
48
- else
49
- for (const known of knownCanonRoots())
50
- candidates.push(validateCanonCandidate("known", known));
53
+ else {
54
+ const installed = installedCanonCandidate(resolveDdFlowHome(env));
55
+ if (installed)
56
+ candidates.push(installed);
57
+ else
58
+ for (const known of knownCanonRoots())
59
+ candidates.push(validateCanonCandidate("known", known));
60
+ }
51
61
  return resolveCanonCandidates(uniqueBy(candidates, (candidate) => `${candidate.source}:${candidate.root}`));
52
62
  }
53
63
  function resolveCanonCandidates(candidates) {
@@ -64,7 +74,7 @@ function resolveCanonCandidates(candidates) {
64
74
  const memorybankRoot = candidate.memorybank_root ?? root;
65
75
  const mbbRoot = candidate.mbb_root ?? path.join(memorybankRoot, "mbb");
66
76
  const layout = candidate.layout ?? "legacy_root";
67
- const metadata = readCanonMetadata(root, flowRoot);
77
+ const metadata = candidate.metadata ?? readCanonMetadata(root, flowRoot);
68
78
  return {
69
79
  ok: true,
70
80
  canon: {
@@ -111,6 +121,30 @@ function resolveCanonCandidates(candidates) {
111
121
  ]
112
122
  };
113
123
  }
124
+ /** Archive provenance belongs to the selected release, not an ancestor Git
125
+ * checkout. A damaged installation is not permission to select nearby code. */
126
+ function installedCanonCandidate(home) {
127
+ if (!fs.existsSync(path.join(home, "installation.json")))
128
+ return null;
129
+ const status = readSetupStatus(home), installation = status.installation;
130
+ const invalid = (root, reason) => ({
131
+ source: "installed", root, realpath: null, valid: false, blockers: [reason]
132
+ });
133
+ if (!installation || status.installation_readiness !== "installed")
134
+ return invalid(home, "Installed canonical release is degraded; reconcile setup before selecting its canon.");
135
+ const roots = fs.readdirSync(installation.canon_root);
136
+ if (roots.length !== 1)
137
+ return invalid(installation.canon_root, "Installed canonical archive has no unique root.");
138
+ const candidate = validateCanonCandidate("installed", path.join(installation.canon_root, roots[0]));
139
+ if (!candidate.valid)
140
+ return candidate;
141
+ const version = readTrimmed(path.join(candidate.root, "VERSION"));
142
+ const flowContract = readFlowContractId(candidate.flow_root);
143
+ if (version !== installation.manifest.canon.version || !flowContract)
144
+ return invalid(candidate.root, "Installed canonical metadata differs from its release selection.");
145
+ return { ...candidate, metadata: { version, commit: installation.manifest.canon.commit,
146
+ flow_contract: flowContract, status: "present", diagnostics: [] } };
147
+ }
114
148
  function canonCandidates(context, input) {
115
149
  const candidates = [];
116
150
  if (input.explicitRoot) {
@@ -126,8 +160,13 @@ function canonCandidates(context, input) {
126
160
  candidates.push(validateCanonCandidate("registered", registered.root));
127
161
  }
128
162
  }
129
- for (const known of knownCanonRoots()) {
130
- candidates.push(validateCanonCandidate("known", known));
163
+ if (!candidates.length) {
164
+ const installed = installedCanonCandidate(context.ddFlowHome);
165
+ if (installed)
166
+ return [installed];
167
+ for (const known of knownCanonRoots()) {
168
+ candidates.push(validateCanonCandidate("known", known));
169
+ }
131
170
  }
132
171
  return uniqueBy(candidates, (candidate) => `${candidate.source}:${candidate.root}`);
133
172
  }
@@ -0,0 +1,21 @@
1
+ import path from "node:path";
2
+ import { AppError } from "../shared/errors.js";
3
+ export function validateCheckEnvironment(value) {
4
+ if (value === undefined)
5
+ return undefined;
6
+ const entries = value && typeof value === "object" && !Array.isArray(value) ? Object.entries(value) : [];
7
+ if (!entries.length || entries.some(([key, selected]) => !["CODEX_HOME", "PLAYWRIGHT_BROWSERS_PATH"].includes(key)
8
+ || typeof selected !== "string" || !selected || selected.length > 4096 || selected.includes("\0") || !path.isAbsolute(selected)))
9
+ throw new AppError("invalid_check_environment", "Owned checks require absolute known resource paths", 2, { effect: "no_effect" });
10
+ return { ...value };
11
+ }
12
+ export function retainedBrowserEnvironment(environment) {
13
+ return environment.PLAYWRIGHT_BROWSERS_PATH === undefined ? undefined
14
+ : validateCheckEnvironment({ PLAYWRIGHT_BROWSERS_PATH: environment.PLAYWRIGHT_BROWSERS_PATH });
15
+ }
16
+ export function ownedCheckEnvironment(environment, requested) {
17
+ const selected = validateCheckEnvironment(requested), retained = retainedBrowserEnvironment(environment);
18
+ if (retained?.PLAYWRIGHT_BROWSERS_PATH && selected?.PLAYWRIGHT_BROWSERS_PATH && retained.PLAYWRIGHT_BROWSERS_PATH !== selected.PLAYWRIGHT_BROWSERS_PATH)
19
+ throw new AppError("invalid_check_environment", "Owned browser resource cannot be rebound", 2, { effect: "no_effect" });
20
+ return retained || selected ? { ...retained, ...selected } : undefined;
21
+ }