spets 0.1.40 → 0.1.42

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 (2) hide show
  1. package/dist/index.js +25 -826
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
5
  import { readFileSync as readFileSync11 } from "fs";
6
- import { dirname as dirname6, join as join11 } from "path";
6
+ import { dirname as dirname5, join as join11 } from "path";
7
7
  import { fileURLToPath as fileURLToPath2 } from "url";
8
8
 
9
9
  // src/commands/init.ts
@@ -729,211 +729,6 @@ import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsS
729
729
  import { join as join5, dirname as dirname2 } from "path";
730
730
  import matter2 from "gray-matter";
731
731
 
732
- // src/core/section-tree.ts
733
- function parseTemplateToTree(template, stepName, documentGoal, outputDir = "sections", instructionSummary = "") {
734
- const lines = template.split("\n");
735
- const headerRegex = /^(#{2,6})\s+(.+)$/;
736
- const headers = [];
737
- lines.forEach((line, index) => {
738
- const match = line.match(headerRegex);
739
- if (match) {
740
- headers.push({
741
- depth: match[1].length,
742
- title: match[2].trim(),
743
- fullTitle: line.trim(),
744
- line: index + 1
745
- });
746
- }
747
- });
748
- if (headers.length === 0) {
749
- return {
750
- stepName,
751
- sharedContext: {
752
- documentGoal,
753
- stepName,
754
- stepInstruction: instructionSummary,
755
- totalSections: 0,
756
- treeOverview: "(no sections)"
757
- },
758
- leaves: [],
759
- consolidateLevels: [],
760
- rootOutputPath: `${outputDir}/${stepName}.md`
761
- };
762
- }
763
- const root = {
764
- id: "root",
765
- title: "# Document",
766
- depth: 1,
767
- startLine: 0,
768
- children: [],
769
- isLeaf: false,
770
- outputPath: `${outputDir}/${stepName}.md`,
771
- position: { path: [], siblings: [], depth: 1 }
772
- };
773
- const stack = [root];
774
- headers.forEach((header, idx) => {
775
- const node = {
776
- id: slugify(header.title),
777
- title: header.fullTitle,
778
- depth: header.depth,
779
- startLine: header.line,
780
- endLine: idx < headers.length - 1 ? headers[idx + 1].line : lines.length + 1,
781
- children: [],
782
- isLeaf: true,
783
- // Will be updated when children are added
784
- outputPath: "",
785
- // Will be set after tree is built
786
- templateContent: extractContent(lines, header.line, idx < headers.length - 1 ? headers[idx + 1].line : lines.length + 1),
787
- position: { path: [], siblings: [], depth: header.depth }
788
- };
789
- while (stack.length > 1 && stack[stack.length - 1].depth >= header.depth) {
790
- stack.pop();
791
- }
792
- const parent = stack[stack.length - 1];
793
- parent.children.push(node);
794
- parent.isLeaf = false;
795
- stack.push(node);
796
- });
797
- calculatePositions(root, [], outputDir);
798
- const leaves = [];
799
- collectLeaves(root, leaves);
800
- const consolidateLevels = generateConsolidateLevels(root);
801
- const treeOverview = generateTreeOverview(root);
802
- const totalSections = countSections(root);
803
- return {
804
- stepName,
805
- sharedContext: {
806
- documentGoal,
807
- stepName,
808
- stepInstruction: instructionSummary,
809
- totalSections,
810
- treeOverview
811
- },
812
- leaves,
813
- consolidateLevels,
814
- rootOutputPath: root.outputPath
815
- };
816
- }
817
- function slugify(title) {
818
- return title.toLowerCase().replace(/[^a-z0-9가-힣]+/g, "-").replace(/^-+|-+$/g, "");
819
- }
820
- function extractContent(lines, startLine, endLine) {
821
- return lines.slice(startLine, endLine - 1).join("\n").trim();
822
- }
823
- function calculatePositions(node, parentPath, outputDir) {
824
- if (node.id === "root") {
825
- node.position = { path: [], siblings: [], depth: 1 };
826
- node.outputPath = `${outputDir}/_root.md`;
827
- }
828
- const siblingTitles = node.children.map(
829
- (c) => c.title.replace(/^#+\s*/, "")
830
- );
831
- node.children.forEach((child, idx) => {
832
- const childTitle = child.title.replace(/^#+\s*/, "");
833
- const currentPath = [...parentPath, childTitle];
834
- child.position = {
835
- path: currentPath,
836
- siblings: siblingTitles.filter((_, i) => i !== idx),
837
- parent: parentPath.length > 0 ? parentPath[parentPath.length - 1] : void 0,
838
- depth: child.depth
839
- };
840
- const pathSlug = currentPath.map((p) => slugify(p)).join("/");
841
- child.outputPath = `${outputDir}/${pathSlug}.md`;
842
- calculatePositions(child, currentPath, outputDir);
843
- });
844
- }
845
- function collectLeaves(node, leaves) {
846
- if (node.isLeaf && node.id !== "root") {
847
- leaves.push(node);
848
- }
849
- node.children.forEach((child) => collectLeaves(child, leaves));
850
- }
851
- function generateConsolidateLevels(root) {
852
- const levelMap = /* @__PURE__ */ new Map();
853
- function traverse(node) {
854
- if (node.children.length > 0) {
855
- const childIds = node.children.map((c) => c.id);
856
- const group = {
857
- parentId: node.id,
858
- childIds,
859
- outputPath: node.outputPath
860
- };
861
- const childDepth = Math.max(...node.children.map((c) => c.depth));
862
- if (!levelMap.has(childDepth)) {
863
- levelMap.set(childDepth, []);
864
- }
865
- levelMap.get(childDepth).push(group);
866
- node.children.forEach((child) => traverse(child));
867
- }
868
- }
869
- traverse(root);
870
- const levels = [];
871
- const depths = Array.from(levelMap.keys()).sort((a, b) => b - a);
872
- for (const depth of depths) {
873
- levels.push({
874
- depth,
875
- groups: levelMap.get(depth)
876
- });
877
- }
878
- return levels;
879
- }
880
- function generateTreeOverview(root) {
881
- const lines = [];
882
- function renderNode(node, prefix, isLast, isRoot) {
883
- if (!isRoot) {
884
- const marker = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
885
- lines.push(prefix + marker + node.title);
886
- }
887
- const childPrefix = isRoot ? "" : prefix + (isLast ? " " : "\u2502 ");
888
- node.children.forEach((child, idx) => {
889
- const isChildLast = idx === node.children.length - 1;
890
- renderNode(child, childPrefix, isChildLast, false);
891
- });
892
- }
893
- renderNode(root, "", true, true);
894
- return lines.join("\n");
895
- }
896
- function countSections(root) {
897
- let count = 0;
898
- function traverse(node) {
899
- if (node.id !== "root") {
900
- count++;
901
- }
902
- node.children.forEach((child) => traverse(child));
903
- }
904
- traverse(root);
905
- return count;
906
- }
907
- function buildSectionInstruction(section, sharedContext) {
908
- return `# Section: ${section.title}
909
-
910
- ## Document Context
911
- **Goal:** ${sharedContext.documentGoal}
912
- **Step:** ${sharedContext.stepName}
913
- **Total Sections:** ${sharedContext.totalSections}
914
-
915
- ## Tree Overview
916
- \`\`\`
917
- ${sharedContext.treeOverview}
918
- \`\`\`
919
-
920
- ## Your Position
921
- - **Path:** ${section.position.path.join(" > ")}
922
- - **Siblings:** ${section.position.siblings.join(", ") || "None"}
923
- - **Parent:** ${section.position.parent || "Root"}
924
-
925
- ## Your Task
926
- Write the "${section.title.replace(/^#+\s*/, "")}" section.
927
- Consider how it relates to sibling sections and contributes to the parent section.
928
-
929
- ${section.templateContent ? `## Template Guide
930
- ${section.templateContent}` : ""}
931
-
932
- ## Output
933
- Save to: ${section.outputPath}
934
- `;
935
- }
936
-
937
732
  // src/core/prompt-builder.ts
938
733
  import { readFileSync as readFileSync4, existsSync as existsSync4 } from "fs";
939
734
  import { join as join4 } from "path";
@@ -1255,111 +1050,6 @@ function buildGeneratePrompt(params) {
1255
1050
  outputPath
1256
1051
  };
1257
1052
  }
1258
- function buildSectionPrompt(params) {
1259
- const { section, sharedContext, gatheredContext, answers } = params;
1260
- const parts = [];
1261
- parts.push(`# Section: ${section.title}`);
1262
- parts.push("");
1263
- parts.push("## Document Context");
1264
- parts.push("");
1265
- parts.push(`**Goal:** ${sharedContext.documentGoal}`);
1266
- parts.push(`**Step:** ${sharedContext.stepName}`);
1267
- parts.push(`**Total Sections:** ${sharedContext.totalSections}`);
1268
- parts.push("");
1269
- parts.push("## Document Structure");
1270
- parts.push("");
1271
- parts.push("```");
1272
- parts.push(sharedContext.treeOverview);
1273
- parts.push("```");
1274
- parts.push("");
1275
- parts.push("## Your Position");
1276
- parts.push("");
1277
- parts.push(`- **Path:** ${section.position.path.join(" > ")}`);
1278
- parts.push(`- **Siblings:** ${section.position.siblings.join(", ") || "None"}`);
1279
- parts.push(`- **Parent:** ${section.position.parent || "Root"}`);
1280
- parts.push("");
1281
- if (gatheredContext) {
1282
- parts.push("## Gathered Context");
1283
- parts.push("");
1284
- parts.push(gatheredContext);
1285
- parts.push("");
1286
- }
1287
- if (answers && answers.length > 0) {
1288
- parts.push("## User Answers");
1289
- parts.push("");
1290
- for (const answer of answers) {
1291
- parts.push(`- **${answer.questionId}**: ${answer.answer}`);
1292
- }
1293
- parts.push("");
1294
- }
1295
- if (section.templateContent) {
1296
- parts.push("## Template Guide");
1297
- parts.push("");
1298
- parts.push(section.templateContent);
1299
- parts.push("");
1300
- }
1301
- parts.push("## Your Task");
1302
- parts.push("");
1303
- parts.push(`Write the "${section.title.replace(/^#+\\s*/, "")}" section.`);
1304
- parts.push("Consider how it relates to sibling sections and contributes to the parent section.");
1305
- parts.push("");
1306
- parts.push("## Output");
1307
- parts.push("");
1308
- parts.push(`Save to: \`${section.outputPath}\``);
1309
- parts.push("");
1310
- parts.push("Write ONLY the content for this section (including its header).");
1311
- parts.push("Do NOT include content from other sections.");
1312
- parts.push("");
1313
- return {
1314
- prompt: parts.join("\n"),
1315
- outputPath: section.outputPath
1316
- };
1317
- }
1318
- function buildConsolidatePrompt(params) {
1319
- const { group, childContents, sharedContext, parentTitle } = params;
1320
- const parts = [];
1321
- parts.push("# Consolidate Sections");
1322
- parts.push("");
1323
- parts.push("## Document Context");
1324
- parts.push("");
1325
- parts.push(`**Goal:** ${sharedContext.documentGoal}`);
1326
- parts.push(`**Step:** ${sharedContext.stepName}`);
1327
- parts.push("");
1328
- parts.push("## Document Structure");
1329
- parts.push("");
1330
- parts.push("```");
1331
- parts.push(sharedContext.treeOverview);
1332
- parts.push("```");
1333
- parts.push("");
1334
- parts.push("## Your Task");
1335
- parts.push("");
1336
- parts.push(`Consolidate the following child sections into the parent section "${parentTitle || group.parentId}".`);
1337
- parts.push("");
1338
- parts.push("## Child Sections to Consolidate");
1339
- parts.push("");
1340
- for (const child of childContents) {
1341
- parts.push(`### Child: ${child.id}`);
1342
- parts.push("");
1343
- parts.push(child.content);
1344
- parts.push("");
1345
- parts.push("---");
1346
- parts.push("");
1347
- }
1348
- parts.push("## Output Instructions");
1349
- parts.push("");
1350
- parts.push(`Save consolidated content to: \`${group.outputPath}\``);
1351
- parts.push("");
1352
- parts.push("**Guidelines:**");
1353
- parts.push("- Combine child sections into a coherent parent section");
1354
- parts.push("- Maintain the hierarchy (parent header, then children)");
1355
- parts.push("- Ensure smooth transitions between sections");
1356
- parts.push("- Preserve all content from child sections");
1357
- parts.push("");
1358
- return {
1359
- prompt: parts.join("\n"),
1360
- outputPath: group.outputPath
1361
- };
1362
- }
1363
1053
  function buildExecutePrompt(params) {
1364
1054
  const cwd = params.cwd || process.cwd();
1365
1055
  const config = loadConfig(cwd);
@@ -1910,131 +1600,6 @@ ${issues}`;
1910
1600
  onComplete: `verify-done ${state.taskId}`
1911
1601
  };
1912
1602
  }
1913
- /**
1914
- * Phase 3 (section mode): Parallel section generation
1915
- */
1916
- responsePhaseGenerateSections(state) {
1917
- if (!state.sectionPlan) {
1918
- throw new Error("Section plan not initialized");
1919
- }
1920
- const steps = this.getSteps();
1921
- const outputPath = this.getOutputPath();
1922
- let previousOutput;
1923
- if (state.stepIndex > 1) {
1924
- const prevStep = steps[state.stepIndex - 2];
1925
- const prevPath = join5(outputPath, state.taskId, `${prevStep}.md`);
1926
- if (existsSync5(prevPath)) {
1927
- previousOutput = prevPath;
1928
- }
1929
- }
1930
- const parallelSections = state.sectionPlan.leaves.map((leaf) => ({
1931
- id: leaf.id,
1932
- title: leaf.title,
1933
- outputPath: join5(outputPath, state.taskId, leaf.outputPath),
1934
- instruction: buildSectionInstruction(leaf, state.sectionPlan.sharedContext),
1935
- position: {
1936
- path: leaf.position.path,
1937
- siblings: leaf.position.siblings,
1938
- parent: leaf.position.parent
1939
- },
1940
- templateContent: leaf.templateContent
1941
- }));
1942
- return {
1943
- type: "phase",
1944
- phase: "generate-sections",
1945
- step: state.currentStep,
1946
- stepIndex: state.stepIndex,
1947
- totalSteps: state.totalSteps,
1948
- taskId: state.taskId,
1949
- description: state.description,
1950
- sharedContext: state.sectionPlan.sharedContext,
1951
- parallelSections,
1952
- consolidateOrder: state.sectionPlan.consolidateLevels,
1953
- context: {
1954
- instruction: this.getStepInstructionPath(state.currentStep),
1955
- template: this.getStepTemplatePath(state.currentStep),
1956
- previousOutput,
1957
- outputDir: join5(outputPath, state.taskId, "sections", state.currentStep)
1958
- },
1959
- onComplete: `sections-done ${state.taskId}`
1960
- };
1961
- }
1962
- /**
1963
- * Phase: Consolidate sections at a specific level
1964
- */
1965
- responsePhaseConsolidate(state, level) {
1966
- if (!state.sectionPlan) {
1967
- throw new Error("Section plan not initialized");
1968
- }
1969
- const outputPath = this.getOutputPath();
1970
- const parallelGroups = level.groups.map((group) => ({
1971
- ...group,
1972
- outputPath: join5(outputPath, state.taskId, group.outputPath)
1973
- }));
1974
- return {
1975
- type: "phase",
1976
- phase: "consolidate",
1977
- step: state.currentStep,
1978
- taskId: state.taskId,
1979
- level: level.depth,
1980
- parallelGroups,
1981
- sharedContext: state.sectionPlan.sharedContext,
1982
- onComplete: `consolidate-level-done ${state.taskId} ${level.depth}`
1983
- };
1984
- }
1985
- /**
1986
- * Validate that all section files exist before consolidation
1987
- */
1988
- validateConsolidateReady(state, level) {
1989
- const outputPath = this.getOutputPath();
1990
- const warnings = [];
1991
- const missing = [];
1992
- for (const group of level.groups) {
1993
- for (const childId of group.childIds) {
1994
- const findSection = (plan, id) => {
1995
- for (const leaf of plan.leaves) {
1996
- if (leaf.id === id) {
1997
- return leaf.outputPath;
1998
- }
1999
- }
2000
- for (const lvl of plan.consolidateLevels) {
2001
- for (const g of lvl.groups) {
2002
- if (g.parentId === id) {
2003
- return g.outputPath;
2004
- }
2005
- }
2006
- }
2007
- return void 0;
2008
- };
2009
- const childPath = findSection(state.sectionPlan, childId);
2010
- if (!childPath) {
2011
- missing.push(childId);
2012
- continue;
2013
- }
2014
- const fullPath = join5(outputPath, state.taskId, childPath);
2015
- if (!existsSync5(fullPath)) {
2016
- missing.push(childId);
2017
- } else {
2018
- const content = readFileSync5(fullPath, "utf-8");
2019
- if (!content.trim()) {
2020
- warnings.push(`Empty section file: ${childId}`);
2021
- }
2022
- if (!content.match(/^#+ /m)) {
2023
- warnings.push(`Section missing header: ${childId}`);
2024
- }
2025
- }
2026
- }
2027
- }
2028
- if (missing.length > 0) {
2029
- return {
2030
- valid: false,
2031
- error: `Missing section files: ${missing.join(", ")}`,
2032
- warnings,
2033
- missing
2034
- };
2035
- }
2036
- return { valid: true, warnings };
2037
- }
2038
1603
  /**
2039
1604
  * Checkpoint: Questions need answers
2040
1605
  */
@@ -2158,7 +1723,7 @@ ${issues}`;
2158
1723
  /**
2159
1724
  * Phase 2 complete: Questions generated (or none)
2160
1725
  * If questions exist → checkpoint
2161
- * If no questions → move to draft phase with accumulated answers
1726
+ * If no questions → move to execute phase with accumulated answers
2162
1727
  */
2163
1728
  cmdClarifyDone(taskId, questions) {
2164
1729
  const state = this.loadState(taskId);
@@ -2173,15 +1738,8 @@ ${issues}`;
2173
1738
  return this.responseCheckpointClarify(state);
2174
1739
  }
2175
1740
  state.answers = state.qaHistory?.map((entry) => entry.answer);
2176
- this.initSectionPlan(state);
2177
- if (state.sectionPlan) {
2178
- state.status = "phase_sections";
2179
- state.phase = "draft";
2180
- this.saveState(state);
2181
- return this.responsePhaseGenerateSections(state);
2182
- }
2183
1741
  state.status = "phase_execute";
2184
- state.phase = "draft";
1742
+ state.phase = "execute";
2185
1743
  state.verifyAttempts = 0;
2186
1744
  this.saveState(state);
2187
1745
  return this.responsePhaseExecute(state);
@@ -2391,110 +1949,6 @@ ${issues}`;
2391
1949
  this.saveState(state);
2392
1950
  return this.responseComplete(state, "stopped");
2393
1951
  }
2394
- // ===========================================================================
2395
- // Section-based Workflow Commands
2396
- // ===========================================================================
2397
- /**
2398
- * Initialize section-based generation for current step
2399
- * Called internally when template has sections
2400
- */
2401
- initSectionPlan(state) {
2402
- const templatePath = this.getStepTemplatePath(state.currentStep);
2403
- if (!existsSync5(templatePath)) {
2404
- return;
2405
- }
2406
- const template = readFileSync5(templatePath, "utf-8");
2407
- const instructionPath = this.getStepInstructionPath(state.currentStep);
2408
- const instructionSummary = existsSync5(instructionPath) ? readFileSync5(instructionPath, "utf-8").slice(0, 500) : "";
2409
- const plan = parseTemplateToTree(
2410
- template,
2411
- state.currentStep,
2412
- state.description,
2413
- `sections/${state.currentStep}`,
2414
- instructionSummary
2415
- );
2416
- if (plan.leaves.length > 1) {
2417
- state.sectionPlan = plan;
2418
- state.sectionStatuses = plan.leaves.map((leaf) => ({
2419
- id: leaf.id,
2420
- status: "pending",
2421
- outputPath: leaf.outputPath
2422
- }));
2423
- state.consolidateProgress = {
2424
- currentLevel: 0,
2425
- completedLevels: [],
2426
- totalLevels: plan.consolidateLevels.length
2427
- };
2428
- }
2429
- }
2430
- /**
2431
- * All sections completed, move to consolidation
2432
- */
2433
- cmdSectionsDone(taskId) {
2434
- const state = this.loadState(taskId);
2435
- if (!state) {
2436
- return this.responseError(`No workflow found: ${taskId}`, taskId);
2437
- }
2438
- if (!state.sectionPlan || !state.consolidateProgress) {
2439
- return this.responseError("No section plan found", taskId, state.currentStep);
2440
- }
2441
- if (state.sectionStatuses) {
2442
- state.sectionStatuses = state.sectionStatuses.map((s) => ({
2443
- ...s,
2444
- status: "completed"
2445
- }));
2446
- }
2447
- if (state.consolidateProgress.totalLevels > 0) {
2448
- state.status = "phase_consolidate";
2449
- state.consolidateProgress.currentLevel = 0;
2450
- this.saveState(state);
2451
- const firstLevel = state.sectionPlan.consolidateLevels[0];
2452
- const validation = this.validateConsolidateReady(state, firstLevel);
2453
- if (!validation.valid) {
2454
- return this.responseError(
2455
- validation.error || "Validation failed",
2456
- taskId,
2457
- state.currentStep
2458
- );
2459
- }
2460
- return this.responsePhaseConsolidate(state, firstLevel);
2461
- }
2462
- state.status = "approve_pending";
2463
- state.phase = "review";
2464
- this.saveState(state);
2465
- return this.responseCheckpointApprove(state);
2466
- }
2467
- /**
2468
- * Consolidation level completed, move to next level or approve
2469
- */
2470
- cmdConsolidateLevelDone(taskId, level) {
2471
- const state = this.loadState(taskId);
2472
- if (!state) {
2473
- return this.responseError(`No workflow found: ${taskId}`, taskId);
2474
- }
2475
- if (!state.sectionPlan || !state.consolidateProgress) {
2476
- return this.responseError("No section plan found", taskId, state.currentStep);
2477
- }
2478
- state.consolidateProgress.completedLevels.push(level);
2479
- state.consolidateProgress.currentLevel++;
2480
- if (state.consolidateProgress.currentLevel < state.consolidateProgress.totalLevels) {
2481
- this.saveState(state);
2482
- const nextLevel = state.sectionPlan.consolidateLevels[state.consolidateProgress.currentLevel];
2483
- const validation = this.validateConsolidateReady(state, nextLevel);
2484
- if (!validation.valid) {
2485
- return this.responseError(
2486
- validation.error || "Validation failed",
2487
- taskId,
2488
- state.currentStep
2489
- );
2490
- }
2491
- return this.responsePhaseConsolidate(state, nextLevel);
2492
- }
2493
- state.status = "approve_pending";
2494
- state.phase = "review";
2495
- this.saveState(state);
2496
- return this.responseCheckpointApprove(state);
2497
- }
2498
1952
  /**
2499
1953
  * Get current workflow status
2500
1954
  */
@@ -2527,15 +1981,6 @@ ${issues}`;
2527
1981
  return this.responsePhaseExecute(state);
2528
1982
  case "phase_verify":
2529
1983
  return this.responsePhaseVerify(state);
2530
- // Section-based workflow
2531
- case "phase_sections":
2532
- return this.responsePhaseGenerateSections(state);
2533
- case "phase_consolidate":
2534
- if (state.sectionPlan && state.consolidateProgress) {
2535
- const level = state.sectionPlan.consolidateLevels[state.consolidateProgress.currentLevel];
2536
- return this.responsePhaseConsolidate(state, level);
2537
- }
2538
- return this.responseError("Invalid consolidate state", taskId);
2539
1984
  // Checkpoints and completion
2540
1985
  case "approve_pending":
2541
1986
  return this.responseCheckpointApprove(state);
@@ -2557,10 +2002,9 @@ ${issues}`;
2557
2002
  };
2558
2003
 
2559
2004
  // src/core/step-executor.ts
2560
- import { existsSync as existsSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "fs";
2561
- import { dirname as dirname3, join as join6 } from "path";
2005
+ import { existsSync as existsSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
2006
+ import { join as join6 } from "path";
2562
2007
  import matter3 from "gray-matter";
2563
- var fsExistsSync = existsSync6;
2564
2008
  var StepExecutor = class {
2565
2009
  adapter;
2566
2010
  config;
@@ -2802,159 +2246,6 @@ var StepExecutor = class {
2802
2246
  };
2803
2247
  }
2804
2248
  // ==========================================================================
2805
- // Phase 3 (Section Mode): Parallel Section Generation
2806
- // ==========================================================================
2807
- /**
2808
- * Execute section generation phase - AI creates individual sections in parallel
2809
- */
2810
- async executeSectionsPhase(sections, sharedContext, gatheredContext, answers) {
2811
- this.adapter.io.notify(
2812
- `Phase 3/4: Generating ${sections.length} sections in parallel`,
2813
- "info"
2814
- );
2815
- const executeParams = sections.map((section) => {
2816
- const params = {
2817
- section: {
2818
- id: section.id,
2819
- title: section.title,
2820
- outputPath: section.outputPath,
2821
- instruction: section.instruction,
2822
- position: section.position,
2823
- templateContent: section.templateContent
2824
- },
2825
- sharedContext,
2826
- gatheredContext,
2827
- answers
2828
- };
2829
- const { prompt, outputPath } = buildSectionPrompt(params);
2830
- return { id: section.id, prompt, outputPath };
2831
- });
2832
- let results;
2833
- if (this.adapter.ai.executeParallel) {
2834
- const parallelResults = await this.adapter.ai.executeParallel(executeParams);
2835
- results = parallelResults.map((r) => {
2836
- const param = executeParams.find((p) => p.id === r.id);
2837
- if (r.success && param && !fsExistsSync(param.outputPath)) {
2838
- return { id: r.id, success: false, error: `File not created: ${param.outputPath}` };
2839
- }
2840
- return { id: r.id, success: r.success, error: r.error };
2841
- });
2842
- } else {
2843
- results = await Promise.all(
2844
- executeParams.map(async ({ id, prompt, outputPath }) => {
2845
- try {
2846
- const dir = dirname3(outputPath);
2847
- if (!fsExistsSync(dir)) {
2848
- mkdirSync4(dir, { recursive: true });
2849
- }
2850
- await this.adapter.ai.execute({ prompt, outputPath });
2851
- if (!fsExistsSync(outputPath)) {
2852
- return { id, success: false, error: `File not created: ${outputPath}` };
2853
- }
2854
- this.adapter.io.notify(`Section created: ${id}`, "success");
2855
- return { id, success: true };
2856
- } catch (error) {
2857
- return {
2858
- id,
2859
- success: false,
2860
- error: error instanceof Error ? error.message : String(error)
2861
- };
2862
- }
2863
- })
2864
- );
2865
- }
2866
- const failures = results.filter((r) => !r.success);
2867
- if (failures.length > 0) {
2868
- const errorMsg = failures.map((f) => `${f.id}: ${f.error}`).join(", ");
2869
- throw new Error(`Section generation failed: ${errorMsg}`);
2870
- }
2871
- return { phase: "generate" };
2872
- }
2873
- /**
2874
- * Execute consolidation phase - AI merges child sections into parent
2875
- */
2876
- async executeConsolidatePhase(groups, sharedContext, getSectionPath) {
2877
- this.adapter.io.notify(
2878
- `Consolidating ${groups.length} section groups`,
2879
- "info"
2880
- );
2881
- const executeParams = [];
2882
- for (const group of groups) {
2883
- const childContents = [];
2884
- let hasError = false;
2885
- for (const childId of group.childIds) {
2886
- const childPath = getSectionPath(childId);
2887
- if (!childPath || !fsExistsSync(childPath)) {
2888
- executeParams.push({ id: group.parentId, error: `Child section not found: ${childId}` });
2889
- hasError = true;
2890
- break;
2891
- }
2892
- childContents.push({
2893
- id: childId,
2894
- content: readFileSync6(childPath, "utf-8")
2895
- });
2896
- }
2897
- if (hasError) continue;
2898
- const params = {
2899
- group: {
2900
- parentId: group.parentId,
2901
- childIds: group.childIds,
2902
- outputPath: group.outputPath
2903
- },
2904
- childContents,
2905
- sharedContext
2906
- };
2907
- const { prompt, outputPath } = buildConsolidatePrompt(params);
2908
- executeParams.push({ id: group.parentId, prompt, outputPath });
2909
- }
2910
- const earlyErrors = executeParams.filter((p) => "error" in p);
2911
- if (earlyErrors.length > 0) {
2912
- const errorMsg = earlyErrors.map((e) => `${e.id}: ${e.error}`).join(", ");
2913
- throw new Error(`Consolidation failed: ${errorMsg}`);
2914
- }
2915
- const validParams = executeParams;
2916
- let results;
2917
- if (this.adapter.ai.executeParallel) {
2918
- const parallelResults = await this.adapter.ai.executeParallel(validParams);
2919
- results = parallelResults.map((r) => {
2920
- const param = validParams.find((p) => p.id === r.id);
2921
- if (r.success && param && !fsExistsSync(param.outputPath)) {
2922
- return { id: r.id, success: false, error: `File not created: ${param.outputPath}` };
2923
- }
2924
- return { id: r.id, success: r.success, error: r.error };
2925
- });
2926
- } else {
2927
- results = await Promise.all(
2928
- validParams.map(async ({ id, prompt, outputPath }) => {
2929
- try {
2930
- const dir = dirname3(outputPath);
2931
- if (!fsExistsSync(dir)) {
2932
- mkdirSync4(dir, { recursive: true });
2933
- }
2934
- await this.adapter.ai.execute({ prompt, outputPath });
2935
- if (!fsExistsSync(outputPath)) {
2936
- return { id, success: false, error: `File not created: ${outputPath}` };
2937
- }
2938
- this.adapter.io.notify(`Consolidated: ${id}`, "success");
2939
- return { id, success: true };
2940
- } catch (error) {
2941
- return {
2942
- id,
2943
- success: false,
2944
- error: error instanceof Error ? error.message : String(error)
2945
- };
2946
- }
2947
- })
2948
- );
2949
- }
2950
- const failures = results.filter((r) => !r.success);
2951
- if (failures.length > 0) {
2952
- const errorMsg = failures.map((f) => `${f.id}: ${f.error}`).join(", ");
2953
- throw new Error(`Consolidation failed: ${errorMsg}`);
2954
- }
2955
- return { phase: "generate" };
2956
- }
2957
- // ==========================================================================
2958
2249
  // Phase 4: Review (Approval)
2959
2250
  // ==========================================================================
2960
2251
  /**
@@ -3156,8 +2447,8 @@ var StepExecutor = class {
3156
2447
 
3157
2448
  // src/adapters/cli.ts
3158
2449
  import { spawn, spawnSync } from "child_process";
3159
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync7, mkdirSync as mkdirSync5 } from "fs";
3160
- import { dirname as dirname4 } from "path";
2450
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
2451
+ import { dirname as dirname3 } from "path";
3161
2452
  import { input, select, confirm } from "@inquirer/prompts";
3162
2453
  var CLIAIAdapter = class {
3163
2454
  claudeCommand;
@@ -3168,9 +2459,9 @@ var CLIAIAdapter = class {
3168
2459
  console.log(`
3169
2460
  \u{1F4DD} Generating...`);
3170
2461
  if (params.outputPath) {
3171
- const outputDir = dirname4(params.outputPath);
2462
+ const outputDir = dirname3(params.outputPath);
3172
2463
  if (!existsSync7(outputDir)) {
3173
- mkdirSync5(outputDir, { recursive: true });
2464
+ mkdirSync4(outputDir, { recursive: true });
3174
2465
  }
3175
2466
  }
3176
2467
  const stdout = await this.callClaude(params.prompt);
@@ -3251,9 +2542,9 @@ var CLIAIAdapter = class {
3251
2542
  const id = p.id || p.outputPath;
3252
2543
  try {
3253
2544
  if (p.outputPath) {
3254
- const outputDir = dirname4(p.outputPath);
2545
+ const outputDir = dirname3(p.outputPath);
3255
2546
  if (!existsSync7(outputDir)) {
3256
- mkdirSync5(outputDir, { recursive: true });
2547
+ mkdirSync4(outputDir, { recursive: true });
3257
2548
  }
3258
2549
  }
3259
2550
  await this.callClaude(p.prompt, false);
@@ -3358,9 +2649,9 @@ var CLISystemAdapter = class {
3358
2649
  return readFileSync7(path, "utf-8");
3359
2650
  }
3360
2651
  writeFile(path, content) {
3361
- const dir = dirname4(path);
2652
+ const dir = dirname3(path);
3362
2653
  if (!existsSync7(dir)) {
3363
- mkdirSync5(dir, { recursive: true });
2654
+ mkdirSync4(dir, { recursive: true });
3364
2655
  }
3365
2656
  writeFileSync5(path, content);
3366
2657
  }
@@ -3396,8 +2687,8 @@ function createCLIAdapter(claudeCommand = "claude") {
3396
2687
 
3397
2688
  // src/adapters/github.ts
3398
2689
  import { spawn as spawn2, spawnSync as spawnSync2 } from "child_process";
3399
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync8, mkdirSync as mkdirSync6 } from "fs";
3400
- import { dirname as dirname5 } from "path";
2690
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync8, mkdirSync as mkdirSync5 } from "fs";
2691
+ import { dirname as dirname4 } from "path";
3401
2692
  var GitHubAIAdapter = class {
3402
2693
  claudeCommand;
3403
2694
  constructor(claudeCommand = "claude") {
@@ -3407,9 +2698,9 @@ var GitHubAIAdapter = class {
3407
2698
  console.log(`
3408
2699
  \u{1F4DD} Generating...`);
3409
2700
  if (params.outputPath) {
3410
- const outputDir = dirname5(params.outputPath);
2701
+ const outputDir = dirname4(params.outputPath);
3411
2702
  if (!existsSync8(outputDir)) {
3412
- mkdirSync6(outputDir, { recursive: true });
2703
+ mkdirSync5(outputDir, { recursive: true });
3413
2704
  }
3414
2705
  }
3415
2706
  const stdout = await this.callClaude(params.prompt);
@@ -3465,9 +2756,9 @@ var GitHubAIAdapter = class {
3465
2756
  const id = p.id || p.outputPath;
3466
2757
  try {
3467
2758
  if (p.outputPath) {
3468
- const outputDir = dirname5(p.outputPath);
2759
+ const outputDir = dirname4(p.outputPath);
3469
2760
  if (!existsSync8(outputDir)) {
3470
- mkdirSync6(outputDir, { recursive: true });
2761
+ mkdirSync5(outputDir, { recursive: true });
3471
2762
  }
3472
2763
  }
3473
2764
  await this.callClaude(p.prompt);
@@ -3640,9 +2931,9 @@ var GitHubSystemAdapter = class {
3640
2931
  return readFileSync8(path, "utf-8");
3641
2932
  }
3642
2933
  writeFile(path, content) {
3643
- const dir = dirname5(path);
2934
+ const dir = dirname4(path);
3644
2935
  if (!existsSync8(dir)) {
3645
- mkdirSync6(dir, { recursive: true });
2936
+ mkdirSync5(dir, { recursive: true });
3646
2937
  }
3647
2938
  writeFileSync6(path, content);
3648
2939
  }
@@ -4275,7 +3566,7 @@ Resume with: spets resume --task ${taskId}`);
4275
3566
  }
4276
3567
 
4277
3568
  // src/commands/plugin.ts
4278
- import { existsSync as existsSync10, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7, rmSync } from "fs";
3569
+ import { existsSync as existsSync10, mkdirSync as mkdirSync6, writeFileSync as writeFileSync7, rmSync } from "fs";
4279
3570
  import { join as join8 } from "path";
4280
3571
  import { homedir } from "os";
4281
3572
  async function pluginCommand(action, name) {
@@ -4320,7 +3611,7 @@ async function installPlugin(name) {
4320
3611
  function installClaudePlugin() {
4321
3612
  const claudeDir = join8(homedir(), ".claude");
4322
3613
  const commandsDir = join8(claudeDir, "commands");
4323
- mkdirSync7(commandsDir, { recursive: true });
3614
+ mkdirSync6(commandsDir, { recursive: true });
4324
3615
  const skillPath = join8(commandsDir, "spets.md");
4325
3616
  writeFileSync7(skillPath, getClaudeSkillContent());
4326
3617
  console.log("Installed Claude Code plugin.");
@@ -4406,8 +3697,6 @@ Parse JSON response \u2192 execute action from table below \u2192 loop until \`t
4406
3697
  | \`clarify\` | [ACTION_CLARIFY](#action_clarify) |
4407
3698
  | \`execute\` | [ACTION_EXECUTE](#action_execute) |
4408
3699
  | \`verify\` | [ACTION_VERIFY](#action_verify) |
4409
- | \`generate-sections\` | [ACTION_PARALLEL_SECTIONS](#action_parallel_sections) |
4410
- | \`consolidate\` | [ACTION_PARALLEL_CONSOLIDATE](#action_parallel_consolidate) |
4411
3700
  | \`context\` | [ACTION_CONTEXT](#action_context) (legacy) |
4412
3701
  | \`generate\` | [ACTION_GENERATE](#action_generate) (legacy) |
4413
3702
 
@@ -4515,65 +3804,6 @@ This ensures identical behavior across CLI, Claude Code, and GitHub modes.
4515
3804
  5. Parse response \u2192 next action
4516
3805
  \`\`\`
4517
3806
 
4518
- ### ACTION_PARALLEL_SECTIONS
4519
-
4520
- **PARALLEL EXECUTION (FOREGROUND)**
4521
-
4522
- \`\`\`
4523
- 1. FOR EACH section IN parallelSections:
4524
- Task(
4525
- subagent_type: "general-purpose",
4526
- prompt: "
4527
- Generate section and save to file. Return ONLY the path.
4528
-
4529
- Path: {section.outputPath}
4530
- Title: {section.title}
4531
- Instruction: {section.instruction}
4532
- Context: {sharedContext.description}
4533
-
4534
- 1. Generate content for this section
4535
- 2. Write to the path using Write tool
4536
- 3. Return ONLY: {section.outputPath}
4537
- (no explanations, no content, just the path)
4538
- "
4539
- )
4540
-
4541
- 2. ALL Task calls MUST be in SINGLE message (parallel execution)
4542
-
4543
- 3. Bash: npx spets orchestrate sections-done {taskId}
4544
-
4545
- 4. Parse response \u2192 next action
4546
- \`\`\`
4547
-
4548
- ### ACTION_PARALLEL_CONSOLIDATE
4549
-
4550
- **PARALLEL EXECUTION (FOREGROUND)**
4551
-
4552
- \`\`\`
4553
- 1. FOR EACH group IN parallelGroups:
4554
- Task(
4555
- subagent_type: "general-purpose",
4556
- prompt: "
4557
- Merge children into parent. Return ONLY the path.
4558
-
4559
- Output: {group.outputPath}
4560
- Children: {group.childPaths}
4561
-
4562
- 1. Read each child file
4563
- 2. Merge preserving hierarchy
4564
- 3. Write to output using Write tool
4565
- 4. Return ONLY: {group.outputPath}
4566
- (no explanations, no content, just the path)
4567
- "
4568
- )
4569
-
4570
- 2. ALL Task calls MUST be in SINGLE message (parallel execution)
4571
-
4572
- 3. Bash: npx spets orchestrate consolidate-level-done {taskId} {level}
4573
-
4574
- 4. Parse response \u2192 next action
4575
- \`\`\`
4576
-
4577
3807
  ### ACTION_ASK_QUESTIONS
4578
3808
 
4579
3809
  \`\`\`
@@ -4645,10 +3875,6 @@ npx spets orchestrate revise <taskId> "<feedback>"
4645
3875
  npx spets orchestrate reject <taskId>
4646
3876
  npx spets orchestrate stop <taskId>
4647
3877
 
4648
- # Section-based workflow
4649
- npx spets orchestrate sections-done <taskId>
4650
- npx spets orchestrate consolidate-level-done <taskId> <level>
4651
-
4652
3878
  # Legacy (backward compatible)
4653
3879
  npx spets orchestrate context-done <taskId>
4654
3880
  npx spets orchestrate generate-done <taskId>
@@ -5388,35 +4614,8 @@ async function orchestrateCommand(action, args) {
5388
4614
  outputJSON(result);
5389
4615
  break;
5390
4616
  }
5391
- // Section-based workflow commands
5392
- case "sections-done": {
5393
- const taskId = args[0];
5394
- if (!taskId) {
5395
- outputError("Task ID is required for sections-done");
5396
- return;
5397
- }
5398
- const result = orchestrator.cmdSectionsDone(taskId);
5399
- outputJSON(result);
5400
- break;
5401
- }
5402
- case "consolidate-level-done": {
5403
- const taskId = args[0];
5404
- const levelStr = args[1];
5405
- if (!taskId || !levelStr) {
5406
- outputError("Task ID and level are required for consolidate-level-done");
5407
- return;
5408
- }
5409
- const level = parseInt(levelStr, 10);
5410
- if (isNaN(level)) {
5411
- outputError("Level must be a number");
5412
- return;
5413
- }
5414
- const result = orchestrator.cmdConsolidateLevelDone(taskId, level);
5415
- outputJSON(result);
5416
- break;
5417
- }
5418
4617
  default:
5419
- outputError(`Unknown action: ${action}. Valid actions: init, explore-done, clarify-done, execute-done, verify-done, clarified, approve, revise, reject, stop, status, sections-done, consolidate-level-done (legacy: context-done, generate-done, draft-done, done)`);
4618
+ outputError(`Unknown action: ${action}. Valid actions: init, explore-done, clarify-done, execute-done, verify-done, clarified, approve, revise, reject, stop, status (legacy: context-done, generate-done, draft-done, done)`);
5420
4619
  }
5421
4620
  } catch (e) {
5422
4621
  outputError(e.message);
@@ -5424,7 +4623,7 @@ async function orchestrateCommand(action, args) {
5424
4623
  }
5425
4624
 
5426
4625
  // src/index.ts
5427
- var __dirname2 = dirname6(fileURLToPath2(import.meta.url));
4626
+ var __dirname2 = dirname5(fileURLToPath2(import.meta.url));
5428
4627
  var pkg = JSON.parse(readFileSync11(join11(__dirname2, "..", "package.json"), "utf-8"));
5429
4628
  var program = new Command();
5430
4629
  program.name("spets").description("Spec Driven Development Execution Framework").version(pkg.version);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spets",
3
- "version": "0.1.40",
3
+ "version": "0.1.42",
4
4
  "description": "Spec Driven Development Execution Framework",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",