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.
Files changed (69) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/template/.opencode/AGENTS.md +1 -1
  3. package/dist/template/.opencode/agent/plan.md +77 -161
  4. package/dist/template/.opencode/command/create.md +75 -307
  5. package/dist/template/.opencode/command/design.md +53 -589
  6. package/dist/template/.opencode/command/handoff.md +76 -180
  7. package/dist/template/.opencode/command/init.md +45 -211
  8. package/dist/template/.opencode/command/plan.md +62 -514
  9. package/dist/template/.opencode/command/pr.md +56 -226
  10. package/dist/template/.opencode/command/research.md +55 -266
  11. package/dist/template/.opencode/command/resume.md +33 -138
  12. package/dist/template/.opencode/command/review-codebase.md +54 -202
  13. package/dist/template/.opencode/command/ship.md +78 -127
  14. package/dist/template/.opencode/command/start.md +47 -577
  15. package/dist/template/.opencode/command/status.md +55 -354
  16. package/dist/template/.opencode/command/ui-review.md +52 -298
  17. package/dist/template/.opencode/command/verify.md +36 -250
  18. package/dist/template/.opencode/memory.db-shm +0 -0
  19. package/dist/template/.opencode/memory.db-wal +0 -0
  20. package/dist/template/.opencode/plugin/README.md +8 -4
  21. package/dist/template/.opencode/plugin/swarm-enforcer.ts +182 -27
  22. package/dist/template/.opencode/skill/augment-context-engine/SKILL.md +112 -0
  23. package/dist/template/.opencode/skill/augment-context-engine/mcp.json +6 -0
  24. package/dist/template/.opencode/skill/core-data-expert/SKILL.md +82 -0
  25. package/dist/template/.opencode/skill/core-data-expert/references/batch-operations.md +543 -0
  26. package/dist/template/.opencode/skill/core-data-expert/references/cloudkit-integration.md +259 -0
  27. package/dist/template/.opencode/skill/core-data-expert/references/concurrency.md +522 -0
  28. package/dist/template/.opencode/skill/core-data-expert/references/fetch-requests.md +643 -0
  29. package/dist/template/.opencode/skill/core-data-expert/references/glossary.md +233 -0
  30. package/dist/template/.opencode/skill/core-data-expert/references/migration.md +393 -0
  31. package/dist/template/.opencode/skill/core-data-expert/references/model-configuration.md +597 -0
  32. package/dist/template/.opencode/skill/core-data-expert/references/performance.md +300 -0
  33. package/dist/template/.opencode/skill/core-data-expert/references/persistent-history.md +553 -0
  34. package/dist/template/.opencode/skill/core-data-expert/references/project-audit.md +60 -0
  35. package/dist/template/.opencode/skill/core-data-expert/references/saving.md +574 -0
  36. package/dist/template/.opencode/skill/core-data-expert/references/stack-setup.md +625 -0
  37. package/dist/template/.opencode/skill/core-data-expert/references/testing.md +300 -0
  38. package/dist/template/.opencode/skill/core-data-expert/references/threading.md +589 -0
  39. package/dist/template/.opencode/skill/swift-concurrency/SKILL.md +246 -0
  40. package/dist/template/.opencode/skill/swift-concurrency/references/actors.md +640 -0
  41. package/dist/template/.opencode/skill/swift-concurrency/references/async-algorithms.md +822 -0
  42. package/dist/template/.opencode/skill/swift-concurrency/references/async-await-basics.md +249 -0
  43. package/dist/template/.opencode/skill/swift-concurrency/references/async-sequences.md +670 -0
  44. package/dist/template/.opencode/skill/swift-concurrency/references/core-data.md +533 -0
  45. package/dist/template/.opencode/skill/swift-concurrency/references/glossary.md +128 -0
  46. package/dist/template/.opencode/skill/swift-concurrency/references/linting.md +142 -0
  47. package/dist/template/.opencode/skill/swift-concurrency/references/memory-management.md +542 -0
  48. package/dist/template/.opencode/skill/swift-concurrency/references/migration.md +1076 -0
  49. package/dist/template/.opencode/skill/swift-concurrency/references/performance.md +574 -0
  50. package/dist/template/.opencode/skill/swift-concurrency/references/sendable.md +578 -0
  51. package/dist/template/.opencode/skill/swift-concurrency/references/tasks.md +604 -0
  52. package/dist/template/.opencode/skill/swift-concurrency/references/testing.md +565 -0
  53. package/dist/template/.opencode/skill/swift-concurrency/references/threading.md +452 -0
  54. package/dist/template/.opencode/skill/swiftui-expert-skill/SKILL.md +290 -0
  55. package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-advanced.md +351 -0
  56. package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-basics.md +284 -0
  57. package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-transitions.md +326 -0
  58. package/dist/template/.opencode/skill/swiftui-expert-skill/references/image-optimization.md +286 -0
  59. package/dist/template/.opencode/skill/swiftui-expert-skill/references/layout-best-practices.md +312 -0
  60. package/dist/template/.opencode/skill/swiftui-expert-skill/references/liquid-glass.md +377 -0
  61. package/dist/template/.opencode/skill/swiftui-expert-skill/references/list-patterns.md +153 -0
  62. package/dist/template/.opencode/skill/swiftui-expert-skill/references/modern-apis.md +400 -0
  63. package/dist/template/.opencode/skill/swiftui-expert-skill/references/performance-patterns.md +377 -0
  64. package/dist/template/.opencode/skill/swiftui-expert-skill/references/scroll-patterns.md +305 -0
  65. package/dist/template/.opencode/skill/swiftui-expert-skill/references/sheet-navigation-patterns.md +292 -0
  66. package/dist/template/.opencode/skill/swiftui-expert-skill/references/state-management.md +447 -0
  67. package/dist/template/.opencode/skill/swiftui-expert-skill/references/text-formatting.md +285 -0
  68. package/dist/template/.opencode/skill/swiftui-expert-skill/references/view-structure.md +276 -0
  69. 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
