@smartmemory/compose 0.2.49-beta → 0.2.51-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/.claude/skills/compose/SKILL.md +24 -1
- package/.claude/skills/compose/references/hermes-tools.md +80 -0
- package/README.md +1 -1
- package/bin/compose.js +340 -70
- package/dist/assets/App-CT0vXPgd.js +724 -0
- package/dist/assets/_baseUniq-CsOHc_iS.js +1 -0
- package/dist/assets/{arc-B1TqAC_R.js → arc-BXht3LyE.js} +1 -1
- package/dist/assets/architectureDiagram-Q4EWVU46-BV1r86-w.js +36 -0
- package/dist/assets/blockDiagram-DXYQGD6D-BgcMJjAR.js +132 -0
- package/dist/assets/{browser-DW2JlJCC.js → browser-CnKiSnlr.js} +6 -6
- package/dist/assets/{c4Diagram-AAUBKEIU-Dc6swoQo.js → c4Diagram-AHTNJAMY-nBIRLJTv.js} +1 -1
- package/dist/assets/channel-Dd4XaiYv.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-CdqXgd68.js → chunk-4BX2VUAB-CNmGyhrp.js} +1 -1
- package/dist/assets/chunk-4TB4RGXK-MLT7I7w4.js +206 -0
- package/dist/assets/{chunk-55IACEB6-D7VauOmU.js → chunk-55IACEB6-D8KuKVLa.js} +1 -1
- package/dist/assets/{chunk-2J33WTMH-6HKDSnOw.js → chunk-EDXVE4YY-TPlt1bS2.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-C1Z5m8DP.js → chunk-FMBD7UC4-tYY8xcjr.js} +1 -1
- package/dist/assets/chunk-OYMX7WX6-yBPwT1AT.js +231 -0
- package/dist/assets/{chunk-QZHKN3VN-DY9GU2uD.js → chunk-QZHKN3VN-B4Wfybww.js} +1 -1
- package/dist/assets/{chunk-ND2GUHAM-DmqZMEQe.js → chunk-YZCP3GAM-DE6_5aqh.js} +1 -1
- package/dist/assets/classDiagram-6PBFFD2Q-DshSQDF9.js +1 -0
- package/dist/assets/classDiagram-v2-HSJHXN6E-DshSQDF9.js +1 -0
- package/dist/assets/clone-CBsbNGAa.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-B34g9xzV.js → cose-bilkent-S5V4N54A-DzzRyJtB.js} +1 -1
- package/dist/assets/dagre-KV5264BT-CTcTVGdU.js +4 -0
- package/dist/assets/diagram-5BDNPKRD-qR6mc8kJ.js +10 -0
- package/dist/assets/diagram-G4DWMVQ6-CUcGXyNb.js +24 -0
- package/dist/assets/diagram-MMDJMWI5-B68cPonH.js +43 -0
- package/dist/assets/diagram-TYMM5635-q8Id8eFG.js +24 -0
- package/dist/assets/{erDiagram-TEJ5UH35-C05_Iqmb.js → erDiagram-SMLLAGMA-CtxJi57K.js} +1 -1
- package/dist/assets/{flowDiagram-I6XJVG4X-lXpnb-Ch.js → flowDiagram-DWJPFMVM-BzzO4JYU.js} +1 -1
- package/dist/assets/ganttDiagram-T4ZO3ILL-Dn0wIyhR.js +292 -0
- package/dist/assets/gitGraphDiagram-UUTBAWPF-tnNFXfMM.js +106 -0
- package/dist/assets/graph-DZe55uk8.js +331 -0
- package/dist/assets/graph-Tq_bs_r0.js +1 -0
- package/dist/assets/index-8UhRLbGq.js +123 -0
- package/dist/assets/index-CRqB9els.css +1 -0
- package/dist/assets/infoDiagram-42DDH7IO-BXLvLeS0.js +2 -0
- package/dist/assets/{ishikawaDiagram-YF4QCWOH-CgdsWdgu.js → ishikawaDiagram-UXIWVN3A-DWx-7BBy.js} +5 -5
- package/dist/assets/{journeyDiagram-JHISSGLW-CyvHmE3z.js → journeyDiagram-VCZTEJTY-C42hXNha.js} +1 -1
- package/dist/assets/{kanban-definition-UN3LZRKU-Bqjdyv0T.js → kanban-definition-6JOO6SKY-CEq930ew.js} +1 -1
- package/dist/assets/katex-DkKDou_j.js +257 -0
- package/dist/assets/layout-qtUgN9BC.js +1 -0
- package/dist/assets/{linear-DecnRXf0.js → linear-D158F7OT.js} +1 -1
- package/dist/assets/min-hESxN-c0.js +1 -0
- package/dist/assets/{mindmap-definition-RKZ34NQL-DM1x9vNY.js → mindmap-definition-QFDTVHPH-d9SSh2nG.js} +7 -7
- package/dist/assets/mobile-1gVCT0OK.css +1 -0
- package/dist/assets/mobile-Chw8RWyH.js +17 -0
- package/dist/assets/pieDiagram-DEJITSTG-gglmeMav.js +30 -0
- package/dist/assets/quadrantDiagram-34T5L4WZ-CqFC_htU.js +7 -0
- package/dist/assets/{requirementDiagram-4Y6WPE33-DD-Gg_y5.js → requirementDiagram-MS252O5E-B1ZFIotK.js} +1 -1
- package/dist/assets/sankeyDiagram-XADWPNL6-BvItvZt5.js +10 -0
- package/dist/assets/sequenceDiagram-FGHM5R23-CAIn5Z3U.js +157 -0
- package/dist/assets/stateDiagram-FHFEXIEX-CyJrGzib.js +1 -0
- package/dist/assets/stateDiagram-v2-QKLJ7IA2-DprhF_Ho.js +1 -0
- package/dist/assets/{timeline-definition-PNZ67QCA-BPm2AEQj.js → timeline-definition-GMOUNBTQ-k_0vJQAK.js} +1 -1
- package/dist/assets/{vennDiagram-CIIHVFJN-DQCDWwlj.js → vennDiagram-DHZGUBPP-TZAW60b0.js} +4 -4
- package/dist/assets/wardley-RL74JXVD-DzQEoG6X.js +162 -0
- package/dist/assets/wardleyDiagram-NUSXRM2D-BAoVVIjZ.js +20 -0
- package/dist/assets/{xychartDiagram-2RQKCTM6-Ba05SXXF.js → xychartDiagram-5P7HB3ND-CynkZcUb.js} +1 -1
- package/dist/index.html +4 -4
- package/lib/build-all.js +2 -1
- package/lib/build.js +363 -38
- package/lib/checkpoint/checkpoint-writer.js +3 -2
- package/lib/codex-preflight.js +151 -0
- package/lib/completion-writer.js +59 -15
- package/lib/feature-json.js +14 -3
- package/lib/feature-validator.js +27 -10
- package/lib/feature-write-guard.js +5 -7
- package/lib/feature-writer.js +3 -3
- package/lib/followup-writer.js +2 -2
- package/lib/get-roadmap.js +2 -2
- package/lib/gsd.js +2 -1
- package/lib/hooks-status.js +135 -0
- package/lib/ideabox.js +3 -2
- package/lib/install-agent-defs.js +22 -0
- package/lib/journal-writer.js +3 -3
- package/lib/migrate-anon.js +277 -0
- package/lib/migrate-roadmap.js +2 -3
- package/lib/paths-core.js +47 -0
- package/lib/project-paths.js +46 -37
- package/lib/roadmap-gen.js +3 -4
- package/lib/roadmap-graph/collect.js +5 -5
- package/lib/roadmap-graph/index.js +2 -2
- package/lib/roadmap-parser.js +1 -1
- package/lib/state-migrations.js +3 -3
- package/lib/test-bootstrap.js +165 -2
- package/lib/tracker/local-provider.js +2 -2
- package/lib/triage.js +7 -5
- package/lib/vocabulary-inject.js +103 -0
- package/lib/xref-push.js +4 -4
- package/lib/xref-sync.js +4 -4
- package/package.json +2 -1
- package/pipelines/build-quick.stratum.yaml +433 -0
- package/pipelines/build.stratum.yaml +60 -3
- package/scripts/watch-server.sh +32 -0
- package/server/build-routes.js +89 -9
- package/server/build-stream-bridge.js +12 -0
- package/server/compose-mcp-tools.js +73 -1
- package/server/compose-mcp.js +27 -0
- package/server/design-routes.js +9 -4
- package/server/drift-axes.js +5 -3
- package/server/feature-scaffold-routes.js +82 -0
- package/server/feature-scan.js +8 -2
- package/server/file-watcher.js +13 -7
- package/server/health-routes.js +261 -0
- package/server/ideabox-routes.js +12 -11
- package/server/project-root.js +7 -4
- package/server/qa-scope-routes.js +96 -0
- package/server/session-routes.js +2 -2
- package/server/stratum-sync.js +85 -9
- package/server/validate-routes.js +70 -0
- package/server/vision-routes.js +46 -2
- package/server/vision-server.js +25 -3
- package/server/vision-utils.js +23 -4
- package/dist/assets/App-DOerhoDp.js +0 -706
- package/dist/assets/architectureDiagram-3BPJPVTR-C4hfxNOw.js +0 -36
- package/dist/assets/blockDiagram-GPEHLZMM-DRqkGncy.js +0 -132
- package/dist/assets/channel-KsY1x-7s.js +0 -1
- package/dist/assets/chunk-727SXJPM-CeKpXDif.js +0 -206
- package/dist/assets/chunk-AQP2D5EJ-y2XL-YHV.js +0 -231
- package/dist/assets/classDiagram-4FO5ZUOK-zDEDoVPk.js +0 -1
- package/dist/assets/classDiagram-v2-Q7XG4LA2-zDEDoVPk.js +0 -1
- package/dist/assets/dagre-BM42HDAG-klZ_GOcw.js +0 -4
- package/dist/assets/diagram-2AECGRRQ-D0FmM6Wf.js +0 -43
- package/dist/assets/diagram-5GNKFQAL-DYuhby6q.js +0 -10
- package/dist/assets/diagram-KO2AKTUF-CCtQZgal.js +0 -3
- package/dist/assets/diagram-LMA3HP47-Cd1OqEln.js +0 -24
- package/dist/assets/diagram-OG6HWLK6-CiJrhoxo.js +0 -24
- package/dist/assets/ganttDiagram-6RSMTGT7-EPbL_2Hr.js +0 -292
- package/dist/assets/gitGraphDiagram-PVQCEYII-COCoF_vW.js +0 -106
- package/dist/assets/graph-BBXaecIU.js +0 -331
- package/dist/assets/graph-CAnANduQ.js +0 -1
- package/dist/assets/index-BwLfbbOu.css +0 -1
- package/dist/assets/index-DlgxA8dX.js +0 -123
- package/dist/assets/infoDiagram-5YYISTIA-B1sJw6j5.js +0 -2
- package/dist/assets/katex-C5jXJg4s.js +0 -257
- package/dist/assets/layout-DGIYPm2g.js +0 -1
- package/dist/assets/mobile-Cag5dHlF.css +0 -1
- package/dist/assets/mobile-DwmxS_O4.js +0 -17
- package/dist/assets/pieDiagram-4H26LBE5-CRtmCvwV.js +0 -30
- package/dist/assets/quadrantDiagram-W4KKPZXB-CsBLWg27.js +0 -7
- package/dist/assets/sankeyDiagram-5OEKKPKP-BPdMN8UU.js +0 -40
- package/dist/assets/sequenceDiagram-3UESZ5HK-D4AENdze.js +0 -162
- package/dist/assets/stateDiagram-AJRCARHV-DDplpCf_.js +0 -1
- package/dist/assets/stateDiagram-v2-BHNVJYJU-J4t9AVzF.js +0 -1
- package/dist/assets/wardley-L42UT6IY-WERqOmJt.js +0 -173
- package/dist/assets/wardleyDiagram-YWT4CUSO-5teUSOiI.js +0 -78
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
# metadata:
|
|
2
|
+
# id: build-quick
|
|
3
|
+
# label: "Quick Feature Build"
|
|
4
|
+
# description: "Trimmed build lifecycle for small additive work — design → implement → ship, single gate, Phase-7 enforcement preserved"
|
|
5
|
+
# category: development
|
|
6
|
+
# steps: 11
|
|
7
|
+
# estimated_minutes: 45
|
|
8
|
+
#
|
|
9
|
+
# COMP-BUILD-QUICK: a trimmed variant of build.stratum.yaml. Symmetric to fix
|
|
10
|
+
# mode's Quick path. Collapses the full lifecycle to design → implement → ship:
|
|
11
|
+
# prd, architecture, blueprint, verification, plan, plan_gate, and report are
|
|
12
|
+
# OMITTED (not self-skipping). Phase-7 enforcement (parallel + codex review,
|
|
13
|
+
# coverage sweep, test review) is preserved verbatim — only phase ceremony
|
|
14
|
+
# shrinks. NOT OpenSpec's no-gates model: the design gate and ship gate remain.
|
|
15
|
+
#
|
|
16
|
+
# workflow.name is kept as `build` so the runner (lib/build.js extractFlowName /
|
|
17
|
+
# step-id couplings for execute|docs|ship) sees the identical flow; only the
|
|
18
|
+
# step list differs. Selected via `compose build --quick` → template 'build-quick'.
|
|
19
|
+
|
|
20
|
+
version: "0.3"
|
|
21
|
+
|
|
22
|
+
workflow:
|
|
23
|
+
name: build
|
|
24
|
+
description: "Quick feature build — design → implement → ship (single design gate, Phase-7 enforcement preserved)"
|
|
25
|
+
input:
|
|
26
|
+
featureCode:
|
|
27
|
+
type: string
|
|
28
|
+
required: true
|
|
29
|
+
description:
|
|
30
|
+
type: string
|
|
31
|
+
required: true
|
|
32
|
+
pre_merge_gate:
|
|
33
|
+
type: array
|
|
34
|
+
required: false # COMP-PAR-MERGE-QUEUE-CONSUMER-RETRY: default-OFF per-task gate (lint+build), omitted unless capabilities.preMergeGate
|
|
35
|
+
|
|
36
|
+
contracts:
|
|
37
|
+
PhaseResult:
|
|
38
|
+
phase: {type: string}
|
|
39
|
+
artifact: {type: string}
|
|
40
|
+
outcome: {type: string, values: [complete, skipped, failed]}
|
|
41
|
+
summary: {type: string}
|
|
42
|
+
|
|
43
|
+
# Canonical review output — produced by both review_check (Codex) and parallel_review (Claude).
|
|
44
|
+
# Schema source: compose/contracts/review-result.json (_roadmap: STRAT-CLAUDE-EFFORT-PARITY)
|
|
45
|
+
ReviewResult:
|
|
46
|
+
clean: {type: boolean}
|
|
47
|
+
summary: {type: string}
|
|
48
|
+
findings: {type: array}
|
|
49
|
+
meta: {type: object}
|
|
50
|
+
lenses_run: {type: array}
|
|
51
|
+
auto_fixes: {type: array}
|
|
52
|
+
asks: {type: array}
|
|
53
|
+
|
|
54
|
+
TestResult:
|
|
55
|
+
passing: {type: boolean}
|
|
56
|
+
summary: {type: string}
|
|
57
|
+
failures: {type: array}
|
|
58
|
+
|
|
59
|
+
TaskGraph:
|
|
60
|
+
tasks: {type: array}
|
|
61
|
+
|
|
62
|
+
LensTask:
|
|
63
|
+
id: {type: string}
|
|
64
|
+
lens_name: {type: string}
|
|
65
|
+
lens_focus: {type: string}
|
|
66
|
+
confidence_gate: {type: number}
|
|
67
|
+
exclusions: {type: string}
|
|
68
|
+
|
|
69
|
+
TriageResult:
|
|
70
|
+
tasks: {type: array}
|
|
71
|
+
|
|
72
|
+
functions:
|
|
73
|
+
design_gate:
|
|
74
|
+
mode: gate
|
|
75
|
+
timeout: 3600
|
|
76
|
+
|
|
77
|
+
ship_gate:
|
|
78
|
+
mode: gate
|
|
79
|
+
timeout: 1800
|
|
80
|
+
|
|
81
|
+
flows:
|
|
82
|
+
# --- Sub-flow: review ---
|
|
83
|
+
# Single-step: codex reviews, stratum retries via ensure_failed.
|
|
84
|
+
# Cross-agent fix (claude) is dispatched by build.js when ensure_failed
|
|
85
|
+
# fires with a recovery_agent configured on the parent flow step.
|
|
86
|
+
review_check:
|
|
87
|
+
input:
|
|
88
|
+
task: {type: string}
|
|
89
|
+
blueprint: {type: string}
|
|
90
|
+
output: ReviewResult
|
|
91
|
+
steps:
|
|
92
|
+
- id: review
|
|
93
|
+
agent: codex
|
|
94
|
+
intent: >
|
|
95
|
+
Review the implementation against the blueprint and task.
|
|
96
|
+
inputs:
|
|
97
|
+
task: "$.input.task"
|
|
98
|
+
blueprint: "$.input.blueprint"
|
|
99
|
+
review_mode: "true"
|
|
100
|
+
confidence_gate: "7"
|
|
101
|
+
output_contract: ReviewResult
|
|
102
|
+
ensure:
|
|
103
|
+
- "result.clean == True"
|
|
104
|
+
retries: 5
|
|
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
|
|
142
|
+
|
|
143
|
+
- id: review_lenses
|
|
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.
|
|
179
|
+
coverage_check:
|
|
180
|
+
input:
|
|
181
|
+
task: {type: string}
|
|
182
|
+
plan: {type: string}
|
|
183
|
+
output: TestResult
|
|
184
|
+
steps:
|
|
185
|
+
- id: run_tests
|
|
186
|
+
agent: "claude::fast"
|
|
187
|
+
intent: >
|
|
188
|
+
Run the project test suite. Return structured JSON:
|
|
189
|
+
{ "passing": boolean, "summary": string, "failures": string[] }.
|
|
190
|
+
inputs:
|
|
191
|
+
task: "$.input.task"
|
|
192
|
+
output_contract: TestResult
|
|
193
|
+
ensure:
|
|
194
|
+
- "result.passing == True"
|
|
195
|
+
retries: 15
|
|
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
|
+
output: ReviewResult
|
|
209
|
+
steps:
|
|
210
|
+
- id: review_generated_tests
|
|
211
|
+
agent: codex
|
|
212
|
+
intent: >
|
|
213
|
+
Review the auto-generated test files listed below (written by the coverage
|
|
214
|
+
step this build) and verify their assertions match intent. Read each file.
|
|
215
|
+
Flag tests that are placeholders (assert true / pass with no real assertion),
|
|
216
|
+
tautological, or assert only on mocks/stubs rather than exercising the
|
|
217
|
+
feature's behavior. For each weak test, cite file:line and state what real
|
|
218
|
+
assertion is missing. Do NOT flag hand-written tests or pure style. Output a
|
|
219
|
+
canonical ReviewResult.
|
|
220
|
+
inputs:
|
|
221
|
+
task: "$.input.task"
|
|
222
|
+
blueprint: "$.input.blueprint"
|
|
223
|
+
review_mode: "true"
|
|
224
|
+
confidence_gate: "7"
|
|
225
|
+
# ADVISORY (COMP-TEST-BOOTSTRAP-4-1): deliberately NO output_contract and NO
|
|
226
|
+
# ensure. A schema/postcondition failure here would trigger executeChildFlow's
|
|
227
|
+
# blocking fix-retry path and could block ship (report→docs→ship chain through
|
|
228
|
+
# test_review). Without either gate the step always completes; build.js captures
|
|
229
|
+
# whatever the reviewer returns and surfaces it via the test_review stream event.
|
|
230
|
+
|
|
231
|
+
# --- Main flow: quick feature lifecycle (design → implement → ship) ---
|
|
232
|
+
build:
|
|
233
|
+
input:
|
|
234
|
+
featureCode: {type: string}
|
|
235
|
+
description: {type: string}
|
|
236
|
+
pre_merge_gate: {type: array} # COMP-PAR-MERGE-QUEUE-CONSUMER-RETRY: optional per-task pre-merge gate
|
|
237
|
+
output: PhaseResult
|
|
238
|
+
max_rounds: 10
|
|
239
|
+
steps:
|
|
240
|
+
# Phase: Explore & Design
|
|
241
|
+
- id: explore_design
|
|
242
|
+
agent: claude
|
|
243
|
+
intent: >
|
|
244
|
+
Explore the codebase and write a design doc for this feature.
|
|
245
|
+
Launch 2-3 explorer subagents in parallel to map architecture,
|
|
246
|
+
find similar features, and analyze related implementations.
|
|
247
|
+
Write the design to docs/features/{featureCode}/design.md.
|
|
248
|
+
Return the artifact path in the "artifact" field.
|
|
249
|
+
|
|
250
|
+
QUICK-PATH GUARDRAIL: this is `compose build --quick`, scoped to small
|
|
251
|
+
additive work (e.g. one flag + a test). If the work proves multi-file,
|
|
252
|
+
cross-cutting, or in need of architecture/PRD-level design, STOP and
|
|
253
|
+
recommend the user re-run with full `compose build` (no `--quick`)
|
|
254
|
+
rather than under-scoping. Note the recommendation in the design doc.
|
|
255
|
+
inputs:
|
|
256
|
+
featureCode: "$.input.featureCode"
|
|
257
|
+
description: "$.input.description"
|
|
258
|
+
output_contract: PhaseResult
|
|
259
|
+
ensure:
|
|
260
|
+
- "result.outcome == 'complete'"
|
|
261
|
+
- "file_exists(result.artifact)"
|
|
262
|
+
retries: 2
|
|
263
|
+
|
|
264
|
+
# Gate: Design review
|
|
265
|
+
- id: design_gate
|
|
266
|
+
function: design_gate
|
|
267
|
+
on_approve: decompose
|
|
268
|
+
on_revise: explore_design
|
|
269
|
+
on_kill: null
|
|
270
|
+
depends_on: [explore_design]
|
|
271
|
+
|
|
272
|
+
# Phase: Decompose — analyze the design and emit a task graph
|
|
273
|
+
# (Quick path: no separate plan step — decompose reads the design doc directly.)
|
|
274
|
+
- id: decompose
|
|
275
|
+
type: decompose
|
|
276
|
+
agent: claude
|
|
277
|
+
intent: >
|
|
278
|
+
Read the design doc at docs/features/{featureCode}/design.md and decompose
|
|
279
|
+
it into independent tasks. For each task, identify files_owned (exclusive
|
|
280
|
+
write), files_read (read-only), and depends_on (tasks that must complete first).
|
|
281
|
+
Return a TaskGraph with the task array.
|
|
282
|
+
|
|
283
|
+
QUICK-PATH GUARDRAIL: if decomposition reveals the work is actually multi-file,
|
|
284
|
+
cross-cutting, or architecture-dependent, STOP and recommend the user re-run
|
|
285
|
+
with full `compose build` (no `--quick`) rather than under-scoping.
|
|
286
|
+
output_contract: TaskGraph
|
|
287
|
+
ensure:
|
|
288
|
+
- "no_file_conflicts(result.tasks)"
|
|
289
|
+
- "len(result.tasks) >= 1"
|
|
290
|
+
retries: 2
|
|
291
|
+
depends_on: [design_gate]
|
|
292
|
+
|
|
293
|
+
# Phase: Execute — parallel dispatch of decomposed tasks
|
|
294
|
+
- id: execute
|
|
295
|
+
type: parallel_dispatch
|
|
296
|
+
source: "$.steps.decompose.output.tasks"
|
|
297
|
+
agent: claude
|
|
298
|
+
max_concurrent: 3
|
|
299
|
+
isolation: worktree
|
|
300
|
+
capture_diff: true
|
|
301
|
+
defer_advance: true
|
|
302
|
+
pre_merge_verify: "$.input.pre_merge_gate" # COMP-PAR-MERGE-QUEUE-CONSUMER-RETRY: optional per-task fast gate (default-OFF)
|
|
303
|
+
require: all
|
|
304
|
+
merge: sequential_apply
|
|
305
|
+
intent_template: >
|
|
306
|
+
Implement this task using TDD. Write the test first, watch it fail,
|
|
307
|
+
implement, watch it pass.
|
|
308
|
+
|
|
309
|
+
Task: {task.description}
|
|
310
|
+
You own these files (may create/modify): {task.files_owned}
|
|
311
|
+
You may read (but NOT modify): {task.files_read}
|
|
312
|
+
|
|
313
|
+
Feature: {task.id}
|
|
314
|
+
depends_on: [decompose]
|
|
315
|
+
|
|
316
|
+
# Sub-flow: Review (parallel multi-lens review; falls back to review_check)
|
|
317
|
+
# Parent-step ensure drives the fix loop: ensure_failed -> build.js fix ->
|
|
318
|
+
# retry the whole parallel_review sub-flow, which re-runs fresh triage/lenses/merge.
|
|
319
|
+
# Quick path: review reference is the design doc (no blueprint step exists).
|
|
320
|
+
- id: review
|
|
321
|
+
flow: parallel_review
|
|
322
|
+
inputs:
|
|
323
|
+
task: "$.steps.execute.output.outcome"
|
|
324
|
+
blueprint: "$.steps.explore_design.output.artifact"
|
|
325
|
+
diff: "$.steps.execute.output.tasks"
|
|
326
|
+
ensure:
|
|
327
|
+
- "result.clean == True"
|
|
328
|
+
depends_on: [execute]
|
|
329
|
+
|
|
330
|
+
# Sub-flow: Codex review (independent cross-model pass after Claude lenses + fixes)
|
|
331
|
+
- id: codex_review
|
|
332
|
+
flow: review_check
|
|
333
|
+
inputs:
|
|
334
|
+
task: "$.steps.execute.output.outcome"
|
|
335
|
+
blueprint: "$.steps.explore_design.output.artifact"
|
|
336
|
+
ensure:
|
|
337
|
+
- "result.clean == True"
|
|
338
|
+
depends_on: [review]
|
|
339
|
+
|
|
340
|
+
# Sub-flow: Coverage (claude runs tests; build.js dispatches fix on ensure_failed)
|
|
341
|
+
- id: coverage
|
|
342
|
+
flow: coverage_check
|
|
343
|
+
inputs:
|
|
344
|
+
task: "$.steps.execute.output.outcome"
|
|
345
|
+
plan: "$.input.description"
|
|
346
|
+
ensure:
|
|
347
|
+
- "result.passing == True"
|
|
348
|
+
depends_on: [codex_review]
|
|
349
|
+
|
|
350
|
+
# Sub-flow: Test review (COMP-TEST-BOOTSTRAP-4-1) — review the tests the
|
|
351
|
+
# coverage step generated this build. build.js injects the generated-test
|
|
352
|
+
# file list into the intent, and reports a synthetic clean result (skip)
|
|
353
|
+
# when coverage produced no test files. Advisory — never blocks ship.
|
|
354
|
+
- id: test_review
|
|
355
|
+
flow: test_review
|
|
356
|
+
inputs:
|
|
357
|
+
task: "$.steps.execute.output.outcome"
|
|
358
|
+
blueprint: "$.steps.explore_design.output.artifact"
|
|
359
|
+
depends_on: [coverage]
|
|
360
|
+
|
|
361
|
+
# Phase: Update Docs
|
|
362
|
+
- id: docs
|
|
363
|
+
agent: claude
|
|
364
|
+
intent: >
|
|
365
|
+
Update project documentation for this feature. You MUST:
|
|
366
|
+
|
|
367
|
+
1. CHANGELOG.md — Add an entry under today's date with the feature code
|
|
368
|
+
and a bullet list of what was built. Read the existing format first.
|
|
369
|
+
2. ROADMAP.md — Find this feature's row and change its status to COMPLETE.
|
|
370
|
+
If this completes a parent feature, update the parent header too.
|
|
371
|
+
3. README.md — Update ONLY if the feature changes user-facing setup,
|
|
372
|
+
commands, or capabilities. Skip if purely internal.
|
|
373
|
+
4. CLAUDE.md — Update ONLY if new conventions, commands, or architecture
|
|
374
|
+
patterns were introduced. Skip if no changes.
|
|
375
|
+
5. Public docs — If the feature introduces or changes any of these, update
|
|
376
|
+
the relevant file in docs/:
|
|
377
|
+
- New CLI commands or flags → docs/compose-one-pager.md
|
|
378
|
+
- New connector or agent type → docs/connectors.md
|
|
379
|
+
- New workflow or lifecycle change → docs/use-cases.md
|
|
380
|
+
- API or config changes → docs/PRODUCT-SPEC.md
|
|
381
|
+
Read each file before editing. Skip if the feature is purely internal
|
|
382
|
+
with no user-facing changes.
|
|
383
|
+
|
|
384
|
+
Read each file before editing. Do not skip CHANGELOG and ROADMAP —
|
|
385
|
+
they are always required. Commit nothing — the ship step handles commits.
|
|
386
|
+
inputs:
|
|
387
|
+
featureCode: "$.input.featureCode"
|
|
388
|
+
description: "$.input.description"
|
|
389
|
+
output_contract: PhaseResult
|
|
390
|
+
retries: 2
|
|
391
|
+
depends_on: [test_review]
|
|
392
|
+
|
|
393
|
+
# Phase: Ship
|
|
394
|
+
- id: ship
|
|
395
|
+
agent: "claude::critical"
|
|
396
|
+
intent: >
|
|
397
|
+
Final verification and commit. You MUST:
|
|
398
|
+
|
|
399
|
+
1. Run the test suite (npm test or node --test test/*.test.js).
|
|
400
|
+
If tests fail, fix them before proceeding.
|
|
401
|
+
2. Run the build (npx vite build). Must pass.
|
|
402
|
+
3. Check git status — verify CHANGELOG.md and ROADMAP.md were updated
|
|
403
|
+
by the docs step. If they weren't, update them now.
|
|
404
|
+
4. Stage all changed files for this feature (git add — be explicit,
|
|
405
|
+
never stage worktrees, pycache, or node_modules).
|
|
406
|
+
5. Commit with message: "feat(<featureCode>): <one-line summary>"
|
|
407
|
+
6. Push to remote.
|
|
408
|
+
7. Read docs/features/{featureCode}/design.md and extract acceptance criteria
|
|
409
|
+
as plan_items: an array of objects { text, file, critical } where:
|
|
410
|
+
- text is the checkbox item text
|
|
411
|
+
- file is the backtick-quoted file path in the item (null if none)
|
|
412
|
+
- critical is true if the item mentions MUST, required, security, or tests
|
|
413
|
+
Use lib/plan-parser.js (parsePlanItems) to do this extraction.
|
|
414
|
+
8. Collect the list of files you staged as files_changed.
|
|
415
|
+
|
|
416
|
+
Include plan_items and files_changed in your result JSON.
|
|
417
|
+
Report the commit hash and files changed.
|
|
418
|
+
inputs:
|
|
419
|
+
featureCode: "$.input.featureCode"
|
|
420
|
+
description: "$.input.description"
|
|
421
|
+
output_contract: PhaseResult
|
|
422
|
+
ensure:
|
|
423
|
+
- "plan_completion(result.plan_items, result.files_changed)"
|
|
424
|
+
retries: 2
|
|
425
|
+
depends_on: [docs]
|
|
426
|
+
|
|
427
|
+
# Gate: Ship review
|
|
428
|
+
- id: ship_gate
|
|
429
|
+
function: ship_gate
|
|
430
|
+
on_approve: null
|
|
431
|
+
on_revise: ship
|
|
432
|
+
on_kill: null
|
|
433
|
+
depends_on: [ship]
|
|
@@ -21,6 +21,12 @@ workflow:
|
|
|
21
21
|
pre_merge_gate:
|
|
22
22
|
type: array
|
|
23
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).
|
|
24
30
|
|
|
25
31
|
contracts:
|
|
26
32
|
PhaseResult:
|
|
@@ -80,10 +86,11 @@ flows:
|
|
|
80
86
|
input:
|
|
81
87
|
task: {type: string}
|
|
82
88
|
blueprint: {type: string}
|
|
89
|
+
reviewer_agent: {type: string} # COMP-CODEX-IMPL: threaded from the parent build flow (sub-flows have their own $.input scope)
|
|
83
90
|
output: ReviewResult
|
|
84
91
|
steps:
|
|
85
92
|
- id: review
|
|
86
|
-
agent: codex
|
|
93
|
+
agent: "$.input.reviewer_agent" # COMP-CODEX-IMPL: codex by default; claude when codex is the implementer (no self-review)
|
|
87
94
|
intent: >
|
|
88
95
|
Review the implementation against the blueprint and task.
|
|
89
96
|
inputs:
|
|
@@ -187,12 +194,49 @@ flows:
|
|
|
187
194
|
- "result.passing == True"
|
|
188
195
|
retries: 15
|
|
189
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
|
+
|
|
190
232
|
# --- Main flow: compose feature lifecycle ---
|
|
191
233
|
build:
|
|
192
234
|
input:
|
|
193
235
|
featureCode: {type: string}
|
|
194
236
|
description: {type: string}
|
|
195
237
|
pre_merge_gate: {type: array} # COMP-PAR-MERGE-QUEUE-CONSUMER-RETRY: optional per-task pre-merge gate
|
|
238
|
+
implementer_agent: {type: string} # COMP-CODEX-IMPL: code-writing executor (default claude; codex under --codex)
|
|
239
|
+
reviewer_agent: {type: string} # COMP-CODEX-IMPL: cross-model reviewer, always != implementer
|
|
196
240
|
output: PhaseResult
|
|
197
241
|
max_rounds: 10
|
|
198
242
|
steps:
|
|
@@ -344,7 +388,7 @@ flows:
|
|
|
344
388
|
- id: execute
|
|
345
389
|
type: parallel_dispatch
|
|
346
390
|
source: "$.steps.decompose.output.tasks"
|
|
347
|
-
agent: claude
|
|
391
|
+
agent: "$.input.implementer_agent" # COMP-CODEX-IMPL: claude by default, codex under --codex (resolved via STRAT-AGENT-INTERP)
|
|
348
392
|
max_concurrent: 3
|
|
349
393
|
isolation: worktree
|
|
350
394
|
capture_diff: true
|
|
@@ -382,6 +426,7 @@ flows:
|
|
|
382
426
|
inputs:
|
|
383
427
|
task: "$.steps.execute.output.outcome"
|
|
384
428
|
blueprint: "$.steps.blueprint.output.artifact"
|
|
429
|
+
reviewer_agent: "$.input.reviewer_agent" # COMP-CODEX-IMPL: thread the role into the sub-flow
|
|
385
430
|
ensure:
|
|
386
431
|
- "result.clean == True"
|
|
387
432
|
depends_on: [review]
|
|
@@ -396,6 +441,18 @@ flows:
|
|
|
396
441
|
- "result.passing == True"
|
|
397
442
|
depends_on: [codex_review]
|
|
398
443
|
|
|
444
|
+
# Sub-flow: Test review (COMP-TEST-BOOTSTRAP-4-1) — review the tests the
|
|
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.
|
|
448
|
+
- id: test_review
|
|
449
|
+
flow: test_review
|
|
450
|
+
inputs:
|
|
451
|
+
task: "$.steps.execute.output.outcome"
|
|
452
|
+
blueprint: "$.steps.blueprint.output.artifact"
|
|
453
|
+
reviewer_agent: "$.input.reviewer_agent" # COMP-CODEX-IMPL: thread the role into the sub-flow
|
|
454
|
+
depends_on: [coverage]
|
|
455
|
+
|
|
399
456
|
# Phase: Report (skippable)
|
|
400
457
|
- id: report
|
|
401
458
|
agent: claude
|
|
@@ -414,7 +471,7 @@ flows:
|
|
|
414
471
|
retries: 2
|
|
415
472
|
skip_if: "true"
|
|
416
473
|
skip_reason: "Report skipped by default — set skip_if to false to enable"
|
|
417
|
-
depends_on: [
|
|
474
|
+
depends_on: [test_review]
|
|
418
475
|
|
|
419
476
|
# Phase: Update Docs
|
|
420
477
|
- id: docs
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# watch-server.sh — restart the Compose :4001 API server on source changes (dev).
|
|
3
|
+
#
|
|
4
|
+
# Frees the port first (killing any stale/orphaned `node server/index.js` left by a
|
|
5
|
+
# dead session — exactly the leftover that reds the pre-push test suite), then runs
|
|
6
|
+
# the server under Node's built-in --watch so any change in the loaded module graph
|
|
7
|
+
# (server/**, lib/**) triggers a clean restart. server/index.js handles SIGTERM with
|
|
8
|
+
# process.exit(0), so the port releases cleanly between restarts.
|
|
9
|
+
#
|
|
10
|
+
# Scope: the :4001 API server only. For the full stack (agent server :4002 + Vite),
|
|
11
|
+
# use `npm run dev:server` (the supervisor) — it crash-restarts but does NOT watch files.
|
|
12
|
+
#
|
|
13
|
+
# Usage: npm run dev:watch (or: bash scripts/watch-server.sh ; PORT=4099 to override)
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
PORT="${PORT:-4001}"
|
|
17
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
18
|
+
cd "$ROOT"
|
|
19
|
+
|
|
20
|
+
# Free the port so --watch can bind: kill any current listener (stale orphan or a
|
|
21
|
+
# previous run). lsof exits non-zero when nothing is listening — the `|| true`
|
|
22
|
+
# keeps `set -e` from tripping on the empty case.
|
|
23
|
+
stale="$(lsof -ti ":$PORT" -sTCP:LISTEN 2>/dev/null || true)"
|
|
24
|
+
if [ -n "$stale" ]; then
|
|
25
|
+
echo "[watch-server] freeing :$PORT — killing listener(s): $(echo "$stale" | tr '\n' ' ')"
|
|
26
|
+
# shellcheck disable=SC2086 # word-splitting intended: $stale may hold several PIDs
|
|
27
|
+
kill $stale 2>/dev/null || true
|
|
28
|
+
sleep 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
echo "[watch-server] node --watch server/index.js on :$PORT — edit server/** or lib/** to restart (Ctrl-C to stop)"
|
|
32
|
+
exec env PORT="$PORT" node --watch server/index.js
|