@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,274 @@
1
+ import crypto from "node:crypto";
2
+ import { constants } from "node:fs";
3
+ import { lstat, open, readdir } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { AppError } from "../shared/errors.js";
6
+ import { canonicalPath } from "../storage/paths.js";
7
+ import { lifecycleCommandFromPayload } from "./lifecycle-command.js";
8
+ import { matchesIssuedNativeCommand, observedLifecycleInvocation } from "./lifecycle-invocations.js";
9
+ import { readNativeDaemonState, requireManagedDaemonBinding } from "./managed-daemon-binding.js";
10
+ import { requireProjectByRoot } from "./project-registry.js";
11
+ import { handleAgyEvent, handleCodexHook, handleDroidEvent, handleOpenCodeEvent, handleGrokEvent, handleZcodeEvent } from "./hooks.js";
12
+ import { withDaemonProgressObserver } from "../harness-runtime/lib/daemon-observation.mjs";
13
+ const object = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
14
+ const sha256 = (value) => crypto.createHash("sha256").update(value).digest("hex");
15
+ const diagnostics = new WeakMap();
16
+ async function regularJson(file) {
17
+ try {
18
+ const handle = await open(file, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
19
+ try {
20
+ if (!(await handle.stat()).isFile())
21
+ return null;
22
+ return object(JSON.parse(await handle.readFile("utf8")));
23
+ }
24
+ finally {
25
+ await handle.close();
26
+ }
27
+ }
28
+ catch (error) {
29
+ if (["ENOENT", "ELOOP", "ENOTDIR"].includes(error.code ?? "") || error instanceof SyntaxError)
30
+ return null;
31
+ throw error;
32
+ }
33
+ }
34
+ async function realDirectory(directory) {
35
+ try {
36
+ const info = await lstat(directory);
37
+ return info.isDirectory() && !info.isSymbolicLink();
38
+ }
39
+ catch (error) {
40
+ if (error.code === "ENOENT")
41
+ return false;
42
+ throw error;
43
+ }
44
+ }
45
+ function payloadCommand(binding) {
46
+ const payload = object(binding.native_payload);
47
+ if (!payload)
48
+ return undefined;
49
+ if (binding.source_harness === "codex-desktop")
50
+ return lifecycleCommandFromPayload(payload) ?? undefined;
51
+ if (binding.source_harness === "grok-acp") {
52
+ const native = object(payload.tool_input ?? payload.toolInput);
53
+ const command = native?.command ?? native?.cmd ?? payload.command;
54
+ return typeof command === "string" ? command : undefined;
55
+ }
56
+ if (binding.source_harness === "zcode-acp") {
57
+ const update = object(object(payload.params)?.update), native = object(update?.rawInput);
58
+ const command = native?.command ?? native?.cmd;
59
+ return typeof command === "string" ? command : undefined;
60
+ }
61
+ const input = object(payload.input);
62
+ const command = input?.command ?? input?.cmd ?? input?.CommandLine;
63
+ return typeof command === "string" ? command : undefined;
64
+ }
65
+ /** The directory is only a locator. The owning daemon must attest the exact
66
+ * binding from its verified native-delivery map before it becomes a receipt. */
67
+ export async function reconcileRetainedNativeHook(context, input) {
68
+ const { scope, invocationId } = input;
69
+ const diagnostic = (phase, error, binding) => {
70
+ if (!input.onDiagnostic)
71
+ return;
72
+ const supplied = error instanceof Error || object(error) ? error.code : undefined;
73
+ const code = typeof supplied === "string" && /^[A-Za-z][A-Za-z0-9_]{0,95}$/.test(supplied) ? supplied : "native_hook_verification_unavailable";
74
+ // Diagnostics never become execution authority or activity. Keep identifiers
75
+ // and a typed cause, not native messages/configs that can contain credentials.
76
+ const value = { phase, code, invocation_id: invocationId,
77
+ ...(typeof binding?.request_id === "string" ? { request_id: binding.request_id } : {}),
78
+ ...(typeof binding?.operation_id === "string" ? { operation_id: binding.operation_id } : {}) };
79
+ const seen = diagnostics.get(context) ?? new Set(), key = JSON.stringify(value);
80
+ if (seen.has(key))
81
+ return;
82
+ seen.add(key);
83
+ diagnostics.set(context, seen);
84
+ input.onDiagnostic(value);
85
+ };
86
+ if (!scope.runId || context.env.DD_FLOW_DAEMON_ID !== scope.daemonId)
87
+ return false;
88
+ let owner = null;
89
+ try {
90
+ owner = object(JSON.parse(context.env.DD_FLOW_RUNTIME_OWNER ?? "null"));
91
+ }
92
+ catch {
93
+ return false;
94
+ }
95
+ const stateDir = owner?.state_dir || context.env.DD_FLOW_CODEX_STATE_DIR || context.env.DD_AGY_STATE_DIR || context.env.DD_GROK_STATE_DIR || context.env.DD_ZCODE_STATE_DIR;
96
+ if (typeof stateDir !== "string" || !path.isAbsolute(stateDir) || !await realDirectory(stateDir))
97
+ return false;
98
+ // This is an optional additional observation source. A missing, retiring or
99
+ // unbound daemon must leave the existing hook path intact, never grant it
100
+ // authority and never turn an otherwise valid legacy delivery into a failure.
101
+ let owned;
102
+ let metadata;
103
+ try {
104
+ const state = readNativeDaemonState(stateDir);
105
+ if ((state.daemon_id ?? state.config?.daemonId) !== scope.daemonId) {
106
+ diagnostic("owner", { code: "daemon_owner_mismatch" });
107
+ return false;
108
+ }
109
+ const project = requireProjectByRoot(context, scope.projectRoot);
110
+ owned = requireManagedDaemonBinding(context, { stateDir, projectId: project.id, runId: scope.runId });
111
+ metadata = JSON.parse(owned.process.metadata_json);
112
+ }
113
+ catch (error) {
114
+ diagnostic("owner", error);
115
+ return false;
116
+ }
117
+ if (metadata.run_generation !== scope.generation) {
118
+ diagnostic("owner", { code: "run_generation_mismatch" });
119
+ return false;
120
+ }
121
+ const operations = path.join(stateDir, "operations");
122
+ if (!await realDirectory(operations))
123
+ return false;
124
+ const candidates = [];
125
+ for (const entry of await readdir(operations, { withFileTypes: true })) {
126
+ if (!entry.isDirectory() || !/^[a-f0-9]{64}$/.test(entry.name))
127
+ continue;
128
+ const directory = path.join(operations, entry.name), hooks = path.join(directory, "hooks");
129
+ if (!await realDirectory(hooks))
130
+ continue;
131
+ const requested = await regularJson(path.join(directory, "requested.json"));
132
+ if (!requested || requested.schema_id !== "dd-flow/daemon-operation@1" || typeof requested.operation_id !== "string"
133
+ || sha256(requested.operation_id) !== entry.name || requested.daemon_id !== scope.daemonId
134
+ || requested.owner_id !== owned.process.owner_id || !["session.create", "session.start", "session.prompt"].includes(String(requested.operation))
135
+ || requested.session_id && requested.session_id !== scope.rootSessionId)
136
+ continue;
137
+ for (const hook of await readdir(hooks, { withFileTypes: true })) {
138
+ if (!hook.isFile() || !/^[A-Za-z0-9-]{1,128}\.json$/.test(hook.name))
139
+ continue;
140
+ const binding = await regularJson(path.join(hooks, hook.name));
141
+ if (!binding || binding.schema_id !== "dd-flow/hook-request@1" || binding.request_id !== hook.name.slice(0, -5)
142
+ || binding.daemon_id !== scope.daemonId || binding.operation_id !== requested.operation_id
143
+ || binding.root_provider_session_id !== scope.rootSessionId || !["codex-desktop", "antigravity-cli", "grok-acp", "zcode-acp", "opencode-server", "droid-cli"].includes(String(binding.source_harness))
144
+ || typeof binding.provider_session_id !== "string" || !binding.provider_session_id
145
+ || !(binding.parent_provider_session_id === null || typeof binding.parent_provider_session_id === "string")
146
+ || typeof binding.tool_call_id !== "string" || !binding.tool_call_id || binding.event !== "PreToolUse"
147
+ || typeof binding.native_command !== "string" || binding.command_sha256 !== sha256(binding.native_command)
148
+ || payloadCommand(binding) !== binding.native_command || !matchesIssuedNativeCommand(context, invocationId, binding.native_command))
149
+ continue;
150
+ candidates.push(binding);
151
+ }
152
+ }
153
+ const verified = [];
154
+ for (const binding of candidates) {
155
+ try {
156
+ const module = binding.source_harness === "codex-desktop"
157
+ ? await import("../harness-runtime/lib/dd-codex-daemon.mjs")
158
+ : binding.source_harness === "grok-acp" ? await import("../harness-runtime/lib/dd-grok-daemon.mjs")
159
+ : binding.source_harness === "zcode-acp" ? await import("../harness-runtime/lib/dd-zcode-daemon.mjs")
160
+ // @ts-expect-error Executable adapter assets have no duplicate typed API.
161
+ : binding.source_harness === "opencode-server" ? await import("../harness-runtime/lib/dd-opencode-daemon.mjs")
162
+ // @ts-expect-error Executable adapter assets have no duplicate typed API.
163
+ : binding.source_harness === "droid-cli" ? await import("../harness-runtime/lib/dd-droid-daemon.mjs")
164
+ : await import("../harness-runtime/lib/dd-agy-daemon.mjs");
165
+ const proof = await withDaemonProgressObserver(progress => {
166
+ if (typeof progress.native_request_id === 'string' && typeof progress.observed_at === 'string')
167
+ input.onProgress?.({ cursor: `${binding.request_id}:${progress.native_request_id}`, observed_at: Date.parse(progress.observed_at) });
168
+ }, () => module.callDaemon(stateDir, "hook.verify", { daemonId: scope.daemonId, requestId: binding.request_id, binding }, 5_000));
169
+ if (binding.native_admission === "assigned_work_start") {
170
+ const resolved = object(proof.nativeHookBinding);
171
+ if (proof.verified !== true || JSON.stringify(proof.registeredHookBinding) !== JSON.stringify(binding) || !resolved
172
+ || !["antigravity-cli", "opencode-server", "droid-cli"].includes(String(binding.source_harness))
173
+ || resolved.native_ancestry !== "confirmed" || typeof resolved.native_cwd !== "string" || !path.isAbsolute(resolved.native_cwd)
174
+ || !(resolved.parent_provider_session_id === null || typeof resolved.parent_provider_session_id === "string")
175
+ || ["request_id", "operation_id", "daemon_id", "turn_generation", "source_harness", "root_provider_session_id", "provider_session_id",
176
+ "tool_call_id", "event", "native_command", "command_sha256", "native_creator", "native_admission"].some(key => resolved[key] !== binding[key])
177
+ || payloadCommand(resolved) !== binding.native_command) {
178
+ diagnostic("verify", { code: "native_hook_unproven" }, binding);
179
+ continue;
180
+ }
181
+ verified.push(resolved);
182
+ }
183
+ else if (proof.verified === true && JSON.stringify(proof.nativeHookBinding) === JSON.stringify(binding))
184
+ verified.push(binding);
185
+ else
186
+ diagnostic("verify", { code: "native_hook_unproven" }, binding);
187
+ }
188
+ catch (error) {
189
+ diagnostic("verify", error, binding);
190
+ }
191
+ }
192
+ // Exact old tool delivery belongs to its immutable prior attempt. A public
193
+ // command may be identical in a fresh no-effect successor; do not repeatedly
194
+ // select its predecessor and starve the new native callback.
195
+ const eligible = verified.filter(binding => observedLifecycleInvocation(context, binding.native_command, scope, { identity: {
196
+ daemonId: scope.daemonId, rootSessionId: scope.rootSessionId, sessionId: binding.provider_session_id,
197
+ parentSessionId: binding.parent_provider_session_id, toolCallId: binding.tool_call_id
198
+ } })?.id === invocationId);
199
+ if (!eligible.length)
200
+ return false;
201
+ const identity = (binding) => JSON.stringify([binding.source_harness, binding.daemon_id, binding.root_provider_session_id,
202
+ binding.provider_session_id, binding.parent_provider_session_id, binding.native_cwd]);
203
+ if (new Set(eligible.map(identity)).size !== 1)
204
+ throw new AppError("invocation_ambiguous", "More than one native executor supplied this issued Work command", 1, { effect: "no_effect", invocation_id: invocationId });
205
+ const binding = eligible[0], payload = object(binding.native_payload);
206
+ if (binding.source_harness === "codex-desktop") {
207
+ const proof = object(binding.codex_proof);
208
+ if (!proof || proof.daemonId !== scope.daemonId || proof.rootSessionId !== scope.rootSessionId
209
+ || proof.sessionId !== binding.provider_session_id || proof.parentSessionId !== binding.parent_provider_session_id
210
+ || proof.toolCallId !== binding.tool_call_id || typeof proof.projectRoot !== "string"
211
+ || canonicalPath(proof.projectRoot) !== canonicalPath(scope.projectRoot) || typeof proof.ddFlowHome !== "string"
212
+ || canonicalPath(proof.ddFlowHome) !== canonicalPath(context.ddFlowHome))
213
+ return false;
214
+ const prior = context.codexHookProof;
215
+ try {
216
+ context.codexHookProof = { daemonId: scope.daemonId, rootSessionId: scope.rootSessionId,
217
+ sessionId: binding.provider_session_id, parentSessionId: binding.parent_provider_session_id,
218
+ toolCallId: binding.tool_call_id, projectRoot: proof.projectRoot, command: binding.native_command };
219
+ handleCodexHook(context, { event: "PreToolUse", projectRoot: scope.projectRoot, stdin: JSON.stringify(payload) });
220
+ }
221
+ finally {
222
+ if (prior)
223
+ context.codexHookProof = prior;
224
+ else
225
+ delete context.codexHookProof;
226
+ }
227
+ }
228
+ else if (binding.source_harness === "grok-acp") {
229
+ const identity = object(object(payload._meta)?.ddGrok);
230
+ if (!identity || identity.daemonId !== scope.daemonId || identity.rootProviderSessionId !== scope.rootSessionId
231
+ || identity.parentProviderSessionId !== binding.parent_provider_session_id
232
+ || (payload.session_id ?? payload.sessionId) !== binding.provider_session_id
233
+ || (payload.tool_use_id ?? payload.toolUseId ?? payload.tool_call_id) !== binding.tool_call_id)
234
+ return false;
235
+ handleGrokEvent(context, { projectRoot: scope.projectRoot, stdin: JSON.stringify(payload) });
236
+ }
237
+ else if (binding.source_harness === "zcode-acp") {
238
+ const controlled = object(object(payload._meta)?.ddZcode), update = object(object(payload.params)?.update), native = object(object(update?._meta)?.zcodeRuntime);
239
+ if (!controlled || controlled.daemonId !== scope.daemonId || controlled.rootProviderSessionId !== scope.rootSessionId
240
+ || controlled.parentProviderSessionId !== binding.parent_provider_session_id || native?.source !== "subagent"
241
+ || native.childSessionId !== binding.provider_session_id || native.childToolCallId !== binding.tool_call_id
242
+ || typeof update?.toolCallId !== "string" || !update.toolCallId || typeof native.nativeTurnId !== "string" || !native.nativeTurnId)
243
+ return false;
244
+ handleZcodeEvent(context, { projectRoot: scope.projectRoot, stdin: JSON.stringify(payload) });
245
+ }
246
+ else if (binding.native_admission === "assigned_work_start") {
247
+ const harness = binding.source_harness, session = object(payload.session);
248
+ if (payload.daemon_id !== scope.daemonId || (harness === "antigravity-cli" ? payload.conversation_id !== binding.provider_session_id
249
+ || (payload.parent_conversation_id ?? null) !== binding.parent_provider_session_id || payload.event_id !== binding.tool_call_id
250
+ : !session || session.provider_session_id !== binding.provider_session_id || (session.parent_provider_session_id ?? null) !== binding.parent_provider_session_id
251
+ || payload.tool_call_id !== binding.tool_call_id))
252
+ return false;
253
+ const prior = context.nativeHookProof;
254
+ try {
255
+ context.nativeHookProof = { harness, daemonId: scope.daemonId, rootSessionId: scope.rootSessionId, sessionId: binding.provider_session_id,
256
+ toolCallId: binding.tool_call_id };
257
+ const handle = harness === "antigravity-cli" ? handleAgyEvent : harness === "droid-cli" ? handleDroidEvent : handleOpenCodeEvent;
258
+ handle(context, { projectRoot: scope.projectRoot, stdin: JSON.stringify(payload) });
259
+ }
260
+ finally {
261
+ if (prior)
262
+ context.nativeHookProof = prior;
263
+ else
264
+ delete context.nativeHookProof;
265
+ }
266
+ }
267
+ else {
268
+ if (payload.daemon_id !== scope.daemonId || payload.conversation_id !== binding.provider_session_id
269
+ || (payload.parent_conversation_id ?? null) !== binding.parent_provider_session_id || payload.event_id !== binding.tool_call_id)
270
+ return false;
271
+ handleAgyEvent(context, { projectRoot: scope.projectRoot, stdin: JSON.stringify(payload) });
272
+ }
273
+ return true;
274
+ }
@@ -0,0 +1,165 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { spawnSync } from "node:child_process";
5
+ import { AppError } from "../shared/errors.js";
6
+ import { ignoredWorkspacePaths } from "./code-checks.js";
7
+ import { localEnvironmentAllowed, ownedWorkspaceHookPath, projectServicePathFilter, workspaceGitFiles } from "./workspace-files.js";
8
+ export function reviewerSourceInputs(root, aspectIds) {
9
+ const criteria = [...new Set(aspectIds)].sort().map(id => {
10
+ if (!/^[a-z][a-z0-9_-]*$/.test(id))
11
+ throw new AppError("review_criterion_invalid", "Assigned aspect has an invalid identity", 1, { aspect_id: id });
12
+ return `.memory-bank/dd-flow/mb-sdlc/plan-aspects/aspects/${id}.md`;
13
+ });
14
+ const orientation = [".memory-bank/index.md", ".memory-bank/spec/engineering/index.md", ".memory-bank/spec/engineering/coding-standards.md"].filter(relative => fs.existsSync(path.join(root, relative)));
15
+ return [...criteria, ...orientation].map(relative => {
16
+ const file = path.join(root, relative);
17
+ if (!fs.existsSync(file))
18
+ throw new AppError("review_criterion_missing", "Assigned reviewer criterion is missing", 1, { path: relative });
19
+ const inside = path.relative(fs.realpathSync(root), fs.realpathSync(file));
20
+ if (inside === ".." || inside.startsWith(`..${path.sep}`) || !fs.statSync(file).isFile())
21
+ throw new AppError("review_criterion_invalid", "Reviewer source must be a file in its workspace", 1, { path: relative });
22
+ return { path: relative, sha256: crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex") };
23
+ });
24
+ }
25
+ export function reviewerSourceInstruction(root, aspectIds) {
26
+ const inputs = reviewerSourceInputs(root, aspectIds);
27
+ return ["Read the assigned canonical criterion files and the available project orientation below before independent review. Apply each criterion's scope; a small behavior change is not by itself a reason to omit testing or evidence. These starting inputs do not limit relevant project investigation. Do not edit them.", ...inputs.map(input => `- ${path.join(root, input.path)} (SHA256 ${input.sha256})`)].join("\n");
28
+ }
29
+ export function reviewEnvironmentAllowed(file) {
30
+ // Relative evidence names are scoped to the project: a private parent also
31
+ // makes its children private. Absolute filesystem traversal checks each
32
+ // directory separately, without classifying ancestors outside the workspace.
33
+ return path.isAbsolute(file) || path.win32.isAbsolute(file)
34
+ ? localEnvironmentAllowed(file)
35
+ : file.split(/[\\/]/).every(part => localEnvironmentAllowed(part));
36
+ }
37
+ export function reviewSourcePaths(root, explicitInputs = [], base = "HEAD") {
38
+ const inventory = workspaceGitFiles(root, ["--cached", "--others", "--exclude-standard"]);
39
+ if (inventory === null)
40
+ return null;
41
+ const serviceAllowed = projectServicePathFilter(root, explicitInputs);
42
+ const hasHead = spawnSync("git", ["-C", root, "rev-parse", "--verify", "HEAD"], { encoding: "utf8" }).status === 0;
43
+ if (base === "unborn" && hasHead)
44
+ throw new AppError("review_git_evidence_failed", "Unborn review baseline no longer matches the workspace", 1, { workspace_root: root });
45
+ const hasBase = base === "unborn" ? false : base !== "HEAD" || hasHead;
46
+ const changes = hasBase ? spawnSync("git", ["-C", root, "diff", "--name-status", "-z", "--find-renames", base, "--"], { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }) : null;
47
+ if (changes && (changes.status !== 0 || changes.error))
48
+ throw new AppError("review_git_evidence_failed", "Could not classify renamed review paths", 1, { workspace_root: root, cause: changes.error?.message ?? changes.stderr });
49
+ const fields = changes?.stdout.split("\0").filter(Boolean) ?? [], tainted = new Set();
50
+ for (let index = 0; index < fields.length;) {
51
+ const status = fields[index++];
52
+ if (/^[RC]/.test(status)) {
53
+ const before = fields[index++], after = fields[index++];
54
+ if (!reviewEnvironmentAllowed(before) || !reviewEnvironmentAllowed(after)) {
55
+ tainted.add(before);
56
+ tainted.add(after);
57
+ }
58
+ }
59
+ else
60
+ index += 1;
61
+ }
62
+ return [...new Set([...inventory, ...explicitInputs])]
63
+ .filter(relative => reviewEnvironmentAllowed(relative) && !tainted.has(relative) && serviceAllowed(path.join(root, relative)))
64
+ .sort();
65
+ }
66
+ export function reviewSourceFilter(root, explicitInputs = [], base = "HEAD") {
67
+ const selected = reviewSourcePaths(root, explicitInputs, base);
68
+ const serviceAllowed = projectServicePathFilter(root, explicitInputs);
69
+ const retained = new Set(selected?.map(relative => path.resolve(root, relative)) ?? []);
70
+ const branches = new Set();
71
+ for (const file of retained)
72
+ for (let directory = path.dirname(file); directory !== path.dirname(directory); directory = path.dirname(directory))
73
+ branches.add(directory);
74
+ return file => {
75
+ const parts = path.relative(root, file).split(path.sep);
76
+ if (parts.some(part => [".git", "node_modules", ".dd-flow"].includes(part)) || !reviewEnvironmentAllowed(file))
77
+ return false;
78
+ return selected === null ? serviceAllowed(file) : retained.has(path.resolve(file)) || branches.has(path.resolve(file));
79
+ };
80
+ }
81
+ export function reviewSourceHash(root, explicitInputs = [], base = "HEAD") {
82
+ const allowed = reviewSourceFilter(root, explicitInputs, base), ownedHook = ownedWorkspaceHookPath(root);
83
+ return reviewCopyHash(root, file => path.relative(root, file) !== ownedHook && allowed(file));
84
+ }
85
+ /** The copied project has no Git index. Apply the source's exact service-file
86
+ * policy to it, while retaining only our frozen Git evidence under .dd-flow. */
87
+ export function reviewExecutionCopyHash(copyRoot, sourceRoot, includeEvidence = true, explicitInputs = [], base = "HEAD") {
88
+ if (ownedWorkspaceHookPath(sourceRoot) && !ownedWorkspaceHookPath(copyRoot))
89
+ throw new AppError("read_only_input_changed", "Qualified review hook differs between execution copy and source", 2, { copy_root: copyRoot });
90
+ const sourceAllowed = reviewSourceFilter(sourceRoot, explicitInputs, base);
91
+ const serviceAllowed = projectServicePathFilter(sourceRoot, explicitInputs);
92
+ const ownedHook = ownedWorkspaceHookPath(sourceRoot);
93
+ const verifySelection = (directory) => {
94
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
95
+ const file = path.join(directory, entry.name), relative = path.relative(copyRoot, file);
96
+ const parts = relative.split(path.sep);
97
+ if (parts[0] === ".dd-flow" || parts.some(part => [".git", "node_modules"].includes(part)))
98
+ continue;
99
+ if (!reviewEnvironmentAllowed(file))
100
+ throw new AppError("read_only_input_changed", "Read-only execution copy contains a local environment file", 2, { path: relative });
101
+ if (!serviceAllowed(path.join(sourceRoot, relative)))
102
+ continue;
103
+ if (!sourceAllowed(path.join(sourceRoot, relative)) && ignoredWorkspacePaths(sourceRoot, [relative]).includes(relative.split(path.sep).join("/")))
104
+ continue;
105
+ if (!sourceAllowed(path.join(sourceRoot, relative)))
106
+ throw new AppError("read_only_input_changed", "Read-only execution copy contains an unselected product input", 2, { path: relative });
107
+ if (entry.isDirectory())
108
+ verifySelection(file);
109
+ }
110
+ };
111
+ verifySelection(copyRoot);
112
+ return reviewCopyHash(copyRoot, file => {
113
+ const relative = path.relative(copyRoot, file);
114
+ const parts = relative.split(path.sep);
115
+ if (parts[0] === ".dd-flow")
116
+ return includeEvidence && (parts.length === 1 || parts[1] === "review-evidence");
117
+ return relative !== ownedHook && sourceAllowed(path.join(sourceRoot, relative));
118
+ });
119
+ }
120
+ /** Exact bytes visible in a read-only execution copy, including symlink targets. */
121
+ export function reviewCopyHash(root, allowed = () => true) {
122
+ const hash = crypto.createHash("sha256");
123
+ let canonicalRoot;
124
+ try {
125
+ canonicalRoot = fs.realpathSync(root);
126
+ }
127
+ catch {
128
+ throw new AppError("read_only_input_changed", "Read-only execution copy is missing", 2, { root });
129
+ }
130
+ const visit = (directory) => {
131
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
132
+ const file = path.join(directory, entry.name);
133
+ if (!allowed(file))
134
+ continue;
135
+ const relative = path.relative(root, file).split(path.sep).join("/");
136
+ const stat = fs.lstatSync(file);
137
+ const record = (kind, value = "") => hash.update(`${JSON.stringify([relative, kind, stat.mode & 0o111, value])}\n`);
138
+ if (entry.isDirectory()) {
139
+ record("directory");
140
+ visit(file);
141
+ continue;
142
+ }
143
+ if (entry.isSymbolicLink()) {
144
+ const link = fs.readlinkSync(file);
145
+ let target;
146
+ try {
147
+ target = fs.realpathSync(file);
148
+ }
149
+ catch {
150
+ throw new AppError("read_only_workspace_escape", "Read-only copy contains an unresolved symlink", 1, { path: relative });
151
+ }
152
+ const inside = path.relative(canonicalRoot, target);
153
+ if (path.isAbsolute(link) || inside === ".." || inside.startsWith(`..${path.sep}`))
154
+ throw new AppError("read_only_workspace_escape", "Read-only copy contains a symlink outside its workspace", 1, { path: relative });
155
+ record("symlink", link);
156
+ }
157
+ else if (entry.isFile())
158
+ record("file", crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex"));
159
+ else
160
+ throw new AppError("read_only_workspace_unsupported", "Read-only copy contains an unsupported file type", 1, { path: relative });
161
+ }
162
+ };
163
+ visit(root);
164
+ return hash.digest("hex");
165
+ }
@@ -0,0 +1,23 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { AppError } from "../shared/errors.js";
5
+ import { assertPortableArtifactRef } from "./portable-refs.js";
6
+ /** A deferral names one project-local file, never an arbitrary path. */
7
+ export function reviewDefEvidence(workspaceRoot, defId) {
8
+ try {
9
+ if (!defId || !/^DEF-[A-Za-z0-9][A-Za-z0-9_-]*$/.test(defId))
10
+ throw new Error("invalid DEF identifier");
11
+ const relative = `.memory-bank/defs/${defId}.md`;
12
+ const file = assertPortableArtifactRef(relative, { workspaceRoot, runHome: workspaceRoot, runId: "" });
13
+ const directory = fs.realpathSync(path.join(workspaceRoot, ".memory-bank", "defs"));
14
+ const root = fs.realpathSync(workspaceRoot);
15
+ const directoryRelative = path.relative(root, directory);
16
+ if (directoryRelative === ".." || directoryRelative.startsWith(`..${path.sep}`) || path.isAbsolute(directoryRelative) || path.dirname(file) !== directory || !fs.statSync(file).isFile())
17
+ throw new Error("DEF must be a regular file in the project defs directory");
18
+ return { def_id: defId, path: relative, sha256: crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex") };
19
+ }
20
+ catch (error) {
21
+ throw new AppError("deferral_invalid", "A deferral requires a readable project-local named DEF", 2, { def_id: defId ?? null, cause: error instanceof Error ? error.message : String(error) });
22
+ }
23
+ }
@@ -0,0 +1,82 @@
1
+ import { createHash } from "node:crypto";
2
+ import { AppError } from "../shared/errors.js";
3
+ import { resolveProjectRoot } from "../storage/paths.js";
4
+ import { requireProjectByRoot } from "./projects.js";
5
+ import { readFlowRunExecutionBundle } from "./runs.js";
6
+ import { readAcceptedStageData } from "./stage-report-renderer.js";
7
+ import { readReviewFixSourceIntake, assertReviewFixSourceIntakeCustody } from "./review-fix-intake-custody.js";
8
+ import { readPreparedMemoryFlowUserInputs } from "./memory-flow-user-inputs.js";
9
+ import { hybridDigest } from "./hybrid-contracts.js";
10
+ import { assertReviewFixStageScope, validateReviewFixStageResult } from "./review-fix-stage-results.js";
11
+ function refuse(reason) {
12
+ throw new AppError("review_fix_handoff_invalid", "Handoff requires accepted scope review and unchanged original user inputs", 2, { reason, effect: "no_effect" });
13
+ }
14
+ /** Prepare an SQL-fenced raw packet for the ordinary Stage settlement writer.
15
+ * No files, RUNs, PRTs or specifications are created. A ready scope is not
16
+ * authorization to formalize; the user must separately request that action.
17
+ */
18
+ export function prepareReviewFixHandoff(context, input) {
19
+ const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
20
+ const scope = { projectId: project.id, runId: input.runId };
21
+ const bundle = readFlowRunExecutionBundle(context, input);
22
+ if (!bundle || bundle.manifest.flow_id !== "review-fix")
23
+ refuse("review_fix_bundle_required");
24
+ const source = readReviewFixSourceIntake(context, input, bundle);
25
+ const read = (reader) => {
26
+ const intake = readAcceptedStageData(reader, { ...scope, stage: "intake" });
27
+ const reviewed = readAcceptedStageData(reader, { ...scope, stage: "scope-review" });
28
+ const users = readPreparedMemoryFlowUserInputs(reader, scope, "review-fix", bundle);
29
+ return { intake, reviewed, users };
30
+ };
31
+ const original = context.db.readSnapshot(() => read(context));
32
+ let prior;
33
+ try {
34
+ prior = JSON.parse(original.intake.bytes.toString("utf8"));
35
+ }
36
+ catch {
37
+ return refuse("accepted_intake_invalid");
38
+ }
39
+ if (original.intake.data_schema_id !== "dd-flow/review-fix-stage-result@1"
40
+ || original.reviewed.data_schema_id !== "dd-flow/review-fix-stage-result@1"
41
+ || prior?.schema_id !== "dd-flow/review-fix-stage-result@1" || prior.flow_id !== "review-fix"
42
+ || prior.run_id !== input.runId || prior.stage !== "intake" || prior.intake_sha256 !== source.sha256
43
+ || prior.input_sha256 !== original.intake.input_sha256 || !original.reviewed.input_sha256)
44
+ refuse("accepted_intake_invalid");
45
+ const reviewed = validateReviewFixStageResult(original.reviewed.bytes, bundle.descriptor.stageBlob("scope-review", "result_schema"), {
46
+ runId: input.runId, stage: "scope-review", inputSha256: original.reviewed.input_sha256, intakeSha256: source.sha256,
47
+ snapshotSha256: prior.snapshot_sha256, userInputsSha256: hybridDigest(original.users),
48
+ findingIds: source.intake.selected_findings.map(finding => finding.id),
49
+ predecessors: [{ stage: "intake", ...original.intake.result }],
50
+ userSources: original.users.sources.map(item => {
51
+ if (!["request", "question", "answer"].includes(item.role))
52
+ return refuse("invalid_user_input_role");
53
+ return { root: item.root, path: item.path, sha256: item.sha256, role: item.role };
54
+ })
55
+ });
56
+ assertReviewFixStageScope(reviewed, prior);
57
+ const disposition = reviewed.details.review.some(item => item.verdict === "revise") ? "needs_scope"
58
+ : reviewed.details.decisions.some(item => item.disposition === "approved") ? "ready"
59
+ : reviewed.details.decisions.some(item => item.disposition === "deferred") ? "deferred" : "declined";
60
+ const bytes = Buffer.from(JSON.stringify({ schema_id: "dd-flow/review-fix-handoff@1", run_id: input.runId,
61
+ disposition, formalization_authorized: false, next_entry: disposition === "ready" ? "vnext/start.md" : null,
62
+ source_intake: source.intake, user_inputs: original.users,
63
+ scope: reviewed.details, accepted_review: { ...original.reviewed.result, authority_sha256: original.reviewed.authority_sha256 }
64
+ }));
65
+ // Keep this packet within the existing Stage reader envelope; never truncate
66
+ // original messages or findings to make an oversized handoff appear valid.
67
+ if (bytes.length > 4 * 1024 * 1024)
68
+ refuse("handoff_exceeds_bound");
69
+ return {
70
+ path: `${bundle.descriptor.stage("handoff").directory}/raw-intake.json`, bytes,
71
+ sha256: createHash("sha256").update(bytes).digest("hex"),
72
+ assertCustody(writer) {
73
+ assertReviewFixSourceIntakeCustody(writer, scope, bundle, source.sha256);
74
+ const current = read(writer);
75
+ if (!current.intake.bytes.equals(original.intake.bytes) || !current.reviewed.bytes.equals(original.reviewed.bytes)
76
+ || current.intake.authority_sha256 !== original.intake.authority_sha256
77
+ || current.reviewed.authority_sha256 !== original.reviewed.authority_sha256
78
+ || hybridDigest(current.users) !== hybridDigest(original.users))
79
+ refuse("accepted_handoff_changed");
80
+ }
81
+ };
82
+ }
@@ -0,0 +1,17 @@
1
+ import { assertDiagnosticRepairSourceIntakeCustody, prepareDiagnosticRepairSourceIntake, readDiagnosticRepairSourceIntake } from "./diagnostic-repair-source-intake.js";
2
+ import { readMemoryFlowUserInputs } from "./memory-flow-user-inputs.js";
3
+ // Preserve this flow's own capsule identity; shared transport grants no approval.
4
+ export function assertReviewFixSourceIntakeCustody(context, scope, bundle, expectedSha256) {
5
+ return assertDiagnosticRepairSourceIntakeCustody(context, scope, bundle, expectedSha256, "review-fix");
6
+ }
7
+ export function prepareReviewFixSourceIntake(context, input) {
8
+ return prepareDiagnosticRepairSourceIntake(context, input, "review-fix");
9
+ }
10
+ export function readReviewFixSourceIntake(context, input, retainedBundle) {
11
+ return readDiagnosticRepairSourceIntake(context, input, "review-fix", retainedBundle);
12
+ }
13
+ /** Original request and all delivered answers, not an agent's replacement spec.
14
+ * Reading these bytes neither accepts scope nor authorizes SDLC formalization. */
15
+ export function readReviewFixUserInputs(context, input, retainedBundle) {
16
+ return readMemoryFlowUserInputs(context, input, "review-fix", retainedBundle);
17
+ }
@@ -0,0 +1,43 @@
1
+ import { AppError } from "../shared/errors.js";
2
+ import { reviewFixStages } from "../domain/review-fix-flow.js";
3
+ import { readFlowRunExecutionBundle, assertPreparedRunBundleSqlAuthority } from "./runs.js";
4
+ import { requireProjectByRoot } from "./projects.js";
5
+ import { resolveProjectRoot } from "../storage/paths.js";
6
+ import { readReviewFixSourceIntake, assertReviewFixSourceIntakeCustody } from "./review-fix-intake-custody.js";
7
+ import { PreparedDescriptorStageStart } from "./descriptor-stage-start.js";
8
+ import { PreparedDescriptorStageCoordinator } from "./descriptor-stage-coordinator.js";
9
+ import { readDiagnosticSnapshot, readDiagnosticSnapshotCustody } from "./diagnostic-snapshot.js";
10
+ import { hybridDigest } from "./hybrid-contracts.js";
11
+ /** Internal family entry. Generic runtime owns attempts, Work and coordinator;
12
+ * this does not register a public flow or authorize a downstream SDLC start. */
13
+ export function readReviewFixStageScope(context, input, historical = false) {
14
+ const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
15
+ const bundle = readFlowRunExecutionBundle(context, input);
16
+ if (!bundle || bundle.manifest.flow_id !== "review-fix" || !reviewFixStages.includes(input.stage))
17
+ throw new AppError("review_fix_stage_invalid", "Review-fix requires its registered three-stage flow and retained intake", 2, { reason: "review_fix_stage_required", effect: "no_effect" });
18
+ bundle.descriptor.stage(input.stage);
19
+ const source = readReviewFixSourceIntake(context, input, bundle);
20
+ const scope = { projectId: project.id, runId: input.runId, stage: input.stage };
21
+ const run = assertPreparedRunBundleSqlAuthority(context, scope, bundle);
22
+ const replay = historical && JSON.parse(run.index_json).stage_runs.some((stage) => stage.stage === input.stage && stage.status === "done");
23
+ const frozen = bundle.execution.snapshot().scope;
24
+ const snapshotSelection = { projectId: project.id, projectRoot: frozen.projectRoot, sourceRoot: frozen.projectRoot,
25
+ requestId: frozen.requestId, flowId: "review-fix" };
26
+ const snapshot = (replay ? readDiagnosticSnapshotCustody : readDiagnosticSnapshot)(context, snapshotSelection, input.runId);
27
+ if (!snapshot || snapshot.root !== frozen.workspace)
28
+ throw new AppError("review_fix_stage_invalid", "Review-fix requires its unchanged private source snapshot", 2, { reason: "snapshot_required", effect: "no_effect" });
29
+ return { bundle, source, scope, run, replay, snapshot, snapshotSelection,
30
+ assertCustody(writer) {
31
+ assertReviewFixSourceIntakeCustody(writer, scope, bundle, source.sha256);
32
+ if (hybridDigest(readDiagnosticSnapshotCustody(writer, snapshotSelection, input.runId)) !== hybridDigest(snapshot))
33
+ throw new AppError("review_fix_stage_invalid", "Review-fix source snapshot custody changed", 2, { reason: "snapshot_changed", effect: "no_effect" });
34
+ }
35
+ };
36
+ }
37
+ export function startReviewFixStage(context, input) {
38
+ const selected = readReviewFixStageScope(context, input), { source } = selected;
39
+ const fence = selected.assertCustody;
40
+ const start = PreparedDescriptorStageStart.prepare(context, input).apply(context, fence);
41
+ const coordinator = PreparedDescriptorStageCoordinator.prepare(context, input).apply(context, fence);
42
+ return { ...start, ...coordinator, intake_sha256: source.sha256, source_intake: source.reference };
43
+ }