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.
- package/README.md +12 -12
- package/dist/index.js +1 -1
- package/dist/metadata.d.ts +1 -1
- package/dist/metadata.js +1 -1
- package/dist/serve/derivation.d.ts +1 -0
- package/dist/serve/derivation.d.ts.map +1 -1
- package/dist/serve/derivation.js +1 -0
- package/dist/serve/derivation.js.map +1 -1
- package/dist/serve/markdown.d.ts +1 -0
- package/dist/serve/markdown.d.ts.map +1 -1
- package/dist/serve/markdown.js +9 -0
- package/dist/serve/markdown.js.map +1 -1
- package/dist/skill-scripts/shared/root.js +1 -1
- package/dist-web/assets/{arc-iQlJHCCV.js → arc-ClZ3judi.js} +1 -1
- package/dist-web/assets/{architectureDiagram-3BPJPVTR-uN2KPcXw.js → architectureDiagram-3BPJPVTR-BRD031Y3.js} +1 -1
- package/dist-web/assets/{blockDiagram-GPEHLZMM-CMt6IBa8.js → blockDiagram-GPEHLZMM-CfaXqzcG.js} +1 -1
- package/dist-web/assets/{c4Diagram-AAUBKEIU-D-YKpLHn.js → c4Diagram-AAUBKEIU-D9Os_mjw.js} +1 -1
- package/dist-web/assets/channel-CJXJUs_u.js +1 -0
- package/dist-web/assets/{chunk-2J33WTMH-BQoe52nS.js → chunk-2J33WTMH-CScaCetR.js} +1 -1
- package/dist-web/assets/{chunk-4BX2VUAB--EBI_DNI.js → chunk-4BX2VUAB-C_0wTF2D.js} +1 -1
- package/dist-web/assets/{chunk-55IACEB6-DE1NbrfX.js → chunk-55IACEB6-BU0yxIXn.js} +1 -1
- package/dist-web/assets/{chunk-727SXJPM-BmknfrzD.js → chunk-727SXJPM-CEYPnfpF.js} +1 -1
- package/dist-web/assets/{chunk-AQP2D5EJ-DTyDzrvL.js → chunk-AQP2D5EJ-3Wp97XA5.js} +1 -1
- package/dist-web/assets/{chunk-FMBD7UC4-CQn7Uvih.js → chunk-FMBD7UC4-B_iff0-_.js} +1 -1
- package/dist-web/assets/{chunk-ND2GUHAM-CnykE_Kg.js → chunk-ND2GUHAM-C9bo0MIV.js} +1 -1
- package/dist-web/assets/{chunk-QZHKN3VN-Be2RyK2s.js → chunk-QZHKN3VN-DuWFBza0.js} +1 -1
- package/dist-web/assets/classDiagram-4FO5ZUOK-DSnAL-3H.js +1 -0
- package/dist-web/assets/classDiagram-v2-Q7XG4LA2-DSnAL-3H.js +1 -0
- package/dist-web/assets/{cose-bilkent-S5V4N54A-BXoChaJd.js → cose-bilkent-S5V4N54A-BvbHJ-Zg.js} +1 -1
- package/dist-web/assets/{dagre-BM42HDAG-CBhGTPWN.js → dagre-BM42HDAG-D6Et-JgF.js} +1 -1
- package/dist-web/assets/{diagram-2AECGRRQ-CQcPLW77.js → diagram-2AECGRRQ-CNCYsbbA.js} +1 -1
- package/dist-web/assets/{diagram-5GNKFQAL-BLq0ZS0T.js → diagram-5GNKFQAL-CxRozyyO.js} +1 -1
- package/dist-web/assets/{diagram-KO2AKTUF-D9his_br.js → diagram-KO2AKTUF-IZlLB90E.js} +1 -1
- package/dist-web/assets/{diagram-LMA3HP47-BWIqxk_u.js → diagram-LMA3HP47-CrSB8ihh.js} +1 -1
- package/dist-web/assets/{diagram-OG6HWLK6-CIg7m_j3.js → diagram-OG6HWLK6-tCjUSZwa.js} +1 -1
- package/dist-web/assets/{erDiagram-TEJ5UH35-Br8X9MlA.js → erDiagram-TEJ5UH35-JLv81E72.js} +1 -1
- package/dist-web/assets/{flowDiagram-I6XJVG4X-DqOFMENS.js → flowDiagram-I6XJVG4X-Det1_WLC.js} +1 -1
- package/dist-web/assets/{ganttDiagram-6RSMTGT7-BkmzGVBg.js → ganttDiagram-6RSMTGT7-Mi2wMw1v.js} +1 -1
- package/dist-web/assets/{gitGraphDiagram-PVQCEYII-CToioniK.js → gitGraphDiagram-PVQCEYII-Ddy55D8B.js} +1 -1
- package/dist-web/assets/{index-BGNxA4ex.js → index-BwABcoi9.js} +4 -4
- package/dist-web/assets/{index-XPUk9J7W.js → index-CEoxzYhV.js} +1 -1
- package/dist-web/assets/{index-BsWEFMQm.js → index-Dw0N6U6b.js} +1 -1
- package/dist-web/assets/{infoDiagram-5YYISTIA-B9SLu6Hy.js → infoDiagram-5YYISTIA-vrktGk5U.js} +1 -1
- package/dist-web/assets/{ishikawaDiagram-YF4QCWOH-wfIRoX5r.js → ishikawaDiagram-YF4QCWOH-CATnDGrp.js} +1 -1
- package/dist-web/assets/{journeyDiagram-JHISSGLW-D7E0q8bZ.js → journeyDiagram-JHISSGLW-CEvYFLj2.js} +1 -1
- package/dist-web/assets/{kanban-definition-UN3LZRKU--2Grx1qD.js → kanban-definition-UN3LZRKU-_6lp0n4D.js} +1 -1
- package/dist-web/assets/{linear-CmD0Yf7Q.js → linear-C1oEZdKm.js} +1 -1
- package/dist-web/assets/{mermaid.core-DvU5X9vY.js → mermaid.core-bqVxqCbb.js} +4 -4
- package/dist-web/assets/{mindmap-definition-RKZ34NQL-RS1L2Img.js → mindmap-definition-RKZ34NQL-DxAus_u1.js} +1 -1
- package/dist-web/assets/{pieDiagram-4H26LBE5-CSmQKvDq.js → pieDiagram-4H26LBE5-Bqjkt8dx.js} +1 -1
- package/dist-web/assets/{quadrantDiagram-W4KKPZXB-C_YvL19n.js → quadrantDiagram-W4KKPZXB-BoZHhSII.js} +1 -1
- package/dist-web/assets/{requirementDiagram-4Y6WPE33-CjM6rNTE.js → requirementDiagram-4Y6WPE33-D0rcLxmM.js} +1 -1
- package/dist-web/assets/{sankeyDiagram-5OEKKPKP-Dxdcp2GO.js → sankeyDiagram-5OEKKPKP-CWShHxDe.js} +1 -1
- package/dist-web/assets/{sequenceDiagram-3UESZ5HK-Bn7dy-8J.js → sequenceDiagram-3UESZ5HK-T8LE2GTr.js} +1 -1
- package/dist-web/assets/{stateDiagram-AJRCARHV-BvGqGTH2.js → stateDiagram-AJRCARHV-a8e0ie70.js} +1 -1
- package/dist-web/assets/stateDiagram-v2-BHNVJYJU-BmYjmWHJ.js +1 -0
- package/dist-web/assets/{timeline-definition-PNZ67QCA-BFzgWjlB.js → timeline-definition-PNZ67QCA-Fn2xKeuG.js} +1 -1
- package/dist-web/assets/{vennDiagram-CIIHVFJN-3vMaDLQj.js → vennDiagram-CIIHVFJN-CdlvIB8X.js} +1 -1
- package/dist-web/assets/{wardley-L42UT6IY-kCHOjqxR.js → wardley-L42UT6IY-9pciD2XX.js} +1 -1
- package/dist-web/assets/{wardleyDiagram-YWT4CUSO-X6ZFLRwo.js → wardleyDiagram-YWT4CUSO-BK6qNOxa.js} +1 -1
- package/dist-web/assets/{xychartDiagram-2RQKCTM6-Ddsjg-Qs.js → xychartDiagram-2RQKCTM6-QjMTFvse.js} +1 -1
- package/dist-web/index.html +1 -1
- package/package.json +1 -1
- package/templates/harness/skills/st-create-plan/scripts/find-strikethroo-root.cjs +1 -1
- package/templates/harness/skills/st-create-plan/scripts/get-next-plan-id.cjs +1 -1
- package/templates/harness/skills/st-execute-blueprint/SKILL.md +5 -3
- package/templates/harness/skills/st-execute-blueprint/scripts/check-phase-readiness.cjs +471 -0
- package/templates/harness/skills/st-execute-blueprint/scripts/create-feature-branch.cjs +17 -9
- package/templates/harness/skills/st-execute-blueprint/scripts/find-strikethroo-root.cjs +1 -1
- package/templates/harness/skills/st-execute-blueprint/scripts/validate-plan-blueprint.cjs +51 -3
- package/templates/harness/skills/st-execute-task/scripts/check-task-dependencies.cjs +114 -72
- package/templates/harness/skills/st-execute-task/scripts/find-strikethroo-root.cjs +1 -1
- package/templates/harness/skills/st-execute-task/scripts/validate-plan-blueprint.cjs +51 -3
- package/templates/harness/skills/st-full-workflow/SKILL.md +60 -12
- package/templates/harness/skills/st-full-workflow/scripts/check-phase-readiness.cjs +471 -0
- package/templates/harness/skills/st-full-workflow/scripts/create-feature-branch.cjs +17 -9
- package/templates/harness/skills/st-full-workflow/scripts/find-strikethroo-root.cjs +1 -1
- package/templates/harness/skills/st-full-workflow/scripts/get-next-plan-id.cjs +1 -1
- package/templates/harness/skills/st-full-workflow/scripts/get-next-task-id.cjs +1 -1
- package/templates/harness/skills/st-full-workflow/scripts/validate-plan-blueprint.cjs +51 -3
- package/templates/harness/skills/st-generate-tasks/SKILL.md +56 -11
- package/templates/harness/skills/st-generate-tasks/scripts/find-strikethroo-root.cjs +1 -1
- package/templates/harness/skills/st-generate-tasks/scripts/get-next-task-id.cjs +1 -1
- package/templates/harness/skills/st-generate-tasks/scripts/validate-plan-blueprint.cjs +51 -3
- package/templates/harness/skills/st-refine-plan/scripts/find-strikethroo-root.cjs +1 -1
- package/templates/harness/skills/st-refine-plan/scripts/validate-plan-blueprint.cjs +51 -3
- package/templates/strikethroo/README.md +1 -1
- package/templates/strikethroo/config/hooks/POST_PHASE.md +5 -4
- package/templates/strikethroo/config/hooks/POST_TASK_GENERATION_ALL.md +3 -13
- package/templates/strikethroo/config/hooks/PRE_PHASE.md +0 -13
- package/templates/strikethroo/config/templates/TASK_TEMPLATE.md +1 -0
- package/dist-web/assets/channel-CUiY3Crj.js +0 -1
- package/dist-web/assets/classDiagram-4FO5ZUOK-Btt3eQId.js +0 -1
- package/dist-web/assets/classDiagram-v2-Q7XG4LA2-Btt3eQId.js +0 -1
- 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
|
|
37
|
-
var
|
|
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 ?
|
|
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/
|
|
248
|
-
var
|
|
249
|
-
|
|
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
|
|
254
|
+
var findTaskFile = (planDir, taskId) => {
|
|
265
255
|
const taskDir = path4.join(planDir, "tasks");
|
|
266
|
-
if (!fs4.existsSync(taskDir))
|
|
267
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
311
|
-
const
|
|
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 =
|
|
340
|
-
if (!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: ${
|
|
396
|
+
_printInfo(`Checking task: ${path5.basename(taskFile)}`);
|
|
345
397
|
console.log("");
|
|
346
|
-
const
|
|
347
|
-
const
|
|
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 =
|
|
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 =
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
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: ${
|
|
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: ${
|
|
441
|
+
_printInfo(`Total dependencies: ${dependencies.length}`);
|
|
399
442
|
_printInfo(`Resolved: ${resolvedCount}`);
|
|
400
|
-
_printInfo(`Unresolved: ${
|
|
443
|
+
_printInfo(`Unresolved: ${dependencies.length - resolvedCount}`);
|
|
401
444
|
console.log("");
|
|
402
|
-
if (
|
|
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 ?
|
|
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 ?
|
|
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.
|
|
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
|
-
####
|
|
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
|
-
|
|
284
|
+
Required additional frontmatter:
|
|
250
285
|
|
|
251
|
-
- `complexity_score` (
|
|
252
|
-
|
|
253
|
-
|
|
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
|
-
####
|
|
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
|
-
####
|
|
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
|
-
####
|
|
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
|
|
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/
|
|
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
|
|