@smartmemory/compose 0.3.6-beta → 0.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/.claude/skills/compose/SKILL.md +42 -88
  2. package/.compose-deps.json +1 -13
  3. package/README.md +72 -5
  4. package/bin/compose.js +754 -347
  5. package/bin/git-hooks/pre-push.template +29 -0
  6. package/bin/judgment-import.js +7 -0
  7. package/bin/judgment-migrate.js +387 -0
  8. package/contracts/comp-obs-contract.schema.json +9 -3
  9. package/contracts/feature-json.schema.json +5 -0
  10. package/contracts/fluid-record.schema.json +209 -0
  11. package/contracts/judgment-record.schema.json +425 -4
  12. package/contracts/lifecycle-backfill.schema.json +322 -0
  13. package/dist/assets/App-Z4MU-H_F.js +916 -0
  14. package/dist/assets/_baseUniq-ClWoCPFl.js +1 -0
  15. package/dist/assets/arc-DY26UIVo.js +1 -0
  16. package/dist/assets/architectureDiagram-Q4EWVU46-6Ggq4DqJ.js +36 -0
  17. package/dist/assets/blockDiagram-DXYQGD6D-CH3Ked0l.js +132 -0
  18. package/dist/assets/{browser-BSM23If2.js → browser-BWkrenen.js} +6 -6
  19. package/dist/assets/{c4Diagram-LMCZKHZV-DZf45Fbz.js → c4Diagram-AHTNJAMY-Bk8dYilu.js} +1 -1
  20. package/dist/assets/channel-SnZzzh7k.js +1 -0
  21. package/dist/assets/{chunk-JWPE2WC7-_7ujgd_Q.js → chunk-4BX2VUAB-BMR0XaAQ.js} +1 -1
  22. package/dist/assets/chunk-4TB4RGXK-JytR14a9.js +206 -0
  23. package/dist/assets/{chunk-XXDRQBXY-DfdVhbmA.js → chunk-55IACEB6-B4Q97BCP.js} +1 -1
  24. package/dist/assets/{chunk-VR4S4FIN-Dt9NZ67m.js → chunk-EDXVE4YY-R_qarkSf.js} +1 -1
  25. package/dist/assets/{chunk-5VM5RSS4-BY4_PV5H.js → chunk-FMBD7UC4-C9s7KR9m.js} +1 -1
  26. package/dist/assets/chunk-OYMX7WX6-BySQzVxc.js +231 -0
  27. package/dist/assets/{chunk-2Q5K7J3B-Dn1spZYu.js → chunk-QZHKN3VN-DdpSYZsW.js} +1 -1
  28. package/dist/assets/{chunk-32BRIVSS-pURGrJDk.js → chunk-YZCP3GAM-iE_tzriw.js} +1 -1
  29. package/dist/assets/classDiagram-6PBFFD2Q-CBu92dSH.js +1 -0
  30. package/dist/assets/classDiagram-v2-HSJHXN6E-CBu92dSH.js +1 -0
  31. package/dist/assets/clone-DgklGjHm.js +1 -0
  32. package/dist/assets/{cose-bilkent-JH36ORCC-BieYif4o.js → cose-bilkent-S5V4N54A-BdlU6ZX_.js} +1 -1
  33. package/dist/assets/dagre-KV5264BT-Cp3F5KTn.js +4 -0
  34. package/dist/assets/diagram-5BDNPKRD-DiR6_2q_.js +10 -0
  35. package/dist/assets/diagram-G4DWMVQ6-w0i-p5HX.js +24 -0
  36. package/dist/assets/diagram-MMDJMWI5-tIHhwUv3.js +43 -0
  37. package/dist/assets/diagram-TYMM5635-BAeY3B19.js +24 -0
  38. package/dist/assets/erDiagram-SMLLAGMA-Ckx_Knko.js +85 -0
  39. package/dist/assets/flowDiagram-DWJPFMVM-DeoNka6J.js +162 -0
  40. package/dist/assets/ganttDiagram-T4ZO3ILL-BmGnFbEg.js +292 -0
  41. package/dist/assets/gitGraphDiagram-UUTBAWPF-Dk48IHsx.js +106 -0
  42. package/dist/assets/graph-BNzKGvoy.js +1 -0
  43. package/dist/assets/graph-CI_1htl0.js +331 -0
  44. package/dist/assets/index-BEfrNBp8.js +123 -0
  45. package/dist/assets/index-yyrA5OZd.css +1 -0
  46. package/dist/assets/infoDiagram-42DDH7IO-BRf827i0.js +2 -0
  47. package/dist/assets/{ishikawaDiagram-FXEZZL3T-CzEB9fQS.js → ishikawaDiagram-UXIWVN3A-0kCZaeCM.js} +5 -5
  48. package/dist/assets/{journeyDiagram-5HDEW3XC-Bz8TCdz2.js → journeyDiagram-VCZTEJTY-rvU7ayRt.js} +1 -1
  49. package/dist/assets/{kanban-definition-HUTT4EX6-tozrMoV_.js → kanban-definition-6JOO6SKY-DpQwX1C5.js} +7 -7
  50. package/dist/assets/katex-DkKDou_j.js +257 -0
  51. package/dist/assets/layout-BI8cXFPI.js +1 -0
  52. package/dist/assets/{linear-Ck7gpa5N.js → linear-a0glcDiw.js} +1 -1
  53. package/dist/assets/min-vPHfnXcC.js +1 -0
  54. package/dist/assets/{mindmap-definition-LN4V7U3C-DTcHO0DJ.js → mindmap-definition-QFDTVHPH-D14eF-7C.js} +7 -7
  55. package/dist/assets/mobile-B7m9EO9D.js +17 -0
  56. package/dist/assets/pieDiagram-DEJITSTG-Cno-gETh.js +30 -0
  57. package/dist/assets/quadrantDiagram-34T5L4WZ-BUQM1Hfm.js +7 -0
  58. package/dist/assets/{requirementDiagram-TGXJPOKE-bnI2zJeT.js → requirementDiagram-MS252O5E-pOXlN2-q.js} +3 -3
  59. package/dist/assets/sankeyDiagram-XADWPNL6-Crynd3_b.js +10 -0
  60. package/dist/assets/sequenceDiagram-FGHM5R23-D9fZdCM8.js +157 -0
  61. package/dist/assets/stateDiagram-FHFEXIEX-CW9qVec8.js +1 -0
  62. package/dist/assets/stateDiagram-v2-QKLJ7IA2-DkVLzHbY.js +1 -0
  63. package/dist/assets/{timeline-definition-FHXFAJF6-D267GQFF.js → timeline-definition-GMOUNBTQ-BcHzhm_8.js} +3 -3
  64. package/dist/assets/vennDiagram-DHZGUBPP-BfytJcWk.js +34 -0
  65. package/dist/assets/wardley-RL74JXVD-DLj-IjyB.js +162 -0
  66. package/dist/assets/wardleyDiagram-NUSXRM2D-Ds0Ue68c.js +20 -0
  67. package/dist/assets/xychartDiagram-5P7HB3ND-vjWDXFL6.js +7 -0
  68. package/dist/index.html +3 -3
  69. package/lib/agent-string.js +7 -5
  70. package/lib/append-integrity.js +81 -0
  71. package/lib/backfill-evidence.js +109 -0
  72. package/lib/bug-escalation.js +39 -4
  73. package/lib/build-stream-schema.js +3 -1
  74. package/lib/build-stream-writer.js +25 -0
  75. package/lib/build.js +1624 -195
  76. package/lib/canon-guard.js +245 -0
  77. package/lib/canon-override.js +196 -0
  78. package/lib/canon-registry.js +291 -0
  79. package/lib/cli-commands.js +144 -0
  80. package/lib/codex-preflight.js +50 -15
  81. package/lib/colleague/context.js +215 -0
  82. package/lib/colleague/writeback.js +95 -0
  83. package/lib/completion-gate.js +1421 -0
  84. package/lib/completion-writer.js +47 -47
  85. package/lib/consumer-fanout.js +105 -11
  86. package/lib/coverage-gate.js +200 -0
  87. package/lib/dir-lock.js +170 -0
  88. package/lib/dispatch-ledger.js +301 -0
  89. package/lib/dispatch-metrics.js +236 -0
  90. package/lib/experiment-judge.js +6 -1
  91. package/lib/feature-json.js +1 -1
  92. package/lib/feature-reconciler.js +8 -0
  93. package/lib/feature-validator.js +64 -1
  94. package/lib/feature-writer.js +66 -2
  95. package/lib/fluid/factory.js +167 -0
  96. package/lib/fluid/ideabox-dates.js +73 -0
  97. package/lib/fluid/ideabox-migrate.js +154 -0
  98. package/lib/fluid/ideabox-ops.js +585 -0
  99. package/lib/fluid/ideabox-view.js +146 -0
  100. package/lib/fluid/import-ideabox.js +186 -0
  101. package/lib/fluid/local-provider.js +606 -0
  102. package/lib/fluid/provider.js +684 -0
  103. package/lib/fluid/record-shape.js +214 -0
  104. package/lib/fluid/record-store.js +328 -0
  105. package/lib/fluid/render-ideabox.js +261 -0
  106. package/lib/fluid/schema.js +40 -0
  107. package/lib/fluid/smartmemory-provider.js +1695 -0
  108. package/lib/gsd.js +63 -14
  109. package/lib/guard-cli.js +175 -0
  110. package/lib/guard-custody.js +141 -0
  111. package/lib/guard-descriptors.js +530 -0
  112. package/lib/guard-enrol.js +254 -0
  113. package/lib/health-score.js +1 -1
  114. package/lib/hooks-status.js +32 -3
  115. package/lib/ideabox-cli.js +315 -0
  116. package/lib/ideabox.js +121 -21
  117. package/lib/judgment/store/index.js +166 -0
  118. package/lib/judgment/store/records.js +184 -25
  119. package/lib/judgment/trace.js +380 -0
  120. package/lib/judgment-attest.js +259 -0
  121. package/lib/judgment-decision-write.js +277 -0
  122. package/lib/judgment-decisions.js +466 -0
  123. package/lib/judgment-gen.js +375 -22
  124. package/lib/judgment-verify.js +153 -0
  125. package/lib/judgment-writer.js +2842 -262
  126. package/lib/lane-gate.js +2 -0
  127. package/lib/lifecycle-modes.js +4 -4
  128. package/lib/lineage.js +400 -0
  129. package/lib/local-claude-connector.js +250 -54
  130. package/lib/maya-client.js +302 -0
  131. package/lib/maya-config.js +53 -0
  132. package/lib/maya-identity.js +283 -0
  133. package/lib/mcp-enforcement.js +21 -35
  134. package/lib/migrate-anon.js +5 -0
  135. package/lib/migrate-roadmap.js +15 -0
  136. package/lib/new.js +13 -1
  137. package/lib/pipeline-compat.js +104 -0
  138. package/lib/policy-catalog.js +295 -0
  139. package/lib/policy-check.js +0 -0
  140. package/lib/process-termination.js +98 -0
  141. package/lib/resolve-workspace.js +5 -1
  142. package/lib/result-normalizer.js +428 -153
  143. package/lib/review-normalize.js +4 -0
  144. package/lib/roadmap-errors.js +65 -0
  145. package/lib/roadmap-preservers.js +24 -4
  146. package/lib/roadmap-residue.js +299 -0
  147. package/lib/smartmemory-client.js +614 -78
  148. package/lib/smartmemory-config.js +54 -0
  149. package/lib/smartmemory-ingest.js +19 -2
  150. package/lib/step-prompt.js +7 -6
  151. package/lib/stratum-engine.js +53 -4
  152. package/lib/stratum-mcp-client.js +391 -31
  153. package/lib/test-bootstrap.js +31 -0
  154. package/lib/tool-inventory.js +122 -0
  155. package/lib/version-check.js +91 -19
  156. package/lib/vision-writer.js +88 -1
  157. package/package.json +7 -6
  158. package/pipelines/bug-fix.stratum.yaml +205 -211
  159. package/pipelines/build-quick.profiles.json +12 -0
  160. package/pipelines/build-quick.stratum.yaml +263 -350
  161. package/pipelines/content.stratum.yaml +81 -77
  162. package/pipelines/coverage-sweep.stratum.yaml +49 -30
  163. package/pipelines/plan.stratum.yaml +76 -86
  164. package/pipelines/refactor.stratum.yaml +125 -125
  165. package/pipelines/research.stratum.yaml +56 -58
  166. package/pipelines/review-fix.profiles.json +6 -0
  167. package/pipelines/review-fix.stratum.yaml +110 -83
  168. package/presets/team-feature.profiles.json +6 -0
  169. package/presets/team-feature.stratum.yaml +93 -66
  170. package/presets/team-research.profiles.json +6 -0
  171. package/presets/team-research.stratum.yaml +89 -80
  172. package/presets/team-review.profiles.json +8 -0
  173. package/presets/team-review.stratum.yaml +98 -80
  174. package/scripts/cost-census.mjs +70 -0
  175. package/scripts/guard-sign/compose-guard-sign.sh +62 -0
  176. package/server/agent-health.js +22 -0
  177. package/server/agent-hooks.js +14 -1
  178. package/server/agent-server.js +5 -248
  179. package/server/agent-spawn.js +3 -4
  180. package/server/agent-workspace.js +294 -0
  181. package/server/build-routes.js +6 -5
  182. package/server/build-stream-bridge.js +53 -0
  183. package/server/cc-session-watcher.js +4 -1
  184. package/server/coalescing-buffer.js +7 -1
  185. package/server/completion-projection.js +228 -0
  186. package/server/compose-mcp-tools.js +124 -24
  187. package/server/compose-mcp.js +91 -790
  188. package/server/decision-event-emit.js +41 -2
  189. package/server/decision-event-id.js +17 -0
  190. package/server/decision-events-snapshot.js +3 -0
  191. package/server/design-routes.js +14 -8
  192. package/server/feature-scan.js +76 -2
  193. package/server/file-watcher.js +170 -21
  194. package/server/ideabox-routes.js +166 -224
  195. package/server/index.js +70 -100
  196. package/server/lifecycle-guard.js +240 -10
  197. package/server/lifecycle-phase-history.js +276 -0
  198. package/server/maya-routes.js +507 -0
  199. package/server/mcp-tool-defs.js +940 -0
  200. package/server/mcp-tool-policy.js +35 -3
  201. package/server/model-tiers.js +22 -5
  202. package/server/pipeline-routes.js +21 -11
  203. package/server/project-root.js +58 -19
  204. package/server/remote-utils.js +3 -1
  205. package/server/schema-validator.js +7 -1
  206. package/server/session-manager.js +5 -6
  207. package/server/session-routes.js +3 -1
  208. package/server/stratum-client.js +57 -10
  209. package/server/stratum-sync.js +6 -3
  210. package/server/summarizer.js +3 -4
  211. package/server/supervisor.js +0 -1
  212. package/server/vision-routes.js +208 -98
  213. package/server/vision-server.js +86 -23
  214. package/server/vision-store.js +60 -6
  215. package/server/vision-utils.js +3 -4
  216. package/server/workspace-activity.js +18 -0
  217. package/server/workspace-middleware.js +2 -2
  218. package/server/workspace-runtime.js +243 -0
  219. package/server/worktree-gc.js +1 -0
  220. package/dist/assets/App-BG3ngu8H.js +0 -896
  221. package/dist/assets/abnfDiagram-VRR7QNED-CjB_sD3D.js +0 -1
  222. package/dist/assets/arc-_v4hR_uD.js +0 -1
  223. package/dist/assets/architectureDiagram-ZJ3FMSHR-DreJmzXQ.js +0 -36
  224. package/dist/assets/blockDiagram-677ZJIJ3-BG9-c0O1.js +0 -132
  225. package/dist/assets/channel-B3U5wFAT.js +0 -1
  226. package/dist/assets/chunk-EX3LRPZG-DdELs1qP.js +0 -231
  227. package/dist/assets/chunk-MOJQB5TN-D-ky35G-.js +0 -88
  228. package/dist/assets/chunk-RYQCIY6F-Dag_kVlO.js +0 -1
  229. package/dist/assets/chunk-V7JOEXUC-BtewURat.js +0 -206
  230. package/dist/assets/classDiagram-OUVF2IWQ-B6fCN-ht.js +0 -1
  231. package/dist/assets/classDiagram-v2-EOCWNBFH-B6fCN-ht.js +0 -1
  232. package/dist/assets/cynefin-VYW2F7L2-CT2BA6KE.js +0 -178
  233. package/dist/assets/cynefinDiagram-TSTJHNR4-Bh6exbyg.js +0 -62
  234. package/dist/assets/dagre-VKFMJZFB-aXMLSmQL.js +0 -4
  235. package/dist/assets/diagram-FQU43EPY-Dr7JAOuQ.js +0 -3
  236. package/dist/assets/diagram-G47NLZAW-DUvA3FQK.js +0 -24
  237. package/dist/assets/diagram-NH7WQ7WH-BQUARqcu.js +0 -24
  238. package/dist/assets/diagram-OA4YK3LP-dDUc1zHi.js +0 -30
  239. package/dist/assets/diagram-WEI45ONY-B2h5Qlb1.js +0 -41
  240. package/dist/assets/ebnfDiagram-CCIWWBDH-DThRGupB.js +0 -1
  241. package/dist/assets/erDiagram-Q63AITRT-BUCsprO2.js +0 -85
  242. package/dist/assets/flowDiagram-23GEKE2U-DXtNNi6r.js +0 -156
  243. package/dist/assets/ganttDiagram-NO4QXBWP-D4zbBHh_.js +0 -292
  244. package/dist/assets/gitGraphDiagram-IHSO6WYX-DpoQws0W.js +0 -106
  245. package/dist/assets/graph-BXPQrYYB.js +0 -331
  246. package/dist/assets/graph-C9eacEi8.js +0 -1
  247. package/dist/assets/index-3ZH5eMcZ.js +0 -119
  248. package/dist/assets/index-LIwREYgH.css +0 -1
  249. package/dist/assets/infoDiagram-FWYZ7A6U-Bbas2GAo.js +0 -2
  250. package/dist/assets/katex-C5jXJg4s.js +0 -257
  251. package/dist/assets/layout-DEXfKzaS.js +0 -1
  252. package/dist/assets/map-Czzmt4hB.js +0 -1
  253. package/dist/assets/mobile-CaoXUwAr.js +0 -17
  254. package/dist/assets/pegDiagram-2B236MQR-CHiINrNy.js +0 -1
  255. package/dist/assets/pieDiagram-ENE6RG2P-CfS4YFlR.js +0 -39
  256. package/dist/assets/quadrantDiagram-ABIIQ3AL-CadesS9w.js +0 -7
  257. package/dist/assets/railroadDiagram-RFXS5EU6-CgWEspBN.js +0 -1
  258. package/dist/assets/sankeyDiagram-HTMAVEWB-YWKFgOGw.js +0 -40
  259. package/dist/assets/sequenceDiagram-DBY2YBRQ-BvkNOyF9.js +0 -162
  260. package/dist/assets/sizeCapture-X5ZJPWSS-DlFPA2yO.js +0 -1
  261. package/dist/assets/stateDiagram-2N3HPSRC-h8NIx0kQ.js +0 -1
  262. package/dist/assets/stateDiagram-v2-6OUMAXLB-DjPgZtJ9.js +0 -1
  263. package/dist/assets/swimlanes-5IMT3BWC-CT5n22kG.js +0 -2
  264. package/dist/assets/swimlanesDiagram-G3AALYLV-Dn318Bhq.js +0 -8
  265. package/dist/assets/vennDiagram-L72KCM5P-Dj-wWLYG.js +0 -34
  266. package/dist/assets/wardleyDiagram-EHGQE667-BxCeYxkG.js +0 -78
  267. package/dist/assets/xychartDiagram-FW5EYKEG-DMFqWn7z.js +0 -7
  268. package/lib/staleness.js +0 -87
  269. package/server/ideabox-cache.js +0 -77
