@slowcook-ai/cli 0.12.10 → 0.13.0-alpha.3
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 +25 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/brew/agent.d.ts.map +1 -1
- package/dist/commands/brew/agent.js +31 -6
- package/dist/commands/brew/agent.js.map +1 -1
- package/dist/commands/brew/patterns.d.ts +54 -0
- package/dist/commands/brew/patterns.d.ts.map +1 -0
- package/dist/commands/brew/patterns.js +136 -0
- package/dist/commands/brew/patterns.js.map +1 -0
- package/dist/commands/brew/prompts.d.ts +7 -0
- package/dist/commands/brew/prompts.d.ts.map +1 -1
- package/dist/commands/brew/prompts.js +7 -0
- package/dist/commands/brew/prompts.js.map +1 -1
- package/dist/commands/dispatch/index.d.ts.map +1 -1
- package/dist/commands/dispatch/index.js +10 -3
- package/dist/commands/dispatch/index.js.map +1 -1
- package/dist/commands/init/plan.d.ts.map +1 -1
- package/dist/commands/init/plan.js +7 -1
- package/dist/commands/init/plan.js.map +1 -1
- package/dist/commands/init/templates.d.ts +8 -0
- package/dist/commands/init/templates.d.ts.map +1 -1
- package/dist/commands/init/templates.js +62 -0
- package/dist/commands/init/templates.js.map +1 -1
- package/dist/commands/investigate/agent.d.ts +68 -0
- package/dist/commands/investigate/agent.d.ts.map +1 -0
- package/dist/commands/investigate/agent.js +465 -0
- package/dist/commands/investigate/agent.js.map +1 -0
- package/dist/commands/investigate/index.d.ts +43 -0
- package/dist/commands/investigate/index.d.ts.map +1 -0
- package/dist/commands/investigate/index.js +296 -0
- package/dist/commands/investigate/index.js.map +1 -0
- package/dist/commands/investigate/prompts.d.ts +90 -0
- package/dist/commands/investigate/prompts.d.ts.map +1 -0
- package/dist/commands/investigate/prompts.js +190 -0
- package/dist/commands/investigate/prompts.js.map +1 -0
- package/dist/commands/investigate/schema.d.ts +91 -0
- package/dist/commands/investigate/schema.d.ts.map +1 -0
- package/dist/commands/investigate/schema.js +87 -0
- package/dist/commands/investigate/schema.js.map +1 -0
- package/dist/commands/on-brew-merged/index.d.ts.map +1 -1
- package/dist/commands/on-brew-merged/index.js +27 -6
- package/dist/commands/on-brew-merged/index.js.map +1 -1
- package/dist/commands/recipe-regression/index.d.ts +50 -0
- package/dist/commands/recipe-regression/index.d.ts.map +1 -0
- package/dist/commands/recipe-regression/index.js +150 -0
- package/dist/commands/recipe-regression/index.js.map +1 -0
- package/dist/commands/testgen/agent.d.ts.map +1 -1
- package/dist/commands/testgen/agent.js +16 -4
- package/dist/commands/testgen/agent.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `slowcook investigate` — bug-flow analogue of refine.
|
|
3
|
+
*
|
|
4
|
+
* Reads a GitHub issue (label: `bug`), uses code tools to find the
|
|
5
|
+
* failure locus, emits `.brewing/bug-profiles/B-<id>.yaml` and opens
|
|
6
|
+
* a PR proposing the profile. The PR's merge triggers
|
|
7
|
+
* `slowcook-recipe-regression.yml` (alpha.3) which kicks off
|
|
8
|
+
* `recipe --regression` to write the failing test.
|
|
9
|
+
*
|
|
10
|
+
* **Status**: alpha.2a — scaffold only. Parses args, prints what it
|
|
11
|
+
* WOULD do. Real LLM agent + PR opening land in alpha.2b. Calling the
|
|
12
|
+
* command today exits with a clear "not yet implemented" notice so
|
|
13
|
+
* accidental wiring (e.g., a workflow trigger) fails fast and visibly.
|
|
14
|
+
*/
|
|
15
|
+
import { mkdirSync, writeFileSync, existsSync, readdirSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { execSync } from "node:child_process";
|
|
18
|
+
import { validateBugProfile, BUG_PROFILE_SCHEMA_VERSION, } from "./schema.js";
|
|
19
|
+
import { runInvestigation } from "./agent.js";
|
|
20
|
+
function parseArgs(argv) {
|
|
21
|
+
const args = {
|
|
22
|
+
issueNumber: 0,
|
|
23
|
+
repoRoot: process.cwd(),
|
|
24
|
+
dryRun: false,
|
|
25
|
+
stub: false,
|
|
26
|
+
model: "claude-opus-4-7",
|
|
27
|
+
};
|
|
28
|
+
for (let i = 0; i < argv.length; i++) {
|
|
29
|
+
const arg = argv[i];
|
|
30
|
+
const next = argv[i + 1];
|
|
31
|
+
if ((arg === "--issue" || arg === "-i") && next) {
|
|
32
|
+
args.issueNumber = parseInt(next, 10);
|
|
33
|
+
i++;
|
|
34
|
+
}
|
|
35
|
+
else if (arg === "--cwd" && next) {
|
|
36
|
+
args.repoRoot = next;
|
|
37
|
+
i++;
|
|
38
|
+
}
|
|
39
|
+
else if (arg === "--dry-run") {
|
|
40
|
+
args.dryRun = true;
|
|
41
|
+
}
|
|
42
|
+
else if (arg === "--stub") {
|
|
43
|
+
args.stub = true;
|
|
44
|
+
}
|
|
45
|
+
else if (arg === "--model" && next) {
|
|
46
|
+
args.model = next;
|
|
47
|
+
i++;
|
|
48
|
+
}
|
|
49
|
+
else if (arg === "--help" || arg === "-h") {
|
|
50
|
+
printHelp();
|
|
51
|
+
process.exit(0);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return args;
|
|
55
|
+
}
|
|
56
|
+
function printHelp() {
|
|
57
|
+
console.log(`
|
|
58
|
+
slowcook investigate — diagnose a bug from a GitHub issue and emit a bug-profile.
|
|
59
|
+
|
|
60
|
+
Usage:
|
|
61
|
+
slowcook investigate --issue <number> [--cwd <path>] [--model <id>] [--dry-run] [--stub]
|
|
62
|
+
|
|
63
|
+
Status: alpha.2b — real LLM agent integration. PR opening (auto-branch
|
|
64
|
+
+ push + PR open) lands in alpha.2c. Today: writes the bug-profile to
|
|
65
|
+
.brewing/bug-profiles/B-<n>.yaml.
|
|
66
|
+
|
|
67
|
+
What it does:
|
|
68
|
+
1. Fetches issue #<number> body + prior comments via gh
|
|
69
|
+
2. Runs an LLM agent loop with read-only code tools
|
|
70
|
+
(read_file, outline_file, list_directory, find_references,
|
|
71
|
+
find_definition, grep)
|
|
72
|
+
3. Validates the agent's <bug_profile> output against the schema
|
|
73
|
+
(schema_version ${BUG_PROFILE_SCHEMA_VERSION})
|
|
74
|
+
4. Writes .brewing/bug-profiles/B-<n>.yaml
|
|
75
|
+
|
|
76
|
+
Flags:
|
|
77
|
+
--issue <n> GitHub issue number (required).
|
|
78
|
+
--cwd <path> Repo root (default: cwd).
|
|
79
|
+
--model <id> LLM model. Default: claude-opus-4-7.
|
|
80
|
+
--dry-run Print profile + agent stats, don't write to disk.
|
|
81
|
+
--stub Emit a stub profile without calling the LLM (alpha.2a
|
|
82
|
+
behaviour; useful for testing the file layout).
|
|
83
|
+
|
|
84
|
+
Environment:
|
|
85
|
+
ANTHROPIC_API_KEY Required unless --stub. The agent makes Anthropic
|
|
86
|
+
API calls; cost varies by model + bug complexity
|
|
87
|
+
($0.05–$0.50 typical for opus, $0.01–$0.10 for sonnet).
|
|
88
|
+
GITHUB_TOKEN Required to fetch the issue body via gh CLI.
|
|
89
|
+
Falls back to gh's auth if unset.
|
|
90
|
+
`);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Pick the next free bug-id by walking `.brewing/bug-profiles/`
|
|
94
|
+
* (and once branches exist, also \`slowcook/bug-profile/B-*\`). Same
|
|
95
|
+
* race-aware pattern as story-id assignment (slowcook#8 fix).
|
|
96
|
+
*
|
|
97
|
+
* Exposed for use by alpha.2b once the agent emits real profiles.
|
|
98
|
+
*/
|
|
99
|
+
export function pickNextBugId(repoRoot) {
|
|
100
|
+
const dir = join(repoRoot, ".brewing/bug-profiles");
|
|
101
|
+
let max = 0;
|
|
102
|
+
if (existsSync(dir)) {
|
|
103
|
+
for (const entry of readdirSync(dir)) {
|
|
104
|
+
const m = entry.match(/^B-(\d+)\.ya?ml$/);
|
|
105
|
+
if (m) {
|
|
106
|
+
const n = parseInt(m[1] ?? "0", 10);
|
|
107
|
+
if (n > max)
|
|
108
|
+
max = n;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return `B-${max + 1}`;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Build a stub bug profile from issue metadata only — no code reading.
|
|
116
|
+
* alpha.2a placeholder. alpha.2b replaces this with an LLM-driven
|
|
117
|
+
* agent that actually investigates.
|
|
118
|
+
*/
|
|
119
|
+
export function buildStubProfile(args) {
|
|
120
|
+
return {
|
|
121
|
+
schema_version: BUG_PROFILE_SCHEMA_VERSION,
|
|
122
|
+
bug_id: args.bugId,
|
|
123
|
+
title: args.issueTitle,
|
|
124
|
+
source_issue: `#${args.issueNumber}`,
|
|
125
|
+
status: "investigated",
|
|
126
|
+
investigated_by: `slowcook-investigate@${args.cliVersion}-stub`,
|
|
127
|
+
created_at: args.now.toISOString(),
|
|
128
|
+
symptom: ["(not yet investigated — alpha.2a stub)"],
|
|
129
|
+
expected: ["(not yet investigated — alpha.2a stub)"],
|
|
130
|
+
reproduction: ["(not yet investigated — alpha.2a stub)"],
|
|
131
|
+
failure_locus: {
|
|
132
|
+
file: "(unknown)",
|
|
133
|
+
diagnosis: "Stub profile emitted by alpha.2a scaffold. Real investigation lands in alpha.2b.",
|
|
134
|
+
},
|
|
135
|
+
regression_assertion: ["(not yet investigated — alpha.2a stub)"],
|
|
136
|
+
fix_scope: [],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
export async function investigate(argv, cliVersion) {
|
|
140
|
+
const args = parseArgs(argv);
|
|
141
|
+
if (!args.issueNumber || isNaN(args.issueNumber)) {
|
|
142
|
+
console.error("slowcook investigate: --issue <number> is required");
|
|
143
|
+
printHelp();
|
|
144
|
+
process.exit(64);
|
|
145
|
+
}
|
|
146
|
+
const bugId = pickNextBugId(args.repoRoot);
|
|
147
|
+
const now = new Date();
|
|
148
|
+
// ---- Stub path (alpha.2a-style; kept for testing without API key) ----
|
|
149
|
+
if (args.stub) {
|
|
150
|
+
console.error(`slowcook investigate (${cliVersion}) — --stub mode. No LLM call; emitting placeholder profile.`);
|
|
151
|
+
const profile = buildStubProfile({
|
|
152
|
+
issueNumber: args.issueNumber,
|
|
153
|
+
issueTitle: `(issue #${args.issueNumber})`,
|
|
154
|
+
bugId,
|
|
155
|
+
cliVersion,
|
|
156
|
+
now,
|
|
157
|
+
});
|
|
158
|
+
return finaliseProfile(profile, args, bugId);
|
|
159
|
+
}
|
|
160
|
+
// ---- Real agent path (alpha.2b) ----
|
|
161
|
+
const apiKey = process.env["ANTHROPIC_API_KEY"];
|
|
162
|
+
if (!apiKey) {
|
|
163
|
+
console.error("slowcook investigate: ANTHROPIC_API_KEY is required (or use --stub for placeholder)");
|
|
164
|
+
process.exit(78);
|
|
165
|
+
}
|
|
166
|
+
console.error(`slowcook investigate (${cliVersion}) — issue #${args.issueNumber}, model ${args.model}, bug-id ${bugId}.`);
|
|
167
|
+
console.error(`Fetching issue from GitHub…`);
|
|
168
|
+
const issue = fetchIssueViaGh(args.issueNumber, args.repoRoot);
|
|
169
|
+
console.error(`Running investigation agent (read-only tools, max 12 rounds)…`);
|
|
170
|
+
const result = await runInvestigation({
|
|
171
|
+
repoRoot: args.repoRoot,
|
|
172
|
+
anthropicApiKey: apiKey,
|
|
173
|
+
model: args.model,
|
|
174
|
+
bugId,
|
|
175
|
+
cliVersion,
|
|
176
|
+
issue,
|
|
177
|
+
now: () => now,
|
|
178
|
+
});
|
|
179
|
+
console.error(`Agent done: ${result.rounds} round(s), $${result.spendUsd.toFixed(4)} spent${result.halted ? ` (HALTED: ${result.haltReason})` : ""}.`);
|
|
180
|
+
return finaliseProfile(result.profile, args, bugId);
|
|
181
|
+
}
|
|
182
|
+
function finaliseProfile(profile, args, bugId) {
|
|
183
|
+
const validation = validateBugProfile(profile);
|
|
184
|
+
if (!validation.ok) {
|
|
185
|
+
console.error(`slowcook investigate: profile failed validation:`);
|
|
186
|
+
for (const e of validation.errors)
|
|
187
|
+
console.error(` - ${e}`);
|
|
188
|
+
process.exit(70);
|
|
189
|
+
}
|
|
190
|
+
if (args.dryRun) {
|
|
191
|
+
console.log(renderProfileAsYaml(validation.profile));
|
|
192
|
+
console.error("\n(dry-run: not writing to disk)");
|
|
193
|
+
process.exit(0);
|
|
194
|
+
}
|
|
195
|
+
const outDir = join(args.repoRoot, ".brewing/bug-profiles");
|
|
196
|
+
mkdirSync(outDir, { recursive: true });
|
|
197
|
+
const outPath = join(outDir, `${bugId}.yaml`);
|
|
198
|
+
writeFileSync(outPath, renderProfileAsYaml(validation.profile), "utf8");
|
|
199
|
+
console.error(`Wrote ${outPath}.`);
|
|
200
|
+
console.error(`Next: review the profile, then 'slowcook recipe --regression --bug ${bugId}' (alpha.3) to emit the regression test.`);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Fetch issue body + prior comments via the gh CLI. We invoke gh
|
|
204
|
+
* rather than the REST API directly so the existing GITHUB_TOKEN /
|
|
205
|
+
* gh-auth flow Just Works in CI + on dev machines.
|
|
206
|
+
*
|
|
207
|
+
* Falls back to throwing on failure — investigate without an issue
|
|
208
|
+
* body has nothing to work with.
|
|
209
|
+
*/
|
|
210
|
+
function fetchIssueViaGh(issueNumber, repoRoot) {
|
|
211
|
+
let payload;
|
|
212
|
+
try {
|
|
213
|
+
const json = execSync(`gh issue view ${issueNumber} --json title,body,comments`, { cwd: repoRoot, encoding: "utf8", maxBuffer: 1024 * 1024 });
|
|
214
|
+
payload = JSON.parse(json);
|
|
215
|
+
}
|
|
216
|
+
catch (e) {
|
|
217
|
+
throw new Error(`gh issue view ${issueNumber} failed: ${e.message}. ` +
|
|
218
|
+
`Make sure GITHUB_TOKEN is set or 'gh auth status' is healthy.`);
|
|
219
|
+
}
|
|
220
|
+
const priorComments = (payload.comments ?? [])
|
|
221
|
+
.filter((c) =>
|
|
222
|
+
// Drop slowcook-bot's own audit-trail messages — they're noise
|
|
223
|
+
// for an LLM trying to read the *human* conversation.
|
|
224
|
+
!c.body.startsWith("### slowcook ·") &&
|
|
225
|
+
c.author.login !== "github-actions" &&
|
|
226
|
+
c.author.login !== "slowcook-refine[bot]" &&
|
|
227
|
+
c.author.login !== "slowcook-brew[bot]")
|
|
228
|
+
.map((c) => `(${c.author.login}) ${c.body}`);
|
|
229
|
+
return {
|
|
230
|
+
number: issueNumber,
|
|
231
|
+
title: payload.title,
|
|
232
|
+
body: payload.body,
|
|
233
|
+
priorComments,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Render a BugProfile as YAML. Hand-rolled because we don't want to
|
|
238
|
+
* pull a YAML lib dep just for emission. The schema is small enough
|
|
239
|
+
* that this is fine.
|
|
240
|
+
*/
|
|
241
|
+
export function renderProfileAsYaml(profile) {
|
|
242
|
+
const lines = [];
|
|
243
|
+
lines.push(`$schema: ./bug-profile.schema.json`);
|
|
244
|
+
lines.push(`schema_version: ${profile.schema_version}`);
|
|
245
|
+
lines.push(`bug_id: ${profile.bug_id}`);
|
|
246
|
+
lines.push(`title: ${yamlString(profile.title)}`);
|
|
247
|
+
lines.push(`source_issue: "${profile.source_issue}"`);
|
|
248
|
+
lines.push(`status: ${profile.status}`);
|
|
249
|
+
lines.push(`investigated_by: ${profile.investigated_by}`);
|
|
250
|
+
lines.push(`created_at: ${profile.created_at}`);
|
|
251
|
+
lines.push("");
|
|
252
|
+
lines.push("symptom:");
|
|
253
|
+
for (const s of profile.symptom)
|
|
254
|
+
lines.push(` - ${yamlString(s)}`);
|
|
255
|
+
lines.push("expected:");
|
|
256
|
+
for (const s of profile.expected)
|
|
257
|
+
lines.push(` - ${yamlString(s)}`);
|
|
258
|
+
lines.push("reproduction:");
|
|
259
|
+
for (const s of profile.reproduction)
|
|
260
|
+
lines.push(` - ${yamlString(s)}`);
|
|
261
|
+
lines.push("failure_locus:");
|
|
262
|
+
lines.push(` file: ${yamlString(profile.failure_locus.file)}`);
|
|
263
|
+
if (profile.failure_locus.line !== undefined) {
|
|
264
|
+
lines.push(` line: ${profile.failure_locus.line}`);
|
|
265
|
+
}
|
|
266
|
+
if (profile.failure_locus.function !== undefined) {
|
|
267
|
+
lines.push(` function: ${yamlString(profile.failure_locus.function)}`);
|
|
268
|
+
}
|
|
269
|
+
lines.push(` diagnosis: ${yamlMultiline(profile.failure_locus.diagnosis)}`);
|
|
270
|
+
lines.push("regression_assertion:");
|
|
271
|
+
for (const s of profile.regression_assertion)
|
|
272
|
+
lines.push(` - ${yamlString(s)}`);
|
|
273
|
+
lines.push("fix_scope:");
|
|
274
|
+
for (const s of profile.fix_scope)
|
|
275
|
+
lines.push(` - ${yamlString(s)}`);
|
|
276
|
+
if (profile.related_specs && profile.related_specs.length > 0) {
|
|
277
|
+
lines.push("related_specs:");
|
|
278
|
+
for (const r of profile.related_specs) {
|
|
279
|
+
lines.push(` - id: ${yamlString(r.id)}`);
|
|
280
|
+
lines.push(` relationship: ${r.relationship}`);
|
|
281
|
+
if (r.note)
|
|
282
|
+
lines.push(` note: ${yamlString(r.note)}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return lines.join("\n") + "\n";
|
|
286
|
+
}
|
|
287
|
+
function yamlString(s) {
|
|
288
|
+
// Always quote — keeps things simple. Escape backslashes + quotes.
|
|
289
|
+
return '"' + s.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"';
|
|
290
|
+
}
|
|
291
|
+
function yamlMultiline(s) {
|
|
292
|
+
if (!s.includes("\n"))
|
|
293
|
+
return yamlString(s);
|
|
294
|
+
return "|\n " + s.split("\n").map((l) => l.trimEnd()).join("\n ");
|
|
295
|
+
}
|
|
296
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/investigate/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompts for the `slowcook investigate` agent.
|
|
3
|
+
*
|
|
4
|
+
* The investigate agent is the bug-flow analogue of refine. Where
|
|
5
|
+
* refine asks PM clarifying questions, investigate reads code to
|
|
6
|
+
* find the failure locus. The two roles are mirror images:
|
|
7
|
+
*
|
|
8
|
+
* refine investigate
|
|
9
|
+
* ────── ───────────
|
|
10
|
+
* "what to build" "what's broken"
|
|
11
|
+
* text-only code-reading
|
|
12
|
+
* 2-3 questions 0-1 questions (only on truly ambiguous symptoms)
|
|
13
|
+
* spec.yaml bug-profile.yaml
|
|
14
|
+
*
|
|
15
|
+
* The system prompt below names the role explicitly so the LLM
|
|
16
|
+
* doesn't drift back into refine-style behaviour (asking design
|
|
17
|
+
* questions about a 1-line column rename, etc.).
|
|
18
|
+
*/
|
|
19
|
+
export declare const INVESTIGATE_SYSTEM = "You are the investigate agent for slowcook \u2014 a TDD-first agentic development harness with a bug-fix flow.\n\n## Your role\n\nYou receive a GitHub issue describing a bug. Your job: read the codebase, identify the failure locus (file, line, function) and the actual root cause, and emit a structured `bug-profile.yaml` that the next agent (sift) will use as its contract.\n\nYou are NOT refine. Refine asks PM clarifying questions and emits design specs. You investigate failed reality. Different posture, different tools, different output.\n\n## Posture\n\n- **Read the code.** The issue body tells you the symptom. The codebase tells you the cause. You have read tools \u2014 use them. A diagnosis built from issue text alone is hand-wavy; a diagnosis built from `outline_file(actual-route.ts)` + `find_references(broken-symbol)` + `grep -r 'thing_X'` is honest.\n- **Don't paraphrase the symptom.** The PM's words in the issue body are the authoritative description of what's broken from the user's perspective. Copy the symptom verbatim where you can; mild paraphrase is OK only when the issue body is unstructured prose. (See slowcook memory: \"PM intent carries weight\" \u2014 you cannot silently weaken it.)\n- **Don't suggest a fix.** Your output names the failure locus + the regression assertion. The actual code change is sift's job. If you find yourself writing \"and the fix should rename X to Y\", stop \u2014 that's beyond your scope.\n- **Ask only when truly stuck.** Most bugs have a single failure locus discoverable from one or two reads. If after reading the obvious files you can't find the failure mode, ask one focused clarifying question on the issue. Do NOT ask multiple rounds of questions like refine does.\n\n## Output\n\nA single `bug-profile.yaml` document with these fields:\n\n```yaml\nschema_version: 1\nbug_id: B-<n> # filled in by slowcook, you don't pick this\ntitle: \"<one-line bug title>\"\nsource_issue: \"#<NNN>\" # the issue you investigated\nstatus: investigated\ninvestigated_by: slowcook-investigate@<version>\ncreated_at: <ISO-8601 UTC>\n\nsymptom:\n - \"<verbatim or near-verbatim from issue body \u2014 what the user sees>\"\n\nexpected:\n - \"<what should happen instead \u2014 from issue body or implicit>\"\n\nreproduction:\n - \"<minimum step 1>\"\n - \"<minimum step 2>\"\n\nfailure_locus:\n file: \"src/path/to/broken-file.ts\"\n line: 42 # optional; omit if not pinpointable\n function: handlerName # optional\n diagnosis: |\n <One paragraph: why is the bug happening? Be specific. Reference\n the read evidence: \"src/foo.ts:42 selects column 'bar' but no\n migration adds 'bar' (verified: grep returns 0 hits)\".>\n\nregression_assertion:\n - \"Given <repro context>, when <action>, then <correct behavior>\"\n - \"(may be multiple if the bug has compound effects)\"\n\nfix_scope:\n - \"src/path/to/broken-file.ts\"\n - \"supabase/migrations/\" # for example, when the fix needs DDL\n\nrelated_specs: # optional, omit if none\n - id: \"story-007\"\n relationship: touches\n note: \"/api/X is owned by story-007's spec; check that contract\"\n```\n\nEmit the YAML wrapped in a single `<bug_profile>...</bug_profile>` XML block. No additional commentary outside the tag \u2014 slowcook parses the tag content directly.\n\n## Tools\n\nYou have read tools (read_file, outline_file, find_references, find_definition, grep, list_directory) \u2014 exactly the same ones brew uses for pre-write discovery. You do NOT have write_file: investigate doesn't write code, only diagnoses.\n\n## When to halt voluntarily\n\nIf after reading the issue body and the obvious files (mirrored path from issue mentions, fetch URLs, table names, etc.) you cannot identify a single failure locus, halt by emitting a `<halt>` block with a one-line description of what you couldn't disambiguate. Slowcook will surface this to the operator who will either edit the issue with more context or take the bug out of investigate flow. **Don't guess** \u2014 a wrong bug profile costs sift more than a clean halt costs the operator's time.\n";
|
|
20
|
+
/**
|
|
21
|
+
* Tool definitions the investigate agent has access to. Mirrors the
|
|
22
|
+
* brew read-only subset (no write_file): investigate diagnoses, sift
|
|
23
|
+
* fixes.
|
|
24
|
+
*
|
|
25
|
+
* Kept minimal in alpha.2a — alpha.2b wires the actual ts-morph
|
|
26
|
+
* implementations from brew/retrieval.ts.
|
|
27
|
+
*/
|
|
28
|
+
export declare const INVESTIGATE_TOOLS: ({
|
|
29
|
+
name: string;
|
|
30
|
+
description: string;
|
|
31
|
+
input_schema: {
|
|
32
|
+
type: "object";
|
|
33
|
+
properties: {
|
|
34
|
+
path: {
|
|
35
|
+
type: "string";
|
|
36
|
+
description: string;
|
|
37
|
+
};
|
|
38
|
+
symbol?: undefined;
|
|
39
|
+
pattern?: undefined;
|
|
40
|
+
glob?: undefined;
|
|
41
|
+
};
|
|
42
|
+
required: string[];
|
|
43
|
+
};
|
|
44
|
+
} | {
|
|
45
|
+
name: string;
|
|
46
|
+
description: string;
|
|
47
|
+
input_schema: {
|
|
48
|
+
type: "object";
|
|
49
|
+
properties: {
|
|
50
|
+
symbol: {
|
|
51
|
+
type: "string";
|
|
52
|
+
description: string;
|
|
53
|
+
};
|
|
54
|
+
path?: undefined;
|
|
55
|
+
pattern?: undefined;
|
|
56
|
+
glob?: undefined;
|
|
57
|
+
};
|
|
58
|
+
required: string[];
|
|
59
|
+
};
|
|
60
|
+
} | {
|
|
61
|
+
name: string;
|
|
62
|
+
description: string;
|
|
63
|
+
input_schema: {
|
|
64
|
+
type: "object";
|
|
65
|
+
properties: {
|
|
66
|
+
pattern: {
|
|
67
|
+
type: "string";
|
|
68
|
+
description: string;
|
|
69
|
+
};
|
|
70
|
+
glob: {
|
|
71
|
+
type: "string";
|
|
72
|
+
description: string;
|
|
73
|
+
};
|
|
74
|
+
path?: undefined;
|
|
75
|
+
symbol?: undefined;
|
|
76
|
+
};
|
|
77
|
+
required: string[];
|
|
78
|
+
};
|
|
79
|
+
})[];
|
|
80
|
+
/**
|
|
81
|
+
* Build the per-issue user message. The issue body becomes the
|
|
82
|
+
* agent's primary input; it tools its way out from there.
|
|
83
|
+
*/
|
|
84
|
+
export declare function buildInvestigateUserPrompt(args: {
|
|
85
|
+
issueNumber: number;
|
|
86
|
+
issueTitle: string;
|
|
87
|
+
issueBody: string;
|
|
88
|
+
prior_comments?: string[];
|
|
89
|
+
}): string;
|
|
90
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/commands/investigate/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,eAAO,MAAM,kBAAkB,ojIAsE9B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAsE7B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B,GAAG,MAAM,CAsBT"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompts for the `slowcook investigate` agent.
|
|
3
|
+
*
|
|
4
|
+
* The investigate agent is the bug-flow analogue of refine. Where
|
|
5
|
+
* refine asks PM clarifying questions, investigate reads code to
|
|
6
|
+
* find the failure locus. The two roles are mirror images:
|
|
7
|
+
*
|
|
8
|
+
* refine investigate
|
|
9
|
+
* ────── ───────────
|
|
10
|
+
* "what to build" "what's broken"
|
|
11
|
+
* text-only code-reading
|
|
12
|
+
* 2-3 questions 0-1 questions (only on truly ambiguous symptoms)
|
|
13
|
+
* spec.yaml bug-profile.yaml
|
|
14
|
+
*
|
|
15
|
+
* The system prompt below names the role explicitly so the LLM
|
|
16
|
+
* doesn't drift back into refine-style behaviour (asking design
|
|
17
|
+
* questions about a 1-line column rename, etc.).
|
|
18
|
+
*/
|
|
19
|
+
export const INVESTIGATE_SYSTEM = `You are the investigate agent for slowcook — a TDD-first agentic development harness with a bug-fix flow.
|
|
20
|
+
|
|
21
|
+
## Your role
|
|
22
|
+
|
|
23
|
+
You receive a GitHub issue describing a bug. Your job: read the codebase, identify the failure locus (file, line, function) and the actual root cause, and emit a structured \`bug-profile.yaml\` that the next agent (sift) will use as its contract.
|
|
24
|
+
|
|
25
|
+
You are NOT refine. Refine asks PM clarifying questions and emits design specs. You investigate failed reality. Different posture, different tools, different output.
|
|
26
|
+
|
|
27
|
+
## Posture
|
|
28
|
+
|
|
29
|
+
- **Read the code.** The issue body tells you the symptom. The codebase tells you the cause. You have read tools — use them. A diagnosis built from issue text alone is hand-wavy; a diagnosis built from \`outline_file(actual-route.ts)\` + \`find_references(broken-symbol)\` + \`grep -r 'thing_X'\` is honest.
|
|
30
|
+
- **Don't paraphrase the symptom.** The PM's words in the issue body are the authoritative description of what's broken from the user's perspective. Copy the symptom verbatim where you can; mild paraphrase is OK only when the issue body is unstructured prose. (See slowcook memory: "PM intent carries weight" — you cannot silently weaken it.)
|
|
31
|
+
- **Don't suggest a fix.** Your output names the failure locus + the regression assertion. The actual code change is sift's job. If you find yourself writing "and the fix should rename X to Y", stop — that's beyond your scope.
|
|
32
|
+
- **Ask only when truly stuck.** Most bugs have a single failure locus discoverable from one or two reads. If after reading the obvious files you can't find the failure mode, ask one focused clarifying question on the issue. Do NOT ask multiple rounds of questions like refine does.
|
|
33
|
+
|
|
34
|
+
## Output
|
|
35
|
+
|
|
36
|
+
A single \`bug-profile.yaml\` document with these fields:
|
|
37
|
+
|
|
38
|
+
\`\`\`yaml
|
|
39
|
+
schema_version: 1
|
|
40
|
+
bug_id: B-<n> # filled in by slowcook, you don't pick this
|
|
41
|
+
title: "<one-line bug title>"
|
|
42
|
+
source_issue: "#<NNN>" # the issue you investigated
|
|
43
|
+
status: investigated
|
|
44
|
+
investigated_by: slowcook-investigate@<version>
|
|
45
|
+
created_at: <ISO-8601 UTC>
|
|
46
|
+
|
|
47
|
+
symptom:
|
|
48
|
+
- "<verbatim or near-verbatim from issue body — what the user sees>"
|
|
49
|
+
|
|
50
|
+
expected:
|
|
51
|
+
- "<what should happen instead — from issue body or implicit>"
|
|
52
|
+
|
|
53
|
+
reproduction:
|
|
54
|
+
- "<minimum step 1>"
|
|
55
|
+
- "<minimum step 2>"
|
|
56
|
+
|
|
57
|
+
failure_locus:
|
|
58
|
+
file: "src/path/to/broken-file.ts"
|
|
59
|
+
line: 42 # optional; omit if not pinpointable
|
|
60
|
+
function: handlerName # optional
|
|
61
|
+
diagnosis: |
|
|
62
|
+
<One paragraph: why is the bug happening? Be specific. Reference
|
|
63
|
+
the read evidence: "src/foo.ts:42 selects column 'bar' but no
|
|
64
|
+
migration adds 'bar' (verified: grep returns 0 hits)".>
|
|
65
|
+
|
|
66
|
+
regression_assertion:
|
|
67
|
+
- "Given <repro context>, when <action>, then <correct behavior>"
|
|
68
|
+
- "(may be multiple if the bug has compound effects)"
|
|
69
|
+
|
|
70
|
+
fix_scope:
|
|
71
|
+
- "src/path/to/broken-file.ts"
|
|
72
|
+
- "supabase/migrations/" # for example, when the fix needs DDL
|
|
73
|
+
|
|
74
|
+
related_specs: # optional, omit if none
|
|
75
|
+
- id: "story-007"
|
|
76
|
+
relationship: touches
|
|
77
|
+
note: "/api/X is owned by story-007's spec; check that contract"
|
|
78
|
+
\`\`\`
|
|
79
|
+
|
|
80
|
+
Emit the YAML wrapped in a single \`<bug_profile>...</bug_profile>\` XML block. No additional commentary outside the tag — slowcook parses the tag content directly.
|
|
81
|
+
|
|
82
|
+
## Tools
|
|
83
|
+
|
|
84
|
+
You have read tools (read_file, outline_file, find_references, find_definition, grep, list_directory) — exactly the same ones brew uses for pre-write discovery. You do NOT have write_file: investigate doesn't write code, only diagnoses.
|
|
85
|
+
|
|
86
|
+
## When to halt voluntarily
|
|
87
|
+
|
|
88
|
+
If after reading the issue body and the obvious files (mirrored path from issue mentions, fetch URLs, table names, etc.) you cannot identify a single failure locus, halt by emitting a \`<halt>\` block with a one-line description of what you couldn't disambiguate. Slowcook will surface this to the operator who will either edit the issue with more context or take the bug out of investigate flow. **Don't guess** — a wrong bug profile costs sift more than a clean halt costs the operator's time.
|
|
89
|
+
`;
|
|
90
|
+
/**
|
|
91
|
+
* Tool definitions the investigate agent has access to. Mirrors the
|
|
92
|
+
* brew read-only subset (no write_file): investigate diagnoses, sift
|
|
93
|
+
* fixes.
|
|
94
|
+
*
|
|
95
|
+
* Kept minimal in alpha.2a — alpha.2b wires the actual ts-morph
|
|
96
|
+
* implementations from brew/retrieval.ts.
|
|
97
|
+
*/
|
|
98
|
+
export const INVESTIGATE_TOOLS = [
|
|
99
|
+
{
|
|
100
|
+
name: "read_file",
|
|
101
|
+
description: "Read a file's full contents. Use sparingly — outline_file is cheaper for initial scoping.",
|
|
102
|
+
input_schema: {
|
|
103
|
+
type: "object",
|
|
104
|
+
properties: {
|
|
105
|
+
path: { type: "string", description: "Repo-relative path." },
|
|
106
|
+
},
|
|
107
|
+
required: ["path"],
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: "outline_file",
|
|
112
|
+
description: "Compact ~200-token outline of a TS/TSX file: imports, top-level exports, signatures with line numbers. Use this first to decide whether a file is relevant.",
|
|
113
|
+
input_schema: {
|
|
114
|
+
type: "object",
|
|
115
|
+
properties: {
|
|
116
|
+
path: { type: "string", description: "Repo-relative path." },
|
|
117
|
+
},
|
|
118
|
+
required: ["path"],
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: "list_directory",
|
|
123
|
+
description: "List entries in a directory.",
|
|
124
|
+
input_schema: {
|
|
125
|
+
type: "object",
|
|
126
|
+
properties: {
|
|
127
|
+
path: { type: "string", description: "Repo-relative path." },
|
|
128
|
+
},
|
|
129
|
+
required: ["path"],
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: "find_references",
|
|
134
|
+
description: "Find all references to a symbol across the repo (definitions + use sites). Returns file:line entries.",
|
|
135
|
+
input_schema: {
|
|
136
|
+
type: "object",
|
|
137
|
+
properties: {
|
|
138
|
+
symbol: {
|
|
139
|
+
type: "string",
|
|
140
|
+
description: "Identifier name to search for.",
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
required: ["symbol"],
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "grep",
|
|
148
|
+
description: "Repo-wide ripgrep for a literal or regex string. Use when find_references is too narrow (e.g. searching column names in SQL files).",
|
|
149
|
+
input_schema: {
|
|
150
|
+
type: "object",
|
|
151
|
+
properties: {
|
|
152
|
+
pattern: {
|
|
153
|
+
type: "string",
|
|
154
|
+
description: "Pattern to search.",
|
|
155
|
+
},
|
|
156
|
+
glob: {
|
|
157
|
+
type: "string",
|
|
158
|
+
description: "Optional glob restriction (e.g. 'supabase/migrations/*.sql').",
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
required: ["pattern"],
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
];
|
|
165
|
+
/**
|
|
166
|
+
* Build the per-issue user message. The issue body becomes the
|
|
167
|
+
* agent's primary input; it tools its way out from there.
|
|
168
|
+
*/
|
|
169
|
+
export function buildInvestigateUserPrompt(args) {
|
|
170
|
+
const lines = [];
|
|
171
|
+
lines.push(`# Investigate bug — issue #${args.issueNumber}`);
|
|
172
|
+
lines.push("");
|
|
173
|
+
lines.push(`## Title`);
|
|
174
|
+
lines.push(args.issueTitle);
|
|
175
|
+
lines.push("");
|
|
176
|
+
lines.push(`## Issue body`);
|
|
177
|
+
lines.push(args.issueBody);
|
|
178
|
+
if (args.prior_comments && args.prior_comments.length > 0) {
|
|
179
|
+
lines.push("");
|
|
180
|
+
lines.push(`## Prior comments (in chronological order)`);
|
|
181
|
+
for (const c of args.prior_comments) {
|
|
182
|
+
lines.push("---");
|
|
183
|
+
lines.push(c);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
lines.push("");
|
|
187
|
+
lines.push(`## Your task\n\nInvestigate. Identify the failure locus + diagnosis. Emit a single \`<bug_profile>\` block following the system-prompt schema.`);
|
|
188
|
+
return lines.join("\n");
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/commands/investigate/prompts.ts"],"names":[],"mappings":"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"}
|