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

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 +965 -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 +257 -110
  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,198 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { AppError } from "../shared/errors.js";
4
+ import { publishImmutableInput } from "../storage/immutable-input.js";
5
+ import { prepareAgentOutputFile } from "../storage/agent-output.js";
6
+ import { parseLifecycleCommand } from "./lifecycle-command.js";
7
+ import { stageAttempt, stageCycle, stageWorkIds } from "./stage-work-graph.js";
8
+ import { assertRunMutationAllowed } from "./run-recovery.js";
9
+ import { appendEvent, digest } from "./run-controller-state.js";
10
+ import { retryWork } from "./work-registry.js";
11
+ import { blockStageForRuntime } from "./stage-blocker.js";
12
+ import { pauseStageForUser } from "./stage-pause.js";
13
+ /** SQL settlement provenance, never the worker's prose, distinguishes a semantic refusal. */
14
+ export function explicitWorkFailure(context, projectId, runId, workId) {
15
+ const work = context.db.get("SELECT w.status,w.result,w.parent_work_id,w.payload_json,r.run_root FROM works w JOIN runs r ON r.project_id=w.project_id AND r.id=w.run_id WHERE w.project_id=? AND w.run_id=? AND w.work_id=?", [projectId, runId, workId]);
16
+ if (!work || work.status !== "failed" || !work.parent_work_id || work.result === null || !work.run_root)
17
+ return null;
18
+ const payload = JSON.parse(work.payload_json ?? "null");
19
+ if (typeof payload?.kind === "string" && /^(memory|interactive)/.test(payload.kind))
20
+ return null;
21
+ if (!context.db.get("SELECT 1 FROM sqlite_schema WHERE name='audit_events'") || !context.db.get("SELECT 1 FROM sqlite_schema WHERE name='lifecycle_invocations'"))
22
+ return null;
23
+ const resultHash = digestBytes(work.result);
24
+ const receipts = context.db.all(`SELECT a.payload_json,l.command,l.status AS invocation_status FROM audit_events a JOIN lifecycle_invocations l ON l.id=json_extract(a.payload_json,'$.invocation_id')
25
+ WHERE a.project_id=? AND a.event_type='lifecycle.work_settlement' AND json_extract(a.payload_json,'$.run_id')=? AND json_extract(a.payload_json,'$.work_id')=? ORDER BY a.rowid DESC`, [projectId, runId, workId]);
26
+ for (const row of receipts) {
27
+ const receipt = JSON.parse(row.payload_json), parsed = parseLifecycleCommand(row.command);
28
+ if (row.invocation_status !== "settled" || parsed.kind !== "standalone" || parsed.invocation.operation !== "work_fail" || receipt.result_sha256 !== resultHash || receipt.response?.status !== "failed")
29
+ continue;
30
+ if (!context.db.get("SELECT 1 FROM work_sessions WHERE id=? AND work_id=? AND status='failed'", [receipt.work_session_id, workId]))
31
+ continue;
32
+ return { work_id: workId, work_session_id: receipt.work_session_id, parent_work_id: work.parent_work_id, result_sha256: resultHash, primary_reason: work.result, result_ref: path.join(work.run_root, "works", workId, "result.json") };
33
+ }
34
+ return null;
35
+ }
36
+ import { createHash } from "node:crypto";
37
+ const digestBytes = (text) => createHash("sha256").update(text).digest("hex");
38
+ function events(context, row, type) {
39
+ return context.db.all(`SELECT e.data_json FROM run_controller_events e JOIN run_controllers c ON c.controller_id=e.controller_id WHERE c.project_id=? AND c.run_id=? AND e.event_type=? ORDER BY e.rowid`, [row.project_id, row.run_id, type]).map(e => JSON.parse(e.data_json));
40
+ }
41
+ export function prepareWorkFailureResolution(context, row, stage, failure) {
42
+ if (!stageWorkIds(context, row.project_id, row.run_id, stage).has(failure.work_id))
43
+ throw new AppError("work_failure_scope_changed", "Failed Work no longer belongs to this Stage", 1);
44
+ const current = explicitWorkFailure(context, row.project_id, row.run_id, failure.work_id);
45
+ if (!current || current.work_session_id !== failure.work_session_id || current.result_sha256 !== failure.result_sha256)
46
+ throw new AppError("work_failure_scope_changed", "Failed Work receipt changed before resolution", 1);
47
+ const attempt = stageAttempt(context, row.project_id, row.run_id, stage), cycle = stageCycle(context, row.project_id, row.run_id, stage);
48
+ const episode = digest([row.project_id, row.run_id, stage, attempt, cycle, failure.work_id, failure.work_session_id, failure.result_sha256]);
49
+ const run = context.db.get("SELECT run_root FROM runs WHERE project_id=? AND id=?", [row.project_id, row.run_id]);
50
+ const round = events(context, row, "work_failure_action_applied").filter(e => e.episode_id === episode).length;
51
+ const root = path.join(run.run_root, "work-failure-resolutions", episode, `round-${round}`);
52
+ const resolution = { ...failure, episode_id: episode, stage, attempt, cycle, decision_file: path.join(root, "decision-input.json"), accepted_file: path.join(root, "decision.json"), diagnostic_file: path.join(root, "failure.json"),
53
+ retry_used: events(context, row, "work_failure_action_reserved").some(e => e.action === "retry" && e.work_id === failure.work_id) };
54
+ fs.mkdirSync(root, { recursive: true });
55
+ publishImmutableInput(resolution.diagnostic_file, Buffer.from(JSON.stringify({ schema_id: "work-failure-context@1", ...failure, episode_id: episode, stage, attempt, cycle, packet: path.join(run.run_root, "works", failure.work_id, "starts") }, null, 2)), "work_failure_context_changed");
56
+ if (!fs.existsSync(resolution.decision_file)) {
57
+ prepareAgentOutputFile(resolution.decision_file);
58
+ fs.writeFileSync(resolution.decision_file, "", { flag: "wx", mode: 0o600 });
59
+ }
60
+ return resolution;
61
+ }
62
+ const text = (value) => typeof value === "string" && value.trim().length > 0;
63
+ export function readFailureDecision(resolution) {
64
+ const file = fs.existsSync(resolution.accepted_file) ? resolution.accepted_file : resolution.decision_file;
65
+ const stat = fs.lstatSync(file);
66
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 1024 * 1024)
67
+ throw new AppError("work_failure_decision_invalid", "Expected a regular decision JSON file", 2);
68
+ let value;
69
+ try {
70
+ value = JSON.parse(fs.readFileSync(file, "utf8"));
71
+ }
72
+ catch {
73
+ throw new AppError("work_failure_decision_invalid", "Write one complete decision JSON object", 2);
74
+ }
75
+ const keys = ["schema_id", "episode_id", "action", "reason", "evidence_refs", "correction", "blocker", "question"];
76
+ if (!value || Array.isArray(value) || typeof value !== "object" || Object.keys(value).some(k => !keys.includes(k)) || value.schema_id !== "work-failure-decision@1" || value.episode_id !== resolution.episode_id || !["retry", "block", "pause", "fail"].includes(value.action) || !text(value.reason) || !Array.isArray(value.evidence_refs) || !value.evidence_refs.length || !value.evidence_refs.every(text)
77
+ || value.action === "retry" && !text(value.correction) || value.action === "pause" && !text(value.question)
78
+ || value.action === "block" && (!value.blocker || !["engine", "harness", "environment"].includes(value.blocker.kind) || !text(value.blocker.code) || !text(value.blocker.summary) || typeof value.blocker.retryable !== "boolean" || Object.keys(value.blocker).some(k => !["kind", "code", "summary", "retryable"].includes(k)))
79
+ || value.action !== "retry" && value.correction !== undefined || value.action !== "pause" && value.question !== undefined || value.action !== "block" && value.blocker !== undefined)
80
+ throw new AppError("work_failure_decision_invalid", "Decision must match its episode and selected action", 2, { episode_id: resolution.episode_id });
81
+ return value;
82
+ }
83
+ export function failureDecisionReady(resolution) { try {
84
+ readFailureDecision(resolution);
85
+ return true;
86
+ }
87
+ catch {
88
+ return false;
89
+ } }
90
+ export function workFailureResolutionPrompt(resolution, diagnostic) {
91
+ return [`Resolve only the retained explicit worker refusal in ${resolution.diagnostic_file}. Read that complete file and its Work packet/results.`,
92
+ "Current implementation is a baseline, not a requirement. Necessary project-local cross-layer corrections are allowed within accepted scope; planned write areas are hints. A worker-authored stop condition cannot silently cancel accepted intent. Do not edit product files, call lifecycle commands, spawn children or run checks in this decision Turn.",
93
+ `Write the decision to this precreated absolute file: ${resolution.decision_file}. No other writes. Return after writing it.`,
94
+ `Use schema_id=work-failure-decision@1, episode_id=${resolution.episode_id}, action=retry|block|pause|fail, nonempty reason and evidence_refs[]. For retry include concrete correction; for block include blocker {kind:engine|harness|environment,code,summary,retryable:boolean}; for pause include question. No extra fields.`,
95
+ resolution.retry_used ? "The one automatic corrective attempt has already been consumed. Select block/pause/fail; another retry cannot be applied automatically." : "Select retry if the Work can be completed in accepted scope; a fresh worker receives your correction. Select pause only for genuinely missing user intent, block for a proven technical dependency, fail only for an explained terminal outcome.",
96
+ "An unsupported exact browser key sequence does not prove all UI work is impossible and selectOption is not keyboard evidence. Preserve unverified mandatory criteria and original requirements.", diagnostic ? `Correct only the rejected decision: ${diagnostic}` : ""].filter(Boolean).join("\n\n");
97
+ }
98
+ export function acceptFailureDecision(context, row, resolution, assertOwner) {
99
+ assertOwner();
100
+ const decision = readFailureDecision(resolution), bytes = Buffer.from(JSON.stringify(decision));
101
+ publishImmutableInput(resolution.accepted_file, bytes, "work_failure_decision_changed");
102
+ context.db.writeTransaction(() => { assertOwner(); if (!events(context, row, "work_failure_decision_accepted").some(e => e.decision_ref === resolution.accepted_file))
103
+ appendEvent(context, row.controller_id, "work_failure_decision_accepted", { episode_id: resolution.episode_id, work_id: resolution.work_id, decision_ref: resolution.accepted_file, decision }); });
104
+ return decision;
105
+ }
106
+ export function workFailureDiagnostic(resolution, decision) {
107
+ return { source: "explicit_work_failure", episode_id: resolution.episode_id, work_id: resolution.work_id, work_session_id: resolution.work_session_id, result_ref: resolution.diagnostic_file, primary_reason: resolution.primary_reason, ...(decision ? { disposition: decision } : {}) };
108
+ }
109
+ /** Repair file-before-event and mutation-before-ack crash windows before HITL delivery. */
110
+ export async function reconcilePendingWorkFailure(context, row, state, continuationKind, projectRoot, assertOwner, writerSettled) {
111
+ const resolution = state.work_failure;
112
+ if (!resolution || resolution.deferred || !fs.existsSync(resolution.accepted_file) || continuationKind === "terminal")
113
+ return "none";
114
+ const session = state.current_session === null ? undefined : state.sessions[state.current_session];
115
+ if (!session)
116
+ throw new AppError("work_failure_scope_changed", "Failure resolution lost its coordinator", 1);
117
+ if (!await writerSettled(session))
118
+ return "waiting";
119
+ const decision = acceptFailureDecision(context, row, resolution, assertOwner);
120
+ applyWorkFailureDecision(context, row, resolution, decision, projectRoot, assertOwner);
121
+ delete state.work_failure;
122
+ state.last_continuation = null;
123
+ return "applied";
124
+ }
125
+ /** Reserve first; a committed retry is recovered through its start authority, never replayed blindly. */
126
+ export function applyWorkFailureDecision(context, row, resolution, decision, projectRoot, assertOwner) {
127
+ assertOwner();
128
+ assertRunMutationAllowed(context, row.project_id, row.run_id, row.generation);
129
+ const index = JSON.parse(context.db.get("SELECT index_json FROM runs WHERE project_id=? AND id=?", [row.project_id, row.run_id])?.index_json ?? "{}");
130
+ if (resolution.stage !== index.current_stage
131
+ || resolution.attempt !== stageAttempt(context, row.project_id, row.run_id, resolution.stage) || resolution.cycle !== stageCycle(context, row.project_id, row.run_id, resolution.stage)
132
+ || !stageWorkIds(context, row.project_id, row.run_id, resolution.stage).has(resolution.work_id))
133
+ throw new AppError("work_failure_scope_changed", "Failure resolution belongs to a stale Stage attempt", 1);
134
+ const applied = events(context, row, "work_failure_action_applied").find(e => e.decision_ref === resolution.accepted_file);
135
+ if (applied)
136
+ return applied;
137
+ const reserved = events(context, row, "work_failure_action_reserved").find(e => e.decision_ref === resolution.accepted_file);
138
+ const current = context.db.get("SELECT status,current_start_invocation_id FROM works WHERE project_id=? AND run_id=? AND work_id=?", [row.project_id, row.run_id, resolution.work_id]);
139
+ if (!current)
140
+ throw new AppError("work_failure_scope_changed", "Work disappeared before resolution", 1);
141
+ let action = decision.action;
142
+ const used = events(context, row, "work_failure_action_reserved").some(e => e.action === "retry" && e.work_id === resolution.work_id && e.decision_ref !== resolution.accepted_file);
143
+ const retainedDecision = events(context, row, "work_failure_decision_accepted").find(e => e.decision_ref === resolution.accepted_file);
144
+ if (!retainedDecision || JSON.stringify(retainedDecision.decision) !== JSON.stringify(decision))
145
+ throw new AppError("work_failure_scope_changed", "Failure decision was not accepted or changed after acceptance", 1);
146
+ const exhausted = action === "retry" && used;
147
+ if (exhausted)
148
+ action = "block";
149
+ if (!reserved) {
150
+ if (current.status !== "failed" || explicitWorkFailure(context, row.project_id, row.run_id, resolution.work_id)?.work_session_id !== resolution.work_session_id)
151
+ throw new AppError("work_failure_scope_changed", "Failure changed before action reservation", 1);
152
+ context.db.writeTransaction(() => { assertOwner(); appendEvent(context, row.controller_id, "work_failure_action_reserved", { episode_id: resolution.episode_id, work_id: resolution.work_id, work_session_id: resolution.work_session_id, action, decision_ref: resolution.accepted_file }); });
153
+ }
154
+ else if (reserved.action !== action)
155
+ throw new AppError("work_failure_scope_changed", "Reserved failure action differs", 1);
156
+ let receipt;
157
+ if (action === "retry") {
158
+ receipt = retryWork(context, resolution.work_id, decision.reason, { episode_id: resolution.episode_id, decision_ref: resolution.accepted_file, correction: decision.correction, failed_result_sha256: resolution.result_sha256 });
159
+ }
160
+ else if (action === "fail")
161
+ throw new AppError("work_failure_unresolved", decision.reason, 1, workFailureDiagnostic(resolution, decision));
162
+ else {
163
+ const coordinator = context.db.get("SELECT status FROM works WHERE project_id=? AND run_id=? AND work_id=?", [row.project_id, row.run_id, resolution.parent_work_id]);
164
+ const blocker = exhausted ? { kind: "engine", code: "work_resolution_exhausted", summary: JSON.stringify(workFailureDiagnostic(resolution, decision)), retryable: false } : decision.blocker;
165
+ const boundBlocker = blocker ? { ...blocker, summary: `${blocker.summary}\n[work-failure:${resolution.episode_id}:${digest(resolution.accepted_file)}]` } : undefined;
166
+ if (coordinator?.status === "paused" && reserved) {
167
+ const stage = index.stage_runs?.find((s) => s.stage === resolution.stage);
168
+ const matches = action === "pause" ? stage?.pause?.work_id === resolution.parent_work_id && typeof stage.pause.question_path === "string" && fs.readFileSync(stage.pause.question_path, "utf8") === decision.question
169
+ : stage?.blocker?.work_id === resolution.parent_work_id && stage.blocker.code === boundBlocker?.code && stage.blocker.kind === boundBlocker?.kind && stage.blocker.summary === boundBlocker?.summary;
170
+ if (!matches)
171
+ throw new AppError("work_failure_scope_changed", "Coordinator pause belongs to another failure action", 1);
172
+ receipt = { ok: true, reconciled: true, outcome: action === "pause" ? "paused" : "blocked", run_id: row.run_id, stage: resolution.stage, work_id: resolution.parent_work_id, ...(boundBlocker ? { blocker: boundBlocker } : {}) };
173
+ }
174
+ else {
175
+ if (coordinator?.status !== "running")
176
+ throw new AppError("work_failure_scope_changed", "Failure resolution needs the running coordinator Work", 1);
177
+ const scope = { projectRoot, runId: row.run_id, stage: resolution.stage, workId: resolution.parent_work_id };
178
+ receipt = action === "pause" ? pauseStageForUser(context, { ...scope, question: decision.question }) : blockStageForRuntime(context, { ...scope, ...boundBlocker });
179
+ }
180
+ }
181
+ const outcome = { episode_id: resolution.episode_id, decision_ref: resolution.accepted_file, stage: resolution.stage, attempt: resolution.attempt, cycle: resolution.cycle, work_id: resolution.work_id, work_session_id: resolution.work_session_id, action, receipt };
182
+ context.db.writeTransaction(() => { assertOwner(); appendEvent(context, row.controller_id, "work_failure_action_applied", outcome); });
183
+ return outcome;
184
+ }
185
+ /** Match only this current bound block; an old unrelated pause must not be hidden. */
186
+ export function workFailureBlockActive(context, row, index) {
187
+ const stage = index.current_stage;
188
+ const blocker = index.stage_runs?.find(s => s.stage === stage)?.blocker;
189
+ if (!stage || !blocker)
190
+ return false;
191
+ return events(context, row, "work_failure_action_applied").some(e => {
192
+ const receipt = e.receipt;
193
+ if (!receipt)
194
+ return false;
195
+ return e.action === "block" && e.stage === stage && e.attempt === stageAttempt(context, row.project_id, row.run_id, stage) && e.cycle === stageCycle(context, row.project_id, row.run_id, stage)
196
+ && receipt?.work_id === blocker.work_id && receipt.blocker?.summary === blocker.summary && receipt.blocker?.code === blocker.code && receipt.blocker?.kind === blocker.kind;
197
+ });
198
+ }
@@ -1,10 +1,12 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { spawnSync } from "node:child_process";
3
+ import { commandResult } from '../harness-runtime/lib/process-json.mjs';
4
+ import { SETUP_STARTUP_MS } from '../harness-runtime/lib/setup-progress.mjs';
4
5
  import { isActiveProtocolStatus, isActiveQueueStatus, isQueueHistoryStatus } from "../domain/contracts.js";
