@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.
Files changed (26) hide show
  1. package/README.md +14 -1
  2. package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts +50 -54
  3. package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts.map +1 -1
  4. package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts +17 -36
  5. package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts.map +1 -1
  6. package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/heuristic.d.ts +1 -1
  7. package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.d.ts +64 -44
  8. package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.d.ts.map +1 -1
  9. package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/scratch.d.ts +43 -0
  10. package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/scratch.d.ts.map +1 -0
  11. package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts +17 -39
  12. package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts.map +1 -1
  13. package/package.json +1 -1
  14. package/src/cli.ts +21 -2
  15. package/src/commands/cli/session.test.ts +223 -0
  16. package/src/commands/cli/session.ts +117 -1
  17. package/src/completions/bash.ts +3 -3
  18. package/src/completions/fish.ts +13 -7
  19. package/src/completions/powershell.ts +3 -0
  20. package/src/completions/zsh.ts +2 -1
  21. package/src/sdk/workflows/builtin/deep-research-codebase/claude/index.ts +260 -157
  22. package/src/sdk/workflows/builtin/deep-research-codebase/copilot/index.ts +224 -125
  23. package/src/sdk/workflows/builtin/deep-research-codebase/helpers/heuristic.ts +2 -2
  24. package/src/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.ts +428 -469
  25. package/src/sdk/workflows/builtin/deep-research-codebase/helpers/scratch.ts +115 -0
  26. 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
- * - Position-aware placement: the research question is repeated at the
6
- * TOP and BOTTOM of every prompt (recall is 85-95% at the edges and
7
- * drops to 76-82% in the middle see context-fundamentals).
8
- * - Informativity over exhaustiveness: each explorer prompt contains
9
- * only that explorer's partition, never the full file list.
10
- * - Explicit trailing commentary (F6): every prompt asks the agent to
11
- * produce a short text summary AFTER any tool/file output, so the
12
- * transcript is not empty when downstream stages read it.
13
- * - File-based handoff (filesystem-context skill): explorer findings
14
- * are written to disk and the aggregator reads them by path, instead
15
- * of inlining N transcripts into the aggregator's prompt.
16
- * - Documentarian role: every prompt explicitly forbids critique or
17
- * improvement suggestions; we are recording what exists.
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 1 — codebase-scout
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
- `- Explorers to spawn: ${opts.explorerCount} (chosen by LOC heuristic)`,
120
+ `- Partitions to investigate: ${opts.explorerCount} (chosen by LOC heuristic)`,
73
121
  ``,
74
- `Pre-computed partition assignments (${opts.explorerCount} explorers):`,
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
- `will help the ${opts.explorerCount} parallel explorer sub-agents understand the`,
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 explorers, not investigation. You may use`,
96
- `Read/Glob/Grep sparingly to verify your guesses about a few key files,`,
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
- `End with a short prose paragraph (NOT a tool call) so this transcript`,
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 — explorer-N
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
- export function buildExplorerPrompt(opts: {
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 assignmentLines = opts.partition
127
- .map((u) => {
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
- `<YOUR_IDENTITY>`,
151
- `You are explorer ${opts.index} of ${opts.total}. You are a COORDINATOR — your`,
152
- `job is to dispatch specialized research sub-agents and synthesize their`,
153
- `findings. You do NOT use Read/Glob/Grep yourself; you orchestrate the`,
154
- `specialists. The codebase has been partitioned across ${opts.total} parallel`,
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
- `<YOUR_ASSIGNMENT>`,
166
- `Your assigned directories (DO NOT search outside these other explorers`,
167
- `cover the rest):`,
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
- ` @"codebase-pattern-finder (agent)" CRITICAL: search ONLY within these`,
207
- ` directories: ${dirListAbs}.`,
207
+ assignment,
208
208
  ``,
209
- ` Find existing code patterns related to "${opts.question}" inside those`,
210
- ` directories. Return concrete code snippets with file:line references.`,
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
- `The file at \`${opts.scratchPath}\` must be a markdown document with these`,
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
- `## Scope`,
249
- `One-line description of which directories you covered.`,
215
+ `### Implementation`,
216
+ `- \`<absolute path>\` 1-line note on relevance`,
250
217
  ``,
