@girardmedia/bootspring 2.1.1 → 2.1.3

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 CHANGED
@@ -1229,6 +1229,83 @@ ${c.bold}Next steps:${c.reset}
1229
1229
  `);
1230
1230
  }
1231
1231
 
1232
+ /**
1233
+ * Extract non-task supplementary content from TASK_QUEUE.md.
1234
+ * Captures context notes, architecture diagrams, integration guidelines,
1235
+ * and any section that isn't the task table or per-task detail blocks.
1236
+ */
1237
+ function extractSupplementaryContent(queueContent) {
1238
+ const lines = queueContent.split('\n');
1239
+ const sections = [];
1240
+ let currentSection = null;
1241
+ let inTaskTable = false;
1242
+ let inTaskDetail = false;
1243
+
1244
+ for (let i = 0; i < lines.length; i++) {
1245
+ const line = lines[i];
1246
+
1247
+ // Detect task table (starts with | Position | or | # |)
1248
+ if (/^\|\s*(Position|#)\s*\|/.test(line)) {
1249
+ inTaskTable = true;
1250
+ continue;
1251
+ }
1252
+ // Still in task table (rows starting with |)
1253
+ if (inTaskTable && /^\|/.test(line)) {
1254
+ continue;
1255
+ }
1256
+ if (inTaskTable && !/^\|/.test(line)) {
1257
+ inTaskTable = false;
1258
+ }
1259
+
1260
+ // Detect per-task detail blocks (### task-XXX: or ### bs-XXX:)
1261
+ if (/^###\s+(task-\d+|bs-\d+)\s*:/.test(line)) {
1262
+ inTaskDetail = true;
1263
+ continue;
1264
+ }
1265
+ // End task detail at next ### or ## heading
1266
+ if (inTaskDetail && /^#{2,3}\s+/.test(line) && !/^###\s+(task-\d+|bs-\d+)\s*:/.test(line)) {
1267
+ inTaskDetail = false;
1268
+ }
1269
+ if (inTaskDetail) continue;
1270
+
1271
+ // Skip the header, queue status heading, and generated boilerplate
1272
+ if (/^#\s+.*Implementation Queue/.test(line)) continue;
1273
+ if (/^>\s*(Ordered task queue|Last Updated|Current Version)/.test(line)) continue;
1274
+ if (/^## Queue Status/.test(line)) { inTaskTable = true; continue; }
1275
+ if (/^## Task Details/.test(line)) { inTaskDetail = true; continue; }
1276
+ if (/^\*Generated by/.test(line)) continue;
1277
+ if (/^---$/.test(line.trim())) continue;
1278
+
1279
+ // Detect section headings for supplementary content
1280
+ if (/^##\s+/.test(line) && !/^## (Queue Status|Task Details|Execution Guidelines)/.test(line)) {
1281
+ if (currentSection) sections.push(currentSection);
1282
+ currentSection = { heading: line, lines: [] };
1283
+ continue;
1284
+ }
1285
+
1286
+ // Execution Guidelines is useful — keep it
1287
+ if (/^## Execution Guidelines/.test(line)) {
1288
+ if (currentSection) sections.push(currentSection);
1289
+ currentSection = { heading: line, lines: [] };
1290
+ continue;
1291
+ }
1292
+
1293
+ if (currentSection) {
1294
+ currentSection.lines.push(line);
1295
+ }
1296
+ }
1297
+
1298
+ if (currentSection) sections.push(currentSection);
1299
+
1300
+ // Filter out empty sections and build output
1301
+ const output = sections
1302
+ .filter(s => s.lines.some(l => l.trim().length > 0))
1303
+ .map(s => `${s.heading}\n\n${s.lines.join('\n').trim()}`)
1304
+ .join('\n\n---\n\n');
1305
+
1306
+ return output.trim();
1307
+ }
1308
+
1232
1309
  /**
1233
1310
  * Migrate from TASK_QUEUE.md to TODO.md as single source of truth.
1234
1311
  */
@@ -1266,17 +1343,33 @@ ${c.cyan}${c.bold}Migrating to TODO.md as Single Source of Truth${c.reset}
1266
1343
  }
1267
1344
  }
1268
1345
 
1269
- // Step 2: Generate enriched TODO.md with full acceptance criteria
1346
+ // Step 2: Extract non-task content from TASK_QUEUE.md (context notes, diagrams, guidelines)
1347
+ let supplementaryContent = '';
1348
+ if (fs.existsSync(queuePath)) {
1349
+ const queueContent = fs.readFileSync(queuePath, 'utf-8');
1350
+ supplementaryContent = extractSupplementaryContent(queueContent);
1351
+ }
1352
+
1353
+ // Step 3: Generate enriched TODO.md with full task metadata
1270
1354
  const planningTemplate = require('../generators/templates/build-planning.template');
1271
- const todo = planningTemplate.generateTodo(state.implementationQueue, {
1355
+ let todo = planningTemplate.generateTodo(state.implementationQueue, {
1272
1356
  projectName: state.projectName
1273
1357
  });
1358
+
1359
+ // Append supplementary content if any was extracted
1360
+ if (supplementaryContent) {
1361
+ todo += `\n---\n\n## Reference (from TASK_QUEUE.md)\n\n${supplementaryContent}\n`;
1362
+ }
1363
+
1274
1364
  fs.writeFileSync(todoPath, todo);
