@deksden-com/dd-flow-cli 0.3.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +74 -5
  3. package/dist/build-info.json +5 -5
  4. package/dist/cli/help.js +103 -15
  5. package/dist/cli/run-cli.js +307 -27
  6. package/dist/schemas/compatibility.schema.json +81 -2
  7. package/dist/schemas/engine-manifest.schema.json +61 -0
  8. package/dist/schemas/flow-guidance.schema.json +17 -0
  9. package/dist/schemas/global-dashboard-data.schema.json +60 -2
  10. package/dist/schemas/mb-upgrade-migration-report.schema.json +93 -0
  11. package/dist/schemas/project-dashboard-data.schema.json +26 -2
  12. package/dist/schemas/project-summary.schema.json +73 -0
  13. package/dist/schemas/protocol-dashboard-data.schema.json +25 -2
  14. package/dist/schemas/status-report.schema.json +4 -2
  15. package/dist/services/cleanup.js +31 -0
  16. package/dist/services/cli-operation-classifier.js +104 -0
  17. package/dist/services/compatibility-preflight.js +124 -0
  18. package/dist/services/config.js +6 -0
  19. package/dist/services/dashboard-targets.js +95 -0
  20. package/dist/services/dashboard.js +376 -59
  21. package/dist/services/engines.js +532 -0
  22. package/dist/services/flow-guidance.js +8 -1
  23. package/dist/services/hooks.js +1 -1
  24. package/dist/services/lanes.js +333 -1
  25. package/dist/services/merge-queue.js +97 -15
  26. package/dist/services/merge-worker.js +36 -2
  27. package/dist/services/migrations.js +231 -0
  28. package/dist/services/project-summary.js +122 -0
  29. package/dist/services/projects.js +41 -6
  30. package/dist/services/protocol-lifecycle.js +144 -0
  31. package/dist/services/protocols.js +29 -7
  32. package/dist/services/sessions.js +21 -4
  33. package/dist/services/status.js +10 -0
  34. package/dist/services/version-status.js +39 -15
  35. package/dist/storage/database.js +25 -0
  36. package/dist/storage/paths.js +12 -0
  37. package/package.json +3 -2
@@ -4,7 +4,18 @@
4
4
  "title": "dd-flow global dashboard data",
5
5
  "type": "object",
6
6
  "additionalProperties": true,
7
- "required": ["schema_id", "generated_at", "target_language", "page", "metrics", "project_cards", "warnings"],
7
+ "required": [
8
+ "schema_id",
9
+ "generated_at",
10
+ "target_language",
11
+ "page",
12
+ "metrics",
13
+ "supported_summary_versions",
14
+ "summary_version_groups",
15
+ "unsupported_projects",
16
+ "project_cards",
17
+ "warnings"
18
+ ],
8
19
  "properties": {
9
20
  "schema_id": { "const": "dd-flow/global-dashboard-data@1" },
10
21
  "generated_at": { "type": "string", "format": "date-time" },
@@ -12,6 +23,9 @@
12
23
  "page": { "$ref": "#/definitions/page" },
13
24
  "links": { "type": "object", "additionalProperties": { "$ref": "#/definitions/link" } },
14
25
  "metrics": { "type": "array", "items": { "$ref": "#/definitions/metric" } },
26
+ "supported_summary_versions": { "type": "array", "items": { "$ref": "#/definitions/summaryVersion" } },
27
+ "summary_version_groups": { "type": "array", "items": { "$ref": "#/definitions/summaryVersionGroup" } },
28
+ "unsupported_projects": { "type": "array", "items": { "$ref": "#/definitions/unsupportedProject" } },
15
29
  "project_cards": { "type": "array", "items": { "$ref": "#/definitions/card" } },
16
30
  "warnings": { "type": "array" }
17
31
  },
