@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.
- package/.claude/skills/compose/SKILL.md +42 -88
- package/.compose-deps.json +1 -13
- package/README.md +72 -5
- package/bin/compose.js +754 -347
- package/bin/git-hooks/pre-push.template +29 -0
- package/bin/judgment-import.js +7 -0
- package/bin/judgment-migrate.js +387 -0
- package/contracts/comp-obs-contract.schema.json +9 -3
- package/contracts/feature-json.schema.json +5 -0
- package/contracts/fluid-record.schema.json +209 -0
- package/contracts/judgment-record.schema.json +425 -4
- package/contracts/lifecycle-backfill.schema.json +322 -0
- package/dist/assets/App-Z4MU-H_F.js +916 -0
- package/dist/assets/_baseUniq-ClWoCPFl.js +1 -0
- package/dist/assets/arc-DY26UIVo.js +1 -0
- package/dist/assets/architectureDiagram-Q4EWVU46-6Ggq4DqJ.js +36 -0
- package/dist/assets/blockDiagram-DXYQGD6D-CH3Ked0l.js +132 -0
- package/dist/assets/{browser-BSM23If2.js → browser-BWkrenen.js} +6 -6
- package/dist/assets/{c4Diagram-LMCZKHZV-DZf45Fbz.js → c4Diagram-AHTNJAMY-Bk8dYilu.js} +1 -1
- package/dist/assets/channel-SnZzzh7k.js +1 -0
- package/dist/assets/{chunk-JWPE2WC7-_7ujgd_Q.js → chunk-4BX2VUAB-BMR0XaAQ.js} +1 -1
- package/dist/assets/chunk-4TB4RGXK-JytR14a9.js +206 -0
- package/dist/assets/{chunk-XXDRQBXY-DfdVhbmA.js → chunk-55IACEB6-B4Q97BCP.js} +1 -1
- package/dist/assets/{chunk-VR4S4FIN-Dt9NZ67m.js → chunk-EDXVE4YY-R_qarkSf.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-BY4_PV5H.js → chunk-FMBD7UC4-C9s7KR9m.js} +1 -1
- package/dist/assets/chunk-OYMX7WX6-BySQzVxc.js +231 -0
- package/dist/assets/{chunk-2Q5K7J3B-Dn1spZYu.js → chunk-QZHKN3VN-DdpSYZsW.js} +1 -1
- package/dist/assets/{chunk-32BRIVSS-pURGrJDk.js → chunk-YZCP3GAM-iE_tzriw.js} +1 -1
- package/dist/assets/classDiagram-6PBFFD2Q-CBu92dSH.js +1 -0
- package/dist/assets/classDiagram-v2-HSJHXN6E-CBu92dSH.js +1 -0
- package/dist/assets/clone-DgklGjHm.js +1 -0
- package/dist/assets/{cose-bilkent-JH36ORCC-BieYif4o.js → cose-bilkent-S5V4N54A-BdlU6ZX_.js} +1 -1
- package/dist/assets/dagre-KV5264BT-Cp3F5KTn.js +4 -0
- package/dist/assets/diagram-5BDNPKRD-DiR6_2q_.js +10 -0
- package/dist/assets/diagram-G4DWMVQ6-w0i-p5HX.js +24 -0
- package/dist/assets/diagram-MMDJMWI5-tIHhwUv3.js +43 -0
- package/dist/assets/diagram-TYMM5635-BAeY3B19.js +24 -0
- package/dist/assets/erDiagram-SMLLAGMA-Ckx_Knko.js +85 -0
- package/dist/assets/flowDiagram-DWJPFMVM-DeoNka6J.js +162 -0
- package/dist/assets/ganttDiagram-T4ZO3ILL-BmGnFbEg.js +292 -0
- package/dist/assets/gitGraphDiagram-UUTBAWPF-Dk48IHsx.js +106 -0
- package/dist/assets/graph-BNzKGvoy.js +1 -0
- package/dist/assets/graph-CI_1htl0.js +331 -0
- package/dist/assets/index-BEfrNBp8.js +123 -0
- package/dist/assets/index-yyrA5OZd.css +1 -0
- package/dist/assets/infoDiagram-42DDH7IO-BRf827i0.js +2 -0
- package/dist/assets/{ishikawaDiagram-FXEZZL3T-CzEB9fQS.js → ishikawaDiagram-UXIWVN3A-0kCZaeCM.js} +5 -5
- package/dist/assets/{journeyDiagram-5HDEW3XC-Bz8TCdz2.js → journeyDiagram-VCZTEJTY-rvU7ayRt.js} +1 -1
- package/dist/assets/{kanban-definition-HUTT4EX6-tozrMoV_.js → kanban-definition-6JOO6SKY-DpQwX1C5.js} +7 -7
- package/dist/assets/katex-DkKDou_j.js +257 -0
- package/dist/assets/layout-BI8cXFPI.js +1 -0
- package/dist/assets/{linear-Ck7gpa5N.js → linear-a0glcDiw.js} +1 -1
- package/dist/assets/min-vPHfnXcC.js +1 -0
- package/dist/assets/{mindmap-definition-LN4V7U3C-DTcHO0DJ.js → mindmap-definition-QFDTVHPH-D14eF-7C.js} +7 -7
- package/dist/assets/mobile-B7m9EO9D.js +17 -0
- package/dist/assets/pieDiagram-DEJITSTG-Cno-gETh.js +30 -0
- package/dist/assets/quadrantDiagram-34T5L4WZ-BUQM1Hfm.js +7 -0
- package/dist/assets/{requirementDiagram-TGXJPOKE-bnI2zJeT.js → requirementDiagram-MS252O5E-pOXlN2-q.js} +3 -3
- package/dist/assets/sankeyDiagram-XADWPNL6-Crynd3_b.js +10 -0
- package/dist/assets/sequenceDiagram-FGHM5R23-D9fZdCM8.js +157 -0
- package/dist/assets/stateDiagram-FHFEXIEX-CW9qVec8.js +1 -0
- package/dist/assets/stateDiagram-v2-QKLJ7IA2-DkVLzHbY.js +1 -0
- package/dist/assets/{timeline-definition-FHXFAJF6-D267GQFF.js → timeline-definition-GMOUNBTQ-BcHzhm_8.js} +3 -3
- package/dist/assets/vennDiagram-DHZGUBPP-BfytJcWk.js +34 -0
- package/dist/assets/wardley-RL74JXVD-DLj-IjyB.js +162 -0
- package/dist/assets/wardleyDiagram-NUSXRM2D-Ds0Ue68c.js +20 -0
- package/dist/assets/xychartDiagram-5P7HB3ND-vjWDXFL6.js +7 -0
- package/dist/index.html +3 -3
- package/lib/agent-string.js +7 -5
- package/lib/append-integrity.js +81 -0
- package/lib/backfill-evidence.js +109 -0
- package/lib/bug-escalation.js +39 -4
- package/lib/build-stream-schema.js +3 -1
- package/lib/build-stream-writer.js +25 -0
- package/lib/build.js +1624 -195
- package/lib/canon-guard.js +245 -0
- package/lib/canon-override.js +196 -0
- package/lib/canon-registry.js +291 -0
- package/lib/cli-commands.js +144 -0
- package/lib/codex-preflight.js +50 -15
- package/lib/colleague/context.js +215 -0
- package/lib/colleague/writeback.js +95 -0
- package/lib/completion-gate.js +1421 -0
- package/lib/completion-writer.js +47 -47
- package/lib/consumer-fanout.js +105 -11
- package/lib/coverage-gate.js +200 -0
- package/lib/dir-lock.js +170 -0
- package/lib/dispatch-ledger.js +301 -0
- package/lib/dispatch-metrics.js +236 -0
- package/lib/experiment-judge.js +6 -1
- package/lib/feature-json.js +1 -1
- package/lib/feature-reconciler.js +8 -0
- package/lib/feature-validator.js +64 -1
- package/lib/feature-writer.js +66 -2
- package/lib/fluid/factory.js +167 -0
- package/lib/fluid/ideabox-dates.js +73 -0
- package/lib/fluid/ideabox-migrate.js +154 -0
- package/lib/fluid/ideabox-ops.js +585 -0
- package/lib/fluid/ideabox-view.js +146 -0
- package/lib/fluid/import-ideabox.js +186 -0
- package/lib/fluid/local-provider.js +606 -0
- package/lib/fluid/provider.js +684 -0
- package/lib/fluid/record-shape.js +214 -0
- package/lib/fluid/record-store.js +328 -0
- package/lib/fluid/render-ideabox.js +261 -0
- package/lib/fluid/schema.js +40 -0
- package/lib/fluid/smartmemory-provider.js +1695 -0
- package/lib/gsd.js +63 -14
- package/lib/guard-cli.js +175 -0
- package/lib/guard-custody.js +141 -0
- package/lib/guard-descriptors.js +530 -0
- package/lib/guard-enrol.js +254 -0
- package/lib/health-score.js +1 -1
- package/lib/hooks-status.js +32 -3
- package/lib/ideabox-cli.js +315 -0
- package/lib/ideabox.js +121 -21
- package/lib/judgment/store/index.js +166 -0
- package/lib/judgment/store/records.js +184 -25
- package/lib/judgment/trace.js +380 -0
- package/lib/judgment-attest.js +259 -0
- package/lib/judgment-decision-write.js +277 -0
- package/lib/judgment-decisions.js +466 -0
- package/lib/judgment-gen.js +375 -22
- package/lib/judgment-verify.js +153 -0
- package/lib/judgment-writer.js +2842 -262
- package/lib/lane-gate.js +2 -0
- package/lib/lifecycle-modes.js +4 -4
- package/lib/lineage.js +400 -0
- package/lib/local-claude-connector.js +250 -54
- package/lib/maya-client.js +302 -0
- package/lib/maya-config.js +53 -0
- package/lib/maya-identity.js +283 -0
- package/lib/mcp-enforcement.js +21 -35
- package/lib/migrate-anon.js +5 -0
- package/lib/migrate-roadmap.js +15 -0
- package/lib/new.js +13 -1
- package/lib/pipeline-compat.js +104 -0
- package/lib/policy-catalog.js +295 -0
- package/lib/policy-check.js +0 -0
- package/lib/process-termination.js +98 -0
- package/lib/resolve-workspace.js +5 -1
- package/lib/result-normalizer.js +428 -153
- package/lib/review-normalize.js +4 -0
- package/lib/roadmap-errors.js +65 -0
- package/lib/roadmap-preservers.js +24 -4
- package/lib/roadmap-residue.js +299 -0
- package/lib/smartmemory-client.js +614 -78
- package/lib/smartmemory-config.js +54 -0
- package/lib/smartmemory-ingest.js +19 -2
- package/lib/step-prompt.js +7 -6
- package/lib/stratum-engine.js +53 -4
- package/lib/stratum-mcp-client.js +391 -31
- package/lib/test-bootstrap.js +31 -0
- package/lib/tool-inventory.js +122 -0
- package/lib/version-check.js +91 -19
- package/lib/vision-writer.js +88 -1
- package/package.json +7 -6
- package/pipelines/bug-fix.stratum.yaml +205 -211
- package/pipelines/build-quick.profiles.json +12 -0
- package/pipelines/build-quick.stratum.yaml +263 -350
- package/pipelines/content.stratum.yaml +81 -77
- package/pipelines/coverage-sweep.stratum.yaml +49 -30
- package/pipelines/plan.stratum.yaml +76 -86
- package/pipelines/refactor.stratum.yaml +125 -125
- package/pipelines/research.stratum.yaml +56 -58
- package/pipelines/review-fix.profiles.json +6 -0
- package/pipelines/review-fix.stratum.yaml +110 -83
- package/presets/team-feature.profiles.json +6 -0
- package/presets/team-feature.stratum.yaml +93 -66
- package/presets/team-research.profiles.json +6 -0
- package/presets/team-research.stratum.yaml +89 -80
- package/presets/team-review.profiles.json +8 -0
- package/presets/team-review.stratum.yaml +98 -80
- package/scripts/cost-census.mjs +70 -0
- package/scripts/guard-sign/compose-guard-sign.sh +62 -0
- package/server/agent-health.js +22 -0
- package/server/agent-hooks.js +14 -1
- package/server/agent-server.js +5 -248
- package/server/agent-spawn.js +3 -4
- package/server/agent-workspace.js +294 -0
- package/server/build-routes.js +6 -5
- package/server/build-stream-bridge.js +53 -0
- package/server/cc-session-watcher.js +4 -1
- package/server/coalescing-buffer.js +7 -1
- package/server/completion-projection.js +228 -0
- package/server/compose-mcp-tools.js +124 -24
- package/server/compose-mcp.js +91 -790
- package/server/decision-event-emit.js +41 -2
- package/server/decision-event-id.js +17 -0
- package/server/decision-events-snapshot.js +3 -0
- package/server/design-routes.js +14 -8
- package/server/feature-scan.js +76 -2
- package/server/file-watcher.js +170 -21
- package/server/ideabox-routes.js +166 -224
- package/server/index.js +70 -100
- package/server/lifecycle-guard.js +240 -10
- package/server/lifecycle-phase-history.js +276 -0
- package/server/maya-routes.js +507 -0
- package/server/mcp-tool-defs.js +940 -0
- package/server/mcp-tool-policy.js +35 -3
- package/server/model-tiers.js +22 -5
- package/server/pipeline-routes.js +21 -11
- package/server/project-root.js +58 -19
- package/server/remote-utils.js +3 -1
- package/server/schema-validator.js +7 -1
- package/server/session-manager.js +5 -6
- package/server/session-routes.js +3 -1
- package/server/stratum-client.js +57 -10
- package/server/stratum-sync.js +6 -3
- package/server/summarizer.js +3 -4
- package/server/supervisor.js +0 -1
- package/server/vision-routes.js +208 -98
- package/server/vision-server.js +86 -23
- package/server/vision-store.js +60 -6
- package/server/vision-utils.js +3 -4
- package/server/workspace-activity.js +18 -0
- package/server/workspace-middleware.js +2 -2
- package/server/workspace-runtime.js +243 -0
- package/server/worktree-gc.js +1 -0
- package/dist/assets/App-BG3ngu8H.js +0 -896
- package/dist/assets/abnfDiagram-VRR7QNED-CjB_sD3D.js +0 -1
- package/dist/assets/arc-_v4hR_uD.js +0 -1
- package/dist/assets/architectureDiagram-ZJ3FMSHR-DreJmzXQ.js +0 -36
- package/dist/assets/blockDiagram-677ZJIJ3-BG9-c0O1.js +0 -132
- package/dist/assets/channel-B3U5wFAT.js +0 -1
- package/dist/assets/chunk-EX3LRPZG-DdELs1qP.js +0 -231
- package/dist/assets/chunk-MOJQB5TN-D-ky35G-.js +0 -88
- package/dist/assets/chunk-RYQCIY6F-Dag_kVlO.js +0 -1
- package/dist/assets/chunk-V7JOEXUC-BtewURat.js +0 -206
- package/dist/assets/classDiagram-OUVF2IWQ-B6fCN-ht.js +0 -1
- package/dist/assets/classDiagram-v2-EOCWNBFH-B6fCN-ht.js +0 -1
- package/dist/assets/cynefin-VYW2F7L2-CT2BA6KE.js +0 -178
- package/dist/assets/cynefinDiagram-TSTJHNR4-Bh6exbyg.js +0 -62
- package/dist/assets/dagre-VKFMJZFB-aXMLSmQL.js +0 -4
- package/dist/assets/diagram-FQU43EPY-Dr7JAOuQ.js +0 -3
- package/dist/assets/diagram-G47NLZAW-DUvA3FQK.js +0 -24
- package/dist/assets/diagram-NH7WQ7WH-BQUARqcu.js +0 -24
- package/dist/assets/diagram-OA4YK3LP-dDUc1zHi.js +0 -30
- package/dist/assets/diagram-WEI45ONY-B2h5Qlb1.js +0 -41
- package/dist/assets/ebnfDiagram-CCIWWBDH-DThRGupB.js +0 -1
- package/dist/assets/erDiagram-Q63AITRT-BUCsprO2.js +0 -85
- package/dist/assets/flowDiagram-23GEKE2U-DXtNNi6r.js +0 -156
- package/dist/assets/ganttDiagram-NO4QXBWP-D4zbBHh_.js +0 -292
- package/dist/assets/gitGraphDiagram-IHSO6WYX-DpoQws0W.js +0 -106
- package/dist/assets/graph-BXPQrYYB.js +0 -331
- package/dist/assets/graph-C9eacEi8.js +0 -1
- package/dist/assets/index-3ZH5eMcZ.js +0 -119
- package/dist/assets/index-LIwREYgH.css +0 -1
- package/dist/assets/infoDiagram-FWYZ7A6U-Bbas2GAo.js +0 -2
- package/dist/assets/katex-C5jXJg4s.js +0 -257
- package/dist/assets/layout-DEXfKzaS.js +0 -1
- package/dist/assets/map-Czzmt4hB.js +0 -1
- package/dist/assets/mobile-CaoXUwAr.js +0 -17
- package/dist/assets/pegDiagram-2B236MQR-CHiINrNy.js +0 -1
- package/dist/assets/pieDiagram-ENE6RG2P-CfS4YFlR.js +0 -39
- package/dist/assets/quadrantDiagram-ABIIQ3AL-CadesS9w.js +0 -7
- package/dist/assets/railroadDiagram-RFXS5EU6-CgWEspBN.js +0 -1
- package/dist/assets/sankeyDiagram-HTMAVEWB-YWKFgOGw.js +0 -40
- package/dist/assets/sequenceDiagram-DBY2YBRQ-BvkNOyF9.js +0 -162
- package/dist/assets/sizeCapture-X5ZJPWSS-DlFPA2yO.js +0 -1
- package/dist/assets/stateDiagram-2N3HPSRC-h8NIx0kQ.js +0 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-DjPgZtJ9.js +0 -1
- package/dist/assets/swimlanes-5IMT3BWC-CT5n22kG.js +0 -2
- package/dist/assets/swimlanesDiagram-G3AALYLV-Dn318Bhq.js +0 -8
- package/dist/assets/vennDiagram-L72KCM5P-Dj-wWLYG.js +0 -34
- package/dist/assets/wardleyDiagram-EHGQE667-BxCeYxkG.js +0 -78
- package/dist/assets/xychartDiagram-FW5EYKEG-DMFqWn7z.js +0 -7
- package/lib/staleness.js +0 -87
- 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:
|
|
7
|
+
# Merge: sequential (patches applied in topo order)
|
|
8
8
|
#
|
|
9
9
|
# Use with: compose build <feature-code> --team feature
|
|
10
|
-
# Customize: Copy
|
|
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:
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
48
|
+
entry: team_feature
|
|
49
|
+
team_feature:
|
|
36
50
|
input:
|
|
37
|
-
featureCode:
|
|
38
|
-
description:
|
|
39
|
-
output:
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
86
|
-
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
All implementation tasks are complete and
|
|
93
|
-
to verify everything works together. Check
|
|
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
|
|
125
|
+
3. The feature matches the original description
|
|
97
126
|
|
|
98
127
|
Report tests_pass as "true" or "false" with details.
|
|
99
|
-
|
|
100
|
-
featureCode: "$.input.featureCode"
|
|
101
|
-
output_contract: VerifyResult
|
|
128
|
+
out: VerifyResult
|
|
102
129
|
ensure:
|
|
103
|
-
- "result.tests_pass == 'true'"
|
|
104
|
-
- "result.summary
|
|
105
|
-
|
|
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:
|
|
5
|
-
# Capability:
|
|
4
|
+
# Pattern: Plan → fanout 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
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
topic: {type: string}
|
|
38
|
+
tasks: object[]
|
|
39
|
+
topic: string
|
|
40
|
+
|
|
20
41
|
ExplorerFindings:
|
|
21
|
-
sources:
|
|
22
|
-
patterns:
|
|
23
|
-
open_questions:
|
|
42
|
+
sources: string
|
|
43
|
+
patterns: string
|
|
44
|
+
open_questions: string
|
|
45
|
+
|
|
24
46
|
ResearchResult:
|
|
25
|
-
synthesis:
|
|
26
|
-
recommendations:
|
|
27
|
-
summary:
|
|
47
|
+
synthesis: string
|
|
48
|
+
recommendations: string
|
|
49
|
+
summary: string
|
|
28
50
|
|
|
29
|
-
|
|
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
|
-
|
|
54
|
+
entry: team_research
|
|
55
|
+
team_research:
|
|
42
56
|
input:
|
|
43
|
-
featureCode:
|
|
44
|
-
description:
|
|
45
|
-
output:
|
|
57
|
+
featureCode: string
|
|
58
|
+
description: string
|
|
59
|
+
output:
|
|
60
|
+
from: "${synthesize.output}"
|
|
61
|
+
contract: ResearchResult
|
|
46
62
|
steps:
|
|
47
63
|
- id: plan
|
|
48
|
-
agent:
|
|
49
|
-
|
|
50
|
-
Plan the research for
|
|
51
|
-
and any existing docs. Produce a task list with
|
|
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"
|
|
54
|
-
|
|
55
|
-
2. id: "web",
|
|
56
|
-
|
|
57
|
-
3. id: "docs",
|
|
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
|
-
|
|
63
|
-
featureCode: "$.input.featureCode"
|
|
64
|
-
description: "$.input.description"
|
|
65
|
-
output_contract: ResearchTaskList
|
|
78
|
+
out: ResearchTaskList
|
|
66
79
|
ensure:
|
|
67
|
-
- "len(result.tasks) == 3"
|
|
68
|
-
|
|
80
|
+
- expr: "len(result.tasks) == 3"
|
|
81
|
+
attempts: 3
|
|
69
82
|
|
|
70
83
|
- id: explore
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
Synthesize findings from all research explorers.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
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 →
|
|
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
|
|
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:
|
|
35
|
+
version: 1
|
|
13
36
|
|
|
14
37
|
contracts:
|
|
15
38
|
TriageResult:
|
|
16
|
-
tasks:
|
|
17
|
-
|
|
18
|
-
|
|
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:
|
|
23
|
-
summary:
|
|
24
|
-
findings:
|
|
25
|
-
meta:
|
|
26
|
-
lenses_run:
|
|
27
|
-
auto_fixes:
|
|
28
|
-
asks:
|
|
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
|
-
|
|
53
|
+
entry: team_review
|
|
54
|
+
team_review:
|
|
43
55
|
input:
|
|
44
|
-
featureCode:
|
|
45
|
-
description:
|
|
46
|
-
output:
|
|
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:
|
|
50
|
-
|
|
51
|
-
Gather the git diff for
|
|
52
|
-
to activate. Read the changed files. Produce
|
|
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
|
-
|
|
63
|
-
featureCode: "$.input.featureCode"
|
|
64
|
-
description: "$.input.description"
|
|
65
|
-
output_contract: TriageResult
|
|
77
|
+
out: TriageResult
|
|
66
78
|
ensure:
|
|
67
|
-
- "len(result.tasks) >= 3"
|
|
68
|
-
|
|
79
|
+
- expr: "len(result.tasks) >= 3"
|
|
80
|
+
attempts: 3
|
|
69
81
|
|
|
70
82
|
- id: review_lenses
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
Consolidate
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
severity (must-fix first,
|
|
104
|
-
only if zero must-fix AND
|
|
105
|
-
one-sentence summary.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|