251
- `## Overview`,
252
- `1-2 paragraph synthesis of all sub-agent findings as they relate to the`,
253
- `research question.`,
218
+ `### Tests`,
219
+ `- ...`,
254
220
  ``,
255
- `## Files in Scope`,
256
- `From codebase-locator (Step 1). Categorized list with absolute paths.`,
221
+ `### Types / Interfaces`,
222
+ `- ...`,
257
223
  ``,
258
- `## How It Works`,
259
- `From codebase-analyzer (Step 2). Control flow, data flow, key abstractions,`,
260
- `with file:line references throughout.`,
224
+ `### Configuration`,
225
+ `- ...`,
261
226
  ``,
262
- `## Patterns`,
263
- `From codebase-pattern-finder (Step 3). Concrete code examples with`,
264
- `file:line refs.`,
227
+ `### Examples / Fixtures`,
228
+ `- ...`,
265
229
  ``,
266
- `## External References`,
267
- `From codebase-online-researcher (Step 4) — INCLUDE ONLY if Step 4 ran.`,
268
- `Otherwise omit this section. Include links the online researcher returned.`,
230
+ `### Documentation`,
231
+ `- ...`,
269
232
  ``,
270
- `## Cross-References`,
271
- `Files OUTSIDE your assigned directories that other explorers should check,`,
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
- `## File Index`,
275
- `Bulleted list of every file the sub-agents touched, each with a 1-line`,
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
- `Use file:line references throughout concrete, not abstract.`,
282
- `Do NOT investigate directories outside your assignment, even via sub-agents.`,
283
- `Do NOT skip Steps 1-3 or 5-6. Step 4 is the only optional step.`,
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
- // Stage 1b — research-history (parallel sibling of codebase-scout)
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
- `<YOUR_IDENTITY>`,
319
- `You are the research-history scout for the deep-research-codebase`,
320
- `workflow. You run in parallel with the codebase-scout. Your job is to`,
321
- `surface relevant historical context from the project's existing research`,
322
- `directory using specialized sub-agents NOT to investigate the live`,
323
- `codebase (the explorers will do that).`,
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
- ` @"codebase-research-locator (agent)" Locate research documents related`,
334
- ` to: "${opts.question}". Search the \`${path.join(opts.root, "research")}\``,
335
- ` directory and any sibling research directories. Return categorized`,
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
- ` Filter out noise. Focus on prior decisions, completed investigations,`,
351
- ` and unresolved questions that bear on the current research question.`,
285
+ `<SCOPE>`,
286
+ assignment,
352
287
  ``,
353
- `── STEP 3 Synthesize ──`,
288
+ `(Quick comma-separated form for tool args: ${dirsAbs})`,
289
+ `</SCOPE>`,
354
290
  ``,
355
- `Output a 200-400 word synthesis of historical context as your final`,
356
- `prose response. Cover:`,
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
- `If no relevant history exists, output a single sentence saying so.`,
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
- `Do NOT write any files your output is consumed via session transcript.`,
365
- `</RESEARCH_PROTOCOL>`,
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
- `Stay under 400 words total in your final synthesis.`,
370
- `Do NOT investigate live source files that's the explorers' job.`,
371
- `End with the prose synthesis (do not end on a tool call).`,
307
+ `Restrict every grep/glob to the SCOPE above.`,
308
+ `Quote code verbatimnever 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
- // Generic variants (Copilot / OpenCode)
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
- scoutOverview: string;
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 assignmentLines = opts.partition
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
- const history =
428
- opts.historyOverview.trim().length > 0
429
- ? opts.historyOverview.trim()
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
- `<YOUR_IDENTITY>`,
438
- `You are explorer ${opts.index} of ${opts.total} in a deep-research workflow.`,
439
- `The codebase has been partitioned across ${opts.total} parallel explorers —`,
440
- `you are responsible for ONE assigned slice. Other explorers are`,
441
- `simultaneously investigating the rest. You are a documentarian, not a`,
442
- `critic: record what EXISTS, do not propose improvements.`,
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
- `<HISTORICAL_CONTEXT>`,
456
- `Prior research surfaced by the research-history scout (supplementary —`,
457
- `live findings you produce below take precedence):`,
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
- history,
460
- `</HISTORICAL_CONTEXT>`,
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
- `Use grep / glob to find files within ONLY these directories:`,
476
- `${dirListAbs}`,
388
+ `### Files Analysed`,
389
+ `<bullet list of the 5-10 files you read, absolute paths>`,
477
390
  ``,
