@deksden-com/dd-flow-cli 0.9.0-beta.137 → 0.9.0-beta.139

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 (283) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +9 -0
  3. package/dist/build-info.json +6 -6
  4. package/dist/cli/argument-values.js +5 -5
  5. package/dist/cli/command-inputs.js +89 -20
  6. package/dist/cli/command-metadata.js +197 -0
  7. package/dist/cli/command-option-descriptions.js +191 -0
  8. package/dist/cli/completion-cli.js +70 -0
  9. package/dist/cli/completion.js +57 -0
  10. package/dist/cli/error-output.js +52 -0
  11. package/dist/cli/executor-onboarding.js +76 -0
  12. package/dist/cli/flows.js +29 -0
  13. package/dist/cli/harnesses.js +84 -0
  14. package/dist/cli/help.js +240 -6
  15. package/dist/cli/input-preparation.js +54 -5
  16. package/dist/cli/memory-flow-admission.js +44 -0
  17. package/dist/cli/memory-init-invocation.js +78 -0
  18. package/dist/cli/memory-init.js +240 -0
  19. package/dist/cli/memory-storage-admission.js +53 -0
  20. package/dist/cli/models.js +39 -0
  21. package/dist/cli/native-hook-ingress.js +1 -1
  22. package/dist/cli/operator-profiles.js +61 -0
  23. package/dist/cli/output-options.js +35 -0
  24. package/dist/cli/response-file.js +71 -0
  25. package/dist/cli/run-cli.js +283 -160
  26. package/dist/cli/runtime-process.js +1 -1
  27. package/dist/cli/setup.js +149 -0
  28. package/dist/cli.js +56 -2
  29. package/dist/domain/stage-handler-identities.js +20 -0
  30. package/dist/harness-runtime/lib/daemon-operations.d.mts +1 -0
  31. package/dist/harness-runtime/lib/daemon-operations.mjs +4 -3
  32. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +53 -22
  33. package/dist/harness-runtime/lib/dd-agy.mjs +16 -5
  34. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +12 -6
  35. package/dist/harness-runtime/lib/dd-codex.mjs +24 -12
  36. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +2 -1
  37. package/dist/harness-runtime/lib/dd-droid.mjs +32 -9
  38. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +11 -3
  39. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +100 -15
  40. package/dist/harness-runtime/lib/dd-opencode.mjs +51 -20
  41. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +22 -10
  42. package/dist/harness-runtime/lib/dd-zcode.mjs +17 -4
  43. package/dist/harness-runtime/lib/delegation-instructions.d.mts +1 -0
  44. package/dist/harness-runtime/lib/delegation-instructions.mjs +16 -3
  45. package/dist/harness-runtime/lib/lease-renewal.mjs +2 -1
  46. package/dist/harness-runtime/lib/lifecycle-command.mjs +1 -0
  47. package/dist/harness-runtime/lib/managed-daemon.d.mts +1 -0
  48. package/dist/harness-runtime/lib/managed-daemon.mjs +50 -15
  49. package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
  50. package/dist/harness-runtime/lib/native-children.d.mts +2 -0
  51. package/dist/harness-runtime/lib/native-children.mjs +20 -1
  52. package/dist/harness-runtime/lib/native-hook-command.mjs +1 -1
  53. package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
  54. package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
  55. package/dist/harness-runtime/lib/opencode-plugin.mjs +32 -9
  56. package/dist/harness-runtime/lib/operation-progress.mjs +3 -1
  57. package/dist/harness-runtime/lib/provider-overload-policy.d.mts +13 -0
  58. package/dist/harness-runtime/lib/provider-overload-policy.mjs +138 -0
  59. package/dist/runtime/context.js +1 -1
  60. package/dist/schemas/discovery-result.schema.json +184 -0
  61. package/dist/schemas/execution-bundle.schema.json +205 -0
  62. package/dist/schemas/execution-settings.schema.json +162 -0
  63. package/dist/schemas/flow-descriptor.schema.json +54 -0
  64. package/dist/schemas/flow-run.schema.json +26 -0
  65. package/dist/schemas/harness-catalog.schema.json +80 -0
  66. package/dist/schemas/mb-init-compose-result.schema.json +457 -0
  67. package/dist/schemas/mb-init-discover-result.schema.json +500 -0
  68. package/dist/schemas/mb-init-finish-result.schema.json +422 -0
  69. package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
  70. package/dist/schemas/mb-init-review-result.schema.json +396 -0
  71. package/dist/schemas/mb-init-verify-result.schema.json +391 -0
  72. package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
  73. package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
  74. package/dist/schemas/memory-composition-work-result.schema.json +38 -0
  75. package/dist/schemas/memory-repair-work-result.schema.json +49 -0
  76. package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
  77. package/dist/schemas/memory-review-work-result.schema.json +43 -0
  78. package/dist/schemas/model-catalog.schema.json +153 -0
  79. package/dist/schemas/profile-settings.schema.json +122 -0
  80. package/dist/schemas/release-manifest.schema.json +291 -0
  81. package/dist/schemas/run-engine-binding.schema.json +1 -1
  82. package/dist/services/check-runner-evidence.js +51 -4
  83. package/dist/services/cli-operation-classifier.js +8 -47
  84. package/dist/services/cli-upgrade-allowlist.js +27 -0
  85. package/dist/services/code-checks.js +387 -34
  86. package/dist/services/controller-child-capacity.js +13 -0
  87. package/dist/services/controller-child-observer.js +18 -2
  88. package/dist/services/controller-execution.js +88 -0
  89. package/dist/services/controller-fanout.js +71 -12
  90. package/dist/services/dashboard.js +8 -2
  91. package/dist/services/descriptor-coordinator-session.js +35 -0
  92. package/dist/services/descriptor-root-work.js +53 -0
  93. package/dist/services/descriptor-run-settlement.js +105 -0
  94. package/dist/services/descriptor-run-start.js +449 -0
  95. package/dist/services/descriptor-stage-coordinator.js +197 -0
  96. package/dist/services/descriptor-stage-settlement.js +222 -0
  97. package/dist/services/descriptor-stage-start.js +139 -0
  98. package/dist/services/discovery/agy-discovery.js +2 -0
  99. package/dist/services/discovery/codex-discovery.js +2 -0
  100. package/dist/services/discovery/droid-discovery.js +2 -0
  101. package/dist/services/discovery/grok-discovery.js +2 -0
  102. package/dist/services/discovery/opencode-discovery.js +2 -0
  103. package/dist/services/discovery/static.js +31 -0
  104. package/dist/services/discovery/zcode-discovery.js +2 -0
  105. package/dist/services/engines.js +39 -22
  106. package/dist/services/eval-snapshots.js +83 -25
  107. package/dist/services/execution-bundles.js +263 -0
  108. package/dist/services/execution-policy.js +20 -16
  109. package/dist/services/executor-onboarding.js +56 -0
  110. package/dist/services/external-work-launch.js +93 -15
  111. package/dist/services/flow-catalog.js +21 -0
  112. package/dist/services/flow-descriptors.js +82 -0
  113. package/dist/services/frozen-engine.js +250 -0
  114. package/dist/services/generic-execution.js +164 -0
  115. package/dist/services/harness-adapter.js +28 -2
  116. package/dist/services/harness-discovery.js +29 -0
  117. package/dist/services/harness-doctor.js +75 -0
  118. package/dist/services/harness-probe-effects.js +51 -0
  119. package/dist/services/harness-version-probe.js +100 -0
  120. package/dist/services/hooks.js +24 -6
  121. package/dist/services/hybrid-contracts.js +483 -0
  122. package/dist/services/ids.js +29 -1
  123. package/dist/services/installation-lock.js +95 -0
  124. package/dist/services/installed-flow-source.js +183 -0
  125. package/dist/services/lifecycle-invocations.js +257 -78
  126. package/dist/services/managed-processes.js +31 -10
  127. package/dist/services/memory-accepted-composition.js +77 -0
  128. package/dist/services/memory-baseline-preservation.js +65 -0
  129. package/dist/services/memory-completed-correction-wave.js +320 -0
  130. package/dist/services/memory-compose-handler.js +258 -0
  131. package/dist/services/memory-composition-acceptance.js +199 -0
  132. package/dist/services/memory-composition-graph.js +134 -0
  133. package/dist/services/memory-composition-registration.js +146 -0
  134. package/dist/services/memory-composition-work-custody.js +151 -0
  135. package/dist/services/memory-composition-work-results.js +96 -0
  136. package/dist/services/memory-corrected-review-acceptance.js +129 -0
  137. package/dist/services/memory-corrected-review-batch.js +30 -0
  138. package/dist/services/memory-corrected-review-findings.js +106 -0
  139. package/dist/services/memory-corrected-review-inputs.js +210 -0
  140. package/dist/services/memory-corrected-review-projection.js +78 -0
  141. package/dist/services/memory-corrected-review-receipt.js +170 -0
  142. package/dist/services/memory-corrected-review-registration.js +191 -0
  143. package/dist/services/memory-correction-check-receipt.js +219 -0
  144. package/dist/services/memory-correction-input-owner.js +6 -0
  145. package/dist/services/memory-discover-handler.js +104 -0
  146. package/dist/services/memory-finish-evidence.js +435 -0
  147. package/dist/services/memory-finish-handler.js +215 -0
  148. package/dist/services/memory-finish-integration.js +280 -0
  149. package/dist/services/memory-finish-readiness.js +122 -0
  150. package/dist/services/memory-git-integration.js +151 -0
  151. package/dist/services/memory-historical-corrected-review.js +206 -0
  152. package/dist/services/memory-historical-original-review.js +130 -0
  153. package/dist/services/memory-historical-repair-registration.js +99 -0
  154. package/dist/services/memory-historical-second-review.js +128 -0
  155. package/dist/services/memory-init-bootstrap-readiness.js +210 -0
  156. package/dist/services/memory-init-contexts.js +89 -0
  157. package/dist/services/memory-init-controller-start.js +84 -0
  158. package/dist/services/memory-init-engine-release.js +223 -0
  159. package/dist/services/memory-init-git-policy.js +136 -0
  160. package/dist/services/memory-init-lint-capability.js +185 -0
  161. package/dist/services/memory-init-native-capacity.js +296 -0
  162. package/dist/services/memory-init-preflight.js +330 -0
  163. package/dist/services/memory-init-project-bootstrap.js +599 -0
  164. package/dist/services/memory-init-request-candidate.js +157 -0
  165. package/dist/services/memory-init-request-input.js +66 -0
  166. package/dist/services/memory-init-resource-storage.js +125 -0
  167. package/dist/services/memory-init-run-allocation.js +81 -0
  168. package/dist/services/memory-init-run-bundle.js +98 -0
  169. package/dist/services/memory-init-start.js +181 -0
  170. package/dist/services/memory-init-startup-custody.js +80 -0
  171. package/dist/services/memory-init-startup-input.js +240 -0
  172. package/dist/services/memory-init-storage.js +81 -0
  173. package/dist/services/memory-init-stores.js +359 -0
  174. package/dist/services/memory-init-worktrunk-capability.js +178 -0
  175. package/dist/services/memory-layer-publication.js +611 -0
  176. package/dist/services/memory-layer.js +156 -0
  177. package/dist/services/memory-lint-config.js +85 -0
  178. package/dist/services/memory-native-review-copy.js +165 -0
  179. package/dist/services/memory-normal-flow-entry.js +75 -0
  180. package/dist/services/memory-ordinary-defaults.js +112 -0
  181. package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
  182. package/dist/services/memory-preflight-handler.js +259 -0
  183. package/dist/services/memory-repair-current-view.js +299 -0
  184. package/dist/services/memory-repair-document-delta.js +451 -0
  185. package/dist/services/memory-repair-history.js +491 -0
  186. package/dist/services/memory-repair-physical-binding.js +312 -0
  187. package/dist/services/memory-repair-publication-files.js +152 -0
  188. package/dist/services/memory-repair-publication-intent.js +27 -0
  189. package/dist/services/memory-repair-publication-plan.js +160 -0
  190. package/dist/services/memory-repair-publication-source.js +225 -0
  191. package/dist/services/memory-repair-publication.js +794 -0
  192. package/dist/services/memory-repair-registration.js +239 -0
  193. package/dist/services/memory-repair-work-baseline.js +413 -0
  194. package/dist/services/memory-repair-work-completion.js +97 -0
  195. package/dist/services/memory-repair-work-custody.js +73 -0
  196. package/dist/services/memory-repair-work-results.js +89 -0
  197. package/dist/services/memory-repair-workspace.js +252 -0
  198. package/dist/services/memory-repair-writer-copy.js +735 -0
  199. package/dist/services/memory-result-binding.js +173 -0
  200. package/dist/services/memory-retained-review-authority.js +129 -0
  201. package/dist/services/memory-retained-review-results.js +70 -0
  202. package/dist/services/memory-retained-second-baseline.js +102 -0
  203. package/dist/services/memory-retained-second-repairs.js +156 -0
  204. package/dist/services/memory-review-acceptance.js +214 -0
  205. package/dist/services/memory-review-correction-plan.js +171 -0
  206. package/dist/services/memory-review-handler.js +585 -0
  207. package/dist/services/memory-review-inputs.js +200 -0
  208. package/dist/services/memory-review-receipt.js +180 -0
  209. package/dist/services/memory-review-registration.js +108 -0
  210. package/dist/services/memory-review-work-custody.js +124 -0
  211. package/dist/services/memory-review-work-input.js +72 -0
  212. package/dist/services/memory-review-work-results.js +73 -0
  213. package/dist/services/memory-second-corrected-review-inputs.js +165 -0
  214. package/dist/services/memory-second-correction-plan.js +76 -0
  215. package/dist/services/memory-second-repair-baseline.js +91 -0
  216. package/dist/services/memory-second-repair-launch.js +614 -0
  217. package/dist/services/memory-second-repair-registration.js +88 -0
  218. package/dist/services/memory-second-repair-source.js +187 -0
  219. package/dist/services/memory-second-review-acceptance.js +115 -0
  220. package/dist/services/memory-source-observations.js +117 -0
  221. package/dist/services/memory-stage-dispatch.js +28 -0
  222. package/dist/services/memory-stage-results.js +199 -0
  223. package/dist/services/memory-verification-acceptance.js +135 -0
  224. package/dist/services/memory-verification-checks.js +252 -0
  225. package/dist/services/memory-verification-receipt.js +159 -0
  226. package/dist/services/memory-verify-handler.js +135 -0
  227. package/dist/services/memory-work-result-preparation.js +63 -0
  228. package/dist/services/merge-server.js +2 -4
  229. package/dist/services/model-catalog.js +109 -0
  230. package/dist/services/model-discovery.js +46 -0
  231. package/dist/services/operator-profiles.js +236 -0
  232. package/dist/services/projects.js +17 -2
  233. package/dist/services/{codex-capacity.js → provider-capacity.js} +34 -16
  234. package/dist/services/recovery-snapshot-database.js +417 -2
  235. package/dist/services/release-archive-producer.js +52 -0
  236. package/dist/services/release-archive.js +143 -0
  237. package/dist/services/release-cache.js +142 -0
  238. package/dist/services/release-compatibility.js +18 -0
  239. package/dist/services/release-download.js +67 -0
  240. package/dist/services/release-envelope.js +104 -0
  241. package/dist/services/release-manifest.js +45 -0
  242. package/dist/services/release-payload.js +114 -0
  243. package/dist/services/release-producer.js +63 -0
  244. package/dist/services/release-provenance.js +160 -0
  245. package/dist/services/release-registry.js +66 -0
  246. package/dist/services/release-source.js +194 -0
  247. package/dist/services/repair-intents.js +1 -1
  248. package/dist/services/review-copy.js +10 -2
  249. package/dist/services/run-control.js +80 -9
  250. package/dist/services/run-controller-adapter.js +1 -1
  251. package/dist/services/run-controller-capture.js +10 -3
  252. package/dist/services/run-controller-process.js +21 -0
  253. package/dist/services/run-controller-recovery.js +5 -5
  254. package/dist/services/run-controller-state.js +1 -1
  255. package/dist/services/run-controller.js +158 -64
  256. package/dist/services/run-recovery-guard.js +5 -3
  257. package/dist/services/run-recovery-runtime.js +3 -3
  258. package/dist/services/run-recovery.js +145 -5
  259. package/dist/services/run-start-custody.js +177 -0
  260. package/dist/services/runs.js +413 -30
  261. package/dist/services/setup.js +377 -0
  262. package/dist/services/stage-context.js +9 -1
  263. package/dist/services/stage-handlers.js +74 -0
  264. package/dist/services/stage-report-renderer.js +63 -0
  265. package/dist/services/stage-work-graph.js +17 -0
  266. package/dist/services/vnext-code-review.js +1 -1
  267. package/dist/services/vnext-code.js +6 -6
  268. package/dist/services/vnext-execution-profile.js +2 -2
  269. package/dist/services/vnext-fanout.js +73 -11
  270. package/dist/services/vnext-merge.js +8 -3
  271. package/dist/services/vnext-plan-review.js +7 -5
  272. package/dist/services/vnext-plan.js +3 -3
  273. package/dist/services/vnext-protocolize.js +20 -6
  274. package/dist/services/vnext-workspace-policy.js +7 -2
  275. package/dist/services/work-registry.js +616 -71
  276. package/dist/services/workspace-files.js +1 -1
  277. package/dist/storage/database.js +84 -6
  278. package/dist/storage/writer-contract.js +11 -7
  279. package/package.json +13 -3
  280. package/tools/create-canon-release.mjs +33 -0
  281. package/tools/produce-hybrid-release.mjs +41 -0
  282. package/dist/harness-runtime/lib/codex-capacity-policy.d.mts +0 -10
  283. package/dist/harness-runtime/lib/codex-capacity-policy.mjs +0 -102
