@slowcook-ai/cli 0.19.0-alpha.18 → 0.19.0-alpha.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/cli.js +28 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/brand/index.d.ts +58 -0
  4. package/dist/commands/brand/index.d.ts.map +1 -0
  5. package/dist/commands/brand/index.js +257 -0
  6. package/dist/commands/brand/index.js.map +1 -0
  7. package/dist/commands/budget/index.d.ts +2 -0
  8. package/dist/commands/budget/index.d.ts.map +1 -0
  9. package/dist/commands/budget/index.js +252 -0
  10. package/dist/commands/budget/index.js.map +1 -0
  11. package/dist/commands/dev-env/config.d.ts +136 -0
  12. package/dist/commands/dev-env/config.d.ts.map +1 -0
  13. package/dist/commands/dev-env/config.js +96 -0
  14. package/dist/commands/dev-env/config.js.map +1 -0
  15. package/dist/commands/dev-env/index.d.ts +27 -0
  16. package/dist/commands/dev-env/index.d.ts.map +1 -0
  17. package/dist/commands/dev-env/index.js +226 -0
  18. package/dist/commands/dev-env/index.js.map +1 -0
  19. package/dist/commands/dev-env/init.d.ts +28 -0
  20. package/dist/commands/dev-env/init.d.ts.map +1 -0
  21. package/dist/commands/dev-env/init.js +135 -0
  22. package/dist/commands/dev-env/init.js.map +1 -0
  23. package/dist/commands/eval/index.d.ts.map +1 -1
  24. package/dist/commands/eval/index.js +15 -1
  25. package/dist/commands/eval/index.js.map +1 -1
  26. package/dist/commands/init/mock-vite.d.ts +54 -0
  27. package/dist/commands/init/mock-vite.d.ts.map +1 -0
  28. package/dist/commands/init/mock-vite.js +611 -0
  29. package/dist/commands/init/mock-vite.js.map +1 -0
  30. package/dist/commands/init/mock.d.ts +6 -0
  31. package/dist/commands/init/mock.d.ts.map +1 -1
  32. package/dist/commands/init/mock.js +20 -4
  33. package/dist/commands/init/mock.js.map +1 -1
  34. package/dist/commands/plate/agent.d.ts +7 -0
  35. package/dist/commands/plate/agent.d.ts.map +1 -1
  36. package/dist/commands/plate/agent.js +1 -1
  37. package/dist/commands/plate/agent.js.map +1 -1
  38. package/dist/commands/plate/index.d.ts.map +1 -1
  39. package/dist/commands/plate/index.js +6 -0
  40. package/dist/commands/plate/index.js.map +1 -1
  41. package/dist/commands/refine/agent.d.ts +12 -0
  42. package/dist/commands/refine/agent.d.ts.map +1 -1
  43. package/dist/commands/refine/agent.js +173 -13
  44. package/dist/commands/refine/agent.js.map +1 -1
  45. package/dist/commands/refine/brownfield-answer.d.ts +81 -0
  46. package/dist/commands/refine/brownfield-answer.d.ts.map +1 -0
  47. package/dist/commands/refine/brownfield-answer.js +231 -0
  48. package/dist/commands/refine/brownfield-answer.js.map +1 -0
  49. package/dist/commands/refine/context.d.ts.map +1 -1
  50. package/dist/commands/refine/context.js +18 -0
  51. package/dist/commands/refine/context.js.map +1 -1
  52. package/dist/commands/refine/history-index.d.ts +29 -0
  53. package/dist/commands/refine/history-index.d.ts.map +1 -1
  54. package/dist/commands/refine/history-index.js +63 -0
  55. package/dist/commands/refine/history-index.js.map +1 -1
  56. package/dist/commands/refine/index.d.ts.map +1 -1
  57. package/dist/commands/refine/index.js +32 -1
  58. package/dist/commands/refine/index.js.map +1 -1
  59. package/dist/commands/refine/proposals-synth.d.ts +50 -1
  60. package/dist/commands/refine/proposals-synth.d.ts.map +1 -1
  61. package/dist/commands/refine/proposals-synth.js +199 -35
  62. package/dist/commands/refine/proposals-synth.js.map +1 -1
  63. package/dist/commands/refine/spec-yaml.d.ts +274 -250
  64. package/dist/commands/refine/spec-yaml.d.ts.map +1 -1
  65. package/dist/commands/refine/spec-yaml.js +10 -0
  66. package/dist/commands/refine/spec-yaml.js.map +1 -1
  67. package/dist/commands/run-mock/index.d.ts.map +1 -1
  68. package/dist/commands/run-mock/index.js +7 -1
  69. package/dist/commands/run-mock/index.js.map +1 -1
  70. package/dist/commands/testgen/agent.d.ts.map +1 -1
  71. package/dist/commands/testgen/agent.js +34 -9
  72. package/dist/commands/testgen/agent.js.map +1 -1
  73. package/dist/commands/vibe/agent.d.ts +7 -0
  74. package/dist/commands/vibe/agent.d.ts.map +1 -1
  75. package/dist/commands/vibe/agent.js +2 -2
  76. package/dist/commands/vibe/agent.js.map +1 -1
  77. package/dist/commands/vibe/index.d.ts.map +1 -1
  78. package/dist/commands/vibe/index.js +7 -1
  79. package/dist/commands/vibe/index.js.map +1 -1
  80. package/dist/cost-store.d.ts +52 -0
  81. package/dist/cost-store.d.ts.map +1 -0
  82. package/dist/cost-store.js +108 -0
  83. package/dist/cost-store.js.map +1 -0
  84. package/dist/lib/budget.d.ts +123 -0
  85. package/dist/lib/budget.d.ts.map +1 -0
  86. package/dist/lib/budget.js +225 -0
  87. package/dist/lib/budget.js.map +1 -0
  88. package/dist/lib/mock-shape.d.ts +44 -0
  89. package/dist/lib/mock-shape.d.ts.map +1 -0
  90. package/dist/lib/mock-shape.js +77 -0
  91. package/dist/lib/mock-shape.js.map +1 -0
  92. package/package.json +4 -4
