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

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 (557) hide show
  1. package/CHANGELOG.md +895 -0
  2. package/README.md +140 -6
  3. package/dist/build-info.json +8 -8
  4. package/dist/cli/argument-values.js +38 -0
  5. package/dist/cli/command-inputs.js +386 -0
  6. package/dist/cli/command-metadata.js +232 -0
  7. package/dist/cli/command-option-descriptions.js +192 -0
  8. package/dist/cli/completion-cli.js +70 -0
  9. package/dist/cli/completion.js +57 -0
  10. package/dist/cli/diagnostic-invocation.js +46 -0
  11. package/dist/cli/diagnostic.js +120 -0
  12. package/dist/cli/error-output.js +52 -0
  13. package/dist/cli/executor-onboarding.js +76 -0
  14. package/dist/cli/flows.js +29 -0
  15. package/dist/cli/harnesses.js +84 -0
  16. package/dist/cli/help.js +396 -19
  17. package/dist/cli/hook-ingress.js +102 -0
  18. package/dist/cli/input-preparation.js +165 -0
  19. package/dist/cli/memory-flow-admission.js +50 -0
  20. package/dist/cli/memory-init-invocation.js +85 -0
  21. package/dist/cli/memory-init.js +249 -0
  22. package/dist/cli/memory-storage-admission.js +54 -0
  23. package/dist/cli/memory-storage-qualification.js +105 -0
  24. package/dist/cli/memory-storage-transition.js +123 -0
  25. package/dist/cli/memory-upgrade.js +189 -0
  26. package/dist/cli/models.js +39 -0
  27. package/dist/cli/native-hook-ingress.js +90 -0
  28. package/dist/cli/native-hook-preparation.js +55 -0
  29. package/dist/cli/operator-profiles.js +61 -0
  30. package/dist/cli/output-options.js +35 -0
  31. package/dist/cli/response-file.js +72 -0
  32. package/dist/cli/run-cli.js +1734 -550
  33. package/dist/cli/runtime-maintenance-diagnostics.js +46 -0
  34. package/dist/cli/runtime-maintenance-ingress.js +52 -0
  35. package/dist/cli/runtime-process.js +153 -0
  36. package/dist/cli/setup.js +150 -0
  37. package/dist/cli.js +89 -2
  38. package/dist/domain/diagnostic-aspects.js +103 -0
  39. package/dist/domain/diagnostic-flows.js +8 -0
  40. package/dist/domain/stage-catalog.js +1 -1
  41. package/dist/domain/stage-handler-identities.js +28 -0
  42. package/dist/harness-runtime/DD-ZCODE.md +112 -0
  43. package/dist/harness-runtime/OPENCODE-LICENSE.txt +24 -0
  44. package/dist/harness-runtime/bin/dd-agy.mjs +56 -0
  45. package/dist/harness-runtime/bin/dd-codex.mjs +27 -0
  46. package/dist/harness-runtime/bin/dd-droid.mjs +34 -0
  47. package/dist/harness-runtime/bin/dd-grok.mjs +40 -0
  48. package/dist/harness-runtime/bin/dd-opencode.mjs +22 -0
  49. package/dist/harness-runtime/bin/dd-zcode.mjs +87 -0
  50. package/dist/harness-runtime/lib/adapter-timeouts.d.mts +5 -0
  51. package/dist/harness-runtime/lib/adapter-timeouts.mjs +34 -0
  52. package/dist/harness-runtime/lib/agy-error-boundary.mjs +58 -0
  53. package/dist/harness-runtime/lib/agy-hooks.d.mts +1 -0
  54. package/dist/harness-runtime/lib/agy-hooks.mjs +9 -0
  55. package/dist/harness-runtime/lib/agy-native-inspection.mjs +216 -0
  56. package/dist/harness-runtime/lib/agy-native_pb.js +117 -0
  57. package/dist/harness-runtime/lib/daemon-observation.d.mts +2 -0
  58. package/dist/harness-runtime/lib/daemon-observation.mjs +163 -0
  59. package/dist/harness-runtime/lib/daemon-operations.d.mts +2 -0
  60. package/dist/harness-runtime/lib/daemon-operations.mjs +462 -0
  61. package/dist/harness-runtime/lib/dd-agy-daemon.d.mts +6 -0
  62. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +1096 -0
  63. package/dist/harness-runtime/lib/dd-agy.mjs +86 -0
  64. package/dist/harness-runtime/lib/dd-codex-daemon.d.mts +1 -0
  65. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +231 -0
  66. package/dist/harness-runtime/lib/dd-codex.d.mts +1 -0
  67. package/dist/harness-runtime/lib/dd-codex.mjs +954 -0
  68. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +141 -0
  69. package/dist/harness-runtime/lib/dd-droid.mjs +626 -0
  70. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +555 -0
  71. package/dist/harness-runtime/lib/dd-grok.mjs +180 -0
  72. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +622 -0
  73. package/dist/harness-runtime/lib/dd-opencode.mjs +390 -0
  74. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +752 -0
  75. package/dist/harness-runtime/lib/dd-zcode.mjs +1175 -0
  76. package/dist/harness-runtime/lib/delegation-instructions.d.mts +14 -0
  77. package/dist/harness-runtime/lib/delegation-instructions.mjs +157 -0
  78. package/dist/harness-runtime/lib/dispatch-fence.mjs +14 -0
  79. package/dist/harness-runtime/lib/driver-recovery.mjs +140 -0
  80. package/dist/harness-runtime/lib/droid-observation.mjs +66 -0
  81. package/dist/harness-runtime/lib/entity-references.d.mts +2 -0
  82. package/dist/harness-runtime/lib/entity-references.mjs +9 -0
  83. package/dist/harness-runtime/lib/lease-renewal.d.mts +8 -0
  84. package/dist/harness-runtime/lib/lease-renewal.mjs +37 -0
  85. package/dist/harness-runtime/lib/lifecycle-command.d.mts +20 -0
  86. package/dist/harness-runtime/lib/lifecycle-command.mjs +273 -0
  87. package/dist/harness-runtime/lib/lifecycle-contract.d.mts +10 -0
  88. package/dist/harness-runtime/lib/lifecycle-contract.mjs +19 -0
  89. package/dist/harness-runtime/lib/managed-daemon.d.mts +16 -0
  90. package/dist/harness-runtime/lib/managed-daemon.mjs +698 -0
  91. package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
  92. package/dist/harness-runtime/lib/model-observations.mjs +101 -0
  93. package/dist/harness-runtime/lib/native-children.d.mts +23 -0
  94. package/dist/harness-runtime/lib/native-children.mjs +219 -0
  95. package/dist/harness-runtime/lib/native-hook-command.d.mts +7 -0
  96. package/dist/harness-runtime/lib/native-hook-command.mjs +251 -0
  97. package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
  98. package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
  99. package/dist/harness-runtime/lib/native-streams.mjs +45 -0
  100. package/dist/harness-runtime/lib/observation-clock.d.mts +18 -0
  101. package/dist/harness-runtime/lib/observation-clock.mjs +95 -0
  102. package/dist/harness-runtime/lib/opencode-plugin.mjs +85 -0
  103. package/dist/harness-runtime/lib/operation-context.mjs +5 -0
  104. package/dist/harness-runtime/lib/operation-errors.d.mts +16 -0
  105. package/dist/harness-runtime/lib/operation-errors.mjs +127 -0
  106. package/dist/harness-runtime/lib/operation-progress.d.mts +7 -0
  107. package/dist/harness-runtime/lib/operation-progress.mjs +114 -0
  108. package/dist/harness-runtime/lib/process-json.d.mts +5 -0
  109. package/dist/harness-runtime/lib/process-json.mjs +201 -0
  110. package/dist/harness-runtime/lib/process-snapshot.mjs +10 -0
  111. package/dist/harness-runtime/lib/provider-overload-policy.d.mts +15 -0
  112. package/dist/harness-runtime/lib/provider-overload-policy.mjs +151 -0
  113. package/dist/harness-runtime/lib/runner-events.mjs +202 -0
  114. package/dist/harness-runtime/lib/runner-lock.mjs +42 -0
  115. package/dist/harness-runtime/lib/session-settlement.mjs +30 -0
  116. package/dist/harness-runtime/lib/setup-progress.d.mts +9 -0
  117. package/dist/harness-runtime/lib/setup-progress.mjs +53 -0
  118. package/dist/harness-runtime/lib/tool-observations.d.mts +21 -0
  119. package/dist/harness-runtime/lib/tool-observations.mjs +228 -0
  120. package/dist/harness-runtime/lib/zcode-usage.mjs +55 -0
  121. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-1y4a697q.js +81 -0
  122. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-2ny4vxct.js +92 -0
  123. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-6mptkzbc.js +0 -0
  124. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-7x67cf1q.js +52 -0
  125. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9rqn6x4v.js +16 -0
  126. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9vdz0zwn.js +1661 -0
  127. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ecs5ftka.js +1466 -0
  128. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-frbwqjmf.js +145 -0
  129. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gne7h7mq.js +50 -0
  130. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gx9wnkzr.js +105 -0
  131. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-m2eywc8w.js +0 -0
  132. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-nwcpakzx.js +12 -0
  133. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-q4g3afnw.js +623 -0
  134. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-qav6mfdz.js +0 -0
  135. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-sxt88q69.js +12 -0
  136. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-t1xa31vm.js +39 -0
  137. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ve4aws36.js +103 -0
  138. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vmytr4q8.js +4 -0
  139. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vt9jbch8.js +36 -0
  140. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vyas3vgt.js +0 -0
  141. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-wjyeq25y.js +30 -0
  142. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-xgnj2w4v.js +20 -0
  143. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-y2etg5bs.js +9 -0
  144. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ydhz1zrh.js +238 -0
  145. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-z6qdwcsf.js +62 -0
  146. package/dist/harness-runtime/vendor/opencode-client/contract.d.ts +1 -0
  147. package/dist/harness-runtime/vendor/opencode-client/contract.js +12 -0
  148. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.d.ts +2806 -0
  149. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.js +0 -0
  150. package/dist/harness-runtime/vendor/opencode-client/effect/api.d.ts +4 -0
  151. package/dist/harness-runtime/vendor/opencode-client/effect/api.js +0 -0
  152. package/dist/harness-runtime/vendor/opencode-client/effect/client.d.ts +2530 -0
  153. package/dist/harness-runtime/vendor/opencode-client/effect/client.js +15 -0
  154. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.d.ts +7 -0
  155. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.js +6 -0
  156. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.d.ts +2529 -0
  157. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.js +8 -0
  158. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.d.ts +2 -0
  159. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.js +12 -0
  160. package/dist/harness-runtime/vendor/opencode-client/effect/index.d.ts +35 -0
  161. package/dist/harness-runtime/vendor/opencode-client/effect/index.js +75 -0
  162. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.d.ts +20 -0
  163. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.js +11 -0
  164. package/dist/harness-runtime/vendor/opencode-client/effect/service.d.ts +90 -0
  165. package/dist/harness-runtime/vendor/opencode-client/effect/service.js +187 -0
  166. package/dist/harness-runtime/vendor/opencode-client/package.json +84 -0
  167. package/dist/harness-runtime/vendor/opencode-client/promise/api.d.ts +21 -0
  168. package/dist/harness-runtime/vendor/opencode-client/promise/api.js +0 -0
  169. package/dist/harness-runtime/vendor/opencode-client/promise/client.d.ts +252 -0
  170. package/dist/harness-runtime/vendor/opencode-client/promise/client.js +14 -0
  171. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.d.ts +8 -0
  172. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.js +6 -0
  173. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.d.ts +259 -0
  174. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.js +7 -0
  175. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.d.ts +3 -0
  176. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.js +79 -0
  177. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.d.ts +8932 -0
  178. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.js +70 -0
  179. package/dist/harness-runtime/vendor/opencode-client/promise/index.d.ts +6 -0
  180. package/dist/harness-runtime/vendor/opencode-client/promise/index.js +83 -0
  181. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.d.ts +32 -0
  182. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.js +7 -0
  183. package/dist/harness-runtime/vendor/opencode-client/promise/service.d.ts +24 -0
  184. package/dist/harness-runtime/vendor/opencode-client/promise/service.js +187 -0
  185. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.d.ts +12 -0
  186. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.js +14 -0
  187. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.d.ts +20 -0
  188. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.js +14 -0
  189. package/dist/harness-runtime/vendor/opencode-client/service-contender.d.ts +37 -0
  190. package/dist/harness-runtime/vendor/opencode-client/service-contender.js +10 -0
  191. package/dist/harness-runtime/vendor/opencode-client/service-probe.d.ts +70 -0
  192. package/dist/harness-runtime/vendor/opencode-client/service-probe.js +16 -0
  193. package/dist/harness-runtime/vendor/opencode-client/service-timing.d.ts +12 -0
  194. package/dist/harness-runtime/vendor/opencode-client/service-timing.js +10 -0
  195. package/dist/harness-runtime/vendor/opencode-client/service-version.d.ts +2 -0
  196. package/dist/harness-runtime/vendor/opencode-client/service-version.js +6 -0
  197. package/dist/harness-runtime/vendor/opencode-client/service.d.ts +52 -0
  198. package/dist/harness-runtime/vendor/opencode-client/service.js +1 -0
  199. package/dist/harness-runtime/vendor/opencode-client/shared-events.d.ts +11 -0
  200. package/dist/harness-runtime/vendor/opencode-client/shared-events.js +8 -0
  201. package/dist/harness-runtime/vendor/opencode-client/solid/connection.d.ts +37 -0
  202. package/dist/harness-runtime/vendor/opencode-client/solid/connection.js +10 -0
  203. package/dist/harness-runtime/vendor/opencode-client/solid/data.d.ts +211 -0
  204. package/dist/harness-runtime/vendor/opencode-client/solid/data.js +18 -0
  205. package/dist/harness-runtime/vendor/opencode-client/solid/index.d.ts +3 -0
  206. package/dist/harness-runtime/vendor/opencode-client/solid/index.js +32 -0
  207. package/dist/harness-runtime/vendor/opencode-client/solid/pty.d.ts +22 -0
  208. package/dist/harness-runtime/vendor/opencode-client/solid/pty.js +8 -0
  209. package/dist/harness-runtime/vendor/opencode-plugin.mjs +3 -0
  210. package/dist/protocol/local-files.js +18 -9
  211. package/dist/runtime/context.js +8 -4
  212. package/dist/schemas/agent-profile.schema.json +1 -1
  213. package/dist/schemas/code-review-decision.schema.json +9 -0
  214. package/dist/schemas/code-review-result.schema.json +1 -1
  215. package/dist/schemas/code-verification.schema.json +7 -5
  216. package/dist/schemas/code-work-batch.schema.json +2 -2
  217. package/dist/schemas/diagnostic-stage-result.schema.json +354 -0
  218. package/dist/schemas/diagnostic-work-result.schema.json +296 -0
  219. package/dist/schemas/discovery-result.schema.json +184 -0
  220. package/dist/schemas/execution-bundle.schema.json +211 -0
  221. package/dist/schemas/execution-settings.schema.json +162 -0
  222. package/dist/schemas/flow-descriptor.schema.json +54 -0
  223. package/dist/schemas/flow-run.schema.json +29 -0
  224. package/dist/schemas/harness-catalog.schema.json +80 -0
  225. package/dist/schemas/mb-init-compose-result.schema.json +457 -0
  226. package/dist/schemas/mb-init-discover-result.schema.json +500 -0
  227. package/dist/schemas/mb-init-finish-result.schema.json +422 -0
  228. package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
  229. package/dist/schemas/mb-init-review-result.schema.json +396 -0
  230. package/dist/schemas/mb-init-verify-result.schema.json +391 -0
  231. package/dist/schemas/mb-upgrade-stage-result.schema.json +863 -0
  232. package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
  233. package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
  234. package/dist/schemas/memory-composition-work-result.schema.json +38 -0
  235. package/dist/schemas/memory-repair-work-result.schema.json +56 -0
  236. package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
  237. package/dist/schemas/memory-review-work-result.schema.json +43 -0
  238. package/dist/schemas/model-catalog.schema.json +153 -0
  239. package/dist/schemas/plan-review-decision.schema.json +12 -3
  240. package/dist/schemas/plan-review-result.schema.json +2 -2
  241. package/dist/schemas/profile-settings.schema.json +122 -0
  242. package/dist/schemas/project-flow-pack-manifest.schema.json +1 -1
  243. package/dist/schemas/release-impact.schema.json +3 -3
  244. package/dist/schemas/release-manifest.schema.json +291 -0
  245. package/dist/schemas/run-control-receipt.schema.json +118 -0
  246. package/dist/schemas/run-control-request.schema.json +36 -0
  247. package/dist/schemas/run-engine-binding.schema.json +1 -1
  248. package/dist/schemas/stage-start-response.schema.json +4 -0
  249. package/dist/schemas/vnext-protocol-plan.schema.json +2 -2
  250. package/dist/services/accepted-intent.js +139 -0
  251. package/dist/services/branch-context.js +3 -3
  252. package/dist/services/canon.js +54 -15
  253. package/dist/services/check-environment.js +21 -0
  254. package/dist/services/check-runner-evidence.js +562 -0
  255. package/dist/services/cleanup.js +133 -40
  256. package/dist/services/cli-operation-classifier.js +26 -63
  257. package/dist/services/cli-upgrade-allowlist.js +27 -0
  258. package/dist/services/code-checks.js +1398 -119
  259. package/dist/services/codex-hook-delivery.js +32 -0
  260. package/dist/services/command-context.js +80 -0
  261. package/dist/services/compatibility-preflight.js +16 -3
  262. package/dist/services/config.js +11 -8
  263. package/dist/services/continuation-outcome.js +20 -0
  264. package/dist/services/controller-child-capacity.js +13 -0
  265. package/dist/services/controller-child-observer.js +115 -0
  266. package/dist/services/controller-execution.js +94 -0
  267. package/dist/services/controller-fanout.js +226 -0
  268. package/dist/services/controller-memory-task.js +45 -0
  269. package/dist/services/controller-memory-worker.js +49 -0
  270. package/dist/services/dashboard.js +143 -58
  271. package/dist/services/descriptor-coordinator-session.js +35 -0
  272. package/dist/services/descriptor-root-work.js +53 -0
  273. package/dist/services/descriptor-run-settlement.js +107 -0
  274. package/dist/services/descriptor-run-start.js +475 -0
  275. package/dist/services/descriptor-stage-coordinator.js +250 -0
  276. package/dist/services/descriptor-stage-settlement.js +223 -0
  277. package/dist/services/descriptor-stage-start.js +175 -0
  278. package/dist/services/diagnostic-evidence.js +73 -0
  279. package/dist/services/diagnostic-report-publication.js +72 -0
  280. package/dist/services/diagnostic-report.js +67 -0
  281. package/dist/services/diagnostic-run-bundle.js +74 -0
  282. package/dist/services/diagnostic-snapshot.js +159 -0
  283. package/dist/services/diagnostic-stage-handlers.js +108 -0
  284. package/dist/services/diagnostic-stage-results.js +132 -0
  285. package/dist/services/diagnostic-start.js +84 -0
  286. package/dist/services/diagnostic-work-batch.js +34 -0
  287. package/dist/services/diagnostic-work-collection.js +97 -0
  288. package/dist/services/diagnostic-work-registration.js +101 -0
  289. package/dist/services/diagnostic-work-results.js +93 -0
  290. package/dist/services/discovery/agy-discovery.js +2 -0
  291. package/dist/services/discovery/codex-discovery.js +2 -0
  292. package/dist/services/discovery/droid-discovery.js +2 -0
  293. package/dist/services/discovery/grok-discovery.js +2 -0
  294. package/dist/services/discovery/opencode-discovery.js +2 -0
  295. package/dist/services/discovery/static.js +31 -0
  296. package/dist/services/discovery/zcode-discovery.js +2 -0
  297. package/dist/services/engines.js +354 -163
  298. package/dist/services/eval-snapshots.js +1316 -150
  299. package/dist/services/execution-bundles.js +275 -0
  300. package/dist/services/execution-policy.js +185 -0
  301. package/dist/services/executor-onboarding.js +56 -0
  302. package/dist/services/external-work-launch.js +310 -0
  303. package/dist/services/flow-catalog.js +30 -0
  304. package/dist/services/flow-descriptors.js +82 -0
  305. package/dist/services/frozen-engine.js +387 -0
  306. package/dist/services/generic-execution.js +164 -0
  307. package/dist/services/harness-adapter.js +355 -36
  308. package/dist/services/harness-config.js +2 -0
  309. package/dist/services/harness-discovery.js +29 -0
  310. package/dist/services/harness-doctor.js +75 -0
  311. package/dist/services/harness-probe-effects.js +51 -0
  312. package/dist/services/harness-version-probe.js +100 -0
  313. package/dist/services/hook-memory-routing.js +188 -0
  314. package/dist/services/hook-recovery-guard.js +14 -0
  315. package/dist/services/hook-session-observation.js +24 -0
  316. package/dist/services/hooks.js +791 -326
  317. package/dist/services/hybrid-contracts.js +474 -0
  318. package/dist/services/hybrid-digest.js +14 -0
  319. package/dist/services/ids.js +29 -1
  320. package/dist/services/installation-lock.js +95 -0
  321. package/dist/services/installed-flow-source.js +226 -0
  322. package/dist/services/lanes.js +78 -65
  323. package/dist/services/lifecycle-command.js +1 -288
  324. package/dist/services/lifecycle-contract.js +1 -0
  325. package/dist/services/lifecycle-invocations.js +2148 -0
  326. package/dist/services/managed-daemon-binding.js +38 -0
  327. package/dist/services/managed-lease-monitor.js +133 -0
  328. package/dist/services/managed-processes.js +449 -69
  329. package/dist/services/memory-accepted-composition.js +78 -0
  330. package/dist/services/memory-baseline-preservation.js +65 -0
  331. package/dist/services/memory-completed-correction-wave.js +328 -0
  332. package/dist/services/memory-compose-handler.js +400 -0
  333. package/dist/services/memory-composition-acceptance.js +375 -0
  334. package/dist/services/memory-composition-graph.js +165 -0
  335. package/dist/services/memory-composition-registration.js +161 -0
  336. package/dist/services/memory-composition-work-custody.js +156 -0
  337. package/dist/services/memory-composition-work-results.js +108 -0
  338. package/dist/services/memory-corrected-review-acceptance.js +129 -0
  339. package/dist/services/memory-corrected-review-batch.js +37 -0
  340. package/dist/services/memory-corrected-review-findings.js +108 -0
  341. package/dist/services/memory-corrected-review-inputs.js +215 -0
  342. package/dist/services/memory-corrected-review-projection.js +78 -0
  343. package/dist/services/memory-corrected-review-receipt.js +178 -0
  344. package/dist/services/memory-corrected-review-registration.js +192 -0
  345. package/dist/services/memory-correction-check-receipt.js +235 -0
  346. package/dist/services/memory-correction-input-owner.js +6 -0
  347. package/dist/services/memory-custody-snapshot.js +36 -0
  348. package/dist/services/memory-discover-handler.js +104 -0
  349. package/dist/services/memory-finish-evidence.js +457 -0
  350. package/dist/services/memory-finish-handler.js +229 -0
  351. package/dist/services/memory-finish-integration.js +450 -0
  352. package/dist/services/memory-finish-readiness.js +169 -0
  353. package/dist/services/memory-git-integration.js +220 -0
  354. package/dist/services/memory-historical-corrected-review.js +212 -0
  355. package/dist/services/memory-historical-original-review.js +143 -0
  356. package/dist/services/memory-historical-repair-registration.js +105 -0
  357. package/dist/services/memory-historical-second-review.js +147 -0
  358. package/dist/services/memory-init-bootstrap-readiness.js +210 -0
  359. package/dist/services/memory-init-contexts.js +131 -0
  360. package/dist/services/memory-init-controller-start.js +103 -0
  361. package/dist/services/memory-init-engine-release.js +223 -0
  362. package/dist/services/memory-init-git-policy.js +165 -0
  363. package/dist/services/memory-init-lint-capability.js +203 -0
  364. package/dist/services/memory-init-native-capacity.js +309 -0
  365. package/dist/services/memory-init-preflight.js +334 -0
  366. package/dist/services/memory-init-project-bootstrap.js +599 -0
  367. package/dist/services/memory-init-request-candidate.js +213 -0
  368. package/dist/services/memory-init-request-input.js +82 -0
  369. package/dist/services/memory-init-resource-storage.js +125 -0
  370. package/dist/services/memory-init-run-allocation.js +81 -0
  371. package/dist/services/memory-init-run-bundle.js +135 -0
  372. package/dist/services/memory-init-start.js +181 -0
  373. package/dist/services/memory-init-startup-custody.js +80 -0
  374. package/dist/services/memory-init-startup-input.js +240 -0
  375. package/dist/services/memory-init-storage.js +91 -0
  376. package/dist/services/memory-init-stores.js +359 -0
  377. package/dist/services/memory-init-worktrunk-capability.js +174 -0
  378. package/dist/services/memory-layer-publication.js +611 -0
  379. package/dist/services/memory-layer.js +221 -0
  380. package/dist/services/memory-lint-config.js +194 -0
  381. package/dist/services/memory-native-review-copy.js +103 -0
  382. package/dist/services/memory-normal-flow-entry.js +87 -0
  383. package/dist/services/memory-ordinary-defaults.js +129 -0
  384. package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
  385. package/dist/services/memory-preflight-handler.js +274 -0
  386. package/dist/services/memory-repair-current-view.js +299 -0
  387. package/dist/services/memory-repair-document-delta.js +488 -0
  388. package/dist/services/memory-repair-history.js +496 -0
  389. package/dist/services/memory-repair-physical-binding.js +194 -0
  390. package/dist/services/memory-repair-publication-files.js +152 -0
  391. package/dist/services/memory-repair-publication-intent.js +27 -0
  392. package/dist/services/memory-repair-publication-plan.js +162 -0
  393. package/dist/services/memory-repair-publication-source.js +225 -0
  394. package/dist/services/memory-repair-publication.js +795 -0
  395. package/dist/services/memory-repair-registration.js +240 -0
  396. package/dist/services/memory-repair-work-baseline.js +415 -0
  397. package/dist/services/memory-repair-work-completion.js +117 -0
  398. package/dist/services/memory-repair-work-custody.js +73 -0
  399. package/dist/services/memory-repair-work-results.js +108 -0
  400. package/dist/services/memory-repair-workspace.js +261 -0
  401. package/dist/services/memory-repair-writer-copy.js +736 -0
  402. package/dist/services/memory-result-binding.js +239 -0
  403. package/dist/services/memory-retained-review-authority.js +138 -0
  404. package/dist/services/memory-retained-review-results.js +70 -0
  405. package/dist/services/memory-retained-second-baseline.js +102 -0
  406. package/dist/services/memory-retained-second-repairs.js +162 -0
  407. package/dist/services/memory-review-acceptance.js +214 -0
  408. package/dist/services/memory-review-correction-plan.js +206 -0
  409. package/dist/services/memory-review-handler.js +585 -0
  410. package/dist/services/memory-review-inputs.js +246 -0
  411. package/dist/services/memory-review-limits.js +10 -0
  412. package/dist/services/memory-review-receipt.js +180 -0
  413. package/dist/services/memory-review-registration.js +117 -0
  414. package/dist/services/memory-review-work-custody.js +126 -0
  415. package/dist/services/memory-review-work-input.js +91 -0
  416. package/dist/services/memory-review-work-results.js +95 -0
  417. package/dist/services/memory-second-corrected-review-inputs.js +167 -0
  418. package/dist/services/memory-second-correction-plan.js +77 -0
  419. package/dist/services/memory-second-repair-baseline.js +91 -0
  420. package/dist/services/memory-second-repair-launch.js +614 -0
  421. package/dist/services/memory-second-repair-registration.js +88 -0
  422. package/dist/services/memory-second-repair-source.js +187 -0
  423. package/dist/services/memory-second-review-acceptance.js +115 -0
  424. package/dist/services/memory-source-observations.js +117 -0
  425. package/dist/services/memory-stage-dispatch.js +65 -0
  426. package/dist/services/memory-stage-results.js +290 -0
  427. package/dist/services/memory-tool-probe.js +25 -0
  428. package/dist/services/memory-upgrade-analysis-handler.js +243 -0
  429. package/dist/services/memory-upgrade-bootstrap-readiness.js +251 -0
  430. package/dist/services/memory-upgrade-evidence.js +100 -0
  431. package/dist/services/memory-upgrade-inventory.js +442 -0
  432. package/dist/services/memory-upgrade-publication-custody.js +73 -0
  433. package/dist/services/memory-upgrade-publication.js +413 -0
  434. package/dist/services/memory-upgrade-selection.js +430 -0
  435. package/dist/services/memory-upgrade-start.js +60 -0
  436. package/dist/services/memory-upgrade-storage-readiness.js +340 -0
  437. package/dist/services/memory-verification-acceptance.js +156 -0
  438. package/dist/services/memory-verification-checks.js +317 -0
  439. package/dist/services/memory-verification-receipt.js +160 -0
  440. package/dist/services/memory-verify-handler.js +137 -0
  441. package/dist/services/memory-work-result-json.js +12 -0
  442. package/dist/services/memory-work-result-preparation.js +64 -0
  443. package/dist/services/merge-queue.js +228 -149
  444. package/dist/services/merge-server.js +163 -35
  445. package/dist/services/migrations.js +164 -114
  446. package/dist/services/model-catalog.js +109 -0
  447. package/dist/services/model-discovery.js +46 -0
  448. package/dist/services/native-daemon-history.js +50 -0
  449. package/dist/services/native-session-control.js +39 -0
  450. package/dist/services/operator-profiles.js +236 -0
  451. package/dist/services/physical-startup.js +45 -0
  452. package/dist/services/plan-runtime.js +26 -11
  453. package/dist/services/plans.js +28 -25
  454. package/dist/services/project-registry.js +97 -0
  455. package/dist/services/project-summary.js +1 -1
  456. package/dist/services/projects.js +17 -87
  457. package/dist/services/prompt-delivery.js +71 -0
  458. package/dist/services/prompts.js +28 -17
  459. package/dist/services/protocols.js +163 -87
  460. package/dist/services/provider-capacity.js +455 -0
  461. package/dist/services/recovery-observation-budget.js +121 -0
  462. package/dist/services/recovery-snapshot-database.js +588 -0
  463. package/dist/services/release-archive-producer.js +52 -0
  464. package/dist/services/release-archive.js +143 -0
  465. package/dist/services/release-cache.js +150 -0
  466. package/dist/services/release-compatibility.js +18 -0
  467. package/dist/services/release-download.js +67 -0
  468. package/dist/services/release-envelope.js +104 -0
  469. package/dist/services/release-manifest.js +45 -0
  470. package/dist/services/release-payload.js +114 -0
  471. package/dist/services/release-producer.js +63 -0
  472. package/dist/services/release-provenance.js +160 -0
  473. package/dist/services/release-registry.js +66 -0
  474. package/dist/services/release-source.js +194 -0
  475. package/dist/services/repair-intents.js +31 -0
  476. package/dist/services/repair-receipt.js +13 -0
  477. package/dist/services/review-copy.js +165 -0
  478. package/dist/services/review-deferral.js +23 -0
  479. package/dist/services/run-control-receipt.js +56 -0
  480. package/dist/services/run-control-worker.js +428 -0
  481. package/dist/services/run-control.js +1092 -0
  482. package/dist/services/run-controller-adapter.js +400 -0
  483. package/dist/services/run-controller-capture.js +186 -0
  484. package/dist/services/run-controller-process.js +205 -0
  485. package/dist/services/run-controller-recovery.js +295 -0
  486. package/dist/services/run-controller-state.js +97 -0
  487. package/dist/services/run-controller.js +1326 -0
  488. package/dist/services/run-engine-bindings.js +1 -1
  489. package/dist/services/run-fork.js +147 -0
  490. package/dist/services/run-health.js +149 -0
  491. package/dist/services/run-observations.js +152 -0
  492. package/dist/services/run-projection.js +22 -64
  493. package/dist/services/run-recovery-guard.js +107 -0
  494. package/dist/services/run-recovery-runtime.js +112 -0
  495. package/dist/services/run-recovery.js +456 -0
  496. package/dist/services/run-start-custody.js +189 -0
  497. package/dist/services/runs.js +1023 -246
  498. package/dist/services/runtime-budget.js +446 -0
  499. package/dist/services/runtime-command.js +43 -0
  500. package/dist/services/runtime-scope-capture.js +52 -0
  501. package/dist/services/runtime-scope-control.js +468 -0
  502. package/dist/services/runtime-scope-resume.js +605 -0
  503. package/dist/services/runtime-scope-stop.js +211 -0
  504. package/dist/services/runtime-scope-worker.js +314 -0
  505. package/dist/services/runtime-service.js +19 -14
  506. package/dist/services/schema-validation.js +10 -8
  507. package/dist/services/scope-writer-cleanup.js +27 -0
  508. package/dist/services/sessions.js +36 -91
  509. package/dist/services/setup.js +427 -0
  510. package/dist/services/stage-blocker.js +17 -7
  511. package/dist/services/stage-context.js +193 -19
  512. package/dist/services/stage-handlers.js +89 -0
  513. package/dist/services/stage-lifecycle.js +152 -116
  514. package/dist/services/stage-pause.js +202 -91
  515. package/dist/services/stage-report-renderer.js +234 -6
  516. package/dist/services/stage-work-graph.js +52 -0
  517. package/dist/services/tooling.js +41 -30
  518. package/dist/services/usage.js +49 -101
  519. package/dist/services/verification-matrix.js +393 -0
  520. package/dist/services/version-status.js +1 -1
  521. package/dist/services/vnext-code-review.js +235 -88
  522. package/dist/services/vnext-code.js +327 -226
  523. package/dist/services/vnext-contracts.js +10 -1
  524. package/dist/services/vnext-execution-profile.js +80 -5
  525. package/dist/services/vnext-fanout.js +355 -21
  526. package/dist/services/vnext-merge.js +332 -111
  527. package/dist/services/vnext-plan-review.js +287 -132
  528. package/dist/services/vnext-plan.js +228 -104
  529. package/dist/services/vnext-protocolize.js +533 -95
  530. package/dist/services/vnext-specify.js +123 -81
  531. package/dist/services/vnext-workspace-policy.js +7 -2
  532. package/dist/services/work-registry.js +1706 -200
  533. package/dist/services/workspace-bootstrap.js +53 -15
  534. package/dist/services/workspace-files.js +85 -0
  535. package/dist/services/worktrees.js +105 -48
  536. package/dist/shared/entity-references.js +1 -0
  537. package/dist/shared/errors.js +27 -0
  538. package/dist/storage/agent-output.js +26 -0
  539. package/dist/storage/data-preservation.js +65 -0
  540. package/dist/storage/database.js +930 -40
  541. package/dist/storage/foreign-key-transaction.js +39 -0
  542. package/dist/storage/immutable-input.js +45 -0
  543. package/dist/storage/import-guard.js +159 -0
  544. package/dist/storage/memory-upgrade-schema-bootstrap.js +38 -0
  545. package/dist/storage/native-cleanup.js +52 -0
  546. package/dist/storage/paired-writer-migration.js +424 -0
  547. package/dist/storage/paths.js +17 -4
  548. package/dist/storage/projection-lock.js +73 -0
  549. package/dist/storage/work-references.js +23 -0
  550. package/dist/storage/writer-contract.js +96 -0
  551. package/dist/storage/writer-migration.js +346 -0
  552. package/dist/storage/writer-restore.js +217 -0
  553. package/package.json +50 -13
  554. package/tools/create-canon-release.mjs +33 -0
  555. package/tools/probe-codex-history.mjs +37 -0
  556. package/tools/produce-hybrid-release.mjs +41 -0
  557. package/tools/repair-paused-run-status.mjs +84 -0
