@bastani/atomic 0.5.17 → 0.5.18-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts +50 -54
- package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts +17 -36
- package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/heuristic.d.ts +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.d.ts +64 -44
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/scratch.d.ts +43 -0
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/scratch.d.ts.map +1 -0
- package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts +17 -39
- package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli.ts +21 -2
- package/src/commands/cli/session.test.ts +223 -0
- package/src/commands/cli/session.ts +117 -1
- package/src/completions/bash.ts +3 -3
- package/src/completions/fish.ts +13 -7
- package/src/completions/powershell.ts +3 -0
- package/src/completions/zsh.ts +2 -1
- package/src/sdk/workflows/builtin/deep-research-codebase/claude/index.ts +260 -157
- package/src/sdk/workflows/builtin/deep-research-codebase/copilot/index.ts +224 -125
- package/src/sdk/workflows/builtin/deep-research-codebase/helpers/heuristic.ts +2 -2
- package/src/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.ts +428 -469
- package/src/sdk/workflows/builtin/deep-research-codebase/helpers/scratch.ts +115 -0
- package/src/sdk/workflows/builtin/deep-research-codebase/opencode/index.ts +249 -137
|
@@ -1,20 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Prompt builders for the deep-research-codebase workflow.
|
|
3
3
|
*
|
|
4
|
+
* Each builder produces a focused, single-responsibility prompt for one
|
|
5
|
+
* specialist sub-agent. The sub-agents themselves are dispatched as separate
|
|
6
|
+
* `ctx.stage(...)` calls via the provider SDK's native `agent` parameter
|
|
7
|
+
* (Claude SDK options, Copilot sessionOpts, OpenCode session.prompt). Because
|
|
8
|
+
* each sub-agent already carries a detailed system prompt in `.claude/agents/`,
|
|
9
|
+
* `.opencode/agents/`, and `.github/agents/`, these user-prompts are intentionally
|
|
10
|
+
* short — they only supply the topic, the scope, and the output shape the
|
|
11
|
+
* downstream synthesizer expects.
|
|
12
|
+
*
|
|
4
13
|
* Context-engineering principles applied throughout:
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
14
|
+
*
|
|
15
|
+
* • Position-aware framing: the research question is repeated at the TOP
|
|
16
|
+
* and BOTTOM of every prompt. Long-context recall is strongest at the
|
|
17
|
+
* edges of the context window (see `context-fundamentals`).
|
|
18
|
+
*
|
|
19
|
+
* • Informativity over exhaustiveness: each per-partition prompt embeds
|
|
20
|
+
* ONLY that partition's directories — never the full file list. This
|
|
21
|
+
* keeps token cost roughly constant in N rather than O(N²).
|
|
22
|
+
*
|
|
23
|
+
* • Forward-only data flow: the analyzer prompt embeds the locator's
|
|
24
|
+
* output verbatim; the online-researcher prompt does the same. No
|
|
25
|
+
* sub-agent has to re-discover what its sibling already produced.
|
|
26
|
+
*
|
|
27
|
+
* • Trailing-prose guarantee (failure-modes F6): every prompt asks for a
|
|
28
|
+
* short prose recap as the final assistant turn so downstream stages
|
|
29
|
+
* reading via `transcript()` never get an empty string when the agent
|
|
30
|
+
* ends on a tool call.
|
|
31
|
+
*
|
|
32
|
+
* • Documentarian framing: every prompt explicitly forbids critique or
|
|
33
|
+
* improvement suggestions. We are recording what EXISTS.
|
|
34
|
+
*
|
|
35
|
+
* • File-based handoff (filesystem-context skill): explorer findings are
|
|
36
|
+
* written deterministically to a scratch file by TypeScript (no extra
|
|
37
|
+
* LLM "synthesizer" stage) and the aggregator reads them by path.
|
|
18
38
|
*/
|
|
19
39
|
|
|
20
40
|
import path from "node:path";
|
|
@@ -25,6 +45,11 @@ const DOCUMENTARIAN_DISCLAIMER =
|
|
|
25
45
|
"propose improvements, identify issues, or suggest refactors. Focus on " +
|
|
26
46
|
"concrete file paths, line numbers, and how things actually work.";
|
|
27
47
|
|
|
48
|
+
const TRAILING_PROSE_REMINDER =
|
|
49
|
+
"End your turn with a short prose paragraph summarising what you produced. " +
|
|
50
|
+
"Do NOT end the turn on a tool call — downstream stages read your assistant " +
|
|
51
|
+
"transcript and will see nothing if the final message is a tool invocation.";
|
|
52
|
+
|
|
28
53
|
/** Slugify the user's prompt for use in the final research filename. */
|
|
29
54
|
export function slugifyPrompt(prompt: string): string {
|
|
30
55
|
const slug = prompt
|
|
@@ -38,8 +63,31 @@ export function slugifyPrompt(prompt: string): string {
|
|
|
38
63
|
return slug || "research";
|
|
39
64
|
}
|
|
40
65
|
|
|
66
|
+
/** Render a partition's directory list as absolute paths with file/LOC counts. */
|
|
67
|
+
function renderPartitionAssignment(
|
|
68
|
+
partition: PartitionUnit[],
|
|
69
|
+
root: string,
|
|
70
|
+
): string {
|
|
71
|
+
return partition
|
|
72
|
+
.map((u) => {
|
|
73
|
+
const abs = path.join(root, u.path);
|
|
74
|
+
return ` - \`${abs}/\` (${u.fileCount} files, ${u.loc.toLocaleString()} LOC)`;
|
|
75
|
+
})
|
|
76
|
+
.join("\n");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Comma-separated absolute directory list (for inline grep/glob scope hints). */
|
|
80
|
+
function renderPartitionDirsAbs(
|
|
81
|
+
partition: PartitionUnit[],
|
|
82
|
+
root: string,
|
|
83
|
+
): string {
|
|
84
|
+
return partition
|
|
85
|
+
.map((u) => `\`${path.join(root, u.path)}\``)
|
|
86
|
+
.join(", ");
|
|
87
|
+
}
|
|
88
|
+
|
|
41
89
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
42
|
-
// Stage
|
|
90
|
+
// Stage 1a — codebase-scout (single LLM orientation call)
|
|
43
91
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
44
92
|
|
|
45
93
|
export function buildScoutPrompt(opts: {
|
|
@@ -69,9 +117,9 @@ export function buildScoutPrompt(opts: {
|
|
|
69
117
|
``,
|
|
70
118
|
`- Total source files: ${opts.totalFiles.toLocaleString()}`,
|
|
71
119
|
`- Total LOC: ${opts.totalLoc.toLocaleString()}`,
|
|
72
|
-
`-
|
|
120
|
+
`- Partitions to investigate: ${opts.explorerCount} (chosen by LOC heuristic)`,
|
|
73
121
|
``,
|
|
74
|
-
`Pre-computed partition assignments (${opts.explorerCount}
|
|
122
|
+
`Pre-computed partition assignments (${opts.explorerCount} partitions):`,
|
|
75
123
|
partitionPreview,
|
|
76
124
|
``,
|
|
77
125
|
`Compact directory tree (depth 3, ≤200 entries):`,
|
|
@@ -82,8 +130,7 @@ export function buildScoutPrompt(opts: {
|
|
|
82
130
|
``,
|
|
83
131
|
`<TASK>`,
|
|
84
132
|
`Read the tree above and produce a brief architectural orientation that`,
|
|
85
|
-
`
|
|
86
|
-
`layout BEFORE they dive into their assigned partitions.`,
|
|
133
|
+
`the downstream specialist sub-agents will use to anchor their searches.`,
|
|
87
134
|
``,
|
|
88
135
|
`Cover, in ≤300 words:`,
|
|
89
136
|
` 1. The repo's overall shape (monorepo vs single package, polyglot or not)`,
|
|
@@ -92,16 +139,15 @@ export function buildScoutPrompt(opts: {
|
|
|
92
139
|
` 4. Where entry points or main modules likely live`,
|
|
93
140
|
``,
|
|
94
141
|
`Do NOT attempt to answer the research question yet — your job is`,
|
|
95
|
-
`orientation for downstream
|
|
96
|
-
`Read/Glob/Grep sparingly to verify
|
|
142
|
+
`orientation for downstream specialists, not investigation. You may use`,
|
|
143
|
+
`Read/Glob/Grep sparingly to verify guesses about a few key files,`,
|
|
97
144
|
`but keep the output short.`,
|
|
98
145
|
`</TASK>`,
|
|
99
146
|
``,
|
|
100
147
|
`<CONSTRAINTS>`,
|
|
101
148
|
DOCUMENTARIAN_DISCLAIMER,
|
|
102
149
|
`Stay under 300 words. No bullet lists longer than 5 items.`,
|
|
103
|
-
|
|
104
|
-
`has content for downstream stages to read.`,
|
|
150
|
+
TRAILING_PROSE_REMINDER,
|
|
105
151
|
`</CONSTRAINTS>`,
|
|
106
152
|
``,
|
|
107
153
|
`<RESEARCH_QUESTION_REMINDER>`,
|
|
@@ -111,32 +157,29 @@ export function buildScoutPrompt(opts: {
|
|
|
111
157
|
}
|
|
112
158
|
|
|
113
159
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
114
|
-
// Stage 2 —
|
|
160
|
+
// Stage 2 — per-partition specialist sub-agents
|
|
115
161
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
162
|
+
//
|
|
163
|
+
// Four specialists run per partition, dispatched as separate headless stages
|
|
164
|
+
// via the provider SDK's native `agent` parameter. Two layers of parallelism:
|
|
165
|
+
//
|
|
166
|
+
// Layer 1 (independent searches): locator ∥ pattern-finder
|
|
167
|
+
// Layer 2 (depend on locator): analyzer ∥ online-researcher
|
|
168
|
+
//
|
|
169
|
+
// The deterministic synthesis step (helpers/scratch.ts) then concatenates
|
|
170
|
+
// the four outputs into the explorer scratch file the aggregator will read.
|
|
116
171
|
|
|
117
|
-
|
|
172
|
+
/** codebase-locator — find files in the partition relevant to the question. */
|
|
173
|
+
export function buildLocatorPrompt(opts: {
|
|
118
174
|
question: string;
|
|
119
|
-
index: number;
|
|
120
|
-
total: number;
|
|
121
175
|
partition: PartitionUnit[];
|
|
122
|
-
scoutOverview: string;
|
|
123
|
-
scratchPath: string;
|
|
124
176
|
root: string;
|
|
177
|
+
scoutOverview: string;
|
|
178
|
+
index: number;
|
|
179
|
+
total: number;
|
|
125
180
|
}): string {
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
const abs = path.join(opts.root, u.path);
|
|
129
|
-
return ` - \`${abs}/\` (${u.fileCount} files, ${u.loc.toLocaleString()} LOC)`;
|
|
130
|
-
})
|
|
131
|
-
.join("\n");
|
|
132
|
-
|
|
133
|
-
// Comma-separated absolute dir list — used in subagent dispatch prompts as
|
|
134
|
-
// an unambiguous scope constraint that the locator/pattern-finder can pass
|
|
135
|
-
// straight to Glob.
|
|
136
|
-
const dirListAbs = opts.partition
|
|
137
|
-
.map((u) => `\`${path.join(opts.root, u.path)}\``)
|
|
138
|
-
.join(", ");
|
|
139
|
-
|
|
181
|
+
const assignment = renderPartitionAssignment(opts.partition, opts.root);
|
|
182
|
+
const dirsAbs = renderPartitionDirsAbs(opts.partition, opts.root);
|
|
140
183
|
const orientation =
|
|
141
184
|
opts.scoutOverview.trim().length > 0
|
|
142
185
|
? opts.scoutOverview.trim()
|
|
@@ -147,143 +190,58 @@ export function buildExplorerPrompt(opts: {
|
|
|
147
190
|
opts.question,
|
|
148
191
|
`</RESEARCH_QUESTION>`,
|
|
149
192
|
``,
|
|
150
|
-
`<
|
|
151
|
-
`You are
|
|
152
|
-
`
|
|
153
|
-
`
|
|
154
|
-
|
|
155
|
-
`explorers — you are responsible for your assigned slice. Other explorers`,
|
|
156
|
-
`are simultaneously covering the rest.`,
|
|
157
|
-
`</YOUR_IDENTITY>`,
|
|
193
|
+
`<MISSION>`,
|
|
194
|
+
`You are the codebase-locator for partition ${opts.index} of ${opts.total} in a`,
|
|
195
|
+
`deep-research workflow. Find every file inside the SCOPE below that`,
|
|
196
|
+
`relates to the research question, and return a categorized index.`,
|
|
197
|
+
`</MISSION>`,
|
|
158
198
|
``,
|
|
159
199
|
`<ARCHITECTURAL_ORIENTATION>`,
|
|
160
|
-
`The codebase scout produced this overview to help you orient before dispatch:`,
|
|
161
|
-
``,
|
|
162
200
|
orientation,
|
|
163
201
|
`</ARCHITECTURAL_ORIENTATION>`,
|
|
164
202
|
``,
|
|
165
|
-
`<
|
|
166
|
-
`
|
|
167
|
-
`
|
|
168
|
-
``,
|
|
169
|
-
assignmentLines,
|
|
170
|
-
`</YOUR_ASSIGNMENT>`,
|
|
171
|
-
``,
|
|
172
|
-
`<RESEARCH_PROTOCOL>`,
|
|
173
|
-
`Execute these steps IN ORDER. Each numbered step must complete before the`,
|
|
174
|
-
`next begins. Use the exact \`@"name (agent)"\` dispatch syntax shown below.`,
|
|
175
|
-
``,
|
|
176
|
-
`── STEP 1 — Locate relevant files (codebase-locator) ──`,
|
|
177
|
-
``,
|
|
178
|
-
`Dispatch the codebase-locator. Constrain it strictly to your assigned dirs:`,
|
|
179
|
-
``,
|
|
180
|
-
` @"codebase-locator (agent)" CRITICAL: search ONLY within these directories`,
|
|
181
|
-
` (do not search elsewhere): ${dirListAbs}.`,
|
|
182
|
-
``,
|
|
183
|
-
` Find files in those directories that relate to this research question:`,
|
|
184
|
-
` "${opts.question}"`,
|
|
185
|
-
``,
|
|
186
|
-
` Categorize results by purpose: implementation, tests, types, config,`,
|
|
187
|
-
` examples, docs. Return absolute paths grouped by category.`,
|
|
188
|
-
``,
|
|
189
|
-
`── STEP 2 — Analyze the most relevant files (codebase-analyzer) ──`,
|
|
190
|
-
``,
|
|
191
|
-
`Pick the 5-10 most relevant IMPLEMENTATION files from STEP 1's output and`,
|
|
192
|
-
`dispatch the codebase-analyzer:`,
|
|
193
|
-
``,
|
|
194
|
-
` @"codebase-analyzer (agent)" Document how the following files work as`,
|
|
195
|
-
` they relate to the research question "${opts.question}":`,
|
|
196
|
-
` <list the files you picked, one per line>`,
|
|
197
|
-
``,
|
|
198
|
-
` Cover control flow, data flow, key abstractions, and any external`,
|
|
199
|
-
` dependencies. Use file:line references throughout. Do NOT critique or`,
|
|
200
|
-
` suggest improvements — describe what exists.`,
|
|
201
|
-
``,
|
|
202
|
-
`── STEP 3 — Find existing patterns (codebase-pattern-finder) ──`,
|
|
203
|
-
``,
|
|
204
|
-
`Dispatch the pattern-finder, scoped to your dirs:`,
|
|
203
|
+
`<SCOPE>`,
|
|
204
|
+
`Search ONLY within these directories. Other partitions cover the rest of`,
|
|
205
|
+
`the codebase — do NOT wander outside your scope:`,
|
|
205
206
|
``,
|
|
206
|
-
|
|
207
|
-
` directories: ${dirListAbs}.`,
|
|
207
|
+
assignment,
|
|
208
208
|
``,
|
|
209
|
-
`
|
|
210
|
-
|
|
211
|
-
``,
|
|
212
|
-
`── STEP 4 — External documentation research (CONDITIONAL) ──`,
|
|
213
|
-
``,
|
|
214
|
-
`ONLY run this step IF Step 2 surfaced external library or dependency`,
|
|
215
|
-
`usage that is CENTRAL to answering the research question. Otherwise SKIP.`,
|
|
216
|
-
``,
|
|
217
|
-
`If applicable, dispatch:`,
|
|
218
|
-
``,
|
|
219
|
-
` @"codebase-online-researcher (agent)" Research the documentation for`,
|
|
220
|
-
` <library/dependency name> as it relates to: "${opts.question}".`,
|
|
221
|
-
``,
|
|
222
|
-
` Return links and concrete findings. The agent should follow the`,
|
|
223
|
-
` token-efficient fetch order described in its instructions.`,
|
|
224
|
-
``,
|
|
225
|
-
`── STEP 5 — Synthesize and write findings ──`,
|
|
226
|
-
``,
|
|
227
|
-
`Combine the outputs from Steps 1-4 into a single markdown document and`,
|
|
228
|
-
`use the Write tool to write it to:`,
|
|
229
|
-
``,
|
|
230
|
-
` ${opts.scratchPath}`,
|
|
231
|
-
``,
|
|
232
|
-
`Use the OUTPUT_FORMAT below.`,
|
|
233
|
-
``,
|
|
234
|
-
`── STEP 6 — Brief summary ──`,
|
|
235
|
-
``,
|
|
236
|
-
`As your final response (after the Write tool call), output a 2-3 sentence`,
|
|
237
|
-
`prose summary of what you found. This is REQUIRED so the aggregator can`,
|
|
238
|
-
`index your report and the transcript is not empty.`,
|
|
239
|
-
`</RESEARCH_PROTOCOL>`,
|
|
209
|
+
`(Quick comma-separated form for tool args: ${dirsAbs})`,
|
|
210
|
+
`</SCOPE>`,
|
|
240
211
|
``,
|
|
241
212
|
`<OUTPUT_FORMAT>`,
|
|
242
|
-
`
|
|
243
|
-
`sections, in this order. Each section should reflect what the corresponding`,
|
|
244
|
-
`sub-agent returned:`,
|
|
245
|
-
``,
|
|
246
|
-
`# Explorer ${opts.index} Findings`,
|
|
213
|
+
`Return a markdown report with this exact structure:`,
|
|
247
214
|
``,
|
|
248
|
-
|
|
249
|
-
|
|
215
|
+
`### Implementation`,
|
|
216
|
+
`- \`<absolute path>\` — 1-line note on relevance`,
|
|
250
217
|
``,
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
`research question.`,
|
|
218
|
+
`### Tests`,
|
|
219
|
+
`- ...`,
|
|
254
220
|
``,
|
|
255
|
-
|
|
256
|
-
|
|
221
|
+
`### Types / Interfaces`,
|
|
222
|
+
`- ...`,
|
|
257
223
|
``,
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
`with file:line references throughout.`,
|
|
224
|
+
`### Configuration`,
|
|
225
|
+
`- ...`,
|
|
261
226
|
``,
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
`file:line refs.`,
|
|
227
|
+
`### Examples / Fixtures`,
|
|
228
|
+
`- ...`,
|
|
265
229
|
``,
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
`Otherwise omit this section. Include links the online researcher returned.`,
|
|
230
|
+
`### Documentation`,
|
|
231
|
+
`- ...`,
|
|
269
232
|
``,
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
`with a 1-line note on why each is relevant.`,
|
|
233
|
+
`### Notable Clusters`,
|
|
234
|
+
`- \`<absolute dir>/\` — N files, why it's a cluster`,
|
|
273
235
|
``,
|
|
274
|
-
|
|
275
|
-
`
|
|
276
|
-
`description of what's in it.`,
|
|
236
|
+
`Omit any section that has no entries (do not write "(none)" placeholders).`,
|
|
237
|
+
`Use ABSOLUTE paths. Do NOT read file contents — your job is location only.`,
|
|
277
238
|
`</OUTPUT_FORMAT>`,
|
|
278
239
|
``,
|
|
279
240
|
`<CONSTRAINTS>`,
|
|
280
241
|
DOCUMENTARIAN_DISCLAIMER,
|
|
281
|
-
`
|
|
282
|
-
`Do
|
|
283
|
-
|
|
284
|
-
`Do NOT use Read/Glob/Grep directly — coordinate via sub-agents only.`,
|
|
285
|
-
`End your turn with the required 2-3 sentence prose summary AFTER writing`,
|
|
286
|
-
`the file (do not end on a tool call).`,
|
|
242
|
+
`Restrict every grep/glob to the SCOPE above.`,
|
|
243
|
+
`Do not analyse implementations — siblings (analyzer, pattern-finder) cover that.`,
|
|
244
|
+
TRAILING_PROSE_REMINDER,
|
|
287
245
|
`</CONSTRAINTS>`,
|
|
288
246
|
``,
|
|
289
247
|
`<RESEARCH_QUESTION_REMINDER>`,
|
|
@@ -292,83 +250,64 @@ export function buildExplorerPrompt(opts: {
|
|
|
292
250
|
].join("\n");
|
|
293
251
|
}
|
|
294
252
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* The research-history scout dispatches specialized sub-agents to surface
|
|
301
|
-
* historical context from the project's `research/` directory:
|
|
302
|
-
* - codebase-research-locator → finds prior research docs about the topic
|
|
303
|
-
* - codebase-research-analyzer → extracts key insights from the most
|
|
304
|
-
* relevant docs
|
|
305
|
-
*
|
|
306
|
-
* Output is consumed via session transcript (not file write) — kept short
|
|
307
|
-
* (≤400 words) so the aggregator can embed it cheaply.
|
|
308
|
-
*/
|
|
309
|
-
export function buildHistoryPrompt(opts: {
|
|
253
|
+
/** codebase-pattern-finder — surface concrete reusable code patterns. */
|
|
254
|
+
export function buildPatternFinderPrompt(opts: {
|
|
310
255
|
question: string;
|
|
256
|
+
partition: PartitionUnit[];
|
|
311
257
|
root: string;
|
|
258
|
+
scoutOverview: string;
|
|
259
|
+
index: number;
|
|
260
|
+
total: number;
|
|
312
261
|
}): string {
|
|
262
|
+
const assignment = renderPartitionAssignment(opts.partition, opts.root);
|
|
263
|
+
const dirsAbs = renderPartitionDirsAbs(opts.partition, opts.root);
|
|
264
|
+
const orientation =
|
|
265
|
+
opts.scoutOverview.trim().length > 0
|
|
266
|
+
? opts.scoutOverview.trim()
|
|
267
|
+
: "(scout overview unavailable — proceed without)";
|
|
268
|
+
|
|
313
269
|
return [
|
|
314
270
|
`<RESEARCH_QUESTION>`,
|
|
315
271
|
opts.question,
|
|
316
272
|
`</RESEARCH_QUESTION>`,
|
|
317
273
|
``,
|
|
318
|
-
`<
|
|
319
|
-
`You are the
|
|
320
|
-
`
|
|
321
|
-
`
|
|
322
|
-
`
|
|
323
|
-
|
|
324
|
-
`</YOUR_IDENTITY>`,
|
|
325
|
-
``,
|
|
326
|
-
`<RESEARCH_PROTOCOL>`,
|
|
327
|
-
`Execute these steps in order:`,
|
|
328
|
-
``,
|
|
329
|
-
`── STEP 1 — Locate prior research documents ──`,
|
|
330
|
-
``,
|
|
331
|
-
`Dispatch the research-locator sub-agent:`,
|
|
274
|
+
`<MISSION>`,
|
|
275
|
+
`You are the codebase-pattern-finder for partition ${opts.index} of ${opts.total}.`,
|
|
276
|
+
`Find concrete code patterns inside the SCOPE that demonstrate how the`,
|
|
277
|
+
`topic of the research question is currently expressed in the codebase.`,
|
|
278
|
+
`Return runnable-looking snippets, not abstract descriptions.`,
|
|
279
|
+
`</MISSION>`,
|
|
332
280
|
``,
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
` document paths (docs/, tickets/, notes/, etc.) with 1-line summaries.`,
|
|
337
|
-
``,
|
|
338
|
-
`If no research/ directory exists or no relevant docs are found, note`,
|
|
339
|
-
`that explicitly and SKIP STEP 2.`,
|
|
340
|
-
``,
|
|
341
|
-
`── STEP 2 — Extract insights from the most relevant documents ──`,
|
|
342
|
-
``,
|
|
343
|
-
`Pick the 3-5 MOST relevant documents from STEP 1 and dispatch the`,
|
|
344
|
-
`research-analyzer:`,
|
|
345
|
-
``,
|
|
346
|
-
` @"codebase-research-analyzer (agent)" Extract key insights from these`,
|
|
347
|
-
` documents as they relate to the research question "${opts.question}":`,
|
|
348
|
-
` <list the doc paths you picked>`,
|
|
281
|
+
`<ARCHITECTURAL_ORIENTATION>`,
|
|
282
|
+
orientation,
|
|
283
|
+
`</ARCHITECTURAL_ORIENTATION>`,
|
|
349
284
|
``,
|
|
350
|
-
|
|
351
|
-
|
|
285
|
+
`<SCOPE>`,
|
|
286
|
+
assignment,
|
|
352
287
|
``,
|
|
353
|
-
|
|
288
|
+
`(Quick comma-separated form for tool args: ${dirsAbs})`,
|
|
289
|
+
`</SCOPE>`,
|
|
354
290
|
``,
|
|
355
|
-
|
|
356
|
-
`
|
|
357
|
-
` - Key prior decisions on related topics`,
|
|
358
|
-
` - Past investigations and their conclusions`,
|
|
359
|
-
` - Open questions from prior research`,
|
|
360
|
-
` - Document paths the aggregator should reference (with brief notes)`,
|
|
291
|
+
`<OUTPUT_FORMAT>`,
|
|
292
|
+
`For each distinct pattern you find, output:`,
|
|
361
293
|
``,
|
|
362
|
-
|
|
294
|
+
`#### Pattern: <short name>`,
|
|
295
|
+
`**Where:** \`<absolute path>:<line>\``,
|
|
296
|
+
`**What:** 1-sentence description.`,
|
|
297
|
+
"```<language>",
|
|
298
|
+
`<5-30 lines of actual code from the file>`,
|
|
299
|
+
"```",
|
|
300
|
+
`**Variations / call-sites:** other \`file.ts:line\` references using the same pattern.`,
|
|
363
301
|
``,
|
|
364
|
-
`
|
|
365
|
-
`</
|
|
302
|
+
`Aim for 3-7 distinct patterns. Skip anything tangential to the question.`,
|
|
303
|
+
`</OUTPUT_FORMAT>`,
|
|
366
304
|
``,
|
|
367
305
|
`<CONSTRAINTS>`,
|
|
368
306
|
DOCUMENTARIAN_DISCLAIMER,
|
|
369
|
-
`
|
|
370
|
-
`
|
|
371
|
-
`
|
|
307
|
+
`Restrict every grep/glob to the SCOPE above.`,
|
|
308
|
+
`Quote code verbatim — never paraphrase a snippet.`,
|
|
309
|
+
`Use file:line references for every claim.`,
|
|
310
|
+
TRAILING_PROSE_REMINDER,
|
|
372
311
|
`</CONSTRAINTS>`,
|
|
373
312
|
``,
|
|
374
313
|
`<RESEARCH_QUESTION_REMINDER>`,
|
|
@@ -377,206 +316,248 @@ export function buildHistoryPrompt(opts: {
|
|
|
377
316
|
].join("\n");
|
|
378
317
|
}
|
|
379
318
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
383
|
-
//
|
|
384
|
-
// The Claude variants above use `@"name (agent)"` sub-agent dispatch, which is
|
|
385
|
-
// a Claude-specific feature. Copilot and OpenCode sessions are bound to a
|
|
386
|
-
// single agent for the lifetime of the session, so replicating the specialist
|
|
387
|
-
// pattern would require spawning separate child sessions for each specialist —
|
|
388
|
-
// a linear blow-up in session count that is not worth the context-isolation
|
|
389
|
-
// benefit for a partition-scoped explorer.
|
|
390
|
-
//
|
|
391
|
-
// Instead, these generic variants guide a single default-agent session through
|
|
392
|
-
// the same conceptual steps (locate → analyze → patterns → synthesize) using
|
|
393
|
-
// its own built-in file tools. The graph topology remains identical to the
|
|
394
|
-
// Claude version: scout ∥ history → explorer-1..N → aggregator.
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* Generic explorer prompt (Copilot / OpenCode). Drives a single default-agent
|
|
398
|
-
* session through the locate → analyze → patterns → synthesize sequence using
|
|
399
|
-
* built-in tools directly, instead of Claude's sub-agent dispatch.
|
|
400
|
-
*/
|
|
401
|
-
export function buildExplorerPromptGeneric(opts: {
|
|
319
|
+
/** codebase-analyzer — document HOW the most relevant impl files work. */
|
|
320
|
+
export function buildAnalyzerPrompt(opts: {
|
|
402
321
|
question: string;
|
|
403
|
-
index: number;
|
|
404
|
-
total: number;
|
|
405
322
|
partition: PartitionUnit[];
|
|
406
|
-
|
|
407
|
-
historyOverview: string;
|
|
408
|
-
scratchPath: string;
|
|
323
|
+
locatorOutput: string;
|
|
409
324
|
root: string;
|
|
325
|
+
scoutOverview: string;
|
|
326
|
+
index: number;
|
|
327
|
+
total: number;
|
|
410
328
|
}): string {
|
|
411
|
-
const
|
|
412
|
-
.map((u) => {
|
|
413
|
-
const abs = path.join(opts.root, u.path);
|
|
414
|
-
return ` - \`${abs}/\` (${u.fileCount} files, ${u.loc.toLocaleString()} LOC)`;
|
|
415
|
-
})
|
|
416
|
-
.join("\n");
|
|
417
|
-
|
|
418
|
-
const dirListAbs = opts.partition
|
|
419
|
-
.map((u) => `\`${path.join(opts.root, u.path)}\``)
|
|
420
|
-
.join(", ");
|
|
421
|
-
|
|
329
|
+
const assignment = renderPartitionAssignment(opts.partition, opts.root);
|
|
422
330
|
const orientation =
|
|
423
331
|
opts.scoutOverview.trim().length > 0
|
|
424
332
|
? opts.scoutOverview.trim()
|
|
425
333
|
: "(scout overview unavailable — proceed without)";
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
: "(no historical research surfaced)";
|
|
334
|
+
const locator =
|
|
335
|
+
opts.locatorOutput.trim().length > 0
|
|
336
|
+
? opts.locatorOutput.trim()
|
|
337
|
+
: "(locator returned no files — analyse the partition directly)";
|
|
431
338
|
|
|
432
339
|
return [
|
|
433
340
|
`<RESEARCH_QUESTION>`,
|
|
434
341
|
opts.question,
|
|
435
342
|
`</RESEARCH_QUESTION>`,
|
|
436
343
|
``,
|
|
437
|
-
`<
|
|
438
|
-
`You are
|
|
439
|
-
`The codebase
|
|
440
|
-
`
|
|
441
|
-
`
|
|
442
|
-
`
|
|
443
|
-
|
|
444
|
-
`Your session is fresh — it was created specifically for this task. Every`,
|
|
445
|
-
`piece of context you need is in this prompt; nothing carries over from the`,
|
|
446
|
-
`scout or from other explorers. Treat this prompt as your complete briefing.`,
|
|
447
|
-
`</YOUR_IDENTITY>`,
|
|
344
|
+
`<MISSION>`,
|
|
345
|
+
`You are the codebase-analyzer for partition ${opts.index} of ${opts.total}.`,
|
|
346
|
+
`The codebase-locator (your sibling) has already enumerated the files in`,
|
|
347
|
+
`your partition that touch this topic. Your job is to read the 5-10 MOST`,
|
|
348
|
+
`relevant IMPLEMENTATION files and document how they actually work, with`,
|
|
349
|
+
`precise \`file.ts:line\` references throughout.`,
|
|
350
|
+
`</MISSION>`,
|
|
448
351
|
``,
|
|
449
352
|
`<ARCHITECTURAL_ORIENTATION>`,
|
|
450
|
-
`The codebase scout produced this overview to help you orient:`,
|
|
451
|
-
``,
|
|
452
353
|
orientation,
|
|
453
354
|
`</ARCHITECTURAL_ORIENTATION>`,
|
|
454
355
|
``,
|
|
455
|
-
`<
|
|
456
|
-
|
|
457
|
-
|
|
356
|
+
`<SCOPE>`,
|
|
357
|
+
assignment,
|
|
358
|
+
`</SCOPE>`,
|
|
359
|
+
``,
|
|
360
|
+
`<LOCATOR_FINDINGS>`,
|
|
361
|
+
`Verbatim output from the codebase-locator sibling for this partition —`,
|
|
362
|
+
`pick the implementation files to read from the "Implementation" section:`,
|
|
363
|
+
``,
|
|
364
|
+
locator,
|
|
365
|
+
`</LOCATOR_FINDINGS>`,
|
|
366
|
+
``,
|
|
367
|
+
`<METHOD>`,
|
|
368
|
+
`1. From the locator findings above, choose 5-10 implementation files most`,
|
|
369
|
+
` central to the research question. Prefer files that look like the`,
|
|
370
|
+
` primary entry points or data-flow hubs.`,
|
|
371
|
+
`2. Read each chosen file in full (no offset / no limit).`,
|
|
372
|
+
`3. For each file, document:`,
|
|
373
|
+
` • Its role (1 sentence)`,
|
|
374
|
+
` • Key exported symbols with \`file.ts:line\` refs`,
|
|
375
|
+
` • Control flow tied to the research question`,
|
|
376
|
+
` • Data flow (what comes in, what goes out, where state lives)`,
|
|
377
|
+
` • External dependencies it imports (libraries, sibling modules)`,
|
|
378
|
+
`4. After per-file documentation, write a short cross-cutting synthesis`,
|
|
379
|
+
` (≤200 words) describing how these files compose to address the topic.`,
|
|
380
|
+
`5. List any files OUTSIDE this partition that you noticed are referenced`,
|
|
381
|
+
` from your reads (so the aggregator can stitch findings across`,
|
|
382
|
+
` partitions). One file per line: \`<absolute path>\` — 1-line reason.`,
|
|
383
|
+
`</METHOD>`,
|
|
458
384
|
``,
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
``,
|
|
462
|
-
`<YOUR_ASSIGNMENT>`,
|
|
463
|
-
`Your assigned directories (DO NOT search outside these — other explorers`,
|
|
464
|
-
`cover the rest):`,
|
|
465
|
-
``,
|
|
466
|
-
assignmentLines,
|
|
467
|
-
`</YOUR_ASSIGNMENT>`,
|
|
468
|
-
``,
|
|
469
|
-
`<RESEARCH_PROTOCOL>`,
|
|
470
|
-
`Execute these steps IN ORDER using your built-in file tools (read, grep,`,
|
|
471
|
-
`glob, shell). Each step must complete before the next begins.`,
|
|
472
|
-
``,
|
|
473
|
-
`── STEP 1 — Locate relevant files ──`,
|
|
385
|
+
`<OUTPUT_FORMAT>`,
|
|
386
|
+
`Use this structure (omit empty sections):`,
|
|
474
387
|
``,
|
|
475
|
-
|
|
476
|
-
|
|
388
|
+
`### Files Analysed`,
|
|
389
|
+
`<bullet list of the 5-10 files you read, absolute paths>`,
|
|
477
390
|
``,
|
|
478
|
-
|
|
479
|
-
|
|
391
|
+
`### Per-File Notes`,
|
|
392
|
+
`#### \`<absolute path>\``,
|
|
393
|
+
`- **Role:** ...`,
|
|
394
|
+
`- **Key symbols:** \`name\` (\`file.ts:line\`), ...`,
|
|
395
|
+
`- **Control flow:** ...`,
|
|
396
|
+
`- **Data flow:** ...`,
|
|
397
|
+
`- **Dependencies:** ...`,
|
|
480
398
|
``,
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
` - Tests (unit / integration / e2e)`,
|
|
484
|
-
` - Types / interfaces`,
|
|
485
|
-
` - Configuration`,
|
|
486
|
-
` - Examples / fixtures`,
|
|
487
|
-
` - Documentation`,
|
|
399
|
+
`### Cross-Cutting Synthesis`,
|
|
400
|
+
`<≤200 words on how these files compose to address the topic>`,
|
|
488
401
|
``,
|
|
489
|
-
|
|
402
|
+
`### Out-of-Partition References`,
|
|
403
|
+
`- \`<absolute path>\` — 1-line note on why it matters`,
|
|
404
|
+
`</OUTPUT_FORMAT>`,
|
|
490
405
|
``,
|
|
491
|
-
|
|
406
|
+
`<CONSTRAINTS>`,
|
|
407
|
+
DOCUMENTARIAN_DISCLAIMER,
|
|
408
|
+
`Use file:line references for every concrete claim — never abstract prose.`,
|
|
409
|
+
`Read files in full; do not paginate via offset/limit unless a file is enormous.`,
|
|
410
|
+
`Do NOT analyse files outside your partition — only LIST them as cross-refs.`,
|
|
411
|
+
TRAILING_PROSE_REMINDER,
|
|
412
|
+
`</CONSTRAINTS>`,
|
|
492
413
|
``,
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
414
|
+
`<RESEARCH_QUESTION_REMINDER>`,
|
|
415
|
+
opts.question,
|
|
416
|
+
`</RESEARCH_QUESTION_REMINDER>`,
|
|
417
|
+
].join("\n");
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/** codebase-online-researcher — focused external doc fetch when libs are central. */
|
|
421
|
+
export function buildOnlineResearcherPrompt(opts: {
|
|
422
|
+
question: string;
|
|
423
|
+
partition: PartitionUnit[];
|
|
424
|
+
locatorOutput: string;
|
|
425
|
+
root: string;
|
|
426
|
+
index: number;
|
|
427
|
+
total: number;
|
|
428
|
+
}): string {
|
|
429
|
+
const assignment = renderPartitionAssignment(opts.partition, opts.root);
|
|
430
|
+
const locator =
|
|
431
|
+
opts.locatorOutput.trim().length > 0
|
|
432
|
+
? opts.locatorOutput.trim()
|
|
433
|
+
: "(locator returned no files)";
|
|
434
|
+
|
|
435
|
+
return [
|
|
436
|
+
`<RESEARCH_QUESTION>`,
|
|
437
|
+
opts.question,
|
|
438
|
+
`</RESEARCH_QUESTION>`,
|
|
499
439
|
``,
|
|
500
|
-
|
|
440
|
+
`<MISSION>`,
|
|
441
|
+
`You are the codebase-online-researcher for partition ${opts.index} of ${opts.total}.`,
|
|
442
|
+
`Decide whether external library / framework documentation is CENTRAL to`,
|
|
443
|
+
`answering the research question for this partition. If yes, fetch focused`,
|
|
444
|
+
`excerpts and tie them back to the partition's files. If no, output a`,
|
|
445
|
+
`single-line "(no external research applicable)" and stop.`,
|
|
446
|
+
`</MISSION>`,
|
|
447
|
+
``,
|
|
448
|
+
`<SCOPE>`,
|
|
449
|
+
assignment,
|
|
450
|
+
`</SCOPE>`,
|
|
451
|
+
``,
|
|
452
|
+
`<LOCATOR_FINDINGS>`,
|
|
453
|
+
`Use this list to identify which third-party libraries / frameworks the`,
|
|
454
|
+
`partition imports. If nothing relevant surfaces, return early.`,
|
|
455
|
+
``,
|
|
456
|
+
locator,
|
|
457
|
+
`</LOCATOR_FINDINGS>`,
|
|
458
|
+
``,
|
|
459
|
+
`<METHOD>`,
|
|
460
|
+
`1. Skim the locator output and any package manifests in the partition`,
|
|
461
|
+
` (package.json, go.mod, requirements.txt, Cargo.toml, etc.) to identify`,
|
|
462
|
+
` external dependencies that are LIKELY central to the research question.`,
|
|
463
|
+
`2. If none qualify, output exactly:`,
|
|
464
|
+
` (no external research applicable)`,
|
|
465
|
+
` and end the turn with a one-sentence prose explanation of why.`,
|
|
466
|
+
`3. If at least one qualifies, follow the token-efficient fetch order from`,
|
|
467
|
+
` your system prompt (llms.txt → Markdown for Agents → playwright-cli)`,
|
|
468
|
+
` to pull focused documentation excerpts.`,
|
|
469
|
+
`4. For each library you researched, return:`,
|
|
470
|
+
` • Library name + version (if discoverable)`,
|
|
471
|
+
` • Key doc URLs you fetched`,
|
|
472
|
+
` • The specific behavior that bears on the research question`,
|
|
473
|
+
` • Where in the partition that behavior is exercised (\`file.ts:line\`)`,
|
|
474
|
+
`</METHOD>`,
|
|
501
475
|
``,
|
|
502
|
-
|
|
476
|
+
`<OUTPUT_FORMAT>`,
|
|
477
|
+
`If you skipped:`,
|
|
503
478
|
``,
|
|
504
|
-
`
|
|
505
|
-
`related to the research question. Return snippets with \`file.ts:line\``,
|
|
506
|
-
`references so the aggregator can cite them directly.`,
|
|
479
|
+
`(no external research applicable)`,
|
|
507
480
|
``,
|
|
508
|
-
|
|
481
|
+
`<one-sentence justification>`,
|
|
509
482
|
``,
|
|
510
|
-
`
|
|
511
|
-
`CENTRAL to answering the research question. Otherwise skip it entirely.`,
|
|
483
|
+
`If you researched, repeat per library:`,
|
|
512
484
|
``,
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
485
|
+
`#### <Library> (vX.Y)`,
|
|
486
|
+
`**Docs:** <url>, <url>`,
|
|
487
|
+
`**Relevant behaviour:** ...`,
|
|
488
|
+
`**Where used:** \`<absolute path>:<line>\` — 1-line note`,
|
|
489
|
+
`</OUTPUT_FORMAT>`,
|
|
517
490
|
``,
|
|
518
|
-
|
|
491
|
+
`<CONSTRAINTS>`,
|
|
492
|
+
DOCUMENTARIAN_DISCLAIMER,
|
|
493
|
+
`Skipping is the correct answer when nothing is central — do NOT pad with`,
|
|
494
|
+
`tutorials or general guides.`,
|
|
495
|
+
`Quote URLs verbatim. Do NOT invent or paraphrase doc URLs.`,
|
|
496
|
+
TRAILING_PROSE_REMINDER,
|
|
497
|
+
`</CONSTRAINTS>`,
|
|
519
498
|
``,
|
|
520
|
-
|
|
521
|
-
|
|
499
|
+
`<RESEARCH_QUESTION_REMINDER>`,
|
|
500
|
+
opts.question,
|
|
501
|
+
`</RESEARCH_QUESTION_REMINDER>`,
|
|
502
|
+
].join("\n");
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
506
|
+
// Stage 1b — research-history specialists
|
|
507
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
508
|
+
|
|
509
|
+
/** codebase-research-locator — find prior research docs about the topic. */
|
|
510
|
+
export function buildHistoryLocatorPrompt(opts: {
|
|
511
|
+
question: string;
|
|
512
|
+
root: string;
|
|
513
|
+
}): string {
|
|
514
|
+
const researchDir = path.join(opts.root, "research");
|
|
515
|
+
|
|
516
|
+
return [
|
|
517
|
+
`<RESEARCH_QUESTION>`,
|
|
518
|
+
opts.question,
|
|
519
|
+
`</RESEARCH_QUESTION>`,
|
|
522
520
|
``,
|
|
523
|
-
|
|
521
|
+
`<MISSION>`,
|
|
522
|
+
`You are the codebase-research-locator. Surface prior research documents`,
|
|
523
|
+
`about this topic from the project's research/ directory so the analyzer`,
|
|
524
|
+
`(your sibling) can extract insights from them.`,
|
|
525
|
+
`</MISSION>`,
|
|
524
526
|
``,
|
|
525
|
-
|
|
526
|
-
`
|
|
527
|
+
`<SCOPE>`,
|
|
528
|
+
`Primary: \`${researchDir}/\` (and standard subdirs: docs/, tickets/, notes/).`,
|
|
529
|
+
`Secondary: any sibling research directories under \`${opts.root}\` that match`,
|
|
530
|
+
`\`*research*\`, \`*adr*\`, \`*rfc*\`, or \`specs\`.`,
|
|
527
531
|
``,
|
|
528
|
-
|
|
532
|
+
`If no research directory exists at all, return a single section:`,
|
|
529
533
|
``,
|
|
530
|
-
|
|
531
|
-
`
|
|
532
|
-
|
|
533
|
-
` 2. If your session ends on a tool call with no trailing prose, the`,
|
|
534
|
-
` downstream handoff will be empty and the aggregator will miss your`,
|
|
535
|
-
` contribution entirely.`,
|
|
536
|
-
`</RESEARCH_PROTOCOL>`,
|
|
534
|
+
`### No Prior Research`,
|
|
535
|
+
`(briefly note what you checked)`,
|
|
536
|
+
`</SCOPE>`,
|
|
537
537
|
``,
|
|
538
538
|
`<OUTPUT_FORMAT>`,
|
|
539
|
-
`
|
|
540
|
-
`sections, in this order:`,
|
|
541
|
-
``,
|
|
542
|
-
`# Explorer ${opts.index} Findings`,
|
|
543
|
-
``,
|
|
544
|
-
`## Scope`,
|
|
545
|
-
`One-line description of which directories you covered.`,
|
|
546
|
-
``,
|
|
547
|
-
`## Overview`,
|
|
548
|
-
`1-2 paragraph synthesis of your findings as they relate to the research`,
|
|
549
|
-
`question.`,
|
|
539
|
+
`Group by document type. Within each group, sort newest first by filename.`,
|
|
550
540
|
``,
|
|
551
|
-
|
|
552
|
-
|
|
541
|
+
`### Docs`,
|
|
542
|
+
`- \`<absolute path>\` — 1-line title-derived summary`,
|
|
553
543
|
``,
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
`references throughout.`,
|
|
544
|
+
`### Tickets`,
|
|
545
|
+
`- ...`,
|
|
557
546
|
``,
|
|
558
|
-
|
|
559
|
-
|
|
547
|
+
`### Notes`,
|
|
548
|
+
`- ...`,
|
|
560
549
|
``,
|
|
561
|
-
|
|
562
|
-
|
|
550
|
+
`### Specs / ADRs / RFCs`,
|
|
551
|
+
`- ...`,
|
|
563
552
|
``,
|
|
564
|
-
|
|
565
|
-
`Files OUTSIDE your assigned directories that other explorers should check,`,
|
|
566
|
-
`with a 1-line note on why each is relevant.`,
|
|
567
|
-
``,
|
|
568
|
-
`## File Index`,
|
|
569
|
-
`Bulleted list of every file you touched, each with a 1-line description.`,
|
|
553
|
+
`Omit empty sections.`,
|
|
570
554
|
`</OUTPUT_FORMAT>`,
|
|
571
555
|
``,
|
|
572
556
|
`<CONSTRAINTS>`,
|
|
573
557
|
DOCUMENTARIAN_DISCLAIMER,
|
|
574
|
-
`
|
|
575
|
-
`Do NOT investigate
|
|
576
|
-
|
|
577
|
-
`End your turn with the required 2-3 sentence prose summary AFTER writing`,
|
|
578
|
-
`the file — do NOT end on a tool call, or your findings will be lost to the`,
|
|
579
|
-
`aggregator.`,
|
|
558
|
+
`Do NOT read file contents in depth — your sibling does that.`,
|
|
559
|
+
`Do NOT investigate live source files — that's the explorers' job.`,
|
|
560
|
+
TRAILING_PROSE_REMINDER,
|
|
580
561
|
`</CONSTRAINTS>`,
|
|
581
562
|
``,
|
|
582
563
|
`<RESEARCH_QUESTION_REMINDER>`,
|
|
@@ -585,77 +566,60 @@ export function buildExplorerPromptGeneric(opts: {
|
|
|
585
566
|
].join("\n");
|
|
586
567
|
}
|
|
587
568
|
|
|
588
|
-
/**
|
|
589
|
-
|
|
590
|
-
* session searches the project's research/ directory using its own file tools,
|
|
591
|
-
* instead of dispatching Claude's codebase-research-locator / analyzer
|
|
592
|
-
* sub-agents.
|
|
593
|
-
*/
|
|
594
|
-
export function buildHistoryPromptGeneric(opts: {
|
|
569
|
+
/** codebase-research-analyzer — synthesize insights from located research docs. */
|
|
570
|
+
export function buildHistoryAnalyzerPrompt(opts: {
|
|
595
571
|
question: string;
|
|
572
|
+
locatorOutput: string;
|
|
596
573
|
root: string;
|
|
597
574
|
}): string {
|
|
598
|
-
const
|
|
575
|
+
const locator =
|
|
576
|
+
opts.locatorOutput.trim().length > 0
|
|
577
|
+
? opts.locatorOutput.trim()
|
|
578
|
+
: "(no prior research surfaced)";
|
|
599
579
|
|
|
600
580
|
return [
|
|
601
581
|
`<RESEARCH_QUESTION>`,
|
|
602
582
|
opts.question,
|
|
603
583
|
`</RESEARCH_QUESTION>`,
|
|
604
584
|
``,
|
|
605
|
-
`<
|
|
606
|
-
`You are the research-
|
|
607
|
-
`
|
|
608
|
-
`
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
585
|
+
`<MISSION>`,
|
|
586
|
+
`You are the codebase-research-analyzer. Extract HIGH-VALUE insights from`,
|
|
587
|
+
`the prior research documents your sibling located, and produce a tight`,
|
|
588
|
+
`synthesis the aggregator can fold in as supplementary context.`,
|
|
589
|
+
`</MISSION>`,
|
|
590
|
+
``,
|
|
591
|
+
`<LOCATOR_FINDINGS>`,
|
|
592
|
+
locator,
|
|
593
|
+
`</LOCATOR_FINDINGS>`,
|
|
594
|
+
``,
|
|
595
|
+
`<METHOD>`,
|
|
596
|
+
`1. Pick the 3-5 MOST relevant documents from the locator output.`,
|
|
597
|
+
`2. Read each in full.`,
|
|
598
|
+
`3. For each, capture:`,
|
|
599
|
+
` • Prior decisions on related topics (and what was actually shipped)`,
|
|
600
|
+
` • Completed investigations and their conclusions`,
|
|
601
|
+
` • Open questions / unresolved threads still in flight`,
|
|
602
|
+
`4. Filter aggressively — drop tangential mentions and outdated context.`,
|
|
603
|
+
`5. Synthesize into a single ≤400-word block. Cite document paths inline.`,
|
|
604
|
+
`</METHOD>`,
|
|
616
605
|
``,
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
`for documents related to the research question. Look for:`,
|
|
621
|
-
` - Research docs (research/docs/, research/*.md)`,
|
|
622
|
-
` - Decision records / ADRs`,
|
|
623
|
-
` - Tickets, notes, or RFCs about related topics`,
|
|
624
|
-
``,
|
|
625
|
-
`If no research/ directory exists at all, note that explicitly and SKIP`,
|
|
626
|
-
`to the final synthesis step with a single-sentence "no history" output.`,
|
|
627
|
-
``,
|
|
628
|
-
`── STEP 2 — Extract insights from the most relevant documents ──`,
|
|
629
|
-
``,
|
|
630
|
-
`Pick the 3-5 MOST relevant documents from STEP 1 and read them. For each,`,
|
|
631
|
-
`extract:`,
|
|
632
|
-
` - Prior decisions that bear on the current question`,
|
|
633
|
-
` - Completed investigations and their conclusions`,
|
|
634
|
-
` - Open questions or unresolved threads`,
|
|
635
|
-
``,
|
|
636
|
-
`Filter out noise — skip anything that isn't directly relevant.`,
|
|
637
|
-
``,
|
|
638
|
-
`── STEP 3 — Synthesize ──`,
|
|
639
|
-
``,
|
|
640
|
-
`Output a 200-400 word synthesis of historical context as your final`,
|
|
641
|
-
`prose response. Cover:`,
|
|
642
|
-
` - Key prior decisions on related topics`,
|
|
643
|
-
` - Past investigations and their conclusions`,
|
|
644
|
-
` - Open questions from prior research`,
|
|
645
|
-
` - Document paths the aggregator should reference (with brief notes)`,
|
|
606
|
+
`<OUTPUT_FORMAT>`,
|
|
607
|
+
`### Documents Reviewed`,
|
|
608
|
+
`- \`<absolute path>\` — 1-line takeaway`,
|
|
646
609
|
``,
|
|
647
|
-
|
|
610
|
+
`### Synthesis`,
|
|
611
|
+
`<≤400 words covering decisions, conclusions, and open questions, with`,
|
|
612
|
+
`inline path citations like (\`research/docs/2025-…md\`)>`,
|
|
648
613
|
``,
|
|
649
|
-
`
|
|
650
|
-
|
|
651
|
-
`end on a tool call with no trailing text, the aggregator will see nothing.`,
|
|
652
|
-
`</RESEARCH_PROTOCOL>`,
|
|
614
|
+
`If no relevant prior research exists, output a single sentence saying so.`,
|
|
615
|
+
`</OUTPUT_FORMAT>`,
|
|
653
616
|
``,
|
|
654
617
|
`<CONSTRAINTS>`,
|
|
655
618
|
DOCUMENTARIAN_DISCLAIMER,
|
|
656
|
-
`Stay under 400 words
|
|
619
|
+
`Stay under 400 words in the Synthesis section.`,
|
|
657
620
|
`Do NOT investigate live source files — that's the explorers' job.`,
|
|
658
|
-
`
|
|
621
|
+
`Do NOT write any new files — your output is consumed via session transcript.`,
|
|
622
|
+
TRAILING_PROSE_REMINDER,
|
|
659
623
|
`</CONSTRAINTS>`,
|
|
660
624
|
``,
|
|
661
625
|
`<RESEARCH_QUESTION_REMINDER>`,
|
|
@@ -685,7 +649,7 @@ export function buildAggregatorPrompt(opts: {
|
|
|
685
649
|
const explorerSummary = opts.explorerFiles
|
|
686
650
|
.map((e) => {
|
|
687
651
|
const dirs = e.partition.map((u) => `\`${u.path}/\``).join(", ");
|
|
688
|
-
return `- **
|
|
652
|
+
return `- **Partition ${e.index}** → \`${e.scratchPath}\`\n Covered: ${dirs}`;
|
|
689
653
|
})
|
|
690
654
|
.join("\n");
|
|
691
655
|
|
|
@@ -704,54 +668,50 @@ export function buildAggregatorPrompt(opts: {
|
|
|
704
668
|
opts.question,
|
|
705
669
|
`</RESEARCH_QUESTION>`,
|
|
706
670
|
``,
|
|
707
|
-
`<
|
|
708
|
-
`You are the aggregator. ${opts.explorerCount} parallel
|
|
709
|
-
`
|
|
710
|
-
`
|
|
711
|
-
`
|
|
712
|
-
|
|
713
|
-
`
|
|
714
|
-
`
|
|
715
|
-
|
|
671
|
+
`<MISSION>`,
|
|
672
|
+
`You are the aggregator. ${opts.explorerCount} parallel partitions of the`,
|
|
673
|
+
`codebase (${opts.totalLoc.toLocaleString()} LOC across ${opts.totalFiles.toLocaleString()} source files)`,
|
|
674
|
+
`have each been investigated by four specialist sub-agents — codebase-locator,`,
|
|
675
|
+
`codebase-pattern-finder, codebase-analyzer, and codebase-online-researcher`,
|
|
676
|
+
`— dispatched directly via the agent SDK. The deterministic synthesis step`,
|
|
677
|
+
`wrote one markdown findings file per partition. A separate research-history`,
|
|
678
|
+
`pipeline (codebase-research-locator → codebase-research-analyzer) surveyed`,
|
|
679
|
+
`the project's prior research documents. Your job: synthesise everything`,
|
|
680
|
+
`into a single comprehensive research document.`,
|
|
681
|
+
`</MISSION>`,
|
|
716
682
|
``,
|
|
717
683
|
`<ARCHITECTURAL_ORIENTATION>`,
|
|
718
684
|
orientation,
|
|
719
685
|
`</ARCHITECTURAL_ORIENTATION>`,
|
|
720
686
|
``,
|
|
721
687
|
`<HISTORICAL_CONTEXT>`,
|
|
722
|
-
`
|
|
723
|
-
`codebase-research-analyzer over the project's research/ directory. Their`,
|
|
724
|
-
`synthesis (use as supplementary context — live findings take precedence):`,
|
|
688
|
+
`Use as supplementary context — live findings take precedence:`,
|
|
725
689
|
``,
|
|
726
690
|
history,
|
|
727
691
|
`</HISTORICAL_CONTEXT>`,
|
|
728
692
|
``,
|
|
729
693
|
`<EXPLORER_REPORTS>`,
|
|
730
|
-
`
|
|
731
|
-
`
|
|
732
|
-
`
|
|
733
|
-
`
|
|
734
|
-
`codebase-pattern-finder, and (sometimes) codebase-online-researcher`,
|
|
735
|
-
`sub-agents — they are LIVE evidence and take precedence over history.`,
|
|
694
|
+
`Each file below has the same structure (Scope / Files in Scope / How It`,
|
|
695
|
+
`Works / Patterns / External References / Out-of-Partition References).`,
|
|
696
|
+
`These are LIVE evidence from the specialist sub-agents and take precedence`,
|
|
697
|
+
`over historical context.`,
|
|
736
698
|
``,
|
|
737
699
|
explorerSummary,
|
|
738
700
|
`</EXPLORER_REPORTS>`,
|
|
739
701
|
``,
|
|
740
|
-
`<
|
|
741
|
-
`1. Read EVERY explorer findings file in full
|
|
742
|
-
`
|
|
743
|
-
`2.
|
|
744
|
-
`
|
|
745
|
-
`
|
|
746
|
-
`
|
|
747
|
-
`
|
|
748
|
-
`
|
|
749
|
-
`5.
|
|
750
|
-
`
|
|
751
|
-
`6. Write the final research document to: \`${opts.finalPath}\``,
|
|
752
|
-
`7. After writing the file, output a ≤200-word executive summary as your`,
|
|
702
|
+
`<METHOD>`,
|
|
703
|
+
`1. Read EVERY explorer findings file in full using the Read tool with no`,
|
|
704
|
+
` offset or limit — these are not optional.`,
|
|
705
|
+
`2. Cross-reference: stitch findings together across partitions using each`,
|
|
706
|
+
` file's "Out-of-Partition References" section.`,
|
|
707
|
+
`3. Resolve contradictions by re-reading the underlying source files`,
|
|
708
|
+
` directly — do not paper over disagreements.`,
|
|
709
|
+
`4. Integrate historical context where it adds value, but trust live`,
|
|
710
|
+
` findings when they conflict with history.`,
|
|
711
|
+
`5. Write the final research document to: \`${opts.finalPath}\``,
|
|
712
|
+
`6. After writing the file, output a ≤200-word executive summary as your`,
|
|
753
713
|
` final prose response so this transcript has content.`,
|
|
754
|
-
`</
|
|
714
|
+
`</METHOD>`,
|
|
755
715
|
``,
|
|
756
716
|
`<OUTPUT_FORMAT>`,
|
|
757
717
|
`The file at \`${opts.finalPath}\` must follow this structure:`,
|
|
@@ -786,27 +746,26 @@ export function buildAggregatorPrompt(opts: {
|
|
|
786
746
|
`...`,
|
|
787
747
|
``,
|
|
788
748
|
`## Architecture & Patterns`,
|
|
789
|
-
`Cross-cutting patterns observed across multiple
|
|
749
|
+
`Cross-cutting patterns observed across multiple partitions.`,
|
|
790
750
|
``,
|
|
791
751
|
`## Code References`,
|
|
792
752
|
`- \`path/to/file.ts:123\` — what's there`,
|
|
793
753
|
``,
|
|
794
754
|
`## Historical Context (from research/)`,
|
|
795
|
-
`Relevant insights from prior research
|
|
796
|
-
`section entirely if the research-history scout found nothing.`,
|
|
755
|
+
`Relevant insights from prior research, with paths. Omit if no history.`,
|
|
797
756
|
``,
|
|
798
757
|
`## Open Questions`,
|
|
799
758
|
`Areas needing further investigation.`,
|
|
800
759
|
``,
|
|
801
760
|
`## Methodology`,
|
|
802
|
-
`Generated by the deep-research-codebase workflow with ${opts.explorerCount}
|
|
803
|
-
`
|
|
804
|
-
`
|
|
805
|
-
`
|
|
806
|
-
`
|
|
807
|
-
`
|
|
808
|
-
`codebase-research-locator
|
|
809
|
-
`
|
|
761
|
+
`Generated by the deep-research-codebase workflow with ${opts.explorerCount} partitions`,
|
|
762
|
+
`covering ${opts.totalFiles.toLocaleString()} source files (${opts.totalLoc.toLocaleString()} LOC).`,
|
|
763
|
+
`Each partition was investigated by four specialist sub-agents dispatched`,
|
|
764
|
+
`directly via the provider SDK's native agent parameter:`,
|
|
765
|
+
`codebase-locator, codebase-pattern-finder, codebase-analyzer, and`,
|
|
766
|
+
`codebase-online-researcher. A separate research-history pipeline ran`,
|
|
767
|
+
`codebase-research-locator → codebase-research-analyzer over the project's`,
|
|
768
|
+
`prior research documents.`,
|
|
810
769
|
"```",
|
|
811
770
|
`</OUTPUT_FORMAT>`,
|
|
812
771
|
``,
|
|
@@ -814,7 +773,7 @@ export function buildAggregatorPrompt(opts: {
|
|
|
814
773
|
DOCUMENTARIAN_DISCLAIMER,
|
|
815
774
|
`Prefer concrete file:line references over abstract descriptions.`,
|
|
816
775
|
`Do NOT skim explorer reports — read each one in full.`,
|
|
817
|
-
`If two
|
|
776
|
+
`If two partitions contradict each other, re-read the underlying source files.`,
|
|
818
777
|
`End with the required ≤200-word executive summary AFTER writing the file.`,
|
|
819
778
|
`</CONSTRAINTS>`,
|
|
820
779
|
``,
|