@deksden-com/dd-flow-cli 0.4.2 → 0.5.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/CHANGELOG.md +27 -4
- package/dist/build-info.json +6 -6
- package/dist/cli/help.js +14 -3
- package/dist/cli/run-cli.js +32 -16
- package/dist/domain/flow-contract.js +81 -2
- package/dist/domain/validation.js +56 -28
- package/dist/protocol/local-files.js +1 -16
- package/dist/schemas/code-stage-report.schema.json +2 -2
- package/dist/schemas/flow-contract.schema.json +150 -94
- package/dist/schemas/flow-run.schema.json +129 -23
- package/dist/schemas/mb-upgrade-review-data.schema.json +2 -2
- package/dist/schemas/memorybank-permissions-preflight.schema.json +13 -73
- package/dist/schemas/merge-stage-report.schema.json +2 -2
- package/dist/schemas/plan-stage-report.schema.json +38 -335
- package/dist/schemas/project-flow-pack-manifest.schema.json +4 -4
- package/dist/schemas/protocol-plan.schema.json +197 -0
- package/dist/schemas/release-impact.schema.json +9 -5
- package/dist/schemas/session-usage.schema.json +16 -0
- package/dist/schemas/stage-finish-input.schema.json +20 -0
- package/dist/schemas/stage-prompt.schema.json +31 -0
- package/dist/schemas/stage-report.schema.json +20 -0
- package/dist/schemas/stage-start-response.schema.json +29 -0
- package/dist/schemas/timeline-event.schema.json +29 -0
- package/dist/schemas/worktrunk-workspace.schema.json +19 -0
- package/dist/services/branch-context.js +9 -4
- package/dist/services/dashboard.js +51 -26
- package/dist/services/engines.js +84 -18
- package/dist/services/hooks.js +80 -246
- package/dist/services/memory-permissions.js +77 -69
- package/dist/services/plan-runtime.js +124 -0
- package/dist/services/plans.js +22 -84
- package/dist/services/projects.js +2 -1
- package/dist/services/prompts.js +26 -21
- package/dist/services/protocols.js +29 -25
- package/dist/services/run-projection.js +77 -11
- package/dist/services/runs.js +95 -61
- package/dist/services/schema-validation.js +168 -7
- package/dist/services/sessions.js +132 -68
- package/dist/services/stage-lifecycle.js +572 -0
- package/dist/services/tooling.js +285 -0
- package/dist/services/usage.js +183 -30
- package/dist/services/version-status.js +1 -1
- package/dist/services/worktrees.js +88 -39
- package/dist/storage/database.js +72 -30
- package/dist/storage/paths.js +0 -9
- package/package.json +14 -13
- package/tools/worktrunk-manifest.json +34 -0
- package/dist/schemas/flow-run-index-v3.schema.json +0 -203
- package/dist/schemas/flow-run-index.schema.json +0 -175
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "dd-flow/protocol-plan@1",
|
|
4
|
+
"title": "Canonical semantic protocol plan",
|
|
5
|
+
"description": "The repository-owned semantic plan. Runtime progress, workers, timestamps and mechanical evidence do not belong here.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["$schema", "schema_id", "plan_id", "protocol_id", "revision", "title", "summary", "specifications", "protocol_reference", "goal", "task_assessment", "route_decision", "policy_context", "sdlc_contours", "items", "verification", "code_handoff"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"$schema": {"type": "string", "minLength": 1},
|
|
11
|
+
"schema_id": {"const": "dd-flow/protocol-plan@1"},
|
|
12
|
+
"plan_id": {"type": "string", "pattern": "^PLAN-[A-Za-z0-9][A-Za-z0-9._-]*$"},
|
|
13
|
+
"protocol_id": {"type": "string", "pattern": "^PRT-[A-Za-z0-9][A-Za-z0-9._-]*$"},
|
|
14
|
+
"revision": {"type": "integer", "minimum": 1},
|
|
15
|
+
"title": {"type": "string", "minLength": 1},
|
|
16
|
+
"summary": {"type": "string", "minLength": 1},
|
|
17
|
+
"specifications": {
|
|
18
|
+
"type": "array", "minItems": 1, "uniqueItems": true,
|
|
19
|
+
"items": {
|
|
20
|
+
"type": "object", "additionalProperties": false,
|
|
21
|
+
"required": ["id", "version", "path", "sha256", "requirements"],
|
|
22
|
+
"properties": {
|
|
23
|
+
"id": {"type": "string", "pattern": "^SPC-[0-9]{3}$"},
|
|
24
|
+
"version": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"},
|
|
25
|
+
"path": {"type": "string", "pattern": "^\\.memory-bank/"},
|
|
26
|
+
"sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$"},
|
|
27
|
+
"requirements": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "string", "pattern": "^R-[0-9]+$"}}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"protocol_reference": {
|
|
32
|
+
"type": "object", "additionalProperties": false, "required": ["path", "sha256"],
|
|
33
|
+
"properties": {
|
|
34
|
+
"path": {"type": "string", "pattern": "^\\.memory-bank/protocol/"},
|
|
35
|
+
"sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$"}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"goal": {
|
|
39
|
+
"type": "object", "additionalProperties": false, "required": ["outcome", "constraints", "non_goals"],
|
|
40
|
+
"properties": {
|
|
41
|
+
"outcome": {"type": "string", "minLength": 1},
|
|
42
|
+
"constraints": {"type": "array", "items": {"type": "string", "minLength": 1}},
|
|
43
|
+
"non_goals": {"type": "array", "items": {"type": "string", "minLength": 1}}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"task_assessment": {"$ref": "#/definitions/taskAssessment"},
|
|
47
|
+
"route_decision": {
|
|
48
|
+
"type": "object", "additionalProperties": false,
|
|
49
|
+
"required": ["initial_state", "selected_route", "selected_execution_mode", "reason", "capacity_probe", "packing"],
|
|
50
|
+
"properties": {
|
|
51
|
+
"initial_state": {"const": "orchestrator_local"},
|
|
52
|
+
"selected_route": {"enum": ["local_compact", "single_wave_grouped", "multi_wave_grouped", "external_handoff"]},
|
|
53
|
+
"selected_execution_mode": {"type": "string", "minLength": 1},
|
|
54
|
+
"reason": {"type": "string", "minLength": 1},
|
|
55
|
+
"capacity_probe": {"type": "string", "minLength": 1},
|
|
56
|
+
"packing": {"type": "string", "minLength": 1}
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"policy_context": {
|
|
60
|
+
"type": "object", "additionalProperties": false,
|
|
61
|
+
"required": ["target_language", "source_authority", "current_truth_boundary", "validation", "lint"],
|
|
62
|
+
"properties": {
|
|
63
|
+
"target_language": {"type": "string", "minLength": 1},
|
|
64
|
+
"source_authority": {"type": "string", "minLength": 1},
|
|
65
|
+
"current_truth_boundary": {"type": "string", "minLength": 1},
|
|
66
|
+
"validation": {"type": "string", "minLength": 1},
|
|
67
|
+
"lint": {"type": "string", "minLength": 1}
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"sdlc_contours": {
|
|
71
|
+
"type": "object", "additionalProperties": false, "required": ["summary", "contours"],
|
|
72
|
+
"properties": {
|
|
73
|
+
"summary": {"type": "string", "minLength": 1},
|
|
74
|
+
"contours": {
|
|
75
|
+
"type": "array", "minItems": 1,
|
|
76
|
+
"items": {
|
|
77
|
+
"type": "object", "additionalProperties": false,
|
|
78
|
+
"required": ["name", "applicability_status", "gate_status", "target_stage", "summary"],
|
|
79
|
+
"properties": {
|
|
80
|
+
"name": {"type": "string", "minLength": 1},
|
|
81
|
+
"applicability_status": {"enum": ["applicable", "external", "not_applicable"]},
|
|
82
|
+
"gate_status": {"enum": ["required", "deferred", "not_applicable"]},
|
|
83
|
+
"target_stage": {"enum": ["specify", "plan", "code", "readiness", "merge", "release"]},
|
|
84
|
+
"summary": {"type": "string", "minLength": 1}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"items": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"$ref": "#/definitions/planItem"}},
|
|
91
|
+
"verification": {
|
|
92
|
+
"type": "object", "additionalProperties": false, "required": ["scenario_seeds", "commands", "acceptance"],
|
|
93
|
+
"properties": {
|
|
94
|
+
"scenario_seeds": {"type": "array", "minItems": 1, "items": {"type": "string", "minLength": 1}},
|
|
95
|
+
"commands": {"type": "array", "minItems": 1, "items": {"type": "string", "minLength": 1}},
|
|
96
|
+
"acceptance": {"type": "string", "minLength": 1}
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"code_handoff": {
|
|
100
|
+
"type": "object", "additionalProperties": false,
|
|
101
|
+
"required": ["must_read", "accepted_plan_ref", "companion_handoffs", "next_stage", "known_external_gate"],
|
|
102
|
+
"properties": {
|
|
103
|
+
"must_read": {"type": "array", "minItems": 1, "items": {"type": "string", "minLength": 1}},
|
|
104
|
+
"accepted_plan_ref": {
|
|
105
|
+
"type": "object", "additionalProperties": false, "required": ["path", "revision", "sha256"],
|
|
106
|
+
"properties": {
|
|
107
|
+
"path": {"type": "string", "pattern": "^\\.memory-bank/protocol/[^/]+/plan\\.json$"},
|
|
108
|
+
"revision": {"type": "integer", "minimum": 1},
|
|
109
|
+
"sha256": {"enum": ["computed_by_stage_finish"]}
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"companion_handoffs": {
|
|
113
|
+
"type": "array",
|
|
114
|
+
"items": {
|
|
115
|
+
"type": "object", "additionalProperties": false, "required": ["protocol_id", "repository", "scope"],
|
|
116
|
+
"properties": {
|
|
117
|
+
"protocol_id": {"type": "string", "pattern": "^PRT-[A-Za-z0-9][A-Za-z0-9._-]*$"},
|
|
118
|
+
"repository": {"type": "string", "minLength": 1},
|
|
119
|
+
"scope": {"type": "string", "minLength": 1}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
"next_stage": {"enum": ["code", "readiness", "merge", "release"]},
|
|
124
|
+
"known_external_gate": {"type": "string", "minLength": 1}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
"definitions": {
|
|
129
|
+
"semanticSpine": {
|
|
130
|
+
"type": "object", "additionalProperties": false,
|
|
131
|
+
"required": ["user_outcome", "component_responsibility", "must_preserve", "non_goals", "acceptance_contribution"],
|
|
132
|
+
"properties": {
|
|
133
|
+
"user_outcome": {"type": "string", "minLength": 1},
|
|
134
|
+
"component_responsibility": {"type": "string", "minLength": 1},
|
|
135
|
+
"must_preserve": {"type": "array", "minItems": 1, "items": {"type": "string", "minLength": 1}},
|
|
136
|
+
"non_goals": {"type": "array", "items": {"type": "string", "minLength": 1}},
|
|
137
|
+
"acceptance_contribution": {"type": "string", "minLength": 1}
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
"executionContext": {
|
|
141
|
+
"type": "object", "additionalProperties": false,
|
|
142
|
+
"required": ["prompt_profile", "required_read", "discovery_boundary", "write_scope", "checks"],
|
|
143
|
+
"properties": {
|
|
144
|
+
"prompt_profile": {"enum": ["documentation_contract", "code_implementation", "verification"]},
|
|
145
|
+
"required_read": {"type": "array", "minItems": 1, "items": {"type": "string", "minLength": 1}},
|
|
146
|
+
"discovery_boundary": {"type": "array", "minItems": 1, "items": {"type": "string", "minLength": 1}},
|
|
147
|
+
"write_scope": {"type": "array", "minItems": 1, "items": {"type": "string", "minLength": 1}},
|
|
148
|
+
"checks": {"type": "array", "minItems": 1, "items": {"type": "string", "minLength": 1}}
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
"verificationContract": {
|
|
152
|
+
"type": "object", "additionalProperties": false, "required": ["checks", "evidence"],
|
|
153
|
+
"properties": {
|
|
154
|
+
"checks": {"type": "array", "minItems": 1, "items": {"type": "string", "minLength": 1}},
|
|
155
|
+
"evidence": {"type": "array", "minItems": 1, "items": {"type": "string", "minLength": 1}}
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"planItem": {
|
|
159
|
+
"type": "object", "additionalProperties": false,
|
|
160
|
+
"required": ["id", "kind", "title", "summary", "depends_on", "owner", "target_stage", "required", "requirements", "semantic_spine", "execution_context", "verification_contract"],
|
|
161
|
+
"properties": {
|
|
162
|
+
"id": {"type": "string", "pattern": "^P[0-9]+$"},
|
|
163
|
+
"kind": {"type": "string", "minLength": 1},
|
|
164
|
+
"title": {"type": "string", "minLength": 1},
|
|
165
|
+
"summary": {"type": "string", "minLength": 1},
|
|
166
|
+
"details": {"type": "string", "minLength": 1},
|
|
167
|
+
"depends_on": {"type": "array", "uniqueItems": true, "items": {"type": "string", "pattern": "^P[0-9]+$"}},
|
|
168
|
+
"owner": {"type": "string", "minLength": 1},
|
|
169
|
+
"target_stage": {"enum": ["specify", "plan", "code", "readiness", "merge", "release"]},
|
|
170
|
+
"required": {"type": "boolean"},
|
|
171
|
+
"requirements": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "string", "pattern": "^SPC-[0-9]{3}@[0-9]+\\.[0-9]+\\.[0-9]+/R-[0-9]+$"}},
|
|
172
|
+
"semantic_spine": {"$ref": "#/definitions/semanticSpine"},
|
|
173
|
+
"execution_context": {"$ref": "#/definitions/executionContext"},
|
|
174
|
+
"verification_contract": {"$ref": "#/definitions/verificationContract"}
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
"taskAssessment": {
|
|
178
|
+
"type": "object", "additionalProperties": false,
|
|
179
|
+
"required": ["scope_breadth", "solution_novelty", "solution_uncertainty", "failure_impact", "plan_floor"],
|
|
180
|
+
"properties": {
|
|
181
|
+
"scope_breadth": {"$ref": "#/definitions/assessmentAxis"},
|
|
182
|
+
"solution_novelty": {"$ref": "#/definitions/assessmentAxis"},
|
|
183
|
+
"solution_uncertainty": {"$ref": "#/definitions/assessmentAxis"},
|
|
184
|
+
"failure_impact": {"$ref": "#/definitions/assessmentAxis"},
|
|
185
|
+
"plan_floor": {"$ref": "#/definitions/assessmentAxis"}
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
"assessmentAxis": {
|
|
189
|
+
"type": "object", "additionalProperties": false, "required": ["level", "surfaces", "reason"],
|
|
190
|
+
"properties": {
|
|
191
|
+
"level": {"type": "string", "minLength": 1},
|
|
192
|
+
"surfaces": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "string", "minLength": 1}},
|
|
193
|
+
"reason": {"type": "string", "minLength": 1}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -7,10 +7,14 @@
|
|
|
7
7
|
"required": ["schema_id", "from_version", "to_version", "minimum_upgrade_mode", "domains", "path_migration", "runtime_migration", "required_checks"],
|
|
8
8
|
"properties": {
|
|
9
9
|
"schema_id": {"const": "dd-flow/release-impact@1"},
|
|
10
|
-
"from_version": {"type": "string"
|
|
10
|
+
"from_version": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"},
|
|
11
|
+
"to_version": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"},
|
|
11
12
|
"minimum_upgrade_mode": {"enum": ["patch", "targeted_minor", "full_migration"]},
|
|
12
|
-
"domains": {"type": "array", "items": {"
|
|
13
|
-
"path_migration": {"type": "boolean"},
|
|
14
|
-
"
|
|
15
|
-
|
|
13
|
+
"domains": {"type": "array", "items": {"enum": ["canonical_layer", "root_structure", "product", "system", "engineering", "operations", "adr", "plans", "scenarios", "ui", "guides", "protocol_evidence", "skills", "archive", "code_traceability"]}, "uniqueItems": true},
|
|
14
|
+
"path_migration": {"type": "boolean"},
|
|
15
|
+
"runtime_migration": {"type": "boolean"},
|
|
16
|
+
"required_checks": {"type": "array", "items": {"type": "string"}, "minItems": 1},
|
|
17
|
+
"notes": {"type": "string"}
|
|
18
|
+
},
|
|
19
|
+
"allOf": [{"if": {"properties": {"minimum_upgrade_mode": {"const": "patch"}}}, "then": {"properties": {"path_migration": {"const": false}, "runtime_migration": {"const": false}}}}]
|
|
16
20
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "dd-flow/session-usage@1",
|
|
4
|
+
"title": "Session and usage coverage",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["schema_id", "session_coverage", "usage_coverage", "sessions", "usage"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"schema_id": {"const": "dd-flow/session-usage@1"},
|
|
10
|
+
"session_coverage": {"$ref": "#/definitions/coverage"},
|
|
11
|
+
"usage_coverage": {"$ref": "#/definitions/coverage"},
|
|
12
|
+
"sessions": {"type": "array", "items": {"type": "object", "required": ["session_id", "kind", "status"], "properties": {"session_id": {"type": "string"}, "kind": {"type": "string"}, "status": {"type": "string"}}, "additionalProperties": true}},
|
|
13
|
+
"usage": {"type": "object", "required": ["input_tokens", "cache_read_input_tokens", "cache_write_input_tokens", "output_tokens", "reasoning_output_tokens"], "properties": {"input_tokens": {"type": ["integer", "null"]}, "cache_read_input_tokens": {"type": ["integer", "null"]}, "cache_write_input_tokens": {"type": ["integer", "null"]}, "output_tokens": {"type": ["integer", "null"]}, "reasoning_output_tokens": {"type": ["integer", "null"]}}, "additionalProperties": true}
|
|
14
|
+
},
|
|
15
|
+
"definitions": {"coverage": {"type": "object", "required": ["status", "expected", "observed", "missing_sessions"], "properties": {"status": {"enum": ["complete", "partial", "unavailable"]}, "expected": {"type": "array"}, "observed": {"type": "array"}, "missing_sessions": {"type": "array"}}, "additionalProperties": true}}
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "dd-flow/stage-finish-input@1",
|
|
4
|
+
"title": "Semantic stage finish input",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["schema_id", "status", "result", "acceptance", "changed_files", "checks", "evidence", "next_action"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"schema_id": {"const": "dd-flow/stage-finish-input@1"},
|
|
10
|
+
"status": {"enum": ["done", "blocked", "failed"]},
|
|
11
|
+
"result": {"type": "string", "minLength": 1},
|
|
12
|
+
"acceptance": {"type": "array", "items": {"type": "string", "minLength": 1}},
|
|
13
|
+
"changed_files": {"type": "array", "items": {"type": "string", "minLength": 1}},
|
|
14
|
+
"checks": {"type": "array", "items": {"type": "string", "minLength": 1}},
|
|
15
|
+
"evidence": {"type": "array", "items": {"type": "string", "minLength": 1}},
|
|
16
|
+
"reviewer_findings": {"type": "array", "items": {"type": "string"}},
|
|
17
|
+
"def_outcomes": {"type": "array", "items": {"type": "string"}},
|
|
18
|
+
"next_action": {"type": "string", "minLength": 1}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "dd-flow/stage-prompt@1",
|
|
4
|
+
"title": "Generated stage prompt",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"if": {"properties": {"stage": {"const": "plan"}}, "required": ["stage"]},
|
|
10
|
+
"then": {
|
|
11
|
+
"properties": {
|
|
12
|
+
"aliases": {
|
|
13
|
+
"required": ["plan", "aspect-map"]
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"required": ["schema_id", "run_id", "stage", "generated_at", "prompt_path", "sections", "aliases", "write_boundary", "source_fragments"],
|
|
20
|
+
"properties": {
|
|
21
|
+
"schema_id": {"const": "dd-flow/stage-prompt@1"},
|
|
22
|
+
"run_id": {"type": "string", "minLength": 1},
|
|
23
|
+
"stage": {"type": "string", "minLength": 1},
|
|
24
|
+
"generated_at": {"type": "string", "format": "date-time"},
|
|
25
|
+
"prompt_path": {"type": "string", "minLength": 1},
|
|
26
|
+
"sections": {"type": "array", "minItems": 7, "maxItems": 7, "items": {"enum": ["stage_identity", "runtime_context", "intake", "applicable_instructions", "stage_cli", "file_boundaries", "completion_contract"]}},
|
|
27
|
+
"aliases": {"type": "object", "required": ["project", "workspace", "run", "stage", "protocol", "intake"], "additionalProperties": {"type": "string"}},
|
|
28
|
+
"write_boundary": {"type": "object", "required": ["current", "archive", "archive_writable"], "properties": {"current": {"const": "@stage"}, "archive": {"pattern": "try-[0-9]{3}"}, "archive_writable": {"const": false}}, "additionalProperties": false},
|
|
29
|
+
"source_fragments": {"type": "array", "items": {"type": "string", "minLength": 1}}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "dd-flow/stage-report@1",
|
|
4
|
+
"title": "Generated stage report",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["schema_id", "run_id", "stage", "generated_at", "verdict", "semantic", "mechanical", "artifacts", "validation"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"schema_id": {"const": "dd-flow/stage-report@1"},
|
|
10
|
+
"run_id": {"type": "string", "minLength": 1},
|
|
11
|
+
"stage": {"type": "string", "minLength": 1},
|
|
12
|
+
"generated_at": {"type": "string", "format": "date-time"},
|
|
13
|
+
"verdict": {"enum": ["done", "blocked", "failed", "degraded"]},
|
|
14
|
+
"semantic": {"type": "object", "required": ["result", "acceptance", "changed_files", "checks", "evidence", "next_action"], "additionalProperties": true, "properties": {"result": {"type": "string"}, "acceptance": {"type": "array"}, "changed_files": {"type": "array"}, "checks": {"type": "array"}, "evidence": {"type": "array"}, "next_action": {"type": "string"}}},
|
|
15
|
+
"mechanical": {"type": "object", "required": ["started_at", "finished_at", "wall_clock_ms", "git", "session_coverage", "usage_coverage"], "additionalProperties": true, "properties": {"started_at": {"type": "string", "format": "date-time"}, "finished_at": {"type": "string", "format": "date-time"}, "wall_clock_ms": {"type": "integer", "minimum": 0}, "git": {"type": "object"}, "session_coverage": {"type": "object"}, "usage_coverage": {"type": "object"}}},
|
|
16
|
+
"artifacts": {"type": "object", "required": ["json", "markdown", "html", "summary"], "additionalProperties": false, "properties": {"json": {"type": "string"}, "markdown": {"type": "string"}, "html": {"type": "string"}, "summary": {"type": "string"}}},
|
|
17
|
+
"validation": {"type": "object", "required": ["permission_scope", "memory_bank_scope", "status"], "additionalProperties": true, "properties": {"permission_scope": {"const": "known_targets_only"}, "memory_bank_scope": {"const": "changed_files_and_links_only"}, "status": {"type": "string"}}},
|
|
18
|
+
"breadcrumbs": {"type": "array", "items": {"type": "object"}}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "dd-flow/stage-start-response@1",
|
|
4
|
+
"title": "Stage start response",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"if": {"properties": {"stage": {"const": "plan"}}, "required": ["stage"]},
|
|
10
|
+
"then": {"required": ["plan_ref", "aspect_map_ref"]}
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"required": ["schema_id", "run_id", "stage", "attempt_number", "stage_root", "prompt_path", "aliases", "next_command"],
|
|
14
|
+
"properties": {
|
|
15
|
+
"schema_id": {"const": "dd-flow/stage-start-response@1"},
|
|
16
|
+
"run_id": {"type": "string", "minLength": 1},
|
|
17
|
+
"stage": {"type": "string", "minLength": 1},
|
|
18
|
+
"attempt_number": {"type": "integer", "minimum": 1},
|
|
19
|
+
"stage_root": {"type": "string", "minLength": 1},
|
|
20
|
+
"archive_path": {"type": ["string", "null"]},
|
|
21
|
+
"prompt_path": {"type": "string", "minLength": 1},
|
|
22
|
+
"aliases": {"type": "object", "additionalProperties": {"type": "string"}},
|
|
23
|
+
"resolved_context": {"type": "object", "additionalProperties": true},
|
|
24
|
+
"plan_ref": {"type": "string", "pattern": "^\\.memory-bank/protocol/[^/]+/plan\\.json$"},
|
|
25
|
+
"aspect_map_ref": {"type": "string", "minLength": 1},
|
|
26
|
+
"next_command": {"const": "dd-flow stage finish"},
|
|
27
|
+
"permission_probe": {"type": "object", "additionalProperties": true}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "dd-flow/timeline-event@1",
|
|
4
|
+
"title": "Safe RUN timeline event",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["schema_id", "timestamp", "event", "run_id", "payload"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"schema_id": {"const": "dd-flow/timeline-event@1"},
|
|
10
|
+
"timestamp": {"type": "string", "format": "date-time"},
|
|
11
|
+
"event": {"type": "string", "minLength": 1},
|
|
12
|
+
"run_id": {"type": "string", "minLength": 1},
|
|
13
|
+
"stage": {"type": ["string", "null"]},
|
|
14
|
+
"attempt_number": {"type": ["integer", "null"], "minimum": 1},
|
|
15
|
+
"session_id": {"type": ["string", "null"]},
|
|
16
|
+
"job_id": {"type": ["string", "null"]},
|
|
17
|
+
"status": {"type": ["string", "null"]},
|
|
18
|
+
"payload": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"additionalProperties": false,
|
|
21
|
+
"properties": {
|
|
22
|
+
"reason": {"type": "string"},
|
|
23
|
+
"source": {"type": "string"},
|
|
24
|
+
"count": {"type": "integer", "minimum": 0},
|
|
25
|
+
"redaction": {"const": "safe-structured-only"}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "dd-flow/worktrunk-workspace@1",
|
|
4
|
+
"title": "Verified Worktrunk workspace result",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["schema_id", "command", "official_pinned_artifact", "workspace_path", "branch", "base", "tool_version", "bootstrap_status"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"schema_id": {"const": "dd-flow/worktrunk-workspace@1"},
|
|
10
|
+
"command": {"const": "wt switch --create <branch> --base <base> --format json"},
|
|
11
|
+
"official_pinned_artifact": {"type": "object", "required": ["url", "version", "sha256", "verified"], "properties": {"url": {"type": "string"}, "version": {"type": "string"}, "sha256": {"pattern": "^[a-f0-9]{64}$"}, "verified": {"const": true}}, "additionalProperties": false},
|
|
12
|
+
"workspace_path": {"type": "string", "minLength": 1},
|
|
13
|
+
"branch": {"type": "string", "minLength": 1},
|
|
14
|
+
"base": {"type": "string", "minLength": 1},
|
|
15
|
+
"tool_version": {"type": "string", "minLength": 1},
|
|
16
|
+
"bootstrap_status": {"type": "string", "minLength": 1},
|
|
17
|
+
"hooks": {"type": "array", "items": {"type": "string"}}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -136,7 +136,7 @@ function summarizeProtocol(row, queue, worktree, activeSessions) {
|
|
|
136
136
|
const worktreePath = normalizePath(stringValue(worktree?.worktree_path) ?? stringValue(workspace.worktree_path));
|
|
137
137
|
const activeDef = parseJsonArray(row.active_def_json);
|
|
138
138
|
const queueStatus = queue?.status ?? null;
|
|
139
|
-
const bundleBlockers = bundleBlockersFor(row.stage, queueStatus, activeDef.
|
|
139
|
+
const bundleBlockers = bundleBlockersFor(row.stage, queueStatus, activeDef.some(isBlockingDeferral));
|
|
140
140
|
return {
|
|
141
141
|
id: row.id,
|
|
142
142
|
stage: row.stage,
|
|
@@ -148,7 +148,7 @@ function summarizeProtocol(row, queue, worktree, activeSessions) {
|
|
|
148
148
|
integration_branch: stringValue(worktree?.integration_branch) ?? stringValue(workspace.integration_branch),
|
|
149
149
|
feature_branch: featureBranch,
|
|
150
150
|
worktree_path: worktreePath,
|
|
151
|
-
bundle_eligible: ["ready_for_merge", "queued_for_merge"].includes(row.stage) && ["ready", "requeued"].includes(queueStatus ?? "") && activeDef.
|
|
151
|
+
bundle_eligible: ["ready_for_merge", "queued_for_merge"].includes(row.stage) && ["ready", "requeued"].includes(queueStatus ?? "") && !activeDef.some(isBlockingDeferral),
|
|
152
152
|
bundle_blockers: bundleBlockers,
|
|
153
153
|
updated_at: row.updated_at
|
|
154
154
|
};
|
|
@@ -192,9 +192,9 @@ function branchDiagnostics(resolved) {
|
|
|
192
192
|
}
|
|
193
193
|
return diagnostics;
|
|
194
194
|
}
|
|
195
|
-
function bundleBlockersFor(stage, queueStatus,
|
|
195
|
+
function bundleBlockersFor(stage, queueStatus, hasBlockingDef) {
|
|
196
196
|
const blockers = [];
|
|
197
|
-
if (
|
|
197
|
+
if (hasBlockingDef)
|
|
198
198
|
blockers.push("active_def");
|
|
199
199
|
if (stage === "blocked")
|
|
200
200
|
blockers.push("protocol_blocked");
|
|
@@ -202,6 +202,11 @@ function bundleBlockersFor(stage, queueStatus, activeDefCount) {
|
|
|
202
202
|
blockers.push("already_claimed");
|
|
203
203
|
return blockers;
|
|
204
204
|
}
|
|
205
|
+
function isBlockingDeferral(value) {
|
|
206
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
207
|
+
return true;
|
|
208
|
+
return value.blocking !== false;
|
|
209
|
+
}
|
|
205
210
|
function bundleReason(eligible, notReady, claimed, blocked, diagnostics) {
|
|
206
211
|
if (diagnostics.length > 0)
|
|
207
212
|
return diagnostics[0] ?? "diagnostic_blocker";
|
|
@@ -12,6 +12,7 @@ import { protocolRunDiagnostics, protocolSetBoardForProtocol, protocolSetBoardsF
|
|
|
12
12
|
import { activeFlowSessionsForProject } from "./sessions.js";
|
|
13
13
|
import { usageForRun } from "./usage.js";
|
|
14
14
|
import { normalizeProtocolLifecycle } from "./protocol-lifecycle.js";
|
|
15
|
+
import { planSummary, planWithProgress } from "./plan-runtime.js";
|
|
15
16
|
export function getCmuxStatus(context, input) {
|
|
16
17
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
17
18
|
return { ok: true, project_root: project.root, cmux: detectCmux(context) };
|
|
@@ -626,14 +627,20 @@ function buildProtocolDashboardData(context, project, protocolId, htmlPath) {
|
|
|
626
627
|
const runs = context.db.all(`SELECT id, short_id, flow_kind, subject_type, subject_id, status, verdict, next_action, run_index_path, index_json, created_at, updated_at, completed_at
|
|
627
628
|
FROM flow_runs WHERE project_id = ? AND subject_type = 'protocol' AND subject_id = ?
|
|
628
629
|
ORDER BY updated_at DESC, id DESC`, [project.id, protocolId]);
|
|
629
|
-
const
|
|
630
|
+
const warnings = [...runDiagnostics.diagnostics];
|
|
631
|
+
const canonicalRuns = runs.filter((run) => {
|
|
632
|
+
if (isCanonicalRun(run))
|
|
633
|
+
return true;
|
|
634
|
+
warnings.push({ code: "legacy_run_ignored", run_id: run.id });
|
|
635
|
+
return false;
|
|
636
|
+
});
|
|
637
|
+
const primaryRun = lifecycle.terminal ? canonicalRuns[0] : canonicalRuns.find((run) => run.status === "running") ?? canonicalRuns[0];
|
|
630
638
|
const observability = primaryRun
|
|
631
639
|
? usageForRun(context, { projectId: project.id, runId: primaryRun.id, groupBy: "role" })
|
|
632
640
|
: { status: "not_observable", reason: "no_protocol_run" };
|
|
633
|
-
const warnings = [...runDiagnostics.diagnostics];
|
|
634
641
|
const protocolSetBoard = protocolSetBoardForProtocol(context, project.id, project.root, protocolId);
|
|
635
642
|
const reviewRuns = recentReviewRunsForProtocol(context, project.id, protocolId, 8);
|
|
636
|
-
const runHistory =
|
|
643
|
+
const runHistory = canonicalRuns.map((run) => {
|
|
637
644
|
const index = safeRunIndex(run.index_json, warnings, run.id);
|
|
638
645
|
return {
|
|
639
646
|
id: run.id,
|
|
@@ -707,10 +714,10 @@ function buildProtocolDashboardData(context, project, protocolId, htmlPath) {
|
|
|
707
714
|
run_history: runHistory,
|
|
708
715
|
stage_pipeline: latestStages(runHistory),
|
|
709
716
|
metrics: [
|
|
710
|
-
metric("runs",
|
|
717
|
+
metric("runs", canonicalRuns.length, "known", "flow_runs"),
|
|
711
718
|
metric("open_defs", jsonArray(protocol.active_def_json).length, "known", "protocols.active_def_json"),
|
|
712
719
|
metric("blockers", jsonArray(protocol.blockers_json).length, "known", "protocols.blockers_json"),
|
|
713
|
-
metric("completed_runs",
|
|
720
|
+
metric("completed_runs", canonicalRuns.filter((run) => run.status === "done").length, "known", "flow_runs"),
|
|
714
721
|
metric("review_runs", reviewRuns.length, "known", "flow_runs.flow_kind=mb-sdlc-review|review")
|
|
715
722
|
],
|
|
716
723
|
warnings
|
|
@@ -881,34 +888,39 @@ function protocolsForProject(context, projectId) {
|
|
|
881
888
|
FROM protocols WHERE project_id = ? ORDER BY updated_at DESC`, [projectId]);
|
|
882
889
|
}
|
|
883
890
|
function planSummaryForProtocol(context, projectId, protocolId) {
|
|
884
|
-
const
|
|
885
|
-
if (!
|
|
891
|
+
const protocol = context.db.get("SELECT plan_path FROM protocols WHERE project_id = ? AND id = ?", [projectId, protocolId]);
|
|
892
|
+
if (!protocol) {
|
|
886
893
|
return { plan_id: "none", total: 0, done: 0, blocked: 0 };
|
|
887
894
|
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
};
|
|
895
|
+
try {
|
|
896
|
+
const summary = planSummary(context, { projectId, protocolId, planPath: protocol.plan_path });
|
|
897
|
+
return { plan_id: summary.plan_id, total: summary.total, done: summary.done, blocked: summary.blocked };
|
|
898
|
+
}
|
|
899
|
+
catch {
|
|
900
|
+
return { plan_id: "stale", total: 0, done: 0, blocked: 0 };
|
|
901
|
+
}
|
|
896
902
|
}
|
|
897
903
|
function activePlanItems(context, projectId, protocols) {
|
|
898
904
|
const items = [];
|
|
899
905
|
for (const protocol of protocols) {
|
|
900
|
-
const
|
|
901
|
-
if (!
|
|
906
|
+
const record = context.db.get("SELECT plan_path FROM protocols WHERE project_id = ? AND id = ?", [projectId, protocol.id]);
|
|
907
|
+
if (!record) {
|
|
902
908
|
continue;
|
|
903
909
|
}
|
|
904
|
-
|
|
905
|
-
|
|
910
|
+
let plan;
|
|
911
|
+
try {
|
|
912
|
+
plan = planWithProgress(context, { projectId, protocolId: protocol.id, planPath: record.plan_path }).plan;
|
|
913
|
+
}
|
|
914
|
+
catch {
|
|
915
|
+
continue;
|
|
916
|
+
}
|
|
917
|
+
for (const item of plan.items) {
|
|
906
918
|
if (["in_progress", "blocked"].includes(item.status ?? "")) {
|
|
907
919
|
items.push({
|
|
908
920
|
protocol: protocol.id,
|
|
909
|
-
id: item.id
|
|
910
|
-
status: item.status
|
|
911
|
-
summary: item.block_reason ?? item.summary ?? item.title
|
|
921
|
+
id: item.id,
|
|
922
|
+
status: item.status,
|
|
923
|
+
summary: item.block_reason ?? item.summary ?? item.title
|
|
912
924
|
});
|
|
913
925
|
}
|
|
914
926
|
}
|
|
@@ -1040,9 +1052,10 @@ function buildProtocolCard(context, project, protocol, generatePage) {
|
|
|
1040
1052
|
const summary = planSummaryForProtocol(context, project.id, protocol.id);
|
|
1041
1053
|
const activeDefCount = jsonArray(protocol.active_def_json).length;
|
|
1042
1054
|
const blockerCount = jsonArray(protocol.blockers_json).length;
|
|
1043
|
-
const
|
|
1055
|
+
const runs = context.db.all(`SELECT id, short_id, flow_kind, subject_type, subject_id, status, verdict, next_action, run_index_path, index_json, created_at, updated_at, completed_at
|
|
1044
1056
|
FROM flow_runs WHERE project_id = ? AND subject_type = 'protocol' AND subject_id = ?
|
|
1045
|
-
ORDER BY updated_at DESC, id DESC
|
|
1057
|
+
ORDER BY updated_at DESC, id DESC`, [project.id, protocol.id]);
|
|
1058
|
+
const latestRun = runs.find((run) => isCanonicalRun(run));
|
|
1046
1059
|
let diagnostics = [];
|
|
1047
1060
|
let lifecycle = normalizeProtocolLifecycle({ rawStage: protocol.stage, rawStatus: protocol.status });
|
|
1048
1061
|
try {
|
|
@@ -1242,10 +1255,19 @@ function safeRunIndex(text, warnings, runId) {
|
|
|
1242
1255
|
return null;
|
|
1243
1256
|
}
|
|
1244
1257
|
}
|
|
1258
|
+
function isCanonicalRun(run) {
|
|
1259
|
+
try {
|
|
1260
|
+
const parsed = JSON.parse(run.index_json);
|
|
1261
|
+
return parsed?.schema_id === "dd-flow/flow-run@2";
|
|
1262
|
+
}
|
|
1263
|
+
catch {
|
|
1264
|
+
return false;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1245
1267
|
function stageLink(projectRoot, run, stage) {
|
|
1246
1268
|
const item = stage && typeof stage === "object" && !Array.isArray(stage) ? stage : {};
|
|
1247
1269
|
const report = typeof item.stage_report === "string" ? item.stage_report : undefined;
|
|
1248
|
-
const href = report ?
|
|
1270
|
+
const href = report ? runArtifactPath(run.run_index_path, report) : "";
|
|
1249
1271
|
return {
|
|
1250
1272
|
order: typeof item.order === "number" ? item.order : 0,
|
|
1251
1273
|
stage: String(item.stage ?? "unknown"),
|
|
@@ -1253,10 +1275,13 @@ function stageLink(projectRoot, run, stage) {
|
|
|
1253
1275
|
status: String(item.status ?? "unknown"),
|
|
1254
1276
|
display_status: normalizeDisplayStatus(String(item.status ?? "unknown")),
|
|
1255
1277
|
report: report ? link("Stage report", href, fs.existsSync(href) ? "available" : "missing", fs.existsSync(href) ? undefined : "stage_report_missing") : link("Stage report", "", "pending", "stage_report_not_created_yet"),
|
|
1256
|
-
data: typeof item.data === "string" ?
|
|
1278
|
+
data: typeof item.data === "string" ? runArtifactPath(run.run_index_path, item.data) : null,
|
|
1257
1279
|
run_index: path.relative(projectRoot, run.run_index_path)
|
|
1258
1280
|
};
|
|
1259
1281
|
}
|
|
1282
|
+
function runArtifactPath(runIndexPath, artifact) {
|
|
1283
|
+
return path.isAbsolute(artifact) ? artifact : path.resolve(path.dirname(runIndexPath), artifact);
|
|
1284
|
+
}
|
|
1260
1285
|
function latestStages(runHistory) {
|
|
1261
1286
|
const byStage = new Map();
|
|
1262
1287
|
for (const run of runHistory) {
|