brain-dev 0.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 +21 -0
- package/README.md +152 -0
- package/agents/brain-checker.md +33 -0
- package/agents/brain-debugger.md +35 -0
- package/agents/brain-executor.md +37 -0
- package/agents/brain-mapper.md +44 -0
- package/agents/brain-planner.md +49 -0
- package/agents/brain-researcher.md +47 -0
- package/agents/brain-synthesizer.md +43 -0
- package/agents/brain-verifier.md +41 -0
- package/bin/brain-tools.cjs +185 -0
- package/bin/lib/adr.cjs +283 -0
- package/bin/lib/agents.cjs +152 -0
- package/bin/lib/anti-patterns.cjs +183 -0
- package/bin/lib/audit.cjs +268 -0
- package/bin/lib/commands/adr.cjs +126 -0
- package/bin/lib/commands/complete.cjs +270 -0
- package/bin/lib/commands/config.cjs +306 -0
- package/bin/lib/commands/discuss.cjs +237 -0
- package/bin/lib/commands/execute.cjs +415 -0
- package/bin/lib/commands/health.cjs +103 -0
- package/bin/lib/commands/map.cjs +101 -0
- package/bin/lib/commands/new-project.cjs +885 -0
- package/bin/lib/commands/pause.cjs +142 -0
- package/bin/lib/commands/phase-manage.cjs +357 -0
- package/bin/lib/commands/plan.cjs +451 -0
- package/bin/lib/commands/progress.cjs +167 -0
- package/bin/lib/commands/quick.cjs +447 -0
- package/bin/lib/commands/resume.cjs +196 -0
- package/bin/lib/commands/storm.cjs +590 -0
- package/bin/lib/commands/verify.cjs +504 -0
- package/bin/lib/commands.cjs +263 -0
- package/bin/lib/complexity.cjs +138 -0
- package/bin/lib/complexity.test.cjs +108 -0
- package/bin/lib/config.cjs +452 -0
- package/bin/lib/core.cjs +62 -0
- package/bin/lib/detect.cjs +603 -0
- package/bin/lib/git.cjs +112 -0
- package/bin/lib/health.cjs +356 -0
- package/bin/lib/init.cjs +310 -0
- package/bin/lib/logger.cjs +100 -0
- package/bin/lib/platform.cjs +58 -0
- package/bin/lib/requirements.cjs +158 -0
- package/bin/lib/roadmap.cjs +228 -0
- package/bin/lib/security.cjs +237 -0
- package/bin/lib/state.cjs +353 -0
- package/bin/lib/templates.cjs +48 -0
- package/bin/templates/advocate.md +182 -0
- package/bin/templates/checkpoint.md +55 -0
- package/bin/templates/debugger.md +148 -0
- package/bin/templates/discuss.md +60 -0
- package/bin/templates/executor.md +201 -0
- package/bin/templates/mapper.md +129 -0
- package/bin/templates/plan-checker.md +134 -0
- package/bin/templates/planner.md +165 -0
- package/bin/templates/researcher.md +78 -0
- package/bin/templates/storm.html +376 -0
- package/bin/templates/synthesis.md +30 -0
- package/bin/templates/verifier.md +181 -0
- package/commands/brain/adr.md +34 -0
- package/commands/brain/complete.md +37 -0
- package/commands/brain/config.md +37 -0
- package/commands/brain/discuss.md +35 -0
- package/commands/brain/execute.md +38 -0
- package/commands/brain/health.md +33 -0
- package/commands/brain/map.md +35 -0
- package/commands/brain/new-project.md +38 -0
- package/commands/brain/pause.md +26 -0
- package/commands/brain/plan.md +38 -0
- package/commands/brain/progress.md +28 -0
- package/commands/brain/quick.md +51 -0
- package/commands/brain/resume.md +28 -0
- package/commands/brain/storm.md +30 -0
- package/commands/brain/verify.md +39 -0
- package/hooks/bootstrap.sh +54 -0
- package/hooks/post-tool-use.sh +45 -0
- package/hooks/statusline.sh +130 -0
- package/package.json +36 -0
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Brain Storm: {{topic}}</title>
|
|
7
|
+
<style>
|
|
8
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
9
|
+
|
|
10
|
+
body {
|
|
11
|
+
background: #1a1a2e;
|
|
12
|
+
color: #e0e0e0;
|
|
13
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
14
|
+
min-height: 100vh;
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
header {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: space-between;
|
|
23
|
+
padding: 1rem 1.5rem;
|
|
24
|
+
background: #0f0f23;
|
|
25
|
+
border-bottom: 1px solid #2a2a4a;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
header h1 {
|
|
29
|
+
font-size: 1.25rem;
|
|
30
|
+
font-weight: 600;
|
|
31
|
+
color: #e94560;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.status {
|
|
35
|
+
display: flex;
|
|
36
|
+
align-items: center;
|
|
37
|
+
gap: 0.5rem;
|
|
38
|
+
font-size: 0.85rem;
|
|
39
|
+
color: #888;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.status-dot {
|
|
43
|
+
width: 10px;
|
|
44
|
+
height: 10px;
|
|
45
|
+
border-radius: 50%;
|
|
46
|
+
background: #e94560;
|
|
47
|
+
transition: background 0.3s;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.status-dot.connected { background: #4ade80; }
|
|
51
|
+
|
|
52
|
+
.card-container {
|
|
53
|
+
flex: 1;
|
|
54
|
+
padding: 1.5rem;
|
|
55
|
+
display: grid;
|
|
56
|
+
grid-template-columns: repeat(3, 1fr);
|
|
57
|
+
gap: 1rem;
|
|
58
|
+
align-content: start;
|
|
59
|
+
overflow-y: auto;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@media (max-width: 768px) {
|
|
63
|
+
.card-container {
|
|
64
|
+
grid-template-columns: 1fr;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.card {
|
|
69
|
+
background: #16213e;
|
|
70
|
+
border-radius: 8px;
|
|
71
|
+
padding: 1rem;
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
border: 2px solid transparent;
|
|
74
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
75
|
+
transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s;
|
|
76
|
+
user-select: none;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.card:hover {
|
|
80
|
+
transform: translateY(-2px);
|
|
81
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.card.highlighted {
|
|
85
|
+
border-color: #e94560;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.card.drag-over {
|
|
89
|
+
border-color: #4ade80;
|
|
90
|
+
background: #1a2940;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.card h3 {
|
|
94
|
+
color: #e94560;
|
|
95
|
+
font-size: 0.95rem;
|
|
96
|
+
margin-bottom: 0.5rem;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.card .body {
|
|
100
|
+
font-size: 0.85rem;
|
|
101
|
+
line-height: 1.5;
|
|
102
|
+
color: #ccc;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.card .body h1, .card .body h2, .card .body h3 {
|
|
106
|
+
color: #e0e0e0;
|
|
107
|
+
margin: 0.5rem 0 0.25rem;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.card .body strong { color: #fff; }
|
|
111
|
+
.card .body em { color: #aaa; font-style: italic; }
|
|
112
|
+
.card .body code {
|
|
113
|
+
background: #0f0f23;
|
|
114
|
+
padding: 0.1rem 0.3rem;
|
|
115
|
+
border-radius: 3px;
|
|
116
|
+
font-size: 0.8rem;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.card .body ul {
|
|
120
|
+
padding-left: 1.2rem;
|
|
121
|
+
margin: 0.25rem 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.input-area {
|
|
125
|
+
display: flex;
|
|
126
|
+
gap: 0.75rem;
|
|
127
|
+
padding: 1rem 1.5rem;
|
|
128
|
+
background: #0f0f23;
|
|
129
|
+
border-top: 1px solid #2a2a4a;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.input-area textarea {
|
|
133
|
+
flex: 1;
|
|
134
|
+
background: #16213e;
|
|
135
|
+
color: #e0e0e0;
|
|
136
|
+
border: 1px solid #2a2a4a;
|
|
137
|
+
border-radius: 6px;
|
|
138
|
+
padding: 0.75rem;
|
|
139
|
+
font-family: inherit;
|
|
140
|
+
font-size: 0.9rem;
|
|
141
|
+
resize: vertical;
|
|
142
|
+
min-height: 48px;
|
|
143
|
+
max-height: 200px;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.input-area textarea:focus {
|
|
147
|
+
outline: none;
|
|
148
|
+
border-color: #e94560;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.input-area button {
|
|
152
|
+
background: #e94560;
|
|
153
|
+
color: #fff;
|
|
154
|
+
border: none;
|
|
155
|
+
border-radius: 6px;
|
|
156
|
+
padding: 0.75rem 1.5rem;
|
|
157
|
+
font-size: 0.9rem;
|
|
158
|
+
cursor: pointer;
|
|
159
|
+
white-space: nowrap;
|
|
160
|
+
align-self: flex-end;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.input-area button:hover { background: #c73652; }
|
|
164
|
+
.input-area button:disabled { background: #555; cursor: not-allowed; }
|
|
165
|
+
|
|
166
|
+
.empty-state {
|
|
167
|
+
grid-column: 1 / -1;
|
|
168
|
+
text-align: center;
|
|
169
|
+
padding: 3rem;
|
|
170
|
+
color: #555;
|
|
171
|
+
font-size: 1rem;
|
|
172
|
+
}
|
|
173
|
+
</style>
|
|
174
|
+
</head>
|
|
175
|
+
<body>
|
|
176
|
+
<header>
|
|
177
|
+
<h1>{{topic}}</h1>
|
|
178
|
+
<div class="status">
|
|
179
|
+
<div class="status-dot" id="statusDot"></div>
|
|
180
|
+
<span id="statusText">Disconnected</span>
|
|
181
|
+
</div>
|
|
182
|
+
</header>
|
|
183
|
+
|
|
184
|
+
<div class="card-container" id="cardContainer">
|
|
185
|
+
<div class="empty-state" id="emptyState">No fragments yet. Add one below or send from the brain agent.</div>
|
|
186
|
+
</div>
|
|
187
|
+
|
|
188
|
+
<div class="input-area">
|
|
189
|
+
<textarea id="fragmentInput" placeholder="Type a fragment... (Shift+Enter for new line, Enter to send)" rows="1"></textarea>
|
|
190
|
+
<button id="sendBtn">Send</button>
|
|
191
|
+
</div>
|
|
192
|
+
|
|
193
|
+
<script>
|
|
194
|
+
(function() {
|
|
195
|
+
var ws = null;
|
|
196
|
+
var reconnectAttempts = 0;
|
|
197
|
+
var maxReconnect = 10;
|
|
198
|
+
var reconnectTimer = null;
|
|
199
|
+
|
|
200
|
+
var container = document.getElementById('cardContainer');
|
|
201
|
+
var emptyState = document.getElementById('emptyState');
|
|
202
|
+
var statusDot = document.getElementById('statusDot');
|
|
203
|
+
var statusText = document.getElementById('statusText');
|
|
204
|
+
var fragmentInput = document.getElementById('fragmentInput');
|
|
205
|
+
var sendBtn = document.getElementById('sendBtn');
|
|
206
|
+
|
|
207
|
+
function connect() {
|
|
208
|
+
var url = 'ws://localhost:' + location.port;
|
|
209
|
+
ws = new WebSocket(url);
|
|
210
|
+
|
|
211
|
+
ws.onopen = function() {
|
|
212
|
+
reconnectAttempts = 0;
|
|
213
|
+
statusDot.classList.add('connected');
|
|
214
|
+
statusText.textContent = 'Connected';
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
ws.onclose = function() {
|
|
218
|
+
statusDot.classList.remove('connected');
|
|
219
|
+
statusText.textContent = 'Disconnected';
|
|
220
|
+
scheduleReconnect();
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
ws.onerror = function() {
|
|
224
|
+
// onclose will fire after this
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
ws.onmessage = function(event) {
|
|
228
|
+
var msg;
|
|
229
|
+
try { msg = JSON.parse(event.data); } catch(e) { return; }
|
|
230
|
+
|
|
231
|
+
if (msg.type === 'fragment') {
|
|
232
|
+
addCard(msg);
|
|
233
|
+
} else if (msg.type === 'fragments-sync') {
|
|
234
|
+
for (var i = 0; i < msg.fragments.length; i++) {
|
|
235
|
+
addCard(msg.fragments[i]);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function scheduleReconnect() {
|
|
242
|
+
if (reconnectAttempts >= maxReconnect) {
|
|
243
|
+
statusText.textContent = 'Connection lost';
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
reconnectAttempts++;
|
|
247
|
+
statusText.textContent = 'Reconnecting (' + reconnectAttempts + '/' + maxReconnect + ')...';
|
|
248
|
+
reconnectTimer = setTimeout(connect, 3000);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function escapeHtml(str) {
|
|
252
|
+
return str
|
|
253
|
+
.replace(/&/g, '&')
|
|
254
|
+
.replace(/</g, '<')
|
|
255
|
+
.replace(/>/g, '>')
|
|
256
|
+
.replace(/"/g, '"')
|
|
257
|
+
.replace(/'/g, ''');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function simpleMarkdown(text) {
|
|
261
|
+
if (!text) return '';
|
|
262
|
+
// Escape HTML first to prevent XSS, then apply markdown formatting
|
|
263
|
+
return escapeHtml(text)
|
|
264
|
+
.replace(/^### (.+)$/gm, '<h3>$1</h3>')
|
|
265
|
+
.replace(/^## (.+)$/gm, '<h2>$1</h2>')
|
|
266
|
+
.replace(/^# (.+)$/gm, '<h1>$1</h1>')
|
|
267
|
+
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
|
|
268
|
+
.replace(/\*(.+?)\*/g, '<em>$1</em>')
|
|
269
|
+
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
|
270
|
+
.replace(/^- (.+)$/gm, '<li>$1</li>')
|
|
271
|
+
.replace(/(<li>.*<\/li>)/gs, '<ul>$1</ul>')
|
|
272
|
+
.replace(/\n/g, '<br>');
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function addCard(data) {
|
|
276
|
+
if (emptyState) {
|
|
277
|
+
emptyState.remove();
|
|
278
|
+
emptyState = null;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
var card = document.createElement('div');
|
|
282
|
+
card.className = 'card';
|
|
283
|
+
card.draggable = true;
|
|
284
|
+
card.dataset.id = data.id || ('f-' + Date.now());
|
|
285
|
+
|
|
286
|
+
var title = document.createElement('h3');
|
|
287
|
+
title.textContent = data.title || 'Fragment';
|
|
288
|
+
card.appendChild(title);
|
|
289
|
+
|
|
290
|
+
var body = document.createElement('div');
|
|
291
|
+
body.className = 'body';
|
|
292
|
+
body.innerHTML = simpleMarkdown(data.body || '');
|
|
293
|
+
card.appendChild(body);
|
|
294
|
+
|
|
295
|
+
// Click handler: toggle highlight
|
|
296
|
+
card.addEventListener('click', function() {
|
|
297
|
+
card.classList.toggle('highlighted');
|
|
298
|
+
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
299
|
+
ws.send(JSON.stringify({
|
|
300
|
+
type: 'click',
|
|
301
|
+
fragmentId: card.dataset.id,
|
|
302
|
+
highlighted: card.classList.contains('highlighted'),
|
|
303
|
+
timestamp: Date.now()
|
|
304
|
+
}));
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// Drag start
|
|
309
|
+
card.addEventListener('dragstart', function(e) {
|
|
310
|
+
e.dataTransfer.setData('text/plain', card.dataset.id);
|
|
311
|
+
e.dataTransfer.effectAllowed = 'move';
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
// Drag over (allow drop)
|
|
315
|
+
card.addEventListener('dragover', function(e) {
|
|
316
|
+
e.preventDefault();
|
|
317
|
+
e.dataTransfer.dropEffect = 'move';
|
|
318
|
+
card.classList.add('drag-over');
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
card.addEventListener('dragleave', function() {
|
|
322
|
+
card.classList.remove('drag-over');
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// Drop: group cards
|
|
326
|
+
card.addEventListener('drop', function(e) {
|
|
327
|
+
e.preventDefault();
|
|
328
|
+
card.classList.remove('drag-over');
|
|
329
|
+
var sourceId = e.dataTransfer.getData('text/plain');
|
|
330
|
+
var targetId = card.dataset.id;
|
|
331
|
+
if (sourceId !== targetId && ws && ws.readyState === WebSocket.OPEN) {
|
|
332
|
+
ws.send(JSON.stringify({
|
|
333
|
+
type: 'group',
|
|
334
|
+
sourceId: sourceId,
|
|
335
|
+
targetId: targetId,
|
|
336
|
+
timestamp: Date.now()
|
|
337
|
+
}));
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
container.appendChild(card);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function sendFragment() {
|
|
345
|
+
var text = fragmentInput.value.trim();
|
|
346
|
+
if (!text || !ws || ws.readyState !== WebSocket.OPEN) return;
|
|
347
|
+
|
|
348
|
+
// Split on first line as title, rest as body
|
|
349
|
+
var lines = text.split('\n');
|
|
350
|
+
var title = lines[0];
|
|
351
|
+
var body = lines.slice(1).join('\n').trim();
|
|
352
|
+
|
|
353
|
+
ws.send(JSON.stringify({
|
|
354
|
+
type: 'add-fragment',
|
|
355
|
+
title: title,
|
|
356
|
+
body: body
|
|
357
|
+
}));
|
|
358
|
+
|
|
359
|
+
fragmentInput.value = '';
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
sendBtn.addEventListener('click', sendFragment);
|
|
363
|
+
|
|
364
|
+
fragmentInput.addEventListener('keydown', function(e) {
|
|
365
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
366
|
+
e.preventDefault();
|
|
367
|
+
sendFragment();
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// Start connection
|
|
372
|
+
connect();
|
|
373
|
+
})();
|
|
374
|
+
</script>
|
|
375
|
+
</body>
|
|
376
|
+
</html>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
You are a research synthesis agent. Combine the findings from 6 research agents into a unified SUMMARY.md.
|
|
2
|
+
|
|
3
|
+
Read all files in {{research_dir}}:
|
|
4
|
+
- stack.md (technology stack and ecosystem)
|
|
5
|
+
- architecture.md (architecture patterns)
|
|
6
|
+
- pitfalls.md (pitfalls and anti-patterns)
|
|
7
|
+
- security.md (security and compliance)
|
|
8
|
+
- competitive.md (competitive analysis)
|
|
9
|
+
- testing.md (testing strategy)
|
|
10
|
+
|
|
11
|
+
Produce {{output_path}} with:
|
|
12
|
+
## Recommended Stack
|
|
13
|
+
## Architecture
|
|
14
|
+
## Key Decisions
|
|
15
|
+
## Risks and Mitigations
|
|
16
|
+
## Testing Strategy
|
|
17
|
+
|
|
18
|
+
Resolve conflicts between researchers (e.g., if stack and architecture disagree on a library).
|
|
19
|
+
Keep total output under 5000 tokens.
|
|
20
|
+
|
|
21
|
+
## Output Marker
|
|
22
|
+
|
|
23
|
+
When synthesis is complete, output:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
## SYNTHESIS COMPLETE
|
|
27
|
+
|
|
28
|
+
**Output:** {{output_path}}
|
|
29
|
+
**Key decisions:** [one-line summary of primary architecture/stack decisions]
|
|
30
|
+
```
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Verifier Agent Instructions
|
|
2
|
+
|
|
3
|
+
## Phase Must-Haves
|
|
4
|
+
|
|
5
|
+
{{must_haves}}
|
|
6
|
+
|
|
7
|
+
## Anti-Pattern Scan Results
|
|
8
|
+
|
|
9
|
+
{{anti_pattern_results}}
|
|
10
|
+
|
|
11
|
+
Use these results when evaluating Level 2 (Substantive) checks. Blockers MUST be reported as verification failures. Warnings should be noted but do not block.
|
|
12
|
+
|
|
13
|
+
## 3-Level Verification
|
|
14
|
+
|
|
15
|
+
For each artifact in must_haves, perform these automated checks:
|
|
16
|
+
|
|
17
|
+
### Level 1: Exists
|
|
18
|
+
- File exists at the specified path
|
|
19
|
+
- File is not empty (has content)
|
|
20
|
+
|
|
21
|
+
### Level 2: Substantive
|
|
22
|
+
- File has real implementation (not stub)
|
|
23
|
+
- No TODO-only files, no empty functions, no log-only handlers
|
|
24
|
+
- Minimum reasonable line count for the artifact type
|
|
25
|
+
- Anti-pattern scan: count TODO/FIXME, placeholder content, empty returns
|
|
26
|
+
- Cross-reference anti-pattern scan results above for blockers
|
|
27
|
+
|
|
28
|
+
### Level 3: Wired (Enhanced Key Link Verification)
|
|
29
|
+
- File is imported/used where expected
|
|
30
|
+
- Check key_links: from-file imports/references to-file with specified pattern
|
|
31
|
+
- Verify exports are actually consumed by dependent modules
|
|
32
|
+
|
|
33
|
+
For each key_link in must_haves, perform three wiring checks:
|
|
34
|
+
1. **Import exists:** grep/search for require() or import of the dependency file
|
|
35
|
+
2. **Function called:** grep for the specific function name being used in the consuming file
|
|
36
|
+
3. **Registration:** for commands, verify entry in commands.cjs COMMANDS array
|
|
37
|
+
|
|
38
|
+
If grep finds the pattern: PASS
|
|
39
|
+
If grep does not find it: read the file fully to check for aliased imports, re-exports, or indirect usage before marking FAIL
|
|
40
|
+
|
|
41
|
+
## Truth Verification
|
|
42
|
+
|
|
43
|
+
Each truth from must_haves should be testable:
|
|
44
|
+
- Run existing tests that cover the truth
|
|
45
|
+
- If no test exists, verify the behavior manually
|
|
46
|
+
|
|
47
|
+
## Nyquist Validation
|
|
48
|
+
|
|
49
|
+
{{nyquist_section}}
|
|
50
|
+
|
|
51
|
+
For each must_have truth, search test files for a matching test:
|
|
52
|
+
- Extract key words from the truth statement (ignore stop words: can, the, a, is, are, and, or, to, in, for, with)
|
|
53
|
+
- Search test file describe/it/test blocks for 60%+ keyword overlap
|
|
54
|
+
- Report coverage ratio: N truths with matching tests / M total truths
|
|
55
|
+
|
|
56
|
+
## Human Verification Detection
|
|
57
|
+
|
|
58
|
+
Scan must_have truths for keywords indicating human verification needed:
|
|
59
|
+
- Keywords: 'live session', 'browser', 'UI', 'visual', 'interactive', 'click', 'drag', 'animation', 'responsive', 'mobile', 'external service'
|
|
60
|
+
- Truths matching these keywords: mark as human-verify level, add to human verification checklist
|
|
61
|
+
- Status becomes 'human_needed' when automated checks pass but human items remain
|
|
62
|
+
|
|
63
|
+
## Human Verification Gate
|
|
64
|
+
|
|
65
|
+
Separate items that require human verification (visual checks, interactive flows, UX evaluation) from automated checks. Present human-verify items for user approval via AskUserQuestion instructions.
|
|
66
|
+
|
|
67
|
+
**Automated checks:** File existence, substantive content, import wiring, test passing
|
|
68
|
+
**Human verification:** Visual design, interactive flows, UX evaluation, cross-browser behavior
|
|
69
|
+
|
|
70
|
+
## Scored Results
|
|
71
|
+
|
|
72
|
+
After checking all must_haves, compute a score:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
Score: [verified_count] / [total_count] must_haves verified
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Where:
|
|
79
|
+
- **verified_count** = number of must_haves that pass all applicable levels
|
|
80
|
+
- **total_count** = total number of must_haves (truths + artifacts + key_links)
|
|
81
|
+
|
|
82
|
+
### Status Determination
|
|
83
|
+
|
|
84
|
+
Based on the score:
|
|
85
|
+
|
|
86
|
+
- **passed** (100%): All must_haves verified at all levels. Phase/plan deliverables are complete.
|
|
87
|
+
- **gaps_found** (<100%): Some must_haves failed verification. List specific gaps with remediation steps.
|
|
88
|
+
- **human_needed**: Some items require human verification (visual, interactive, UX). Automated checks passed but human gate pending.
|
|
89
|
+
|
|
90
|
+
## Output Format
|
|
91
|
+
|
|
92
|
+
Write results to `{{output_path}}` with this structure:
|
|
93
|
+
|
|
94
|
+
### YAML Frontmatter
|
|
95
|
+
|
|
96
|
+
Start the file with YAML frontmatter containing machine-parseable metadata:
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
---
|
|
100
|
+
phase: [phase number]
|
|
101
|
+
status: passed | gaps_found | human_needed
|
|
102
|
+
score: [verified]/[total]
|
|
103
|
+
must_haves_verified: [count]
|
|
104
|
+
must_haves_total: [count]
|
|
105
|
+
human_verification_count: [count]
|
|
106
|
+
anti_pattern_blockers: [count]
|
|
107
|
+
anti_pattern_warnings: [count]
|
|
108
|
+
gaps:
|
|
109
|
+
- id: GAP-001
|
|
110
|
+
severity: blocker | warning
|
|
111
|
+
truth: "[the must_have truth that failed]"
|
|
112
|
+
description: "[what specifically failed]"
|
|
113
|
+
files: ["file1.cjs", "file2.cjs"]
|
|
114
|
+
suggested_fix: "[concrete fix suggestion]"
|
|
115
|
+
---
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Per-Truth Results
|
|
119
|
+
|
|
120
|
+
```markdown
|
|
121
|
+
### Truth: "[truth statement]"
|
|
122
|
+
**Status:** PASS | FAIL
|
|
123
|
+
**Evidence:** [how it was verified -- test name, command output, manual check]
|
|
124
|
+
**Level:** [automated | human-verify]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Per-Artifact Results
|
|
128
|
+
|
|
129
|
+
```markdown
|
|
130
|
+
### Artifact: [file path]
|
|
131
|
+
**Provides:** [what the artifact provides]
|
|
132
|
+
|
|
133
|
+
| Level | Check | Status | Evidence |
|
|
134
|
+
|-------|-------|--------|----------|
|
|
135
|
+
| 1 - Exists | File exists on disk | PASS/FAIL | [file size, line count] |
|
|
136
|
+
| 1 - Exists | File is not empty | PASS/FAIL | [line count] |
|
|
137
|
+
| 2 - Substantive | Real implementation | PASS/FAIL | [exports found, function count] |
|
|
138
|
+
| 2 - Substantive | No TODO-only content | PASS/FAIL | [TODO/FIXME count] |
|
|
139
|
+
| 2 - Substantive | Minimum line count | PASS/FAIL | [actual vs expected] |
|
|
140
|
+
| 3 - Wired | Imported by consumers | PASS/FAIL | [importing files found] |
|
|
141
|
+
| 3 - Wired | Exports consumed | PASS/FAIL | [usage locations] |
|
|
142
|
+
| 3 - Wired | Tests assert behavior | PASS/FAIL | [test file, assertion count] |
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Per-Key-Link Results
|
|
146
|
+
|
|
147
|
+
```markdown
|
|
148
|
+
### Key Link: [from] -> [to]
|
|
149
|
+
**Via:** [connection description]
|
|
150
|
+
**Pattern:** [regex pattern]
|
|
151
|
+
**Status:** PASS | FAIL
|
|
152
|
+
**Evidence:** [grep result showing the connection exists]
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Summary
|
|
156
|
+
|
|
157
|
+
```markdown
|
|
158
|
+
## Verification Summary
|
|
159
|
+
|
|
160
|
+
**Score:** [N] / [M] must_haves verified
|
|
161
|
+
**Status:** passed | gaps_found | human_needed
|
|
162
|
+
|
|
163
|
+
### Gaps (if any)
|
|
164
|
+
1. [must_have]: [what failed] -- [suggested fix]
|
|
165
|
+
|
|
166
|
+
### Human Verification Required (if any)
|
|
167
|
+
1. [item]: [what needs human check] -- [instructions for user]
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Output Marker
|
|
171
|
+
|
|
172
|
+
When verification is complete, output:
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
## VERIFICATION COMPLETE
|
|
176
|
+
|
|
177
|
+
**Score:** [N]/[M]
|
|
178
|
+
**Status:** [passed | gaps_found | human_needed]
|
|
179
|
+
**Gaps:** [count of failed must_haves, or "none"]
|
|
180
|
+
**Human items:** [count of items needing human verification, or "none"]
|
|
181
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brain:adr
|
|
3
|
+
description: Manage Architecture Decision Records
|
|
4
|
+
argument-hint: "create|list|search [args]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Write
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Bash
|
|
11
|
+
- AskUserQuestion
|
|
12
|
+
---
|
|
13
|
+
<objective>
|
|
14
|
+
Manage Architecture Decision Records (ADRs) stored in .brain/adrs/.
|
|
15
|
+
Supports creating new ADRs, listing existing ones, and searching decision history.
|
|
16
|
+
</objective>
|
|
17
|
+
|
|
18
|
+
<context>
|
|
19
|
+
`$ARGUMENTS` contains a subcommand and optional args:
|
|
20
|
+
- `create` — Create a new ADR with guided prompts
|
|
21
|
+
- `list` — List all existing ADRs with status (proposed, accepted, deprecated)
|
|
22
|
+
- `search <query>` — Search ADRs by keyword or tag
|
|
23
|
+
</context>
|
|
24
|
+
|
|
25
|
+
<process>
|
|
26
|
+
1. Run the brain CLI to manage ADRs:
|
|
27
|
+
```bash
|
|
28
|
+
npx brain-dev adr $ARGUMENTS
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
2. For `create`: the CLI guides through a structured template. Use AskUserQuestion if additional context is needed from the user.
|
|
32
|
+
|
|
33
|
+
3. For `list` or `search`: present the results in a readable format showing ADR number, title, and status.
|
|
34
|
+
</process>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brain:complete
|
|
3
|
+
description: Archive milestone and tag release
|
|
4
|
+
argument-hint: "[--audit-only] [--force]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Write
|
|
8
|
+
- Edit
|
|
9
|
+
- Glob
|
|
10
|
+
- Grep
|
|
11
|
+
- Bash
|
|
12
|
+
- Task
|
|
13
|
+
- AskUserQuestion
|
|
14
|
+
---
|
|
15
|
+
<objective>
|
|
16
|
+
Archive the current milestone, run a completion audit, generate release notes, and create a git tag.
|
|
17
|
+
Ensures all phases are verified before completing.
|
|
18
|
+
</objective>
|
|
19
|
+
|
|
20
|
+
<context>
|
|
21
|
+
`$ARGUMENTS` contains optional flags:
|
|
22
|
+
- `--audit-only` — Run the completion audit without archiving or tagging
|
|
23
|
+
- `--force` — Force completion even if some verifications are pending
|
|
24
|
+
</context>
|
|
25
|
+
|
|
26
|
+
<process>
|
|
27
|
+
1. Run the brain CLI to complete the milestone:
|
|
28
|
+
```bash
|
|
29
|
+
npx brain-dev complete $ARGUMENTS
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
2. The CLI audits all phases, archives the milestone, generates release notes, and creates a git tag. It blocks if any phases have unresolved failures unless `--force` is used.
|
|
33
|
+
|
|
34
|
+
3. Review the audit results and release notes. Confirm the git tag was created.
|
|
35
|
+
|
|
36
|
+
4. **Next step:** Run `/brain:new-project` to start the next milestone.
|
|
37
|
+
</process>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brain:config
|
|
3
|
+
description: Configure brain settings
|
|
4
|
+
argument-hint: "[set|get|list|reset|docs|export|import] [--global]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Write
|
|
8
|
+
- Bash
|
|
9
|
+
- AskUserQuestion
|
|
10
|
+
---
|
|
11
|
+
<objective>
|
|
12
|
+
Configure brain settings at project or global level. Manage configuration values, export/import settings, and view documentation for available options.
|
|
13
|
+
When no subcommand is given, launches an interactive menu.
|
|
14
|
+
</objective>
|
|
15
|
+
|
|
16
|
+
<context>
|
|
17
|
+
`$ARGUMENTS` contains an optional subcommand and flags:
|
|
18
|
+
- `set <key> <value>` — Set a configuration value
|
|
19
|
+
- `get <key>` — Get a configuration value
|
|
20
|
+
- `list` — List all configuration values
|
|
21
|
+
- `reset` — Reset configuration to defaults
|
|
22
|
+
- `docs` — Show configuration documentation
|
|
23
|
+
- `export` — Export configuration to file
|
|
24
|
+
- `import <file>` — Import configuration from file
|
|
25
|
+
- `--global` — Apply to global config instead of project config
|
|
26
|
+
</context>
|
|
27
|
+
|
|
28
|
+
<process>
|
|
29
|
+
1. Run the brain CLI to manage configuration:
|
|
30
|
+
```bash
|
|
31
|
+
npx brain-dev config $ARGUMENTS
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
2. If no subcommand was given, the CLI shows an interactive menu. Follow the prompts.
|
|
35
|
+
|
|
36
|
+
3. For `set`/`reset`: confirm the change was applied and validated against the schema. For `list`/`get`/`docs`: present the output to the user.
|
|
37
|
+
</process>
|