478
- `that relate to the research question. CRITICAL: restrict every search to`,
479
- `the directories listed above — do not wander into the rest of the codebase.`,
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
- `Categorize what you find by purpose:`,
482
- ` - Implementation (core logic)`,
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
- `Record absolute paths grouped by category. Do NOT read file contents yet.`,
402
+ `### Out-of-Partition References`,
403
+ `- \`<absolute path>\` — 1-line note on why it matters`,
404
+ `</OUTPUT_FORMAT>`,
490
405
  ``,
491
- `── STEP 2 — Analyze the most relevant implementation files ──`,
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
- `Pick the 5-10 MOST relevant implementation files from STEP 1 and read them`,
494
- `in full. For each file, document:`,
495
- ` - Its role (what it does, why it exists)`,
496
- ` - Key abstractions, types, and functions with \`file.ts:line\` references`,
497
- ` - Control flow and data flow as they relate to the research question`,
498
- ` - External dependencies it uses (libraries, other modules)`,
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
- `Use file:line references throughout — never abstract descriptions.`,
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
- `── STEP 3 — Find existing patterns ──`,
476
+ `<OUTPUT_FORMAT>`,
477
+ `If you skipped:`,
503
478
  ``,
504
- `Search (within your assigned directories only) for concrete code patterns`,
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
- `── STEP 4 — External documentation (CONDITIONAL) ──`,
481
+ `<one-sentence justification>`,
509
482
  ``,
510
- `ONLY run this step IF Step 2 surfaced external library usage that is`,
511
- `CENTRAL to answering the research question. Otherwise skip it entirely.`,
483
+ `If you researched, repeat per library:`,
512
484
  ``,
513
- `If applicable, use your web-fetch / web-search tools to pull focused`,
514
- `documentation excerpts for the relevant library, tied back to how your`,
515
- `assigned files use it. Return links and concrete findings only — no`,
516
- `general tutorials.`,
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
- `── STEP 5 — Synthesize and write findings ──`,
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
- `Combine the outputs from Steps 1-4 into a single markdown document and`,
521
- `write it to this path using your write / edit tool:`,
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
- ` ${opts.scratchPath}`,
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
- `Use the OUTPUT_FORMAT below. This file is the ONLY way your findings`,
526
- `reach the aggregator be complete and precise.`,
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
- `── STEP 6 Brief prose summary (REQUIRED) ──`,
532
+ `If no research directory exists at all, return a single section:`,
529
533
  ``,
530
- `AFTER writing the file, output a 2-3 sentence prose summary as your final`,
531
- `textual response. This is required for two reasons:`,
532
- ` 1. The aggregator uses it as an index of your report`,
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
- `The file at \`${opts.scratchPath}\` must be a markdown document with these`,
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
- `## Files in Scope`,
552
- `From Step 1. Categorized list with absolute paths.`,
541
+ `### Docs`,
542
+ `- \`<absolute path>\` 1-line title-derived summary`,
553
543
  ``,
554
- `## How It Works`,
555
- `From Step 2. Control flow, data flow, key abstractions, with \`file.ts:line\``,
556
- `references throughout.`,
544
+ `### Tickets`,
545
+ `- ...`,
557
546
  ``,
558
- `## Patterns`,
559
- `From Step 3. Concrete code examples with \`file.ts:line\` references.`,
547
+ `### Notes`,
548
+ `- ...`,
560
549
  ``,
561
- `## External References`,
562
- `From Step 4 — INCLUDE ONLY if Step 4 ran. Otherwise omit this section.`,
550
+ `### Specs / ADRs / RFCs`,
551
+ `- ...`,
563
552
  ``,