@@ -4,47 +4,65 @@
4
4
  # Pattern: Decompose → parallel implement with files_owned → verify
5
5
  # Capability: Orchestrator decomposes, implementers have full access
6
6
  # Isolation: worktree (each task in its own worktree)
7
- # Merge: sequential_apply (patches applied in topo order)
7
+ # Merge: sequential (patches applied in topo order)
8
8
  #
9
9
  # Use with: compose build <feature-code> --team feature
10
- # Customize: Copy to your project's pipelines/ as team-feature.stratum.yaml and edit.
10
+ # Customize: Copy BOTH team-feature.stratum.yaml AND team-feature.profiles.json into
11
+ # your project's pipelines/ and edit. Copying only the YAML is a trap:
12
+ # a project-local spec wins resolution, but profiles load only from an
13
+ # ADJACENT sidecar and fail open — so the tool restrictions vanish.
14
+ #
15
+ # COMP-PIPELINE-QUARANTINE: re-authored from v0.3 to TS v1.
16
+ # - `parallel_dispatch` + `source`/`intent_template` becomes a `fanout:` block
17
+ # with `over`/`dispatch: consumer`/`steps`, matching the construct the build
18
+ # conversion settled on. The per-item prompt reads `${item}` rather than
19
+ # `{task.*}`, so the item's own fields (id, description, files_owned,
20
+ # files_read) travel as data instead of being string-substituted.
21
+ # - Agent PROFILE strings move to team-feature.profiles.json — v1 accepts only
22
+ # the bare `claude`/`codex` literals, and compose re-applies the profiles at
23
+ # invocation.
24
+ # - `no_file_conflicts(...)` is not an engine predicate; file-ownership
25
+ # exclusivity is stated as a hard rule in the decompose prompt (as the build
26
+ # pipeline's own decompose step does) and remains enforced compose-side.
27
+ # - `retries: 2` -> `attempts: 3`.
28
+ # - An `execute_merge` gate was ADDED after the worktree fanout: the engine
29
+ # requires one (CONSUMER_WORKTREE_GATE_REQUIRED) and the v0.3 preset had none,
30
+ # so merging per-task worktree patches was never a decision point.
11
31
 
