opencodekit 0.16.15 → 0.16.17
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/dist/index.js +1 -1
- package/dist/template/.opencode/AGENTS.md +1 -1
- package/dist/template/.opencode/agent/plan.md +77 -161
- package/dist/template/.opencode/command/create.md +75 -307
- package/dist/template/.opencode/command/design.md +53 -589
- package/dist/template/.opencode/command/handoff.md +76 -180
- package/dist/template/.opencode/command/init.md +45 -211
- package/dist/template/.opencode/command/plan.md +62 -514
- package/dist/template/.opencode/command/pr.md +56 -226
- package/dist/template/.opencode/command/research.md +55 -266
- package/dist/template/.opencode/command/resume.md +33 -138
- package/dist/template/.opencode/command/review-codebase.md +54 -202
- package/dist/template/.opencode/command/ship.md +78 -127
- package/dist/template/.opencode/command/start.md +47 -577
- package/dist/template/.opencode/command/status.md +55 -354
- package/dist/template/.opencode/command/ui-review.md +52 -298
- package/dist/template/.opencode/command/verify.md +36 -250
- package/dist/template/.opencode/memory.db-shm +0 -0
- package/dist/template/.opencode/memory.db-wal +0 -0
- package/dist/template/.opencode/plugin/README.md +8 -4
- package/dist/template/.opencode/plugin/swarm-enforcer.ts +182 -27
- package/dist/template/.opencode/skill/augment-context-engine/SKILL.md +112 -0
- package/dist/template/.opencode/skill/augment-context-engine/mcp.json +6 -0
- package/dist/template/.opencode/skill/core-data-expert/SKILL.md +82 -0
- package/dist/template/.opencode/skill/core-data-expert/references/batch-operations.md +543 -0
- package/dist/template/.opencode/skill/core-data-expert/references/cloudkit-integration.md +259 -0
- package/dist/template/.opencode/skill/core-data-expert/references/concurrency.md +522 -0
- package/dist/template/.opencode/skill/core-data-expert/references/fetch-requests.md +643 -0
- package/dist/template/.opencode/skill/core-data-expert/references/glossary.md +233 -0
- package/dist/template/.opencode/skill/core-data-expert/references/migration.md +393 -0
- package/dist/template/.opencode/skill/core-data-expert/references/model-configuration.md +597 -0
- package/dist/template/.opencode/skill/core-data-expert/references/performance.md +300 -0
- package/dist/template/.opencode/skill/core-data-expert/references/persistent-history.md +553 -0
- package/dist/template/.opencode/skill/core-data-expert/references/project-audit.md +60 -0
- package/dist/template/.opencode/skill/core-data-expert/references/saving.md +574 -0
- package/dist/template/.opencode/skill/core-data-expert/references/stack-setup.md +625 -0
- package/dist/template/.opencode/skill/core-data-expert/references/testing.md +300 -0
- package/dist/template/.opencode/skill/core-data-expert/references/threading.md +589 -0
- package/dist/template/.opencode/skill/swift-concurrency/SKILL.md +246 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/actors.md +640 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/async-algorithms.md +822 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/async-await-basics.md +249 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/async-sequences.md +670 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/core-data.md +533 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/glossary.md +128 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/linting.md +142 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/memory-management.md +542 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/migration.md +1076 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/performance.md +574 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/sendable.md +578 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/tasks.md +604 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/testing.md +565 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/threading.md +452 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/SKILL.md +290 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-advanced.md +351 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-basics.md +284 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-transitions.md +326 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/image-optimization.md +286 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/layout-best-practices.md +312 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/liquid-glass.md +377 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/list-patterns.md +153 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/modern-apis.md +400 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/performance-patterns.md +377 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/scroll-patterns.md +305 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/sheet-navigation-patterns.md +292 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/state-management.md +447 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/text-formatting.md +285 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/view-structure.md +276 -0
- package/package.json +1 -1
|
@@ -2,20 +2,17 @@
|
|
|
2
2
|
description: Verify implementation completeness, correctness, and coherence
|
|
3
3
|
argument-hint: "<bead-id> [--quick] [--fix]"
|
|
4
4
|
agent: review
|
|
5
|
-
subtask: true
|
|
6
5
|
---
|
|
7
6
|
|
|
8
7
|
# Verify: $ARGUMENTS
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
Check implementation against PRD before shipping.
|
|
11
10
|
|
|
12
11
|
## Load Skills
|
|
13
12
|
|
|
14
13
|
```typescript
|
|
15
14
|
skill({ name: "beads" });
|
|
16
15
|
skill({ name: "verification-before-completion" });
|
|
17
|
-
skill({ name: "systematic-debugging" });
|
|
18
|
-
skill({ name: "memory-system" });
|
|
19
16
|
```
|
|
20
17
|
|
|
21
18
|
## Parse Arguments
|
|
@@ -23,285 +20,74 @@ skill({ name: "memory-system" });
|
|
|
23
20
|
| Argument | Default | Description |
|
|
24
21
|
| ----------- | -------- | -------------------------------- |
|
|
25
22
|
| `<bead-id>` | required | The bead to verify |
|
|
26
|
-
| `--quick` | false |
|
|
27
|
-
| `--fix` | false | Auto-fix issues
|
|
23
|
+
| `--quick` | false | Gates only, skip coherence check |
|
|
24
|
+
| `--fix` | false | Auto-fix lint/format issues |
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
## Phase 1: Check Memory for Context
|
|
32
|
-
|
|
33
|
-
Search for relevant verification patterns and past issues:
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
memory_search({ query: "$ARGUMENTS verification issues patterns", limit: 3 });
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## Phase 2: Gather Artifacts
|
|
26
|
+
## Phase 1: Gather Context
|
|
42
27
|
|
|
43
28
|
```bash
|
|
44
29
|
br show $ARGUMENTS
|
|
45
30
|
ls .beads/artifacts/$ARGUMENTS/
|
|
46
31
|
```
|
|
47
32
|
|
|
48
|
-
Read
|
|
33
|
+
Read the PRD and any other artifacts (plan.md, research.md, design.md).
|
|
49
34
|
|
|
50
|
-
|
|
51
|
-
cat .beads/artifacts/$ARGUMENTS/prd.md 2>/dev/null
|
|
52
|
-
cat .beads/artifacts/$ARGUMENTS/plan.md 2>/dev/null
|
|
53
|
-
cat .beads/artifacts/$ARGUMENTS/research.md 2>/dev/null
|
|
54
|
-
cat .beads/artifacts/$ARGUMENTS/design.md 2>/dev/null
|
|
55
|
-
```
|
|
35
|
+
## Phase 2: Completeness
|
|
56
36
|
|
|
57
|
-
|
|
37
|
+
Extract all requirements/tasks from the PRD and verify each is implemented:
|
|
58
38
|
|
|
59
|
-
|
|
39
|
+
- For each requirement: find evidence in the codebase (file:line reference)
|
|
40
|
+
- Mark as: complete, partial, or missing
|
|
41
|
+
- Report completeness score (X/Y requirements met)
|
|
60
42
|
|
|
61
|
-
|
|
43
|
+
## Phase 3: Correctness
|
|
62
44
|
|
|
63
|
-
|
|
64
|
-
| ------------- | -------- | ------ |
|
|
65
|
-
| `prd.md` | Yes | [ ] |
|
|
66
|
-
| `plan.md` | Yes | [ ] |
|
|
67
|
-
| `research.md` | No | [ ] |
|
|
68
|
-
| `design.md` | No | [ ] |
|
|
45
|
+
Detect project type and run the appropriate verification gates:
|
|
69
46
|
|
|
70
|
-
|
|
47
|
+
| Project Type | Detect Via | Build | Test | Lint | Typecheck |
|
|
48
|
+
| --------------- | ----------------------------- | ---------------- | --------------- | ----------------------------- | ------------------------------------- |
|
|
49
|
+
| Node/TypeScript | `package.json` | `npm run build` | `npm test` | `npm run lint` | `npm run typecheck` or `tsc --noEmit` |
|
|
50
|
+
| Rust | `Cargo.toml` | `cargo build` | `cargo test` | `cargo clippy -- -D warnings` | (included in build) |
|
|
51
|
+
| Python | `pyproject.toml` / `setup.py` | — | `pytest` | `ruff check .` | `mypy .` |
|
|
52
|
+
| Go | `go.mod` | `go build ./...` | `go test ./...` | `golangci-lint run` | (included in build) |
|
|
71
53
|
|
|
72
|
-
|
|
54
|
+
Check `package.json` scripts, `Makefile`, or `justfile` for project-specific commands first — prefer those over generic defaults.
|
|
73
55
|
|
|
74
|
-
|
|
75
|
-
## Completeness Report
|
|
56
|
+
If `--fix` flag provided, run the project's auto-fix command (e.g., `npm run lint:fix`, `ruff check --fix`, `cargo clippy --fix`).
|
|
76
57
|
|
|
77
|
-
|
|
78
|
-
| ----------------- | ---------- | ----------------------- |
|
|
79
|
-
| [Req 1 from spec] | ✓ Complete | `src/foo.ts:42` |
|
|
80
|
-
| [Req 2 from spec] | ✓ Complete | `src/bar.ts:15` |
|
|
81
|
-
| [Req 3 from spec] | ⚠ Partial | Missing edge case tests |
|
|
82
|
-
| [Req 4 from spec] | ✗ Missing | Not implemented |
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
**Completeness Score:** X/Y requirements met
|
|
86
|
-
|
|
87
|
-
---
|
|
88
|
-
|
|
89
|
-
## Phase 4: Correctness Check
|
|
90
|
-
|
|
91
|
-
**Do the automated gates pass?**
|
|
92
|
-
|
|
93
|
-
```bash
|
|
94
|
-
# Detect project type and run gates
|
|
95
|
-
ls package.json Cargo.toml pyproject.toml go.mod 2>/dev/null
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
**Node/TypeScript:**
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
npm run build 2>&1 | tail -10
|
|
102
|
-
npm test 2>&1 | tail -20
|
|
103
|
-
npm run lint 2>&1 | tail -10
|
|
104
|
-
npm run typecheck 2>&1 | tail -10
|
|
105
|
-
```
|
|
58
|
+
Report gate results (pass/warn/fail for each).
|
|
106
59
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
cargo build 2>&1 | tail -10
|
|
111
|
-
cargo test 2>&1 | tail -20
|
|
112
|
-
cargo clippy -- -D warnings 2>&1 | tail -10
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
**Python:**
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
pytest 2>&1 | tail -20
|
|
119
|
-
ruff check . 2>&1 | tail -10
|
|
120
|
-
mypy . 2>&1 | tail -10
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
**Go:**
|
|
124
|
-
|
|
125
|
-
```bash
|
|
126
|
-
go build ./... 2>&1 | tail -10
|
|
127
|
-
go test ./... 2>&1 | tail -20
|
|
128
|
-
golangci-lint run 2>&1 | tail -10
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
```markdown
|
|
132
|
-
## Correctness Report
|
|
133
|
-
|
|
134
|
-
| Gate | Status | Details |
|
|
135
|
-
| --------- | ------ | ------------------------- |
|
|
136
|
-
| Build | ✓ Pass | |
|
|
137
|
-
| Tests | ✓ Pass | 42 tests, 0 failures |
|
|
138
|
-
| Lint | ⚠ Warn | 2 warnings (non-blocking) |
|
|
139
|
-
| Typecheck | ✓ Pass | |
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
**Correctness Score:** X/Y gates passed
|
|
143
|
-
|
|
144
|
-
---
|
|
145
|
-
|
|
146
|
-
## Phase 5: Coherence Check (skip with --quick)
|
|
147
|
-
|
|
148
|
-
**Do artifacts agree with each other?**
|
|
60
|
+
## Phase 4: Coherence (skip with --quick)
|
|
149
61
|
|
|
150
62
|
Cross-reference artifacts for contradictions:
|
|
151
63
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
| plan.md ↔ implementation | ✓ | Code follows plan structure |
|
|
156
|
-
| research.md ↔ implementation | ⚠ | Didn't use recommended approach |
|
|
157
|
-
| design.md ↔ implementation | ✓ | Follows design patterns |
|
|
158
|
-
|
|
159
|
-
**Common coherence issues:**
|
|
160
|
-
|
|
161
|
-
- Plan says X, implementation does Y
|
|
162
|
-
- Research recommended approach A, used approach B (without justification)
|
|
163
|
-
- Spec says must-have, implementation treats as optional
|
|
164
|
-
- Design specifies pattern, implementation uses different pattern
|
|
64
|
+
- PRD vs implementation (does code address all PRD requirements?)
|
|
65
|
+
- Plan vs implementation (did code follow the plan?)
|
|
66
|
+
- Research recommendations vs actual approach (if different, is it justified?)
|
|
165
67
|
|
|
166
|
-
|
|
167
|
-
## Coherence Report
|
|
168
|
-
|
|
169
|
-
Contradictions found: 1
|
|
170
|
-
|
|
171
|
-
1. **Research vs Implementation**
|
|
172
|
-
- Research recommended: Use `zod` for validation
|
|
173
|
-
- Implementation uses: Manual validation
|
|
174
|
-
- Impact: Medium - works but less maintainable
|
|
175
|
-
- Action: Document decision or refactor
|
|
176
|
-
```
|
|
68
|
+
Flag contradictions with specific file references.
|
|
177
69
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
---
|
|
181
|
-
|
|
182
|
-
## Phase 6: Verification Summary
|
|
183
|
-
|
|
184
|
-
```
|
|
185
|
-
Verification: $ARGUMENTS
|
|
186
|
-
━━━━━━━━━━━━━━━━━━━━━━━
|
|
187
|
-
|
|
188
|
-
Dimension Score Status
|
|
189
|
-
───────────────────────────────
|
|
190
|
-
Completeness 4/5 ⚠ PARTIAL
|
|
191
|
-
Correctness 4/4 ✓ PASS
|
|
192
|
-
Coherence 3/4 ⚠ PARTIAL
|
|
193
|
-
|
|
194
|
-
Overall: ⚠ NEEDS ATTENTION
|
|
195
|
-
|
|
196
|
-
Issues Found:
|
|
197
|
-
─────────────
|
|
198
|
-
BLOCKING (must fix):
|
|
199
|
-
• [Req 4] Not implemented
|
|
200
|
-
|
|
201
|
-
NON-BLOCKING (should fix):
|
|
202
|
-
• [Req 3] Missing edge case tests
|
|
203
|
-
• Research recommendation not followed
|
|
204
|
-
|
|
205
|
-
Recommendations:
|
|
206
|
-
────────────────
|
|
207
|
-
1. Implement [Req 4] before closing
|
|
208
|
-
2. Add tests for edge case X
|
|
209
|
-
3. Document why zod was not used, or refactor to use it
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
## Phase 7: Auto-Fix (if --fix)
|
|
215
|
-
|
|
216
|
-
For fixable issues, attempt automatic resolution:
|
|
217
|
-
|
|
218
|
-
```typescript
|
|
219
|
-
// If lint issues are fixable
|
|
220
|
-
if (hasLintWarnings && canAutoFix) {
|
|
221
|
-
bash({ command: "npm run lint -- --fix" });
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// If missing tests detected
|
|
225
|
-
if (missingTests) {
|
|
226
|
-
console.log("Consider adding tests for: [list uncovered code]");
|
|
227
|
-
}
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
---
|
|
231
|
-
|
|
232
|
-
## Phase 8: Update Bead Notes
|
|
233
|
-
|
|
234
|
-
Record verification results in bead:
|
|
70
|
+
## Phase 5: Report
|
|
235
71
|
|
|
236
72
|
```bash
|
|
237
73
|
br comments add $ARGUMENTS "Verification: [PASS|PARTIAL|FAIL] - [summary]"
|
|
238
74
|
```
|
|
239
75
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
## Phase 9: Record Findings
|
|
243
|
-
|
|
244
|
-
If significant issues or patterns discovered:
|
|
245
|
-
|
|
246
|
-
```typescript
|
|
247
|
-
observation({
|
|
248
|
-
type: "discovery",
|
|
249
|
-
title: "Verification findings for $ARGUMENTS",
|
|
250
|
-
narrative: "[Summary of issues found, patterns discovered, or lessons learned]",
|
|
251
|
-
concepts: "verification, testing, quality",
|
|
252
|
-
bead_id: "$ARGUMENTS",
|
|
253
|
-
confidence: "high",
|
|
254
|
-
});
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
---
|
|
258
|
-
|
|
259
|
-
## Output
|
|
260
|
-
|
|
261
|
-
```
|
|
262
|
-
Verification Complete: $ARGUMENTS
|
|
263
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
264
|
-
|
|
265
|
-
Result: ✓ READY TO SHIP | ⚠ NEEDS WORK | ✗ BLOCKED
|
|
266
|
-
|
|
267
|
-
Completeness: [score] - [status]
|
|
268
|
-
Correctness: [score] - [status]
|
|
269
|
-
Coherence: [score] - [status]
|
|
270
|
-
|
|
271
|
-
[If READY TO SHIP]
|
|
272
|
-
Next: /ship $ARGUMENTS
|
|
273
|
-
|
|
274
|
-
[If NEEDS WORK]
|
|
275
|
-
Fix these before shipping:
|
|
276
|
-
• [issue 1]
|
|
277
|
-
• [issue 2]
|
|
278
|
-
|
|
279
|
-
[If BLOCKED]
|
|
280
|
-
Cannot proceed until:
|
|
281
|
-
• [blocker 1]
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
---
|
|
285
|
-
|
|
286
|
-
## Examples
|
|
287
|
-
|
|
288
|
-
```bash
|
|
289
|
-
# Full verification
|
|
290
|
-
/verify br-feature-auth
|
|
291
|
-
|
|
292
|
-
# Quick check (gates only)
|
|
293
|
-
/verify br-feature-auth --quick
|
|
76
|
+
Output:
|
|
294
77
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
78
|
+
1. **Result**: READY TO SHIP / NEEDS WORK / BLOCKED
|
|
79
|
+
2. **Completeness**: score and status
|
|
80
|
+
3. **Correctness**: gate results
|
|
81
|
+
4. **Coherence**: contradictions found (if not --quick)
|
|
82
|
+
5. **Blocking issues** to fix before shipping
|
|
83
|
+
6. **Next step**: `/ship $ARGUMENTS` if ready, or list fixes needed
|
|
298
84
|
|
|
299
|
-
|
|
85
|
+
Record significant findings with `observation()`.
|
|
300
86
|
|
|
301
87
|
## Related Commands
|
|
302
88
|
|
|
303
89
|
| Need | Command |
|
|
304
90
|
| ----------------- | ------------------ |
|
|
305
|
-
| Ship after verify | `/ship
|
|
91
|
+
| Ship after verify | `/ship <id>` |
|
|
306
92
|
| Review code | `/review-codebase` |
|
|
307
93
|
| Check status | `/status` |
|
|
Binary file
|
|
Binary file
|
|
@@ -82,12 +82,16 @@ Session 3: read_session("previous") → Tests (90k) → close
|
|
|
82
82
|
|
|
83
83
|
### swarm-enforcer.ts
|
|
84
84
|
|
|
85
|
-
**Swarm protocol guardrails (Beads-as-board)** -
|
|
85
|
+
**Swarm protocol guardrails (Beads-as-board)** - enforces the `/create` → `/start` → `/ship` workflow.
|
|
86
86
|
|
|
87
87
|
- Treats `.beads/` as the single source of truth for the swarm task board
|
|
88
|
-
-
|
|
89
|
-
-
|
|
90
|
-
-
|
|
88
|
+
- **Workflow stage tracking**: Computes each bead's stage based on artifacts and status:
|
|
89
|
+
- `⏳needs:/create` — no prd.md exists yet
|
|
90
|
+
- `⏳needs:/start` — has prd.md but not claimed (in_progress)
|
|
91
|
+
- `✅ready:/ship` — in_progress with prd.md, ready for implementation
|
|
92
|
+
- `⚠needs:/create→/start` — in_progress but missing prd.md
|
|
93
|
+
- **System prompt injection** via `experimental.chat.system.transform`: injects workflow stage per bead, enforcement rules ("Do NOT implement until `/start`"), and protocol reminders into every LLM call
|
|
94
|
+
- On `file.edited`, warns if code is being changed without a claimed task or when workflow is incomplete (no prd.md)
|
|
91
95
|
- On `session.idle`, reminds to `br close` + `br sync` when work is done
|
|
92
96
|
|
|
93
97
|
### notification.ts
|
|
@@ -3,14 +3,13 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Beads is the single source of truth for the swarm board.
|
|
5
5
|
* This plugin provides non-intrusive enforcement:
|
|
6
|
+
* - System prompt injection with active beads state (via experimental.chat.system.transform)
|
|
7
|
+
* - Workflow stage tracking: /create → /start → /ship (enforced order)
|
|
6
8
|
* - Toast warning when code is edited without a claimed task
|
|
7
|
-
* - Toast warning when in-progress tasks are missing
|
|
9
|
+
* - Toast warning when in-progress tasks are missing prd.md
|
|
10
|
+
* - Toast warning when implementation starts before /start
|
|
8
11
|
* - Session-end reminder to close/sync in-progress tasks
|
|
9
12
|
*
|
|
10
|
-
* NOTE: chat.message nudging was removed — AGENTS.md and the beads skill
|
|
11
|
-
* already instruct agents on the beads protocol. Injecting ASCII blocks
|
|
12
|
-
* on every user message mentioning work intent caused excessive noise.
|
|
13
|
-
*
|
|
14
13
|
* This plugin is intentionally non-destructive: it never runs `br update/close/sync`.
|
|
15
14
|
*/
|
|
16
15
|
|
|
@@ -22,8 +21,19 @@ type BeadsIssue = {
|
|
|
22
21
|
id: string;
|
|
23
22
|
title?: string;
|
|
24
23
|
status?: string;
|
|
24
|
+
priority?: number;
|
|
25
|
+
issue_type?: string;
|
|
25
26
|
};
|
|
26
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Workflow stage for a bead:
|
|
30
|
+
* - "uncreated": No prd.md exists — needs `/create`
|
|
31
|
+
* - "created": Has prd.md but not in_progress — needs `/start`
|
|
32
|
+
* - "started": In progress with prd.md — ready for `/ship`
|
|
33
|
+
* - "started-no-prd": In progress but missing prd.md — needs `/create` first
|
|
34
|
+
*/
|
|
35
|
+
type WorkflowStage = "uncreated" | "created" | "started" | "started-no-prd";
|
|
36
|
+
|
|
27
37
|
const BEADS_DIR = ".beads";
|
|
28
38
|
const ISSUES_FILE = "issues.jsonl";
|
|
29
39
|
|
|
@@ -88,6 +98,12 @@ async function readIssuesJsonl(repoDir: string): Promise<BeadsIssue[]> {
|
|
|
88
98
|
id: parsed.id,
|
|
89
99
|
title: typeof parsed.title === "string" ? parsed.title : undefined,
|
|
90
100
|
status: typeof parsed.status === "string" ? parsed.status : undefined,
|
|
101
|
+
priority:
|
|
102
|
+
typeof parsed.priority === "number" ? parsed.priority : undefined,
|
|
103
|
+
issue_type:
|
|
104
|
+
typeof parsed.issue_type === "string"
|
|
105
|
+
? parsed.issue_type
|
|
106
|
+
: undefined,
|
|
91
107
|
});
|
|
92
108
|
}
|
|
93
109
|
} catch {
|
|
@@ -98,27 +114,46 @@ async function readIssuesJsonl(repoDir: string): Promise<BeadsIssue[]> {
|
|
|
98
114
|
return issues;
|
|
99
115
|
}
|
|
100
116
|
|
|
101
|
-
async function
|
|
102
|
-
|
|
117
|
+
async function artifactExists(
|
|
118
|
+
repoDir: string,
|
|
119
|
+
issueId: string,
|
|
120
|
+
filename: string,
|
|
121
|
+
): Promise<boolean> {
|
|
122
|
+
const filePath = path.join(
|
|
103
123
|
repoDir,
|
|
104
124
|
BEADS_DIR,
|
|
105
125
|
"artifacts",
|
|
106
126
|
issueId,
|
|
107
|
-
|
|
127
|
+
filename,
|
|
108
128
|
);
|
|
109
129
|
try {
|
|
110
|
-
await fsPromises.access(
|
|
130
|
+
await fsPromises.access(filePath);
|
|
111
131
|
return true;
|
|
112
132
|
} catch {
|
|
113
133
|
return false;
|
|
114
134
|
}
|
|
115
135
|
}
|
|
116
136
|
|
|
137
|
+
function getWorkflowStage(issue: BeadsIssue, hasPrd: boolean): WorkflowStage {
|
|
138
|
+
const isInProgress = issue.status === "in_progress";
|
|
139
|
+
|
|
140
|
+
if (isInProgress && hasPrd) return "started";
|
|
141
|
+
if (isInProgress && !hasPrd) return "started-no-prd";
|
|
142
|
+
if (hasPrd) return "created";
|
|
143
|
+
return "uncreated";
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
type IssueWithStage = BeadsIssue & {
|
|
147
|
+
stage: WorkflowStage;
|
|
148
|
+
hasPrd: boolean;
|
|
149
|
+
hasPlan: boolean;
|
|
150
|
+
};
|
|
151
|
+
|
|
117
152
|
export const SwarmEnforcer: Plugin = async ({ client, directory }) => {
|
|
118
153
|
const repoDir = directory || process.cwd();
|
|
119
154
|
let lastStateAt = 0;
|
|
120
|
-
let cachedInProgress:
|
|
121
|
-
let
|
|
155
|
+
let cachedInProgress: IssueWithStage[] = [];
|
|
156
|
+
let cachedAllActive: IssueWithStage[] = [];
|
|
122
157
|
|
|
123
158
|
const refreshState = async () => {
|
|
124
159
|
const now = Date.now();
|
|
@@ -126,17 +161,20 @@ export const SwarmEnforcer: Plugin = async ({ client, directory }) => {
|
|
|
126
161
|
lastStateAt = now;
|
|
127
162
|
|
|
128
163
|
const issues = await readIssuesJsonl(repoDir);
|
|
129
|
-
const
|
|
164
|
+
const active = issues.filter(
|
|
165
|
+
(i) => i.status === "in_progress" || i.status === "open",
|
|
166
|
+
);
|
|
130
167
|
|
|
131
|
-
const
|
|
132
|
-
for (const issue of
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
168
|
+
const enriched: IssueWithStage[] = [];
|
|
169
|
+
for (const issue of active.slice(0, 15)) {
|
|
170
|
+
const hasPrd = await artifactExists(repoDir, issue.id, "prd.md");
|
|
171
|
+
const hasPlan = await artifactExists(repoDir, issue.id, "plan.md");
|
|
172
|
+
const stage = getWorkflowStage(issue, hasPrd);
|
|
173
|
+
enriched.push({ ...issue, stage, hasPrd, hasPlan });
|
|
136
174
|
}
|
|
137
175
|
|
|
138
|
-
|
|
139
|
-
|
|
176
|
+
cachedAllActive = enriched;
|
|
177
|
+
cachedInProgress = enriched.filter((i) => i.status === "in_progress");
|
|
140
178
|
};
|
|
141
179
|
|
|
142
180
|
const showToast = async (
|
|
@@ -159,7 +197,115 @@ export const SwarmEnforcer: Plugin = async ({ client, directory }) => {
|
|
|
159
197
|
};
|
|
160
198
|
|
|
161
199
|
return {
|
|
162
|
-
//
|
|
200
|
+
// Inject active beads state + workflow stage into system prompt
|
|
201
|
+
"experimental.chat.system.transform": async (_input, output) => {
|
|
202
|
+
await refreshState();
|
|
203
|
+
|
|
204
|
+
if (cachedAllActive.length === 0) return;
|
|
205
|
+
|
|
206
|
+
const priorityLabel = (p?: number) => {
|
|
207
|
+
if (p === 0) return "P0-critical";
|
|
208
|
+
if (p === 1) return "P1-high";
|
|
209
|
+
if (p === 2) return "P2-normal";
|
|
210
|
+
if (p === 3) return "P3-low";
|
|
211
|
+
return "P?";
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const stageLabel = (stage: WorkflowStage) => {
|
|
215
|
+
switch (stage) {
|
|
216
|
+
case "uncreated":
|
|
217
|
+
return "⏳needs:/create";
|
|
218
|
+
case "created":
|
|
219
|
+
return "⏳needs:/start";
|
|
220
|
+
case "started":
|
|
221
|
+
return "✅ready:/ship";
|
|
222
|
+
case "started-no-prd":
|
|
223
|
+
return "⚠needs:/create→/start";
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
const lines: string[] = [];
|
|
228
|
+
lines.push("<beads-state>");
|
|
229
|
+
lines.push("## Active Beads");
|
|
230
|
+
lines.push("");
|
|
231
|
+
|
|
232
|
+
// Show in-progress first, then open
|
|
233
|
+
const sorted = [...cachedAllActive].sort((a, b) => {
|
|
234
|
+
if (a.status === "in_progress" && b.status !== "in_progress") return -1;
|
|
235
|
+
if (a.status !== "in_progress" && b.status === "in_progress") return 1;
|
|
236
|
+
return 0;
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
for (const issue of sorted.slice(0, 7)) {
|
|
240
|
+
const typeTag = issue.issue_type || "task";
|
|
241
|
+
const prioTag = priorityLabel(issue.priority);
|
|
242
|
+
const stage = stageLabel(issue.stage);
|
|
243
|
+
const statusTag =
|
|
244
|
+
issue.status === "in_progress" ? "🔧in_progress" : "📋open";
|
|
245
|
+
lines.push(
|
|
246
|
+
`- **${issue.id}** ${issue.title || "(untitled)"} [${typeTag} ${prioTag}] ${statusTag} ${stage}`,
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Workflow enforcement warnings
|
|
251
|
+
const needsCreate = cachedAllActive.filter(
|
|
252
|
+
(i) => i.stage === "uncreated" || i.stage === "started-no-prd",
|
|
253
|
+
);
|
|
254
|
+
const needsStart = cachedAllActive.filter((i) => i.stage === "created");
|
|
255
|
+
const readyToShip = cachedInProgress.filter((i) => i.stage === "started");
|
|
256
|
+
|
|
257
|
+
lines.push("");
|
|
258
|
+
lines.push("**Workflow enforcement (required order):**");
|
|
259
|
+
lines.push(
|
|
260
|
+
"1. `/create <description>` — creates bead + prd.md (specification)",
|
|
261
|
+
);
|
|
262
|
+
lines.push(
|
|
263
|
+
"2. `/start <id>` — claims task, creates branch, sets in_progress",
|
|
264
|
+
);
|
|
265
|
+
lines.push("3. `/ship <id>` — implement, verify, review, close");
|
|
266
|
+
lines.push("");
|
|
267
|
+
lines.push(
|
|
268
|
+
"⛔ **Do NOT implement code until `/start` has been run.** Edit code only for beads marked ✅ready:/ship.",
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
if (needsCreate.length > 0) {
|
|
272
|
+
lines.push("");
|
|
273
|
+
lines.push(
|
|
274
|
+
`⚠ ${needsCreate.length} bead(s) need \`/create\`: ${needsCreate.map((i) => i.id).join(", ")}`,
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (needsStart.length > 0) {
|
|
279
|
+
lines.push("");
|
|
280
|
+
lines.push(
|
|
281
|
+
`⚠ ${needsStart.length} bead(s) have prd.md but need \`/start\`: ${needsStart.map((i) => i.id).join(", ")}`,
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (readyToShip.length > 0) {
|
|
286
|
+
lines.push("");
|
|
287
|
+
lines.push(
|
|
288
|
+
`✅ ${readyToShip.length} bead(s) ready for \`/ship\`: ${readyToShip.map((i) => i.id).join(", ")}`,
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
lines.push("");
|
|
293
|
+
lines.push("**Beads protocol reminders:**");
|
|
294
|
+
lines.push(
|
|
295
|
+
"- Claim before editing: `br update <id> --status in_progress`",
|
|
296
|
+
);
|
|
297
|
+
lines.push(
|
|
298
|
+
'- When done: `br close <id> --reason="..."` → `br sync --flush-only` → git commit',
|
|
299
|
+
);
|
|
300
|
+
lines.push(
|
|
301
|
+
'- Discovered work (>2min): `br create --title "..." --type bug|task`',
|
|
302
|
+
);
|
|
303
|
+
lines.push("</beads-state>");
|
|
304
|
+
|
|
305
|
+
output.system.push(lines.join("\n"));
|
|
306
|
+
},
|
|
307
|
+
|
|
308
|
+
// Warn if code gets edited while no task is claimed / workflow not followed
|
|
163
309
|
event: async ({ event }) => {
|
|
164
310
|
if (event.type === "file.edited") {
|
|
165
311
|
const filePath = event.properties?.file;
|
|
@@ -174,22 +320,31 @@ export const SwarmEnforcer: Plugin = async ({ client, directory }) => {
|
|
|
174
320
|
|
|
175
321
|
await refreshState();
|
|
176
322
|
|
|
323
|
+
// No tasks claimed at all
|
|
177
324
|
if (cachedInProgress.length === 0) {
|
|
178
325
|
await showToast(
|
|
179
326
|
"Beads: No task claimed",
|
|
180
|
-
"Run
|
|
327
|
+
"Run /start <id> to claim a task before editing code.",
|
|
181
328
|
"warning",
|
|
182
329
|
);
|
|
183
330
|
return;
|
|
184
331
|
}
|
|
185
332
|
|
|
186
|
-
|
|
333
|
+
// Tasks in progress but none are ready for /ship
|
|
334
|
+
const readyForShip = cachedInProgress.filter(
|
|
335
|
+
(i) => i.stage === "started",
|
|
336
|
+
);
|
|
337
|
+
if (readyForShip.length === 0) {
|
|
338
|
+
const notReady = cachedInProgress.filter(
|
|
339
|
+
(i) => i.stage !== "started",
|
|
340
|
+
);
|
|
341
|
+
const ids = notReady
|
|
342
|
+
.slice(0, 3)
|
|
343
|
+
.map((i) => i.id)
|
|
344
|
+
.join(", ");
|
|
187
345
|
await showToast(
|
|
188
|
-
"Beads:
|
|
189
|
-
`
|
|
190
|
-
.slice(0, 3)
|
|
191
|
-
.map((i) => i.id)
|
|
192
|
-
.join(", ")}`,
|
|
346
|
+
"Beads: Workflow incomplete",
|
|
347
|
+
`Task(s) ${ids} need prd.md via /create before implementing.`,
|
|
193
348
|
"warning",
|
|
194
349
|
);
|
|
195
350
|
}
|