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.
Files changed (167) hide show
  1. package/LICENSE +65 -0
  2. package/README.md +397 -0
  3. package/dist/cli/build.d.ts +39 -0
  4. package/dist/cli/build.d.ts.map +1 -0
  5. package/dist/cli/build.js +288 -0
  6. package/dist/cli/build.js.map +1 -0
  7. package/dist/cli/review-loop.d.ts +2 -0
  8. package/dist/cli/review-loop.d.ts.map +1 -0
  9. package/dist/cli/review-loop.js +97 -0
  10. package/dist/cli/review-loop.js.map +1 -0
  11. package/dist/cli/scenarios-runner.d.ts +12 -0
  12. package/dist/cli/scenarios-runner.d.ts.map +1 -0
  13. package/dist/cli/scenarios-runner.js +158 -0
  14. package/dist/cli/scenarios-runner.js.map +1 -0
  15. package/dist/cli/verify.d.ts +13 -0
  16. package/dist/cli/verify.d.ts.map +1 -0
  17. package/dist/cli/verify.js +149 -0
  18. package/dist/cli/verify.js.map +1 -0
  19. package/dist/cli.d.ts +3 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +1135 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/core/index.d.ts +3 -0
  24. package/dist/core/index.d.ts.map +1 -0
  25. package/dist/core/index.js +2 -0
  26. package/dist/core/index.js.map +1 -0
  27. package/dist/core/parsers.d.ts +29 -0
  28. package/dist/core/parsers.d.ts.map +1 -0
  29. package/dist/core/parsers.js +296 -0
  30. package/dist/core/parsers.js.map +1 -0
  31. package/dist/core/parsers.test.d.ts +2 -0
  32. package/dist/core/parsers.test.d.ts.map +1 -0
  33. package/dist/core/parsers.test.js +198 -0
  34. package/dist/core/parsers.test.js.map +1 -0
  35. package/dist/core/prompts.d.ts +30 -0
  36. package/dist/core/prompts.d.ts.map +1 -0
  37. package/dist/core/prompts.js +346 -0
  38. package/dist/core/prompts.js.map +1 -0
  39. package/dist/core/refine.d.ts +38 -0
  40. package/dist/core/refine.d.ts.map +1 -0
  41. package/dist/core/refine.js +233 -0
  42. package/dist/core/refine.js.map +1 -0
  43. package/dist/core/spec-score.d.ts +17 -0
  44. package/dist/core/spec-score.d.ts.map +1 -0
  45. package/dist/core/spec-score.js +59 -0
  46. package/dist/core/spec-score.js.map +1 -0
  47. package/dist/formatters/index.d.ts +2 -0
  48. package/dist/formatters/index.d.ts.map +1 -0
  49. package/dist/formatters/index.js +2 -0
  50. package/dist/formatters/index.js.map +1 -0
  51. package/dist/formatters/stage-formatters.d.ts +10 -0
  52. package/dist/formatters/stage-formatters.d.ts.map +1 -0
  53. package/dist/formatters/stage-formatters.js +100 -0
  54. package/dist/formatters/stage-formatters.js.map +1 -0
  55. package/dist/formatters/stage-formatters.test.d.ts +2 -0
  56. package/dist/formatters/stage-formatters.test.d.ts.map +1 -0
  57. package/dist/formatters/stage-formatters.test.js +107 -0
  58. package/dist/formatters/stage-formatters.test.js.map +1 -0
  59. package/dist/guardrails/index.d.ts +2 -0
  60. package/dist/guardrails/index.d.ts.map +1 -0
  61. package/dist/guardrails/index.js +2 -0
  62. package/dist/guardrails/index.js.map +1 -0
  63. package/dist/guardrails/loader.d.ts +9 -0
  64. package/dist/guardrails/loader.d.ts.map +1 -0
  65. package/dist/guardrails/loader.js +56 -0
  66. package/dist/guardrails/loader.js.map +1 -0
  67. package/dist/guardrails/refine.d.ts +53 -0
  68. package/dist/guardrails/refine.d.ts.map +1 -0
  69. package/dist/guardrails/refine.js +184 -0
  70. package/dist/guardrails/refine.js.map +1 -0
  71. package/dist/index.d.ts +6 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +196 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/storage/change-detection.d.ts +2 -0
  76. package/dist/storage/change-detection.d.ts.map +1 -0
  77. package/dist/storage/change-detection.js +47 -0
  78. package/dist/storage/change-detection.js.map +1 -0
  79. package/dist/storage/change-detection.test.d.ts +2 -0
  80. package/dist/storage/change-detection.test.d.ts.map +1 -0
  81. package/dist/storage/change-detection.test.js +81 -0
  82. package/dist/storage/change-detection.test.js.map +1 -0
  83. package/dist/storage/index.d.ts +9 -0
  84. package/dist/storage/index.d.ts.map +1 -0
  85. package/dist/storage/index.js +6 -0
  86. package/dist/storage/index.js.map +1 -0
  87. package/dist/storage/moodboard-describe.d.ts +14 -0
  88. package/dist/storage/moodboard-describe.d.ts.map +1 -0
  89. package/dist/storage/moodboard-describe.js +185 -0
  90. package/dist/storage/moodboard-describe.js.map +1 -0
  91. package/dist/storage/moodboard-sync.d.ts +11 -0
  92. package/dist/storage/moodboard-sync.d.ts.map +1 -0
  93. package/dist/storage/moodboard-sync.js +205 -0
  94. package/dist/storage/moodboard-sync.js.map +1 -0
  95. package/dist/storage/moodboard.d.ts +4 -0
  96. package/dist/storage/moodboard.d.ts.map +1 -0
  97. package/dist/storage/moodboard.js +68 -0
  98. package/dist/storage/moodboard.js.map +1 -0
  99. package/dist/storage/moodboard.test.d.ts +2 -0
  100. package/dist/storage/moodboard.test.d.ts.map +1 -0
  101. package/dist/storage/moodboard.test.js +133 -0
  102. package/dist/storage/moodboard.test.js.map +1 -0
  103. package/dist/storage/project-scan.d.ts +12 -0
  104. package/dist/storage/project-scan.d.ts.map +1 -0
  105. package/dist/storage/project-scan.js +118 -0
  106. package/dist/storage/project-scan.js.map +1 -0
  107. package/dist/storage/project.d.ts +10 -0
  108. package/dist/storage/project.d.ts.map +1 -0
  109. package/dist/storage/project.js +101 -0
  110. package/dist/storage/project.js.map +1 -0
  111. package/dist/storage/roles-refine.d.ts +59 -0
  112. package/dist/storage/roles-refine.d.ts.map +1 -0
  113. package/dist/storage/roles-refine.js +223 -0
  114. package/dist/storage/roles-refine.js.map +1 -0
  115. package/dist/storage/roles.d.ts +6 -0
  116. package/dist/storage/roles.d.ts.map +1 -0
  117. package/dist/storage/roles.js +41 -0
  118. package/dist/storage/roles.js.map +1 -0
  119. package/dist/storage/scenarios-refine.d.ts +47 -0
  120. package/dist/storage/scenarios-refine.d.ts.map +1 -0
  121. package/dist/storage/scenarios-refine.js +311 -0
  122. package/dist/storage/scenarios-refine.js.map +1 -0
  123. package/dist/storage/scenarios.d.ts +12 -0
  124. package/dist/storage/scenarios.d.ts.map +1 -0
  125. package/dist/storage/scenarios.js +37 -0
  126. package/dist/storage/scenarios.js.map +1 -0
  127. package/dist/storage/specs.d.ts +17 -0
  128. package/dist/storage/specs.d.ts.map +1 -0
  129. package/dist/storage/specs.js +104 -0
  130. package/dist/storage/specs.js.map +1 -0
  131. package/dist/tools/index.d.ts +2 -0
  132. package/dist/tools/index.d.ts.map +1 -0
  133. package/dist/tools/index.js +2 -0
  134. package/dist/tools/index.js.map +1 -0
  135. package/dist/tools/rerefine.d.ts +8 -0
  136. package/dist/tools/rerefine.d.ts.map +1 -0
  137. package/dist/tools/rerefine.js +153 -0
  138. package/dist/tools/rerefine.js.map +1 -0
  139. package/dist/tools/rerefine.test.d.ts +2 -0
  140. package/dist/tools/rerefine.test.d.ts.map +1 -0
  141. package/dist/tools/rerefine.test.js +123 -0
  142. package/dist/tools/rerefine.test.js.map +1 -0
  143. package/dist/utils/index.d.ts +3 -0
  144. package/dist/utils/index.d.ts.map +1 -0
  145. package/dist/utils/index.js +3 -0
  146. package/dist/utils/index.js.map +1 -0
  147. package/dist/utils/slug.d.ts +3 -0
  148. package/dist/utils/slug.d.ts.map +1 -0
  149. package/dist/utils/slug.js +33 -0
  150. package/dist/utils/slug.js.map +1 -0
  151. package/dist/utils/spec-helpers.d.ts +12 -0
  152. package/dist/utils/spec-helpers.d.ts.map +1 -0
  153. package/dist/utils/spec-helpers.js +95 -0
  154. package/dist/utils/spec-helpers.js.map +1 -0
  155. package/dist/utils/spec-helpers.test.d.ts +2 -0
  156. package/dist/utils/spec-helpers.test.d.ts.map +1 -0
  157. package/dist/utils/spec-helpers.test.js +114 -0
  158. package/dist/utils/spec-helpers.test.js.map +1 -0
  159. package/package.json +53 -0
  160. package/templates/guardrails/ask-when-unclear.md +3 -0
  161. package/templates/guardrails/dont-delete-code.md +3 -0
  162. package/templates/guardrails/explain-changes.md +3 -0
  163. package/templates/guardrails/run-tests.md +3 -0
  164. package/templates/guardrails/small-changes.md +3 -0
  165. package/templates/roles/builder.md +3 -0
  166. package/templates/roles/fixer.md +3 -0
  167. package/templates/roles/planner.md +3 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moodboard.test.d.ts","sourceRoot":"","sources":["../../src/storage/moodboard.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,133 @@
