@girardmedia/bootspring 2.0.13 → 2.0.14
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/cli/build.js +9 -73
- package/generators/templates/agents.template.js +5 -5
- package/generators/templates/build-planning.template.js +11 -11
- package/generators/templates/claude.template.js +11 -12
- package/mcp/contracts/mcp-contract.v1.json +1 -1
- package/mcp/tools/build-tool.js +4 -67
- package/package.json +1 -1
package/cli/build.js
CHANGED
|
@@ -249,87 +249,26 @@ async function buildNextTask(projectRoot, _args = {}) {
|
|
|
249
249
|
|
|
250
250
|
if (!nextTask) {
|
|
251
251
|
console.log(`${c.green}All tasks complete!${c.reset}`);
|
|
252
|
-
clearCurrentTask(projectRoot);
|
|
253
252
|
return;
|
|
254
253
|
}
|
|
255
254
|
|
|
256
255
|
// Mark task as in progress
|
|
257
256
|
buildState.updateProgress(projectRoot, nextTask.id, 'in_progress');
|
|
258
257
|
|
|
259
|
-
// Generate the task prompt
|
|
260
|
-
const prompt = generateTaskPrompt(nextTask, projectRoot);
|
|
261
|
-
|
|
262
|
-
// Write to CURRENT_TASK.md for Claude Code to read
|
|
263
|
-
const taskFile = writeCurrentTask(projectRoot, nextTask, prompt);
|
|
264
|
-
|
|
265
258
|
console.log(`
|
|
266
|
-
${c.green}${c.bold}✓ Task
|
|
259
|
+
${c.green}${c.bold}✓ Task ${nextTask.id} now in progress${c.reset}
|
|
267
260
|
|
|
268
261
|
${c.bold}Task:${c.reset} ${nextTask.title}
|
|
269
|
-
${c.bold}
|
|
262
|
+
${c.bold}Phase:${c.reset} ${nextTask.phase || 'MVP'}
|
|
263
|
+
${c.bold}Source:${c.reset} ${nextTask.source || 'PRD.md'}
|
|
270
264
|
|
|
271
265
|
${c.cyan}${c.bold}Tell Claude Code:${c.reset}
|
|
272
|
-
"Read planning/
|
|
266
|
+
"Read planning/TASK_QUEUE.md, find ${nextTask.id}, and implement it"
|
|
273
267
|
|
|
274
|
-
${c.dim}
|
|
268
|
+
${c.dim}When done, run: bootspring build done${c.reset}
|
|
275
269
|
`);
|
|
276
270
|
}
|
|
277
271
|
|
|
278
|
-
/**
|
|
279
|
-
* Write current task to planning/CURRENT_TASK.md
|
|
280
|
-
*/
|
|
281
|
-
function writeCurrentTask(projectRoot, task, prompt) {
|
|
282
|
-
const planningDir = path.join(projectRoot, 'planning');
|
|
283
|
-
if (!fs.existsSync(planningDir)) {
|
|
284
|
-
fs.mkdirSync(planningDir, { recursive: true });
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
const taskFile = path.join(planningDir, 'CURRENT_TASK.md');
|
|
288
|
-
const content = `# Current Task
|
|
289
|
-
|
|
290
|
-
> This file is auto-generated by bootspring. Claude Code should read this and implement the task.
|
|
291
|
-
|
|
292
|
-
---
|
|
293
|
-
|
|
294
|
-
## ${task.title}
|
|
295
|
-
|
|
296
|
-
${prompt}
|
|
297
|
-
|
|
298
|
-
---
|
|
299
|
-
|
|
300
|
-
## When Complete
|
|
301
|
-
|
|
302
|
-
Run this command to mark the task done and get the next task:
|
|
303
|
-
|
|
304
|
-
\`\`\`bash
|
|
305
|
-
bootspring build done
|
|
306
|
-
\`\`\`
|
|
307
|
-
|
|
308
|
-
Or to skip this task:
|
|
309
|
-
|
|
310
|
-
\`\`\`bash
|
|
311
|
-
bootspring build skip
|
|
312
|
-
\`\`\`
|
|
313
|
-
|
|
314
|
-
---
|
|
315
|
-
|
|
316
|
-
*Task ID: ${task.id}*
|
|
317
|
-
*Generated: ${new Date().toISOString()}*
|
|
318
|
-
`;
|
|
319
|
-
|
|
320
|
-
fs.writeFileSync(taskFile, content);
|
|
321
|
-
return taskFile;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
/**
|
|
325
|
-
* Clear the current task file
|
|
326
|
-
*/
|
|
327
|
-
function clearCurrentTask(projectRoot) {
|
|
328
|
-
const taskFile = path.join(projectRoot, 'planning', 'CURRENT_TASK.md');
|
|
329
|
-
if (fs.existsSync(taskFile)) {
|
|
330
|
-
fs.unlinkSync(taskFile);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
272
|
|
|
334
273
|
/**
|
|
335
274
|
* Generate a prompt for Claude Code to execute
|
|
@@ -400,19 +339,16 @@ async function markTaskDone(projectRoot, _args = {}) {
|
|
|
400
339
|
const nextTask = buildState.getNextTask(projectRoot);
|
|
401
340
|
|
|
402
341
|
if (nextTask) {
|
|
403
|
-
// Mark as in progress
|
|
342
|
+
// Mark as in progress
|
|
404
343
|
buildState.updateProgress(projectRoot, nextTask.id, 'in_progress');
|
|
405
|
-
const prompt = generateTaskPrompt(nextTask, projectRoot);
|
|
406
|
-
const taskFile = writeCurrentTask(projectRoot, nextTask, prompt);
|
|
407
344
|
|
|
408
345
|
console.log(`
|
|
409
|
-
${c.cyan}${c.bold}Next task
|
|
410
|
-
${c.dim}File: ${path.relative(projectRoot, taskFile)}${c.reset}
|
|
346
|
+
${c.cyan}${c.bold}Next task:${c.reset} ${nextTask.title} (${nextTask.id})
|
|
411
347
|
|
|
412
|
-
${c.bold}
|
|
348
|
+
${c.bold}Find task in:${c.reset} planning/TASK_QUEUE.md
|
|
349
|
+
${c.dim}When done, run: bootspring build done${c.reset}
|
|
413
350
|
`);
|
|
414
351
|
} else {
|
|
415
|
-
clearCurrentTask(projectRoot);
|
|
416
352
|
console.log(`
|
|
417
353
|
${c.green}${c.bold}🎉 All tasks complete!${c.reset}
|
|
418
354
|
|
|
@@ -46,7 +46,7 @@ function generate(config) {
|
|
|
46
46
|
sections.push('');
|
|
47
47
|
sections.push('This project uses Bootspring for autonomous task management.');
|
|
48
48
|
sections.push('');
|
|
49
|
-
sections.push('1. Check `planning/
|
|
49
|
+
sections.push('1. Check `planning/TASK_QUEUE.md` for the current task (status: in_progress)');
|
|
50
50
|
sections.push('2. Implement the task following acceptance criteria');
|
|
51
51
|
sections.push('3. Run quality checks');
|
|
52
52
|
sections.push('4. Commit changes');
|
|
@@ -129,7 +129,7 @@ function generatePlanningAgents(_config) {
|
|
|
129
129
|
|
|
130
130
|
sections.push('## Current Task');
|
|
131
131
|
sections.push('');
|
|
132
|
-
sections.push('
|
|
132
|
+
sections.push('Find the task with `status: in_progress` in `TASK_QUEUE.md`.');
|
|
133
133
|
sections.push('');
|
|
134
134
|
|
|
135
135
|
sections.push('## Commands');
|
|
@@ -145,16 +145,16 @@ function generatePlanningAgents(_config) {
|
|
|
145
145
|
sections.push('');
|
|
146
146
|
sections.push('| File | Purpose |');
|
|
147
147
|
sections.push('|------|---------|');
|
|
148
|
-
sections.push('| `
|
|
148
|
+
sections.push('| `TASK_QUEUE.md` | All tasks - find in_progress task |');
|
|
149
149
|
sections.push('| `TODO.md` | Full task checklist |');
|
|
150
150
|
sections.push('| `BUILD_STATE.json` | Build state (do not edit) |');
|
|
151
|
-
sections.push('| `
|
|
151
|
+
sections.push('| `TASK_QUEUE.md` | Ordered task queue |');
|
|
152
152
|
sections.push('| `CONTEXT.md` | Build context summary |');
|
|
153
153
|
sections.push('');
|
|
154
154
|
|
|
155
155
|
sections.push('## Workflow');
|
|
156
156
|
sections.push('');
|
|
157
|
-
sections.push('1.
|
|
157
|
+
sections.push('1. Find in_progress task in `TASK_QUEUE.md`');
|
|
158
158
|
sections.push('2. Implement in the main codebase (not here)');
|
|
159
159
|
sections.push('3. Ensure acceptance criteria met');
|
|
160
160
|
sections.push('4. Run `npm run lint && npm run test`');
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Generates planning artifacts for the autonomous build loop:
|
|
5
5
|
* - MASTER_PLAN.md - Vision + phases + progress tracker
|
|
6
6
|
* - TODO.md - Checkbox list by phase
|
|
7
|
-
* -
|
|
7
|
+
* - TASK_QUEUE.md - Ordered tasks with acceptance criteria
|
|
8
8
|
* - CONTEXT.md - Condensed context for AI iterations
|
|
9
9
|
*
|
|
10
10
|
* @package bootspring
|
|
@@ -44,9 +44,9 @@ function generateAll(projectRoot, docs, tasks, options = {}) {
|
|
|
44
44
|
fs.writeFileSync(todoPath, todo);
|
|
45
45
|
files.todo = todoPath;
|
|
46
46
|
|
|
47
|
-
// Generate
|
|
47
|
+
// Generate TASK_QUEUE.md
|
|
48
48
|
const queue = generateImplementationQueue(tasks, options);
|
|
49
|
-
const queuePath = path.join(planningDir, '
|
|
49
|
+
const queuePath = path.join(planningDir, 'TASK_QUEUE.md');
|
|
50
50
|
fs.writeFileSync(queuePath, queue);
|
|
51
51
|
files.implementationQueue = queuePath;
|
|
52
52
|
|
|
@@ -86,11 +86,11 @@ bootspring build status # View progress
|
|
|
86
86
|
|
|
87
87
|
## Current Task
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
Find the task with \`status: in_progress\` in \`TASK_QUEUE.md\`.
|
|
90
90
|
|
|
91
91
|
## Workflow
|
|
92
92
|
|
|
93
|
-
1.
|
|
93
|
+
1. Find in_progress task in \`TASK_QUEUE.md\`
|
|
94
94
|
2. Implement in the main codebase (not in this folder)
|
|
95
95
|
3. Ensure acceptance criteria are met
|
|
96
96
|
4. Run quality checks: \`npm run lint && npm run test\`
|
|
@@ -101,10 +101,10 @@ Read \`CURRENT_TASK.md\` for the task you should implement now.
|
|
|
101
101
|
|
|
102
102
|
| File | Purpose |
|
|
103
103
|
|------|---------|
|
|
104
|
-
| \`
|
|
104
|
+
| \`TASK_QUEUE.md\` | All tasks - find in_progress task |
|
|
105
105
|
| \`TODO.md\` | Full task checklist |
|
|
106
106
|
| \`BUILD_STATE.json\` | Build state (do not edit directly) |
|
|
107
|
-
| \`
|
|
107
|
+
| \`TASK_QUEUE.md\` | Ordered task queue |
|
|
108
108
|
| \`CONTEXT.md\` | Build context summary |
|
|
109
109
|
|
|
110
110
|
## Boundaries
|
|
@@ -301,10 +301,10 @@ function generateTodo(tasks, options = {}) {
|
|
|
301
301
|
}
|
|
302
302
|
|
|
303
303
|
/**
|
|
304
|
-
* Generate
|
|
304
|
+
* Generate TASK_QUEUE.md
|
|
305
305
|
* @param {array} tasks - Extracted tasks
|
|
306
306
|
* @param {object} options - Options
|
|
307
|
-
* @returns {string}
|
|
307
|
+
* @returns {string} TASK_QUEUE.md content
|
|
308
308
|
*/
|
|
309
309
|
function generateImplementationQueue(tasks, options = {}) {
|
|
310
310
|
const projectName = options.projectName || 'Project';
|
|
@@ -642,9 +642,9 @@ function updateFromState(projectRoot, state) {
|
|
|
642
642
|
const todo = generateTodo(tasks, { projectName: state.projectName });
|
|
643
643
|
fs.writeFileSync(path.join(planningDir, 'TODO.md'), todo);
|
|
644
644
|
|
|
645
|
-
// Regenerate
|
|
645
|
+
// Regenerate TASK_QUEUE.md
|
|
646
646
|
const queue = generateImplementationQueue(tasks, { projectName: state.projectName });
|
|
647
|
-
fs.writeFileSync(path.join(planningDir, '
|
|
647
|
+
fs.writeFileSync(path.join(planningDir, 'TASK_QUEUE.md'), queue);
|
|
648
648
|
}
|
|
649
649
|
|
|
650
650
|
module.exports = {
|
|
@@ -32,7 +32,7 @@ function generate(config) {
|
|
|
32
32
|
sections.push('');
|
|
33
33
|
sections.push('### Before Writing ANY Code');
|
|
34
34
|
sections.push('1. Read `planning/MASTER_PLAN.md` - Overall vision and phases');
|
|
35
|
-
sections.push('2. Read `planning/
|
|
35
|
+
sections.push('2. Read `planning/TASK_QUEUE.md` - Your specific task');
|
|
36
36
|
sections.push('3. Read `planning/CONTEXT.md` - Current build context');
|
|
37
37
|
sections.push('4. Understand the acceptance criteria before implementing');
|
|
38
38
|
sections.push('');
|
|
@@ -52,11 +52,10 @@ function generate(config) {
|
|
|
52
52
|
sections.push('| File | Purpose | When to Read |');
|
|
53
53
|
sections.push('|------|---------|--------------|');
|
|
54
54
|
sections.push('| `MASTER_PLAN.md` | Overall vision, phases, success criteria | **Always read first** |');
|
|
55
|
-
sections.push('| `
|
|
55
|
+
sections.push('| `TASK_QUEUE.md` | All tasks with acceptance criteria, find current task by status | **Before each task** |');
|
|
56
56
|
sections.push('| `CONTEXT.md` | Current build context and decisions | Before each task |');
|
|
57
|
-
sections.push('| `IMPLEMENTATION_QUEUE.md` | Ordered list of all tasks | To understand scope |');
|
|
58
57
|
sections.push('| `TODO.md` | Checkbox task list | Update after completing |');
|
|
59
|
-
sections.push('| `BUILD_STATE.json` | Machine state
|
|
58
|
+
sections.push('| `BUILD_STATE.json` | Machine state - shows current task ID | Reference only |');
|
|
60
59
|
sections.push('');
|
|
61
60
|
sections.push('---');
|
|
62
61
|
sections.push('');
|
|
@@ -219,15 +218,15 @@ function generate(config) {
|
|
|
219
218
|
sections.push('');
|
|
220
219
|
sections.push('```');
|
|
221
220
|
sections.push('┌─────────────────────────────────────────────────────────────┐');
|
|
222
|
-
sections.push('│ 1. READ
|
|
223
|
-
sections.push('│
|
|
221
|
+
sections.push('│ 1. READ planning/MASTER_PLAN.md │');
|
|
222
|
+
sections.push('│ planning/TASK_QUEUE.md (find in_progress task) │');
|
|
224
223
|
sections.push('│ ↓ │');
|
|
225
224
|
sections.push('│ 2. IMPLEMENT Write code to meet acceptance criteria │');
|
|
226
225
|
sections.push('│ ↓ │');
|
|
227
|
-
sections.push('│ 3.
|
|
228
|
-
sections.push('│
|
|
226
|
+
sections.push('│ 3. COMPLETE Run: bootspring build done │');
|
|
227
|
+
sections.push('│ (marks done, queues next task) │');
|
|
229
228
|
sections.push('│ ↓ │');
|
|
230
|
-
sections.push('│ 4. REPEAT
|
|
229
|
+
sections.push('│ 4. REPEAT Check TASK_QUEUE.md for next in_progress task │');
|
|
231
230
|
sections.push('└─────────────────────────────────────────────────────────────┘');
|
|
232
231
|
sections.push('```');
|
|
233
232
|
sections.push('');
|
|
@@ -236,8 +235,8 @@ function generate(config) {
|
|
|
236
235
|
sections.push('| Command | What it does |');
|
|
237
236
|
sections.push('|---------|--------------|');
|
|
238
237
|
sections.push('| `bootspring build` | Interactive menu |');
|
|
239
|
-
sections.push('| `bootspring build next` |
|
|
240
|
-
sections.push('| `bootspring build done` | Mark complete,
|
|
238
|
+
sections.push('| `bootspring build next` | Mark next task as in_progress |');
|
|
239
|
+
sections.push('| `bootspring build done` | Mark current complete, queue next |');
|
|
241
240
|
sections.push('| `bootspring build status` | View progress |');
|
|
242
241
|
sections.push('| `bootspring build skip` | Skip current task |');
|
|
243
242
|
sections.push('');
|
|
@@ -247,7 +246,7 @@ function generate(config) {
|
|
|
247
246
|
// Rules
|
|
248
247
|
sections.push('## Rules');
|
|
249
248
|
sections.push('');
|
|
250
|
-
sections.push('1. **Always read before coding** - No implementation without reading MASTER_PLAN.md and
|
|
249
|
+
sections.push('1. **Always read before coding** - No implementation without reading MASTER_PLAN.md and TASK_QUEUE.md');
|
|
251
250
|
sections.push('2. **Follow acceptance criteria exactly** - The task is not done until all criteria are met');
|
|
252
251
|
sections.push('3. **Update planning docs** - Check off TODO.md items, run `bootspring build done`');
|
|
253
252
|
sections.push('4. **One task at a time** - Complete current task before starting next');
|
package/mcp/tools/build-tool.js
CHANGED
|
@@ -271,9 +271,6 @@ function createHandler({ configModule }) {
|
|
|
271
271
|
// Mark as in progress
|
|
272
272
|
buildState.updateProgress(projectRoot, nextTask.id, 'in_progress');
|
|
273
273
|
|
|
274
|
-
// Write to CURRENT_TASK.md
|
|
275
|
-
writeCurrentTaskFile(projectRoot, nextTask);
|
|
276
|
-
|
|
277
274
|
return {
|
|
278
275
|
content: [{
|
|
279
276
|
type: 'text',
|
|
@@ -287,9 +284,9 @@ function createHandler({ configModule }) {
|
|
|
287
284
|
sourceSection: nextTask.sourceSection,
|
|
288
285
|
acceptanceCriteria: nextTask.acceptanceCriteria || []
|
|
289
286
|
},
|
|
290
|
-
file: 'planning/
|
|
287
|
+
file: 'planning/TASK_QUEUE.md',
|
|
291
288
|
instructions: [
|
|
292
|
-
|
|
289
|
+
`Find ${nextTask.id} in planning/TASK_QUEUE.md for full details`,
|
|
293
290
|
'Implement the task in the codebase',
|
|
294
291
|
'Ensure acceptance criteria are met',
|
|
295
292
|
'Run quality checks (lint, test)',
|
|
@@ -336,9 +333,6 @@ function createHandler({ configModule }) {
|
|
|
336
333
|
// Auto-queue next task
|
|
337
334
|
if (nextTask) {
|
|
338
335
|
buildState.updateProgress(projectRoot, nextTask.id, 'in_progress');
|
|
339
|
-
writeCurrentTaskFile(projectRoot, nextTask);
|
|
340
|
-
} else {
|
|
341
|
-
clearCurrentTaskFile(projectRoot);
|
|
342
336
|
}
|
|
343
337
|
|
|
344
338
|
return {
|
|
@@ -402,7 +396,6 @@ function createHandler({ configModule }) {
|
|
|
402
396
|
|
|
403
397
|
if (nextTask) {
|
|
404
398
|
buildState.updateProgress(projectRoot, nextTask.id, 'in_progress');
|
|
405
|
-
writeCurrentTaskFile(projectRoot, nextTask);
|
|
406
399
|
}
|
|
407
400
|
|
|
408
401
|
return {
|
|
@@ -417,7 +410,8 @@ function createHandler({ configModule }) {
|
|
|
417
410
|
nextTask: nextTask ? {
|
|
418
411
|
id: nextTask.id,
|
|
419
412
|
title: nextTask.title,
|
|
420
|
-
description: nextTask.description
|
|
413
|
+
description: nextTask.description,
|
|
414
|
+
file: 'planning/TASK_QUEUE.md'
|
|
421
415
|
} : null,
|
|
422
416
|
message: nextTask
|
|
423
417
|
? `Skipped. Next: ${nextTask.title}`
|
|
@@ -441,63 +435,6 @@ function createHandler({ configModule }) {
|
|
|
441
435
|
};
|
|
442
436
|
}
|
|
443
437
|
|
|
444
|
-
/**
|
|
445
|
-
* Write task to planning/CURRENT_TASK.md
|
|
446
|
-
*/
|
|
447
|
-
function writeCurrentTaskFile(projectRoot, task) {
|
|
448
|
-
const planningDir = path.join(projectRoot, 'planning');
|
|
449
|
-
if (!fs.existsSync(planningDir)) {
|
|
450
|
-
fs.mkdirSync(planningDir, { recursive: true });
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
const content = `# Current Task
|
|
454
|
-
|
|
455
|
-
> Auto-generated by bootspring. Implement this task.
|
|
456
|
-
|
|
457
|
-
---
|
|
458
|
-
|
|
459
|
-
## ${task.title}
|
|
460
|
-
|
|
461
|
-
${task.description || ''}
|
|
462
|
-
|
|
463
|
-
${task.acceptanceCriteria?.length ? `### Acceptance Criteria
|
|
464
|
-
|
|
465
|
-
${task.acceptanceCriteria.map(ac => `- [ ] ${ac}`).join('\n')}
|
|
466
|
-
` : ''}
|
|
467
|
-
|
|
468
|
-
### Source
|
|
469
|
-
|
|
470
|
-
${task.source}${task.sourceSection ? ` - ${task.sourceSection}` : ''}
|
|
471
|
-
|
|
472
|
-
---
|
|
473
|
-
|
|
474
|
-
## Instructions
|
|
475
|
-
|
|
476
|
-
1. Implement the task as described above
|
|
477
|
-
2. Ensure all acceptance criteria are met
|
|
478
|
-
3. Run quality checks (lint, test)
|
|
479
|
-
4. Commit your changes
|
|
480
|
-
5. Mark complete with: \`bootspring build done\` or MCP action=done
|
|
481
|
-
|
|
482
|
-
---
|
|
483
|
-
|
|
484
|
-
*Task ID: ${task.id}*
|
|
485
|
-
*Generated: ${new Date().toISOString()}*
|
|
486
|
-
`;
|
|
487
|
-
|
|
488
|
-
fs.writeFileSync(path.join(planningDir, 'CURRENT_TASK.md'), content);
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
/**
|
|
492
|
-
* Clear CURRENT_TASK.md
|
|
493
|
-
*/
|
|
494
|
-
function clearCurrentTaskFile(projectRoot) {
|
|
495
|
-
const taskFile = path.join(projectRoot, 'planning', 'CURRENT_TASK.md');
|
|
496
|
-
if (fs.existsSync(taskFile)) {
|
|
497
|
-
fs.unlinkSync(taskFile);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
|
|
501
438
|
module.exports = {
|
|
502
439
|
getToolDefinition,
|
|
503
440
|
createHandler
|
package/package.json
CHANGED