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

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 (260) hide show
  1. package/CHANGELOG.md +4 -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/setup.js +149 -0
  27. package/dist/cli.js +54 -2
  28. package/dist/domain/stage-handler-identities.js +20 -0
  29. package/dist/harness-runtime/lib/daemon-operations.d.mts +1 -0
  30. package/dist/harness-runtime/lib/daemon-operations.mjs +4 -3
  31. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +4 -2
  32. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +11 -5
  33. package/dist/harness-runtime/lib/dd-codex.mjs +22 -10
  34. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +2 -1
  35. package/dist/harness-runtime/lib/dd-droid.mjs +2 -1
  36. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +4 -2
  37. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +6 -4
  38. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +9 -9
  39. package/dist/harness-runtime/lib/delegation-instructions.mjs +5 -3
  40. package/dist/harness-runtime/lib/lifecycle-command.mjs +1 -0
  41. package/dist/harness-runtime/lib/managed-daemon.d.mts +1 -0
  42. package/dist/harness-runtime/lib/managed-daemon.mjs +50 -15
  43. package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
  44. package/dist/harness-runtime/lib/native-hook-command.mjs +1 -1
  45. package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
  46. package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
  47. package/dist/harness-runtime/lib/opencode-plugin.mjs +2 -0
  48. package/dist/harness-runtime/lib/operation-progress.mjs +3 -1
  49. package/dist/runtime/context.js +1 -1
  50. package/dist/schemas/discovery-result.schema.json +184 -0
  51. package/dist/schemas/execution-bundle.schema.json +205 -0
  52. package/dist/schemas/execution-settings.schema.json +162 -0
  53. package/dist/schemas/flow-descriptor.schema.json +54 -0
  54. package/dist/schemas/flow-run.schema.json +22 -0
  55. package/dist/schemas/harness-catalog.schema.json +80 -0
  56. package/dist/schemas/mb-init-compose-result.schema.json +457 -0
  57. package/dist/schemas/mb-init-discover-result.schema.json +500 -0
  58. package/dist/schemas/mb-init-finish-result.schema.json +422 -0
  59. package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
  60. package/dist/schemas/mb-init-review-result.schema.json +396 -0
  61. package/dist/schemas/mb-init-verify-result.schema.json +391 -0
  62. package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
  63. package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
  64. package/dist/schemas/memory-composition-work-result.schema.json +38 -0
  65. package/dist/schemas/memory-repair-work-result.schema.json +49 -0
  66. package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
  67. package/dist/schemas/memory-review-work-result.schema.json +43 -0
  68. package/dist/schemas/model-catalog.schema.json +153 -0
  69. package/dist/schemas/profile-settings.schema.json +122 -0
  70. package/dist/schemas/release-manifest.schema.json +291 -0
  71. package/dist/schemas/run-engine-binding.schema.json +1 -1
  72. package/dist/services/check-runner-evidence.js +51 -4
  73. package/dist/services/cli-operation-classifier.js +8 -47
  74. package/dist/services/cli-upgrade-allowlist.js +27 -0
  75. package/dist/services/code-checks.js +387 -34
  76. package/dist/services/controller-execution.js +88 -0
  77. package/dist/services/controller-fanout.js +71 -12
  78. package/dist/services/dashboard.js +8 -2
  79. package/dist/services/descriptor-coordinator-session.js +35 -0
  80. package/dist/services/descriptor-root-work.js +53 -0
  81. package/dist/services/descriptor-run-settlement.js +105 -0
  82. package/dist/services/descriptor-run-start.js +449 -0
  83. package/dist/services/descriptor-stage-coordinator.js +197 -0
  84. package/dist/services/descriptor-stage-settlement.js +222 -0
  85. package/dist/services/descriptor-stage-start.js +139 -0
  86. package/dist/services/discovery/agy-discovery.js +2 -0
  87. package/dist/services/discovery/codex-discovery.js +2 -0
  88. package/dist/services/discovery/droid-discovery.js +2 -0
  89. package/dist/services/discovery/grok-discovery.js +2 -0
  90. package/dist/services/discovery/opencode-discovery.js +2 -0
  91. package/dist/services/discovery/static.js +31 -0
  92. package/dist/services/discovery/zcode-discovery.js +2 -0
  93. package/dist/services/engines.js +39 -22
  94. package/dist/services/eval-snapshots.js +83 -25
  95. package/dist/services/execution-bundles.js +263 -0
  96. package/dist/services/execution-policy.js +20 -16
  97. package/dist/services/executor-onboarding.js +56 -0
  98. package/dist/services/external-work-launch.js +91 -11
  99. package/dist/services/flow-catalog.js +21 -0
  100. package/dist/services/flow-descriptors.js +82 -0
  101. package/dist/services/frozen-engine.js +242 -0
  102. package/dist/services/generic-execution.js +164 -0
  103. package/dist/services/harness-adapter.js +28 -2
  104. package/dist/services/harness-discovery.js +29 -0
  105. package/dist/services/harness-doctor.js +75 -0
  106. package/dist/services/harness-probe-effects.js +51 -0
  107. package/dist/services/harness-version-probe.js +100 -0
  108. package/dist/services/hooks.js +24 -6
  109. package/dist/services/hybrid-contracts.js +483 -0
  110. package/dist/services/ids.js +29 -1
  111. package/dist/services/installation-lock.js +95 -0
  112. package/dist/services/installed-flow-source.js +183 -0
  113. package/dist/services/lifecycle-invocations.js +257 -78
  114. package/dist/services/memory-accepted-composition.js +77 -0
  115. package/dist/services/memory-baseline-preservation.js +65 -0
  116. package/dist/services/memory-completed-correction-wave.js +320 -0
  117. package/dist/services/memory-compose-handler.js +258 -0
  118. package/dist/services/memory-composition-acceptance.js +199 -0
  119. package/dist/services/memory-composition-graph.js +134 -0
  120. package/dist/services/memory-composition-registration.js +146 -0
  121. package/dist/services/memory-composition-work-custody.js +151 -0
  122. package/dist/services/memory-composition-work-results.js +96 -0
  123. package/dist/services/memory-corrected-review-acceptance.js +129 -0
  124. package/dist/services/memory-corrected-review-batch.js +30 -0
  125. package/dist/services/memory-corrected-review-findings.js +106 -0
  126. package/dist/services/memory-corrected-review-inputs.js +210 -0
  127. package/dist/services/memory-corrected-review-projection.js +78 -0
  128. package/dist/services/memory-corrected-review-receipt.js +170 -0
  129. package/dist/services/memory-corrected-review-registration.js +191 -0
  130. package/dist/services/memory-correction-check-receipt.js +219 -0
  131. package/dist/services/memory-correction-input-owner.js +6 -0
  132. package/dist/services/memory-discover-handler.js +104 -0
  133. package/dist/services/memory-finish-evidence.js +435 -0
  134. package/dist/services/memory-finish-handler.js +215 -0
  135. package/dist/services/memory-finish-integration.js +280 -0
  136. package/dist/services/memory-finish-readiness.js +122 -0
  137. package/dist/services/memory-git-integration.js +151 -0
  138. package/dist/services/memory-historical-corrected-review.js +206 -0
  139. package/dist/services/memory-historical-original-review.js +130 -0
  140. package/dist/services/memory-historical-repair-registration.js +99 -0
  141. package/dist/services/memory-historical-second-review.js +128 -0
  142. package/dist/services/memory-init-bootstrap-readiness.js +210 -0
  143. package/dist/services/memory-init-contexts.js +89 -0
  144. package/dist/services/memory-init-controller-start.js +84 -0
  145. package/dist/services/memory-init-engine-release.js +223 -0
  146. package/dist/services/memory-init-git-policy.js +136 -0
  147. package/dist/services/memory-init-lint-capability.js +185 -0
  148. package/dist/services/memory-init-native-capacity.js +241 -0
  149. package/dist/services/memory-init-preflight.js +312 -0
  150. package/dist/services/memory-init-project-bootstrap.js +599 -0
  151. package/dist/services/memory-init-request-candidate.js +157 -0
  152. package/dist/services/memory-init-request-input.js +66 -0
  153. package/dist/services/memory-init-resource-storage.js +125 -0
  154. package/dist/services/memory-init-run-allocation.js +81 -0
  155. package/dist/services/memory-init-run-bundle.js +98 -0
  156. package/dist/services/memory-init-start.js +175 -0
  157. package/dist/services/memory-init-startup-custody.js +80 -0
  158. package/dist/services/memory-init-startup-input.js +240 -0
  159. package/dist/services/memory-init-storage.js +81 -0
  160. package/dist/services/memory-init-stores.js +359 -0
  161. package/dist/services/memory-init-worktrunk-capability.js +172 -0
  162. package/dist/services/memory-layer-publication.js +611 -0
  163. package/dist/services/memory-layer.js +156 -0
  164. package/dist/services/memory-lint-config.js +85 -0
  165. package/dist/services/memory-native-review-copy.js +165 -0
  166. package/dist/services/memory-normal-flow-entry.js +75 -0
  167. package/dist/services/memory-ordinary-defaults.js +112 -0
  168. package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
  169. package/dist/services/memory-preflight-handler.js +259 -0
  170. package/dist/services/memory-repair-current-view.js +299 -0
  171. package/dist/services/memory-repair-document-delta.js +451 -0
  172. package/dist/services/memory-repair-history.js +491 -0
  173. package/dist/services/memory-repair-physical-binding.js +312 -0
  174. package/dist/services/memory-repair-publication-files.js +152 -0
  175. package/dist/services/memory-repair-publication-intent.js +27 -0
  176. package/dist/services/memory-repair-publication-plan.js +160 -0
  177. package/dist/services/memory-repair-publication-source.js +225 -0
  178. package/dist/services/memory-repair-publication.js +794 -0
  179. package/dist/services/memory-repair-registration.js +239 -0
  180. package/dist/services/memory-repair-work-baseline.js +413 -0
  181. package/dist/services/memory-repair-work-completion.js +97 -0
  182. package/dist/services/memory-repair-work-custody.js +73 -0
  183. package/dist/services/memory-repair-work-results.js +89 -0
  184. package/dist/services/memory-repair-workspace.js +252 -0
  185. package/dist/services/memory-repair-writer-copy.js +735 -0
  186. package/dist/services/memory-result-binding.js +173 -0
  187. package/dist/services/memory-retained-review-authority.js +129 -0
  188. package/dist/services/memory-retained-review-results.js +70 -0
  189. package/dist/services/memory-retained-second-baseline.js +102 -0
  190. package/dist/services/memory-retained-second-repairs.js +156 -0
  191. package/dist/services/memory-review-acceptance.js +214 -0
  192. package/dist/services/memory-review-correction-plan.js +171 -0
  193. package/dist/services/memory-review-handler.js +585 -0
  194. package/dist/services/memory-review-inputs.js +200 -0
  195. package/dist/services/memory-review-receipt.js +180 -0
  196. package/dist/services/memory-review-registration.js +108 -0
  197. package/dist/services/memory-review-work-custody.js +124 -0
  198. package/dist/services/memory-review-work-input.js +72 -0
  199. package/dist/services/memory-review-work-results.js +73 -0
  200. package/dist/services/memory-second-corrected-review-inputs.js +165 -0
  201. package/dist/services/memory-second-correction-plan.js +76 -0
  202. package/dist/services/memory-second-repair-baseline.js +91 -0
  203. package/dist/services/memory-second-repair-launch.js +614 -0
  204. package/dist/services/memory-second-repair-registration.js +88 -0
  205. package/dist/services/memory-second-repair-source.js +187 -0
  206. package/dist/services/memory-second-review-acceptance.js +115 -0
  207. package/dist/services/memory-source-observations.js +117 -0
  208. package/dist/services/memory-stage-dispatch.js +28 -0
  209. package/dist/services/memory-stage-results.js +199 -0
  210. package/dist/services/memory-verification-acceptance.js +135 -0
  211. package/dist/services/memory-verification-checks.js +252 -0
  212. package/dist/services/memory-verification-receipt.js +159 -0
  213. package/dist/services/memory-verify-handler.js +135 -0
  214. package/dist/services/memory-work-result-preparation.js +63 -0
  215. package/dist/services/model-catalog.js +109 -0
  216. package/dist/services/model-discovery.js +46 -0
  217. package/dist/services/operator-profiles.js +236 -0
  218. package/dist/services/projects.js +17 -2
  219. package/dist/services/recovery-snapshot-database.js +416 -1
  220. package/dist/services/release-archive-producer.js +52 -0
  221. package/dist/services/release-archive.js +143 -0
  222. package/dist/services/release-cache.js +142 -0
  223. package/dist/services/release-compatibility.js +18 -0
  224. package/dist/services/release-download.js +67 -0
  225. package/dist/services/release-envelope.js +104 -0
  226. package/dist/services/release-manifest.js +45 -0
  227. package/dist/services/release-payload.js +114 -0
  228. package/dist/services/release-producer.js +63 -0
  229. package/dist/services/release-provenance.js +160 -0
  230. package/dist/services/release-registry.js +66 -0
  231. package/dist/services/release-source.js +194 -0
  232. package/dist/services/repair-intents.js +1 -1
  233. package/dist/services/review-copy.js +10 -2
  234. package/dist/services/run-control.js +80 -9
  235. package/dist/services/run-controller-capture.js +10 -3
  236. package/dist/services/run-controller-process.js +21 -0
  237. package/dist/services/run-controller-recovery.js +3 -1
  238. package/dist/services/run-controller-state.js +1 -1
  239. package/dist/services/run-controller.js +101 -40
  240. package/dist/services/run-recovery-guard.js +2 -0
  241. package/dist/services/run-recovery.js +145 -5
  242. package/dist/services/run-start-custody.js +177 -0
  243. package/dist/services/runs.js +319 -25
  244. package/dist/services/setup.js +377 -0
  245. package/dist/services/stage-context.js +9 -1
  246. package/dist/services/stage-handlers.js +74 -0
  247. package/dist/services/stage-report-renderer.js +63 -0
  248. package/dist/services/stage-work-graph.js +17 -0
  249. package/dist/services/vnext-code.js +3 -3
  250. package/dist/services/vnext-execution-profile.js +2 -2
  251. package/dist/services/vnext-fanout.js +70 -9
  252. package/dist/services/vnext-merge.js +8 -3
  253. package/dist/services/vnext-plan-review.js +6 -4
  254. package/dist/services/work-registry.js +616 -71
  255. package/dist/services/workspace-files.js +1 -1
  256. package/dist/storage/database.js +84 -6
  257. package/dist/storage/writer-contract.js +11 -7
  258. package/package.json +13 -3
  259. package/tools/create-canon-release.mjs +33 -0
  260. package/tools/produce-hybrid-release.mjs +41 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @deksden-com/dd-flow-cli