@@ -0,0 +1,252 @@
1
+ /**
2
+ * 0.19.0-α.35 (sc#66 follow-up) — `slowcook budget` subcommand.
3
+ *
4
+ * slowcook budget # show config + month-to-date spend
5
+ * slowcook budget set --monthly 50 # set monthly_budget_usd
6
+ * slowcook budget set --monthly 50 --start-day 15 --story 10
7
+ * slowcook budget rm # delete config (disables gauge)
8
+ *
9
+ * Writes/reads `.brewing/budget.yaml`. Idempotent: `set` merges into
10
+ * existing config; absent flags keep their current values; missing
11
+ * monthly_budget_usd on a brand-new config defaults nothing (must be
12
+ * supplied at least once).
13
+ */
14
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
15
+ import { join } from "node:path";
16
+ import YAML from "yaml";
17
+ import { loadBudgetConfig, aggregateMonthSpend, aggregateSpendSince, currentPeriodStart, classifyBudgetStatus, } from "../../lib/budget.js";
18
+ function parseArgs(argv) {
19
+ const args = { cwd: process.cwd(), action: "show" };
20
+ const positional = [];
21
+ for (let i = 0; i < argv.length; i++) {
22
+ const arg = argv[i];
23
+ const next = argv[i + 1];
24
+ if (arg === "--cwd" && next) {
25
+ args.cwd = next;
26
+ i++;
27
+ }
28
+ else if (arg === "--monthly" && next) {
29
+ args.monthly = Number(next);
30
+ i++;
31
+ }
32
+ else if (arg === "--start-day" && next) {
33
+ args.startDay = Number(next);
34
+ i++;
35
+ }
36
+ else if (arg === "--story" && next) {
37
+ args.story = Number(next);
38
+ i++;
39
+ }
40
+ else if (arg === "--credit" && next) {
41
+ args.credit = Number(next);
42
+ i++;
43
+ }
44
+ else if (arg === "--credit-baseline" && next) {
45
+ args.creditBaselineAt = next;
46
+ i++;
47
+ }
48
+ else if (arg === "--help" || arg === "-h") {
49
+ printHelp();
50
+ process.exit(0);
51
+ }
52
+ else if (arg && !arg.startsWith("--")) {
53
+ positional.push(arg);
54
+ }
55
+ }
56
+ const verb = positional[0];
57
+ if (verb === "set" || verb === "rm")
58
+ args.action = verb;
59
+ else if (verb && verb !== "show") {
60
+ throw new Error(`Unknown budget action: ${verb}. Use show | set | rm.`);
61
+ }
62
+ return args;
63
+ }
64
+ function printHelp() {
65
+ console.log(`
66
+ slowcook budget — manage the project budget(s) for the fuel gauge
67
+
68
+ Two independent gauges, both optional, both opt-in:
69
+
70
+ monthly_budget_usd A per-period cap that resets each month.
71
+ credit_balance_usd A non-recurring credit deposit (e.g. you topped
72
+ up $25 on Anthropic and DON'T have auto-recharge);
73
+ the gauge subtracts ALL-TIME spend from this.
74
+
75
+ Usage:
76
+ slowcook budget Show current config + spend
77
+ slowcook budget set --monthly <usd> Set the monthly cap
78
+ slowcook budget set --monthly 50 --start-day 15 Non-1st reset day
79
+ slowcook budget set --credit <usd> Track a one-shot deposit
80
+ slowcook budget set --story <usd> Optional per-story ceiling
81
+ slowcook budget rm Delete .brewing/budget.yaml
82
+
83
+ Flags:
84
+ --monthly <usd> Monthly budget in USD. Resets each period.
85
+ --start-day <1-31> Calendar day the monthly budget resets. Default 1.
86
+ --credit <usd> One-shot credit deposit. Captures the date of set as
87
+ a baseline; spend tracked from there. Re-run to top up.
88
+ --story <usd> Optional per-story informational ceiling.
89
+ --cwd <path> Project root. Defaults to current working dir.
90
+
91
+ When set, every refine comment appends:
92
+ ⛽ Project this month: $X of $Y (monthly cap)
93
+ 🪙 Anthropic credit: $X of $Y (credit balance)
94
+
95
+ Both fire ⚠️ at 80% and 🛑 at 95%.
96
+
97
+ Top-up workflow (no auto-recharge):
98
+ $ slowcook budget set --credit 25 # at the start of $25 deposit
99
+ ... burn through credit ...
100
+ $ slowcook budget set --credit 50 # after topping up to $50 (new baseline)
101
+ `);
102
+ }
103
+ function configPath(cwd) {
104
+ return join(cwd, ".brewing", "budget.yaml");
105
+ }
106
+ function fmtUsd(n) {
107
+ return `$${n.toFixed(2)}`;
108
+ }
109
+ export async function budget(argv) {
110
+ let parsed;
111
+ try {
112
+ parsed = parseArgs(argv);
113
+ }
114
+ catch (e) {
115
+ console.error(e.message);
116
+ process.exit(2);
117
+ }
118
+ if (parsed.action === "rm") {
119
+ const p = configPath(parsed.cwd);
120
+ if (!existsSync(p)) {
121
+ console.log(`No .brewing/budget.yaml — nothing to remove.`);
122
+ return;
123
+ }
124
+ unlinkSync(p);
125
+ console.log(`Removed ${p}. Fuel gauge now disabled.`);
126
+ return;
127
+ }
128
+ if (parsed.action === "set") {
129
+ // Merge into existing config; allow updating individual fields.
130
+ let existing = null;
131
+ try {
132
+ existing = loadBudgetConfig(parsed.cwd);
133
+ }
134
+ catch (e) {
135
+ console.error(`Existing config is invalid — fix or rm first: ${e.message}`);
136
+ process.exit(2);
137
+ }
138
+ const monthly = parsed.monthly ?? existing?.monthly_budget_usd;
139
+ if (monthly !== undefined && (!Number.isFinite(monthly) || monthly <= 0)) {
140
+ console.error(`--monthly must be a positive number, got ${parsed.monthly}`);
141
+ process.exit(2);
142
+ }
143
+ const startDay = parsed.startDay ?? existing?.monthly_start_day ?? 1;
144
+ if (!Number.isInteger(startDay) || startDay < 1 || startDay > 31) {
145
+ console.error(`--start-day must be an integer 1-31, got ${parsed.startDay}`);
146
+ process.exit(2);
147
+ }
148
+ const story = parsed.story ?? existing?.story_budget_usd;
149
+ if (story !== undefined && (!Number.isFinite(story) || story <= 0)) {
150
+ console.error(`--story must be a positive number, got ${parsed.story}`);
151
+ process.exit(2);
152
+ }
153
+ // Credit handling — a fresh --credit captures "now" as the
154
+ // baseline. Re-running --credit (top-up) refreshes the baseline so
155
+ // the gauge tracks ONLY spend from the new deposit forward.
156
+ let credit = existing?.credit_balance_usd;
157
+ let creditBaselineAt = existing?.credit_baseline_at;
158
+ if (parsed.credit !== undefined) {
159
+ if (!Number.isFinite(parsed.credit) || parsed.credit <= 0) {
160
+ console.error(`--credit must be a positive number, got ${parsed.credit}`);
161
+ process.exit(2);
162
+ }
163
+ credit = parsed.credit;
164
+ creditBaselineAt = parsed.creditBaselineAt ?? new Date().toISOString();
165
+ }
166
+ if (monthly === undefined && credit === undefined) {
167
+ console.error(`Set at least one of --monthly or --credit. Try: slowcook budget set --credit 25`);
168
+ process.exit(2);
169
+ }
170
+ const next = {
171
+ schema_version: 1,
172
+ monthly_start_day: startDay,
173
+ ...(monthly !== undefined ? { monthly_budget_usd: monthly } : {}),
174
+ ...(story !== undefined ? { story_budget_usd: story } : {}),
175
+ ...(credit !== undefined ? { credit_balance_usd: credit } : {}),
176
+ ...(creditBaselineAt !== undefined ? { credit_baseline_at: creditBaselineAt } : {}),
177
+ };
178
+ const p = configPath(parsed.cwd);
179
+ mkdirSync(join(parsed.cwd, ".brewing"), { recursive: true });
180
+ writeFileSync(p, YAML.stringify(next, { lineWidth: 0 }), "utf8");
181
+ const verb = existing ? "Updated" : "Wrote";
182
+ console.log(`${verb} ${p}`);
183
+ console.log(readFileSync(p, "utf8"));
184
+ return;
185
+ }
186
+ // show
187
+ let config;
188
+ try {
189
+ config = loadBudgetConfig(parsed.cwd);
190
+ }
191
+ catch (e) {
192
+ console.error(`Config at ${configPath(parsed.cwd)} is invalid: ${e.message}`);
193
+ process.exit(2);
194
+ }
195
+ if (!config) {
196
+ console.log(`No .brewing/budget.yaml — fuel gauge disabled.`);
197
+ console.log(`Set one with: slowcook budget set --credit 25 (one-shot deposit)`);
198
+ console.log(` or: slowcook budget set --monthly 50 (recurring cap)`);
199
+ return;
200
+ }
201
+ const now = new Date();
202
+ console.log(`Config: ${configPath(parsed.cwd)}`);
203
+ if (config.monthly_budget_usd !== undefined) {
204
+ console.log(` monthly_budget_usd: ${fmtUsd(config.monthly_budget_usd)}`);
205
+ console.log(` monthly_start_day: ${config.monthly_start_day}`);
206
+ }
207
+ if (config.story_budget_usd !== undefined) {
208
+ console.log(` story_budget_usd: ${fmtUsd(config.story_budget_usd)}`);
209
+ }
210
+ if (config.credit_balance_usd !== undefined) {
211
+ console.log(` credit_balance_usd: ${fmtUsd(config.credit_balance_usd)}`);
212
+ console.log(` credit_baseline_at: ${config.credit_baseline_at ?? "(unset)"}`);
213
+ }
214
+ console.log(``);
215
+ if (config.monthly_budget_usd !== undefined) {
216
+ const period = currentPeriodStart(config, now);
217
+ const spend = aggregateMonthSpend(parsed.cwd, config, now);
218
+ const status = classifyBudgetStatus(spend.usd, config.monthly_budget_usd);
219
+ const pct = Math.round((spend.usd / config.monthly_budget_usd) * 100);
220
+ const icon = status === "halt" ? "🛑" : status === "warn" ? "⚠️" : "⛽";
221
+ console.log(`Period start: ${period.toISOString().slice(0, 10)}`);
222
+ console.log(`${icon} Spent this period: ${fmtUsd(spend.usd)} of ${fmtUsd(config.monthly_budget_usd)} (${pct}%)`);
223
+ console.log(` ${spend.entryCount} entr${spend.entryCount === 1 ? "y" : "ies"} across ${spend.storyCount} stor${spend.storyCount === 1 ? "y" : "ies"}.`);
224
+ if (status === "warn") {
225
+ console.log(` ⚠️ approaching monthly budget — consider topping up.`);
226
+ }
227
+ else if (status === "halt") {
228
+ console.log(` 🛑 over budget — agents will halt without the override-budget label.`);
229
+ }
230
+ console.log(``);
231
+ }
232
+ if (config.credit_balance_usd !== undefined && config.credit_baseline_at) {
233
+ const baseline = new Date(config.credit_baseline_at);
234
+ const spend = aggregateSpendSince(parsed.cwd, baseline);
235
+ const status = classifyBudgetStatus(spend.usd, config.credit_balance_usd);
236
+ const remaining = Math.max(0, config.credit_balance_usd - spend.usd);
237
+ const pctLeft = Math.max(0, 100 - Math.round((spend.usd / config.credit_balance_usd) * 100));
238
+ const icon = status === "halt" ? "🛑" : status === "warn" ? "⚠️" : "🪙";
239
+ console.log(`Credit baseline: ${config.credit_baseline_at.slice(0, 10)}`);
240
+ console.log(`${icon} Anthropic credit: ${fmtUsd(remaining)} of ${fmtUsd(config.credit_balance_usd)} remaining (${pctLeft}%)`);
241
+ console.log(` Spent ${fmtUsd(spend.usd)} since baseline. ${spend.entryCount} entr${spend.entryCount === 1 ? "y" : "ies"}.`);
242
+ if (status === "warn") {
243
+ console.log(` ⚠️ approaching empty — top up at https://console.anthropic.com/settings/billing.`);
244
+ console.log(` Then: slowcook budget set --credit <new-total> # captures fresh baseline`);
245
+ }
246
+ else if (status === "halt") {
247
+ console.log(` 🛑 credit nearly exhausted — pipeline will halt on 402 imminently.`);
248
+ console.log(` Top up + re-run: slowcook budget set --credit <new-total>`);
249
+ }
250
+ }
251
+ }
252
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/budget/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * `.brewing/dev-env.yaml` config schema — Phase 2 of the dev-env
3
+ * upstreaming (delgoosh-first proof in Phase 1, generalised here).
4
+ *
5
+ * Consumers describe their dev env once: which apps run, in what
6
+ * mode (hot-reload vs production-shaped), which git branch the env
7
+ * mirrors (default `dev`), how seed data flows, and the optional SSH
8
+ * target if the env runs on a remote box.
9
+ *
10
+ * Then `slowcook dev-env <subcmd>` reads the file and acts. Today
11
+ * this Phase 2 cut ships only `push` end-to-end (the load-bearing
12
+ * operation for Phase 3 brew/plate wiring); `up`, `sync`, `switch`,
13
+ * `reset` ship as stubs that emit the canonical command shell for
14
+ * the consumer to wire into their workflow.
15
+ */
16
+ import { z } from "zod";
17
+ export declare const DEV_ENV_CONFIG_PATH = ".brewing/dev-env.yaml";
18
+ declare const AppModeSchema: z.ZodEnum<["dev", "start", "nest-watch", "static", "none"]>;
19
+ export declare const DevEnvConfigSchema: z.ZodObject<{
20
+ $schema: z.ZodOptional<z.ZodString>;
21
+ schema_version: z.ZodLiteral<1>;
22
+ /**
23
+ * The git branch the dev env always reads from. Force-pushable —
24
+ * agents shove story-branch heads here to preview them. Default:
25
+ * `dev`.
26
+ */
27
+ source_branch: z.ZodDefault<z.ZodString>;
28
+ /**
29
+ * Path (repo-relative) to the seed script. Run by `dev-env up` and
30
+ * `dev-env reset`. Must be idempotent on already-seeded data.
31
+ */
32
+ seed_script: z.ZodOptional<z.ZodString>;
33
+ /**
34
+ * Where the dev env physically runs. Omit for "local docker compose
35
+ * on the runner" semantics (rare); set for SSH-to-box deploys.
36
+ */
37
+ ssh_target: z.ZodOptional<z.ZodObject<{
38
+ host: z.ZodString;
39
+ user: z.ZodString;
40
+ /** Absolute path on the box where the consumer's checkout lives. */
41
+ checkout_dir: z.ZodString;
42
+ /** Repo secret name holding the SSH private key. */
43
+ key_secret: z.ZodDefault<z.ZodString>;
44
+ }, "strip", z.ZodTypeAny, {
45
+ host: string;
46
+ user: string;
47
+ checkout_dir: string;
48
+ key_secret: string;
49
+ }, {
50
+ host: string;
51
+ user: string;
52
+ checkout_dir: string;
53
+ key_secret?: string | undefined;
54
+ }>>;
55
+ persistence: z.ZodDefault<z.ZodOptional<z.ZodObject<{
56
+ /**
57
+ * Named docker volume that survives `dev-env reset`. PM-added DB
58
+ * rows persist across redeploys; only the seed-owned rows are
59
+ * touched by reset.
60
+ */
61
+ db_volume: z.ZodOptional<z.ZodString>;
62
+ /** Named volume for uploaded user files / object storage. */
63
+ uploads_volume: z.ZodOptional<z.ZodString>;
64
+ }, "strip", z.ZodTypeAny, {
65
+ db_volume?: string | undefined;
66
+ uploads_volume?: string | undefined;
67
+ }, {
68
+ db_volume?: string | undefined;
69
+ uploads_volume?: string | undefined;
70
+ }>>>;
71
+ apps: z.ZodRecord<z.ZodString, z.ZodObject<{
72
+ mode: z.ZodEnum<["dev", "start", "nest-watch", "static", "none"]>;
73
+ port: z.ZodNumber;
74
+ /** Restart on crash. Defaults to true. */
75
+ autoheal: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
76
+ /** Optional: explicit container/process name override (otherwise the key). */
77
+ container: z.ZodOptional<z.ZodString>;
78
+ }, "strip", z.ZodTypeAny, {
79
+ mode: "dev" | "start" | "nest-watch" | "static" | "none";
80
+ port: number;
81
+ autoheal: boolean;
82
+ container?: string | undefined;
83
+ }, {
84
+ mode: "dev" | "start" | "nest-watch" | "static" | "none";
85
+ port: number;
86
+ autoheal?: boolean | undefined;
87
+ container?: string | undefined;
88
+ }>>;
89
+ }, "strip", z.ZodTypeAny, {
90
+ schema_version: 1;
91
+ source_branch: string;
92
+ persistence: {
93
+ db_volume?: string | undefined;
94
+ uploads_volume?: string | undefined;
95
+ };
96
+ apps: Record<string, {
97
+ mode: "dev" | "start" | "nest-watch" | "static" | "none";
98
+ port: number;
99
+ autoheal: boolean;
100
+ container?: string | undefined;
101
+ }>;
102
+ $schema?: string | undefined;
103
+ seed_script?: string | undefined;
104
+ ssh_target?: {
105
+ host: string;
106
+ user: string;
107
+ checkout_dir: string;
108
+ key_secret: string;
109
+ } | undefined;
110
+ }, {
111
+ schema_version: 1;
112
+ apps: Record<string, {
113
+ mode: "dev" | "start" | "nest-watch" | "static" | "none";
114
+ port: number;
115
+ autoheal?: boolean | undefined;
116
+ container?: string | undefined;
117
+ }>;
118
+ $schema?: string | undefined;
119
+ source_branch?: string | undefined;
120
+ seed_script?: string | undefined;
121
+ ssh_target?: {
122
+ host: string;
123
+ user: string;
124
+ checkout_dir: string;
125
+ key_secret?: string | undefined;
126
+ } | undefined;
127
+ persistence?: {
128
+ db_volume?: string | undefined;
129
+ uploads_volume?: string | undefined;
130
+ } | undefined;
131
+ }>;
132
+ export type DevEnvConfig = z.infer<typeof DevEnvConfigSchema>;
133
+ export type AppMode = z.infer<typeof AppModeSchema>;
134
+ export declare function loadDevEnvConfig(repoRoot: string): DevEnvConfig;
135
+ export {};
136
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/commands/dev-env/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,mBAAmB,0BAA0B,CAAC;AAE3D,QAAA,MAAM,aAAa,6DAMjB,CAAC;AA+BH,eAAO,MAAM,kBAAkB;;;IAG7B;;;;OAIG;;IAEH;;;OAGG;;IAEH;;;OAGG;;;;QAvBH,oEAAoE;;QAEpE,oDAAoD;;;;;;;;;;;;;;QAfpD;;;;WAIG;;QAEH,6DAA6D;;;;;;;;;;;;QAb7D,0CAA0C;;QAE1C,8EAA8E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6C9E,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAwB/D"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * `.brewing/dev-env.yaml` config schema — Phase 2 of the dev-env
3
+ * upstreaming (delgoosh-first proof in Phase 1, generalised here).
4
+ *
5
+ * Consumers describe their dev env once: which apps run, in what
6
+ * mode (hot-reload vs production-shaped), which git branch the env
7
+ * mirrors (default `dev`), how seed data flows, and the optional SSH
8
+ * target if the env runs on a remote box.
9
+ *
10
+ * Then `slowcook dev-env <subcmd>` reads the file and acts. Today
11
+ * this Phase 2 cut ships only `push` end-to-end (the load-bearing
12
+ * operation for Phase 3 brew/plate wiring); `up`, `sync`, `switch`,
13
+ * `reset` ship as stubs that emit the canonical command shell for
14
+ * the consumer to wire into their workflow.
15
+ */
16
+ import { z } from "zod";
17
+ import { existsSync, readFileSync } from "node:fs";
18
+ import { join } from "node:path";
19
+ import YAML from "yaml";
20
+ export const DEV_ENV_CONFIG_PATH = ".brewing/dev-env.yaml";
21
+ const AppModeSchema = z.enum([
22
+ "dev", // Next dev (hot reload) — for apps under active story development
23
+ "start", // next build + next start — production-shaped, slower restart
24
+ "nest-watch", // ts-node-dev / nest start --watch — backend hot reload
25
+ "static", // serve a built static export, never re-run
26
+ "none", // entry exists but isn't started by `dev-env up` (e.g. cron)
27
+ ]);
28
+ const AppSchema = z.object({
29
+ mode: AppModeSchema,
30
+ port: z.number().int().positive(),
31
+ /** Restart on crash. Defaults to true. */
32
+ autoheal: z.boolean().optional().default(true),
33
+ /** Optional: explicit container/process name override (otherwise the key). */
34
+ container: z.string().optional(),
35
+ });
36
+ const PersistenceSchema = z.object({
37
+ /**
38
+ * Named docker volume that survives `dev-env reset`. PM-added DB
39
+ * rows persist across redeploys; only the seed-owned rows are
40
+ * touched by reset.
41
+ */
42
+ db_volume: z.string().optional(),
43
+ /** Named volume for uploaded user files / object storage. */
44
+ uploads_volume: z.string().optional(),
45
+ });
46
+ const SshTargetSchema = z.object({
47
+ host: z.string(),
48
+ user: z.string(),
49
+ /** Absolute path on the box where the consumer's checkout lives. */
50
+ checkout_dir: z.string(),
51
+ /** Repo secret name holding the SSH private key. */
52
+ key_secret: z.string().default("DEV_DEPLOY_SSH_KEY"),
53
+ });
54
+ export const DevEnvConfigSchema = z.object({
55
+ $schema: z.string().optional(),
56
+ schema_version: z.literal(1),
57
+ /**
58
+ * The git branch the dev env always reads from. Force-pushable —
59
+ * agents shove story-branch heads here to preview them. Default:
60
+ * `dev`.
61
+ */
62
+ source_branch: z.string().default("dev"),
63
+ /**
64
+ * Path (repo-relative) to the seed script. Run by `dev-env up` and
65
+ * `dev-env reset`. Must be idempotent on already-seeded data.
66
+ */
67
+ seed_script: z.string().optional(),
68
+ /**
69
+ * Where the dev env physically runs. Omit for "local docker compose
70
+ * on the runner" semantics (rare); set for SSH-to-box deploys.
71
+ */
72
+ ssh_target: SshTargetSchema.optional(),
73
+ persistence: PersistenceSchema.optional().default({}),
74
+ apps: z.record(z.string(), AppSchema),
75
+ });
76
+ export function loadDevEnvConfig(repoRoot) {
77
+ const path = join(repoRoot, DEV_ENV_CONFIG_PATH);
78
+ if (!existsSync(path)) {
79
+ throw new Error(`${DEV_ENV_CONFIG_PATH} not found. Run \`slowcook dev-env init\` to scaffold.`);
80
+ }
81
+ let raw;
82
+ try {
83
+ raw = YAML.parse(readFileSync(path, "utf8"));
84
+ }
85
+ catch (e) {
86
+ throw new Error(`${DEV_ENV_CONFIG_PATH} is not valid YAML: ${e.message}`);
87
+ }
88
+ const parsed = DevEnvConfigSchema.safeParse(raw);
89
+ if (!parsed.success) {
90
+ throw new Error(`${DEV_ENV_CONFIG_PATH} failed validation: ${parsed.error.issues
91
+ .map((i) => `${i.path.join(".")}: ${i.message}`)
92
+ .join("; ")}`);
93
+ }
94
+ return parsed.data;
95
+ }
96
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/commands/dev-env/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `slowcook dev-env <subcmd>` — manages the consumer's long-lived
3
+ * dev/preview environment. Phase 2 of the dev-env design.
4
+ *
5
+ * Subcommands:
6
+ *
7
+ * push --story <id> [--branch <name>]
8
+ * Force-push the current branch (or --branch) to the configured
9
+ * `source_branch` (default: `dev`). Agents (brew, plate) invoke
10
+ * this to preview their story-branch on the shared dev URL.
11
+ * Phase 3 wires this into brew/plate workflows automatically.
12
+ *
13
+ * switch --story <id>
14
+ * Locate the PR for story <id>, force-push its HEAD to
15
+ * `source_branch`. Operator-driven version of `push`.
16
+ *
17
+ * up | sync | reset
18
+ * Phase 2 stubs — print the canonical shell-out for the consumer
19
+ * to wire into their dev-deploy workflow. Phase 2.1 fills in the
20
+ * SSH-driven runtime path.
21
+ *
22
+ * init
23
+ * Phase 2.1 stub — scaffold `.brewing/dev-env.yaml` from detected
24
+ * apps. Not implemented yet; consumers hand-author for now.
25
+ */
26
+ export declare function devEnv(argv: string[]): Promise<void>;
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/dev-env/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAuEH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyC1D"}