1275
1365
 
1276
1366
  const stats = buildState.getStats(projectRoot);
1277
1367
  console.log(`${c.green}✓${c.reset} Generated TODO.md with ${state.implementationQueue.length} tasks (${stats?.completed || 0} completed)`);
1368
+ if (supplementaryContent) {
1369
+ console.log(`${c.green}✓${c.reset} Preserved supplementary content (context notes, diagrams, guidelines)`);
1370
+ }
1278
1371
 
1279
- // Step 3: Archive TASK_QUEUE.md unless --keep-queue
1372
+ // Step 4: Archive TASK_QUEUE.md unless --keep-queue
1280
1373
  if (fs.existsSync(queuePath) && !keepQueue) {
1281
1374
  const archivePath = path.join(planningDir, 'TASK_QUEUE.md.bak');
1282
1375
  fs.renameSync(queuePath, archivePath);
@@ -1290,7 +1383,8 @@ ${c.green}${c.bold}Migration complete${c.reset}
1290
1383
 
1291
1384
  ${c.bold}What changed:${c.reset}
1292
1385
  - ${c.cyan}planning/TODO.md${c.reset} is now the single source of truth
1293
- - Task IDs, acceptance criteria, and status are all inline
1386
+ - Task IDs, source, description, acceptance criteria, and status are all inline
1387
+ - Non-task content (context notes, diagrams, guidelines) preserved in Reference section
1294
1388
  - Build loop reads TODO.md instead of TASK_QUEUE.md
1295
1389
  ${!keepQueue && fs.existsSync(path.join(planningDir, 'TASK_QUEUE.md.bak')) ? ` - Old TASK_QUEUE.md archived as TASK_QUEUE.md.bak
1296
1390
  ` : ''}
@@ -288,7 +288,28 @@ function generateTodo(tasks, options = {}) {
288
288
  task.status === 'skipped' ? ' (`skipped`)' : '';
289
289
  content += `- ${checkbox} \`${task.id}\` ${task.title}${statusTag}\n`;
290
290
 
291
- // Add acceptance criteria as sub-items (all of them — this is the source of truth)
291
+ // Source traceability
292
+ if (task.source) {
293
+ const sourceStr = task.sourceSection
294
+ ? `${task.source} (${task.sourceSection})`
295
+ : task.source;
296
+ content += ` - **Source:** ${sourceStr}\n`;
297
+ }
298
+
299
+ // Description
300
+ if (task.description) {
301
+ content += ` - **Description:** ${task.description}\n`;
302
+ }
303
+
304
+ // Complexity and dependencies
305
+ if (task.estimatedComplexity && task.estimatedComplexity !== 'medium') {
306
+ content += ` - **Complexity:** ${task.estimatedComplexity}\n`;
307
+ }
308
+ if (task.dependencies && task.dependencies.length > 0) {
309
+ content += ` - **Dependencies:** ${task.dependencies.join(', ')}\n`;
310
+ }
311
+
312
+ // Acceptance criteria as sub-items (all of them — this is the source of truth)
292
313
  if (task.acceptanceCriteria && task.acceptanceCriteria.length > 0) {
293
314
  for (const criteria of task.acceptanceCriteria) {
294
315
  const subCheckbox = task.status === 'completed' ? '[x]' : '[ ]';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@girardmedia/bootspring",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "Thin client for Bootspring cloud MCP, hosted agents, and paywalled workflow intelligence",
5
5
  "keywords": [
6
6
  "ai",