@@ -55,14 +69,58 @@
55
69
  "card": {
56
70
  "type": "object",
57
71
  "additionalProperties": true,
58
- "required": ["id", "title", "display_status", "action_level", "metrics"],
72
+ "required": ["id", "title", "display_status", "action_level", "lifecycle_summary", "resource_summary", "metrics"],
59
73
  "properties": {
60
74
  "id": { "type": "string", "minLength": 1 },
61
75
  "title": { "type": "string", "minLength": 1 },
62
76
  "display_status": { "type": "string", "minLength": 1 },
63
77
  "action_level": { "type": "string", "enum": ["none", "watch", "actionable", "blocked"] },
78
+ "lifecycle_summary": { "type": "object", "additionalProperties": true },
79
+ "resource_summary": { "type": "object", "additionalProperties": true },
64
80
  "metrics": { "type": "object" }
65
81
  }
82
+ },
83
+ "summaryVersion": {
84
+ "type": "object",
85
+ "additionalProperties": true,
86
+ "required": ["schema_id", "schema_version", "label", "status"],
87
+ "properties": {
88
+ "schema_id": { "type": "string", "minLength": 1 },
89
+ "schema_version": { "type": ["string", "null"] },
90
+ "label": { "type": "string", "minLength": 1 },
91
+ "status": { "type": "string", "minLength": 1 }
92
+ }
93
+ },
94
+ "summaryVersionGroup": {
95
+ "type": "object",
96
+ "additionalProperties": true,
97
+ "required": ["schema_id", "schema_version", "compatible", "count", "project_ids", "project_names"],
98
+ "properties": {
99
+ "schema_id": { "type": "string", "minLength": 1 },
100
+ "schema_version": { "type": "string", "minLength": 1 },
101
+ "compatible": { "type": "boolean" },
102
+ "count": { "type": "integer", "minimum": 0 },
103
+ "project_ids": { "type": "array", "items": { "type": "string" } },
104
+ "project_names": { "type": "array", "items": { "type": "string" } }
105
+ }
106
+ },
107
+ "unsupportedProject": {
108
+ "type": "object",
109
+ "additionalProperties": true,
110
+ "required": ["id", "title", "root", "status", "display_status", "reason", "summary_path"],
111
+ "properties": {
112
+ "id": { "type": "string", "minLength": 1 },
113
+ "title": { "type": "string", "minLength": 1 },
114
+ "root": { "type": "string", "minLength": 1 },
115
+ "status": { "type": "string", "minLength": 1 },
116
+ "display_status": { "const": "unsupported" },
117
+ "reason": { "type": "string", "minLength": 1 },
118
+ "detail": { "type": "string" },
119
+ "summary_schema_id": { "type": ["string", "null"] },
120
+ "summary_schema_version": { "type": ["string", "null"] },
121
+ "summary_path": { "type": "string", "minLength": 1 },
122
+ "install_hint": { "type": ["string", "null"] }
123
+ }
66
124
  }
67
125
  }
68
126
  }
