@vpxa/aikit 0.1.20 → 0.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/package.json +1 -1
  2. package/packages/core/dist/types.d.ts +2 -0
  3. package/packages/flows/dist/adapters/claude-plugin.js +1 -1
  4. package/packages/flows/dist/adapters/copilot.js +1 -1
  5. package/packages/flows/dist/builtins.js +1 -1
  6. package/packages/flows/dist/loader.js +1 -1
  7. package/packages/flows/dist/types.d.ts +2 -2
  8. package/packages/indexer/dist/smart-index-scheduler.d.ts +4 -1
  9. package/packages/indexer/dist/smart-index-scheduler.js +1 -1
  10. package/packages/server/dist/index.js +1 -1
  11. package/packages/server/dist/tool-metadata.js +1 -1
  12. package/packages/server/dist/tools/flow.tools.js +1 -1
  13. package/packages/store/dist/lance-store.d.ts +2 -0
  14. package/packages/store/dist/lance-store.js +1 -1
  15. package/scaffold/definitions/bodies.mjs +8 -8
  16. package/scaffold/definitions/plugins.mjs +92 -0
  17. package/scaffold/definitions/protocols.mjs +2 -2
  18. package/scaffold/flows/aikit-advanced/README.md +10 -10
  19. package/scaffold/flows/aikit-advanced/flow.json +6 -6
  20. package/scaffold/flows/aikit-advanced/{skills/design/SKILL.md → steps/design/README.md} +30 -0
  21. package/scaffold/flows/aikit-advanced/{skills/execute/SKILL.md → steps/execute/README.md} +19 -0
  22. package/scaffold/flows/aikit-advanced/{skills/plan/SKILL.md → steps/plan/README.md} +20 -0
  23. package/scaffold/flows/aikit-advanced/{skills/spec/SKILL.md → steps/spec/README.md} +19 -0
  24. package/scaffold/flows/aikit-advanced/{skills/task/SKILL.md → steps/task/README.md} +18 -0
  25. package/scaffold/flows/aikit-advanced/{skills/verify/SKILL.md → steps/verify/README.md} +21 -0
  26. package/scaffold/flows/aikit-basic/README.md +8 -8
  27. package/scaffold/flows/aikit-basic/flow.json +4 -4
  28. package/scaffold/flows/aikit-basic/{skills/assess/SKILL.md → steps/assess/README.md} +25 -0
  29. package/scaffold/flows/aikit-basic/{skills/design/SKILL.md → steps/design/README.md} +32 -0
  30. package/scaffold/flows/aikit-basic/{skills/implement/SKILL.md → steps/implement/README.md} +24 -0
  31. package/scaffold/flows/aikit-basic/{skills/verify/SKILL.md → steps/verify/README.md} +25 -0
  32. package/scaffold/general/agents/Orchestrator.agent.md +6 -6
  33. package/scaffold/general/agents/Planner.agent.md +2 -2
  34. package/scaffold/general/agents/_shared/code-agent-base.md +2 -2
  35. package/scaffold/general/skills/adr-skill/SKILL.md +6 -6
  36. package/scaffold/general/skills/aikit/SKILL.md +10 -10
  37. package/scaffold/general/skills/brainstorming/SKILL.md +11 -13
  38. package/scaffold/general/skills/c4-architecture/SKILL.md +1 -0
  39. package/scaffold/general/skills/requirements-clarity/SKILL.md +5 -3
  40. package/scaffold/general/skills/session-handoff/SKILL.md +2 -0
  41. package/scaffold/general/skills/brainstorming/scripts/frame-template.html +0 -365
  42. package/scaffold/general/skills/brainstorming/scripts/helper.js +0 -216
  43. package/scaffold/general/skills/brainstorming/scripts/server.cjs +0 -9
  44. package/scaffold/general/skills/brainstorming/scripts/server.src.cjs +0 -249
  45. package/scaffold/general/skills/brainstorming/visual-companion.md +0 -430
