@deksden-com/dd-flow-cli 0.2.0 → 0.3.1
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/CHANGELOG.md +43 -0
- package/README.md +76 -5
- package/dist/build-info.json +10 -6
- package/dist/cli/help.js +165 -20
- package/dist/cli/run-cli.js +427 -17
- package/dist/schemas/compatibility.schema.json +105 -0
- package/dist/schemas/engine-manifest.schema.json +61 -0
- package/dist/schemas/flow-guidance.schema.json +90 -0
- package/dist/schemas/flow-run-index.schema.json +30 -4
- package/dist/schemas/global-dashboard-data.schema.json +126 -0
- package/dist/schemas/mb-sdlc-review-report.schema.json +242 -0
- package/dist/schemas/mb-upgrade-migration-report.schema.json +93 -0
- package/dist/schemas/plan-stage-report.schema.json +83 -0
- package/dist/schemas/project-dashboard-data.schema.json +122 -0
- package/dist/schemas/project-flow-pack-manifest.schema.json +5 -1
- package/dist/schemas/project-summary.schema.json +73 -0
- package/dist/schemas/protocol-dashboard-data.schema.json +112 -0
- package/dist/schemas/status-report.schema.json +38 -2
- package/dist/schemas/version-report.schema.json +22 -0
- package/dist/services/build-info.js +26 -3
- package/dist/services/canon.js +93 -22
- package/dist/services/cleanup.js +45 -1
- package/dist/services/cli-operation-classifier.js +104 -0
- package/dist/services/compatibility-preflight.js +124 -0
- package/dist/services/config.js +31 -0
- package/dist/services/dashboard-targets.js +95 -0
- package/dist/services/dashboard.js +972 -10
- package/dist/services/engines.js +532 -0
- package/dist/services/flow-guidance.js +221 -0
- package/dist/services/hooks.js +1 -1
- package/dist/services/ids.js +106 -0
- package/dist/services/lanes.js +333 -1
- package/dist/services/merge-queue.js +106 -16
- package/dist/services/merge-worker.js +67 -4
- package/dist/services/migrations.js +231 -0
- package/dist/services/project-summary.js +122 -0
- package/dist/services/projects.js +44 -3
- package/dist/services/protocol-lifecycle.js +144 -0
- package/dist/services/protocols.js +660 -7
- package/dist/services/runs.js +98 -21
- package/dist/services/schema-validation.js +84 -4
- package/dist/services/sessions.js +21 -4
- package/dist/services/status.js +199 -1
- package/dist/services/version-status.js +59 -9
- package/dist/storage/database.js +31 -0
- package/dist/storage/paths.js +33 -0
- package/package.json +3 -2
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { defaultFlowContract, flowContractForState, normalizeStage } from "../domain/flow-contract.js";
|
|
2
|
+
export function normalizeProtocolLifecycle(input) {
|
|
3
|
+
const source = input.state ? "runtime_state" : input.rawStage || input.rawStatus ? "protocol_record" : "missing";
|
|
4
|
+
const contract = input.flowContract ?? (input.state ? flowContractForState(input.state) : defaultFlowContract);
|
|
5
|
+
const rawStage = nonEmpty(input.state?.stage) ?? nonEmpty(input.rawStage) ?? "unregistered";
|
|
6
|
+
const rawStatus = nonEmpty(input.state?.status) ?? nonEmpty(input.rawStatus) ?? "unknown";
|
|
7
|
+
const normalizedRawStage = safeNormalizeStage(rawStage, contract);
|
|
8
|
+
const diagnostics = [];
|
|
9
|
+
const mapped = mapLegacyLifecycle(normalizedRawStage, rawStatus, input.queueStatus ?? null, contract);
|
|
10
|
+
if (normalizedRawStage !== rawStage) {
|
|
11
|
+
diagnostics.push({
|
|
12
|
+
code: "lifecycle_legacy_alias_normalized",
|
|
13
|
+
severity: "info",
|
|
14
|
+
raw_stage: rawStage,
|
|
15
|
+
normalized_stage: normalizedRawStage
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
if (mapped.stage === "unknown") {
|
|
19
|
+
diagnostics.push({
|
|
20
|
+
code: "lifecycle_stage_unknown",
|
|
21
|
+
severity: "warning",
|
|
22
|
+
raw_stage: rawStage,
|
|
23
|
+
raw_status: rawStatus
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
if (["blocked", "waiting_for_user"].includes(normalizedRawStage) && !mapped.status_reason) {
|
|
27
|
+
diagnostics.push({
|
|
28
|
+
code: "lifecycle_return_stage_missing",
|
|
29
|
+
severity: "warning",
|
|
30
|
+
raw_stage: rawStage,
|
|
31
|
+
summary: `${normalizedRawStage} is a status-like legacy stage without explicit return_to_stage metadata.`
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
flow: nonEmpty(input.flow) ?? "mb_sdlc",
|
|
36
|
+
stage: mapped.stage,
|
|
37
|
+
substage: mapped.substage,
|
|
38
|
+
status: mapped.status,
|
|
39
|
+
status_reason: mapped.status_reason,
|
|
40
|
+
terminal: mapped.terminal,
|
|
41
|
+
legacy_stage: mapped.legacy_stage,
|
|
42
|
+
legacy_status: mapped.legacy_status,
|
|
43
|
+
raw_stage: rawStage,
|
|
44
|
+
raw_status: rawStatus,
|
|
45
|
+
queue_status: input.queueStatus ?? null,
|
|
46
|
+
source,
|
|
47
|
+
diagnostics
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export function lifecycleIsTerminalSuccess(lifecycle) {
|
|
51
|
+
return lifecycle.terminal && lifecycle.status === "done";
|
|
52
|
+
}
|
|
53
|
+
export function lifecycleIsTerminalFailure(lifecycle) {
|
|
54
|
+
return lifecycle.terminal && ["cancelled", "failed"].includes(lifecycle.status);
|
|
55
|
+
}
|
|
56
|
+
export function lifecycleLegacyStage(lifecycle) {
|
|
57
|
+
return lifecycle.legacy_stage ?? lifecycle.raw_stage;
|
|
58
|
+
}
|
|
59
|
+
function mapLegacyLifecycle(stage, rawStatus, queueStatus, contract) {
|
|
60
|
+
if (stage === "registered") {
|
|
61
|
+
return mapped("protocol", null, "registered", "registered", rawStatus, false);
|
|
62
|
+
}
|
|
63
|
+
if (stage === "priming" || stage === "prime") {
|
|
64
|
+
return mapped("specify", "priming", statusFromRaw(rawStatus, "in_progress"), stage, rawStatus, false);
|
|
65
|
+
}
|
|
66
|
+
if (stage === "specify") {
|
|
67
|
+
return mapped("specify", null, statusFromRaw(rawStatus, "in_progress"), null, null, false);
|
|
68
|
+
}
|
|
69
|
+
if (stage === "plan") {
|
|
70
|
+
return mapped("plan", null, statusFromRaw(rawStatus, "in_progress"), null, null, false);
|
|
71
|
+
}
|
|
72
|
+
if (stage === "implementation") {
|
|
73
|
+
return mapped("code", "implementation", statusFromRaw(rawStatus, "in_progress"), "implementation", rawStatus, false);
|
|
74
|
+
}
|
|
75
|
+
if (stage === "readiness") {
|
|
76
|
+
return mapped("code", "readiness", rawStatus === "running" ? "readiness" : statusFromRaw(rawStatus, "readiness"), "readiness", rawStatus, false);
|
|
77
|
+
}
|
|
78
|
+
if (stage === "ready_for_merge") {
|
|
79
|
+
const status = queueStatus && ["ready", "requeued"].includes(queueStatus) ? "ready_for_merge" : "ready_for_merge";
|
|
80
|
+
return mapped("code", null, status, "ready_for_merge", rawStatus, false);
|
|
81
|
+
}
|
|
82
|
+
if (stage === "queued_for_merge") {
|
|
83
|
+
return mapped("merge", null, queueStatus === "claimed" ? "claimed" : "queued", "queued_for_merge", rawStatus, false);
|
|
84
|
+
}
|
|
85
|
+
if (stage === "integration") {
|
|
86
|
+
return mapped("merge", "integration", queueStatus === "claimed" ? "in_progress" : statusFromRaw(rawStatus, "in_progress"), "integration", rawStatus, false);
|
|
87
|
+
}
|
|
88
|
+
if (stage === "blocked") {
|
|
89
|
+
return mapped("unknown", null, "blocked", "blocked", rawStatus, false);
|
|
90
|
+
}
|
|
91
|
+
if (stage === "waiting_for_user") {
|
|
92
|
+
return mapped("unknown", null, "waiting_for_user", "waiting_for_user", rawStatus, false);
|
|
93
|
+
}
|
|
94
|
+
if (stage === "closed") {
|
|
95
|
+
return mapped("closed", null, "done", "closed", rawStatus, true);
|
|
96
|
+
}
|
|
97
|
+
if (stage === "cancelled") {
|
|
98
|
+
return mapped("closed", null, "cancelled", "cancelled", rawStatus, true);
|
|
99
|
+
}
|
|
100
|
+
if (contract.stages[stage]?.terminal) {
|
|
101
|
+
return mapped(stage, null, statusFromRaw(rawStatus, "done"), stage, rawStatus, true);
|
|
102
|
+
}
|
|
103
|
+
if (contract.stages[stage]) {
|
|
104
|
+
return mapped(stage, null, statusFromRaw(rawStatus, "in_progress"), null, null, false);
|
|
105
|
+
}
|
|
106
|
+
return mapped("unknown", null, statusFromRaw(rawStatus, "unknown"), stage, rawStatus, false);
|
|
107
|
+
}
|
|
108
|
+
function mapped(stage, substage, status, legacyStage, legacyStatus, terminal) {
|
|
109
|
+
return {
|
|
110
|
+
stage,
|
|
111
|
+
substage,
|
|
112
|
+
status,
|
|
113
|
+
status_reason: null,
|
|
114
|
+
terminal,
|
|
115
|
+
legacy_stage: legacyStage,
|
|
116
|
+
legacy_status: legacyStatus
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function statusFromRaw(rawStatus, fallback) {
|
|
120
|
+
if (rawStatus === "running")
|
|
121
|
+
return fallback;
|
|
122
|
+
if (rawStatus === "closed")
|
|
123
|
+
return "done";
|
|
124
|
+
if (rawStatus === "registered")
|
|
125
|
+
return "registered";
|
|
126
|
+
if (rawStatus === "waiting_user")
|
|
127
|
+
return "waiting_for_user";
|
|
128
|
+
if (rawStatus === "active")
|
|
129
|
+
return "in_progress";
|
|
130
|
+
if (rawStatus === "unknown")
|
|
131
|
+
return fallback;
|
|
132
|
+
return rawStatus || fallback;
|
|
133
|
+
}
|
|
134
|
+
function safeNormalizeStage(stage, contract) {
|
|
135
|
+
try {
|
|
136
|
+
return normalizeStage(stage, contract);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return stage;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function nonEmpty(value) {
|
|
143
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
144
|
+
}
|