@deksden-com/dd-flow-cli 0.1.0 → 0.2.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.
- package/README.md +11 -0
- package/dist/build-info.json +11 -0
- package/dist/cli/help.js +63 -1
- package/dist/cli/run-cli.js +104 -0
- package/dist/schemas/archived-flow-manifest.schema.json +112 -0
- package/dist/schemas/merge-stage-report.schema.json +61 -1
- package/dist/schemas/plan-stage-report.schema.json +172 -0
- package/dist/schemas/project-flow-pack-manifest.schema.json +123 -0
- package/dist/schemas/status-report.schema.json +152 -0
- package/dist/services/build-info.js +91 -0
- package/dist/services/canon.js +227 -0
- package/dist/services/lanes.js +6 -2
- package/dist/services/merge-queue.js +59 -3
- package/dist/services/merge-worker.js +148 -0
- package/dist/services/protocols.js +12 -12
- package/dist/services/schema-validation.js +4 -5
- package/dist/services/sessions.js +3 -2
- package/dist/services/status.js +118 -0
- package/dist/services/version-status.js +258 -0
- package/dist/storage/database.js +7 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -41,6 +41,17 @@ The flow contract defines mechanical protocol stages, allowed transitions, the `
|
|
|
41
41
|
|
|
42
42
|
## Basic Commands
|
|
43
43
|
|
|
44
|
+
Inspect runtime and canonical Memory Bank discovery:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
dd-flow status --project-root "$PWD" --json
|
|
48
|
+
dd-flow canon resolve --json
|
|
49
|
+
dd-flow canon register --root "$DD_MEMORYBANK" --json
|
|
50
|
+
dd-flow canon status --json
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`canon resolve` checks explicit `--root`, then `DD_MEMORYBANK`, then the globally registered value in `DD_FLOW_HOME`, then known nearby `dd-memorybank` checkouts from the current working directory. If two different valid canonical roots are discovered, it fails closed with structured blockers and bootstrap hints. Use `DD_MEMORYBANK` for the local canonical `dd-memorybank` checkout.
|
|
54
|
+
|
|
44
55
|
Register a project:
|
|
45
56
|
|
|
46
57
|
```bash
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cli_package": "@deksden-com/dd-flow-cli",
|
|
3
|
+
"cli_version": "0.2.0",
|
|
4
|
+
"cli_commit": "8351d94bdeaca22d2fff503fd2b08071c86205cd",
|
|
5
|
+
"built_at": "2026-06-15T14:46:55.550Z",
|
|
6
|
+
"built_with_canon": {
|
|
7
|
+
"version": "2.4.0",
|
|
8
|
+
"commit": "cf1f6d08e8d4775bf14334c6010b479d1c6fd73f",
|
|
9
|
+
"flow_contract": "dd-flow-canonical-2026-05"
|
|
10
|
+
}
|
|
11
|
+
}
|
package/dist/cli/help.js
CHANGED
|
@@ -9,6 +9,8 @@ Usage:
|
|
|
9
9
|
dd-flow <command> --help
|
|
10
10
|
|
|
11
11
|
Core commands:
|
|
12
|
+
status Inspect dd-flow runtime, project and canon roots.
|
|
13
|
+
canon register/status/resolve Register and resolve the canonical Memory Bank.
|
|
12
14
|
project register/status Register a project and inspect runtime state.
|
|
13
15
|
project resolve/archive Resolve typed ids and archive stale project roots.
|
|
14
16
|
project migrate-ids Migrate old project ids.
|
|
@@ -17,6 +19,8 @@ Core commands:
|
|
|
17
19
|
run start/status/list Track concrete flow executions and stage artifacts.
|
|
18
20
|
plan set/status/item Attach and update protocol plans.
|
|
19
21
|
lane workspace/lock/status Manage shared workspace lanes and leases.
|
|
22
|
+
merge status/one-shot Inspect or claim one merge job from the current session.
|
|
23
|
+
merge-worker status/start/stop Manage long-lived project merge workers.
|
|
20
24
|
merge-queue status/next Claim, wait for, complete, or fail merge jobs.
|
|
21
25
|
session register/status/stop Register flow sessions and stop workers.
|
|
22
26
|
dashboard render/open/refresh Render markdown project/global dashboards.
|
|
@@ -28,6 +32,9 @@ Core commands:
|
|
|
28
32
|
|
|
29
33
|
Examples:
|
|
30
34
|
dd-flow project register --root "$PWD"
|
|
35
|
+
dd-flow status --project-root "$PWD" --json
|
|
36
|
+
dd-flow canon register --root "$DD_MEMORYBANK" --json
|
|
37
|
+
dd-flow canon resolve --json
|
|
31
38
|
dd-flow project status --root "$PWD" --json
|
|
32
39
|
dd-flow project resolve PRJ-001 --json
|
|
33
40
|
dd-flow project archive PRJ-001 --reason "old missing worktree root" --json
|
|
@@ -35,10 +42,44 @@ Examples:
|
|
|
35
42
|
dd-flow run start --project-root "$PWD" --flow-kind coding --subject-type protocol --subject-id PRT-001-demo --slug demo --json
|
|
36
43
|
dd-flow lane workspace set --project-root "$PWD" --lane merge --path "$PWD" --branch main --json
|
|
37
44
|
dd-flow lane lock acquire --project-root "$PWD" --lane merge --worker-id worker-1 --path "$PWD" --ttl 300 --reason "merge worker" --json
|
|
45
|
+
dd-flow merge status --project-root "$PWD" --json
|
|
46
|
+
dd-flow merge-worker start --project-root "$PWD" --worker-id merge-worker --path "$PWD" --json
|
|
38
47
|
|
|
39
48
|
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
49
|
|
|
41
50
|
project_root is the stable repository identity. workspace_path is the concrete checkout where an agent is about to work.`
|
|
51
|
+
],
|
|
52
|
+
[
|
|
53
|
+
"status",
|
|
54
|
+
`dd-flow status - inspect runtime roots and active discovery state
|
|
55
|
+
|
|
56
|
+
Usage:
|
|
57
|
+
dd-flow status [--project-root <root>] --json
|
|
58
|
+
dd-flow status [--root <root>] --json
|
|
59
|
+
|
|
60
|
+
status reports DD_FLOW_HOME, the requested or current project root, registered project identity when available, and canonical Memory Bank discovery. It does not require the project to be registered and does not mutate state. In JSON mode canon discovery is embedded as a structured assessment so agents can detect missing or ambiguous canon roots without parsing stderr.
|
|
61
|
+
|
|
62
|
+
Examples:
|
|
63
|
+
dd-flow status --project-root "$PWD" --json
|
|
64
|
+
dd-flow status --json`
|
|
65
|
+
],
|
|
66
|
+
[
|
|
67
|
+
"canon",
|
|
68
|
+
`dd-flow canon - register and resolve the canonical Memory Bank checkout
|
|
69
|
+
|
|
70
|
+
Usage:
|
|
71
|
+
dd-flow canon register --root <canonical-dd-memorybank-root> --json
|
|
72
|
+
dd-flow canon status [--root <canonical-dd-memorybank-root>] --json
|
|
73
|
+
dd-flow canon resolve [--root <canonical-dd-memorybank-root>] --json
|
|
74
|
+
|
|
75
|
+
Discovery order is explicit --root, then DD_MEMORYBANK, then the globally registered runtime value in DD_FLOW_HOME, then known nearby dd-memorybank checkouts from the current working directory. Explicit --root is the only source considered for that command. If multiple different valid canonical checkouts are found, resolve fails closed with blockers so the caller chooses intentionally.
|
|
76
|
+
|
|
77
|
+
A valid canonical root contains dd-flow/README.md, mbb/index.md, protocol/index.md, and canonical-only entrypoints such as dd-flow/mb-init.md, dd-flow/mb-upgrade.md, dd-flow/mb-upgrade-review.md, and dd-flow/mb-distill.md.
|
|
78
|
+
|
|
79
|
+
Examples:
|
|
80
|
+
dd-flow canon register --root "$DD_MEMORYBANK" --json
|
|
81
|
+
dd-flow canon resolve --json
|
|
82
|
+
dd-flow canon status --json`
|
|
42
83
|
],
|
|
43
84
|
[
|
|
44
85
|
"run",
|
|
@@ -132,6 +173,27 @@ Examples:
|
|
|
132
173
|
dd-flow lane lock acquire --project-root "$PWD" --lane merge --worker-id worker-1 --path "$PWD" --ttl 300 --reason "merge worker" --json
|
|
133
174
|
dd-flow lane lock heartbeat --project-root "$PWD" --lane merge --worker-id worker-1 --path "$PWD" --lease-token "$TOKEN" --json
|
|
134
175
|
dd-flow lane lock release --project-root "$PWD" --lane merge --worker-id worker-1 --path "$PWD" --lease-token "$TOKEN" --reason done --json`
|
|
176
|
+
],
|
|
177
|
+
[
|
|
178
|
+
"merge",
|
|
179
|
+
`dd-flow merge - current-session merge entrypoint helpers
|
|
180
|
+
|
|
181
|
+
Usage:
|
|
182
|
+
dd-flow merge status --project-root <root> --json
|
|
183
|
+
dd-flow merge one-shot --project-root <root> --worker-id <id> [--path <workspace>] --json
|
|
184
|
+
|
|
185
|
+
merge status reports active merge worker, claimed jobs, active merge lane lock and queue state. merge one-shot is status-only when a long-lived worker, claimed job or active lock exists; otherwise it acquires the merge lane, claims at most one ready job, and returns that job for the shared merge job prompt. If no job is ready, it releases the lock and returns job: null.`
|
|
186
|
+
],
|
|
187
|
+
[
|
|
188
|
+
"merge-worker",
|
|
189
|
+
`dd-flow merge-worker - manage long-lived project merge workers
|
|
190
|
+
|
|
191
|
+
Usage:
|
|
192
|
+
dd-flow merge-worker status --project-root <root> --json
|
|
193
|
+
dd-flow merge-worker start --project-root <root> --worker-id <id> [--path <workspace>] [--branch <branch>] --json
|
|
194
|
+
dd-flow merge-worker stop --project-root <root> [--worker-id <id>] --reason <text> --json
|
|
195
|
+
|
|
196
|
+
start is idempotent: if a worker, claimed job, or active merge lock already exists it returns status instead of creating a duplicate worker. stop is no-op/status when no worker exists, refuses ambiguous multiple workers unless --worker-id is provided, stops idle workers immediately, and marks busy workers as stop-after-current while preserving the claimed job and lock.`
|
|
135
197
|
],
|
|
136
198
|
[
|
|
137
199
|
"merge-queue",
|
|
@@ -233,7 +295,7 @@ Dashboards are rendered views of dd-flow state. State-changing commands refresh
|
|
|
233
295
|
Usage:
|
|
234
296
|
dd-flow schema validate --schema <name> --file <json-file> [--project-root <root>] [--schema-dir <dir>] --json
|
|
235
297
|
|
|
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.`
|
|
298
|
+
Schema names resolve to <name>.schema.json. Lookup order is --schema-dir, then <project-root>/.memory-bank/dd-flow/schemas/, then <project-root>/dd-flow/schemas/ for canonical checkouts, 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
299
|
],
|
|
238
300
|
[
|
|
239
301
|
"schema validate",
|
package/dist/cli/run-cli.js
CHANGED
|
@@ -6,11 +6,14 @@ import { archiveProject, getProjectStatus, migrateProjectIds, registerProject, r
|
|
|
6
6
|
import { cancelProtocol, getProtocolStatus, readyForMerge, registerProtocol, requireProtocol, transitionProtocol } from "../services/protocols.js";
|
|
7
7
|
import { blockPlanItem, completePlanItem, getPlanStatus, setProtocolPlan, skipPlanItem, startPlanItem } from "../services/plans.js";
|
|
8
8
|
import { cancelMergeQueueJob, claimNextMergeJob, completeMergeJob, failMergeJob, getMergeQueueStatus, noteMergeJob, waitNextMergeJob } from "../services/merge-queue.js";
|
|
9
|
+
import { getMergeWorkerStatus, oneShotMergeClaim, startMergeWorker, stopProjectMergeWorker } from "../services/merge-worker.js";
|
|
9
10
|
import { cleanupApply, cleanupScan } from "../services/cleanup.js";
|
|
10
11
|
import { getCodexHomeStatus, getCodexHooksStatus, handleCodexHook, initCodexHome, installCodexHooks, planCodexHome, printCodexHomeEnv, printCodexHooks, removeCodexHome, removeCodexHooks } from "../services/hooks.js";
|
|
11
12
|
import { bootstrapWorktree, closeWorktree, createWorktreeRecord, getWorktreeStatus, planWorktree } from "../services/worktrees.js";
|
|
12
13
|
import { acquireLaneLock, checkLaneWorkspace, getLaneStatus, heartbeatLaneLock, releaseLaneLock, setLaneWorkspace, waitForLaneLock } from "../services/lanes.js";
|
|
13
14
|
import { getProjectConfigStatus, setProjectConfigValue } from "../services/config.js";
|
|
15
|
+
import { getCanonStatus, registerCanonRoot, resolveCanonRoot } from "../services/canon.js";
|
|
16
|
+
import { getRuntimeStatus } from "../services/status.js";
|
|
14
17
|
import { autoRefreshDashboards, getCmuxStatus, openDashboard, refreshDashboard, refreshGlobalDashboard, renderDashboard, renderGlobalDashboard } from "../services/dashboard.js";
|
|
15
18
|
import { getFlowSessionStatus, registerFlowSession, stopFlowSession, stopMergeWorker } from "../services/sessions.js";
|
|
16
19
|
import { attachFlowRunStage, completeFlowRun, completeFlowRunStage, getFlowRunStatus, listFlowRuns, startFlowRun } from "../services/runs.js";
|
|
@@ -91,6 +94,8 @@ function progressForCommand(args) {
|
|
|
91
94
|
];
|
|
92
95
|
}
|
|
93
96
|
if ((family === "cleanup" && command === "apply") ||
|
|
97
|
+
(family === "merge" && command === "one-shot") ||
|
|
98
|
+
family === "merge-worker" ||
|
|
94
99
|
(family === "protocol" && command === "cancel") ||
|
|
95
100
|
(family === "project" && command === "archive") ||
|
|
96
101
|
family === "run") {
|
|
@@ -144,6 +149,9 @@ function renderHumanResult(args, result) {
|
|
|
144
149
|
lines.push(`errors: ${errors.length}`);
|
|
145
150
|
return `${lines.join("\n")}\n`;
|
|
146
151
|
}
|
|
152
|
+
if (family === "status") {
|
|
153
|
+
return renderStatusHuman(record);
|
|
154
|
+
}
|
|
147
155
|
const lines = [`dd-flow ${family ?? ""}${command ? ` ${command}` : ""}: ${ok}`.trim()];
|
|
148
156
|
const project = record.project && typeof record.project === "object" ? record.project : null;
|
|
149
157
|
const protocol = record.protocol && typeof record.protocol === "object" ? record.protocol : null;
|
|
@@ -170,9 +178,47 @@ function renderHumanResult(args, result) {
|
|
|
170
178
|
}
|
|
171
179
|
return `${lines.join("\n")}\n`;
|
|
172
180
|
}
|
|
181
|
+
function renderStatusHuman(record) {
|
|
182
|
+
const lines = [`dd-flow status: ${record.ok === false ? "failed" : "ok"}`];
|
|
183
|
+
const cli = recordObject(record.cli);
|
|
184
|
+
const cliBuild = recordObject(cli?.build);
|
|
185
|
+
const builtWithCanon = recordObject(cliBuild?.built_with_canon);
|
|
186
|
+
const canon = recordObject(record.canon);
|
|
187
|
+
const resolvedCanon = recordObject(canon?.resolved);
|
|
188
|
+
const project = recordObject(record.project);
|
|
189
|
+
const memoryBank = recordObject(project?.memory_bank);
|
|
190
|
+
const flowPack = recordObject(project?.flow_pack);
|
|
191
|
+
const drift = recordObject(project?.drift);
|
|
192
|
+
lines.push(`CLI package: ${stringValue(cli?.package_name) ?? "unknown"} ${stringValue(cli?.version) ?? "unknown"}`);
|
|
193
|
+
lines.push(`CLI tested with canon: ${stringValue(builtWithCanon?.version) ?? "unknown"} @ ${shortSha(stringValue(builtWithCanon?.commit))}`);
|
|
194
|
+
lines.push(`Active local canon: ${stringValue(resolvedCanon?.root) ?? "unresolved"} ${stringValue(resolvedCanon?.version) ?? "unknown"} @ ${shortSha(stringValue(resolvedCanon?.commit))}`);
|
|
195
|
+
lines.push(`Project: ${stringValue(project?.root) ?? "unknown"}${project?.registered === true ? " (registered)" : " (unregistered)"}`);
|
|
196
|
+
lines.push(`Project Memory Bank: ${stringValue(memoryBank?.version) ?? stringValue(memoryBank?.status) ?? "unknown"}`);
|
|
197
|
+
lines.push(`Project flow pack: ${stringValue(flowPack?.pack_version) ?? stringValue(flowPack?.status) ?? "unknown"} @ ${shortSha(stringValue(flowPack?.source_commit))}`);
|
|
198
|
+
lines.push(`Drift: ${stringValue(drift?.overall) ?? "unknown"}`);
|
|
199
|
+
if (drift?.next_action)
|
|
200
|
+
lines.push(`Next action: ${String(drift.next_action)}`);
|
|
201
|
+
return `${lines.join("\n")}\n`;
|
|
202
|
+
}
|
|
203
|
+
function recordObject(value) {
|
|
204
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
205
|
+
}
|
|
206
|
+
function stringValue(value) {
|
|
207
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
208
|
+
}
|
|
209
|
+
function shortSha(value) {
|
|
210
|
+
return value ? value.slice(0, 12) : "unknown";
|
|
211
|
+
}
|
|
173
212
|
async function dispatch(args, context, io) {
|
|
174
213
|
const [family, command, ...rest] = args;
|
|
175
214
|
const parsed = parseArgs(rest);
|
|
215
|
+
if (family === "status") {
|
|
216
|
+
const rootParsed = parseArgs([command ?? "", ...rest]);
|
|
217
|
+
return getRuntimeStatus(context, { projectRoot: optionalOption(rootParsed, "project-root") ?? optionalOption(rootParsed, "root") });
|
|
218
|
+
}
|
|
219
|
+
if (family === "canon") {
|
|
220
|
+
return dispatchCanon(context, command, parsed);
|
|
221
|
+
}
|
|
176
222
|
if (family === "project" && command === "register") {
|
|
177
223
|
return registerProject(context, { root: requiredOption(parsed, "root") });
|
|
178
224
|
}
|
|
@@ -252,6 +298,12 @@ async function dispatch(args, context, io) {
|
|
|
252
298
|
if (family === "merge-queue") {
|
|
253
299
|
return dispatchMergeQueue(context, command, parsed);
|
|
254
300
|
}
|
|
301
|
+
if (family === "merge") {
|
|
302
|
+
return dispatchMerge(context, command, parsed);
|
|
303
|
+
}
|
|
304
|
+
if (family === "merge-worker") {
|
|
305
|
+
return dispatchMergeWorker(context, command, parsed);
|
|
306
|
+
}
|
|
255
307
|
if (family === "cleanup") {
|
|
256
308
|
return dispatchCleanup(context, command, parsed);
|
|
257
309
|
}
|
|
@@ -287,6 +339,18 @@ async function dispatch(args, context, io) {
|
|
|
287
339
|
}
|
|
288
340
|
throw new AppError("usage", `Unknown command: ${args.join(" ") || "<empty>"}`, 2);
|
|
289
341
|
}
|
|
342
|
+
function dispatchCanon(context, command, parsed) {
|
|
343
|
+
if (command === "register") {
|
|
344
|
+
return registerCanonRoot(context, { root: requiredOption(parsed, "root") });
|
|
345
|
+
}
|
|
346
|
+
if (command === "status") {
|
|
347
|
+
return getCanonStatus(context, { root: optionalOption(parsed, "root") });
|
|
348
|
+
}
|
|
349
|
+
if (command === "resolve") {
|
|
350
|
+
return resolveCanonRoot(context, { explicitRoot: optionalOption(parsed, "root") });
|
|
351
|
+
}
|
|
352
|
+
throw new AppError("usage", `Unknown canon command: ${command ?? "<empty>"}`, 2);
|
|
353
|
+
}
|
|
290
354
|
function dispatchMergeQueue(context, command, parsed) {
|
|
291
355
|
if (hasOption(parsed, "session-id")) {
|
|
292
356
|
throw new AppError("usage", "--session-id is no longer accepted on merge-queue commands; use --worker-id", 2);
|
|
@@ -346,6 +410,40 @@ function dispatchMergeQueue(context, command, parsed) {
|
|
|
346
410
|
}
|
|
347
411
|
throw new AppError("usage", `Unknown merge-queue command: ${command ?? "<empty>"}`, 2);
|
|
348
412
|
}
|
|
413
|
+
function dispatchMerge(context, command, parsed) {
|
|
414
|
+
if (command === "status") {
|
|
415
|
+
return getMergeWorkerStatus(context, { projectRoot: requiredOption(parsed, "project-root") });
|
|
416
|
+
}
|
|
417
|
+
if (command === "one-shot") {
|
|
418
|
+
return oneShotMergeClaim(context, {
|
|
419
|
+
projectRoot: requiredOption(parsed, "project-root"),
|
|
420
|
+
workerId: requiredWorkerId(parsed),
|
|
421
|
+
workspacePath: workspacePathOption(parsed)
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
throw new AppError("usage", `Unknown merge command: ${command ?? "<empty>"}`, 2);
|
|
425
|
+
}
|
|
426
|
+
function dispatchMergeWorker(context, command, parsed) {
|
|
427
|
+
if (command === "status") {
|
|
428
|
+
return getMergeWorkerStatus(context, { projectRoot: requiredOption(parsed, "project-root") });
|
|
429
|
+
}
|
|
430
|
+
if (command === "start") {
|
|
431
|
+
return startMergeWorker(context, {
|
|
432
|
+
projectRoot: requiredOption(parsed, "project-root"),
|
|
433
|
+
workerId: requiredWorkerId(parsed),
|
|
434
|
+
workspacePath: workspacePathOption(parsed),
|
|
435
|
+
branch: optionalOption(parsed, "branch")
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
if (command === "stop") {
|
|
439
|
+
return stopProjectMergeWorker(context, {
|
|
440
|
+
projectRoot: requiredOption(parsed, "project-root"),
|
|
441
|
+
workerId: optionalOption(parsed, "worker-id"),
|
|
442
|
+
reason: requiredOption(parsed, "reason")
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
throw new AppError("usage", `Unknown merge-worker command: ${command ?? "<empty>"}`, 2);
|
|
446
|
+
}
|
|
349
447
|
function dispatchMemory(command, parsed) {
|
|
350
448
|
const subcommand = requiredPosition(parsed, 0, "memory subcommand");
|
|
351
449
|
if (command === "permissions" && subcommand === "preflight") {
|
|
@@ -882,6 +980,12 @@ function projectRootForMutation(context, args, result) {
|
|
|
882
980
|
if (family === "merge-queue") {
|
|
883
981
|
return projectRootForMergeQueueMutation(context, command, parsed);
|
|
884
982
|
}
|
|
983
|
+
if (family === "merge" && command === "one-shot") {
|
|
984
|
+
return requiredOption(parsed, "project-root");
|
|
985
|
+
}
|
|
986
|
+
if (family === "merge-worker" && ["start", "stop"].includes(command ?? "")) {
|
|
987
|
+
return requiredOption(parsed, "project-root");
|
|
988
|
+
}
|
|
885
989
|
if (family === "cleanup" && command === "apply") {
|
|
886
990
|
return requiredOption(parsed, "project-root");
|
|
887
991
|
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "dd-flow/archived-flow-manifest@1",
|
|
4
|
+
"title": "Archived flow manifest",
|
|
5
|
+
"description": "Manifest for dd-flow files archived from an active project flow pack during Memory Bank upgrade.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"schema_id",
|
|
10
|
+
"archive_id",
|
|
11
|
+
"created_at",
|
|
12
|
+
"target_project_root",
|
|
13
|
+
"source_flow_root",
|
|
14
|
+
"archive_root",
|
|
15
|
+
"items"
|
|
16
|
+
],
|
|
17
|
+
"properties": {
|
|
18
|
+
"schema_id": {
|
|
19
|
+
"const": "dd-flow/archived-flow-manifest@1"
|
|
20
|
+
},
|
|
21
|
+
"archive_id": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"minLength": 1
|
|
24
|
+
},
|
|
25
|
+
"created_at": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"minLength": 1
|
|
28
|
+
},
|
|
29
|
+
"target_project_root": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"minLength": 1
|
|
32
|
+
},
|
|
33
|
+
"source_flow_root": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"minLength": 1
|
|
36
|
+
},
|
|
37
|
+
"archive_root": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"minLength": 1
|
|
40
|
+
},
|
|
41
|
+
"items": {
|
|
42
|
+
"type": "array",
|
|
43
|
+
"minItems": 1,
|
|
44
|
+
"items": {
|
|
45
|
+
"$ref": "#/definitions/item"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"notes": {
|
|
49
|
+
"type": "string"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"definitions": {
|
|
53
|
+
"item": {
|
|
54
|
+
"type": "object",
|
|
55
|
+
"additionalProperties": false,
|
|
56
|
+
"required": [
|
|
57
|
+
"original_path",
|
|
58
|
+
"archive_path",
|
|
59
|
+
"classification",
|
|
60
|
+
"reason",
|
|
61
|
+
"manual_review_required",
|
|
62
|
+
"replacement"
|
|
63
|
+
],
|
|
64
|
+
"properties": {
|
|
65
|
+
"original_path": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"minLength": 1,
|
|
68
|
+
"pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*//)[A-Za-z0-9._-]+(?:/[A-Za-z0-9._-]+)*$"
|
|
69
|
+
},
|
|
70
|
+
"archive_path": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"minLength": 1,
|
|
73
|
+
"pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*//)[A-Za-z0-9._-]+(?:/[A-Za-z0-9._-]+)*$"
|
|
74
|
+
},
|
|
75
|
+
"classification": {
|
|
76
|
+
"type": "string",
|
|
77
|
+
"enum": ["canonical_only_obsolete", "old_full_canonical_copy", "project_customization", "unknown_extra", "generated_or_runtime"]
|
|
78
|
+
},
|
|
79
|
+
"reason": {
|
|
80
|
+
"type": "string",
|
|
81
|
+
"minLength": 1
|
|
82
|
+
},
|
|
83
|
+
"manual_review_required": {
|
|
84
|
+
"type": "boolean"
|
|
85
|
+
},
|
|
86
|
+
"replacement": {
|
|
87
|
+
"type": "object",
|
|
88
|
+
"additionalProperties": false,
|
|
89
|
+
"required": ["kind", "hint"],
|
|
90
|
+
"properties": {
|
|
91
|
+
"kind": {
|
|
92
|
+
"type": "string",
|
|
93
|
+
"enum": ["canonical_only_flow", "project_flow_pack_file", "removed", "needs_decision"]
|
|
94
|
+
},
|
|
95
|
+
"hint": {
|
|
96
|
+
"type": "string",
|
|
97
|
+
"minLength": 1
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"source_commit": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"minLength": 7
|
|
104
|
+
},
|
|
105
|
+
"source_hash": {
|
|
106
|
+
"type": "string",
|
|
107
|
+
"minLength": 1
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -11,7 +11,12 @@
|
|
|
11
11
|
"project",
|
|
12
12
|
"subject",
|
|
13
13
|
"overall",
|
|
14
|
+
"invocation_mode",
|
|
14
15
|
"breadcrumbs",
|
|
16
|
+
"worker",
|
|
17
|
+
"queue_context",
|
|
18
|
+
"lane_lock",
|
|
19
|
+
"integration",
|
|
15
20
|
"merge_job",
|
|
16
21
|
"git",
|
|
17
22
|
"checks",
|
|
@@ -29,6 +34,61 @@
|
|
|
29
34
|
"type": "array",
|
|
30
35
|
"items": { "$ref": "#/definitions/breadcrumb" }
|
|
31
36
|
},
|
|
37
|
+
"invocation_mode": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"enum": ["one_shot", "long_lived_worker"]
|
|
40
|
+
},
|
|
41
|
+
"worker": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"additionalProperties": true,
|
|
44
|
+
"required": ["id", "session_kind", "status_before", "status_after"],
|
|
45
|
+
"properties": {
|
|
46
|
+
"id": { "type": "string", "minLength": 1 },
|
|
47
|
+
"session_kind": { "type": "string", "enum": ["merge_job", "merge_worker"] },
|
|
48
|
+
"status_before": { "type": "string", "minLength": 1 },
|
|
49
|
+
"status_after": { "type": "string", "minLength": 1 },
|
|
50
|
+
"stop_flag": { "type": "string" }
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"queue_context": {
|
|
54
|
+
"type": "object",
|
|
55
|
+
"additionalProperties": true,
|
|
56
|
+
"required": ["before", "claimed_job", "after", "final_reason"],
|
|
57
|
+
"properties": {
|
|
58
|
+
"before": { "type": "string", "minLength": 1 },
|
|
59
|
+
"claimed_job": { "type": "string", "minLength": 1 },
|
|
60
|
+
"position_before": { "type": ["number", "null"] },
|
|
61
|
+
"pending_after": { "type": ["number", "null"] },
|
|
62
|
+
"after": { "type": "string", "minLength": 1 },
|
|
63
|
+
"final_reason": { "type": "string", "minLength": 1 }
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"lane_lock": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"additionalProperties": true,
|
|
69
|
+
"required": ["owner", "status_before", "status_after"],
|
|
70
|
+
"properties": {
|
|
71
|
+
"owner": { "type": "string", "minLength": 1 },
|
|
72
|
+
"lease_token": { "type": "string" },
|
|
73
|
+
"status_before": { "type": "string", "minLength": 1 },
|
|
74
|
+
"status_after": { "type": "string", "minLength": 1 },
|
|
75
|
+
"acquired_at": { "type": "string" },
|
|
76
|
+
"released_at": { "type": "string" }
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"integration": {
|
|
80
|
+
"type": "object",
|
|
81
|
+
"additionalProperties": true,
|
|
82
|
+
"required": ["source_branch", "target_branch", "result"],
|
|
83
|
+
"properties": {
|
|
84
|
+
"source_branch": { "type": "string", "minLength": 1 },
|
|
85
|
+
"source_commit": { "type": "string" },
|
|
86
|
+
"target_branch": { "type": "string", "minLength": 1 },
|
|
87
|
+
"result": { "type": "string", "enum": ["merged", "failed", "requeued", "blocked"] },
|
|
88
|
+
"result_commit": { "type": "string" },
|
|
89
|
+
"conflicts": { "type": "string" }
|
|
90
|
+
}
|
|
91
|
+
},
|
|
32
92
|
"merge_job": {
|
|
33
93
|
"type": "object",
|
|
34
94
|
"additionalProperties": true,
|
|
@@ -96,7 +156,7 @@
|
|
|
96
156
|
"additionalProperties": true,
|
|
97
157
|
"required": ["verdict", "summary", "next_action"],
|
|
98
158
|
"properties": {
|
|
99
|
-
"verdict": { "type": "string", "
|
|
159
|
+
"verdict": { "type": "string", "enum": ["merged", "failed", "requeued", "blocked"] },
|
|
100
160
|
"summary": { "type": "string", "minLength": 1 },
|
|
101
161
|
"next_action": { "type": "string", "minLength": 1 }
|
|
102
162
|
}
|