@@ -0,0 +1,93 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "dd-flow/mb-upgrade-migration-report@1",
4
+ "title": "mb-upgrade runtime/home migration report",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": [
8
+ "ok",
9
+ "schema_id",
10
+ "generated_at",
11
+ "project",
12
+ "migration",
13
+ "backup",
14
+ "active_state",
15
+ "primary_data",
16
+ "derived_artifacts",
17
+ "verification"
18
+ ],
19
+ "properties": {
20
+ "ok": { "const": true },
21
+ "schema_id": { "const": "dd-flow/mb-upgrade-migration-report@1" },
22
+ "generated_at": { "type": "string", "minLength": 1 },
23
+ "project": {
24
+ "type": "object",
25
+ "required": ["id", "root", "memory_bank_version"],
26
+ "additionalProperties": true,
27
+ "properties": {
28
+ "id": { "type": "string", "minLength": 1 },
29
+ "root": { "type": "string", "minLength": 1 },
30
+ "memory_bank_version": { "type": ["string", "null"] }
31
+ }
32
+ },
33
+ "migration": {
34
+ "type": "object",
35
+ "required": [
36
+ "mode",
37
+ "status",
38
+ "source_memory_bank_version",
39
+ "target_memory_bank_version",
40
+ "adjacent_only",
41
+ "chain",
42
+ "blocked_reasons"
43
+ ],
44
+ "additionalProperties": true,
45
+ "properties": {
46
+ "mode": { "const": "mb-upgrade-only" },
47
+ "status": { "enum": ["ready", "blocked", "noop", "completed", "failed", "degraded"] },
48
+ "source_memory_bank_version": { "type": "string", "minLength": 1 },
49
+ "target_memory_bank_version": { "type": "string", "minLength": 1 },
50
+ "adjacent_only": { "const": true },
51
+ "chain": {
52
+ "type": "array",
53
+ "items": {
54
+ "type": "object",
55
+ "required": ["id", "from", "to", "status"],
56
+ "additionalProperties": true,
57
+ "properties": {
58
+ "id": { "type": "string", "minLength": 1 },
59
+ "from": { "type": "string", "minLength": 1 },
60
+ "to": { "type": "string", "minLength": 1 },
61
+ "status": { "enum": ["planned", "applied", "skipped", "failed", "blocked"] }
62
+ }
63
+ }
64
+ },
65
+ "blocked_reasons": {
66
+ "type": "array",
67
+ "items": { "type": "string", "minLength": 1 }
68
+ }
69
+ }
70
+ },
71
+ "backup": {
72
+ "type": "object",
73
+ "required": ["status", "path", "created_at", "rollback_route"],
74
+ "additionalProperties": true,
75
+ "properties": {
76
+ "status": { "enum": ["present", "planned", "missing"] },
77
+ "path": { "type": ["string", "null"] },
78
+ "created_at": { "type": ["string", "null"] },
79
+ "rollback_route": { "type": "string", "minLength": 1 }
80
+ }
81
+ },
82
+ "active_state": { "type": "object", "additionalProperties": true },
83
+ "primary_data": {
84
+ "type": "array",
85
+ "items": { "type": "string", "minLength": 1 }
86
+ },
87
+ "derived_artifacts": {
88
+ "type": "array",
89
+ "items": { "type": "string", "minLength": 1 }
90
+ },
91
+ "verification": { "type": "object", "additionalProperties": true }
92
+ }
93
+ }
@@ -4,7 +4,7 @@
4
4
  "title": "dd-flow project dashboard data",
5
5
  "type": "object",
6
6
  "additionalProperties": true,
7
- "required": ["schema_id", "generated_at", "target_language", "page", "project", "metrics", "protocol_cards", "warnings"],
7
+ "required": ["schema_id", "generated_at", "target_language", "page", "project", "metrics", "lifecycle_summary", "resource_summary", "protocol_cards", "warnings"],
8
8
  "properties": {
9
9
  "schema_id": { "const": "dd-flow/project-dashboard-data@1" },
10
10
  "generated_at": { "type": "string", "format": "date-time" },
@@ -24,8 +24,11 @@
24
24
  },
25
25
  "links": { "type": "object", "additionalProperties": { "$ref": "#/definitions/link" } },
26
26
  "metrics": { "type": "array", "items": { "$ref": "#/definitions/metric" } },
27
+ "lifecycle_summary": { "type": "object", "additionalProperties": true },
28
+ "resource_summary": { "type": "object", "additionalProperties": true },
27
29
  "protocol_cards": { "type": "array", "items": { "$ref": "#/definitions/protocolCard" } },
28
30
  "review_runs": { "type": "array", "items": { "$ref": "#/definitions/reviewRun" } },
31
+ "queued_protocols": { "type": "array" },
29
32
  "merge_queue": { "type": "array" },
30
33
  "sessions": { "type": "array" },
31
34
  "locks": { "type": "array" },
@@ -71,16 +74,37 @@
71
74
  "protocolCard": {
72
75
  "type": "object",
73
76
  "additionalProperties": true,
74
- "required": ["id", "short_id", "display_status", "action_level", "current_stage", "href"],
77
+ "required": ["id", "short_id", "display_status", "action_level", "lifecycle", "current_stage", "href"],
75
78
  "properties": {
76
79
  "id": { "type": "string", "minLength": 1 },
77
80
  "short_id": { "type": "string", "minLength": 1 },
78
81
  "display_status": { "type": "string", "minLength": 1 },
79
82
  "action_level": { "type": "string", "enum": ["none", "watch", "actionable", "blocked"] },
83
+ "lifecycle": { "$ref": "#/definitions/lifecycle" },
84
+ "lifecycle_stage": { "type": "string" },
85
+ "lifecycle_status": { "type": "string" },
86
+ "resource": { "type": "object", "additionalProperties": true },
80
87
  "current_stage": { "type": "string", "minLength": 1 },
81
88
  "href": { "type": "string", "minLength": 1 }
82
89
  }
83
90
  },
