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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (670) hide show
  1. package/CHANGELOG.md +959 -0
  2. package/README.md +139 -10
  3. package/dist/build-info.json +8 -8
  4. package/dist/cli/argument-values.js +38 -0
  5. package/dist/cli/command-inputs.js +417 -0
  6. package/dist/cli/command-metadata.js +303 -0
  7. package/dist/cli/command-option-descriptions.js +192 -0
  8. package/dist/cli/completion-cli.js +70 -0
  9. package/dist/cli/completion.js +57 -0
  10. package/dist/cli/delivery.js +108 -0
  11. package/dist/cli/diagnostic-invocation.js +62 -0
  12. package/dist/cli/diagnostic.js +131 -0
  13. package/dist/cli/error-output.js +62 -0
  14. package/dist/cli/executor-onboarding.js +76 -0
  15. package/dist/cli/flows.js +29 -0
  16. package/dist/cli/harnesses.js +84 -0
  17. package/dist/cli/help.js +521 -19
  18. package/dist/cli/hook-ingress.js +89 -0
  19. package/dist/cli/input-preparation.js +193 -0
  20. package/dist/cli/interactive-invocation.js +33 -0
  21. package/dist/cli/interactive.js +114 -0
  22. package/dist/cli/memory-fix-invocation.js +52 -0
  23. package/dist/cli/memory-fix.js +100 -0
  24. package/dist/cli/memory-flow-admission.js +54 -0
  25. package/dist/cli/memory-init-invocation.js +85 -0
  26. package/dist/cli/memory-init.js +250 -0
  27. package/dist/cli/memory-storage-admission.js +54 -0
  28. package/dist/cli/memory-storage-qualification.js +105 -0
  29. package/dist/cli/memory-storage-transition.js +123 -0
  30. package/dist/cli/memory-upgrade.js +189 -0
  31. package/dist/cli/models.js +39 -0
  32. package/dist/cli/native-hook-ingress.js +94 -0
  33. package/dist/cli/native-hook-preparation.js +82 -0
  34. package/dist/cli/operator-profiles.js +61 -0
  35. package/dist/cli/output-options.js +35 -0
  36. package/dist/cli/response-file.js +72 -0
  37. package/dist/cli/run-cli.js +2020 -555
  38. package/dist/cli/runtime-maintenance-diagnostics.js +46 -0
  39. package/dist/cli/runtime-maintenance-ingress.js +52 -0
  40. package/dist/cli/runtime-process.js +153 -0
  41. package/dist/cli/setup.js +150 -0
  42. package/dist/cli.js +103 -2
  43. package/dist/domain/delivery-flows.js +8 -0
  44. package/dist/domain/diagnostic-aspects.js +103 -0
  45. package/dist/domain/diagnostic-flows.js +8 -0
  46. package/dist/domain/distill-flow.js +20 -0
  47. package/dist/domain/interactive-flow.js +1 -0
  48. package/dist/domain/memory-fix-flow.js +2 -0
  49. package/dist/domain/review-fix-flow.js +2 -0
  50. package/dist/domain/source-snapshot-flows.js +4 -0
  51. package/dist/domain/stage-catalog.js +1 -1
  52. package/dist/domain/stage-handler-identities.js +28 -0
  53. package/dist/harness-runtime/DD-ZCODE.md +112 -0
  54. package/dist/harness-runtime/OPENCODE-LICENSE.txt +24 -0
  55. package/dist/harness-runtime/bin/dd-agy.mjs +71 -0
  56. package/dist/harness-runtime/bin/dd-codex.mjs +27 -0
  57. package/dist/harness-runtime/bin/dd-droid.mjs +34 -0
  58. package/dist/harness-runtime/bin/dd-grok.mjs +50 -0
  59. package/dist/harness-runtime/bin/dd-opencode.mjs +22 -0
  60. package/dist/harness-runtime/bin/dd-zcode.mjs +95 -0
  61. package/dist/harness-runtime/lib/adapter-timeouts.d.mts +5 -0
  62. package/dist/harness-runtime/lib/adapter-timeouts.mjs +34 -0
  63. package/dist/harness-runtime/lib/agy-error-boundary.mjs +87 -0
  64. package/dist/harness-runtime/lib/agy-hooks.d.mts +1 -0
  65. package/dist/harness-runtime/lib/agy-hooks.mjs +9 -0
  66. package/dist/harness-runtime/lib/agy-native-inspection.mjs +225 -0
  67. package/dist/harness-runtime/lib/agy-native-inventory.mjs +19 -0
  68. package/dist/harness-runtime/lib/agy-native_pb.js +117 -0
  69. package/dist/harness-runtime/lib/agy-terminal-envelope.mjs +74 -0
  70. package/dist/harness-runtime/lib/agy-transcript-stream.mjs +54 -0
  71. package/dist/harness-runtime/lib/daemon-observation.d.mts +3 -0
  72. package/dist/harness-runtime/lib/daemon-observation.mjs +171 -0
  73. package/dist/harness-runtime/lib/daemon-operations.d.mts +2 -0
  74. package/dist/harness-runtime/lib/daemon-operations.mjs +512 -0
  75. package/dist/harness-runtime/lib/dd-agy-daemon.d.mts +7 -0
  76. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +1362 -0
  77. package/dist/harness-runtime/lib/dd-agy.mjs +105 -0
  78. package/dist/harness-runtime/lib/dd-codex-daemon.d.mts +1 -0
  79. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +271 -0
  80. package/dist/harness-runtime/lib/dd-codex.d.mts +1 -0
  81. package/dist/harness-runtime/lib/dd-codex.mjs +986 -0
  82. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +155 -0
  83. package/dist/harness-runtime/lib/dd-droid.mjs +739 -0
  84. package/dist/harness-runtime/lib/dd-grok-daemon.d.mts +1 -0
  85. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +667 -0
  86. package/dist/harness-runtime/lib/dd-grok.mjs +182 -0
  87. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +772 -0
  88. package/dist/harness-runtime/lib/dd-opencode.mjs +411 -0
  89. package/dist/harness-runtime/lib/dd-zcode-daemon.d.mts +1 -0
  90. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +845 -0
  91. package/dist/harness-runtime/lib/dd-zcode.mjs +1239 -0
  92. package/dist/harness-runtime/lib/delegation-instructions.d.mts +16 -0
  93. package/dist/harness-runtime/lib/delegation-instructions.mjs +179 -0
  94. package/dist/harness-runtime/lib/delivery-command.mjs +84 -0
  95. package/dist/harness-runtime/lib/dispatch-fence.mjs +14 -0
  96. package/dist/harness-runtime/lib/driver-recovery.mjs +121 -0
  97. package/dist/harness-runtime/lib/droid-observation.mjs +70 -0
  98. package/dist/harness-runtime/lib/entity-references.d.mts +2 -0
  99. package/dist/harness-runtime/lib/entity-references.mjs +9 -0
  100. package/dist/harness-runtime/lib/lease-renewal.d.mts +8 -0
  101. package/dist/harness-runtime/lib/lease-renewal.mjs +37 -0
  102. package/dist/harness-runtime/lib/lifecycle-command.d.mts +20 -0
  103. package/dist/harness-runtime/lib/lifecycle-command.mjs +273 -0
  104. package/dist/harness-runtime/lib/lifecycle-contract.d.mts +11 -0
  105. package/dist/harness-runtime/lib/lifecycle-contract.mjs +20 -0
  106. package/dist/harness-runtime/lib/managed-daemon.d.mts +16 -0
  107. package/dist/harness-runtime/lib/managed-daemon.mjs +698 -0
  108. package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
  109. package/dist/harness-runtime/lib/model-observations.mjs +113 -0
  110. package/dist/harness-runtime/lib/native-children.d.mts +34 -0
  111. package/dist/harness-runtime/lib/native-children.mjs +265 -0
  112. package/dist/harness-runtime/lib/native-hook-command.d.mts +8 -0
  113. package/dist/harness-runtime/lib/native-hook-command.mjs +306 -0
  114. package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
  115. package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
  116. package/dist/harness-runtime/lib/native-streams.mjs +38 -0
  117. package/dist/harness-runtime/lib/observation-clock.d.mts +18 -0
  118. package/dist/harness-runtime/lib/observation-clock.mjs +95 -0
  119. package/dist/harness-runtime/lib/opencode-plugin.mjs +112 -0
  120. package/dist/harness-runtime/lib/operation-context.mjs +5 -0
  121. package/dist/harness-runtime/lib/operation-errors.d.mts +16 -0
  122. package/dist/harness-runtime/lib/operation-errors.mjs +140 -0
  123. package/dist/harness-runtime/lib/operation-progress.d.mts +7 -0
  124. package/dist/harness-runtime/lib/operation-progress.mjs +118 -0
  125. package/dist/harness-runtime/lib/process-json.d.mts +5 -0
  126. package/dist/harness-runtime/lib/process-json.mjs +200 -0
  127. package/dist/harness-runtime/lib/process-snapshot.mjs +10 -0
  128. package/dist/harness-runtime/lib/provider-overload-policy.d.mts +23 -0
  129. package/dist/harness-runtime/lib/provider-overload-policy.mjs +242 -0
  130. package/dist/harness-runtime/lib/runner-events.mjs +202 -0
  131. package/dist/harness-runtime/lib/runner-lock.mjs +42 -0
  132. package/dist/harness-runtime/lib/session-settlement.mjs +30 -0
  133. package/dist/harness-runtime/lib/setup-progress.d.mts +9 -0
  134. package/dist/harness-runtime/lib/setup-progress.mjs +53 -0
  135. package/dist/harness-runtime/lib/tool-observations.d.mts +21 -0
  136. package/dist/harness-runtime/lib/tool-observations.mjs +238 -0
  137. package/dist/harness-runtime/lib/zcode-native-hook-ownership.mjs +109 -0
  138. package/dist/harness-runtime/lib/zcode-usage.mjs +55 -0
  139. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-1y4a697q.js +81 -0
  140. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-2ny4vxct.js +92 -0
  141. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-6mptkzbc.js +0 -0
  142. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-7x67cf1q.js +52 -0
  143. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9rqn6x4v.js +16 -0
  144. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9vdz0zwn.js +1661 -0
  145. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ecs5ftka.js +1466 -0
  146. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-frbwqjmf.js +145 -0
  147. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gne7h7mq.js +50 -0
  148. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gx9wnkzr.js +105 -0
  149. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-m2eywc8w.js +0 -0
  150. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-nwcpakzx.js +12 -0
  151. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-q4g3afnw.js +623 -0
  152. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-qav6mfdz.js +0 -0
  153. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-sxt88q69.js +12 -0
  154. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-t1xa31vm.js +39 -0
  155. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ve4aws36.js +103 -0
  156. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vmytr4q8.js +4 -0
  157. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vt9jbch8.js +36 -0
  158. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vyas3vgt.js +0 -0
  159. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-wjyeq25y.js +30 -0
  160. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-xgnj2w4v.js +20 -0
  161. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-y2etg5bs.js +9 -0
  162. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ydhz1zrh.js +238 -0
  163. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-z6qdwcsf.js +62 -0
  164. package/dist/harness-runtime/vendor/opencode-client/contract.d.ts +1 -0
  165. package/dist/harness-runtime/vendor/opencode-client/contract.js +12 -0
  166. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.d.ts +2806 -0
  167. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.js +0 -0
  168. package/dist/harness-runtime/vendor/opencode-client/effect/api.d.ts +4 -0
  169. package/dist/harness-runtime/vendor/opencode-client/effect/api.js +0 -0
  170. package/dist/harness-runtime/vendor/opencode-client/effect/client.d.ts +2530 -0
  171. package/dist/harness-runtime/vendor/opencode-client/effect/client.js +15 -0
  172. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.d.ts +7 -0
  173. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.js +6 -0
  174. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.d.ts +2529 -0
  175. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.js +8 -0
  176. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.d.ts +2 -0
  177. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.js +12 -0
  178. package/dist/harness-runtime/vendor/opencode-client/effect/index.d.ts +35 -0
  179. package/dist/harness-runtime/vendor/opencode-client/effect/index.js +75 -0
  180. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.d.ts +20 -0
  181. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.js +11 -0
  182. package/dist/harness-runtime/vendor/opencode-client/effect/service.d.ts +90 -0
  183. package/dist/harness-runtime/vendor/opencode-client/effect/service.js +187 -0
  184. package/dist/harness-runtime/vendor/opencode-client/package.json +84 -0
  185. package/dist/harness-runtime/vendor/opencode-client/promise/api.d.ts +21 -0
  186. package/dist/harness-runtime/vendor/opencode-client/promise/api.js +0 -0
  187. package/dist/harness-runtime/vendor/opencode-client/promise/client.d.ts +252 -0
  188. package/dist/harness-runtime/vendor/opencode-client/promise/client.js +14 -0
  189. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.d.ts +8 -0
  190. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.js +6 -0
  191. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.d.ts +259 -0
  192. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.js +7 -0
  193. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.d.ts +3 -0
  194. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.js +79 -0
  195. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.d.ts +8932 -0
  196. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.js +70 -0
  197. package/dist/harness-runtime/vendor/opencode-client/promise/index.d.ts +6 -0
  198. package/dist/harness-runtime/vendor/opencode-client/promise/index.js +83 -0
  199. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.d.ts +32 -0
  200. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.js +7 -0
  201. package/dist/harness-runtime/vendor/opencode-client/promise/service.d.ts +24 -0
  202. package/dist/harness-runtime/vendor/opencode-client/promise/service.js +187 -0
  203. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.d.ts +12 -0
  204. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.js +14 -0
  205. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.d.ts +20 -0
  206. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.js +14 -0
  207. package/dist/harness-runtime/vendor/opencode-client/service-contender.d.ts +37 -0
  208. package/dist/harness-runtime/vendor/opencode-client/service-contender.js +10 -0
  209. package/dist/harness-runtime/vendor/opencode-client/service-probe.d.ts +70 -0
  210. package/dist/harness-runtime/vendor/opencode-client/service-probe.js +16 -0
  211. package/dist/harness-runtime/vendor/opencode-client/service-timing.d.ts +12 -0
  212. package/dist/harness-runtime/vendor/opencode-client/service-timing.js +10 -0
  213. package/dist/harness-runtime/vendor/opencode-client/service-version.d.ts +2 -0
  214. package/dist/harness-runtime/vendor/opencode-client/service-version.js +6 -0
  215. package/dist/harness-runtime/vendor/opencode-client/service.d.ts +52 -0
  216. package/dist/harness-runtime/vendor/opencode-client/service.js +1 -0
  217. package/dist/harness-runtime/vendor/opencode-client/shared-events.d.ts +11 -0
  218. package/dist/harness-runtime/vendor/opencode-client/shared-events.js +8 -0
  219. package/dist/harness-runtime/vendor/opencode-client/solid/connection.d.ts +37 -0
  220. package/dist/harness-runtime/vendor/opencode-client/solid/connection.js +10 -0
  221. package/dist/harness-runtime/vendor/opencode-client/solid/data.d.ts +211 -0
  222. package/dist/harness-runtime/vendor/opencode-client/solid/data.js +18 -0
  223. package/dist/harness-runtime/vendor/opencode-client/solid/index.d.ts +3 -0
  224. package/dist/harness-runtime/vendor/opencode-client/solid/index.js +32 -0
  225. package/dist/harness-runtime/vendor/opencode-client/solid/pty.d.ts +22 -0
  226. package/dist/harness-runtime/vendor/opencode-client/solid/pty.js +8 -0
  227. package/dist/harness-runtime/vendor/opencode-plugin.mjs +3 -0
  228. package/dist/protocol/local-files.js +18 -9
  229. package/dist/runtime/context.js +8 -4
  230. package/dist/schemas/agent-profile.schema.json +1 -1
  231. package/dist/schemas/code-review-decision.schema.json +9 -0
  232. package/dist/schemas/code-review-result.schema.json +1 -1
  233. package/dist/schemas/code-verification.schema.json +7 -5
  234. package/dist/schemas/code-work-batch.schema.json +2 -2
  235. package/dist/schemas/code-work-result.schema.json +2 -1
  236. package/dist/schemas/delivery-stage-result.schema.json +286 -0
  237. package/dist/schemas/diagnostic-stage-result.schema.json +354 -0
  238. package/dist/schemas/diagnostic-work-result.schema.json +296 -0
  239. package/dist/schemas/discovery-result.schema.json +184 -0
  240. package/dist/schemas/distill-stage-result.schema.json +667 -0
  241. package/dist/schemas/distill-work-result.schema.json +428 -0
  242. package/dist/schemas/execution-bundle.schema.json +215 -0
  243. package/dist/schemas/execution-settings.schema.json +162 -0
  244. package/dist/schemas/flow-descriptor.schema.json +54 -0
  245. package/dist/schemas/flow-run.schema.json +29 -0
  246. package/dist/schemas/harness-catalog.schema.json +80 -0
  247. package/dist/schemas/interactive-stage-result.schema.json +47 -0
  248. package/dist/schemas/interactive-work-result.schema.json +63 -0
  249. package/dist/schemas/mb-fix-stage-result.schema.json +93 -0
  250. package/dist/schemas/mb-init-compose-result.schema.json +457 -0
  251. package/dist/schemas/mb-init-discover-result.schema.json +500 -0
  252. package/dist/schemas/mb-init-finish-result.schema.json +422 -0
  253. package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
  254. package/dist/schemas/mb-init-review-result.schema.json +396 -0
  255. package/dist/schemas/mb-init-verify-result.schema.json +391 -0
  256. package/dist/schemas/mb-upgrade-stage-result.schema.json +863 -0
  257. package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
  258. package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
  259. package/dist/schemas/memory-composition-work-result.schema.json +38 -0
  260. package/dist/schemas/memory-repair-work-result.schema.json +56 -0
  261. package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
  262. package/dist/schemas/memory-review-work-result.schema.json +43 -0
  263. package/dist/schemas/model-catalog.schema.json +153 -0
  264. package/dist/schemas/plan-review-decision.schema.json +12 -3
  265. package/dist/schemas/plan-review-result.schema.json +2 -2
  266. package/dist/schemas/profile-settings.schema.json +122 -0
  267. package/dist/schemas/project-flow-pack-manifest.schema.json +2 -2
  268. package/dist/schemas/release-impact.schema.json +3 -3
  269. package/dist/schemas/release-manifest.schema.json +291 -0
  270. package/dist/schemas/review-fix-stage-result.schema.json +210 -0
  271. package/dist/schemas/run-control-receipt.schema.json +119 -0
  272. package/dist/schemas/run-control-request.schema.json +36 -0
  273. package/dist/schemas/run-engine-binding.schema.json +1 -1
  274. package/dist/schemas/stage-start-response.schema.json +4 -0
  275. package/dist/schemas/vnext-protocol-plan.schema.json +3 -3
  276. package/dist/services/accepted-intent.js +139 -0
  277. package/dist/services/assigned-lifecycle.js +382 -0
  278. package/dist/services/branch-context.js +3 -3
  279. package/dist/services/canon.js +54 -15
  280. package/dist/services/check-environment.js +21 -0
  281. package/dist/services/check-runner-evidence.js +344 -0
  282. package/dist/services/check-runner-proof.js +373 -0
  283. package/dist/services/cleanup.js +133 -40
  284. package/dist/services/cli-operation-classifier.js +32 -64
  285. package/dist/services/cli-upgrade-allowlist.js +27 -0
  286. package/dist/services/code-checks.js +1426 -121
  287. package/dist/services/codex-capacity.js +367 -0
  288. package/dist/services/codex-hook-delivery.js +41 -0
  289. package/dist/services/command-context.js +80 -0
  290. package/dist/services/compatibility-preflight.js +16 -3
  291. package/dist/services/config.js +11 -8
  292. package/dist/services/continuation-outcome.js +25 -0
  293. package/dist/services/controller-child-capacity.js +71 -0
  294. package/dist/services/controller-child-observer.js +121 -0
  295. package/dist/services/controller-child-repair.js +117 -0
  296. package/dist/services/controller-execution.js +97 -0
  297. package/dist/services/controller-fanout.js +277 -0
  298. package/dist/services/controller-memory-task.js +45 -0
  299. package/dist/services/controller-memory-worker.js +51 -0
  300. package/dist/services/controller-result-authority.js +127 -0
  301. package/dist/services/controller-work-failure.js +198 -0
  302. package/dist/services/dashboard.js +145 -58
  303. package/dist/services/delivery-access.js +123 -0
  304. package/dist/services/delivery-approval.js +68 -0
  305. package/dist/services/delivery-artifact.js +86 -0
  306. package/dist/services/delivery-checks.js +178 -0
  307. package/dist/services/delivery-execution.js +181 -0
  308. package/dist/services/delivery-intents.js +212 -0
  309. package/dist/services/delivery-operation.js +81 -0
  310. package/dist/services/delivery-policy.js +91 -0
  311. package/dist/services/delivery-procedures.js +43 -0
  312. package/dist/services/delivery-request.js +99 -0
  313. package/dist/services/delivery-result.js +144 -0
  314. package/dist/services/delivery-stage-commands.js +26 -0
  315. package/dist/services/delivery-stage-entry.js +56 -0
  316. package/dist/services/delivery-stage-handlers.js +135 -0
  317. package/dist/services/delivery-stage-results.js +94 -0
  318. package/dist/services/descriptor-coordinator-session.js +37 -0
  319. package/dist/services/descriptor-root-work.js +53 -0
  320. package/dist/services/descriptor-run-settlement.js +107 -0
  321. package/dist/services/descriptor-run-start.js +495 -0
  322. package/dist/services/descriptor-stage-coordinator.js +318 -0
  323. package/dist/services/descriptor-stage-settlement.js +268 -0
  324. package/dist/services/descriptor-stage-start.js +175 -0
  325. package/dist/services/diagnostic-evidence.js +73 -0
  326. package/dist/services/diagnostic-repair-intake.js +123 -0
  327. package/dist/services/diagnostic-repair-source-intake.js +102 -0
  328. package/dist/services/diagnostic-report-publication.js +72 -0
  329. package/dist/services/diagnostic-report.js +97 -0
  330. package/dist/services/diagnostic-run-bundle.js +113 -0
  331. package/dist/services/diagnostic-snapshot.js +159 -0
  332. package/dist/services/diagnostic-stage-handlers.js +109 -0
  333. package/dist/services/diagnostic-stage-results.js +158 -0
  334. package/dist/services/diagnostic-start.js +134 -0
  335. package/dist/services/diagnostic-work-batch.js +34 -0
  336. package/dist/services/diagnostic-work-collection.js +97 -0
  337. package/dist/services/diagnostic-work-registration.js +101 -0
  338. package/dist/services/diagnostic-work-results.js +93 -0
  339. package/dist/services/discovery/agy-discovery.js +2 -0
  340. package/dist/services/discovery/codex-discovery.js +2 -0
  341. package/dist/services/discovery/droid-discovery.js +2 -0
  342. package/dist/services/discovery/grok-discovery.js +2 -0
  343. package/dist/services/discovery/opencode-discovery.js +2 -0
  344. package/dist/services/discovery/static.js +31 -0
  345. package/dist/services/discovery/zcode-discovery.js +2 -0
  346. package/dist/services/distill-document-publication.js +280 -0
  347. package/dist/services/distill-promotion.js +197 -0
  348. package/dist/services/distill-publication-custody.js +162 -0
  349. package/dist/services/distill-stage-handlers.js +249 -0
  350. package/dist/services/distill-stage-results.js +105 -0
  351. package/dist/services/distill-user-inputs.js +4 -0
  352. package/dist/services/distill-work-batch.js +42 -0
  353. package/dist/services/distill-work-collection.js +74 -0
  354. package/dist/services/distill-work-registration.js +93 -0
  355. package/dist/services/distill-work-results.js +98 -0
  356. package/dist/services/engines.js +354 -163
  357. package/dist/services/eval-snapshots.js +1326 -150
  358. package/dist/services/execution-bundles.js +275 -0
  359. package/dist/services/execution-policy.js +185 -0
  360. package/dist/services/executor-onboarding.js +56 -0
  361. package/dist/services/external-work-launch.js +316 -0
  362. package/dist/services/flow-catalog.js +54 -0
  363. package/dist/services/flow-descriptors.js +82 -0
  364. package/dist/services/frozen-engine.js +404 -0
  365. package/dist/services/generic-execution.js +165 -0
  366. package/dist/services/harness-adapter.js +342 -35
  367. package/dist/services/harness-config.js +2 -0
  368. package/dist/services/harness-discovery.js +29 -0
  369. package/dist/services/harness-doctor.js +75 -0
  370. package/dist/services/harness-probe-effects.js +51 -0
  371. package/dist/services/harness-version-probe.js +100 -0
  372. package/dist/services/hook-memory-routing.js +188 -0
  373. package/dist/services/hook-recovery-guard.js +14 -0
  374. package/dist/services/hook-session-observation.js +24 -0
  375. package/dist/services/hooks.js +813 -327
  376. package/dist/services/hybrid-contracts.js +479 -0
  377. package/dist/services/hybrid-digest.js +14 -0
  378. package/dist/services/ids.js +29 -1
  379. package/dist/services/installation-lock.js +95 -0
  380. package/dist/services/installed-flow-source.js +261 -0
  381. package/dist/services/interactive-attached-session.js +215 -0
  382. package/dist/services/interactive-baseline-custody.js +54 -0
  383. package/dist/services/interactive-before-versions.js +148 -0
  384. package/dist/services/interactive-bundle-data.js +85 -0
  385. package/dist/services/interactive-checks.js +179 -0
  386. package/dist/services/interactive-execution.js +33 -0
  387. package/dist/services/interactive-finish-integration.js +236 -0
  388. package/dist/services/interactive-git-baseline.js +230 -0
  389. package/dist/services/interactive-git-dispatch.js +278 -0
  390. package/dist/services/interactive-input-delivery.js +82 -0
  391. package/dist/services/interactive-mutation-scope.js +231 -0
  392. package/dist/services/interactive-request.js +287 -0
  393. package/dist/services/interactive-run-bundle.js +109 -0
  394. package/dist/services/interactive-stage-entry.js +41 -0
  395. package/dist/services/interactive-stage-handlers.js +289 -0
  396. package/dist/services/interactive-stage-observation.js +136 -0
  397. package/dist/services/interactive-stage-results.js +111 -0
  398. package/dist/services/interactive-user-inputs.js +142 -0
  399. package/dist/services/interactive-work-batch.js +43 -0
  400. package/dist/services/interactive-work-collection.js +119 -0
  401. package/dist/services/interactive-work-completion.js +180 -0
  402. package/dist/services/interactive-work-context.js +249 -0
  403. package/dist/services/interactive-work-history.js +112 -0
  404. package/dist/services/interactive-work-registration.js +124 -0
  405. package/dist/services/interactive-work-results.js +115 -0
  406. package/dist/services/interactive-work-start.js +155 -0
  407. package/dist/services/lanes.js +78 -65
  408. package/dist/services/lifecycle-command.js +1 -288
  409. package/dist/services/lifecycle-contract.js +1 -0
  410. package/dist/services/lifecycle-invocations.js +2549 -0
  411. package/dist/services/managed-daemon-binding.js +129 -0
  412. package/dist/services/managed-lease-monitor.js +133 -0
  413. package/dist/services/managed-processes.js +449 -69
  414. package/dist/services/memory-accepted-composition.js +78 -0
  415. package/dist/services/memory-baseline-preservation.js +65 -0
  416. package/dist/services/memory-completed-correction-wave.js +328 -0
  417. package/dist/services/memory-compose-handler.js +380 -0
  418. package/dist/services/memory-composition-acceptance.js +375 -0
  419. package/dist/services/memory-composition-graph.js +165 -0
  420. package/dist/services/memory-composition-registration.js +161 -0
  421. package/dist/services/memory-composition-work-custody.js +156 -0
  422. package/dist/services/memory-composition-work-results.js +108 -0
  423. package/dist/services/memory-corrected-review-acceptance.js +129 -0
  424. package/dist/services/memory-corrected-review-batch.js +37 -0
  425. package/dist/services/memory-corrected-review-findings.js +108 -0
  426. package/dist/services/memory-corrected-review-inputs.js +215 -0
  427. package/dist/services/memory-corrected-review-projection.js +78 -0
  428. package/dist/services/memory-corrected-review-receipt.js +178 -0
  429. package/dist/services/memory-corrected-review-registration.js +192 -0
  430. package/dist/services/memory-correction-check-receipt.js +235 -0
  431. package/dist/services/memory-correction-input-owner.js +6 -0
  432. package/dist/services/memory-custody-snapshot.js +36 -0
  433. package/dist/services/memory-discover-handler.js +104 -0
  434. package/dist/services/memory-finish-evidence.js +457 -0
  435. package/dist/services/memory-finish-handler.js +229 -0
  436. package/dist/services/memory-finish-integration.js +491 -0
  437. package/dist/services/memory-finish-readiness.js +169 -0
  438. package/dist/services/memory-fix-finish-integration.js +129 -0
  439. package/dist/services/memory-fix-git-dispatch.js +139 -0
  440. package/dist/services/memory-fix-intake-custody.js +11 -0
  441. package/dist/services/memory-fix-intake-settlement.js +127 -0
  442. package/dist/services/memory-fix-publication.js +196 -0
  443. package/dist/services/memory-fix-repair-admission.js +116 -0
  444. package/dist/services/memory-fix-request.js +141 -0
  445. package/dist/services/memory-fix-run-bundle.js +83 -0
  446. package/dist/services/memory-fix-scope.js +78 -0
  447. package/dist/services/memory-fix-sources.js +85 -0
  448. package/dist/services/memory-fix-stage-entry.js +24 -0
  449. package/dist/services/memory-fix-stage-handlers.js +282 -0
  450. package/dist/services/memory-fix-stage-results.js +106 -0
  451. package/dist/services/memory-fix-workspace.js +127 -0
  452. package/dist/services/memory-flow-user-inputs.js +88 -0
  453. package/dist/services/memory-git-integration.js +220 -0
  454. package/dist/services/memory-historical-corrected-review.js +212 -0
  455. package/dist/services/memory-historical-original-review.js +143 -0
  456. package/dist/services/memory-historical-repair-registration.js +105 -0
  457. package/dist/services/memory-historical-second-review.js +147 -0
  458. package/dist/services/memory-init-bootstrap-readiness.js +210 -0
  459. package/dist/services/memory-init-contexts.js +181 -0
  460. package/dist/services/memory-init-controller-start.js +119 -0
  461. package/dist/services/memory-init-engine-release.js +223 -0
  462. package/dist/services/memory-init-git-policy.js +165 -0
  463. package/dist/services/memory-init-lint-capability.js +203 -0
  464. package/dist/services/memory-init-native-capacity.js +309 -0
  465. package/dist/services/memory-init-preflight.js +334 -0
  466. package/dist/services/memory-init-project-bootstrap.js +599 -0
  467. package/dist/services/memory-init-request-candidate.js +213 -0
  468. package/dist/services/memory-init-request-input.js +82 -0
  469. package/dist/services/memory-init-resource-storage.js +125 -0
  470. package/dist/services/memory-init-run-allocation.js +81 -0
  471. package/dist/services/memory-init-run-bundle.js +135 -0
  472. package/dist/services/memory-init-start.js +181 -0
  473. package/dist/services/memory-init-startup-custody.js +80 -0
  474. package/dist/services/memory-init-startup-input.js +240 -0
  475. package/dist/services/memory-init-storage.js +91 -0
  476. package/dist/services/memory-init-stores.js +359 -0
  477. package/dist/services/memory-init-worktrunk-capability.js +174 -0
  478. package/dist/services/memory-layer-publication.js +611 -0
  479. package/dist/services/memory-layer.js +225 -0
  480. package/dist/services/memory-lint-config.js +194 -0
  481. package/dist/services/memory-native-review-copy.js +127 -0
  482. package/dist/services/memory-normal-flow-entry.js +87 -0
  483. package/dist/services/memory-ordinary-defaults.js +129 -0
  484. package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
  485. package/dist/services/memory-preflight-handler.js +274 -0
  486. package/dist/services/memory-repair-current-view.js +299 -0
  487. package/dist/services/memory-repair-document-delta.js +489 -0
  488. package/dist/services/memory-repair-history.js +496 -0
  489. package/dist/services/memory-repair-physical-binding.js +194 -0
  490. package/dist/services/memory-repair-publication-files.js +152 -0
  491. package/dist/services/memory-repair-publication-intent.js +27 -0
  492. package/dist/services/memory-repair-publication-plan.js +162 -0
  493. package/dist/services/memory-repair-publication-source.js +225 -0
  494. package/dist/services/memory-repair-publication.js +795 -0
  495. package/dist/services/memory-repair-registration.js +240 -0
  496. package/dist/services/memory-repair-work-baseline.js +415 -0
  497. package/dist/services/memory-repair-work-completion.js +117 -0
  498. package/dist/services/memory-repair-work-custody.js +73 -0
  499. package/dist/services/memory-repair-work-results.js +108 -0
  500. package/dist/services/memory-repair-workspace.js +261 -0
  501. package/dist/services/memory-repair-writer-copy.js +736 -0
  502. package/dist/services/memory-result-binding.js +239 -0
  503. package/dist/services/memory-retained-review-authority.js +138 -0
  504. package/dist/services/memory-retained-review-results.js +70 -0
  505. package/dist/services/memory-retained-second-baseline.js +102 -0
  506. package/dist/services/memory-retained-second-repairs.js +162 -0
  507. package/dist/services/memory-review-acceptance.js +214 -0
  508. package/dist/services/memory-review-correction-plan.js +206 -0
  509. package/dist/services/memory-review-handler.js +585 -0
  510. package/dist/services/memory-review-inputs.js +246 -0
  511. package/dist/services/memory-review-limits.js +10 -0
  512. package/dist/services/memory-review-receipt.js +180 -0
  513. package/dist/services/memory-review-registration.js +117 -0
  514. package/dist/services/memory-review-work-custody.js +126 -0
  515. package/dist/services/memory-review-work-input.js +91 -0
  516. package/dist/services/memory-review-work-results.js +95 -0
  517. package/dist/services/memory-second-corrected-review-inputs.js +167 -0
  518. package/dist/services/memory-second-correction-plan.js +77 -0
  519. package/dist/services/memory-second-repair-baseline.js +91 -0
  520. package/dist/services/memory-second-repair-launch.js +614 -0
  521. package/dist/services/memory-second-repair-registration.js +88 -0
  522. package/dist/services/memory-second-repair-source.js +187 -0
  523. package/dist/services/memory-second-review-acceptance.js +115 -0
  524. package/dist/services/memory-source-observations.js +117 -0
  525. package/dist/services/memory-stage-dispatch.js +65 -0
  526. package/dist/services/memory-stage-results.js +290 -0
  527. package/dist/services/memory-tool-probe.js +25 -0
  528. package/dist/services/memory-upgrade-analysis-handler.js +243 -0
  529. package/dist/services/memory-upgrade-bootstrap-readiness.js +251 -0
  530. package/dist/services/memory-upgrade-evidence.js +100 -0
  531. package/dist/services/memory-upgrade-inventory.js +442 -0
  532. package/dist/services/memory-upgrade-publication-custody.js +73 -0
  533. package/dist/services/memory-upgrade-publication.js +413 -0
  534. package/dist/services/memory-upgrade-selection.js +430 -0
  535. package/dist/services/memory-upgrade-start.js +60 -0
  536. package/dist/services/memory-upgrade-storage-readiness.js +340 -0
  537. package/dist/services/memory-verification-acceptance.js +156 -0
  538. package/dist/services/memory-verification-checks.js +317 -0
  539. package/dist/services/memory-verification-receipt.js +160 -0
  540. package/dist/services/memory-verify-handler.js +137 -0
  541. package/dist/services/memory-work-result-json.js +12 -0
  542. package/dist/services/memory-work-result-preparation.js +64 -0
  543. package/dist/services/merge-queue.js +228 -149
  544. package/dist/services/merge-server.js +163 -35
  545. package/dist/services/migrations.js +164 -114
  546. package/dist/services/model-catalog.js +109 -0
  547. package/dist/services/model-discovery.js +46 -0
  548. package/dist/services/native-daemon-history.js +50 -0
  549. package/dist/services/native-session-control.js +39 -0
  550. package/dist/services/operator-profiles.js +236 -0
  551. package/dist/services/physical-startup.js +45 -0
  552. package/dist/services/plan-runtime.js +26 -11
  553. package/dist/services/plans.js +28 -25
  554. package/dist/services/project-flow-source.js +195 -0
  555. package/dist/services/project-git-integration.js +92 -0
  556. package/dist/services/project-registry.js +97 -0
  557. package/dist/services/project-summary.js +1 -1
  558. package/dist/services/projects.js +17 -87
  559. package/dist/services/prompt-delivery.js +71 -0
  560. package/dist/services/prompts.js +28 -17
  561. package/dist/services/protocols.js +163 -87
  562. package/dist/services/provider-capacity.js +463 -0
  563. package/dist/services/recovery-observation-budget.js +121 -0
  564. package/dist/services/recovery-snapshot-database.js +588 -0
  565. package/dist/services/release-archive-producer.js +52 -0
  566. package/dist/services/release-archive.js +143 -0
  567. package/dist/services/release-cache.js +150 -0
  568. package/dist/services/release-compatibility.js +18 -0
  569. package/dist/services/release-download.js +67 -0
  570. package/dist/services/release-envelope.js +104 -0
  571. package/dist/services/release-manifest.js +45 -0
  572. package/dist/services/release-payload.js +114 -0
  573. package/dist/services/release-producer.js +63 -0
  574. package/dist/services/release-provenance.js +160 -0
  575. package/dist/services/release-registry.js +66 -0
  576. package/dist/services/release-source.js +194 -0
  577. package/dist/services/repair-intents.js +29 -0
  578. package/dist/services/repair-receipt.js +13 -0
  579. package/dist/services/retained-native-hook.js +274 -0
  580. package/dist/services/review-copy.js +165 -0
  581. package/dist/services/review-deferral.js +23 -0
  582. package/dist/services/review-fix-handoff.js +82 -0
  583. package/dist/services/review-fix-intake-custody.js +17 -0
  584. package/dist/services/review-fix-stage-entry.js +43 -0
  585. package/dist/services/review-fix-stage-handlers.js +176 -0
  586. package/dist/services/review-fix-stage-results.js +86 -0
  587. package/dist/services/run-control-receipt.js +56 -0
  588. package/dist/services/run-control-worker.js +469 -0
  589. package/dist/services/run-control.js +1109 -0
  590. package/dist/services/run-controller-adapter.js +434 -0
  591. package/dist/services/run-controller-capture.js +186 -0
  592. package/dist/services/run-controller-process.js +226 -0
  593. package/dist/services/run-controller-recovery.js +335 -0
  594. package/dist/services/run-controller-state.js +106 -0
  595. package/dist/services/run-controller.js +1717 -0
  596. package/dist/services/run-engine-bindings.js +1 -1
  597. package/dist/services/run-fork.js +147 -0
  598. package/dist/services/run-health.js +149 -0
  599. package/dist/services/run-observations.js +152 -0
  600. package/dist/services/run-projection.js +22 -64
  601. package/dist/services/run-recovery-guard.js +107 -0
  602. package/dist/services/run-recovery-runtime.js +112 -0
  603. package/dist/services/run-recovery.js +485 -0
  604. package/dist/services/run-start-custody.js +189 -0
  605. package/dist/services/run-timeline.js +59 -0
  606. package/dist/services/runs.js +996 -271
  607. package/dist/services/runtime-budget.js +446 -0
  608. package/dist/services/runtime-command.js +43 -0
  609. package/dist/services/runtime-scope-capture.js +52 -0
  610. package/dist/services/runtime-scope-control.js +468 -0
  611. package/dist/services/runtime-scope-resume.js +605 -0
  612. package/dist/services/runtime-scope-stop.js +211 -0
  613. package/dist/services/runtime-scope-worker.js +314 -0
  614. package/dist/services/runtime-service.js +19 -14
  615. package/dist/services/schema-validation.js +10 -8
  616. package/dist/services/scope-writer-cleanup.js +27 -0
  617. package/dist/services/sessions.js +37 -91
  618. package/dist/services/setup.js +427 -0
  619. package/dist/services/stage-blocker.js +17 -7
  620. package/dist/services/stage-context.js +240 -18
  621. package/dist/services/stage-handlers.js +141 -0
  622. package/dist/services/stage-lifecycle.js +156 -119
  623. package/dist/services/stage-pause.js +222 -94
  624. package/dist/services/stage-report-renderer.js +230 -6
  625. package/dist/services/stage-work-graph.js +52 -0
  626. package/dist/services/technical-notes.js +31 -0
  627. package/dist/services/tooling.js +111 -44
  628. package/dist/services/usage.js +49 -101
  629. package/dist/services/verification-matrix.js +393 -0
  630. package/dist/services/version-status.js +1 -1
  631. package/dist/services/vnext-code-review.js +302 -91
  632. package/dist/services/vnext-code.js +325 -251
  633. package/dist/services/vnext-contracts.js +10 -1
  634. package/dist/services/vnext-execution-profile.js +80 -5
  635. package/dist/services/vnext-fanout.js +399 -20
  636. package/dist/services/vnext-merge.js +336 -114
  637. package/dist/services/vnext-plan-review.js +288 -133
  638. package/dist/services/vnext-plan.js +230 -106
  639. package/dist/services/vnext-protocolize.js +534 -96
  640. package/dist/services/vnext-specify.js +131 -84
  641. package/dist/services/vnext-workspace-policy.js +7 -2
  642. package/dist/services/work-registry.js +1950 -215
  643. package/dist/services/work-retry-context.js +55 -0
  644. package/dist/services/workspace-bootstrap.js +53 -15
  645. package/dist/services/workspace-files.js +85 -0
  646. package/dist/services/worktrees.js +108 -48
  647. package/dist/shared/entity-references.js +1 -0
  648. package/dist/shared/errors.js +27 -0
  649. package/dist/storage/agent-output.js +26 -0
  650. package/dist/storage/data-preservation.js +65 -0
  651. package/dist/storage/database.js +931 -40
  652. package/dist/storage/foreign-key-transaction.js +39 -0
  653. package/dist/storage/immutable-input.js +45 -0
  654. package/dist/storage/import-guard.js +159 -0
  655. package/dist/storage/memory-upgrade-schema-bootstrap.js +38 -0
  656. package/dist/storage/native-cleanup.js +52 -0
  657. package/dist/storage/paired-writer-migration.js +424 -0
  658. package/dist/storage/paths.js +17 -4
  659. package/dist/storage/projection-lock.js +73 -0
  660. package/dist/storage/work-references.js +23 -0
  661. package/dist/storage/writer-contract.js +96 -0
  662. package/dist/storage/writer-migration.js +346 -0
  663. package/dist/storage/writer-restore.js +217 -0
  664. package/dist/verification-components.json +384 -0
  665. package/package.json +52 -13
  666. package/tools/create-canon-release.mjs +33 -0
  667. package/tools/probe-codex-history.mjs +37 -0
  668. package/tools/produce-hybrid-release.mjs +41 -0
  669. package/tools/repair-paused-run-status.mjs +84 -0
  670. package/tools/verification-jobs.mjs +342 -0