564
- `## Cross-References`,
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
- `Use file:line references throughoutconcrete, not abstract.`,
575
- `Do NOT investigate directories outside your assignment.`,
576
- `Do NOT skip Steps 1-3 or 5-6. Step 4 is the only optional step.`,
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
- * Generic research-history prompt (Copilot / OpenCode). A single default-agent
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 researchDir = path.join(opts.root, "research");
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
- `<YOUR_IDENTITY>`,
606
- `You are the research-history scout for the deep-research-codebase`,
607
- `workflow. You run in parallel with the codebase-scout. Your job is to`,
608
- `surface relevant historical context from the project's existing research`,
609
- `directory (${researchDir}) — NOT to investigate the live codebase (the`,
610
- `explorers will do that).`,
611
- `</YOUR_IDENTITY>`,
612
- ``,
613
- `<RESEARCH_PROTOCOL>`,
614
- `Execute these steps in order using your built-in file tools (read, grep,`,
615
- `glob, shell):`,
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
- `── STEP 1 — Locate prior research documents ──`,
618
- ``,
619
- `Search \`${researchDir}\` (and any sibling research directories that exist)`,
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
- `If no relevant history exists, output a single sentence saying so.`,
610
+ `### Synthesis`,
611
+ `<≤400 words covering decisions, conclusions, and open questions, with`,
612
+ `inline path citations like (\`research/docs/2025-…md\`)>`,
648
613
  ``,
649
- `Do NOT write any files your output is consumed via session transcript.`,
650
- `Your final assistant message must contain the synthesis as prose. If you`,
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 total in your final synthesis.`,
619
+ `Stay under 400 words in the Synthesis section.`,
657
620
  `Do NOT investigate live source files — that's the explorers' job.`,
658
- `End with the prose synthesis (do not end on a tool call).`,
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 `- **Explorer ${e.index}** → \`${e.scratchPath}\`\n Covered: ${dirs}`;
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
- `<YOUR_IDENTITY>`,
708
- `You are the aggregator. ${opts.explorerCount} parallel explorer sub-agents`,
709
- `have completed their investigations of the codebase`,
710
- `(${opts.totalLoc.toLocaleString()} LOC across ${opts.totalFiles.toLocaleString()} source files),`,
711
- `and a parallel research-history scout has surveyed the project's prior`,
712
- `research documents. Each explorer wrote a detailed findings file. Your`,
713
- `job is to synthesize these findings together with historical context —`,
714
- `into a single comprehensive research document that answers the question.`,
715
- `</YOUR_IDENTITY>`,
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
- `The research-history scout dispatched codebase-research-locator and`,
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
- `Read each explorer's findings file in full. Each file has the same`,
731
- `structure (Scope / Overview / Files in Scope / How It Works / Patterns /`,
732
- `External References / Cross-References / File Index). The findings`,
733
- `inside each file were produced by codebase-locator, codebase-analyzer,`,
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
- `<TASK>`,
741
- `1. Read EVERY explorer findings file in full, one at a time, using the`,
742
- ` Read tool with no offset or limit.`,
743
- `2. Synthesize the findings into a unified research document.`,
744
- `3. Cross-reference: identify connections between findings from different`,
745
- ` explorers, especially via the "Cross-References" sections.`,
746
- `4. Integrate historical context where it adds value — but live findings`,
747
- ` from the explorers are the primary source of truth. If history and`,
748
- ` live findings disagree, trust the live findings.`,
749
- `5. Resolve any remaining contradictions by re-reading the underlying`,
750
- ` source files directly.`,
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
- `</TASK>`,
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 components.`,
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 documents, with paths. Omit this`,
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} parallel`,
803
- `explorers covering ${opts.totalFiles.toLocaleString()} source files`,
804
- `(${opts.totalLoc.toLocaleString()} LOC). Each explorer dispatched the`,
805
- `codebase-locator, codebase-analyzer, codebase-pattern-finder, and (when`,
806
- `applicable) codebase-online-researcher sub-agents over its assigned`,
807
- `partition. A parallel research-history scout dispatched`,
808
- `codebase-research-locator and codebase-research-analyzer over the`,
809
- `project's prior research documents.`,
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 explorers contradict each other, re-read the underlying source files.`,
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
  ``,