2
2
 
3
+ ## 0.9.0-beta.138
4
+
5
+ - Retain causal native check failures and permit fenced source repair in the same Session. Reject malformed repair proofs and preserve physical execution blockers during reconciliation.
6
+
3
7
  ## 0.9.0-beta.137
4
8
 
5
9
  - Preserve shared reasoning/mode options in OpenCode v2 and support non-generative doctor before daemon startup.
package/README.md CHANGED
@@ -36,6 +36,15 @@ Add `DD_TEST_OPENCODE_LONG=1` to prove shell progress beyond the old 120s cutoff
36
36
 
37
37
  ## Native daemon shutdown
38
38
 
39
+ Managed native shells use the launch-bound `DD_FLOW_DAEMON_ID`, `DD_FLOW_HOME`,
40
+ `DD_FLOW_BIN` and resource path. Inherited invocation/control authority is
41
+ cleared; security-only launches do not borrow a previous RUN's identity.
42
+ Compact lifecycle commands resolve private arguments from the issued assignment
43
+ and its native receipt, not from a model-supplied ID or the latest matching row.
44
+ A lost managed binding is a tooling failure, not permission to replay a short
45
+ command. Corrective retries are scoped to the action, Session and Stage attempt;
46
+ exact native event re-delivery returns the retained outcome.
47
+
39
48
  `daemon.stop` fences productive dispatch before awaiting settlement. A successful
