@pruddiman/dispatch 1.4.4 → 1.5.0-beta.07e10a8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -12
- package/dist/cli.js +9210 -10117
- package/dist/cli.js.map +1 -1
- package/dist/mcp/dispatch-worker.js +7343 -0
- package/dist/mcp/dispatch-worker.js.map +1 -0
- package/package.json +21 -9
- package/skills/dispatch/SKILL.md +144 -0
- package/skills/dispatch/references/ordering-reference.md +215 -0
- package/skills/dispatch/references/troubleshooting.md +34 -0
- package/skills/dispatch/references/workflow-recipes.md +105 -0
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pruddiman/dispatch",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0-beta.07e10a8",
|
|
4
4
|
"description": "AI agent orchestration CLI — parse markdown task files, dispatch each unit of work to code agents (OpenCode, GitHub Copilot, etc.), and commit results with conventional commits",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"dispatch": "dist/cli.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"dist"
|
|
10
|
+
"dist",
|
|
11
|
+
"skills"
|
|
11
12
|
],
|
|
12
13
|
"scripts": {
|
|
13
14
|
"build": "tsup",
|
|
@@ -27,7 +28,8 @@
|
|
|
27
28
|
"orchestration",
|
|
28
29
|
"dispatch",
|
|
29
30
|
"tasks",
|
|
30
|
-
"markdown"
|
|
31
|
+
"markdown",
|
|
32
|
+
"beta"
|
|
31
33
|
],
|
|
32
34
|
"license": "MIT",
|
|
33
35
|
"repository": {
|
|
@@ -43,23 +45,33 @@
|
|
|
43
45
|
"node": ">=20.12.0"
|
|
44
46
|
},
|
|
45
47
|
"dependencies": {
|
|
46
|
-
"@anthropic-ai/claude-agent-sdk": "^0.2.
|
|
48
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.98",
|
|
47
49
|
"@azure/identity": "^4.13.0",
|
|
48
|
-
"@
|
|
50
|
+
"@github/copilot-sdk": "^0.2.1",
|
|
51
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
49
52
|
"@octokit/auth-oauth-device": "^7.1.5",
|
|
50
53
|
"@octokit/rest": "^21.1.1",
|
|
51
|
-
"@openai/codex": "^0.
|
|
52
|
-
"@opencode-ai/sdk": "^1.2
|
|
54
|
+
"@openai/codex-sdk": "^0.118.0",
|
|
55
|
+
"@opencode-ai/sdk": "^1.4.2",
|
|
53
56
|
"azure-devops-node-api": "^14.1.0",
|
|
57
|
+
"better-sqlite3": "^12.8.0",
|
|
54
58
|
"chalk": "^5.4.1",
|
|
55
59
|
"commander": "^14.0.3",
|
|
56
60
|
"glob": "^11.0.1",
|
|
57
|
-
"
|
|
61
|
+
"ink": "^6.0.0",
|
|
62
|
+
"ink-select-input": "^6.0.0",
|
|
63
|
+
"ink-spinner": "^5.0.0",
|
|
64
|
+
"ink-text-input": "^6.0.0",
|
|
65
|
+
"open": "^10.2.0",
|
|
66
|
+
"react": "^19.0.0",
|
|
67
|
+
"zod": "^4.3.6"
|
|
58
68
|
},
|
|
59
69
|
"devDependencies": {
|
|
60
|
-
"@
|
|
70
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
61
71
|
"@types/node": "^22.13.4",
|
|
72
|
+
"@types/react": "^19.0.0",
|
|
62
73
|
"@vitest/coverage-v8": "^4.0.18",
|
|
74
|
+
"ink-testing-library": "^4.0.0",
|
|
63
75
|
"semantic-release": "^25.0.3",
|
|
64
76
|
"tsup": "^8.4.0",
|
|
65
77
|
"typescript": "^5.7.3",
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dispatch
|
|
3
|
+
description: >
|
|
4
|
+
Orchestrate work using the Dispatch MCP server (@pruddiman/dispatch). Use when the
|
|
5
|
+
user wants to spec issues, dispatch tasks, plan execution order, manage
|
|
6
|
+
dependencies between issues, or run any dispatch operation. Covers correct
|
|
7
|
+
spec ordering, dependency analysis, and the spec-plan-execute pipeline.
|
|
8
|
+
metadata:
|
|
9
|
+
author: pruddiman
|
|
10
|
+
version: "2.1.0"
|
|
11
|
+
license: MIT
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Dispatch Orchestration
|
|
15
|
+
|
|
16
|
+
Dispatch turns issues into working code: fetch work items → generate structured specs → plan and execute tasks in isolated AI sessions → commit and open PRs.
|
|
17
|
+
|
|
18
|
+
**Pipeline:** Issues → `spec_generate` → Spec files → `dispatch_run` → Plan → Execute → Commit/PR
|
|
19
|
+
|
|
20
|
+
Use MCP tools directly. Do not shell out to the `dispatch` CLI.
|
|
21
|
+
|
|
22
|
+
## MCP Tool Reference
|
|
23
|
+
|
|
24
|
+
| Category | Tool | What it does |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| **Spec** | `spec_generate` | Generate spec files from issue IDs, glob pattern, or inline text |
|
|
27
|
+
| | `spec_list` | List spec files in `.dispatch/specs/` |
|
|
28
|
+
| | `spec_read` | Read a spec file's contents |
|
|
29
|
+
| | `spec_runs_list` | List recent spec generation runs |
|
|
30
|
+
| | `spec_run_status` | Get status of a specific spec run by runId |
|
|
31
|
+
| **Dispatch** | `dispatch_run` | Execute dispatch pipeline for one or more issues |
|
|
32
|
+
| | `dispatch_dry_run` | Preview tasks without executing (synchronous) |
|
|
33
|
+
| **Monitor** | `status_get` | Get run status and per-task details by runId |
|
|
34
|
+
| | `runs_list` | List recent dispatch runs (filter by status) |
|
|
35
|
+
| | `issues_list` | List open issues from the configured datasource |
|
|
36
|
+
| | `issues_fetch` | Fetch full details for specific issues |
|
|
37
|
+
| **Recovery** | `run_retry` | Re-run all failed tasks from a previous run |
|
|
38
|
+
| | `task_retry` | Retry a single failed task by taskId |
|
|
39
|
+
| **Config** | `config_get` | Read the current Dispatch configuration |
|
|
40
|
+
|
|
41
|
+
## Async Pattern — runId + Polling
|
|
42
|
+
|
|
43
|
+
`spec_generate` and `dispatch_run` are **fire-and-forget**: they return a `runId` immediately; progress arrives as logging notifications.
|
|
44
|
+
|
|
45
|
+
**Always poll for completion before moving to the next step:**
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
# After spec_generate
|
|
49
|
+
loop: status = spec_run_status({ runId }); break if status.status in ["completed","failed"]
|
|
50
|
+
|
|
51
|
+
# After dispatch_run
|
|
52
|
+
loop: status = status_get({ runId }); break if status.run.status in ["completed","failed"]
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`dispatch_dry_run` is synchronous — returns results directly, no runId.
|
|
56
|
+
|
|
57
|
+
## Pipeline Phases
|
|
58
|
+
|
|
59
|
+
| Phase | When to use |
|
|
60
|
+
|---|---|
|
|
61
|
+
| `spec_generate` | Issue is vague/complex, needs task breakdown, or involves multiple agents. Skip if a good spec already exists. |
|
|
62
|
+
| Planning (default) | Complex tasks, unfamiliar code, refactors. Skip with `noPlan: true` for mechanical/obvious changes. |
|
|
63
|
+
| `dispatch_dry_run` | Always dry-run before dispatching an unfamiliar spec to verify task count and ordering. |
|
|
64
|
+
|
|
65
|
+
## Spec Ordering — The Core Discipline
|
|
66
|
+
|
|
67
|
+
**This is the most critical part of using Dispatch correctly.**
|
|
68
|
+
|
|
69
|
+
### The Rule
|
|
70
|
+
|
|
71
|
+
**Never spec an issue whose prerequisites have not been fully implemented and merged.**
|
|
72
|
+
|
|
73
|
+
The spec agent explores the *current* codebase. If issue B depends on code that issue A creates, and A hasn't been executed yet, B's spec will be wrong — written against a codebase missing B's foundations. A spec that exists for A is not enough; A must be fully executed and its code present on disk.
|
|
74
|
+
|
|
75
|
+
### Dependency Analysis
|
|
76
|
+
|
|
77
|
+
Before speccing anything:
|
|
78
|
+
|
|
79
|
+
1. `issues_list` → `issues_fetch` to read all issue descriptions.
|
|
80
|
+
2. Map dependencies: if B imports or calls something A creates, B depends on A.
|
|
81
|
+
3. Group into layers: Layer 0 = no deps. Layer 1 = depends on layer 0. Etc.
|
|
82
|
+
4. Independent issues within a layer can be specced and executed concurrently.
|
|
83
|
+
|
|
84
|
+
### Execution Pattern
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
Layer 0 (no deps): spec_generate → poll → dispatch_run → poll
|
|
88
|
+
↓
|
|
89
|
+
Layer 1 (needs 0): spec_generate → poll → dispatch_run → poll
|
|
90
|
+
↓
|
|
91
|
+
Layer 2 (needs 1): spec_generate → poll → dispatch_run → poll
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Spec layer N only after layer N-1 is **executed and complete** — not just specced.
|
|
95
|
+
|
|
96
|
+
### Concrete Example
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
Issues: #10 user model, #11 user API (needs #10), #12 admin dashboard (needs #11)
|
|
100
|
+
#20 logging (independent), #21 request tracing (needs #20)
|
|
101
|
+
|
|
102
|
+
Layer 0: #10, #20 → spec + dispatch together (concurrent, no prerequisites)
|
|
103
|
+
Layer 1: #11, #21 → spec + dispatch after layer 0 done (concurrent within layer)
|
|
104
|
+
Layer 2: #12 → spec + dispatch after layer 1 done
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Anti-Patterns
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
# BAD: speccing everything at once — #11's spec references code that doesn't exist yet
|
|
111
|
+
spec_generate({ issues: "10,11,12,20,21" })
|
|
112
|
+
|
|
113
|
+
# BAD: not waiting for spec before dispatch — spec may still be running
|
|
114
|
+
rid = spec_generate({ issues: "42" }); dispatch_run({ issueIds: ["42"] })
|
|
115
|
+
|
|
116
|
+
# BAD: speccing layer 1 before layer 0 is executed — spec alone is not enough
|
|
117
|
+
spec_generate({ issues: "10" })
|
|
118
|
+
spec_generate({ issues: "11" }) # WRONG: #10's code doesn't exist yet
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Pre-Spec Checklist
|
|
122
|
+
|
|
123
|
+
Before calling `spec_generate` on any issue:
|
|
124
|
+
|
|
125
|
+
1. What code does it depend on? (imports, APIs, schemas, utilities)
|
|
126
|
+
2. Does that code exist in the codebase *right now*? (verify with grep/glob)
|
|
127
|
+
3. If not — which issue creates it? Execute that issue first, fully.
|
|
128
|
+
4. Are there other issues at the same dependency layer? Spec them together.
|
|
129
|
+
|
|
130
|
+
## Task Ordering Inside Specs
|
|
131
|
+
|
|
132
|
+
`spec_generate` tags tasks automatically. You do not write P/S/I tags — understand them to read generated specs:
|
|
133
|
+
|
|
134
|
+
- `(P)` **Parallel-safe** — runs concurrently with adjacent `(P)` tasks
|
|
135
|
+
- `(S)` **Serial/dependent** — waits for all prior tasks, then runs alone (caps the current group)
|
|
136
|
+
- `(I)` **Isolated/barrier** — runs completely alone; used for validation steps (tests, lint, build)
|
|
137
|
+
|
|
138
|
+
See [references/ordering-reference.md](references/ordering-reference.md) for the full grouping algorithm and edge cases.
|
|
139
|
+
|
|
140
|
+
## References
|
|
141
|
+
|
|
142
|
+
- [references/workflow-recipes.md](references/workflow-recipes.md) — single issue, multi-issue, retry, and feature-branch recipes
|
|
143
|
+
- [references/ordering-reference.md](references/ordering-reference.md) — P/S/I grouping algorithm with walkthrough examples
|
|
144
|
+
- [references/troubleshooting.md](references/troubleshooting.md) — symptom/cause/fix for common failures
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# P/S/I Ordering Reference
|
|
2
|
+
|
|
3
|
+
Detailed reference for Dispatch's task grouping algorithm and execution ordering.
|
|
4
|
+
|
|
5
|
+
## The `groupTasksByMode()` Algorithm
|
|
6
|
+
|
|
7
|
+
The algorithm in `src/parser.ts` converts a flat list of tagged tasks into ordered execution groups:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Input: flat list of tasks, each with mode: "parallel" | "serial" | "isolated"
|
|
11
|
+
Output: array of groups (Task[][]), executed sequentially
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
**Rules:**
|
|
15
|
+
|
|
16
|
+
1. **Parallel `(P)`** — accumulate into the current group
|
|
17
|
+
2. **Serial `(S)`** — append to the current group, then start a new empty group (acts as a "cap")
|
|
18
|
+
3. **Isolated `(I)`** — flush any accumulated tasks as their own group, then create a solo group for the isolated task
|
|
19
|
+
|
|
20
|
+
After processing all tasks, any remaining accumulated parallel tasks form a final group.
|
|
21
|
+
|
|
22
|
+
## Walkthrough Examples
|
|
23
|
+
|
|
24
|
+
### Example 1: Mixed modes
|
|
25
|
+
|
|
26
|
+
```markdown
|
|
27
|
+
- [ ] (P) Task A
|
|
28
|
+
- [ ] (P) Task B
|
|
29
|
+
- [ ] (S) Task C
|
|
30
|
+
- [ ] (P) Task D
|
|
31
|
+
- [ ] (P) Task E
|
|
32
|
+
- [ ] (I) Task F
|
|
33
|
+
- [ ] (P) Task G
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Step-by-step:**
|
|
37
|
+
|
|
38
|
+
| Task | Mode | Action | Current group | Groups so far |
|
|
39
|
+
|------|------|--------|--------------|---------------|
|
|
40
|
+
| A | P | accumulate | [A] | [] |
|
|
41
|
+
| B | P | accumulate | [A, B] | [] |
|
|
42
|
+
| C | S | cap group | [] | [[A, B, C]] |
|
|
43
|
+
| D | P | accumulate | [D] | [[A, B, C]] |
|
|
44
|
+
| E | P | accumulate | [D, E] | [[A, B, C]] |
|
|
45
|
+
| F | I | flush + solo | [] | [[A, B, C], [D, E], [F]] |
|
|
46
|
+
| G | P | accumulate | [G] | [[A, B, C], [D, E], [F]] |
|
|
47
|
+
| end | — | flush remaining | [] | [[A, B, C], [D, E], [F], [G]] |
|
|
48
|
+
|
|
49
|
+
**Result:** `[[A, B, C], [D, E], [F], [G]]`
|
|
50
|
+
|
|
51
|
+
**Execution:**
|
|
52
|
+
1. A, B run concurrently → C runs (S caps the group, so C waits for A and B)
|
|
53
|
+
2. D, E run concurrently
|
|
54
|
+
3. F runs alone (isolated)
|
|
55
|
+
4. G runs alone (only task in its group)
|
|
56
|
+
|
|
57
|
+
### Example 2: All parallel
|
|
58
|
+
|
|
59
|
+
```markdown
|
|
60
|
+
- [ ] (P) Task A
|
|
61
|
+
- [ ] (P) Task B
|
|
62
|
+
- [ ] (P) Task C
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Result:** `[[A, B, C]]` — all three run concurrently in one group.
|
|
66
|
+
|
|
67
|
+
### Example 3: All serial
|
|
68
|
+
|
|
69
|
+
```markdown
|
|
70
|
+
- [ ] (S) Task A
|
|
71
|
+
- [ ] (S) Task B
|
|
72
|
+
- [ ] (S) Task C
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Result:** `[[A], [B], [C]]` — each runs alone, sequentially.
|
|
76
|
+
|
|
77
|
+
### Example 4: Parallel then isolated validation
|
|
78
|
+
|
|
79
|
+
```markdown
|
|
80
|
+
- [ ] (P) Implement feature module
|
|
81
|
+
- [ ] (P) Write unit tests for feature
|
|
82
|
+
- [ ] (P) Update documentation
|
|
83
|
+
- [ ] (I) Run full test suite
|
|
84
|
+
- [ ] (I) Run linter
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Result:** `[[module, tests, docs], [test suite], [linter]]`
|
|
88
|
+
|
|
89
|
+
**Execution:**
|
|
90
|
+
1. Module, tests, and docs all run concurrently
|
|
91
|
+
2. Full test suite runs alone
|
|
92
|
+
3. Linter runs alone
|
|
93
|
+
|
|
94
|
+
### Example 5: Serial dependency chain
|
|
95
|
+
|
|
96
|
+
```markdown
|
|
97
|
+
- [ ] (P) Create database schema migration
|
|
98
|
+
- [ ] (P) Add seed data script
|
|
99
|
+
- [ ] (S) Run migration and seed the database
|
|
100
|
+
- [ ] (P) Implement API endpoints using new schema
|
|
101
|
+
- [ ] (P) Write API integration tests
|
|
102
|
+
- [ ] (I) Run all tests
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Result:** `[[schema, seed, run migration], [endpoints, tests], [run all tests]]`
|
|
106
|
+
|
|
107
|
+
**Execution:**
|
|
108
|
+
1. Schema and seed created concurrently, then migration runs (S caps)
|
|
109
|
+
2. Endpoints and tests written concurrently (safe — schema exists now)
|
|
110
|
+
3. Full test suite runs alone
|
|
111
|
+
|
|
112
|
+
### Example 6: Isolated as a phase gate
|
|
113
|
+
|
|
114
|
+
```markdown
|
|
115
|
+
- [ ] (P) Refactor module A
|
|
116
|
+
- [ ] (P) Refactor module B
|
|
117
|
+
- [ ] (I) Run tests to verify refactors
|
|
118
|
+
- [ ] (P) Update module C (imports from A and B)
|
|
119
|
+
- [ ] (P) Update module D (imports from A and B)
|
|
120
|
+
- [ ] (I) Run final test suite
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Result:** `[[A, B], [verify], [C, D], [final tests]]`
|
|
124
|
+
|
|
125
|
+
The first `(I)` acts as a phase gate — it verifies the refactors before dependent work begins.
|
|
126
|
+
|
|
127
|
+
## Edge Cases
|
|
128
|
+
|
|
129
|
+
### Single task
|
|
130
|
+
|
|
131
|
+
```markdown
|
|
132
|
+
- [ ] (P) Only task
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Result:** `[[Only task]]` — works fine regardless of mode prefix.
|
|
136
|
+
|
|
137
|
+
### Serial followed immediately by parallel
|
|
138
|
+
|
|
139
|
+
```markdown
|
|
140
|
+
- [ ] (S) Setup step
|
|
141
|
+
- [ ] (P) Task A
|
|
142
|
+
- [ ] (P) Task B
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**Result:** `[[Setup step], [A, B]]` — serial creates its own group, then parallel tasks accumulate.
|
|
146
|
+
|
|
147
|
+
### Isolated at the very start
|
|
148
|
+
|
|
149
|
+
```markdown
|
|
150
|
+
- [ ] (I) Clean build artifacts
|
|
151
|
+
- [ ] (P) Task A
|
|
152
|
+
- [ ] (P) Task B
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Result:** `[[Clean], [A, B]]` — isolated runs first (no prior tasks to flush), then parallel group.
|
|
156
|
+
|
|
157
|
+
### No mode prefix (defaults to serial)
|
|
158
|
+
|
|
159
|
+
```markdown
|
|
160
|
+
- [ ] Task without prefix
|
|
161
|
+
- [ ] (P) Parallel task
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Result:** `[[no-prefix, parallel]]` — the untagged task is treated as serial, which caps the group after it. But since the parallel task follows, it starts a new group... Actually: the untagged task (serial) starts accumulating, the `(P)` task accumulates into the same group. Then `(S)` caps — but there's no `(S)`. The untagged task is serial, so it caps immediately: `[[no-prefix], [parallel]]`.
|
|
165
|
+
|
|
166
|
+
**Takeaway:** Always tag explicitly. Untagged = serial = immediate group cap.
|
|
167
|
+
|
|
168
|
+
## Common Patterns
|
|
169
|
+
|
|
170
|
+
### The "implement then validate" pattern
|
|
171
|
+
```markdown
|
|
172
|
+
- [ ] (P) Implement feature X
|
|
173
|
+
- [ ] (P) Implement feature Y
|
|
174
|
+
- [ ] (I) Run tests
|
|
175
|
+
```
|
|
176
|
+
Best for: independent features that need a shared validation gate.
|
|
177
|
+
|
|
178
|
+
### The "foundation then consumers" pattern
|
|
179
|
+
```markdown
|
|
180
|
+
- [ ] (S) Create shared utility/interface
|
|
181
|
+
- [ ] (P) Consumer A uses the utility
|
|
182
|
+
- [ ] (P) Consumer B uses the utility
|
|
183
|
+
- [ ] (I) Run tests
|
|
184
|
+
```
|
|
185
|
+
Best for: creating something that multiple subsequent tasks depend on.
|
|
186
|
+
|
|
187
|
+
### The "phased rollout" pattern
|
|
188
|
+
```markdown
|
|
189
|
+
- [ ] (P) Phase 1 task A
|
|
190
|
+
- [ ] (P) Phase 1 task B
|
|
191
|
+
- [ ] (I) Verify phase 1
|
|
192
|
+
- [ ] (P) Phase 2 task A (depends on phase 1)
|
|
193
|
+
- [ ] (P) Phase 2 task B (depends on phase 1)
|
|
194
|
+
- [ ] (I) Verify phase 2
|
|
195
|
+
```
|
|
196
|
+
Best for: large changes that need intermediate verification.
|
|
197
|
+
|
|
198
|
+
### The "all parallel" pattern
|
|
199
|
+
```markdown
|
|
200
|
+
- [ ] (P) Independent change A
|
|
201
|
+
- [ ] (P) Independent change B
|
|
202
|
+
- [ ] (P) Independent change C
|
|
203
|
+
- [ ] (I) Run tests
|
|
204
|
+
```
|
|
205
|
+
Best for: maximum throughput when all tasks are truly independent.
|
|
206
|
+
|
|
207
|
+
## Troubleshooting
|
|
208
|
+
|
|
209
|
+
| Symptom | Likely cause | Diagnostic | Fix |
|
|
210
|
+
|---|---|---|---|
|
|
211
|
+
| Task reads a file that doesn't exist | Task should be `(S)` not `(P)` — it ran before the task that creates the file | Check which prior task creates the file | Move the dependent task after its prerequisite with `(S)` |
|
|
212
|
+
| File has conflicts or garbled content | Two `(P)` tasks in the same group wrote to the same file | Check task descriptions for shared file targets | Make one task `(S)` after the other |
|
|
213
|
+
| Tasks run slower than expected | Too many `(S)` tags killing parallelism | Count `(P)` vs `(S)` tags — most tasks should be `(P)` | Audit each `(S)` for genuine dependency |
|
|
214
|
+
| Isolated task fails | Prior parallel tasks didn't complete correctly | Check logs for failures in the preceding group | Fix the failing task; `(I)` correctly waited for it |
|
|
215
|
+
| Wrong execution order | Misunderstanding of how `(S)` caps groups | Use `--dry-run` to preview grouping | Reorder tasks and re-tag |
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
## Dispatch / Spec Failures
|
|
4
|
+
|
|
5
|
+
| Symptom | Cause | Fix |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| Spec references code that doesn't exist | Prerequisite issue hasn't been executed | Execute the prerequisite first, then call `spec_generate` again |
|
|
8
|
+
| `dispatch_run` tasks fail — "file not found" or "symbol not found" | Task depends on code from a prior issue that isn't done | Execute issues in dependency order; re-spec if needed |
|
|
9
|
+
| Spec quality is poor / tasks seem wrong | Spec was generated before prerequisite code existed | Execute prerequisites, then `spec_generate` the issue again |
|
|
10
|
+
| Planner times out | Complex task or slow codebase exploration | Pass `planTimeout` (minutes) to `dispatch_run`, or `noPlan: true` for simpler tasks |
|
|
11
|
+
| Too slow — everything sequential | Independent issues dispatched one at a time | Identify independent issues and spec/execute with `concurrency` > 1 |
|
|
12
|
+
| `spec_run_status` shows `failed` | Spec pipeline error | Check `error` field in status response; re-run `spec_generate` |
|
|
13
|
+
| `status_get` shows tasks stuck in `running` | Agent hung | Use `run_retry` to re-run; check logs via logging notifications |
|
|
14
|
+
| Dispatched before spec finished | Polling skipped between `spec_generate` and `dispatch_run` | Always poll `spec_run_status` to `completed` before calling `dispatch_run` |
|
|
15
|
+
|
|
16
|
+
## Task Ordering Issues (Inside Specs)
|
|
17
|
+
|
|
18
|
+
| Symptom | Likely cause | Fix |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| Task reads a file that doesn't exist | Task ran in parallel before the task that creates the file | The task should be `(S)` not `(P)` — report to spec author or regenerate |
|
|
21
|
+
| File has conflicts or garbled content | Two `(P)` tasks wrote to the same file concurrently | One task needs to be `(S)` after the other |
|
|
22
|
+
| Tasks run slower than expected | Too many `(S)` tags killing parallelism | Audit each `(S)` — most tasks should be `(P)` |
|
|
23
|
+
| Isolated task fails | Prior parallel tasks didn't complete correctly | Fix the failing task; `(I)` correctly waited for it |
|
|
24
|
+
| Wrong execution order | Misunderstanding of how `(S)` caps groups | Use `dispatch_dry_run` to preview grouping before executing |
|
|
25
|
+
|
|
26
|
+
## Dependency Order Violations
|
|
27
|
+
|
|
28
|
+
These produce subtle, hard-to-debug failures. When in doubt, verify with `issues_fetch` and grep/glob the codebase before speccing.
|
|
29
|
+
|
|
30
|
+
| Scenario | What goes wrong | Correct action |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| Specced B before A is executed | B's spec is written against missing code; tasks will fail or be wrong | Execute A fully, then `spec_generate` B |
|
|
33
|
+
| Specced A and B together (B depends on A) | B's spec has no A code to reference | Spec them in separate layers |
|
|
34
|
+
| Re-specced an issue after its dependency changed | Spec may now be stale | Re-spec again after verifying dependencies exist |
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Workflow Recipes
|
|
2
|
+
|
|
3
|
+
Common dispatch workflows. All async tools require polling — see SKILL.md for the polling pattern.
|
|
4
|
+
|
|
5
|
+
## Single Issue — Full Pipeline
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
# 1. Generate spec
|
|
9
|
+
rid_spec = spec_generate({ issues: "42" })
|
|
10
|
+
poll spec_run_status({ runId: rid_spec }) until completed
|
|
11
|
+
|
|
12
|
+
# 2. Review the spec (optional but recommended)
|
|
13
|
+
spec_list({})
|
|
14
|
+
spec_read({ file: "42-my-issue.md" })
|
|
15
|
+
|
|
16
|
+
# 3. Preview tasks (optional but recommended for unfamiliar specs)
|
|
17
|
+
dispatch_dry_run({ issueIds: ["42"] })
|
|
18
|
+
|
|
19
|
+
# 4. Execute
|
|
20
|
+
rid_run = dispatch_run({ issueIds: ["42"] })
|
|
21
|
+
poll status_get({ runId: rid_run }) until completed
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Multiple Independent Issues
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
# Spec all at once (safe — no dependencies between them)
|
|
28
|
+
rid_spec = spec_generate({ issues: "42,43,44" })
|
|
29
|
+
poll spec_run_status({ runId: rid_spec }) until completed
|
|
30
|
+
|
|
31
|
+
# Execute concurrently
|
|
32
|
+
rid_run = dispatch_run({ issueIds: ["42", "43", "44"], concurrency: 3 })
|
|
33
|
+
poll status_get({ runId: rid_run }) until completed
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Dependent Issue Chain
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
# Layer 0 — no dependencies
|
|
40
|
+
rid_s0 = spec_generate({ issues: "42" })
|
|
41
|
+
poll spec_run_status({ runId: rid_s0 }) until completed
|
|
42
|
+
rid_r0 = dispatch_run({ issueIds: ["42"] })
|
|
43
|
+
poll status_get({ runId: rid_r0 }) until completed
|
|
44
|
+
|
|
45
|
+
# Layer 1 — safe now that #42 is implemented and its code exists
|
|
46
|
+
rid_s1 = spec_generate({ issues: "43" })
|
|
47
|
+
poll spec_run_status({ runId: rid_s1 }) until completed
|
|
48
|
+
rid_r1 = dispatch_run({ issueIds: ["43"] })
|
|
49
|
+
poll status_get({ runId: rid_r1 }) until completed
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Regenerate a Spec (Respec)
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
# Call spec_generate again — it overwrites the existing spec file
|
|
56
|
+
rid = spec_generate({ issues: "42" })
|
|
57
|
+
poll spec_run_status({ runId: rid }) until completed
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Use this when prerequisite code has changed or the original spec was generated too early.
|
|
61
|
+
|
|
62
|
+
## Skip Planning (Simple Tasks)
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
rid = dispatch_run({ issueIds: ["42"], noPlan: true })
|
|
66
|
+
poll status_get({ runId: rid }) until completed
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Good for: typo fixes, config changes, adding a single obvious field.
|
|
70
|
+
|
|
71
|
+
## From Inline Description (No Issue)
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
rid = spec_generate({ issues: "add dark mode toggle to settings page" })
|
|
75
|
+
poll spec_run_status({ runId: rid }) until completed
|
|
76
|
+
# then dispatch as normal
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Retry Failed Tasks
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
# Inspect the failure
|
|
83
|
+
status = status_get({ runId: "abc-123" })
|
|
84
|
+
|
|
85
|
+
# Retry all failures in the run
|
|
86
|
+
rid_retry = run_retry({ runId: "abc-123" })
|
|
87
|
+
poll status_get({ runId: rid_retry }) until completed
|
|
88
|
+
|
|
89
|
+
# Or retry a single specific task
|
|
90
|
+
rid_task = task_retry({ runId: "abc-123", taskId: "42:3" })
|
|
91
|
+
poll status_get({ runId: rid_task }) until completed
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Check Recent Activity
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
runs_list({}) # all recent dispatch runs
|
|
98
|
+
runs_list({ status: "failed" }) # only failures
|
|
99
|
+
runs_list({ status: "running" }) # currently in-progress
|
|
100
|
+
spec_runs_list({}) # recent spec generation runs
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Feature Branch (Group Multiple Issues into One PR)
|
|
104
|
+
|
|
105
|
+
Run dispatch with `--feature` via the CLI, or dispatch issues sequentially and they'll be grouped if you use a shared branch. Consult the Dispatch README for the `--feature` flag usage.
|