@@ -70,7 +70,7 @@ When invoked, detect vague requirements:
70
70
  1. Parse and understand core requirement
71
71
  2. Generate feature name (kebab-case format)
72
72
  3. Determine document version (default `1.0` unless user specifies otherwise)
73
- 4. Ensure `./docs/prds/` exists for PRD output
73
+ 4. Ensure `.spec/{feature_name}/` exists for PRD output
74
74
  5. Perform initial clarity assessment (0-100)
75
75
 
76
76
  **Assessment Rubric**:
@@ -85,6 +85,8 @@ Technical Specificity: /25 points
85
85
  - Integration points identified: 8 pts
86
86
  - Constraints specified: 9 pts
87
87
 
88
+
89
+ If you present this rubric or a requirements scorecard to the user, use `present({ format: 'html' })` to display a rich dashboard when visual formatting would help.
88
90
  Implementation Completeness: /25 points
89
91
  - Edge cases considered: 8 pts
90
92
  - Error handling mentioned: 9 pts
@@ -191,9 +193,9 @@ Once clarity score ≥ 90, generate comprehensive PRD.
191
193
 
192
194
  **Output File**:
193
195
 
194
- 1. **Final PRD**: `./docs/prds/{feature_name}-v{version}-prd.md`
196
+ 1. **Final PRD**: `.spec/{feature_name}/requirements.md`
195
197
 
196
- Use the `Write` tool to create or update this file. Derive `{version}` from the document version recorded in the PRD (default `1.0`).
198
+ Use `create_file` to save this file. Derive `{version}` from the document version recorded in the PRD (default `1.0`).
197
199
 
198
200
  ## PRD Document Structure
199
201
 
@@ -20,6 +20,8 @@ Determine which mode applies:
20
20
  **Proactive suggestion?** After substantial work (5+ file edits, complex debugging, major decisions), suggest:
21
21
  > "We've made significant progress. Consider creating a handoff document to preserve this context for future sessions. Say 'create handoff' when ready."
22
22
 
23
+ > **aikit Integration:** If the project uses the aikit MCP server, complement file-based handoffs with `remember({ title: "Session checkpoint: ...", content: "...", category: "conventions" })` to persist key decisions in the knowledge base. Use `search({ query: "SESSION CHECKPOINT" })` at session start to retrieve past checkpoints.
24
+
23
25
  ## CREATE Workflow
24
26
 
25
27
  ### Step 1: Generate Scaffold
