@smartmemory/compose 0.2.58-beta → 0.3.1-beta
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 +2 -2
- package/bin/compose.js +55 -54
- package/dist/assets/{App-s4CulNkO.js → App-DR9pCiNE.js} +290 -290
- package/dist/assets/{abnfDiagram-VRR7QNED-CDwzQ5wr.js → abnfDiagram-VRR7QNED-CZ6p2bRe.js} +1 -1
- package/dist/assets/{arc-kIU8DDth.js → arc-6j04LBqn.js} +1 -1
- package/dist/assets/{architectureDiagram-ZJ3FMSHR-CleorO_0.js → architectureDiagram-ZJ3FMSHR-00QM3pmc.js} +1 -1
- package/dist/assets/{blockDiagram-677ZJIJ3-NvEFfoMk.js → blockDiagram-677ZJIJ3-BUb9Kjfd.js} +1 -1
- package/dist/assets/{c4Diagram-LMCZKHZV-BcDQdTVB.js → c4Diagram-LMCZKHZV-D1PkhmSm.js} +1 -1
- package/dist/assets/channel-BcWZM2KA.js +1 -0
- package/dist/assets/{chunk-2Q5K7J3B-BseRkpm4.js → chunk-2Q5K7J3B-CduDdMf4.js} +1 -1
- package/dist/assets/{chunk-32BRIVSS-DCHhvgFV.js → chunk-32BRIVSS-CH8Kj5rh.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-DcTpMdJ4.js → chunk-5VM5RSS4-Cfts6Lix.js} +1 -1
- package/dist/assets/{chunk-EX3LRPZG-BdN8fvWs.js → chunk-EX3LRPZG-Dguk4yKZ.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-DmZJP-8E.js → chunk-JWPE2WC7-DbCJp6t9.js} +1 -1
- package/dist/assets/{chunk-MOJQB5TN-V74uYM17.js → chunk-MOJQB5TN-CNjM_9_U.js} +1 -1
- package/dist/assets/{chunk-RYQCIY6F-CoXUXbn_.js → chunk-RYQCIY6F-D4k-BUbh.js} +1 -1
- package/dist/assets/{chunk-V7JOEXUC-DUscIydR.js → chunk-V7JOEXUC-O1sFoHf1.js} +1 -1
- package/dist/assets/{chunk-VR4S4FIN-C4UDHq_a.js → chunk-VR4S4FIN-CGbSXVPL.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-DIH9i8mZ.js → chunk-XXDRQBXY-iIelV7SO.js} +1 -1
- package/dist/assets/classDiagram-OUVF2IWQ-Ce7YjlIK.js +1 -0
- package/dist/assets/classDiagram-v2-EOCWNBFH-Ce7YjlIK.js +1 -0
- package/dist/assets/{cose-bilkent-JH36ORCC-Dn6Gy6l1.js → cose-bilkent-JH36ORCC-BKmPLgw2.js} +1 -1
- package/dist/assets/{cynefin-VYW2F7L2-C2LW5fzB.js → cynefin-VYW2F7L2-CmT6ieC5.js} +1 -1
- package/dist/assets/{cynefinDiagram-TSTJHNR4-CGoAq7C9.js → cynefinDiagram-TSTJHNR4-Hn2vSVOw.js} +1 -1
- package/dist/assets/{dagre-VKFMJZFB-BaOKtuBE.js → dagre-VKFMJZFB-B0ifIwlU.js} +1 -1
- package/dist/assets/{diagram-FQU43EPY-BdQwqt4x.js → diagram-FQU43EPY-BuCDB-JG.js} +1 -1
- package/dist/assets/{diagram-G47NLZAW-Dkcf0o5z.js → diagram-G47NLZAW-D5avTZAQ.js} +1 -1
- package/dist/assets/{diagram-NH7WQ7WH-C_fDi59r.js → diagram-NH7WQ7WH-24QCIgpj.js} +1 -1
- package/dist/assets/{diagram-OA4YK3LP-jaTQcOxt.js → diagram-OA4YK3LP-A-bbUTK3.js} +1 -1
- package/dist/assets/{diagram-WEI45ONY-dEtqVj3s.js → diagram-WEI45ONY-BIMDm-Kj.js} +1 -1
- package/dist/assets/{ebnfDiagram-CCIWWBDH-s8ImqsSs.js → ebnfDiagram-CCIWWBDH-DCXMfG-M.js} +1 -1
- package/dist/assets/{erDiagram-Q63AITRT-5Zy29-SA.js → erDiagram-Q63AITRT-BlDrG0Ev.js} +1 -1
- package/dist/assets/{flowDiagram-23GEKE2U-DV74V9he.js → flowDiagram-23GEKE2U-aTyazY6P.js} +1 -1
- package/dist/assets/{ganttDiagram-NO4QXBWP-BND-CiLO.js → ganttDiagram-NO4QXBWP-Bxo-a80f.js} +1 -1
- package/dist/assets/{gitGraphDiagram-IHSO6WYX-B_-Mf9Jo.js → gitGraphDiagram-IHSO6WYX-COhKb9wR.js} +1 -1
- package/dist/assets/index-BcmsQZX-.js +119 -0
- package/dist/assets/{infoDiagram-FWYZ7A6U-Duyz8rZM.js → infoDiagram-FWYZ7A6U-DLCbpinV.js} +1 -1
- package/dist/assets/{ishikawaDiagram-FXEZZL3T-D2Qft0e5.js → ishikawaDiagram-FXEZZL3T-eyHF7GIj.js} +1 -1
- package/dist/assets/{journeyDiagram-5HDEW3XC-q6rG4Rig.js → journeyDiagram-5HDEW3XC-BsVocmlw.js} +1 -1
- package/dist/assets/{kanban-definition-HUTT4EX6-CsPX7gBL.js → kanban-definition-HUTT4EX6-CaFPSZxY.js} +1 -1
- package/dist/assets/{linear-CiccpAAd.js → linear-cqnI_wgW.js} +1 -1
- package/dist/assets/{mindmap-definition-LN4V7U3C-DRW2njpA.js → mindmap-definition-LN4V7U3C-B66BGqKn.js} +1 -1
- package/dist/assets/{pegDiagram-2B236MQR-DoDgm2S_.js → pegDiagram-2B236MQR-F6IN0_L5.js} +1 -1
- package/dist/assets/{pieDiagram-ENE6RG2P-CNSYLVAF.js → pieDiagram-ENE6RG2P-D5nOQxpo.js} +1 -1
- package/dist/assets/{quadrantDiagram-ABIIQ3AL-8-Nd6ony.js → quadrantDiagram-ABIIQ3AL-DwUAYbMO.js} +1 -1
- package/dist/assets/{railroadDiagram-RFXS5EU6-bfdg6Bo4.js → railroadDiagram-RFXS5EU6-Cvmlah5P.js} +1 -1
- package/dist/assets/{requirementDiagram-TGXJPOKE-slDkxCQy.js → requirementDiagram-TGXJPOKE-DoUtsFnL.js} +1 -1
- package/dist/assets/{sankeyDiagram-HTMAVEWB-CR3CboiK.js → sankeyDiagram-HTMAVEWB-D4XTwiKp.js} +1 -1
- package/dist/assets/{sequenceDiagram-DBY2YBRQ-BIXw1JS1.js → sequenceDiagram-DBY2YBRQ-CiG9yRIR.js} +1 -1
- package/dist/assets/{sizeCapture-X5ZJPWSS-BdKI7JyF.js → sizeCapture-X5ZJPWSS-zd7ydQ_Y.js} +1 -1
- package/dist/assets/{stateDiagram-2N3HPSRC-ktVgpBZS.js → stateDiagram-2N3HPSRC-BZesBHQ4.js} +1 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-BnlLOJzB.js +1 -0
- package/dist/assets/{swimlanes-5IMT3BWC-CaXpC3FM.js → swimlanes-5IMT3BWC-Bg8exSE7.js} +2 -2
- package/dist/assets/swimlanesDiagram-G3AALYLV-DZMVxqbs.js +8 -0
- package/dist/assets/{timeline-definition-FHXFAJF6-CKWSlRUl.js → timeline-definition-FHXFAJF6-TKj_HY9k.js} +1 -1
- package/dist/assets/{vennDiagram-L72KCM5P-CwOhxDyv.js → vennDiagram-L72KCM5P-CJf-bqn0.js} +1 -1
- package/dist/assets/{wardleyDiagram-EHGQE667-DGavMpEB.js → wardleyDiagram-EHGQE667-CqizSfCL.js} +1 -1
- package/dist/assets/{xychartDiagram-FW5EYKEG-CWmnmLZz.js → xychartDiagram-FW5EYKEG-CK-OErMM.js} +1 -1
- package/dist/index.html +1 -1
- package/lib/build-all.js +0 -5
- package/lib/build-stream-schema.js +1 -1
- package/lib/build.js +1762 -2614
- package/lib/consumer-fanout.js +1317 -0
- package/lib/feature-validator.js +6 -4
- package/lib/flow-state.js +15 -14
- package/lib/gsd-budget.js +48 -10
- package/lib/gsd-prompt.js +3 -4
- package/lib/gsd-stuck.js +1 -1
- package/lib/gsd.js +303 -149
- package/lib/local-claude-connector.js +149 -0
- package/lib/new.js +162 -307
- package/lib/result-normalizer.js +233 -18
- package/lib/review-lenses.js +1 -1
- package/lib/step-prompt.js +41 -119
- package/lib/stratum-engine.js +297 -0
- package/lib/stratum-mcp-client.js +224 -213
- package/lib/vocabulary-compliance.js +268 -0
- package/lib/vocabulary-inject.js +1 -36
- package/package.json +6 -2
- package/pipelines/build-quick.stratum.yaml +5 -17
- package/pipelines/build.profiles.json +11 -0
- package/pipelines/build.stratum.yaml +288 -467
- package/pipelines/gsd.stratum.yaml +73 -125
- package/pipelines/new.stratum.yaml +68 -149
- package/server/build-routes.js +4 -1
- package/server/design-routes.js +37 -21
- package/server/index.js +13 -21
- package/server/lifecycle-guard.js +1 -1
- package/server/pipeline-routes.js +113 -31
- package/server/stratum-client.js +33 -47
- package/server/stratum-sync.js +3 -4
- package/server/vision-server.js +1 -1
- package/dist/assets/channel-DiJkE9og.js +0 -1
- package/dist/assets/classDiagram-OUVF2IWQ-DS76VBEL.js +0 -1
- package/dist/assets/classDiagram-v2-EOCWNBFH-DS76VBEL.js +0 -1
- package/dist/assets/index-CBWbmG7W.js +0 -119
- package/dist/assets/stateDiagram-v2-6OUMAXLB-CzPQnlan.js +0 -1
- package/dist/assets/swimlanesDiagram-G3AALYLV-rIDv6EuQ.js +0 -8
- package/lib/connector-factory-shim.js +0 -167
- package/server/agent-mcp.js +0 -10
|
@@ -3,546 +3,367 @@
|
|
|
3
3
|
# label: "Feature Build"
|
|
4
4
|
# description: "Execute a feature through the full Compose lifecycle — design, plan, implement, review, test, ship"
|
|
5
5
|
# category: development
|
|
6
|
-
# steps:
|
|
6
|
+
# steps: 19
|
|
7
7
|
# estimated_minutes: 120
|
|
8
8
|
|
|
9
|
-
version:
|
|
10
|
-
|
|
11
|
-
workflow:
|
|
12
|
-
name: build
|
|
13
|
-
description: "Execute a feature through the full Compose lifecycle"
|
|
14
|
-
input:
|
|
15
|
-
featureCode:
|
|
16
|
-
type: string
|
|
17
|
-
required: true
|
|
18
|
-
description:
|
|
19
|
-
type: string
|
|
20
|
-
required: true
|
|
21
|
-
pre_merge_gate:
|
|
22
|
-
type: array
|
|
23
|
-
required: false # COMP-PAR-MERGE-QUEUE-CONSUMER-RETRY: default-OFF per-task gate (lint+build), omitted unless capabilities.preMergeGate
|
|
24
|
-
implementer_agent:
|
|
25
|
-
type: string
|
|
26
|
-
required: false # COMP-CODEX-IMPL: who writes the code (default claude; codex under --codex). Compose always supplies it.
|
|
27
|
-
reviewer_agent:
|
|
28
|
-
type: string
|
|
29
|
-
required: false # COMP-CODEX-IMPL: cross-model reviewer, always != implementer (default codex; claude under --codex).
|
|
9
|
+
version: 1
|
|
30
10
|
|
|
31
11
|
contracts:
|
|
32
12
|
PhaseResult:
|
|
33
|
-
phase:
|
|
34
|
-
artifact:
|
|
35
|
-
outcome:
|
|
36
|
-
summary:
|
|
13
|
+
phase: string
|
|
14
|
+
artifact: string
|
|
15
|
+
outcome: complete|skipped|failed
|
|
16
|
+
summary: string
|
|
17
|
+
plan_items: array?
|
|
18
|
+
files_changed: string[]?
|
|
19
|
+
commit_hash: string?
|
|
37
20
|
|
|
38
|
-
# Canonical review output — produced by both review_check (Codex) and parallel_review (Claude).
|
|
39
|
-
# Schema source: compose/contracts/review-result.json (_roadmap: STRAT-CLAUDE-EFFORT-PARITY)
|
|
40
21
|
ReviewResult:
|
|
41
|
-
clean:
|
|
42
|
-
summary:
|
|
43
|
-
findings:
|
|
44
|
-
meta:
|
|
45
|
-
lenses_run:
|
|
46
|
-
auto_fixes:
|
|
47
|
-
asks:
|
|
22
|
+
clean: boolean
|
|
23
|
+
summary: string
|
|
24
|
+
findings: array
|
|
25
|
+
meta: object
|
|
26
|
+
lenses_run: string[]
|
|
27
|
+
auto_fixes: array
|
|
28
|
+
asks: array
|
|
48
29
|
|
|
49
30
|
TestResult:
|
|
50
|
-
passing:
|
|
51
|
-
summary:
|
|
52
|
-
failures:
|
|
31
|
+
passing: boolean
|
|
32
|
+
summary: string
|
|
33
|
+
failures: string[]
|
|
53
34
|
|
|
54
35
|
TaskGraph:
|
|
55
|
-
tasks:
|
|
36
|
+
tasks: object[]
|
|
56
37
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
confidence_gate: {type: number}
|
|
62
|
-
exclusions: {type: string}
|
|
38
|
+
TaskResult:
|
|
39
|
+
outcome: string
|
|
40
|
+
summary: string
|
|
41
|
+
files_changed: string[]?
|
|
63
42
|
|
|
64
43
|
TriageResult:
|
|
65
|
-
tasks:
|
|
66
|
-
|
|
67
|
-
functions:
|
|
68
|
-
design_gate:
|
|
69
|
-
mode: gate
|
|
70
|
-
timeout: 3600
|
|
71
|
-
|
|
72
|
-
plan_gate:
|
|
73
|
-
mode: gate
|
|
74
|
-
timeout: 3600
|
|
75
|
-
|
|
76
|
-
ship_gate:
|
|
77
|
-
mode: gate
|
|
78
|
-
timeout: 1800
|
|
44
|
+
tasks: object[]
|
|
79
45
|
|
|
80
46
|
flows:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
#
|
|
84
|
-
# fires with a recovery_agent configured on the parent flow step.
|
|
47
|
+
entry: build
|
|
48
|
+
|
|
49
|
+
# Task-only subflow: cross-model implementation review.
|
|
85
50
|
review_check:
|
|
86
51
|
input:
|
|
87
|
-
task:
|
|
88
|
-
blueprint:
|
|
89
|
-
reviewer_agent:
|
|
90
|
-
output:
|
|
52
|
+
task: string
|
|
53
|
+
blueprint: string
|
|
54
|
+
reviewer_agent: string
|
|
55
|
+
output:
|
|
56
|
+
from: "${review.output}"
|
|
57
|
+
contract: ReviewResult
|
|
91
58
|
steps:
|
|
92
59
|
- id: review
|
|
93
|
-
agent: "$.input.reviewer_agent"
|
|
94
|
-
|
|
60
|
+
agent: "$.input.reviewer_agent"
|
|
61
|
+
do: >
|
|
95
62
|
Review the implementation against the blueprint and task.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
confidence_gate: "7"
|
|
101
|
-
output_contract: ReviewResult
|
|
63
|
+
Task: ${input.task}
|
|
64
|
+
Blueprint: ${input.blueprint}
|
|
65
|
+
Return the canonical ReviewResult shape.
|
|
66
|
+
out: ReviewResult
|
|
102
67
|
ensure:
|
|
103
|
-
- "result.clean ==
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
# --- Sub-flow: parallel_review ---
|
|
107
|
-
# Multi-lens review: triage selects lenses, parallel dispatch runs them,
|
|
108
|
-
# merge deduplicates and classifies findings. Falls back to review_check
|
|
109
|
-
# if parallel dispatch is unavailable.
|
|
110
|
-
parallel_review:
|
|
111
|
-
input:
|
|
112
|
-
task: {type: string}
|
|
113
|
-
blueprint: {type: string}
|
|
114
|
-
diff: {type: string}
|
|
115
|
-
prior_dirty_lenses: {type: array, optional: true}
|
|
116
|
-
output: ReviewResult
|
|
117
|
-
steps:
|
|
118
|
-
- id: triage
|
|
119
|
-
agent: "claude:orchestrator"
|
|
120
|
-
intent: >
|
|
121
|
-
Decide which review lenses to activate.
|
|
122
|
-
|
|
123
|
-
RETRY PATH — If the file .compose/prior_dirty_lenses.json exists, read it.
|
|
124
|
-
It contains a JSON array of lens IDs that had actionable findings in the prior
|
|
125
|
-
review run. In this case:
|
|
126
|
-
- Activate all lenses listed in that array.
|
|
127
|
-
- Always also include diff-quality and contract-compliance (baseline lenses —
|
|
128
|
-
they re-run on every retry to catch regressions introduced by the fix, even
|
|
129
|
-
if they passed clean last time).
|
|
130
|
-
- Skip all other lenses — they already passed clean.
|
|
131
|
-
|
|
132
|
-
FIRST RUN PATH — If .compose/prior_dirty_lenses.json does not exist:
|
|
133
|
-
- Always include diff-quality and contract-compliance.
|
|
134
|
-
- Add security if files touch auth, crypto, SQL, HTTP handlers.
|
|
135
|
-
- Add framework if detected framework files (React, Express, Next.js, etc).
|
|
136
|
-
|
|
137
|
-
Return JSON: { "tasks": LensTask[] } where each task has id, lens_name,
|
|
138
|
-
lens_focus, confidence_gate, exclusions.
|
|
139
|
-
inputs:
|
|
140
|
-
diff: "$.input.diff"
|
|
141
|
-
output_contract: TriageResult
|
|
68
|
+
- expr: "result.clean == true"
|
|
69
|
+
attempts: 5
|
|
142
70
|
|
|
143
|
-
|
|
144
|
-
type: parallel_dispatch
|
|
145
|
-
agent: "claude:read-only-reviewer"
|
|
146
|
-
source: "$.steps.triage.output.tasks"
|
|
147
|
-
max_concurrent: 4
|
|
148
|
-
isolation: none
|
|
149
|
-
output_contract: ReviewResult
|
|
150
|
-
intent_template: >
|
|
151
|
-
Lens: {lens_name}. Focus: {lens_focus}.
|
|
152
|
-
require: all
|
|
153
|
-
|
|
154
|
-
- id: merge
|
|
155
|
-
agent: "claude:orchestrator"
|
|
156
|
-
intent: >
|
|
157
|
-
Merge ReviewResult arrays from all lens runs into a single canonical ReviewResult.
|
|
158
|
-
The input contains the parallel dispatch aggregate with tasks[].result for each lens.
|
|
159
|
-
1. Concatenate all findings arrays from completed task results.
|
|
160
|
-
Deduplicate by file+line+lens: keep finding with highest confidence;
|
|
161
|
-
carry over its applied_gate.
|
|
162
|
-
2. Recompute clean: zero must-fix AND zero should-fix findings (post-dedupe, post-gate).
|
|
163
|
-
3. lenses_run = IDs of lenses that produced any must-fix or should-fix finding.
|
|
164
|
-
4. auto_fixes = mechanical fixes (formatting, typos, simple tests).
|
|
165
|
-
5. asks = findings requiring human judgment.
|
|
166
|
-
Return canonical ReviewResult with clean, summary, findings, lenses_run,
|
|
167
|
-
auto_fixes, asks, meta.
|
|
168
|
-
inputs:
|
|
169
|
-
results: "$.steps.review_lenses.output"
|
|
170
|
-
task: "$.input.task"
|
|
171
|
-
blueprint: "$.input.blueprint"
|
|
172
|
-
reduce_mode: "true"
|
|
173
|
-
output_contract: ReviewResult
|
|
174
|
-
depends_on: [review_lenses]
|
|
175
|
-
|
|
176
|
-
# --- Sub-flow: coverage ---
|
|
177
|
-
# Single-step: claude runs tests, stratum retries via ensure_failed.
|
|
178
|
-
# Cross-agent fix is dispatched by build.js on ensure_failed.
|
|
71
|
+
# Task-only subflow: test generation and coverage sweep.
|
|
179
72
|
coverage_check:
|
|
180
73
|
input:
|
|
181
|
-
task:
|
|
182
|
-
plan:
|
|
183
|
-
output:
|
|
74
|
+
task: string
|
|
75
|
+
plan: string
|
|
76
|
+
output:
|
|
77
|
+
from: "${run_tests.output}"
|
|
78
|
+
contract: TestResult
|
|
184
79
|
steps:
|
|
185
80
|
- id: run_tests
|
|
186
|
-
agent:
|
|
187
|
-
|
|
188
|
-
Run the project test suite.
|
|
189
|
-
{
|
|
190
|
-
|
|
191
|
-
task: "$.input.task"
|
|
192
|
-
output_contract: TestResult
|
|
81
|
+
agent: claude
|
|
82
|
+
do: >
|
|
83
|
+
Run the project test suite for ${input.task}, following plan ${input.plan}.
|
|
84
|
+
Return {passing, summary, failures}.
|
|
85
|
+
out: TestResult
|
|
193
86
|
ensure:
|
|
194
|
-
- "result.passing ==
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
# --- Sub-flow: test_review (COMP-TEST-BOOTSTRAP-4-1) ---
|
|
198
|
-
# Reviews the test files the coverage step generated this build. The
|
|
199
|
-
# implementation review (review/codex_review) runs BEFORE coverage, so
|
|
200
|
-
# generated tests are never otherwise reviewed. build.js injects the exact
|
|
201
|
-
# generated-test file list into this step's intent, and skips the step
|
|
202
|
-
# entirely (synthetic clean stepDone) when coverage produced no test files.
|
|
203
|
-
# ADVISORY: no blocking ensure — findings surface to the human, never fail ship.
|
|
204
|
-
test_review:
|
|
205
|
-
input:
|
|
206
|
-
task: {type: string}
|
|
207
|
-
blueprint: {type: string}
|
|
208
|
-
reviewer_agent: {type: string} # COMP-CODEX-IMPL: threaded from the parent build flow
|
|
209
|
-
output: ReviewResult
|
|
210
|
-
steps:
|
|
211
|
-
- id: review_generated_tests
|
|
212
|
-
agent: "$.input.reviewer_agent" # COMP-CODEX-IMPL: codex by default; claude when codex implements
|
|
213
|
-
intent: >
|
|
214
|
-
Review the auto-generated test files listed below (written by the coverage
|
|
215
|
-
step this build) and verify their assertions match intent. Read each file.
|
|
216
|
-
Flag tests that are placeholders (assert true / pass with no real assertion),
|
|
217
|
-
tautological, or assert only on mocks/stubs rather than exercising the
|
|
218
|
-
feature's behavior. For each weak test, cite file:line and state what real
|
|
219
|
-
assertion is missing. Do NOT flag hand-written tests or pure style. Output a
|
|
220
|
-
canonical ReviewResult.
|
|
221
|
-
inputs:
|
|
222
|
-
task: "$.input.task"
|
|
223
|
-
blueprint: "$.input.blueprint"
|
|
224
|
-
review_mode: "true"
|
|
225
|
-
confidence_gate: "7"
|
|
226
|
-
# ADVISORY (COMP-TEST-BOOTSTRAP-4-1): deliberately NO output_contract and NO
|
|
227
|
-
# ensure. A schema/postcondition failure here would trigger executeChildFlow's
|
|
228
|
-
# blocking fix-retry path and could block ship (report→docs→ship chain through
|
|
229
|
-
# test_review). Without either gate the step always completes; build.js captures
|
|
230
|
-
# whatever the reviewer returns and surfaces it via the test_review stream event.
|
|
231
|
-
|
|
232
|
-
# --- Main flow: compose feature lifecycle ---
|
|
87
|
+
- expr: "result.passing == true"
|
|
88
|
+
attempts: 15
|
|
89
|
+
|
|
233
90
|
build:
|
|
234
91
|
input:
|
|
235
|
-
featureCode:
|
|
236
|
-
description:
|
|
237
|
-
pre_merge_gate:
|
|
238
|
-
implementer_agent:
|
|
239
|
-
reviewer_agent:
|
|
240
|
-
output:
|
|
92
|
+
featureCode: string
|
|
93
|
+
description: string
|
|
94
|
+
pre_merge_gate: string[]?
|
|
95
|
+
implementer_agent: string
|
|
96
|
+
reviewer_agent: string
|
|
97
|
+
output:
|
|
98
|
+
from: "${ship.output}"
|
|
99
|
+
contract: PhaseResult
|
|
241
100
|
max_rounds: 10
|
|
242
101
|
steps:
|
|
243
|
-
# Phase: Explore & Design
|
|
244
102
|
- id: explore_design
|
|
245
103
|
agent: claude
|
|
246
|
-
|
|
247
|
-
Explore the codebase and write a design doc for
|
|
248
|
-
Launch 2-3 explorer subagents in parallel to map architecture,
|
|
249
|
-
|
|
250
|
-
Write
|
|
251
|
-
|
|
252
|
-
inputs:
|
|
253
|
-
featureCode: "$.input.featureCode"
|
|
254
|
-
description: "$.input.description"
|
|
255
|
-
output_contract: PhaseResult
|
|
104
|
+
do: >
|
|
105
|
+
Explore the codebase and write a design doc for ${input.featureCode}.
|
|
106
|
+
Launch 2-3 explorer subagents in parallel to map architecture, find similar
|
|
107
|
+
features, and analyze related implementations. Feature: ${input.description}.
|
|
108
|
+
Write docs/features/${input.featureCode}/design.md and return PhaseResult.
|
|
109
|
+
out: PhaseResult
|
|
256
110
|
ensure:
|
|
257
|
-
- "result.outcome == 'complete'"
|
|
258
|
-
- "file_exists(result.artifact)"
|
|
259
|
-
|
|
111
|
+
- expr: "result.outcome == 'complete'"
|
|
112
|
+
- expr: "file_exists(result.artifact)"
|
|
113
|
+
attempts: 2
|
|
260
114
|
|
|
261
|
-
# Gate: Design review
|
|
262
115
|
- id: design_gate
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
116
|
+
after: [explore_design]
|
|
117
|
+
gate:
|
|
118
|
+
on_approve: prd
|
|
119
|
+
on_revise: explore_design
|
|
120
|
+
on_kill: null
|
|
268
121
|
|
|
269
|
-
# Phase: PRD (skippable)
|
|
270
122
|
- id: prd
|
|
123
|
+
when: "false"
|
|
271
124
|
agent: claude
|
|
272
|
-
|
|
273
|
-
Write a product requirements document for
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
inputs:
|
|
277
|
-
featureCode: "$.input.featureCode"
|
|
278
|
-
description: "$.input.description"
|
|
279
|
-
output_contract: PhaseResult
|
|
125
|
+
do: >
|
|
126
|
+
Write a product requirements document for ${input.featureCode} at
|
|
127
|
+
docs/features/${input.featureCode}/prd.md. Return PhaseResult.
|
|
128
|
+
out: PhaseResult
|
|
280
129
|
ensure:
|
|
281
|
-
- "result.outcome == 'complete'"
|
|
282
|
-
- "file_exists(result.artifact)"
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
skip_reason: "PRD skipped by default — set skip_if to false to enable"
|
|
286
|
-
depends_on: [design_gate]
|
|
287
|
-
|
|
288
|
-
# Phase: Architecture (skippable)
|
|
130
|
+
- expr: "result.outcome == 'complete'"
|
|
131
|
+
- expr: "file_exists(result.artifact)"
|
|
132
|
+
attempts: 2
|
|
133
|
+
|
|
289
134
|
- id: architecture
|
|
135
|
+
after: [prd]
|
|
136
|
+
when: "false"
|
|
290
137
|
agent: claude
|
|
291
|
-
|
|
292
|
-
Write an architecture doc with competing proposals.
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
inputs:
|
|
296
|
-
featureCode: "$.input.featureCode"
|
|
297
|
-
description: "$.input.description"
|
|
298
|
-
output_contract: PhaseResult
|
|
138
|
+
do: >
|
|
139
|
+
Write an architecture doc with competing proposals for ${input.featureCode}
|
|
140
|
+
at docs/features/${input.featureCode}/architecture.md. Return PhaseResult.
|
|
141
|
+
out: PhaseResult
|
|
299
142
|
ensure:
|
|
300
|
-
- "result.outcome == 'complete'"
|
|
301
|
-
- "file_exists(result.artifact)"
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
skip_reason: "Architecture skipped by default — set skip_if to false to enable"
|
|
305
|
-
depends_on: [prd]
|
|
306
|
-
|
|
307
|
-
# Phase: Blueprint
|
|
143
|
+
- expr: "result.outcome == 'complete'"
|
|
144
|
+
- expr: "file_exists(result.artifact)"
|
|
145
|
+
attempts: 2
|
|
146
|
+
|
|
308
147
|
- id: blueprint
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
description: "$.input.description"
|
|
317
|
-
output_contract: PhaseResult
|
|
148
|
+
after: [architecture]
|
|
149
|
+
agent: claude
|
|
150
|
+
do: >
|
|
151
|
+
Write an implementation blueprint with verified file:line references for
|
|
152
|
+
${input.featureCode} at docs/features/${input.featureCode}/blueprint.md.
|
|
153
|
+
Return PhaseResult.
|
|
154
|
+
out: PhaseResult
|
|
318
155
|
ensure:
|
|
319
|
-
- "result.outcome == 'complete'"
|
|
320
|
-
- "file_exists(result.artifact)"
|
|
321
|
-
|
|
322
|
-
depends_on: [architecture]
|
|
156
|
+
- expr: "result.outcome == 'complete'"
|
|
157
|
+
- expr: "file_exists(result.artifact)"
|
|
158
|
+
attempts: 3
|
|
323
159
|
|
|
324
|
-
# Phase: Blueprint Verification
|
|
325
160
|
- id: verification
|
|
161
|
+
after: [blueprint]
|
|
326
162
|
agent: claude
|
|
327
|
-
|
|
328
|
-
Verify every file:line reference in
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
Summarize Boundary Map results (counts of violations and warnings, plus any
|
|
333
|
-
must-fix detail) inside the existing `summary` string field of the PhaseResult —
|
|
334
|
-
do not add new top-level fields. The phase outcome is `complete` only when every
|
|
335
|
-
file:line reference is valid AND the Boundary Map (if present) has zero violations.
|
|
336
|
-
inputs:
|
|
337
|
-
featureCode: "$.input.featureCode"
|
|
338
|
-
description: "$.input.description"
|
|
339
|
-
output_contract: PhaseResult
|
|
163
|
+
do: >
|
|
164
|
+
Verify every file:line reference in ${blueprint.output.artifact}. If it has a
|
|
165
|
+
Boundary Map, invoke validateBoundaryMap from lib/boundary-map.js. Return a
|
|
166
|
+
complete PhaseResult only when references are valid and violations are zero.
|
|
167
|
+
out: PhaseResult
|
|
340
168
|
ensure:
|
|
341
|
-
- "result.outcome == 'complete'"
|
|
342
|
-
|
|
343
|
-
on_fail: blueprint
|
|
344
|
-
depends_on: [blueprint]
|
|
169
|
+
- expr: "result.outcome == 'complete'"
|
|
170
|
+
attempts: 2
|
|
345
171
|
|
|
346
|
-
# Phase: Implementation Plan
|
|
347
172
|
- id: plan
|
|
173
|
+
after: [verification]
|
|
348
174
|
agent: claude
|
|
349
|
-
|
|
350
|
-
Write an ordered implementation plan with tasks,
|
|
351
|
-
and acceptance criteria
|
|
352
|
-
Return
|
|
353
|
-
|
|
354
|
-
featureCode: "$.input.featureCode"
|
|
355
|
-
description: "$.input.description"
|
|
356
|
-
output_contract: PhaseResult
|
|
175
|
+
do: >
|
|
176
|
+
Write an ordered implementation plan for ${input.featureCode} with tasks,
|
|
177
|
+
dependencies, file paths, and acceptance criteria at
|
|
178
|
+
docs/features/${input.featureCode}/plan.md. Return PhaseResult.
|
|
179
|
+
out: PhaseResult
|
|
357
180
|
ensure:
|
|
358
|
-
- "result.outcome == 'complete'"
|
|
359
|
-
- "file_exists(result.artifact)"
|
|
360
|
-
|
|
361
|
-
depends_on: [verification]
|
|
181
|
+
- expr: "result.outcome == 'complete'"
|
|
182
|
+
- expr: "file_exists(result.artifact)"
|
|
183
|
+
attempts: 2
|
|
362
184
|
|
|
363
|
-
# Gate: Plan review
|
|
364
185
|
- id: plan_gate
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
186
|
+
after: [plan]
|
|
187
|
+
gate:
|
|
188
|
+
on_approve: decompose
|
|
189
|
+
on_revise: plan
|
|
190
|
+
on_kill: null
|
|
370
191
|
|
|
371
|
-
# Phase: Decompose — analyze the plan and emit a task graph
|
|
372
192
|
- id: decompose
|
|
373
|
-
type: decompose
|
|
374
193
|
agent: claude
|
|
375
|
-
|
|
376
|
-
Read
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
output_contract: TaskGraph
|
|
194
|
+
do: >
|
|
195
|
+
Read ${plan.output.artifact} and decompose it into independent tasks. For each
|
|
196
|
+
task identify id, description, files_owned, files_read, and depends_on. Reject
|
|
197
|
+
file ownership conflicts. Return {tasks}.
|
|
198
|
+
out: TaskGraph
|
|
381
199
|
ensure:
|
|
382
|
-
- "
|
|
383
|
-
|
|
384
|
-
retries: 2
|
|
385
|
-
depends_on: [plan_gate]
|
|
200
|
+
- expr: "len(result.tasks) >= 1"
|
|
201
|
+
attempts: 2
|
|
386
202
|
|
|
387
|
-
#
|
|
203
|
+
# v0.3 parallel_dispatch -> TS v1 consumer fanout. Compose owns worktrees,
|
|
204
|
+
# pre-merge commands, retained diffs, and the downstream merge handshake.
|
|
388
205
|
- id: execute
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
206
|
+
after: [decompose]
|
|
207
|
+
attempts: 2
|
|
208
|
+
fanout:
|
|
209
|
+
over: "${decompose.output.tasks}"
|
|
210
|
+
dispatch: consumer
|
|
211
|
+
concurrency: 3
|
|
212
|
+
isolation: worktree
|
|
213
|
+
require: all
|
|
214
|
+
merge: sequential
|
|
215
|
+
pre_merge: "$.input.pre_merge_gate"
|
|
216
|
+
steps:
|
|
217
|
+
- agent: "$.input.implementer_agent"
|
|
218
|
+
do: >
|
|
219
|
+
Implement the task described by ${item} using TDD. Write the test first,
|
|
220
|
+
watch it fail, implement, and watch it pass. Honor the item's id,
|
|
221
|
+
files_owned, files_read, description, and dependency fields.
|
|
222
|
+
Return {outcome, summary, files_changed}.
|
|
223
|
+
out: TaskResult
|
|
224
|
+
|
|
225
|
+
- id: execute_merge
|
|
226
|
+
after: [execute]
|
|
227
|
+
gate:
|
|
228
|
+
on_approve: review_triage
|
|
229
|
+
on_revise: execute
|
|
230
|
+
on_kill: null
|
|
231
|
+
max_rounds: 10
|
|
232
|
+
|
|
233
|
+
# The former parallel_review subflow is flattened because TS v1 permits
|
|
234
|
+
# fanout only in the entry flow.
|
|
235
|
+
- id: review_triage
|
|
236
|
+
agent: claude
|
|
237
|
+
do: >
|
|
238
|
+
Select review lenses for the implementation results ${execute.output}.
|
|
239
|
+
|
|
240
|
+
RETRY PATH — If .compose/prior_dirty_lenses.json exists, read its JSON array.
|
|
241
|
+
Activate all lenses listed in that array. Always also include diff-quality
|
|
242
|
+
and contract-compliance. Skip all other lenses because they already passed
|
|
243
|
+
clean.
|
|
244
|
+
|
|
245
|
+
FIRST RUN PATH — If .compose/prior_dirty_lenses.json does not exist, always
|
|
246
|
+
include diff-quality, contract-compliance, and debug-discipline. Add security
|
|
247
|
+
for auth, crypto, SQL, or HTTP-handler changes, and add framework for detected
|
|
248
|
+
framework files.
|
|
249
|
+
|
|
250
|
+
Return {tasks}; each task must include id, lens_name, lens_focus,
|
|
251
|
+
confidence_gate, and exclusions.
|
|
252
|
+
out: TriageResult
|
|
253
|
+
|
|
254
|
+
- id: review_lenses
|
|
255
|
+
after: [review_triage]
|
|
256
|
+
fanout:
|
|
257
|
+
over: "${review_triage.output.tasks}"
|
|
258
|
+
dispatch: consumer
|
|
259
|
+
concurrency: 4
|
|
260
|
+
isolation: none
|
|
261
|
+
require: all
|
|
262
|
+
merge: sequential
|
|
263
|
+
steps:
|
|
264
|
+
- agent: claude
|
|
265
|
+
do: >
|
|
266
|
+
Run the review lens described by ${item}. Honor its lens_name,
|
|
267
|
+
lens_focus, confidence_gate, and exclusions fields. Return the canonical
|
|
268
|
+
ReviewResult shape.
|
|
269
|
+
out: ReviewResult
|
|
270
|
+
|
|
271
|
+
- id: review_lenses_gate
|
|
272
|
+
after: [review_lenses]
|
|
273
|
+
gate:
|
|
274
|
+
on_approve: review_merge
|
|
275
|
+
on_revise: review_triage
|
|
276
|
+
on_kill: null
|
|
277
|
+
max_rounds: 10
|
|
278
|
+
|
|
279
|
+
- id: review_merge
|
|
280
|
+
agent: claude
|
|
281
|
+
do: >
|
|
282
|
+
Merge ${review_lenses.output} into one canonical ReviewResult. Concatenate and
|
|
283
|
+
deduplicate findings by file+line+lens, keep the highest confidence, recompute
|
|
284
|
+
clean, set lenses_run to dirty lens ids, and classify auto_fixes and asks.
|
|
285
|
+
out: ReviewResult
|
|
286
|
+
|
|
287
|
+
# I1: dirty-review recovery is engine-native. review_merge cannot converge on
|
|
288
|
+
# its own (re-running the reducer re-merges the SAME frozen lens outputs), so
|
|
289
|
+
# the cleanliness decision is a GATE. Compose resolves it by policy: a clean
|
|
290
|
+
# merge approves; a dirty merge runs the corrective fixer, persists the dirty
|
|
291
|
+
# lens ids, and REVISES — the engine reroutes to review_triage, whose RETRY
|
|
292
|
+
# PATH reads the sidecar and re-runs only the dirty lenses on the fixed code.
|
|
293
|
+
- id: review_gate
|
|
294
|
+
after: [review_merge]
|
|
295
|
+
gate:
|
|
296
|
+
on_approve: codex_review
|
|
297
|
+
on_revise: review_triage
|
|
298
|
+
on_kill: null
|
|
299
|
+
max_rounds: 10
|
|
422
300
|
|
|
423
|
-
# Sub-flow: Codex review (independent cross-model pass after Claude lenses + fixes)
|
|
424
301
|
- id: codex_review
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
- "result.clean == True"
|
|
432
|
-
depends_on: [review]
|
|
302
|
+
after: [review_gate]
|
|
303
|
+
run: review_check
|
|
304
|
+
with:
|
|
305
|
+
task: "${review_merge.output.summary}"
|
|
306
|
+
blueprint: "${blueprint.output.artifact}"
|
|
307
|
+
reviewer_agent: "${input.reviewer_agent}"
|
|
433
308
|
|
|
434
|
-
# Sub-flow: Coverage (claude runs tests; build.js dispatches fix on ensure_failed)
|
|
435
309
|
- id: coverage
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
- "result.passing == True"
|
|
442
|
-
depends_on: [codex_review]
|
|
310
|
+
after: [codex_review]
|
|
311
|
+
run: coverage_check
|
|
312
|
+
with:
|
|
313
|
+
task: "${input.description}"
|
|
314
|
+
plan: "${plan.output.artifact}"
|
|
443
315
|
|
|
444
|
-
#
|
|
445
|
-
# coverage step generated this build. build.js injects the generated-test
|
|
446
|
-
# file list into the intent, and reports a synthetic clean result (skip)
|
|
447
|
-
# when coverage produced no test files. Advisory — never blocks ship.
|
|
316
|
+
# Advisory by construction: no output contract and no ensure.
|
|
448
317
|
- id: test_review
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
# Phase: Report (skippable)
|
|
318
|
+
after: [coverage]
|
|
319
|
+
agent: "$.input.reviewer_agent"
|
|
320
|
+
do: >
|
|
321
|
+
Review tests generated for ${input.featureCode}. Flag placeholders,
|
|
322
|
+
tautologies, and assertions that only exercise mocks. Cite file:line and the
|
|
323
|
+
missing real assertion. This is advisory and must not block ship.
|
|
324
|
+
|
|
457
325
|
- id: report
|
|
326
|
+
after: [test_review]
|
|
327
|
+
when: "false"
|
|
458
328
|
agent: claude
|
|
459
|
-
|
|
460
|
-
Write
|
|
461
|
-
deviations
|
|
462
|
-
|
|
463
|
-
Return the artifact path in the "artifact" field.
|
|
464
|
-
inputs:
|
|
465
|
-
featureCode: "$.input.featureCode"
|
|
466
|
-
description: "$.input.description"
|
|
467
|
-
output_contract: PhaseResult
|
|
329
|
+
do: >
|
|
330
|
+
Write docs/features/${input.featureCode}/report.md covering delivered work,
|
|
331
|
+
deviations, and lessons learned. Return PhaseResult.
|
|
332
|
+
out: PhaseResult
|
|
468
333
|
ensure:
|
|
469
|
-
- "result.outcome == 'complete'"
|
|
470
|
-
- "file_exists(result.artifact)"
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
skip_reason: "Report skipped by default — set skip_if to false to enable"
|
|
474
|
-
depends_on: [test_review]
|
|
475
|
-
|
|
476
|
-
# Phase: Update Docs
|
|
334
|
+
- expr: "result.outcome == 'complete'"
|
|
335
|
+
- expr: "file_exists(result.artifact)"
|
|
336
|
+
attempts: 2
|
|
337
|
+
|
|
477
338
|
- id: docs
|
|
339
|
+
after: [report]
|
|
478
340
|
agent: claude
|
|
479
|
-
|
|
480
|
-
Update
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
3. README.md — Update ONLY if the feature changes user-facing setup,
|
|
487
|
-
commands, or capabilities. Skip if purely internal.
|
|
488
|
-
4. CLAUDE.md — Update ONLY if new conventions, commands, or architecture
|
|
489
|
-
patterns were introduced. Skip if no changes.
|
|
490
|
-
5. Public docs — If the feature introduces or changes any of these, update
|
|
491
|
-
the relevant file in docs/:
|
|
492
|
-
- New CLI commands or flags → docs/compose-one-pager.md
|
|
493
|
-
- New connector or agent type → docs/connectors.md
|
|
494
|
-
- New workflow or lifecycle change → docs/use-cases.md
|
|
495
|
-
- API or config changes → docs/PRODUCT-SPEC.md
|
|
496
|
-
Read each file before editing. Skip if the feature is purely internal
|
|
497
|
-
with no user-facing changes.
|
|
498
|
-
|
|
499
|
-
Read each file before editing. Do not skip CHANGELOG and ROADMAP —
|
|
500
|
-
they are always required. Commit nothing — the ship step handles commits.
|
|
501
|
-
inputs:
|
|
502
|
-
featureCode: "$.input.featureCode"
|
|
503
|
-
description: "$.input.description"
|
|
504
|
-
output_contract: PhaseResult
|
|
505
|
-
retries: 2
|
|
506
|
-
depends_on: [report]
|
|
507
|
-
|
|
508
|
-
# Phase: Ship
|
|
341
|
+
do: >
|
|
342
|
+
Update CHANGELOG.md and ROADMAP.md for ${input.featureCode}. Update README.md,
|
|
343
|
+
CLAUDE.md, and public docs only when the feature changes their documented
|
|
344
|
+
surfaces. Commit nothing. Return PhaseResult.
|
|
345
|
+
out: PhaseResult
|
|
346
|
+
attempts: 2
|
|
347
|
+
|
|
509
348
|
- id: ship
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
as plan_items: an array of objects { text, file, critical } where:
|
|
525
|
-
- text is the checkbox item text
|
|
526
|
-
- file is the backtick-quoted file path in the item (null if none)
|
|
527
|
-
- critical is true if the item mentions MUST, required, security, or tests
|
|
528
|
-
Use lib/plan-parser.js (parsePlanItems) to do this extraction.
|
|
529
|
-
8. Collect the list of files you staged as files_changed.
|
|
530
|
-
|
|
531
|
-
Include plan_items and files_changed in your result JSON.
|
|
532
|
-
Report the commit hash and files changed.
|
|
533
|
-
inputs:
|
|
534
|
-
featureCode: "$.input.featureCode"
|
|
535
|
-
description: "$.input.description"
|
|
536
|
-
output_contract: PhaseResult
|
|
537
|
-
ensure:
|
|
538
|
-
- "plan_completion(result.plan_items, result.files_changed)"
|
|
539
|
-
retries: 2
|
|
540
|
-
depends_on: [docs]
|
|
349
|
+
after: [docs]
|
|
350
|
+
agent: claude
|
|
351
|
+
do: >
|
|
352
|
+
Run the full test suite and build for ${input.featureCode}; fix failures.
|
|
353
|
+
Verify CHANGELOG.md and ROADMAP.md, stage only feature files, commit and push.
|
|
354
|
+
Parse plan acceptance criteria with lib/plan-parser.js and return PhaseResult
|
|
355
|
+
including plan_items, files_changed, and commit_hash.
|
|
356
|
+
out: PhaseResult
|
|
357
|
+
# C5: the judged ship ensure was removed — it is unevaluable from the
|
|
358
|
+
# {result, input} the judge receives (it fails closed even on evidenced
|
|
359
|
+
# results, so real TS-default builds would plausibly die at ship). Same
|
|
360
|
+
# class as the F5 vocabulary ruling. Ship stays gated by ship_gate; revisit
|
|
361
|
+
# when a deterministic/tunable judge backend exists (stratum follow-up).
|
|
362
|
+
attempts: 2
|
|
541
363
|
|
|
542
|
-
# Gate: Ship review
|
|
543
364
|
- id: ship_gate
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
365
|
+
after: [ship]
|
|
366
|
+
gate:
|
|
367
|
+
on_approve: null
|
|
368
|
+
on_revise: ship
|
|
369
|
+
on_kill: null
|