5
6
  import { AppError } from "../shared/errors.js";
6
- import { ensureDir, resolveProjectRoot } from "../storage/paths.js";
7
- import { dashboardMarkdownPath, globalDashboardHtmlPath, globalDashboardJsonPath, globalDashboardMarkdownPath, projectDashboardHtmlPath, projectDashboardJsonPath, projectSummaryJsonPath, protocolDashboardHtmlPath, protocolDashboardJsonPath, readProjectConfig } from "./config.js";
7
+ import { prepareOutputFile } from "../cli/input-preparation.js";
8
+ import { ensureDir, resolveProjectRoot, resolveProtocolPlanPath } from "../storage/paths.js";
9
+ import { dashboardMarkdownPath, globalDashboardHtmlPath, globalDashboardJsonPath, globalDashboardMarkdownPath, projectDashboardHtmlPath, projectDashboardJsonPath, projectDashboardDir, projectSummaryJsonPath, protocolDashboardHtmlPath, protocolDashboardJsonPath, readProjectConfig } from "./config.js";
8
10
  import { queueForProject } from "./merge-queue.js";
9
11
  import { publishProjectSummary } from "./project-summary.js";
10
12
  import { requireProjectByRoot } from "./projects.js";
@@ -13,70 +15,82 @@ import { activeFlowSessionsForProject } from "./sessions.js";
13
15
  import { usageForRun } from "./usage.js";
