@openplaybooks/converge 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +131 -0
- package/dist/index.js +212278 -0
- package/package.json +54 -0
- package/skills/converge-control/SKILL.md +208 -0
- package/skills/converge-control/reference/cli.md +128 -0
- package/skills/converge-control/reference/events.md +165 -0
- package/skills/converge-control/troubleshooting/playbook.md +367 -0
- package/skills/converge-development/SKILL.md +303 -0
- package/skills/converge-development/reference/framework-map.md +294 -0
- package/skills/converge-development/reference/observability.md +132 -0
- package/skills/converge-development/troubleshooting/playbook.md +213 -0
- package/skills/converge-planning/SKILL.md +302 -0
- package/skills/converge-planning/references/anti-patterns.md +35 -0
- package/skills/converge-planning/references/model.md +317 -0
- package/skills/converge-planning/references/patterns.md +169 -0
- package/skills/converge-planning/references/phases.md +168 -0
- package/skills/converge-planning/references/schema.md +313 -0
- package/skills/converge-planning/references/static-dynamic.md +38 -0
- package/skills/converge-planning/references/tests.md +91 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Phases Reference
|
|
2
|
+
|
|
3
|
+
Step-by-step execution guide for converge-planning. Read during active planning when you need detailed instructions with commands.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Process Overview
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
1. EXTRACT GOAL → clear one-sentence deliverable goal
|
|
11
|
+
2. GATHER REQS → exhaustive list of must-haves, should-haves, constraints, non-goals
|
|
12
|
+
3. DECOMPOSE → sub-goal tree (recursive, until leaves are workable)
|
|
13
|
+
4. CONTRACT → write TASK.md + playbook.yml from the goal tree
|
|
14
|
+
5. VALIDATE → contract review + requirement coverage gate
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
These aren't separate phases producing separate files — they're the thinking steps you go through before writing contracts. The only files produced are the playbook structure.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Step 1 — Extract Goal
|
|
22
|
+
|
|
23
|
+
Reduce the user's request to one sentence: what complete, usable thing must exist when this is done?
|
|
24
|
+
|
|
25
|
+
**Good:** "A deployed blog with post CRUD, comments, RSS feed, and responsive design."
|
|
26
|
+
**Bad:** "A blog." (too vague)
|
|
27
|
+
**Bad:** "Plan, design, implement, and test a blog." (process, not result)
|
|
28
|
+
|
|
29
|
+
If the user hasn't stated a clear goal, ask. If the goal is too broad ("Build me a SaaS platform"), narrow it with follow-up questions before proceeding.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Step 2 — Gather Requirements
|
|
34
|
+
|
|
35
|
+
Extract every requirement from the user's prompt and from discovery questions. Capture them as specific, testable statements.
|
|
36
|
+
|
|
37
|
+
**Discovery questions (ask if not already answered):**
|
|
38
|
+
|
|
39
|
+
1. **Vision** — what is this project, what problem does it solve?
|
|
40
|
+
2. **Core features** — top 3–5, ranked by priority.
|
|
41
|
+
3. **User flows** — the main journey through the product.
|
|
42
|
+
4. **Data & APIs** — entities, external services, integrations.
|
|
43
|
+
5. **Constraints** — deadlines, tech stack, compliance, budget.
|
|
44
|
+
6. **Non-goals** — what are we explicitly NOT building? (Prevents scope creep.)
|
|
45
|
+
|
|
46
|
+
**Capture format:**
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
R1: [must] Authors can create, edit, publish, and delete posts
|
|
50
|
+
R2: [must] Readers can submit comments on published posts
|
|
51
|
+
R3: [must] RSS feed of latest published posts at /feed.xml
|
|
52
|
+
R4: [should] Comments support threaded replies
|
|
53
|
+
R5: [must] Posts support markdown with syntax highlighting
|
|
54
|
+
R6: [constraint] Tech stack: Node.js + PostgreSQL + React
|
|
55
|
+
R7: [non-goal] No user registration beyond author account
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Tag each as `[must]`, `[should]`, `[constraint]`, or `[non-goal]`. Number them. This list is your requirement coverage checklist in later steps.
|
|
59
|
+
|
|
60
|
+
**Surfacing goals from requirements:** When the work is large, replayable, or reactive — and the user describes a measurable end state — surface these as candidate **playbook goals**. Goals are different from sub-goal deliverables:
|
|
61
|
+
- **Sub-goals** are things that must *exist* (a database, an API endpoint, a UI page)
|
|
62
|
+
- **Goals** are conditions that must be *true* (all tests pass, type checking is clean, coverage reaches 90%)
|
|
63
|
+
|
|
64
|
+
A requirement like "the codebase must have zero type errors" is a goal. It may require many sub-goal deliverables to achieve, but the goal itself is the completion condition. Goals become the `goals:` list in `playbook.yml` and drive a goal-driven epoch loop. See `references/patterns.md` § Goal-Driven Epoch Loop.
|
|
65
|
+
|
|
66
|
+
**Existing codebase?** Run these before gathering requirements:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
ls package.json pyproject.toml go.mod Cargo.toml 2>/dev/null # runtime
|
|
70
|
+
cat package.json 2>/dev/null | jq -r '.dependencies // {} | keys[]' | head -20 # framework
|
|
71
|
+
find . -maxdepth 2 -type d -not -path '*/node_modules/*' -not -path '*/.git/*' | sort # structure
|
|
72
|
+
git log --oneline -10 2>/dev/null && git status --short 2>/dev/null # state
|
|
73
|
+
ls -la .converge/ 2>/dev/null # existing converge
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Capture tech stack, conventions, and existing state. These inform constraints but don't produce a separate deliverable file.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Step 3 — Decompose into Sub-Goals
|
|
81
|
+
|
|
82
|
+
Decompose the user's goal into deliverable sub-goals. Each sub-goal is a **complete, independently verifiable result**.
|
|
83
|
+
|
|
84
|
+
### Decomposition rules
|
|
85
|
+
|
|
86
|
+
- **3–7 children per level.** Less than 3 → no real decomposition. More than 7 → group into an intermediate level.
|
|
87
|
+
- **Name by deliverable, not activity.** "Database schema" not "Design database." "Working API endpoints" not "Build API."
|
|
88
|
+
- **Each child produces a complete thing.** Not a stage of producing a thing.
|
|
89
|
+
- **Children form a complete cover.** Reading all children's deliverables together achieves the parent goal.
|
|
90
|
+
|
|
91
|
+
### Recursive application
|
|
92
|
+
|
|
93
|
+
For each sub-goal, ask: *can one agent produce this complete deliverable in one session?*
|
|
94
|
+
|
|
95
|
+
- **Yes** → it's a leaf. Stop decomposing.
|
|
96
|
+
- **No** → decompose further. Split by sub-feature, by entity, by endpoint — not by workflow stage.
|
|
97
|
+
- **Same shape repeats N times** → use a runtime template plus `converge spawn` (see `references/static-dynamic.md`).
|
|
98
|
+
|
|
99
|
+
### Requirement mapping
|
|
100
|
+
|
|
101
|
+
Before proceeding, run the requirement coverage check:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
R1 → Sub-goal A ✓
|
|
105
|
+
R2 → Sub-goal B ✓
|
|
106
|
+
R3 → Sub-goal C ✓
|
|
107
|
+
R4 → ??? ← GAP: add a sub-goal or expand existing scope
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Every `[must]` requirement must map to at least one sub-goal. Unmapped requirements are gaps. Sub-goals with no mapped requirements are scope creep.
|
|
111
|
+
|
|
112
|
+
### Pattern recognition (after decomposition)
|
|
113
|
+
|
|
114
|
+
Once the goal tree exists, recognize its shape to sanity-check the design:
|
|
115
|
+
|
|
116
|
+
- Linear dependencies between sub-goals → ordered stages
|
|
117
|
+
- N identical sub-goals from a catalog → seed fan-out
|
|
118
|
+
- Iterative improvement until quality threshold → epoch loop
|
|
119
|
+
- N distinct domains with their own sub-trees → domain split
|
|
120
|
+
|
|
121
|
+
The shape confirms the decomposition; it doesn't drive it. If the shape looks wrong, the decomposition might be wrong.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Step 4 — Write Contracts
|
|
126
|
+
|
|
127
|
+
Write contracts from the goal tree. Start at the root, one layer at a time.
|
|
128
|
+
|
|
129
|
+
### For each leaf task
|
|
130
|
+
|
|
131
|
+
Write `TASK.md` with:
|
|
132
|
+
- **title + description:** What complete deliverable this produces
|
|
133
|
+
- **inputs:** Files it reads (upstream outputs, project data)
|
|
134
|
+
- **outputs:** Specific paths for its complete deliverable
|
|
135
|
+
- **checks:** Deterministic verification commands (exit 0 = pass)
|
|
136
|
+
- **depends_on:** Tasks that must complete first
|
|
137
|
+
|
|
138
|
+
### For each container task
|
|
139
|
+
|
|
140
|
+
Write `TASK.md` + `PLAN.md`. The TASK.md body describes:
|
|
141
|
+
1. **Decomposition** — what sub-goals exist and why
|
|
142
|
+
2. **Convergence** — how to integrate children's deliverables, what cross-child validation to run, what the converged output is
|
|
143
|
+
|
|
144
|
+
### Playbook-level
|
|
145
|
+
|
|
146
|
+
Write `playbook.yml` referencing top-level tasks with `depends_on` edges. Add playbook-level checks (e.g., `npx tsc --noEmit`, `npm test`).
|
|
147
|
+
|
|
148
|
+
Write the root `PLAN.md` capturing:
|
|
149
|
+
- **Goal:** The user's one-sentence goal
|
|
150
|
+
- **Decision:** Why this decomposition
|
|
151
|
+
- **Children:** Each top-level sub-goal with id, kind, objective, inputs, dependencies, outputs, checks
|
|
152
|
+
- **Requirements:** The full numbered list with sub-goal mappings
|
|
153
|
+
- **Open questions:** Things unknown at plan time
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Step 5 — Validate
|
|
158
|
+
|
|
159
|
+
Run contract review on every TASK.md. See SKILL.md §7 for the full checklist.
|
|
160
|
+
|
|
161
|
+
Key gates:
|
|
162
|
+
- Every output has a deterministic check
|
|
163
|
+
- Every input traces to an upstream output
|
|
164
|
+
- Every requirement maps to ≥1 task
|
|
165
|
+
- No middle work — every leaf produces a complete, usable deliverable
|
|
166
|
+
- No verb-named siblings
|
|
167
|
+
|
|
168
|
+
When validation passes, the plan is ready for `converge run`.
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# Schema Reference
|
|
2
|
+
|
|
3
|
+
Format reference for converge planning artifacts. Read when you need to write or validate TASK.md frontmatter, playbook.yml, checks, container behavior, and spawn templates.
|
|
4
|
+
|
|
5
|
+
For the contract model that explains *why* these fields exist, see `../SKILL.md` or `model.md`.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## `playbook.yml`
|
|
10
|
+
|
|
11
|
+
Playbook manifest. Defines the top-level task list, dependencies, run config, and playbook-level checks.
|
|
12
|
+
|
|
13
|
+
**Location:** `.converge/playbooks/{name}/playbook.yml`
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
name: default
|
|
17
|
+
description: End-to-end app generation
|
|
18
|
+
run:
|
|
19
|
+
mode: autonomous
|
|
20
|
+
maxIterations: 50
|
|
21
|
+
maxTaskAttempts: 3
|
|
22
|
+
tasks:
|
|
23
|
+
- path: prepare
|
|
24
|
+
- path: design-system
|
|
25
|
+
- path: build-screens
|
|
26
|
+
checks:
|
|
27
|
+
- id: type-check
|
|
28
|
+
cmd: npx tsc --noEmit
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## `TASK.md`
|
|
34
|
+
|
|
35
|
+
The delegation contract. One per task directory. **Same schema at every nesting level** — top-level tasks and deeply nested children use identical TASK.md format.
|
|
36
|
+
|
|
37
|
+
**Location:** `.converge/playbooks/{name}/tasks/{path-to-task}/TASK.md`
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
---
|
|
41
|
+
id: task-name
|
|
42
|
+
title: Human-Readable Title
|
|
43
|
+
description: What this task accomplishes in one sentence
|
|
44
|
+
depends_on:
|
|
45
|
+
- upstream-task-id
|
|
46
|
+
- prepare.catalog # Cross-branch dotted path
|
|
47
|
+
inputs:
|
|
48
|
+
- path/to/input.md
|
|
49
|
+
outputs:
|
|
50
|
+
- path/to/output.md
|
|
51
|
+
skills:
|
|
52
|
+
- skill-name
|
|
53
|
+
checks:
|
|
54
|
+
- id: check-id
|
|
55
|
+
cmd: shell-command-returns-0
|
|
56
|
+
description: What this validates
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
# Task Title
|
|
60
|
+
|
|
61
|
+
[Concrete, step-by-step instructions for the executor]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Three practical TASK.md roles
|
|
65
|
+
|
|
66
|
+
- **Leaf task** — produces outputs directly.
|
|
67
|
+
- **Static container** — owns child tasks under `tasks/` and converges their results.
|
|
68
|
+
- **Dynamic container** — marked `passthrough: true`; its body orchestrates work, emits `converge spawn ...`, and relies on a `converge` post-check contract to decide whether to continue.
|
|
69
|
+
|
|
70
|
+
### Frontmatter fields
|
|
71
|
+
|
|
72
|
+
| Field | Required | Contract role | Type | Description |
|
|
73
|
+
|-------|----------|---------------|------|-------------|
|
|
74
|
+
| `id` | Yes | identity | string | Unique kebab-case slug (`prepare`, `build-screens`). No numeric prefix. |
|
|
75
|
+
| `title` | Yes | scope | string | Human-readable title |
|
|
76
|
+
| `description` | Recommended | scope | string | One-line purpose |
|
|
77
|
+
| `inputs` | If reads | **Context In** | string[] | Files this task reads (must be upstream outputs) |
|
|
78
|
+
| `outputs` | Yes | **Context Out** | string[] | Files this task produces |
|
|
79
|
+
| `checks` | Yes | acceptance | Check[] | Deterministic validation commands |
|
|
80
|
+
| `depends_on` | If needed | deps | string[] | Sibling/cross-branch task IDs that must complete first |
|
|
81
|
+
| `skills` | If using | resources | string[] | Converge skills to invoke |
|
|
82
|
+
| `references` | Optional | resources | string[] | Skill libraries to reference |
|
|
83
|
+
| `vars` | Optional | resources | object | Template variables passed to seed/children |
|
|
84
|
+
| `passthrough` | Dynamic/container tasks | execution | boolean | Run shell body directly; common for orchestration parents that emit `converge spawn ...` |
|
|
85
|
+
| `converge` | Looping/container tasks | convergence | string/object | Post-body verdict prompt that decides continue vs halt |
|
|
86
|
+
| `tags` | Optional | metadata | string[] | Categorization labels |
|
|
87
|
+
| `blocking` | Optional | scheduling | boolean | If true, blocks all downstream until done |
|
|
88
|
+
| `executor` | Optional | execution | object | Execution method override |
|
|
89
|
+
| `allowed-tools` | Optional | sandbox | string[] | Restrict available tools |
|
|
90
|
+
|
|
91
|
+
A leaky contract is one where any field above is missing, vague, or over-broad.
|
|
92
|
+
|
|
93
|
+
### Recommended dynamic-container shape
|
|
94
|
+
|
|
95
|
+
Use this when a parent task needs to adapt at runtime:
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
---
|
|
99
|
+
id: build
|
|
100
|
+
title: Build
|
|
101
|
+
passthrough: true
|
|
102
|
+
checks:
|
|
103
|
+
- id: finished
|
|
104
|
+
cmd: test -f output/done.flag
|
|
105
|
+
converge: |
|
|
106
|
+
Decide whether this task should continue or halt.
|
|
107
|
+
---
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Then in the body:
|
|
111
|
+
|
|
112
|
+
- write evidence files
|
|
113
|
+
- emit `converge spawn <id> <template> --var ...` commands as needed
|
|
114
|
+
- use idempotency markers so repeat body runs do not duplicate-spawn
|
|
115
|
+
- call `converge tasks mark <id> --status done` when the stop condition is reached
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Dependency formats
|
|
120
|
+
|
|
121
|
+
```yaml
|
|
122
|
+
# Sibling (same level)
|
|
123
|
+
depends_on:
|
|
124
|
+
- upstream-task
|
|
125
|
+
|
|
126
|
+
# Cross-branch (dotted path from playbook root)
|
|
127
|
+
depends_on:
|
|
128
|
+
- prepare.catalog
|
|
129
|
+
|
|
130
|
+
# Tag-based (any task with this tag)
|
|
131
|
+
depends_on:
|
|
132
|
+
- tag:setup
|
|
133
|
+
|
|
134
|
+
# Mixed
|
|
135
|
+
depends_on:
|
|
136
|
+
- setup
|
|
137
|
+
- prepare.catalog
|
|
138
|
+
- tag:foundation
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Rules:**
|
|
142
|
+
- No cycles. If you find one, split the task.
|
|
143
|
+
- Minimize: depend only on what you actually consume.
|
|
144
|
+
- Dependencies are declared in `TASK.md` `depends_on` — each task owns its own edges.
|
|
145
|
+
- playbook.yml lists task paths only (no dependency wiring).
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Check schema
|
|
150
|
+
|
|
151
|
+
```yaml
|
|
152
|
+
checks:
|
|
153
|
+
- id: string # Unique kebab-case identifier
|
|
154
|
+
cmd: string # Shell command (exit 0 = pass, non-zero = fail)
|
|
155
|
+
description: string # Human-readable description
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Common patterns
|
|
159
|
+
|
|
160
|
+
```yaml
|
|
161
|
+
# File exists
|
|
162
|
+
- id: exists
|
|
163
|
+
cmd: test -f output.md
|
|
164
|
+
description: Output file exists
|
|
165
|
+
tags: [fast]
|
|
166
|
+
|
|
167
|
+
# Non-empty
|
|
168
|
+
- id: nonempty
|
|
169
|
+
cmd: test -s output.md
|
|
170
|
+
description: Output file is not empty
|
|
171
|
+
tags: [fast]
|
|
172
|
+
|
|
173
|
+
# Valid JSON
|
|
174
|
+
- id: valid-json
|
|
175
|
+
cmd: jq empty data.json
|
|
176
|
+
description: Valid JSON format
|
|
177
|
+
tags: [fast]
|
|
178
|
+
|
|
179
|
+
# JSON Schema validation
|
|
180
|
+
- id: valid-schema
|
|
181
|
+
cmd: jq -e '.items | type == "array" and length >= 3' data.json
|
|
182
|
+
description: Items array has at least 3 entries
|
|
183
|
+
tags: [fast]
|
|
184
|
+
|
|
185
|
+
# Valid YAML
|
|
186
|
+
- id: valid-yaml
|
|
187
|
+
cmd: python3 -c "import yaml; yaml.safe_load(open('config.yaml'))"
|
|
188
|
+
description: Valid YAML format
|
|
189
|
+
tags: [fast]
|
|
190
|
+
|
|
191
|
+
# Has required section
|
|
192
|
+
- id: has-overview
|
|
193
|
+
cmd: grep -q "## Overview" output.md
|
|
194
|
+
description: Has Overview section
|
|
195
|
+
tags: [fast]
|
|
196
|
+
|
|
197
|
+
# TypeScript compiles
|
|
198
|
+
- id: compiles
|
|
199
|
+
cmd: npx tsc --noEmit
|
|
200
|
+
description: TypeScript compiles
|
|
201
|
+
tags: [slow, build]
|
|
202
|
+
|
|
203
|
+
# Tests pass
|
|
204
|
+
- id: tests-pass
|
|
205
|
+
cmd: npm test -- --passWithNoTests
|
|
206
|
+
description: All tests passing
|
|
207
|
+
tags: [slow, build]
|
|
208
|
+
|
|
209
|
+
# File count
|
|
210
|
+
- id: screens-generated
|
|
211
|
+
cmd: test $(ls screens/*.html 2>/dev/null | wc -l) -ge 3
|
|
212
|
+
description: At least 3 screens generated
|
|
213
|
+
tags: [fast]
|
|
214
|
+
|
|
215
|
+
# Cross-reference: every catalog entry has a corresponding output
|
|
216
|
+
- id: all-catalog-entries-built
|
|
217
|
+
cmd: |
|
|
218
|
+
count=$(jq '.items | length' tokens-catalog.json)
|
|
219
|
+
built=$(ls tokens/*.json 2>/dev/null | wc -l)
|
|
220
|
+
test "$built" -eq "$count"
|
|
221
|
+
description: One output file per catalog entry
|
|
222
|
+
tags: [slow]
|
|
223
|
+
|
|
224
|
+
# Cross-task consistency: every screen in catalog has a source file
|
|
225
|
+
- id: screens-consistent
|
|
226
|
+
cmd: |
|
|
227
|
+
jq -r '.screens[].id' screens.json | while read id; do
|
|
228
|
+
test -f "lib/screens/$id.html" || exit 1
|
|
229
|
+
done
|
|
230
|
+
description: Every screen in catalog has a generated file
|
|
231
|
+
tags: [slow]
|
|
232
|
+
|
|
233
|
+
# No broken references
|
|
234
|
+
- id: no-broken-refs
|
|
235
|
+
cmd: |
|
|
236
|
+
! grep -r "\[\[missing" output/ 2>/dev/null
|
|
237
|
+
description: No unresolved [[wikilinks]] in output
|
|
238
|
+
tags: [fast]
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Rules:**
|
|
242
|
+
- Every output gets at least one check (existence + non-empty minimum).
|
|
243
|
+
- Code outputs add a compilation check. Data outputs add format validation.
|
|
244
|
+
- Container tasks add cross-child consistency checks (count match, every-catalog-entry).
|
|
245
|
+
- Playbook-level checks validate cross-task invariants.
|
|
246
|
+
- Tag checks by cost: `fast` for file/grep checks, `slow` for compilation/test suites.
|
|
247
|
+
- Never use exact string matching — too brittle.
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Dynamic work shapes
|
|
252
|
+
|
|
253
|
+
Current Converge uses one primary dynamic-work mechanism in source playbooks:
|
|
254
|
+
|
|
255
|
+
**Runtime spawn templates** in `templates/<name>/TASK.md`
|
|
256
|
+
|
|
257
|
+
Use them with `converge spawn <id> <template>` from a passthrough task body when the task needs to materialize children at runtime.
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Spawn-template pattern
|
|
262
|
+
|
|
263
|
+
Use runtime templates when the same child shape repeats:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
converge spawn sprint-3 sprint --var wave=3 --var sprint_id=sprint-3
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
The template resolves to:
|
|
270
|
+
|
|
271
|
+
```text
|
|
272
|
+
.converge/playbooks/<name>/templates/sprint/TASK.md
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Recommended usage:
|
|
276
|
+
|
|
277
|
+
- keep repeated child shapes in `templates/`
|
|
278
|
+
- pass runtime data with `--var`
|
|
279
|
+
- use idempotency markers in the parent body so repeated runs do not duplicate-spawn
|
|
280
|
+
- pair spawn with checks plus a `converge` verdict that decides whether to continue
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Directory naming
|
|
285
|
+
|
|
286
|
+
Static tasks live under `.converge/playbooks/{name}/tasks/`. Runtime-spawn templates live under `.converge/playbooks/{name}/templates/`.
|
|
287
|
+
|
|
288
|
+
```
|
|
289
|
+
tasks/{id}/TASK.md → static task contract (executable or container)
|
|
290
|
+
tasks/{id}/PLAN.md → container blueprint
|
|
291
|
+
templates/{name}/TASK.md → runtime spawn template
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
- IDs are plain kebab-case slugs (`prepare`, `build-screens`, `per-character`).
|
|
295
|
+
- **Static children** under a parent's `tasks/` subdirectory MUST use `\d{2,3}-` prefixes (e.g., `01-prepare`, `02-build-screens`). This is required by `discoverStaticChildren` which matches `^\d{2,3}-` to discover child TASK.md files. The numeric prefix controls execution order within the parent.
|
|
296
|
+
- **Top-level tasks** and **templates** use kebab-case without numeric prefixes — order comes from `depends_on` edges in `playbook.yml`.
|
|
297
|
+
- `tasks/` and `templates/` are siblings at the playbook root.
|
|
298
|
+
- Spawned children are materialized by the runtime, not written during init.
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
playbooks/default/
|
|
302
|
+
├── playbook.yml
|
|
303
|
+
├── PLAN.md
|
|
304
|
+
├── tasks/
|
|
305
|
+
│ └── build/
|
|
306
|
+
│ ├── TASK.md
|
|
307
|
+
│ └── PLAN.md
|
|
308
|
+
└── templates/
|
|
309
|
+
├── sprint/
|
|
310
|
+
│ └── TASK.md
|
|
311
|
+
└── phase/
|
|
312
|
+
└── TASK.md
|
|
313
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Static vs. Dynamic Subtask Reference
|
|
2
|
+
|
|
3
|
+
Decision guide for static vs. dynamic subtask decomposition. Read when planning a container and deciding whether to hand-write children or use runtime spawn templates.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Static vs. Dynamic Subtasks
|
|
8
|
+
|
|
9
|
+
**The core decomposition choice: when you split a task into subtasks, each subtask is either static or dynamic.**
|
|
10
|
+
|
|
11
|
+
| Subtask type | How it's created | When it's knowable | Use when |
|
|
12
|
+
|---|---|---|---|
|
|
13
|
+
| **Static** | Hand-written `TASK.md` file | Compile time (*concrete*) | Fixed set, known at plan time, ≤ ~7 children |
|
|
14
|
+
| **Dynamic** | parent body spawns it from a template at runtime | After the parent runs (*expected* or *adaptive*) | Data-driven list, unknown at plan time, N > 7, or N may grow |
|
|
15
|
+
|
|
16
|
+
**Static subtasks** are the default. Write each child's `TASK.md` by hand. The DAG is fully concrete at compile time — every node exists on disk, every edge is declared.
|
|
17
|
+
|
|
18
|
+
**Dynamic subtasks** use runtime templates. The parent task body emits `converge spawn <id> <template>` for each child. Two sub-cases:
|
|
19
|
+
|
|
20
|
+
- **Expected** — an upstream "catalog" task produces a structured file (e.g., `tokens-catalog.json`) listing what entities exist. The parent reads it and spawns children from it. Children's IDs and count are predictable from the catalog.
|
|
21
|
+
- **Adaptive** — no catalog exists. The parent decides what to spawn at runtime. Children are unknowable until the parent runs.
|
|
22
|
+
|
|
23
|
+
**The catalog pattern** (prefer `expected` over `frontier`):
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
upstream catalog task → downstream dynamic container
|
|
27
|
+
writes tokens-catalog.json → reads it, spawns per-token children
|
|
28
|
+
(concrete) → (children are expected)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
One extra task makes the rest of the DAG queryable. See `examples/game-assets-video` for the worked example.
|
|
32
|
+
|
|
33
|
+
**Decision heuristic:**
|
|
34
|
+
- ≤ 7 items, known at plan time → **static subtasks** (hand-write each `TASK.md`)
|
|
35
|
+
- > 7 items, or the list comes from data → **catalog task + dynamic container** (dynamic, expected)
|
|
36
|
+
- The list requires runtime reasoning to determine → **dynamic container** (adaptive)
|
|
37
|
+
|
|
38
|
+
**Mixed containers:** a container can have both static and dynamic children. A `03-build-screens` phase might have one static `001-design-system` task plus a body that spawns per-screen children. Both coexist in the same DAG.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Checks Reference
|
|
2
|
+
|
|
3
|
+
Full check reference for converge-planning. Read when you need to design deterministic checks for tasks, wire reusable helpers through `scripts/`, or plan convergence loops that rely on post-check evidence.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Checks are part of the contract
|
|
8
|
+
|
|
9
|
+
Write checks during planning, not after. For every task contract, add checks that validate:
|
|
10
|
+
- the output exists
|
|
11
|
+
- the output is well-formed
|
|
12
|
+
- the output satisfies the actual task contract
|
|
13
|
+
|
|
14
|
+
Examples:
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
checks:
|
|
18
|
+
- id: file-exists
|
|
19
|
+
cmd: test -f output.md
|
|
20
|
+
- id: schema-valid
|
|
21
|
+
cmd: jq empty data.json
|
|
22
|
+
- id: section-present
|
|
23
|
+
cmd: grep -q "## Required Section" output.md
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Use checks at every level:
|
|
27
|
+
- Leaf task: its own outputs exist and are valid.
|
|
28
|
+
- Container task: child outputs are complete and internally consistent.
|
|
29
|
+
- Playbook: cross-task invariants still hold.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Reusable helpers live in `scripts/`
|
|
34
|
+
|
|
35
|
+
There is no `.test.md` registry and no `checks/` folder. If a check needs shared logic, put the helper under the playbook's `scripts/` tree and call it directly from `cmd`.
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
playbooks/default/
|
|
39
|
+
scripts/
|
|
40
|
+
file-exists.sh
|
|
41
|
+
backend-configured.js
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```yaml
|
|
45
|
+
checks:
|
|
46
|
+
- id: idea-exists
|
|
47
|
+
cmd: bash scripts/file-exists.sh idea.md
|
|
48
|
+
- id: backend-configured
|
|
49
|
+
cmd: node scripts/backend-configured.js image-generate
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Rules:
|
|
53
|
+
- The command is the API. Keep it explicit.
|
|
54
|
+
- If a command references `scripts/...`, that file must actually exist.
|
|
55
|
+
- Do not rely on named test registries, `type: test`, or auto-discovered helper folders.
|
|
56
|
+
|
|
57
|
+
When to extract a helper into `scripts/`:
|
|
58
|
+
- the same command logic appears in multiple tasks
|
|
59
|
+
- the check needs real control flow or parsing
|
|
60
|
+
- the check needs a stable interface that several tasks can call
|
|
61
|
+
|
|
62
|
+
When not to extract:
|
|
63
|
+
- one-off shell checks
|
|
64
|
+
- tiny checks that stay readable inline
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Dynamic containers and post-check loops
|
|
69
|
+
|
|
70
|
+
For dynamic or adaptive parents, the checks should describe the real stop condition. The body does work and spawns children; the `converge` prompt decides whether another wave is needed after the checks run.
|
|
71
|
+
|
|
72
|
+
Typical shape:
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
id: improve
|
|
76
|
+
passthrough: true
|
|
77
|
+
checks:
|
|
78
|
+
- id: backlog-empty
|
|
79
|
+
cmd: test ! -s artifacts/backlog.txt
|
|
80
|
+
- id: report-valid
|
|
81
|
+
cmd: node scripts/verify-report.js artifacts/report.json
|
|
82
|
+
converge: |
|
|
83
|
+
Review the current evidence and decide whether to continue or halt.
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The important split:
|
|
87
|
+
- body: gather evidence, write state, `converge spawn ...`
|
|
88
|
+
- checks: verify the current state
|
|
89
|
+
- `converge`: decide continue vs halt based on the checked evidence
|
|
90
|
+
|
|
91
|
+
That is the current self-correcting loop model.
|