opencodekit 0.12.2 → 0.12.3
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 +40 -417
- package/dist/template/.opencode/agent/build.md +53 -0
- package/dist/template/.opencode/agent/planner.md +0 -1
- package/dist/template/.opencode/agent/rush.md +38 -0
- package/dist/template/.opencode/command/accessibility-check.md +1 -1
- package/dist/template/.opencode/command/commit.md +1 -1
- package/dist/template/.opencode/command/create.md +68 -441
- package/dist/template/.opencode/command/finish.md +82 -252
- package/dist/template/.opencode/command/fix-ci.md +52 -247
- package/dist/template/.opencode/command/fix-types.md +32 -292
- package/dist/template/.opencode/command/fix-ui.md +49 -234
- package/dist/template/.opencode/command/fix.md +57 -194
- package/dist/template/.opencode/command/handoff.md +66 -243
- package/dist/template/.opencode/command/implement.md +67 -231
- package/dist/template/.opencode/command/issue.md +42 -190
- package/dist/template/.opencode/command/plan.md +86 -442
- package/dist/template/.opencode/command/pr.md +3 -1
- package/dist/template/.opencode/command/research-and-implement.md +69 -370
- package/dist/template/.opencode/command/research.md +72 -197
- package/dist/template/.opencode/command/resume.md +70 -438
- package/dist/template/.opencode/command/status.md +11 -11
- package/dist/template/.opencode/command/triage.md +23 -18
- package/dist/template/.opencode/memory/project/commands.md +139 -7
- package/dist/template/.opencode/memory/project/gotchas.md +85 -0
- package/dist/template/.opencode/plugin/beads.ts +181 -16
- package/dist/template/.opencode/skill/beads/SKILL.md +15 -0
- package/dist/template/.opencode/skill/context-engineering/SKILL.md +94 -0
- package/dist/template/.opencode/skill/memory-system/SKILL.md +107 -0
- package/dist/template/.opencode/skill/session-management/SKILL.md +111 -0
- package/dist/template/.opencode/skill/tool-priority/SKILL.md +115 -0
- package/package.json +1 -1
|
@@ -17,7 +17,7 @@ Analyze open tasks and optimize prioritization using dependency graph analysis,
|
|
|
17
17
|
## Phase 1: Initialize Beads Connection
|
|
18
18
|
|
|
19
19
|
```typescript
|
|
20
|
-
bd_init({
|
|
20
|
+
bd_init({ team: "project", role: "build" });
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## Phase 2: Gather Workspace State
|
|
@@ -27,7 +27,7 @@ Run in parallel:
|
|
|
27
27
|
```typescript
|
|
28
28
|
bd_status({ include_agents: true });
|
|
29
29
|
bd_ls({ status: "open", limit: 50, offset: 0 });
|
|
30
|
-
bd_reservations(
|
|
30
|
+
bd_reservations();
|
|
31
31
|
bd_inbox({ n: 10, unread: true, global: true });
|
|
32
32
|
|
|
33
33
|
// Search for past discussions on recurring issues
|
|
@@ -199,14 +199,14 @@ AGENT WORKLOAD
|
|
|
199
199
|
━━━━━━━━━━━━━━
|
|
200
200
|
Agent │ Active │ Completed │ Load
|
|
201
201
|
──────────┼────────┼───────────┼──────
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
202
|
+
build-1 │ 2 │ 8 │ HIGH
|
|
203
|
+
build-2 │ 1 │ 12 │ MEDIUM
|
|
204
|
+
review │ 0 │ 5 │ LOW
|
|
205
205
|
|
|
206
206
|
RECOMMENDATIONS
|
|
207
207
|
━━━━━━━━━━━━━━━
|
|
208
|
-
1. 🔴 URGENT: bd-abc12 is blocking 4 tasks - assign to
|
|
209
|
-
2. 🟡 REBALANCE:
|
|
208
|
+
1. 🔴 URGENT: bd-abc12 is blocking 4 tasks - assign to build agent
|
|
209
|
+
2. 🟡 REBALANCE: build-1 has high load - redistribute to review agent
|
|
210
210
|
3. 🟢 PARALLEL: Start Track A and B simultaneously
|
|
211
211
|
4. ⚠️ STALE: bd-old99 has no activity for 7 days - review or close
|
|
212
212
|
|
|
@@ -221,12 +221,13 @@ If `--auto-assign` flag:
|
|
|
221
221
|
|
|
222
222
|
```typescript
|
|
223
223
|
const assignmentRules = {
|
|
224
|
-
//
|
|
225
|
-
"frontend|ui|css|react|vue": "
|
|
226
|
-
"backend|api|database|server": "
|
|
227
|
-
"
|
|
228
|
-
"
|
|
229
|
-
|
|
224
|
+
// All implementation work goes to build agents
|
|
225
|
+
"frontend|ui|css|react|vue": "build",
|
|
226
|
+
"backend|api|database|server": "build",
|
|
227
|
+
"deploy|ci|docker|infra": "build",
|
|
228
|
+
"mobile|ios|android|react-native": "build",
|
|
229
|
+
// Review/QA work goes to review agent
|
|
230
|
+
"test|qa|e2e|integration": "review",
|
|
230
231
|
};
|
|
231
232
|
|
|
232
233
|
// Load balancing: prefer agent with lowest active count
|
|
@@ -253,12 +254,12 @@ for (const task of readyTasks.filter((t) => !t.assignee && t.priority <= 2)) {
|
|
|
253
254
|
AUTO-ASSIGNMENTS
|
|
254
255
|
━━━━━━━━━━━━━━━━
|
|
255
256
|
|
|
256
|
-
✓ bd-abc12 →
|
|
257
|
-
✓ bd-def34 →
|
|
258
|
-
✓ bd-ghi56 →
|
|
257
|
+
✓ bd-abc12 → build (detected: backend, API)
|
|
258
|
+
✓ bd-def34 → build (detected: frontend, React)
|
|
259
|
+
✓ bd-ghi56 → build (detected: infrastructure)
|
|
259
260
|
|
|
260
261
|
Skipped:
|
|
261
|
-
- bd-xyz99: Already assigned to
|
|
262
|
+
- bd-xyz99: Already assigned to review agent
|
|
262
263
|
- bd-old88: No matching role detected (manual assignment needed)
|
|
263
264
|
```
|
|
264
265
|
|
|
@@ -293,7 +294,11 @@ console.log("3. Review individually");
|
|
|
293
294
|
## Phase 9: Sync and Notify
|
|
294
295
|
|
|
295
296
|
```typescript
|
|
296
|
-
|
|
297
|
+
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
bd_sync({ reason: "Sync triage changes" });
|
|
297
302
|
|
|
298
303
|
// Broadcast triage summary if significant changes
|
|
299
304
|
if (assignmentsMade > 0 || priorityChanges > 0) {
|
|
@@ -52,14 +52,146 @@ OPENCODE_DISABLE_PRUNE=true # Disable DCP pruning
|
|
|
52
52
|
"nudgeFrequency": 8 // LLM nudged every 8 tool calls (default: 10)
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
## Beads CLI (Core)
|
|
56
|
+
|
|
57
|
+
The `bd` command is your issue tracker. JSONL is source of truth, SQLite is cache.
|
|
58
|
+
|
|
59
|
+
### Essential Commands
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
bd ready # Unblocked tasks (use this to find work)
|
|
63
|
+
bd list --status=open # All open issues
|
|
64
|
+
bd show <id> # Full details
|
|
65
|
+
bd create "Title" -t task -p 2 # Create (type: task/bug/feature/epic, priority: 0-4)
|
|
66
|
+
bd update <id> --status in_progress # Claim work
|
|
67
|
+
bd close <id> --reason "Done" # Complete
|
|
68
|
+
bd sync # Export/commit/push (always run at session end)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Dependencies
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
bd dep add <child> <parent> --type blocks # Child blocked until parent closes
|
|
75
|
+
bd dep tree <id> # Visualize dependency chain
|
|
76
|
+
bd blocked # Show all blocked issues
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Coordination
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
bd list --status in_progress # See what's claimed by others
|
|
83
|
+
git pull && bd import # Get latest from team
|
|
84
|
+
bd sync # Push your changes
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Priority Levels
|
|
88
|
+
|
|
89
|
+
- **P0** - Critical (security, data loss)
|
|
90
|
+
- **P1** - High (major features, important bugs)
|
|
91
|
+
- **P2** - Medium (default)
|
|
92
|
+
- **P3** - Low
|
|
93
|
+
- **P4** - Backlog
|
|
94
|
+
|
|
95
|
+
### Sandbox Mode
|
|
96
|
+
|
|
97
|
+
If running in restricted environment (Claude Code, etc.):
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
bd --sandbox ready
|
|
101
|
+
# Or: bd --no-daemon --no-auto-flush --no-auto-import list
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Beads Plugin Tools (For OpenCode Agents)
|
|
105
|
+
|
|
106
|
+
This project's plugin (`.opencode/plugin/beads.ts`) provides typed tools that wrap the CLI.
|
|
107
|
+
|
|
108
|
+
### Session Lifecycle
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
bd_init({ role: "build" }); // Join workspace - MUST call first
|
|
112
|
+
bd_claim(); // Get next ready task, mark in_progress
|
|
113
|
+
bd_reserve({ paths: ["src/foo.ts"] }); // Lock files before editing
|
|
114
|
+
// ... do work ...
|
|
115
|
+
bd_done({ id: "bd-xxx", msg: "Done" }); // Close + release locks + sync
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Task Management
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
bd_add({ title: "Task", pri: 2, type: "task" }); // Create issue
|
|
122
|
+
bd_show({ id: "bd-xxx" }); // Get full details
|
|
123
|
+
bd_ls({ status: "open", limit: 10 }); // List issues
|
|
124
|
+
bd_ready(); // Ready-to-work tasks
|
|
125
|
+
bd_update({ id: "bd-xxx", status: "in_progress" }); // Update issue
|
|
126
|
+
bd_search({ query: "auth" }); // Search issues
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### File Locking (Plugin-Only)
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
bd_reserve({ paths: ["src/a.ts", "src/b.ts"], ttl: 600 }); // Lock files
|
|
133
|
+
bd_reservations(); // List active locks
|
|
134
|
+
bd_release({ paths: ["src/a.ts"] }); // Release specific
|
|
135
|
+
bd_release(); // Release all
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Messaging (Plugin-Only)
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
bd_msg({ subj: "Done", to: "all", global: true }); // Broadcast
|
|
142
|
+
bd_inbox({ n: 5, unread: true }); // Check messages
|
|
143
|
+
bd_ack({ ids: ["msg-abc", "msg-def"] }); // Mark messages as read
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Agent Coordination (Plugin-Only)
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
bd_whois(); // See all agents and their current work
|
|
150
|
+
bd_whois({ agent: "build-abc" }); // Lookup specific agent
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Maintenance
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
bd_sync(); // Sync with git
|
|
157
|
+
bd_status({ include_agents: true }); // Workspace overview
|
|
158
|
+
bd_doctor(); // Check database health
|
|
159
|
+
bd_cleanup({ days: 7 }); // Remove old closed issues
|
|
160
|
+
```
|
|
161
|
+
|
|
55
162
|
## Beads Workflow
|
|
56
163
|
|
|
164
|
+
### Start Work
|
|
165
|
+
|
|
57
166
|
```bash
|
|
58
|
-
bd ready
|
|
59
|
-
bd
|
|
60
|
-
|
|
61
|
-
bd create --title="..." --type=task --priority=2
|
|
62
|
-
bd update <id> --status=in_progress
|
|
63
|
-
bd close <id> --reason="Completed"
|
|
64
|
-
bd sync # Commit and push changes
|
|
167
|
+
bd ready # Find unblocked task
|
|
168
|
+
bd update bd-xxx --status in_progress # Claim it
|
|
169
|
+
git checkout -b bd-xxx # Create branch
|
|
65
170
|
```
|
|
171
|
+
|
|
172
|
+
### During Work
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
git commit -m "WIP: bd-xxx - [progress]" # Checkpoint commits
|
|
176
|
+
bd sync # Sync beads state
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### End Session
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
git add -A && git commit -m "bd-xxx: [summary]"
|
|
183
|
+
bd close bd-xxx --reason "Completed: [what]"
|
|
184
|
+
bd sync
|
|
185
|
+
git push
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Handoff (If Not Finishing)
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
git commit -m "WIP: bd-xxx - [where stopped]"
|
|
192
|
+
# Create handoff in .beads/artifacts/bd-xxx/handoffs/
|
|
193
|
+
bd sync
|
|
194
|
+
git push
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Resume later with: `/resume bd-xxx`
|
|
@@ -58,3 +58,88 @@ If tools are unexpectedly blocked:
|
|
|
58
58
|
2. Check project config: `.opencode/opencode.json`
|
|
59
59
|
3. Project config takes precedence
|
|
60
60
|
4. Use `"*": "ask"` as base rule to debug which pattern is matching
|
|
61
|
+
|
|
62
|
+
## Beads Gotchas
|
|
63
|
+
|
|
64
|
+
### Core Beads CLI vs This Project's Plugin
|
|
65
|
+
|
|
66
|
+
**Core beads CLI** (`bd`) is the upstream tool from steveyegge/beads.
|
|
67
|
+
|
|
68
|
+
**This project's plugin** (`.opencode/plugin/beads.ts`) wraps the CLI and adds:
|
|
69
|
+
|
|
70
|
+
- `bd_done()` - closes task + releases locks + syncs in one call
|
|
71
|
+
- `bd_reserve()` / `bd_release()` - atomic file locking via mkdir
|
|
72
|
+
- `bd_claim()` - finds ready task + marks in_progress
|
|
73
|
+
- `bd_msg()` / `bd_inbox()` / `bd_ack()` - agent-to-agent messaging
|
|
74
|
+
- `bd_whois()` - agent directory lookup (who's working on what)
|
|
75
|
+
- Agent state (current task, reserved files, agent ID)
|
|
76
|
+
|
|
77
|
+
### Which To Use
|
|
78
|
+
|
|
79
|
+
| Context | Use |
|
|
80
|
+
| -------------------- | ----------------------- |
|
|
81
|
+
| OpenCode agents | Plugin tools (`bd_*()`) |
|
|
82
|
+
| Shell scripts, CI/CD | CLI (`bd`) |
|
|
83
|
+
| Human terminal | CLI (`bd`) |
|
|
84
|
+
|
|
85
|
+
### Plugin Tools (Preferred for Agents)
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
bd_init({ role: "build" }); // Join workspace
|
|
89
|
+
bd_claim(); // Get next ready task
|
|
90
|
+
bd_reserve({ paths: ["src/foo.ts"] }); // Lock files
|
|
91
|
+
// ... do work ...
|
|
92
|
+
bd_done({ id: "bd-xxx", msg: "Done" }); // Close + release + sync
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### CLI Commands (For Scripts/Humans)
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
bd create "Task title" -t task -p 2 # Create
|
|
99
|
+
bd update bd-xxx --status in_progress # Claim
|
|
100
|
+
bd close bd-xxx --reason "Done" # Complete
|
|
101
|
+
bd sync # Push to git
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Hash-Based IDs Prevent Collisions
|
|
105
|
+
|
|
106
|
+
Beads uses hash IDs (`bd-a3f8`) not sequential IDs (`bd-1`, `bd-2`). This eliminates merge conflicts when multiple agents create issues on different branches.
|
|
107
|
+
|
|
108
|
+
Don't assume sequential IDs. Always use `bd show` to get exact IDs.
|
|
109
|
+
|
|
110
|
+
### `bd ready` Is Your Friend
|
|
111
|
+
|
|
112
|
+
`bd ready` shows tasks with NO unresolved blockers. Use it to find work instead of `bd list`.
|
|
113
|
+
|
|
114
|
+
### Dependencies Block Work
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
bd dep add bd-child bd-parent --type blocks
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Now `bd-child` won't appear in `bd ready` until `bd-parent` closes. Check `bd blocked` to see what's waiting.
|
|
121
|
+
|
|
122
|
+
### Git Is The Coordination Layer
|
|
123
|
+
|
|
124
|
+
No central server. Agents coordinate via:
|
|
125
|
+
|
|
126
|
+
1. Issue status (in_progress = claimed)
|
|
127
|
+
2. Git branches
|
|
128
|
+
3. `bd sync` to push/pull changes
|
|
129
|
+
|
|
130
|
+
### Sandbox Environments (Claude Code, etc.)
|
|
131
|
+
|
|
132
|
+
Daemon can't be killed by sandbox. Use:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
bd --sandbox ready
|
|
136
|
+
# Or: bd --no-daemon --no-auto-flush --no-auto-import list
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 30-Second Debounce
|
|
140
|
+
|
|
141
|
+
Rapid operations get batched into single JSONL flush after 30s. Force immediate sync:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
bd sync
|
|
145
|
+
```
|
|
@@ -366,10 +366,12 @@ export const BeadsCorePlugin: Plugin = async ({ $, directory }) => {
|
|
|
366
366
|
filePath: string,
|
|
367
367
|
reason?: string,
|
|
368
368
|
ttlSeconds = 600,
|
|
369
|
+
overrideAgent?: string,
|
|
369
370
|
): Promise<{ acquired: boolean; holder?: string }> {
|
|
370
371
|
const lockPath = lockDir(filePath);
|
|
371
372
|
const now = Date.now();
|
|
372
373
|
const expires = now + ttlSeconds * 1000;
|
|
374
|
+
const agentToUse = overrideAgent || state.agentId;
|
|
373
375
|
|
|
374
376
|
// Atomic: mkdir fails if dir exists
|
|
375
377
|
try {
|
|
@@ -384,10 +386,10 @@ export const BeadsCorePlugin: Plugin = async ({ $, directory }) => {
|
|
|
384
386
|
if (lock.expires < now) {
|
|
385
387
|
// Expired - remove and retry
|
|
386
388
|
await $`rm -rf ${lockPath}`.cwd(directory).quiet();
|
|
387
|
-
return acquireLock(filePath, reason, ttlSeconds);
|
|
389
|
+
return acquireLock(filePath, reason, ttlSeconds, overrideAgent);
|
|
388
390
|
}
|
|
389
391
|
|
|
390
|
-
if (lock.agent ===
|
|
392
|
+
if (lock.agent === agentToUse) {
|
|
391
393
|
// We already hold this lock - refresh it
|
|
392
394
|
lock.expires = expires;
|
|
393
395
|
await $`echo ${JSON.stringify(lock)} > ${metaPath}`
|
|
@@ -400,14 +402,14 @@ export const BeadsCorePlugin: Plugin = async ({ $, directory }) => {
|
|
|
400
402
|
} catch {
|
|
401
403
|
// Corrupted lock - remove and retry
|
|
402
404
|
await $`rm -rf ${lockPath}`.cwd(directory).quiet();
|
|
403
|
-
return acquireLock(filePath, reason, ttlSeconds);
|
|
405
|
+
return acquireLock(filePath, reason, ttlSeconds, overrideAgent);
|
|
404
406
|
}
|
|
405
407
|
}
|
|
406
408
|
|
|
407
409
|
// Lock acquired - write metadata
|
|
408
410
|
const lockData: LockData = {
|
|
409
411
|
path: filePath,
|
|
410
|
-
agent:
|
|
412
|
+
agent: agentToUse,
|
|
411
413
|
reason,
|
|
412
414
|
created: now,
|
|
413
415
|
expires,
|
|
@@ -597,7 +599,7 @@ export const BeadsCorePlugin: Plugin = async ({ $, directory }) => {
|
|
|
597
599
|
role: tool.schema
|
|
598
600
|
.string()
|
|
599
601
|
.optional()
|
|
600
|
-
.describe("Role:
|
|
602
|
+
.describe("Role: build|rush|explore|planner|review|scout|vision"),
|
|
601
603
|
},
|
|
602
604
|
async execute(args) {
|
|
603
605
|
await $`bd init`
|
|
@@ -670,11 +672,17 @@ export const BeadsCorePlugin: Plugin = async ({ $, directory }) => {
|
|
|
670
672
|
.default("completed")
|
|
671
673
|
.describe("Completion message"),
|
|
672
674
|
},
|
|
673
|
-
async execute(args) {
|
|
675
|
+
async execute(args, context) {
|
|
674
676
|
const taskId = args.id || state.currentTask;
|
|
675
677
|
if (!taskId) return json({ error: "No task ID" });
|
|
676
678
|
|
|
677
|
-
|
|
679
|
+
// Audit trail
|
|
680
|
+
const auditAgent = context?.agent || state.agentId;
|
|
681
|
+
|
|
682
|
+
const closeResult = await bdClose(
|
|
683
|
+
taskId,
|
|
684
|
+
`${args.msg} [by ${auditAgent}]`,
|
|
685
|
+
);
|
|
678
686
|
if (closeResult.error) return json({ error: closeResult.error });
|
|
679
687
|
|
|
680
688
|
// Release all locks
|
|
@@ -708,7 +716,9 @@ export const BeadsCorePlugin: Plugin = async ({ $, directory }) => {
|
|
|
708
716
|
tags: tool.schema
|
|
709
717
|
.array(tool.schema.string())
|
|
710
718
|
.optional()
|
|
711
|
-
.describe(
|
|
719
|
+
.describe(
|
|
720
|
+
"Agent tags: build,rush,explore,planner,review,scout,vision",
|
|
721
|
+
),
|
|
712
722
|
parent: tool.schema.string().optional().describe("Parent issue ID"),
|
|
713
723
|
deps: tool.schema
|
|
714
724
|
.array(tool.schema.string())
|
|
@@ -754,7 +764,9 @@ export const BeadsCorePlugin: Plugin = async ({ $, directory }) => {
|
|
|
754
764
|
"Assign task to role (leader only). Adds tag and notifies.",
|
|
755
765
|
args: {
|
|
756
766
|
id: tool.schema.string().describe("Issue ID"),
|
|
757
|
-
role: tool.schema
|
|
767
|
+
role: tool.schema
|
|
768
|
+
.string()
|
|
769
|
+
.describe("Role: build|rush|explore|planner|review|scout|vision"),
|
|
758
770
|
notify: tool.schema
|
|
759
771
|
.boolean()
|
|
760
772
|
.default(true)
|
|
@@ -882,16 +894,24 @@ export const BeadsCorePlugin: Plugin = async ({ $, directory }) => {
|
|
|
882
894
|
.default(600)
|
|
883
895
|
.describe("Seconds until expiry"),
|
|
884
896
|
},
|
|
885
|
-
async execute(args) {
|
|
897
|
+
async execute(args, context) {
|
|
886
898
|
if (!args.paths?.length) return json({ error: "paths required" });
|
|
887
899
|
|
|
900
|
+
// Log who is reserving for audit
|
|
901
|
+
const reservingAgent = context?.agent || state.agentId;
|
|
902
|
+
|
|
888
903
|
await ensureReservationsDir();
|
|
889
904
|
|
|
890
905
|
const granted: string[] = [];
|
|
891
906
|
const conflicts: { path: string; holder?: string }[] = [];
|
|
892
907
|
|
|
893
908
|
for (const path of args.paths) {
|
|
894
|
-
const result = await acquireLock(
|
|
909
|
+
const result = await acquireLock(
|
|
910
|
+
path,
|
|
911
|
+
args.reason,
|
|
912
|
+
args.ttl,
|
|
913
|
+
reservingAgent,
|
|
914
|
+
);
|
|
895
915
|
if (result.acquired) {
|
|
896
916
|
granted.push(path);
|
|
897
917
|
} else {
|
|
@@ -963,12 +983,15 @@ export const BeadsCorePlugin: Plugin = async ({ $, directory }) => {
|
|
|
963
983
|
.default(false)
|
|
964
984
|
.describe("Send to all workspaces"),
|
|
965
985
|
},
|
|
966
|
-
async execute(args) {
|
|
986
|
+
async execute(args, context) {
|
|
967
987
|
if (!args.subj) return json({ error: "subj required" });
|
|
968
988
|
|
|
989
|
+
// Use context agent if available for audit trail
|
|
990
|
+
const senderAgent = context?.agent || state.agentId;
|
|
991
|
+
|
|
969
992
|
const msg: Message = {
|
|
970
993
|
id: `msg-${Date.now().toString(36)}`,
|
|
971
|
-
from:
|
|
994
|
+
from: senderAgent,
|
|
972
995
|
to: args.to || "all",
|
|
973
996
|
subj: args.subj,
|
|
974
997
|
body: args.body,
|
|
@@ -1000,6 +1023,117 @@ export const BeadsCorePlugin: Plugin = async ({ $, directory }) => {
|
|
|
1000
1023
|
},
|
|
1001
1024
|
}),
|
|
1002
1025
|
|
|
1026
|
+
bd_ack: tool({
|
|
1027
|
+
description: "Acknowledge message(s). Marks as read.",
|
|
1028
|
+
args: {
|
|
1029
|
+
ids: tool.schema
|
|
1030
|
+
.array(tool.schema.string())
|
|
1031
|
+
.describe("Message IDs to acknowledge"),
|
|
1032
|
+
},
|
|
1033
|
+
async execute(args) {
|
|
1034
|
+
if (!args.ids?.length) return json({ error: "ids required" });
|
|
1035
|
+
|
|
1036
|
+
try {
|
|
1037
|
+
const content =
|
|
1038
|
+
await $`cat ${RESERVATIONS_DIR}/messages.jsonl 2>/dev/null`
|
|
1039
|
+
.cwd(directory)
|
|
1040
|
+
.text();
|
|
1041
|
+
|
|
1042
|
+
if (!content.trim()) return json({ acked: 0 });
|
|
1043
|
+
|
|
1044
|
+
const idsToAck = new Set(args.ids);
|
|
1045
|
+
let acked = 0;
|
|
1046
|
+
|
|
1047
|
+
const msgs = content
|
|
1048
|
+
.trim()
|
|
1049
|
+
.split("\n")
|
|
1050
|
+
.map((line) => {
|
|
1051
|
+
try {
|
|
1052
|
+
const msg = JSON.parse(line) as Message;
|
|
1053
|
+
if (idsToAck.has(msg.id) && !msg.read) {
|
|
1054
|
+
msg.read = true;
|
|
1055
|
+
acked++;
|
|
1056
|
+
}
|
|
1057
|
+
return msg;
|
|
1058
|
+
} catch {
|
|
1059
|
+
return null;
|
|
1060
|
+
}
|
|
1061
|
+
})
|
|
1062
|
+
.filter((m): m is Message => m !== null);
|
|
1063
|
+
|
|
1064
|
+
const newContent = msgs.map((m) => JSON.stringify(m)).join("\n");
|
|
1065
|
+
await $`echo ${newContent} > ${RESERVATIONS_DIR}/messages.jsonl`
|
|
1066
|
+
.cwd(directory)
|
|
1067
|
+
.quiet();
|
|
1068
|
+
|
|
1069
|
+
return json({ ok: 1, acked });
|
|
1070
|
+
} catch {
|
|
1071
|
+
return json({ acked: 0 });
|
|
1072
|
+
}
|
|
1073
|
+
},
|
|
1074
|
+
}),
|
|
1075
|
+
|
|
1076
|
+
bd_whois: tool({
|
|
1077
|
+
description: "Agent directory lookup. See who's working on what.",
|
|
1078
|
+
args: {
|
|
1079
|
+
agent: tool.schema
|
|
1080
|
+
.string()
|
|
1081
|
+
.optional()
|
|
1082
|
+
.describe("Agent ID to lookup (empty=all)"),
|
|
1083
|
+
},
|
|
1084
|
+
async execute(args) {
|
|
1085
|
+
const locks = await getAllLocks();
|
|
1086
|
+
const { tasks: inProgressTasks } = await bdList({
|
|
1087
|
+
status: "in_progress",
|
|
1088
|
+
});
|
|
1089
|
+
|
|
1090
|
+
// Build agent activity map
|
|
1091
|
+
const agentMap: Record<
|
|
1092
|
+
string,
|
|
1093
|
+
{
|
|
1094
|
+
files: string[];
|
|
1095
|
+
task?: string;
|
|
1096
|
+
role?: string;
|
|
1097
|
+
}
|
|
1098
|
+
> = {};
|
|
1099
|
+
|
|
1100
|
+
// Add locks info
|
|
1101
|
+
for (const lock of locks) {
|
|
1102
|
+
if (!agentMap[lock.agent]) {
|
|
1103
|
+
agentMap[lock.agent] = { files: [] };
|
|
1104
|
+
}
|
|
1105
|
+
agentMap[lock.agent].files.push(lock.path);
|
|
1106
|
+
if (lock.task) {
|
|
1107
|
+
agentMap[lock.agent].task = lock.task;
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
// Add current agent info
|
|
1112
|
+
if (!agentMap[state.agentId]) {
|
|
1113
|
+
agentMap[state.agentId] = { files: [] };
|
|
1114
|
+
}
|
|
1115
|
+
agentMap[state.agentId].role = state.role || undefined;
|
|
1116
|
+
if (state.currentTask) {
|
|
1117
|
+
agentMap[state.agentId].task = state.currentTask;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
// Filter if specific agent requested
|
|
1121
|
+
if (args.agent) {
|
|
1122
|
+
const agent = agentMap[args.agent];
|
|
1123
|
+
if (!agent) return json({ error: "agent not found" });
|
|
1124
|
+
return json({ agent: args.agent, ...agent });
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
return json({
|
|
1128
|
+
agents: Object.entries(agentMap).map(([id, info]) => ({
|
|
1129
|
+
id,
|
|
1130
|
+
...info,
|
|
1131
|
+
})),
|
|
1132
|
+
in_progress_tasks: inProgressTasks.length,
|
|
1133
|
+
});
|
|
1134
|
+
},
|
|
1135
|
+
}),
|
|
1136
|
+
|
|
1003
1137
|
bd_status: tool({
|
|
1004
1138
|
description: "Workspace overview. Shows agents, tasks, locks.",
|
|
1005
1139
|
args: {
|
|
@@ -1038,10 +1172,22 @@ export const BeadsCorePlugin: Plugin = async ({ $, directory }) => {
|
|
|
1038
1172
|
|
|
1039
1173
|
bd_sync: tool({
|
|
1040
1174
|
description: "Sync with git. Pull/push changes.",
|
|
1041
|
-
args: {
|
|
1042
|
-
|
|
1175
|
+
args: {
|
|
1176
|
+
reason: tool.schema
|
|
1177
|
+
.string()
|
|
1178
|
+
.optional()
|
|
1179
|
+
.describe("Audit trail reason for sync"),
|
|
1180
|
+
},
|
|
1181
|
+
async execute(args, context) {
|
|
1043
1182
|
const result = await bdSync();
|
|
1044
|
-
|
|
1183
|
+
// Log sync with context for audit trail
|
|
1184
|
+
const syncAgent = context?.agent || state.agentId;
|
|
1185
|
+
return json({
|
|
1186
|
+
ok: 1,
|
|
1187
|
+
output: result.output,
|
|
1188
|
+
by: syncAgent,
|
|
1189
|
+
reason: args.reason,
|
|
1190
|
+
});
|
|
1045
1191
|
},
|
|
1046
1192
|
}),
|
|
1047
1193
|
|
|
@@ -1249,6 +1395,25 @@ export const BeadsCorePlugin: Plugin = async ({ $, directory }) => {
|
|
|
1249
1395
|
if (event.type === "session.idle" && state.currentTask) {
|
|
1250
1396
|
await bdSync();
|
|
1251
1397
|
}
|
|
1398
|
+
|
|
1399
|
+
// Cleanup expired locks on compaction
|
|
1400
|
+
if (event.type === "session.compacted") {
|
|
1401
|
+
await cleanupExpiredLocks();
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
// Log errors to audit trail
|
|
1405
|
+
if (event.type === "session.error" && state.currentTask) {
|
|
1406
|
+
await appendMessage({
|
|
1407
|
+
id: `err-${Date.now().toString(36)}`,
|
|
1408
|
+
from: state.agentId,
|
|
1409
|
+
to: "all",
|
|
1410
|
+
subj: `Session error on task ${state.currentTask}`,
|
|
1411
|
+
body: `Error occurred during task execution`,
|
|
1412
|
+
importance: "high",
|
|
1413
|
+
at: Date.now(),
|
|
1414
|
+
read: false,
|
|
1415
|
+
});
|
|
1416
|
+
}
|
|
1252
1417
|
},
|
|
1253
1418
|
};
|
|
1254
1419
|
};
|
|
@@ -340,6 +340,21 @@ bd_msg({
|
|
|
340
340
|
bd_inbox({ unread: true, n: 10 });
|
|
341
341
|
```
|
|
342
342
|
|
|
343
|
+
### Acknowledge Messages
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
bd_ack({ ids: ["msg-abc", "msg-def"] }); // Mark as read
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Agent Coordination
|
|
350
|
+
|
|
351
|
+
### Who's Working on What
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
bd_whois(); // All agents with their files and tasks
|
|
355
|
+
bd_whois({ agent: "build-abc" }); // Specific agent lookup
|
|
356
|
+
```
|
|
357
|
+
|
|
343
358
|
## Status and Analysis
|
|
344
359
|
|
|
345
360
|
### Workspace Overview
|