14
16
  import { normalizeProtocolLifecycle } from "./protocol-lifecycle.js";
15
17
  import { planSummary, planWithProgress } from "./plan-runtime.js";
16
- export function getCmuxStatus(context, input) {
18
+ export async function getCmuxStatus(context, input) {
17
19
  const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
18
- return { ok: true, project_root: project.root, cmux: detectCmux(context) };
20
+ return { ok: true, project_root: project.root, cmux: await detectCmux(context) };
19
21
  }
20
- export function renderDashboard(context, input) {
22
+ export function prepareDashboardRender(context, input) {
21
23
  const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
24
+ if (projectRecoveryGuarded(context, project.id))
25
+ throw new AppError("run_recovery_guarded", "Project dashboard is frozen while its RUN is retained for recovery", 1);
22
26
  const format = parseDashboardFormat(input.format);
27
+ if (input.protocol)
28
+ requireProtocol(context, input.protocol, project.id);
29
+ const config = readProjectConfig(context, project.id);
30
+ const output = input.output
31
+ ? path.resolve(project.root, input.output)
32
+ : format === "html"
33
+ ? input.protocol ? protocolDashboardHtmlPath(context, project.id, input.protocol) : projectDashboardHtmlPath(context, project.id)
34
+ : dashboardMarkdownPath(project.root, config);
35
+ prepareOutputFile(output);
36
+ if (format === "html")
37
+ prepareOutputFile(input.protocol ? protocolDashboardJsonPath(context, project.id, input.protocol) : projectDashboardJsonPath(context, project.id));
38
+ return { project, format, output };
39
+ }
40
+ export function renderDashboard(context, input) {
41
+ const { project, format, output } = prepareDashboardRender(context, input);
23
42
  if (format === "html") {
24
43
  if (input.protocol) {
25
44
  return renderProtocolDashboardHtml(context, project, input.protocol, input.output);
26
45
  }
27
46
  return renderProjectDashboardHtml(context, project, input.output);
28
47
  }
29
- const config = readProjectConfig(context, project.id);
30
- const output = input.output
31
- ? path.resolve(path.isAbsolute(input.output) ? input.output : path.join(project.root, input.output))
32
- : dashboardMarkdownPath(project.root, config);
33
48
  const markdown = renderProjectDashboardMarkdown(context, project, output);
34
49
  writeMarkdown(output, markdown);
35
50
  return { ok: true, project_root: project.root, dashboard: { path: output, bytes: Buffer.byteLength(markdown) } };
36
51
  }
37
- export function renderGlobalDashboard(context, input = {}) {
52
+ export function prepareGlobalDashboardRender(context, input = {}) {
38
53
  const format = parseDashboardFormat(input.format);
54
+ const output = input.output ? path.resolve(input.output) : format === "html" ? globalDashboardHtmlPath(context) : globalDashboardMarkdownPath(context);
55
+ prepareOutputFile(output);
56
+ if (format === "html")
57
+ prepareOutputFile(globalDashboardJsonPath(context));
58
+ return { format, output };
59
+ }
60
+ export function renderGlobalDashboard(context, input = {}) {
61
+ const { format, output } = prepareGlobalDashboardRender(context, input);
39
62
  if (format === "html") {
40
63
  return renderGlobalDashboardHtml(context, input.output);
41
64
  }
42
- const output = input.output
43
- ? path.resolve(input.output)
44
- : globalDashboardMarkdownPath(context);
45
65
  const markdown = renderGlobalDashboardMarkdown(context, output);
46
66
  writeMarkdown(output, markdown);
47
67
  return { ok: true, dashboard: { path: output, bytes: Buffer.byteLength(markdown) } };
48
68
  }
49
- export function openDashboard(context, input) {
69
+ export async function openDashboard(context, input) {
70
+ prepareDashboardOptions(input);
50
71
  const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
51
72
  const config = readProjectConfig(context, project.id);
52
73
  const format = parseDashboardFormat(input.format, "html");
53
- if (input.viewer && input.viewer !== "cmux") {
54
- throw new AppError("validation", "--viewer must be cmux", 2);
55
- }
56
74
  const dashboardPath = format === "html" ? projectDashboardHtmlPath(context, project.id) : dashboardMarkdownPath(project.root, config);
57
75
  return {
58
76
  ok: true,
59
77
  project_root: project.root,
60
78
  dashboard: { path: dashboardPath },
61
- open: openCmuxDashboard(context, project.root, dashboardPath, format)
79
+ open: await openCmuxDashboard(context, project.root, dashboardPath, format)
62
80
  };
63
81
  }
64
- export function openGlobalDashboard(context, input = {}) {
65
- if (input.viewer && input.viewer !== "cmux") {
66
- throw new AppError("validation", "--viewer must be cmux", 2);
67
- }
82
+ export async function openGlobalDashboard(context, input = {}) {
83
+ prepareDashboardOptions(input);
68
84
  const format = parseDashboardFormat(input.format, "html");
69
85
  const rendered = renderGlobalDashboard(context, { format });
70
86
  return {
71
87
  ok: true,
72
88
  dashboard: rendered.dashboard,
73
- open: openDashboardPath(context, rendered.dashboard.path, format)
89
+ open: await openDashboardPath(context, rendered.dashboard.path, format)
74
90
  };
75
91
  }
76
- export function openProtocolDashboard(context, input) {
77
- if (input.viewer && input.viewer !== "cmux") {
78
- throw new AppError("validation", "--viewer must be cmux", 2);
79
- }
92
+ export async function openProtocolDashboard(context, input) {
93
+ prepareDashboardOptions(input);
80
94
  const format = parseDashboardFormat(input.format, "html");
81
95
  const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
82
96
  if (format !== "html") {
@@ -90,17 +104,43 @@ export function openProtocolDashboard(context, input) {
90
104
  project_root: project.root,
91
105
  protocol_id: input.protocol,
92
106
  dashboard: rendered.dashboard,
93
- open: openCmuxDashboard(context, project.root, rendered.dashboard.path, format)
107
+ open: await openCmuxDashboard(context, project.root, rendered.dashboard.path, format)
94
108
  };
95
109
  }
96
- export function refreshDashboard(context, input) {
110
+ export function prepareDashboardRefresh(context, input) {
111
+ prepareDashboardOptions(input);
97
112
  const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
98
113
  const config = readProjectConfig(context, project.id);
99
114
  const format = parseDashboardFormat(input.format);
100
115
  const openMode = input.open ?? "auto";
101
- if (!["auto", "true", "false"].includes(openMode)) {
102
- throw new AppError("validation", "--open must be auto, true, or false", 2);
116
+ if (config.dashboard.project) {
117
+ if (projectRecoveryGuarded(context, project.id))
118
+ throw new AppError("run_recovery_guarded", "Project dashboard is frozen while its RUN is retained for recovery", 1);
119
+ if (input.protocol)
120
+ requireProtocol(context, input.protocol, project.id);
121
+ prepareRefreshOutputs(context, project, config, format, input.protocol);
103
122
  }
123
+ return { project, config, format, openMode };
124
+ }
125
+ function prepareRefreshOutputs(context, project, config, format, protocol) {
126
+ if (config.dashboard.project) {
127
+ if (!protocol)
128
+ prepareOutputFile(projectSummaryJsonPath(context, project.id));
129
+ if (format === "html") {
130
+ prepareOutputFile(protocol ? protocolDashboardHtmlPath(context, project.id, protocol) : projectDashboardHtmlPath(context, project.id));
131
+ prepareOutputFile(protocol ? protocolDashboardJsonPath(context, project.id, protocol) : projectDashboardJsonPath(context, project.id));
132
+ }
133
+ else
134
+ prepareOutputFile(dashboardMarkdownPath(project.root, config));
135
+ }
136
+ if (config.dashboard.global) {
137
+ prepareOutputFile(format === "html" ? globalDashboardHtmlPath(context) : globalDashboardMarkdownPath(context, config));
138
+ if (format === "html")
139
+ prepareOutputFile(globalDashboardJsonPath(context));
140
+ }
141
+ }
142
+ export async function refreshDashboard(context, input) {
143
+ const { project, config, format, openMode } = prepareDashboardRefresh(context, input);
104
144
  if (!config.dashboard.project) {
105
145
  return {
106
146
  ok: true,
@@ -124,7 +164,7 @@ export function refreshDashboard(context, input) {
124
164
  dashboard: rendered.dashboard,
125
165
  project_summary: projectSummary,
126
166
  global_dashboard: global.dashboard,
127
- open: shouldOpen ? openCmuxDashboard(context, project.root, rendered.dashboard.path, format) : { ok: true, skipped: true, reason: "open_disabled" }
167
+ open: shouldOpen ? await openCmuxDashboard(context, project.root, rendered.dashboard.path, format) : { ok: true, skipped: true, reason: "open_disabled" }
128
168
  };
129
169
  }
130
170
  export function refreshGlobalDashboard(context, input = {}) {
@@ -143,8 +183,9 @@ export function refreshAllDashboards(context, input = {}) {
143
183
  return { ok: true, project_id: project.id, project_root: project.root, skipped: true, reason: "dashboard_project_disabled" };
144
184
  }
145
185
  try {
146
- const projectSummary = publishProjectSummary(context, { project });
186
+ prepareRefreshOutputs(context, project, { ...config, dashboard: { ...config.dashboard, global: false } }, format);
147
187
  const rendered = renderDashboard(context, { projectRoot: project.root, format });
188
+ const projectSummary = publishProjectSummary(context, { project });
148
189
  return { ok: true, project_id: project.id, project_root: project.root, dashboard: rendered.dashboard, project_summary: projectSummary };
149
190
  }
150
191
  catch (error) {
@@ -170,10 +211,22 @@ export function refreshAllDashboards(context, input = {}) {
170
211
  }
171
212
  export function autoRefreshDashboards(context, input) {
172
213
  const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
173
- const config = readProjectConfig(context, project.id);
214
+ // Hooks and usage ingestion continue to record receipts after capture.
215
+ // Their derived timestamp must not mutate the captured workspace.
216
+ if (projectRecoveryGuarded(context, project.id))
217
+ return { ok: true, skipped: true, reason: "run_recovery_guarded" };
218
+ const configured = readProjectConfig(context, project.id);
219
+ // Automatic observation must not change a memory/diagnostic baseline or
220
+ // invalidate accepted delivery checks by rewriting workspace projections.
221
+ // Keep projections in Home; do not hide runtime-created paths in Git or
222
+ // weaken source preservation by excluding user-owned .tasks directories.
223
+ const initializing = context.db.get("SELECT 1 FROM runs WHERE project_id=? AND (flow_kind IN ('mb-init','mb-upgrade','mb-fix','mb-audit','project-review','review-fix','interactive') OR flow_kind='mb-distill' AND json_extract(index_json,'$.execution_bundle.flow_id')='mb-distill' OR flow_kind IN ('release','deploy','publish') AND json_extract(index_json,'$.execution_bundle.flow_id')=flow_kind) AND (id=? OR status IN ('created','running','paused','waiting_for_user','blocked')) LIMIT 1", [project.id, input.runId ?? null]);
224
+ const config = initializing ? { ...configured, dashboard: { ...configured.dashboard,
225
+ markdown_path: path.join(projectDashboardDir(context.ddFlowHome, project.id), "project-dashboard.md") } } : configured;
174
226
  if (!config.dashboard.auto_refresh) {
175
227
  return { ok: true, skipped: true, reason: "dashboard_auto_refresh_disabled" };
176
228
  }
229
+ prepareRefreshOutputs(context, project, config, "markdown");
177
230
  const result = { ok: true, project_root: project.root };
178
231
  if (config.dashboard.project) {
179
232
  publishProjectSummary(context, { project });
@@ -196,6 +249,9 @@ export function autoRefreshDashboards(context, input) {
196
249
  }
197
250
  return result;
198
251
  }
252
+ function projectRecoveryGuarded(context, projectId) {
253
+ return Boolean(context.db.get("SELECT 1 FROM run_recovery_guards WHERE project_id = ? AND status IN ('draining', 'sealed', 'resuming') LIMIT 1", [projectId]));
254
+ }
199
255
  export function dashboardSummary(context, projectId, projectRoot) {
200
256
  const config = readProjectConfig(context, projectId);
201
257
  return {
@@ -221,13 +277,13 @@ export function dashboardData(context, input) {
221
277
  }
222
278
  return { ok: true, dashboard: buildProjectDashboardData(context, project, projectDashboardHtmlPath(context, project.id)) };
223
279
  }
224
- function openCmuxDashboard(context, projectRoot, dashboardPath, format = "markdown") {
280
+ async function openCmuxDashboard(context, projectRoot, dashboardPath, format = "markdown") {
225
281
  const project = requireProjectByRoot(context, resolveProjectRoot(projectRoot));
226
282
  const config = readProjectConfig(context, project.id);
227
283
  if (config.integrations.cmux.mode === "off") {
228
284
  return { ok: true, skipped: true, reason: "cmux_off" };
229
285
  }
230
- const cmux = detectCmux(context);
286
+ const cmux = await detectCmux(context);
231
287
  if (!cmux.available) {
232
288
  if (config.integrations.cmux.mode === "required") {
233
289
  throw new AppError("cmux_unavailable", "cmux is required by project config but is unavailable", 1, { cmux });
@@ -238,20 +294,20 @@ function openCmuxDashboard(context, projectRoot, dashboardPath, format = "markdo
238
294
  return { ok: true, opened: false, dry_run: true, command: cmuxOpenCommand(format, dashboardPath) };
239
295
  }
240
296
  const command = cmuxOpenCommand(format, dashboardPath);
241
- const result = spawnSync(command[0], command.slice(1), { encoding: "utf8" });
242
- if (result.status !== 0) {
297
+ const result = await commandResult(command[0], command.slice(1), { startupMs: SETUP_STARTUP_MS });
298
+ if (result.exit_code !== 0) {
243
299
  if (config.integrations.cmux.mode === "required") {
244
300
  throw new AppError("cmux_open_failed", "cmux markdown open failed", 1, {
245
- status: result.status,
301
+ status: result.exit_code,
246
302
  stderr: result.stderr.trim()
247
303
  });
248
304
  }
249
- return { ok: true, skipped: true, reason: "cmux_open_failed", status: result.status, stderr: result.stderr.trim() };
305
+ return { ok: true, skipped: true, reason: "cmux_open_failed", status: result.exit_code, stderr: result.stderr.trim() };
250
306
  }
251
307
  return { ok: true, opened: true, command };
252
308
  }
253
- function openDashboardPath(context, dashboardPath, format) {
254
- const cmux = detectCmux(context);
309
+ async function openDashboardPath(context, dashboardPath, format) {
310
+ const cmux = await detectCmux(context);
255
311
  if (!cmux.available) {
256
312
  return { ok: true, skipped: true, reason: "cmux_unavailable", cmux };
257
313
  }
@@ -259,9 +315,9 @@ function openDashboardPath(context, dashboardPath, format) {
259
315
  return { ok: true, opened: false, dry_run: true, command: cmuxOpenCommand(format, dashboardPath) };
260
316
  }
261
317
  const command = cmuxOpenCommand(format, dashboardPath);
262
- const result = spawnSync(command[0], command.slice(1), { encoding: "utf8" });
263
- if (result.status !== 0) {
264
- return { ok: true, skipped: true, reason: "cmux_open_failed", status: result.status, stderr: result.stderr.trim() };
318
+ const result = await commandResult(command[0], command.slice(1), { startupMs: SETUP_STARTUP_MS });
319
+ if (result.exit_code !== 0) {
320
+ return { ok: true, skipped: true, reason: "cmux_open_failed", status: result.exit_code, stderr: result.stderr.trim() };
265
321
  }
266
322
  return { ok: true, opened: true, command };
267
323
  }
@@ -270,17 +326,31 @@ function cmuxOpenCommand(format, dashboardPath) {
270
326
  ? ["cmux", "browser", "open", pathToFileUrl(dashboardPath)]
271
327
  : ["cmux", "markdown", "open", dashboardPath];
272
328
  }
273
- function detectCmux(context) {
329
+ async function detectCmux(context) {
274
330
  if (context.env.DD_FLOW_CMUX_AVAILABLE === "true") {
275
331
  return { available: true, source: "env" };
276
332
  }
277
333
  if (context.env.DD_FLOW_CMUX_AVAILABLE === "false") {
278
334
  return { available: false, source: "env", reason: "forced_unavailable" };
279
335
  }
280
- const result = spawnSync("cmux", ["--version"], { encoding: "utf8" });
281
- return result.status === 0
336
+ let result;
337
+ try {
338
+ result = await commandResult("cmux", ["--version"], { startupMs: SETUP_STARTUP_MS, phase: 'native-version' });
339
+ }
340
+ catch (error) {
341
+ return { available: false, source: 'path', reason: error instanceof Error ? error.message : String(error) };
342
+ }
343
+ return result.exit_code === 0
282
344
  ? { available: true, source: "path", version: result.stdout.trim() }
283
- : { available: false, source: "path", reason: result.error?.message ?? result.stderr.trim() ?? "cmux not found" };
345
+ : { available: false, source: "path", reason: result.stderr.trim() || "cmux not found" };
346
+ }
347
+ export function prepareDashboardOptions(input) {
348
+ if (input.format !== undefined)
349
+ parseDashboardFormat(input.format);
350
+ if (input.viewer !== undefined && input.viewer !== "cmux")
351
+ throw new AppError("validation", "--viewer must be cmux", 2);
352
+ if (input.open !== undefined && !["auto", "true", "false"].includes(input.open))
353
+ throw new AppError("validation", "--open must be auto, true, or false", 2);
284
354
  }
285
355
  function parseDashboardFormat(value, defaultFormat = "markdown") {
286
356
  const format = value ?? defaultFormat;
@@ -294,15 +364,18 @@ function renderProjectDashboardHtml(context, project, output) {
294
364
  ? path.resolve(path.isAbsolute(output) ? output : path.join(project.root, output))
295
365
  : projectDashboardHtmlPath(context, project.id);
296
366
  const jsonPath = projectDashboardJsonPath(context, project.id);
367
+ prepareOutputFile(htmlPath);
368
+ prepareOutputFile(jsonPath);
297
369
  const data = buildProjectDashboardData(context, project, htmlPath);
298
370
  const html = renderDashboardHtmlPage(data);
299
- writeJsonFile(jsonPath, data);
300
- writeTextFile(htmlPath, html);
301
371
  const protocolCards = Array.isArray(data.protocol_cards) ? data.protocol_cards : [];
302
- const protocolPages = protocolCards
372
+ const preparedPages = protocolCards
303
373
  .filter((card) => card.generate_page !== false)
304
374
  .slice(0, 24)
305
- .map((card) => renderProtocolDashboardHtml(context, project, String(card.id)))
375
+ .map((card) => prepareProtocolDashboardHtml(context, project, String(card.id)));
376
+ writeJsonFile(jsonPath, data);
377
+ writeTextFile(htmlPath, html);
378
+ const protocolPages = preparedPages.map(writeProtocolDashboardHtml)
306
379
  .map((result) => ({
307
380
  id: String(result.protocol_id),
308
381
  path: result.dashboard.path,
@@ -321,12 +394,23 @@ function renderProjectDashboardHtml(context, project, output) {
321
394
  };
322
395
  }
323
396
  function renderProtocolDashboardHtml(context, project, protocolId, output) {
397
+ return writeProtocolDashboardHtml(prepareProtocolDashboardHtml(context, project, protocolId, output));
398
+ }
399
+ function prepareProtocolDashboardHtml(context, project, protocolId, output) {
400
+ if (projectRecoveryGuarded(context, project.id))
401
+ throw new AppError("run_recovery_guarded", "Project dashboard is frozen while its RUN is retained for recovery", 1);
324
402
  const htmlPath = output
325
403
  ? path.resolve(path.isAbsolute(output) ? output : path.join(project.root, output))
326
404
  : protocolDashboardHtmlPath(context, project.id, protocolId);
327
405
  const jsonPath = protocolDashboardJsonPath(context, project.id, protocolId);
406
+ prepareOutputFile(htmlPath);
407
+ prepareOutputFile(jsonPath);
328
408
  const data = buildProtocolDashboardData(context, project, protocolId, htmlPath);
329
409
  const html = renderDashboardHtmlPage(data);
410
+ return { project, protocolId, htmlPath, jsonPath, data, html };
411
+ }
412
+ function writeProtocolDashboardHtml(prepared) {
413
+ const { project, protocolId, htmlPath, jsonPath, data, html } = prepared;
330
414
  writeJsonFile(jsonPath, data);
331
415
  writeTextFile(htmlPath, html);
332
416
  return {
@@ -344,6 +428,8 @@ function renderProtocolDashboardHtml(context, project, protocolId, output) {
344
428
  function renderGlobalDashboardHtml(context, output) {
345
429
  const htmlPath = output ? path.resolve(output) : globalDashboardHtmlPath(context);
346
430
  const jsonPath = globalDashboardJsonPath(context);
431
+ prepareOutputFile(htmlPath);
432
+ prepareOutputFile(jsonPath);
347
433
  const data = buildGlobalDashboardData(context, htmlPath);
348
434
  const html = renderDashboardHtmlPage(data);
349
435
  writeJsonFile(jsonPath, data);
@@ -888,12 +974,12 @@ function protocolsForProject(context, projectId) {
888
974
  FROM protocols WHERE project_id = ? ORDER BY updated_at DESC`, [projectId]);
889
975
  }
890
976
  function planSummaryForProtocol(context, projectId, protocolId) {
891
- const protocol = context.db.get("SELECT plan_path FROM protocols WHERE project_id = ? AND id = ?", [projectId, protocolId]);
977
+ const protocol = context.db.get("SELECT plan_path, project_root FROM protocols WHERE project_id = ? AND id = ?", [projectId, protocolId]);
892
978
  if (!protocol) {
893
979
  return { plan_id: "none", total: 0, done: 0, blocked: 0 };
894
980
  }
895
981
  try {
896
- const summary = planSummary(context, { projectId, protocolId, planPath: protocol.plan_path }, { bind: false });
982
+ const summary = planSummary(context, { projectId, protocolId, planPath: resolveProtocolPlanPath(protocol.project_root, protocolId, protocol.plan_path) }, { bind: false });
897
983
  return { plan_id: summary.plan_id, total: summary.total, done: summary.done, blocked: summary.blocked };
898
984
  }
899
985
  catch {
@@ -903,13 +989,13 @@ function planSummaryForProtocol(context, projectId, protocolId) {
903
989
  function activePlanItems(context, projectId, protocols) {
904
990
  const items = [];
905
991
  for (const protocol of protocols) {
906
- const record = context.db.get("SELECT plan_path FROM protocols WHERE project_id = ? AND id = ?", [projectId, protocol.id]);
992
+ const record = context.db.get("SELECT plan_path, project_root FROM protocols WHERE project_id = ? AND id = ?", [projectId, protocol.id]);
907
993
  if (!record) {
908
994
  continue;
909
995
  }
910
996
  let plan;
911
997
  try {
912
- plan = planWithProgress(context, { projectId, protocolId: protocol.id, planPath: record.plan_path }, { bind: false }).plan;
998
+ plan = planWithProgress(context, { projectId, protocolId: protocol.id, planPath: resolveProtocolPlanPath(record.project_root, protocol.id, record.plan_path) }, { bind: false }).plan;
913
999
  }
914
1000
  catch {
915
1001
  continue;
@@ -1222,6 +1308,7 @@ function normalizeFlowKind(flowKind) {
1222
1308
  "mb-upgrade",
1223
1309
  "mb-audit",
1224
1310
  "mb-fix",
1311
+ "review-fix",
1225
1312
  "mb-distill",
1226
1313
  "mb-upgrade-review",
1227
1314
  "mb-sdlc-review",