@deksden-com/dd-flow-cli 0.1.0

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 (35) hide show
  1. package/README.md +274 -0
  2. package/dist/cli/help.js +308 -0
  3. package/dist/cli/run-cli.js +945 -0
  4. package/dist/cli.js +4 -0
  5. package/dist/domain/contracts.js +57 -0
  6. package/dist/domain/entity-ids.js +47 -0
  7. package/dist/domain/flow-contract.js +233 -0
  8. package/dist/domain/validation.js +91 -0
  9. package/dist/protocol/local-files.js +141 -0
  10. package/dist/runtime/context.js +11 -0
  11. package/dist/schemas/code-stage-report.schema.json +181 -0
  12. package/dist/schemas/flow-run-index.schema.json +129 -0
  13. package/dist/schemas/mb-upgrade-review-data.schema.json +813 -0
  14. package/dist/schemas/memorybank-permissions-preflight.schema.json +154 -0
  15. package/dist/schemas/merge-stage-report.schema.json +135 -0
  16. package/dist/services/audit.js +19 -0
  17. package/dist/services/cleanup.js +310 -0
  18. package/dist/services/config.js +143 -0
  19. package/dist/services/dashboard.js +436 -0
  20. package/dist/services/hooks.js +929 -0
  21. package/dist/services/lanes.js +327 -0
  22. package/dist/services/memory-permissions.js +344 -0
  23. package/dist/services/merge-queue.js +333 -0
  24. package/dist/services/plans.js +149 -0
  25. package/dist/services/projects.js +286 -0
  26. package/dist/services/protocols.js +606 -0
  27. package/dist/services/runs.js +359 -0
  28. package/dist/services/schema-validation.js +185 -0
  29. package/dist/services/sessions.js +365 -0
  30. package/dist/services/worktrees.js +204 -0
  31. package/dist/shared/errors.js +14 -0
  32. package/dist/shared/json.js +17 -0
  33. package/dist/storage/database.js +325 -0
  34. package/dist/storage/paths.js +56 -0
  35. package/package.json +44 -0
