@slowcook-ai/cli 0.19.0-alpha.1 → 0.19.0-alpha.8
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/dist/cli.js +27 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/brew/agent.d.ts +129 -0
- package/dist/commands/brew/agent.d.ts.map +1 -1
- package/dist/commands/brew/agent.js +132 -0
- package/dist/commands/brew/agent.js.map +1 -1
- package/dist/commands/chef/orchestrate.d.ts +34 -0
- package/dist/commands/chef/orchestrate.d.ts.map +1 -0
- package/dist/commands/chef/orchestrate.js +385 -0
- package/dist/commands/chef/orchestrate.js.map +1 -0
- package/dist/commands/init/mock.d.ts +46 -0
- package/dist/commands/init/mock.d.ts.map +1 -1
- package/dist/commands/init/mock.js +142 -2
- package/dist/commands/init/mock.js.map +1 -1
- package/dist/commands/recon/index.d.ts.map +1 -1
- package/dist/commands/recon/index.js +108 -5
- package/dist/commands/recon/index.js.map +1 -1
- package/dist/commands/recon/reuse.d.ts +118 -0
- package/dist/commands/recon/reuse.d.ts.map +1 -0
- package/dist/commands/recon/reuse.js +269 -0
- package/dist/commands/recon/reuse.js.map +1 -0
- package/dist/commands/recon/shape-preserve.d.ts +46 -0
- package/dist/commands/recon/shape-preserve.d.ts.map +1 -1
- package/dist/commands/recon/shape-preserve.js +126 -0
- package/dist/commands/recon/shape-preserve.js.map +1 -1
- package/dist/commands/refactor/index.d.ts +15 -0
- package/dist/commands/refactor/index.d.ts.map +1 -0
- package/dist/commands/refactor/index.js +126 -0
- package/dist/commands/refactor/index.js.map +1 -0
- package/dist/commands/refactor/score.d.ts +38 -0
- package/dist/commands/refactor/score.d.ts.map +1 -0
- package/dist/commands/refactor/score.js +79 -0
- package/dist/commands/refactor/score.js.map +1 -0
- package/dist/commands/refactor/types.d.ts +64 -0
- package/dist/commands/refactor/types.d.ts.map +1 -0
- package/dist/commands/refactor/types.js +26 -0
- package/dist/commands/refactor/types.js.map +1 -0
- package/package.json +5 -5
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `slowcook chef-orchestrate` — α.10 L3 cross-pipeline orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Sibling to chef-drift. Where chef-drift edits source files, chef-
|
|
5
|
+
* orchestrate decides what to do with a HALTED PR: re-dispatch brew,
|
|
6
|
+
* rebase against main, escalate to PM, or close. Reads the chef-drift
|
|
7
|
+
* ledger (so it knows what's already been tried) plus PR state, spec,
|
|
8
|
+
* navigator history, open PRs.
|
|
9
|
+
*
|
|
10
|
+
* Hard execution today (cli α.10 L3 α.0):
|
|
11
|
+
* - escalate → posts comment + applies label (real)
|
|
12
|
+
* - close → posts comment + closes PR (real)
|
|
13
|
+
* - rebase → writes verdict to disk; auto-resolution lands in α.10.X
|
|
14
|
+
* - redispatch_brew → writes verdict to disk; auto-dispatch lands in α.10.X
|
|
15
|
+
*
|
|
16
|
+
* Run from consumer repo root:
|
|
17
|
+
* ANTHROPIC_API_KEY=... GITHUB_TOKEN=... slowcook chef-orchestrate \
|
|
18
|
+
* --pr 153 \
|
|
19
|
+
* --story 018
|
|
20
|
+
*/
|
|
21
|
+
import { execSync } from "node:child_process";
|
|
22
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
23
|
+
import { dirname, join } from "node:path";
|
|
24
|
+
import { AnthropicClient, CHEF_ORCHESTRATE_SYSTEM, buildChefOrchestratePrompt, } from "@slowcook-ai/llm-anthropic";
|
|
25
|
+
function parseArgs(argv) {
|
|
26
|
+
const args = {
|
|
27
|
+
storyId: "",
|
|
28
|
+
prNumber: 0,
|
|
29
|
+
repoRoot: process.cwd(),
|
|
30
|
+
model: "claude-sonnet-4-5-20250929",
|
|
31
|
+
budgetUsd: 0.5,
|
|
32
|
+
dryRun: false,
|
|
33
|
+
recentRunnerOutputPath: null,
|
|
34
|
+
};
|
|
35
|
+
for (let i = 0; i < argv.length; i++) {
|
|
36
|
+
const a = argv[i];
|
|
37
|
+
const next = argv[i + 1];
|
|
38
|
+
if (a === "--story" && next) {
|
|
39
|
+
args.storyId = next;
|
|
40
|
+
i++;
|
|
41
|
+
}
|
|
42
|
+
else if (a === "--pr" && next) {
|
|
43
|
+
args.prNumber = parseInt(next, 10);
|
|
44
|
+
i++;
|
|
45
|
+
}
|
|
46
|
+
else if (a === "--cwd" && next) {
|
|
47
|
+
args.repoRoot = next;
|
|
48
|
+
i++;
|
|
49
|
+
}
|
|
50
|
+
else if (a === "--model" && next) {
|
|
51
|
+
args.model = next;
|
|
52
|
+
i++;
|
|
53
|
+
}
|
|
54
|
+
else if (a === "--budget-usd" && next) {
|
|
55
|
+
args.budgetUsd = parseFloat(next);
|
|
56
|
+
i++;
|
|
57
|
+
}
|
|
58
|
+
else if (a === "--dry-run") {
|
|
59
|
+
args.dryRun = true;
|
|
60
|
+
}
|
|
61
|
+
else if (a === "--runner-output" && next) {
|
|
62
|
+
args.recentRunnerOutputPath = next;
|
|
63
|
+
i++;
|
|
64
|
+
}
|
|
65
|
+
else if (a === "--help" || a === "-h") {
|
|
66
|
+
printHelp();
|
|
67
|
+
process.exit(0);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (!args.storyId) {
|
|
71
|
+
console.error("--story <id> is required");
|
|
72
|
+
printHelp();
|
|
73
|
+
process.exit(64);
|
|
74
|
+
}
|
|
75
|
+
if (!args.prNumber) {
|
|
76
|
+
console.error("--pr <number> is required");
|
|
77
|
+
printHelp();
|
|
78
|
+
process.exit(64);
|
|
79
|
+
}
|
|
80
|
+
return args;
|
|
81
|
+
}
|
|
82
|
+
function printHelp() {
|
|
83
|
+
console.log(`
|
|
84
|
+
slowcook chef-orchestrate — pipeline orchestrator (cli α.10 L3)
|
|
85
|
+
|
|
86
|
+
Sibling to chef-drift. Where chef-drift edits source files surgically,
|
|
87
|
+
chef-orchestrate decides what to do with a HALTED brew PR:
|
|
88
|
+
redispatch_brew | rebase | escalate | close
|
|
89
|
+
|
|
90
|
+
Usage:
|
|
91
|
+
slowcook chef-orchestrate --pr <n> --story <id> [options]
|
|
92
|
+
|
|
93
|
+
Options:
|
|
94
|
+
--pr <n> PR number (required).
|
|
95
|
+
--story <id> Story id (required, e.g. "018").
|
|
96
|
+
--cwd <path> Repo root (default: cwd).
|
|
97
|
+
--model <id> Anthropic model id.
|
|
98
|
+
--budget-usd <n> Per-decision budget cap (default: 0.50).
|
|
99
|
+
--runner-output <path> Optional path to brew runner output (re-context).
|
|
100
|
+
--dry-run Print verdict; do not act.
|
|
101
|
+
|
|
102
|
+
Environment:
|
|
103
|
+
ANTHROPIC_API_KEY (required) — for the LLM call.
|
|
104
|
+
GITHUB_TOKEN (required for escalate/close) — comment + label + close.
|
|
105
|
+
|
|
106
|
+
Reads (.brewing/chef/story-<id>.json) for chef-drift's prior moves.
|
|
107
|
+
Writes the verdict to (.brewing/chef-orchestrate/story-<id>.json) so a
|
|
108
|
+
follow-up step (or workflow) can act on redispatch/rebase decisions.
|
|
109
|
+
`);
|
|
110
|
+
}
|
|
111
|
+
function repoSlug(repoRoot) {
|
|
112
|
+
return execSync(`git -C "${repoRoot}" remote get-url origin | sed -E 's|^.*github\\.com[:/]||; s|\\.git$||'`, { encoding: "utf8" }).trim();
|
|
113
|
+
}
|
|
114
|
+
function fetchPrSnapshot(repoRoot, prNumber) {
|
|
115
|
+
const slug = repoSlug(repoRoot);
|
|
116
|
+
const json = execSync(`gh pr view ${prNumber} --repo "${slug}" --json headRefName,baseRefName,state,mergeStateStatus,title,statusCheckRollup`, { encoding: "utf8", maxBuffer: 1024 * 256 });
|
|
117
|
+
const obj = JSON.parse(json);
|
|
118
|
+
const failingChecks = (obj.statusCheckRollup ?? [])
|
|
119
|
+
.filter((c) => (c.conclusion ?? "").toLowerCase() === "failure")
|
|
120
|
+
.map((c) => c.name ?? "")
|
|
121
|
+
.filter(Boolean);
|
|
122
|
+
return {
|
|
123
|
+
headRef: obj.headRefName,
|
|
124
|
+
baseRef: obj.baseRefName,
|
|
125
|
+
state: obj.state,
|
|
126
|
+
mergeStateStatus: obj.mergeStateStatus,
|
|
127
|
+
title: obj.title,
|
|
128
|
+
failingChecks,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function loadChefDriftLedger(repoRoot, storyId) {
|
|
132
|
+
const path = join(repoRoot, `.brewing/chef/story-${storyId}.json`);
|
|
133
|
+
if (!existsSync(path)) {
|
|
134
|
+
return { story_id: storyId, moves: [], cumulative_cost_usd: 0 };
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const obj = JSON.parse(readFileSync(path, "utf8"));
|
|
138
|
+
return {
|
|
139
|
+
story_id: obj.story_id ?? storyId,
|
|
140
|
+
moves: obj.moves ?? [],
|
|
141
|
+
cumulative_cost_usd: obj.cumulative_cost_usd ?? 0,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return { story_id: storyId, moves: [], cumulative_cost_usd: 0 };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function loadOpenPrs(repoRoot, storyId) {
|
|
149
|
+
const out = [];
|
|
150
|
+
try {
|
|
151
|
+
const slug = repoSlug(repoRoot);
|
|
152
|
+
const json = execSync(`gh pr list --repo "${slug}" --search "story-${storyId}" --state all --json number,headRefName,headRefOid,title,state --limit 20`, { encoding: "utf8" });
|
|
153
|
+
const prs = JSON.parse(json);
|
|
154
|
+
for (const pr of prs) {
|
|
155
|
+
const branch = pr.headRefName;
|
|
156
|
+
let kind;
|
|
157
|
+
if (branch.includes("/spec/"))
|
|
158
|
+
kind = "spec";
|
|
159
|
+
else if (branch.includes("/mockup/"))
|
|
160
|
+
kind = "mockup";
|
|
161
|
+
else if (branch.includes("/tests/") || branch.includes("/recipe/"))
|
|
162
|
+
kind = "tests";
|
|
163
|
+
else if (branch.includes("/brew/"))
|
|
164
|
+
kind = "brew";
|
|
165
|
+
else
|
|
166
|
+
continue;
|
|
167
|
+
out.push({
|
|
168
|
+
kind,
|
|
169
|
+
number: pr.number,
|
|
170
|
+
branch,
|
|
171
|
+
state: pr.state,
|
|
172
|
+
title: pr.title,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
catch (e) {
|
|
177
|
+
console.warn(` warn: could not list open PRs (${e.message.slice(0, 100)})`);
|
|
178
|
+
}
|
|
179
|
+
return out;
|
|
180
|
+
}
|
|
181
|
+
function loadSpec(repoRoot, storyId) {
|
|
182
|
+
const path = `specs/story-${storyId}.yaml`;
|
|
183
|
+
const abs = join(repoRoot, path);
|
|
184
|
+
if (!existsSync(abs))
|
|
185
|
+
return { path, yaml: "" };
|
|
186
|
+
return { path, yaml: readFileSync(abs, "utf8") };
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Validate a verdict's action shape against its kind. Pure: throws on
|
|
190
|
+
* mismatch so the orchestrator can early-fail before posting comments
|
|
191
|
+
* or applying labels.
|
|
192
|
+
*/
|
|
193
|
+
export function validateVerdictShape(verdict) {
|
|
194
|
+
if (!verdict.kind || !verdict.rationale || !verdict.action) {
|
|
195
|
+
throw new Error("verdict missing kind / rationale / action");
|
|
196
|
+
}
|
|
197
|
+
const a = verdict.action;
|
|
198
|
+
switch (verdict.kind) {
|
|
199
|
+
case "redispatch_brew":
|
|
200
|
+
if (typeof a["brew_workflow"] !== "string" || typeof a["additional_context"] !== "string") {
|
|
201
|
+
throw new Error("redispatch_brew action must include brew_workflow + additional_context strings");
|
|
202
|
+
}
|
|
203
|
+
break;
|
|
204
|
+
case "rebase":
|
|
205
|
+
if (typeof a["onto"] !== "string" || !Array.isArray(a["expected_conflict_paths"])) {
|
|
206
|
+
throw new Error("rebase action must include onto:string + expected_conflict_paths:string[]");
|
|
207
|
+
}
|
|
208
|
+
break;
|
|
209
|
+
case "escalate":
|
|
210
|
+
if (typeof a["issue_number"] !== "number" || typeof a["label"] !== "string" || typeof a["comment"] !== "string") {
|
|
211
|
+
throw new Error("escalate action must include issue_number:number + label:string + comment:string");
|
|
212
|
+
}
|
|
213
|
+
break;
|
|
214
|
+
case "close":
|
|
215
|
+
if (typeof a["reason"] !== "string" || typeof a["comment"] !== "string") {
|
|
216
|
+
throw new Error("close action must include reason:string + comment:string");
|
|
217
|
+
}
|
|
218
|
+
break;
|
|
219
|
+
default:
|
|
220
|
+
throw new Error(`unknown verdict kind: ${verdict.kind}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Save verdict + dispatch-payload to disk so a follow-up workflow step
|
|
225
|
+
* can pick up redispatch / rebase decisions. Idempotent (overwrites).
|
|
226
|
+
*/
|
|
227
|
+
export function persistVerdict(repoRoot, storyId, prNumber, verdict) {
|
|
228
|
+
const path = join(repoRoot, `.brewing/chef-orchestrate/story-${storyId}.json`);
|
|
229
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
230
|
+
const payload = {
|
|
231
|
+
story_id: storyId,
|
|
232
|
+
pr_number: prNumber,
|
|
233
|
+
verdict,
|
|
234
|
+
timestamp: new Date().toISOString(),
|
|
235
|
+
};
|
|
236
|
+
writeFileSync(path, JSON.stringify(payload, null, 2), "utf8");
|
|
237
|
+
return path;
|
|
238
|
+
}
|
|
239
|
+
function applyEscalate(repoRoot, prNumber, action) {
|
|
240
|
+
const slug = repoSlug(repoRoot);
|
|
241
|
+
let posted = false;
|
|
242
|
+
let labeled = false;
|
|
243
|
+
// Comment on the source ISSUE (escalation goes to the PM, not the bot PR).
|
|
244
|
+
const tmp = "/tmp/chef-orchestrate-escalate-comment.md";
|
|
245
|
+
writeFileSync(tmp, action.comment, "utf8");
|
|
246
|
+
try {
|
|
247
|
+
execSync(`gh issue comment ${action.issue_number} --repo "${slug}" --body-file ${tmp}`, { stdio: "inherit" });
|
|
248
|
+
posted = true;
|
|
249
|
+
}
|
|
250
|
+
catch (e) {
|
|
251
|
+
console.warn(` warn: failed to post escalation comment: ${e.message.slice(0, 200)}`);
|
|
252
|
+
}
|
|
253
|
+
// Apply label to the PR (so future filters surface escalated PRs).
|
|
254
|
+
try {
|
|
255
|
+
execSync(`gh pr edit ${prNumber} --repo "${slug}" --add-label "${action.label}"`, { stdio: "inherit" });
|
|
256
|
+
labeled = true;
|
|
257
|
+
}
|
|
258
|
+
catch (e) {
|
|
259
|
+
console.warn(` warn: failed to apply label '${action.label}' to PR #${prNumber}: ${e.message.slice(0, 200)}`);
|
|
260
|
+
}
|
|
261
|
+
return { posted, labeled };
|
|
262
|
+
}
|
|
263
|
+
function applyClose(repoRoot, prNumber, action) {
|
|
264
|
+
const slug = repoSlug(repoRoot);
|
|
265
|
+
let commented = false;
|
|
266
|
+
let closed = false;
|
|
267
|
+
const tmp = "/tmp/chef-orchestrate-close-comment.md";
|
|
268
|
+
writeFileSync(tmp, action.comment, "utf8");
|
|
269
|
+
try {
|
|
270
|
+
execSync(`gh pr comment ${prNumber} --repo "${slug}" --body-file ${tmp}`, { stdio: "inherit" });
|
|
271
|
+
commented = true;
|
|
272
|
+
}
|
|
273
|
+
catch (e) {
|
|
274
|
+
console.warn(` warn: failed to post close comment: ${e.message.slice(0, 200)}`);
|
|
275
|
+
}
|
|
276
|
+
try {
|
|
277
|
+
execSync(`gh pr close ${prNumber} --repo "${slug}"`, { stdio: "inherit" });
|
|
278
|
+
closed = true;
|
|
279
|
+
}
|
|
280
|
+
catch (e) {
|
|
281
|
+
console.warn(` warn: failed to close PR #${prNumber}: ${e.message.slice(0, 200)}`);
|
|
282
|
+
}
|
|
283
|
+
return { commented, closed };
|
|
284
|
+
}
|
|
285
|
+
export async function chefOrchestrate(argv, _cliVersion) {
|
|
286
|
+
const args = parseArgs(argv);
|
|
287
|
+
const apiKey = process.env["ANTHROPIC_API_KEY"];
|
|
288
|
+
if (!apiKey) {
|
|
289
|
+
console.error("ANTHROPIC_API_KEY env var is required.");
|
|
290
|
+
process.exit(2);
|
|
291
|
+
}
|
|
292
|
+
console.log(`slowcook chef-orchestrate · story-${args.storyId} · PR #${args.prNumber}`);
|
|
293
|
+
// Gather inputs.
|
|
294
|
+
const prState = fetchPrSnapshot(args.repoRoot, args.prNumber);
|
|
295
|
+
const ledger = loadChefDriftLedger(args.repoRoot, args.storyId);
|
|
296
|
+
const openPrs = loadOpenPrs(args.repoRoot, args.storyId);
|
|
297
|
+
const spec = loadSpec(args.repoRoot, args.storyId);
|
|
298
|
+
let runnerOutput = undefined;
|
|
299
|
+
if (args.recentRunnerOutputPath && existsSync(args.recentRunnerOutputPath)) {
|
|
300
|
+
runnerOutput = readFileSync(args.recentRunnerOutputPath, "utf8");
|
|
301
|
+
}
|
|
302
|
+
console.log(` PR state: ${prState.state} · merge=${prState.mergeStateStatus} · failing=${prState.failingChecks?.length ?? 0}`);
|
|
303
|
+
console.log(` ledger: ${ledger.moves.length} prior chef-drift move(s) · cum-cost $${ledger.cumulative_cost_usd.toFixed(4)}`);
|
|
304
|
+
console.log(` openPrs: ${openPrs.length} (spec=${openPrs.filter(p => p.kind === "spec").length}, mockup=${openPrs.filter(p => p.kind === "mockup").length}, tests=${openPrs.filter(p => p.kind === "tests").length}, brew=${openPrs.filter(p => p.kind === "brew").length})`);
|
|
305
|
+
const prompt = buildChefOrchestratePrompt({
|
|
306
|
+
storyId: args.storyId,
|
|
307
|
+
prNumber: args.prNumber,
|
|
308
|
+
prState,
|
|
309
|
+
chefDriftLedger: ledger,
|
|
310
|
+
navigatorHistory: null, // hooked up in α.10 L3 α.1
|
|
311
|
+
spec,
|
|
312
|
+
storyOpenPrs: openPrs,
|
|
313
|
+
recentRunnerOutput: runnerOutput,
|
|
314
|
+
});
|
|
315
|
+
console.log(` prompt: ${prompt.length} chars · calling chef-orchestrate LLM (${args.model})`);
|
|
316
|
+
const client = new AnthropicClient(apiKey);
|
|
317
|
+
const resp = await client.complete({
|
|
318
|
+
model: args.model,
|
|
319
|
+
system: CHEF_ORCHESTRATE_SYSTEM,
|
|
320
|
+
messages: [{ role: "user", content: prompt }],
|
|
321
|
+
maxTokens: 4096,
|
|
322
|
+
});
|
|
323
|
+
console.log(` chef-orchestrate LLM: ${resp.usage.inputTokens}→${resp.usage.outputTokens} tok · $${resp.costUsd.toFixed(4)}`);
|
|
324
|
+
if (resp.costUsd > args.budgetUsd) {
|
|
325
|
+
console.warn(` warn: cost $${resp.costUsd.toFixed(4)} exceeded budget $${args.budgetUsd}. Continuing (decision is in-hand).`);
|
|
326
|
+
}
|
|
327
|
+
let verdict;
|
|
328
|
+
try {
|
|
329
|
+
const text = resp.text.trim();
|
|
330
|
+
const fence = text.match(/```json\s*([\s\S]*?)```/);
|
|
331
|
+
verdict = JSON.parse(fence ? fence[1] : text);
|
|
332
|
+
validateVerdictShape(verdict);
|
|
333
|
+
}
|
|
334
|
+
catch (e) {
|
|
335
|
+
console.error(` ! verdict parse/shape error: ${e.message}`);
|
|
336
|
+
console.error(` raw: ${resp.text.slice(0, 600)}`);
|
|
337
|
+
process.exit(1);
|
|
338
|
+
}
|
|
339
|
+
console.log(`\n VERDICT: ${verdict.kind.toUpperCase()}`);
|
|
340
|
+
console.log(` rationale: ${verdict.rationale}`);
|
|
341
|
+
// Always persist the verdict — workflows / follow-up steps consume it.
|
|
342
|
+
if (!args.dryRun) {
|
|
343
|
+
const path = persistVerdict(args.repoRoot, args.storyId, args.prNumber, verdict);
|
|
344
|
+
console.log(` wrote: ${path.replace(args.repoRoot + "/", "")}`);
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
console.log(` [dry-run] would persist verdict to .brewing/chef-orchestrate/story-${args.storyId}.json`);
|
|
348
|
+
}
|
|
349
|
+
// Execute the verdict.
|
|
350
|
+
if (args.dryRun) {
|
|
351
|
+
console.log(` [dry-run] would execute: ${verdict.kind}`);
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
switch (verdict.kind) {
|
|
355
|
+
case "escalate": {
|
|
356
|
+
const action = verdict.action;
|
|
357
|
+
console.log(` → escalate: post comment on issue #${action.issue_number} + apply label '${action.label}' to PR #${args.prNumber}`);
|
|
358
|
+
const r = applyEscalate(args.repoRoot, args.prNumber, action);
|
|
359
|
+
console.log(` posted=${r.posted} labeled=${r.labeled}`);
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
case "close": {
|
|
363
|
+
const action = verdict.action;
|
|
364
|
+
console.log(` → close PR #${args.prNumber}: ${action.reason}`);
|
|
365
|
+
const r = applyClose(args.repoRoot, args.prNumber, action);
|
|
366
|
+
console.log(` commented=${r.commented} closed=${r.closed}`);
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
case "redispatch_brew": {
|
|
370
|
+
const action = verdict.action;
|
|
371
|
+
console.log(` → redispatch_brew (deferred): would dispatch ${action.brew_workflow} with additional_context (${action.additional_context.length} chars)`);
|
|
372
|
+
console.log(` verdict persisted; α.10 L3 α.0 does not auto-dispatch — workflow consumer picks up the verdict file`);
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
case "rebase": {
|
|
376
|
+
const action = verdict.action;
|
|
377
|
+
console.log(` → rebase (deferred): would rebase ${prState.headRef} onto ${action.onto}`);
|
|
378
|
+
console.log(` expected conflicts: ${action.expected_conflict_paths.join(", ") || "(none)"}`);
|
|
379
|
+
console.log(` verdict persisted; α.10 L3 α.0 does not auto-rebase — workflow consumer picks up the verdict file`);
|
|
380
|
+
break;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
console.log(`\n done · cost $${resp.costUsd.toFixed(4)}`);
|
|
384
|
+
}
|
|
385
|
+
//# sourceMappingURL=orchestrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrate.js","sourceRoot":"","sources":["../../../src/commands/chef/orchestrate.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,52 @@ interface FileToWrite {
|
|
|
31
31
|
export declare function parseMockInitArgs(argv: string[], runtimeVersion: string): MockInitArgs;
|
|
32
32
|
export declare function planMockFiles(args: MockInitArgs): FileToWrite[];
|
|
33
33
|
export declare function initMock(argv: string[], cliVersion: string): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Detect the consumer's package manager from lockfile presence.
|
|
36
|
+
* Pure: takes an `exists` predicate so it can be unit-tested without IO.
|
|
37
|
+
*/
|
|
38
|
+
export declare function detectPackageManager(cwd: string, exists: (p: string) => boolean): "pnpm" | "npm" | "yarn" | "unknown";
|
|
39
|
+
/**
|
|
40
|
+
* Detect whether `mock` is already declared in the consumer's
|
|
41
|
+
* pnpm-workspace.yaml `packages` list. Pure parser — handles the
|
|
42
|
+
* common YAML shapes: flow array (`packages: [mock]`) + block list
|
|
43
|
+
* (`packages:\n - mock`). Returns true on any literal "mock" entry.
|
|
44
|
+
*/
|
|
45
|
+
export declare function isMockInPnpmWorkspace(yamlContent: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Result of ensurePnpmWorkspace — what the cli did (if anything) so the
|
|
48
|
+
* caller can print accurate "Next steps" text.
|
|
49
|
+
*/
|
|
50
|
+
export type EnsureWorkspaceResult = {
|
|
51
|
+
kind: "added-to-existing";
|
|
52
|
+
path: string;
|
|
53
|
+
} | {
|
|
54
|
+
kind: "already-listed";
|
|
55
|
+
path: string;
|
|
56
|
+
} | {
|
|
57
|
+
kind: "created";
|
|
58
|
+
path: string;
|
|
59
|
+
} | {
|
|
60
|
+
kind: "not-pnpm";
|
|
61
|
+
pkgManager: "npm" | "yarn" | "unknown";
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Make sure `mock` is a pnpm-workspace member when the consumer is on
|
|
65
|
+
* pnpm. Three paths:
|
|
66
|
+
* - pnpm-workspace.yaml exists + lists "mock" → already-listed
|
|
67
|
+
* - pnpm-workspace.yaml exists + missing "mock" → added-to-existing
|
|
68
|
+
* - pnpm-lock.yaml present + no workspace.yaml → created (block-list shape)
|
|
69
|
+
* - npm/yarn/unknown (no pnpm signal) → not-pnpm
|
|
70
|
+
*
|
|
71
|
+
* We DON'T auto-migrate npm/yarn consumers — that requires re-resolving
|
|
72
|
+
* the lockfile and is too invasive for an `init mock` step. Caller
|
|
73
|
+
* prints a one-line recommendation in that case.
|
|
74
|
+
*
|
|
75
|
+
* Conservative writes: when adding to an existing block-list workspace,
|
|
76
|
+
* we append a new `- mock` line preserving prior content; we never
|
|
77
|
+
* rewrite the whole file.
|
|
78
|
+
*/
|
|
79
|
+
export declare function ensurePnpmWorkspace(cwd: string): EnsureWorkspaceResult;
|
|
34
80
|
/**
|
|
35
81
|
* Patch the consumer's tsconfig.json so `mock` is in the `exclude`
|
|
36
82
|
* array. Idempotent — returns false when nothing changed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../../src/commands/init/mock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,UAAU,YAAY;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,gEAAgE;IAChE,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,cAAc,EAAE,MAAM,GAAG,YAAY,CAoBtF;AAsDD,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,WAAW,EAAE,CAmC/D;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../../src/commands/init/mock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,UAAU,YAAY;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,gEAAgE;IAChE,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,cAAc,EAAE,MAAM,GAAG,YAAY,CAoBtF;AAsDD,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,WAAW,EAAE,CAmC/D;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmGhF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,GAC7B,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAKrC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAYlE;AAED;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAC7B;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEjE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB,CAiDtE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAmBzE"}
|
|
@@ -186,16 +186,156 @@ export async function initMock(argv, cliVersion) {
|
|
|
186
186
|
console.log(` SKIP tsconfig.json (mock already in exclude or no exclude field)`);
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
|
+
// Wire mock as a pnpm-workspace member when the consumer is on pnpm
|
|
190
|
+
// so its node_modules dedupes against the prod tree (Next/React/
|
|
191
|
+
// Vitest/Tailwind are typically the same versions both sides). Two
|
|
192
|
+
// separate node_modules costs ~200-500MB on a typical Next 16 + RTL
|
|
193
|
+
// setup. Discovered post-rewo (2026-05-06) — by which time the rewo
|
|
194
|
+
// mock had its own node_modules + lockfile.
|
|
195
|
+
const wsResult = ensurePnpmWorkspace(args.cwd);
|
|
196
|
+
switch (wsResult.kind) {
|
|
197
|
+
case "added-to-existing":
|
|
198
|
+
console.log(` PATCH ${wsResult.path} (appended mock to packages list)`);
|
|
199
|
+
break;
|
|
200
|
+
case "already-listed":
|
|
201
|
+
console.log(` SKIP ${wsResult.path} (mock already a workspace member)`);
|
|
202
|
+
break;
|
|
203
|
+
case "created":
|
|
204
|
+
console.log(` WRITE ${wsResult.path} (created — pnpm workspace lists [mock])`);
|
|
205
|
+
break;
|
|
206
|
+
case "not-pnpm":
|
|
207
|
+
console.log(` SKIP pnpm-workspace.yaml (consumer uses ${wsResult.pkgManager}; recommend pnpm to share node_modules)`);
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
189
210
|
console.log(`Done. Wrote ${written} file(s); skipped ${skipped}.`);
|
|
190
211
|
console.log();
|
|
191
212
|
console.log("Next steps:");
|
|
192
|
-
|
|
193
|
-
|
|
213
|
+
if (wsResult.kind === "not-pnpm") {
|
|
214
|
+
console.log(" 1. cd mock && npm install # (or yarn install — separate node_modules)");
|
|
215
|
+
console.log(" 2. cd mock && npm run dev # http://localhost:3100");
|
|
216
|
+
console.log(" TIP: pnpm + a workspace would let mock + prod share node_modules");
|
|
217
|
+
console.log(" (saves ~200-500MB). Migrate later via:");
|
|
218
|
+
console.log(" echo 'packages:\\n - mock' > pnpm-workspace.yaml");
|
|
219
|
+
console.log(" rm -rf node_modules mock/node_modules package-lock.json mock/package-lock.json");
|
|
220
|
+
console.log(" pnpm install");
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
console.log(" 1. pnpm install # at repo root — installs both halves");
|
|
224
|
+
console.log(" 2. pnpm --filter mock dev # http://localhost:3100");
|
|
225
|
+
}
|
|
194
226
|
console.log(" 3. Verify the empty scenario picker renders");
|
|
195
227
|
console.log(" 4. Commit + push the mock/ directory");
|
|
196
228
|
console.log(" 5. Future vibe runs (slowcook 0.16-α.3+) populate mock/scenarios/ +");
|
|
197
229
|
console.log(" extend mock/src/lib/scenario-registry.ts");
|
|
198
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* Detect the consumer's package manager from lockfile presence.
|
|
233
|
+
* Pure: takes an `exists` predicate so it can be unit-tested without IO.
|
|
234
|
+
*/
|
|
235
|
+
export function detectPackageManager(cwd, exists) {
|
|
236
|
+
if (exists(join(cwd, "pnpm-lock.yaml")) || exists(join(cwd, "pnpm-workspace.yaml")))
|
|
237
|
+
return "pnpm";
|
|
238
|
+
if (exists(join(cwd, "yarn.lock")))
|
|
239
|
+
return "yarn";
|
|
240
|
+
if (exists(join(cwd, "package-lock.json")))
|
|
241
|
+
return "npm";
|
|
242
|
+
return "unknown";
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Detect whether `mock` is already declared in the consumer's
|
|
246
|
+
* pnpm-workspace.yaml `packages` list. Pure parser — handles the
|
|
247
|
+
* common YAML shapes: flow array (`packages: [mock]`) + block list
|
|
248
|
+
* (`packages:\n - mock`). Returns true on any literal "mock" entry.
|
|
249
|
+
*/
|
|
250
|
+
export function isMockInPnpmWorkspace(yamlContent) {
|
|
251
|
+
// Strip comments to keep the regex simple.
|
|
252
|
+
const stripped = yamlContent.replace(/#[^\n]*/g, "");
|
|
253
|
+
// Block-list entries: `- mock` or `- "mock"` or `- 'mock'`
|
|
254
|
+
if (/^\s*-\s*["']?mock["']?\s*$/m.test(stripped))
|
|
255
|
+
return true;
|
|
256
|
+
// Flow-array form: `packages: [..., mock, ...]`
|
|
257
|
+
const flowMatch = stripped.match(/packages\s*:\s*\[([^\]]*)\]/);
|
|
258
|
+
if (flowMatch) {
|
|
259
|
+
const items = flowMatch[1].split(",").map((s) => s.trim().replace(/^["']|["']$/g, ""));
|
|
260
|
+
if (items.includes("mock"))
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Make sure `mock` is a pnpm-workspace member when the consumer is on
|
|
267
|
+
* pnpm. Three paths:
|
|
268
|
+
* - pnpm-workspace.yaml exists + lists "mock" → already-listed
|
|
269
|
+
* - pnpm-workspace.yaml exists + missing "mock" → added-to-existing
|
|
270
|
+
* - pnpm-lock.yaml present + no workspace.yaml → created (block-list shape)
|
|
271
|
+
* - npm/yarn/unknown (no pnpm signal) → not-pnpm
|
|
272
|
+
*
|
|
273
|
+
* We DON'T auto-migrate npm/yarn consumers — that requires re-resolving
|
|
274
|
+
* the lockfile and is too invasive for an `init mock` step. Caller
|
|
275
|
+
* prints a one-line recommendation in that case.
|
|
276
|
+
*
|
|
277
|
+
* Conservative writes: when adding to an existing block-list workspace,
|
|
278
|
+
* we append a new `- mock` line preserving prior content; we never
|
|
279
|
+
* rewrite the whole file.
|
|
280
|
+
*/
|
|
281
|
+
export function ensurePnpmWorkspace(cwd) {
|
|
282
|
+
const pkgMgr = detectPackageManager(cwd, existsSync);
|
|
283
|
+
if (pkgMgr !== "pnpm") {
|
|
284
|
+
return { kind: "not-pnpm", pkgManager: pkgMgr };
|
|
285
|
+
}
|
|
286
|
+
const workspacePath = join(cwd, "pnpm-workspace.yaml");
|
|
287
|
+
const relPath = "pnpm-workspace.yaml";
|
|
288
|
+
if (existsSync(workspacePath)) {
|
|
289
|
+
const original = readFileSync(workspacePath, "utf8");
|
|
290
|
+
if (isMockInPnpmWorkspace(original)) {
|
|
291
|
+
return { kind: "already-listed", path: relPath };
|
|
292
|
+
}
|
|
293
|
+
// Append a `- mock` entry to the existing packages list. If we can't
|
|
294
|
+
// find a `packages:` block, fall through to create it.
|
|
295
|
+
let updated;
|
|
296
|
+
if (/^packages\s*:/m.test(original)) {
|
|
297
|
+
// Existing block-list — append at the end of the list.
|
|
298
|
+
// Heuristic: find the last `-` line under packages: and add after.
|
|
299
|
+
// Simplest correct: append `\n - mock\n` after `packages:`'s last
|
|
300
|
+
// child (we accept slight indentation imperfection over parser risk).
|
|
301
|
+
const lines = original.split("\n");
|
|
302
|
+
let lastBlockIdx = -1;
|
|
303
|
+
let inPackages = false;
|
|
304
|
+
for (let i = 0; i < lines.length; i++) {
|
|
305
|
+
if (/^packages\s*:/.test(lines[i])) {
|
|
306
|
+
inPackages = true;
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
if (!inPackages)
|
|
310
|
+
continue;
|
|
311
|
+
if (/^\s*-\s+/.test(lines[i]))
|
|
312
|
+
lastBlockIdx = i;
|
|
313
|
+
else if (/^\S/.test(lines[i]) && lines[i].trim() !== "")
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
if (lastBlockIdx === -1) {
|
|
317
|
+
// packages: is empty or flow form; append a fresh block-list line.
|
|
318
|
+
updated = original.replace(/(^packages\s*:.*$)/m, `$1\n - mock`);
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
// Preserve the indent of the prior list item.
|
|
322
|
+
const priorIndent = lines[lastBlockIdx].match(/^(\s*)-/)[1] ?? " ";
|
|
323
|
+
lines.splice(lastBlockIdx + 1, 0, `${priorIndent}- mock`);
|
|
324
|
+
updated = lines.join("\n");
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
updated = original.trimEnd() + `\npackages:\n - mock\n`;
|
|
329
|
+
}
|
|
330
|
+
writeFileSync(workspacePath, updated, "utf8");
|
|
331
|
+
return { kind: "added-to-existing", path: relPath };
|
|
332
|
+
}
|
|
333
|
+
// No workspace.yaml — create a minimal one. Block-list form is more
|
|
334
|
+
// approachable than flow-array for downstream edits.
|
|
335
|
+
const fresh = `# pnpm workspace — auto-created by 'slowcook init mock' so the\n# mock app shares node_modules with the prod tree (no duplicate installs).\npackages:\n - mock\n`;
|
|
336
|
+
writeFileSync(workspacePath, fresh, "utf8");
|
|
337
|
+
return { kind: "created", path: relPath };
|
|
338
|
+
}
|
|
199
339
|
/**
|
|
200
340
|
* Patch the consumer's tsconfig.json so `mock` is in the `exclude`
|
|
201
341
|
* array. Idempotent — returns false when nothing changed.
|