workerssuper 5.0.4
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/.claude-plugin/marketplace.json +20 -0
- package/.claude-plugin/plugin.json +13 -0
- package/.codex/INSTALL.md +67 -0
- package/.cursor-plugin/plugin.json +18 -0
- package/.gitattributes +18 -0
- package/.github/FUNDING.yml +3 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +52 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +34 -0
- package/.github/ISSUE_TEMPLATE/platform_support.md +23 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +87 -0
- package/.opencode/INSTALL.md +83 -0
- package/.opencode/plugins/superpowers.js +107 -0
- package/CHANGELOG.md +13 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/GEMINI.md +2 -0
- package/LICENSE +21 -0
- package/README.md +187 -0
- package/RELEASE-NOTES.md +1057 -0
- package/agents/code-reviewer.md +48 -0
- package/commands/brainstorm.md +5 -0
- package/commands/execute-plan.md +5 -0
- package/commands/write-plan.md +5 -0
- package/docs/README.codex.md +126 -0
- package/docs/README.opencode.md +130 -0
- package/docs/plans/2025-11-22-opencode-support-design.md +294 -0
- package/docs/plans/2025-11-22-opencode-support-implementation.md +1095 -0
- package/docs/plans/2025-11-28-skills-improvements-from-user-feedback.md +711 -0
- package/docs/plans/2026-01-17-visual-brainstorming.md +571 -0
- package/docs/superpowers/plans/2026-01-22-document-review-system.md +301 -0
- package/docs/superpowers/plans/2026-02-19-visual-brainstorming-refactor.md +523 -0
- package/docs/superpowers/plans/2026-03-11-zero-dep-brainstorm-server.md +479 -0
- package/docs/superpowers/specs/2026-01-22-document-review-system-design.md +136 -0
- package/docs/superpowers/specs/2026-02-19-visual-brainstorming-refactor-design.md +162 -0
- package/docs/superpowers/specs/2026-03-11-zero-dep-brainstorm-server-design.md +118 -0
- package/docs/testing.md +303 -0
- package/docs/windows/polyglot-hooks.md +212 -0
- package/gemini-extension.json +6 -0
- package/hooks/hooks-cursor.json +10 -0
- package/hooks/hooks.json +16 -0
- package/hooks/run-hook.cmd +46 -0
- package/hooks/session-start +57 -0
- package/package.json +5 -0
- package/skills/brainstorming/SKILL.md +164 -0
- package/skills/brainstorming/scripts/frame-template.html +214 -0
- package/skills/brainstorming/scripts/helper.js +88 -0
- package/skills/brainstorming/scripts/server.cjs +338 -0
- package/skills/brainstorming/scripts/start-server.sh +153 -0
- package/skills/brainstorming/scripts/stop-server.sh +55 -0
- package/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
- package/skills/brainstorming/visual-companion.md +286 -0
- package/skills/dispatching-parallel-agents/SKILL.md +182 -0
- package/skills/executing-plans/SKILL.md +70 -0
- package/skills/finishing-a-development-branch/SKILL.md +200 -0
- package/skills/receiving-code-review/SKILL.md +213 -0
- package/skills/requesting-code-review/SKILL.md +105 -0
- package/skills/requesting-code-review/code-reviewer.md +146 -0
- package/skills/subagent-driven-development/SKILL.md +277 -0
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
- package/skills/subagent-driven-development/implementer-prompt.md +113 -0
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/skills/systematic-debugging/SKILL.md +296 -0
- package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/skills/systematic-debugging/find-polluter.sh +63 -0
- package/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/skills/systematic-debugging/test-academic.md +14 -0
- package/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/skills/test-driven-development/SKILL.md +371 -0
- package/skills/test-driven-development/testing-anti-patterns.md +299 -0
- package/skills/using-git-worktrees/SKILL.md +218 -0
- package/skills/using-superpowers/SKILL.md +115 -0
- package/skills/using-superpowers/references/codex-tools.md +25 -0
- package/skills/using-superpowers/references/gemini-tools.md +33 -0
- package/skills/verification-before-completion/SKILL.md +139 -0
- package/skills/writing-plans/SKILL.md +145 -0
- package/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
- package/skills/writing-skills/SKILL.md +655 -0
- package/skills/writing-skills/anthropic-best-practices.md +1150 -0
- package/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/skills/writing-skills/graphviz-conventions.dot +172 -0
- package/skills/writing-skills/persuasion-principles.md +187 -0
- package/skills/writing-skills/render-graphs.js +168 -0
- package/skills/writing-skills/testing-skills-with-subagents.md +384 -0
- package/tests/brainstorm-server/package-lock.json +36 -0
- package/tests/brainstorm-server/package.json +10 -0
- package/tests/brainstorm-server/server.test.js +424 -0
- package/tests/brainstorm-server/windows-lifecycle.test.sh +351 -0
- package/tests/brainstorm-server/ws-protocol.test.js +392 -0
- package/tests/claude-code/README.md +158 -0
- package/tests/claude-code/analyze-token-usage.py +168 -0
- package/tests/claude-code/run-skill-tests.sh +187 -0
- package/tests/claude-code/test-document-review-system.sh +177 -0
- package/tests/claude-code/test-helpers.sh +202 -0
- package/tests/claude-code/test-subagent-driven-development-integration.sh +314 -0
- package/tests/claude-code/test-subagent-driven-development.sh +165 -0
- package/tests/explicit-skill-requests/prompts/action-oriented.txt +3 -0
- package/tests/explicit-skill-requests/prompts/after-planning-flow.txt +17 -0
- package/tests/explicit-skill-requests/prompts/claude-suggested-it.txt +11 -0
- package/tests/explicit-skill-requests/prompts/i-know-what-sdd-means.txt +8 -0
- package/tests/explicit-skill-requests/prompts/mid-conversation-execute-plan.txt +3 -0
- package/tests/explicit-skill-requests/prompts/please-use-brainstorming.txt +1 -0
- package/tests/explicit-skill-requests/prompts/skip-formalities.txt +3 -0
- package/tests/explicit-skill-requests/prompts/subagent-driven-development-please.txt +1 -0
- package/tests/explicit-skill-requests/prompts/use-systematic-debugging.txt +1 -0
- package/tests/explicit-skill-requests/run-all.sh +70 -0
- package/tests/explicit-skill-requests/run-claude-describes-sdd.sh +100 -0
- package/tests/explicit-skill-requests/run-extended-multiturn-test.sh +113 -0
- package/tests/explicit-skill-requests/run-haiku-test.sh +144 -0
- package/tests/explicit-skill-requests/run-multiturn-test.sh +143 -0
- package/tests/explicit-skill-requests/run-test.sh +136 -0
- package/tests/opencode/run-tests.sh +163 -0
- package/tests/opencode/setup.sh +73 -0
- package/tests/opencode/test-plugin-loading.sh +72 -0
- package/tests/opencode/test-priority.sh +198 -0
- package/tests/opencode/test-tools.sh +104 -0
- package/tests/skill-triggering/prompts/dispatching-parallel-agents.txt +8 -0
- package/tests/skill-triggering/prompts/executing-plans.txt +1 -0
- package/tests/skill-triggering/prompts/requesting-code-review.txt +3 -0
- package/tests/skill-triggering/prompts/systematic-debugging.txt +11 -0
- package/tests/skill-triggering/prompts/test-driven-development.txt +7 -0
- package/tests/skill-triggering/prompts/writing-plans.txt +10 -0
- package/tests/skill-triggering/run-all.sh +60 -0
- package/tests/skill-triggering/run-test.sh +88 -0
- package/tests/subagent-driven-dev/go-fractals/design.md +81 -0
- package/tests/subagent-driven-dev/go-fractals/plan.md +172 -0
- package/tests/subagent-driven-dev/go-fractals/scaffold.sh +45 -0
- package/tests/subagent-driven-dev/run-test.sh +106 -0
- package/tests/subagent-driven-dev/svelte-todo/design.md +70 -0
- package/tests/subagent-driven-dev/svelte-todo/plan.md +222 -0
- package/tests/subagent-driven-dev/svelte-todo/scaffold.sh +46 -0
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
# Visual Brainstorming Companion Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
4
|
+
|
|
5
|
+
**Goal:** Give Claude a browser-based visual companion for brainstorming sessions - show mockups, prototypes, and interactive choices alongside terminal conversation.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Claude writes HTML to a temp file. A local Node.js server watches that file and serves it with an auto-injected helper library. User interactions flow via WebSocket to server stdout, which Claude sees in background task output.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Node.js, Express, ws (WebSocket), chokidar (file watching)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Task 1: Create the Server Foundation
|
|
14
|
+
|
|
15
|
+
**Files:**
|
|
16
|
+
- Create: `lib/brainstorm-server/index.js`
|
|
17
|
+
- Create: `lib/brainstorm-server/package.json`
|
|
18
|
+
|
|
19
|
+
**Step 1: Create package.json**
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"name": "brainstorm-server",
|
|
24
|
+
"version": "1.0.0",
|
|
25
|
+
"description": "Visual brainstorming companion server for Claude Code",
|
|
26
|
+
"main": "index.js",
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"chokidar": "^3.5.3",
|
|
29
|
+
"express": "^4.18.2",
|
|
30
|
+
"ws": "^8.14.2"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Step 2: Create minimal server that starts**
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
const express = require('express');
|
|
39
|
+
const http = require('http');
|
|
40
|
+
const WebSocket = require('ws');
|
|
41
|
+
const chokidar = require('chokidar');
|
|
42
|
+
const fs = require('fs');
|
|
43
|
+
const path = require('path');
|
|
44
|
+
|
|
45
|
+
const PORT = process.env.BRAINSTORM_PORT || 3333;
|
|
46
|
+
const SCREEN_FILE = process.env.BRAINSTORM_SCREEN || '/tmp/brainstorm/screen.html';
|
|
47
|
+
const SCREEN_DIR = path.dirname(SCREEN_FILE);
|
|
48
|
+
|
|
49
|
+
// Ensure screen directory exists
|
|
50
|
+
if (!fs.existsSync(SCREEN_DIR)) {
|
|
51
|
+
fs.mkdirSync(SCREEN_DIR, { recursive: true });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Create default screen if none exists
|
|
55
|
+
if (!fs.existsSync(SCREEN_FILE)) {
|
|
56
|
+
fs.writeFileSync(SCREEN_FILE, `<!DOCTYPE html>
|
|
57
|
+
<html>
|
|
58
|
+
<head>
|
|
59
|
+
<title>Brainstorm Companion</title>
|
|
60
|
+
<style>
|
|
61
|
+
body { font-family: system-ui, sans-serif; padding: 2rem; max-width: 800px; margin: 0 auto; }
|
|
62
|
+
h1 { color: #333; }
|
|
63
|
+
p { color: #666; }
|
|
64
|
+
</style>
|
|
65
|
+
</head>
|
|
66
|
+
<body>
|
|
67
|
+
<h1>Brainstorm Companion</h1>
|
|
68
|
+
<p>Waiting for Claude to push a screen...</p>
|
|
69
|
+
</body>
|
|
70
|
+
</html>`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const app = express();
|
|
74
|
+
const server = http.createServer(app);
|
|
75
|
+
const wss = new WebSocket.Server({ server });
|
|
76
|
+
|
|
77
|
+
// Track connected browsers for reload notifications
|
|
78
|
+
const clients = new Set();
|
|
79
|
+
|
|
80
|
+
wss.on('connection', (ws) => {
|
|
81
|
+
clients.add(ws);
|
|
82
|
+
ws.on('close', () => clients.delete(ws));
|
|
83
|
+
|
|
84
|
+
ws.on('message', (data) => {
|
|
85
|
+
// User interaction event - write to stdout for Claude
|
|
86
|
+
const event = JSON.parse(data.toString());
|
|
87
|
+
console.log(JSON.stringify({ type: 'user-event', ...event }));
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Serve current screen with helper.js injected
|
|
92
|
+
app.get('/', (req, res) => {
|
|
93
|
+
let html = fs.readFileSync(SCREEN_FILE, 'utf-8');
|
|
94
|
+
|
|
95
|
+
// Inject helper script before </body>
|
|
96
|
+
const helperScript = fs.readFileSync(path.join(__dirname, 'helper.js'), 'utf-8');
|
|
97
|
+
const injection = `<script>\n${helperScript}\n</script>`;
|
|
98
|
+
|
|
99
|
+
if (html.includes('</body>')) {
|
|
100
|
+
html = html.replace('</body>', `${injection}\n</body>`);
|
|
101
|
+
} else {
|
|
102
|
+
html += injection;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
res.type('html').send(html);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Watch for screen file changes
|
|
109
|
+
chokidar.watch(SCREEN_FILE).on('change', () => {
|
|
110
|
+
console.log(JSON.stringify({ type: 'screen-updated', file: SCREEN_FILE }));
|
|
111
|
+
// Notify all browsers to reload
|
|
112
|
+
clients.forEach(ws => {
|
|
113
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
114
|
+
ws.send(JSON.stringify({ type: 'reload' }));
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
server.listen(PORT, '127.0.0.1', () => {
|
|
120
|
+
console.log(JSON.stringify({ type: 'server-started', port: PORT, url: `http://localhost:${PORT}` }));
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Step 3: Run npm install**
|
|
125
|
+
|
|
126
|
+
Run: `cd lib/brainstorm-server && npm install`
|
|
127
|
+
Expected: Dependencies installed
|
|
128
|
+
|
|
129
|
+
**Step 4: Test server starts**
|
|
130
|
+
|
|
131
|
+
Run: `cd lib/brainstorm-server && timeout 3 node index.js || true`
|
|
132
|
+
Expected: See JSON with `server-started` and port info
|
|
133
|
+
|
|
134
|
+
**Step 5: Commit**
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
git add lib/brainstorm-server/
|
|
138
|
+
git commit -m "feat: add brainstorm server foundation"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Task 2: Create the Helper Library
|
|
144
|
+
|
|
145
|
+
**Files:**
|
|
146
|
+
- Create: `lib/brainstorm-server/helper.js`
|
|
147
|
+
|
|
148
|
+
**Step 1: Create helper.js with event auto-capture**
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
(function() {
|
|
152
|
+
const WS_URL = 'ws://' + window.location.host;
|
|
153
|
+
let ws = null;
|
|
154
|
+
let eventQueue = [];
|
|
155
|
+
|
|
156
|
+
function connect() {
|
|
157
|
+
ws = new WebSocket(WS_URL);
|
|
158
|
+
|
|
159
|
+
ws.onopen = () => {
|
|
160
|
+
// Send any queued events
|
|
161
|
+
eventQueue.forEach(e => ws.send(JSON.stringify(e)));
|
|
162
|
+
eventQueue = [];
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
ws.onmessage = (msg) => {
|
|
166
|
+
const data = JSON.parse(msg.data);
|
|
167
|
+
if (data.type === 'reload') {
|
|
168
|
+
window.location.reload();
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
ws.onclose = () => {
|
|
173
|
+
// Reconnect after 1 second
|
|
174
|
+
setTimeout(connect, 1000);
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function send(event) {
|
|
179
|
+
event.timestamp = Date.now();
|
|
180
|
+
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
181
|
+
ws.send(JSON.stringify(event));
|
|
182
|
+
} else {
|
|
183
|
+
eventQueue.push(event);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Auto-capture clicks on interactive elements
|
|
188
|
+
document.addEventListener('click', (e) => {
|
|
189
|
+
const target = e.target.closest('button, a, [data-choice], [role="button"], input[type="submit"]');
|
|
190
|
+
if (!target) return;
|
|
191
|
+
|
|
192
|
+
// Don't capture regular link navigation
|
|
193
|
+
if (target.tagName === 'A' && !target.dataset.choice) return;
|
|
194
|
+
|
|
195
|
+
e.preventDefault();
|
|
196
|
+
|
|
197
|
+
send({
|
|
198
|
+
type: 'click',
|
|
199
|
+
text: target.textContent.trim(),
|
|
200
|
+
choice: target.dataset.choice || null,
|
|
201
|
+
id: target.id || null,
|
|
202
|
+
className: target.className || null
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Auto-capture form submissions
|
|
207
|
+
document.addEventListener('submit', (e) => {
|
|
208
|
+
e.preventDefault();
|
|
209
|
+
const form = e.target;
|
|
210
|
+
const formData = new FormData(form);
|
|
211
|
+
const data = {};
|
|
212
|
+
formData.forEach((value, key) => { data[key] = value; });
|
|
213
|
+
|
|
214
|
+
send({
|
|
215
|
+
type: 'submit',
|
|
216
|
+
formId: form.id || null,
|
|
217
|
+
formName: form.name || null,
|
|
218
|
+
data: data
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// Auto-capture input changes (debounced)
|
|
223
|
+
let inputTimeout = null;
|
|
224
|
+
document.addEventListener('input', (e) => {
|
|
225
|
+
const target = e.target;
|
|
226
|
+
if (!target.matches('input, textarea, select')) return;
|
|
227
|
+
|
|
228
|
+
clearTimeout(inputTimeout);
|
|
229
|
+
inputTimeout = setTimeout(() => {
|
|
230
|
+
send({
|
|
231
|
+
type: 'input',
|
|
232
|
+
name: target.name || null,
|
|
233
|
+
id: target.id || null,
|
|
234
|
+
value: target.value,
|
|
235
|
+
inputType: target.type || target.tagName.toLowerCase()
|
|
236
|
+
});
|
|
237
|
+
}, 500); // 500ms debounce
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Expose for explicit use if needed
|
|
241
|
+
window.brainstorm = {
|
|
242
|
+
send: send,
|
|
243
|
+
choice: (value, metadata = {}) => send({ type: 'choice', value, ...metadata })
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
connect();
|
|
247
|
+
})();
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Step 2: Verify helper.js is syntactically valid**
|
|
251
|
+
|
|
252
|
+
Run: `node -c lib/brainstorm-server/helper.js`
|
|
253
|
+
Expected: No syntax errors
|
|
254
|
+
|
|
255
|
+
**Step 3: Commit**
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
git add lib/brainstorm-server/helper.js
|
|
259
|
+
git commit -m "feat: add browser helper library for event capture"
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Task 3: Write Tests for the Server
|
|
265
|
+
|
|
266
|
+
**Files:**
|
|
267
|
+
- Create: `tests/brainstorm-server/server.test.js`
|
|
268
|
+
- Create: `tests/brainstorm-server/package.json`
|
|
269
|
+
|
|
270
|
+
**Step 1: Create test package.json**
|
|
271
|
+
|
|
272
|
+
```json
|
|
273
|
+
{
|
|
274
|
+
"name": "brainstorm-server-tests",
|
|
275
|
+
"version": "1.0.0",
|
|
276
|
+
"scripts": {
|
|
277
|
+
"test": "node server.test.js"
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**Step 2: Write server tests**
|
|
283
|
+
|
|
284
|
+
```javascript
|
|
285
|
+
const { spawn } = require('child_process');
|
|
286
|
+
const http = require('http');
|
|
287
|
+
const WebSocket = require('ws');
|
|
288
|
+
const fs = require('fs');
|
|
289
|
+
const path = require('path');
|
|
290
|
+
const assert = require('assert');
|
|
291
|
+
|
|
292
|
+
const SERVER_PATH = path.join(__dirname, '../../lib/brainstorm-server/index.js');
|
|
293
|
+
const TEST_PORT = 3334;
|
|
294
|
+
const TEST_SCREEN = '/tmp/brainstorm-test/screen.html';
|
|
295
|
+
|
|
296
|
+
// Clean up test directory
|
|
297
|
+
function cleanup() {
|
|
298
|
+
if (fs.existsSync(path.dirname(TEST_SCREEN))) {
|
|
299
|
+
fs.rmSync(path.dirname(TEST_SCREEN), { recursive: true });
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async function sleep(ms) {
|
|
304
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async function fetch(url) {
|
|
308
|
+
return new Promise((resolve, reject) => {
|
|
309
|
+
http.get(url, (res) => {
|
|
310
|
+
let data = '';
|
|
311
|
+
res.on('data', chunk => data += chunk);
|
|
312
|
+
res.on('end', () => resolve({ status: res.statusCode, body: data }));
|
|
313
|
+
}).on('error', reject);
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
async function runTests() {
|
|
318
|
+
cleanup();
|
|
319
|
+
|
|
320
|
+
// Start server
|
|
321
|
+
const server = spawn('node', [SERVER_PATH], {
|
|
322
|
+
env: { ...process.env, BRAINSTORM_PORT: TEST_PORT, BRAINSTORM_SCREEN: TEST_SCREEN }
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
let stdout = '';
|
|
326
|
+
server.stdout.on('data', (data) => { stdout += data.toString(); });
|
|
327
|
+
server.stderr.on('data', (data) => { console.error('Server stderr:', data.toString()); });
|
|
328
|
+
|
|
329
|
+
await sleep(1000); // Wait for server to start
|
|
330
|
+
|
|
331
|
+
try {
|
|
332
|
+
// Test 1: Server starts and outputs JSON
|
|
333
|
+
console.log('Test 1: Server startup message');
|
|
334
|
+
assert(stdout.includes('server-started'), 'Should output server-started');
|
|
335
|
+
assert(stdout.includes(TEST_PORT.toString()), 'Should include port');
|
|
336
|
+
console.log(' PASS');
|
|
337
|
+
|
|
338
|
+
// Test 2: GET / returns HTML with helper injected
|
|
339
|
+
console.log('Test 2: Serves HTML with helper injected');
|
|
340
|
+
const res = await fetch(`http://localhost:${TEST_PORT}/`);
|
|
341
|
+
assert.strictEqual(res.status, 200);
|
|
342
|
+
assert(res.body.includes('brainstorm'), 'Should include brainstorm content');
|
|
343
|
+
assert(res.body.includes('WebSocket'), 'Should have helper.js injected');
|
|
344
|
+
console.log(' PASS');
|
|
345
|
+
|
|
346
|
+
// Test 3: WebSocket connection and event relay
|
|
347
|
+
console.log('Test 3: WebSocket relays events to stdout');
|
|
348
|
+
stdout = ''; // Reset stdout capture
|
|
349
|
+
const ws = new WebSocket(`ws://localhost:${TEST_PORT}`);
|
|
350
|
+
await new Promise(resolve => ws.on('open', resolve));
|
|
351
|
+
|
|
352
|
+
ws.send(JSON.stringify({ type: 'click', text: 'Test Button' }));
|
|
353
|
+
await sleep(100);
|
|
354
|
+
|
|
355
|
+
assert(stdout.includes('user-event'), 'Should relay user events');
|
|
356
|
+
assert(stdout.includes('Test Button'), 'Should include event data');
|
|
357
|
+
ws.close();
|
|
358
|
+
console.log(' PASS');
|
|
359
|
+
|
|
360
|
+
// Test 4: File change triggers reload notification
|
|
361
|
+
console.log('Test 4: File change notifies browsers');
|
|
362
|
+
const ws2 = new WebSocket(`ws://localhost:${TEST_PORT}`);
|
|
363
|
+
await new Promise(resolve => ws2.on('open', resolve));
|
|
364
|
+
|
|
365
|
+
let gotReload = false;
|
|
366
|
+
ws2.on('message', (data) => {
|
|
367
|
+
const msg = JSON.parse(data.toString());
|
|
368
|
+
if (msg.type === 'reload') gotReload = true;
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// Modify the screen file
|
|
372
|
+
fs.writeFileSync(TEST_SCREEN, '<html><body>Updated</body></html>');
|
|
373
|
+
await sleep(500);
|
|
374
|
+
|
|
375
|
+
assert(gotReload, 'Should send reload message on file change');
|
|
376
|
+
ws2.close();
|
|
377
|
+
console.log(' PASS');
|
|
378
|
+
|
|
379
|
+
console.log('\nAll tests passed!');
|
|
380
|
+
|
|
381
|
+
} finally {
|
|
382
|
+
server.kill();
|
|
383
|
+
cleanup();
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
runTests().catch(err => {
|
|
388
|
+
console.error('Test failed:', err);
|
|
389
|
+
process.exit(1);
|
|
390
|
+
});
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
**Step 3: Run tests**
|
|
394
|
+
|
|
395
|
+
Run: `cd tests/brainstorm-server && npm install ws && node server.test.js`
|
|
396
|
+
Expected: All tests pass
|
|
397
|
+
|
|
398
|
+
**Step 4: Commit**
|
|
399
|
+
|
|
400
|
+
```bash
|
|
401
|
+
git add tests/brainstorm-server/
|
|
402
|
+
git commit -m "test: add brainstorm server integration tests"
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## Task 4: Add Visual Companion to Brainstorming Skill
|
|
408
|
+
|
|
409
|
+
**Files:**
|
|
410
|
+
- Modify: `skills/brainstorming/SKILL.md`
|
|
411
|
+
- Create: `skills/brainstorming/visual-companion.md` (supporting doc)
|
|
412
|
+
|
|
413
|
+
**Step 1: Create the supporting documentation**
|
|
414
|
+
|
|
415
|
+
Create `skills/brainstorming/visual-companion.md`:
|
|
416
|
+
|
|
417
|
+
```markdown
|
|
418
|
+
# Visual Companion Reference
|
|
419
|
+
|
|
420
|
+
## Starting the Server
|
|
421
|
+
|
|
422
|
+
Run as a background job:
|
|
423
|
+
|
|
424
|
+
```bash
|
|
425
|
+
node ${PLUGIN_ROOT}/lib/brainstorm-server/index.js
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
Tell the user: "I've started a visual companion at http://localhost:3333 - open it in a browser."
|
|
429
|
+
|
|
430
|
+
## Pushing Screens
|
|
431
|
+
|
|
432
|
+
Write HTML to `/tmp/brainstorm/screen.html`. The server watches this file and auto-refreshes the browser.
|
|
433
|
+
|
|
434
|
+
## Reading User Responses
|
|
435
|
+
|
|
436
|
+
Check the background task output for JSON events:
|
|
437
|
+
|
|
438
|
+
```json
|
|
439
|
+
{"type":"user-event","type":"click","text":"Option A","choice":"optionA","timestamp":1234567890}
|
|
440
|
+
{"type":"user-event","type":"submit","data":{"notes":"My feedback"},"timestamp":1234567891}
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
Event types:
|
|
444
|
+
- **click**: User clicked button or `data-choice` element
|
|
445
|
+
- **submit**: User submitted form (includes all form data)
|
|
446
|
+
- **input**: User typed in field (debounced 500ms)
|
|
447
|
+
|
|
448
|
+
## HTML Patterns
|
|
449
|
+
|
|
450
|
+
### Choice Cards
|
|
451
|
+
|
|
452
|
+
```html
|
|
453
|
+
<div class="options">
|
|
454
|
+
<button data-choice="optionA">
|
|
455
|
+
<h3>Option A</h3>
|
|
456
|
+
<p>Description</p>
|
|
457
|
+
</button>
|
|
458
|
+
<button data-choice="optionB">
|
|
459
|
+
<h3>Option B</h3>
|
|
460
|
+
<p>Description</p>
|
|
461
|
+
</button>
|
|
462
|
+
</div>
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Interactive Mockup
|
|
466
|
+
|
|
467
|
+
```html
|
|
468
|
+
<div class="mockup">
|
|
469
|
+
<header data-choice="header">App Header</header>
|
|
470
|
+
<nav data-choice="nav">Navigation</nav>
|
|
471
|
+
<main data-choice="main">Content</main>
|
|
472
|
+
</div>
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### Form with Notes
|
|
476
|
+
|
|
477
|
+
```html
|
|
478
|
+
<form>
|
|
479
|
+
<label>Priority: <input type="range" name="priority" min="1" max="5"></label>
|
|
480
|
+
<textarea name="notes" placeholder="Additional thoughts..."></textarea>
|
|
481
|
+
<button type="submit">Submit</button>
|
|
482
|
+
</form>
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### Explicit JavaScript
|
|
486
|
+
|
|
487
|
+
```html
|
|
488
|
+
<button onclick="brainstorm.choice('custom', {extra: 'data'})">Custom</button>
|
|
489
|
+
```
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
**Step 2: Add visual companion section to brainstorming skill**
|
|
493
|
+
|
|
494
|
+
Add after "Key Principles" in `skills/brainstorming/SKILL.md`:
|
|
495
|
+
|
|
496
|
+
```markdown
|
|
497
|
+
|
|
498
|
+
## Visual Companion (Optional)
|
|
499
|
+
|
|
500
|
+
When brainstorming involves visual elements - UI mockups, wireframes, interactive prototypes - use the browser-based visual companion.
|
|
501
|
+
|
|
502
|
+
**When to use:**
|
|
503
|
+
- Presenting UI/UX options that benefit from visual comparison
|
|
504
|
+
- Showing wireframes or layout options
|
|
505
|
+
- Gathering structured feedback (ratings, forms)
|
|
506
|
+
- Prototyping click interactions
|
|
507
|
+
|
|
508
|
+
**How it works:**
|
|
509
|
+
1. Start the server as a background job
|
|
510
|
+
2. Tell user to open http://localhost:3333
|
|
511
|
+
3. Write HTML to `/tmp/brainstorm/screen.html` (auto-refreshes)
|
|
512
|
+
4. Check background task output for user interactions
|
|
513
|
+
|
|
514
|
+
The terminal remains the primary conversation interface. The browser is a visual aid.
|
|
515
|
+
|
|
516
|
+
**Reference:** See `visual-companion.md` in this skill directory for HTML patterns and API details.
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
**Step 3: Verify the edits**
|
|
520
|
+
|
|
521
|
+
Run: `grep -A5 "Visual Companion" skills/brainstorming/SKILL.md`
|
|
522
|
+
Expected: Shows the new section
|
|
523
|
+
|
|
524
|
+
**Step 4: Commit**
|
|
525
|
+
|
|
526
|
+
```bash
|
|
527
|
+
git add skills/brainstorming/
|
|
528
|
+
git commit -m "feat: add visual companion to brainstorming skill"
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
## Task 5: Add Server to Plugin Ignore (Optional Cleanup)
|
|
534
|
+
|
|
535
|
+
**Files:**
|
|
536
|
+
- Check if `.gitignore` needs node_modules exclusion for lib/brainstorm-server
|
|
537
|
+
|
|
538
|
+
**Step 1: Check current gitignore**
|
|
539
|
+
|
|
540
|
+
Run: `cat .gitignore 2>/dev/null || echo "No .gitignore"`
|
|
541
|
+
|
|
542
|
+
**Step 2: Add node_modules if needed**
|
|
543
|
+
|
|
544
|
+
If not already present, add:
|
|
545
|
+
```
|
|
546
|
+
lib/brainstorm-server/node_modules/
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
**Step 3: Commit if changed**
|
|
550
|
+
|
|
551
|
+
```bash
|
|
552
|
+
git add .gitignore
|
|
553
|
+
git commit -m "chore: ignore brainstorm-server node_modules"
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
## Summary
|
|
559
|
+
|
|
560
|
+
After completing all tasks:
|
|
561
|
+
|
|
562
|
+
1. **Server** at `lib/brainstorm-server/` - Node.js server that watches HTML file and relays events
|
|
563
|
+
2. **Helper library** auto-injected - captures clicks, forms, inputs
|
|
564
|
+
3. **Tests** at `tests/brainstorm-server/` - verifies server behavior
|
|
565
|
+
4. **Brainstorming skill** updated with visual companion section and `visual-companion.md` reference doc
|
|
566
|
+
|
|
567
|
+
**To use:**
|
|
568
|
+
1. Start server as background job: `node lib/brainstorm-server/index.js &`
|
|
569
|
+
2. Tell user to open `http://localhost:3333`
|
|
570
|
+
3. Write HTML to `/tmp/brainstorm/screen.html`
|
|
571
|
+
4. Check task output for user events
|