- Three-dimensional verification before claiming work complete. Inspired by OpenSpec's verify workflow.
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 | Skip coherence check, gates only |
27
- | `--fix` | false | Auto-fix issues where possible |
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 all artifacts:
33
+ Read the PRD and any other artifacts (plan.md, research.md, design.md).
49
34
 
50
- ```bash
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
- ## Phase 3: Completeness Check
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
- **Are all required artifacts present?**
43
+ ## Phase 3: Correctness
62
44
 
63
- | Artifact | Required | Status |
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
- **Are all tasks in the PRD addressed?**
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
- Extract tasks/criteria from prd.md and verify each is implemented:
54
+ Check `package.json` scripts, `Makefile`, or `justfile` for project-specific commands first — prefer those over generic defaults.
73
55
 
74
- ```markdown
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
- | Requirement | Status | Evidence |
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
- **Rust:**
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
- | Check | Status | Issue |
153
- | ---------------------------- | ------ | ----------------------------------- |
154
- | prd.md plan.md | ✓ | Plan addresses all PRD requirements |
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
- ```markdown
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
- **Coherence Score:** X/Y checks passed
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
- # Verify and auto-fix where possible
296
- /verify br-feature-auth --fix
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 $ARGUMENTS` |
91
+ | Ship after verify | `/ship <id>` |
306
92
  | Review code | `/review-codebase` |
307
93
  | Check status | `/status` |
@@ -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)** - nudges agents to follow the Beads-first workflow.
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
- - If user expresses implementation intent and no task is `in_progress`, injects a nudge to use `br ready/show/update`
89
- - If there are `in_progress` tasks but `.beads/artifacts/<id>/spec.md` is missing, nudges to create it before implementation
90
- - On `file.edited`, warns if code is being changed without a claimed task or with missing `spec.md`
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 spec.md
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 specExists(repoDir: string, issueId: string): Promise<boolean> {
102
- const specPath = path.join(
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
- "spec.md",
127
+ filename,
108
128
  );
109
129
  try {
110
- await fsPromises.access(specPath);
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: BeadsIssue[] = [];
121
- let cachedMissingSpec: BeadsIssue[] = [];
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 inProgress = issues.filter((i) => i.status === "in_progress");
164
+ const active = issues.filter(
165
+ (i) => i.status === "in_progress" || i.status === "open",
166
+ );
130
167
 
131
- const missingSpec: BeadsIssue[] = [];
132
- for (const issue of inProgress.slice(0, 10)) {
133
- if (!(await specExists(repoDir, issue.id))) {
134
- missingSpec.push(issue);
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
- cachedInProgress = inProgress;
139
- cachedMissingSpec = missingSpec;
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
- // Warn if code gets edited while no task is claimed / spec missing
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 br ready/show/update to claim a task before edits.",
327
+ "Run /start <id> to claim a task before editing code.",
181
328
  "warning",
182
329
  );
183
330
  return;
184
331
  }
185
332
 
186
- if (cachedMissingSpec.length > 0) {
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: Missing spec.md",
189
- `Create .beads/artifacts/<id>/spec.md for: ${cachedMissingSpec
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
  }