91
+ "lifecycle": {
92
+ "type": "object",
93
+ "additionalProperties": true,
94
+ "required": ["flow", "stage", "status", "terminal", "raw_stage", "raw_status"],
95
+ "properties": {
96
+ "flow": { "type": "string", "minLength": 1 },
97
+ "stage": { "type": "string", "minLength": 1 },
98
+ "substage": { "type": ["string", "null"] },
99
+ "status": { "type": "string", "minLength": 1 },
100
+ "terminal": { "type": "boolean" },
101
+ "legacy_stage": { "type": ["string", "null"] },
102
+ "legacy_status": { "type": ["string", "null"] },
103
+ "raw_stage": { "type": "string", "minLength": 1 },
104
+ "raw_status": { "type": "string", "minLength": 1 },
105
+ "queue_status": { "type": ["string", "null"] }
106
+ }
107
+ },
84
108
  "reviewRun": {
85
109
  "type": "object",
86
110
  "additionalProperties": true,
@@ -0,0 +1,73 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "dd-flow/project-summary@1",
4
+ "title": "dd-flow project summary",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": [
8
+ "schema_id",
9
+ "schema_version",
10
+ "generated_at",
11
+ "project_id",
12
+ "name",
13
+ "root",
14
+ "root_exists",
15
+ "status",
16
+ "memorybank_version",
17
+ "cli_version",
18
+ "engine_version",
19
+ "summary_path",
20
+ "protocol_counts",
21
+ "active_protocols",
22
+ "waiting_items",
23
+ "resource_summary",
24
+ "warnings",
25
+ "last_activity_at"
26
+ ],
27
+ "properties": {
28
+ "schema_id": { "const": "dd-flow/project-summary@1" },
29
+ "schema_version": { "const": "1.0.0" },
30
+ "generated_at": { "type": "string", "minLength": 1 },
31
+ "project_id": { "type": "string", "minLength": 1 },
32
+ "name": { "type": "string", "minLength": 1 },
33
+ "root": { "type": "string", "minLength": 1 },
34
+ "root_exists": { "type": "boolean" },
35
+ "status": { "type": "string", "minLength": 1 },
36
+ "memorybank_version": { "type": ["string", "null"] },
37
+ "memorybank_status": { "type": "string" },
38
+ "flow_pack_status": { "type": "string" },
39
+ "required_engine_range": { "type": ["string", "null"] },
40
+ "cli_version": { "type": "string", "minLength": 1 },
41
+ "engine_version": { "type": ["string", "null"] },
42
+ "engine_status": { "type": "string" },
43
+ "summary_path": { "type": "string", "minLength": 1 },
44
+ "dashboard_path": { "type": "string" },
45
+ "protocol_counts": {
46
+ "type": "object",
47
+ "required": ["active", "waiting", "done", "total"],
48
+ "additionalProperties": true,
49
+ "properties": {
50
+ "active": { "type": "integer", "minimum": 0 },
51
+ "waiting": { "type": "integer", "minimum": 0 },
52
+ "done": { "type": "integer", "minimum": 0 },
53
+ "total": { "type": "integer", "minimum": 0 }
54
+ }
55
+ },
56
+ "active_protocols": { "type": "array" },
57
+ "waiting_items": { "type": "array" },
58
+ "resource_summary": {
59
+ "type": "object",
60
+ "required": ["queue", "locks", "waiters", "sessions", "open_defs"],
61
+ "additionalProperties": true,
62
+ "properties": {
63
+ "queue": { "type": "integer", "minimum": 0 },
64
+ "locks": { "type": "integer", "minimum": 0 },
65
+ "waiters": { "type": "integer", "minimum": 0 },
66
+ "sessions": { "type": "integer", "minimum": 0 },
67
+ "open_defs": { "type": "integer", "minimum": 0 }
68
+ }
69
+ },
70
+ "warnings": { "type": "array" },
71
+ "last_activity_at": { "type": "string", "minLength": 1 }
72
+ }
73
+ }
@@ -4,7 +4,7 @@
4
4
  "title": "dd-flow protocol dashboard data",
5
5
  "type": "object",
6
6
  "additionalProperties": true,