40
49
  durable stop receipt follows native tree settlement, physical provider exit,
41
50
  journal drain and required resource/auth finalization. The endpoint then retires
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "cli_package": "@deksden-com/dd-flow-cli",
3
- "cli_version": "0.9.0-beta.137",
4
- "cli_commit": "3a1e4cb4a0a24e388228ebb85591350fa4f5886b",
5
- "built_at": "2026-10-14T05:52:24.329Z",
3
+ "cli_version": "0.9.0-beta.138",
4
+ "cli_commit": "c1a9786d04e0944daac204e1c767414904d9ced2",
5
+ "built_at": "2026-10-15T05:27:46.626Z",
6
6
  "built_with_canon": {
7
7
  "version": "4.1.2",
8
8
  "commit": "1ddedf9d3f086e046f8e7b194c739ec386e7c8b9",
9
9
  "flow_contract": "dd-flow-canonical-2026-08",
10
- "repo_root": "/Users/deksden/Documents/_Projects/dd-memorybank",
11
- "memorybank_root": "/Users/deksden/Documents/_Projects/dd-memorybank/.memory-bank",
12
- "flow_root": "/Users/deksden/Documents/_Projects/dd-memorybank/.memory-bank/dd-flow",
10
+ "repo_root": "/Users/deksden/Documents/_Projects/_worktrees/dd-memorybank-084-release",
11
+ "memorybank_root": "/Users/deksden/Documents/_Projects/_worktrees/dd-memorybank-084-release/.memory-bank",
12
+ "flow_root": "/Users/deksden/Documents/_Projects/_worktrees/dd-memorybank-084-release/.memory-bank/dd-flow",
13
13
  "layout": "dot_memory_bank"
14
14
  }
15
15
  }
@@ -4,15 +4,15 @@ export function optionalOption(parsed, key) {
4
4
  const values = parsed.options.get(key);
5
5
  const value = values?.[values.length - 1];
6
6
  if (value === flagValue)
7
- throw new AppError("usage", `--${key} requires a value`, 2);
7
+ throw new AppError("usage", `--${key} requires a value`, 2, { parameter: key, reason: "missing_option_value" });
8
8
  if (value !== undefined && !value.trim())
9
- throw new AppError("usage", `--${key} requires a non-empty value`, 2);
9
+ throw new AppError("usage", `--${key} requires a non-empty value`, 2, { parameter: key, reason: "empty_option_value" });
10
10
  return value;
11
11
  }
12
12
  export function requiredOption(parsed, key) {
13
13
  const value = optionalOption(parsed, key);
14
14
  if (!value) {
15
- throw new AppError("usage", `Missing required option: --${key}`, 2);
15
+ throw new AppError("usage", `Missing required option: --${key}`, 2, { parameter: key, reason: "missing_required_option" });
16
16
  }
17
17
  return value;
18
18
  }
@@ -23,7 +23,7 @@ export function optionalNumber(parsed, key) {
23
23
  }
24
24
  const parsedNumber = Number(value);
25
25
  if (!Number.isFinite(parsedNumber)) {
26
- throw new AppError("validation", `--${key} must be a number`, 2);
26
+ throw new AppError("validation", `--${key} must be a number`, 2, { parameter: key, reason: "invalid_number" });
27
27
  }
28
28
  return parsedNumber;
29
29
  }
@@ -32,7 +32,7 @@ export function optionalPositiveNumber(parsed, key, integer = false) {
32
32
  if (typeof value === "undefined")
33
33
  return undefined;
34
34
  if (value <= 0 || (integer && !Number.isInteger(value))) {
35
- throw new AppError("validation", `--${key} must be a positive${integer ? " integer" : ""} number`, 2);
35
+ throw new AppError("validation", `--${key} must be a positive${integer ? " integer" : ""} number`, 2, { parameter: key, reason: "invalid_number" });
36
36
  }
37
37
  return value;
38
38
  }
@@ -1,7 +1,7 @@
1
1
  import { AppError } from "../shared/errors.js";
2
2
  import { parseCommandArgs } from "../services/lifecycle-command.js";
3
3
  import { lifecycleInternalOptions, lifecycleRouteForOperation } from "../services/lifecycle-contract.js";
4
- import { isUpgradeAllowlisted } from "../services/cli-operation-classifier.js";
4
+ import { isUpgradeAllowlisted } from "../services/cli-upgrade-allowlist.js";
5
5
  const words = (value) => value.split(" ").filter(Boolean);
