@slowcook-ai/cli 0.15.0-alpha.4 → 0.16.0-alpha.10
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/README.md +10 -0
- package/dist/cli.js +18 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/brew/agent.d.ts.map +1 -1
- package/dist/commands/brew/agent.js +26 -3
- package/dist/commands/brew/agent.js.map +1 -1
- package/dist/commands/init/index.d.ts.map +1 -1
- package/dist/commands/init/index.js +7 -0
- package/dist/commands/init/index.js.map +1 -1
- package/dist/commands/init/mock.d.ts +35 -0
- package/dist/commands/init/mock.d.ts.map +1 -0
- package/dist/commands/init/mock.js +500 -0
- package/dist/commands/init/mock.js.map +1 -0
- package/dist/commands/plate/classify.d.ts +65 -0
- package/dist/commands/plate/classify.d.ts.map +1 -0
- package/dist/commands/plate/classify.js +194 -0
- package/dist/commands/plate/classify.js.map +1 -0
- package/dist/commands/plate/index.d.ts.map +1 -1
- package/dist/commands/plate/index.js +121 -17
- package/dist/commands/plate/index.js.map +1 -1
- package/dist/commands/port/index.d.ts +21 -0
- package/dist/commands/port/index.d.ts.map +1 -0
- package/dist/commands/port/index.js +203 -0
- package/dist/commands/port/index.js.map +1 -0
- package/dist/commands/port/transform.d.ts +51 -0
- package/dist/commands/port/transform.d.ts.map +1 -0
- package/dist/commands/port/transform.js +102 -0
- package/dist/commands/port/transform.js.map +1 -0
- package/dist/commands/preview/config.d.ts +73 -0
- package/dist/commands/preview/config.d.ts.map +1 -0
- package/dist/commands/preview/config.js +200 -0
- package/dist/commands/preview/config.js.map +1 -0
- package/dist/commands/preview/deploy.d.ts +35 -0
- package/dist/commands/preview/deploy.d.ts.map +1 -0
- package/dist/commands/preview/deploy.js +247 -0
- package/dist/commands/preview/deploy.js.map +1 -0
- package/dist/commands/preview/index.d.ts +9 -0
- package/dist/commands/preview/index.d.ts.map +1 -0
- package/dist/commands/preview/index.js +67 -0
- package/dist/commands/preview/index.js.map +1 -0
- package/dist/commands/preview/ssh.d.ts +49 -0
- package/dist/commands/preview/ssh.d.ts.map +1 -0
- package/dist/commands/preview/ssh.js +99 -0
- package/dist/commands/preview/ssh.js.map +1 -0
- package/dist/commands/preview/teardown.d.ts +25 -0
- package/dist/commands/preview/teardown.d.ts.map +1 -0
- package/dist/commands/preview/teardown.js +164 -0
- package/dist/commands/preview/teardown.js.map +1 -0
- package/dist/commands/refine/proposals-synth.js +17 -1
- package/dist/commands/refine/proposals-synth.js.map +1 -1
- package/dist/commands/refine/spec-yaml.d.ts +100 -100
- package/dist/commands/vibe/emit.d.ts +6 -0
- package/dist/commands/vibe/emit.d.ts.map +1 -1
- package/dist/commands/vibe/emit.js +12 -0
- package/dist/commands/vibe/emit.js.map +1 -1
- package/dist/commands/vibe/index.d.ts.map +1 -1
- package/dist/commands/vibe/index.js +143 -44
- package/dist/commands/vibe/index.js.map +1 -1
- package/package.json +6 -5
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `slowcook init mock` — scaffold the consumer's mock/ directory.
|
|
3
|
+
*
|
|
4
|
+
* Writes the consumer-side shell of the singular mock app: package.json
|
|
5
|
+
* (depending on @slowcook-ai/mock-runtime + next + react), Dockerfile,
|
|
6
|
+
* tsconfig, next.config.js, postcss.config.mjs, layout.tsx, page.tsx,
|
|
7
|
+
* scenario-registry.ts, globals.css (copied from src/app/globals.css if
|
|
8
|
+
* present), .gitignore, README.md.
|
|
9
|
+
*
|
|
10
|
+
* Refuses to overwrite existing files unless --force.
|
|
11
|
+
*
|
|
12
|
+
* After running this once, the consumer commits + pushes; vibe runs
|
|
13
|
+
* after (slowcook 0.16-α.3+) populate `mock/scenarios/` + extend
|
|
14
|
+
* `mock/src/lib/scenario-registry.ts`.
|
|
15
|
+
*/
|
|
16
|
+
import { writeFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
17
|
+
import { dirname, join, relative } from "node:path";
|
|
18
|
+
export function parseMockInitArgs(argv, runtimeVersion) {
|
|
19
|
+
const args = {
|
|
20
|
+
cwd: process.cwd(),
|
|
21
|
+
force: false,
|
|
22
|
+
dryRun: false,
|
|
23
|
+
runtimeVersion,
|
|
24
|
+
};
|
|
25
|
+
for (let i = 0; i < argv.length; i++) {
|
|
26
|
+
const a = argv[i];
|
|
27
|
+
const next = argv[i + 1];
|
|
28
|
+
if (a === "--cwd" && next) {
|
|
29
|
+
args.cwd = next;
|
|
30
|
+
i++;
|
|
31
|
+
}
|
|
32
|
+
else if (a === "--force") {
|
|
33
|
+
args.force = true;
|
|
34
|
+
}
|
|
35
|
+
else if (a === "--dry-run") {
|
|
36
|
+
args.dryRun = true;
|
|
37
|
+
}
|
|
38
|
+
else if (a === "--runtime-version" && next) {
|
|
39
|
+
args.runtimeVersion = next;
|
|
40
|
+
i++;
|
|
41
|
+
}
|
|
42
|
+
else if (a === "--help" || a === "-h") {
|
|
43
|
+
printHelp();
|
|
44
|
+
process.exit(0);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return args;
|
|
48
|
+
}
|
|
49
|
+
function printHelp() {
|
|
50
|
+
console.log(`
|
|
51
|
+
slowcook init mock — scaffold the consumer's mock/ directory
|
|
52
|
+
|
|
53
|
+
Writes the consumer-side shell of the singular UI mock app.
|
|
54
|
+
Imports its runtime (Scenario types, hooks, ScenarioPicker,
|
|
55
|
+
ScenarioRegistryProvider) from @slowcook-ai/mock-runtime so updates
|
|
56
|
+
ship via npm bump rather than a re-init.
|
|
57
|
+
|
|
58
|
+
Usage:
|
|
59
|
+
slowcook init mock [--cwd <path>] [--force] [--dry-run]
|
|
60
|
+
|
|
61
|
+
Options:
|
|
62
|
+
--cwd <path> Repo root (default: cwd).
|
|
63
|
+
--force Overwrite existing files.
|
|
64
|
+
--dry-run Print planned actions without writing.
|
|
65
|
+
--runtime-version <v> Pin of @slowcook-ai/mock-runtime (default: matches cli version).
|
|
66
|
+
|
|
67
|
+
What it writes:
|
|
68
|
+
mock/package.json depends on @slowcook-ai/mock-runtime + next + react
|
|
69
|
+
mock/Dockerfile multi-stage; runs on port 3100
|
|
70
|
+
mock/tsconfig.json path aliases @/* → src/*; @/mock/* → lib/mock-runtime/*
|
|
71
|
+
mock/next.config.js turbopack root pinned to mock/ (avoids parent-src auto-discovery)
|
|
72
|
+
mock/postcss.config.mjs @tailwindcss/postcss plugin
|
|
73
|
+
mock/.gitignore node_modules, .next, .turbo, .env*.local
|
|
74
|
+
mock/README.md what the mock is + scenario authoring guide
|
|
75
|
+
mock/src/app/layout.tsx root layout; ScenarioRegistryProvider wraps children
|
|
76
|
+
mock/src/app/page.tsx renders <ScenarioPicker /> from the runtime
|
|
77
|
+
mock/src/app/globals.css copied from src/app/globals.css if present, else a minimal
|
|
78
|
+
Tailwind-v4 directives file (consumer expected to extend)
|
|
79
|
+
mock/src/lib/scenario-registry.ts consumer-owned; vibe extends this with scenario imports
|
|
80
|
+
mock/scenarios/.gitkeep empty until vibe writes story-N.ts files
|
|
81
|
+
`);
|
|
82
|
+
}
|
|
83
|
+
export function planMockFiles(args) {
|
|
84
|
+
const productionGlobals = join(args.cwd, "src/app/globals.css");
|
|
85
|
+
let globalsContents;
|
|
86
|
+
let globalsNote;
|
|
87
|
+
if (existsSync(productionGlobals)) {
|
|
88
|
+
try {
|
|
89
|
+
globalsContents = readFileSync(productionGlobals, "utf8");
|
|
90
|
+
globalsNote = `(copied from src/app/globals.css — design tokens shared with production)`;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
globalsContents = MINIMAL_GLOBALS_CSS;
|
|
94
|
+
globalsNote = "(could not read src/app/globals.css; wrote minimal Tailwind directives — extend manually)";
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
globalsContents = MINIMAL_GLOBALS_CSS;
|
|
99
|
+
globalsNote = "(no src/app/globals.css found; wrote minimal Tailwind directives — extend manually)";
|
|
100
|
+
}
|
|
101
|
+
return [
|
|
102
|
+
{ path: "mock/package.json", contents: PACKAGE_JSON(args.runtimeVersion), skipIfExists: true },
|
|
103
|
+
{ path: "mock/Dockerfile", contents: DOCKERFILE, skipIfExists: true },
|
|
104
|
+
{ path: "mock/tsconfig.json", contents: TSCONFIG, skipIfExists: true },
|
|
105
|
+
{ path: "mock/next.config.js", contents: NEXT_CONFIG, skipIfExists: true },
|
|
106
|
+
{ path: "mock/postcss.config.mjs", contents: POSTCSS_CONFIG, skipIfExists: true },
|
|
107
|
+
{ path: "mock/.gitignore", contents: GITIGNORE, skipIfExists: true },
|
|
108
|
+
{ path: "mock/README.md", contents: README, skipIfExists: true },
|
|
109
|
+
{ path: "mock/src/app/layout.tsx", contents: LAYOUT_TSX, skipIfExists: true },
|
|
110
|
+
{ path: "mock/src/app/page.tsx", contents: PAGE_TSX, skipIfExists: true },
|
|
111
|
+
{
|
|
112
|
+
path: "mock/src/app/globals.css",
|
|
113
|
+
contents: globalsContents + `\n/* ${globalsNote} */\n`,
|
|
114
|
+
skipIfExists: true,
|
|
115
|
+
},
|
|
116
|
+
{ path: "mock/src/lib/scenario-registry.ts", contents: SCENARIO_REGISTRY, skipIfExists: true },
|
|
117
|
+
{ path: "mock/scenarios/.gitkeep", contents: "", skipIfExists: true },
|
|
118
|
+
];
|
|
119
|
+
}
|
|
120
|
+
export async function initMock(argv, cliVersion) {
|
|
121
|
+
const runtimeVersion = mockRuntimeVersionFor(cliVersion);
|
|
122
|
+
const args = parseMockInitArgs(argv, runtimeVersion);
|
|
123
|
+
const files = planMockFiles(args);
|
|
124
|
+
console.log(`slowcook init mock · cwd: ${relative(process.cwd(), args.cwd) || "."}`);
|
|
125
|
+
console.log(`runtime: @slowcook-ai/mock-runtime@${args.runtimeVersion}`);
|
|
126
|
+
console.log();
|
|
127
|
+
const actions = [];
|
|
128
|
+
for (const f of files) {
|
|
129
|
+
const full = join(args.cwd, f.path);
|
|
130
|
+
if (existsSync(full) && !args.force) {
|
|
131
|
+
actions.push({ action: "SKIP", reason: "exists (pass --force to overwrite)", path: f.path });
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
actions.push({ action: "WRITE", reason: "", path: f.path });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
for (const a of actions) {
|
|
138
|
+
const tag = a.action === "WRITE" ? "WRITE" : "SKIP ";
|
|
139
|
+
console.log(` ${tag} ${a.path}${a.reason ? ` (${a.reason})` : ""}`);
|
|
140
|
+
}
|
|
141
|
+
console.log();
|
|
142
|
+
if (args.dryRun) {
|
|
143
|
+
console.log("--dry-run: no files written.");
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
let written = 0;
|
|
147
|
+
let skipped = 0;
|
|
148
|
+
for (const f of files) {
|
|
149
|
+
const full = join(args.cwd, f.path);
|
|
150
|
+
if (existsSync(full) && !args.force) {
|
|
151
|
+
skipped += 1;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
mkdirSync(dirname(full), { recursive: true });
|
|
155
|
+
writeFileSync(full, f.contents, "utf8");
|
|
156
|
+
written += 1;
|
|
157
|
+
}
|
|
158
|
+
console.log(`Done. Wrote ${written} file(s); skipped ${skipped}.`);
|
|
159
|
+
console.log();
|
|
160
|
+
console.log("Next steps:");
|
|
161
|
+
console.log(" 1. cd mock && npm install");
|
|
162
|
+
console.log(" 2. npm run dev # http://localhost:3100");
|
|
163
|
+
console.log(" 3. Verify the empty scenario picker renders");
|
|
164
|
+
console.log(" 4. Commit + push the mock/ directory");
|
|
165
|
+
console.log(" 5. Future vibe runs (slowcook 0.16-α.3+) populate mock/scenarios/ +");
|
|
166
|
+
console.log(" extend mock/src/lib/scenario-registry.ts");
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* The mock-runtime package versions track slowcook's overall release
|
|
170
|
+
* cadence. Until 0.16 final cuts we hardcode the latest known version
|
|
171
|
+
* here. After 0.16 the cli's package.json could carry a peer-pin field.
|
|
172
|
+
*/
|
|
173
|
+
function mockRuntimeVersionFor(_cliVersion) {
|
|
174
|
+
return "^0.1.1";
|
|
175
|
+
}
|
|
176
|
+
// ---------------- templates ----------------
|
|
177
|
+
const PACKAGE_JSON = (runtimeVersion) => `{
|
|
178
|
+
"name": "${"$"}{REPO_NAME}-mock",
|
|
179
|
+
"version": "0.0.0",
|
|
180
|
+
"private": true,
|
|
181
|
+
"description": "Singular UI mock app. Run with \`npm run dev\` on :3100. See mock/README.md.",
|
|
182
|
+
"type": "module",
|
|
183
|
+
"scripts": {
|
|
184
|
+
"dev": "next dev -p 3100",
|
|
185
|
+
"build": "next build",
|
|
186
|
+
"start": "next start -p 3100",
|
|
187
|
+
"lint": "next lint"
|
|
188
|
+
},
|
|
189
|
+
"dependencies": {
|
|
190
|
+
"@slowcook-ai/mock-runtime": "${runtimeVersion}",
|
|
191
|
+
"next": "^16.0.0",
|
|
192
|
+
"react": "^19.0.0",
|
|
193
|
+
"react-dom": "^19.0.0"
|
|
194
|
+
},
|
|
195
|
+
"devDependencies": {
|
|
196
|
+
"@tailwindcss/postcss": "^4",
|
|
197
|
+
"@types/node": "^22",
|
|
198
|
+
"@types/react": "^19",
|
|
199
|
+
"@types/react-dom": "^19",
|
|
200
|
+
"tailwindcss": "^4",
|
|
201
|
+
"typescript": "^5"
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
`;
|
|
205
|
+
const DOCKERFILE = `# Singular UI mock — runnable on the consumer's box per scenario.
|
|
206
|
+
# Build (from repo root): docker build -t mock -f mock/Dockerfile .
|
|
207
|
+
# Run: docker run -p 3100:3100 mock
|
|
208
|
+
# Open: http://localhost:3100/?scenario=story-N
|
|
209
|
+
|
|
210
|
+
FROM node:20-alpine AS deps
|
|
211
|
+
WORKDIR /app
|
|
212
|
+
COPY mock/package.json mock/package-lock.json* ./
|
|
213
|
+
RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
|
|
214
|
+
|
|
215
|
+
FROM node:20-alpine AS builder
|
|
216
|
+
WORKDIR /app
|
|
217
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
218
|
+
COPY mock ./
|
|
219
|
+
RUN npm run build
|
|
220
|
+
|
|
221
|
+
FROM node:20-alpine AS runner
|
|
222
|
+
WORKDIR /app
|
|
223
|
+
ENV NODE_ENV=production
|
|
224
|
+
ENV PORT=3100
|
|
225
|
+
ENV HOSTNAME=0.0.0.0
|
|
226
|
+
COPY --from=builder /app/public ./public
|
|
227
|
+
COPY --from=builder /app/.next ./.next
|
|
228
|
+
COPY --from=builder /app/node_modules ./node_modules
|
|
229
|
+
COPY --from=builder /app/package.json ./package.json
|
|
230
|
+
EXPOSE 3100
|
|
231
|
+
CMD ["npm", "run", "start"]
|
|
232
|
+
`;
|
|
233
|
+
const TSCONFIG = `{
|
|
234
|
+
"compilerOptions": {
|
|
235
|
+
"target": "ES2017",
|
|
236
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
237
|
+
"allowJs": true,
|
|
238
|
+
"skipLibCheck": true,
|
|
239
|
+
"strict": true,
|
|
240
|
+
"noEmit": true,
|
|
241
|
+
"esModuleInterop": true,
|
|
242
|
+
"module": "esnext",
|
|
243
|
+
"moduleResolution": "bundler",
|
|
244
|
+
"resolveJsonModule": true,
|
|
245
|
+
"isolatedModules": true,
|
|
246
|
+
"jsx": "react-jsx",
|
|
247
|
+
"incremental": true,
|
|
248
|
+
"plugins": [{ "name": "next" }],
|
|
249
|
+
"baseUrl": ".",
|
|
250
|
+
"paths": {
|
|
251
|
+
"@/*": ["src/*"]
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
"include": ["next-env.d.ts", "src/**/*.ts", "src/**/*.tsx", "scenarios/**/*.ts", ".next/types/**/*.ts"],
|
|
255
|
+
"exclude": ["node_modules"]
|
|
256
|
+
}
|
|
257
|
+
`;
|
|
258
|
+
const NEXT_CONFIG = `import { fileURLToPath } from "node:url";
|
|
259
|
+
import { dirname } from "node:path";
|
|
260
|
+
|
|
261
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
262
|
+
|
|
263
|
+
/** @type {import('next').NextConfig} */
|
|
264
|
+
const nextConfig = {
|
|
265
|
+
reactStrictMode: true,
|
|
266
|
+
images: { unoptimized: true },
|
|
267
|
+
// Mock app lives inside the consumer's repo. Without an explicit
|
|
268
|
+
// turbopack root, Next walks up + treats the parent as the workspace
|
|
269
|
+
// root, which can pull the parent's src/ into the mock build. Pinning
|
|
270
|
+
// to this directory keeps the mock self-contained.
|
|
271
|
+
turbopack: { root: __dirname },
|
|
272
|
+
outputFileTracingRoot: __dirname,
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
export default nextConfig;
|
|
276
|
+
`;
|
|
277
|
+
const POSTCSS_CONFIG = `export default {
|
|
278
|
+
plugins: {
|
|
279
|
+
"@tailwindcss/postcss": {},
|
|
280
|
+
},
|
|
281
|
+
};
|
|
282
|
+
`;
|
|
283
|
+
const GITIGNORE = `node_modules
|
|
284
|
+
.next
|
|
285
|
+
.turbo
|
|
286
|
+
out
|
|
287
|
+
.env*.local
|
|
288
|
+
`;
|
|
289
|
+
const MINIMAL_GLOBALS_CSS = `@import "tailwindcss";
|
|
290
|
+
|
|
291
|
+
/*
|
|
292
|
+
* No src/app/globals.css was found at init time. This is a minimal
|
|
293
|
+
* Tailwind-v4 directives file. Add your project's tokens (CSS custom
|
|
294
|
+
* properties, @theme block) here so the mock matches production
|
|
295
|
+
* visually.
|
|
296
|
+
*
|
|
297
|
+
* Vibe + plate work best when this file mirrors production's tokens
|
|
298
|
+
* exactly — they steer toward existing token names, so the better the
|
|
299
|
+
* token coverage here the cleaner their output.
|
|
300
|
+
*/
|
|
301
|
+
|
|
302
|
+
:root {
|
|
303
|
+
--background: #ffffff;
|
|
304
|
+
--foreground: #1a1a1a;
|
|
305
|
+
--card-bg: #ffffff;
|
|
306
|
+
--card-border: rgba(26, 26, 26, 0.06);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
@media (prefers-color-scheme: dark) {
|
|
310
|
+
:root {
|
|
311
|
+
--background: #0f0f18;
|
|
312
|
+
--foreground: #e8e8f0;
|
|
313
|
+
--card-bg: rgba(255, 255, 255, 0.03);
|
|
314
|
+
--card-border: rgba(255, 255, 255, 0.06);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
@theme inline {
|
|
319
|
+
--color-background: var(--background);
|
|
320
|
+
--color-foreground: var(--foreground);
|
|
321
|
+
--color-card-bg: var(--card-bg);
|
|
322
|
+
--color-card-border: var(--card-border);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
body {
|
|
326
|
+
background: var(--background);
|
|
327
|
+
color: var(--foreground);
|
|
328
|
+
}
|
|
329
|
+
`;
|
|
330
|
+
const LAYOUT_TSX = `import type { Metadata } from "next";
|
|
331
|
+
import type { ReactNode } from "react";
|
|
332
|
+
import { ScenarioRegistryProvider } from "@slowcook-ai/mock-runtime";
|
|
333
|
+
import { registry } from "@/lib/scenario-registry";
|
|
334
|
+
import "./globals.css";
|
|
335
|
+
|
|
336
|
+
export const metadata: Metadata = {
|
|
337
|
+
title: "mock",
|
|
338
|
+
description: "Singular mock app. Each ?scenario=story-N renders the UI with that story's fixture data.",
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
export default function RootLayout({ children }: { children: ReactNode }) {
|
|
342
|
+
return (
|
|
343
|
+
<html lang="en">
|
|
344
|
+
<body className="bg-background text-foreground antialiased">
|
|
345
|
+
<ScenarioRegistryProvider registry={registry}>
|
|
346
|
+
{children}
|
|
347
|
+
{/*
|
|
348
|
+
Review-overlay mount-point.
|
|
349
|
+
npm install @slowcook-ai/review-overlay
|
|
350
|
+
import { SlowcookReviewOverlay } from "@slowcook-ai/review-overlay/react";
|
|
351
|
+
<SlowcookReviewOverlay
|
|
352
|
+
enabled={process.env["NEXT_PUBLIC_SLOWCOOK_REVIEW"] === "1"}
|
|
353
|
+
owner={process.env["NEXT_PUBLIC_SLOWCOOK_OWNER"] ?? ""}
|
|
354
|
+
repo={process.env["NEXT_PUBLIC_SLOWCOOK_REPO"] ?? ""}
|
|
355
|
+
prNumber={parseInt(process.env["NEXT_PUBLIC_SLOWCOOK_PR_NUMBER"] ?? "0", 10)}
|
|
356
|
+
storyId={process.env["NEXT_PUBLIC_SLOWCOOK_STORY_ID"] ?? null}
|
|
357
|
+
/>
|
|
358
|
+
Slowcook's preview-deploy workflow sets the env vars from the PR
|
|
359
|
+
context. Production builds keep NEXT_PUBLIC_SLOWCOOK_REVIEW unset
|
|
360
|
+
so the overlay tree-shakes out.
|
|
361
|
+
*/}
|
|
362
|
+
</ScenarioRegistryProvider>
|
|
363
|
+
</body>
|
|
364
|
+
</html>
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
`;
|
|
368
|
+
const PAGE_TSX = `import { ScenarioPicker } from "@slowcook-ai/mock-runtime";
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Mock app homepage = scenario picker (provided by the runtime).
|
|
372
|
+
*
|
|
373
|
+
* Replaces this with a custom picker if you want different grouping/
|
|
374
|
+
* filtering. The runtime's hooks + registry API are stable; this UI
|
|
375
|
+
* is a default that consumers can swap.
|
|
376
|
+
*/
|
|
377
|
+
export default function Page() {
|
|
378
|
+
return <ScenarioPicker />;
|
|
379
|
+
}
|
|
380
|
+
`;
|
|
381
|
+
const SCENARIO_REGISTRY = `import { defineScenarios } from "@slowcook-ai/mock-runtime";
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* The consumer-owned scenario registry.
|
|
385
|
+
*
|
|
386
|
+
* Vibe extends this when it adds a new scenario:
|
|
387
|
+
* - one new \`import\` line for the scenario file
|
|
388
|
+
* - one new entry in the \`defineScenarios([...])\` array
|
|
389
|
+
*
|
|
390
|
+
* Hand-edits are fine too — vibe + plate respect existing entries
|
|
391
|
+
* and only append.
|
|
392
|
+
*/
|
|
393
|
+
|
|
394
|
+
// Vibe-managed imports below this line. Don't reorder; vibe inserts
|
|
395
|
+
// new lines at the bottom of the import block.
|
|
396
|
+
// e.g. import story017 from "../../scenarios/story-017.js";
|
|
397
|
+
|
|
398
|
+
export const registry = defineScenarios([
|
|
399
|
+
// story017,
|
|
400
|
+
]);
|
|
401
|
+
`;
|
|
402
|
+
const README = `# \`mock/\` — singular UI mock app
|
|
403
|
+
|
|
404
|
+
Per-consumer mock app, scaffolded by \`slowcook init mock\`. The runtime
|
|
405
|
+
(scenario types + hooks + picker UI) ships via \`@slowcook-ai/mock-runtime\`;
|
|
406
|
+
the bits in this directory are the consumer-owned shell.
|
|
407
|
+
|
|
408
|
+
## Run it
|
|
409
|
+
|
|
410
|
+
\`\`\`bash
|
|
411
|
+
cd mock
|
|
412
|
+
npm install
|
|
413
|
+
npm run dev
|
|
414
|
+
# → http://localhost:3100
|
|
415
|
+
\`\`\`
|
|
416
|
+
|
|
417
|
+
The homepage is the **scenario picker**. Each scenario maps to one
|
|
418
|
+
story (or one flow within a story) — clicking a scenario navigates to
|
|
419
|
+
that story's preferred initial path with \`?scenario=story-N\` set.
|
|
420
|
+
|
|
421
|
+
## Architecture in one paragraph
|
|
422
|
+
|
|
423
|
+
The mock is the **design contract**. Vibe writes scenarios for each
|
|
424
|
+
story (\`mock/scenarios/story-N.ts\`); plate amends per PM feedback;
|
|
425
|
+
PM reviews via the live mock URL on the consumer's box. After PM
|
|
426
|
+
approves, brew copies the mock's components into \`src/\` and adds the
|
|
427
|
+
real-data wiring. The mock + production stay in two separate
|
|
428
|
+
filesystems; mock never touches \`src/\`, brew never touches \`mock/\`.
|
|
429
|
+
|
|
430
|
+
The mock has NO backend. Scenarios are plain TypeScript modules read
|
|
431
|
+
by React hooks. Mutations are local component state — they reset on
|
|
432
|
+
page reload, which is the right behavior for a mockup (PM either keeps
|
|
433
|
+
clicking or refreshes to start over).
|
|
434
|
+
|
|
435
|
+
## Add a scenario by hand
|
|
436
|
+
|
|
437
|
+
\`\`\`ts
|
|
438
|
+
// mock/scenarios/story-017.ts
|
|
439
|
+
import type { Scenario } from "@slowcook-ai/mock-runtime";
|
|
440
|
+
|
|
441
|
+
const scenario: Scenario = {
|
|
442
|
+
id: "017",
|
|
443
|
+
name: "Owner with 3 pins, 8 reactions",
|
|
444
|
+
user: { id: "amin", handle: "amin", display_name: "Amin Azar" },
|
|
445
|
+
initialPath: "/u/amin",
|
|
446
|
+
fixtures: {
|
|
447
|
+
pins: [/* ... */],
|
|
448
|
+
reactions: [/* ... */],
|
|
449
|
+
},
|
|
450
|
+
expectedInteractions: [
|
|
451
|
+
"Click Pin on first reaction → strip prepends",
|
|
452
|
+
"Click Pinned on strip card → strip removes; reaction's Pin re-enables",
|
|
453
|
+
],
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
export default scenario;
|
|
457
|
+
\`\`\`
|
|
458
|
+
|
|
459
|
+
Then add to the registry in \`mock/src/lib/scenario-registry.ts\`:
|
|
460
|
+
|
|
461
|
+
\`\`\`ts
|
|
462
|
+
import { defineScenarios } from "@slowcook-ai/mock-runtime";
|
|
463
|
+
import story017 from "../../scenarios/story-017.js";
|
|
464
|
+
|
|
465
|
+
export const registry = defineScenarios([story017]);
|
|
466
|
+
\`\`\`
|
|
467
|
+
|
|
468
|
+
Refresh the dev server — the scenario appears in the picker.
|
|
469
|
+
|
|
470
|
+
## Use scenario data in a component
|
|
471
|
+
|
|
472
|
+
\`\`\`tsx
|
|
473
|
+
"use client";
|
|
474
|
+
import { useScenarioFixture } from "@slowcook-ai/mock-runtime";
|
|
475
|
+
|
|
476
|
+
interface Pin { id: string; rewo_id: string; pinned_at: string; }
|
|
477
|
+
|
|
478
|
+
export function PinsStrip() {
|
|
479
|
+
const pins = useScenarioFixture<Pin[]>("pins");
|
|
480
|
+
return <div>{pins.map(p => /* ... */)}</div>;
|
|
481
|
+
}
|
|
482
|
+
\`\`\`
|
|
483
|
+
|
|
484
|
+
The hook is a typed accessor over \`useScenario().fixtures[domain]\`.
|
|
485
|
+
It throws a clear error in dev when the scenario doesn't have that
|
|
486
|
+
domain populated.
|
|
487
|
+
|
|
488
|
+
## Roadmap
|
|
489
|
+
|
|
490
|
+
- \`@slowcook-ai/review-overlay\` package (slowcook 0.16-α.5) — adds
|
|
491
|
+
a floating toggle for nav-mode ↔ comment-mode; comments post to
|
|
492
|
+
the mockup PR with element selector + screenshot + viewport metadata
|
|
493
|
+
- \`slowcook preview deploy\` (0.16-α.4) — SSH-deploys the docker
|
|
494
|
+
build to the consumer's box; preview URL posted to PR
|
|
495
|
+
- \`slowcook port\` (0.16-α.7) — deterministic copy of mock components
|
|
496
|
+
→ \`src/\` (mock + production stay separate filesystems)
|
|
497
|
+
- Vibe + plate v2 (0.16-α.3 / α.6) — populate this directory based
|
|
498
|
+
on spec + PM feedback
|
|
499
|
+
`;
|
|
500
|
+
//# sourceMappingURL=mock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock.js","sourceRoot":"","sources":["../../../src/commands/init/mock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PM-comment classifier — 0.16.0-α.7.
|
|
3
|
+
*
|
|
4
|
+
* Each element-anchored review-overlay comment on a slowcook-mockup PR
|
|
5
|
+
* gets categorized so plate knows what to do with it:
|
|
6
|
+
*
|
|
7
|
+
* - "cosmetic" → amend the mock with minimum diff
|
|
8
|
+
* - "spec-altering" → ESCALATE: would invalidate a spec assertion or
|
|
9
|
+
* acceptance scenario; PM must confirm the spec
|
|
10
|
+
* change before plate touches the mock
|
|
11
|
+
* - "mock-divergence" → the mock diverged from the spec; align mock
|
|
12
|
+
* to spec; note in summary why the PM ask is
|
|
13
|
+
* being interpreted this way
|
|
14
|
+
*
|
|
15
|
+
* α.7 ships a deterministic heuristic. Each classification has a clear
|
|
16
|
+
* rationale string so the escalation comment can quote the trigger.
|
|
17
|
+
*
|
|
18
|
+
* Heuristic structure:
|
|
19
|
+
* 1. Parse the spec YAML to extract the salient assertion targets:
|
|
20
|
+
* - acceptance_scenarios prose lines
|
|
21
|
+
* - api_contract response field names
|
|
22
|
+
* - invariants prose
|
|
23
|
+
* - ui_behavior viewport prose
|
|
24
|
+
* → a flat set of "spec terms" (lowercased, normalized words).
|
|
25
|
+
* 2. Score the comment prose against those terms:
|
|
26
|
+
* - any direct mention of an acceptance keyword phrase → spec-altering
|
|
27
|
+
* - mention of a domain noun + a "remove/change/replace" → spec-altering
|
|
28
|
+
* - mentions only adjective/style words (color, padding, → cosmetic
|
|
29
|
+
* font, spacing, alignment, shadow, etc.)
|
|
30
|
+
* - else → mock-divergence
|
|
31
|
+
*
|
|
32
|
+
* The heuristic is intentionally conservative on spec-altering: false
|
|
33
|
+
* positives only cost a PM confirm round; false negatives let plate
|
|
34
|
+
* silently weaken the spec, which is the failure mode the architecture
|
|
35
|
+
* is designed to prevent. When in doubt → escalate.
|
|
36
|
+
*
|
|
37
|
+
* No LLM dep here — pure functions over inputs. LLM-backed classifier
|
|
38
|
+
* is a future α.7.1 upgrade if heuristic shows real misses.
|
|
39
|
+
*/
|
|
40
|
+
export type Classification = "cosmetic" | "spec-altering" | "mock-divergence";
|
|
41
|
+
export interface ClassifyResult {
|
|
42
|
+
classification: Classification;
|
|
43
|
+
/** Why this classification — included verbatim in escalation comments. */
|
|
44
|
+
rationale: string;
|
|
45
|
+
/** The spec terms (if any) that matched in the comment prose. */
|
|
46
|
+
matchedSpecTerms: string[];
|
|
47
|
+
}
|
|
48
|
+
export interface ClassifyArgs {
|
|
49
|
+
/** Free prose written by the PM in the review-overlay comment. */
|
|
50
|
+
prose: string;
|
|
51
|
+
/**
|
|
52
|
+
* Spec YAML body. Hand-parsed for the assertion targets; we don't
|
|
53
|
+
* need a full YAML parser since the heuristic only needs salient
|
|
54
|
+
* words from acceptance_scenarios / invariants / api_contract.
|
|
55
|
+
*/
|
|
56
|
+
specYaml: string;
|
|
57
|
+
}
|
|
58
|
+
export declare function classifyComment(args: ClassifyArgs): ClassifyResult;
|
|
59
|
+
/**
|
|
60
|
+
* Extract candidate "spec terms" — lowercase, deduplicated significant
|
|
61
|
+
* tokens from the spec sections plate cares about. Used by the
|
|
62
|
+
* classifier to detect overlap between PM prose and spec assertions.
|
|
63
|
+
*/
|
|
64
|
+
export declare function extractSpecTerms(specYaml: string): string[];
|
|
65
|
+
//# sourceMappingURL=classify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../../src/commands/plate/classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,eAAe,GAAG,iBAAiB,CAAC;AAE9E,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,cAAc,CAAC;IAC/B,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAyBD,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,CAgElE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAe3D"}
|