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,56 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { toSlug } from "../utils/slug.js";
|
|
4
|
+
function guardrailsDir() {
|
|
5
|
+
return join(process.cwd(), ".stoa", "guardrails");
|
|
6
|
+
}
|
|
7
|
+
export function listGuardrails() {
|
|
8
|
+
if (!existsSync(guardrailsDir()))
|
|
9
|
+
return [];
|
|
10
|
+
const files = readdirSync(guardrailsDir())
|
|
11
|
+
.filter((f) => f.endsWith(".md"))
|
|
12
|
+
.sort();
|
|
13
|
+
return files.map((file) => {
|
|
14
|
+
const slug = file.replace(/\.md$/, "");
|
|
15
|
+
const content = readFileSync(join(guardrailsDir(), file), "utf-8");
|
|
16
|
+
const firstLine = content.split("\n")[0] ?? "";
|
|
17
|
+
const title = firstLine.replace(/^#\s*/, "");
|
|
18
|
+
return { slug, title };
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export function addGuardrail(title) {
|
|
22
|
+
const slug = toSlug(title);
|
|
23
|
+
const filePath = join(guardrailsDir(), `${slug}.md`);
|
|
24
|
+
if (existsSync(filePath)) {
|
|
25
|
+
throw new Error(`Guardrail already exists: ${slug}`);
|
|
26
|
+
}
|
|
27
|
+
mkdirSync(guardrailsDir(), { recursive: true });
|
|
28
|
+
writeFileSync(filePath, `# ${title}\n`, "utf-8");
|
|
29
|
+
}
|
|
30
|
+
export function showGuardrail(slug) {
|
|
31
|
+
const filePath = join(guardrailsDir(), `${slug}.md`);
|
|
32
|
+
if (!existsSync(filePath)) {
|
|
33
|
+
throw new Error(`Guardrail not found: ${slug}`);
|
|
34
|
+
}
|
|
35
|
+
return readFileSync(filePath, "utf-8");
|
|
36
|
+
}
|
|
37
|
+
export function removeGuardrail(slug) {
|
|
38
|
+
const filePath = join(guardrailsDir(), `${slug}.md`);
|
|
39
|
+
if (!existsSync(filePath)) {
|
|
40
|
+
throw new Error(`Guardrail not found: ${slug}`);
|
|
41
|
+
}
|
|
42
|
+
unlinkSync(filePath);
|
|
43
|
+
}
|
|
44
|
+
export function loadAllGuardrails() {
|
|
45
|
+
if (!existsSync(guardrailsDir()))
|
|
46
|
+
return "";
|
|
47
|
+
const files = readdirSync(guardrailsDir())
|
|
48
|
+
.filter((f) => f.endsWith(".md"))
|
|
49
|
+
.sort();
|
|
50
|
+
if (files.length === 0)
|
|
51
|
+
return "";
|
|
52
|
+
return files
|
|
53
|
+
.map((file) => readFileSync(join(guardrailsDir(), file), "utf-8"))
|
|
54
|
+
.join("\n---\n");
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/guardrails/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guardrail Refine Pipeline.
|
|
3
|
+
* Runs a 3-stage refinement pipeline that transforms raw guardrail rules
|
|
4
|
+
* into precise, verifiable, example-backed specifications.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Build the Stage 1 prompt: Clarify & Tighten.
|
|
8
|
+
* Rewrites the guardrail rule to be unambiguous, specific, and actionable.
|
|
9
|
+
* Removes vague language while preserving original intent.
|
|
10
|
+
* @param seed - The raw guardrail markdown content.
|
|
11
|
+
* @returns The full prompt string for Stage 1.
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildStage1Prompt(seed: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Build the Stage 2 prompt: Add Verification (How to Check).
|
|
16
|
+
* Appends a "How to Check" section with concrete, mechanical verification steps.
|
|
17
|
+
* @param stage1Output - The clarified guardrail text from Stage 1.
|
|
18
|
+
* @returns The full prompt string for Stage 2.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildStage2Prompt(stage1Output: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Build the Stage 3 prompt: Add Examples (Good/Bad).
|
|
23
|
+
* Appends Good Example and Bad Example sections with inline code snippets.
|
|
24
|
+
* @param stage2Output - The guardrail text with verification from Stage 2.
|
|
25
|
+
* @returns The full prompt string for Stage 3.
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildStage3Prompt(stage2Output: string): string;
|
|
28
|
+
/** Options for the guardrail refine pipeline. */
|
|
29
|
+
export interface GuardrailRefineOptions {
|
|
30
|
+
name: string;
|
|
31
|
+
mode: "clipboard" | "api" | "claude-code";
|
|
32
|
+
model?: string;
|
|
33
|
+
apiKey?: string;
|
|
34
|
+
onStageComplete?: (stageIndex: number, label: string, output: string) => void;
|
|
35
|
+
}
|
|
36
|
+
/** Result of the guardrail refine pipeline. */
|
|
37
|
+
export interface GuardrailRefineResult {
|
|
38
|
+
prompts: string[];
|
|
39
|
+
finalOutput: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Run the 3-stage guardrail refinement pipeline.
|
|
43
|
+
*
|
|
44
|
+
* - clipboard: Executes all 3 stages via Anthropic API with chained outputs. Does not modify files.
|
|
45
|
+
* - api: Executes all 3 stages via Anthropic API. Writes final output to file.
|
|
46
|
+
* - claude-code: Executes via Claude Code CLI. Writes final output to file.
|
|
47
|
+
*
|
|
48
|
+
* @param options - Pipeline configuration including name, mode, and optional model/apiKey.
|
|
49
|
+
* @returns The prompts used and the final output.
|
|
50
|
+
* @throws If the guardrail file does not exist.
|
|
51
|
+
*/
|
|
52
|
+
export declare function refinePipeline(options: GuardrailRefineOptions): Promise<GuardrailRefineResult>;
|
|
53
|
+
//# sourceMappingURL=refine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refine.d.ts","sourceRoot":"","sources":["../../src/guardrails/refine.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAuBH;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CActD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAc9D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAe9D;AAgFD,iDAAiD;AACjD,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,GAAG,KAAK,GAAG,aAAa,CAAC;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/E;AAED,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAqChC"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guardrail Refine Pipeline.
|
|
3
|
+
* Runs a 3-stage refinement pipeline that transforms raw guardrail rules
|
|
4
|
+
* into precise, verifiable, example-backed specifications.
|
|
5
|
+
*/
|
|
6
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
7
|
+
import { spawn } from "child_process";
|
|
8
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
const SPAWN_TIMEOUT_MS = 300_000;
|
|
11
|
+
function guardrailsDir() {
|
|
12
|
+
return join(process.cwd(), ".stoa", "guardrails");
|
|
13
|
+
}
|
|
14
|
+
// ── Stage names ──────────────────────────────────────────────────────
|
|
15
|
+
const STAGE_LABELS = [
|
|
16
|
+
"Stage 1: Clarify & Tighten",
|
|
17
|
+
"Stage 2: Add Verification (How to Check)",
|
|
18
|
+
"Stage 3: Add Examples (Good/Bad)",
|
|
19
|
+
];
|
|
20
|
+
// ── Pure prompt builders ─────────────────────────────────────────────
|
|
21
|
+
/**
|
|
22
|
+
* Build the Stage 1 prompt: Clarify & Tighten.
|
|
23
|
+
* Rewrites the guardrail rule to be unambiguous, specific, and actionable.
|
|
24
|
+
* Removes vague language while preserving original intent.
|
|
25
|
+
* @param seed - The raw guardrail markdown content.
|
|
26
|
+
* @returns The full prompt string for Stage 1.
|
|
27
|
+
*/
|
|
28
|
+
export function buildStage1Prompt(seed) {
|
|
29
|
+
return [
|
|
30
|
+
"You are a technical writing editor specializing in software engineering guardrails and coding standards.",
|
|
31
|
+
"",
|
|
32
|
+
"Rewrite the following guardrail rule so it is unambiguous, specific, and actionable.",
|
|
33
|
+
"Remove vague language like \"should\", \"try to\", \"generally\", \"where possible\".",
|
|
34
|
+
"Replace subjective terms with objective, measurable criteria.",
|
|
35
|
+
"Preserve the original intent and all technical details.",
|
|
36
|
+
"Output only the rewritten guardrail in markdown format — no preamble, no commentary.",
|
|
37
|
+
"",
|
|
38
|
+
"---",
|
|
39
|
+
"",
|
|
40
|
+
seed,
|
|
41
|
+
].join("\n");
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Build the Stage 2 prompt: Add Verification (How to Check).
|
|
45
|
+
* Appends a "How to Check" section with concrete, mechanical verification steps.
|
|
46
|
+
* @param stage1Output - The clarified guardrail text from Stage 1.
|
|
47
|
+
* @returns The full prompt string for Stage 2.
|
|
48
|
+
*/
|
|
49
|
+
export function buildStage2Prompt(stage1Output) {
|
|
50
|
+
return [
|
|
51
|
+
"You are a technical writing editor specializing in software engineering guardrails and coding standards.",
|
|
52
|
+
"",
|
|
53
|
+
"The following is a refined guardrail rule. Append a \"## How to Check\" section at the end.",
|
|
54
|
+
"The section must describe concrete, mechanical ways to verify the rule is being followed.",
|
|
55
|
+
"Include specific grep patterns, lint rules, code review checkpoints, or CI checks as appropriate.",
|
|
56
|
+
"Each verification step must be a checklist item (- [ ]) that a reviewer can mark off.",
|
|
57
|
+
"Output the complete guardrail with the new section appended — no preamble, no commentary.",
|
|
58
|
+
"",
|
|
59
|
+
"---",
|
|
60
|
+
"",
|
|
61
|
+
stage1Output,
|
|
62
|
+
].join("\n");
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Build the Stage 3 prompt: Add Examples (Good/Bad).
|
|
66
|
+
* Appends Good Example and Bad Example sections with inline code snippets.
|
|
67
|
+
* @param stage2Output - The guardrail text with verification from Stage 2.
|
|
68
|
+
* @returns The full prompt string for Stage 3.
|
|
69
|
+
*/
|
|
70
|
+
export function buildStage3Prompt(stage2Output) {
|
|
71
|
+
return [
|
|
72
|
+
"You are a technical writing editor specializing in software engineering guardrails and coding standards.",
|
|
73
|
+
"",
|
|
74
|
+
"The following is a refined guardrail rule with verification steps.",
|
|
75
|
+
"Append a \"## Good Example\" section and a \"## Bad Example\" section at the end.",
|
|
76
|
+
"Each section must contain inline code snippets (using fenced code blocks) that illustrate",
|
|
77
|
+
"compliance and violation of the rule respectively.",
|
|
78
|
+
"Include brief comments in the code explaining why each example is good or bad.",
|
|
79
|
+
"Output the complete guardrail with both new sections appended — no preamble, no commentary.",
|
|
80
|
+
"",
|
|
81
|
+
"---",
|
|
82
|
+
"",
|
|
83
|
+
stage2Output,
|
|
84
|
+
].join("\n");
|
|
85
|
+
}
|
|
86
|
+
// ── Execution helpers ────────────────────────────────────────────────
|
|
87
|
+
async function executeStage(prompt, mode, model, apiKey) {
|
|
88
|
+
if (mode === "api") {
|
|
89
|
+
const client = new Anthropic({
|
|
90
|
+
apiKey: apiKey || process.env.ANTHROPIC_API_KEY,
|
|
91
|
+
});
|
|
92
|
+
const response = await client.messages.create({
|
|
93
|
+
model,
|
|
94
|
+
max_tokens: 4096,
|
|
95
|
+
messages: [{ role: "user", content: prompt }],
|
|
96
|
+
});
|
|
97
|
+
const textBlock = response.content.find((block) => block.type === "text");
|
|
98
|
+
return textBlock ? textBlock.text : "";
|
|
99
|
+
}
|
|
100
|
+
// claude-code mode — pipe prompt via stdin (the -p flag hangs as subprocess)
|
|
101
|
+
return new Promise((resolve, reject) => {
|
|
102
|
+
const child = spawn("claude", ["--print"], {
|
|
103
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
104
|
+
});
|
|
105
|
+
let stdout = "";
|
|
106
|
+
let resolved = false;
|
|
107
|
+
let dataTimer = null;
|
|
108
|
+
const finish = () => {
|
|
109
|
+
if (resolved)
|
|
110
|
+
return;
|
|
111
|
+
resolved = true;
|
|
112
|
+
clearTimeout(overallTimer);
|
|
113
|
+
if (dataTimer)
|
|
114
|
+
clearTimeout(dataTimer);
|
|
115
|
+
child.kill();
|
|
116
|
+
resolve(stdout.trim());
|
|
117
|
+
};
|
|
118
|
+
child.stdout.on("data", (chunk) => {
|
|
119
|
+
stdout += chunk.toString();
|
|
120
|
+
if (dataTimer)
|
|
121
|
+
clearTimeout(dataTimer);
|
|
122
|
+
dataTimer = setTimeout(finish, 2000);
|
|
123
|
+
});
|
|
124
|
+
child.on("close", () => {
|
|
125
|
+
finish();
|
|
126
|
+
});
|
|
127
|
+
const overallTimer = setTimeout(() => {
|
|
128
|
+
if (!resolved) {
|
|
129
|
+
resolved = true;
|
|
130
|
+
if (dataTimer)
|
|
131
|
+
clearTimeout(dataTimer);
|
|
132
|
+
child.kill("SIGKILL");
|
|
133
|
+
reject(new Error(`Claude Code timed out after ${SPAWN_TIMEOUT_MS / 1000}s`));
|
|
134
|
+
}
|
|
135
|
+
}, SPAWN_TIMEOUT_MS);
|
|
136
|
+
child.on("error", (err) => {
|
|
137
|
+
if (!resolved) {
|
|
138
|
+
resolved = true;
|
|
139
|
+
clearTimeout(overallTimer);
|
|
140
|
+
if (dataTimer)
|
|
141
|
+
clearTimeout(dataTimer);
|
|
142
|
+
reject(err);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
// Write prompt to stdin and close it
|
|
146
|
+
child.stdin.write(prompt);
|
|
147
|
+
child.stdin.end();
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Run the 3-stage guardrail refinement pipeline.
|
|
152
|
+
*
|
|
153
|
+
* - clipboard: Executes all 3 stages via Anthropic API with chained outputs. Does not modify files.
|
|
154
|
+
* - api: Executes all 3 stages via Anthropic API. Writes final output to file.
|
|
155
|
+
* - claude-code: Executes via Claude Code CLI. Writes final output to file.
|
|
156
|
+
*
|
|
157
|
+
* @param options - Pipeline configuration including name, mode, and optional model/apiKey.
|
|
158
|
+
* @returns The prompts used and the final output.
|
|
159
|
+
* @throws If the guardrail file does not exist.
|
|
160
|
+
*/
|
|
161
|
+
export async function refinePipeline(options) {
|
|
162
|
+
const filePath = join(guardrailsDir(), `${options.name}.md`);
|
|
163
|
+
if (!existsSync(filePath)) {
|
|
164
|
+
throw new Error(`Guardrail not found: .stoa/guardrails/${options.name}.md`);
|
|
165
|
+
}
|
|
166
|
+
const seed = readFileSync(filePath, "utf-8");
|
|
167
|
+
const model = options.model ?? "claude-sonnet-4-6";
|
|
168
|
+
const builders = [buildStage1Prompt, buildStage2Prompt, buildStage3Prompt];
|
|
169
|
+
const executeMode = options.mode === "clipboard" ? "api" : options.mode;
|
|
170
|
+
const prompts = [];
|
|
171
|
+
let currentInput = seed;
|
|
172
|
+
for (let i = 0; i < builders.length; i++) {
|
|
173
|
+
const prompt = builders[i](currentInput);
|
|
174
|
+
prompts.push(prompt);
|
|
175
|
+
currentInput = await executeStage(prompt, executeMode, model, options.apiKey);
|
|
176
|
+
options.onStageComplete?.(i, STAGE_LABELS[i], currentInput);
|
|
177
|
+
}
|
|
178
|
+
// Only write back to file for api/claude-code modes
|
|
179
|
+
if (options.mode !== "clipboard") {
|
|
180
|
+
writeFileSync(filePath, currentInput, "utf-8");
|
|
181
|
+
}
|
|
182
|
+
return { prompts, finalOutput: currentInput };
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=refine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refine.js","sourceRoot":"","sources":["../../src/guardrails/refine.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stoa MCP Server entry point.
|
|
3
|
+
* Registers refine_task, score_spec tools, guardrails resource, and refine prompt.
|
|
4
|
+
*/
|
|
5
|
+
import { access, readdir, readFile } from "node:fs/promises";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import { refinePipeline } from "./core/refine.js";
|
|
11
|
+
import { computeSpecScore } from "./core/spec-score.js";
|
|
12
|
+
import { writeSpecFiles, writeRefineMeta } from "./storage/index.js";
|
|
13
|
+
import { toSlug, resolveSlug } from "./utils/slug.js";
|
|
14
|
+
import { scanProject } from "./storage/project-scan.js";
|
|
15
|
+
import { syncMoodboard } from "./storage/moodboard-sync.js";
|
|
16
|
+
const STAGE_NAMES = ["clarify", "structure", "score", "harden", "finalize"];
|
|
17
|
+
const STAGE_NAME_TO_NUMBER = {
|
|
18
|
+
clarify: 1,
|
|
19
|
+
structure: 2,
|
|
20
|
+
score: 3,
|
|
21
|
+
harden: 4,
|
|
22
|
+
finalize: 5,
|
|
23
|
+
};
|
|
24
|
+
const server = new McpServer({
|
|
25
|
+
name: "stoa",
|
|
26
|
+
version: "0.1.0",
|
|
27
|
+
});
|
|
28
|
+
// ── Tool: refine_task ─────────────────────────────────────────────────
|
|
29
|
+
server.tool("refine_task", "Refine a task description through a multi-stage pipeline that produces a structured specification.", {
|
|
30
|
+
title: z.string(),
|
|
31
|
+
description: z.string(),
|
|
32
|
+
stages: z.array(z.string()).optional(),
|
|
33
|
+
project_context: z.string().optional(),
|
|
34
|
+
role: z.string().optional(),
|
|
35
|
+
}, async ({ title, description, stages, project_context, role }) => {
|
|
36
|
+
// Check that .stoa/ exists before running the pipeline
|
|
37
|
+
const stoaDir = join(process.cwd(), ".stoa");
|
|
38
|
+
try {
|
|
39
|
+
await access(stoaDir);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return {
|
|
43
|
+
content: [
|
|
44
|
+
{
|
|
45
|
+
type: "text",
|
|
46
|
+
text: "Error: .stoa/ directory not found. Run 'stoa init' to initialize your project.",
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
isError: true,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const stageNumbers = (stages ?? [...STAGE_NAMES]).map((name) => {
|
|
53
|
+
const num = STAGE_NAME_TO_NUMBER[name];
|
|
54
|
+
if (!num) {
|
|
55
|
+
throw new Error(`Unknown stage: ${name}. Valid stages: ${STAGE_NAMES.join(", ")}`);
|
|
56
|
+
}
|
|
57
|
+
return num;
|
|
58
|
+
});
|
|
59
|
+
// Sync moodboard tokens before pipeline
|
|
60
|
+
try {
|
|
61
|
+
syncMoodboard(process.cwd());
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Non-critical — notes.md may not exist
|
|
65
|
+
}
|
|
66
|
+
// Scan project for context
|
|
67
|
+
let projectCtx;
|
|
68
|
+
try {
|
|
69
|
+
projectCtx = scanProject(process.cwd());
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Non-critical
|
|
73
|
+
}
|
|
74
|
+
const result = await refinePipeline({
|
|
75
|
+
title,
|
|
76
|
+
description,
|
|
77
|
+
projectContext: project_context,
|
|
78
|
+
projectCtx,
|
|
79
|
+
role,
|
|
80
|
+
}, { stages: stageNumbers });
|
|
81
|
+
// Write spec files to .stoa/specs/ — surface errors to caller
|
|
82
|
+
const specsDir = join(stoaDir, "specs");
|
|
83
|
+
const slug = await resolveSlug(specsDir, toSlug(title));
|
|
84
|
+
const stagesRun = {};
|
|
85
|
+
for (const sr of result.stages) {
|
|
86
|
+
stagesRun[sr.stage] = sr.rawResponse;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
await writeSpecFiles(specsDir, slug, stagesRun);
|
|
90
|
+
await writeRefineMeta(specsDir, slug, result.stages.map((s) => s.stage), result.executionMode, "0.1.0");
|
|
91
|
+
}
|
|
92
|
+
catch (writeErr) {
|
|
93
|
+
const msg = writeErr instanceof Error ? writeErr.message : String(writeErr);
|
|
94
|
+
process.stderr.write(`Warning: Failed to write spec files to .stoa/specs/${slug}/: ${msg}\n`);
|
|
95
|
+
}
|
|
96
|
+
// If all 5 stages ran successfully, the score is 5/5 regardless of input fields
|
|
97
|
+
const allFiveRan = result.stages.length === 5 &&
|
|
98
|
+
[1, 2, 3, 4, 5].every((s) => result.stages.some((sr) => sr.stage === s));
|
|
99
|
+
if (allFiveRan) {
|
|
100
|
+
result.finalSpecScore = 5;
|
|
101
|
+
}
|
|
102
|
+
const specPath = join(specsDir, slug);
|
|
103
|
+
const response = { ...result, spec_path: specPath };
|
|
104
|
+
return {
|
|
105
|
+
content: [{ type: "text", text: JSON.stringify(response, null, 2) }],
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
// ── Tool: score_spec ──────────────────────────────────────────────────
|
|
109
|
+
server.tool("score_spec", "Compute a spec-readiness score for a specification string.", {
|
|
110
|
+
spec: z.string(),
|
|
111
|
+
}, ({ spec }) => {
|
|
112
|
+
const hasDescription = spec.length > 0;
|
|
113
|
+
const result = computeSpecScore({
|
|
114
|
+
hasDescription,
|
|
115
|
+
descriptionLength: spec.length,
|
|
116
|
+
wasRefined: false,
|
|
117
|
+
hasAcceptanceCriteria: false,
|
|
118
|
+
hasGuardrails: false,
|
|
119
|
+
hasRole: false,
|
|
120
|
+
hasScenarios: false,
|
|
121
|
+
hasSubtasks: false,
|
|
122
|
+
});
|
|
123
|
+
return {
|
|
124
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
// ── Resource: guardrails ──────────────────────────────────────────────
|
|
128
|
+
server.resource("guardrails", "stoa://guardrails", { description: "Project guardrails from .stoa/guardrails/ directory" }, async () => {
|
|
129
|
+
const guardrailsDir = join(process.cwd(), ".stoa", "guardrails");
|
|
130
|
+
try {
|
|
131
|
+
const files = await readdir(guardrailsDir);
|
|
132
|
+
const mdFiles = files.filter((f) => f.endsWith(".md")).sort();
|
|
133
|
+
if (mdFiles.length === 0) {
|
|
134
|
+
return {
|
|
135
|
+
contents: [
|
|
136
|
+
{
|
|
137
|
+
uri: "stoa://guardrails",
|
|
138
|
+
text: "No guardrail files found in .stoa/guardrails/",
|
|
139
|
+
mimeType: "text/plain",
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
const parts = [];
|
|
145
|
+
for (const file of mdFiles) {
|
|
146
|
+
const content = await readFile(join(guardrailsDir, file), "utf-8");
|
|
147
|
+
parts.push(content);
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
contents: [
|
|
151
|
+
{
|
|
152
|
+
uri: "stoa://guardrails",
|
|
153
|
+
text: parts.join("\n\n"),
|
|
154
|
+
mimeType: "text/markdown",
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return {
|
|
161
|
+
contents: [
|
|
162
|
+
{
|
|
163
|
+
uri: "stoa://guardrails",
|
|
164
|
+
text: "Guardrails directory (.stoa/guardrails/) does not exist.",
|
|
165
|
+
mimeType: "text/plain",
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
// ── Prompt: refine ────────────────────────────────────────────────────
|
|
172
|
+
server.prompt("refine", "Generate a prompt to refine a task using the refine_task tool.", {
|
|
173
|
+
title: z.string(),
|
|
174
|
+
description: z.string(),
|
|
175
|
+
}, ({ title, description }) => ({
|
|
176
|
+
messages: [
|
|
177
|
+
{
|
|
178
|
+
role: "user",
|
|
179
|
+
content: {
|
|
180
|
+
type: "text",
|
|
181
|
+
text: `Please call the refine_task tool with the following:\n\ntitle: ${title}\ndescription: ${description}`,
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
}));
|
|
186
|
+
// ── Start server ──────────────────────────────────────────────────────
|
|
187
|
+
async function main() {
|
|
188
|
+
const transport = new StdioServerTransport();
|
|
189
|
+
await server.connect(transport);
|
|
190
|
+
process.stderr.write("stoa-mcp server running on stdio\n");
|
|
191
|
+
}
|
|
192
|
+
main().catch((err) => {
|
|
193
|
+
process.stderr.write(`Fatal: ${err}\n`);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
});
|
|
196
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,WAAW,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAU,CAAC;AAErF,MAAM,oBAAoB,GAAsC;IAC9D,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,CAAC;IACZ,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC;IACT,QAAQ,EAAE,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,yEAAyE;AAEzE,MAAM,CAAC,IAAI,CACT,aAAa,EACb,oGAAoG,EACpG;IACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACtC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACtC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC5B,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,EAAE,EAAE;IAC9D,uDAAuD;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;IAC7C,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,gFAAgF;iBACvF;aACF;YACD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC7D,MAAM,GAAG,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,mBAAmB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,wCAAwC;IACxC,IAAI,CAAC;QACH,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,wCAAwC;IAC1C,CAAC;IAED,2BAA2B;IAC3B,IAAI,UAAU,CAAC;IACf,IAAI,CAAC;QACH,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,cAAc,CACjC;QACE,KAAK;QACL,WAAW;QACX,cAAc,EAAE,eAAe;QAC/B,UAAU;QACV,IAAI;KACL,EACD,EAAE,MAAM,EAAE,YAAY,EAAE,CACzB,CAAC;IAEF,8DAA8D;IAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACxD,MAAM,SAAS,GAA2B,EAAE,CAAC;IAC7C,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/B,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC;IACvC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAChD,MAAM,eAAe,CACnB,QAAQ,EACR,IAAI,EACJ,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAoB,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EACpD,MAAM,CAAC,aAAa,EACpB,OAAO,CACR,CAAC;IACJ,CAAC;IAAC,OAAO,QAAiB,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,QAAQ,YAAY,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sDAAsD,IAAI,MAAM,GAAG,IAAI,CAAC,CAAC;IAChG,CAAC;IAED,gFAAgF;IAChF,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAC3C,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3E,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,cAAc,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;IAEpD,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KACrE,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,yEAAyE;AAEzE,MAAM,CAAC,IAAI,CACT,YAAY,EACZ,4DAA4D,EAC5D;IACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;CACjB,EACD,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;IACX,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,gBAAgB,CAAC;QAC9B,cAAc;QACd,iBAAiB,EAAE,IAAI,CAAC,MAAM;QAC9B,UAAU,EAAE,KAAK;QACjB,qBAAqB,EAAE,KAAK;QAC5B,aAAa,EAAE,KAAK;QACpB,OAAO,EAAE,KAAK;QACd,YAAY,EAAE,KAAK;QACnB,WAAW,EAAE,KAAK;KACnB,CAAC,CAAC;IAEH,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KACnE,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,yEAAyE;AAEzE,MAAM,CAAC,QAAQ,CACb,YAAY,EACZ,mBAAmB,EACnB,EAAE,WAAW,EAAE,qDAAqD,EAAE,EACtE,KAAK,IAAI,EAAE;IACT,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IAEjE,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAE9D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,mBAAmB;wBACxB,IAAI,EAAE,+CAA+C;wBACrD,QAAQ,EAAE,YAAY;qBACvB;iBACF;aACF,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;YACnE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;QAED,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,mBAAmB;oBACxB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;oBACxB,QAAQ,EAAE,eAAe;iBAC1B;aACF;SACF,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,mBAAmB;oBACxB,IAAI,EAAE,0DAA0D;oBAChE,QAAQ,EAAE,YAAY;iBACvB;aACF;SACF,CAAC;IACJ,CAAC;AACH,CAAC,CACF,CAAC;AAEF,yEAAyE;AAEzE,MAAM,CAAC,MAAM,CACX,QAAQ,EACR,gEAAgE,EAChE;IACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;CACxB,EACD,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;IAC3B,QAAQ,EAAE;QACR;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,kEAAkE,KAAK,kBAAkB,WAAW,EAAE;aAC7G;SACF;KACF;CACF,CAAC,CACH,CAAC;AAEF,yEAAyE;AAEzE,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;AAC7D,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-detection.d.ts","sourceRoot":"","sources":["../../src/storage/change-detection.ts"],"names":[],"mappings":"AAWA,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,MAAM,EAAE,CAAC,CA6CnB"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
const STAGE_MAP = {
|
|
4
|
+
"01-problem-statement.md": [2, 3, 5],
|
|
5
|
+
"02-acceptance-criteria.md": [3, 5],
|
|
6
|
+
"03-constraints.md": [5],
|
|
7
|
+
"user-notes.md": [1, 3, 5],
|
|
8
|
+
"moodboard.md": [1, 3],
|
|
9
|
+
};
|
|
10
|
+
export async function detectChanges(specDir, snapshot) {
|
|
11
|
+
// Check all files in STAGE_MAP — not just snapshot keys.
|
|
12
|
+
// Files absent from the snapshot but now present on disk are new (dirty).
|
|
13
|
+
const filenames = Object.keys(STAGE_MAP);
|
|
14
|
+
const results = await Promise.all(filenames.map(async (filename) => {
|
|
15
|
+
let current;
|
|
16
|
+
try {
|
|
17
|
+
current = await readFile(join(specDir, filename), "utf-8");
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
current = null;
|
|
21
|
+
}
|
|
22
|
+
const prev = snapshot[filename];
|
|
23
|
+
// File didn't exist before and still doesn't — no change
|
|
24
|
+
if (prev === undefined && current === null) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
// File is new (didn't exist in snapshot but exists now)
|
|
28
|
+
if (prev === undefined && current !== null) {
|
|
29
|
+
process.stderr.write(`[change-detection] new: ${filename}\n`);
|
|
30
|
+
return STAGE_MAP[filename] ?? [];
|
|
31
|
+
}
|
|
32
|
+
// File was deleted (existed in snapshot but gone now)
|
|
33
|
+
if (prev !== undefined && current === null) {
|
|
34
|
+
process.stderr.write(`[change-detection] deleted: ${filename}\n`);
|
|
35
|
+
return STAGE_MAP[filename] ?? [];
|
|
36
|
+
}
|
|
37
|
+
// File content changed
|
|
38
|
+
if (current !== prev) {
|
|
39
|
+
process.stderr.write(`[change-detection] dirty: ${filename}\n`);
|
|
40
|
+
return STAGE_MAP[filename] ?? [];
|
|
41
|
+
}
|
|
42
|
+
return [];
|
|
43
|
+
}));
|
|
44
|
+
const stages = new Set(results.flat());
|
|
45
|
+
return [...stages].sort((a, b) => a - b);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=change-detection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-detection.js","sourceRoot":"","sources":["../../src/storage/change-detection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,SAAS,GAAsC;IACnD,yBAAyB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACpC,2BAA2B,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACnC,mBAAmB,EAAE,CAAC,CAAC,CAAC;IACxB,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC1B,cAAc,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;CACd,CAAC;AAEX,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,QAAgC;IAEhC,yDAAyD;IACzD,0EAA0E;IAC1E,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEzC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QAC/B,IAAI,OAAsB,CAAC;QAC3B,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QAED,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAEhC,yDAAyD;QACzD,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YAC3C,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,wDAAwD;QACxD,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YAC3C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,QAAQ,IAAI,CAAC,CAAC;YAC9D,OAAO,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,CAAC;QAED,sDAAsD;QACtD,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YAC3C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,QAAQ,IAAI,CAAC,CAAC;YAClE,OAAO,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,CAAC;QAED,uBAAuB;QACvB,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,QAAQ,IAAI,CAAC,CAAC;YAChE,OAAO,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,CAAC;QAED,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,CACH,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-detection.test.d.ts","sourceRoot":"","sources":["../../src/storage/change-detection.test.ts"],"names":[],"mappings":""}
|