6
6
  const route = (positions, required = "", values = "", switches = "", repeatable = "", enums = {}) => ({
7
7
  positions: typeof positions === "number" ? [positions, positions] : positions,
@@ -12,12 +12,50 @@ const scoped = "project-root"; // Optional when the router resolves a unique ret
12
12
  const lifecycle = lifecycleInternalOptions.join(" ");
13
13
  const worker = "worker-id";
14
14
  const control = "project-root run";
15
+ const protocolTransitionInput = route(1, "to", `${scoped} payload-file json-file reason`, "force");
16
+ const setupInput = route(0, "request-id trust-file", "canon-source canon-version release-registry channel profile profile-file save-profile-intent", "non-interactive skip-agent-setup", "", { channel: ["stable", "preview", "development"] });
17
+ const memoryInitInput = route(0, "project-root workspace-root request-id", "intake-file intake-sha256 profile profile-file stage-profile work-profile max-parallel delegation native-config-home git-route integration-branch", "detach non-interactive prepare-only allow-live-probe", "stage-profile work-profile", { "git-route": ["integration_branch_direct", "feature_worktree"], delegation: ["external", "native"] });
18
+ export const commandAliases = { transition: "protocol transition", init: "flow mb-init" };
15
19
  /** Path-shaped arguments default to physical paths unless the route explicitly
16
20
  * opts into contextualPaths. This inventory does not expand arbitrary strings. */
17
- export const physicalPathOptions = new Set(words("root project-root workspace-root workspace-path path dir file schema-dir output result-file semantic-file data decision-file verification-file reason-file task-file intake-file context-file observations-file observation-file summary-file question-file answer-file payload-file json-file task-profile-file execution-routing-file protocol-override-file manifest-file routing-file config-file input-file report-file snapshot-file output-dir state-dir capture-root capture-path destination source archive snapshot plan-file backup-path database backup source-home target-home stdout stderr adapter-executable memory-bank flow stage-report dashboard report"));
21
+ export const physicalPathOptions = new Set(words("canon-source trust-file root project-root workspace-root workspace-path workspace-path path dir file schema-dir output result-file semantic-file data decision-file verification-file reason-file task-file intake-file context-file observations-file observation-file summary-file question-file answer-file payload-file json-file task-profile-file execution-routing-file protocol-override-file manifest-file routing-file config-file input-file report-file snapshot-file output-dir state-dir capture-root capture-path destination source archive snapshot plan-file backup-path database backup source-home target-home stdout stderr adapter-executable memory-bank flow stage-report dashboard report"));
22
+ physicalPathOptions.add("profile-file");
23
+ physicalPathOptions.add("save-profile-intent");
24
+ physicalPathOptions.add("model-observation-file");
25
+ physicalPathOptions.add("release-registry");
26
+ physicalPathOptions.add("seed-file");
27
+ physicalPathOptions.add("native-executable");
28
+ physicalPathOptions.add("native-config-home");
18
29
  physicalPathOptions.add("operational-decision-file");
19
30
  export const commandInputs = {
20
31
  "version": route(0),
32
+ "flow list": route(0),
33
+ "flow show": route(1),
34
+ "flow mb-init": memoryInitInput,
35
+ "init": memoryInitInput,
36
+ "runtime storage admit": route(0, "operation", "", "", "", { operation: ["memory-init"] }),
37
+ "runtime flow admit": route(0, "operation", "", "", "", { operation: ["memory-init"] }),
38
+ "completion bash": route(0),
39
+ "completion zsh": route(0),
40
+ "completion fish": route(0),
41
+ "completion candidates": route([0, 1000]),
42
+ "harnesses list": route(0),
43
+ "models list": route(0, "", "harness provider account-sha256 seed-file observation-file", "", "", { harness: ["codex", "zcode", "agy", "opencode", "grok", "droid"] }),
44
+ "models show": route(1, "", "harness provider account-sha256 seed-file observation-file", "", "", { harness: ["codex", "zcode", "agy", "opencode", "grok", "droid"] }),
45
+ "harnesses show": route(1),
46
+ "harnesses discover": route(0, "", "harness executable", "", "", { harness: ["codex", "zcode", "agy", "opencode", "grok", "droid"] }),
47
+ "harnesses probe-version": route(0, "harness", "executable timeout-ms", "allow-processes allow-credentials allow-writes", "", { harness: ["codex", "zcode", "agy", "opencode", "grok", "droid"] }),
48
+ "harnesses doctor": route(0, "harness", "executable native-executable state-dir timeout-ms provider account-sha256 model-observation-file", "allow-processes allow-services allow-credentials allow-writes", "", { harness: ["codex", "zcode", "agy", "opencode", "grok", "droid"] }),
49
+ "setup": setupInput,
50
+ "setup update": setupInput,
51
+ "setup status": route(0),
52
+ "profiles list": route(0),
53
+ "profiles show": route(1),
54
+ "profiles create": route(0, "file expected-revision", "", "set-default"),
55
+ "profiles edit": route(0, "file expected-revision"),
56
+ "profiles remove": route(1, "expected-revision"),
57
+ "profiles alias": route(1, "expected-revision", "target", "remove"),
58
+ "profiles set-default": route([0, 1], "expected-revision", "", "clear"),
21
59
  "status": route(0, "", "root project-root", "check-registry"),
22
60
  "project register": route(0, "root"),
23
61
  "project status": route(0, "root"),
@@ -34,8 +72,8 @@ export const commandInputs = {
34
72
  "protocol blockers": route(1, project),
35
73
  "protocol implement": route(1, "", `${scoped} reason`, "force"),
36
74
  "protocol ready-for-merge": route(1, "", scoped),
37
- "protocol transition": route(1, "to", `${scoped} payload-file json-file reason`, "force"),
38
- "transition": route(1, "to", `${scoped} payload-file json-file reason`, "force"),
75
+ "protocol transition": protocolTransitionInput,
76
+ "transition": protocolTransitionInput,
39
77
  "protocol sync-from-run": route(1, "run", `${scoped} target`),
40
78
  "protocol cancel": route(1, "reason", `${scoped} close-sessions cancel-queue release-locks worktree`, "force"),
41
79
  "plan status": route(1, "", scoped),
@@ -57,7 +95,7 @@ export const commandInputs = {
57
95
  "stage fanout reconcile": { ...route(1, "stage observations-file", scoped), contextualPaths: words("project-root observations-file") },
58
96
  "stage native observe": { ...route(1, "stage observations-file", scoped), contextualPaths: words("project-root observations-file") },
59
97
  "work status": route(1, project),
60
- "work add-batch": { ...route(0, "parent file", scoped), contextualPaths: words("project-root file") },
98
+ "work add-batch": { ...route(0, "parent file", `${scoped} stage request-key`), contextualPaths: words("project-root file") },
61
99
  "work ls": route(0, "", `${scoped} run parent status limit`, "ready include-results", "", { status: ["created", "running", "paused", "completed", "failed", "cancelled"] }),
62
100
  "work show": route(1, "", scoped),
63
101
  "work repair add": { ...route(0, "run", `${scoped} origin-work from-check from-finding from-unresolved check-ref verification-file task-file`, "task-stdin", "origin-work from-finding from-unresolved check-ref"), contextualPaths: words("project-root verification-file task-file") },
@@ -101,7 +139,7 @@ export const commandInputs = {
101
139
  "run recovery capture": route(1, `${project} recovery-id capture-path`),
102
140
  "run recovery resume": route(1, `${project} recovery-id daemon-id harness native-session-id`),
103
141
  "run recovery accept": { ...route(1, `${project} recovery-id`, lifecycle), contextualPaths: ["project-root"] },
104
- "run snapshot bootstrap create": route(0, `${project} output`),
142
+ "run snapshot bootstrap create": route(0, `${project} output flow`),
105
143
  "run snapshot bootstrap restore": route(0, `${project} snapshot`),
106
144
  "run snapshot create": route(1, `${project} output`, "recovery-id stage-entry", "candidate incomplete"),
107
145
  "run snapshot restore": route(0, `${project} snapshot`, "execution-routing-file operational-decision-file recovery-id"),
@@ -225,14 +263,33 @@ export const commandInputs = {
225
263
  "dashboard refresh": route(0, "", "project project-root protocol open format output", "all"),
226
264
  "dashboard refresh-global": route(0, "", "output format"),
227
265
  "schema validate": { ...route(0, "schema file", "schema-dir project-root run"), contextualPaths: words("project-root file") },
228
- "memory permissions preflight": route(0, "root memory-bank flow mode", "tasks")
266
+ "memory permissions preflight": route(0, "root memory-bank flow mode", "tasks"),
267
+ "memory compose register": route(0, "project-root run request-key result-file"),
268
+ "memory verify checks": route(0, "project-root run"),
269
+ "memory review register": route(0, "project-root run"),
270
+ "memory review collect": route(0, "project-root run"),
271
+ "memory finish evidence": route(0, "project-root run"),
272
+ "memory finish integrate": route(0, "project-root run"),
273
+ "memory corrections register": route(0, "project-root run wave result-file", "", "", "", { wave: ["1", "2"] }),
274
+ "memory corrections checks": route(0, "project-root run wave", "", "", "", { wave: ["1", "2"] }),
275
+ "memory review selective-register": route(0, "project-root run wave", "", "", "", { wave: ["1", "2"] }),
276
+ "memory review selective-collect": route(0, "project-root run wave", "", "", "", { wave: ["1", "2"] }),
277
+ "memory repair baseline": route(0, "project-root run wave work", "", "", "", { wave: ["1", "2"] }),
278
+ "memory repair copy-reserve": route(0, "project-root run wave work", "", "", "", { wave: ["1", "2"] }),
279
+ "memory repair copy-materialize": route(0, "project-root run wave work", "", "", "", { wave: ["1", "2"] }),
280
+ "memory repair copy-dispatch": route(0, "project-root run wave work", "", "", "", { wave: ["1", "2"] }),
281
+ "memory repair current-view": route(0, "project-root run wave work workspace-root", "", "", "", { wave: ["1", "2"] }),
282
+ "memory repair publication-source": route(0, "project-root run wave work workspace-root work-session", "", "", "", { wave: ["1"] }),
283
+ "memory repair publication-reserve": route(0, "project-root run wave work workspace-root work-session result-file", "", "", "", { wave: ["1", "2"] }),
284
+ "memory repair publication-apply": route(0, "project-root run wave work workspace-root work-session", "", "", "", { wave: ["1", "2"] }),
285
+ "memory repair publication-finish": route(0, "project-root run wave work workspace-root work-session", "", "", "", { wave: ["1", "2"] })
229
286
  };
230
287
  export function contextualPathOptionsForLifecycle(operation) {
231
288
  const key = lifecycleRouteForOperation(operation);
232
289
  return new Set(commandInputs[key]?.contextualPaths ?? []);
233
290
  }
234
291
  const flag = "__dd_flow_flag__";
235
- const positiveInteger = new Set(words("limit lease-ms pid owner-pid process-group-id ready-timeout-ms max-parallel-projects expected-revision"));
292
+ const positiveInteger = new Set(words("limit lease-ms pid owner-pid process-group-id ready-timeout-ms max-parallel max-parallel-projects expected-revision"));
236
293
  const nonnegativeInteger = new Set(words("after generation wait-ms grace-ms available-slots"));
237
294
  const positiveNumber = new Set(words("ttl poll-interval poll-seconds"));
238
295
  const booleans = new Set(words("write close-sessions cancel-queue release-locks user-required requeue acquire-lock"));
@@ -240,7 +297,7 @@ export function prepareCommandRoute(args) {
240
297
  const parsed = parseCommandArgs(args);
241
298
  const key = Object.keys(commandInputs).filter(key => key.split(" ").every((part, index) => parsed.positional[index] === part))
242
299
  .sort((a, b) => b.split(" ").length - a.split(" ").length)[0];
243
- const reject = (message, parameter) => { throw new AppError("usage", message, 2, { phase: "prepare", effect: "no_effect", recoverable: true, ...(parameter ? { parameter } : {}) }); };
300
+ const reject = (message, parameter, reason = "invalid_argument") => { throw new AppError("usage", message, 2, { phase: "prepare", effect: "no_effect", recoverable: true, reason, ...(parameter ? { parameter } : {}) }); };
244
301
  if (!key)
245
302
  return reject("Unknown command; use dd-flow --help");
246
303
  const contract = commandInputs[key];
@@ -259,7 +316,7 @@ export function prepareCommandRoute(args) {
259
316
  if (!upgrade && !contract.values.includes(name) && !contract.switches.includes(name))
260
317
  reject(`${key} does not accept --${name}`, name);
261
318
  if (values.length > 1 && !contract.repeatable.includes(name))
262
- reject(`--${name} must occur once`, name);
319
+ reject(`--${name} must occur once`, name, "duplicate_option");
263
320
  for (const value of values) {
264
321
  if (contract.switches.includes(name) || name === "mb-upgrade-mode") {
265
322
  if (value !== flag)
@@ -267,26 +324,38 @@ export function prepareCommandRoute(args) {
267
324
  continue;
268
325
  }
269
326
  if (value === flag || !value.trim())
270
- reject(`--${name} requires a non-empty value`, name);
327
+ reject(`--${name} requires a non-empty value`, name, value === flag ? "missing_option_value" : "empty_option_value");
271
328
  if (name === "compatibility-mode" && value !== "mb-upgrade")
272
- reject("--compatibility-mode must be mb-upgrade", name);
329
+ reject("--compatibility-mode must be mb-upgrade", name, "invalid_choice");
273
330
  const choices = contract.enums[name];
274
331
  if (choices && !choices.includes(key === "id next" && name === "type" ? value.toLowerCase() : value))
275
- reject(`--${name} must be ${choices.join(" or ")}`, name);
332
+ reject(`--${name} must be ${choices.join(" or ")}`, name, "invalid_choice");
276
333
  if (booleans.has(name) && !["true", "false"].includes(value))
277
- reject(`--${name} must be true or false`, name);
334
+ reject(`--${name} must be true or false`, name, "invalid_choice");
278
335
  const number = Number(value);
279
- if (positiveInteger.has(name) && (!/^[0-9]+$/.test(value) || !Number.isSafeInteger(number) || number <= 0)
336
+ const profileRevision = key.startsWith("profiles ") && name === "expected-revision";
337
+ if (profileRevision && !/^[a-f0-9]{64}$/.test(value))
338
+ reject("--expected-revision requires the SHA-256 returned by profiles list", name);
339
+ if (!profileRevision && positiveInteger.has(name) && (!/^[0-9]+$/.test(value) || !Number.isSafeInteger(number) || number <= 0)
280
340
  || nonnegativeInteger.has(name) && (!/^[0-9]+$/.test(value) || !Number.isSafeInteger(number) || number < 0)
281
341
  || positiveNumber.has(name) && (!Number.isFinite(number) || number <= 0)
282
342
  || name === "timeout" && (!Number.isFinite(number) || number < 0)
283
- || name === "available-slots" && number > 15)
284
- reject(`Invalid numeric value for --${name}`, name);
343
+ || name === "available-slots" && number > 15
344
+ || name === "max-parallel" && number > 256)
345
+ reject(`Invalid numeric value for --${name}`, name, "invalid_number");
285
346
  }
286
347
  }
287
348
  for (const name of contract.required)
288
349
  if (!parsed.options.has(name))
289
- reject(`Missing required option: --${name}`, name);
350
+ reject(`Missing required option: --${name}`, name, "missing_required_option");
351
+ if (key === "work add-batch" && parsed.options.has("request-key")) {
352
+ const requestKey = parsed.options.get("request-key")[0];
353
+ const stage = parsed.options.get("stage")?.[0];
354
+ if (!/^[A-Za-z0-9][A-Za-z0-9_.-]{0,95}$/.test(requestKey))
355
+ reject("--request-key requires a bounded identifier (1..96 characters)", "request-key");
356
+ if (!stage || !/^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/.test(stage))
357
+ reject("--request-key requires an explicit bounded --stage", "stage");
358
+ }
290
359
  for (const aliases of [
291
360
  ["root", "project-root"], ["payload-file", "json-file"],
292
361
  ["payload-file", "payload-json", "payload-base64"], ["semantic-file", "data", "result-file", "result-stdin"],
@@ -296,12 +365,12 @@ export function prepareCommandRoute(args) {
296
365
  ]) {
297
366
  const present = aliases.filter(name => parsed.options.has(name));
298
367
  if (present.length > 1)
299
- reject(`Use only one of ${present.map(name => `--${name}`).join(", ")}`);
368
+ reject(`Use only one of ${present.map(name => `--${name}`).join(", ")}`, [...present].sort(), "duplicate_option");
300
369
  }
301
370
  if (contract.values.includes("retry-check") && parsed.options.has("retry-check") !== (parsed.options.has("reason") || parsed.options.has("reason-file")))
302
371
  reject("--retry-check requires exactly one of --reason or --reason-file");
303
372
  // Retain the dispatcher's historic offsets for nested action positions.
304
373
  const family = parsed.positional[0];
305
- const singleWord = ["status", "version", "transition"].includes(family);
374
+ const singleWord = ["status", "version", "transition", "init"].includes(family);
306
375
  return { key, family, command: singleWord ? undefined : parsed.positional[1], parsed: { options: parsed.options, positional: parsed.positional.slice(singleWord ? 1 : 2) } };
307
376
  }
@@ -0,0 +1,197 @@
1
+ import { commandInputs, physicalPathOptions } from "./command-inputs.js";
2
+ import { runtimeOptionDescriptions } from "./command-option-descriptions.js";
3
+ const optionDescriptions = {
4
+ "intake-sha256": "SHA-256 of the exact original intake file bytes. Fresh execution verifies the bytes; replay compares the retained hash without reopening the original file.",
5
+ "stage-profile": "Repeatable stage=profile assignment for the six mb-init stages. Each stage may occur once; the selected profile ID or alias is frozen before dispatch.",
6
+ "work-profile": "Repeatable approved Work executor profile ID or alias. Explicit order is retained; duplicate profiles refuse.",
7
+ "git-route": "Explicit project Git integration route. Direct integration uses the integration branch checkout; feature_worktree uses an already assigned separate checkout.",
8
+ "integration-branch": "Explicit project integration branch, validated with Git before project publication. No branch is inferred from the current checkout.",
9
+ "detach": "Return the accepted managed-controller receipt without observing until completion. Disconnecting the observer never stops the controller.",
10
+ "harness": "Select one supported harness family. Static discovery checks executable presence, not authentication or model access; diagnostics require separate effect consent.",
11
+ "provider": "Exact provider namespace for model filtering or doctor observation binding, including namespaced IDs such as builtin:zai-coding-plan. An account binding requires --account-sha256; this selector does not authenticate credentials.",
12
+ "executable": "Explicit installed harness executable path, including paths with spaces. Resolves ambiguous installations without choosing an arbitrary PATH candidate. Discovery never executes it; probes require explicit effect flags.",
13
+ "state-dir": "Existing OpenCode server state directory for the selected doctor. Its daemon configuration must bind the selected executable; doctor does not start or stop an unrelated daemon. Not an executor profile or project directory.",
14
+ "model-observation-file": "Optional destination for a standalone model listing snapshot from the admitted doctor. Requires --provider and --account-sha256; operator scope is unverified. Artifact publication is explicit, separate from provider writes, and never proves account access. Must differ from --response-file.",
15
+ "save-profile-intent": "Explicit frozen dd-flow/profile-creation-intent@1 JSON file containing before/after settings, profile and default consent. Setup binds it to request identity, saves under revision CAS and reconciles exact replay. Conflicts with --skip-agent-setup; an additional selected profile must match. This file is not provider authorization.",
16
+ "set-default": "Explicitly select the newly created profile as global default in the same atomic settings write. Omission preserves the existing default. Does not change frozen RUN settings.",
17
+ "remove": "Remove the positional operator alias binding, not its target profile; conflicts with --target.",
18
+ "clear": "Clear the operator global default without removing profiles or changing project routing and frozen RUN snapshots.",
19
+ "allow-processes": "Explicit permission to execute installed diagnostic code. Version/doctor probes are opt-in; static discovery never requires this flag.",
20
+ "allow-services": "Permit the selected adapter doctor's possible service process effects. Does not authorize model Turns, a flow, or reuse of an unrelated service.",
21
+ "allow-credentials": "Permit possible credential reads by the installed diagnostic; no credentials or raw adapter output enter this command's result.",
22
+ "allow-writes": "Permit possible diagnostic temporary/runtime writes by installed code; not permission to modify project packs or RUN settings.",
23
+ "native-executable": "Absolute native ZCode executable for the selected ZCode ACP doctor; no ambient ZCODE_BIN fallback. Invalid for other families.",
24
+ "timeout-ms": "Timeout in milliseconds for the selected operation. Harness diagnostics accept 1..60000: version defaults to 3000 and doctor to 30000. Other commands retain their own operation timeout policy; this option is not a productive RUN inactivity policy.",
25
+ "seed-file": "Optional reviewed dd-flow/model-catalog@1 JSON input; default is the bundled seed. Seed-only entries cannot establish account access or runtime qualification.",
26
+ "observation-file": "Explicit regular-file model listing snapshot; requires --harness, --provider and --account-sha256. Foreign scopes are ignored; malformed or secret-bearing fields refuse. No live listing is started.",
27
+ "account-sha256": "Opaque 64-character lowercase SHA-256 account binding, never an account name, token or credential path. Requires --harness and --provider; does not authenticate the account.",
28
+ "canon-source": "Explicit local signed release bundle or HTTPS envelope URL. Remote archives must use the same origin; trust comes only from --trust-file. Exclusive with --canon-version.",
29
+ "canon-version": "Exact canon release version in the selected channel of the operator release registry; exclusive with --canon-source. Omission selects the registry's explicit channel default.",
30
+ "release-registry": "Operator dd-flow/release-registry@1 JSON selector; default is DD_FLOW_RELEASE_REGISTRY or release-registry.json in DD_FLOW_HOME. Registry entries never enroll signing keys.",
31
+ "trust-file": "Explicit operator dd-flow/release-trust@1 file; release bytes cannot enroll their own signing key.",
32
+ "channel": "Selected release channel; preview and development must be requested explicitly.",
33
+ "skip-agent-setup": "Install without selecting or configuring an executor; conflicts with --profile.",
34
+ "non-interactive": "Never request interactive input; a missing executor selection fails unless agent setup is explicitly skipped.",
35
+ "project-root": "Stable repository identity; not the assigned feature workspace.",
36
+ "workspace-root": "Concrete assigned checkout used for this operation.",
37
+ "workspace-path": "Concrete assigned checkout; does not change project identity.",
38
+ "root": "Explicit root for the selected command; prevents implicit root discovery.",
39
+ "run": "Exact retained RUN identity; its frozen execution settings remain authoritative.",
40
+ "reason": "Operator explanation retained with the requested change.",
41
+ "request-id": "Stable request identity for reconciliation and idempotent retry.",
42
+ "request-key": "Stable exact-request replay identity; changed inputs or missing independent custody refuse rather than allocate again. The owning command defines scope and syntax.",
43
+ "expected-revision": "Required current revision; stale changes are rejected instead of overwriting concurrent edits.",
44
+ "profile": "Explicit configured profile identifier; credentials are not stored in profiles.",
45
+ "profile-file": "Complete validated executor profile; exclusive with --profile and --skip-agent-setup. Does not change operator defaults.",
46
+ "agent-profile": "Explicit configured executor profile; no automatic model selection.",
47
+ "force": "Explicit force request; does not bypass ownership, compatibility or authorization gates.",
48
+ "offline": "Explicit drained/offline operation; does not establish physical settlement by itself."
49
+ };
50
+ /** Option names alone are insufficient when different commands own different inputs. */
51
+ const memoryRepairOptions = {
52
+ run: "Active registered mb-init review RUN; retained correction graph and frozen execution own every repair operation.",
53
+ wave: "Exact causal correction wave 1 or 2; never falls back to another wave or permits a third wave.",
54
+ work: "Exact registered repair Work in the selected correction wave; foreign Work and generation custody refuse.",
55
+ "workspace-root": "Shared frozen RUN workspace, not the private repair copy; independent source and scope custody remain required.",
56
+ "work-session": "Exact independently started repair WorkSession; this command never creates or claims a provider Session."
57
+ };
58
+ const memoryInitOptions = {
59
+ "prepare-only": "Prepare or replay the frozen Memory RUN and project bootstrap without launching a controller or provider Session. This publishes project/runtime state; it is not a dry run. Use run drive launch with the returned RUN to select bounded observation/capture. Exclusive with --detach; replay never stops an existing controller.",
60
+ "profile-file": "Absolute regular JSON file with one complete validated operation-only executor profile. Exclusive with --profile; never saves settings or changes defaults. Omit on replay to reuse frozen bytes; supplied profile content must match the original selection.",
61
+ "non-interactive": "Never open the first-flow executor dialog, even on a terminal. Without an explicit profile/file or configured default, refuse before project effects; init cannot skip its executor."
62
+ };
63
+ const commandOptionDescriptions = {
64
+ "flow mb-init": memoryInitOptions,
65
+ init: memoryInitOptions,
66
+ "runtime storage admit": { operation: "Operation-specific writable-connection admission: memory-init only. Requires explicit canonical DD_FLOW_HOME and an existing compatible resource registry. Never initializes, migrates, repairs or starts agents." },
67
+ "runtime flow admit": { operation: "Memory-init handler admission in the executing engine. Reads bounded UTF-8 JSON stdin with source and source_sha256; optional startup_input_schema additionally requires support by this engine's startup reader. Validates the exact six-stage descriptor using actual registered handlers. Does not establish release trust, storage/provider readiness or semantic completion, and never creates Home, RUN or agents." },
68
+ "profiles create": { file: "Regular UTF-8 JSON file containing one complete validated agent profile. The ID must be unused. Credentials and unknown fields are refused; creation uses --expected-revision and never starts a model Turn." },
69
+ "profiles edit": { file: "Regular UTF-8 JSON file containing the complete replacement agent profile, not a patch. Its ID must already exist. Revision conflicts refuse the edit; retained RUN snapshots are unchanged." },
70
+ "profiles alias": {
71
+ target: "Existing canonical profile ID for the positional alias. Aliases cannot chain or collide with profile IDs. Supply exactly one of --target or --remove, plus --expected-revision.",
72
+ remove: "Remove the positional alias, not its target profile. Exclusive with --target. The revision-checked change does not rewrite retained RUN settings."
73
+ },
74
+ "profiles set-default": { clear: "Clear only the operator global default. Exclusive with a positional profile ID or alias; existing profiles, project routing and frozen RUN settings remain unchanged." },
75
+ "work add-batch": {
76
+ file: "Validated Work batch JSON file declaring children of --parent, including their task and dependency inputs. Adding logical Work does not launch physical Sessions.",
77
+ stage: "Explicit owner stage. With --request-key it must be the active running coordinator stage; attempt and cycle are resolved from retained RUN authority.",
78
+ "request-key": "Stable registration ID (1..96 letters, digits, dots, underscores or hyphens, starting with a letter or digit). Requires --stage. Identical replay returns the retained Work IDs; changed input or missing custody refuses allocation. Without this option the historical non-replayable batch behavior is retained."
79
+ },
80
+ "schema validate": { file: "JSON document to validate against --schema in the selected schema directory. Validation does not execute a flow or accept semantic completion." },
81
+ "migration verify": { file: "Existing dd-flow/mb-upgrade-migration-report@1 JSON report to verify against migration evidence; verification does not apply a storage migration." },
82
+ "migration apply": { file: "Explicit migration report JSON file used for admission to the requested apply operation; backup and ownership gates remain mandatory." },
83
+ "prompt render": { profile: "Prompt profile name required by the assigned Work execution context; not an operator executor profile ID or a Codex home profile." },
84
+ "runtime process register": { harness: "Harness family associated with the registered process/budget; registration is not a discovery or doctor probe.", "state-dir": "Adapter runtime state directory retained with the physical process for later ownership/admission checks." },
85
+ "runtime process admission": { "state-dir": "Exact adapter runtime state directory matching the confirmed process record; mismatched ownership refuses provider admission." },
86
+ "runtime process release-turn": { "observation-file": "Provider turn release observation file for the selected daemon/operation budget. This is not a model inventory snapshot or account listing." },
87
+ "runtime scope control": { mode: "Recoverable scope control intent: pause or stop. Drain/settlement remains pending until owned physical evidence is confirmed." },
88
+ "merge request route": { mode: "Route this MERGE request through same_session or server; selected execution policy and workspace admission still apply." },
89
+ "worktree close": { mode: "keep retains the feature checkout; remove requests its guarded removal. Dirty or foreign worktrees must not be silently discarded." },
90
+ "codex home remove": { mode: "keep-shared preserves shared state; remove-owned removes only the verified project-owned home entries.", profile: "Isolated project Codex home profile name, not an executor agent-profile ID." },
91
+ "codex home plan": { profile: "Isolated project Codex home profile name, not an executor agent-profile ID." },
92
+ "codex home init": { profile: "Isolated project Codex home profile name, not an executor agent-profile ID." },
93
+ "codex home status": { profile: "Isolated project Codex home profile name, not an executor agent-profile ID." },
94
+ "codex home print-env": { profile: "Isolated project Codex home profile name, not an executor agent-profile ID." },
95
+ "codex hooks print": { target: "Hook installation target: isolated (default) or default Codex home. Printing does not install hooks.", profile: "Project Codex home profile used to locate isolated hooks; not an executor profile." },
96
+ "codex hooks status": { target: "Hook installation target: isolated (default) or default Codex home. Status does not install hooks.", profile: "Project Codex home profile used to locate isolated hooks; not an executor profile." },
97
+ "codex hooks install": { target: "Hook installation target: isolated (default) or default Codex home; mutation also requires explicit confirmation.", profile: "Project Codex home profile used to locate isolated hooks; not an executor profile." },
98
+ "codex hooks remove": { target: "Hook installation target: isolated (default) or default Codex home; removal also requires explicit confirmation.", profile: "Project Codex home profile used to locate isolated hooks; not an executor profile." },
99
+ "protocol sync-from-run": { target: "Protocol state target derived from the selected RUN; auto uses the command's supported state mapping." },
100
+ "run reconcile": {
101
+ apply: "Persist the observed RUN health under its current ownership and revision fences. Without this switch, report only; never launch, resume or stop a provider.",
102
+ "no-progress-ms": "Override the health-assessment progress-age threshold in milliseconds; integer at least 1000. Defaults are 120000 for starting, 300000 for capturing and 1800000 otherwise. This is not a productive command timeout or permission to stop a live owner."
103
+ },
104
+ "run fork": { from: "Existing retained snapshot path to fork into a new RUN with the explicitly selected engine; not a control request identity." },
105
+ "run control resume": { from: "Exact retained pause/stop control ID whose captured state authorizes this resume request; not a snapshot path." },
106
+ "stage block": { kind: "Blocker category: engine, harness or environment; code and summary identify the actionable cause." },
107
+ "migration impact": { mode: "Optional full_migration request forces the strict full-migration assessment; otherwise impact evidence determines patch, targeted_minor or full_migration." },
108
+ "memory permissions preflight": { mode: "Permission contour to check: read, write, repair or report_only; write checks may create temporary permission probes.", flow: "Workflow permission contour: mb-init, mb-upgrade, mb-audit, mb-fix, mb-upgrade-review or custom. Not a filesystem path." },
109
+ "memory compose register": { "run": "Active registered mb-init RUN whose accepted discovery and immutable execution bind the composition graph.", "request-key": "Stable composition registration identity; exact replay retains the original Work graph.", "result-file": "Bounded proposed composition JSON. Bytes are prepared before registration; agent fields do not grant Work or write authority." },
110
+ "memory verify checks": { "run": "Active registered mb-init RUN. Execute only its independently selected declared verification checks." },
111
+ "memory review register": { "run": "Active registered mb-init RUN with accepted verification. Register initial independent reviewers; this does not launch providers." },
112
+ "memory review collect": { "run": "Active registered mb-init RUN. Collect genuine registered initial-wave results without accepting the Stage or granting correction authority." },
113
+ "memory finish evidence": { "run": "Active registered mb-init finish RUN. Publish independently prepared coverage, integration and readiness evidence; publication does not complete Stage or RUN." },
114
+ "memory finish integrate": { "run": "Active mb-init finish RUN. Commit only accepted Memory Bank and owned lint files under retained Git policy, then integrate the admitted workspace locally. Preserve unrelated staged/dirty files; never push. Lost-response replay observes the original effects without another commit." },
115
+ "memory corrections register": { run: "Active registered mb-init review RUN. Register only the correction plan bound to the independently retained preceding review.", wave: "Correction wave 1 follows initial review; wave 2 requires settled first selective review. A third wave is unsupported.", "result-file": "Bounded correction-plan JSON prepared before graph registration; exact retained replay cannot substitute another plan." },
116
+ "memory corrections checks": { run: "Active registered mb-init review RUN with a genuinely settled correction view.", wave: "Run only the independently selected finite check profile for correction wave 1 or 2; this does not accept semantic quality." },
117
+ "memory review selective-register": { run: "Active registered mb-init review RUN. Allocate selective reviewers only after their wave's committed checks.", wave: "Select correction wave 1 or 2. Unaffected accepted units remain retained; registration does not launch providers." },
118
+ "memory review selective-collect": { run: "Active registered mb-init review RUN. Return genuine selective reviewer references, not Stage or RUN acceptance.", wave: "Select independently registered review of correction wave 1 or 2; missing wave custody never falls back to initial review." },
119
+ "memory repair baseline": { ...memoryRepairOptions, work: "Register the immutable prelaunch baseline for this repair Work; dependent/peer changes require explicit current-view registration first. Does not launch providers." },
120
+ "memory repair copy-reserve": { ...memoryRepairOptions, work: "Reserve the owned private copy for this repair Work after its committed baseline; reservation does not create the copy or launch providers." },
121
+ "memory repair copy-materialize": { ...memoryRepairOptions, work: "Materialize the reserved private copy for this repair Work with retained build/ready receipts; no provider launch or shared document publication." },
122
+ "memory repair copy-dispatch": { ...memoryRepairOptions, work: "Prepare the frozen profile and verified ready-copy root for this repair Work. Read-only packet output does not launch a provider, claim a Session or replace fresh launcher custody checks." },
123
+ "memory repair current-view": { ...memoryRepairOptions, work: "Retain the explained settled-peer input view for this repair Work; does not replace an existing immutable baseline or grant launch authority." },
124
+ "memory repair publication-source": { ...memoryRepairOptions, wave: "Wave 1 only: retain independently explained shared publication source before reserving output. Wave 2 uses its separate retained launch owner." },
125
+ "memory repair publication-reserve": { ...memoryRepairOptions, "result-file": "Bounded exact private repair result bytes prepared before dispatch. Reserve the independently validated delta only; wave 1 requires a previously registered publication-source." },
126
+ "memory repair publication-apply": { ...memoryRepairOptions, work: "Apply or reconcile one retained publication action for this repair Work; repeat until physical publication completes. Unknown effect never authorizes blind retry." },
127
+ "memory repair publication-finish": { ...memoryRepairOptions, work: "Settle this repair Work only after independently proven physical publication completion; does not accept semantic review or finish Stage/RUN." }
128
+ };
129
+ export const globalOptionDocumentation = [
130
+ { name: "help", description: "Show help before command preparation or resource access; -h is equivalent.", kind: "switch", required: false, repeatable: false, choices: [], physical_path: false },
131
+ { name: "option", description: "Help-only selector for one option; accepts name or --name.", kind: "value", required: false, repeatable: false, choices: [], physical_path: false },
132
+ { name: "json", description: "Emit structured JSON rather than human text.", kind: "switch", required: false, repeatable: false, choices: [], physical_path: false },
133
+ { name: "progress-jsonl", description: "Emit machine-readable progress events during command execution.", kind: "switch", required: false, repeatable: false, choices: [], physical_path: false },
134
+ { name: "response-file", description: "Execution-only response destination; help never opens or writes it.", kind: "value", required: false, repeatable: false, choices: [], physical_path: true }
135
+ ];
136
+ export function optionsForCommand(input, command) {
137
+ return [...new Set([...input.values, ...input.switches])].map(name => ({
138
+ name,
139
+ description: optionDescription(name, command),
140
+ kind: input.switches.includes(name) ? "switch" : "value",
141
+ required: input.required.includes(name), repeatable: input.repeatable.includes(name),
142
+ choices: input.enums[name] ?? [], physical_path: physicalPathOptions.has(name) && name !== "flow" && name !== "stage"
143
+ }));
144
+ }
145
+ function optionDescription(name, command) {
146
+ const description = (command ? commandOptionDescriptions[command]?.[name] : undefined) ?? optionDescriptions[name] ?? runtimeOptionDescriptions[name];
147
+ if (!description)
148
+ throw new Error(`Missing CLI option documentation: ${command ?? "inventory"} --${name}`);
149
+ return description;
150
+ }
151
+ /** Shared help/completion option set for a route, family or root catalog. */
152
+ export function optionsForCommandTree(command) {
153
+ const options = new Map(globalOptionDocumentation.map(option => [option.name, option]));
154
+ for (const [key, input] of Object.entries(commandInputs)) {
155
+ if (!command || key === command || key.startsWith(`${command} `)) {
156
+ for (const option of optionsForCommand(input, key))
157
+ options.set(option.name, option);
158
+ }
159
+ }
160
+ return [...options.values()].sort((left, right) => left.name.localeCompare(right.name, "en"));
161
+ }
162
+ /** One exact native routing classification shared by router and compatibility admission. */
163
+ export function routerNativeRoute(key) {
164
+ return key === "version" || key.startsWith("engine ") || key === "schema validate"
165
+ || key === "flow list" || key === "flow show" || key === "flow mb-init" || key === "init"
166
+ || key === "run reconcile" || key === "runtime storage admit"
167
+ || key === "runtime flow admit"
168
+ || key.startsWith("profiles ") || key.startsWith("models ") || key.startsWith("harnesses ") || key.startsWith("completion ") || key === "setup" || key.startsWith("setup ")
169
+ || key === "storage migrate-writer" || key === "codex hook handle"
170
+ || key === "zcode hook handle" || key === "zcode invocation prepare"
171
+ || /^(zcode|grok|droid|opencode|agy) (event handle|usage ingest)$/.test(key);
172
+ }
173
+ export function commandKeyForPositions(positions) {
174
+ return Object.keys(commandInputs).filter(key => key.split(" ").every((part, index) => positions[index] === part))
175
+ .sort((a, b) => b.split(" ").length - a.split(" ").length)[0];
176
+ }
177
+ /** Best matching help topic for rejected argv; never validates or executes it.
178
+ * Option values and literal passthrough cannot impersonate a command path.
179
+ */
180
+ export function commandHelpTopic(args, fallback) {
181
+ const switches = new Set([...globalOptionDocumentation.filter(option => option.kind === "switch").map(option => option.name),
182
+ ...Object.values(commandInputs).flatMap(input => input.switches)]);
183
+ const positions = [];
184
+ for (let index = 0; index < args.length; index++) {
185
+ const arg = args[index];
186
+ if (arg === "--")
187
+ break;
188
+ if (arg.startsWith("--")) {
189
+ const name = arg.slice(2).split("=", 1)[0];
190
+ if (!arg.includes("=") && !switches.has(name) && args[index + 1] && !args[index + 1].startsWith("-"))
191
+ index++;
192
+ }
193
+ else if (!arg.startsWith("-"))
194
+ positions.push(arg);
195
+ }
196
+ return commandKeyForPositions(positions) ?? fallback;
197
+ }