spets 0.1.38 → 0.1.40
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/dist/index.js +1624 -638
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -725,8 +725,8 @@ function formatDocStatus(status) {
|
|
|
725
725
|
import { execSync as execSync2 } from "child_process";
|
|
726
726
|
|
|
727
727
|
// src/orchestrator/index.ts
|
|
728
|
-
import { readFileSync as
|
|
729
|
-
import { join as
|
|
728
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
|
|
729
|
+
import { join as join5, dirname as dirname2 } from "path";
|
|
730
730
|
import matter2 from "gray-matter";
|
|
731
731
|
|
|
732
732
|
// src/core/section-tree.ts
|
|
@@ -934,66 +934,732 @@ Save to: ${section.outputPath}
|
|
|
934
934
|
`;
|
|
935
935
|
}
|
|
936
936
|
|
|
937
|
-
// src/
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
937
|
+
// src/core/prompt-builder.ts
|
|
938
|
+
import { readFileSync as readFileSync4, existsSync as existsSync4 } from "fs";
|
|
939
|
+
import { join as join4 } from "path";
|
|
940
|
+
function buildContextPrompt(params) {
|
|
941
|
+
const cwd = params.cwd || process.cwd();
|
|
942
|
+
const stepsDir = getStepsDir(cwd);
|
|
943
|
+
const isFirstStep = params.stepIndex === 1;
|
|
944
|
+
const instructionPath = join4(stepsDir, params.step, "instruction.md");
|
|
945
|
+
const instruction = existsSync4(instructionPath) ? readFileSync4(instructionPath, "utf-8") : "";
|
|
946
|
+
const parts = [];
|
|
947
|
+
parts.push("# Context Gathering Phase");
|
|
948
|
+
parts.push("");
|
|
949
|
+
parts.push("Your task is to gather context before generating a document.");
|
|
950
|
+
parts.push("Do NOT generate the document yet - only gather information.");
|
|
951
|
+
parts.push("");
|
|
952
|
+
parts.push("## Task Information");
|
|
953
|
+
parts.push("");
|
|
954
|
+
parts.push(`- **Task ID**: ${params.taskId}`);
|
|
955
|
+
parts.push(`- **Current Step**: ${params.step} (${params.stepIndex}/${params.totalSteps})`);
|
|
956
|
+
parts.push("");
|
|
957
|
+
if (isFirstStep) {
|
|
958
|
+
parts.push("## User Request");
|
|
959
|
+
parts.push("");
|
|
960
|
+
parts.push(`> ${params.description}`);
|
|
961
|
+
parts.push("");
|
|
962
|
+
} else if (params.previousOutput) {
|
|
963
|
+
parts.push("## Previous Step Output");
|
|
964
|
+
parts.push("");
|
|
965
|
+
if (existsSync4(params.previousOutput)) {
|
|
966
|
+
parts.push(readFileSync4(params.previousOutput, "utf-8"));
|
|
967
|
+
}
|
|
968
|
+
parts.push("");
|
|
942
969
|
}
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
970
|
+
if (instruction) {
|
|
971
|
+
parts.push("## Step Instruction (Preview)");
|
|
972
|
+
parts.push("");
|
|
973
|
+
parts.push("The next phase will use this instruction to generate a document:");
|
|
974
|
+
parts.push("");
|
|
975
|
+
parts.push("```");
|
|
976
|
+
parts.push(instruction.slice(0, 500) + (instruction.length > 500 ? "..." : ""));
|
|
977
|
+
parts.push("```");
|
|
978
|
+
parts.push("");
|
|
949
979
|
}
|
|
950
|
-
|
|
951
|
-
|
|
980
|
+
parts.push("## Your Task");
|
|
981
|
+
parts.push("");
|
|
982
|
+
parts.push("1. **Analyze** the request/input to understand what is being asked");
|
|
983
|
+
parts.push("2. **Search** the codebase for relevant files, patterns, conventions");
|
|
984
|
+
parts.push("3. **Identify** key constraints, dependencies, and considerations");
|
|
985
|
+
parts.push("");
|
|
986
|
+
parts.push("## Output Format");
|
|
987
|
+
parts.push("");
|
|
988
|
+
parts.push("Output a JSON object with this structure:");
|
|
989
|
+
parts.push("");
|
|
990
|
+
parts.push("```json");
|
|
991
|
+
parts.push("{");
|
|
992
|
+
parts.push(' "summary": "Brief summary of what you understood and found",');
|
|
993
|
+
parts.push(' "relevantFiles": ["path/to/file1.ts", "path/to/file2.ts"],');
|
|
994
|
+
parts.push(' "keyFindings": [');
|
|
995
|
+
parts.push(' "Finding 1: description",');
|
|
996
|
+
parts.push(' "Finding 2: description"');
|
|
997
|
+
parts.push(" ]");
|
|
998
|
+
parts.push("}");
|
|
999
|
+
parts.push("```");
|
|
1000
|
+
parts.push("");
|
|
1001
|
+
parts.push("**Important:** Output ONLY the JSON, no other text.");
|
|
1002
|
+
parts.push("");
|
|
1003
|
+
return parts.join("\n");
|
|
1004
|
+
}
|
|
1005
|
+
function buildExplorePrompt(params) {
|
|
1006
|
+
const cwd = params.cwd || process.cwd();
|
|
1007
|
+
const stepsDir = getStepsDir(cwd);
|
|
1008
|
+
const isFirstStep = params.stepIndex === 1;
|
|
1009
|
+
const instructionPath = join4(stepsDir, params.step, "instruction.md");
|
|
1010
|
+
const instruction = existsSync4(instructionPath) ? readFileSync4(instructionPath, "utf-8") : "";
|
|
1011
|
+
const parts = [];
|
|
1012
|
+
parts.push("# Explore Phase - Deep Codebase Analysis");
|
|
1013
|
+
parts.push("");
|
|
1014
|
+
parts.push("Your task is to deeply explore the codebase to understand context for document generation.");
|
|
1015
|
+
parts.push("**IMPORTANT:** Do NOT just list files. You MUST read file contents and analyze them.");
|
|
1016
|
+
parts.push("");
|
|
1017
|
+
parts.push("## Task Information");
|
|
1018
|
+
parts.push("");
|
|
1019
|
+
parts.push(`- **Task ID**: ${params.taskId}`);
|
|
1020
|
+
parts.push(`- **Current Step**: ${params.step} (${params.stepIndex}/${params.totalSteps})`);
|
|
1021
|
+
parts.push("");
|
|
1022
|
+
if (isFirstStep) {
|
|
1023
|
+
parts.push("## User Request");
|
|
1024
|
+
parts.push("");
|
|
1025
|
+
parts.push(`> ${params.description}`);
|
|
1026
|
+
parts.push("");
|
|
1027
|
+
} else if (params.previousOutput) {
|
|
1028
|
+
parts.push("## Previous Step Output");
|
|
1029
|
+
parts.push("");
|
|
1030
|
+
if (existsSync4(params.previousOutput)) {
|
|
1031
|
+
parts.push(readFileSync4(params.previousOutput, "utf-8"));
|
|
1032
|
+
}
|
|
1033
|
+
parts.push("");
|
|
952
1034
|
}
|
|
953
|
-
|
|
954
|
-
|
|
1035
|
+
if (instruction) {
|
|
1036
|
+
parts.push("## Step Instruction (Preview)");
|
|
1037
|
+
parts.push("");
|
|
1038
|
+
parts.push("The document to be generated must follow this instruction:");
|
|
1039
|
+
parts.push("");
|
|
1040
|
+
parts.push("```");
|
|
1041
|
+
parts.push(instruction.slice(0, 1e3) + (instruction.length > 1e3 ? "\n...(truncated)" : ""));
|
|
1042
|
+
parts.push("```");
|
|
1043
|
+
parts.push("");
|
|
955
1044
|
}
|
|
956
|
-
|
|
957
|
-
|
|
1045
|
+
parts.push("## Your Task");
|
|
1046
|
+
parts.push("");
|
|
1047
|
+
parts.push("1. **Search** for relevant files using patterns (Glob, Grep)");
|
|
1048
|
+
parts.push("2. **Read** the content of important files (not just paths)");
|
|
1049
|
+
parts.push("3. **Analyze** code patterns, naming conventions, architecture");
|
|
1050
|
+
parts.push('4. **Identify** constraints (e.g., "uses TypeScript strict mode")');
|
|
1051
|
+
parts.push("5. **Find** dependencies (internal and external)");
|
|
1052
|
+
parts.push("");
|
|
1053
|
+
parts.push("**Key difference from context phase:** You must READ file contents, not just list them.");
|
|
1054
|
+
parts.push("");
|
|
1055
|
+
parts.push("## Output Format");
|
|
1056
|
+
parts.push("");
|
|
1057
|
+
parts.push("Output a JSON object with this structure:");
|
|
1058
|
+
parts.push("");
|
|
1059
|
+
parts.push("```json");
|
|
1060
|
+
parts.push("{");
|
|
1061
|
+
parts.push(' "summary": "Comprehensive summary of what you found and understood",');
|
|
1062
|
+
parts.push(' "relevantFiles": [');
|
|
1063
|
+
parts.push(" {");
|
|
1064
|
+
parts.push(' "path": "src/core/example.ts",');
|
|
1065
|
+
parts.push(' "purpose": "Why this file is relevant",');
|
|
1066
|
+
parts.push(' "keySnippets": ["function doSomething() {...}", "export interface Config {...}"]');
|
|
1067
|
+
parts.push(" }");
|
|
1068
|
+
parts.push(" ],");
|
|
1069
|
+
parts.push(' "patterns": [');
|
|
1070
|
+
parts.push(' "Uses dependency injection pattern",');
|
|
1071
|
+
parts.push(' "All exports are named (no default exports)"');
|
|
1072
|
+
parts.push(" ],");
|
|
1073
|
+
parts.push(' "constraints": [');
|
|
1074
|
+
parts.push(' "TypeScript strict mode enabled",');
|
|
1075
|
+
parts.push(' "Must maintain backward compatibility"');
|
|
1076
|
+
parts.push(" ],");
|
|
1077
|
+
parts.push(' "dependencies": [');
|
|
1078
|
+
parts.push(' "gray-matter for frontmatter parsing",');
|
|
1079
|
+
parts.push(' "Internal: uses ../core/config.js"');
|
|
1080
|
+
parts.push(" ]");
|
|
1081
|
+
parts.push("}");
|
|
1082
|
+
parts.push("```");
|
|
1083
|
+
parts.push("");
|
|
1084
|
+
parts.push("**Important:** Output ONLY the JSON, no other text.");
|
|
1085
|
+
parts.push("");
|
|
1086
|
+
return parts.join("\n");
|
|
1087
|
+
}
|
|
1088
|
+
function buildClarifyPrompt(params) {
|
|
1089
|
+
const cwd = params.cwd || process.cwd();
|
|
1090
|
+
const stepsDir = getStepsDir(cwd);
|
|
1091
|
+
const instructionPath = join4(stepsDir, params.step, "instruction.md");
|
|
1092
|
+
const instruction = existsSync4(instructionPath) ? readFileSync4(instructionPath, "utf-8") : "";
|
|
1093
|
+
const parts = [];
|
|
1094
|
+
parts.push("# Clarify Phase");
|
|
1095
|
+
parts.push("");
|
|
1096
|
+
parts.push("Your task is to identify any questions that need user input before generating the document.");
|
|
1097
|
+
parts.push("Do NOT generate the document yet - only generate questions if needed.");
|
|
1098
|
+
parts.push("");
|
|
1099
|
+
parts.push("## Task Information");
|
|
1100
|
+
parts.push("");
|
|
1101
|
+
parts.push(`- **Task ID**: ${params.taskId}`);
|
|
1102
|
+
parts.push(`- **Current Step**: ${params.step}`);
|
|
1103
|
+
parts.push(`- **Description**: ${params.description}`);
|
|
1104
|
+
parts.push("");
|
|
1105
|
+
parts.push("## Gathered Context");
|
|
1106
|
+
parts.push("");
|
|
1107
|
+
parts.push(params.gatheredContext);
|
|
1108
|
+
parts.push("");
|
|
1109
|
+
if (instruction) {
|
|
1110
|
+
parts.push("## Step Instruction");
|
|
1111
|
+
parts.push("");
|
|
1112
|
+
parts.push(instruction);
|
|
1113
|
+
parts.push("");
|
|
958
1114
|
}
|
|
959
|
-
|
|
960
|
-
|
|
1115
|
+
if (params.previousQA && params.previousQA.length > 0) {
|
|
1116
|
+
parts.push("## Previous Questions & Answers");
|
|
1117
|
+
parts.push("");
|
|
1118
|
+
parts.push("The following questions have already been asked and answered:");
|
|
1119
|
+
parts.push("");
|
|
1120
|
+
for (const entry of params.previousQA) {
|
|
1121
|
+
parts.push(`**Q: ${entry.question.question}**`);
|
|
1122
|
+
if (entry.question.context) {
|
|
1123
|
+
parts.push(`Context: ${entry.question.context}`);
|
|
1124
|
+
}
|
|
1125
|
+
parts.push(`A: ${entry.answer.answer}`);
|
|
1126
|
+
parts.push("");
|
|
1127
|
+
}
|
|
1128
|
+
parts.push("Based on these answers, determine if there are still ambiguities that need clarification.");
|
|
1129
|
+
parts.push("Do NOT repeat questions that have already been answered.");
|
|
1130
|
+
parts.push("");
|
|
961
1131
|
}
|
|
962
|
-
|
|
963
|
-
|
|
1132
|
+
parts.push("## Consider These Questions");
|
|
1133
|
+
parts.push("");
|
|
1134
|
+
parts.push("1. Is the task description clear enough to proceed?");
|
|
1135
|
+
parts.push("2. Are there multiple valid approaches that need user decision?");
|
|
1136
|
+
parts.push("3. Are there ambiguities that could lead to wrong implementation?");
|
|
1137
|
+
parts.push("4. Are there missing requirements or constraints?");
|
|
1138
|
+
parts.push("");
|
|
1139
|
+
parts.push("## Output Format");
|
|
1140
|
+
parts.push("");
|
|
1141
|
+
parts.push("Output a JSON object with questions array:");
|
|
1142
|
+
parts.push("");
|
|
1143
|
+
parts.push("```json");
|
|
1144
|
+
parts.push("{");
|
|
1145
|
+
parts.push(' "questions": [');
|
|
1146
|
+
parts.push(" {");
|
|
1147
|
+
parts.push(' "id": "q1",');
|
|
1148
|
+
parts.push(' "question": "Your specific question?",');
|
|
1149
|
+
parts.push(' "context": "Why this matters for the document",');
|
|
1150
|
+
parts.push(' "options": ["Option A", "Option B"] // optional');
|
|
1151
|
+
parts.push(" }");
|
|
1152
|
+
parts.push(" ]");
|
|
1153
|
+
parts.push("}");
|
|
1154
|
+
parts.push("```");
|
|
1155
|
+
parts.push("");
|
|
1156
|
+
parts.push('If no questions are needed, return: `{"questions": []}`');
|
|
1157
|
+
parts.push("");
|
|
1158
|
+
parts.push("**Important:** Output ONLY the JSON, no other text.");
|
|
1159
|
+
parts.push("");
|
|
1160
|
+
return parts.join("\n");
|
|
1161
|
+
}
|
|
1162
|
+
function buildGeneratePrompt(params) {
|
|
1163
|
+
const cwd = params.cwd || process.cwd();
|
|
1164
|
+
const config = loadConfig(cwd);
|
|
1165
|
+
const stepsDir = getStepsDir(cwd);
|
|
1166
|
+
const outputsDir = getOutputsDir(cwd);
|
|
1167
|
+
const isFirstStep = params.stepIndex === 1;
|
|
1168
|
+
const prevStep = params.stepIndex > 1 ? config.steps[params.stepIndex - 2] : null;
|
|
1169
|
+
const instructionPath = join4(stepsDir, params.step, "instruction.md");
|
|
1170
|
+
const templatePath = join4(stepsDir, params.step, "template.md");
|
|
1171
|
+
const outputPath = join4(outputsDir, params.taskId, `${params.step}.md`);
|
|
1172
|
+
if (!existsSync4(instructionPath)) {
|
|
1173
|
+
throw new Error(`Instruction not found: ${instructionPath}`);
|
|
964
1174
|
}
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
const
|
|
970
|
-
if (
|
|
971
|
-
|
|
1175
|
+
const instruction = readFileSync4(instructionPath, "utf-8");
|
|
1176
|
+
const template = existsSync4(templatePath) ? readFileSync4(templatePath, "utf-8") : null;
|
|
1177
|
+
let previousSpec = null;
|
|
1178
|
+
if (prevStep) {
|
|
1179
|
+
const prevPath = join4(outputsDir, params.taskId, `${prevStep}.md`);
|
|
1180
|
+
if (existsSync4(prevPath)) {
|
|
1181
|
+
previousSpec = {
|
|
1182
|
+
step: prevStep,
|
|
1183
|
+
content: readFileSync4(prevPath, "utf-8")
|
|
1184
|
+
};
|
|
972
1185
|
}
|
|
973
|
-
const data = JSON.parse(readFileSync4(statePath, "utf-8"));
|
|
974
|
-
return data;
|
|
975
1186
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1187
|
+
const parts = [];
|
|
1188
|
+
parts.push("# Document Generation Phase");
|
|
1189
|
+
parts.push("");
|
|
1190
|
+
parts.push("Generate the document based on the gathered context and user answers.");
|
|
1191
|
+
parts.push("");
|
|
1192
|
+
parts.push("## Step Instruction");
|
|
1193
|
+
parts.push("");
|
|
1194
|
+
parts.push(instruction);
|
|
1195
|
+
parts.push("");
|
|
1196
|
+
if (template) {
|
|
1197
|
+
parts.push("## Document Template");
|
|
1198
|
+
parts.push("");
|
|
1199
|
+
parts.push("**CRITICAL: You MUST follow this template structure completely.**");
|
|
1200
|
+
parts.push("");
|
|
1201
|
+
parts.push(template);
|
|
1202
|
+
parts.push("");
|
|
984
1203
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
1204
|
+
parts.push("## Gathered Context");
|
|
1205
|
+
parts.push("");
|
|
1206
|
+
parts.push(params.gatheredContext);
|
|
1207
|
+
parts.push("");
|
|
1208
|
+
if (params.answers && params.answers.length > 0) {
|
|
1209
|
+
parts.push("## User Answers");
|
|
1210
|
+
parts.push("");
|
|
1211
|
+
for (const answer of params.answers) {
|
|
1212
|
+
parts.push(`- **${answer.questionId}**: ${answer.answer}`);
|
|
991
1213
|
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
1214
|
+
parts.push("");
|
|
1215
|
+
}
|
|
1216
|
+
if (isFirstStep) {
|
|
1217
|
+
parts.push("## User Request");
|
|
1218
|
+
parts.push("");
|
|
1219
|
+
parts.push(`> ${params.description}`);
|
|
1220
|
+
parts.push("");
|
|
1221
|
+
} else if (previousSpec) {
|
|
1222
|
+
parts.push(`## Input: ${previousSpec.step}.md`);
|
|
1223
|
+
parts.push("");
|
|
1224
|
+
parts.push(previousSpec.content);
|
|
1225
|
+
parts.push("");
|
|
1226
|
+
}
|
|
1227
|
+
parts.push("## Task Context");
|
|
1228
|
+
parts.push("");
|
|
1229
|
+
parts.push(`- **Task ID**: ${params.taskId}`);
|
|
1230
|
+
parts.push(`- **Current Step**: ${params.step} (${params.stepIndex}/${params.totalSteps})`);
|
|
1231
|
+
parts.push("");
|
|
1232
|
+
if (params.revisionFeedback) {
|
|
1233
|
+
parts.push("## Revision Feedback");
|
|
1234
|
+
parts.push("");
|
|
1235
|
+
parts.push("Previous version was not approved. Please revise based on this feedback:");
|
|
1236
|
+
parts.push("");
|
|
1237
|
+
parts.push(`> ${params.revisionFeedback}`);
|
|
1238
|
+
parts.push("");
|
|
1239
|
+
}
|
|
1240
|
+
parts.push("## Output Instructions");
|
|
1241
|
+
parts.push("");
|
|
1242
|
+
parts.push(`Generate the document and save to: \`${outputPath}\``);
|
|
1243
|
+
parts.push("");
|
|
1244
|
+
parts.push("**Required frontmatter:**");
|
|
1245
|
+
parts.push("```yaml");
|
|
1246
|
+
parts.push("---");
|
|
1247
|
+
parts.push(`id: ${params.taskId}`);
|
|
1248
|
+
parts.push(`step: ${params.step}`);
|
|
1249
|
+
parts.push("status: pending_approval");
|
|
1250
|
+
parts.push("---");
|
|
1251
|
+
parts.push("```");
|
|
1252
|
+
parts.push("");
|
|
1253
|
+
return {
|
|
1254
|
+
prompt: parts.join("\n"),
|
|
1255
|
+
outputPath
|
|
1256
|
+
};
|
|
1257
|
+
}
|
|
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
|
+
function buildExecutePrompt(params) {
|
|
1364
|
+
const cwd = params.cwd || process.cwd();
|
|
1365
|
+
const config = loadConfig(cwd);
|
|
1366
|
+
const stepsDir = getStepsDir(cwd);
|
|
1367
|
+
const outputsDir = getOutputsDir(cwd);
|
|
1368
|
+
const isFirstStep = params.stepIndex === 1;
|
|
1369
|
+
const prevStep = params.stepIndex > 1 ? config.steps[params.stepIndex - 2] : null;
|
|
1370
|
+
const instructionPath = join4(stepsDir, params.step, "instruction.md");
|
|
1371
|
+
const templatePath = join4(stepsDir, params.step, "template.md");
|
|
1372
|
+
const outputPath = join4(outputsDir, params.taskId, `${params.step}.md`);
|
|
1373
|
+
if (!existsSync4(instructionPath)) {
|
|
1374
|
+
throw new Error(`Instruction not found: ${instructionPath}`);
|
|
1375
|
+
}
|
|
1376
|
+
const instruction = readFileSync4(instructionPath, "utf-8");
|
|
1377
|
+
const template = existsSync4(templatePath) ? readFileSync4(templatePath, "utf-8") : null;
|
|
1378
|
+
let previousSpec = null;
|
|
1379
|
+
if (prevStep) {
|
|
1380
|
+
const prevPath = join4(outputsDir, params.taskId, `${prevStep}.md`);
|
|
1381
|
+
if (existsSync4(prevPath)) {
|
|
1382
|
+
previousSpec = {
|
|
1383
|
+
step: prevStep,
|
|
1384
|
+
content: readFileSync4(prevPath, "utf-8")
|
|
1385
|
+
};
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
const parts = [];
|
|
1389
|
+
parts.push("# Execute Phase - Document/Code Generation");
|
|
1390
|
+
parts.push("");
|
|
1391
|
+
parts.push("Generate the document/code based on the explored context and user answers.");
|
|
1392
|
+
parts.push("");
|
|
1393
|
+
parts.push("## Step Instruction");
|
|
1394
|
+
parts.push("");
|
|
1395
|
+
parts.push(instruction);
|
|
1396
|
+
parts.push("");
|
|
1397
|
+
if (template) {
|
|
1398
|
+
parts.push("## Document Template");
|
|
1399
|
+
parts.push("");
|
|
1400
|
+
parts.push("**CRITICAL: You MUST follow this template structure completely.**");
|
|
1401
|
+
parts.push("");
|
|
1402
|
+
parts.push(template);
|
|
1403
|
+
parts.push("");
|
|
1404
|
+
}
|
|
1405
|
+
parts.push("## Explored Context");
|
|
1406
|
+
parts.push("");
|
|
1407
|
+
parts.push(`### Summary`);
|
|
1408
|
+
parts.push(params.exploreOutput.summary);
|
|
1409
|
+
parts.push("");
|
|
1410
|
+
if (params.exploreOutput.relevantFiles.length > 0) {
|
|
1411
|
+
parts.push("### Relevant Files");
|
|
1412
|
+
for (const file of params.exploreOutput.relevantFiles) {
|
|
1413
|
+
parts.push(`- **${file.path}**: ${file.purpose}`);
|
|
1414
|
+
if (file.keySnippets && file.keySnippets.length > 0) {
|
|
1415
|
+
parts.push(" ```");
|
|
1416
|
+
parts.push(" " + file.keySnippets.slice(0, 2).join("\n "));
|
|
1417
|
+
parts.push(" ```");
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
parts.push("");
|
|
1421
|
+
}
|
|
1422
|
+
if (params.exploreOutput.patterns.length > 0) {
|
|
1423
|
+
parts.push("### Patterns");
|
|
1424
|
+
for (const pattern of params.exploreOutput.patterns) {
|
|
1425
|
+
parts.push(`- ${pattern}`);
|
|
1426
|
+
}
|
|
1427
|
+
parts.push("");
|
|
1428
|
+
}
|
|
1429
|
+
if (params.exploreOutput.constraints.length > 0) {
|
|
1430
|
+
parts.push("### Constraints");
|
|
1431
|
+
for (const constraint of params.exploreOutput.constraints) {
|
|
1432
|
+
parts.push(`- ${constraint}`);
|
|
1433
|
+
}
|
|
1434
|
+
parts.push("");
|
|
1435
|
+
}
|
|
1436
|
+
if (params.exploreOutput.dependencies.length > 0) {
|
|
1437
|
+
parts.push("### Dependencies");
|
|
1438
|
+
for (const dep of params.exploreOutput.dependencies) {
|
|
1439
|
+
parts.push(`- ${dep}`);
|
|
1440
|
+
}
|
|
1441
|
+
parts.push("");
|
|
1442
|
+
}
|
|
1443
|
+
if (params.answers && params.answers.length > 0) {
|
|
1444
|
+
parts.push("## User Answers");
|
|
1445
|
+
parts.push("");
|
|
1446
|
+
for (const answer of params.answers) {
|
|
1447
|
+
parts.push(`- **${answer.questionId}**: ${answer.answer}`);
|
|
1448
|
+
}
|
|
1449
|
+
parts.push("");
|
|
1450
|
+
}
|
|
1451
|
+
if (isFirstStep) {
|
|
1452
|
+
parts.push("## User Request");
|
|
1453
|
+
parts.push("");
|
|
1454
|
+
parts.push(`> ${params.description}`);
|
|
1455
|
+
parts.push("");
|
|
1456
|
+
} else if (previousSpec) {
|
|
1457
|
+
parts.push(`## Input: ${previousSpec.step}.md`);
|
|
1458
|
+
parts.push("");
|
|
1459
|
+
parts.push(previousSpec.content);
|
|
1460
|
+
parts.push("");
|
|
1461
|
+
}
|
|
1462
|
+
parts.push("## Task Context");
|
|
1463
|
+
parts.push("");
|
|
1464
|
+
parts.push(`- **Task ID**: ${params.taskId}`);
|
|
1465
|
+
parts.push(`- **Current Step**: ${params.step} (${params.stepIndex}/${params.totalSteps})`);
|
|
1466
|
+
parts.push("");
|
|
1467
|
+
if (params.verifyFeedback) {
|
|
1468
|
+
parts.push("## Auto-Fix Required");
|
|
1469
|
+
parts.push("");
|
|
1470
|
+
parts.push("**Previous draft failed verification. Fix these issues:**");
|
|
1471
|
+
parts.push("");
|
|
1472
|
+
parts.push(params.verifyFeedback);
|
|
1473
|
+
parts.push("");
|
|
1474
|
+
}
|
|
1475
|
+
if (params.revisionFeedback) {
|
|
1476
|
+
parts.push("## Revision Feedback");
|
|
1477
|
+
parts.push("");
|
|
1478
|
+
parts.push("Previous version was not approved. Please revise based on this feedback:");
|
|
1479
|
+
parts.push("");
|
|
1480
|
+
parts.push(`> ${params.revisionFeedback}`);
|
|
1481
|
+
parts.push("");
|
|
1482
|
+
}
|
|
1483
|
+
parts.push("## Output Instructions");
|
|
1484
|
+
parts.push("");
|
|
1485
|
+
parts.push(`Generate the document and save to: \`${outputPath}\``);
|
|
1486
|
+
parts.push("");
|
|
1487
|
+
parts.push("**Required frontmatter:**");
|
|
1488
|
+
parts.push("```yaml");
|
|
1489
|
+
parts.push("---");
|
|
1490
|
+
parts.push(`id: ${params.taskId}`);
|
|
1491
|
+
parts.push(`step: ${params.step}`);
|
|
1492
|
+
parts.push("status: pending_approval");
|
|
1493
|
+
parts.push("---");
|
|
1494
|
+
parts.push("```");
|
|
1495
|
+
parts.push("");
|
|
1496
|
+
return {
|
|
1497
|
+
prompt: parts.join("\n"),
|
|
1498
|
+
outputPath
|
|
1499
|
+
};
|
|
1500
|
+
}
|
|
1501
|
+
function buildVerifyPrompt(params) {
|
|
1502
|
+
const cwd = params.cwd || process.cwd();
|
|
1503
|
+
const stepsDir = getStepsDir(cwd);
|
|
1504
|
+
const instructionPath = join4(stepsDir, params.step, "instruction.md");
|
|
1505
|
+
const templatePath = join4(stepsDir, params.step, "template.md");
|
|
1506
|
+
const instruction = existsSync4(instructionPath) ? readFileSync4(instructionPath, "utf-8") : "";
|
|
1507
|
+
const template = existsSync4(templatePath) ? readFileSync4(templatePath, "utf-8") : "";
|
|
1508
|
+
const document = existsSync4(params.documentPath) ? readFileSync4(params.documentPath, "utf-8") : "";
|
|
1509
|
+
const parts = [];
|
|
1510
|
+
parts.push("# Verify Phase - Self-Validation");
|
|
1511
|
+
parts.push("");
|
|
1512
|
+
parts.push("Your task is to validate the generated document against the requirements.");
|
|
1513
|
+
parts.push("This is an automated quality check before human review.");
|
|
1514
|
+
parts.push("");
|
|
1515
|
+
parts.push(`**Attempt ${params.verifyAttempts} of 3**`);
|
|
1516
|
+
parts.push("");
|
|
1517
|
+
parts.push("## Task Information");
|
|
1518
|
+
parts.push("");
|
|
1519
|
+
parts.push(`- **Task ID**: ${params.taskId}`);
|
|
1520
|
+
parts.push(`- **Current Step**: ${params.step} (${params.stepIndex}/${params.totalSteps})`);
|
|
1521
|
+
parts.push("");
|
|
1522
|
+
parts.push("## Document to Verify");
|
|
1523
|
+
parts.push("");
|
|
1524
|
+
parts.push("```markdown");
|
|
1525
|
+
parts.push(document);
|
|
1526
|
+
parts.push("```");
|
|
1527
|
+
parts.push("");
|
|
1528
|
+
parts.push("## Requirements (Instruction)");
|
|
1529
|
+
parts.push("");
|
|
1530
|
+
if (instruction) {
|
|
1531
|
+
parts.push(instruction);
|
|
1532
|
+
} else {
|
|
1533
|
+
parts.push("(No instruction found)");
|
|
1534
|
+
}
|
|
1535
|
+
parts.push("");
|
|
1536
|
+
if (template) {
|
|
1537
|
+
parts.push("## Expected Structure (Template)");
|
|
1538
|
+
parts.push("");
|
|
1539
|
+
parts.push(template);
|
|
1540
|
+
parts.push("");
|
|
1541
|
+
}
|
|
1542
|
+
parts.push("## Verification Checklist");
|
|
1543
|
+
parts.push("");
|
|
1544
|
+
parts.push("Evaluate the document against these criteria:");
|
|
1545
|
+
parts.push("");
|
|
1546
|
+
parts.push("1. **Requirements Coverage** (0-100)");
|
|
1547
|
+
parts.push(" - Does the document address all requirements from the instruction?");
|
|
1548
|
+
parts.push(" - Are there missing pieces?");
|
|
1549
|
+
parts.push("");
|
|
1550
|
+
parts.push("2. **Template Compliance** (0-100)");
|
|
1551
|
+
parts.push(" - Does it follow the template structure?");
|
|
1552
|
+
parts.push(" - Are all required sections present?");
|
|
1553
|
+
parts.push(" - Is frontmatter correct?");
|
|
1554
|
+
parts.push("");
|
|
1555
|
+
parts.push("3. **Consistency** (0-100)");
|
|
1556
|
+
parts.push(" - Is terminology consistent throughout?");
|
|
1557
|
+
parts.push(" - Are there contradictions?");
|
|
1558
|
+
parts.push(" - Does it align with explored codebase patterns?");
|
|
1559
|
+
parts.push("");
|
|
1560
|
+
parts.push("4. **Completeness** (0-100)");
|
|
1561
|
+
parts.push(" - Are all sections fully filled in?");
|
|
1562
|
+
parts.push(" - Are there placeholder texts or TODOs?");
|
|
1563
|
+
parts.push(" - Is there enough detail?");
|
|
1564
|
+
parts.push("");
|
|
1565
|
+
parts.push("## Pass Criteria");
|
|
1566
|
+
parts.push("");
|
|
1567
|
+
parts.push("The document passes if:");
|
|
1568
|
+
parts.push("- ALL scores >= 70");
|
|
1569
|
+
parts.push('- NO issues with severity "error"');
|
|
1570
|
+
parts.push("");
|
|
1571
|
+
parts.push("If it fails, the document will be automatically revised (up to 3 attempts).");
|
|
1572
|
+
parts.push("");
|
|
1573
|
+
parts.push("## Output Format");
|
|
1574
|
+
parts.push("");
|
|
1575
|
+
parts.push("Output a JSON object with this structure:");
|
|
1576
|
+
parts.push("");
|
|
1577
|
+
parts.push("```json");
|
|
1578
|
+
parts.push("{");
|
|
1579
|
+
parts.push(' "passed": true,');
|
|
1580
|
+
parts.push(' "score": {');
|
|
1581
|
+
parts.push(' "requirementsCoverage": 85,');
|
|
1582
|
+
parts.push(' "templateCompliance": 90,');
|
|
1583
|
+
parts.push(' "consistency": 80,');
|
|
1584
|
+
parts.push(' "completeness": 75');
|
|
1585
|
+
parts.push(" },");
|
|
1586
|
+
parts.push(' "issues": [');
|
|
1587
|
+
parts.push(" {");
|
|
1588
|
+
parts.push(' "severity": "warning",');
|
|
1589
|
+
parts.push(' "category": "completeness",');
|
|
1590
|
+
parts.push(' "description": "Section X could use more detail",');
|
|
1591
|
+
parts.push(' "suggestion": "Add examples for the edge cases"');
|
|
1592
|
+
parts.push(" }");
|
|
1593
|
+
parts.push(" ],");
|
|
1594
|
+
parts.push(' "summary": "Document meets requirements with minor suggestions for improvement."');
|
|
1595
|
+
parts.push("}");
|
|
1596
|
+
parts.push("```");
|
|
1597
|
+
parts.push("");
|
|
1598
|
+
parts.push("**Important:** Output ONLY the JSON, no other text.");
|
|
1599
|
+
parts.push("");
|
|
1600
|
+
return parts.join("\n");
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
// src/orchestrator/index.ts
|
|
1604
|
+
var Orchestrator = class {
|
|
1605
|
+
cwd;
|
|
1606
|
+
constructor(cwd = process.cwd()) {
|
|
1607
|
+
this.cwd = cwd;
|
|
1608
|
+
}
|
|
1609
|
+
// ===========================================================================
|
|
1610
|
+
// Config & Path Helpers
|
|
1611
|
+
// ===========================================================================
|
|
1612
|
+
getSteps() {
|
|
1613
|
+
const config = loadConfig(this.cwd);
|
|
1614
|
+
return config.steps;
|
|
1615
|
+
}
|
|
1616
|
+
getOutputPath() {
|
|
1617
|
+
return getOutputsDir(this.cwd);
|
|
1618
|
+
}
|
|
1619
|
+
getStatePath(taskId) {
|
|
1620
|
+
return join5(this.getOutputPath(), taskId, ".state.json");
|
|
1621
|
+
}
|
|
1622
|
+
getSpecPath(taskId, step) {
|
|
1623
|
+
return join5(this.getOutputPath(), taskId, `${step}.md`);
|
|
1624
|
+
}
|
|
1625
|
+
getStepInstructionPath(step) {
|
|
1626
|
+
return join5(getStepsDir(this.cwd), step, "instruction.md");
|
|
1627
|
+
}
|
|
1628
|
+
getStepTemplatePath(step) {
|
|
1629
|
+
return join5(getStepsDir(this.cwd), step, "template.md");
|
|
1630
|
+
}
|
|
1631
|
+
// ===========================================================================
|
|
1632
|
+
// State Management
|
|
1633
|
+
// ===========================================================================
|
|
1634
|
+
loadState(taskId) {
|
|
1635
|
+
const statePath = this.getStatePath(taskId);
|
|
1636
|
+
if (!existsSync5(statePath)) {
|
|
1637
|
+
return null;
|
|
1638
|
+
}
|
|
1639
|
+
const data = JSON.parse(readFileSync5(statePath, "utf-8"));
|
|
1640
|
+
return data;
|
|
1641
|
+
}
|
|
1642
|
+
saveState(state) {
|
|
1643
|
+
state.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1644
|
+
const statePath = this.getStatePath(state.taskId);
|
|
1645
|
+
const dir = dirname2(statePath);
|
|
1646
|
+
if (!existsSync5(dir)) {
|
|
1647
|
+
mkdirSync3(dir, { recursive: true });
|
|
1648
|
+
}
|
|
1649
|
+
writeFileSync3(statePath, JSON.stringify(state, null, 2));
|
|
1650
|
+
}
|
|
1651
|
+
// ===========================================================================
|
|
1652
|
+
// Spec Helpers
|
|
1653
|
+
// ===========================================================================
|
|
1654
|
+
checkUnresolvedQuestions(specPath) {
|
|
1655
|
+
if (!existsSync5(specPath)) {
|
|
1656
|
+
return [];
|
|
1657
|
+
}
|
|
1658
|
+
const content = readFileSync5(specPath, "utf-8");
|
|
1659
|
+
const { data } = matter2(content);
|
|
1660
|
+
const questions = [];
|
|
1661
|
+
if (data.open_questions && Array.isArray(data.open_questions)) {
|
|
1662
|
+
for (let i = 0; i < data.open_questions.length; i++) {
|
|
997
1663
|
const q = data.open_questions[i];
|
|
998
1664
|
if (!q.resolved) {
|
|
999
1665
|
questions.push({
|
|
@@ -1013,6 +1679,7 @@ var Orchestrator = class {
|
|
|
1013
1679
|
// ===========================================================================
|
|
1014
1680
|
/**
|
|
1015
1681
|
* Phase 1: Context gathering
|
|
1682
|
+
* @deprecated Use responsePhaseExplore instead
|
|
1016
1683
|
*/
|
|
1017
1684
|
responsePhaseContext(state) {
|
|
1018
1685
|
const steps = this.getSteps();
|
|
@@ -1020,8 +1687,8 @@ var Orchestrator = class {
|
|
|
1020
1687
|
let previousOutput;
|
|
1021
1688
|
if (state.stepIndex > 1) {
|
|
1022
1689
|
const prevStep = steps[state.stepIndex - 2];
|
|
1023
|
-
const prevPath =
|
|
1024
|
-
if (
|
|
1690
|
+
const prevPath = join5(outputPath, state.taskId, `${prevStep}.md`);
|
|
1691
|
+
if (existsSync5(prevPath)) {
|
|
1025
1692
|
previousOutput = prevPath;
|
|
1026
1693
|
}
|
|
1027
1694
|
}
|
|
@@ -1040,16 +1707,64 @@ var Orchestrator = class {
|
|
|
1040
1707
|
onComplete: `context-done ${state.taskId}`
|
|
1041
1708
|
};
|
|
1042
1709
|
}
|
|
1710
|
+
/**
|
|
1711
|
+
* Phase 1 (New): Deep codebase exploration
|
|
1712
|
+
*/
|
|
1713
|
+
responsePhaseExplore(state) {
|
|
1714
|
+
const steps = this.getSteps();
|
|
1715
|
+
const outputPath = this.getOutputPath();
|
|
1716
|
+
let previousOutput;
|
|
1717
|
+
if (state.stepIndex > 1) {
|
|
1718
|
+
const prevStep = steps[state.stepIndex - 2];
|
|
1719
|
+
const prevPath = join5(outputPath, state.taskId, `${prevStep}.md`);
|
|
1720
|
+
if (existsSync5(prevPath)) {
|
|
1721
|
+
previousOutput = prevPath;
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
const prompt = buildExplorePrompt({
|
|
1725
|
+
taskId: state.taskId,
|
|
1726
|
+
step: state.currentStep,
|
|
1727
|
+
description: state.description,
|
|
1728
|
+
stepIndex: state.stepIndex,
|
|
1729
|
+
totalSteps: state.totalSteps,
|
|
1730
|
+
previousOutput,
|
|
1731
|
+
cwd: this.cwd
|
|
1732
|
+
});
|
|
1733
|
+
return {
|
|
1734
|
+
type: "phase",
|
|
1735
|
+
phase: "explore",
|
|
1736
|
+
step: state.currentStep,
|
|
1737
|
+
stepIndex: state.stepIndex,
|
|
1738
|
+
totalSteps: state.totalSteps,
|
|
1739
|
+
taskId: state.taskId,
|
|
1740
|
+
description: state.description,
|
|
1741
|
+
prompt,
|
|
1742
|
+
context: {
|
|
1743
|
+
instruction: this.getStepInstructionPath(state.currentStep),
|
|
1744
|
+
previousOutput
|
|
1745
|
+
},
|
|
1746
|
+
onComplete: `explore-done ${state.taskId}`
|
|
1747
|
+
};
|
|
1748
|
+
}
|
|
1043
1749
|
/**
|
|
1044
1750
|
* Phase 2: Question generation
|
|
1045
1751
|
*/
|
|
1046
1752
|
responsePhaseClarify(state) {
|
|
1753
|
+
const prompt = buildClarifyPrompt({
|
|
1754
|
+
taskId: state.taskId,
|
|
1755
|
+
step: state.currentStep,
|
|
1756
|
+
description: state.description,
|
|
1757
|
+
gatheredContext: state.context || "",
|
|
1758
|
+
previousQA: state.qaHistory,
|
|
1759
|
+
cwd: this.cwd
|
|
1760
|
+
});
|
|
1047
1761
|
return {
|
|
1048
1762
|
type: "phase",
|
|
1049
1763
|
phase: "clarify",
|
|
1050
1764
|
step: state.currentStep,
|
|
1051
1765
|
taskId: state.taskId,
|
|
1052
1766
|
description: state.description,
|
|
1767
|
+
prompt,
|
|
1053
1768
|
gatheredContext: state.context || "",
|
|
1054
1769
|
previousQA: state.qaHistory,
|
|
1055
1770
|
context: {
|
|
@@ -1060,6 +1775,7 @@ var Orchestrator = class {
|
|
|
1060
1775
|
}
|
|
1061
1776
|
/**
|
|
1062
1777
|
* Phase 3: Document generation
|
|
1778
|
+
* @deprecated Use responsePhaseExecute instead
|
|
1063
1779
|
*/
|
|
1064
1780
|
responsePhaseGenerate(state) {
|
|
1065
1781
|
const steps = this.getSteps();
|
|
@@ -1067,13 +1783,13 @@ var Orchestrator = class {
|
|
|
1067
1783
|
let previousOutput;
|
|
1068
1784
|
if (state.stepIndex > 1) {
|
|
1069
1785
|
const prevStep = steps[state.stepIndex - 2];
|
|
1070
|
-
const prevPath =
|
|
1071
|
-
if (
|
|
1786
|
+
const prevPath = join5(outputPath, state.taskId, `${prevStep}.md`);
|
|
1787
|
+
if (existsSync5(prevPath)) {
|
|
1072
1788
|
previousOutput = prevPath;
|
|
1073
1789
|
}
|
|
1074
1790
|
}
|
|
1075
1791
|
const templatePath = this.getStepTemplatePath(state.currentStep);
|
|
1076
|
-
const hasTemplate =
|
|
1792
|
+
const hasTemplate = existsSync5(templatePath);
|
|
1077
1793
|
return {
|
|
1078
1794
|
type: "phase",
|
|
1079
1795
|
phase: "generate",
|
|
@@ -1088,12 +1804,112 @@ var Orchestrator = class {
|
|
|
1088
1804
|
instruction: this.getStepInstructionPath(state.currentStep),
|
|
1089
1805
|
template: hasTemplate ? templatePath : void 0,
|
|
1090
1806
|
previousOutput,
|
|
1091
|
-
output:
|
|
1807
|
+
output: join5(outputPath, state.taskId, `${state.currentStep}.md`),
|
|
1092
1808
|
revisionFeedback: state.revisionFeedback
|
|
1093
1809
|
},
|
|
1094
1810
|
onComplete: `generate-done ${state.taskId}`
|
|
1095
1811
|
};
|
|
1096
1812
|
}
|
|
1813
|
+
/**
|
|
1814
|
+
* Phase 3 (New): Document/code generation with explore output
|
|
1815
|
+
*/
|
|
1816
|
+
responsePhaseExecute(state) {
|
|
1817
|
+
const steps = this.getSteps();
|
|
1818
|
+
const outputPath = this.getOutputPath();
|
|
1819
|
+
let previousOutput;
|
|
1820
|
+
if (state.stepIndex > 1) {
|
|
1821
|
+
const prevStep = steps[state.stepIndex - 2];
|
|
1822
|
+
const prevPath = join5(outputPath, state.taskId, `${prevStep}.md`);
|
|
1823
|
+
if (existsSync5(prevPath)) {
|
|
1824
|
+
previousOutput = prevPath;
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1827
|
+
const templatePath = this.getStepTemplatePath(state.currentStep);
|
|
1828
|
+
const hasTemplate = existsSync5(templatePath);
|
|
1829
|
+
let verifyFeedback;
|
|
1830
|
+
if (state.verifyOutput && !state.verifyOutput.passed && state.verifyAttempts && state.verifyAttempts > 1) {
|
|
1831
|
+
const issues = state.verifyOutput.issues.filter((i) => i.severity === "error").map((i) => `- [${i.category}] ${i.description}${i.suggestion ? ` \u2192 ${i.suggestion}` : ""}`).join("\n");
|
|
1832
|
+
verifyFeedback = `Auto-fix attempt ${state.verifyAttempts}/3. Fix these issues:
|
|
1833
|
+
${issues}`;
|
|
1834
|
+
}
|
|
1835
|
+
const exploreOutput = state.exploreOutput || {
|
|
1836
|
+
summary: state.context || "",
|
|
1837
|
+
relevantFiles: [],
|
|
1838
|
+
patterns: [],
|
|
1839
|
+
constraints: [],
|
|
1840
|
+
dependencies: []
|
|
1841
|
+
};
|
|
1842
|
+
const { prompt } = buildExecutePrompt({
|
|
1843
|
+
taskId: state.taskId,
|
|
1844
|
+
step: state.currentStep,
|
|
1845
|
+
description: state.description,
|
|
1846
|
+
stepIndex: state.stepIndex,
|
|
1847
|
+
totalSteps: state.totalSteps,
|
|
1848
|
+
exploreOutput,
|
|
1849
|
+
answers: state.answers,
|
|
1850
|
+
revisionFeedback: state.revisionFeedback,
|
|
1851
|
+
verifyFeedback,
|
|
1852
|
+
cwd: this.cwd
|
|
1853
|
+
});
|
|
1854
|
+
return {
|
|
1855
|
+
type: "phase",
|
|
1856
|
+
phase: "execute",
|
|
1857
|
+
step: state.currentStep,
|
|
1858
|
+
stepIndex: state.stepIndex,
|
|
1859
|
+
totalSteps: state.totalSteps,
|
|
1860
|
+
taskId: state.taskId,
|
|
1861
|
+
description: state.description,
|
|
1862
|
+
prompt,
|
|
1863
|
+
exploreOutput,
|
|
1864
|
+
answers: state.answers,
|
|
1865
|
+
context: {
|
|
1866
|
+
instruction: this.getStepInstructionPath(state.currentStep),
|
|
1867
|
+
template: hasTemplate ? templatePath : void 0,
|
|
1868
|
+
previousOutput,
|
|
1869
|
+
output: join5(outputPath, state.taskId, `${state.currentStep}.md`),
|
|
1870
|
+
revisionFeedback: state.revisionFeedback,
|
|
1871
|
+
verifyFeedback
|
|
1872
|
+
},
|
|
1873
|
+
onComplete: `execute-done ${state.taskId}`
|
|
1874
|
+
};
|
|
1875
|
+
}
|
|
1876
|
+
/**
|
|
1877
|
+
* Phase 4 (New): Self-validation
|
|
1878
|
+
*/
|
|
1879
|
+
responsePhaseVerify(state) {
|
|
1880
|
+
const outputPath = this.getOutputPath();
|
|
1881
|
+
const templatePath = this.getStepTemplatePath(state.currentStep);
|
|
1882
|
+
const hasTemplate = existsSync5(templatePath);
|
|
1883
|
+
const documentPath = join5(outputPath, state.taskId, `${state.currentStep}.md`);
|
|
1884
|
+
const prompt = buildVerifyPrompt({
|
|
1885
|
+
taskId: state.taskId,
|
|
1886
|
+
step: state.currentStep,
|
|
1887
|
+
description: state.description,
|
|
1888
|
+
stepIndex: state.stepIndex,
|
|
1889
|
+
totalSteps: state.totalSteps,
|
|
1890
|
+
documentPath,
|
|
1891
|
+
verifyAttempts: state.verifyAttempts || 1,
|
|
1892
|
+
cwd: this.cwd
|
|
1893
|
+
});
|
|
1894
|
+
return {
|
|
1895
|
+
type: "phase",
|
|
1896
|
+
phase: "verify",
|
|
1897
|
+
step: state.currentStep,
|
|
1898
|
+
stepIndex: state.stepIndex,
|
|
1899
|
+
totalSteps: state.totalSteps,
|
|
1900
|
+
taskId: state.taskId,
|
|
1901
|
+
description: state.description,
|
|
1902
|
+
prompt,
|
|
1903
|
+
verifyAttempts: state.verifyAttempts || 1,
|
|
1904
|
+
maxAttempts: 3,
|
|
1905
|
+
context: {
|
|
1906
|
+
instruction: this.getStepInstructionPath(state.currentStep),
|
|
1907
|
+
template: hasTemplate ? templatePath : void 0,
|
|
1908
|
+
document: documentPath
|
|
1909
|
+
},
|
|
1910
|
+
onComplete: `verify-done ${state.taskId}`
|
|
1911
|
+
};
|
|
1912
|
+
}
|
|
1097
1913
|
/**
|
|
1098
1914
|
* Phase 3 (section mode): Parallel section generation
|
|
1099
1915
|
*/
|
|
@@ -1106,15 +1922,15 @@ var Orchestrator = class {
|
|
|
1106
1922
|
let previousOutput;
|
|
1107
1923
|
if (state.stepIndex > 1) {
|
|
1108
1924
|
const prevStep = steps[state.stepIndex - 2];
|
|
1109
|
-
const prevPath =
|
|
1110
|
-
if (
|
|
1925
|
+
const prevPath = join5(outputPath, state.taskId, `${prevStep}.md`);
|
|
1926
|
+
if (existsSync5(prevPath)) {
|
|
1111
1927
|
previousOutput = prevPath;
|
|
1112
1928
|
}
|
|
1113
1929
|
}
|
|
1114
1930
|
const parallelSections = state.sectionPlan.leaves.map((leaf) => ({
|
|
1115
1931
|
id: leaf.id,
|
|
1116
1932
|
title: leaf.title,
|
|
1117
|
-
outputPath:
|
|
1933
|
+
outputPath: join5(outputPath, state.taskId, leaf.outputPath),
|
|
1118
1934
|
instruction: buildSectionInstruction(leaf, state.sectionPlan.sharedContext),
|
|
1119
1935
|
position: {
|
|
1120
1936
|
path: leaf.position.path,
|
|
@@ -1138,7 +1954,7 @@ var Orchestrator = class {
|
|
|
1138
1954
|
instruction: this.getStepInstructionPath(state.currentStep),
|
|
1139
1955
|
template: this.getStepTemplatePath(state.currentStep),
|
|
1140
1956
|
previousOutput,
|
|
1141
|
-
outputDir:
|
|
1957
|
+
outputDir: join5(outputPath, state.taskId, "sections", state.currentStep)
|
|
1142
1958
|
},
|
|
1143
1959
|
onComplete: `sections-done ${state.taskId}`
|
|
1144
1960
|
};
|
|
@@ -1153,7 +1969,7 @@ var Orchestrator = class {
|
|
|
1153
1969
|
const outputPath = this.getOutputPath();
|
|
1154
1970
|
const parallelGroups = level.groups.map((group) => ({
|
|
1155
1971
|
...group,
|
|
1156
|
-
outputPath:
|
|
1972
|
+
outputPath: join5(outputPath, state.taskId, group.outputPath)
|
|
1157
1973
|
}));
|
|
1158
1974
|
return {
|
|
1159
1975
|
type: "phase",
|
|
@@ -1195,11 +2011,11 @@ var Orchestrator = class {
|
|
|
1195
2011
|
missing.push(childId);
|
|
1196
2012
|
continue;
|
|
1197
2013
|
}
|
|
1198
|
-
const fullPath =
|
|
1199
|
-
if (!
|
|
2014
|
+
const fullPath = join5(outputPath, state.taskId, childPath);
|
|
2015
|
+
if (!existsSync5(fullPath)) {
|
|
1200
2016
|
missing.push(childId);
|
|
1201
2017
|
} else {
|
|
1202
|
-
const content =
|
|
2018
|
+
const content = readFileSync5(fullPath, "utf-8");
|
|
1203
2019
|
if (!content.trim()) {
|
|
1204
2020
|
warnings.push(`Empty section file: ${childId}`);
|
|
1205
2021
|
}
|
|
@@ -1244,7 +2060,7 @@ var Orchestrator = class {
|
|
|
1244
2060
|
step: state.currentStep,
|
|
1245
2061
|
stepIndex: state.stepIndex,
|
|
1246
2062
|
totalSteps: state.totalSteps,
|
|
1247
|
-
specPath:
|
|
2063
|
+
specPath: join5(outputPath, state.taskId, `${state.currentStep}.md`),
|
|
1248
2064
|
options: ["approve", "revise", "reject", "stop"],
|
|
1249
2065
|
onComplete: {
|
|
1250
2066
|
approve: `approve ${state.taskId}`,
|
|
@@ -1259,8 +2075,8 @@ var Orchestrator = class {
|
|
|
1259
2075
|
const outputPath = this.getOutputPath();
|
|
1260
2076
|
const outputs = [];
|
|
1261
2077
|
for (let i = 0; i < state.stepIndex; i++) {
|
|
1262
|
-
const specPath =
|
|
1263
|
-
if (
|
|
2078
|
+
const specPath = join5(outputPath, state.taskId, `${steps[i]}.md`);
|
|
2079
|
+
if (existsSync5(specPath)) {
|
|
1264
2080
|
outputs.push(specPath);
|
|
1265
2081
|
}
|
|
1266
2082
|
}
|
|
@@ -1287,7 +2103,7 @@ var Orchestrator = class {
|
|
|
1287
2103
|
// Command Handlers
|
|
1288
2104
|
// ===========================================================================
|
|
1289
2105
|
/**
|
|
1290
|
-
* Initialize a new workflow - starts at
|
|
2106
|
+
* Initialize a new workflow - starts at phase_explore
|
|
1291
2107
|
*/
|
|
1292
2108
|
cmdInit(description) {
|
|
1293
2109
|
try {
|
|
@@ -1299,18 +2115,19 @@ var Orchestrator = class {
|
|
|
1299
2115
|
currentStep: steps[0],
|
|
1300
2116
|
stepIndex: 1,
|
|
1301
2117
|
totalSteps: steps.length,
|
|
1302
|
-
status: "
|
|
1303
|
-
phase: "
|
|
2118
|
+
status: "phase_explore",
|
|
2119
|
+
phase: "explore",
|
|
1304
2120
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1305
2121
|
};
|
|
1306
2122
|
this.saveState(state);
|
|
1307
|
-
return this.
|
|
2123
|
+
return this.responsePhaseExplore(state);
|
|
1308
2124
|
} catch (e) {
|
|
1309
2125
|
return this.responseError(e.message);
|
|
1310
2126
|
}
|
|
1311
2127
|
}
|
|
1312
2128
|
/**
|
|
1313
2129
|
* Phase 1 complete: Context gathered, move to clarify phase
|
|
2130
|
+
* @deprecated Use cmdExploreDone instead
|
|
1314
2131
|
*/
|
|
1315
2132
|
cmdContextDone(taskId, context) {
|
|
1316
2133
|
const state = this.loadState(taskId);
|
|
@@ -1323,10 +2140,25 @@ var Orchestrator = class {
|
|
|
1323
2140
|
this.saveState(state);
|
|
1324
2141
|
return this.responsePhaseClarify(state);
|
|
1325
2142
|
}
|
|
2143
|
+
/**
|
|
2144
|
+
* Phase 1 complete (New): Exploration complete, move to clarify phase
|
|
2145
|
+
*/
|
|
2146
|
+
cmdExploreDone(taskId, exploreOutput) {
|
|
2147
|
+
const state = this.loadState(taskId);
|
|
2148
|
+
if (!state) {
|
|
2149
|
+
return this.responseError(`No workflow found: ${taskId}`, taskId);
|
|
2150
|
+
}
|
|
2151
|
+
state.exploreOutput = exploreOutput;
|
|
2152
|
+
state.context = JSON.stringify(exploreOutput);
|
|
2153
|
+
state.status = "phase_clarify";
|
|
2154
|
+
state.phase = "clarify";
|
|
2155
|
+
this.saveState(state);
|
|
2156
|
+
return this.responsePhaseClarify(state);
|
|
2157
|
+
}
|
|
1326
2158
|
/**
|
|
1327
2159
|
* Phase 2 complete: Questions generated (or none)
|
|
1328
2160
|
* If questions exist → checkpoint
|
|
1329
|
-
* If no questions → move to
|
|
2161
|
+
* If no questions → move to draft phase with accumulated answers
|
|
1330
2162
|
*/
|
|
1331
2163
|
cmdClarifyDone(taskId, questions) {
|
|
1332
2164
|
const state = this.loadState(taskId);
|
|
@@ -1344,14 +2176,15 @@ var Orchestrator = class {
|
|
|
1344
2176
|
this.initSectionPlan(state);
|
|
1345
2177
|
if (state.sectionPlan) {
|
|
1346
2178
|
state.status = "phase_sections";
|
|
1347
|
-
state.phase = "
|
|
2179
|
+
state.phase = "draft";
|
|
1348
2180
|
this.saveState(state);
|
|
1349
2181
|
return this.responsePhaseGenerateSections(state);
|
|
1350
2182
|
}
|
|
1351
|
-
state.status = "
|
|
1352
|
-
state.phase = "
|
|
2183
|
+
state.status = "phase_execute";
|
|
2184
|
+
state.phase = "draft";
|
|
2185
|
+
state.verifyAttempts = 0;
|
|
1353
2186
|
this.saveState(state);
|
|
1354
|
-
return this.
|
|
2187
|
+
return this.responsePhaseExecute(state);
|
|
1355
2188
|
}
|
|
1356
2189
|
/**
|
|
1357
2190
|
* Human answered questions, loop back to clarify phase
|
|
@@ -1376,6 +2209,7 @@ var Orchestrator = class {
|
|
|
1376
2209
|
}
|
|
1377
2210
|
/**
|
|
1378
2211
|
* Phase 3 complete: Document generated, move to approve checkpoint
|
|
2212
|
+
* @deprecated Use cmdExecuteDone instead for new workflow
|
|
1379
2213
|
*/
|
|
1380
2214
|
cmdGenerateDone(taskId) {
|
|
1381
2215
|
const state = this.loadState(taskId);
|
|
@@ -1383,7 +2217,7 @@ var Orchestrator = class {
|
|
|
1383
2217
|
return this.responseError(`No workflow found: ${taskId}`, taskId);
|
|
1384
2218
|
}
|
|
1385
2219
|
const specPath = this.getSpecPath(taskId, state.currentStep);
|
|
1386
|
-
if (!
|
|
2220
|
+
if (!existsSync5(specPath)) {
|
|
1387
2221
|
return this.responseError(`Document not found: ${specPath}`, taskId, state.currentStep);
|
|
1388
2222
|
}
|
|
1389
2223
|
state.status = "approve_pending";
|
|
@@ -1392,209 +2226,79 @@ var Orchestrator = class {
|
|
|
1392
2226
|
return this.responseCheckpointApprove(state);
|
|
1393
2227
|
}
|
|
1394
2228
|
/**
|
|
1395
|
-
*
|
|
1396
|
-
*/
|
|
1397
|
-
cmdDone(taskId) {
|
|
1398
|
-
const state = this.loadState(taskId);
|
|
1399
|
-
if (!state) {
|
|
1400
|
-
return this.responseError(`No workflow found: ${taskId}`, taskId);
|
|
1401
|
-
}
|
|
1402
|
-
const specPath = this.getSpecPath(taskId, state.currentStep);
|
|
1403
|
-
if (!existsSync4(specPath)) {
|
|
1404
|
-
return this.responseError(`Spec not found: ${specPath}`, taskId, state.currentStep);
|
|
1405
|
-
}
|
|
1406
|
-
const questions = this.checkUnresolvedQuestions(specPath);
|
|
1407
|
-
if (questions.length > 0) {
|
|
1408
|
-
state.questions = questions;
|
|
1409
|
-
state.status = "clarify_pending";
|
|
1410
|
-
state.phase = "clarify";
|
|
1411
|
-
this.saveState(state);
|
|
1412
|
-
return this.responseCheckpointClarify(state);
|
|
1413
|
-
}
|
|
1414
|
-
state.status = "approve_pending";
|
|
1415
|
-
state.phase = "review";
|
|
1416
|
-
this.saveState(state);
|
|
1417
|
-
return this.responseCheckpointApprove(state);
|
|
1418
|
-
}
|
|
1419
|
-
/**
|
|
1420
|
-
* Approve current step and move to next
|
|
1421
|
-
*/
|
|
1422
|
-
cmdApprove(taskId) {
|
|
1423
|
-
const state = this.loadState(taskId);
|
|
1424
|
-
if (!state) {
|
|
1425
|
-
return this.responseError(`No workflow found: ${taskId}`, taskId);
|
|
1426
|
-
}
|
|
1427
|
-
const steps = this.getSteps();
|
|
1428
|
-
const specPath = this.getSpecPath(taskId, state.currentStep);
|
|
1429
|
-
if (existsSync4(specPath)) {
|
|
1430
|
-
const content = readFileSync4(specPath, "utf-8");
|
|
1431
|
-
const { content: body, data } = matter2(content);
|
|
1432
|
-
data.status = "approved";
|
|
1433
|
-
data.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
1434
|
-
writeFileSync3(specPath, matter2.stringify(body, data));
|
|
1435
|
-
}
|
|
1436
|
-
if (state.stepIndex < state.totalSteps) {
|
|
1437
|
-
state.currentStep = steps[state.stepIndex];
|
|
1438
|
-
state.stepIndex += 1;
|
|
1439
|
-
state.status = "phase_context";
|
|
1440
|
-
state.phase = "context";
|
|
1441
|
-
state.context = void 0;
|
|
1442
|
-
state.questions = void 0;
|
|
1443
|
-
state.answers = void 0;
|
|
1444
|
-
state.qaHistory = void 0;
|
|
1445
|
-
state.revisionFeedback = void 0;
|
|
1446
|
-
this.saveState(state);
|
|
1447
|
-
return this.responsePhaseContext(state);
|
|
1448
|
-
} else {
|
|
1449
|
-
state.status = "completed";
|
|
1450
|
-
this.saveState(state);
|
|
1451
|
-
return this.responseComplete(state, "completed");
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
/**
|
|
1455
|
-
* Request revision with feedback - goes back to generate phase
|
|
1456
|
-
*/
|
|
1457
|
-
cmdRevise(taskId, feedback) {
|
|
1458
|
-
const state = this.loadState(taskId);
|
|
1459
|
-
if (!state) {
|
|
1460
|
-
return this.responseError(`No workflow found: ${taskId}`, taskId);
|
|
1461
|
-
}
|
|
1462
|
-
state.status = "phase_generate";
|
|
1463
|
-
state.phase = "generate";
|
|
1464
|
-
state.revisionFeedback = feedback;
|
|
1465
|
-
this.saveState(state);
|
|
1466
|
-
return this.responsePhaseGenerate(state);
|
|
1467
|
-
}
|
|
1468
|
-
/**
|
|
1469
|
-
* Reject and stop workflow
|
|
2229
|
+
* Phase 3 complete (New): Execution complete, move to verify phase
|
|
1470
2230
|
*/
|
|
1471
|
-
|
|
2231
|
+
cmdExecuteDone(taskId) {
|
|
1472
2232
|
const state = this.loadState(taskId);
|
|
1473
2233
|
if (!state) {
|
|
1474
2234
|
return this.responseError(`No workflow found: ${taskId}`, taskId);
|
|
1475
2235
|
}
|
|
1476
2236
|
const specPath = this.getSpecPath(taskId, state.currentStep);
|
|
1477
|
-
if (
|
|
1478
|
-
|
|
1479
|
-
const { content: body, data } = matter2(content);
|
|
1480
|
-
data.status = "rejected";
|
|
1481
|
-
data.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
1482
|
-
writeFileSync3(specPath, matter2.stringify(body, data));
|
|
1483
|
-
}
|
|
1484
|
-
state.status = "rejected";
|
|
1485
|
-
this.saveState(state);
|
|
1486
|
-
return this.responseComplete(state, "rejected");
|
|
1487
|
-
}
|
|
1488
|
-
/**
|
|
1489
|
-
* Stop workflow (can resume later)
|
|
1490
|
-
*/
|
|
1491
|
-
cmdStop(taskId) {
|
|
1492
|
-
const state = this.loadState(taskId);
|
|
1493
|
-
if (!state) {
|
|
1494
|
-
return this.responseError(`No workflow found: ${taskId}`, taskId);
|
|
2237
|
+
if (!existsSync5(specPath)) {
|
|
2238
|
+
return this.responseError(`Document not found: ${specPath}`, taskId, state.currentStep);
|
|
1495
2239
|
}
|
|
1496
|
-
state.status = "
|
|
2240
|
+
state.status = "phase_verify";
|
|
2241
|
+
state.phase = "verify";
|
|
2242
|
+
state.verifyAttempts = (state.verifyAttempts || 0) + 1;
|
|
1497
2243
|
this.saveState(state);
|
|
1498
|
-
return this.
|
|
2244
|
+
return this.responsePhaseVerify(state);
|
|
1499
2245
|
}
|
|
1500
|
-
// ===========================================================================
|
|
1501
|
-
// Section-based Workflow Commands
|
|
1502
|
-
// ===========================================================================
|
|
1503
2246
|
/**
|
|
1504
|
-
*
|
|
1505
|
-
* Called internally when template has sections
|
|
2247
|
+
* @deprecated Use cmdExecuteDone instead
|
|
1506
2248
|
*/
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
if (!existsSync4(templatePath)) {
|
|
1510
|
-
return;
|
|
1511
|
-
}
|
|
1512
|
-
const template = readFileSync4(templatePath, "utf-8");
|
|
1513
|
-
const instructionPath = this.getStepInstructionPath(state.currentStep);
|
|
1514
|
-
const instructionSummary = existsSync4(instructionPath) ? readFileSync4(instructionPath, "utf-8").slice(0, 500) : "";
|
|
1515
|
-
const plan = parseTemplateToTree(
|
|
1516
|
-
template,
|
|
1517
|
-
state.currentStep,
|
|
1518
|
-
state.description,
|
|
1519
|
-
`sections/${state.currentStep}`,
|
|
1520
|
-
instructionSummary
|
|
1521
|
-
);
|
|
1522
|
-
if (plan.leaves.length > 1) {
|
|
1523
|
-
state.sectionPlan = plan;
|
|
1524
|
-
state.sectionStatuses = plan.leaves.map((leaf) => ({
|
|
1525
|
-
id: leaf.id,
|
|
1526
|
-
status: "pending",
|
|
1527
|
-
outputPath: leaf.outputPath
|
|
1528
|
-
}));
|
|
1529
|
-
state.consolidateProgress = {
|
|
1530
|
-
currentLevel: 0,
|
|
1531
|
-
completedLevels: [],
|
|
1532
|
-
totalLevels: plan.consolidateLevels.length
|
|
1533
|
-
};
|
|
1534
|
-
}
|
|
2249
|
+
cmdDraftDone(taskId) {
|
|
2250
|
+
return this.cmdExecuteDone(taskId);
|
|
1535
2251
|
}
|
|
1536
2252
|
/**
|
|
1537
|
-
*
|
|
2253
|
+
* Phase 4 complete (New): Verification done
|
|
2254
|
+
* If passed → approve_pending
|
|
2255
|
+
* If failed → phase_execute (auto-fix, max 3 attempts)
|
|
2256
|
+
* If max attempts reached → approve_pending with warning
|
|
1538
2257
|
*/
|
|
1539
|
-
|
|
2258
|
+
cmdVerifyDone(taskId, verifyOutput) {
|
|
1540
2259
|
const state = this.loadState(taskId);
|
|
1541
2260
|
if (!state) {
|
|
1542
2261
|
return this.responseError(`No workflow found: ${taskId}`, taskId);
|
|
1543
2262
|
}
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
status: "completed"
|
|
1551
|
-
}));
|
|
2263
|
+
state.verifyOutput = verifyOutput;
|
|
2264
|
+
if (verifyOutput.passed) {
|
|
2265
|
+
state.status = "approve_pending";
|
|
2266
|
+
state.phase = "review";
|
|
2267
|
+
this.saveState(state);
|
|
2268
|
+
return this.responseCheckpointApprove(state);
|
|
1552
2269
|
}
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
state.
|
|
2270
|
+
const attempts = state.verifyAttempts || 1;
|
|
2271
|
+
if (attempts >= 3) {
|
|
2272
|
+
state.status = "approve_pending";
|
|
2273
|
+
state.phase = "review";
|
|
1556
2274
|
this.saveState(state);
|
|
1557
|
-
const
|
|
1558
|
-
|
|
1559
|
-
if (!validation.valid) {
|
|
1560
|
-
return this.responseError(
|
|
1561
|
-
validation.error || "Validation failed",
|
|
1562
|
-
taskId,
|
|
1563
|
-
state.currentStep
|
|
1564
|
-
);
|
|
1565
|
-
}
|
|
1566
|
-
return this.responsePhaseConsolidate(state, firstLevel);
|
|
2275
|
+
const response = this.responseCheckpointApprove(state);
|
|
2276
|
+
return response;
|
|
1567
2277
|
}
|
|
1568
|
-
state.status = "
|
|
1569
|
-
state.phase = "
|
|
2278
|
+
state.status = "phase_execute";
|
|
2279
|
+
state.phase = "draft";
|
|
1570
2280
|
this.saveState(state);
|
|
1571
|
-
return this.
|
|
2281
|
+
return this.responsePhaseExecute(state);
|
|
1572
2282
|
}
|
|
1573
2283
|
/**
|
|
1574
|
-
*
|
|
2284
|
+
* @deprecated Use cmdExploreDone, cmdClarifyDone, cmdExecuteDone, cmdVerifyDone instead
|
|
1575
2285
|
*/
|
|
1576
|
-
|
|
2286
|
+
cmdDone(taskId) {
|
|
1577
2287
|
const state = this.loadState(taskId);
|
|
1578
2288
|
if (!state) {
|
|
1579
2289
|
return this.responseError(`No workflow found: ${taskId}`, taskId);
|
|
1580
2290
|
}
|
|
1581
|
-
|
|
1582
|
-
|
|
2291
|
+
const specPath = this.getSpecPath(taskId, state.currentStep);
|
|
2292
|
+
if (!existsSync5(specPath)) {
|
|
2293
|
+
return this.responseError(`Spec not found: ${specPath}`, taskId, state.currentStep);
|
|
1583
2294
|
}
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
2295
|
+
const questions = this.checkUnresolvedQuestions(specPath);
|
|
2296
|
+
if (questions.length > 0) {
|
|
2297
|
+
state.questions = questions;
|
|
2298
|
+
state.status = "clarify_pending";
|
|
2299
|
+
state.phase = "clarify";
|
|
1587
2300
|
this.saveState(state);
|
|
1588
|
-
|
|
1589
|
-
const validation = this.validateConsolidateReady(state, nextLevel);
|
|
1590
|
-
if (!validation.valid) {
|
|
1591
|
-
return this.responseError(
|
|
1592
|
-
validation.error || "Validation failed",
|
|
1593
|
-
taskId,
|
|
1594
|
-
state.currentStep
|
|
1595
|
-
);
|
|
1596
|
-
}
|
|
1597
|
-
return this.responsePhaseConsolidate(state, nextLevel);
|
|
2301
|
+
return this.responseCheckpointClarify(state);
|
|
1598
2302
|
}
|
|
1599
2303
|
state.status = "approve_pending";
|
|
1600
2304
|
state.phase = "review";
|
|
@@ -1602,394 +2306,261 @@ var Orchestrator = class {
|
|
|
1602
2306
|
return this.responseCheckpointApprove(state);
|
|
1603
2307
|
}
|
|
1604
2308
|
/**
|
|
1605
|
-
*
|
|
2309
|
+
* Approve current step and move to next
|
|
1606
2310
|
*/
|
|
1607
|
-
|
|
2311
|
+
cmdApprove(taskId) {
|
|
1608
2312
|
const state = this.loadState(taskId);
|
|
1609
2313
|
if (!state) {
|
|
1610
2314
|
return this.responseError(`No workflow found: ${taskId}`, taskId);
|
|
1611
2315
|
}
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
return this.responsePhaseGenerate(state);
|
|
1621
|
-
case "phase_sections":
|
|
1622
|
-
return this.responsePhaseGenerateSections(state);
|
|
1623
|
-
case "phase_consolidate":
|
|
1624
|
-
if (state.sectionPlan && state.consolidateProgress) {
|
|
1625
|
-
const level = state.sectionPlan.consolidateLevels[state.consolidateProgress.currentLevel];
|
|
1626
|
-
return this.responsePhaseConsolidate(state, level);
|
|
1627
|
-
}
|
|
1628
|
-
return this.responseError("Invalid consolidate state", taskId);
|
|
1629
|
-
case "approve_pending":
|
|
1630
|
-
return this.responseCheckpointApprove(state);
|
|
1631
|
-
case "completed":
|
|
1632
|
-
case "stopped":
|
|
1633
|
-
case "rejected":
|
|
1634
|
-
return this.responseComplete(state, state.status);
|
|
1635
|
-
default:
|
|
1636
|
-
return this.responseError(`Unknown status: ${state.status}`, taskId);
|
|
1637
|
-
}
|
|
1638
|
-
}
|
|
1639
|
-
};
|
|
1640
|
-
|
|
1641
|
-
// src/core/step-executor.ts
|
|
1642
|
-
import { existsSync as existsSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
1643
|
-
import matter3 from "gray-matter";
|
|
1644
|
-
|
|
1645
|
-
// src/core/prompt-builder.ts
|
|
1646
|
-
import { readFileSync as readFileSync5, existsSync as existsSync5 } from "fs";
|
|
1647
|
-
import { join as join5 } from "path";
|
|
1648
|
-
function buildContextPrompt(params) {
|
|
1649
|
-
const cwd = params.cwd || process.cwd();
|
|
1650
|
-
const stepsDir = getStepsDir(cwd);
|
|
1651
|
-
const isFirstStep = params.stepIndex === 1;
|
|
1652
|
-
const instructionPath = join5(stepsDir, params.step, "instruction.md");
|
|
1653
|
-
const instruction = existsSync5(instructionPath) ? readFileSync5(instructionPath, "utf-8") : "";
|
|
1654
|
-
const parts = [];
|
|
1655
|
-
parts.push("# Context Gathering Phase");
|
|
1656
|
-
parts.push("");
|
|
1657
|
-
parts.push("Your task is to gather context before generating a document.");
|
|
1658
|
-
parts.push("Do NOT generate the document yet - only gather information.");
|
|
1659
|
-
parts.push("");
|
|
1660
|
-
parts.push("## Task Information");
|
|
1661
|
-
parts.push("");
|
|
1662
|
-
parts.push(`- **Task ID**: ${params.taskId}`);
|
|
1663
|
-
parts.push(`- **Current Step**: ${params.step} (${params.stepIndex}/${params.totalSteps})`);
|
|
1664
|
-
parts.push("");
|
|
1665
|
-
if (isFirstStep) {
|
|
1666
|
-
parts.push("## User Request");
|
|
1667
|
-
parts.push("");
|
|
1668
|
-
parts.push(`> ${params.description}`);
|
|
1669
|
-
parts.push("");
|
|
1670
|
-
} else if (params.previousOutput) {
|
|
1671
|
-
parts.push("## Previous Step Output");
|
|
1672
|
-
parts.push("");
|
|
1673
|
-
if (existsSync5(params.previousOutput)) {
|
|
1674
|
-
parts.push(readFileSync5(params.previousOutput, "utf-8"));
|
|
1675
|
-
}
|
|
1676
|
-
parts.push("");
|
|
1677
|
-
}
|
|
1678
|
-
if (instruction) {
|
|
1679
|
-
parts.push("## Step Instruction (Preview)");
|
|
1680
|
-
parts.push("");
|
|
1681
|
-
parts.push("The next phase will use this instruction to generate a document:");
|
|
1682
|
-
parts.push("");
|
|
1683
|
-
parts.push("```");
|
|
1684
|
-
parts.push(instruction.slice(0, 500) + (instruction.length > 500 ? "..." : ""));
|
|
1685
|
-
parts.push("```");
|
|
1686
|
-
parts.push("");
|
|
1687
|
-
}
|
|
1688
|
-
parts.push("## Your Task");
|
|
1689
|
-
parts.push("");
|
|
1690
|
-
parts.push("1. **Analyze** the request/input to understand what is being asked");
|
|
1691
|
-
parts.push("2. **Search** the codebase for relevant files, patterns, conventions");
|
|
1692
|
-
parts.push("3. **Identify** key constraints, dependencies, and considerations");
|
|
1693
|
-
parts.push("");
|
|
1694
|
-
parts.push("## Output Format");
|
|
1695
|
-
parts.push("");
|
|
1696
|
-
parts.push("Output a JSON object with this structure:");
|
|
1697
|
-
parts.push("");
|
|
1698
|
-
parts.push("```json");
|
|
1699
|
-
parts.push("{");
|
|
1700
|
-
parts.push(' "summary": "Brief summary of what you understood and found",');
|
|
1701
|
-
parts.push(' "relevantFiles": ["path/to/file1.ts", "path/to/file2.ts"],');
|
|
1702
|
-
parts.push(' "keyFindings": [');
|
|
1703
|
-
parts.push(' "Finding 1: description",');
|
|
1704
|
-
parts.push(' "Finding 2: description"');
|
|
1705
|
-
parts.push(" ]");
|
|
1706
|
-
parts.push("}");
|
|
1707
|
-
parts.push("```");
|
|
1708
|
-
parts.push("");
|
|
1709
|
-
parts.push("**Important:** Output ONLY the JSON, no other text.");
|
|
1710
|
-
parts.push("");
|
|
1711
|
-
return parts.join("\n");
|
|
1712
|
-
}
|
|
1713
|
-
function buildClarifyPrompt(params) {
|
|
1714
|
-
const cwd = params.cwd || process.cwd();
|
|
1715
|
-
const stepsDir = getStepsDir(cwd);
|
|
1716
|
-
const instructionPath = join5(stepsDir, params.step, "instruction.md");
|
|
1717
|
-
const instruction = existsSync5(instructionPath) ? readFileSync5(instructionPath, "utf-8") : "";
|
|
1718
|
-
const parts = [];
|
|
1719
|
-
parts.push("# Clarify Phase");
|
|
1720
|
-
parts.push("");
|
|
1721
|
-
parts.push("Your task is to identify any questions that need user input before generating the document.");
|
|
1722
|
-
parts.push("Do NOT generate the document yet - only generate questions if needed.");
|
|
1723
|
-
parts.push("");
|
|
1724
|
-
parts.push("## Task Information");
|
|
1725
|
-
parts.push("");
|
|
1726
|
-
parts.push(`- **Task ID**: ${params.taskId}`);
|
|
1727
|
-
parts.push(`- **Current Step**: ${params.step}`);
|
|
1728
|
-
parts.push(`- **Description**: ${params.description}`);
|
|
1729
|
-
parts.push("");
|
|
1730
|
-
parts.push("## Gathered Context");
|
|
1731
|
-
parts.push("");
|
|
1732
|
-
parts.push(params.gatheredContext);
|
|
1733
|
-
parts.push("");
|
|
1734
|
-
if (instruction) {
|
|
1735
|
-
parts.push("## Step Instruction");
|
|
1736
|
-
parts.push("");
|
|
1737
|
-
parts.push(instruction);
|
|
1738
|
-
parts.push("");
|
|
1739
|
-
}
|
|
1740
|
-
if (params.previousQA && params.previousQA.length > 0) {
|
|
1741
|
-
parts.push("## Previous Questions & Answers");
|
|
1742
|
-
parts.push("");
|
|
1743
|
-
parts.push("The following questions have already been asked and answered:");
|
|
1744
|
-
parts.push("");
|
|
1745
|
-
for (const entry of params.previousQA) {
|
|
1746
|
-
parts.push(`**Q: ${entry.question.question}**`);
|
|
1747
|
-
if (entry.question.context) {
|
|
1748
|
-
parts.push(`Context: ${entry.question.context}`);
|
|
1749
|
-
}
|
|
1750
|
-
parts.push(`A: ${entry.answer.answer}`);
|
|
1751
|
-
parts.push("");
|
|
2316
|
+
const steps = this.getSteps();
|
|
2317
|
+
const specPath = this.getSpecPath(taskId, state.currentStep);
|
|
2318
|
+
if (existsSync5(specPath)) {
|
|
2319
|
+
const content = readFileSync5(specPath, "utf-8");
|
|
2320
|
+
const { content: body, data } = matter2(content);
|
|
2321
|
+
data.status = "approved";
|
|
2322
|
+
data.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
2323
|
+
writeFileSync3(specPath, matter2.stringify(body, data));
|
|
1752
2324
|
}
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
parts.push(' "id": "q1",');
|
|
1773
|
-
parts.push(' "question": "Your specific question?",');
|
|
1774
|
-
parts.push(' "context": "Why this matters for the document",');
|
|
1775
|
-
parts.push(' "options": ["Option A", "Option B"] // optional');
|
|
1776
|
-
parts.push(" }");
|
|
1777
|
-
parts.push(" ]");
|
|
1778
|
-
parts.push("}");
|
|
1779
|
-
parts.push("```");
|
|
1780
|
-
parts.push("");
|
|
1781
|
-
parts.push('If no questions are needed, return: `{"questions": []}`');
|
|
1782
|
-
parts.push("");
|
|
1783
|
-
parts.push("**Important:** Output ONLY the JSON, no other text.");
|
|
1784
|
-
parts.push("");
|
|
1785
|
-
return parts.join("\n");
|
|
1786
|
-
}
|
|
1787
|
-
function buildGeneratePrompt(params) {
|
|
1788
|
-
const cwd = params.cwd || process.cwd();
|
|
1789
|
-
const config = loadConfig(cwd);
|
|
1790
|
-
const stepsDir = getStepsDir(cwd);
|
|
1791
|
-
const outputsDir = getOutputsDir(cwd);
|
|
1792
|
-
const isFirstStep = params.stepIndex === 1;
|
|
1793
|
-
const prevStep = params.stepIndex > 1 ? config.steps[params.stepIndex - 2] : null;
|
|
1794
|
-
const instructionPath = join5(stepsDir, params.step, "instruction.md");
|
|
1795
|
-
const templatePath = join5(stepsDir, params.step, "template.md");
|
|
1796
|
-
const outputPath = join5(outputsDir, params.taskId, `${params.step}.md`);
|
|
1797
|
-
if (!existsSync5(instructionPath)) {
|
|
1798
|
-
throw new Error(`Instruction not found: ${instructionPath}`);
|
|
1799
|
-
}
|
|
1800
|
-
const instruction = readFileSync5(instructionPath, "utf-8");
|
|
1801
|
-
const template = existsSync5(templatePath) ? readFileSync5(templatePath, "utf-8") : null;
|
|
1802
|
-
let previousSpec = null;
|
|
1803
|
-
if (prevStep) {
|
|
1804
|
-
const prevPath = join5(outputsDir, params.taskId, `${prevStep}.md`);
|
|
1805
|
-
if (existsSync5(prevPath)) {
|
|
1806
|
-
previousSpec = {
|
|
1807
|
-
step: prevStep,
|
|
1808
|
-
content: readFileSync5(prevPath, "utf-8")
|
|
1809
|
-
};
|
|
2325
|
+
if (state.stepIndex < state.totalSteps) {
|
|
2326
|
+
state.currentStep = steps[state.stepIndex];
|
|
2327
|
+
state.stepIndex += 1;
|
|
2328
|
+
state.status = "phase_explore";
|
|
2329
|
+
state.phase = "explore";
|
|
2330
|
+
state.context = void 0;
|
|
2331
|
+
state.exploreOutput = void 0;
|
|
2332
|
+
state.questions = void 0;
|
|
2333
|
+
state.answers = void 0;
|
|
2334
|
+
state.qaHistory = void 0;
|
|
2335
|
+
state.verifyOutput = void 0;
|
|
2336
|
+
state.verifyAttempts = void 0;
|
|
2337
|
+
state.revisionFeedback = void 0;
|
|
2338
|
+
this.saveState(state);
|
|
2339
|
+
return this.responsePhaseExplore(state);
|
|
2340
|
+
} else {
|
|
2341
|
+
state.status = "completed";
|
|
2342
|
+
this.saveState(state);
|
|
2343
|
+
return this.responseComplete(state, "completed");
|
|
1810
2344
|
}
|
|
1811
2345
|
}
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
parts.push(instruction);
|
|
1820
|
-
parts.push("");
|
|
1821
|
-
if (template) {
|
|
1822
|
-
parts.push("## Document Template");
|
|
1823
|
-
parts.push("");
|
|
1824
|
-
parts.push("**CRITICAL: You MUST follow this template structure completely.**");
|
|
1825
|
-
parts.push("");
|
|
1826
|
-
parts.push(template);
|
|
1827
|
-
parts.push("");
|
|
1828
|
-
}
|
|
1829
|
-
parts.push("## Gathered Context");
|
|
1830
|
-
parts.push("");
|
|
1831
|
-
parts.push(params.gatheredContext);
|
|
1832
|
-
parts.push("");
|
|
1833
|
-
if (params.answers && params.answers.length > 0) {
|
|
1834
|
-
parts.push("## User Answers");
|
|
1835
|
-
parts.push("");
|
|
1836
|
-
for (const answer of params.answers) {
|
|
1837
|
-
parts.push(`- **${answer.questionId}**: ${answer.answer}`);
|
|
2346
|
+
/**
|
|
2347
|
+
* Request revision with feedback - goes back to draft phase
|
|
2348
|
+
*/
|
|
2349
|
+
cmdRevise(taskId, feedback) {
|
|
2350
|
+
const state = this.loadState(taskId);
|
|
2351
|
+
if (!state) {
|
|
2352
|
+
return this.responseError(`No workflow found: ${taskId}`, taskId);
|
|
1838
2353
|
}
|
|
1839
|
-
|
|
2354
|
+
state.status = "phase_execute";
|
|
2355
|
+
state.phase = "draft";
|
|
2356
|
+
state.revisionFeedback = feedback;
|
|
2357
|
+
state.verifyOutput = void 0;
|
|
2358
|
+
state.verifyAttempts = 0;
|
|
2359
|
+
this.saveState(state);
|
|
2360
|
+
return this.responsePhaseExecute(state);
|
|
1840
2361
|
}
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
2362
|
+
/**
|
|
2363
|
+
* Reject and stop workflow
|
|
2364
|
+
*/
|
|
2365
|
+
cmdReject(taskId) {
|
|
2366
|
+
const state = this.loadState(taskId);
|
|
2367
|
+
if (!state) {
|
|
2368
|
+
return this.responseError(`No workflow found: ${taskId}`, taskId);
|
|
2369
|
+
}
|
|
2370
|
+
const specPath = this.getSpecPath(taskId, state.currentStep);
|
|
2371
|
+
if (existsSync5(specPath)) {
|
|
2372
|
+
const content = readFileSync5(specPath, "utf-8");
|
|
2373
|
+
const { content: body, data } = matter2(content);
|
|
2374
|
+
data.status = "rejected";
|
|
2375
|
+
data.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
2376
|
+
writeFileSync3(specPath, matter2.stringify(body, data));
|
|
2377
|
+
}
|
|
2378
|
+
state.status = "rejected";
|
|
2379
|
+
this.saveState(state);
|
|
2380
|
+
return this.responseComplete(state, "rejected");
|
|
1851
2381
|
}
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
parts.push("");
|
|
2382
|
+
/**
|
|
2383
|
+
* Stop workflow (can resume later)
|
|
2384
|
+
*/
|
|
2385
|
+
cmdStop(taskId) {
|
|
2386
|
+
const state = this.loadState(taskId);
|
|
2387
|
+
if (!state) {
|
|
2388
|
+
return this.responseError(`No workflow found: ${taskId}`, taskId);
|
|
2389
|
+
}
|
|
2390
|
+
state.status = "stopped";
|
|
2391
|
+
this.saveState(state);
|
|
2392
|
+
return this.responseComplete(state, "stopped");
|
|
1864
2393
|
}
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
parts.push("## Your Position");
|
|
1901
|
-
parts.push("");
|
|
1902
|
-
parts.push(`- **Path:** ${section.position.path.join(" > ")}`);
|
|
1903
|
-
parts.push(`- **Siblings:** ${section.position.siblings.join(", ") || "None"}`);
|
|
1904
|
-
parts.push(`- **Parent:** ${section.position.parent || "Root"}`);
|
|
1905
|
-
parts.push("");
|
|
1906
|
-
if (gatheredContext) {
|
|
1907
|
-
parts.push("## Gathered Context");
|
|
1908
|
-
parts.push("");
|
|
1909
|
-
parts.push(gatheredContext);
|
|
1910
|
-
parts.push("");
|
|
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
|
+
}
|
|
1911
2429
|
}
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
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);
|
|
1917
2437
|
}
|
|
1918
|
-
|
|
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);
|
|
1919
2466
|
}
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
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);
|
|
1925
2497
|
}
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
2498
|
+
/**
|
|
2499
|
+
* Get current workflow status
|
|
2500
|
+
*/
|
|
2501
|
+
cmdStatus(taskId) {
|
|
2502
|
+
const state = this.loadState(taskId);
|
|
2503
|
+
if (!state) {
|
|
2504
|
+
return this.responseError(`No workflow found: ${taskId}`, taskId);
|
|
2505
|
+
}
|
|
2506
|
+
const migratedStatus = this.migrateStatus(state.status);
|
|
2507
|
+
if (migratedStatus !== state.status) {
|
|
2508
|
+
state.status = migratedStatus;
|
|
2509
|
+
this.saveState(state);
|
|
2510
|
+
}
|
|
2511
|
+
switch (state.status) {
|
|
2512
|
+
// Legacy (backward compatibility)
|
|
2513
|
+
case "phase_context":
|
|
2514
|
+
return this.responsePhaseContext(state);
|
|
2515
|
+
case "phase_generate":
|
|
2516
|
+
return this.responsePhaseGenerate(state);
|
|
2517
|
+
case "phase_draft":
|
|
2518
|
+
return this.responsePhaseExecute(state);
|
|
2519
|
+
// New 5-phase workflow
|
|
2520
|
+
case "phase_explore":
|
|
2521
|
+
return this.responsePhaseExplore(state);
|
|
2522
|
+
case "phase_clarify":
|
|
2523
|
+
return this.responsePhaseClarify(state);
|
|
2524
|
+
case "clarify_pending":
|
|
2525
|
+
return this.responseCheckpointClarify(state);
|
|
2526
|
+
case "phase_execute":
|
|
2527
|
+
return this.responsePhaseExecute(state);
|
|
2528
|
+
case "phase_verify":
|
|
2529
|
+
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
|
+
// Checkpoints and completion
|
|
2540
|
+
case "approve_pending":
|
|
2541
|
+
return this.responseCheckpointApprove(state);
|
|
2542
|
+
case "completed":
|
|
2543
|
+
case "stopped":
|
|
2544
|
+
case "rejected":
|
|
2545
|
+
return this.responseComplete(state, state.status);
|
|
2546
|
+
default:
|
|
2547
|
+
return this.responseError(`Unknown status: ${state.status}`, taskId);
|
|
2548
|
+
}
|
|
1972
2549
|
}
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
parts.push("- Preserve all content from child sections");
|
|
1982
|
-
parts.push("");
|
|
1983
|
-
return {
|
|
1984
|
-
prompt: parts.join("\n"),
|
|
1985
|
-
outputPath: group.outputPath
|
|
1986
|
-
};
|
|
1987
|
-
}
|
|
2550
|
+
/**
|
|
2551
|
+
* Migrate legacy workflow status to new status
|
|
2552
|
+
* This allows existing workflows to continue working
|
|
2553
|
+
*/
|
|
2554
|
+
migrateStatus(status) {
|
|
2555
|
+
return status;
|
|
2556
|
+
}
|
|
2557
|
+
};
|
|
1988
2558
|
|
|
1989
2559
|
// src/core/step-executor.ts
|
|
1990
|
-
import { readFileSync as readFileSync6,
|
|
1991
|
-
import { dirname as dirname3 } from "path";
|
|
1992
|
-
import
|
|
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";
|
|
2562
|
+
import matter3 from "gray-matter";
|
|
2563
|
+
var fsExistsSync = existsSync6;
|
|
1993
2564
|
var StepExecutor = class {
|
|
1994
2565
|
adapter;
|
|
1995
2566
|
config;
|
|
@@ -2005,6 +2576,7 @@ var StepExecutor = class {
|
|
|
2005
2576
|
/**
|
|
2006
2577
|
* Execute context phase - AI gathers context
|
|
2007
2578
|
* Returns gathered context as string
|
|
2579
|
+
* @deprecated Use executeExplorePhase instead
|
|
2008
2580
|
*/
|
|
2009
2581
|
async executeContextPhase(step, context) {
|
|
2010
2582
|
this.adapter.io.notify(`Phase 1/4: Gathering context for ${step}`, "info");
|
|
@@ -2030,6 +2602,39 @@ var StepExecutor = class {
|
|
|
2030
2602
|
};
|
|
2031
2603
|
}
|
|
2032
2604
|
// ==========================================================================
|
|
2605
|
+
// Phase 1 (New): Explore - Deep Codebase Analysis
|
|
2606
|
+
// ==========================================================================
|
|
2607
|
+
/**
|
|
2608
|
+
* Execute explore phase - AI deeply analyzes codebase
|
|
2609
|
+
* Returns detailed exploration output with patterns, constraints, etc.
|
|
2610
|
+
*/
|
|
2611
|
+
async executeExplorePhase(step, context) {
|
|
2612
|
+
this.adapter.io.notify(`Phase 1/5: Exploring codebase for ${step}`, "info");
|
|
2613
|
+
const params = {
|
|
2614
|
+
taskId: context.taskId,
|
|
2615
|
+
step,
|
|
2616
|
+
description: context.description,
|
|
2617
|
+
stepIndex: context.stepIndex,
|
|
2618
|
+
totalSteps: context.totalSteps,
|
|
2619
|
+
previousOutput: context.previousOutput,
|
|
2620
|
+
cwd: this.cwd
|
|
2621
|
+
};
|
|
2622
|
+
const prompt = buildExplorePrompt(params);
|
|
2623
|
+
const response = await this.adapter.ai.execute({
|
|
2624
|
+
prompt,
|
|
2625
|
+
outputPath: ""
|
|
2626
|
+
// No file output needed
|
|
2627
|
+
});
|
|
2628
|
+
const exploreOutput = this.parseExploreOutput(response || "");
|
|
2629
|
+
this.adapter.io.notify(`Found ${exploreOutput.relevantFiles.length} relevant files, ${exploreOutput.patterns.length} patterns`, "info");
|
|
2630
|
+
return {
|
|
2631
|
+
phase: "explore",
|
|
2632
|
+
exploreOutput,
|
|
2633
|
+
context: JSON.stringify(exploreOutput)
|
|
2634
|
+
// Also set legacy context
|
|
2635
|
+
};
|
|
2636
|
+
}
|
|
2637
|
+
// ==========================================================================
|
|
2033
2638
|
// Phase 2: Clarify (Question Generation)
|
|
2034
2639
|
// ==========================================================================
|
|
2035
2640
|
/**
|
|
@@ -2082,6 +2687,7 @@ var StepExecutor = class {
|
|
|
2082
2687
|
// ==========================================================================
|
|
2083
2688
|
/**
|
|
2084
2689
|
* Execute generate phase - AI creates document
|
|
2690
|
+
* @deprecated Use executeDraftPhase instead
|
|
2085
2691
|
*/
|
|
2086
2692
|
async executeGeneratePhase(step, context) {
|
|
2087
2693
|
this.adapter.io.notify(`Phase 3/4: Generating document for ${step}`, "info");
|
|
@@ -2108,6 +2714,94 @@ var StepExecutor = class {
|
|
|
2108
2714
|
return { phase: "generate" };
|
|
2109
2715
|
}
|
|
2110
2716
|
// ==========================================================================
|
|
2717
|
+
// Phase 3 (New): Execute - Document/Code Generation with Explore Output
|
|
2718
|
+
// ==========================================================================
|
|
2719
|
+
/**
|
|
2720
|
+
* Execute the execute phase - AI creates document/code using explore output
|
|
2721
|
+
*/
|
|
2722
|
+
async executeExecutePhase(step, context) {
|
|
2723
|
+
const attemptInfo = context.verifyAttempts && context.verifyAttempts > 1 ? ` (attempt ${context.verifyAttempts}/3)` : "";
|
|
2724
|
+
this.adapter.io.notify(`Phase 3/5: Executing for ${step}${attemptInfo}`, "info");
|
|
2725
|
+
if (!context.exploreOutput && !context.gatheredContext) {
|
|
2726
|
+
throw new Error("Explore phase must be completed before draft phase");
|
|
2727
|
+
}
|
|
2728
|
+
const exploreOutput = context.exploreOutput || {
|
|
2729
|
+
summary: context.gatheredContext || "",
|
|
2730
|
+
relevantFiles: [],
|
|
2731
|
+
patterns: [],
|
|
2732
|
+
constraints: [],
|
|
2733
|
+
dependencies: []
|
|
2734
|
+
};
|
|
2735
|
+
const params = {
|
|
2736
|
+
taskId: context.taskId,
|
|
2737
|
+
step,
|
|
2738
|
+
description: context.description,
|
|
2739
|
+
stepIndex: context.stepIndex,
|
|
2740
|
+
totalSteps: context.totalSteps,
|
|
2741
|
+
exploreOutput,
|
|
2742
|
+
answers: context.answers,
|
|
2743
|
+
revisionFeedback: context.revisionFeedback,
|
|
2744
|
+
verifyFeedback: context.verifyFeedback,
|
|
2745
|
+
cwd: this.cwd
|
|
2746
|
+
};
|
|
2747
|
+
const { prompt, outputPath } = buildExecutePrompt(params);
|
|
2748
|
+
await this.adapter.ai.execute({ prompt, outputPath });
|
|
2749
|
+
if (!existsSync6(outputPath)) {
|
|
2750
|
+
throw new Error(`AI did not create document at ${outputPath}`);
|
|
2751
|
+
}
|
|
2752
|
+
this.adapter.io.notify(`Document created: ${outputPath}`, "success");
|
|
2753
|
+
return { phase: "execute" };
|
|
2754
|
+
}
|
|
2755
|
+
/**
|
|
2756
|
+
* @deprecated Use executeExecutePhase instead
|
|
2757
|
+
*/
|
|
2758
|
+
async executeDraftPhase(step, context) {
|
|
2759
|
+
return this.executeExecutePhase(step, context);
|
|
2760
|
+
}
|
|
2761
|
+
// ==========================================================================
|
|
2762
|
+
// Phase 4 (New): Verify - Self-Validation
|
|
2763
|
+
// ==========================================================================
|
|
2764
|
+
/**
|
|
2765
|
+
* Execute verify phase - AI validates the generated document
|
|
2766
|
+
*/
|
|
2767
|
+
async executeVerifyPhase(step, context) {
|
|
2768
|
+
const attempts = context.verifyAttempts || 1;
|
|
2769
|
+
this.adapter.io.notify(`Phase 4/5: Verifying document for ${step} (attempt ${attempts}/3)`, "info");
|
|
2770
|
+
const outputsDir = getOutputsDir(this.cwd);
|
|
2771
|
+
const documentPath = join6(outputsDir, context.taskId, `${step}.md`);
|
|
2772
|
+
if (!existsSync6(documentPath)) {
|
|
2773
|
+
throw new Error(`Document not found: ${documentPath}`);
|
|
2774
|
+
}
|
|
2775
|
+
const params = {
|
|
2776
|
+
taskId: context.taskId,
|
|
2777
|
+
step,
|
|
2778
|
+
description: context.description,
|
|
2779
|
+
stepIndex: context.stepIndex,
|
|
2780
|
+
totalSteps: context.totalSteps,
|
|
2781
|
+
documentPath,
|
|
2782
|
+
verifyAttempts: attempts,
|
|
2783
|
+
cwd: this.cwd
|
|
2784
|
+
};
|
|
2785
|
+
const prompt = buildVerifyPrompt(params);
|
|
2786
|
+
const response = await this.adapter.ai.execute({
|
|
2787
|
+
prompt,
|
|
2788
|
+
outputPath: ""
|
|
2789
|
+
// No file output needed
|
|
2790
|
+
});
|
|
2791
|
+
const verifyOutput = this.parseVerifyOutput(response || "");
|
|
2792
|
+
if (verifyOutput.passed) {
|
|
2793
|
+
this.adapter.io.notify(`Verification passed! Scores: ${JSON.stringify(verifyOutput.score)}`, "success");
|
|
2794
|
+
} else {
|
|
2795
|
+
const errorCount = verifyOutput.issues.filter((i) => i.severity === "error").length;
|
|
2796
|
+
const warningCount = verifyOutput.issues.filter((i) => i.severity === "warning").length;
|
|
2797
|
+
this.adapter.io.notify(`Verification failed: ${errorCount} errors, ${warningCount} warnings`, "warning");
|
|
2798
|
+
}
|
|
2799
|
+
return {
|
|
2800
|
+
phase: "verify",
|
|
2801
|
+
verifyOutput
|
|
2802
|
+
};
|
|
2803
|
+
}
|
|
2804
|
+
// ==========================================================================
|
|
2111
2805
|
// Phase 3 (Section Mode): Parallel Section Generation
|
|
2112
2806
|
// ==========================================================================
|
|
2113
2807
|
/**
|
|
@@ -2379,6 +3073,75 @@ var StepExecutor = class {
|
|
|
2379
3073
|
}
|
|
2380
3074
|
return { questions: [] };
|
|
2381
3075
|
}
|
|
3076
|
+
/**
|
|
3077
|
+
* Parse explore phase output (JSON)
|
|
3078
|
+
*/
|
|
3079
|
+
parseExploreOutput(response) {
|
|
3080
|
+
try {
|
|
3081
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
3082
|
+
if (jsonMatch) {
|
|
3083
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
3084
|
+
if (typeof parsed.summary === "string") {
|
|
3085
|
+
return {
|
|
3086
|
+
summary: parsed.summary || "",
|
|
3087
|
+
relevantFiles: Array.isArray(parsed.relevantFiles) ? parsed.relevantFiles : [],
|
|
3088
|
+
patterns: Array.isArray(parsed.patterns) ? parsed.patterns : [],
|
|
3089
|
+
constraints: Array.isArray(parsed.constraints) ? parsed.constraints : [],
|
|
3090
|
+
dependencies: Array.isArray(parsed.dependencies) ? parsed.dependencies : []
|
|
3091
|
+
};
|
|
3092
|
+
}
|
|
3093
|
+
}
|
|
3094
|
+
} catch {
|
|
3095
|
+
}
|
|
3096
|
+
return {
|
|
3097
|
+
summary: response,
|
|
3098
|
+
relevantFiles: [],
|
|
3099
|
+
patterns: [],
|
|
3100
|
+
constraints: [],
|
|
3101
|
+
dependencies: []
|
|
3102
|
+
};
|
|
3103
|
+
}
|
|
3104
|
+
/**
|
|
3105
|
+
* Parse verify phase output (JSON)
|
|
3106
|
+
*/
|
|
3107
|
+
parseVerifyOutput(response) {
|
|
3108
|
+
try {
|
|
3109
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
3110
|
+
if (jsonMatch) {
|
|
3111
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
3112
|
+
if (typeof parsed.passed === "boolean" && parsed.score) {
|
|
3113
|
+
return {
|
|
3114
|
+
passed: parsed.passed,
|
|
3115
|
+
score: {
|
|
3116
|
+
requirementsCoverage: parsed.score.requirementsCoverage ?? 0,
|
|
3117
|
+
templateCompliance: parsed.score.templateCompliance ?? 0,
|
|
3118
|
+
consistency: parsed.score.consistency ?? 0,
|
|
3119
|
+
completeness: parsed.score.completeness ?? 0
|
|
3120
|
+
},
|
|
3121
|
+
issues: Array.isArray(parsed.issues) ? parsed.issues : [],
|
|
3122
|
+
summary: parsed.summary || ""
|
|
3123
|
+
};
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
3126
|
+
} catch {
|
|
3127
|
+
}
|
|
3128
|
+
return {
|
|
3129
|
+
passed: false,
|
|
3130
|
+
score: {
|
|
3131
|
+
requirementsCoverage: 0,
|
|
3132
|
+
templateCompliance: 0,
|
|
3133
|
+
consistency: 0,
|
|
3134
|
+
completeness: 0
|
|
3135
|
+
},
|
|
3136
|
+
issues: [{
|
|
3137
|
+
severity: "error",
|
|
3138
|
+
category: "parsing",
|
|
3139
|
+
description: "Failed to parse verification output",
|
|
3140
|
+
suggestion: "Ensure AI returns valid JSON"
|
|
3141
|
+
}],
|
|
3142
|
+
summary: "Verification parsing failed"
|
|
3143
|
+
};
|
|
3144
|
+
}
|
|
2382
3145
|
/**
|
|
2383
3146
|
* Update document status in frontmatter
|
|
2384
3147
|
*/
|
|
@@ -2990,7 +3753,7 @@ async function startCommand(query, options) {
|
|
|
2990
3753
|
console.log(`
|
|
2991
3754
|
\u{1F680} Starting workflow: ${query}
|
|
2992
3755
|
`);
|
|
2993
|
-
if (response.type === "phase" && response.phase === "context") {
|
|
3756
|
+
if (response.type === "phase" && (response.phase === "explore" || response.phase === "context")) {
|
|
2994
3757
|
taskId = response.taskId;
|
|
2995
3758
|
if (isGitHubMode && "io" in adapter && "setTaskId" in adapter.io) {
|
|
2996
3759
|
adapter.io.setTaskId(taskId);
|
|
@@ -3001,7 +3764,21 @@ async function startCommand(query, options) {
|
|
|
3001
3764
|
if (response.type === "phase") {
|
|
3002
3765
|
const phaseResponse = response;
|
|
3003
3766
|
taskId = phaseResponse.taskId;
|
|
3004
|
-
if (phaseResponse.phase === "
|
|
3767
|
+
if (phaseResponse.phase === "explore") {
|
|
3768
|
+
const exploreResp = phaseResponse;
|
|
3769
|
+
console.log(`
|
|
3770
|
+
--- Step ${exploreResp.stepIndex}/${exploreResp.totalSteps}: ${exploreResp.step} ---`);
|
|
3771
|
+
console.log("Phase 1/5: Exploring codebase...\n");
|
|
3772
|
+
const stepContext = {
|
|
3773
|
+
taskId: exploreResp.taskId,
|
|
3774
|
+
description: exploreResp.description,
|
|
3775
|
+
stepIndex: exploreResp.stepIndex,
|
|
3776
|
+
totalSteps: exploreResp.totalSteps,
|
|
3777
|
+
previousOutput: exploreResp.context.previousOutput
|
|
3778
|
+
};
|
|
3779
|
+
const result = await stepExecutor.executeExplorePhase(exploreResp.step, stepContext);
|
|
3780
|
+
response = orchestrator.cmdExploreDone(taskId, result.exploreOutput);
|
|
3781
|
+
} else if (phaseResponse.phase === "context") {
|
|
3005
3782
|
const contextResp = phaseResponse;
|
|
3006
3783
|
console.log(`
|
|
3007
3784
|
--- Step ${contextResp.stepIndex}/${contextResp.totalSteps}: ${contextResp.step} ---`);
|
|
@@ -3028,6 +3805,36 @@ async function startCommand(query, options) {
|
|
|
3028
3805
|
};
|
|
3029
3806
|
const result = await stepExecutor.executeClarifyPhase(clarifyResp.step, stepContext);
|
|
3030
3807
|
response = orchestrator.cmdClarifyDone(taskId, result.questions || []);
|
|
3808
|
+
} else if (phaseResponse.phase === "execute" || phaseResponse.phase === "draft") {
|
|
3809
|
+
const executeResp = phaseResponse;
|
|
3810
|
+
const attemptInfo = executeResp.context.verifyFeedback ? " (auto-fix)" : "";
|
|
3811
|
+
console.log(`Phase 3/5: Executing${attemptInfo}...
|
|
3812
|
+
`);
|
|
3813
|
+
const stepContext = {
|
|
3814
|
+
taskId: executeResp.taskId,
|
|
3815
|
+
description: executeResp.description,
|
|
3816
|
+
stepIndex: executeResp.stepIndex,
|
|
3817
|
+
totalSteps: executeResp.totalSteps,
|
|
3818
|
+
exploreOutput: executeResp.exploreOutput,
|
|
3819
|
+
answers: executeResp.answers,
|
|
3820
|
+
revisionFeedback: executeResp.context.revisionFeedback,
|
|
3821
|
+
verifyFeedback: executeResp.context.verifyFeedback
|
|
3822
|
+
};
|
|
3823
|
+
await stepExecutor.executeExecutePhase(executeResp.step, stepContext);
|
|
3824
|
+
response = orchestrator.cmdExecuteDone(taskId);
|
|
3825
|
+
} else if (phaseResponse.phase === "verify") {
|
|
3826
|
+
const verifyResp = phaseResponse;
|
|
3827
|
+
console.log(`Phase 4/5: Verifying document (attempt ${verifyResp.verifyAttempts}/${verifyResp.maxAttempts})...
|
|
3828
|
+
`);
|
|
3829
|
+
const stepContext = {
|
|
3830
|
+
taskId: verifyResp.taskId,
|
|
3831
|
+
description: verifyResp.description,
|
|
3832
|
+
stepIndex: verifyResp.stepIndex,
|
|
3833
|
+
totalSteps: verifyResp.totalSteps,
|
|
3834
|
+
verifyAttempts: verifyResp.verifyAttempts
|
|
3835
|
+
};
|
|
3836
|
+
const result = await stepExecutor.executeVerifyPhase(verifyResp.step, stepContext);
|
|
3837
|
+
response = orchestrator.cmdVerifyDone(taskId, result.verifyOutput);
|
|
3031
3838
|
} else if (phaseResponse.phase === "generate") {
|
|
3032
3839
|
const generateResp = phaseResponse;
|
|
3033
3840
|
console.log("Phase 3/4: Generating document...\n");
|
|
@@ -3280,7 +4087,21 @@ async function resumeCommand(options) {
|
|
|
3280
4087
|
if (response.type === "phase") {
|
|
3281
4088
|
const phaseResponse = response;
|
|
3282
4089
|
taskId = phaseResponse.taskId;
|
|
3283
|
-
if (phaseResponse.phase === "
|
|
4090
|
+
if (phaseResponse.phase === "explore") {
|
|
4091
|
+
const exploreResp = phaseResponse;
|
|
4092
|
+
console.log(`
|
|
4093
|
+
--- Step ${exploreResp.stepIndex}/${exploreResp.totalSteps}: ${exploreResp.step} ---`);
|
|
4094
|
+
console.log("Phase 1/5: Exploring codebase...\n");
|
|
4095
|
+
const stepContext = {
|
|
4096
|
+
taskId: exploreResp.taskId,
|
|
4097
|
+
description: exploreResp.description,
|
|
4098
|
+
stepIndex: exploreResp.stepIndex,
|
|
4099
|
+
totalSteps: exploreResp.totalSteps,
|
|
4100
|
+
previousOutput: exploreResp.context.previousOutput
|
|
4101
|
+
};
|
|
4102
|
+
const result = await stepExecutor.executeExplorePhase(exploreResp.step, stepContext);
|
|
4103
|
+
response = orchestrator.cmdExploreDone(taskId, result.exploreOutput);
|
|
4104
|
+
} else if (phaseResponse.phase === "context") {
|
|
3284
4105
|
const contextResp = phaseResponse;
|
|
3285
4106
|
console.log(`
|
|
3286
4107
|
--- Step ${contextResp.stepIndex}/${contextResp.totalSteps}: ${contextResp.step} ---`);
|
|
@@ -3306,6 +4127,36 @@ async function resumeCommand(options) {
|
|
|
3306
4127
|
};
|
|
3307
4128
|
const result = await stepExecutor.executeClarifyPhase(clarifyResp.step, stepContext);
|
|
3308
4129
|
response = orchestrator.cmdClarifyDone(taskId, result.questions || []);
|
|
4130
|
+
} else if (phaseResponse.phase === "execute" || phaseResponse.phase === "draft") {
|
|
4131
|
+
const executeResp = phaseResponse;
|
|
4132
|
+
const attemptInfo = executeResp.context.verifyFeedback ? " (auto-fix)" : "";
|
|
4133
|
+
console.log(`Phase 3/5: Executing${attemptInfo}...
|
|
4134
|
+
`);
|
|
4135
|
+
const stepContext = {
|
|
4136
|
+
taskId: executeResp.taskId,
|
|
4137
|
+
description: executeResp.description,
|
|
4138
|
+
stepIndex: executeResp.stepIndex,
|
|
4139
|
+
totalSteps: executeResp.totalSteps,
|
|
4140
|
+
exploreOutput: executeResp.exploreOutput,
|
|
4141
|
+
answers: executeResp.answers,
|
|
4142
|
+
revisionFeedback: executeResp.context.revisionFeedback,
|
|
4143
|
+
verifyFeedback: executeResp.context.verifyFeedback
|
|
4144
|
+
};
|
|
4145
|
+
await stepExecutor.executeExecutePhase(executeResp.step, stepContext);
|
|
4146
|
+
response = orchestrator.cmdExecuteDone(taskId);
|
|
4147
|
+
} else if (phaseResponse.phase === "verify") {
|
|
4148
|
+
const verifyResp = phaseResponse;
|
|
4149
|
+
console.log(`Phase 4/5: Verifying document (attempt ${verifyResp.verifyAttempts}/${verifyResp.maxAttempts})...
|
|
4150
|
+
`);
|
|
4151
|
+
const stepContext = {
|
|
4152
|
+
taskId: verifyResp.taskId,
|
|
4153
|
+
description: verifyResp.description,
|
|
4154
|
+
stepIndex: verifyResp.stepIndex,
|
|
4155
|
+
totalSteps: verifyResp.totalSteps,
|
|
4156
|
+
verifyAttempts: verifyResp.verifyAttempts
|
|
4157
|
+
};
|
|
4158
|
+
const result = await stepExecutor.executeVerifyPhase(verifyResp.step, stepContext);
|
|
4159
|
+
response = orchestrator.cmdVerifyDone(taskId, result.verifyOutput);
|
|
3309
4160
|
} else if (phaseResponse.phase === "generate") {
|
|
3310
4161
|
const generateResp = phaseResponse;
|
|
3311
4162
|
console.log("Phase 3/4: Generating document...\n");
|
|
@@ -3551,11 +4402,14 @@ Parse JSON response \u2192 execute action from table below \u2192 loop until \`t
|
|
|
3551
4402
|
|
|
3552
4403
|
| \`phase\` | Action |
|
|
3553
4404
|
|---------|--------|
|
|
3554
|
-
| \`
|
|
4405
|
+
| \`explore\` | [ACTION_EXPLORE](#action_explore) |
|
|
3555
4406
|
| \`clarify\` | [ACTION_CLARIFY](#action_clarify) |
|
|
3556
|
-
| \`
|
|
4407
|
+
| \`execute\` | [ACTION_EXECUTE](#action_execute) |
|
|
4408
|
+
| \`verify\` | [ACTION_VERIFY](#action_verify) |
|
|
3557
4409
|
| \`generate-sections\` | [ACTION_PARALLEL_SECTIONS](#action_parallel_sections) |
|
|
3558
4410
|
| \`consolidate\` | [ACTION_PARALLEL_CONSOLIDATE](#action_parallel_consolidate) |
|
|
4411
|
+
| \`context\` | [ACTION_CONTEXT](#action_context) (legacy) |
|
|
4412
|
+
| \`generate\` | [ACTION_GENERATE](#action_generate) (legacy) |
|
|
3559
4413
|
|
|
3560
4414
|
### \`type: "checkpoint"\`
|
|
3561
4415
|
|
|
@@ -3580,28 +4434,66 @@ Print: "Error: {error}" \u2192 STOP
|
|
|
3580
4434
|
|
|
3581
4435
|
## Action Definitions
|
|
3582
4436
|
|
|
3583
|
-
|
|
4437
|
+
**IMPORTANT:** Each phase response includes a \`prompt\` field containing the exact instructions to follow.
|
|
4438
|
+
This ensures identical behavior across CLI, Claude Code, and GitHub modes.
|
|
4439
|
+
|
|
4440
|
+
### ACTION_EXPLORE
|
|
3584
4441
|
|
|
3585
4442
|
\`\`\`
|
|
3586
|
-
1.
|
|
3587
|
-
2.
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
4443
|
+
1. Follow the instructions in response.prompt EXACTLY
|
|
4444
|
+
2. The prompt tells you:
|
|
4445
|
+
- What to search for
|
|
4446
|
+
- How to analyze the codebase
|
|
4447
|
+
- The exact JSON output format required
|
|
4448
|
+
3. Bash: npx spets orchestrate explore-done {taskId} '{exploreJson}'
|
|
4449
|
+
4. Parse response \u2192 next action
|
|
3591
4450
|
\`\`\`
|
|
3592
4451
|
|
|
3593
4452
|
### ACTION_CLARIFY
|
|
3594
4453
|
|
|
3595
4454
|
\`\`\`
|
|
3596
|
-
1.
|
|
3597
|
-
2.
|
|
4455
|
+
1. Follow the instructions in response.prompt EXACTLY
|
|
4456
|
+
2. The prompt tells you:
|
|
4457
|
+
- What context to analyze
|
|
4458
|
+
- How to generate questions
|
|
4459
|
+
- The exact JSON output format required
|
|
3598
4460
|
3. Bash: npx spets orchestrate clarify-done {taskId} '{questionsJson}'
|
|
3599
4461
|
- Format: [{"id":"q1","question":"..."},...]
|
|
3600
4462
|
- Empty if no questions: []
|
|
3601
4463
|
4. Parse response \u2192 next action
|
|
3602
4464
|
\`\`\`
|
|
3603
4465
|
|
|
3604
|
-
###
|
|
4466
|
+
### ACTION_EXECUTE
|
|
4467
|
+
|
|
4468
|
+
\`\`\`
|
|
4469
|
+
1. Follow the instructions in response.prompt EXACTLY
|
|
4470
|
+
2. The prompt tells you:
|
|
4471
|
+
- The instruction and template to follow
|
|
4472
|
+
- The explore output and answers to use
|
|
4473
|
+
- Where to save the document/code (context.output)
|
|
4474
|
+
- Any revision/verify feedback to address
|
|
4475
|
+
3. Write the document/code to context.output
|
|
4476
|
+
4. Bash: npx spets orchestrate execute-done {taskId}
|
|
4477
|
+
5. Parse response \u2192 next action
|
|
4478
|
+
\`\`\`
|
|
4479
|
+
|
|
4480
|
+
### ACTION_VERIFY
|
|
4481
|
+
|
|
4482
|
+
\`\`\`
|
|
4483
|
+
1. Follow the instructions in response.prompt EXACTLY
|
|
4484
|
+
2. The prompt tells you:
|
|
4485
|
+
- The document to verify (already included in prompt)
|
|
4486
|
+
- The requirements and template to check against
|
|
4487
|
+
- The scoring criteria and pass conditions
|
|
4488
|
+
- The exact JSON output format required
|
|
4489
|
+
3. Bash: npx spets orchestrate verify-done {taskId} '{verifyJson}'
|
|
4490
|
+
4. Parse response \u2192 next action
|
|
4491
|
+
- If passed: goes to human review
|
|
4492
|
+
- If failed (attempts < 3): goes back to draft phase (auto-fix)
|
|
4493
|
+
- If failed (attempts >= 3): goes to human review with warning
|
|
4494
|
+
\`\`\`
|
|
4495
|
+
|
|
4496
|
+
### ACTION_GENERATE (legacy)
|
|
3605
4497
|
|
|
3606
4498
|
\`\`\`
|
|
3607
4499
|
1. Read(context.instruction)
|
|
@@ -3613,6 +4505,16 @@ Print: "Error: {error}" \u2192 STOP
|
|
|
3613
4505
|
7. Parse response \u2192 next action
|
|
3614
4506
|
\`\`\`
|
|
3615
4507
|
|
|
4508
|
+
### ACTION_CONTEXT (legacy)
|
|
4509
|
+
|
|
4510
|
+
\`\`\`
|
|
4511
|
+
1. Read(context.instruction)
|
|
4512
|
+
2. IF context.previousOutput EXISTS: Read(context.previousOutput)
|
|
4513
|
+
3. Explore codebase for: {description}
|
|
4514
|
+
4. Bash: npx spets orchestrate context-done {taskId}
|
|
4515
|
+
5. Parse response \u2192 next action
|
|
4516
|
+
\`\`\`
|
|
4517
|
+
|
|
3616
4518
|
### ACTION_PARALLEL_SECTIONS
|
|
3617
4519
|
|
|
3618
4520
|
**PARALLEL EXECUTION (FOREGROUND)**
|
|
@@ -3731,17 +4633,25 @@ Print: "Error: {error}" \u2192 STOP
|
|
|
3731
4633
|
## Orchestrator Commands Reference
|
|
3732
4634
|
|
|
3733
4635
|
\`\`\`bash
|
|
4636
|
+
# New 5-phase workflow
|
|
3734
4637
|
npx spets orchestrate init "<description>"
|
|
3735
|
-
npx spets orchestrate
|
|
4638
|
+
npx spets orchestrate explore-done <taskId> '<json>'
|
|
3736
4639
|
npx spets orchestrate clarify-done <taskId> '<json>'
|
|
3737
4640
|
npx spets orchestrate clarified <taskId> '<json>'
|
|
3738
|
-
npx spets orchestrate
|
|
3739
|
-
npx spets orchestrate
|
|
3740
|
-
npx spets orchestrate consolidate-level-done <taskId> <level>
|
|
4641
|
+
npx spets orchestrate execute-done <taskId>
|
|
4642
|
+
npx spets orchestrate verify-done <taskId> '<json>'
|
|
3741
4643
|
npx spets orchestrate approve <taskId>
|
|
3742
4644
|
npx spets orchestrate revise <taskId> "<feedback>"
|
|
3743
4645
|
npx spets orchestrate reject <taskId>
|
|
3744
4646
|
npx spets orchestrate stop <taskId>
|
|
4647
|
+
|
|
4648
|
+
# Section-based workflow
|
|
4649
|
+
npx spets orchestrate sections-done <taskId>
|
|
4650
|
+
npx spets orchestrate consolidate-level-done <taskId> <level>
|
|
4651
|
+
|
|
4652
|
+
# Legacy (backward compatible)
|
|
4653
|
+
npx spets orchestrate context-done <taskId>
|
|
4654
|
+
npx spets orchestrate generate-done <taskId>
|
|
3745
4655
|
\`\`\`
|
|
3746
4656
|
|
|
3747
4657
|
---
|
|
@@ -4293,6 +5203,31 @@ async function orchestrateCommand(action, args) {
|
|
|
4293
5203
|
outputJSON(result);
|
|
4294
5204
|
break;
|
|
4295
5205
|
}
|
|
5206
|
+
case "explore-done": {
|
|
5207
|
+
const taskId = args[0];
|
|
5208
|
+
const exploreJson = args[1];
|
|
5209
|
+
if (!taskId) {
|
|
5210
|
+
outputError("Task ID is required for explore-done");
|
|
5211
|
+
return;
|
|
5212
|
+
}
|
|
5213
|
+
let exploreOutput = {
|
|
5214
|
+
summary: "",
|
|
5215
|
+
relevantFiles: [],
|
|
5216
|
+
patterns: [],
|
|
5217
|
+
constraints: [],
|
|
5218
|
+
dependencies: []
|
|
5219
|
+
};
|
|
5220
|
+
if (exploreJson) {
|
|
5221
|
+
try {
|
|
5222
|
+
exploreOutput = JSON.parse(exploreJson);
|
|
5223
|
+
} catch {
|
|
5224
|
+
exploreOutput.summary = exploreJson;
|
|
5225
|
+
}
|
|
5226
|
+
}
|
|
5227
|
+
const result = orchestrator.cmdExploreDone(taskId, exploreOutput);
|
|
5228
|
+
outputJSON(result);
|
|
5229
|
+
break;
|
|
5230
|
+
}
|
|
4296
5231
|
case "clarify-done": {
|
|
4297
5232
|
const taskId = args[0];
|
|
4298
5233
|
const questionsJson = args[1];
|
|
@@ -4323,6 +5258,57 @@ async function orchestrateCommand(action, args) {
|
|
|
4323
5258
|
outputJSON(result);
|
|
4324
5259
|
break;
|
|
4325
5260
|
}
|
|
5261
|
+
case "execute-done": {
|
|
5262
|
+
const taskId = args[0];
|
|
5263
|
+
if (!taskId) {
|
|
5264
|
+
outputError("Task ID is required for execute-done");
|
|
5265
|
+
return;
|
|
5266
|
+
}
|
|
5267
|
+
const result = orchestrator.cmdExecuteDone(taskId);
|
|
5268
|
+
outputJSON(result);
|
|
5269
|
+
break;
|
|
5270
|
+
}
|
|
5271
|
+
// Legacy alias for execute-done
|
|
5272
|
+
case "draft-done": {
|
|
5273
|
+
const taskId = args[0];
|
|
5274
|
+
if (!taskId) {
|
|
5275
|
+
outputError("Task ID is required for draft-done");
|
|
5276
|
+
return;
|
|
5277
|
+
}
|
|
5278
|
+
const result = orchestrator.cmdExecuteDone(taskId);
|
|
5279
|
+
outputJSON(result);
|
|
5280
|
+
break;
|
|
5281
|
+
}
|
|
5282
|
+
case "verify-done": {
|
|
5283
|
+
const taskId = args[0];
|
|
5284
|
+
const verifyJson = args[1];
|
|
5285
|
+
if (!taskId) {
|
|
5286
|
+
outputError("Task ID is required for verify-done");
|
|
5287
|
+
return;
|
|
5288
|
+
}
|
|
5289
|
+
let verifyOutput = {
|
|
5290
|
+
passed: false,
|
|
5291
|
+
score: {
|
|
5292
|
+
requirementsCoverage: 0,
|
|
5293
|
+
templateCompliance: 0,
|
|
5294
|
+
consistency: 0,
|
|
5295
|
+
completeness: 0
|
|
5296
|
+
},
|
|
5297
|
+
issues: [],
|
|
5298
|
+
summary: ""
|
|
5299
|
+
};
|
|
5300
|
+
if (verifyJson) {
|
|
5301
|
+
try {
|
|
5302
|
+
verifyOutput = JSON.parse(verifyJson);
|
|
5303
|
+
} catch {
|
|
5304
|
+
outputError("Invalid JSON for verify output");
|
|
5305
|
+
return;
|
|
5306
|
+
}
|
|
5307
|
+
}
|
|
5308
|
+
const result = orchestrator.cmdVerifyDone(taskId, verifyOutput);
|
|
5309
|
+
outputJSON(result);
|
|
5310
|
+
break;
|
|
5311
|
+
}
|
|
4326
5312
|
case "done": {
|
|
4327
5313
|
const taskId = args[0];
|
|
4328
5314
|
if (!taskId) {
|
|
@@ -4430,7 +5416,7 @@ async function orchestrateCommand(action, args) {
|
|
|
4430
5416
|
break;
|
|
4431
5417
|
}
|
|
4432
5418
|
default:
|
|
4433
|
-
outputError(`Unknown action: ${action}. Valid actions: init,
|
|
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)`);
|
|
4434
5420
|
}
|
|
4435
5421
|
} catch (e) {
|
|
4436
5422
|
outputError(e.message);
|