12
- version: "0.3"
32
+ version: 1
13
33
 
14
34
  contracts:
15
35
  TaskGraph:
16
- tasks:
17
- type: array
18
- values: [{type: object}]
19
- VerifyResult:
20
- tests_pass: {type: string}
21
- summary: {type: string}
36
+ tasks: object[]
22
37
 
23
- workflow:
24
- name: team-feature
25
- description: "Multi-agent parallel feature implementation"
26
- input:
27
- featureCode:
28
- type: string
29
- required: true
30
- description:
31
- type: string
32
- required: true
38
+ TaskResult:
39
+ outcome: string
40
+ summary: string
41
+ files_changed: string[]?
42
+
43
+ VerifyResult:
44
+ tests_pass: string
45
+ summary: string
33
46
 
34
47
  flows:
35
- team-feature:
48
+ entry: team_feature
49
+ team_feature:
36
50
  input:
37
- featureCode: {type: string}
38
- description: {type: string}
39
- output: VerifyResult
51
+ featureCode: string
52
+ description: string
53
+ output:
54
+ from: "${verify.output}"
55
+ contract: VerifyResult
56
+ # Required by the engine once any gate declares on_revise, since a revise edge
57
+ # is what makes a flow able to loop (GATE_REVISE_REQUIRES_MAX_ROUNDS).
58
+ max_rounds: 10
40
59
  steps:
