stoa-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +65 -0
- package/README.md +397 -0
- package/dist/cli/build.d.ts +39 -0
- package/dist/cli/build.d.ts.map +1 -0
- package/dist/cli/build.js +288 -0
- package/dist/cli/build.js.map +1 -0
- package/dist/cli/review-loop.d.ts +2 -0
- package/dist/cli/review-loop.d.ts.map +1 -0
- package/dist/cli/review-loop.js +97 -0
- package/dist/cli/review-loop.js.map +1 -0
- package/dist/cli/scenarios-runner.d.ts +12 -0
- package/dist/cli/scenarios-runner.d.ts.map +1 -0
- package/dist/cli/scenarios-runner.js +158 -0
- package/dist/cli/scenarios-runner.js.map +1 -0
- package/dist/cli/verify.d.ts +13 -0
- package/dist/cli/verify.d.ts.map +1 -0
- package/dist/cli/verify.js +149 -0
- package/dist/cli/verify.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1135 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +2 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/parsers.d.ts +29 -0
- package/dist/core/parsers.d.ts.map +1 -0
- package/dist/core/parsers.js +296 -0
- package/dist/core/parsers.js.map +1 -0
- package/dist/core/parsers.test.d.ts +2 -0
- package/dist/core/parsers.test.d.ts.map +1 -0
- package/dist/core/parsers.test.js +198 -0
- package/dist/core/parsers.test.js.map +1 -0
- package/dist/core/prompts.d.ts +30 -0
- package/dist/core/prompts.d.ts.map +1 -0
- package/dist/core/prompts.js +346 -0
- package/dist/core/prompts.js.map +1 -0
- package/dist/core/refine.d.ts +38 -0
- package/dist/core/refine.d.ts.map +1 -0
- package/dist/core/refine.js +233 -0
- package/dist/core/refine.js.map +1 -0
- package/dist/core/spec-score.d.ts +17 -0
- package/dist/core/spec-score.d.ts.map +1 -0
- package/dist/core/spec-score.js +59 -0
- package/dist/core/spec-score.js.map +1 -0
- package/dist/formatters/index.d.ts +2 -0
- package/dist/formatters/index.d.ts.map +1 -0
- package/dist/formatters/index.js +2 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/formatters/stage-formatters.d.ts +10 -0
- package/dist/formatters/stage-formatters.d.ts.map +1 -0
- package/dist/formatters/stage-formatters.js +100 -0
- package/dist/formatters/stage-formatters.js.map +1 -0
- package/dist/formatters/stage-formatters.test.d.ts +2 -0
- package/dist/formatters/stage-formatters.test.d.ts.map +1 -0
- package/dist/formatters/stage-formatters.test.js +107 -0
- package/dist/formatters/stage-formatters.test.js.map +1 -0
- package/dist/guardrails/index.d.ts +2 -0
- package/dist/guardrails/index.d.ts.map +1 -0
- package/dist/guardrails/index.js +2 -0
- package/dist/guardrails/index.js.map +1 -0
- package/dist/guardrails/loader.d.ts +9 -0
- package/dist/guardrails/loader.d.ts.map +1 -0
- package/dist/guardrails/loader.js +56 -0
- package/dist/guardrails/loader.js.map +1 -0
- package/dist/guardrails/refine.d.ts +53 -0
- package/dist/guardrails/refine.d.ts.map +1 -0
- package/dist/guardrails/refine.js +184 -0
- package/dist/guardrails/refine.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +196 -0
- package/dist/index.js.map +1 -0
- package/dist/storage/change-detection.d.ts +2 -0
- package/dist/storage/change-detection.d.ts.map +1 -0
- package/dist/storage/change-detection.js +47 -0
- package/dist/storage/change-detection.js.map +1 -0
- package/dist/storage/change-detection.test.d.ts +2 -0
- package/dist/storage/change-detection.test.d.ts.map +1 -0
- package/dist/storage/change-detection.test.js +81 -0
- package/dist/storage/change-detection.test.js.map +1 -0
- package/dist/storage/index.d.ts +9 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +6 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/moodboard-describe.d.ts +14 -0
- package/dist/storage/moodboard-describe.d.ts.map +1 -0
- package/dist/storage/moodboard-describe.js +185 -0
- package/dist/storage/moodboard-describe.js.map +1 -0
- package/dist/storage/moodboard-sync.d.ts +11 -0
- package/dist/storage/moodboard-sync.d.ts.map +1 -0
- package/dist/storage/moodboard-sync.js +205 -0
- package/dist/storage/moodboard-sync.js.map +1 -0
- package/dist/storage/moodboard.d.ts +4 -0
- package/dist/storage/moodboard.d.ts.map +1 -0
- package/dist/storage/moodboard.js +68 -0
- package/dist/storage/moodboard.js.map +1 -0
- package/dist/storage/moodboard.test.d.ts +2 -0
- package/dist/storage/moodboard.test.d.ts.map +1 -0
- package/dist/storage/moodboard.test.js +133 -0
- package/dist/storage/moodboard.test.js.map +1 -0
- package/dist/storage/project-scan.d.ts +12 -0
- package/dist/storage/project-scan.d.ts.map +1 -0
- package/dist/storage/project-scan.js +118 -0
- package/dist/storage/project-scan.js.map +1 -0
- package/dist/storage/project.d.ts +10 -0
- package/dist/storage/project.d.ts.map +1 -0
- package/dist/storage/project.js +101 -0
- package/dist/storage/project.js.map +1 -0
- package/dist/storage/roles-refine.d.ts +59 -0
- package/dist/storage/roles-refine.d.ts.map +1 -0
- package/dist/storage/roles-refine.js +223 -0
- package/dist/storage/roles-refine.js.map +1 -0
- package/dist/storage/roles.d.ts +6 -0
- package/dist/storage/roles.d.ts.map +1 -0
- package/dist/storage/roles.js +41 -0
- package/dist/storage/roles.js.map +1 -0
- package/dist/storage/scenarios-refine.d.ts +47 -0
- package/dist/storage/scenarios-refine.d.ts.map +1 -0
- package/dist/storage/scenarios-refine.js +311 -0
- package/dist/storage/scenarios-refine.js.map +1 -0
- package/dist/storage/scenarios.d.ts +12 -0
- package/dist/storage/scenarios.d.ts.map +1 -0
- package/dist/storage/scenarios.js +37 -0
- package/dist/storage/scenarios.js.map +1 -0
- package/dist/storage/specs.d.ts +17 -0
- package/dist/storage/specs.d.ts.map +1 -0
- package/dist/storage/specs.js +104 -0
- package/dist/storage/specs.js.map +1 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/rerefine.d.ts +8 -0
- package/dist/tools/rerefine.d.ts.map +1 -0
- package/dist/tools/rerefine.js +153 -0
- package/dist/tools/rerefine.js.map +1 -0
- package/dist/tools/rerefine.test.d.ts +2 -0
- package/dist/tools/rerefine.test.d.ts.map +1 -0
- package/dist/tools/rerefine.test.js +123 -0
- package/dist/tools/rerefine.test.js.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/slug.d.ts +3 -0
- package/dist/utils/slug.d.ts.map +1 -0
- package/dist/utils/slug.js +33 -0
- package/dist/utils/slug.js.map +1 -0
- package/dist/utils/spec-helpers.d.ts +12 -0
- package/dist/utils/spec-helpers.d.ts.map +1 -0
- package/dist/utils/spec-helpers.js +95 -0
- package/dist/utils/spec-helpers.js.map +1 -0
- package/dist/utils/spec-helpers.test.d.ts +2 -0
- package/dist/utils/spec-helpers.test.d.ts.map +1 -0
- package/dist/utils/spec-helpers.test.js +114 -0
- package/dist/utils/spec-helpers.test.js.map +1 -0
- package/package.json +53 -0
- package/templates/guardrails/ask-when-unclear.md +3 -0
- package/templates/guardrails/dont-delete-code.md +3 -0
- package/templates/guardrails/explain-changes.md +3 -0
- package/templates/guardrails/run-tests.md +3 -0
- package/templates/guardrails/small-changes.md +3 -0
- package/templates/roles/builder.md +3 -0
- package/templates/roles/fixer.md +3 -0
- package/templates/roles/planner.md +3 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { existsSync, readFileSync, mkdirSync, createWriteStream, readdirSync } from "node:fs";
|
|
2
|
+
import { join, relative } from "node:path";
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import { createInterface } from "node:readline";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import { loadAllGuardrails } from "../guardrails/loader.js";
|
|
7
|
+
import { loadRole } from "../storage/roles.js";
|
|
8
|
+
/**
|
|
9
|
+
* Read an approved spec file and extract Stage 1 + Stage 3 content.
|
|
10
|
+
* Exits non-zero if the file is missing or either stage is absent.
|
|
11
|
+
*/
|
|
12
|
+
export function readApprovedSpec(name) {
|
|
13
|
+
const specDir = join(process.cwd(), ".stoa", "specs", name);
|
|
14
|
+
const descPath = join(specDir, "01-problem-statement.md");
|
|
15
|
+
const constraintsPath = join(specDir, "03-constraints.md");
|
|
16
|
+
if (!existsSync(descPath)) {
|
|
17
|
+
process.stderr.write(`Error: Spec description not found: ${descPath}\n`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
if (!existsSync(constraintsPath)) {
|
|
21
|
+
process.stderr.write(`Error: Spec constraints not found: ${constraintsPath}\n`);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
const stage1 = readFileSync(descPath, "utf-8").trim();
|
|
25
|
+
const stage3 = readFileSync(constraintsPath, "utf-8").trim();
|
|
26
|
+
if (stage1.length === 0) {
|
|
27
|
+
process.stderr.write(`Error: Stage 1 (Problem Statement) is empty in ${descPath}\n`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
if (stage3.length === 0) {
|
|
31
|
+
process.stderr.write(`Error: Stage 3 (Constraints) is empty in ${constraintsPath}\n`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
return { stage1, stage3 };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Extract a stage section from the approved spec markdown.
|
|
38
|
+
* Matches `## Stage N:` headers and captures content until the next `## Stage` header or EOF.
|
|
39
|
+
*/
|
|
40
|
+
function extractSection(content, stageNum) {
|
|
41
|
+
const pattern = new RegExp(`^## Stage ${stageNum}:[^\\n]*\\n([\\s\\S]*?)(?=^## Stage \\d|$)`, "m");
|
|
42
|
+
const match = pattern.exec(content);
|
|
43
|
+
if (!match)
|
|
44
|
+
return null;
|
|
45
|
+
const text = match[1].trim();
|
|
46
|
+
return text.length > 0 ? text : null;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Compose a full build prompt from an approved spec, role, guardrails, and moodboard.
|
|
50
|
+
* Does NOT include scenario content.
|
|
51
|
+
*/
|
|
52
|
+
export function composePrompt(name, opts) {
|
|
53
|
+
const { stage1, stage3 } = readApprovedSpec(name);
|
|
54
|
+
const roleText = loadRole(opts.role);
|
|
55
|
+
const guardrailsText = loadAllGuardrails();
|
|
56
|
+
const parts = [];
|
|
57
|
+
// Role persona
|
|
58
|
+
parts.push("# Role\n");
|
|
59
|
+
parts.push(roleText);
|
|
60
|
+
// Stage 1: Problem Statement
|
|
61
|
+
parts.push("\n\n# Task\n");
|
|
62
|
+
parts.push(stage1);
|
|
63
|
+
// Stage 3: Constraints
|
|
64
|
+
parts.push("\n\n# Constraints\n");
|
|
65
|
+
parts.push(stage3);
|
|
66
|
+
// Guardrails
|
|
67
|
+
if (guardrailsText.length > 0) {
|
|
68
|
+
parts.push("\n\n# Guardrails\n");
|
|
69
|
+
parts.push(guardrailsText);
|
|
70
|
+
}
|
|
71
|
+
// Moodboard reference
|
|
72
|
+
const moodboardPath = join(process.cwd(), ".stoa", "moodboard", "notes.md");
|
|
73
|
+
if (existsSync(moodboardPath)) {
|
|
74
|
+
const moodboardText = readFileSync(moodboardPath, "utf-8").trim();
|
|
75
|
+
if (moodboardText.length > 0) {
|
|
76
|
+
parts.push("\n\n# Moodboard\n");
|
|
77
|
+
parts.push(moodboardText);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return parts.join("");
|
|
81
|
+
}
|
|
82
|
+
const ALLOWED_TOOLS = "Edit,Write,Read,Glob,Grep,LSP";
|
|
83
|
+
const OVERALL_TIMEOUT_MS = 600_000;
|
|
84
|
+
/**
|
|
85
|
+
* Spawn Claude Code in Edit Files mode with the build prompt.
|
|
86
|
+
* Streams output to both terminal and a session log file in `.stoa/sessions/`.
|
|
87
|
+
* Uses --allowedTools so Claude Code can create/edit files (not --print).
|
|
88
|
+
* Completes when the close event fires (Claude Code exits normally in Edit Files mode).
|
|
89
|
+
*/
|
|
90
|
+
export function runBuild(name, prompt) {
|
|
91
|
+
return new Promise((resolve, reject) => {
|
|
92
|
+
const startTime = Date.now();
|
|
93
|
+
// Ensure sessions directory exists
|
|
94
|
+
const sessionsDir = join(process.cwd(), ".stoa", "sessions");
|
|
95
|
+
mkdirSync(sessionsDir, { recursive: true });
|
|
96
|
+
// Session file: <name>-<ISO8601>.md
|
|
97
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
98
|
+
const sessionFile = `${name}-${timestamp}.md`;
|
|
99
|
+
const sessionPath = join(sessionsDir, sessionFile);
|
|
100
|
+
// Write session header
|
|
101
|
+
const logStream = createWriteStream(sessionPath, { flags: "a" });
|
|
102
|
+
logStream.write(`# Build Session: ${name}\n`);
|
|
103
|
+
logStream.write(`- Timestamp: ${new Date().toISOString()}\n`);
|
|
104
|
+
logStream.write(`- Spec: ${name}\n`);
|
|
105
|
+
logStream.write(`- Mode: claude-code (Edit Files)\n\n---\n\n`);
|
|
106
|
+
const child = spawn("claude", [
|
|
107
|
+
"--output-format", "text",
|
|
108
|
+
"--allowedTools", ALLOWED_TOOLS,
|
|
109
|
+
], {
|
|
110
|
+
shell: false,
|
|
111
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
112
|
+
cwd: process.cwd(),
|
|
113
|
+
});
|
|
114
|
+
let resolved = false;
|
|
115
|
+
const finish = () => {
|
|
116
|
+
if (resolved)
|
|
117
|
+
return;
|
|
118
|
+
resolved = true;
|
|
119
|
+
clearTimeout(overallTimer);
|
|
120
|
+
process.removeListener("SIGINT", onParentSigint);
|
|
121
|
+
child.kill();
|
|
122
|
+
const durationSec = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
123
|
+
logStream.write(`\n\n---\nDuration: ${durationSec}s\n`);
|
|
124
|
+
logStream.end();
|
|
125
|
+
process.stdout.write("\n");
|
|
126
|
+
process.stdout.write(chalk.green(`Build complete in ${durationSec}s\n`));
|
|
127
|
+
process.stdout.write(chalk.dim(`Session saved: ${sessionPath}\n`));
|
|
128
|
+
// Post-build: scan for package.json files needing npm install
|
|
129
|
+
postBuildInstall();
|
|
130
|
+
// Detect start command
|
|
131
|
+
postBuildStartHint();
|
|
132
|
+
process.stdout.write(chalk.cyan(`Run ${chalk.white("stoa verify")} to check blind test scenarios.\n`));
|
|
133
|
+
resolve();
|
|
134
|
+
};
|
|
135
|
+
child.stdout.on("data", (chunk) => {
|
|
136
|
+
process.stdout.write(chunk);
|
|
137
|
+
logStream.write(chunk);
|
|
138
|
+
});
|
|
139
|
+
child.stderr.on("data", (chunk) => {
|
|
140
|
+
process.stderr.write(chunk);
|
|
141
|
+
});
|
|
142
|
+
child.on("close", () => {
|
|
143
|
+
finish();
|
|
144
|
+
});
|
|
145
|
+
const overallTimer = setTimeout(() => {
|
|
146
|
+
if (!resolved) {
|
|
147
|
+
resolved = true;
|
|
148
|
+
process.removeListener("SIGINT", onParentSigint);
|
|
149
|
+
child.kill("SIGKILL");
|
|
150
|
+
logStream.end();
|
|
151
|
+
reject(new Error(`Claude Code subprocess timed out after ${OVERALL_TIMEOUT_MS / 1000}s`));
|
|
152
|
+
}
|
|
153
|
+
}, OVERALL_TIMEOUT_MS);
|
|
154
|
+
const onParentSigint = () => {
|
|
155
|
+
child.kill("SIGINT");
|
|
156
|
+
};
|
|
157
|
+
process.once("SIGINT", onParentSigint);
|
|
158
|
+
child.on("error", (err) => {
|
|
159
|
+
if (!resolved) {
|
|
160
|
+
resolved = true;
|
|
161
|
+
clearTimeout(overallTimer);
|
|
162
|
+
process.removeListener("SIGINT", onParentSigint);
|
|
163
|
+
logStream.end();
|
|
164
|
+
if (err.code === "ENOENT") {
|
|
165
|
+
process.stderr.write(chalk.red("\nError: Claude Code CLI not found.\n") +
|
|
166
|
+
chalk.dim("Install: https://docs.anthropic.com/en/docs/claude-code\n") +
|
|
167
|
+
chalk.dim("Or use `stoa export " + name + "` to copy the prompt to clipboard.\n"));
|
|
168
|
+
}
|
|
169
|
+
reject(err);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
// Write prompt to stdin and close
|
|
173
|
+
child.stdin.write(prompt);
|
|
174
|
+
child.stdin.end();
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Scan for package.json files (max 3 levels deep) that lack node_modules/.
|
|
179
|
+
* Auto-run npm install for each.
|
|
180
|
+
*/
|
|
181
|
+
function postBuildInstall() {
|
|
182
|
+
const cwd = process.cwd();
|
|
183
|
+
const found = findPackageJsons(cwd, 0, 3);
|
|
184
|
+
for (const dir of found) {
|
|
185
|
+
const nodeModulesPath = join(dir, "node_modules");
|
|
186
|
+
if (!existsSync(nodeModulesPath)) {
|
|
187
|
+
const relDir = relative(cwd, dir) || ".";
|
|
188
|
+
process.stdout.write(chalk.dim(`Installing dependencies in ./${relDir}...\n`));
|
|
189
|
+
try {
|
|
190
|
+
const child = spawn("npm", ["install"], {
|
|
191
|
+
cwd: dir,
|
|
192
|
+
stdio: "inherit",
|
|
193
|
+
shell: false,
|
|
194
|
+
});
|
|
195
|
+
// Fire-and-forget — don't block on npm install
|
|
196
|
+
child.unref();
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
// Non-critical — continue
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Recursively find directories containing package.json, up to maxDepth levels.
|
|
206
|
+
*/
|
|
207
|
+
function findPackageJsons(dir, depth, maxDepth) {
|
|
208
|
+
const results = [];
|
|
209
|
+
if (depth > maxDepth)
|
|
210
|
+
return results;
|
|
211
|
+
if (existsSync(join(dir, "package.json"))) {
|
|
212
|
+
results.push(dir);
|
|
213
|
+
}
|
|
214
|
+
if (depth < maxDepth) {
|
|
215
|
+
try {
|
|
216
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
217
|
+
for (const entry of entries) {
|
|
218
|
+
if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) {
|
|
219
|
+
results.push(...findPackageJsons(join(dir, entry.name), depth + 1, maxDepth));
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
// Permission error or similar — skip
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return results;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Check for dev or start script in package.json and print a hint.
|
|
231
|
+
*/
|
|
232
|
+
function postBuildStartHint() {
|
|
233
|
+
const pkgPath = join(process.cwd(), "package.json");
|
|
234
|
+
if (!existsSync(pkgPath))
|
|
235
|
+
return;
|
|
236
|
+
try {
|
|
237
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
238
|
+
const scripts = pkg.scripts ?? {};
|
|
239
|
+
if (scripts.dev) {
|
|
240
|
+
process.stdout.write(chalk.dim(`To start the app: ${chalk.white("npm run dev")}\n`));
|
|
241
|
+
}
|
|
242
|
+
else if (scripts.start) {
|
|
243
|
+
process.stdout.write(chalk.dim(`To start the app: ${chalk.white("npm start")}\n`));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// ignore malformed package.json
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Parse a `## Subtasks` section from spec content.
|
|
252
|
+
* Extracts numbered items (e.g. "1. Do something").
|
|
253
|
+
* Returns empty array if no Subtasks section exists.
|
|
254
|
+
*/
|
|
255
|
+
export function parseSubtasks(specContent) {
|
|
256
|
+
const pattern = /^## Subtasks\s*\n([\s\S]*?)(?=\n## )/m;
|
|
257
|
+
const match = pattern.exec(specContent);
|
|
258
|
+
// If no next ## heading, try matching to end of string
|
|
259
|
+
const endPattern = /^## Subtasks\s*\n([\s\S]*)$/m;
|
|
260
|
+
const result = match ?? endPattern.exec(specContent);
|
|
261
|
+
if (!result)
|
|
262
|
+
return [];
|
|
263
|
+
const body = result[1];
|
|
264
|
+
const subtasks = [];
|
|
265
|
+
const itemPattern = /^(\d+)\.\s+(.+(?:\n(?!\d+\.).*)*)/gm;
|
|
266
|
+
let itemMatch;
|
|
267
|
+
while ((itemMatch = itemPattern.exec(body)) !== null) {
|
|
268
|
+
subtasks.push({
|
|
269
|
+
index: parseInt(itemMatch[1], 10),
|
|
270
|
+
text: itemMatch[2].trim(),
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
return subtasks;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Prompt user to choose subtask execution mode.
|
|
277
|
+
* Returns "all", "q", or a 1-based subtask number.
|
|
278
|
+
*/
|
|
279
|
+
export function promptSubtaskChoice(subtasks) {
|
|
280
|
+
return new Promise((resolve) => {
|
|
281
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
282
|
+
rl.question(chalk.cyan(`Build all sequentially or pick one? [all/1-${subtasks.length}/q] `), (answer) => {
|
|
283
|
+
rl.close();
|
|
284
|
+
resolve(answer.trim().toLowerCase());
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-loop.d.ts","sourceRoot":"","sources":["../../src/cli/review-loop.ts"],"names":[],"mappings":"AAuCA,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAiEf"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { readFile, appendFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { createInterface } from "node:readline/promises";
|
|
5
|
+
const SECTIONS = [
|
|
6
|
+
{ display: "DESCRIPTION", file: "01-problem-statement.md" },
|
|
7
|
+
{ display: "CRITERIA", file: "02-acceptance-criteria.md" },
|
|
8
|
+
{ display: "CONSTRAINTS", file: "03-constraints.md" },
|
|
9
|
+
{ display: "SUBTASKS", file: "04-decomposition.md" },
|
|
10
|
+
{ display: "SCENARIOS", file: "05-evaluation-design.md" },
|
|
11
|
+
];
|
|
12
|
+
function readKeypress() {
|
|
13
|
+
return new Promise((resolve, reject) => {
|
|
14
|
+
const wasRaw = process.stdin.isRaw;
|
|
15
|
+
process.stdin.setRawMode(true);
|
|
16
|
+
process.stdin.resume();
|
|
17
|
+
process.stdin.once("data", (data) => {
|
|
18
|
+
process.stdin.setRawMode(wasRaw);
|
|
19
|
+
process.stdin.pause();
|
|
20
|
+
resolve(data);
|
|
21
|
+
});
|
|
22
|
+
process.stdin.once("error", (err) => {
|
|
23
|
+
process.stdin.setRawMode(wasRaw);
|
|
24
|
+
process.stdin.pause();
|
|
25
|
+
reject(err);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
async function readSectionContent(filePath) {
|
|
30
|
+
try {
|
|
31
|
+
return await readFile(filePath, "utf-8");
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export async function runReviewLoop(specDir) {
|
|
38
|
+
for (const section of SECTIONS) {
|
|
39
|
+
const filePath = join(specDir, section.file);
|
|
40
|
+
process.stdout.write(`\n=== ${section.display} ===\n`);
|
|
41
|
+
const content = await readSectionContent(filePath);
|
|
42
|
+
if (content === null) {
|
|
43
|
+
process.stdout.write("[no content]\n");
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
process.stdout.write(content);
|
|
47
|
+
if (!content.endsWith("\n")) {
|
|
48
|
+
process.stdout.write("\n");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
let handled = false;
|
|
52
|
+
while (!handled) {
|
|
53
|
+
process.stdout.write("[Enter] continue [e] edit [s] skip");
|
|
54
|
+
const buf = await readKeypress();
|
|
55
|
+
const byte = buf[0];
|
|
56
|
+
process.stdout.write("\n");
|
|
57
|
+
if (byte === 0x0d || byte === 0x0a) {
|
|
58
|
+
// Enter — advance
|
|
59
|
+
handled = true;
|
|
60
|
+
}
|
|
61
|
+
else if (byte === 0x65) {
|
|
62
|
+
// 'e' — edit
|
|
63
|
+
const editor = process.env["EDITOR"] || "vi";
|
|
64
|
+
try {
|
|
65
|
+
spawnSync(editor, [filePath], { stdio: "inherit" });
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
if (err instanceof Error &&
|
|
69
|
+
"code" in err &&
|
|
70
|
+
err.code === "ENOENT") {
|
|
71
|
+
process.stderr.write(`Editor not found: ${editor}\n`);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
handled = true;
|
|
77
|
+
}
|
|
78
|
+
else if (byte === 0x73) {
|
|
79
|
+
// 's' — skip
|
|
80
|
+
handled = true;
|
|
81
|
+
}
|
|
82
|
+
// Any other key: loop re-prompts
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Additional notes prompt
|
|
86
|
+
process.stdout.write("\nAdditional notes (leave blank to skip): ");
|
|
87
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
88
|
+
const line = await rl.question("");
|
|
89
|
+
rl.close();
|
|
90
|
+
const trimmed = line.trim();
|
|
91
|
+
if (trimmed.length > 0) {
|
|
92
|
+
const now = new Date().toISOString();
|
|
93
|
+
const entry = `\n## Notes — ${now}\n${trimmed}\n`;
|
|
94
|
+
await appendFile(join(specDir, "user-notes.md"), entry, "utf-8");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=review-loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-loop.js","sourceRoot":"","sources":["../../src/cli/review-loop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface Scenario {
|
|
2
|
+
title: string;
|
|
3
|
+
given: string;
|
|
4
|
+
expected: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function loadSpecScenarios(specName?: string): Promise<{
|
|
7
|
+
specName: string;
|
|
8
|
+
scenarios: Scenario[];
|
|
9
|
+
}>;
|
|
10
|
+
export declare function runSpecScenarios(specName?: string): Promise<void>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=scenarios-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenarios-runner.d.ts","sourceRoot":"","sources":["../../src/cli/scenarios-runner.ts"],"names":[],"mappings":"AAIA,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAoGD,wBAAsB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,QAAQ,EAAE,CAAA;CAAE,CAAC,CAkB/G;AAUD,wBAAsB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDvE"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { createInterface } from "node:readline";
|
|
2
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
function parseSpecScenarios(content) {
|
|
5
|
+
const scenarios = [];
|
|
6
|
+
// Strip markdown code fences if present
|
|
7
|
+
const stripped = content.replace(/^```(?:json)?\s*\n?/gm, "").replace(/\n?```\s*$/gm, "");
|
|
8
|
+
const trimmed = stripped.trim();
|
|
9
|
+
// Try JSON array first (raw stage 5 output)
|
|
10
|
+
if (trimmed.startsWith("[")) {
|
|
11
|
+
try {
|
|
12
|
+
const parsed = JSON.parse(trimmed);
|
|
13
|
+
if (Array.isArray(parsed)) {
|
|
14
|
+
for (const item of parsed) {
|
|
15
|
+
if (typeof item === "object" && item !== null &&
|
|
16
|
+
typeof item.title === "string" &&
|
|
17
|
+
typeof item.given === "string" &&
|
|
18
|
+
typeof item.expected === "string") {
|
|
19
|
+
scenarios.push(item);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (scenarios.length > 0)
|
|
23
|
+
return scenarios;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Not JSON — fall through to markdown parsing
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// Parse markdown format: ## Title blocks with **Given:**/**Expected:** or Given:/Expected:
|
|
31
|
+
const blocks = content.split(/^##\s+/m);
|
|
32
|
+
for (const block of blocks) {
|
|
33
|
+
const blockTrimmed = block.trim();
|
|
34
|
+
if (blockTrimmed.length === 0)
|
|
35
|
+
continue;
|
|
36
|
+
const firstNewline = blockTrimmed.indexOf("\n");
|
|
37
|
+
if (firstNewline === -1)
|
|
38
|
+
continue;
|
|
39
|
+
const title = blockTrimmed.slice(0, firstNewline).trim();
|
|
40
|
+
const body = blockTrimmed.slice(firstNewline + 1);
|
|
41
|
+
const givenMatch = body.match(/\*{0,2}(?:given|GIVEN)\*{0,2}[:\s]+(.+?)(?=\*{0,2}(?:expected|EXPECTED)\*{0,2}[:\s])/is);
|
|
42
|
+
const expectedMatch = body.match(/\*{0,2}(?:expected|EXPECTED)\*{0,2}[:\s]+(.+)/is);
|
|
43
|
+
if (givenMatch && expectedMatch) {
|
|
44
|
+
scenarios.push({
|
|
45
|
+
title,
|
|
46
|
+
given: givenMatch[1].replace(/^\*+|\*+$/g, "").trim(),
|
|
47
|
+
expected: expectedMatch[1].replace(/^\*+|\*+$/g, "").trim(),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Fallback: numbered list with title / given / expected per block
|
|
52
|
+
if (scenarios.length === 0) {
|
|
53
|
+
const numberedBlocks = content.split(/^\d+\.\s+/m);
|
|
54
|
+
for (const block of numberedBlocks) {
|
|
55
|
+
const blockTrimmed = block.trim();
|
|
56
|
+
if (blockTrimmed.length === 0)
|
|
57
|
+
continue;
|
|
58
|
+
const titleMatch = blockTrimmed.match(/^\*{0,2}(.+?)\*{0,2}\s*$/m);
|
|
59
|
+
const givenMatch = blockTrimmed.match(/\*{0,2}(?:given|GIVEN)\*{0,2}[:\s]+(.+?)(?=\*{0,2}(?:expected|EXPECTED)\*{0,2}[:\s])/is);
|
|
60
|
+
const expectedMatch = blockTrimmed.match(/\*{0,2}(?:expected|EXPECTED)\*{0,2}[:\s]+(.+)/is);
|
|
61
|
+
if (titleMatch && givenMatch && expectedMatch) {
|
|
62
|
+
scenarios.push({
|
|
63
|
+
title: titleMatch[1].replace(/^\*+|\*+$/g, "").trim(),
|
|
64
|
+
given: givenMatch[1].replace(/^\*+|\*+$/g, "").trim(),
|
|
65
|
+
expected: expectedMatch[1].replace(/^\*+|\*+$/g, "").trim(),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return scenarios;
|
|
71
|
+
}
|
|
72
|
+
async function getMostRecentSpec() {
|
|
73
|
+
const specsDir = join(process.cwd(), ".stoa", "specs");
|
|
74
|
+
const entries = await readdir(specsDir);
|
|
75
|
+
const { stat } = await import("node:fs/promises");
|
|
76
|
+
const dirs = [];
|
|
77
|
+
for (const entry of entries) {
|
|
78
|
+
const s = await stat(join(specsDir, entry));
|
|
79
|
+
if (s.isDirectory()) {
|
|
80
|
+
dirs.push({ name: entry, mtime: s.mtimeMs });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (dirs.length === 0) {
|
|
84
|
+
throw new Error("No specs found. Run 'stoa refine' first.");
|
|
85
|
+
}
|
|
86
|
+
dirs.sort((a, b) => b.mtime - a.mtime);
|
|
87
|
+
return dirs[0].name;
|
|
88
|
+
}
|
|
89
|
+
export async function loadSpecScenarios(specName) {
|
|
90
|
+
const resolvedName = specName ?? await getMostRecentSpec();
|
|
91
|
+
const specDir = join(process.cwd(), ".stoa", "specs", resolvedName);
|
|
92
|
+
const scenarioFile = join(specDir, "05-evaluation-design.md");
|
|
93
|
+
let content;
|
|
94
|
+
try {
|
|
95
|
+
content = await readFile(scenarioFile, "utf-8");
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
throw new Error(`No scenarios found for spec "${resolvedName}". Run a full refine first.`);
|
|
99
|
+
}
|
|
100
|
+
const scenarios = parseSpecScenarios(content);
|
|
101
|
+
if (scenarios.length === 0) {
|
|
102
|
+
throw new Error(`Could not parse scenarios from spec "${resolvedName}".`);
|
|
103
|
+
}
|
|
104
|
+
return { specName: resolvedName, scenarios };
|
|
105
|
+
}
|
|
106
|
+
function askQuestion(rl, prompt) {
|
|
107
|
+
return new Promise((resolve) => {
|
|
108
|
+
rl.question(prompt, (answer) => {
|
|
109
|
+
resolve(answer.trim().toLowerCase());
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
export async function runSpecScenarios(specName) {
|
|
114
|
+
const { specName: name, scenarios } = await loadSpecScenarios(specName);
|
|
115
|
+
process.stdout.write(`\nScenarios for: ${name}\n`);
|
|
116
|
+
process.stdout.write(`${scenarios.length} scenario(s)\n`);
|
|
117
|
+
process.stdout.write("─".repeat(40) + "\n");
|
|
118
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
119
|
+
let passed = 0;
|
|
120
|
+
let failed = 0;
|
|
121
|
+
let skipped = 0;
|
|
122
|
+
const failures = [];
|
|
123
|
+
try {
|
|
124
|
+
for (let i = 0; i < scenarios.length; i++) {
|
|
125
|
+
const s = scenarios[i];
|
|
126
|
+
process.stdout.write(`\nScenario ${i + 1}/${scenarios.length}: ${s.title}\n\n`);
|
|
127
|
+
process.stdout.write(` GIVEN:\n ${s.given}\n\n`);
|
|
128
|
+
process.stdout.write(` EXPECTED:\n ${s.expected}\n\n`);
|
|
129
|
+
const answer = await askQuestion(rl, " Pass? [y/n/s(skip)] ");
|
|
130
|
+
if (answer === "y" || answer === "yes") {
|
|
131
|
+
passed++;
|
|
132
|
+
process.stdout.write(" ✓ Passed\n");
|
|
133
|
+
}
|
|
134
|
+
else if (answer === "s" || answer === "skip") {
|
|
135
|
+
skipped++;
|
|
136
|
+
process.stdout.write(" — Skipped\n");
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
failed++;
|
|
140
|
+
failures.push(s.title);
|
|
141
|
+
process.stdout.write(" ✗ Failed\n");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
rl.close();
|
|
147
|
+
}
|
|
148
|
+
// Summary
|
|
149
|
+
process.stdout.write("\n" + "─".repeat(40) + "\n");
|
|
150
|
+
process.stdout.write(`Results: ${passed} passed, ${failed} failed, ${skipped} skipped\n`);
|
|
151
|
+
if (failures.length > 0) {
|
|
152
|
+
process.stdout.write("Failed:\n");
|
|
153
|
+
for (const f of failures) {
|
|
154
|
+
process.stdout.write(` - ${f}\n`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=scenarios-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenarios-runner.js","sourceRoot":"","sources":["../../src/cli/scenarios-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface VerifyFailure {
|
|
2
|
+
scenarioId: number;
|
|
3
|
+
expected: string;
|
|
4
|
+
actual: string;
|
|
5
|
+
}
|
|
6
|
+
export interface VerifyResult {
|
|
7
|
+
passed: number;
|
|
8
|
+
failed: number;
|
|
9
|
+
skipped: number;
|
|
10
|
+
failures: VerifyFailure[];
|
|
11
|
+
}
|
|
12
|
+
export declare function runVerify(name: string): Promise<VerifyResult>;
|
|
13
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/cli/verify.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAsED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA2FnE"}
|