@@ -1,365 +0,0 @@
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">
6
- <title>Brainstorming</title>
7
- <style>
8
- *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
9
-
10
- :root {
11
- --bg: #0d1117;
12
- --surface: #161b22;
13
- --border: #30363d;
14
- --text: #e6edf3;
15
- --text-muted: #8b949e;
16
- --accent: #58a6ff;
17
- --accent-glow: rgba(88, 166, 255, 0.15);
18
- --success: #3fb950;
19
- --radius: 8px;
20
- }
21
-
22
- body {
23
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
24
- background: var(--bg);
25
- color: var(--text);
26
- line-height: 1.6;
27
- min-height: 100vh;
28
- }
29
-
30
- .frame-header {
31
- padding: 16px 24px;
32
- border-bottom: 1px solid var(--border);
33
- display: flex;
34
- align-items: center;
35
- gap: 12px;
36
- }
37
- .frame-header .logo {
38
- font-size: 14px;
39
- font-weight: 600;
40
- color: var(--text-muted);
41
- letter-spacing: 0.5px;
42
- text-transform: uppercase;
43
- }
44
-
45
- .frame-content {
46
- max-width: 960px;
47
- margin: 0 auto;
48
- padding: 32px 24px;
49
- }
50
-
51
- /* Selection indicator bar */
52
- #selection-indicator {
53
- position: fixed;
54
- bottom: 0;
55
- left: 0;
56
- right: 0;
57
- background: var(--surface);
58
- border-top: 1px solid var(--border);
59
- padding: 12px 24px;
60
- display: none;
61
- align-items: center;
62
- justify-content: center;
63
- gap: 8px;
64
- font-size: 14px;
65
- color: var(--accent);
66
- z-index: 100;
67
- }
68
- #selection-indicator.visible { display: flex; }
69
- #selection-indicator .check { font-size: 18px; }
70
-
71
- /* Typography */
72
- h2 {
73
- font-size: 24px;
74
- font-weight: 600;
75
- margin-bottom: 8px;
76
- color: var(--text);
77
- }
78
- h3 {
79
- font-size: 18px;
80
- font-weight: 600;
81
- margin-bottom: 4px;
82
- color: var(--text);
83
- }
84
- h4 {
85
- font-size: 14px;
86
- font-weight: 600;
87
- margin-bottom: 8px;
88
- color: var(--text);
89
- }
90
- .subtitle {
91
- font-size: 16px;
92
- color: var(--text-muted);
93
- margin-bottom: 24px;
94
- }
95
- .section {
96
- margin-bottom: 32px;
97
- }
98
- .label {
99
- font-size: 11px;
100
- font-weight: 600;
101
- text-transform: uppercase;
102
- letter-spacing: 0.8px;
103
- color: var(--text-muted);
104
- margin-bottom: 8px;
105
- }
106
-
107
- /* Options (A/B/C choices) */
108
- .options {
109
- display: flex;
110
- flex-direction: column;
111
- gap: 12px;
112
- margin: 16px 0;
113
- }
114
- .option {
115
- display: flex;
116
- align-items: flex-start;
117
- gap: 16px;
118
- padding: 16px 20px;
119
- background: var(--surface);
120
- border: 2px solid var(--border);
121
- border-radius: var(--radius);
122
- cursor: pointer;
123
- transition: border-color 0.15s, background 0.15s;
124
- }
125
- .option:hover {
126
- border-color: var(--accent);
127
- background: var(--accent-glow);
128
- }
129
- .option.selected {
130
- border-color: var(--accent);
131
- background: var(--accent-glow);
132
- }
133
- .option .letter {
134
- flex-shrink: 0;
135
- width: 32px;
136
- height: 32px;
137
- display: flex;
138
- align-items: center;
139
- justify-content: center;
140
- border-radius: 50%;
141
- background: var(--border);
142
- font-weight: 700;
143
- font-size: 14px;
144
- color: var(--text-muted);
145
- transition: background 0.15s, color 0.15s;
146
- }
147
- .option.selected .letter {
148
- background: var(--accent);
149
- color: var(--bg);
150
- }
151
- .option .content { flex: 1; }
152
- .option .content p {
153
- color: var(--text-muted);
154
- font-size: 14px;
155
- margin-top: 4px;
156
- }
157
-
158
- /* Cards (visual designs) */
159
- .cards {
160
- display: grid;
161
- grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
162
- gap: 16px;
163
- margin: 16px 0;
164
- }
165
- .card {
166
- background: var(--surface);
167
- border: 2px solid var(--border);
168
- border-radius: var(--radius);
169
- overflow: hidden;
170
- cursor: pointer;
171
- transition: border-color 0.15s, transform 0.15s;
172
- }
173
- .card:hover {
174
- border-color: var(--accent);
175
- transform: translateY(-2px);
176
- }
177
- .card.selected {
178
- border-color: var(--accent);
179
- }
180
- .card-image {
181
- padding: 20px;
182
- background: rgba(255,255,255,0.02);
183
- min-height: 180px;
184
- display: flex;
185
- align-items: center;
186
- justify-content: center;
187
- }
188
- .card-body {
189
- padding: 16px;
190
- }
191
- .card-body p {
192
- color: var(--text-muted);
193
- font-size: 14px;
194
- margin-top: 4px;
195
- }
196
-
197
- /* Mockup container */
198
- .mockup {
199
- background: var(--surface);
200
- border: 1px solid var(--border);
201
- border-radius: var(--radius);
202
- overflow: hidden;
203
- margin: 16px 0;
204
- }
205
- .mockup-header {
206
- padding: 8px 16px;
207
- font-size: 12px;
208
- font-weight: 600;
209
- color: var(--text-muted);
210
- background: rgba(255,255,255,0.03);
211
- border-bottom: 1px solid var(--border);
212
- }
213
- .mockup-body {
214
- padding: 20px;
215
- }
216
-
217
- /* Split view */
218
- .split {
219
- display: grid;
220
- grid-template-columns: 1fr 1fr;
221
- gap: 16px;
222
- margin: 16px 0;
223
- }
224
- @media (max-width: 700px) {
225
- .split { grid-template-columns: 1fr; }
226
- }
227
-
228
- /* Pros/Cons */
229
- .pros-cons {
230
- display: grid;
231
- grid-template-columns: 1fr 1fr;
232
- gap: 16px;
233
- margin: 16px 0;
234
- }
235
- .pros, .cons {
236
- padding: 16px;
237
- border-radius: var(--radius);
238
- }
239
- .pros {
240
- background: rgba(63, 185, 80, 0.08);
241
- border: 1px solid rgba(63, 185, 80, 0.3);
242
- }
243
- .cons {
244
- background: rgba(248, 81, 73, 0.08);
245
- border: 1px solid rgba(248, 81, 73, 0.3);
246
- }
247
- .pros h4 { color: #3fb950; }
248
- .cons h4 { color: #f85149; }
249
- .pros-cons ul {
250
- list-style: none;
251
- padding: 0;
252
- }
253
- .pros-cons li {
254
- padding: 4px 0;
255
- font-size: 14px;
256
- color: var(--text-muted);
257
- }
258
- .pros-cons li::before {
259
- margin-right: 8px;
260
- font-weight: 600;
261
- }
262
- .pros li::before { content: '+'; color: #3fb950; }
263
- .cons li::before { content: '−'; color: #f85149; }
264
-
265
- /* Mock elements (wireframe building blocks) */
266
- .mock-nav {
267
- background: var(--surface);
268
- border: 1px solid var(--border);
269
- border-radius: var(--radius);
270
- padding: 12px 20px;
271
- font-size: 14px;
272
- color: var(--text-muted);
273
- margin-bottom: 12px;
274
- }
275
- .mock-sidebar {
276
- width: 200px;
277
- flex-shrink: 0;
278
- background: var(--surface);
279
- border: 1px solid var(--border);
280
- border-radius: var(--radius);
281
- padding: 16px;
282
- font-size: 13px;
283
- color: var(--text-muted);
284
- margin-right: 12px;
285
- }
286
- .mock-content {
287
- flex: 1;
288
- background: var(--surface);
289
- border: 1px solid var(--border);
290
- border-radius: var(--radius);
291
- padding: 20px;
292
- font-size: 14px;
293
- color: var(--text-muted);
294
- min-height: 200px;
295
- }
296
- .mock-button {
297
- padding: 8px 20px;
298
- background: var(--accent);
299
- color: var(--bg);
300
- border: none;
301
- border-radius: 6px;
302
- font-size: 14px;
303
- font-weight: 600;
304
- cursor: pointer;
305
- }
306
- .mock-button:hover { opacity: 0.9; }
307
- .mock-input {
308
- padding: 8px 12px;
309
- background: var(--surface);
310
- border: 1px solid var(--border);
311
- border-radius: 6px;
312
- color: var(--text);
313
- font-size: 14px;
314
- width: 100%;
315
- max-width: 300px;
316
- }
317
- .mock-input::placeholder { color: var(--text-muted); }
318
- .placeholder {
319
- background: rgba(255,255,255,0.03);
320
- border: 1px dashed var(--border);
321
- border-radius: var(--radius);
322
- padding: 40px 20px;
323
- text-align: center;
324
- color: var(--text-muted);
325
- font-size: 14px;
326
- }
327
-
328
- /* General list styling inside content */
329
- .frame-content ul, .frame-content ol {
330
- padding-left: 20px;
331
- margin: 8px 0;
332
- }
333
- .frame-content li {
334
- margin: 4px 0;
335
- color: var(--text-muted);
336
- font-size: 14px;
337
- }
338
- .frame-content p {
339
- margin: 8px 0;
340
- }
341
- .frame-content a {
342
- color: var(--accent);
343
- text-decoration: none;
344
- }
345
- .frame-content a:hover { text-decoration: underline; }
346
-
347
- </style>
348
- </head>
349
- <body>
350
- <div class="frame-header">
351
- <span class="logo">Brainstorming</span>
352
- </div>
353
- <div class="frame-content">
354
- <!-- CONTENT -->
355
- </div>
356
- <div id="selection-indicator">
357
- <span class="check">✓</span>
358
- <span id="selection-text">Selected</span>
359
- </div>
360
- <script>
361
- const BRAINSTORM_DIR = __BRAINSTORM_DIR__;
362
- <!-- HELPER_SCRIPT -->
363
- </script>
364
- </body>
365
- </html>
@@ -1,216 +0,0 @@
1
- /* helper.js — injected into every page served by the visual companion */
2
-
3
- (() => {
4
- let currentFile = null;
5
- let pollTimer = null;
6
-
7
- // --- Selection ---
8
-
9
- function toggleSelect(el) {
10
- const parent = el.closest('.options, .cards');
11
- const isMulti = parent?.hasAttribute('data-multiselect');
12
-
13
- if (!isMulti && parent) {
14
- for (const sib of parent.querySelectorAll('.selected')) {
15
- if (sib !== el) sib.classList.remove('selected');
16
- }
17
- }
18
-
19
- el.classList.toggle('selected');
20
- updateIndicator();
21
- postEvent(el);
22
- }
23
-
24
- function updateIndicator() {
25
- const selected = document.querySelectorAll('.selected');
26
- const bar = document.getElementById('selection-indicator');
27
- const text = document.getElementById('selection-text');
28
- if (!bar || !text) return;
29
-
30
- if (selected.length === 0) {
31
- bar.classList.remove('visible');
32
- return;
33
- }
34
-
35
- const labels = [];
36
- for (const el of selected) {
37
- const letter = el.querySelector('.letter');
38
- const heading = el.querySelector('h3, h4');
39
- labels.push(letter ? letter.textContent.trim() : heading ? heading.textContent.trim() : '?');
40
- }
41
- text.textContent = `Selected: ${labels.join(', ')}`;
42
- bar.classList.add('visible');
43
- }
44
-
45
- // --- Events ---
46
-
47
- function postEvent(el) {
48
- const letter = el.querySelector('.letter');
49
- const heading = el.querySelector('h3, h4');
50
-
51
- const data = {
52
- type: 'click',
53
- choice: letter ? letter.textContent.trim() : '',
54
- text: heading ? heading.textContent.trim() : el.textContent.trim().slice(0, 80),
55
- selected: el.classList.contains('selected'),
56
- timestamp: Date.now(),
57
- };
58
-
59
- fetch('/events', {
60
- method: 'POST',
61
- headers: { 'Content-Type': 'application/json' },
62
- body: JSON.stringify(data),
63
- }).catch(() => {
64
- /* server may have stopped */
65
- });
66
- }
67
-
68
- // --- Transport: WebSocket with polling fallback ---
69
-
70
- function startTransport() {
71
- if (!tryWebSocket()) {
72
- startPolling();
73
- }
74
- }
75
-
76
- function tryWebSocket() {
77
- const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
78
- const url = `${protocol}//${location.host}`;
79
- let ws;
80
- try {
81
- ws = new WebSocket(url);
82
- } catch (_e) {
83
- return false;
84
- }
85
-
86
- ws.onopen = () => {
87
- // Connected — stop polling if it was running
88
- if (pollTimer) {
89
- clearInterval(pollTimer);
90
- pollTimer = null;
91
- }
92
- };
93
-
94
- ws.onmessage = (e) => {
95
- try {
96
- const msg = JSON.parse(e.data);
97
- if (msg.type === 'new-file') {
98
- if (currentFile === null) {
99
- // First file arrived while showing "Waiting for content..." — reload
100
- currentFile = msg.name;
101
- location.reload();
102
- } else if (msg.name !== currentFile) {
103
- currentFile = msg.name;
104
- location.reload();
105
- }
106
- }
107
- // 'event' messages are echoes — browser doesn't need to act on them
108
- } catch (_err) {
109
- /* ignore malformed */
110
- }
111
- };
112
-
113
- ws.onclose = () => {
114
- // WebSocket lost — fall back to polling
115
- startPolling();
116
- };
117
-
118
- ws.onerror = () => {
119
- // Will trigger onclose → polling fallback
120
- };
121
-
122
- return true;
123
- }
124
-
125
- function startPolling() {
126
- if (pollTimer) return;
127
- pollTimer = setInterval(poll, 1500);
128
- }
129
-
130
- function poll() {
131
- fetch('/poll')
132
- .then((r) => (r.ok ? r.json() : null))
133
- .then((data) => {
134
- if (!data?.file) return;
135
- if (currentFile === null) {
136
- // First file arrived while showing "Waiting for content..." — reload
137
- currentFile = data.file;
138
- location.reload();
139
- return;
140
- }
141
- if (data.file !== currentFile) {
142
- currentFile = data.file;
143
- location.reload();
144
- }
145
- })
146
- .catch(() => {
147
- /* ignore */
148
- });
149
- }
150
-
151
- // --- Session state restoration ---
152
-
153
- function restoreSelections() {
154
- fetch('/state')
155
- .then((r) => (r.ok ? r.json() : null))
156
- .then((state) => {
157
- if (!state?.currentScreen || !state.selections) return;
158
- const screenSelections = state.selections[state.currentScreen];
159
- if (!screenSelections || screenSelections.length === 0) return;
160
-
161
- // Build a map of choice → selected
162
- const choiceMap = {};
163
- for (let i = 0; i < screenSelections.length; i++) {
164
- if (screenSelections[i].selected !== false) {
165
- choiceMap[screenSelections[i].choice] = true;
166
- }
167
- }
168
-
169
- // Apply to DOM
170
- const options = document.querySelectorAll('.option, .card');
171
- for (let j = 0; j < options.length; j++) {
172
- const letter = options[j].querySelector('.letter');
173
- const key = letter ? letter.textContent.trim() : '';
174
- if (choiceMap[key]) {
175
- options[j].classList.add('selected');
176
- }
177
- }
178
- updateIndicator();
179
- })
180
- .catch(() => {
181
- /* no state yet, that's fine */
182
- });
183
- }
184
-
185
- // --- Wire up ---
186
-
187
- function init() {
188
- // Attach click handlers to all options and cards
189
- document.addEventListener('click', (e) => {
190
- const option = e.target.closest('.option');
191
- if (option) {
192
- toggleSelect(option);
193
- return;
194
- }
195
-
196
- const card = e.target.closest('.card');
197
- if (card) {
198
- toggleSelect(card);
199
- return;
200
- }
201
- });
202
-
203
- updateIndicator();
204
- restoreSelections();
205
- startTransport();
206
- }
207
-
208
- // Expose for inline onclick if needed
209
- window.toggleSelect = toggleSelect;
210
-
211
- if (document.readyState === 'loading') {
212
- document.addEventListener('DOMContentLoaded', init);
213
- } else {
214
- init();
215
- }
216
- })();