41
60
  - id: decompose
42
- type: decompose
43
- agent: "claude:orchestrator"
44
- intent: >
45
- Read the feature description and any existing plan/blueprint docs.
46
- Break down this feature into parallel implementation tasks.
47
- Each task must have:
61
+ agent: claude
62
+ do: >
63
+ Read the description for ${input.featureCode} (${input.description}) and
64
+ any existing plan/blueprint docs. Break the feature down into parallel
65
+ implementation tasks. Each task must have:
48
66
  - id: unique short identifier
49
67
  - description: what to implement
50
68
  - files_owned: list of files this task may create or modify
@@ -52,54 +70,63 @@ flows:
52
70
  - depends_on: list of task ids that must complete first (empty if independent)
53
71
 
54
72
  Rules:
55
- - No two tasks may share files_owned (each file has exactly one owner)
73
+ - No two tasks may share files_owned (each file has exactly one owner).
74
+ Reject the decomposition and redo it if any file would have two owners.
56
75
  - Minimize dependencies — prefer independent parallel tasks
57
76
  - Each task should be completable in one focused session
58
77
  - Target 2-4 tasks for a typical feature
59
- inputs:
60
- featureCode: "$.input.featureCode"
61
- description: "$.input.description"
62
- output_contract: TaskGraph
78
+ out: TaskGraph
63
79
  ensure:
64
- - "len(result.tasks) >= 1"
65
- - "len(result.tasks) <= 6"
66
- - "no_file_conflicts(result.tasks)"
67
- retries: 2
80
+ - expr: "len(result.tasks) >= 1"
81
+ - expr: "len(result.tasks) <= 6"
82
+ attempts: 3
68
83
 
69
84
  - id: execute
70
- type: parallel_dispatch
71
- source: "$.steps.decompose.output.tasks"
72
- agent: "claude:implementer"
73
- max_concurrent: 3
74
- isolation: worktree
75
- require: all
76
- merge: sequential_apply
77
- intent_template: >
78
- Implement this task using TDD. Write the test first, watch it fail,
79
- implement, watch it pass.
80
-
81
- Task: {task.description}
82
- You own these files (may create/modify): {task.files_owned}
83
- You may read (but NOT modify): {task.files_read}
85
+ after: [decompose]
86
+ fanout:
87
+ over: "${decompose.output.tasks}"
88
+ dispatch: consumer
89
+ concurrency: 3
90
+ isolation: worktree
91
+ require: all
92
+ merge: sequential
93
+ steps:
94
+ - agent: claude
95
+ do: >
96
+ Implement the task described by ${item} using TDD. Write the test
97
+ first, watch it fail, implement, and watch it pass. Honor the
98
+ item's id, description, files_owned (you may create/modify these)
99
+ and files_read (you may read but NOT modify these).
100
+ Return {outcome, summary, files_changed}.
101
+ out: TaskResult
84
102
 
85
- Feature: {task.id}
86
- depends_on: [decompose]
103
+ # Engine invariant (CONSUMER_WORKTREE_GATE_REQUIRED): a consumer worktree
104
+ # fanout must be followed by an unconditional gate. The v0.3 preset had no
105
+ # such step — it declared `merge: sequential_apply` and moved straight on —
106
+ # so the merge of per-task worktree patches was never a decision point.
107
+ # This is the same execute -> execute_merge pairing build.stratum.yaml uses.
108
+ - id: execute_merge
109
+ after: [execute]
110
+ gate:
111
+ on_approve: verify
112
+ on_revise: execute
113
+ on_kill: null
114
+ max_rounds: 10
87
115
 
88
116
  - id: verify
89
- agent: "claude:orchestrator"
90
- depends_on: [execute]
91
- intent: >
92
- All implementation tasks are complete and merged. Run the test suite
93
- to verify everything works together. Check that:
117
+ after: [execute_merge]
118
+ agent: claude
119
+ do: >
120
+ All implementation tasks for ${input.featureCode} are complete and
121
+ merged. Run the test suite to verify everything works together. Check
122
+ that:
94
123
  1. All tests pass
95
124
  2. No merge conflicts remain
96
- 3. The feature matches the original task description
125
+ 3. The feature matches the original description
97
126
 
98
127
  Report tests_pass as "true" or "false" with details.
99
- inputs:
100
- featureCode: "$.input.featureCode"
101
- output_contract: VerifyResult
128
+ out: VerifyResult
102
129
  ensure:
103
- - "result.tests_pass == 'true'"
104
- - "result.summary != ''"
105
- retries: 2
130
+ - expr: "result.tests_pass == 'true'"
131
+ - expr: "len(result.summary) > 0"
132
+ attempts: 3
@@ -0,0 +1,6 @@
1
+ {
2
+ "_comment": "COMP-PIPELINE-QUARANTINE: compose-owned agent profiles for team-research.stratum.yaml. The TS engine accepts only the literal claude|codex agent, so the profile strings (tool restrictions + model tier) that the v0.3->v1 conversion stripped live here, keyed by step id, and are applied compose-side at invocation (lib/build.js loadPipelineProfiles). These are load-bearing, not cosmetic: the explore fanout runs at isolation:none, so without the read-only restriction its explorers would hold full write capability while claiming to be read-only exploration.",
3
+ "plan": "claude:orchestrator",
4
+ "explore": "claude:read-only-reviewer",
5
+ "synthesize": "claude:orchestrator"
6
+ }
@@ -1,108 +1,117 @@
1
1
  # TEAM PRESET: research
2
2
  #
3
3
  # Purpose: Parallel exploration for cold-start discovery
4
- # Pattern: Triageparallel_dispatch explorers → synthesize findings
5
- # Capability: codebase/docs use read-only-reviewer, web uses read-only-researcher
4
+ # Pattern: Planfanout explorers → synthesize findings
5
+ # Capability: ALL explorers run read-only-reviewer (see the limitation note below)
6
6
  # Isolation: none (read-only exploration)