package/README.md ADDED
@@ -0,0 +1,274 @@
1
+ # dd-flow-cli
2
+
3
+ `dd-flow-cli` is the mechanical control layer for `dd-flow` workflows.
4
+
5
+ It does not replace Memory Bank prompts and does not make product, design, merge, or verification judgments. Prompts own intent, route selection, planning depth, evidence meaning, and semantic readiness. The CLI owns explicit local state: projects, protocols, Codex session bindings, transitions, worktree records, lanes, locks, merge queue jobs, hook records, and audit events.
6
+
7
+ ## Runtime Model
8
+
9
+ Root local database:
10
+
11
+ ```text
12
+ ~/.dd-flow/db.sqlite
13
+ ```
14
+
15
+ New projects use typed full ids and aliases:
16
+
17
+ ```text
18
+ PRJ-001-dd-flow-playground
19
+ PRJ-001
20
+ ```
21
+
22
+ Project-scoped runtime protocol state:
23
+
24
+ ```text
25
+ ~/.dd-flow/projects/<PRJ-ID-slug>/runtime/protocols/<protocol-id>/state.json
26
+ ~/.dd-flow/projects/<PRJ-ID-slug>/runtime/protocols/<protocol-id>/plan.json
27
+ ```
28
+
29
+ Project Memory Bank files under `.memory-bank/protocol/PRT-.../` are durable documentation and evidence snapshots. Runtime commands such as status, transition, merge completion, cancel, and cleanup do not require a feature-worktree-local `state.json` to exist.
30
+
31
+ Project flow contract:
32
+
33
+ ```text
34
+ .memory-bank/dd-flow/flow-contract.json
35
+ .memory-bank/dd-flow/flow-contract.yaml
36
+ ```
37
+
38
+ The flow contract defines mechanical protocol stages, allowed transitions, the `ready-for-merge` gate, merge completion target stage, and the default first `next_action`. If no file exists, the built-in canonical contract is used. JSON takes precedence over YAML when both are present. The default canonical stages are `prime`, `readiness`, and `integration`; legacy `g0`, `m1`, and `m2` inputs are normalized as aliases for local migration safety.
39
+
40
+ `project_root` is the stable repository identity in dd-flow state. `workspace_path` is the concrete checkout where an agent is about to work. They can be the same path, or different paths when a feature worktree, merge checkout, direct integration checkout, or temporary fixture workspace is used.
41
+
42
+ ## Basic Commands
43
+
44
+ Register a project:
45
+
46
+ ```bash
47
+ dd-flow project register --root "$PWD" --json
48
+ dd-flow project status --root "$PWD" --json
49
+ dd-flow project resolve PRJ-001 --json
50
+ dd-flow project archive PRJ-001 --reason "old missing worktree root" --json
51
+ dd-flow project archive --root /abs/old/deleted/root --reason "old missing worktree root" --json
52
+ dd-flow project migrate-ids --root "$PWD" --json
53
+ dd-flow project migrate-ids --root "$PWD" --apply --json
54
+ ```
55
+
56
+ Use `project archive` for old registered roots that no longer exist, especially historical feature-worktree roots from earlier runtime layouts. Archiving does not delete protocols, queue rows, or audit history; it removes the project from active global dashboards and keeps it in the archived section for traceability. Re-registering the same existing root reactivates it.
57
+
58
+ `migrate-ids` is explicit on purpose. It reports the old hash-based local id and the planned typed id in dry-run mode, then updates project references only with `--apply`.
59
+
60
+ Register and inspect a protocol:
61
+
62
+ ```bash
63
+ dd-flow protocol register HANDSHAKE-001 --project-root "$PWD" --json
64
+ dd-flow protocol status PRT-HANDSHAKE-001 --json
65
+ ```
66
+
67
+ Attach and update a plan:
68
+
69
+ ```bash
70
+ dd-flow plan set PRT-HANDSHAKE-001 --file plan.json --json
71
+ dd-flow plan item start PRT-HANDSHAKE-001 P1 --json
72
+ dd-flow plan item done PRT-HANDSHAKE-001 P1 --summary "Implemented" --evidence "pnpm test" --json
73
+ ```
74
+
75
+ Human help is available for the operator-facing command groups:
76
+
77
+ ```bash
78
+ dd-flow --help
79
+ dd-flow lane --help
80
+ dd-flow lane workspace --help
81
+ dd-flow lane lock --help
82
+ dd-flow merge-queue --help
83
+ dd-flow merge-queue wait-next --help
84
+ dd-flow cleanup --help
85
+ dd-flow codex home --help
86
+ dd-flow worktree --help
87
+ ```
88
+
89
+ ## Lanes And Locks
90
+
91
+ A lane is a named shared operational workspace inside a project. A lane lock is a time-bound ownership lease on that workspace. The CLI enforces one active non-expired lock per project/lane; prompts decide whether a task should use a feature worktree, `direct-main`, or `merge`.
92
+
93
+ Register and check a lane workspace:
94
+
95
+ ```bash
96
+ dd-flow lane workspace set --project-root "$PROJECT_ROOT" --lane merge --path "$WORKSPACE" --branch main --json
97
+ dd-flow lane workspace check --project-root "$PROJECT_ROOT" --lane merge --path "$PWD" --json
98
+ ```
99
+
100
+ Acquire, heartbeat, and release a lane lock:
101
+
102
+ ```bash
103
+ dd-flow lane lock acquire --project-root "$PROJECT_ROOT" --lane merge --worker-id "$WORKER_ID" --path "$WORKSPACE" --ttl 300 --reason "merge worker" --json
104
+ dd-flow lane lock heartbeat --project-root "$PROJECT_ROOT" --lane merge --worker-id "$WORKER_ID" --path "$WORKSPACE" --lease-token "$TOKEN" --json
105
+ dd-flow lane lock release --project-root "$PROJECT_ROOT" --lane merge --worker-id "$WORKER_ID" --path "$WORKSPACE" --lease-token "$TOKEN" --reason done --json
106
+ ```
107
+
108
+ Inspect lane state:
109
+
110
+ ```bash
111
+ dd-flow lane status --project-root "$PROJECT_ROOT" --json
112
+ dd-flow lane lock status --project-root "$PROJECT_ROOT" --lane merge --json
113
+ ```
114
+
115
+ Branch checks are factual diagnostics. Lock mutation and merge queue claiming validate the registered workspace path mechanically. A mismatch can help a prompt or operator notice the wrong checkout, but the CLI does not decide whether the route is semantically allowed.
116
+
117
+ ## Direct Main Recipe
118
+
119
+ Use `direct-main` only after the prompt or operator has chosen direct integration work for a small, low-risk task.
120
+
121
+ ```bash
122
+ dd-flow lane workspace set --project-root "$PROJECT_ROOT" --lane direct-main --path "$PROJECT_ROOT" --branch main --json
123
+ dd-flow lane workspace check --project-root "$PROJECT_ROOT" --lane direct-main --path "$PWD" --json
124
+ dd-flow lane lock acquire --project-root "$PROJECT_ROOT" --lane direct-main --worker-id "$PROTOCOL_ID" --path "$PWD" --ttl 300 --reason "direct integration work" --json
125
+ ```
126
+
127
+ When the task stops using the shared checkout:
128
+
129
+ ```bash
130
+ dd-flow lane lock release --project-root "$PROJECT_ROOT" --lane direct-main --worker-id "$PROTOCOL_ID" --path "$PWD" --lease-token "$TOKEN" --reason done --json
131
+ ```
132
+
133
+ ## Merge Queue Recipe
134
+
135
+ Prompts enqueue protocols only after explicit readiness signals exist:
136
+
137
+ ```bash
138
+ dd-flow protocol ready-for-merge PRT-... --json
139
+ dd-flow merge-queue status --project-root "$PROJECT_ROOT" --json
140
+ ```
141
+
142
+ A merge worker must own the `merge` lane before claiming jobs:
143
+
144
+ ```bash
145
+ dd-flow lane workspace set --project-root "$PROJECT_ROOT" --lane merge --path "$MERGE_WORKSPACE" --branch main --json
146
+ dd-flow lane lock acquire --project-root "$PROJECT_ROOT" --lane merge --worker-id "$WORKER_ID" --path "$MERGE_WORKSPACE" --ttl 300 --reason "merge worker" --json
147
+ dd-flow merge-queue next --project-root "$PROJECT_ROOT" --worker-id "$WORKER_ID" --path "$MERGE_WORKSPACE" --json
148
+ ```
149
+
150
+ For supervisor-style waiting outside model tokens:
151
+
152
+ ```bash
153
+ dd-flow merge-queue wait-next --project-root "$PROJECT_ROOT" --worker-id "$WORKER_ID" --path "$MERGE_WORKSPACE" --timeout 1200 --poll-interval 10 --acquire-lock true --json
154
+ ```
155
+
156
+ With `--acquire-lock true`, `wait-next` heartbeats the merge lane lock while it waits and releases a lock it acquired itself when the wait times out. Live merge workers should prefer long waits, for example 1200 seconds / 20 minutes, so the agent sleeps inside the CLI process instead of spending model tokens on frequent polling.
157
+
158
+ Complete or fail the claimed job:
159
+
160
+ ```bash
161
+ dd-flow merge-queue complete PRT-... --worker-id "$WORKER_ID" --path "$MERGE_WORKSPACE" --summary "merged locally" --json
162
+ dd-flow merge-queue fail PRT-... --worker-id "$WORKER_ID" --path "$MERGE_WORKSPACE" --reason "conflict requires owner" --requeue true --json
163
+ ```
164
+
165
+ Successful `merge-queue complete` is terminal for the protocol runtime: it writes `stage: closed`, `status: closed`, and `next_action: none`. Post-complete cleanup can still update the queue reason with `merge-queue note`, but dashboards must no longer show the protocol as active work.
166
+
167
+ Cancel stale or intentionally abandoned queue work explicitly:
168
+
169
+ ```bash
170
+ dd-flow merge-queue cancel PRT-... --reason "abandoned rerun" --json
171
+ dd-flow merge-queue cancel PRT-... --worker-id "$WORKER_ID" --path "$MERGE_WORKSPACE" --reason "owner cancelled claimed job" --json
172
+ ```
173
+
174
+ Flow sessions are registered explicitly with `dd-flow session register`; merge queue commands use `--worker-id` only. Codex prompts should prefer a JSON payload file:
175
+
176
+ ```bash
177
+ dd-flow session register --payload-file ".tasks/dd-flow/session-payload.json" --json
178
+ ```
179
+
180
+ `--payload-base64` remains supported for callers that can pass a literal value, but it must not use shell variables in Codex-hooked sessions because `PreToolUse` receives the raw command before shell expansion.
181
+
182
+ For feature worktrees, keep the stable project identity separate from the checkout where the agent works:
183
+
184
+ ```bash
185
+ dd-flow protocol register PRT-... --project-root "$PROJECT_ROOT" --workspace-path "$FEATURE_WORKTREE" --json
186
+ ```
187
+
188
+ Codex hooks enforce merge-role boundaries mechanically. A normal planning or implementation session may mark a protocol ready for merge, but it may not claim merge queue jobs, mutate the merge lane lock, complete/fail a merge job, run `git merge`, or re-register itself as a merge worker/job. Hook guards also block removing the current Codex session worktree, because deleting the session `cwd` breaks later tool and hook calls.
189
+
190
+ Cancel a full protocol runtime record by explicit operator intent:
191
+
192
+ ```bash
193
+ dd-flow protocol cancel PRT-... --reason "replaced by fresh run" --close-sessions true --cancel-queue true --release-locks true --worktree keep --json
194
+ ```
195
+
196
+ For a stale disposable feature checkout, use `--worktree remove`. The command removes the git worktree recorded either in `worktree_records` or in stable runtime `state.workspace`; with `--force`, it also force-deletes the local feature branch when present. It refuses dirty worktrees without `--force` and refuses to remove the stable project root or the current process working directory.
197
+
198
+ ## Cleanup
199
+
200
+ Use cleanup when local runtime state is stale after a crash, abandoned rerun, or removed feature worktree. `cleanup scan` is read-only. `cleanup apply` requires an explicit plan file and reason, reports requested/applied/changed/skipped action results, and dirty/destructive worktree actions require `--force --reason`. Worktree record cleanup marks a checkout `removed` only when the path is already absent; if the checkout still exists, the record is closed as `kept` rather than silently deleting files.
201
+
202
+ ```bash
203
+ dd-flow cleanup scan --project-root "$PROJECT_ROOT" --json > .tasks/dd-flow-cleanup-scan.json
204
+ jq '.plan' .tasks/dd-flow-cleanup-scan.json > .tasks/dd-flow-cleanup-plan.json
205
+ dd-flow cleanup apply --project-root "$PROJECT_ROOT" --plan-file .tasks/dd-flow-cleanup-plan.json --reason "clear stale local rerun state" --json
206
+ ```
207
+
208
+ The CLI remains mechanical: it cancels or repairs explicit runtime rows, but it does not decide whether a protocol, experiment, merge, or verification was semantically good.
209
+
210
+ ## Dashboards
211
+
212
+ Dashboard markdown is rendered state, not source of truth. Successful state-changing commands refresh project and global dashboards automatically when `dashboard.auto_refresh` is enabled. `dashboard refresh` also rewrites both the project dashboard and the global dashboard when they are enabled, so an already-open cmux markdown viewer receives live updates.
213
+
214
+ The dashboard is intentionally compact: it shows the last update time, active protocols/sessions, merge queue summary, active locks, recent outcomes, and missing project roots without dumping full hook payloads into the main view.
215
+
216
+ Defaults:
217
+
218
+ ```text
219
+ project dashboard: .tasks/dd-flow-dashboard.md
220
+ global dashboard: ~/.dd-flow/dashboard.md
221
+ ```
222
+
223
+ Useful commands:
224
+
225
+ ```bash
226
+ dd-flow dashboard render --project-root "$PROJECT_ROOT" --json
227
+ dd-flow dashboard render-global --json
228
+ dd-flow dashboard refresh --project-root "$PROJECT_ROOT" --open false --json
229
+ dd-flow dashboard open --project-root "$PROJECT_ROOT" --viewer cmux --json
230
+ ```
231
+
232
+ Config keys:
233
+
234
+ ```bash
235
+ dd-flow project config set --project-root "$PROJECT_ROOT" --key dashboard.auto_refresh --value true --json
236
+ dd-flow project config set --project-root "$PROJECT_ROOT" --key dashboard.project --value true --json
237
+ dd-flow project config set --project-root "$PROJECT_ROOT" --key dashboard.global --value true --json
238
+ dd-flow project config set --project-root "$PROJECT_ROOT" --key integrations.cmux.mode --value auto --json
239
+ ```
240
+
241
+ cmux is a viewer only. Ordinary auto-refresh writes markdown and does not open cmux.
242
+
243
+ ## Worktrunk And Codex
244
+
245
+ `dd-flow-cli` records Worktrunk-backed worktree state but does not replace Worktrunk as the owner of worktree lifecycle.
246
+
247
+ ```bash
248
+ dd-flow worktree plan --protocol-id PRT-... --json
249
+ dd-flow worktree create --protocol-id PRT-... --branch feature/name --base main --path "$DD_FLOW_HOME/projects/PRJ-001-dd-flow-playground/checkouts/worktrees/PRT-.../repo" --json
250
+ dd-flow worktree status --protocol-id PRT-... --json
251
+ ```
252
+
253
+ `worktree plan` suggests project-scoped service checkout paths under `DD_FLOW_HOME/projects/<PRJ-ID-slug>/checkouts/`; it no longer points new work at project-local `.tasks/worktrees`.
254
+
255
+ Codex integration is explicit and auditable. Managed Codex homes and hooks are local operational scaffolding; deterministic tests must not mutate the user's default `~/.codex` without an explicit target and confirmation.
256
+
257
+ ```bash
258
+ dd-flow codex home plan --project-root "$PROJECT_ROOT" --json
259
+ dd-flow codex hooks status --project-root "$PROJECT_ROOT" --target isolated --json
260
+ dd-flow codex hook handle --event Stop --project-root "$PROJECT_ROOT" --json
261
+ ```
262
+
263
+ ## Verification
264
+
265
+ Local verification for this repository:
266
+
267
+ ```bash
268
+ pnpm test
269
+ pnpm typecheck
270
+ pnpm lint
271
+ pnpm build
272
+ ```
273
+
274
+ Manual smoke checks should use a temporary `DD_FLOW_HOME` when they do not intentionally inspect the operator's real local state.
@@ -0,0 +1,308 @@
1
+ const helpPages = new Map([
2
+ [
3
+ "",
4
+ `dd-flow - mechanical control layer for dd-flow workflows
5
+
6
+ Usage:
7
+ dd-flow <command> [options]
8
+ dd-flow <command> [options] --json
9
+ dd-flow <command> --help
10
+
11
+ Core commands:
12
+ project register/status Register a project and inspect runtime state.
13
+ project resolve/archive Resolve typed ids and archive stale project roots.
14
+ project migrate-ids Migrate old project ids.
15
+ protocol register/status Register and inspect protocol state.
16
+ cleanup scan/apply Detect and repair stale local runtime state.
17
+ run start/status/list Track concrete flow executions and stage artifacts.
18
+ plan set/status/item Attach and update protocol plans.
19
+ lane workspace/lock/status Manage shared workspace lanes and leases.
20
+ merge-queue status/next Claim, wait for, complete, or fail merge jobs.
21
+ session register/status/stop Register flow sessions and stop workers.
22
+ dashboard render/open/refresh Render markdown project/global dashboards.
23
+ schema validate Validate canonical dd-flow JSON data contracts.
24
+ memory permissions preflight Check Memory Bank write/read permissions.
25
+ integration cmux status Inspect optional cmux integration.
26
+ codex home/hooks/hook Manage Codex homes, hooks, and hook events.
27
+ worktree plan/create/status Record Worktrunk-backed feature worktrees.
28
+
29
+ Examples:
30
+ dd-flow project register --root "$PWD"
31
+ dd-flow project status --root "$PWD" --json
32
+ dd-flow project resolve PRJ-001 --json
33
+ dd-flow project archive PRJ-001 --reason "old missing worktree root" --json
34
+ dd-flow project migrate-ids --root "$PWD" --apply --json
35
+ dd-flow run start --project-root "$PWD" --flow-kind coding --subject-type protocol --subject-id PRT-001-demo --slug demo --json
36
+ dd-flow lane workspace set --project-root "$PWD" --lane merge --path "$PWD" --branch main --json
37
+ dd-flow lane lock acquire --project-root "$PWD" --lane merge --worker-id worker-1 --path "$PWD" --ttl 300 --reason "merge worker" --json
38
+
39
+ Default output is human-readable. Use --json for hooks, prompts, scripts and other agent automation; JSON mode never mixes human progress text into stdout.
40
+
41
+ project_root is the stable repository identity. workspace_path is the concrete checkout where an agent is about to work.`
42
+ ],
43
+ [
44
+ "run",
45
+ `dd-flow run - track concrete flow executions
46
+
47
+ Usage:
48
+ dd-flow run start --project-root <root> [--workspace-root <checkout>] --flow-kind <kind> --subject-type <type> --subject-id <id> --slug <slug> [--next-action <text>] --json
49
+ dd-flow run status <RUN-ID|RUN-NNN> --project-root <root> --json
50
+ dd-flow run list --project-root <root> --json
51
+ dd-flow run attach-stage <RUN-ID|RUN-NNN> --project-root <root> --stage <name> --dir <NN-stage-slug> --status <status> [--data-schema-id <id>] --json
52
+ dd-flow run complete-stage <RUN-ID|RUN-NNN> --project-root <root> --stage <name> --status <status> [--stage-report <path>] [--data <path>] [--data-schema-id <id>] [--report <path>] [--alias <path>] --json
53
+ dd-flow run complete <RUN-ID|RUN-NNN> --project-root <root> --status done|blocked|cancelled|failed [--verdict <text>] [--next-action <text>] --json
54
+
55
+ RUN-* is the execution envelope for one concrete flow launch. Semantic truth remains in protocol, experiment, DEF, scenario, evidence, and Memory Bank documents. Runtime state is stored under DD_FLOW_HOME/projects/<PRJ-ID-slug>/runtime/runs/<RUN-ID-slug>/, while human-facing artifacts are indexed through <workspace>/.tasks/dd-flow-runs/<RUN-ID-slug>/run-index.json.
56
+
57
+ Examples:
58
+ dd-flow run start --project-root "$PWD" --flow-kind coding --subject-type protocol --subject-id PRT-001-demo --slug demo --json
59
+ dd-flow run attach-stage RUN-001 --project-root "$PWD" --stage plan --dir 01-plan --status running --json
60
+ dd-flow run complete-stage RUN-001 --project-root "$PWD" --stage plan --status done --data 01-plan/stage-report.json --stage-report 01-plan/stage-report.html --report 01-plan/report.md --json`
61
+ ],
62
+ [
63
+ "protocol",
64
+ `dd-flow protocol - register and inspect protocol state
65
+
66
+ Usage:
67
+ dd-flow protocol register <handshake-id> --project-root <root> [--workspace-path <checkout>] --json
68
+ dd-flow protocol status <protocol-id> --json
69
+ dd-flow protocol ready-for-merge <protocol-id> --json
70
+ dd-flow protocol cancel <protocol-id> --reason <text> [--close-sessions true|false] [--cancel-queue true|false] [--release-locks true|false] [--worktree keep|remove] [--force] --json
71
+
72
+ The project_root is the stable project identity used for queues, sessions, lanes, and dashboards. Runtime state is stored under DD_FLOW_HOME/projects/<PRJ-ID-slug>/runtime so feature worktree removal does not break status, cancel, or merge finalization. The optional workspace_path records the concrete checkout where the agent works. With --worktree remove, cancel removes the disposable git worktree recorded in runtime state or worktree records; with --force it also force-deletes the local feature branch when present.`
73
+ ],
74
+ [
75
+ "project",
76
+ `dd-flow project - register and inspect typed project identity
77
+
78
+ Usage:
79
+ dd-flow project register --root <root> --json
80
+ dd-flow project status --root <root> --json
81
+ dd-flow project resolve <PRJ-ID|PRJ-NNN> --json
82
+ dd-flow project archive <PRJ-ID|PRJ-NNN> --reason <text> --json
83
+ dd-flow project archive --root <previous-root-path> --reason <text> --json
84
+ dd-flow project migrate-ids --root <root> [--apply] --json
85
+
86
+ New registrations use full typed ids such as PRJ-001-dd-flow-playground and short aliases such as PRJ-001. project resolve accepts full id or unique short alias. project archive removes stale or deleted project roots from active dashboards without deleting history. Re-registering an existing root reactivates it. migrate-ids is the explicit transition path for old hash-based local project ids; without --apply it returns a dry-run plan.`
87
+ ],
88
+ [
89
+ "lane",
90
+ `dd-flow lane - coordinate shared project workspaces
91
+
92
+ Usage:
93
+ dd-flow lane status --project-root <root> --json
94
+ dd-flow lane workspace <action> [options] --json
95
+ dd-flow lane lock <action> [options] --json
96
+
97
+ Use lanes when multiple agents might edit or merge through the same workspace. The CLI enforces mechanical ownership only; prompts decide whether a route should use merge, direct-main, or a feature worktree.
98
+
99
+ Examples:
100
+ dd-flow lane status --project-root "$PWD" --json
101
+ dd-flow lane workspace set --project-root "$PWD" --lane direct-main --path "$PWD" --branch main --json
102
+ dd-flow lane lock status --project-root "$PWD" --lane direct-main --json`
103
+ ],
104
+ [
105
+ "lane workspace",
106
+ `dd-flow lane workspace - register and check lane workspaces
107
+
108
+ Usage:
109
+ dd-flow lane workspace set --project-root <root> --lane <name> --path <workspace> [--branch <name>] --json
110
+ dd-flow lane workspace check --project-root <root> --lane <name> --path <workspace> --json
111
+
112
+ The project_root identifies the repository in dd-flow state. The workspace_path is the checkout where the worker is running. Branch checks are factual diagnostics, not semantic policy decisions.
113
+
114
+ Examples:
115
+ dd-flow lane workspace set --project-root "$PWD" --lane merge --path "$PWD" --branch main --json
116
+ dd-flow lane workspace check --project-root "$PWD" --lane merge --path "$(pwd)" --json`
117
+ ],
118
+ [
119
+ "lane lock",
120
+ `dd-flow lane lock - acquire, heartbeat, wait for, and release lane leases
121
+
122
+ Usage:
123
+ dd-flow lane lock acquire --project-root <root> --lane <name> --worker-id <id> [--path <workspace>] [--ttl 300] --reason <text> --json
124
+ dd-flow lane lock heartbeat --project-root <root> --lane <name> --worker-id <id> [--path <workspace>] [--lease-token <token>] [--ttl 300] --json
125
+ dd-flow lane lock release --project-root <root> --lane <name> --worker-id <id> [--path <workspace>] [--lease-token <token>] --reason <text> --json
126
+ dd-flow lane lock status --project-root <root> --lane <name> --json
127
+ dd-flow lane lock wait --project-root <root> --lane <name> --worker-id <id> [--path <workspace>] --timeout <seconds> --poll-interval <seconds> --json
128
+
129
+ Lock mutation commands validate that --path, or the current working directory when --path is omitted, matches the registered lane workspace. Only the owner can heartbeat or release an active lease. Expired leases can be taken over mechanically and are recorded in audit.
130
+
131
+ Examples:
132
+ dd-flow lane lock acquire --project-root "$PWD" --lane merge --worker-id worker-1 --path "$PWD" --ttl 300 --reason "merge worker" --json
133
+ dd-flow lane lock heartbeat --project-root "$PWD" --lane merge --worker-id worker-1 --path "$PWD" --lease-token "$TOKEN" --json
134
+ dd-flow lane lock release --project-root "$PWD" --lane merge --worker-id worker-1 --path "$PWD" --lease-token "$TOKEN" --reason done --json`
135
+ ],
136
+ [
137
+ "merge-queue",
138
+ `dd-flow merge-queue - inspect and process ready-for-merge protocols
139
+
140
+ Usage:
141
+ dd-flow merge-queue status --project-root <root> --json
142
+ dd-flow merge-queue next --project-root <root> --worker-id <id> [--path <workspace>] --json
143
+ dd-flow merge-queue wait-next --project-root <root> --worker-id <id> [--path <workspace>] --timeout <seconds> --poll-interval <seconds> [--acquire-lock true] --json
144
+ dd-flow merge-queue complete <protocol-id> --worker-id <id> [--path <workspace>] --summary <text> --json
145
+ dd-flow merge-queue note <protocol-id> --worker-id <id> --summary <text> --json
146
+ dd-flow merge-queue fail <protocol-id> --worker-id <id> [--path <workspace>] --reason <text> --requeue true|false --json
147
+ dd-flow merge-queue cancel <protocol-id> --reason <text> [--worker-id <id>] [--path <workspace>] [--force] --json
148
+
149
+ The worker must own the merge lane from the registered merge workspace before claiming, completing, or failing jobs. note updates the final completion summary after post-complete cleanup and does not require a lane lock. --path defaults to the current working directory. Use --worker-id as the owner identity.
150
+
151
+ Examples:
152
+ dd-flow merge-queue wait-next --project-root "$PWD" --worker-id merge-worker --path "$PWD" --timeout 1200 --poll-interval 10 --acquire-lock true --json
153
+ dd-flow merge-queue complete PRT-123 --worker-id merge-worker --path "$PWD" --summary "merged locally; cleanup follows" --json
154
+ dd-flow merge-queue note PRT-123 --worker-id merge-worker --summary "merged, pushed, checked, and cleanup completed" --json`
155
+ ],
156
+ [
157
+ "cleanup",
158
+ `dd-flow cleanup - scan and apply explicit local runtime cleanup plans
159
+
160
+ Usage:
161
+ dd-flow cleanup scan --project-root <root> --json
162
+ dd-flow cleanup apply --project-root <root> --plan-file <file> --reason <text> [--force] --json
163
+
164
+ cleanup scan is read-only and returns deterministic findings plus plan.actions. cleanup apply validates project identity, action kinds, reason, and destructive force requirements before mutating runtime state, then reports requested/applied/changed/skipped action results. Worktree record cleanup marks a checkout removed only when its path is already absent; existing checkouts are kept instead of being silently deleted. Use this for stale queue jobs, missing protocol runtime snapshots, stale sessions, expired locks, and terminal-protocol worktree records.`
165
+ ],
166
+ [
167
+ "merge-queue wait-next",
168
+ `dd-flow merge-queue wait-next - wait for the next ready merge job
169
+
170
+ Usage:
171
+ dd-flow merge-queue wait-next --project-root <root> --worker-id <id> [--path <workspace>] --timeout <seconds> --poll-interval <seconds> [--acquire-lock true] --json
172
+
173
+ Use this from a shell or supervisor to wait outside model tokens. Live merge workers should prefer long waits, for example --timeout 1200 --poll-interval 10, so the agent sleeps inside the CLI process instead of spending model tokens on frequent polling. If --acquire-lock true is used, the merge lock is heartbeated while waiting and a lock acquired by this command is released on timeout. If a job is ready, it is claimed atomically. If no job appears before the timeout, the command returns a structured timeout result.
174
+
175
+ Examples:
176
+ dd-flow merge-queue wait-next --project-root "$PWD" --worker-id supervisor --path "$PWD" --timeout 1200 --poll-interval 10 --acquire-lock true --json`
177
+ ],
178
+ [
179
+ "session",
180
+ `dd-flow session - register and stop explicit flow sessions
181
+
182
+ Usage:
183
+ dd-flow session register --payload-file <file> --json
184
+ dd-flow session register --payload-base64 <payload> --json
185
+ dd-flow session status --project-root <root> [--session-id <id>] [--worker-id <id>] --json
186
+ dd-flow session stop --project-root <root> --session-id <id> --reason <text> --json
187
+ dd-flow session stop-worker --project-root <root> --worker-id <id> --reason <text> --json
188
+
189
+ Session registration is the durable contract used by Stop hooks. Prompts register flow_kind, continuation_policy, protocol_id, worker_id, and workspace_path explicitly. Prefer --payload-file in Codex prompts because PreToolUse hooks see the raw shell command before variable expansion.`
190
+ ],
191
+ [
192
+ "project config",
193
+ `dd-flow project config - inspect and update project configuration
194
+
195
+ Usage:
196
+ dd-flow project config status --project-root <root> --json
197
+ dd-flow project config set --project-root <root> --key <path> --value <value> --json
198
+
199
+ Supported keys:
200
+ dashboard.auto_refresh = true|false
201
+ dashboard.project = true|false
202
+ dashboard.global = true|false
203
+ dashboard.open_on_session_start = true|false
204
+ dashboard.open_on_merge_worker_start = true|false
205
+ dashboard.markdown_path = <path>
206
+ dashboard.global_markdown_path = <path>
207
+ integrations.cmux.mode = off|auto|required`
208
+ ],
209
+ [
210
+ "integration cmux",
211
+ `dd-flow integration cmux - inspect optional cmux availability
212
+
213
+ Usage:
214
+ dd-flow integration cmux status --project-root <root> --json`
215
+ ],
216
+ [
217
+ "dashboard",
218
+ `dd-flow dashboard - render or open markdown dashboards
219
+
220
+ Usage:
221
+ dd-flow dashboard render --project-root <root> [--output <path>] --json
222
+ dd-flow dashboard render-global [--output <path>] --json
223
+ dd-flow dashboard open --project-root <root> [--viewer cmux] --json
224
+ dd-flow dashboard refresh --project-root <root> [--open auto|true|false] --json
225
+ dd-flow dashboard refresh-global [--output <path>] --json
226
+
227
+ Dashboards are rendered views of dd-flow state. State-changing commands refresh markdown automatically when dashboard.auto_refresh is enabled. dashboard refresh rewrites project and global markdown when enabled. cmux is used only by explicit open/refresh commands and only according to project config.`
228
+ ],
229
+ [
230
+ "schema",
231
+ `dd-flow schema - validate canonical dd-flow data contracts
232
+
233
+ Usage:
234
+ dd-flow schema validate --schema <name> --file <json-file> [--project-root <root>] [--schema-dir <dir>] --json
235
+
236
+ Schema names resolve to <name>.schema.json. Lookup order is --schema-dir, then <project-root>/.memory-bank/dd-flow/schemas/, then bundled CLI schemas. If --project-root is omitted, the current working directory is used. JSON mode writes valid results to stdout and structured validation/usage errors to stderr.`
237
+ ],
238
+ [
239
+ "schema validate",
240
+ `dd-flow schema validate - validate a JSON artifact against a canonical schema
241
+
242
+ Usage:
243
+ dd-flow schema validate --schema mb-upgrade-review-data --file review-data.json [--project-root <root>] [--schema-dir <dir>] --json
244
+
245
+ Exit codes:
246
+ 0 valid
247
+ 2 usage, unknown schema, invalid JSON, or schema validation failure
248
+
249
+ Examples:
250
+ dd-flow schema validate --schema mb-upgrade-review-data --file .tasks/mb-upgrade-review-2026-06-04-hr-agent/review-data.json --project-root "$PWD" --json
251
+ dd-flow schema validate --schema mb-upgrade-review-data --file review-data.json --schema-dir .memory-bank/dd-flow/schemas`
252
+ ],
253
+ [
254
+ "memory",
255
+ `dd-flow memory - Memory Bank runtime gates
256
+
257
+ Usage:
258
+ dd-flow memory permissions preflight --root <project-root> --memory-bank <path> [--tasks <path>] --flow <flow> --mode <mode> --json
259
+
260
+ permissions preflight checks project, Memory Bank, and optional .tasks read/write permissions before memory flows mutate files. It never runs privileged repair commands. A completed assessment returns JSON on stdout with exit_code 0 when the flow can continue and exit_code 1 when permission blockers are found. Runtime/configuration mistakes exit 2 as structured errors.`
261
+ ],
262
+ [
263
+ "memory permissions",
264
+ `dd-flow memory permissions - inspect Memory Bank filesystem access
265
+
266
+ Usage:
267
+ dd-flow memory permissions preflight --root . --memory-bank .memory-bank --tasks .tasks --flow mb-upgrade --mode write --json
268
+
269
+ Flows: mb-init, mb-upgrade, mb-audit, mb-fix, mb-upgrade-review, custom.
270
+ Modes: read, write, repair, report_only.
271
+
272
+ Use read mode before read-only audit analysis. Use write or report_only before creating or updating Memory Bank files, DEF records, dashboards, or .tasks artifacts. The command may create and remove temporary probe files in checked writable directories, but it does not persist files as part of diagnosis.`
273
+ ],
274
+ [
275
+ "codex home",
276
+ `dd-flow codex home - manage isolated Codex homes
277
+
278
+ Usage:
279
+ dd-flow codex home plan --project-root <root> [--profile <name>] --json
280
+ dd-flow codex home init --project-root <root> [--profile <name>] [--source-home <path>] [--target-home <path>] --json
281
+ dd-flow codex home status --project-root <root> [--profile <name>] --json
282
+ dd-flow codex home print-env --project-root <root> [--profile <name>] --json
283
+ dd-flow codex home remove --project-root <root> [--profile <name>] --mode keep-shared|remove-owned --json
284
+
285
+ Managed homes isolate dd-flow hooks while sharing selected Codex state from the source home.`
286
+ ],
287
+ [
288
+ "worktree",
289
+ `dd-flow worktree - record Worktrunk-backed feature worktrees
290
+
291
+ Usage:
292
+ dd-flow worktree plan --protocol-id <protocol-id> --json
293
+ dd-flow worktree create --protocol-id <protocol-id> --branch <name> --base <ref> --path <path> --json
294
+ dd-flow worktree status --protocol-id <protocol-id> --json
295
+ dd-flow worktree bootstrap --protocol-id <protocol-id> --json
296
+ dd-flow worktree close --protocol-id <protocol-id> --mode keep|remove --json
297
+
298
+ worktree plan suggests a project-scoped service checkout under DD_FLOW_HOME/projects/<PRJ-ID-slug>/checkouts/. Worktrunk owns the actual worktree lifecycle. dd-flow records explicit state and structured degraded mode.`
299
+ ]
300
+ ]);
301
+ export function helpForArgs(args) {
302
+ const helpIndex = args.findIndex((arg) => arg === "--help" || arg === "-h");
303
+ if (helpIndex === -1) {
304
+ return undefined;
305
+ }
306
+ const path = args.slice(0, helpIndex).filter((arg) => !arg.startsWith("--")).join(" ");
307
+ return helpPages.get(path) ?? helpPages.get(path.split(" ").slice(0, 2).join(" ")) ?? helpPages.get("");
308
+ }