7
- "required": ["schema_id", "generated_at", "target_language", "page", "project", "protocol", "primary_run_id", "run_history", "stage_pipeline", "metrics", "warnings"],
7
+ "required": ["schema_id", "generated_at", "target_language", "page", "project", "protocol", "resource", "primary_run_id", "run_history", "stage_pipeline", "metrics", "warnings"],
8
8
  "properties": {
9
9
  "schema_id": { "const": "dd-flow/protocol-dashboard-data@1" },
10
10
  "generated_at": { "type": "string", "format": "date-time" },
@@ -14,17 +14,23 @@
14
14
  "protocol": {
15
15
  "type": "object",
16
16
  "additionalProperties": true,
17
- "required": ["id", "short_id", "raw_status", "raw_stage", "display_status", "action_level", "updated_at"],
17
+ "required": ["id", "short_id", "lifecycle", "raw_status", "raw_stage", "display_status", "action_level", "updated_at"],
18
18
  "properties": {
19
19
  "id": { "type": "string", "minLength": 1 },
20
20
  "short_id": { "type": "string", "minLength": 1 },
21
21
  "raw_status": { "type": "string", "minLength": 1 },
22
22
  "raw_stage": { "type": "string", "minLength": 1 },
23
+ "lifecycle": { "$ref": "#/definitions/lifecycle" },
24
+ "lifecycle_stage": { "type": "string" },
25
+ "lifecycle_status": { "type": "string" },
23
26
  "display_status": { "type": "string", "minLength": 1 },
24
27
  "action_level": { "type": "string", "enum": ["none", "watch", "actionable", "blocked"] },
25
28
  "updated_at": { "type": "string", "minLength": 1 }
26
29
  }
27
30
  },
31
+ "resource": { "type": "object", "additionalProperties": true },
32
+ "queue_item": { "type": ["object", "null"], "additionalProperties": true },
33
+ "claim": { "type": ["object", "null"], "additionalProperties": true },
28
34
  "links": { "type": "object", "additionalProperties": { "$ref": "#/definitions/link" } },
29
35
  "primary_run_id": { "type": ["string", "null"] },
30
36
  "primary_run_reason": { "type": "string" },
@@ -84,6 +90,23 @@
84
90
  "display_status": { "type": "string", "minLength": 1 },
85
91
  "stages": { "type": "array" }
86
92
  }
93
+ },
94
+ "lifecycle": {
95
+ "type": "object",
96
+ "additionalProperties": true,
97
+ "required": ["flow", "stage", "status", "terminal", "raw_stage", "raw_status"],
98
+ "properties": {
99
+ "flow": { "type": "string", "minLength": 1 },
100
+ "stage": { "type": "string", "minLength": 1 },
101
+ "substage": { "type": ["string", "null"] },
102
+ "status": { "type": "string", "minLength": 1 },
103
+ "terminal": { "type": "boolean" },
104
+ "legacy_stage": { "type": ["string", "null"] },
105
+ "legacy_status": { "type": ["string", "null"] },
106
+ "raw_stage": { "type": "string", "minLength": 1 },
107
+ "raw_status": { "type": "string", "minLength": 1 },
108
+ "queue_status": { "type": ["string", "null"] }
109
+ }
87
110
  }
88
111
  }
89
112
  }