7
7
  # Merge: Sequential synthesis step
8
8
  #
9
9
  # Use with: compose build <feature-code> --team research
10
- # Customize: Copy to your project's pipelines/ as team-research.stratum.yaml and edit.
11
-
12
- version: "0.3"
10
+ # Customize: Copy BOTH team-research.stratum.yaml AND team-research.profiles.json into
11
+ # your project's pipelines/ and edit. Copying only the YAML is a trap:
12
+ # a project-local spec wins resolution, but profiles load only from an
13
+ # ADJACENT sidecar and fail open — so the tool restrictions vanish.
14
+ #
15
+ # COMP-PIPELINE-QUARANTINE: re-authored from v0.3 to TS v1.
16
+ # - `parallel_dispatch` + `source`/`intent_template`/`output_fields` becomes a
17
+ # `fanout:` block with `over`/`dispatch: consumer`/`steps`, matching the
18
+ # construct the build conversion settled on. The per-item prompt reads
19
+ # `${item}` instead of `{task.*}`.
20
+ # - Agent PROFILE strings (`claude:orchestrator`, `claude:read-only-reviewer`)
21
+ # are not engine values — v1 accepts only the bare `claude`/`codex` literals.
22
+ # They move to team-research.profiles.json, keyed by step id, and compose
23
+ # re-applies them at invocation. Dropping them instead would silently hand
24
+ # read-only explorers full write capability.
25
+ # - `retries: N` -> `attempts: N + 1`.
26
+ #
27
+ # KNOWN LIMITATION, inherited from v0.3 and NOT introduced here: the header used
28
+ # to claim the web lane runs `read-only-researcher`, but a consumer fanout binds
29
+ # ONE profile for the whole step (lib/build.js resolves it per fanout step, not
30
+ # per item), so every explorer gets `explore`'s profile. read-only-reviewer has
31
+ # no WebSearch/WebFetch, so the web task cannot actually search the web. The
32
+ # claim has been corrected rather than left as an aspiration; giving the lanes
33
+ # distinct capabilities needs either per-item profile resolution or three
34
+ # separate steps, which is a redesign.
13
35
 
14
36
  contracts:
15
37
  ResearchTaskList:
16
- tasks:
17
- type: array
18
- values: [{type: object}]
19
- topic: {type: string}
38
+ tasks: object[]
39
+ topic: string
40
+
20
41
  ExplorerFindings:
21
- sources: {type: string}
22
- patterns: {type: string}
23
- open_questions: {type: string}
42
+ sources: string
43
+ patterns: string
44
+ open_questions: string
45
+
24
46
  ResearchResult:
25
- synthesis: {type: string}
26
- recommendations: {type: string}
27
- summary: {type: string}
47
+ synthesis: string
48
+ recommendations: string
49
+ summary: string
28
50
 
29
- workflow:
30
- name: team-research
31
- description: "Parallel multi-source research and synthesis"
32
- input:
33
- featureCode:
34
- type: string
35
- required: true
36
- description:
37
- type: string
38
- required: true
51
+ version: 1
39
52
 
40
53
  flows:
41
- team-research:
54
+ entry: team_research
55
+ team_research:
42
56
  input:
43
- featureCode: {type: string}
44
- description: {type: string}
45
- output: ResearchResult
57
+ featureCode: string
58
+ description: string
59
+ output:
60
+ from: "${synthesize.output}"
61
+ contract: ResearchResult
46
62
  steps:
47
63
  - id: plan
48
- agent: "claude:orchestrator"
49
- intent: >
50
- Plan the research for this feature. Read the feature description
51
- and any existing docs. Produce a task list with 3 research tasks:
64
+ agent: claude
65
+ do: >
66
+ Plan the research for ${input.featureCode}. Read the feature description
67
+ (${input.description}) and any existing docs. Produce a task list with
68
+ exactly 3 research tasks:
52
69
 
53
- 1. id: "codebase", agent: "claude:read-only-reviewer"
54
- - Explore the local codebase for relevant patterns, files, conventions
55
- 2. id: "web", agent: "claude:read-only-researcher"
56
- - Search the web for best practices, library docs, similar implementations
57
- 3. id: "docs", agent: "claude:read-only-reviewer"
58
- - Read local docs, READMEs, specs, ADRs for relevant context
70
+ 1. id: "codebase" explore the local codebase for relevant patterns,
71
+ files and conventions
72
+ 2. id: "web" — search the web for best practices, library docs and
73
+ similar implementations
74
+ 3. id: "docs" — read local docs, READMEs, specs and ADRs for context
59
75
 
60
76
  Each task must have: id, description, agent.
61
77
  Also output the research topic derived from the feature description.
62
- inputs:
63
- featureCode: "$.input.featureCode"
64
- description: "$.input.description"
65
- output_contract: ResearchTaskList
78
+ out: ResearchTaskList
66
79
  ensure:
67
- - "len(result.tasks) == 3"
68
- retries: 2
80
+ - expr: "len(result.tasks) == 3"
81
+ attempts: 3
69
82
 
70
83
  - id: explore
71
- type: parallel_dispatch
72
- source: "$.steps.plan.output.tasks"
73
- agent: "claude:read-only-reviewer"
74
- max_concurrent: 3
75
- isolation: none
76
- require: all
77
- intent_template: >
78
- Research this topic: {task.description}
79
-
80
- Find relevant sources, patterns, and open questions.
81
- List sources with file:line references (for code) or URLs (for web).
82
- Note patterns that could inform the implementation.
83
- List open questions that need answers before implementation.
84
- output_fields:
85
- sources: {type: string}
86
- patterns: {type: string}
87
- open_questions: {type: string}
88
- ensure:
89
- - "result.sources is not None"
90
- depends_on: [plan]
84
+ after: [plan]
85
+ fanout:
86
+ over: "${plan.output.tasks}"
87
+ dispatch: consumer
88
+ concurrency: 3
89
+ isolation: none
90
+ require: all
91
+ merge: sequential
92
+ steps:
93
+ - agent: claude
94
+ do: >
95
+ Research the topic described by ${item}. Honor its id, description
96
+ and agent fields. Find relevant sources, patterns and open
97
+ questions. List sources with file:line references (for code) or
98
+ URLs (for web). Note patterns that could inform the
99
+ implementation. List open questions that need answers before
100
+ implementation.
101
+ out: ExplorerFindings
91
102
 
