bobs-workshop 0.3.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +2 -2
- package/README.md +199 -210
- package/bin/bobs-workshop.js +109 -0
- package/config/agents.json +27 -0
- package/dist/plugins/bobs-workshop.js +34 -0
- package/dist/tools/background-agent/cancel.d.ts +3 -0
- package/dist/tools/background-agent/cancel.d.ts.map +1 -0
- package/dist/tools/background-agent/cancel.js +52 -0
- package/dist/tools/background-agent/concurrency.d.ts +15 -0
- package/dist/tools/background-agent/concurrency.d.ts.map +1 -0
- package/dist/tools/background-agent/concurrency.js +61 -0
- package/dist/tools/background-agent/index.d.ts +8 -0
- package/dist/tools/background-agent/index.d.ts.map +1 -0
- package/dist/tools/background-agent/index.js +7 -0
- package/dist/tools/background-agent/launch.d.ts +6 -0
- package/dist/tools/background-agent/launch.d.ts.map +1 -0
- package/dist/tools/background-agent/launch.js +33 -0
- package/dist/tools/background-agent/list.d.ts +7 -0
- package/dist/tools/background-agent/list.d.ts.map +1 -0
- package/dist/tools/background-agent/list.js +40 -0
- package/dist/tools/background-agent/manager.d.ts +29 -0
- package/dist/tools/background-agent/manager.d.ts.map +1 -0
- package/dist/tools/background-agent/manager.js +377 -0
- package/dist/tools/background-agent/output.d.ts +3 -0
- package/dist/tools/background-agent/output.d.ts.map +1 -0
- package/dist/tools/background-agent/output.js +41 -0
- package/dist/tools/background-agent/types.d.ts +46 -0
- package/dist/tools/background-agent/types.d.ts.map +1 -0
- package/dist/tools/background-agent/types.js +1 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +8 -0
- package/dist/tools/manual/index.d.ts +3 -0
- package/dist/tools/manual/index.d.ts.map +1 -0
- package/dist/tools/manual/index.js +2 -0
- package/dist/tools/manual/manual-update.d.ts +4 -0
- package/dist/tools/manual/manual-update.d.ts.map +1 -0
- package/dist/tools/manual/manual-update.js +190 -0
- package/dist/tools/manual/verify-manual.d.ts +4 -0
- package/dist/tools/manual/verify-manual.d.ts.map +1 -0
- package/dist/tools/manual/verify-manual.js +46 -0
- package/package.json +35 -67
- package/postinstall.js +190 -0
- package/src/agents/alice.md +466 -0
- package/src/agents/bob-rev.md +493 -0
- package/src/agents/bob-send.md +277 -0
- package/src/agents/bob.md +442 -0
- package/src/agents/trace.md +451 -0
- package/src/plugins/bobs-workshop.ts +45 -0
- package/src/skills/api-patterns/SKILL.md +376 -0
- package/src/skills/architecture/SKILL.md +271 -0
- package/src/skills/bobs-workshop/performance/icon.svg +3 -0
- package/src/skills/brainstorming/SKILL.md +210 -0
- package/src/skills/clean-code/SKILL.md +151 -0
- package/src/skills/code-review-checklist/SKILL.md +220 -0
- package/src/skills/database-design/SKILL.md +271 -0
- package/src/skills/exploration/SKILL.md +257 -0
- package/src/skills/frontend-ui-ux/SKILL.md +78 -0
- package/src/skills/git-master/SKILL.md +1105 -0
- package/src/skills/performance/SKILL.md +144 -0
- package/src/skills/performance/icon.svg +3 -0
- package/src/skills/plan-writing/SKILL.md +225 -0
- package/src/skills/security/SKILL.md +410 -0
- package/src/skills/simplification/SKILL.md +238 -0
- package/src/skills/systematic-debugging/SKILL.md +175 -0
- package/src/skills/testing-patterns/SKILL.md +305 -0
- package/src/skills/verification/SKILL.md +286 -0
- package/src/tools/background-agent/cancel.ts +67 -0
- package/src/tools/background-agent/concurrency.ts +71 -0
- package/src/tools/background-agent/index.ts +7 -0
- package/src/tools/background-agent/launch.ts +39 -0
- package/src/tools/background-agent/list.ts +50 -0
- package/src/tools/background-agent/manager.ts +455 -0
- package/src/tools/background-agent/output.ts +57 -0
- package/src/tools/background-agent/types.ts +55 -0
- package/src/tools/index.ts +8 -0
- package/src/tools/manual/index.ts +2 -0
- package/src/tools/manual/manual-update.ts +197 -0
- package/src/tools/manual/verify-manual.ts +55 -0
- package/uninstall.js +64 -0
- package/Claude.md +0 -162
- package/bin/bobs-mcp-server.js +0 -11
- package/bin/bobs-mcp.js +0 -130
- package/dist/api/taskLogger.js +0 -106
- package/dist/api/taskLogger.js.map +0 -1
- package/dist/cli/checker.js +0 -401
- package/dist/cli/checker.js.map +0 -1
- package/dist/cli/cleanup.js +0 -131
- package/dist/cli/cleanup.js.map +0 -1
- package/dist/cli/debug.js +0 -157
- package/dist/cli/debug.js.map +0 -1
- package/dist/cli/health.js +0 -97
- package/dist/cli/health.js.map +0 -1
- package/dist/cli/setup.js +0 -81
- package/dist/cli/setup.js.map +0 -1
- package/dist/cli/workshop.js +0 -42
- package/dist/cli/workshop.js.map +0 -1
- package/dist/dashboard/server.js +0 -1203
- package/dist/dashboard/server.js.map +0 -1
- package/dist/index.js +0 -960
- package/dist/index.js.map +0 -1
- package/dist/prompts/architect.js +0 -221
- package/dist/prompts/architect.js.map +0 -1
- package/dist/prompts/debugger.js +0 -257
- package/dist/prompts/debugger.js.map +0 -1
- package/dist/prompts/engineer.js +0 -249
- package/dist/prompts/engineer.js.map +0 -1
- package/dist/prompts/orchestrator.js +0 -304
- package/dist/prompts/orchestrator.js.map +0 -1
- package/dist/prompts/reviewer.js +0 -289
- package/dist/prompts/reviewer.js.map +0 -1
- package/dist/services/activitySummarizer.js +0 -388
- package/dist/services/activitySummarizer.js.map +0 -1
- package/dist/services/changeValidator.js +0 -396
- package/dist/services/changeValidator.js.map +0 -1
- package/dist/services/claudeOrchestrator.js +0 -343
- package/dist/services/claudeOrchestrator.js.map +0 -1
- package/dist/services/fileMonitor.js +0 -250
- package/dist/services/fileMonitor.js.map +0 -1
- package/dist/services/implementationSummarizer.js +0 -306
- package/dist/services/implementationSummarizer.js.map +0 -1
- package/dist/services/liveMonitor.js +0 -315
- package/dist/services/liveMonitor.js.map +0 -1
- package/dist/services/mcpAuditLogger.js +0 -104
- package/dist/services/mcpAuditLogger.js.map +0 -1
- package/dist/services/mcpLogger.js +0 -223
- package/dist/services/mcpLogger.js.map +0 -1
- package/dist/services/tmuxManager.js +0 -541
- package/dist/services/tmuxManager.js.map +0 -1
- package/dist/tools/approvalTools.js +0 -244
- package/dist/tools/approvalTools.js.map +0 -1
- package/dist/tools/autoDebugger.js +0 -147
- package/dist/tools/autoDebugger.js.map +0 -1
- package/dist/tools/cleanupService.js +0 -221
- package/dist/tools/cleanupService.js.map +0 -1
- package/dist/tools/dashboardTools.js +0 -342
- package/dist/tools/dashboardTools.js.map +0 -1
- package/dist/tools/developmentNudges.js +0 -336
- package/dist/tools/developmentNudges.js.map +0 -1
- package/dist/tools/gitTools.js +0 -741
- package/dist/tools/gitTools.js.map +0 -1
- package/dist/tools/orchestratorTools.js +0 -832
- package/dist/tools/orchestratorTools.js.map +0 -1
- package/dist/tools/searchCache.js +0 -64
- package/dist/tools/searchCache.js.map +0 -1
- package/dist/tools/searchTools.js +0 -1107
- package/dist/tools/searchTools.js.map +0 -1
- package/dist/tools/semgrep-patterns.js +0 -296
- package/dist/tools/semgrep-patterns.js.map +0 -1
- package/dist/tools/specTools.js +0 -332
- package/dist/tools/specTools.js.map +0 -1
- package/dist/tools/structural/__tests__/orchestrator.test.js +0 -61
- package/dist/tools/structural/__tests__/orchestrator.test.js.map +0 -1
- package/dist/tools/structural/cache.js +0 -226
- package/dist/tools/structural/cache.js.map +0 -1
- package/dist/tools/structural/engines/python/index.js +0 -118
- package/dist/tools/structural/engines/python/index.js.map +0 -1
- package/dist/tools/structural/engines/typescript/__tests__/typescript-engine.test.js +0 -97
- package/dist/tools/structural/engines/typescript/__tests__/typescript-engine.test.js.map +0 -1
- package/dist/tools/structural/engines/typescript/analyzer.js +0 -433
- package/dist/tools/structural/engines/typescript/analyzer.js.map +0 -1
- package/dist/tools/structural/engines/typescript/index.js +0 -381
- package/dist/tools/structural/engines/typescript/index.js.map +0 -1
- package/dist/tools/structural/engines/typescript/utils.js +0 -279
- package/dist/tools/structural/engines/typescript/utils.js.map +0 -1
- package/dist/tools/structural/index.js +0 -248
- package/dist/tools/structural/index.js.map +0 -1
- package/dist/tools/structural/types.js +0 -18
- package/dist/tools/structural/types.js.map +0 -1
- package/dist/tools/tmuxTools.js +0 -100
- package/dist/tools/tmuxTools.js.map +0 -1
- package/dist/tools/workRecorder.js +0 -215
- package/dist/tools/workRecorder.js.map +0 -1
- package/dist/tools/worktreeTools.js +0 -705
- package/dist/tools/worktreeTools.js.map +0 -1
- package/dist/utils/__tests__/integration.test.js +0 -57
- package/dist/utils/__tests__/integration.test.js.map +0 -1
- package/dist/utils/__tests__/serverDetection.test.js +0 -151
- package/dist/utils/__tests__/serverDetection.test.js.map +0 -1
- package/dist/utils/errorHandling.js +0 -336
- package/dist/utils/errorHandling.js.map +0 -1
- package/dist/utils/processManager.js +0 -172
- package/dist/utils/processManager.js.map +0 -1
- package/dist/utils/reliability.js +0 -263
- package/dist/utils/reliability.js.map +0 -1
- package/dist/utils/responseFormatter.js +0 -250
- package/dist/utils/responseFormatter.js.map +0 -1
- package/dist/utils/serverDetection.js +0 -133
- package/dist/utils/serverDetection.js.map +0 -1
- package/dist/utils/specMigration.js +0 -105
- package/dist/utils/specMigration.js.map +0 -1
- package/dist/validation/schemas.js +0 -299
- package/dist/validation/schemas.js.map +0 -1
- package/public/.well-known/mcp/manifest.json +0 -473
- package/public/index.html +0 -3157
- package/public/index.html.backup +0 -2805
- package/public/index.html.backup2 +0 -1292
- package/scripts/cleanup-system-logs.ts +0 -121
- package/scripts/init-workspace.js +0 -63
- package/scripts/install-search-tools.js +0 -116
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: verification
|
|
3
|
+
description: Evidence-based verification methodology. SEE code working, do not just trust tests. Use when shipping code, final verification, output validation, evidence gathering. CRITICAL: Evidence before assertions.
|
|
4
|
+
metadata:
|
|
5
|
+
recommended_for: bob-send
|
|
6
|
+
category: verification
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Evidence-Based Verification Skill
|
|
10
|
+
|
|
11
|
+
## Core Philosophy
|
|
12
|
+
|
|
13
|
+
> "Evidence before assertions. Always."
|
|
14
|
+
|
|
15
|
+
Never claim code works without **seeing** it work. Tests passing is not enough. You must SEE the output.
|
|
16
|
+
|
|
17
|
+
## When to Use
|
|
18
|
+
|
|
19
|
+
Use this skill during the SEND phase or any final verification:
|
|
20
|
+
- Before shipping code
|
|
21
|
+
- When validating implementation works
|
|
22
|
+
- When gathering evidence for review
|
|
23
|
+
- When tests pass but you need runtime proof
|
|
24
|
+
|
|
25
|
+
## The Three Laws
|
|
26
|
+
|
|
27
|
+
1. **See it working** - Screenshots, curl responses, CLI output. Actual evidence.
|
|
28
|
+
2. **Human checkpoint** - No auto-shipping. Human reviews evidence and decides.
|
|
29
|
+
3. **Fallback hierarchy** - If primary method fails, try the next method down.
|
|
30
|
+
|
|
31
|
+
## Project Type Detection
|
|
32
|
+
|
|
33
|
+
First, detect what type of project you're verifying:
|
|
34
|
+
|
|
35
|
+
| Detection Pattern | Project Type | Primary Method |
|
|
36
|
+
|-------------------|--------------|----------------|
|
|
37
|
+
| package.json + src/app or pages/ | Web app | Screenshot + test flows |
|
|
38
|
+
| package.json + routes or controllers/ | API | Curl endpoints |
|
|
39
|
+
| Cargo.toml + src/main.rs with clap | CLI | Run commands |
|
|
40
|
+
| pyproject.toml + `__main__.py` | CLI | Run commands |
|
|
41
|
+
| `**/lib.rs` or `setup.py` | Library | Run examples |
|
|
42
|
+
| Dockerfile or docker-compose.yml | Service | Health check + logs |
|
|
43
|
+
|
|
44
|
+
## Verification Methods
|
|
45
|
+
|
|
46
|
+
### Web Applications
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# 1. Start dev server
|
|
50
|
+
npm run dev &
|
|
51
|
+
SERVER_PID=$!
|
|
52
|
+
|
|
53
|
+
# 2. Wait for server (max 30s)
|
|
54
|
+
sleep 5 # or: until curl -s http://localhost:3000 > /dev/null
|
|
55
|
+
|
|
56
|
+
# 3. Verify key pages load
|
|
57
|
+
curl -s http://localhost:3000 | head -20
|
|
58
|
+
|
|
59
|
+
# 4. Check for errors (if browser available, take screenshots)
|
|
60
|
+
|
|
61
|
+
# 5. Cleanup
|
|
62
|
+
kill $SERVER_PID
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Evidence to capture:**
|
|
66
|
+
- Screenshots of key pages (if browser available)
|
|
67
|
+
- HTML response showing expected content
|
|
68
|
+
- Console errors (if any)
|
|
69
|
+
|
|
70
|
+
### Browser Verification (Playwright)
|
|
71
|
+
|
|
72
|
+
For web applications, use Playwright for comprehensive browser verification:
|
|
73
|
+
|
|
74
|
+
**Capabilities:**
|
|
75
|
+
- **Verification**: Ensure web elements are present and functional
|
|
76
|
+
- **Browsing**: Navigate through web pages to gather information
|
|
77
|
+
- **Web Scraping**: Extract data from websites
|
|
78
|
+
- **Testing**: Run end-to-end tests
|
|
79
|
+
- **Screenshots**: Capture visual evidence of web states
|
|
80
|
+
|
|
81
|
+
**Usage:**
|
|
82
|
+
When a task involves browser interactions, use Playwright MCP tools:
|
|
83
|
+
```bash
|
|
84
|
+
# Navigate to page
|
|
85
|
+
playwright_browser_navigate(url="http://localhost:3000")
|
|
86
|
+
|
|
87
|
+
# Take screenshot
|
|
88
|
+
playwright_browser_take_screenshot(filename="homepage.png", type="png")
|
|
89
|
+
|
|
90
|
+
# Interact with elements
|
|
91
|
+
playwright_browser_click(ref="submit-button")
|
|
92
|
+
|
|
93
|
+
# Verify element present
|
|
94
|
+
playwright_browser_snapshot()
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Best practices:**
|
|
98
|
+
- Capture screenshots before and after interactions
|
|
99
|
+
- Verify console for errors
|
|
100
|
+
- Test across different viewport sizes
|
|
101
|
+
- Document all browser-based evidence
|
|
102
|
+
|
|
103
|
+
### APIs
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# 1. Start server
|
|
107
|
+
npm start &
|
|
108
|
+
sleep 3
|
|
109
|
+
|
|
110
|
+
# 2. Test key endpoints
|
|
111
|
+
curl -s -w "%{http_code}" http://localhost:3000/api/health
|
|
112
|
+
curl -s -X POST http://localhost:3000/api/[endpoint] \
|
|
113
|
+
-H "Content-Type: application/json" \
|
|
114
|
+
-d '{"test": true}'
|
|
115
|
+
|
|
116
|
+
# 3. Verify response shapes match spec
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Evidence to capture:**
|
|
120
|
+
- Status codes for each endpoint
|
|
121
|
+
- Response bodies (truncated if large)
|
|
122
|
+
- Error responses
|
|
123
|
+
|
|
124
|
+
### CLI Tools
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# 1. Test help
|
|
128
|
+
./cli --help
|
|
129
|
+
echo "Exit code: $?"
|
|
130
|
+
|
|
131
|
+
# 2. Test primary commands
|
|
132
|
+
./cli [command] test-input.txt
|
|
133
|
+
echo "Exit code: $?"
|
|
134
|
+
|
|
135
|
+
# 3. Test error handling
|
|
136
|
+
./cli [command] nonexistent.txt
|
|
137
|
+
echo "Exit code: $?" # Should be non-zero
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Evidence to capture:**
|
|
141
|
+
- Command output (stdout)
|
|
142
|
+
- Error output (stderr)
|
|
143
|
+
- Exit codes
|
|
144
|
+
|
|
145
|
+
### Libraries
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# 1. Run tests (confirm they pass)
|
|
149
|
+
npm test
|
|
150
|
+
|
|
151
|
+
# 2. Run examples from documentation
|
|
152
|
+
node examples/basic-usage.js
|
|
153
|
+
|
|
154
|
+
# 3. Check types compile
|
|
155
|
+
npm run typecheck
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Evidence to capture:**
|
|
159
|
+
- Example output
|
|
160
|
+
- Test coverage summary
|
|
161
|
+
|
|
162
|
+
## Fallback Hierarchy
|
|
163
|
+
|
|
164
|
+
If primary method fails, fall back in order:
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
1. Full runtime (screenshot/curl/run) ─ FAILED
|
|
168
|
+
│
|
|
169
|
+
└─► 2. Integration tests ─ FAILED
|
|
170
|
+
│
|
|
171
|
+
└─► 3. Unit tests + examples ─ FAILED
|
|
172
|
+
│
|
|
173
|
+
└─► 4. Type check + lint only ─ FAILED
|
|
174
|
+
│
|
|
175
|
+
└─► 5. Code review only (last resort)
|
|
176
|
+
└─► Report: "Unable to verify runtime behavior"
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Always record:**
|
|
180
|
+
- Which method was attempted
|
|
181
|
+
- Why it failed
|
|
182
|
+
- Which fallback was used
|
|
183
|
+
|
|
184
|
+
## Timeout Handling
|
|
185
|
+
|
|
186
|
+
**30-second timeout per verification method.**
|
|
187
|
+
|
|
188
|
+
If method times out:
|
|
189
|
+
1. Kill the process
|
|
190
|
+
2. Log the timeout
|
|
191
|
+
3. Try fallback method
|
|
192
|
+
|
|
193
|
+
## Evidence Storage
|
|
194
|
+
|
|
195
|
+
Document evidence in MANUAL Verification Logs:
|
|
196
|
+
|
|
197
|
+
```markdown
|
|
198
|
+
## ✅ Verification Evidence
|
|
199
|
+
|
|
200
|
+
### Runtime Verification
|
|
201
|
+
**Project Type**: web
|
|
202
|
+
**Method Used**: curl + HTML inspection
|
|
203
|
+
**Fallback Level**: Primary (no fallback needed)
|
|
204
|
+
|
|
205
|
+
### Evidence Captured
|
|
206
|
+
1. **Homepage**: Returns 200, contains expected title
|
|
207
|
+
2. **API Health**: /api/health returns {"status": "ok"}
|
|
208
|
+
3. **Login Flow**: Form renders, submits correctly
|
|
209
|
+
|
|
210
|
+
### Screenshots/Output
|
|
211
|
+
- [Describe what was observed]
|
|
212
|
+
- [Key behaviors verified]
|
|
213
|
+
|
|
214
|
+
### Result: ✅ VERIFIED
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Red Flags — STOP and Reassess
|
|
218
|
+
|
|
219
|
+
If you're thinking any of these, you're about to violate the methodology:
|
|
220
|
+
|
|
221
|
+
- "Tests pass, that's good enough" → **NO. SEE it working.**
|
|
222
|
+
- "I'll verify after shipping" → **NO. Verify BEFORE ship.**
|
|
223
|
+
- "The type checker caught everything" → **NO. Types don't catch runtime issues.**
|
|
224
|
+
- "Screenshot failed but it probably works" → **NO. "Probably" isn't evidence.**
|
|
225
|
+
- "It should work because..." → **NO. SHOW it works.**
|
|
226
|
+
- "Evidence isn't necessary for this change" → **NO. Every change gets verified.**
|
|
227
|
+
|
|
228
|
+
## Rationalizations to Resist
|
|
229
|
+
|
|
230
|
+
| Excuse | Reality |
|
|
231
|
+
|--------|---------|
|
|
232
|
+
| "Tests pass" | Tests aren't enough. SEE it working. |
|
|
233
|
+
| "Type checker caught everything" | Types don't catch runtime issues. |
|
|
234
|
+
| "It worked before" | Prove it works NOW. |
|
|
235
|
+
| "Human checkpoint is formality" | Human checkpoint is the gate. |
|
|
236
|
+
| "Code review is enough" | Code review is last resort fallback. |
|
|
237
|
+
| "Tests are flaky, ignore failure" | Flaky tests hide real failures. Fix or accept with caveat. |
|
|
238
|
+
|
|
239
|
+
## Flaky Test Detection
|
|
240
|
+
|
|
241
|
+
```
|
|
242
|
+
Test fails?
|
|
243
|
+
├── Re-run failed tests
|
|
244
|
+
├── Pass 2nd time?
|
|
245
|
+
│ └── Yes → Note flakiness, accept with caveat
|
|
246
|
+
└── Fail 2nd time?
|
|
247
|
+
├── Run isolated
|
|
248
|
+
└── Still fail? → Real failure, must fix
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Output Format
|
|
252
|
+
|
|
253
|
+
When verification completes:
|
|
254
|
+
|
|
255
|
+
```markdown
|
|
256
|
+
### Verification Summary
|
|
257
|
+
|
|
258
|
+
| Check | Status | Method | Notes |
|
|
259
|
+
|-------|--------|--------|-------|
|
|
260
|
+
| Build | ✅ | npm run build | No errors |
|
|
261
|
+
| Lint | ✅ | npm run lint | 0 issues |
|
|
262
|
+
| Tests | ✅ | npm test | 47/47 passed |
|
|
263
|
+
| Runtime | ✅ | curl + inspect | Evidence captured |
|
|
264
|
+
|
|
265
|
+
### Evidence
|
|
266
|
+
- Homepage renders correctly (verified via curl)
|
|
267
|
+
- API returns expected responses
|
|
268
|
+
- No console errors observed
|
|
269
|
+
|
|
270
|
+
### Result: ✅ ALL CHECKS PASS + EVIDENCE GATHERED
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Anti-Patterns
|
|
274
|
+
|
|
275
|
+
**Don't do these:**
|
|
276
|
+
|
|
277
|
+
- Trusting test results without seeing code run
|
|
278
|
+
- Skipping output verification because "tests pass"
|
|
279
|
+
- Proceeding when verification method fails without fallback
|
|
280
|
+
- Modifying code after verification passes (invalidates verification)
|
|
281
|
+
- Ignoring flaky test warnings
|
|
282
|
+
- Auto-approving without human checkpoint
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
**Remember**: You are gathering EVIDENCE. The human decides if it ships. Your job is to SEE the code work and document what you observed.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin";
|
|
2
|
+
import type { PluginInput } from "@opencode-ai/plugin";
|
|
3
|
+
import { BackgroundManager } from "./manager.js";
|
|
4
|
+
|
|
5
|
+
const BackgroundCancelTool: any = tool({
|
|
6
|
+
description: "Cancel running background agent sessions (cleanup)",
|
|
7
|
+
args: {
|
|
8
|
+
task_id: tool.schema.string().optional()
|
|
9
|
+
.describe("Specific task ID to cancel (omit to cancel all)"),
|
|
10
|
+
all: tool.schema.boolean().optional()
|
|
11
|
+
.describe("Cancel all running tasks"),
|
|
12
|
+
},
|
|
13
|
+
async execute(args, context) {
|
|
14
|
+
const ctx = context as unknown as PluginInput & { sessionID: string };
|
|
15
|
+
const manager = BackgroundManager.getInstance(ctx);
|
|
16
|
+
|
|
17
|
+
if (!args.task_id && !args.all) {
|
|
18
|
+
return "❌ Must specify task_id OR all=true";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (args.all) {
|
|
22
|
+
const runningTasks = manager.getRunningTasks();
|
|
23
|
+
|
|
24
|
+
if (runningTasks.length === 0) {
|
|
25
|
+
return "📭 No running tasks to cancel";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let cancelledCount = 0;
|
|
29
|
+
for (const task of runningTasks) {
|
|
30
|
+
if (task.sessionID) {
|
|
31
|
+
await ctx.client.session.delete({
|
|
32
|
+
path: { id: task.sessionID },
|
|
33
|
+
});
|
|
34
|
+
cancelledCount++;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return `🗑️ Cancelled ${cancelledCount} running tasks`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (args.task_id) {
|
|
42
|
+
const task = manager.getTask(args.task_id);
|
|
43
|
+
|
|
44
|
+
if (!task) {
|
|
45
|
+
return `❌ Task ${args.task_id} not found`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (task.status !== "running") {
|
|
49
|
+
return `⚠️ Task ${args.task_id} is ${task.status}, cannot cancel`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!task.sessionID) {
|
|
53
|
+
return `❌ Task ${args.task_id} has no session`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
await ctx.client.session.delete({
|
|
57
|
+
path: { id: task.sessionID },
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return `🗑️ Cancelled task ${args.task_id}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return "";
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
export default BackgroundCancelTool;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple concurrency manager for background agents.
|
|
3
|
+
* Limits concurrent tasks per model/agent.
|
|
4
|
+
*/
|
|
5
|
+
export class ConcurrencyManager {
|
|
6
|
+
private counts: Map<string, number> = new Map();
|
|
7
|
+
private queues: Map<string, Array<() => void>> = new Map();
|
|
8
|
+
private readonly defaultLimit = 5;
|
|
9
|
+
|
|
10
|
+
getConcurrencyLimit(key: string): number {
|
|
11
|
+
return this.defaultLimit;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async acquire(key: string): Promise<void> {
|
|
15
|
+
const limit = this.getConcurrencyLimit(key);
|
|
16
|
+
if (limit === Infinity) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const current = this.counts.get(key) ?? 0;
|
|
21
|
+
if (current < limit) {
|
|
22
|
+
this.counts.set(key, current + 1);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return new Promise<void>((resolve) => {
|
|
27
|
+
const queue = this.queues.get(key) ?? [];
|
|
28
|
+
queue.push(resolve);
|
|
29
|
+
this.queues.set(key, queue);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
release(key: string): void {
|
|
34
|
+
const limit = this.getConcurrencyLimit(key);
|
|
35
|
+
if (limit === Infinity) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const queue = this.queues.get(key);
|
|
40
|
+
|
|
41
|
+
// Try to hand off to a waiting entry
|
|
42
|
+
while (queue && queue.length > 0) {
|
|
43
|
+
const next = queue.shift()!;
|
|
44
|
+
if (next) {
|
|
45
|
+
next();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// No handoff occurred - decrement count to free slot
|
|
51
|
+
const current = this.counts.get(key) ?? 0;
|
|
52
|
+
if (current > 0) {
|
|
53
|
+
this.counts.set(key, current - 1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
clear(): void {
|
|
58
|
+
for (const [key] of this.queues) {
|
|
59
|
+
this.cancelWaiters(key);
|
|
60
|
+
}
|
|
61
|
+
this.counts.clear();
|
|
62
|
+
this.queues.clear();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private cancelWaiters(key: string): void {
|
|
66
|
+
const queue = this.queues.get(key);
|
|
67
|
+
if (queue) {
|
|
68
|
+
this.queues.delete(key);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from "./types";
|
|
2
|
+
export { BackgroundManager } from "./manager";
|
|
3
|
+
export { ConcurrencyManager } from "./concurrency";
|
|
4
|
+
export { default as background_agent } from "./launch.js";
|
|
5
|
+
export { default as list_background_tasks } from "./list.js";
|
|
6
|
+
export { default as background_output } from "./output.js";
|
|
7
|
+
export { default as background_cancel } from "./cancel.js";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import type { PluginInput } from "@opencode-ai/plugin";
|
|
3
|
+
import { BackgroundManager } from "./manager.js";
|
|
4
|
+
import type { LaunchInput } from "./types.js";
|
|
5
|
+
|
|
6
|
+
const BackgroundAgentTool: ToolDefinition = tool({
|
|
7
|
+
description: "Launch a background agent for LSP code exploration or verification",
|
|
8
|
+
args: {
|
|
9
|
+
agent: tool.schema.enum(["alice", "bob", "bob-eng", "bob-rev", "trace", "bob-send"])
|
|
10
|
+
.describe("Agent name to launch in background"),
|
|
11
|
+
prompt: tool.schema.string().describe("Prompt for the background agent"),
|
|
12
|
+
skills: tool.schema.array(tool.schema.string()).optional()
|
|
13
|
+
.describe("Skills to load from .opencode/skill/"),
|
|
14
|
+
model: tool.schema.string().optional()
|
|
15
|
+
.describe("Override model (defaults to agent's configured model)"),
|
|
16
|
+
manual_path: tool.schema.string().optional()
|
|
17
|
+
.describe("Path to MANUAL file (for bob/bob-rev agents)"),
|
|
18
|
+
},
|
|
19
|
+
async execute(args, context) {
|
|
20
|
+
const ctx = context as unknown as PluginInput & { sessionID: string };
|
|
21
|
+
const manager = BackgroundManager.getInstance(ctx);
|
|
22
|
+
|
|
23
|
+
const input: LaunchInput = {
|
|
24
|
+
description: `${args.agent} - ${args.prompt.slice(0, 50)}`,
|
|
25
|
+
prompt: args.prompt,
|
|
26
|
+
agent: args.agent,
|
|
27
|
+
parentSessionID: ctx.sessionID,
|
|
28
|
+
model: args.model,
|
|
29
|
+
skills: args.skills,
|
|
30
|
+
manual_path: args.manual_path,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const task = await manager.launch(input);
|
|
34
|
+
return `✅ Started background ${args.agent} session: ${task.id}`;
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export default BackgroundAgentTool;
|
|
39
|
+
export { BackgroundManager };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin";
|
|
2
|
+
import type { PluginInput } from "@opencode-ai/plugin";
|
|
3
|
+
import { BackgroundManager } from "./index.js";
|
|
4
|
+
|
|
5
|
+
const ListBackgroundTasksTool = tool({
|
|
6
|
+
description: "List all running background agent sessions",
|
|
7
|
+
args: {},
|
|
8
|
+
async execute(args, context) {
|
|
9
|
+
const ctx = context as unknown as PluginInput;
|
|
10
|
+
const manager = BackgroundManager.getInstance(ctx);
|
|
11
|
+
|
|
12
|
+
const tasks = manager.getAllTasks();
|
|
13
|
+
|
|
14
|
+
if (tasks.length === 0) {
|
|
15
|
+
return "📭 No background sessions running";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const output = tasks.map((t) => {
|
|
19
|
+
const statusEmoji: Record<string, string> = {
|
|
20
|
+
pending: "⏳",
|
|
21
|
+
running: "🔄",
|
|
22
|
+
completed: "✅",
|
|
23
|
+
error: "❌",
|
|
24
|
+
cancelled: "🚫",
|
|
25
|
+
};
|
|
26
|
+
const emoji = statusEmoji[t.status] || "❓";
|
|
27
|
+
const duration = t.startedAt && t.completedAt
|
|
28
|
+
? `${Math.round((t.completedAt.getTime() - t.startedAt.getTime()) / 1000)}s`
|
|
29
|
+
: t.startedAt
|
|
30
|
+
? `${Math.round((Date.now() - t.startedAt.getTime()) / 1000)}s (running)`
|
|
31
|
+
: "-";
|
|
32
|
+
|
|
33
|
+
const skillInfo = t.skills && t.skills.length > 0
|
|
34
|
+
? ` [skills: ${t.skills.join(", ")}]`
|
|
35
|
+
: "";
|
|
36
|
+
|
|
37
|
+
return `${emoji} \`${t.id}\` - ${t.description} [${t.status}] ${duration}${skillInfo}`;
|
|
38
|
+
}).join('\n');
|
|
39
|
+
|
|
40
|
+
const runningCount = tasks.filter(t => t.status === "running").length;
|
|
41
|
+
const completedCount = tasks.filter(t => t.status === "completed").length;
|
|
42
|
+
const errorCount = tasks.filter(t => t.status === "error").length;
|
|
43
|
+
|
|
44
|
+
return `🗂️ Background Sessions (${tasks.length} total):\n` +
|
|
45
|
+
` 🔄 Running: ${runningCount} | ✅ Completed: ${completedCount} | ❌ Error: ${errorCount}\n\n` +
|
|
46
|
+
`${output}`;
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
export default ListBackgroundTasksTool;
|