@@ -0,0 +1,191 @@
1
+ /** Reviewed meanings for existing runtime options. Grammar owns requiredness,
2
+ * repetition and enumerations; these descriptions do not grant effect authority.
3
+ */
4
+ export const runtimeOptionDescriptions = {
5
+ "acquire-lock": "Boolean: acquire the workspace lane lock when claiming the next merge job; waiting alone does not grant ownership.",
6
+ "adapter-executable": "Executable path retained with the registered adapter process for ownership and later reconciliation.",
7
+ after: "Timeline cursor for controller status; return observations after this sequence number.",
8
+ alias: "Additional report alias to retain with the completed stage; repeat for multiple aliases.",
9
+ all: "Refresh dashboards for all selected projects rather than only the current project.",
10
+ "allow-downgrade": "Explicitly permit lowering flow flags during a revision-checked change; other admission gates still apply.",
11
+ "answer-file": "File containing the user's answer for the selected paused stage or drive request; not a replacement task or execution policy.",
12
+ "answer-stdin": "Read the stage answer from standard input instead of --answer-file.",
13
+ apply: "Apply the proposed project-ID migration; without this switch the command remains a preview.",
14
+ "available-slots": "Record available native delegation capacity as an integer from 0 through 15; capacity is not proof of child settlement.",
15
+ "max-parallel": "Freeze the Work concurrency limit (external integer 1..256; explicit native 1..15). Omit on replay to retain the original selection; native capacity requires an authorized technical probe and never overrides runtime budgets or Work dependencies.",
16
+ "delegation": "Select external Work sessions (default) or explicit native children. Native fresh init requires --allow-live-probe; it cannot switch worker profiles.",
17
+ "allow-live-probe": "Authorize this request's bounded technical native child probe outside the RUN. It can incur provider usage; unknown effects retain exact operation custody and never restart fan-out.",
18
+ "native-config-home": "Optional absolute provider configuration home for native qualification. Otherwise preserve normal harness authentication and configuration. The CLI never copies or links credentials or rewrites operator configuration.",
19
+ backup: "New absolute backup destination for the explicitly drained database; an existing backup is never overwritten.",
20
+ "backup-created-at": "Timestamp of the retained backup used as migration evidence; must agree with the selected migration inputs.",
21
+ "backup-path": "Path to the retained backup bound into migration planning, reporting or application evidence.",
22
+ base: "Git base reference from which the requested feature worktree is created.",
23
+ bootstrap: "Request the supported initial stage bootstrap rather than starting a stage on an existing RUN; still requires declared intake and admission.",
24
+ branch: "Git branch assigned to the selected workspace or worker; a branch name does not itself authorize creation or merge.",
25
+ "budget-json": "Inline JSON declaration of runtime process budget; validated by the process owner before registration.",
26
+ "cancel-queue": "Boolean: cancel protocol queue entries as part of cancellation; does not silently settle running workers.",
27
+ candidate: "Mark the created snapshot as a recovery candidate rather than claiming accepted restoration.",
28
+ "capture-key": "Exact retained capture digest selecting the recovery state for the requested scope generation.",
29
+ "capture-path": "Destination for the selected RUN recovery capture; capture is distinct from accepting recovery.",
30
+ "capture-root": "Root directory for controller recovery captures associated with this drive request.",
31
+ check: "Check identity associated with a registered runtime process, preserving its ownership scope.",
32
+ "check-ref": "Retained check evidence reference motivating repair Work; repeat to bind multiple checks.",
33
+ "check-registry": "Include project registry consistency diagnostics in status; does not repair the registry.",
34
+ "close-sessions": "Boolean: request closing protocol Sessions during cancellation; physical completion requires separate evidence.",
35
+ code: "Stable diagnostic code for the engine, harness or environment blocker being recorded.",
36
+ command: "Command to launch as the owned runtime service, with declared ports and readiness checks.",
37
+ "context-file": "Prepared context file for the selected stage/controller request; its bytes must match --context-sha256.",
38
+ "context-sha256": "SHA-256 of the exact --context-file bytes, preventing substitution of prepared context.",
39
+ "control-id": "Retained RUN control request identity used by its owner or reconciliation command.",
40
+ "controller-id": "Retained drive controller identity; does not create an unrelated controller or bypass ownership.",
41
+ "daemon-id": "Selected provider daemon identity for scoped admission or recovery; not a request to start an arbitrary daemon.",
42
+ dashboard: "Dashboard artifact path associated with the completed stage.",
43
+ data: "Stage data artifact path supplied for validation and completion; its applicable schema is independently selected.",
44
+ "data-schema-id": "Registered schema identity for the stage data artifact; selecting a schema is not semantic acceptance.",
45
+ database: "Existing absolute SQLite database path to migrate; the command does not initialize a missing runtime database.",
46
+ "decision-file": "Retained stage decision artifact required by the selected finish contract.",
47
+ dir: "Stage artifact directory selected for attachment or lifecycle processing; must satisfy the selected stage's layout contract.",
48
+ "dispatch-barrier": "Retained dispatch barrier associated with the registered runtime process; not proof of productive admission.",
49
+ "engine-version": "Exact installed engine version selected for legacy binding recovery or a requested RUN fork.",
50
+ escalate: "Escalation policy for an owned pause/stop operation; does not authorize stopping unrelated processes.",
51
+ event: "Hook event name identifying the Codex event being handled; hook payload is validated separately.",
52
+ evidence: "Evidence reference supporting a completed plan item; repeat to retain multiple references.",
53
+ "execution-routing-file": "Validated execution routing JSON file used for the selected RUN creation or restoration; retained RUN profiles remain frozen.",
54
+ file: "JSON input file consumed by this command's declared validator; see the exact command topic for its contract.",
55
+ flag: "Explicit flow flag assignment for creation or revision; repeat for multiple assignments. Revision and policy gates still apply.",
56
+ flow: "Memory workflow whose permissions are checked; preflight does not execute that workflow.",
57
+ "flow-kind": "Flow kind recorded when creating the RUN; a label alone cannot register handlers or admit execution.",
58
+ format: "Dashboard output format; rendering and opening follow the selected command's supported formats.",
59
+ from: "Retained source identity for a fork or resume; its meaning is specified by the exact command topic.",
60
+ "from-check": "Check identity causing the repair Work, preserving traceability to the failed check.",
61
+ "from-finding": "Review finding identity motivating repair Work; repeat for multiple findings.",
62
+ "from-unresolved": "Unresolved issue identity motivating repair Work; repeat for multiple issues.",
63
+ generation: "Exact runtime scope generation; stale generations cannot admit recovery or new dispatch.",
64
+ global: "Read global dashboard data rather than one project dashboard.",
65
+ "grace-ms": "Grace period in milliseconds for an owned process or control stop before reconciliation/escalation.",
66
+ "group-by": "Usage aggregation dimension; grouping does not change source-backed usage evidence.",
67
+ hide: "Timeline event category to hide from the displayed view; repeat for multiple categories. Retained events are not deleted.",
68
+ "hook-event-id": "Trusted hook event identity binding this lifecycle invocation to its physical event.",
69
+ id: "Exact runtime process registry identity targeted by registration, lease operations or admission.",
70
+ "idempotency-key": "Stable flow-flag revision request key; retry the exact same change rather than applying it twice.",
71
+ "include-results": "Include retained Work result projections in the listing; listing remains an observation, not acceptance.",
72
+ incomplete: "Permit creation of an explicitly incomplete recovery snapshot; does not qualify it as a restorable complete snapshot.",
73
+ "intake-file": "File containing the raw user intake for initial stage bootstrap; do not replace it with an inferred solution.",
74
+ "intake-stdin": "Read raw bootstrap intake from standard input instead of --intake-file.",
75
+ "integrity-checksum": "Expected retained engine integrity checksum, checked independently of its version label.",
76
+ "interruption-json": "Inline JSON interruption evidence opening the selected RUN recovery attempt.",
77
+ "invocation-id": "Exact retained lifecycle invocation identity; syntax alone does not establish generation, ownership or authorization.",
78
+ "json-file": "JSON transition payload file; an alternative to the transition payload-file input.",
79
+ key: "Configuration or RUN variable key selected for reading or writing; supported configuration keys are validated by the owner.",
80
+ kind: "Classification of the recorded blocker or process; the exact command determines supported kinds.",
81
+ lane: "Named project workspace lane whose workspace, waiters or lock are being inspected or changed.",
82
+ "lease-ms": "Runtime process lease duration in milliseconds; renewal requires the current lease token.",
83
+ "lease-token": "Current owned lease token for the exact process or lane; not an executor credential or an ownership override.",
84
+ "registration-sha256": "Exact managed-process registration binding returned by confirmation or renewal. Pins the resource Home and registered owner/PID identity; a changed registration refuses rather than matching a reused process ID.",
85
+ limit: "Maximum number of Work entries returned by the listing; must be a positive integer.",
86
+ "manifest-json": "Inline runtime-scope manifest declaration binding the selected source manifest and executions; changed declarations refuse.",
87
+ "max-parallel-projects": "Maximum projects processed concurrently by the merge server; does not widen per-project merge authority.",
88
+ "memory-bank": "Memory Bank path whose access is checked by permission preflight; no installation or workflow is started.",
89
+ mode: "Operation mode accepted by this exact command; consult its allowed values and mode-specific effects.",
90
+ "native-session-id": "Existing physical provider Session identity for scoped recovery/admission; logical Work ancestry is separate.",
91
+ "next-action": "Explicit next-action projection stored with RUN creation or an operator override; it is not automatic dispatch.",
92
+ "observations-file": "Bounded observations JSON file for the selected fan-out/native scope; observations must satisfy ownership and settlement contracts.",
93
+ on: "Dependency Work identity to add or remove; repeat for multiple dependencies. Dependencies are not physical Session parentage.",
94
+ once: "Process one merge-server iteration instead of polling continuously.",
95
+ open: "Open the refreshed dashboard after rendering; does not alter RUN control state.",
96
+ operation: "Named operation associated with a registered process or provider admission request.",
97
+ "operation-id": "Exact retained provider operation identity bound to turn admission or release.",
98
+ "operational-decision-file": "Validated operational decision artifact authorizing the applicable snapshot restoration or fork route; not a release or arbitrary mutation permit.",
99
+ "origin-work": "Origin Work identity motivating repair; repeat to preserve multiple origins.",
100
+ outcome: "Outcome declared for the selected stage result; finish still validates its contract and evidence before transition.",
101
+ output: "Destination for a created snapshot, fork artifact or rendered dashboard; see the command's artifact contract.",
102
+ owner: "Runtime resource owner identity used for registration, admission or reconciliation; ownership is independently checked.",
103
+ "owner-pid": "Operating-system PID of the registered process owner, used for scoped liveness and reconciliation.",
104
+ package: "Engine package name used to locate the requested installed snapshot.",
105
+ parent: "Logical parent Work identity for batch creation or listing; does not make children physical subagents automatically.",
106
+ path: "Concrete workspace path used by lane, merge or worktree operations; not the stable project identity.",
107
+ "pause-id": "Exact retained user-interaction pause identity answered by this drive request.",
108
+ "payload-base64": "Base64-encoded Session registration payload; use only one payload transport.",
109
+ "payload-file": "File containing the selected transition or Session registration payload; validated before registration or transition.",
110
+ "payload-json": "Inline JSON Session registration payload; use only one payload transport.",
111
+ pid: "Operating-system PID of the registered physical process; a PID alone does not prove ownership or completion.",
112
+ "plan-file": "Previously generated cleanup plan file; application still checks its scope and explicit reason.",
113
+ "plan-item": "Plan item identity selected for the bounded worker prompt.",
114
+ "poll-interval": "Polling interval in seconds for lane/merge waiting; must be positive.",
115
+ "poll-seconds": "Merge server polling interval in seconds; must be positive.",
116
+ ports: "Comma-separated port declarations for the owned runtime service.",
117
+ preset: "Named flow-flag preset for creation or revision; explicit flag assignments and policy admission remain separate.",
118
+ "process-group-id": "Operating-system process-group identity retained for owned-tree cleanup; not a permit to kill unrelated groups.",
119
+ project: "Project selector for dashboard data, rendering or opening.",
120
+ "project-id": "Registered project identity associated with the physical runtime process.",
121
+ "prompt-sha256": "Digest of exact provider prompt bytes associated with operation admission.",
122
+ protocol: "Protocol selector limiting dashboard output to the requested protocol.",
123
+ "protocol-id": "Existing protocol identity whose feature worktree is planned, created, inspected or closed.",
124
+ "protocol-override-file": "Validated protocol override JSON input supplied at RUN creation; does not overwrite an existing frozen RUN.",
125
+ "question-file": "File containing the user question that pauses this stage/Work under the selected interaction contract.",
126
+ "question-stdin": "Read the stage question from standard input instead of --question-file.",
127
+ ready: "List dependency-ready Work entries rather than all entries; readiness does not launch them.",
128
+ "ready-path": "HTTP path used for the runtime service readiness check.",
129
+ "ready-port": "Declared service port used for the runtime readiness check.",
130
+ "ready-timeout-ms": "Maximum service readiness wait in milliseconds; must be a positive integer.",
131
+ "reason-file": "File containing the reason artifact required by the selected lifecycle finish contract.",
132
+ "recovery-id": "Exact retained RUN recovery attempt identity; recovery acceptance and physical settlement remain separate gates.",
133
+ "release-locks": "Boolean: request protocol lock release during cancellation; ownership checks still apply.",
134
+ report: "Report artifact path associated with the completed stage.",
135
+ request: "Retained request reference supplied to the selected stage finish contract; not a new setup request ID.",
136
+ requeue: "Boolean: put the failed merge job or bundle back in the queue; a failure is not converted into accepted merge evidence.",
137
+ "require-session-binding": "Require trusted physical Session binding before starting the stage; do not synthesize one from a RUN ID.",
138
+ "result-file": "Validated result JSON artifact for this stage or Work; process exit success is not a substitute for accepted result evidence.",
139
+ "result-stdin": "Read result JSON from standard input instead of --result-file.",
140
+ "retry-check": "Check identity requested for the selected bounded retry path; prior results cannot be reused without matching evidence.",
141
+ retryable: "Mark the recorded blocker as retryable; does not launch a retry or bypass the blocker.",
142
+ role: "Role metadata retained with the registered runtime process.",
143
+ schema: "Registered JSON schema name against which the supplied file is validated.",
144
+ "schema-dir": "Explicit schema directory for validation; not a workflow handler registry or permission to execute code.",
145
+ "scope-id": "Exact retained runtime/EVAL scope identity; operations must not affect neighboring scopes.",
146
+ "semantic-file": "Stage semantic result artifact; applicable schema and finish checks are selected independently.",
147
+ session: "Physical Session selector for source-backed usage aggregation.",
148
+ "session-id": "Exact retained physical Session identity for registration, status, stop or usage synchronization.",
149
+ "settlement-json": "Inline JSON physical settlement evidence sealing a recovery attempt; logical inactivity alone is insufficient.",
150
+ slug: "Safe human-readable slug used for the new typed identifier or RUN.",
151
+ snapshot: "Existing snapshot artifact selected for bootstrap or RUN restoration; restored execution requires independent admission.",
152
+ "source-home": "Source Codex home used to plan or initialize the isolated project home; credentials remain operator-owned.",
153
+ "source-version": "Source Memory Bank version whose migration impact and evidence are being assessed.",
154
+ stage: "Stage identity within the selected flow/RUN; a name alone cannot admit a foreign stage.",
155
+ "stage-entry": "Stage entry selected for snapshot capture.",
156
+ "stage-report": "Stage report artifact path supplied for completion and retained observation.",
157
+ state: "Terminal state reported for the owned runtime process; supported values are shown below.",
158
+ status: "Work filter or declared stage/RUN state, depending on the exact command; lifecycle admission remains authoritative.",
159
+ stderr: "Retained standard-error log path associated with the registered process.",
160
+ stdout: "Retained standard-output log path associated with the registered process.",
161
+ "stop-after": "Stage boundary at which the drive controller should stop advancing; not proof of physical child settlement.",
162
+ subject: "Safe subject text for the bootstrap RUN; raw user intake is supplied separately.",
163
+ "subject-id": "Identity of the protocol or other subject associated with the new RUN.",
164
+ "subject-type": "Type of subject associated with RUN creation; it does not select an executor.",
165
+ summary: "Human summary retained with plan-item or merge completion/note evidence.",
166
+ "summary-file": "File containing the diagnostic summary for a stage blocker.",
167
+ "summary-stdin": "Read the blocker summary from standard input instead of --summary-file.",
168
+ target: "Destination selector for protocol synchronization or hook management; see the exact command topic.",
169
+ "target-home": "Destination isolated Codex home used by the project home plan/init operation.",
170
+ "target-version": "Target Memory Bank version selected for migration impact, planning or application.",
171
+ "task-file": "Bounded worker task artifact used for prompt rendering or repair Work creation.",
172
+ "task-profile-file": "Validated task-profile JSON input used when freezing a new RUN's task policy.",
173
+ "task-stdin": "Read repair task content from standard input instead of --task-file.",
174
+ tasks: "Task directory whose access is checked by Memory Bank permission preflight.",
175
+ timeout: "Maximum lane/merge waiting duration in seconds; not a provider model timeout.",
176
+ to: "Requested protocol lifecycle target; transition requirements are validated before changing state.",
177
+ ttl: "Lane lease lifetime in seconds; expiry does not by itself prove physical process settlement.",
178
+ type: "Typed identifier family whose next identifier is being previewed.",
179
+ "user-required": "Boolean indicating that the blocked plan item requires a user decision.",
180
+ value: "Configuration or RUN variable value to store under --key; configuration-specific validation still applies.",
181
+ verdict: "Operator override verdict projection; cannot turn an override into ordinary semantic acceptance.",
182
+ "verification-file": "Verification evidence artifact required by the selected stage finish or repair provenance contract.",
183
+ version: "Exact engine package version to inspect; omitted selection follows the engine-info command's existing resolver.",
184
+ viewer: "Viewer requested for opening the rendered dashboard.",
185
+ "wait-ms": "Maximum observation wait in milliseconds for the requested RUN control operation; timeout is not terminal settlement.",
186
+ work: "Exact Work identity within the selected RUN/stage or associated with a registered process/merge request.",
187
+ "worker-id": "Worker identity bound to the selected Session, lane lease or merge claim; not a model/profile selector.",
188
+ worktree: "Worktree handling policy requested during protocol cancellation; project ownership and cleanup guards still apply.",
189
+ write: "Boolean: publish the project summary instead of only returning its current projection.",
190
+ yes: "Explicit confirmation for hook installation/removal; does not bypass project access or target validation."
191
+ };
@@ -0,0 +1,70 @@
1
+ import { completionCandidates } from "./completion.js";
2
+ import { prepareCommandRoute } from "./command-inputs.js";
3
+ import { parseOutputOptions } from "./output-options.js";
4
+ import { writePreparationError } from "./error-output.js";
5
+ import { AppError, errorRecord } from "../shared/errors.js";
6
+ import { prepareResponseDestination, writeResponseFile } from "./response-file.js";
7
+ export function completionScript(shell) {
8
+ if (shell === "bash")
9
+ return `# dd-flow completion: bash
10
+ _dd_flow_complete() {
11
+ local candidate
12
+ COMPREPLY=()
13
+ while IFS= read -r candidate; do
14
+ [ -n "$candidate" ] && COMPREPLY+=("$candidate")
15
+ done < <("${"$"}{COMP_WORDS[0]}" completion candidates -- "${"$"}{COMP_WORDS[@]:1:COMP_CWORD}")
16
+ }
17
+ complete -o default -F _dd_flow_complete dd-flow
18
+ `;
19
+ if (shell === "zsh")
20
+ return `#compdef dd-flow
21
+ _dd_flow_complete() {
22
+ local -a replies
23
+ replies=("${"$"}{(@f)$("${"$"}{words[1]}" completion candidates -- "${"$"}{(@)words[2,CURRENT]}")}")
24
+ if (( ${"$"}{#replies} )) && [[ -n "$replies[1]" ]]; then
25
+ compadd -a replies
26
+ else
27
+ _files
28
+ fi
29
+ }
30
+ compdef _dd_flow_complete dd-flow
31
+ `;
32
+ if (shell === "fish")
33
+ return `function __dd_flow_candidates
34
+ set -l tokens (commandline -opc)
35
+ set -l prefix (commandline -ct)
36
+ set -l arguments
37
+ if test (count $tokens) -gt 1
38
+ set arguments $tokens[2..-1]
39
+ end
40
+ $tokens[1] completion candidates -- $arguments "$prefix"
41
+ end
42
+ complete -c dd-flow -a '(__dd_flow_candidates)'
43
+ `;
44
+ throw new AppError("usage", "Supported completion shells: bash, zsh, fish", 2, { effect: "no_effect" });
45
+ }
46
+ /** Completion is grammar-only: never constructs an AppContext or writes a home. */
47
+ export function runCompletionCli(args, io = { stdout: process.stdout, stderr: process.stderr }) {
48
+ let json = false;
49
+ try {
50
+ const output = parseOutputOptions(args);
51
+ json = output.json;
52
+ if (output.responseFile)
53
+ prepareResponseDestination(output.responseFile);
54
+ const route = prepareCommandRoute(output.args);
55
+ if (route.key === "completion candidates") {
56
+ const candidates = completionCandidates(route.parsed.positional);
57
+ io.stdout.write(json ? `${JSON.stringify(writeResponseFile({ candidates }, output))}\n` : candidates.map(value => `${value}\n`).join(""));
58
+ }
59
+ else {
60
+ const script = completionScript(route.command);
61
+ io.stdout.write(json ? `${JSON.stringify(writeResponseFile({ shell: route.command, script }, output))}\n` : script);
62
+ }
63
+ return 0;
64
+ }
65
+ catch (error) {
66
+ const record = errorRecord(error);
67
+ writePreparationError(io, args, record);
68
+ return record.exitCode;
69
+ }
70
+ }
@@ -0,0 +1,57 @@
1
+ import { commandInputs } from "./command-inputs.js";
2
+ import { globalOptionDocumentation, optionsForCommandTree } from "./command-metadata.js";
3
+ const globalSwitches = globalOptionDocumentation.filter(option => option.kind === "switch").map(option => `--${option.name}`);
4
+ const globalValues = globalOptionDocumentation.filter(option => option.kind === "value").map(option => `--${option.name}`);
5
+ /** Read-only completion grammar. Last word is the cursor's unfinished token. */
6
+ export function completionCandidates(words) {
7
+ const prefix = words.at(-1) ?? "";
8
+ const completed = words.slice(0, -1);
9
+ if (completed.includes("--"))
10
+ return [];
11
+ const positions = [];
12
+ let awaiting;
13
+ let routeKey;
14
+ const keys = Object.keys(commandInputs).filter(key => !commandInputs[key].retired);
15
+ const select = () => keys.filter(key => key.split(" ").every((part, index) => positions[index] === part))
16
+ .sort((left, right) => right.split(" ").length - left.split(" ").length)[0];
17
+ for (const word of completed) {
18
+ if (awaiting) {
19
+ awaiting = undefined;
20
+ continue;
21
+ }
22
+ if (word.startsWith("--")) {
23
+ const name = word.slice(2).split("=")[0];
24
+ const input = routeKey ? commandInputs[routeKey] : undefined;
25
+ const values = input?.values ?? [...new Set(Object.values(commandInputs).flatMap(item => item.values))];
26
+ if (!word.includes("=") && (values.includes(name) || globalValues.includes(`--${name}`)))
27
+ awaiting = name;
28
+ continue;
29
+ }
30
+ if (word === "-h")
31
+ continue;
32
+ positions.push(word);
33
+ routeKey = select();
34
+ }
35
+ const input = routeKey ? commandInputs[routeKey] : undefined;
36
+ let candidates;
37
+ const inline = prefix.match(/^--([^=]+)=(.*)$/);
38
+ if (awaiting || inline) {
39
+ const option = awaiting ?? inline[1];
40
+ candidates = option === "option" ? optionsForCommandTree(routeKey ?? positions.join(" ")).map(item => item.name)
41
+ : [...(input?.enums[option] ?? [])];
42
+ if (option === "option" && (inline?.[2] ?? prefix).startsWith("--"))
43
+ candidates = candidates.map(name => `--${name}`);
44
+ if (inline)
45
+ return candidates.filter(value => value.startsWith(inline[2])).map(value => `--${option}=${value}`).sort();
46
+ }
47
+ else if (prefix.startsWith("-")) {
48
+ candidates = [...globalSwitches, ...globalValues, ...(input ? [...input.values, ...input.switches].map(name => `--${name}`) : [])];
49
+ }
50
+ else {
51
+ candidates = keys.filter(key => {
52
+ const tokens = key.split(" ");
53
+ return positions.every((part, index) => tokens[index] === part) && tokens.length > positions.length;
54
+ }).map(key => key.split(" ")[positions.length]);
55
+ }
56
+ return [...new Set(candidates)].filter(value => value.startsWith(prefix)).sort();
57
+ }
@@ -0,0 +1,52 @@
1
+ import { hasHelpIntent } from "./help.js";
2
+ import { commandHelpTopic } from "./command-metadata.js";
3
+ import { writeJson } from "../shared/json.js";
4
+ export function writePreparationError(io, args, error) {
5
+ const literal = args.indexOf("--");
6
+ const options = literal < 0 ? args : args.slice(0, literal);
7
+ const payload = { ok: false, error };
8
+ const help = hasHelpIntent(args);
9
+ let json = false;
10
+ for (let index = 0; index < options.length; index++) {
11
+ if (help && options[index] === "--option") {
12
+ index++;
13
+ continue;
14
+ }
15
+ if (options[index] === "--json")
16
+ json = true;
17
+ }
18
+ // Retain the hook's machine-only contract even when transport validation fails.
19
+ if (json || args.slice(0, 3).join(" ") === "codex hook handle")
20
+ writeJson(io.stderr, payload);
21
+ else
22
+ io.stderr.write(renderHumanError(payload, args));
23
+ }
24
+ export function renderHumanError(payload, args) {
25
+ const lines = [`dd-flow: ${payload.error.message}`];
26
+ const details = recordObject(payload.error.details);
27
+ const compatibility = recordObject(details?.compatibility);
28
+ const remediation = recordObject(details?.remediation);
29
+ if (compatibility) {
30
+ lines.push(`Compatibility: ${String(compatibility.verdict ?? "unknown")} (${String(compatibility.engine_resolution ?? "unknown")})`);
31
+ if (compatibility.blocked_operation)
32
+ lines.push(`Blocked operation: ${String(compatibility.blocked_operation)}`);
33
+ if (compatibility.install_hint)
34
+ lines.push(`Install compatible engine: ${String(compatibility.install_hint)}`);
35
+ }
36
+ if (remediation?.mb_upgrade_mode)
37
+ lines.push(`Upgrade mode: ${String(remediation.mb_upgrade_mode)}`);
38
+ if (details?.preferred_command)
39
+ lines.push(`Preferred command: ${String(details.preferred_command)}`);
40
+ const related = Array.isArray(details?.related_commands) ? details.related_commands.map(String) : [];
41
+ if (related.length > 0) {
42
+ lines.push("", "Related commands:");
43
+ for (const command of related)
44
+ lines.push(` ${command}`);
45
+ }
46
+ const topic = commandHelpTopic(args, "");
47
+ lines.push(`See: dd-flow${topic ? ` ${topic}` : ""} --help`);
48
+ return `${lines.join("\n")}\n`;
49
+ }
50
+ function recordObject(value) {
51
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
52
+ }
@@ -0,0 +1,76 @@
1
+ import { createInterface } from "node:readline";
2
+ import { AppError } from "../shared/errors.js";
3
+ import { prepareOperatorProfile, prepareProfileCreation, readOperatorProfileInput } from "../services/operator-profiles.js";
4
+ /** One explicit choice; prompts go to stderr so stdout remains machine-readable. */
5
+ export async function askExecutorChoice(settings, io, policy = {}) {
6
+ const ids = settings.profiles.map(entry => entry.id);
7
+ io.stderr.write(`Executor profiles: ${ids.length ? ids.join(", ") : "none configured"}\n`);
8
+ io.stderr.write(`Choose a profile ID/alias, file:/absolute/profile.json, create${policy.allowSkip === false ? "" : ", or skip"}. No model is selected automatically.\n`);
9
+ const terminal = createInterface({ input: io.stdin, output: io.stderr });
10
+ const lines = terminal[Symbol.asyncIterator]();
11
+ const cancelled = () => new AppError("onboarding_cancelled", "Executor onboarding was cancelled", 1, { effect: "no_effect" });
12
+ terminal.on("SIGINT", () => terminal.close());
13
+ const ask = async (prompt) => {
14
+ io.stderr.write(prompt);
15
+ const line = await lines.next();
16
+ if (line.done)
17
+ throw cancelled();
18
+ const answer = line.value.trim();
19
+ if (answer.length > 4096)
20
+ throw new AppError("usage", "Executor choice exceeds the input limit", 2, { effect: "no_effect" });
21
+ return answer;
22
+ };
23
+ try {
24
+ const answer = await ask("Executor: ");
25
+ if (answer === "skip") {
26
+ if (policy.allowSkip === false)
27
+ throw new AppError("agent_profile_missing", "This flow requires an executor profile", 1, { effect: "no_effect" });
28
+ return { skip: true };
29
+ }
30
+ if (answer === "create") {
31
+ io.stderr.write("Enter explicit profile settings; this does not probe providers or verify model access. Nothing is saved by this dialog.\n");
32
+ const input = { schema_id: "dd-flow/agent-profile@1" };
33
+ for (const [key, prompt] of [
34
+ ["id", "Profile ID: "], ["harness", "Harness (codex/zcode/agy/opencode/grok/droid): "],
35
+ ["provider", "Provider ID: "], ["model", "Model ID: "], ["reasoning", "Reasoning setting: "],
36
+ ["mode", "Mode setting: "], ["permission", "Permission (allow/deny): "]
37
+ ])
38
+ input[key] = await ask(prompt);
39
+ const profile = prepareOperatorProfile(input);
40
+ if (settings.profiles.some(entry => entry.id === profile.id) || Object.hasOwn(settings.aliases, profile.id)) {
41
+ throw new AppError("profile_id_conflict", "New profile ID collides with an existing profile or alias", 2, { effect: "no_effect" });
42
+ }
43
+ if (await ask("Use this profile for this operation? Type yes: ") !== "yes")
44
+ throw cancelled();
45
+ if (policy.allowSave === false)
46
+ return { profile };
47
+ const save = await ask("Save this profile globally during installation? Type yes or no: ");
48
+ if (save !== "yes" && save !== "no")
49
+ throw cancelled();
50
+ if (save === "yes") {
51
+ const defaultChoice = await ask("Set it as global default? Type yes or no: ");
52
+ if (defaultChoice !== "yes" && defaultChoice !== "no")
53
+ throw cancelled();
54
+ return { profile, profileCreation: prepareProfileCreation(settings, profile, defaultChoice === "yes") };
55
+ }
56
+ return { profile };
57
+ }
58
+ if (answer.startsWith("file:")) {
59
+ const file = answer.slice(5);
60
+ if (!file.startsWith("/") && !/^[A-Za-z]:[\\/]/.test(file))
61
+ throw new AppError("usage", "Profile file must be an absolute path", 2, { effect: "no_effect" });
62
+ return { profile: readOperatorProfileInput(file) };
63
+ }
64
+ if (!answer)
65
+ throw new AppError("agent_profile_missing", "An explicit executor choice is required", 1, { effect: "no_effect" });
66
+ return { profileId: answer };
67
+ }
68
+ catch (error) {
69
+ if (error instanceof AppError)
70
+ throw error;
71
+ throw cancelled();
72
+ }
73
+ finally {
74
+ terminal.close();
75
+ }
76
+ }
@@ -0,0 +1,29 @@
1
+ import { prepareCommandRoute } from "./command-inputs.js";
2
+ import { parseOutputOptions } from "./output-options.js";
3
+ import { prepareResponseDestination, writeResponseFile } from "./response-file.js";
4
+ import { listBundledFlows, showBundledFlow } from "../services/flow-catalog.js";
5
+ import { AppError, errorRecord } from "../shared/errors.js";
6
+ import { writePreparationError } from "./error-output.js";
7
+ /** Catalog inspection never creates an AppContext or executes a flow. */
8
+ export function runFlowCatalogCli(args, io = process) {
9
+ try {
10
+ const output = parseOutputOptions(args);
11
+ const route = prepareCommandRoute(output.args);
12
+ let result;
13
+ if (route.key === "flow list")
14
+ result = { flows: listBundledFlows() };
15
+ else if (route.key === "flow show")
16
+ result = { flow: showBundledFlow(route.parsed.positional[0]) };
17
+ else
18
+ throw new AppError("usage", "Use dd-flow flow list or flow show <id>", 2, { effect: "no_effect" });
19
+ if (output.responseFile)
20
+ prepareResponseDestination(output.responseFile);
21
+ io.stdout.write(`${JSON.stringify(writeResponseFile({ ok: true, action: route.key.replaceAll(" ", "_"), ...result }, output), null, output.json ? undefined : 2)}\n`);
22
+ return 0;
23
+ }
24
+ catch (error) {
25
+ const record = errorRecord(error);
26
+ writePreparationError(io, args, record);
27
+ return record.exitCode;
28
+ }
29
+ }
@@ -0,0 +1,84 @@
1
+ import { prepareCommandRoute } from "./command-inputs.js";
2
+ import { writePreparationError } from "./error-output.js";
3
+ import { parseOutputOptions } from "./output-options.js";
4
+ import { optionalOption, optionalPositiveNumber } from "./argument-values.js";
5
+ import { discoverHarnesses, harnessCatalog } from "../services/harness-discovery.js";
6
+ import { AppError, errorRecord } from "../shared/errors.js";
7
+ import { probeHarnessVersion } from "../services/harness-version-probe.js";
8
+ import { probeHarnessDoctor } from "../services/harness-doctor.js";
9
+ import { prepareResponseDestination, writeResponseFile } from "./response-file.js";
10
+ import path from "node:path";
11
+ import { validateModelScope } from "../services/model-discovery.js";
12
+ /** Home-free ingress: process diagnostics require explicit effect admission. */
13
+ export async function runHarnessesCli(args, env, io = { stdout: process.stdout, stderr: process.stderr }) {
14
+ let json = false;
15
+ try {
16
+ const output = parseOutputOptions(args);
17
+ json = output.json;
18
+ if (output.responseFile)
19
+ prepareResponseDestination(output.responseFile);
20
+ const route = prepareCommandRoute(output.args);
21
+ const family = route.key === "harnesses show" ? route.parsed.positional[0] : optionalOption(route.parsed, "harness");
22
+ if (family && !harnessCatalog.entries.some(entry => entry.id === family))
23
+ throw new AppError("usage", "Unknown harness; see dd-flow harnesses --help", 2, { effect: "no_effect" });
24
+ const provider = optionalOption(route.parsed, "provider"), account = optionalOption(route.parsed, "account-sha256");
25
+ const observationFile = optionalOption(route.parsed, "model-observation-file");
26
+ let modelScope;
27
+ if (provider !== undefined || account !== undefined || observationFile !== undefined) {
28
+ if (!provider || !account)
29
+ throw new AppError("usage", "Doctor model observations require both --provider and --account-sha256", 2, { effect: "no_effect", help: "harnesses doctor" });
30
+ modelScope = { harness: family, provider, account_sha256: account };
31
+ validateModelScope(modelScope);
32
+ if (observationFile) {
33
+ if (output.responseFile && path.resolve(observationFile) === path.resolve(output.responseFile))
34
+ throw new AppError("usage", "Model observation and command response destinations must differ", 2, { effect: "no_effect" });
35
+ prepareResponseDestination(observationFile);
36
+ }
37
+ }
38
+ const discovery = discoverHarnesses({ env, ...(family ? { harness: family } : {}),
39
+ ...(optionalOption(route.parsed, "executable") ? { executable: optionalOption(route.parsed, "executable") } : {}) });
40
+ let probe;
41
+ let modelObservation;
42
+ let observationPublication;
43
+ if (route.key === "harnesses doctor") {
44
+ const selected = discovery.entries[0]?.candidates.find(candidate => candidate.selected);
45
+ if (!selected)
46
+ throw new AppError("harness_selection_required", "Doctor requires one installed executable; use --executable for ambiguous installations", 1, { effect: "no_effect" });
47
+ const stateDir = optionalOption(route.parsed, "state-dir"), nativeExecutable = optionalOption(route.parsed, "native-executable");
48
+ const timeoutMs = optionalPositiveNumber(route.parsed, "timeout-ms", true);
49
+ probe = await probeHarnessDoctor({ harness: family, executable: selected.path, env,
50
+ ...(stateDir !== undefined ? { stateDir } : {}), ...(nativeExecutable !== undefined ? { nativeExecutable } : {}),
51
+ ...(timeoutMs !== undefined ? { timeoutMs } : {}),
52
+ scope: { processes: route.parsed.options.has("allow-processes"), services: route.parsed.options.has("allow-services"),
53
+ credentials: route.parsed.options.has("allow-credentials"), writes: route.parsed.options.has("allow-writes") } });
54
+ if (modelScope) {
55
+ modelObservation = { scope: modelScope, observed_at: new Date().toISOString(),
56
+ status: probe.reported_models.length ? "listed" : "unavailable", complete: false, models: [...probe.reported_models] };
57
+ if (observationFile) {
58
+ const published = writeResponseFile(modelObservation, { responseFile: observationFile });
59
+ observationPublication = { path: observationFile, status: published.response_file_error ? "unknown" : "published",
60
+ ...(published.response_file_error ? { error: published.response_file_error } : {}) };
61
+ }
62
+ }
63
+ }
64
+ else if (route.key === "harnesses probe-version") {
65
+ const selected = discovery.entries[0]?.candidates.find(candidate => candidate.selected);
66
+ if (!selected)
67
+ throw new AppError("harness_selection_required", "Version probe requires one installed executable; use --executable for ambiguous installations", 1, { effect: "no_effect" });
68
+ probe = await probeHarnessVersion({ harness: family, executable: selected.path, env,
69
+ ...(optionalPositiveNumber(route.parsed, "timeout-ms", true) === undefined ? {} : { timeoutMs: optionalPositiveNumber(route.parsed, "timeout-ms", true) }),
70
+ scope: { processes: route.parsed.options.has("allow-processes"), services: false,
71
+ credentials: route.parsed.options.has("allow-credentials"), writes: route.parsed.options.has("allow-writes") } });
72
+ }
73
+ const result = { ok: true, action: route.key.replaceAll(" ", "_"), catalog: harnessCatalog, discovery, ...(probe ? { probe } : {}),
74
+ ...(modelObservation ? { model_observation: modelObservation, observation_scope_binding: "operator_declared_unverified" } : {}),
75
+ ...(observationPublication ? { model_observation_publication: observationPublication } : {}) };
76
+ io.stdout.write(`${JSON.stringify(writeResponseFile(result, output), null, json ? undefined : 2)}\n`);
77
+ return 0;
78
+ }
79
+ catch (error) {
80
+ const record = errorRecord(error);
81
+ writePreparationError(io, args, record);
82
+ return record.exitCode;
83
+ }
84
+ }