1
+ import { describe, it, afterEach } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdir, writeFile, readFile, rm } from "node:fs/promises";
4
+ import { join } from "node:path";
5
+ import { tmpdir } from "node:os";
6
+ import { readMoodboard } from "./moodboard.js";
7
+ const TEST_ROOT = join(tmpdir(), "stoa-moodboard-test-" + Date.now());
8
+ async function setup(files) {
9
+ const root = join(TEST_ROOT, String(Math.random()).slice(2));
10
+ const moodDir = join(root, ".stoa", "moodboard");
11
+ await mkdir(moodDir, { recursive: true });
12
+ for (const [name, content] of Object.entries(files)) {
13
+ await writeFile(join(moodDir, name), content);
14
+ }
15
+ return root;
16
+ }
17
+ afterEach(async () => {
18
+ try {
19
+ await rm(TEST_ROOT, { recursive: true, force: true });
20
+ }
21
+ catch {
22
+ // ignore
23
+ }
24
+ });
25
+ describe("readMoodboard", () => {
26
+ it("returns null when moodboard dir does not exist", async () => {
27
+ const result = await readMoodboard(join(TEST_ROOT, "nonexistent"));
28
+ assert.equal(result, null);
29
+ });
30
+ it("returns null for empty moodboard dir", async () => {
31
+ const root = await setup({});
32
+ const result = await readMoodboard(root);
33
+ assert.equal(result, null);
34
+ });
35
+ it("throws TypeError for non-string projectRoot", async () => {
36
+ await assert.rejects(() => readMoodboard(""), { name: "TypeError" });
37
+ await assert.rejects(() => readMoodboard(null), { name: "TypeError" });
38
+ });
39
+ it("returns sections and imageFiles", async () => {
40
+ const root = await setup({
41
+ "notes.md": "# Colors\nPrimary: #E8C872\n\n# Layout\nSidebar left\n",
42
+ "hero.png": "",
43
+ "palette.jpg": "",
44
+ });
45
+ const result = await readMoodboard(root);
46
+ assert.notEqual(result, null);
47
+ assert.equal(result.sections["Colors"], "Primary: #E8C872");
48
+ assert.equal(result.sections["Layout"], "Sidebar left");
49
+ assert.deepEqual(result.imageFiles, ["hero.png", "palette.jpg"]);
50
+ });
51
+ it("writes .snapshot with hash, imageFiles, and timestamp", async () => {
52
+ const root = await setup({
53
+ "notes.md": "# Colors\n#FF0000\n",
54
+ "hero.png": "",
55
+ });
56
+ await readMoodboard(root);
57
+ const raw = await readFile(join(root, ".stoa", "moodboard", ".snapshot"), "utf-8");
58
+ const snapshot = JSON.parse(raw);
59
+ assert.ok(typeof snapshot.hash === "string");
60
+ assert.equal(snapshot.hash.length, 64);
61
+ assert.match(snapshot.hash, /^[0-9a-f]{64}$/);
62
+ assert.deepEqual(snapshot.imageFiles, ["hero.png"]);
63
+ assert.ok(typeof snapshot.timestamp === "string");
64
+ });
65
+ it("strips HTML comments from sections", async () => {
66
+ const root = await setup({
67
+ "notes.md": "# Colors\n<!-- Hex values -->\nPrimary: #000\n",
68
+ });
69
+ const result = await readMoodboard(root);
70
+ assert.notEqual(result, null);
71
+ assert.equal(result.sections["Colors"], "Primary: #000");
72
+ assert.ok(!JSON.stringify(result.sections).includes("<!--"));
73
+ });
74
+ it("skips empty sections (template hints only)", async () => {
75
+ const root = await setup({
76
+ "notes.md": "# Colors\n<!-- Hex values -->\n\n# Layout\nSidebar left\n# Typography\n<!-- Sans-serif -->\n",
77
+ });
78
+ const result = await readMoodboard(root);
79
+ assert.notEqual(result, null);
80
+ assert.ok(!("Colors" in result.sections));
81
+ assert.equal(result.sections["Layout"], "Sidebar left");
82
+ assert.ok(!("Typography" in result.sections));
83
+ });
84
+ it("returns null when notes.md has only template (all empty sections)", async () => {
85
+ const root = await setup({
86
+ "notes.md": "# Colors\n<!-- hints -->\n\n# Layout\n<!-- hints -->\n",
87
+ });
88
+ const result = await readMoodboard(root);
89
+ assert.equal(result, null);
90
+ });
91
+ it("returns imageFiles when no notes.md", async () => {
92
+ const root = await setup({
93
+ "logo.svg": "<svg></svg>",
94
+ });
95
+ const result = await readMoodboard(root);
96
+ assert.notEqual(result, null);
97
+ assert.deepEqual(result.imageFiles, ["logo.svg"]);
98
+ assert.deepEqual(result.sections, {});
99
+ });
100
+ it("handles case-insensitive image extensions", async () => {
101
+ const root = await setup({
102
+ "photo.PNG": "",
103
+ "banner.JPEG": "",
104
+ });
105
+ const result = await readMoodboard(root);
106
+ assert.notEqual(result, null);
107
+ assert.deepEqual(result.imageFiles, ["banner.JPEG", "photo.PNG"]);
108
+ });
109
+ it("ignores non-image files", async () => {
110
+ const root = await setup({
111
+ "notes.md": "# Colors\n#000\n",
112
+ "data.json": "{}",
113
+ "script.ts": "",
114
+ "hero.png": "",
115
+ });
116
+ const result = await readMoodboard(root);
117
+ assert.deepEqual(result.imageFiles, ["hero.png"]);
118
+ });
119
+ it("sorts image filenames", async () => {
120
+ const root = await setup({
121
+ "z-last.png": "",
122
+ "a-first.jpg": "",
123
+ "m-middle.webp": "",
124
+ });
125
+ const result = await readMoodboard(root);
126
+ assert.deepEqual(result.imageFiles, [
127
+ "a-first.jpg",
128
+ "m-middle.webp",
129
+ "z-last.png",
130
+ ]);
131
+ });
132
+ });
133
+ //# sourceMappingURL=moodboard.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moodboard.test.js","sourceRoot":"","sources":["../../src/storage/moodboard.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface ProjectContext {
2
+ hasExistingCode: boolean;
3
+ packageName?: string;
4
+ stack: string[];
5
+ components: string[];
6
+ previousSpecs: string[];
7
+ tokens?: Record<string, unknown>;
8
+ context?: string;
9
+ lessons?: string;
10
+ }
11
+ export declare function scanProject(dir: string): ProjectContext;
12
+ //# sourceMappingURL=project-scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-scan.d.ts","sourceRoot":"","sources":["../../src/storage/project-scan.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,eAAe,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAkDD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CA8EvD"}
@@ -0,0 +1,118 @@
1
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ const FRAMEWORK_DETECTORS = {
4
+ react: "React",
5
+ "react-dom": "React",
6
+ next: "Next.js",
7
+ vue: "Vue",
8
+ svelte: "Svelte",
9
+ vite: "Vite",
10
+ "@angular/core": "Angular",
11
+ nuxt: "Nuxt",
12
+ };
13
+ const STYLE_DETECTORS = {
14
+ tailwindcss: "Tailwind",
15
+ "styled-components": "styled-components",
16
+ "@emotion/react": "Emotion",
17
+ sass: "Sass",
18
+ };
19
+ function detectStack(deps) {
20
+ const stack = [];
21
+ for (const [pkg, label] of Object.entries(FRAMEWORK_DETECTORS)) {
22
+ if (deps[pkg]) {
23
+ const version = deps[pkg].replace(/[\^~>=<]/g, "").split(".")[0];
24
+ stack.push(version ? `${label} ${version}` : label);
25
+ }
26
+ }
27
+ for (const [pkg, label] of Object.entries(STYLE_DETECTORS)) {
28
+ if (deps[pkg]) {
29
+ stack.push(label);
30
+ }
31
+ }
32
+ return stack;
33
+ }
34
+ function readFileSafe(path) {
35
+ try {
36
+ const content = readFileSync(path, "utf-8").trim();
37
+ // Strip HTML comments and check if there's real content
38
+ const stripped = content.replace(/<!--[\s\S]*?-->/g, "").replace(/^#.*$/gm, "").trim();
39
+ return stripped.length > 0 ? content : undefined;
40
+ }
41
+ catch {
42
+ return undefined;
43
+ }
44
+ }
45
+ export function scanProject(dir) {
46
+ const context = {
47
+ hasExistingCode: false,
48
+ stack: [],
49
+ components: [],
50
+ previousSpecs: [],
51
+ };
52
+ // Check package.json
53
+ const pkgPath = join(dir, "package.json");
54
+ if (existsSync(pkgPath)) {
55
+ try {
56
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
57
+ context.packageName = pkg.name;
58
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
59
+ context.stack = detectStack(allDeps);
60
+ // TypeScript detection
61
+ if (allDeps["typescript"] || existsSync(join(dir, "tsconfig.json"))) {
62
+ context.stack.push("TypeScript");
63
+ }
64
+ }
65
+ catch {
66
+ // Invalid package.json — skip
67
+ }
68
+ }
69
+ // Scan src/ or app/ (1 level deep)
70
+ for (const srcDir of ["src", "app"]) {
71
+ const srcPath = join(dir, srcDir);
72
+ if (existsSync(srcPath)) {
73
+ try {
74
+ const entries = readdirSync(srcPath);
75
+ const codeFiles = entries.filter((f) => /\.(ts|tsx|js|jsx|vue|svelte)$/.test(f));
76
+ context.components.push(...codeFiles);
77
+ }
78
+ catch {
79
+ // Permission error or not a directory — skip
80
+ }
81
+ }
82
+ }
83
+ context.hasExistingCode = context.components.length > 0 || existsSync(pkgPath);
84
+ // Check for previous specs
85
+ const specsDir = join(dir, ".stoa", "specs");
86
+ if (existsSync(specsDir)) {
87
+ try {
88
+ const specDirs = readdirSync(specsDir).filter((entry) => {
89
+ try {
90
+ return readdirSync(join(specsDir, entry)).length > 0;
91
+ }
92
+ catch {
93
+ return false;
94
+ }
95
+ });
96
+ context.previousSpecs = specDirs;
97
+ }
98
+ catch {
99
+ // No specs dir — skip
100
+ }
101
+ }
102
+ // Read tokens.json
103
+ const tokensPath = join(dir, ".stoa", "moodboard", "tokens.json");
104
+ if (existsSync(tokensPath)) {
105
+ try {
106
+ context.tokens = JSON.parse(readFileSync(tokensPath, "utf-8"));
107
+ }
108
+ catch {
109
+ // Invalid JSON — skip
110
+ }
111
+ }
112
+ // Read context.md (merged brand voice + dependencies + conventions)
113
+ context.context = readFileSafe(join(dir, ".stoa", "context.md"));
114
+ // Read lessons.md (separate — auto-grows)
115
+ context.lessons = readFileSafe(join(dir, ".stoa", "lessons.md"));
116
+ return context;
117
+ }
118
+ //# sourceMappingURL=project-scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-scan.js","sourceRoot":"","sources":["../../src/storage/project-scan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAajC,MAAM,mBAAmB,GAA2B;IAClD,KAAK,EAAE,OAAO;IACd,WAAW,EAAE,OAAO;IACpB,IAAI,EAAE,SAAS;IACf,GAAG,EAAE,KAAK;IACV,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,eAAe,EAAE,SAAS;IAC1B,IAAI,EAAE,MAAM;CACb,CAAC;AAEF,MAAM,eAAe,GAA2B;IAC9C,WAAW,EAAE,UAAU;IACvB,mBAAmB,EAAE,mBAAmB;IACxC,gBAAgB,EAAE,SAAS;IAC3B,IAAI,EAAE,MAAM;CACb,CAAC;AAEF,SAAS,WAAW,CAAC,IAA4B;IAC/C,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC/D,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACd,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACjE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QAC3D,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACd,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QACnD,wDAAwD;QACxD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACvF,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,OAAO,GAAmB;QAC9B,eAAe,EAAE,KAAK;QACtB,KAAK,EAAE,EAAE;QACT,UAAU,EAAE,EAAE;QACd,aAAa,EAAE,EAAE;KAClB,CAAC;IAEF,qBAAqB;IACrB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC1C,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;YACvD,OAAO,CAAC,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC;YAC/B,MAAM,OAAO,GAAG,EAAE,GAAG,GAAG,CAAC,YAAY,EAAE,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC;YAEhE,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;YAErC,uBAAuB;YACvB,IAAI,OAAO,CAAC,YAAY,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC;gBACpE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,8BAA8B;QAChC,CAAC;IACH,CAAC;IAED,mCAAmC;IACnC,KAAK,MAAM,MAAM,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAClC,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;gBACrC,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACrC,+BAA+B,CAAC,IAAI,CAAC,CAAC,CAAC,CACxC,CAAC;gBACF,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;YACxC,CAAC;YAAC,MAAM,CAAC;gBACP,6CAA6C;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;IAE/E,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACtD,IAAI,CAAC;oBACH,OAAO,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;gBACvD,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC,CAAC,CAAC;YACH,OAAO,CAAC,aAAa,GAAG,QAAQ,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;IAClE,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QACjE,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;IACH,CAAC;IAED,oEAAoE;IACpE,OAAO,CAAC,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IACjE,0CAA0C;IAC1C,OAAO,CAAC,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IAEjE,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,10 @@
1
+ interface ProjectConfig {
2
+ name: string;
3
+ type: string;
4
+ model: string;
5
+ defaultRole?: string;
6
+ }
7
+ export declare function initProject(name: string, type: string, noTemplates?: boolean): Promise<boolean>;
8
+ export declare function loadConfig(): Promise<ProjectConfig>;
9
+ export {};
10
+ //# sourceMappingURL=project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/storage/project.ts"],"names":[],"mappings":"AAMA,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAqCD,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,UAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CA2FnG;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,CAIzD"}
@@ -0,0 +1,101 @@
1
+ import { existsSync } from "node:fs";
2
+ import { copyFile, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { toSlug } from "../utils/slug.js";
6
+ function getTemplatesDir() {
7
+ return fileURLToPath(new URL("../../templates/", import.meta.url));
8
+ }
9
+ async function copyTemplates(stoaDir) {
10
+ const templatesDir = getTemplatesDir();
11
+ const copied = [];
12
+ for (const subdir of ["roles", "guardrails"]) {
13
+ const srcDir = join(templatesDir, subdir);
14
+ const destDir = join(stoaDir, subdir);
15
+ if (!existsSync(srcDir))
16
+ continue;
17
+ await mkdir(destDir, { recursive: true });
18
+ const files = await readdir(srcDir);
19
+ for (const file of files) {
20
+ const destPath = join(destDir, file);
21
+ if (!existsSync(destPath)) {
22
+ await copyFile(join(srcDir, file), destPath);
23
+ copied.push(`${subdir}/${file}`);
24
+ }
25
+ }
26
+ }
27
+ return copied;
28
+ }
29
+ export async function initProject(name, type, noTemplates = false) {
30
+ const stoaDir = join(process.cwd(), ".stoa");
31
+ if (existsSync(stoaDir)) {
32
+ process.stderr.write(".stoa/ already exists. Delete it to reinitialize.\n");
33
+ return false;
34
+ }
35
+ await mkdir(stoaDir, { recursive: true });
36
+ await mkdir(join(stoaDir, "roles"), { recursive: true });
37
+ await mkdir(join(stoaDir, "guardrails"), { recursive: true });
38
+ await mkdir(join(stoaDir, "scenarios"), { recursive: true });
39
+ await mkdir(join(stoaDir, "specs"), { recursive: true });
40
+ await mkdir(join(stoaDir, "moodboard"), { recursive: true });
41
+ await writeFile(join(stoaDir, "moodboard", "notes.md"), `# Design Direction
42
+ <!-- What should this feel like? E.g. "Minimal and fast like Linear" -->
43
+
44
+ # Colors
45
+ <!-- Hex values. E.g. Primary: #E8C872, Background: #1A1A1A -->
46
+
47
+ # Layout
48
+ <!-- E.g. "Sidebar navigation left, card-based content right" -->
49
+
50
+ # Typography
51
+ <!-- E.g. "Sans-serif, large headings, compact body text" -->
52
+
53
+ # Component Style
54
+ <!-- E.g. "Rounded corners, subtle borders, no drop shadows" -->
55
+
56
+ # References
57
+ <!-- Apps to emulate. E.g. "Linear — task list density. Arc — sidebar tabs." -->
58
+
59
+ # Images
60
+ <!-- Drop files in moodboard/ folder, describe each here -->
61
+ <!-- E.g. homepage-inspo.png — I want this hero layout -->
62
+ `, "utf-8");
63
+ // Create context.md (brand voice + dependencies + conventions in one file)
64
+ await writeFile(join(stoaDir, "context.md"), `# Project Context
65
+
66
+ ## Brand Voice
67
+ <!-- How should the app talk? E.g. "Friendly, not robotic. Use 'Save' not 'Submit'." -->
68
+
69
+ ## Dependencies
70
+ <!-- Libraries to use and avoid. E.g. "Use date-fns, not moment. Use zustand, not redux." -->
71
+
72
+ ## UI Library
73
+ <!-- E.g. "HeroUI (https://www.heroui.com) — buttons, inputs, cards, modals" -->
74
+
75
+ ## Code Conventions
76
+ <!-- E.g. "PascalCase components. One component per file. Test files next to source." -->
77
+ `, "utf-8");
78
+ // Create lessons.md
79
+ await writeFile(join(stoaDir, "lessons.md"), `# Lessons Learned
80
+
81
+ <!-- This file grows over time. After a failed build or fix, add what went wrong and how to prevent it. -->
82
+ <!-- Each entry becomes a constraint in future refines, preventing the same mistake twice. -->
83
+ `, "utf-8");
84
+ const config = {
85
+ name: toSlug(name),
86
+ type,
87
+ model: "claude-sonnet-4-6",
88
+ defaultRole: "builder",
89
+ };
90
+ await writeFile(join(stoaDir, "config.json"), JSON.stringify(config, null, 2) + "\n", "utf-8");
91
+ if (!noTemplates) {
92
+ await copyTemplates(stoaDir);
93
+ }
94
+ return true;
95
+ }
96
+ export async function loadConfig() {
97
+ const configPath = join(process.cwd(), ".stoa", "config.json");
98
+ const raw = await readFile(configPath, "utf-8");
99
+ return JSON.parse(raw);
100
+ }
101
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/storage/project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Role Refine Pipeline.
3
+ * Runs a 3-stage refinement pipeline that transforms raw role definitions
4
+ * into precise, bounded, guardrail-ready specifications.
5
+ *
6
+ * Stage 1 — Sharpen Identity: Rewrite the role persona to be specific and unambiguous.
7
+ * Stage 2 — Define Boundaries: Generate explicit boundary rules (file scope, tech limits, escalation).
8
+ * Stage 3 — Suggest Guardrails: Print 2–4 guardrail suggestions to stdout only (no file writes).
9
+ */
10
+ /**
11
+ * Build the Stage 1 prompt: Sharpen Identity.
12
+ * Rewrites the role persona to be specific, unambiguous, and self-contained.
13
+ * @param seed - The raw role markdown content.
14
+ * @returns The full prompt string for Stage 1.
15
+ */
16
+ export declare function buildStage1Prompt(seed: string): string;
17
+ /**
18
+ * Build the Stage 2 prompt: Define Boundaries.
19
+ * Generates explicit boundary rules covering file scope, technology limits, and escalation triggers.
20
+ * @param stage1Output - The sharpened role definition from Stage 1.
21
+ * @returns The full prompt string for Stage 2.
22
+ */
23
+ export declare function buildStage2Prompt(stage1Output: string): string;
24
+ /**
25
+ * Build the Stage 3 prompt: Suggest Guardrails.
26
+ * Generates 2–4 guardrail rule suggestions based on the sharpened identity and defined boundaries.
27
+ * @param stage2Output - The role definition with boundaries from Stage 2.
28
+ * @returns The full prompt string for Stage 3.
29
+ */
30
+ export declare function buildStage3Prompt(stage2Output: string): string;
31
+ /** Options for the role refine pipeline. */
32
+ export interface RoleRefineOptions {
33
+ name: string;
34
+ mode: "clipboard" | "api" | "claude-code";
35
+ model?: string;
36
+ apiKey?: string;
37
+ onStageComplete?: (stageIndex: number, label: string, output: string) => void;
38
+ }
39
+ /** Result of the role refine pipeline. */
40
+ export interface RoleRefineResult {
41
+ prompts: string[];
42
+ finalOutput: string;
43
+ }
44
+ /**
45
+ * Run the 3-stage role refinement pipeline.
46
+ *
47
+ * - clipboard: Builds all 3 stage prompts and returns them via onStageComplete callback.
48
+ * Does not call any AI API. Does not modify files.
49
+ * - api: Executes all 3 stages via Anthropic API. Writes stage 1+2 output to file.
50
+ * Stage 3 output is returned but not written.
51
+ * - claude-code: Executes via Claude Code CLI. Writes stage 1+2 output to file.
52
+ * Stage 3 output is returned but not written.
53
+ *
54
+ * @param options - Pipeline configuration including name, mode, and optional model/apiKey.
55
+ * @returns The prompts used and the final output.
56
+ * @throws If the role file does not exist.
57
+ */
58
+ export declare function refinePipeline(options: RoleRefineOptions): Promise<RoleRefineResult>;
59
+ //# sourceMappingURL=roles-refine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roles-refine.d.ts","sourceRoot":"","sources":["../../src/storage/roles-refine.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuBH;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmBtD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAuB9D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAoB9D;AAgFD,4CAA4C;AAC5C,MAAM,WAAW,iBAAiB;IAChC,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,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CAoD3B"}