strikethroo 3.6.1 → 3.8.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.
Files changed (95) hide show
  1. package/README.md +12 -12
  2. package/dist/index.js +1 -1
  3. package/dist/metadata.d.ts +1 -1
  4. package/dist/metadata.js +1 -1
  5. package/dist/serve/derivation.d.ts +1 -0
  6. package/dist/serve/derivation.d.ts.map +1 -1
  7. package/dist/serve/derivation.js +1 -0
  8. package/dist/serve/derivation.js.map +1 -1
  9. package/dist/serve/markdown.d.ts +1 -0
  10. package/dist/serve/markdown.d.ts.map +1 -1
  11. package/dist/serve/markdown.js +9 -0
  12. package/dist/serve/markdown.js.map +1 -1
  13. package/dist/skill-scripts/shared/root.js +1 -1
  14. package/dist-web/assets/{arc-iQlJHCCV.js → arc-ClZ3judi.js} +1 -1
  15. package/dist-web/assets/{architectureDiagram-3BPJPVTR-uN2KPcXw.js → architectureDiagram-3BPJPVTR-BRD031Y3.js} +1 -1
  16. package/dist-web/assets/{blockDiagram-GPEHLZMM-CMt6IBa8.js → blockDiagram-GPEHLZMM-CfaXqzcG.js} +1 -1
  17. package/dist-web/assets/{c4Diagram-AAUBKEIU-D-YKpLHn.js → c4Diagram-AAUBKEIU-D9Os_mjw.js} +1 -1
  18. package/dist-web/assets/channel-CJXJUs_u.js +1 -0
  19. package/dist-web/assets/{chunk-2J33WTMH-BQoe52nS.js → chunk-2J33WTMH-CScaCetR.js} +1 -1
  20. package/dist-web/assets/{chunk-4BX2VUAB--EBI_DNI.js → chunk-4BX2VUAB-C_0wTF2D.js} +1 -1
  21. package/dist-web/assets/{chunk-55IACEB6-DE1NbrfX.js → chunk-55IACEB6-BU0yxIXn.js} +1 -1
  22. package/dist-web/assets/{chunk-727SXJPM-BmknfrzD.js → chunk-727SXJPM-CEYPnfpF.js} +1 -1
  23. package/dist-web/assets/{chunk-AQP2D5EJ-DTyDzrvL.js → chunk-AQP2D5EJ-3Wp97XA5.js} +1 -1
  24. package/dist-web/assets/{chunk-FMBD7UC4-CQn7Uvih.js → chunk-FMBD7UC4-B_iff0-_.js} +1 -1
  25. package/dist-web/assets/{chunk-ND2GUHAM-CnykE_Kg.js → chunk-ND2GUHAM-C9bo0MIV.js} +1 -1
  26. package/dist-web/assets/{chunk-QZHKN3VN-Be2RyK2s.js → chunk-QZHKN3VN-DuWFBza0.js} +1 -1
  27. package/dist-web/assets/classDiagram-4FO5ZUOK-DSnAL-3H.js +1 -0
  28. package/dist-web/assets/classDiagram-v2-Q7XG4LA2-DSnAL-3H.js +1 -0
  29. package/dist-web/assets/{cose-bilkent-S5V4N54A-BXoChaJd.js → cose-bilkent-S5V4N54A-BvbHJ-Zg.js} +1 -1
  30. package/dist-web/assets/{dagre-BM42HDAG-CBhGTPWN.js → dagre-BM42HDAG-D6Et-JgF.js} +1 -1
  31. package/dist-web/assets/{diagram-2AECGRRQ-CQcPLW77.js → diagram-2AECGRRQ-CNCYsbbA.js} +1 -1
  32. package/dist-web/assets/{diagram-5GNKFQAL-BLq0ZS0T.js → diagram-5GNKFQAL-CxRozyyO.js} +1 -1
  33. package/dist-web/assets/{diagram-KO2AKTUF-D9his_br.js → diagram-KO2AKTUF-IZlLB90E.js} +1 -1
  34. package/dist-web/assets/{diagram-LMA3HP47-BWIqxk_u.js → diagram-LMA3HP47-CrSB8ihh.js} +1 -1
  35. package/dist-web/assets/{diagram-OG6HWLK6-CIg7m_j3.js → diagram-OG6HWLK6-tCjUSZwa.js} +1 -1
  36. package/dist-web/assets/{erDiagram-TEJ5UH35-Br8X9MlA.js → erDiagram-TEJ5UH35-JLv81E72.js} +1 -1
  37. package/dist-web/assets/{flowDiagram-I6XJVG4X-DqOFMENS.js → flowDiagram-I6XJVG4X-Det1_WLC.js} +1 -1
  38. package/dist-web/assets/{ganttDiagram-6RSMTGT7-BkmzGVBg.js → ganttDiagram-6RSMTGT7-Mi2wMw1v.js} +1 -1
  39. package/dist-web/assets/{gitGraphDiagram-PVQCEYII-CToioniK.js → gitGraphDiagram-PVQCEYII-Ddy55D8B.js} +1 -1
  40. package/dist-web/assets/{index-BGNxA4ex.js → index-BwABcoi9.js} +4 -4
  41. package/dist-web/assets/{index-XPUk9J7W.js → index-CEoxzYhV.js} +1 -1
  42. package/dist-web/assets/{index-BsWEFMQm.js → index-Dw0N6U6b.js} +1 -1
  43. package/dist-web/assets/{infoDiagram-5YYISTIA-B9SLu6Hy.js → infoDiagram-5YYISTIA-vrktGk5U.js} +1 -1
  44. package/dist-web/assets/{ishikawaDiagram-YF4QCWOH-wfIRoX5r.js → ishikawaDiagram-YF4QCWOH-CATnDGrp.js} +1 -1
  45. package/dist-web/assets/{journeyDiagram-JHISSGLW-D7E0q8bZ.js → journeyDiagram-JHISSGLW-CEvYFLj2.js} +1 -1
  46. package/dist-web/assets/{kanban-definition-UN3LZRKU--2Grx1qD.js → kanban-definition-UN3LZRKU-_6lp0n4D.js} +1 -1
  47. package/dist-web/assets/{linear-CmD0Yf7Q.js → linear-C1oEZdKm.js} +1 -1
  48. package/dist-web/assets/{mermaid.core-DvU5X9vY.js → mermaid.core-bqVxqCbb.js} +4 -4
  49. package/dist-web/assets/{mindmap-definition-RKZ34NQL-RS1L2Img.js → mindmap-definition-RKZ34NQL-DxAus_u1.js} +1 -1
  50. package/dist-web/assets/{pieDiagram-4H26LBE5-CSmQKvDq.js → pieDiagram-4H26LBE5-Bqjkt8dx.js} +1 -1
  51. package/dist-web/assets/{quadrantDiagram-W4KKPZXB-C_YvL19n.js → quadrantDiagram-W4KKPZXB-BoZHhSII.js} +1 -1
  52. package/dist-web/assets/{requirementDiagram-4Y6WPE33-CjM6rNTE.js → requirementDiagram-4Y6WPE33-D0rcLxmM.js} +1 -1
  53. package/dist-web/assets/{sankeyDiagram-5OEKKPKP-Dxdcp2GO.js → sankeyDiagram-5OEKKPKP-CWShHxDe.js} +1 -1
  54. package/dist-web/assets/{sequenceDiagram-3UESZ5HK-Bn7dy-8J.js → sequenceDiagram-3UESZ5HK-T8LE2GTr.js} +1 -1
  55. package/dist-web/assets/{stateDiagram-AJRCARHV-BvGqGTH2.js → stateDiagram-AJRCARHV-a8e0ie70.js} +1 -1
  56. package/dist-web/assets/stateDiagram-v2-BHNVJYJU-BmYjmWHJ.js +1 -0
  57. package/dist-web/assets/{timeline-definition-PNZ67QCA-BFzgWjlB.js → timeline-definition-PNZ67QCA-Fn2xKeuG.js} +1 -1
  58. package/dist-web/assets/{vennDiagram-CIIHVFJN-3vMaDLQj.js → vennDiagram-CIIHVFJN-CdlvIB8X.js} +1 -1
  59. package/dist-web/assets/{wardley-L42UT6IY-kCHOjqxR.js → wardley-L42UT6IY-9pciD2XX.js} +1 -1
  60. package/dist-web/assets/{wardleyDiagram-YWT4CUSO-X6ZFLRwo.js → wardleyDiagram-YWT4CUSO-BK6qNOxa.js} +1 -1
  61. package/dist-web/assets/{xychartDiagram-2RQKCTM6-Ddsjg-Qs.js → xychartDiagram-2RQKCTM6-QjMTFvse.js} +1 -1
  62. package/dist-web/index.html +1 -1
  63. package/package.json +1 -1
  64. package/templates/harness/skills/st-create-plan/scripts/find-strikethroo-root.cjs +1 -1
  65. package/templates/harness/skills/st-create-plan/scripts/get-next-plan-id.cjs +1 -1
  66. package/templates/harness/skills/st-execute-blueprint/SKILL.md +5 -3
  67. package/templates/harness/skills/st-execute-blueprint/scripts/check-phase-readiness.cjs +471 -0
  68. package/templates/harness/skills/st-execute-blueprint/scripts/create-feature-branch.cjs +17 -9
  69. package/templates/harness/skills/st-execute-blueprint/scripts/find-strikethroo-root.cjs +1 -1
  70. package/templates/harness/skills/st-execute-blueprint/scripts/validate-plan-blueprint.cjs +51 -3
  71. package/templates/harness/skills/st-execute-task/scripts/check-task-dependencies.cjs +114 -72
  72. package/templates/harness/skills/st-execute-task/scripts/find-strikethroo-root.cjs +1 -1
  73. package/templates/harness/skills/st-execute-task/scripts/validate-plan-blueprint.cjs +51 -3
  74. package/templates/harness/skills/st-full-workflow/SKILL.md +60 -12
  75. package/templates/harness/skills/st-full-workflow/scripts/check-phase-readiness.cjs +471 -0
  76. package/templates/harness/skills/st-full-workflow/scripts/create-feature-branch.cjs +17 -9
  77. package/templates/harness/skills/st-full-workflow/scripts/find-strikethroo-root.cjs +1 -1
  78. package/templates/harness/skills/st-full-workflow/scripts/get-next-plan-id.cjs +1 -1
  79. package/templates/harness/skills/st-full-workflow/scripts/get-next-task-id.cjs +1 -1
  80. package/templates/harness/skills/st-full-workflow/scripts/validate-plan-blueprint.cjs +51 -3
  81. package/templates/harness/skills/st-generate-tasks/SKILL.md +56 -11
  82. package/templates/harness/skills/st-generate-tasks/scripts/find-strikethroo-root.cjs +1 -1
  83. package/templates/harness/skills/st-generate-tasks/scripts/get-next-task-id.cjs +1 -1
  84. package/templates/harness/skills/st-generate-tasks/scripts/validate-plan-blueprint.cjs +51 -3
  85. package/templates/harness/skills/st-refine-plan/scripts/find-strikethroo-root.cjs +1 -1
  86. package/templates/harness/skills/st-refine-plan/scripts/validate-plan-blueprint.cjs +51 -3
  87. package/templates/strikethroo/README.md +1 -1
  88. package/templates/strikethroo/config/hooks/POST_PHASE.md +5 -4
  89. package/templates/strikethroo/config/hooks/POST_TASK_GENERATION_ALL.md +3 -13
  90. package/templates/strikethroo/config/hooks/PRE_PHASE.md +0 -13
  91. package/templates/strikethroo/config/templates/TASK_TEMPLATE.md +1 -0
  92. package/dist-web/assets/channel-CUiY3Crj.js +0 -1
  93. package/dist-web/assets/classDiagram-4FO5ZUOK-Btt3eQId.js +0 -1
  94. package/dist-web/assets/classDiagram-v2-Q7XG4LA2-Btt3eQId.js +0 -1
  95. package/dist-web/assets/stateDiagram-v2-BHNVJYJU-CQGQryEj.js +0 -1