92
103
  - id: synthesize
93
- agent: "claude:orchestrator"
94
- depends_on: [explore]
95
- intent: >
96
- Synthesize findings from all research explorers. Cross-reference
97
- sources. Identify consensus patterns and contradictions. Produce
98
- actionable recommendations for the feature implementation.
99
- Write a one-sentence summary.
100
- inputs:
101
- research_results: "$.steps.explore.output"
102
- topic: "$.steps.plan.output.topic"
103
- output_contract: ResearchResult
104
+ after: [explore]
105
+ agent: claude
106
+ do: >
107
+ Synthesize the findings from all research explorers (${explore.output})
108
+ on the topic ${plan.output.topic}. Cross-reference sources. Identify
109
+ consensus patterns and contradictions. Produce actionable
110
+ recommendations for implementing ${input.featureCode}. Write a
111
+ one-sentence summary.
112
+ out: ResearchResult
104
113
  ensure:
105
- - "result.synthesis != ''"
106
- - "result.recommendations != ''"
107
- - "result.summary != ''"
108
- retries: 2
114
+ - expr: "len(result.synthesis) > 0"
115
+ - expr: "len(result.recommendations) > 0"
116
+ - expr: "len(result.summary) > 0"
117
+ attempts: 3
@@ -0,0 +1,8 @@
1
+ {
2
+ "_comment": "COMP-PIPELINE-QUARANTINE: compose-owned agent profiles for team-review.stratum.yaml. The TS engine accepts only the literal claude|codex agent, so the profile strings (tool restrictions + model tier) that the v0.3->v1 conversion stripped live here, keyed by step id, and are applied compose-side at invocation (lib/build.js loadPipelineProfiles). The review_lenses fanout runs at isolation:none and MUST bind the read-only-reviewer restriction — without it the lenses would hold write capability while the preset advertises read-only review.",
3
+ "_reduceSteps": ["merge"],
4
+ "_reduceSteps_comment": "ReviewResult-out steps that MERGE/deduplicate rather than review. They get review normalization but never the review scaffold (H1, mirroring build.profiles.json).",
5
+ "triage": "claude:orchestrator",
6
+ "review_lenses": "claude:read-only-reviewer",
7
+ "merge": "claude:orchestrator"
8
+ }
@@ -1,56 +1,71 @@
1
1
  # TEAM PRESET: review
2
2
  #
3
3
  # Purpose: Parallel multi-lens review after implementation
4
- # Pattern: Triage → parallel_dispatch reviewers → merge findings → gate
4
+ # Pattern: Triage → fanout reviewers → merge findings → gate
5
5
  # Capability: Agents use read-only-reviewer profile (Read/Grep/Glob/Agent only)
6
6
  # Isolation: none (reviewers read shared state, don't modify)
7
7
  # Merge: Deduplication step consolidates findings
8
8
  #
9
9
  # Use with: compose build <feature-code> --team review
10
- # Customize: Copy to your project's pipelines/ as team-review.stratum.yaml and edit.
10
+ # Customize: Copy BOTH team-review.stratum.yaml AND team-review.profiles.json into
11
+ # your project's pipelines/ and edit. Copying only the YAML is a trap:
12
+ # a project-local spec wins resolution, but profiles load only from an
13
+ # ADJACENT sidecar and fail open — so the tool restrictions vanish, and
14
+ # the review gate stops seeing its reducer's result entirely.
15
+ #
16
+ # COMP-PIPELINE-QUARANTINE: re-authored from v0.3 to TS v1.
17
+ # - `parallel_dispatch` becomes a `fanout:` block; the per-lens prompt reads
18
+ # `${item}` and honors its lens_name/lens_focus/confidence_gate/exclusions
19
+ # fields rather than string-substituting them.
20
+ # - Agent PROFILE strings move to team-review.profiles.json. Load-bearing here:
21
+ # the lenses run at isolation:none, so losing the read-only restriction would
22
+ # hand "read-only reviewers" full write capability.
23
+ # - The merge step's `ensure: result.clean == true` is REMOVED and the
24
+ # cleanliness decision becomes a gate, mirroring what the build conversion
25
+ # learned (build.stratum.yaml, note I1): a reducer cannot converge by
26
+ # retrying, because re-running it re-merges the SAME frozen lens outputs.
27
+ # Keeping the ensure would spin the reducer until its attempts ran out and
28
+ # then fail the flow, with no chance of the code being fixed in between.
29
+ # The gate is named `review_gate` because compose resolves THAT id
30
+ # programmatically — clean approves, dirty runs the corrective fixer and
31
+ # revises back to triage so the lenses re-run on fixed code. A differently
32
+ # named gate is inert, which is what the first draft shipped.
33
+ # - `retries: 2` -> `attempts: 3`.
11
34
 
12
- version: "0.3"
35
+ version: 1
13
36
 
14
37
  contracts:
15
38
  TriageResult:
16
- tasks:
17
- type: array
18
- values: [{type: object}]
19
- diff: {type: string}
39
+ tasks: object[]
40
+ diff: string
41
+
20
42
  # Canonical schema — STRAT-CLAUDE-EFFORT-PARITY. Local MergedReviewResult removed.
21
43
  ReviewResult:
22
- clean: {type: boolean}
23
- summary: {type: string}
24
- findings: {type: array}
25
- meta: {type: object}
26
- lenses_run: {type: array}
27
- auto_fixes: {type: array}
28
- asks: {type: array}
29
-
30
- workflow:
31
- name: team-review
32
- description: "Parallel multi-lens code review"
33
- input:
34
- featureCode:
35
- type: string
36
- required: true
37
- description:
38
- type: string
39
- required: true
44
+ clean: boolean
45
+ summary: string
46
+ findings: object[]
47
+ meta: object
48
+ lenses_run: string[]
49
+ auto_fixes: object[]
50
+ asks: object[]
40
51
 
41
52
  flows:
42
- team-review:
53
+ entry: team_review
54
+ team_review:
43
55
  input:
44
- featureCode: {type: string}
45
- description: {type: string}
46
- output: ReviewResult
56
+ featureCode: string
57
+ description: string
58
+ output:
59
+ from: "${merge.output}"
60
+ contract: ReviewResult
61
+ max_rounds: 10
47
62
  steps:
48
63
  - id: triage
49
- agent: "claude:orchestrator"
50
- intent: >
51
- Gather the git diff for this feature and decide which review lenses
52
- to activate. Read the changed files. Produce a task list with one
53
- entry per lens. Each task must have:
64
+ agent: claude
65
+ do: >
66
+ Gather the git diff for ${input.featureCode} (${input.description}) and
67
+ decide which review lenses to activate. Read the changed files. Produce
68
+ a task list with one entry per lens. Each task must have:
54
69
  - id: lens name (e.g. "security", "performance", "architecture")
55
70
  - lens_name: same as id
56
71
  - lens_focus: one-sentence description of what to look for
@@ -59,55 +74,58 @@ flows:
59
74
 
60
75
  Always include: security, performance, architecture.
61
76
  Include the full git diff in your output.
62
- inputs:
63
- featureCode: "$.input.featureCode"
64
- description: "$.input.description"
65
- output_contract: TriageResult
77
+ out: TriageResult
66
78
  ensure:
67
- - "len(result.tasks) >= 3"
68
- retries: 2
79
+ - expr: "len(result.tasks) >= 3"
80
+ attempts: 3
69
81
 
70
82
  - id: review_lenses
71
- type: parallel_dispatch
72
- source: "$.steps.triage.output.tasks"
73
- agent: "claude:read-only-reviewer"
74
- max_concurrent: 4
75
- isolation: none
76
- require: all
77
- intent_template: >
78
- You are reviewing a code diff as the {lens_name} reviewer.
79
-
80
- Focus: {lens_focus}
81
- Confidence gate: only report findings with confidence >= {confidence_gate}/10.
82
- Exclusions: do NOT flag {exclusions}.
83
+ after: [triage]
84
+ fanout:
85
+ over: "${triage.output.tasks}"
86
+ dispatch: consumer
87
+ concurrency: 4
88
+ isolation: none
89
+ require: all
90
+ merge: sequential
91
+ steps:
92
+ - agent: claude
93
+ do: >
94
+ Review the code diff as the reviewer described by ${item}. Honor
95
+ its lens_name, lens_focus, confidence_gate (only report findings
96
+ at or above that confidence) and exclusions (never flag those).
83
97
 
84
- Return JSON: { "clean": boolean, "findings": <ReviewResult finding items> }
85
- where each finding has: lens, file, line, severity (must-fix|should-fix|nit),
86
- finding (description), confidence (1-10), applied_gate (integer).
87
-
88
- If no issues found, return { "clean": true, "findings": [] }.
89
- output_fields:
90
- clean: {type: string}
91
- findings: {type: string}
92
- ensure:
93
- - "result.findings is not None"
94
- depends_on: [triage]
98
+ Return the canonical ReviewResult shape. Each finding has: lens,
99
+ file, line, severity (must-fix|should-fix|nit), finding
100
+ (description), confidence (1-10), applied_gate (integer).
101
+ If no issues are found, return clean=true with no findings.
102
+ out: ReviewResult
95
103
 
104
+ # Reducer: NO ensure by construction — see the header note. It consolidates,
105
+ # it does not judge, and it cannot fix anything by being retried.
96
106
  - id: merge
97
- agent: "claude:orchestrator"
98
- depends_on: [review_lenses]
99
- intent: >
100
- Consolidate ReviewResult arrays from all review lenses into a single
101
- canonical ReviewResult. Deduplicate findings (same file:line+lens,
102
- keep highest confidence; carry over its applied_gate). Rank by
103
- severity (must-fix first, then should-fix, then nit). Set clean=true
104
- only if zero must-fix AND zero should-fix findings remain. Write a
105
- one-sentence summary.
106
- inputs:
107
- review_results: "$.steps.review_lenses.output"
108
- reduce_mode: "true"
109
- output_contract: ReviewResult
110
- ensure:
111
- - "result.clean == True"
112
- - "result.summary != ''"
113
- retries: 2
107
+ after: [review_lenses]
108
+ agent: claude
109
+ do: >
110
+ Consolidate the ReviewResults from all review lenses
111
+ (${review_lenses.output}) into a single canonical ReviewResult.
112
+ Deduplicate findings (same file:line+lens, keep the highest confidence
113
+ and carry over its applied_gate). Rank by severity (must-fix first,
114
+ then should-fix, then nit). Set clean=true only if zero must-fix AND
115
+ zero should-fix findings remain. Write a one-sentence summary.
116
+ out: ReviewResult
117
+ attempts: 3
118
+
119
+ # The cleanliness decision, resolved PROGRAMMATICALLY by compose, not by a
120
+ # human. The gate MUST be called `review_gate`: lib/build.js keys the
121
+ # corrective-fixer path on that exact id. Named anything else (the first
122
+ # draft called it `merge_gate`) the gate is inert — approving it can
123
+ # complete the flow with clean:false, and revising re-reviews unchanged code
124
+ # because no fixer ever runs. Caught in review.
125
+ - id: review_gate
126
+ after: [merge]
127
+ gate:
128
+ on_approve: null
129
+ on_revise: triage
130
+ on_kill: null
131
+ max_rounds: 10