@@ -0,0 +1,28 @@
1
+ /** Engine-owned identities shared by inspection and executable registration.
2
+ * Keep this module dependency-free: catalog inspection must not load handlers.
3
+ */
4
+ export const sdlcHandlerIdentities = Object.freeze({
5
+ specify: Object.freeze({ stage: "specify", entryId: "sdlc-specify-entry", finishId: "sdlc-specify-finish" }),
6
+ protocolize: Object.freeze({ stage: "protocolize", entryId: "sdlc-protocolize-entry", finishId: "sdlc-protocolize-finish" }),
7
+ plan: Object.freeze({ stage: "plan", entryId: "sdlc-plan-entry", finishId: "sdlc-plan-finish" }),
8
+ "plan-review": Object.freeze({ stage: "plan-review", entryId: "sdlc-plan-review-entry", finishId: "sdlc-plan-review-finish" }),
9
+ code: Object.freeze({ stage: "code", entryId: "sdlc-code-entry", finishId: "sdlc-code-finish" }),
10
+ "code-review": Object.freeze({ stage: "code-review", entryId: "sdlc-code-review-entry", finishId: "sdlc-code-review-finish" }),
11
+ merge: Object.freeze({ stage: "merge", entryId: "sdlc-merge-entry", finishId: "sdlc-merge-finish" })
12
+ });
13
+ export const memoryInitHandlerIdentities = Object.freeze({
14
+ preflight: Object.freeze({ stage: "preflight", entryId: "memory-stage-entry", finishId: "memory-stage-finish" }),
15
+ discover: Object.freeze({ stage: "discover", entryId: "memory-stage-entry", finishId: "memory-stage-finish" }),
16
+ compose: Object.freeze({ stage: "compose", entryId: "memory-stage-entry", finishId: "memory-stage-finish" }),
17
+ verify: Object.freeze({ stage: "verify", entryId: "memory-stage-entry", finishId: "memory-stage-finish" }),
18
+ review: Object.freeze({ stage: "review", entryId: "memory-stage-entry", finishId: "memory-stage-finish" }),
19
+ finish: Object.freeze({ stage: "finish", entryId: "memory-stage-entry", finishId: "memory-stage-finish" })
20
+ });
21
+ export const memoryUpgradeHandlerIdentities = Object.freeze({
22
+ preflight: Object.freeze({ stage: "preflight", entryId: "memory-upgrade-stage-entry", finishId: "memory-upgrade-stage-finish" }),
23
+ "diff-analysis": Object.freeze({ stage: "diff-analysis", entryId: "memory-upgrade-stage-entry", finishId: "memory-upgrade-stage-finish" }),
24
+ upgrade: Object.freeze({ stage: "upgrade", entryId: "memory-upgrade-stage-entry", finishId: "memory-upgrade-stage-finish" }),
25
+ verify: Object.freeze({ stage: "verify", entryId: "memory-upgrade-stage-entry", finishId: "memory-upgrade-stage-finish" }),
26
+ review: Object.freeze({ stage: "review", entryId: "memory-upgrade-stage-entry", finishId: "memory-upgrade-stage-finish" }),
27
+ finish: Object.freeze({ stage: "finish", entryId: "memory-upgrade-stage-entry", finishId: "memory-upgrade-stage-finish" })
28
+ });
@@ -0,0 +1,112 @@
1
+ # dd-zcode integration boundary
2
+
3
+ `bin/dd-zcode.mjs`, `lib/dd-zcode.mjs` and `lib/dd-zcode-daemon.mjs` implement the
4
+ dd-flow adapter over ACP. The maintained bridge is
5
+ [deksden-com/zcode-acp](https://github.com/deksden-com/zcode-acp), based on upstream
6
+ [william0wang/zcode-acp](https://github.com/william0wang/zcode-acp).
7
+
8
+ | Owner | Responsibility |
9
+ | --- | --- |
10
+ | Upstream bridge | ZCode protocol compatibility, ACP transport, native event translation and general session mechanics. |
11
+ | Downstream bridge extensions | Expose native identity, evidence and control primitives missing upstream; preserve native errors and side-effect semantics. |
12
+ | dd-zcode | Requested/observed profile checks, native-to-dd-flow identity mapping, event normalization, lifecycle forwarding, execution daemon ownership, cancellation/settlement verification and usage forwarding. |
13
+ | dd-flow services | Durable lifecycle decisions, Work/RUN state and usage ingestion/accounting. |
14
+ | dd-eval | Qualify the complete tuple, pin profiles/artifacts and run/monitor evaluations. |
15
+
16
+ Native turn completion is evidence, not proof of semantic Work success. A
17
+ closed transport is not proof that its native descendants stopped. The adapter
18
+ must retain causal errors, missing observations and usage completeness rather
19
+ than turn them into successful/zero-valued results.
20
+
21
+ ## Retained child observations
22
+
23
+ Daemon capability `retained_child_observation` enables `session observe-children`
24
+ for its registered root. It reads retained topology and exact terminal metadata,
25
+ never loads/resumes a child or performs semantic work. During fanout the controller
26
+ records failed child facts before dispatching anything else; healthy in-flight
27
+ siblings may settle normally. Observation polling is not productive model activity.
28
+ Ordinary `session inspect` is not a substitute for this read-only operation.
29
+
30
+ Native attribution is a reported fact, not proof that an HTTP request reached a
31
+ provider. If the native store discarded the causal exception, retain unknown;
32
+ do not scrape ambient logs or infer overload/retry authority from an error message.
33
+
34
+ The bridge marks heuristic ACP completion with
35
+ `_meta.zcodeCompletionEvidence: "inferred"` and exhausted failed turns with
36
+ `"failed"`. dd-zcode rejects these before any post-turn materializing read:
37
+ inferred means `native_outcome_unknown` (not retryable automatically), failed
38
+ means `zcode_turn_not_completed`. This additive evidence does not change the
39
+ acceptance of already-qualified immutable older tuples. Native allocation
40
+ notifications are causal identity evidence, not authorization to replay a turn.
41
+
42
+ ## Bridge contract
43
+
44
+ The identity check uses `--dd-harness-version` (`dd-zcode-harness@1` for existing
45
+ qualified builds, `dd-zcode-harness@2` for the qualified v0.46.7 bridge) and
46
+ `--dd-harness-commit`, alongside native and bridge versions. This is the current
47
+ mechanism, not a general capability negotiation protocol. `zcodeLifecycleQualification`
48
+ also admits exact native-binary SHA / bridge-commit tuples; a new tuple requires
49
+ behavioral evidence before admission. Merely changing an allowlist is not that
50
+ evidence.
51
+
52
+ The adapter consumes `zcode/session/resolve`, `read`, `subagents`, `usage`,
53
+ `close`, `resident` and `retainedSubagents`, plus standard/existing session
54
+ operations. Resolution must preserve the session's trusted workspace.
55
+ Residency and retained-tree reads after close must not implicitly resume it.
56
+ Cancellation must target owned sessions and verify resulting tree state.
57
+ Profile facts must come from native readback. Session updates supply tool events.
58
+ The adapter forwards a standalone public lifecycle command to `dd-flow zcode
59
+ event handle`; native Session/tool identity binds it to the one exact issued
60
+ assignment in that daemon scope. The command never exposes the runtime-owned
61
+ invocation ID. Its shell inherits `DD_FLOW_DAEMON_ID`, finds the assignment and
62
+ waits for the committed receipt before any lifecycle mutation can execute.
63
+
64
+ The execution-scoped daemon preserves the live native handles needed for
65
+ background children. Inspection remains available during productive operations;
66
+ a lost owner cannot be repaired by pretending retained topology is a live tree.
67
+ Keep process identity, native identity and adapter control locator distinct.
68
+
69
+ ## Usage and contract @2
70
+
71
+ The @2 bridge returns native usage unchanged. `lib/zcode-usage.mjs` reads native
72
+ session evidence and computes request counters in the adapter. It deduplicates
73
+ identified requests, rejects conflicting/invalid measurements and records read
74
+ failures as incomplete evidence. Full history is required for cumulative usage;
75
+ turn-liveness history limits must not be applied here. Immutable @1 bridges
76
+ remain supported through their existing measured projection. All adapter usage
77
+ paths use the same helper; dd-flow services still own accounting deltas.
78
+
79
+ Contract support does not admit a new binary/commit tuple automatically. The
80
+ v0.46.7 @2 tuple is admitted for native SHA `500ae84f…f466` or the ZCode
81
+ Desktop 3.14.3 SHA `b1df2ef3…dad529`, with bridge commit `f4d47b5…2833`.
82
+ The latter passed the published beta.99 public-command probe on 2026-09-23:
83
+ root and two concurrent child Work starts/finishes, plus same-child continuation,
84
+ all with durable native identity receipts. Preserve that
85
+ fail-closed distinction when preparing later evals.
86
+
87
+ Future consumer-only retry, recovery, readiness and accounting rules belong
88
+ here or in the owning dd-flow service. Bridge changes are justified when native
89
+ access or protocol mechanics cannot be implemented through its public interface.
90
+ Review existing patches individually; do not claim that all policy has already
91
+ been extracted from the bridge.
92
+
93
+ ## Verification and operations
94
+
95
+ Relevant adapter regressions include `test/zcode-invocation-observer.test.ts`;
96
+ select the additional daemon, usage and lifecycle tests affected by a change.
97
+ Bridge tests check transport facts; adapter tests check their interpretation;
98
+ live qualification checks the actual installed tuple. Release the adapter with
99
+ dd-flow when adapter code or qualification admission changes. A bridge-only
100
+ update does not inherently require an adapter release, but current exact-commit
101
+ admission may require one.
102
+
103
+ Follow the [ZCode upgrade runbook](https://github.com/deksden-com/dd-eval/blob/main/runbooks/update-zcode.md)
104
+ for release discovery, qualification, rollout and rollback. Fork patch maintenance
105
+ is documented in the fork itself. Neither procedure is duplicated here.
106
+
107
+ Adapter changes use short-lived `feat/`, `fix/` or `docs/` branches from `main`,
108
+ reviewed with affected checks before integration (normally squash merge).
109
+ Releases identify verified immutable artifacts, not moving main HEAD. See the
110
+ [cross-repository Git workflow](https://github.com/deksden-com/dd-eval/blob/main/runbooks/git-workflow.md)
111
+ for upgrade ordering, candidate acceptance and hotfixes. Branch-protection
112
+ configuration is separate from this documented policy.
@@ -0,0 +1,24 @@
1
+ OpenCode 2.0.28 Promise client/plugin assets are copied unmodified by the build.
2
+ Source: https://github.com/anomalyco/opencode/tree/v2.0.28
3
+
4
+ MIT License
5
+
6
+ Copyright (c) 2025 opencode
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to deal
10
+ in the Software without restriction, including without limitation the rights
11
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ copies of the Software, and to permit persons to whom the Software is
13
+ furnished to do so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in all
16
+ copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ SOFTWARE.
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ import { adapterTimeoutOptions } from "../lib/adapter-timeouts.mjs";
3
+ import { durableDaemonStart, inspectDaemonOperation, interruptDaemonOperation, settleDaemonOperation } from "../lib/daemon-operations.mjs";
4
+ import { readFile } from "node:fs/promises";
5
+ import { randomUUID } from "node:crypto";
6
+ import path from "node:path";
7
+ import { writeJsonAtomic } from "../lib/runner-events.mjs";
8
+ import { hookBudget, invokeNativeHook, readNativeHookInput } from "../lib/native-hook-command.mjs";
9
+ import { doctor } from "../lib/dd-agy.mjs";
10
+ import { callDaemon, qualifyAgyHooks, serveDaemon, startDaemon, stopDaemon } from "../lib/dd-agy-daemon.mjs";
11
+
12
+ function parse(argv) { const positional = [], options = {}; for (let i = 0; i < argv.length; i += 1) { const token = argv[i]; if (!token.startsWith("--")) { positional.push(token); continue; } const key = token.slice(2); if (["json","cancel-tree","tree","no-flow"].includes(key)) options[key] = true; else { if (argv[i + 1] === undefined) throw new Error(`--${key} requires a value`); options[key] = argv[++i]; } } return { positional, options }; }
13
+ const prompt = async options => options["prompt-file"] ? await readFile(options["prompt-file"], "utf8") : options.prompt;
14
+ async function hook(options) {
15
+ const budget = hookBudget(), requestId = randomUUID();
16
+ const payload = JSON.parse(await readNativeHookInput(process.stdin, budget) || "{}"), event = options.event;
17
+ try {
18
+ const observationMs = budget.remaining("observation");
19
+ const identity = await callDaemon(options["state-dir"], "hook.observe", { event, payload, daemonId: options["daemon-id"], deadlineAt: budget.deadlineAt }, observationMs, requestId);
20
+ if (identity.stale) return event === "PreToolUse" ? { decision: "deny", reason: "agy_stale_hook" } : {};
21
+ if (event === "PreToolUse" || event === "PostToolUse") {
22
+ const phase = event === "PreToolUse" ? "before" : "after", args = payload.toolCall?.args ?? {};
23
+ const normalized = { schema_id: "dd-flow/agy-tool-event@1", event_id: identity.event_id, phase, daemon_id: identity.daemon_id, launch_cwd: identity.launch_cwd, conversation_id: payload.conversationId, parent_conversation_id: identity.parent_conversation_id, execution_num: payload.executionNum, step_index: payload.stepIdx, tool: payload.toolCall?.name, input: args, workspace_paths: payload.workspacePaths, transcript_path: payload.transcriptPath, model: payload.modelName, profile: identity.profile, ...(phase === "after" ? { error: payload.error ?? "" } : {}) };
24
+ await invokeNativeHook({ bin: options["dd-flow-bin"] ?? identity.dd_flow_bin,
25
+ args: ["agy", "event", "handle", "--project-root", options["project-root"] ?? identity.project_root, "--json"],
26
+ payload: normalized, home: options["dd-flow-home"] ?? identity.dd_flow_home, timeoutMs: budget.remaining("admission") });
27
+ }
28
+ return event === "PreToolUse" ? { decision: "allow" } : {};
29
+ } catch (error) {
30
+ // A failed socket cannot be used to report its own failure. The daemon
31
+ // reads only receipts matching request IDs it actually accepted this turn.
32
+ const correctable = event === "PreToolUse" && error.code === "lifecycle_shell_syntax_invalid" && error.details?.effect === "no_effect"
33
+ && error.details?.recoverable === true && error.details?.disposition === "pre_cli_shell_refusal";
34
+ try { await budget.run(() => writeJsonAtomic(path.join(options["state-dir"], "hook-failures", `${requestId}.json`), { request_id: requestId, observed_at: new Date().toISOString(), code: error.code ?? "agy_hook_rejected", message: error.message,
35
+ details: { ...error.details, effect: correctable ? "no_effect" : "unknown", ...(correctable ? { native_pre_cli_refusal: true } : {}) } }, () => budget.remaining("failure_receipt_commit")), "failure_receipt"); }
36
+ catch (storage) { process.stderr.write(`${JSON.stringify({ code: error.code, receipt_error: storage.message })}\n`); }
37
+ throw error;
38
+ }
39
+ }
40
+
41
+ try {
42
+ const { positional, options } = parse(process.argv.slice(2)), [family, command, modifier] = positional; const common = { journal: options.journal, stateDir: options["state-dir"], cwd: options.cwd, bin: options["agy-bin"], provider: options.provider, model: options.model, reasoning: options.reasoning, mode: options.mode, projectRoot: options["project-root"], ddFlowBin: options["dd-flow-bin"], ddFlowHome: options["dd-flow-home"], noFlow: options["no-flow"] === true, ...adapterTimeoutOptions(options, family === "session" ? command : null) }; let result;
43
+ if (family === "doctor") result = await doctor(common);
44
+ else if (family === "hooks" && ["install", "check"].includes(command)) result = await qualifyAgyHooks(common.projectRoot, { stateDir: common.stateDir, install: command === "install" });
45
+ else if (family === "daemon" && command === "start") result = await durableDaemonStart({ ...common, sessionId: options["session-id"], entryPath: process.argv[1] }, startDaemon);
46
+ else if (family === "daemon" && command === "serve") { await serveDaemon(common.stateDir); process.exit(0); }
47
+ else if (family === "daemon" && command === "status") result = await callDaemon(common.stateDir, "daemon.status");
48
+ else if (family === "daemon" && command === "operation" && modifier === "interrupt") result = await interruptDaemonOperation(common.stateDir, options["operation-id"], { control_id: options["control-id"], stop_operation_id: options["stop-operation-id"], daemon_id: options["daemon-id"], session_id: options["session-id"], evidence: options.evidence ? JSON.parse(options.evidence) : null });
49
+ else if (family === "daemon" && command === "operation" && modifier === "settle") result = await settleDaemonOperation(common.stateDir, options["operation-id"]);
50
+ else if (family === "daemon" && command === "operation") result = await inspectDaemonOperation(common.stateDir, options["operation-id"]);
51
+ else if (family === "daemon" && command === "stop") result = await stopDaemon({ stateDir: common.stateDir, cancelTree: options["cancel-tree"], timeoutMs: common.timeoutMs });
52
+ else if (family === "hook" && command === "handle") { process.stdout.write(`${JSON.stringify(await hook(options))}\n`); process.exit(0); }
53
+ else if (family === "session") { if (command === "fork") throw Object.assign(new Error("Antigravity native headless fork is unsupported; use deterministic_replay"), { code: "agy_headless_fork_unsupported" }); const operation = command === "status" ? "inspect" : command; result = await callDaemon(common.stateDir, `session.${operation}`, { sessionId: options["session-id"], livenessTimeoutMs: common.livenessTimeoutMs, ...(command === "create" || command === "prompt" ? { prompt: await prompt(options) } : {}), tree: options.tree === true }, common.timeoutMs ?? 1_800_000); }
54
+ else throw new Error("usage: dd-agy doctor | hooks install|check | daemon start|status|stop | session create|prompt|inspect|resume|cancel|fork [options] --json");
55
+ process.stdout.write(`${JSON.stringify({ ok: true, ...result })}\n`);
56
+ } catch (error) { if (process.argv.includes("hook") && process.argv.includes("handle")) { process.stdout.write(`${JSON.stringify({ decision: "deny", reason: `${error.code ?? "agy_hook_rejected"}: ${error.message ?? "Native hook refused this tool call"}` })}\n`); process.exit(0); } process.stderr.write(`${JSON.stringify({ ok: false, error: error.message, ...(error.code ? { code: error.code, retryable: error.retryable === true, details: error.details } : {}) })}\n`); process.exit(1); }
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ import { adapterTimeoutOptions } from "../lib/adapter-timeouts.mjs";
3
+ import { durableDaemonStart, inspectDaemonOperation, interruptDaemonOperation, settleDaemonOperation } from "../lib/daemon-operations.mjs";
4
+ import { cancelSession, createSession, doctor, inspectSession, promptFromFile, promptSession, startSession } from "../lib/dd-codex.mjs";
5
+ import { callDaemon, serveDaemon, startDaemon, stopDaemon } from "../lib/dd-codex-daemon.mjs";
6
+ import { errorRecord } from "../lib/operation-errors.mjs";
7
+
8
+ function parse(argv) { const positional = []; const options = {}; for (let i = 0; i < argv.length; i += 1) { const token = argv[i]; if (!token.startsWith("--")) { positional.push(token); continue; } const key = token.slice(2); if (["json", "cancel-tree", "no-flow"].includes(key)) { options[key] = true; continue; } const value = argv[++i]; if (value === undefined) throw new Error(`--${key} requires a value`); options[key] = value; } return { positional, options }; }
9
+ function common(options, operation) { return { bin: options["codex-bin"], journal: options.journal, stateDir: options["state-dir"], cwd: options.cwd, sessionId: options["session-id"], turnId: options["turn-id"], model: options.model, reasoning: options.reasoning, ddFlowBin: options["dd-flow-bin"], ddFlowHome: options["dd-flow-home"], projectRoot: options["project-root"], noFlow: options["no-flow"] === true, ...adapterTimeoutOptions(options, operation) }; }
10
+ try {
11
+ const { positional, options } = parse(process.argv.slice(2)); const [family, command, modifier] = positional; const shared = common(options, family === "session" ? command : null); let result;
12
+ if (family === "doctor") result = await doctor(shared);
13
+ else if (family === "daemon" && command === "start") result = await durableDaemonStart({ ...shared, entryPath: process.argv[1] }, startDaemon);
14
+ else if (family === "daemon" && command === "serve") { await serveDaemon(shared.stateDir); process.exit(0); }
15
+ else if (family === "daemon" && command === "status") result = await callDaemon(shared.stateDir, "daemon.status");
16
+ else if (family === "daemon" && command === "operation" && modifier === "interrupt") result = await interruptDaemonOperation(shared.stateDir, options["operation-id"], { control_id: options["control-id"], stop_operation_id: options["stop-operation-id"], daemon_id: options["daemon-id"], session_id: options["session-id"], evidence: options.evidence ? JSON.parse(options.evidence) : null });
17
+ else if (family === "daemon" && command === "operation" && modifier === "settle") result = await settleDaemonOperation(shared.stateDir, options["operation-id"]);
18
+ else if (family === "daemon" && command === "operation") result = await inspectDaemonOperation(shared.stateDir, options["operation-id"]);
19
+ else if (family === "daemon" && command === "stop") result = await stopDaemon({ ...shared, cancelTree: options["cancel-tree"] });
20
+ else if (family === "session" && command === "create") result = shared.stateDir ? await callDaemon(shared.stateDir, "session.create", shared) : await createSession(shared);
21
+ else if (family === "session" && command === "prompt") result = shared.stateDir ? await callDaemon(shared.stateDir, "session.prompt", { ...shared, prompt: options["prompt-file"] ? await promptFromFile(options["prompt-file"]) : options.prompt }, shared.timeoutMs ?? 1_800_000) : await promptSession({ ...shared, prompt: options["prompt-file"] ? await promptFromFile(options["prompt-file"]) : options.prompt });
22
+ else if (family === "session" && command === "start") result = shared.stateDir ? await callDaemon(shared.stateDir, "session.start", { ...shared, prompt: options["prompt-file"] ? await promptFromFile(options["prompt-file"]) : options.prompt }, shared.timeoutMs ?? 30_000) : await startSession({ ...shared, prompt: options["prompt-file"] ? await promptFromFile(options["prompt-file"]) : options.prompt });
23
+ else if (family === "session" && ["inspect", "status", "resume"].includes(command)) result = shared.stateDir ? await callDaemon(shared.stateDir, command === "resume" ? "session.resume" : "session.inspect", shared) : await inspectSession(shared);
24
+ else if (family === "session" && command === "cancel") result = shared.stateDir ? await callDaemon(shared.stateDir, "session.cancel", shared) : await cancelSession(shared);
25
+ else throw new Error("usage: dd-codex doctor | daemon start|status|stop | session create|start|prompt|inspect|status|resume|cancel [--json]");
26
+ process.stdout.write(`${JSON.stringify({ ok: true, ...result })}\n`);
27
+ } catch (error) { const failure = errorRecord(error); process.stderr.write(`${JSON.stringify({ ok: false, error: failure.message, code: failure.code, ...(failure.details ? { details: failure.details } : {}), ...(failure.cause ? { cause: failure.cause } : {}) })}\n`); process.exit(1); }
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ import { adapterTimeoutOptions } from "../lib/adapter-timeouts.mjs";
3
+ import { durableDaemonStart, inspectDaemonOperation, interruptDaemonOperation, settleDaemonOperation } from "../lib/daemon-operations.mjs";
4
+ import { mkdtemp, readFile, rm } from "node:fs/promises";
5
+ import { randomUUID } from "node:crypto";
6
+ import os from "node:os";
7
+ import path from "node:path";
8
+ import { DROID_CONTRACT, DROID_PROTOCOL, DroidRuntime, droidVersion } from "../lib/dd-droid.mjs";
9
+ import { callDaemon, serveDaemon, startDaemon, stopDaemon } from "../lib/dd-droid-daemon.mjs";
10
+ import { errorRecord } from "../lib/operation-errors.mjs";
11
+ import { hookBudget, readNativeHookInput } from "../lib/native-hook-command.mjs";
12
+
13
+ function parse(argv) { const positional = [], options = {}; for (let i = 0; i < argv.length; i++) { const word = argv[i]; if (!word.startsWith("--")) { positional.push(word); continue; } const key = word.slice(2); if (["json", "cancel-tree", "tree", "no-flow"].includes(key)) options[key] = true; else { if (argv[i + 1] === undefined) throw new Error(`${word} requires a value`); options[key] = argv[++i]; } } return { positional, options }; }
14
+ try {
15
+ const { positional: [family, command, modifier], options } = parse(process.argv.slice(2));
16
+ const config = { stateDir: options["state-dir"], sessionId: options["session-id"], cwd: options.cwd, projectRoot: options["project-root"], bin: options["droid-bin"] ?? "droid", entryPath: process.argv[1], journal: options.journal, authHome: options["auth-home"], model: options.model, provider: options.provider, reasoning: options.reasoning, mode: options.mode, ddFlowBin: options["dd-flow-bin"], ddFlowHome: options["dd-flow-home"], noFlow: options["no-flow"] === true, ...adapterTimeoutOptions(options, family === "session" ? command : null, "droid-cli") };
17
+ let result;
18
+ if (family === "doctor") {
19
+ const dir = await mkdtemp(path.join(os.tmpdir(), "dd-droid-doctor-"));
20
+ const runtime = new DroidRuntime({ ...config, stateDir: dir, home: path.join(dir, "home"), cwd: config.cwd ?? process.cwd(), journal: path.join(dir, "events.jsonl"), daemonId: randomUUID(), ddFlowHome: null, ddFlowBin: null }, {}, async () => {});
21
+ try { await runtime.start(); result = { harness: "droid-cli", observed_runtime: { droid: await droidVersion(config.bin), factory_protocol: runtime.protocol, dd_harness_contract: DROID_CONTRACT }, models: runtime.models.map(model => model.id ?? model.modelId), capabilities: { native_children: true, tree_cancel: true, selective_child_cancel: false, native_fork: false }, protocol_expected: DROID_PROTOCOL }; }
22
+ finally { await runtime.closeTree(true); await rm(dir, { recursive: true, force: true }); }
23
+ } else if (family === "daemon" && command === "start") result = await durableDaemonStart(config, startDaemon);
24
+ else if (family === "daemon" && command === "serve") { await serveDaemon(config.stateDir); process.exit(0); }
25
+ else if (family === "daemon" && command === "status") result = await callDaemon(config.stateDir, "daemon.status");
26
+ else if (family === "daemon" && command === "operation" && modifier === "interrupt") result = await interruptDaemonOperation(config.stateDir, options["operation-id"], { control_id: options["control-id"], stop_operation_id: options["stop-operation-id"], daemon_id: options["daemon-id"], session_id: options["session-id"], evidence: options.evidence ? JSON.parse(options.evidence) : null });
27
+ else if (family === "daemon" && command === "operation" && modifier === "settle") result = await settleDaemonOperation(config.stateDir, options["operation-id"]);
28
+ else if (family === "daemon" && command === "operation") result = await inspectDaemonOperation(config.stateDir, options["operation-id"]);
29
+ else if (family === "daemon" && command === "stop") result = await stopDaemon({ stateDir: config.stateDir, cancelTree: options["cancel-tree"] });
30
+ else if (family === "hook" && command === "handle") { const budget = hookBudget(); const payload = JSON.parse(await readNativeHookInput(process.stdin, budget)); const eventId = randomUUID(); result = await callDaemon(config.stateDir, "hook.observe", { payload, eventId, deadlineAt: budget.deadlineAt }, budget.remaining("observation"), eventId); }
31
+ else if (family === "session") { if (command === "fork") throw new Error("Droid fork is not qualified for this adapter"); const prompt = options["prompt-file"] ? await readFile(options["prompt-file"], "utf8") : options.prompt; result = await callDaemon(config.stateDir, `session.${command === "status" ? "inspect" : command}`, { sessionId: options["session-id"], livenessTimeoutMs: config.livenessTimeoutMs, ...(config.noFlow ? { noFlow: true } : {}), ...(prompt ? { prompt } : {}) }); }
32
+ else throw new Error("usage: dd-droid doctor | daemon start|status|operation|stop | session create|resume|prompt|inspect|cancel");
33
+ process.stdout.write(`${JSON.stringify(family === "hook" ? { ...(result.hookSpecificOutput ? { hookSpecificOutput: result.hookSpecificOutput } : {}), ...(typeof result.continue === "boolean" ? { continue: result.continue } : {}), ...(result.stopReason ? { stopReason: result.stopReason } : {}) } : { ok: true, ...result })}\n`);
34
+ } catch (error) { process.stderr.write(`${JSON.stringify({ ok: false, error: errorRecord(error) })}\n`); process.exitCode = process.argv[2] === "hook" ? 2 : 1; }
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env node
2
+ import { adapterTimeoutOptions } from "../lib/adapter-timeouts.mjs";
3
+ import { durableDaemonStart, inspectDaemonOperation, interruptDaemonOperation, settleDaemonOperation } from "../lib/daemon-operations.mjs";
4
+ import { hookBudget, invokeNativeHook, readNativeHookInput, writeNativeHookFailure } from "../lib/native-hook-command.mjs";
5
+ import { cancelSession, createSession, doctor, forkSession, inspectSession, promptFromFile, promptSession } from "../lib/dd-grok.mjs";
6
+ import { callDaemon, serveDaemon, startDaemon, stopDaemon } from "../lib/dd-grok-daemon.mjs";
7
+ import { errorRecord } from "../lib/operation-errors.mjs";
8
+
9
+ function parse(argv) { const positional = []; const options = {}; for (let index = 0; index < argv.length; index += 1) { const token = argv[index]; if (!token.startsWith("--")) { positional.push(token); continue; } const key = token.slice(2); if (["json", "cancel-tree", "no-flow"].includes(key)) { options[key] = true; continue; } const value = argv[++index]; if (value === undefined) throw new Error(`--${key} requires a value`); options[key] = value; } return { positional, options }; }
10
+ function common(options, operation) { return { bin: options["grok-bin"], journal: options.journal, stateDir: options["state-dir"], cwd: options.cwd, sessionId: options["session-id"], model: options.model, reasoning: options.reasoning, mode: options.mode ?? "bypassPermissions", authPath: options["auth-path"], authMethodId: options["auth-method-id"], ddFlowBin: options["dd-flow-bin"], ddFlowHome: options["dd-flow-home"], projectRoot: options["project-root"], sessionArchive: options["session-archive"], noFlow: options["no-flow"] === true, ...adapterTimeoutOptions(options, operation) }; }
11
+ async function hook(options) {
12
+ const budget = hookBudget();
13
+ const stdin = await readNativeHookInput(process.stdin, budget); const payload = JSON.parse(stdin || "{}"); const identity = await callDaemon(options["state-dir"], "hook.resolve", { sessionId: payload.sessionId ?? payload.session_id, payload }, budget.remaining("identity"));
14
+ const enriched = { ...payload, _meta: { ...(payload._meta ?? {}), ddGrok: identity } }; const args = ["grok", "event", "handle", "--project-root", options["project-root"], "--json"]; const command = options["dd-flow-bin"];
15
+ try { return await invokeNativeHook({ bin: command, args, home: options["dd-flow-home"], payload: enriched, timeoutMs: budget.remaining("admission") }); }
16
+ catch (error) {
17
+ if (identity.nativeHookBinding) error.details = { ...error.details, native_hook_binding: identity.nativeHookBinding };
18
+ try {
19
+ await writeNativeHookFailure(options["state-dir"], identity.nativeHookBinding, error, budget);
20
+ if (identity.nativeHookBinding) await callDaemon(options["state-dir"], "hook.failed", { requestId: identity.nativeHookBinding.request_id }, budget.remaining("failure_notification"));
21
+ } catch (storage) { process.stderr.write(`${JSON.stringify({ code: error.code, receipt_error: storage.message })}\n`); }
22
+ throw error;
23
+ }
24
+ }
25
+
26
+ try {
27
+ const { positional, options } = parse(process.argv.slice(2)); const [family, command, modifier] = positional; const shared = common(options, family === "session" ? command : null); let result;
28
+ if (family === "doctor") result = await doctor(shared);
29
+ else if (family === "daemon" && command === "start") result = await durableDaemonStart({ ...shared, entryPath: process.argv[1] }, startDaemon);
30
+ else if (family === "daemon" && command === "serve") { await serveDaemon(shared.stateDir); process.exit(0); }
31
+ else if (family === "daemon" && command === "status") result = await callDaemon(shared.stateDir, "daemon.status");
32
+ else if (family === "daemon" && command === "operation" && modifier === "interrupt") result = await interruptDaemonOperation(shared.stateDir, options["operation-id"], { control_id: options["control-id"], stop_operation_id: options["stop-operation-id"], daemon_id: options["daemon-id"], session_id: options["session-id"], evidence: options.evidence ? JSON.parse(options.evidence) : null });
33
+ else if (family === "daemon" && command === "operation" && modifier === "settle") result = await settleDaemonOperation(shared.stateDir, options["operation-id"]);
34
+ else if (family === "daemon" && command === "operation") result = await inspectDaemonOperation(shared.stateDir, options["operation-id"]);
35
+ else if (family === "daemon" && command === "stop") result = await stopDaemon({ stateDir: shared.stateDir, cancelTree: options["cancel-tree"], timeoutMs: shared.timeoutMs });
36
+ else if (family === "hook" && command === "handle") { process.stdout.write(`${JSON.stringify(await hook(options))}\n`); process.exit(0); }
37
+ else if (family === "session") { const params = { ...shared, ...(command === "create" || command === "prompt" ? { prompt: options["prompt-file"] ? await promptFromFile(options["prompt-file"]) : options.prompt } : {}), ...(command === "fork" ? { target: JSON.parse(options["target-json"] ?? "null") } : {}), ...(command === "archive" ? { archiveDir: options["archive-dir"] } : {}) }; if (shared.stateDir) result = await callDaemon(shared.stateDir, `session.${command === "status" ? "inspect" : command}`, params, shared.timeoutMs ?? 1_800_000); else if (command === "create") result = await createSession(params); else if (command === "prompt") result = await promptSession(params); else if (["inspect", "status", "resume"].includes(command)) result = await inspectSession(params); else if (command === "cancel") result = await cancelSession(params); else if (command === "fork") result = await forkSession(params); else throw new Error(`unknown session command: ${command}`); }
38
+ else throw new Error("usage: dd-grok doctor | daemon start|status|stop | session create|prompt|inspect|status|resume|cancel|fork|archive [options] --json");
39
+ process.stdout.write(`${JSON.stringify({ ok: true, ...result })}\n`);
40
+ } catch (error) { if (process.argv[2] === "hook") { process.stderr.write(`${JSON.stringify({ native_hook_failure: errorRecord(error), bound: Boolean(error.details?.native_hook_binding) })}\n`); process.stdout.write(`${JSON.stringify({ decision: "deny", reason: error.message })}\n`); process.exit(2); } const failure = errorRecord(error); process.stderr.write(`${JSON.stringify({ ok: false, error: failure.message, ...failure })}\n`); process.exit(1); }
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ import { adapterTimeoutOptions } from "../lib/adapter-timeouts.mjs";
3
+ import { durableDaemonStart, inspectDaemonOperation, interruptDaemonOperation, settleDaemonOperation } from "../lib/daemon-operations.mjs";
4
+ import { readFile } from "node:fs/promises";
5
+ import { callDaemon, doctor, openCodeProfileOptions, serveDaemon, startDaemon, stopDaemon } from "../lib/dd-opencode-daemon.mjs";
6
+
7
+ function parse(argv) { const positional = [], options = {}; for (let i = 0; i < argv.length; i += 1) { const token = argv[i]; if (!token.startsWith("--")) { positional.push(token); continue; } const key = token.slice(2); if (["json","cancel-tree","no-flow"].includes(key)) options[key] = true; else { if (argv[i + 1] === undefined) throw new Error(`--${key} requires a value`); options[key] = argv[++i]; } } return { positional, options }; }
8
+ const prompt = async options => options["prompt-file"] ? await readFile(options["prompt-file"], "utf8") : options.prompt;
9
+ try {
10
+ const { positional, options } = parse(process.argv.slice(2)), [family, command, modifier] = positional; const common = { journal: options.journal, stateDir: options["state-dir"], sessionId: options["session-id"], cwd: options.cwd, bin: options["opencode-bin"], provider: options.provider, model: options.model, ...openCodeProfileOptions(options), authPath: options["auth-path"], configPath: options["config-path"], projectRoot: options["project-root"], ddFlowBin: options["dd-flow-bin"], ddFlowHome: options["dd-flow-home"], noFlow: options["no-flow"] === true, sessionArchive: options["session-archive"], ...adapterTimeoutOptions(options, family === "session" ? command : null) }; let result;
11
+ if (family === "daemon" && command === "start") result = await durableDaemonStart({ ...common, entryPath: process.argv[1] }, startDaemon);
12
+ else if (family === "daemon" && command === "serve") { await serveDaemon(common.stateDir); process.exit(0); }
13
+ else if (family === "daemon" && command === "status") result = await callDaemon(common.stateDir, "daemon.status");
14
+ else if (family === "daemon" && command === "operation" && modifier === "interrupt") result = await interruptDaemonOperation(common.stateDir, options["operation-id"], { control_id: options["control-id"], stop_operation_id: options["stop-operation-id"], daemon_id: options["daemon-id"], session_id: options["session-id"], evidence: options.evidence ? JSON.parse(options.evidence) : null });
15
+ else if (family === "daemon" && command === "operation" && modifier === "settle") result = await settleDaemonOperation(common.stateDir, options["operation-id"]);
16
+ else if (family === "daemon" && command === "operation") result = await inspectDaemonOperation(common.stateDir, options["operation-id"]);
17
+ else if (family === "doctor") result = await doctor(common);
18
+ else if (family === "daemon" && command === "stop") result = await stopDaemon({ stateDir: common.stateDir, cancelTree: options["cancel-tree"], timeoutMs: common.timeoutMs });
19
+ else if (family === "session") { const operation = command === "status" ? "inspect" : command; const params = { livenessTimeoutMs: common.livenessTimeoutMs, sessionId: options["session-id"], title: options.title, messageId: options["message-id"], archiveFile: options["archive-file"], ...(command === "prompt" ? { prompt: await prompt(options) } : {}) }; result = await callDaemon(common.stateDir, `session.${operation}`, params, common.timeoutMs ?? 1_800_000); }
20
+ else throw new Error("usage: dd-opencode daemon start|status|stop | session create|prompt|inspect|fork|cancel|archive [options] --json");
21
+ process.stdout.write(`${JSON.stringify({ ok: true, ...result })}\n`);
22
+ } catch (error) { process.stderr.write(`${JSON.stringify({ ok: false, error: error.message, ...(error.code ? { code: error.code, retryable: error.retryable === true, details: error.details } : {}) })}\n`); process.exit(1); }
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ import { adapterTimeoutOptions } from "../lib/adapter-timeouts.mjs";
3
+ import { durableDaemonStart, inspectDaemonOperation, interruptDaemonOperation, settleDaemonOperation } from "../lib/daemon-operations.mjs";
4
+ import { hookBudget, invokeNativeHook, readNativeHookInput, writeNativeHookFailure } from "../lib/native-hook-command.mjs";
5
+ import { cancelChild, cancelSession, createSession, doctor, forkSession, inspectSession, promptFromFile, promptSession } from "../lib/dd-zcode.mjs";
6
+ import { callDaemon, serveDaemon, startDaemon, stopDaemon } from "../lib/dd-zcode-daemon.mjs";
7
+ import { errorRecord } from "../lib/operation-errors.mjs";
8
+
9
+ function parse(argv) {
10
+ const positional = []; const options = {};
11
+ for (let index = 0; index < argv.length; index += 1) {
12
+ const token = argv[index];
13
+ if (!token.startsWith("--")) { positional.push(token); continue; }
14
+ const key = token.slice(2); if (["json", "cancel-tree", "no-flow"].includes(key)) { options[key] = true; continue; }
15
+ const value = argv[++index]; if (value === undefined) throw new Error(`--${key} requires a value`); options[key] = value;
16
+ }
17
+ return { positional, options };
18
+ }
19
+
20
+ function common(options, operation) {
21
+ return {
22
+ bin: options["zcode-acp-bin"], zcodePath: options["zcode-path"], journal: options.journal,
23
+ stateDir: options["state-dir"],
24
+ cwd: options.cwd, sessionId: options["session-id"], adapterSessionId: options["adapter-session-id"], provider: options.provider,
25
+ childSessionId: options["child-session-id"],
26
+ model: options.model, reasoning: options.reasoning, mode: options.mode,
27
+ permission: options.permission ?? "deny", ddFlowBin: options["dd-flow-bin"],
28
+ ddFlowHome: options["dd-flow-home"], projectRoot: options["project-root"], noFlow: options["no-flow"] === true,
29
+ env: options["dd-flow-home"] ? { DD_FLOW_HOME: options["dd-flow-home"] } : undefined,
30
+ ...adapterTimeoutOptions(options, operation),
31
+ };
32
+ }
33
+
34
+ async function hook(options) {
35
+ const budget = hookBudget();
36
+ const payload = JSON.parse((await readNativeHookInput(process.stdin, budget)) || "{}");
37
+ const identity = await callDaemon(options["state-dir"], "hook.resolve", { sessionId: payload.session_id ?? payload.sessionId, payload }, budget.remaining("identity"));
38
+ const command = options["dd-flow-bin"]; const args = ["zcode", "hook", "handle", "--project-root", options["project-root"], "--json"];
39
+
40
+ try { return await invokeNativeHook({ bin: command, args, home: options["dd-flow-home"], timeoutMs: budget.remaining("admission"), payload: { ...payload, _meta: { ...(payload._meta ?? {}), ddZcode: identity } } }); }
41
+ catch (error) {
42
+ if (identity.nativeHookBinding) error.details = { ...error.details, native_hook_binding: identity.nativeHookBinding };
43
+ try {
44
+ // Evidence shares the original deadline; an expired admission cannot
45
+ // start a new independent failure-report window.
46
+ await writeNativeHookFailure(options["state-dir"], identity.nativeHookBinding, error, budget);
47
+ if (identity.nativeHookBinding) await callDaemon(options["state-dir"], "hook.failed", { requestId: identity.nativeHookBinding.request_id }, budget.remaining("failure_notification"));
48
+ } catch (storage) { process.stderr.write(`${JSON.stringify({ code: error.code, receipt_error: storage.message })}\n`); }
49
+ throw error;
50
+ }
51
+ }
52
+
53
+ try {
54
+ const { positional, options } = parse(process.argv.slice(2)); const [family, command, modifier] = positional; let result;
55
+ const answers = options["answers-file"] ? JSON.parse(await promptFromFile(options["answers-file"])) : undefined;
56
+ const shared = common(options, family === "session" ? command : null);
57
+ if (family === "doctor") result = await doctor(shared);
58
+ else if (family === "daemon" && command === "start") result = await durableDaemonStart({ ...shared, entryPath: process.argv[1] }, startDaemon);
59
+ else if (family === "daemon" && command === "serve") { await serveDaemon(shared.stateDir); process.exit(0); }
60
+ else if (family === "daemon" && command === "status") result = await callDaemon(shared.stateDir, "daemon.status");
61
+ else if (family === "daemon" && command === "operation" && modifier === "interrupt") result = await interruptDaemonOperation(shared.stateDir, options["operation-id"], { control_id: options["control-id"], stop_operation_id: options["stop-operation-id"], daemon_id: options["daemon-id"], session_id: options["session-id"], evidence: options.evidence ? JSON.parse(options.evidence) : null });
62
+ else if (family === "daemon" && command === "operation" && modifier === "settle") result = await settleDaemonOperation(shared.stateDir, options["operation-id"]);
63
+ else if (family === "daemon" && command === "operation") result = await inspectDaemonOperation(shared.stateDir, options["operation-id"]);
64
+ else if (family === "daemon" && command === "stop") result = await stopDaemon({ stateDir: shared.stateDir, cancelTree: options["cancel-tree"], timeoutMs: shared.timeoutMs });
65
+ else if (family === "hook" && command === "handle") { process.stdout.write(`${JSON.stringify(await hook(options))}\n`); process.exit(0); }
66
+ else if (family === "session") {
67
+ const params = { ...shared, answers, ...(command === "create" || command === "prompt" ? { prompt: options["prompt-file"] ? await promptFromFile(options["prompt-file"]) : options.prompt } : {}), ...(command === "fork" ? { target: JSON.parse(options["target-json"] ?? "null") } : {}) };
68
+ // The daemon owns the durable native-request deadline. A disposable RPC
69
+ // wait must not manufacture a second provider timeout.
70
+ const operation = `session.${command === "status" ? "inspect" : command}`;
71
+ const rpcTimeout = command === "prompt" && shared.timeoutMs === undefined
72
+ ? null
73
+ : (shared.timeoutMs ?? 1_800_000);
74
+ if (shared.stateDir) result = await callDaemon(shared.stateDir, operation, params, rpcTimeout);
75
+ else if (command === "create") result = await createSession(params);
76
+ else if (command === "prompt") result = await promptSession(params);
77
+ else if (["inspect", "status", "resume"].includes(command)) result = await inspectSession(params);
78
+ else if (command === "cancel") result = await cancelSession(params);
79
+ else if (command === "cancel-child") result = await cancelChild(params);
80
+ else if (command === "fork") result = await forkSession(params);
81
+ else throw new Error(`unknown session command: ${command}`);
82
+ } else throw new Error("usage: dd-zcode doctor | daemon start|status|stop | hook handle | session create|prompt|inspect|status|resume|cancel|cancel-child|fork [options] --json");
83
+ process.stdout.write(`${JSON.stringify({ ok: true, ...result })}\n`);
84
+ } catch (error) {
85
+ if (process.argv[2] === "hook") { process.stderr.write(`${JSON.stringify({ native_hook_failure: errorRecord(error), bound: Boolean(error.details?.native_hook_binding) })}\n`); process.stdout.write(`${JSON.stringify({ decision: "deny", reason: error.message })}\n`); process.exit(2); }
86
+ const failure = errorRecord(error); process.stderr.write(`${JSON.stringify({ ok: false, error: failure.message, ...failure })}\n`); process.exit(1);
87
+ }
@@ -0,0 +1,5 @@
1
+ export const NATIVE_OPERATION_WAIT_CONTRACT: "native-operation-wait@1";
2
+ export function canonicalNativeOperation(harness: string, operation: string): string;
3
+ export function nativeOperationWait(harness: string, operation: string): "native-work" | "control";
4
+ export function validateDaemonWait(harness: string, operation: string, duration: number | null): void;
5
+ export function adapterTimeoutOptions(options: Record<string, unknown>, operation?: string | null, harness?: string): { timeoutMs?: number; livenessTimeoutMs?: number; requestTimeoutMs?: number };
@@ -0,0 +1,34 @@
1
+ // Public work flags express silence, never the lifetime of a native Turn.
2
+ import { validateObservationDuration } from "./observation-clock.mjs";
3
+ export const NATIVE_OPERATION_WAIT_CONTRACT = "native-operation-wait@1";
4
+ // Grok's resume only inspects its retained native Session. Other adapters
5
+ // materialize that Session, so their original operation remains productive.
6
+ export function canonicalNativeOperation(harness, operation) {
7
+ return ["grok", "grok-acp"].includes(harness) && operation === "session.resume" ? "session.inspect" : operation;
8
+ }
9
+ // Only Droid's start waits for the full Turn. Codex start returns acceptance;
10
+ // the other bundled adapters do not expose start as a productive operation.
11
+ export function nativeOperationWait(harness, operation) {
12
+ operation = canonicalNativeOperation(harness, operation);
13
+ return operation === "session.prompt" || ["droid", "droid-cli"].includes(harness) && operation === "session.start" ? "native-work" : "control";
14
+ }
15
+ export function validateDaemonWait(harness, operation, duration) {
16
+ if (duration === null && nativeOperationWait(harness, operation) === "native-work") return;
17
+ validateObservationDuration(duration, "daemon control duration");
18
+ }
19
+
20
+ export function adapterTimeoutOptions(options, operation, harness) {
21
+ const duration = name => {
22
+ if (options[name] === undefined) return undefined;
23
+ const ms = Number(options[name]) * 1_000;
24
+ if (!Number.isInteger(ms) || ms < 1 || ms > 2_147_483_647) throw Object.assign(new Error(`--${name} requires positive finite seconds within the timer range`), { code: "invalid_timeout" });
25
+ return ms;
26
+ };
27
+ const timeoutMs = duration("timeout"), livenessTimeoutMs = duration("liveness-timeout"), requestTimeoutMs = duration("request-timeout");
28
+ if (operation === "prompt" || nativeOperationWait(harness, `session.${operation}`) === "native-work") {
29
+ if (timeoutMs !== undefined && livenessTimeoutMs !== undefined && timeoutMs !== livenessTimeoutMs) throw Object.assign(new Error("--timeout and --liveness-timeout must agree for session.prompt"), { code: "invalid_timeout" });
30
+ if (requestTimeoutMs !== undefined) throw Object.assign(new Error("--request-timeout cannot limit a productive prompt"), { code: "invalid_timeout" });
31
+ return { timeoutMs: undefined, livenessTimeoutMs: livenessTimeoutMs ?? timeoutMs };
32
+ }
33
+ return { timeoutMs, livenessTimeoutMs, requestTimeoutMs };
34
+ }
@@ -0,0 +1,58 @@
1
+ import { parseLifecycleCommand, commandOption, commandPosition } from "./lifecycle-command.mjs";
2
+ import { entityReferenceVariants } from "./entity-references.mjs";
3
+
4
+ /** Ordered native transcript evidence, never assistant text as a success signal. */
5
+ export function recoveredAgyErrorBoundary(text, error, floor = -1) {
6
+ let rows;
7
+ try { rows = text.trim().split("\n").filter(Boolean).map(JSON.parse); } catch { return null; }
8
+ let previous = -1, lastError = null, boundary = null, invocation = null;
9
+ for (const row of rows) {
10
+ if (!Number.isInteger(row.step_index) || row.step_index <= previous) return null;
11
+ previous = row.step_index;
12
+ if (row.step_index <= (floor ?? -1)) continue;
13
+ if (row.type === "USER_INPUT") { lastError = null; boundary = null; invocation = null; continue; }
14
+ if (row.type === "ERROR_MESSAGE") { lastError = row; boundary = null; invocation = null; continue; }
15
+ if (Array.isArray(row.tool_calls)) {
16
+ invocation = null;
17
+ if (row.tool_calls.length === 1 && row.tool_calls[0]?.name === "run_command") {
18
+ let command = row.tool_calls[0]?.args?.CommandLine;
19
+ if (typeof command === "string") {
20
+ try { const unquoted = JSON.parse(command); if (typeof unquoted === "string") command = unquoted; } catch { /* ordinary shell bytes */ }
21
+ const parsed = parseLifecycleCommand(command);
22
+ if ((parsed.kind === "standalone" || parsed.kind === "compound" && parsed.supported === true && parsed.invocations?.length === 1) && ["stage_finish", "work_finish", "stage_pause", "recovery_accept"].includes(parsed.invocation.operation)) invocation = parsed.invocation;
23
+ }
24
+ }
25
+ }
26
+ if (!lastError || row.type !== "GENERIC" || row.status !== "DONE" || typeof row.content !== "string" || !row.content.includes("Command exited with code 0.")) continue;
27
+ const output = row.content.split("Command output:\n")[1]?.replaceAll("\r", "");
28
+ if (!output) continue;
29
+ for (const match of output.matchAll(/^\s*\{/gm)) {
30
+ let receipt;
31
+ const candidate = output.slice(match.index).trim();
32
+ try { receipt = JSON.parse(candidate); } catch {
33
+ // AGY's transcript renderer can unescape control characters inside
34
+ // pause.user_message. Parse only the intact machine header, never the
35
+ // rendered question; the controller must still verify the DB receipt.
36
+ const end = candidate.indexOf(',\n "user_message":');
37
+ if (end < 0) continue;
38
+ try { receipt = JSON.parse(`${candidate.slice(0, end)}}}`); } catch { continue; }
39
+ }
40
+ if (receipt.ok === true && invocation && invocation.operation !== "stage_pause") {
41
+ if (invocation.operation === "recovery_accept" && receipt.accepted === true && typeof receipt.recovery_id === "string") boundary = { receipt: { ok: true, outcome: "completed", lifecycle_operation: "recovery_accept", recovery_id: receipt.recovery_id }, error_step: lastError.step_index, boundary_step: row.step_index };
42
+ const stage = receipt.stage ?? commandOption(invocation, "stage");
43
+ const runId = receipt.run_id;
44
+ const workId = receipt.work_id ?? receipt.work?.work_id ?? commandOption(invocation, "work") ?? (invocation.operation === "work_finish" ? commandPosition(invocation, 0) : null);
45
+ if (invocation.operation === "work_finish" && receipt.status === "completed" && typeof workId === "string") boundary = { receipt: { ok: true, outcome: "completed", work_id: workId, lifecycle_operation: "work_finish" }, error_step: lastError.step_index, boundary_step: row.step_index };
46
+ if (typeof stage === "string" && typeof runId === "string" && (invocation.operation === "work_finish" || entityReferenceVariants(runId).includes(commandPosition(invocation, 0)))) {
47
+ boundary = { receipt: { ok: true, outcome: "completed", run_id: runId, stage, ...(workId ? { work_id: workId } : {}), lifecycle_operation: invocation.operation }, error_step: lastError.step_index, boundary_step: row.step_index };
48
+ }
49
+ }
50
+ if (invocation?.operation === "stage_pause" && commandOption(invocation, "stage") === receipt.stage && receipt.ok === true && receipt.outcome === "paused"
51
+ && [receipt.run_id, receipt.stage, receipt.work_id].every(value => typeof value === "string" && value)
52
+ && (receipt.outcome !== "paused" || typeof receipt.pause?.id === "string")) boundary = { receipt: { ok: true, outcome: receipt.outcome, run_id: receipt.run_id, stage: receipt.stage, work_id: receipt.work_id,
53
+ lifecycle_operation: "stage_pause", pause: { id: receipt.pause.id } }, error_step: lastError.step_index, boundary_step: row.step_index };
54
+ }
55
+ }
56
+ return boundary && lastError?.error === error ? boundary : null;
57
+ }
58
+
@@ -0,0 +1 @@
1
+ export function agyWorkspaceHooks(): Record<string, unknown>;
@@ -0,0 +1,9 @@
1
+ // Qualified hooks are stable; only the launching process selects its pinned
2
+ // entrypoint and daemon. Keep this document shared with product-file policy.
3
+ export function agyWorkspaceHooks() {
4
+ const command = '"${DD_AGY_HOOK_NODE:?missing AGY hook binding}" "${DD_AGY_HOOK_ENTRY:?missing AGY hook binding}" hook handle --event __EVENT__ --state-dir "${DD_AGY_STATE_DIR:?missing AGY hook binding}" --daemon-id "${DD_AGY_DAEMON_ID:?missing AGY hook binding}" --json';
5
+ return { "dd-flow": {
6
+ PreToolUse: [{ matcher: "^run_command$", hooks: [{ type: "command", command: command.replace("__EVENT__", "PreToolUse"), timeout: 30 }] }],
7
+ Stop: [{ type: "command", command: command.replace("__EVENT__", "Stop"), timeout: 30 }]
8
+ } };
9
+ }