@@ -1,59 +1,366 @@
1
1
  import { spawn } from "node:child_process";
2
- import { AppError } from "../shared/errors.js";
3
- /** Runs one harness command with the lifecycle guarantees shared by agent services. */
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
5
+ import { AppError, errorRecord } from "../shared/errors.js";
6
+ import { stopProcessGroup } from "../harness-runtime/lib/managed-daemon.mjs";
7
+ import { recoveryObservationBudget, recoveryRpcTimeout, withRecoveryObservation } from "./recovery-observation-budget.js";
8
+ import { ObservationClock, validateObservationDuration } from "../harness-runtime/lib/observation-clock.mjs";
9
+ import { canonicalNativeOperation, nativeOperationWait } from "../harness-runtime/lib/adapter-timeouts.mjs";
10
+ import { readOperationProgress, readOperationRecord, readOperationWaiting, suspendOperationClock } from "../harness-runtime/lib/operation-progress.mjs";
11
+ import { recoverDaemonReply } from "../harness-runtime/lib/daemon-observation.mjs";
12
+ import { isObservationLoss } from "../harness-runtime/lib/operation-errors.mjs";
13
+ import { readBoundedReleaseFile } from "./release-source.js";
14
+ /** Native hooks need a real executable, not a PATH-dependent shell expression. */
15
+ export function prepareHarnessFlowExecutable(context, stateDir, engine) {
16
+ // Native login shells rewrite search paths. The owned SDK must execute with
17
+ // the same original paths as its controller, not merely hash them as equal.
18
+ const searchPaths = ["PATH", "FPATH", "INFOPATH"].map(name => context.env[name] === undefined
19
+ ? `delete process.env.${name};\n` : `process.env.${name} = ${JSON.stringify(context.env[name])};\n`).join("");
20
+ if (engine) {
21
+ const executable = path.join(stateDir, "dd-flow");
22
+ const contents = `#!${engine.nodeExecutable}\n${searchPaths}process.env.DD_FLOW_HOME = ${JSON.stringify(context.ddFlowHome)};\nprocess.env.DD_FLOW_ENGINE_MODE = "1";\nprocess.env.DD_FLOW_ENGINE_HOME = ${JSON.stringify(engine.manifest().snapshot_root)};\nconst { spawnSync } = await import("node:child_process");\nconst child = spawnSync(${JSON.stringify(engine.nodeExecutable)}, [${JSON.stringify(engine.entrypoint)}, ...process.argv.slice(2)], { stdio: "inherit", env: process.env });\nif (child.error) throw child.error;\nif (child.signal) process.kill(process.pid, child.signal);\nprocess.exit(child.status ?? 1);\n`;
23
+ try {
24
+ fs.writeFileSync(executable, contents, { flag: "wx", mode: 0o700 });
25
+ }
26
+ catch (error) {
27
+ const conflict = () => new AppError("harness_runtime_binding_conflict", "Launch runtime executable already has different or linked content", 1, { path: executable });
28
+ if (error.code !== "EEXIST")
29
+ throw conflict();
30
+ try {
31
+ const stat = fs.lstatSync(executable);
32
+ if (!stat.isFile() || stat.nlink !== 1 || readBoundedReleaseFile(executable, 64 * 1024).toString("utf8") !== contents)
33
+ throw conflict();
34
+ }
35
+ catch {
36
+ throw conflict();
37
+ }
38
+ }
39
+ return executable;
40
+ }
41
+ const configured = context.env.DD_FLOW_BIN;
42
+ if (configured !== undefined) {
43
+ if (!path.isAbsolute(configured) || !fs.existsSync(configured))
44
+ throw new AppError("harness_runtime_missing", "DD_FLOW_BIN must identify an existing absolute executable", 2);
45
+ if (path.basename(configured) === "dd-flow")
46
+ return configured;
47
+ }
48
+ const isolated = path.join(context.ddFlowHome, "bin", "dd-flow");
49
+ if (!configured && fs.existsSync(isolated))
50
+ return isolated;
51
+ const entry = fileURLToPath(new URL("../cli.js", import.meta.url));
52
+ if (!configured && !fs.existsSync(entry))
53
+ throw new AppError("harness_runtime_unbuilt", "Build the CLI or supply its pinned DD_FLOW_BIN before launching a harness", 1);
54
+ // The trusted lifecycle parser recognizes this basename, including for a
55
+ // custom pinned executable. Do not broaden that parser to arbitrary scripts.
56
+ const executable = path.join(stateDir, "dd-flow");
57
+ const dispatch = configured
58
+ ? `const { spawnSync } = await import("node:child_process");\nconst child = spawnSync(${JSON.stringify(configured)}, process.argv.slice(2), { stdio: "inherit", env: process.env });\nif (child.error) throw child.error;\nif (child.signal) process.kill(process.pid, child.signal);\nprocess.exit(child.status ?? 1);\n`
59
+ : `await import(${JSON.stringify(pathToFileURL(entry).href)});\n`;
60
+ const contents = `#!${process.execPath}\n${searchPaths}process.env.DD_FLOW_HOME = ${JSON.stringify(context.ddFlowHome)};\n${dispatch}`;
61
+ try {
62
+ fs.writeFileSync(executable, contents, { flag: "wx", mode: 0o700 });
63
+ }
64
+ catch (error) {
65
+ if (error.code !== "EEXIST" || fs.readFileSync(executable, "utf8") !== contents)
66
+ throw new AppError("harness_runtime_binding_conflict", "Launch runtime executable already has different content", 1, { path: executable });
67
+ }
68
+ return executable;
69
+ }
4
70
  export function runHarnessAdapter(input) {
5
- const timeoutMs = input.timeoutMs ?? 120_000;
71
+ const index = input.args.indexOf("--state-dir"), stateDir = index >= 0 ? input.args[index + 1] : undefined;
72
+ const operation = canonicalNativeOperation(input.harness ?? "", `${input.args[0]}.${input.args[1]}`);
73
+ const boundOperation = ["session.create", "session.fork", "session.start", "session.resume"].includes(operation);
74
+ const binding = { operation, ...(input.runtimeOwner ? { owner_id: input.runtimeOwner.owner_id } : {}) };
75
+ let retainedOutcome;
76
+ const onOutcome = (value) => {
77
+ const fingerprint = JSON.stringify(value);
78
+ if (fingerprint !== retainedOutcome) {
79
+ input.onNativeOutcome?.(value);
80
+ retainedOutcome = fingerprint;
81
+ }
82
+ };
83
+ const dispatched = runAdapterTransport(input, stateDir, binding);
84
+ return dispatched.catch(async (error) => {
85
+ if (!stateDir || !boundOperation || input.signal?.aborted || !(isObservationLoss(error) || isObservationLoss(error?.details?.cause)))
86
+ throw error;
87
+ try {
88
+ return await recoverDaemonReply(stateDir, input.operationId, { timeoutMs: recoveryRpcTimeout(30_000), ...(input.signal ? { signal: input.signal } : {}), ...(error?.observationClock ? { observationClock: error.observationClock } : {}), binding, onOutcome,
89
+ // Reconcile only original bookkeeping. Work/MERGE share this path and
90
+ // must not replay creation merely because its release receipt is pending.
91
+ onPendingSettlement: async (retained) => {
92
+ input.signal?.throwIfAborted();
93
+ await withRecoveryObservation(recoveryObservationBudget(retained), () => runAdapterTransport({ ...input, args: ["daemon", "operation", "settle", "--state-dir", stateDir, "--operation-id", input.operationId, "--json"], operationId: `${input.operationId}:settlement`, timeoutMs: recoveryRpcTimeout(30_000) }, stateDir, {}), true);
94
+ }
95
+ });
96
+ }
97
+ catch (recovery) {
98
+ if (recovery && typeof recovery === "object")
99
+ Object.assign(recovery, { cause: error });
100
+ throw recovery;
101
+ }
102
+ });
103
+ }
104
+ function runAdapterTransport(input, stateDir, binding = {}) {
105
+ // `null` is deliberate: a productive Turn has no adapter-wall-clock limit.
106
+ // Preserve it instead of treating it like an omitted short control request.
107
+ if (input.timeoutMs != null)
108
+ validateObservationDuration(input.timeoutMs);
109
+ const operation = canonicalNativeOperation(input.harness ?? "", `${input.args[0]}.${input.args[1]}`);
110
+ const productive = input.harness !== undefined && nativeOperationWait(input.harness, operation) === "native-work";
111
+ const timeoutMs = recoveryRpcTimeout(productive ? null : input.timeoutMs === undefined ? 120_000 : input.timeoutMs);
112
+ if (timeoutMs !== null)
113
+ validateObservationDuration(timeoutMs);
114
+ if (!input.operationId.trim())
115
+ throw new AppError("operation_id_required", "Harness calls require a scoped operation id", 2);
116
+ // The current adapter transport uses this name; its identity is runtime-owned,
117
+ // never the operation or trusted daemon identity of the calling coordinator.
118
+ const env = { ...input.env, DD_EVAL_OPERATION_ID: input.operationId };
119
+ delete env.DD_FLOW_DAEMON_ID;
120
+ delete env.DD_FLOW_SCOPE_CONTROL_TOKEN;
121
+ delete env.DD_FLOW_RUNTIME_OWNER;
122
+ if (input.runtimeOwner) {
123
+ if (!path.isAbsolute(input.executable) || input.runtimeOwner.adapter_executable !== undefined && input.runtimeOwner.adapter_executable !== input.executable)
124
+ throw new AppError("harness_runtime_binding_conflict", "Owned harness call must use its frozen absolute adapter executable", 1);
125
+ env.DD_FLOW_RUNTIME_OWNER = JSON.stringify({ ...input.runtimeOwner, adapter_executable: input.executable });
126
+ }
6
127
  return new Promise((resolve, reject) => {
128
+ if (input.signal?.aborted)
129
+ return reject(new AppError("harness_adapter_aborted", "Harness adapter call was cancelled before dispatch", 1));
7
130
  const detached = process.platform !== "win32";
8
- const child = spawn(input.executable, input.args, { env: input.env, detached, stdio: ["ignore", "pipe", "pipe"] });
131
+ const child = spawn(input.executable, input.args, { env, ...(input.cwd ? { cwd: input.cwd } : {}), detached, stdio: ["ignore", "pipe", "pipe"] });
9
132
  let stdout = "";
10
133
  let stderr = "";
11
134
  let timedOut = false;
12
- let killTimer;
13
- const terminate = (signal) => { try {
14
- if (detached && child.pid)
15
- process.kill(-child.pid, signal);
16
- else
17
- child.kill(signal);
18
- }
19
- catch { /* The process already settled. */ } };
20
- const heartbeat = input.progress && input.progressMessage ? setInterval(() => input.progress?.(`${input.progressMessage}; waiting for adapter completion`), 15_000) : undefined;
21
- const timer = setTimeout(() => { timedOut = true; terminate("SIGTERM"); killTimer = setTimeout(() => terminate("SIGKILL"), 5_000); }, timeoutMs);
22
- const evidence = (value) => input.onEvidence?.({ executable: input.executable, args: input.args, ...value, at: new Date().toISOString() });
135
+ let aborted = false;
136
+ let cleanup;
137
+ let pendingDiagnostic = "", droppingDiagnostic = false, progressCursor = 0;
138
+ let prettyDiagnostic = "", retainedError;
139
+ const phases = new Set();
140
+ let operationSequence = 0;
141
+ let diagnosticReads = Promise.resolve();
142
+ const clock = timeoutMs === null ? null : new ObservationClock({ timeoutMs });
143
+ clock?.sample(progressCursor);
144
+ let settled = false;
145
+ let callbackError;
146
+ let spawnError;
147
+ const stopTransport = () => {
148
+ cleanup ??= stopProcessGroup(child, 5_000, { detached }).catch(error => {
149
+ if (timer)
150
+ clearInterval(timer);
151
+ if (heartbeat)
152
+ clearInterval(heartbeat);
153
+ input.signal?.removeEventListener("abort", abort);
154
+ const details = { cleanup_error: errorRecord(error) };
155
+ if (callbackError instanceof Error) {
156
+ Object.assign(callbackError, { cleanup_error: details.cleanup_error, details: { ...callbackError.details, ...details } });
157
+ reject(callbackError);
158
+ }
159
+ else
160
+ reject(new AppError(timedOut ? "harness_adapter_timeout" : aborted ? "harness_adapter_aborted" : "harness_adapter_cleanup_unconfirmed", "Adapter transport cleanup could not be confirmed", 1, details));
161
+ });
162
+ };
163
+ const deliver = (callback) => {
164
+ try {
165
+ const result = callback();
166
+ if (result && typeof result.then === "function") {
167
+ void Promise.resolve(result).catch(() => { });
168
+ throw new AppError("progress_callback_async", "Harness callbacks must be synchronous", 1);
169
+ }
170
+ }
171
+ catch (error) {
172
+ callbackError ??= error;
173
+ if (!settled)
174
+ stopTransport();
175
+ }
176
+ };
177
+ const heartbeat = input.progress && input.progressMessage ? setInterval(() => deliver(() => input.progress?.(`${input.progressMessage}; waiting for adapter completion`)), 15_000) : undefined;
178
+ let observing = false;
179
+ const timer = timeoutMs === null ? undefined : setInterval(async () => {
180
+ if (settled || cleanup)
181
+ return;
182
+ if (observing)
183
+ return;
184
+ observing = true;
185
+ // Helper phase progress must never replenish its owner's independent
186
+ // physical-settlement episode. ALS retains that existing budget here.
187
+ try {
188
+ recoveryRpcTimeout(timeoutMs);
189
+ }
190
+ catch (error) {
191
+ callbackError ??= error;
192
+ stopTransport();
193
+ observing = false;
194
+ return;
195
+ }
196
+ try {
197
+ const waiting = stateDir && await readOperationWaiting(stateDir, input.operationId, binding);
198
+ if (settled || cleanup)
199
+ return;
200
+ if (waiting)
201
+ suspendOperationClock(clock);
202
+ else if (clock.sample(progressCursor)) {
203
+ timedOut = true;
204
+ stopTransport();
205
+ }
206
+ }
207
+ catch (error) {
208
+ callbackError ??= error;
209
+ stopTransport();
210
+ }
211
+ finally {
212
+ observing = false;
213
+ }
214
+ }, Math.max(1, Math.min(1000, timeoutMs / 4)));
215
+ const abort = () => { aborted = true; stopTransport(); };
216
+ if (input.signal?.aborted)
217
+ abort();
218
+ else
219
+ input.signal?.addEventListener("abort", abort, { once: true });
220
+ const evidence = (value) => input.onEvidence?.({ operation_id: input.operationId, executable: input.executable, args: input.args, ...value, at: new Date().toISOString() });
221
+ const observeDiagnostic = (line) => {
222
+ if (prettyDiagnostic === null) {
223
+ if (line.trimEnd() === "}")
224
+ prettyDiagnostic = "";
225
+ return;
226
+ }
227
+ const candidate = prettyDiagnostic ? `${prettyDiagnostic}\n${line}` : line;
228
+ if (candidate.length > 64_000) {
229
+ prettyDiagnostic = null;
230
+ return;
231
+ }
232
+ let value;
233
+ try {
234
+ value = JSON.parse(candidate);
235
+ prettyDiagnostic = "";
236
+ }
237
+ catch {
238
+ prettyDiagnostic = prettyDiagnostic || line.trimStart().startsWith("{") ? candidate : "";
239
+ return;
240
+ }
241
+ if (!value || typeof value !== "object" || Array.isArray(value))
242
+ return;
243
+ if (value.kind === "operation_progress" && stateDir && value.operation_id === input.operationId) {
244
+ // The diagnostic is only a wake-up: durable, bound evidence owns liveness.
245
+ diagnosticReads = diagnosticReads.then(async () => {
246
+ const record = await readOperationProgress(stateDir, input.operationId, binding);
247
+ if (!record || record.sequence <= operationSequence)
248
+ return;
249
+ const requested = await readOperationRecord(stateDir, input.operationId, "requested.json");
250
+ if (!requested)
251
+ throw new AppError("operation_progress_invalid", "Operation request disappeared while observing progress", 1);
252
+ for (const key of ["daemon_id", "params_sha256", "generation"])
253
+ binding[key] ??= requested[key] ?? null;
254
+ operationSequence = record.sequence;
255
+ clock?.sample(++progressCursor, Date.parse(record.observed_at));
256
+ }).catch(error => { callbackError ??= error; if (!settled)
257
+ stopTransport(); });
258
+ return;
259
+ }
260
+ const cause = adapterCause(candidate);
261
+ if (typeof cause.code === "string")
262
+ retainedError = cause;
263
+ if (clock && !(stateDir && ["session.create", "session.fork", "session.start", "session.resume", "session.prompt"].includes(operation))
264
+ && ["native_hook_phase", "process_maintenance_phase"].includes(String(value.kind))
265
+ && typeof value.phase === "string" && /^[a-z_]{1,48}$/.test(value.phase)
266
+ && !["heartbeat", "poll", "elapsed", "wait", "waiting", "status"].includes(value.phase)) {
267
+ const marker = JSON.stringify([value.kind, value.phase, value.operation_id ?? value.process_id]);
268
+ if (!phases.has(marker)) {
269
+ phases.add(marker);
270
+ clock.sample(++progressCursor);
271
+ }
272
+ }
273
+ };
23
274
  child.stdout.setEncoding("utf8").on("data", (chunk) => { stdout += chunk; });
24
- child.stderr.setEncoding("utf8").on("data", (chunk) => { stderr += chunk; });
25
- child.once("error", (error) => { clearTimeout(timer); if (heartbeat)
26
- clearInterval(heartbeat); if (killTimer)
27
- clearTimeout(killTimer); evidence({ status: null, error: error.message }); reject(new AppError("merge_adapter_failed", "Harness adapter call failed", 1, { executable: input.executable, args: input.args.slice(0, 3), error: error.message })); });
28
- child.once("close", (status, signal) => {
29
- clearTimeout(timer);
275
+ // Diagnostics have no lifetime quota. Stream to the existing evidence sink
276
+ // and carry only a bounded tail in the disposable RPC receipt.
277
+ child.stderr.setEncoding("utf8").on("data", (chunk) => {
278
+ stderr = (stderr + chunk).slice(-64_000);
279
+ for (const piece of chunk.split(/(?<=\n)/)) {
280
+ if (!droppingDiagnostic)
281
+ pendingDiagnostic += piece;
282
+ if (pendingDiagnostic.length > 64_000) {
283
+ prettyDiagnostic = prettyDiagnostic || pendingDiagnostic.trimStart().startsWith("{") ? null : "";
284
+ pendingDiagnostic = "";
285
+ droppingDiagnostic = true;
286
+ }
287
+ if (!piece.endsWith("\n"))
288
+ continue;
289
+ if (!droppingDiagnostic)
290
+ observeDiagnostic(pendingDiagnostic);
291
+ pendingDiagnostic = "";
292
+ droppingDiagnostic = false;
293
+ }
294
+ if (input.onEvidence)
295
+ deliver(() => evidence({ type: "adapter_diagnostic", stderr: chunk }));
296
+ });
297
+ child.once("error", (error) => { spawnError = error; });
298
+ child.once("close", async (status, signal) => {
299
+ if (settled)
300
+ return;
301
+ settled = true;
302
+ if (timer)
303
+ clearInterval(timer);
304
+ input.signal?.removeEventListener("abort", abort);
30
305
  if (heartbeat)
31
306
  clearInterval(heartbeat);
32
- if (killTimer)
33
- clearTimeout(killTimer);
34
- evidence({ status, signal, timed_out: timedOut, stdout, stderr });
307
+ await cleanup;
308
+ if (!droppingDiagnostic && pendingDiagnostic)
309
+ observeDiagnostic(pendingDiagnostic);
310
+ await diagnosticReads;
311
+ const progressFailure = callbackError;
312
+ deliver(() => evidence({ status, signal, timed_out: timedOut, aborted, stdout, stderr, ...(spawnError ? { error: spawnError.message } : {}) }));
313
+ if (spawnError)
314
+ return reject(new AppError("harness_adapter_failed", "Harness adapter call failed", 1, { cause: adapterCause(spawnError.message), ...(callbackError ? { evidence_error: String(callbackError) } : {}) }));
35
315
  if (timedOut)
36
- return reject(new AppError("merge_adapter_timeout", "Harness adapter call timed out", 1, { executable: input.executable, args: input.args.slice(0, 3), timeout_ms: timeoutMs }));
316
+ return reject(Object.assign(new AppError("harness_adapter_timeout", "Harness adapter call timed out", 1, { executable: input.executable, args: input.args.slice(0, 3), timeout_ms: timeoutMs }), { observationClock: clock }));
317
+ if (aborted)
318
+ return reject(new AppError("harness_adapter_aborted", "Harness adapter call was cancelled", 1, { executable: input.executable, args: input.args.slice(0, 3) }));
37
319
  if (status !== 0)
38
- return reject(new AppError("merge_adapter_failed", "Harness adapter call failed", 1, { executable: input.executable, args: input.args.slice(0, 3), status, signal, stderr }));
320
+ return reject(progressFailure ?? new AppError("harness_adapter_failed", "Harness adapter call failed", 1, { executable: input.executable, args: input.args.slice(0, 3), status, signal, stderr, cause: adapterCause(stdout, stderr, retainedError ? JSON.stringify(retainedError) : ""), ...(callbackError ? { evidence_error: String(callbackError) } : {}) }));
321
+ if (callbackError)
322
+ return reject(callbackError);
39
323
  try {
40
- resolve(JSON.parse(stdout));
324
+ const reply = JSON.parse(stdout);
325
+ if (!reply || typeof reply !== "object" || Array.isArray(reply))
326
+ throw new Error("not object");
327
+ const value = reply;
328
+ if (value.ok === false)
329
+ return reject(new AppError("harness_adapter_failed", "Harness adapter reported a runtime failure", 1, { cause: adapterCause(stdout) }));
330
+ resolve(reply);
41
331
  }
42
332
  catch {
43
- reject(new AppError("merge_adapter_invalid", "Harness adapter returned invalid JSON", 1, { executable: input.executable, stdout }));
333
+ reject(new AppError("harness_adapter_invalid", "Harness adapter returned one invalid JSON object", 1, { executable: input.executable }));
44
334
  }
45
335
  });
46
336
  });
47
337
  }
338
+ function adapterCause(...outputs) {
339
+ for (const output of outputs)
340
+ for (const line of [output.trim(), ...output.trim().split("\n").reverse()]) {
341
+ try {
342
+ const value = JSON.parse(line);
343
+ const nested = value.error && typeof value.error === "object" && !Array.isArray(value.error) ? value.error : null;
344
+ const code = typeof nested?.code === "string" ? nested.code : typeof value.code === "string" ? value.code : null;
345
+ const message = typeof nested?.message === "string" ? nested.message : typeof value.error === "string" ? value.error : typeof value.message === "string" ? value.message : code;
346
+ if (code)
347
+ return errorRecord({ ...(nested ?? value), code, message });
348
+ }
349
+ catch { /* Adapter diagnostics need not be JSON. */ }
350
+ }
351
+ return { message: outputs.map(output => output.trim()).filter(Boolean).join("\n") || "adapter process failed" };
352
+ }
48
353
  export function adapterSessionId(value) {
49
354
  if (!value || typeof value !== "object")
50
355
  return null;
51
- for (const [key, item] of Object.entries(value)) {
52
- if (["session_id", "sessionId", "provider_session_id", "providerSessionId", "adapter_session_id", "adapterSessionId", "thread_id", "threadId", "conversation_id"].includes(key) && typeof item === "string")
53
- return item;
54
- const nested = adapterSessionId(item);
55
- if (nested)
56
- return nested;
57
- }
356
+ const reply = value;
357
+ for (const key of ["provider_session_id", "adapter_session_id", "session_id"])
358
+ if (typeof reply[key] === "string" && reply[key].trim())
359
+ return reply[key];
360
+ const session = reply.session;
361
+ if (session && typeof session === "object" && !Array.isArray(session))
362
+ for (const key of ["provider_session_id", "session_id"])
363
+ if (typeof session[key] === "string" && String(session[key]).trim())
364
+ return session[key];
58
365
  return null;
59
366
  }
@@ -10,6 +10,7 @@ export function harnessKey(value) {
10
10
  zcode: "zcode-acp", "zcode-acp": "zcode-acp",
11
11
  grok: "grok-acp", "grok-acp": "grok-acp",
12
12
  agy: "antigravity-cli", "antigravity-cli": "antigravity-cli",
13
+ droid: "droid-cli", "droid-cli": "droid-cli",
13
14
  opencode: "opencode-server", "opencode-server": "opencode-server"
14
15
  };
15
16
  const resolved = keys[value];
@@ -60,6 +61,7 @@ export function harnessRuntimeArguments(ddFlowHome, harness) {
60
61
  "zcode-acp": "--zcode-acp-bin",
61
62
  "grok-acp": "--grok-bin",
62
63
  "antigravity-cli": "--agy-bin",
64
+ "droid-cli": "--droid-bin",
63
65
  "opencode-server": "--opencode-bin"
64
66
  };
65
67
  return [option[key], runtime];
@@ -0,0 +1,29 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { validateHybridContract } from "./hybrid-contracts.js";
3
+ import { AppError } from "../shared/errors.js";
4
+ import { discoverCodex } from "./discovery/codex-discovery.js";
5
+ import { discoverZcode } from "./discovery/zcode-discovery.js";
6
+ import { discoverAgy } from "./discovery/agy-discovery.js";
7
+ import { discoverOpenCode } from "./discovery/opencode-discovery.js";
8
+ import { discoverGrok } from "./discovery/grok-discovery.js";
9
+ import { discoverDroid } from "./discovery/droid-discovery.js";
10
+ import { readOnlyProbeScope, runScopedProbe, staticDiscoveryEffects } from "./harness-probe-effects.js";
11
+ const modules = { codex: discoverCodex, zcode: discoverZcode, agy: discoverAgy, opencode: discoverOpenCode, grok: discoverGrok, droid: discoverDroid };
12
+ export const harnessCatalog = {
13
+ schema_id: "dd-flow/harness-catalog@1", version: "1.0.0",
14
+ entries: Object.keys(modules).map(id => ({ id, executable_candidates: [id], probe_module: `${id}-discovery`,
15
+ probe_timeout_ms: 3000, version_range: "unknown_requires_review", protocol_version: "unknown_requires_protocol_probe" }))
16
+ };
17
+ export function discoverHarnesses(input) {
18
+ if (input.harness && !Object.hasOwn(modules, input.harness))
19
+ throw new AppError("usage", "Unknown harness family", 2, { effect: "no_effect" });
20
+ if (input.executable && !input.harness)
21
+ throw new AppError("usage", "Explicit executable requires one harness family", 2, { effect: "no_effect" });
22
+ const families = input.harness ? [input.harness] : Object.keys(modules);
23
+ const result = { schema_id: "dd-flow/discovery-result@1", request_id: input.requestId ?? randomUUID(), observed_at: new Date().toISOString(),
24
+ probe_scope: "static", live_authorization_receipt: null, entries: families.map(family => runScopedProbe(staticDiscoveryEffects, readOnlyProbeScope, () => modules[family](input))) };
25
+ if (validateHybridContract("harness-catalog", harnessCatalog).length || validateHybridContract("discovery-result", result).length) {
26
+ throw new AppError("discovery_contract", "Discovery owner produced invalid facts", 1, { effect: "no_effect" });
27
+ }
28
+ return result;
29
+ }
@@ -0,0 +1,75 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { parse } from "semver";
4
+ import { AppError } from "../shared/errors.js";
5
+ import { legacyDoctorEffects, runScopedProbe } from "./harness-probe-effects.js";
6
+ import { readBoundedReleaseFile } from "./release-source.js";
7
+ import { discoverExecutable } from "./discovery/static.js";
8
+ const binOptions = {
9
+ codex: "codex-bin", zcode: "zcode-acp-bin", agy: "agy-bin", opencode: "opencode-bin", grok: "grok-bin", droid: "droid-bin"
10
+ };
11
+ function refuse(code, message, exitCode = 1) {
12
+ throw new AppError(code, message, exitCode, { phase: "harness_doctor", help: "harnesses doctor" });
13
+ }
14
+ /** Existing non-generative adapter doctor, bounded by its owner transport.
15
+ * Reported compatibility is not qualification or verified account access.
16
+ * OpenCode observes an explicitly bound existing daemon; it never starts one.
17
+ */
18
+ export async function probeHarnessDoctor(input) {
19
+ const timeoutMs = input.timeoutMs ?? 30_000;
20
+ if (!Object.hasOwn(binOptions, input.harness) || !path.isAbsolute(input.executable)
21
+ || !Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 60_000
22
+ || input.stateDir !== undefined && !path.isAbsolute(input.stateDir)
23
+ || input.nativeExecutable !== undefined && (!path.isAbsolute(input.nativeExecutable) || input.harness !== "zcode")
24
+ || input.stateDir !== undefined && input.harness !== "opencode")
25
+ refuse("usage", "Doctor requires explicit contained diagnostic inputs", 2);
26
+ return runScopedProbe(legacyDoctorEffects[input.harness], input.scope, async () => {
27
+ if (input.harness === "droid" && discoverExecutable("system-ps", ["ps"], { env: { ...process.env, ...input.env } }).candidates.length === 0) {
28
+ throw new AppError("doctor_prerequisite_missing", "Droid doctor requires the OS ps utility for physical process settlement", 1, { phase: "harness_doctor", effect: "no_effect", prerequisite: "ps", help: "harnesses doctor" });
29
+ }
30
+ const args = [fileURLToPath(new URL(`../harness-runtime/bin/dd-${input.harness}.mjs`, import.meta.url)), "doctor",
31
+ `--${binOptions[input.harness]}`, input.executable, "--timeout-ms", String(timeoutMs), "--json"];
32
+ if (input.harness === "zcode") {
33
+ if (!input.nativeExecutable)
34
+ refuse("harness_selection_required", "ZCode doctor also requires --native-executable for its native runtime");
35
+ args.push("--zcode-path", input.nativeExecutable);
36
+ }
37
+ if (input.harness === "opencode") {
38
+ if (!input.stateDir)
39
+ refuse("harness_selection_required", "OpenCode doctor requires --state-dir for an existing owned daemon; no service is started");
40
+ let state;
41
+ try {
42
+ state = JSON.parse(readBoundedReleaseFile(path.join(input.stateDir, "daemon.json"), 1024 * 1024).toString("utf8"));
43
+ }
44
+ catch {
45
+ return refuse("doctor_state_unavailable", "Selected daemon identity cannot be read");
46
+ }
47
+ const selected = state;
48
+ if (selected?.config?.bin !== input.executable)
49
+ refuse("doctor_state_mismatch", "Selected daemon does not bind the discovered executable");
50
+ args.push("--state-dir", input.stateDir);
51
+ }
52
+ const transport = await import(new URL("../harness-runtime/lib/process-json.mjs", import.meta.url).href);
53
+ let report;
54
+ try {
55
+ report = await transport.commandJson(process.execPath, args, { env: input.env, timeoutMs, signal: AbortSignal.timeout(timeoutMs), phase: "native-doctor" });
56
+ }
57
+ catch {
58
+ return refuse("harness_doctor_failed", "Adapter doctor failed or could not confirm its observation; no model Turn was requested");
59
+ }
60
+ if (!report || typeof report !== "object" || Array.isArray(report) || report.ok !== true)
61
+ refuse("harness_doctor_failed", "Adapter doctor did not return an accepted diagnostic");
62
+ const observed = report.observed_runtime && typeof report.observed_runtime === "object" ? report.observed_runtime : {};
63
+ const versionField = input.harness === "codex" ? "codex_cli" : input.harness === "zcode" ? "zcode_acp" : input.harness;
64
+ const versions = report.versions && typeof report.versions === "object" && !Array.isArray(report.versions) ? report.versions : {};
65
+ // Existing OpenCode doctor reports versions separately from observed_runtime.
66
+ const versionValue = input.harness === "opencode" ? versions.opencode : observed[versionField];
67
+ const version = typeof versionValue === "string" ? parse(versionValue)?.version ?? null : null;
68
+ const protocol = observed.dd_harness_contract;
69
+ const models = Array.isArray(report.models) ? report.models.filter((model) => typeof model === "string" && /^[A-Za-z0-9][A-Za-z0-9._:/+-]{0,255}$/.test(model)).slice(0, 10_000) : [];
70
+ return { harness: input.harness, effects: legacyDoctorEffects[input.harness], reported_version: version,
71
+ reported_protocol: typeof protocol === "string" && /^dd-[a-z0-9-]+@[0-9]+$/.test(protocol) ? protocol : null,
72
+ reported_models: [...new Set(models)].sort(), models_complete: false, reported_compatible: typeof report.compatible === "boolean" ? report.compatible : null,
73
+ account_access: "unknown", qualified: "unknown", model_turn: "not_requested" };
74
+ });
75
+ }
@@ -0,0 +1,51 @@
1
+ import { AppError } from "../shared/errors.js";
2
+ export const readOnlyProbeScope = Object.freeze({
3
+ processes: false, services: false, credentials: false, writes: false
4
+ });
5
+ /** Source-grounded effects of existing adapters; this is not permission to invoke them. */
6
+ export const legacyDoctorEffects = {
7
+ codex: { child_process: true, service_process: true, credential_access: "possible", filesystem: "temporary_or_runtime_writes", model_turn: "not_requested", source_owner: "harness-runtime/lib/dd-codex.mjs:doctor/withBridge" },
8
+ zcode: { child_process: true, service_process: false, credential_access: "possible", filesystem: "read_only", model_turn: "not_requested", source_owner: "harness-runtime/lib/dd-zcode.mjs:doctor" },
9
+ agy: { child_process: true, service_process: false, credential_access: "possible", filesystem: "temporary_or_runtime_writes", model_turn: "not_requested", source_owner: "harness-runtime/lib/dd-agy.mjs:doctor" },
10
+ opencode: { child_process: true, service_process: true, credential_access: "possible", filesystem: "temporary_or_runtime_writes", model_turn: "not_requested", source_owner: "harness-runtime/lib/dd-opencode-daemon.mjs:daemon.doctor/startDaemon" },
11
+ grok: { child_process: true, service_process: false, credential_access: "possible", filesystem: "read_only", model_turn: "not_requested", source_owner: "harness-runtime/lib/dd-grok.mjs:doctor" },
12
+ droid: { child_process: true, service_process: true, credential_access: "possible", filesystem: "temporary_or_runtime_writes", model_turn: "not_requested", source_owner: "harness-runtime/lib/dd-droid-daemon.mjs:runtime.start" }
13
+ };
14
+ for (const effects of Object.values(legacyDoctorEffects))
15
+ Object.freeze(effects);
16
+ Object.freeze(legacyDoctorEffects);
17
+ export const staticDiscoveryEffects = Object.freeze({
18
+ child_process: false, service_process: false, credential_access: "none", filesystem: "read_only", model_turn: "not_requested",
19
+ source_owner: "services/discovery/static.ts:discoverExecutable"
20
+ });
21
+ /** Enforce effect ceilings before invoking a probe. A non-generative label alone is insufficient. */
22
+ export function assertProbeWithinScope(effects, scope) {
23
+ const scopeKeys = ["processes", "services", "credentials", "writes"];
24
+ const effectKeys = ["child_process", "service_process", "credential_access", "filesystem", "model_turn", "source_owner"];
25
+ if (!scope || typeof scope !== "object" || Array.isArray(scope)
26
+ || Object.keys(scope).some(key => !scopeKeys.includes(key))
27
+ || scopeKeys.some(key => !Object.hasOwn(scope, key) || typeof scope[key] !== "boolean")
28
+ || !effects || typeof effects !== "object" || Array.isArray(effects)
29
+ || effectKeys.some(key => !Object.hasOwn(effects, key)) || Object.keys(effects).some(key => !effectKeys.includes(key))
30
+ || typeof effects.child_process !== "boolean" || typeof effects.service_process !== "boolean"
31
+ || !["none", "possible"].includes(effects.credential_access)
32
+ || !["read_only", "temporary_or_runtime_writes"].includes(effects.filesystem)
33
+ || !["not_requested", "possible"].includes(effects.model_turn)
34
+ || typeof effects.source_owner !== "string" || !effects.source_owner.trim()) {
35
+ throw new AppError("probe_scope_invalid", "Probe effects and permissions require an explicit typed scope", 2, { phase: "probe_admission", effect: "no_effect", help: "harnesses" });
36
+ }
37
+ const blocked = [
38
+ effects.child_process && !scope.processes ? "child_process" : null,
39
+ effects.service_process && !scope.services ? "service_process" : null,
40
+ effects.credential_access !== "none" && !scope.credentials ? "credential_access" : null,
41
+ effects.filesystem !== "read_only" && !scope.writes ? "filesystem_writes" : null,
42
+ effects.model_turn !== "not_requested" ? "live_authorization_required" : null
43
+ ].filter(Boolean);
44
+ if (blocked.length)
45
+ throw new AppError("probe_effects_not_authorized", "Probe exceeds the selected effect scope", 1, { phase: "probe_admission", effect: "no_effect", blocked_effects: blocked, help: "harnesses" });
46
+ }
47
+ /** The callback is not entered, including synchronous effects, until admission succeeds. */
48
+ export function runScopedProbe(effects, scope, probe) {
49
+ assertProbeWithinScope(effects, scope);
50
+ return probe();
51
+ }