strikethroo 3.7.0 → 3.9.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 -12
- package/dist/serve/markdown.d.ts.map +1 -1
- package/dist/serve/markdown.js +9 -2
- package/dist/serve/markdown.js.map +1 -1
- package/dist/skill-scripts/shared/complexity-score.d.ts +14 -0
- package/dist/skill-scripts/shared/complexity-score.d.ts.map +1 -0
- package/dist/skill-scripts/shared/complexity-score.js +21 -0
- package/dist/skill-scripts/shared/complexity-score.js.map +1 -0
- package/dist/skill-scripts/shared/root.js +1 -1
- package/dist-web/assets/{arc-xFaTbwSI.js → arc-U8dalZIB.js} +1 -1
- package/dist-web/assets/{architectureDiagram-3BPJPVTR-Xz0i2dF0.js → architectureDiagram-3BPJPVTR-BII4UusQ.js} +1 -1
- package/dist-web/assets/{blockDiagram-GPEHLZMM-BdKR7Rki.js → blockDiagram-GPEHLZMM-DY4WZYhw.js} +1 -1
- package/dist-web/assets/{c4Diagram-AAUBKEIU-DAayjcH7.js → c4Diagram-AAUBKEIU-ByZWkPq5.js} +1 -1
- package/dist-web/assets/channel-hoQZJ4FP.js +1 -0
- package/dist-web/assets/{chunk-2J33WTMH-D4OfjzqG.js → chunk-2J33WTMH-BkTWBAb4.js} +1 -1
- package/dist-web/assets/{chunk-4BX2VUAB-Ds6twHLE.js → chunk-4BX2VUAB-CQkRWCB3.js} +1 -1
- package/dist-web/assets/{chunk-55IACEB6-CoVGj0A6.js → chunk-55IACEB6-C-6bW0I1.js} +1 -1
- package/dist-web/assets/{chunk-727SXJPM--kGZcEL_.js → chunk-727SXJPM-C4TUUt4s.js} +1 -1
- package/dist-web/assets/{chunk-AQP2D5EJ-dK8X6Knv.js → chunk-AQP2D5EJ-Dtp8JWF7.js} +1 -1
- package/dist-web/assets/{chunk-FMBD7UC4-CIkH8fwk.js → chunk-FMBD7UC4-BwHFSRRs.js} +1 -1
- package/dist-web/assets/{chunk-ND2GUHAM-BqrY0fV2.js → chunk-ND2GUHAM-Cig_3TB-.js} +1 -1
- package/dist-web/assets/{chunk-QZHKN3VN-Bx8TPE1r.js → chunk-QZHKN3VN-BGETuJY7.js} +1 -1
- package/dist-web/assets/classDiagram-4FO5ZUOK-B0lk8Y6z.js +1 -0
- package/dist-web/assets/classDiagram-v2-Q7XG4LA2-B0lk8Y6z.js +1 -0
- package/dist-web/assets/{cose-bilkent-S5V4N54A-PyZxi1yI.js → cose-bilkent-S5V4N54A-DuOybbaS.js} +1 -1
- package/dist-web/assets/{dagre-BM42HDAG-yXPAIOqC.js → dagre-BM42HDAG-VnC37qtr.js} +1 -1
- package/dist-web/assets/{diagram-2AECGRRQ-DDkzzAIo.js → diagram-2AECGRRQ-Ty7SQMgH.js} +1 -1
- package/dist-web/assets/{diagram-5GNKFQAL-BD_aXIRb.js → diagram-5GNKFQAL-BlKDu0VW.js} +1 -1
- package/dist-web/assets/{diagram-KO2AKTUF-rntOw_IG.js → diagram-KO2AKTUF-Bbg0OCZg.js} +1 -1
- package/dist-web/assets/{diagram-LMA3HP47-BAB3HQQs.js → diagram-LMA3HP47-kkVpRIsu.js} +1 -1
- package/dist-web/assets/{diagram-OG6HWLK6-CwTzozdw.js → diagram-OG6HWLK6-DOWYkZlS.js} +1 -1
- package/dist-web/assets/{erDiagram-TEJ5UH35-BW-Ha54s.js → erDiagram-TEJ5UH35-D8WlLdtK.js} +1 -1
- package/dist-web/assets/{flowDiagram-I6XJVG4X-AGkxH_mx.js → flowDiagram-I6XJVG4X-U7NYonjl.js} +1 -1
- package/dist-web/assets/{ganttDiagram-6RSMTGT7--ZS9LkZ2.js → ganttDiagram-6RSMTGT7-vw1uFVh5.js} +1 -1
- package/dist-web/assets/{gitGraphDiagram-PVQCEYII-D4KfIxPI.js → gitGraphDiagram-PVQCEYII-Coc0d6Bs.js} +1 -1
- package/dist-web/assets/{index-uk0kSvAs.js → index-4vwdK2qG.js} +4 -4
- package/dist-web/assets/{index-IHSMZO2U.js → index-D53fh0zY.js} +1 -1
- package/dist-web/assets/{index-BN30VZfQ.js → index-TwwNd18Z.js} +1 -1
- package/dist-web/assets/{infoDiagram-5YYISTIA-D_Z40zdo.js → infoDiagram-5YYISTIA-D1rd3cgn.js} +1 -1
- package/dist-web/assets/{ishikawaDiagram-YF4QCWOH-CGzxJ2vS.js → ishikawaDiagram-YF4QCWOH-C6QHofgd.js} +1 -1
- package/dist-web/assets/{journeyDiagram-JHISSGLW-DLtpX1Ni.js → journeyDiagram-JHISSGLW-CfCP3_lL.js} +1 -1
- package/dist-web/assets/{kanban-definition-UN3LZRKU-C4_O7GEC.js → kanban-definition-UN3LZRKU-eK9aAtUE.js} +1 -1
- package/dist-web/assets/{linear-BoMijEDN.js → linear-Xl4NTVLR.js} +1 -1
- package/dist-web/assets/{mermaid.core-B7AM5BmV.js → mermaid.core-Bpv3Fy5r.js} +4 -4
- package/dist-web/assets/{mindmap-definition-RKZ34NQL-b8o1AjHb.js → mindmap-definition-RKZ34NQL-C-UftEj-.js} +1 -1
- package/dist-web/assets/{pieDiagram-4H26LBE5-D7BGsvW4.js → pieDiagram-4H26LBE5--B3LdTQd.js} +1 -1
- package/dist-web/assets/{quadrantDiagram-W4KKPZXB-BOsVmBQ_.js → quadrantDiagram-W4KKPZXB-DTr-7cow.js} +1 -1
- package/dist-web/assets/{requirementDiagram-4Y6WPE33-BwuELhlD.js → requirementDiagram-4Y6WPE33-CMKPuFbL.js} +1 -1
- package/dist-web/assets/{sankeyDiagram-5OEKKPKP-DDoQnSJz.js → sankeyDiagram-5OEKKPKP-DnThFDZc.js} +1 -1
- package/dist-web/assets/{sequenceDiagram-3UESZ5HK-Dto9SgGd.js → sequenceDiagram-3UESZ5HK-WqT16YFF.js} +1 -1
- package/dist-web/assets/{stateDiagram-AJRCARHV-Dx0qn_5x.js → stateDiagram-AJRCARHV-5nr9Um5q.js} +1 -1
- package/dist-web/assets/stateDiagram-v2-BHNVJYJU-Doh4LSg5.js +1 -0
- package/dist-web/assets/{timeline-definition-PNZ67QCA-Dbhzc3Xh.js → timeline-definition-PNZ67QCA-CNOVn_B3.js} +1 -1
- package/dist-web/assets/{vennDiagram-CIIHVFJN-BEUtD6fT.js → vennDiagram-CIIHVFJN-D-h0Gph6.js} +1 -1
- package/dist-web/assets/{wardley-L42UT6IY-CqNfcWnP.js → wardley-L42UT6IY-C1fuBpoj.js} +1 -1
- package/dist-web/assets/{wardleyDiagram-YWT4CUSO-Co_bCOQZ.js → wardleyDiagram-YWT4CUSO-BauL5Z2B.js} +1 -1
- package/dist-web/assets/{xychartDiagram-2RQKCTM6-CguzZIIB.js → xychartDiagram-2RQKCTM6-Z9Z3wS3v.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 +1 -1
- package/templates/harness/skills/st-execute-blueprint/scripts/check-phase-readiness.cjs +1 -1
- package/templates/harness/skills/st-execute-blueprint/scripts/create-feature-branch.cjs +1 -1
- 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 +93 -22
- package/templates/harness/skills/st-execute-task/scripts/check-task-dependencies.cjs +1 -1
- 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 +93 -22
- package/templates/harness/skills/st-full-workflow/SKILL.md +56 -10
- package/templates/harness/skills/st-full-workflow/scripts/check-phase-readiness.cjs +1 -1
- package/templates/harness/skills/st-full-workflow/scripts/create-feature-branch.cjs +1 -1
- 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 +93 -22
- 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 +93 -22
- 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 +93 -22
- package/templates/strikethroo/README.md +1 -1
- package/templates/strikethroo/config/hooks/POST_TASK_GENERATION_ALL.md +3 -13
- package/templates/strikethroo/config/templates/TASK_TEMPLATE.md +1 -0
- package/dist-web/assets/channel-Cmb5ngmL.js +0 -1
- package/dist-web/assets/classDiagram-4FO5ZUOK-Dh2pEfOy.js +0 -1
- package/dist-web/assets/classDiagram-v2-Q7XG4LA2-Dh2pEfOy.js +0 -1
- package/dist-web/assets/stateDiagram-v2-BHNVJYJU-qo6que2v.js +0 -1
|
@@ -33,13 +33,11 @@ __export(validate_plan_blueprint_exports, {
|
|
|
33
33
|
main: () => main
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(validate_plan_blueprint_exports);
|
|
36
|
-
var fs4 = __toESM(require("fs"));
|
|
37
|
-
var path4 = __toESM(require("path"));
|
|
38
36
|
|
|
39
37
|
// src/skill-scripts/shared/root.ts
|
|
40
38
|
var fs = __toESM(require("fs"));
|
|
41
39
|
var path = __toESM(require("path"));
|
|
42
|
-
var EXPECTED_SCHEMA = true ?
|
|
40
|
+
var EXPECTED_SCHEMA = true ? 3 : 3;
|
|
43
41
|
var isValidStrikethrooRoot = (strikethrooPath) => {
|
|
44
42
|
try {
|
|
45
43
|
if (!fs.existsSync(strikethrooPath)) return false;
|
|
@@ -242,34 +240,104 @@ var resolvePlan = (input, startPath = process.cwd()) => {
|
|
|
242
240
|
return resolveByIdInAncestry(planId, startPath);
|
|
243
241
|
};
|
|
244
242
|
|
|
245
|
-
// src/skill-scripts/
|
|
246
|
-
var
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
243
|
+
// src/skill-scripts/shared/blueprint-detection.ts
|
|
244
|
+
var fs4 = __toESM(require("fs"));
|
|
245
|
+
var hasExecutionBlueprint = (planFile) => {
|
|
246
|
+
try {
|
|
247
|
+
const content = fs4.readFileSync(planFile, "utf8");
|
|
248
|
+
return /^## Execution Blueprint/m.test(content);
|
|
249
|
+
} catch (_err) {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// src/skill-scripts/shared/task-count.ts
|
|
255
|
+
var fs5 = __toESM(require("fs"));
|
|
256
|
+
var path4 = __toESM(require("path"));
|
|
257
|
+
var countTaskFiles = (planDir) => {
|
|
255
258
|
const tasksDir = path4.join(planDir, "tasks");
|
|
256
|
-
if (!
|
|
259
|
+
if (!fs5.existsSync(tasksDir)) return 0;
|
|
257
260
|
try {
|
|
258
|
-
const stat =
|
|
261
|
+
const stat = fs5.lstatSync(tasksDir);
|
|
259
262
|
if (!stat.isDirectory()) return 0;
|
|
260
|
-
return
|
|
263
|
+
return fs5.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).length;
|
|
261
264
|
} catch (_err) {
|
|
262
265
|
return 0;
|
|
263
266
|
}
|
|
264
267
|
};
|
|
265
|
-
|
|
268
|
+
|
|
269
|
+
// src/skill-scripts/shared/task-complexity.ts
|
|
270
|
+
var fs6 = __toESM(require("fs"));
|
|
271
|
+
var path5 = __toESM(require("path"));
|
|
272
|
+
|
|
273
|
+
// src/skill-scripts/shared/complexity-score.ts
|
|
274
|
+
var validateComplexityScore = (value) => {
|
|
275
|
+
const trimmed = value.trim();
|
|
276
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
277
|
+
return { valid: false, reason: "non-integer" };
|
|
278
|
+
}
|
|
279
|
+
const parsed = Number.parseInt(trimmed, 10);
|
|
280
|
+
if (parsed < 1 || parsed > 10) {
|
|
281
|
+
return { valid: false, reason: "out-of-range", value: parsed };
|
|
282
|
+
}
|
|
283
|
+
return { valid: true, value: parsed };
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
// src/skill-scripts/shared/task-file.ts
|
|
287
|
+
var extractFrontmatter = (content) => {
|
|
288
|
+
const match = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/);
|
|
289
|
+
return match && match[1] ? match[1] : null;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// src/skill-scripts/shared/task-complexity.ts
|
|
293
|
+
var validateTaskComplexityScores = (planDir) => {
|
|
294
|
+
const tasksDir = path5.join(planDir, "tasks");
|
|
295
|
+
if (!fs6.existsSync(tasksDir)) return [];
|
|
296
|
+
let files;
|
|
266
297
|
try {
|
|
267
|
-
|
|
268
|
-
|
|
298
|
+
if (!fs6.lstatSync(tasksDir).isDirectory()) return [];
|
|
299
|
+
files = fs6.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).sort();
|
|
269
300
|
} catch (_err) {
|
|
270
|
-
return
|
|
301
|
+
return [];
|
|
271
302
|
}
|
|
303
|
+
const invalid = [];
|
|
304
|
+
for (const file of files) {
|
|
305
|
+
let content;
|
|
306
|
+
try {
|
|
307
|
+
content = fs6.readFileSync(path5.join(tasksDir, file), "utf8");
|
|
308
|
+
} catch (_err) {
|
|
309
|
+
invalid.push(`${file}: unreadable`);
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
const frontmatter = extractFrontmatter(content);
|
|
313
|
+
const match = frontmatter ? frontmatter.match(/^\s*complexity_score\s*:\s*(.*?)\s*(?:#.*)?$/im) : null;
|
|
314
|
+
if (!match || match[1] === void 0) {
|
|
315
|
+
invalid.push(`${file}: missing complexity_score`);
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
const raw = match[1].trim();
|
|
319
|
+
const result = validateComplexityScore(raw);
|
|
320
|
+
if (result.valid) continue;
|
|
321
|
+
if (result.reason === "non-integer") {
|
|
322
|
+
invalid.push(`${file}: non-integer complexity_score "${raw}"`);
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
invalid.push(`${file}: complexity_score ${result.value} out of range 1-10`);
|
|
326
|
+
}
|
|
327
|
+
return invalid;
|
|
272
328
|
};
|
|
329
|
+
|
|
330
|
+
// src/skill-scripts/validate-plan-blueprint.ts
|
|
331
|
+
var VALID_FIELDS = [
|
|
332
|
+
"planFile",
|
|
333
|
+
"planDir",
|
|
334
|
+
"taskCount",
|
|
335
|
+
"blueprintExists",
|
|
336
|
+
"strikethrooRoot",
|
|
337
|
+
"planId",
|
|
338
|
+
"complexityScoresValid",
|
|
339
|
+
"invalidComplexityTasks"
|
|
340
|
+
];
|
|
273
341
|
var usage = () => {
|
|
274
342
|
const lines = [
|
|
275
343
|
"Plan ID or absolute path is required",
|
|
@@ -324,13 +392,16 @@ var main = () => {
|
|
|
324
392
|
}
|
|
325
393
|
process.exit(1);
|
|
326
394
|
}
|
|
395
|
+
const invalidComplexity = validateTaskComplexityScores(resolved.planDir);
|
|
327
396
|
const result = {
|
|
328
397
|
planFile: resolved.planFile,
|
|
329
398
|
planDir: resolved.planDir,
|
|
330
399
|
strikethrooRoot: resolved.strikethrooRoot,
|
|
331
400
|
planId: resolved.planId,
|
|
332
|
-
taskCount:
|
|
333
|
-
blueprintExists:
|
|
401
|
+
taskCount: countTaskFiles(resolved.planDir),
|
|
402
|
+
blueprintExists: hasExecutionBlueprint(resolved.planFile) ? "yes" : "no",
|
|
403
|
+
complexityScoresValid: invalidComplexity.length === 0 ? "yes" : "no",
|
|
404
|
+
invalidComplexityTasks: invalidComplexity.join("; ")
|
|
334
405
|
};
|
|
335
406
|
if (fieldName) {
|
|
336
407
|
if (!VALID_FIELDS.includes(fieldName)) {
|
|
@@ -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;
|
|
@@ -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;
|
|
@@ -33,13 +33,11 @@ __export(validate_plan_blueprint_exports, {
|
|
|
33
33
|
main: () => main
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(validate_plan_blueprint_exports);
|
|
36
|
-
var fs4 = __toESM(require("fs"));
|
|
37
|
-
var path4 = __toESM(require("path"));
|
|
38
36
|
|
|
39
37
|
// src/skill-scripts/shared/root.ts
|
|
40
38
|
var fs = __toESM(require("fs"));
|
|
41
39
|
var path = __toESM(require("path"));
|
|
42
|
-
var EXPECTED_SCHEMA = true ?
|
|
40
|
+
var EXPECTED_SCHEMA = true ? 3 : 3;
|
|
43
41
|
var isValidStrikethrooRoot = (strikethrooPath) => {
|
|
44
42
|
try {
|
|
45
43
|
if (!fs.existsSync(strikethrooPath)) return false;
|
|
@@ -242,34 +240,104 @@ var resolvePlan = (input, startPath = process.cwd()) => {
|
|
|
242
240
|
return resolveByIdInAncestry(planId, startPath);
|
|
243
241
|
};
|
|
244
242
|
|
|
245
|
-
// src/skill-scripts/
|
|
246
|
-
var
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
243
|
+
// src/skill-scripts/shared/blueprint-detection.ts
|
|
244
|
+
var fs4 = __toESM(require("fs"));
|
|
245
|
+
var hasExecutionBlueprint = (planFile) => {
|
|
246
|
+
try {
|
|
247
|
+
const content = fs4.readFileSync(planFile, "utf8");
|
|
248
|
+
return /^## Execution Blueprint/m.test(content);
|
|
249
|
+
} catch (_err) {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// src/skill-scripts/shared/task-count.ts
|
|
255
|
+
var fs5 = __toESM(require("fs"));
|
|
256
|
+
var path4 = __toESM(require("path"));
|
|
257
|
+
var countTaskFiles = (planDir) => {
|
|
255
258
|
const tasksDir = path4.join(planDir, "tasks");
|
|
256
|
-
if (!
|
|
259
|
+
if (!fs5.existsSync(tasksDir)) return 0;
|
|
257
260
|
try {
|
|
258
|
-
const stat =
|
|
261
|
+
const stat = fs5.lstatSync(tasksDir);
|
|
259
262
|
if (!stat.isDirectory()) return 0;
|
|
260
|
-
return
|
|
263
|
+
return fs5.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).length;
|
|
261
264
|
} catch (_err) {
|
|
262
265
|
return 0;
|
|
263
266
|
}
|
|
264
267
|
};
|
|
265
|
-
|
|
268
|
+
|
|
269
|
+
// src/skill-scripts/shared/task-complexity.ts
|
|
270
|
+
var fs6 = __toESM(require("fs"));
|
|
271
|
+
var path5 = __toESM(require("path"));
|
|
272
|
+
|
|
273
|
+
// src/skill-scripts/shared/complexity-score.ts
|
|
274
|
+
var validateComplexityScore = (value) => {
|
|
275
|
+
const trimmed = value.trim();
|
|
276
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
277
|
+
return { valid: false, reason: "non-integer" };
|
|
278
|
+
}
|
|
279
|
+
const parsed = Number.parseInt(trimmed, 10);
|
|
280
|
+
if (parsed < 1 || parsed > 10) {
|
|
281
|
+
return { valid: false, reason: "out-of-range", value: parsed };
|
|
282
|
+
}
|
|
283
|
+
return { valid: true, value: parsed };
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
// src/skill-scripts/shared/task-file.ts
|
|
287
|
+
var extractFrontmatter = (content) => {
|
|
288
|
+
const match = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/);
|
|
289
|
+
return match && match[1] ? match[1] : null;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// src/skill-scripts/shared/task-complexity.ts
|
|
293
|
+
var validateTaskComplexityScores = (planDir) => {
|
|
294
|
+
const tasksDir = path5.join(planDir, "tasks");
|
|
295
|
+
if (!fs6.existsSync(tasksDir)) return [];
|
|
296
|
+
let files;
|
|
266
297
|
try {
|
|
267
|
-
|
|
268
|
-
|
|
298
|
+
if (!fs6.lstatSync(tasksDir).isDirectory()) return [];
|
|
299
|
+
files = fs6.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).sort();
|
|
269
300
|
} catch (_err) {
|
|
270
|
-
return
|
|
301
|
+
return [];
|
|
271
302
|
}
|
|
303
|
+
const invalid = [];
|
|
304
|
+
for (const file of files) {
|
|
305
|
+
let content;
|
|
306
|
+
try {
|
|
307
|
+
content = fs6.readFileSync(path5.join(tasksDir, file), "utf8");
|
|
308
|
+
} catch (_err) {
|
|
309
|
+
invalid.push(`${file}: unreadable`);
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
const frontmatter = extractFrontmatter(content);
|
|
313
|
+
const match = frontmatter ? frontmatter.match(/^\s*complexity_score\s*:\s*(.*?)\s*(?:#.*)?$/im) : null;
|
|
314
|
+
if (!match || match[1] === void 0) {
|
|
315
|
+
invalid.push(`${file}: missing complexity_score`);
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
const raw = match[1].trim();
|
|
319
|
+
const result = validateComplexityScore(raw);
|
|
320
|
+
if (result.valid) continue;
|
|
321
|
+
if (result.reason === "non-integer") {
|
|
322
|
+
invalid.push(`${file}: non-integer complexity_score "${raw}"`);
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
invalid.push(`${file}: complexity_score ${result.value} out of range 1-10`);
|
|
326
|
+
}
|
|
327
|
+
return invalid;
|
|
272
328
|
};
|
|
329
|
+
|
|
330
|
+
// src/skill-scripts/validate-plan-blueprint.ts
|
|
331
|
+
var VALID_FIELDS = [
|
|
332
|
+
"planFile",
|
|
333
|
+
"planDir",
|
|
334
|
+
"taskCount",
|
|
335
|
+
"blueprintExists",
|
|
336
|
+
"strikethrooRoot",
|
|
337
|
+
"planId",
|
|
338
|
+
"complexityScoresValid",
|
|
339
|
+
"invalidComplexityTasks"
|
|
340
|
+
];
|
|
273
341
|
var usage = () => {
|
|
274
342
|
const lines = [
|
|
275
343
|
"Plan ID or absolute path is required",
|
|
@@ -324,13 +392,16 @@ var main = () => {
|
|
|
324
392
|
}
|
|
325
393
|
process.exit(1);
|
|
326
394
|
}
|
|
395
|
+
const invalidComplexity = validateTaskComplexityScores(resolved.planDir);
|
|
327
396
|
const result = {
|
|
328
397
|
planFile: resolved.planFile,
|
|
329
398
|
planDir: resolved.planDir,
|
|
330
399
|
strikethrooRoot: resolved.strikethrooRoot,
|
|
331
400
|
planId: resolved.planId,
|
|
332
|
-
taskCount:
|
|
333
|
-
blueprintExists:
|
|
401
|
+
taskCount: countTaskFiles(resolved.planDir),
|
|
402
|
+
blueprintExists: hasExecutionBlueprint(resolved.planFile) ? "yes" : "no",
|
|
403
|
+
complexityScoresValid: invalidComplexity.length === 0 ? "yes" : "no",
|
|
404
|
+
invalidComplexityTasks: invalidComplexity.join("; ")
|
|
334
405
|
};
|
|
335
406
|
if (fieldName) {
|
|
336
407
|
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:
|
|
285
|
+
|
|
286
|
+
- `complexity_score` (integer 1–10, required on every emitted task)
|
|
287
|
+
|
|
288
|
+
Optional frontmatter:
|
|
250
289
|
|
|
251
|
-
- `
|
|
252
|
-
|
|
253
|
-
|
|
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
|
|
|
@@ -86,7 +86,7 @@ var path3 = __toESM(require("path"));
|
|
|
86
86
|
// src/skill-scripts/shared/root.ts
|
|
87
87
|
var fs = __toESM(require("fs"));
|
|
88
88
|
var path = __toESM(require("path"));
|
|
89
|
-
var EXPECTED_SCHEMA = true ?
|
|
89
|
+
var EXPECTED_SCHEMA = true ? 3 : 3;
|
|
90
90
|
var isValidStrikethrooRoot = (strikethrooPath) => {
|
|
91
91
|
try {
|
|
92
92
|
if (!fs.existsSync(strikethrooPath)) return false;
|
|
@@ -54,7 +54,7 @@ var path3 = __toESM(require("path"));
|
|
|
54
54
|
// src/skill-scripts/shared/root.ts
|
|
55
55
|
var fs = __toESM(require("fs"));
|
|
56
56
|
var path = __toESM(require("path"));
|
|
57
|
-
var EXPECTED_SCHEMA = true ?
|
|
57
|
+
var EXPECTED_SCHEMA = true ? 3 : 3;
|
|
58
58
|
var isValidStrikethrooRoot = (strikethrooPath) => {
|
|
59
59
|
try {
|
|
60
60
|
if (!fs.existsSync(strikethrooPath)) return false;
|
|
@@ -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;
|
|
@@ -37,7 +37,7 @@ module.exports = __toCommonJS(get_next_plan_id_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;
|
|
@@ -41,7 +41,7 @@ var path3 = __toESM(require("path"));
|
|
|
41
41
|
// src/skill-scripts/shared/root.ts
|
|
42
42
|
var fs = __toESM(require("fs"));
|
|
43
43
|
var path = __toESM(require("path"));
|
|
44
|
-
var EXPECTED_SCHEMA = true ?
|
|
44
|
+
var EXPECTED_SCHEMA = true ? 3 : 3;
|
|
45
45
|
var isValidStrikethrooRoot = (strikethrooPath) => {
|
|
46
46
|
try {
|
|
47
47
|
if (!fs.existsSync(strikethrooPath)) return false;
|
|
@@ -33,13 +33,11 @@ __export(validate_plan_blueprint_exports, {
|
|
|
33
33
|
main: () => main
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(validate_plan_blueprint_exports);
|
|
36
|
-
var fs4 = __toESM(require("fs"));
|
|
37
|
-
var path4 = __toESM(require("path"));
|
|
38
36
|
|
|
39
37
|
// src/skill-scripts/shared/root.ts
|
|
40
38
|
var fs = __toESM(require("fs"));
|
|
41
39
|
var path = __toESM(require("path"));
|
|
42
|
-
var EXPECTED_SCHEMA = true ?
|
|
40
|
+
var EXPECTED_SCHEMA = true ? 3 : 3;
|
|
43
41
|
var isValidStrikethrooRoot = (strikethrooPath) => {
|
|
44
42
|
try {
|
|
45
43
|
if (!fs.existsSync(strikethrooPath)) return false;
|
|
@@ -242,34 +240,104 @@ var resolvePlan = (input, startPath = process.cwd()) => {
|
|
|
242
240
|
return resolveByIdInAncestry(planId, startPath);
|
|
243
241
|
};
|
|
244
242
|
|
|
245
|
-
// src/skill-scripts/
|
|
246
|
-
var
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
243
|
+
// src/skill-scripts/shared/blueprint-detection.ts
|
|
244
|
+
var fs4 = __toESM(require("fs"));
|
|
245
|
+
var hasExecutionBlueprint = (planFile) => {
|
|
246
|
+
try {
|
|
247
|
+
const content = fs4.readFileSync(planFile, "utf8");
|
|
248
|
+
return /^## Execution Blueprint/m.test(content);
|
|
249
|
+
} catch (_err) {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// src/skill-scripts/shared/task-count.ts
|
|
255
|
+
var fs5 = __toESM(require("fs"));
|
|
256
|
+
var path4 = __toESM(require("path"));
|
|
257
|
+
var countTaskFiles = (planDir) => {
|
|
255
258
|
const tasksDir = path4.join(planDir, "tasks");
|
|
256
|
-
if (!
|
|
259
|
+
if (!fs5.existsSync(tasksDir)) return 0;
|
|
257
260
|
try {
|
|
258
|
-
const stat =
|
|
261
|
+
const stat = fs5.lstatSync(tasksDir);
|
|
259
262
|
if (!stat.isDirectory()) return 0;
|
|
260
|
-
return
|
|
263
|
+
return fs5.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).length;
|
|
261
264
|
} catch (_err) {
|
|
262
265
|
return 0;
|
|
263
266
|
}
|
|
264
267
|
};
|
|
265
|
-
|
|
268
|
+
|
|
269
|
+
// src/skill-scripts/shared/task-complexity.ts
|
|
270
|
+
var fs6 = __toESM(require("fs"));
|
|
271
|
+
var path5 = __toESM(require("path"));
|
|
272
|
+
|
|
273
|
+
// src/skill-scripts/shared/complexity-score.ts
|
|
274
|
+
var validateComplexityScore = (value) => {
|
|
275
|
+
const trimmed = value.trim();
|
|
276
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
277
|
+
return { valid: false, reason: "non-integer" };
|
|
278
|
+
}
|
|
279
|
+
const parsed = Number.parseInt(trimmed, 10);
|
|
280
|
+
if (parsed < 1 || parsed > 10) {
|
|
281
|
+
return { valid: false, reason: "out-of-range", value: parsed };
|
|
282
|
+
}
|
|
283
|
+
return { valid: true, value: parsed };
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
// src/skill-scripts/shared/task-file.ts
|
|
287
|
+
var extractFrontmatter = (content) => {
|
|
288
|
+
const match = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/);
|
|
289
|
+
return match && match[1] ? match[1] : null;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// src/skill-scripts/shared/task-complexity.ts
|
|
293
|
+
var validateTaskComplexityScores = (planDir) => {
|
|
294
|
+
const tasksDir = path5.join(planDir, "tasks");
|
|
295
|
+
if (!fs6.existsSync(tasksDir)) return [];
|
|
296
|
+
let files;
|
|
266
297
|
try {
|
|
267
|
-
|
|
268
|
-
|
|
298
|
+
if (!fs6.lstatSync(tasksDir).isDirectory()) return [];
|
|
299
|
+
files = fs6.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).sort();
|
|
269
300
|
} catch (_err) {
|
|
270
|
-
return
|
|
301
|
+
return [];
|
|
271
302
|
}
|
|
303
|
+
const invalid = [];
|
|
304
|
+
for (const file of files) {
|
|
305
|
+
let content;
|
|
306
|
+
try {
|
|
307
|
+
content = fs6.readFileSync(path5.join(tasksDir, file), "utf8");
|
|
308
|
+
} catch (_err) {
|
|
309
|
+
invalid.push(`${file}: unreadable`);
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
const frontmatter = extractFrontmatter(content);
|
|
313
|
+
const match = frontmatter ? frontmatter.match(/^\s*complexity_score\s*:\s*(.*?)\s*(?:#.*)?$/im) : null;
|
|
314
|
+
if (!match || match[1] === void 0) {
|
|
315
|
+
invalid.push(`${file}: missing complexity_score`);
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
const raw = match[1].trim();
|
|
319
|
+
const result = validateComplexityScore(raw);
|
|
320
|
+
if (result.valid) continue;
|
|
321
|
+
if (result.reason === "non-integer") {
|
|
322
|
+
invalid.push(`${file}: non-integer complexity_score "${raw}"`);
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
invalid.push(`${file}: complexity_score ${result.value} out of range 1-10`);
|
|
326
|
+
}
|
|
327
|
+
return invalid;
|
|
272
328
|
};
|
|
329
|
+
|
|
330
|
+
// src/skill-scripts/validate-plan-blueprint.ts
|
|
331
|
+
var VALID_FIELDS = [
|
|
332
|
+
"planFile",
|
|
333
|
+
"planDir",
|
|
334
|
+
"taskCount",
|
|
335
|
+
"blueprintExists",
|
|
336
|
+
"strikethrooRoot",
|
|
337
|
+
"planId",
|
|
338
|
+
"complexityScoresValid",
|
|
339
|
+
"invalidComplexityTasks"
|
|
340
|
+
];
|
|
273
341
|
var usage = () => {
|
|
274
342
|
const lines = [
|
|
275
343
|
"Plan ID or absolute path is required",
|
|
@@ -324,13 +392,16 @@ var main = () => {
|
|
|
324
392
|
}
|
|
325
393
|
process.exit(1);
|
|
326
394
|
}
|
|
395
|
+
const invalidComplexity = validateTaskComplexityScores(resolved.planDir);
|
|
327
396
|
const result = {
|
|
328
397
|
planFile: resolved.planFile,
|
|
329
398
|
planDir: resolved.planDir,
|
|
330
399
|
strikethrooRoot: resolved.strikethrooRoot,
|
|
331
400
|
planId: resolved.planId,
|
|
332
|
-
taskCount:
|
|
333
|
-
blueprintExists:
|
|
401
|
+
taskCount: countTaskFiles(resolved.planDir),
|
|
402
|
+
blueprintExists: hasExecutionBlueprint(resolved.planFile) ? "yes" : "no",
|
|
403
|
+
complexityScoresValid: invalidComplexity.length === 0 ? "yes" : "no",
|
|
404
|
+
invalidComplexityTasks: invalidComplexity.join("; ")
|
|
334
405
|
};
|
|
335
406
|
if (fieldName) {
|
|
336
407
|
if (!VALID_FIELDS.includes(fieldName)) {
|