@@ -135,13 +135,14 @@
135
135
  "flowPack": {
136
136
  "type": ["object", "null"],
137
137
  "additionalProperties": true,
138
- "required": ["manifest_path", "schema_id", "pack_version", "source_commit", "canon_version_at_source_commit", "status", "canonical_only_files"],
138
+ "required": ["manifest_path", "schema_id", "pack_version", "source_commit", "canon_version_at_source_commit", "flow_contract", "status", "canonical_only_files"],
139
139
  "properties": {
140
140
  "manifest_path": { "type": ["string", "null"] },
141
141
  "schema_id": { "type": ["string", "null"] },
142
142
  "pack_version": { "type": ["string", "null"] },
143
143
  "source_commit": { "type": ["string", "null"] },
144
144
  "canon_version_at_source_commit": { "type": ["string", "null"] },
145
+ "flow_contract": { "type": ["string", "null"] },
145
146
  "status": { "type": "string", "enum": ["present", "missing", "invalid", "degraded"] },
146
147
  "reason": { "type": "string" },
147
148
  "canonical_only_files": {
@@ -153,10 +154,11 @@
153
154
  "drift": {
154
155
  "type": ["object", "null"],
155
156
  "additionalProperties": true,
156
- "required": ["memory_bank_version", "flow_pack_commit", "overall", "next_action"],
157
+ "required": ["memory_bank_version", "flow_pack_commit", "flow_contract", "overall", "next_action"],
157
158
  "properties": {
158
159
  "memory_bank_version": { "$ref": "#/definitions/comparison" },
159
160
  "flow_pack_commit": { "$ref": "#/definitions/comparison" },
161
+ "flow_contract": { "$ref": "#/definitions/comparison" },
160
162
  "overall": {
161
163
  "type": "string",
162
164
  "enum": ["same", "behind", "ahead", "diverged", "missing", "invalid", "unknown", "not_applicable"]
@@ -13,6 +13,7 @@ const actionKinds = new Set([
13
13
  "cancel_queue_job",
14
14
  "close_flow_session",
15
15
  "expire_lane_lock",
16
+ "expire_lane_waiter",
16
17
  "close_worktree_record"
17
18
  ]);
18
19
  export function cleanupScan(context, input) {
@@ -98,6 +99,18 @@ export function cleanupScan(context, input) {
98
99
  action: { kind: "expire_lane_lock", project_id: project.id, lock_id: lock.id }
99
100
  });
100
101
  }
102
+ const expiredWaiters = context.db.all(`SELECT id, lane, worker_id, expires_at FROM lane_waiters
103
+ WHERE project_id = ? AND status = 'queued' AND expires_at IS NOT NULL AND expires_at <= ?
104
+ ORDER BY id ASC`, [project.id, now]);
105
+ for (const waiter of expiredWaiters) {
106
+ pushFinding(findings, actions, "expired_lane_waiter", "warning", {
107
+ waiter_id: waiter.id,
108
+ lane: waiter.lane,
109
+ worker_id: waiter.worker_id,
110
+ expires_at: waiter.expires_at,
111
+ action: { kind: "expire_lane_waiter", project_id: project.id, waiter_id: waiter.id }
112
+ });
113
+ }
101
114
  const staleWorktrees = context.db.all(`SELECT wr.protocol_id, wr.worktree_path FROM worktree_records wr
102
115
  JOIN protocols p ON p.id = wr.protocol_id
103
116
  WHERE wr.project_id = ?
@@ -285,6 +298,24 @@ function applyAction(context, action, reason, force, now) {
285
298
  lock_id: action.lock_id
286
299
  };
287
300
  }
301
+ if (action.kind === "expire_lane_waiter" && typeof action.waiter_id === "number") {
302
+ const result = context.db.run("UPDATE lane_waiters SET status = 'expired', reason = ?, updated_at = ? WHERE project_id = ? AND id = ? AND status = 'queued'", [reason, now, action.project_id, action.waiter_id]);
303
+ if (result.changes === 1) {
304
+ appendAudit(context, {
305
+ projectId: action.project_id,
306
+ eventType: "lane_waiter.expired",
307
+ reason,
308
+ forced: force,
309
+ payload: { waiter_id: action.waiter_id, source: "cleanup.apply" }
310
+ });
311
+ }
312
+ return {
313
+ kind: action.kind,
314
+ changed: result.changes === 1,
315
+ ...(result.changes === 1 ? {} : { skipped: true, reason: "already_inactive" }),
316
+ waiter_id: action.waiter_id
317
+ };
318
+ }
288
319
  if (action.kind === "close_worktree_record" && action.protocol_id) {
289
320
  const worktreePath = action.worktree_path ?? context.db.get("SELECT worktree_path FROM worktree_records WHERE project_id = ? AND protocol_id = ?", [action.project_id, action.protocol_id])?.worktree_path;
290
321
  const status = worktreePath && fs.existsSync(worktreePath) ? "kept" : "removed";
@@ -0,0 +1,104 @@
1
+ export function classifyCliOperation(args, env = process.env) {
2
+ const positional = positionalArgs(args);
3
+ const [family = null, command = null, action = null] = positional;
4
+ const operation = [family, command, action].filter(Boolean).join(".") || "help";
5
+ if (isMbUpgradeMode(args, env)) {
6
+ return { mode: "mb_upgrade", operation, family, command, action };
7
+ }
8
+ if (isRouterNative(args)) {
9
+ return { mode: "router_native", operation, family, command, action };
10
+ }
11
+ if (isReadOnlyDiagnostic(family, command, action)) {
12
+ return { mode: "read_only_diagnostics", operation, family, command, action };
13
+ }
14
+ return { mode: "normal_write", operation, family, command, action };
15
+ }
16
+ function positionalArgs(args) {
17
+ const positional = [];
18
+ for (let index = 0; index < args.length; index += 1) {
19
+ const value = args[index];
20
+ if (!value)
21
+ continue;
22
+ if (value.startsWith("--")) {
23
+ if (!value.includes("=") && args[index + 1] && !args[index + 1]?.startsWith("--"))
24
+ index += 1;
25
+ continue;
26
+ }
27
+ positional.push(value);
28
+ }
29
+ return positional;
30
+ }
31
+ export function isReadOnlyCliOperation(args, env = process.env) {
32
+ return classifyCliOperation(args, env).mode === "read_only_diagnostics";
33
+ }
34
+ export function isMbUpgradeCliOperation(args, env = process.env) {
35
+ return classifyCliOperation(args, env).mode === "mb_upgrade";
36
+ }
37
+ function isMbUpgradeMode(args, env) {
38
+ if (env.DD_FLOW_COMPATIBILITY_MODE === "mb-upgrade" || env.DD_FLOW_MB_UPGRADE_MODE === "1") {
39
+ return true;
40
+ }
41
+ for (let index = 0; index < args.length; index += 1) {
42
+ const arg = args[index];
43
+ if (arg === "--compatibility-mode" && args[index + 1] === "mb-upgrade")
44
+ return true;
45
+ if (arg === "--mb-upgrade-mode")
46
+ return true;
47
+ if (arg?.startsWith("--compatibility-mode="))
48
+ return arg.slice("--compatibility-mode=".length) === "mb-upgrade";
49
+ }
50
+ return false;
51
+ }
52
+ function isRouterNative(args) {
53
+ const first = args[0];
54
+ if (!first || first === "--version")
55
+ return true;
56
+ if (first === "--help" || first === "-h")
57
+ return true;
58
+ if (args.includes("--help") || args.includes("-h"))
59
+ return true;
60
+ return ["engine", "version", "schema"].includes(first);
61
+ }
62
+ function isReadOnlyDiagnostic(family, command, action) {
63
+ if (!family)
64
+ return true;
65
+ if (family === "status" || family === "version" || family === "id" || family === "integration")
66
+ return true;
67
+ if (family === "canon")
68
+ return command === "status" || command === "resolve";
69
+ if (family === "project")
70
+ return command === "status" || command === "resolve";
71
+ if (family === "protocol")
72
+ return ["status", "ready", "blockers", "implement"].includes(command ?? "");
73
+ if (family === "plan")
74
+ return command === "status";
75
+ if (family === "run")
76
+ return command === "status" || command === "list";
77
+ if (family === "lane") {
78
+ return (command === "status" ||
79
+ command === "waiters" ||
80
+ (command === "lock" && action === "status") ||
81
+ (command === "workspace" && action === "check"));
82
+ }
83
+ if (family === "merge")
84
+ return command === "status";
85
+ if (family === "merge-worker")
86
+ return command === "status";
87
+ if (family === "merge-queue")
88
+ return command === "status";
89
+ if (family === "migration")
90
+ return ["plan", "report", "verify"].includes(command ?? "");
91
+ if (family === "session")
92
+ return command === "status";
93
+ if (family === "dashboard")
94
+ return command === "data" || command === "open";
95
+ if (family === "memory")
96
+ return command === "permissions" && action === "preflight";
97
+ if (family === "codex" && command === "hooks")
98
+ return action === "print" || action === "status";
99
+ if (family === "codex" && command === "home")
100
+ return ["plan", "status", "print-env"].includes(action ?? "");
101
+ if (family === "worktree")
102
+ return command === "plan" || command === "status";
103
+ return false;
104
+ }