@@ -33,8 +33,8 @@ __export(check_task_dependencies_exports, {
33
33
  _main: () => _main
34
34
  });
35
35
  module.exports = __toCommonJS(check_task_dependencies_exports);
36
- var fs4 = __toESM(require("fs"));
37
- var path4 = __toESM(require("path"));
36
+ var fs5 = __toESM(require("fs"));
37
+ var path5 = __toESM(require("path"));
38
38
 
39
39
  // src/skill-scripts/shared/plan-resolve.ts
40
40
  var fs3 = __toESM(require("fs"));
@@ -43,7 +43,7 @@ var path3 = __toESM(require("path"));
43
43
  // src/skill-scripts/shared/root.ts
44
44
  var fs = __toESM(require("fs"));
45
45
  var path = __toESM(require("path"));
46
- var EXPECTED_SCHEMA = true ? 2 : 2;
46
+ var EXPECTED_SCHEMA = true ? 3 : 3;
47
47
  var isValidStrikethrooRoot = (strikethrooPath) => {
48
48
  try {
49
49
  if (!fs.existsSync(strikethrooPath)) return false;
@@ -244,43 +244,31 @@ var resolvePlan = (input, startPath = process.cwd()) => {
244
244
  return resolveByIdInAncestry(planId, startPath);
245
245
  };
246
246
 
247
- // src/skill-scripts/check-task-dependencies.ts
248
- var _printError = (message) => {
249
- console.error(`ERROR: ${message}`);
250
- };
251
- var _printSuccess = (message) => {
252
- console.log(`\u2713 ${message}`);
253
- };
254
- var _printWarning = (message) => {
255
- console.log(`\u26A0 ${message}`);
256
- };
257
- var _printInfo = (message) => {
258
- console.log(message);
259
- };
260
- var _extractFrontmatter = (content) => {
247
+ // src/skill-scripts/shared/task-file.ts
248
+ var fs4 = __toESM(require("fs"));
249
+ var path4 = __toESM(require("path"));
250
+ var extractFrontmatter = (content) => {
261
251
  const match = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/);
262
252
  return match && match[1] ? match[1] : null;
263
253
  };
264
- var _findTaskFile = (planDir, taskId) => {
254
+ var findTaskFile = (planDir, taskId) => {
265
255
  const taskDir = path4.join(planDir, "tasks");
266
- if (!fs4.existsSync(taskDir)) {
267
- return null;
268
- }
269
- const variations = [taskId, taskId.padStart(2, "0"), taskId.replace(/^0+/, "") || "0"];
256
+ if (!fs4.existsSync(taskDir)) return null;
257
+ const idStr = String(taskId);
258
+ const variations = [idStr, idStr.padStart(2, "0"), idStr.replace(/^0+/, "") || "0"];
270
259
  const uniqueVariations = [...new Set(variations)];
271
260
  try {
272
261
  const files = fs4.readdirSync(taskDir);
273
- const found = uniqueVariations.reduce((acc, v) => {
262
+ return uniqueVariations.reduce((acc, v) => {
274
263
  if (acc) return acc;
275
264
  const match = files.find((f) => f.startsWith(`${v}--`) && f.endsWith(".md"));
276
265
  return match ? path4.join(taskDir, match) : null;
277
- }, null);
278
- return found;
266
+ }, null) ?? null;
279
267
  } catch (_err) {
280
268
  return null;
281
269
  }
282
270
  };
283
- var _extractDependencies = (frontmatter) => {
271
+ var extractDependencies = (frontmatter) => {
284
272
  const lines = frontmatter.split("\n");
285
273
  const dependencies = [];
286
274
  let inDependenciesSection = false;
@@ -300,22 +288,86 @@ var _extractDependencies = (frontmatter) => {
300
288
  }
301
289
  if (inDependenciesSection && line.match(/^[ \t]*-/)) {
302
290
  const dep = line.replace(/^[ \t]*-[ \t]*/, "").replace(/[ \t]*$/, "").replace(/['"]/g, "");
303
- if (dep.length > 0) {
304
- dependencies.push(dep);
305
- }
291
+ if (dep.length > 0) dependencies.push(dep);
306
292
  }
307
293
  }
308
294
  return dependencies;
309
295
  };
310
- var _extractStatus = (frontmatter) => {
311
- const lines = frontmatter.split("\n");
312
- for (const line of lines) {
296
+ var extractStatus = (frontmatter) => {
297
+ for (const line of frontmatter.split("\n")) {
313
298
  if (line.match(/^status:/)) {
314
299
  return line.replace(/^status:[ \t]*/, "").replace(/^["']/, "").replace(/["']$/, "").trim();
315
300
  }
316
301
  }
317
302
  return null;
318
303
  };
304
+ var collectTaskReadinessIssues = (planDir, taskId) => {
305
+ const issues = [];
306
+ const taskFile = findTaskFile(planDir, taskId);
307
+ const idLabel = String(taskId);
308
+ if (!taskFile || !fs4.existsSync(taskFile)) {
309
+ issues.push({ taskId: idLabel, kind: "missing", detail: "task file not found" });
310
+ return issues;
311
+ }
312
+ const taskContent = fs4.readFileSync(taskFile, "utf8");
313
+ const frontmatter = extractFrontmatter(taskContent);
314
+ if (!frontmatter) {
315
+ issues.push({ taskId: idLabel, kind: "missing", detail: "task frontmatter not found" });
316
+ return issues;
317
+ }
318
+ const status = extractStatus(frontmatter);
319
+ if (status === "needs-clarification") {
320
+ issues.push({
321
+ taskId: idLabel,
322
+ kind: "needs-clarification",
323
+ detail: "status is needs-clarification"
324
+ });
325
+ }
326
+ for (const depId of extractDependencies(frontmatter)) {
327
+ const depFile = findTaskFile(planDir, depId);
328
+ if (!depFile || !fs4.existsSync(depFile)) {
329
+ issues.push({
330
+ taskId: idLabel,
331
+ kind: "unresolved-dependency",
332
+ detail: `dependency ${depId} not found`
333
+ });
334
+ continue;
335
+ }
336
+ const depContent = fs4.readFileSync(depFile, "utf8");
337
+ const depFrontmatter = extractFrontmatter(depContent);
338
+ if (!depFrontmatter) {
339
+ issues.push({
340
+ taskId: idLabel,
341
+ kind: "unresolved-dependency",
342
+ detail: `dependency ${depId} has no frontmatter`
343
+ });
344
+ continue;
345
+ }
346
+ const depStatus = extractStatus(depFrontmatter);
347
+ if (depStatus !== "completed") {
348
+ issues.push({
349
+ taskId: idLabel,
350
+ kind: "unresolved-dependency",
351
+ detail: `dependency ${depId} status is ${depStatus ?? "unknown"}`
352
+ });
353
+ }
354
+ }
355
+ return issues;
356
+ };
357
+
358
+ // src/skill-scripts/check-task-dependencies.ts
359
+ var _printError = (message) => {
360
+ console.error(`ERROR: ${message}`);
361
+ };
362
+ var _printSuccess = (message) => {
363
+ console.log(`\u2713 ${message}`);
364
+ };
365
+ var _printWarning = (message) => {
366
+ console.log(`\u26A0 ${message}`);
367
+ };
368
+ var _printInfo = (message) => {
369
+ console.log(message);
370
+ };
319
371
  var _main = (startPath = process.cwd()) => {
320
372
  if (process.argv.length !== 4) {
321
373
  _printError("Invalid number of arguments");
@@ -336,20 +388,29 @@ var _main = (startPath = process.cwd()) => {
336
388
  }
337
389
  const { planDir, planId } = resolved;
338
390
  _printInfo(`Found plan directory: ${planDir}`);
339
- const taskFile = _findTaskFile(planDir, taskId);
340
- if (!taskFile || !fs4.existsSync(taskFile)) {
391
+ const taskFile = findTaskFile(planDir, taskId);
392
+ if (!taskFile) {
341
393
  _printError(`Task with ID ${taskId} not found in plan ${planId}`);
342
394
  process.exit(1);
343
395
  }
344
- _printInfo(`Checking task: ${path4.basename(taskFile)}`);
396
+ _printInfo(`Checking task: ${path5.basename(taskFile)}`);
345
397
  console.log("");
346
- const taskContent = fs4.readFileSync(taskFile, "utf8");
347
- const frontmatter = _extractFrontmatter(taskContent);
398
+ const issues = collectTaskReadinessIssues(planDir, taskId);
399
+ const dependencyIssues = issues.filter((issue) => issue.kind === "unresolved-dependency");
400
+ const blockingIssues = issues.filter((issue) => issue.kind !== "unresolved-dependency");
401
+ if (blockingIssues.length > 0) {
402
+ for (const issue of blockingIssues) {
403
+ _printError(issue.detail);
404
+ }
405
+ process.exit(1);
406
+ }
407
+ const taskContent = fs5.readFileSync(taskFile, "utf8");
408
+ const frontmatter = extractFrontmatter(taskContent);
348
409
  if (!frontmatter) {
349
410
  _printError("Could not extract frontmatter from task file");
350
411
  process.exit(1);
351
412
  }
352
- const dependencies = _extractDependencies(frontmatter);
413
+ const dependencies = extractDependencies(frontmatter);
353
414
  if (dependencies.length === 0) {
354
415
  _printSuccess("Task has no dependencies - ready to execute!");
355
416
  process.exit(0);
@@ -359,57 +420,38 @@ var _main = (startPath = process.cwd()) => {
359
420
  console.log(` - Task ${dep}`);
360
421
  });
361
422
  console.log("");
362
- let allResolved = true;
363
- const unresolvedDeps = [];
364
- let resolvedCount = 0;
365
- const totalDeps = dependencies.length;
366
423
  _printInfo("Checking dependency status...");
367
424
  console.log("");
425
+ let resolvedCount = 0;
368
426
  for (const depId of dependencies) {
369
- const depFile = _findTaskFile(planDir, depId);
370
- if (!depFile || !fs4.existsSync(depFile)) {
371
- _printError(`Dependency task ${depId} not found`);
372
- allResolved = false;
373
- unresolvedDeps.push(`${depId} (not found)`);
374
- continue;
375
- }
376
- const depContent = fs4.readFileSync(depFile, "utf8");
377
- const depFrontmatter = _extractFrontmatter(depContent);
378
- if (!depFrontmatter) {
379
- _printError(`Could not extract frontmatter from dependency task ${depId}`);
380
- allResolved = false;
381
- unresolvedDeps.push(`${depId} (no frontmatter)`);
382
- continue;
383
- }
384
- const status = _extractStatus(depFrontmatter);
385
- if (status === "completed") {
427
+ const depFile = findTaskFile(planDir, depId);
428
+ const depFrontmatter = depFile ? extractFrontmatter(fs5.readFileSync(depFile, "utf8")) : null;
429
+ const depStatus = depFrontmatter ? extractStatus(depFrontmatter) : null;
430
+ if (depStatus === "completed") {
386
431
  _printSuccess(`Task ${depId} - Status: completed \u2713`);
387
432
  resolvedCount++;
388
433
  } else {
389
- _printWarning(`Task ${depId} - Status: ${status || "unknown"} \u2717`);
390
- allResolved = false;
391
- unresolvedDeps.push(`${depId} (${status || "unknown"})`);
434
+ _printWarning(`Task ${depId} - Status: ${depStatus ?? "unknown"} \u2717`);
392
435
  }
393
436
  }
394
437
  console.log("");
395
438
  _printInfo("=========================================");
396
439
  _printInfo("Dependency Check Summary");
397
440
  _printInfo("=========================================");
398
- _printInfo(`Total dependencies: ${totalDeps}`);
441
+ _printInfo(`Total dependencies: ${dependencies.length}`);
399
442
  _printInfo(`Resolved: ${resolvedCount}`);
400
- _printInfo(`Unresolved: ${totalDeps - resolvedCount}`);
443
+ _printInfo(`Unresolved: ${dependencies.length - resolvedCount}`);
401
444
  console.log("");
402
- if (allResolved) {
445
+ if (dependencyIssues.length === 0) {
403
446
  _printSuccess(`All dependencies are resolved! Task ${taskId} is ready to execute.`);
404
447
  process.exit(0);
405
- } else {
406
- _printError(`Task ${taskId} has unresolved dependencies:`);
407
- unresolvedDeps.forEach((dep) => {
408
- console.log(dep);
409
- });
410
- _printInfo("Please complete the dependencies before executing this task.");
411
- process.exit(1);
412
448
  }
449
+ _printError(`Task ${taskId} has unresolved dependencies:`);
450
+ dependencyIssues.forEach((issue) => {
451
+ console.log(issue.detail);
452
+ });
453
+ _printInfo("Please complete the dependencies before executing this task.");
454
+ process.exit(1);
413
455
  };
414
456
  if (require.main === module) {
415
457
  _main();
@@ -37,7 +37,7 @@ module.exports = __toCommonJS(find_strikethroo_root_exports);
37
37
  // src/skill-scripts/shared/root.ts
38
38
  var fs = __toESM(require("fs"));
39
39
  var path = __toESM(require("path"));
40
- var EXPECTED_SCHEMA = true ? 2 : 2;
40
+ var EXPECTED_SCHEMA = true ? 3 : 3;
41
41
  var isValidStrikethrooRoot = (strikethrooPath) => {
42
42
  try {
43
43
  if (!fs.existsSync(strikethrooPath)) return false;
@@ -39,7 +39,7 @@ var path4 = __toESM(require("path"));
39
39
  // src/skill-scripts/shared/root.ts
40
40
  var fs = __toESM(require("fs"));
41
41
  var path = __toESM(require("path"));
42
- var EXPECTED_SCHEMA = true ? 2 : 2;
42
+ var EXPECTED_SCHEMA = true ? 3 : 3;
43
43
  var isValidStrikethrooRoot = (strikethrooPath) => {
44
44
  try {
45
45
  if (!fs.existsSync(strikethrooPath)) return false;
@@ -242,6 +242,12 @@ var resolvePlan = (input, startPath = process.cwd()) => {
242
242
  return resolveByIdInAncestry(planId, startPath);
243
243
  };
244
244
 
245
+ // src/skill-scripts/shared/task-file.ts
246
+ var extractFrontmatter = (content) => {
247
+ const match = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/);
248
+ return match && match[1] ? match[1] : null;
249
+ };
250
+
245
251
  // src/skill-scripts/validate-plan-blueprint.ts
246
252
  var VALID_FIELDS = [
247
253
  "planFile",
@@ -249,8 +255,47 @@ var VALID_FIELDS = [
249
255
  "taskCount",
250
256
  "blueprintExists",
251
257
  "strikethrooRoot",
252
- "planId"
258
+ "planId",
259
+ "complexityScoresValid",
260
+ "invalidComplexityTasks"
253
261
  ];
262
+ var validateComplexityScores = (planDir) => {
263
+ const tasksDir = path4.join(planDir, "tasks");
264
+ if (!fs4.existsSync(tasksDir)) return [];
265
+ let files;
266
+ try {
267
+ if (!fs4.lstatSync(tasksDir).isDirectory()) return [];
268
+ files = fs4.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).sort();
269
+ } catch (_err) {
270
+ return [];
271
+ }
272
+ const invalid = [];
273
+ for (const file of files) {
274
+ let content;
275
+ try {
276
+ content = fs4.readFileSync(path4.join(tasksDir, file), "utf8");
277
+ } catch (_err) {
278
+ invalid.push(`${file}: unreadable`);
279
+ continue;
280
+ }
281
+ const frontmatter = extractFrontmatter(content);
282
+ const match = frontmatter ? frontmatter.match(/^\s*complexity_score\s*:\s*(.*?)\s*(?:#.*)?$/im) : null;
283
+ if (!match || match[1] === void 0) {
284
+ invalid.push(`${file}: missing complexity_score`);
285
+ continue;
286
+ }
287
+ const raw = match[1].trim();
288
+ if (!/^\d+$/.test(raw)) {
289
+ invalid.push(`${file}: non-integer complexity_score "${raw}"`);
290
+ continue;
291
+ }
292
+ const parsed = Number.parseInt(raw, 10);
293
+ if (parsed < 1 || parsed > 10) {
294
+ invalid.push(`${file}: complexity_score ${parsed} out of range 1-10`);
295
+ }
296
+ }
297
+ return invalid;
298
+ };
254
299
  var countTasks = (planDir) => {
255
300
  const tasksDir = path4.join(planDir, "tasks");
256
301
  if (!fs4.existsSync(tasksDir)) return 0;
@@ -324,13 +369,16 @@ var main = () => {
324
369
  }
325
370
  process.exit(1);
326
371
  }
372
+ const invalidComplexity = validateComplexityScores(resolved.planDir);
327
373
  const result = {
328
374
  planFile: resolved.planFile,
329
375
  planDir: resolved.planDir,
330
376
  strikethrooRoot: resolved.strikethrooRoot,
331
377
  planId: resolved.planId,
332
378
  taskCount: countTasks(resolved.planDir),
333
- blueprintExists: checkBlueprintExists(resolved.planFile) ? "yes" : "no"
379
+ blueprintExists: checkBlueprintExists(resolved.planFile) ? "yes" : "no",
380
+ complexityScoresValid: invalidComplexity.length === 0 ? "yes" : "no",
381
+ invalidComplexityTasks: invalidComplexity.join("; ")
334
382
  };
335
383
  if (fieldName) {
336
384
  if (!VALID_FIELDS.includes(fieldName)) {
@@ -222,13 +222,48 @@ For each task, identify:
222
222
 
223
223
  A task B depends on A if B requires A's output or artifacts, modifies code created by A, or tests functionality implemented by A. Validate that the final dependency graph is acyclic.
224
224
 
225
- #### 7. Allocate task IDs
225
+ #### 7. Complexity analysis
226
+
227
+ For every candidate task, assign a `complexity_score` (integer 1–10) before
228
+ writing any file. Base the score on these four dimensions:
229
+
230
+ | Score | Skill breadth | Acceptance-criteria clarity | Integration surface | Decomposition depth |
231
+ | --- | --- | --- | --- | --- |
232
+ | 1–3 | One well-known skill | Criteria are concrete and observable | None or a single file/module | No further split possible |
233
+ | 4–5 | One primary skill plus a familiar adjacent skill | Criteria are clear with few edge cases | One component or API boundary | Already atomic |
234
+ | 6–7 | Two distinct skills, or one skill with ambiguous requirements | Criteria need clarification or have multiple edge cases | Multiple components or contracts | Could still be split |
235
+ | 8–10 | Three or more skills, or cross-cutting design decisions | Criteria are vague, unknown, or depend on unresolved choices | Wide integration surface or external systems | Must be decomposed further |
236
+
237
+ **Pre-emission sanity rules** — apply these before any task is written:
238
+
239
+ - 3+ skills assigned → split the task into smaller tasks, each with 1–2 skills.
240
+ - Vague acceptance criteria → sharpen them until they include at least one
241
+ concrete, runnable verification step.
242
+ - Trivially small adjacent tasks → merge them into a single task.
243
+ - Score ≥ 8 → decompose further; do not emit as-is.
244
+ - Score 6–7 → either sharpen criteria or split; do not emit without an
245
+ explicit reason.
246
+
247
+ **Required frontmatter:**
248
+
249
+ - Every emitted task MUST include `complexity_score` (integer 1–10).
250
+ - Optionally include `complexity_notes` when the score needs justification,
251
+ such as "Ambiguous API contract" or "Decomposed from a higher-score parent".
252
+
253
+ **Loop-back rule:**
254
+
255
+ After applying split, sharpen, or merge, re-run dependency analysis and
256
+ re-score the adjusted tasks. Repeat this loop no more than three times. If
257
+ complexity is still unresolved after three passes, stop and surface the
258
+ blocker to the user.
259
+
260
+ #### 8. Allocate task IDs
226
261
 
227
262
  Run `scripts/get-next-task-id.cjs <plan-id>` to obtain the first available task ID. Allocate subsequent IDs by incrementing in-process. Use the unpadded integer in the task frontmatter `id` field and the zero-padded form (`{padded-id}--{slug}`) for the filename.
228
263
 
229
264
  The slug derives from a short task title: lowercase, alphanumeric and hyphens only, collapsed, trimmed.
230
265
 
231
- #### 8. Emit the task files
266
+ #### 9. Emit the task files
232
267
 
233
268
  Write each task to:
234
269
 
@@ -246,11 +281,15 @@ including required frontmatter fields:
246
281
  - `created` (YYYY-MM-DD)
247
282
  - `skills` (array of 1–2 kebab-case skills)
248
283
 
249
- Optional frontmatter for high-complexity or decomposed tasks:
284
+ Required additional frontmatter:
250
285
 
251
- - `complexity_score` (number, 1–10, include only if >4 or for decomposed
252
- tasks)
253
- - `complexity_notes` (string)
286
+ - `complexity_score` (integer 1–10, required on every emitted task)
287
+
288
+ Optional frontmatter:
289
+
290
+ - `complexity_notes` (string) — include when the score needs justification,
291
+ such as "Decomposed from a cross-cutting parent task" or "Ambiguous API
292
+ contract".
254
293
 
255
294
  The body sections (Objective, Skills Required, Acceptance Criteria, Technical
256
295
  Requirements, Input Dependencies, Output Artifacts, Implementation Notes)
@@ -258,7 +297,7 @@ must be filled with task-specific content. Place detailed implementation
258
297
  guidance inside a `<details>` block under "Implementation Notes" — write it
259
298
  so a non-thinking LLM could execute the task from that section alone.
260
299
 
261
- #### 9. Validation checklist
300
+ #### 10. Validation checklist
262
301
 
263
302
  Before declaring task generation complete, verify:
264
303
 
@@ -276,16 +315,23 @@ Before declaring task generation complete, verify:
276
315
  - Minimization applied (20–30% reduction target).
277
316
  - Test tasks focus on business logic, not framework functionality.
278
317
  - No gold-plating: only plan requirements are addressed.
318
+ - After writing the task files, run
319
+ `scripts/validate-plan-blueprint.cjs <plan-id> complexityScoresValid`. Stop
320
+ unless it prints `yes`; if it prints `no`, run
321
+ `scripts/validate-plan-blueprint.cjs <plan-id> invalidComplexityTasks` to see
322
+ which files are missing, non-integer, or out-of-range, fix them, and re-run.
323
+ Every generated task must carry an integer `complexity_score` from 1 to 10.
324
+ - Add `complexity_notes` only when a score needs explanation (typically atomic
325
+ tasks scoring greater than 4).
279
326
 
280
- #### 10. Run the POST_TASK_GENERATION_ALL hook
327
+ #### 11. Run the POST_TASK_GENERATION_ALL hook
281
328
 
282
329
  Read `<root>/config/hooks/POST_TASK_GENERATION_ALL.md` and follow its instructions. This typically requires:
283
330
 
284
- - Sanity-checking complexity.
285
331
  - Appending an Execution Blueprint section to the plan document, including a Mermaid dependency diagram and explicit phase groupings.
286
332
  - Use `<root>/config/templates/BLUEPRINT_TEMPLATE.md` for structure.
287
333
 
288
- #### 11. Emit the Phase 2 structured summary
334
+ #### 12. Emit the Phase 2 structured summary
289
335
 
290
336
  Conclude Phase 2 with exactly this block:
291
337
 
@@ -330,7 +376,7 @@ If `taskCount` is 0 or `blueprintExists` is `no`:
330
376
 
331
377
  #### 3. Optionally create a feature branch
332
378
 
333
- Run `scripts/create-feature-branch.cjs <plan-id>`. The script creates a branch named after the plan and prints the branch name. Continue execution regardless of whether a branch is created.
379
+ Run `scripts/create-feature-branch.cjs <plan-id>` once before phase execution. Branch creation is best-effort: when the script reports that it skipped creation (for example, not on `main`/`master`), continue on the current branch and do not retry or create a branch manually. When the script exits with an error (for example, uncommitted changes on `main`/`master`), halt and report the error. Do not treat a skipped branch as a failure or spend effort working around a skip.
334
380
 
335
381
  #### 4. Load execution blueprint
336
382
 
@@ -346,10 +392,12 @@ Read these files in order:
346
392
  Use an internal task or todo tracker to monitor progress. For each phase defined in the Execution Blueprint:
347
393
 
348
394
  ##### 5a. Phase pre-execution
395
+ Run `scripts/check-phase-readiness.cjs <plan-id> <phase-number>`. If the script exits non-zero, halt the phase and report the blocking issues before continuing.
396
+
349
397
  Read `<root>/config/hooks/PRE_PHASE.md` and execute its instructions before starting the phase.
350
398
 
351
399
  ##### 5b. Task dispatch
352
- Identify all tasks scheduled for this phase whose dependencies are fully satisfied. Read `<root>/config/hooks/PRE_TASK_EXECUTION.md` and execute its instructions before starting any implementation work.
400
+ Identify all tasks scheduled for this phase whose dependencies are fully satisfied. Read `<root>/config/hooks/PRE_TASK_ASSIGNMENT.md` and follow its instructions for agent selection before dispatching tasks.
353
401
 
354
402
  Deploy all selected agents simultaneously using your internal Task tool. Each agent MUST:
355
403