@bastani/atomic 0.8.21-0 → 0.8.22-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/CHANGELOG.md +46 -9
- package/dist/builtin/intercom/broker/broker.ts +3 -3
- package/dist/builtin/intercom/config.ts +3 -3
- package/dist/builtin/intercom/index.ts +1 -1
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/intercom/ui/compose.ts +2 -2
- package/dist/builtin/mcp/host-html-template.ts +0 -3
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +13 -4
- package/dist/builtin/subagents/agents/codebase-online-researcher.md +9 -9
- package/dist/builtin/subagents/agents/debugger.md +6 -6
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/prompts/parallel-handoff-plan.md +1 -1
- package/dist/builtin/subagents/skills/browser-use/SKILL.md +234 -0
- package/dist/builtin/subagents/skills/browser-use/references/cdp-python.md +76 -0
- package/dist/builtin/subagents/skills/browser-use/references/multi-session.md +92 -0
- package/dist/builtin/subagents/skills/subagent/SKILL.md +4 -4
- package/dist/builtin/subagents/src/agents/skills.ts +19 -1
- package/dist/builtin/subagents/src/extension/index.ts +24 -22
- package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +7 -1
- package/dist/builtin/subagents/src/runs/background/async-execution.ts +23 -7
- package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +98 -3
- package/dist/builtin/subagents/src/runs/background/async-status.ts +3 -1
- package/dist/builtin/subagents/src/runs/background/run-status.ts +1 -1
- package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +3 -0
- package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +37 -12
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify.ts +15 -15
- package/dist/builtin/subagents/src/runs/foreground/execution.ts +26 -2
- package/dist/builtin/subagents/src/runs/shared/nested-render.ts +1 -1
- package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +7 -0
- package/dist/builtin/subagents/src/runs/shared/pi-args.ts +28 -1
- package/dist/builtin/subagents/src/shared/fast-mode.ts +80 -0
- package/dist/builtin/subagents/src/shared/formatters.ts +4 -2
- package/dist/builtin/subagents/src/shared/types.ts +4 -2
- package/dist/builtin/subagents/src/shared/utils.ts +3 -61
- package/dist/builtin/subagents/src/tui/render.ts +303 -157
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +101 -35
- package/dist/builtin/workflows/README.md +228 -41
- package/dist/builtin/workflows/builtin/deep-research-codebase.ts +535 -541
- package/dist/builtin/workflows/builtin/goal.ts +39 -25
- package/dist/builtin/workflows/builtin/open-claude-design.ts +66 -69
- package/dist/builtin/workflows/builtin/ralph.ts +21 -21
- package/dist/builtin/workflows/package.json +6 -5
- package/dist/builtin/workflows/skills/research-codebase/SKILL.md +1 -1
- package/dist/builtin/workflows/src/extension/background-ui-adapter.ts +2 -2
- package/dist/builtin/workflows/src/extension/discovery.ts +25 -146
- package/dist/builtin/workflows/src/extension/dispatcher.ts +72 -24
- package/dist/builtin/workflows/src/extension/hil-answer-notifications.ts +363 -0
- package/dist/builtin/workflows/src/extension/index.ts +690 -352
- package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +99 -62
- package/dist/builtin/workflows/src/extension/render-call.ts +2 -1
- package/dist/builtin/workflows/src/extension/render-result.ts +9 -3
- package/dist/builtin/workflows/src/extension/renderers.ts +5 -3
- package/dist/builtin/workflows/src/extension/runtime.ts +68 -33
- package/dist/builtin/workflows/src/extension/status-writer.ts +1 -1
- package/dist/builtin/workflows/src/extension/wiring.ts +34 -13
- package/dist/builtin/workflows/src/extension/workflow-module-loader.ts +142 -0
- package/dist/builtin/workflows/src/extension/workflow-schema.ts +4 -4
- package/dist/builtin/workflows/src/index.ts +2 -0
- package/dist/builtin/workflows/src/intercom/result-intercom.ts +1 -1
- package/dist/builtin/workflows/src/runs/background/runner.ts +6 -4
- package/dist/builtin/workflows/src/runs/background/status.ts +45 -21
- package/dist/builtin/workflows/src/runs/foreground/executor.ts +624 -52
- package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +80 -24
- package/dist/builtin/workflows/src/runs/shared/validate-inputs.ts +61 -24
- package/dist/builtin/workflows/src/runs/shared/workflow-runner.ts +32 -10
- package/dist/builtin/workflows/src/sdk-surface.ts +6 -0
- package/dist/builtin/workflows/src/shared/expanded-workflow-graph.ts +178 -0
- package/dist/builtin/workflows/src/shared/persistence-restore.ts +92 -12
- package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +21 -3
- package/dist/builtin/workflows/src/shared/render-inputs-schema.ts +1 -2
- package/dist/builtin/workflows/src/shared/run-visibility.ts +9 -0
- package/dist/builtin/workflows/src/shared/schema-introspection.ts +121 -0
- package/dist/builtin/workflows/src/shared/serializable.ts +132 -0
- package/dist/builtin/workflows/src/shared/stage-ui-broker.ts +91 -9
- package/dist/builtin/workflows/src/shared/store-types.ts +31 -3
- package/dist/builtin/workflows/src/shared/store.ts +58 -14
- package/dist/builtin/workflows/src/shared/types.ts +105 -40
- package/dist/builtin/workflows/src/tui/chat-surface-message.ts +129 -13
- package/dist/builtin/workflows/src/tui/chat-surface.ts +6 -1
- package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +3 -2
- package/dist/builtin/workflows/src/tui/graph-canvas.ts +1 -1
- package/dist/builtin/workflows/src/tui/graph-view.ts +91 -65
- package/dist/builtin/workflows/src/tui/inline-form-card.ts +1 -1
- package/dist/builtin/workflows/src/tui/inline-form-overlay.ts +3 -2
- package/dist/builtin/workflows/src/tui/inputs-overlay.ts +3 -2
- package/dist/builtin/workflows/src/tui/inputs-picker.ts +8 -7
- package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +2 -0
- package/dist/builtin/workflows/src/tui/node-card.ts +34 -8
- package/dist/builtin/workflows/src/tui/overlay-adapter.ts +4 -11
- package/dist/builtin/workflows/src/tui/prompt-card.ts +98 -50
- package/dist/builtin/workflows/src/tui/session-list.ts +7 -2
- package/dist/builtin/workflows/src/tui/session-picker.ts +2 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view.ts +226 -55
- package/dist/builtin/workflows/src/tui/status-helpers.ts +2 -0
- package/dist/builtin/workflows/src/tui/store-widget-installer.ts +37 -158
- package/dist/builtin/workflows/src/tui/toast.ts +2 -2
- package/dist/builtin/workflows/src/tui/widget.ts +53 -12
- package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +270 -19
- package/dist/builtin/workflows/src/tui/workflow-notice-card.ts +184 -0
- package/dist/builtin/workflows/src/workflows/define-workflow.ts +138 -43
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +45 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +27 -9
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +196 -17
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/atomic-guide-command.d.ts.map +1 -1
- package/dist/core/atomic-guide-command.js +2 -2
- package/dist/core/atomic-guide-command.js.map +1 -1
- package/dist/core/codex-fast-mode.d.ts +36 -0
- package/dist/core/codex-fast-mode.d.ts.map +1 -0
- package/dist/core/codex-fast-mode.js +117 -0
- package/dist/core/codex-fast-mode.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +1 -1
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +1 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/index.d.ts +4 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -0
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +7 -2
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +23 -8
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/reactive-widget.d.ts +58 -0
- package/dist/core/extensions/reactive-widget.d.ts.map +1 -0
- package/dist/core/extensions/reactive-widget.js +182 -0
- package/dist/core/extensions/reactive-widget.js.map +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +1 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +26 -12
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/messages.d.ts +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +8 -2
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry.d.ts +4 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +11 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/resource-loader.d.ts +9 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +49 -21
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +22 -13
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +7 -5
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +5 -3
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +16 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +64 -5
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +7 -4
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/ask-user-question.js +2 -2
- package/dist/core/tools/ask-user-question/ask-user-question.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +12 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/chat-input-actions.d.ts.map +1 -1
- package/dist/modes/interactive/chat-input-actions.js.map +1 -1
- package/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/dist/modes/interactive/components/diff.js +0 -1
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/fast-mode-selector.d.ts +27 -0
- package/dist/modes/interactive/components/fast-mode-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/fast-mode-selector.js +105 -0
- package/dist/modes/interactive/components/fast-mode-selector.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +7 -12
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +132 -30
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +53 -6
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +3 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/docs/compaction.md +1 -1
- package/docs/custom-provider.md +2 -2
- package/docs/development.md +2 -2
- package/docs/docs.json +2 -2
- package/docs/extensions.md +18 -13
- package/docs/providers.md +5 -1
- package/docs/quickstart.md +5 -3
- package/docs/rpc.md +5 -5
- package/docs/sdk.md +12 -12
- package/docs/settings.md +18 -0
- package/docs/themes.md +6 -6
- package/docs/tui.md +20 -18
- package/docs/usage.md +2 -0
- package/docs/workflows.md +403 -39
- package/examples/extensions/qna.ts +2 -2
- package/package.json +4 -4
- package/dist/builtin/subagents/skills/playwright-cli/SKILL.md +0 -392
- package/dist/builtin/subagents/skills/playwright-cli/references/element-attributes.md +0 -23
- package/dist/builtin/subagents/skills/playwright-cli/references/playwright-tests.md +0 -39
- package/dist/builtin/subagents/skills/playwright-cli/references/request-mocking.md +0 -87
- package/dist/builtin/subagents/skills/playwright-cli/references/running-code.md +0 -241
- package/dist/builtin/subagents/skills/playwright-cli/references/session-management.md +0 -225
- package/dist/builtin/subagents/skills/playwright-cli/references/spec-driven-testing.md +0 -305
- package/dist/builtin/subagents/skills/playwright-cli/references/storage-state.md +0 -275
- package/dist/builtin/subagents/skills/playwright-cli/references/test-generation.md +0 -134
- package/dist/builtin/subagents/skills/playwright-cli/references/tracing.md +0 -139
- package/dist/builtin/subagents/skills/playwright-cli/references/video-recording.md +0 -143
|
@@ -8,31 +8,35 @@
|
|
|
8
8
|
* ctx.parallel(), and ctx.chain().
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
11
12
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
12
13
|
import { dirname, extname, isAbsolute, join, relative } from "node:path";
|
|
13
|
-
import { defineWorkflow } from "../src/
|
|
14
|
+
import { defineWorkflow } from "../src/workflows/define-workflow.js";
|
|
15
|
+
import { Type } from "typebox";
|
|
14
16
|
import type {
|
|
15
17
|
WorkflowOutputMode,
|
|
16
|
-
|
|
18
|
+
WorkflowOutputValues,
|
|
17
19
|
WorkflowTaskResult,
|
|
18
20
|
WorkflowTaskStep,
|
|
19
21
|
} from "../src/shared/types.js";
|
|
20
22
|
|
|
21
23
|
const DEFAULT_MAX_PARTITIONS = 100;
|
|
22
|
-
const DEFAULT_MAX_CONCURRENCY =
|
|
24
|
+
const DEFAULT_MAX_CONCURRENCY = 100;
|
|
23
25
|
const LOC_PER_PARTITION = 10_000;
|
|
24
26
|
const DEFAULT_RESEARCH_DOC_DIR = "research";
|
|
25
27
|
const DEEP_RESEARCH_RUN_DIR_PREFIX = ".deep-research-";
|
|
26
28
|
const MAX_RESEARCH_DOC_SLUG_LENGTH = 80;
|
|
29
|
+
const GIT_LS_FILES_TIMEOUT_MS = 2_000;
|
|
27
30
|
|
|
28
31
|
type PromptSection = readonly [tag: string, content: string];
|
|
29
32
|
|
|
30
|
-
interface DeepResearchCodebaseResult extends
|
|
33
|
+
interface DeepResearchCodebaseResult extends WorkflowOutputValues {
|
|
34
|
+
readonly result: string;
|
|
31
35
|
readonly findings: string;
|
|
32
36
|
readonly research_doc_path: string;
|
|
33
37
|
readonly artifact_dir: string;
|
|
34
38
|
readonly manifest_path: string;
|
|
35
|
-
readonly partitions:
|
|
39
|
+
readonly partitions: string[];
|
|
36
40
|
readonly explorer_count: number;
|
|
37
41
|
readonly specialist_count: number;
|
|
38
42
|
readonly max_concurrency: number;
|
|
@@ -74,6 +78,14 @@ function positiveInteger(value: number | undefined, fallback: number): number {
|
|
|
74
78
|
: fallback;
|
|
75
79
|
}
|
|
76
80
|
|
|
81
|
+
function countNewlineBytes(bytes: Uint8Array): number {
|
|
82
|
+
let total = 0;
|
|
83
|
+
for (let i = 0; i < bytes.length; i += 1) {
|
|
84
|
+
if (bytes[i] === 10) total += 1;
|
|
85
|
+
}
|
|
86
|
+
return total;
|
|
87
|
+
}
|
|
88
|
+
|
|
77
89
|
function countCodebaseLines(cwd = process.cwd()): number {
|
|
78
90
|
try {
|
|
79
91
|
const gitFiles = Bun.spawnSync({
|
|
@@ -81,36 +93,26 @@ function countCodebaseLines(cwd = process.cwd()): number {
|
|
|
81
93
|
stdout: "pipe",
|
|
82
94
|
stderr: "pipe",
|
|
83
95
|
cwd,
|
|
96
|
+
timeout: GIT_LS_FILES_TIMEOUT_MS,
|
|
84
97
|
});
|
|
85
98
|
const files =
|
|
86
99
|
gitFiles.success && gitFiles.stdout
|
|
87
100
|
? gitFiles.stdout
|
|
88
101
|
.toString()
|
|
89
102
|
.split("\n")
|
|
103
|
+
.map((line) => line.replace(/\r$/, ""))
|
|
90
104
|
.filter((line) => line.length > 0)
|
|
91
105
|
: [];
|
|
92
106
|
|
|
93
107
|
if (files.length === 0) return 0;
|
|
94
108
|
|
|
95
109
|
let total = 0;
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
stderr: "pipe",
|
|
103
|
-
cwd,
|
|
104
|
-
});
|
|
105
|
-
if (!wc.stdout) continue;
|
|
106
|
-
|
|
107
|
-
for (const line of wc.stdout.toString().split("\n")) {
|
|
108
|
-
const match = line.match(/^\s*(\d+)\s+(.+)$/);
|
|
109
|
-
const countText = match?.[1];
|
|
110
|
-
const path = match?.[2]?.trim();
|
|
111
|
-
if (countText === undefined || path === undefined || path === "total")
|
|
112
|
-
continue;
|
|
113
|
-
total += Number.parseInt(countText, 10);
|
|
110
|
+
for (const file of files) {
|
|
111
|
+
try {
|
|
112
|
+
total += countNewlineBytes(readFileSync(join(cwd, file)));
|
|
113
|
+
} catch {
|
|
114
|
+
// The line count is only a partition-sizing heuristic. Ignore files
|
|
115
|
+
// that disappear, are unreadable, or are not regular files.
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
return total;
|
|
@@ -151,9 +153,14 @@ function slugifyResearchTopic(prompt: string): string {
|
|
|
151
153
|
return slug.length > 0 ? slug : "deep-research-codebase";
|
|
152
154
|
}
|
|
153
155
|
|
|
154
|
-
function defaultResearchDocPath(
|
|
156
|
+
function defaultResearchDocPath(
|
|
157
|
+
prompt: string,
|
|
158
|
+
cwd = process.cwd(),
|
|
159
|
+
now = new Date(),
|
|
160
|
+
): string {
|
|
155
161
|
const date = now.toISOString().slice(0, 10);
|
|
156
162
|
return join(
|
|
163
|
+
cwd,
|
|
157
164
|
DEFAULT_RESEARCH_DOC_DIR,
|
|
158
165
|
`${date}-${slugifyResearchTopic(prompt)}.md`,
|
|
159
166
|
);
|
|
@@ -315,8 +322,9 @@ function displayPath(path: string): string {
|
|
|
315
322
|
return path.replace(/\\/g, "/");
|
|
316
323
|
}
|
|
317
324
|
|
|
318
|
-
function
|
|
319
|
-
|
|
325
|
+
function displayRelativePath(path: string, fromCwd: string): string {
|
|
326
|
+
if (!isAbsolute(path)) return displayPath(path);
|
|
327
|
+
const relativePath = relative(fromCwd, path);
|
|
320
328
|
if (relativePath.length === 0) return ".";
|
|
321
329
|
if (!relativePath.startsWith("..") && !isAbsolute(relativePath)) {
|
|
322
330
|
return displayPath(relativePath);
|
|
@@ -324,582 +332,568 @@ function displayPathFrom(cwd: string, path: string): string {
|
|
|
324
332
|
return displayPath(path);
|
|
325
333
|
}
|
|
326
334
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
)
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
)
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
"
|
|
404
|
-
"
|
|
405
|
-
|
|
406
|
-
],
|
|
407
|
-
thinkingLevel: "high" as const,
|
|
408
|
-
excludedTools: ["ask_user_question"],
|
|
409
|
-
};
|
|
410
|
-
|
|
411
|
-
const explorerModelConfig = {
|
|
412
|
-
model: "openai/gpt-5.4-mini",
|
|
413
|
-
fallbackModels: [
|
|
414
|
-
"openai-codex/gpt-5.4-mini",
|
|
415
|
-
"github-copilot/gpt-5.4-mini",
|
|
416
|
-
"anthropic/claude-haiku-4-5",
|
|
417
|
-
"github-copilot/claude-haiku-4.5",
|
|
418
|
-
],
|
|
419
|
-
thinkingLevel: "low" as const,
|
|
420
|
-
excludedTools: ["ask_user_question"],
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
const initialDiscovery = await ctx.parallel(
|
|
424
|
-
[
|
|
425
|
-
{
|
|
426
|
-
name: "codebase-scout",
|
|
427
|
-
task: taggedPrompt([
|
|
428
|
-
[
|
|
429
|
-
"role",
|
|
430
|
-
"You are a senior codebase research scout preparing work for specialist agents.",
|
|
431
|
-
],
|
|
432
|
-
["objective", `Map the repository. Research question: ${prompt}`],
|
|
433
|
-
[
|
|
434
|
-
"codebase_skills",
|
|
435
|
-
codebaseSkillGuidance("locator", "analyzer", "patternFinder"),
|
|
436
|
-
],
|
|
437
|
-
[
|
|
438
|
-
"instructions",
|
|
439
|
-
[
|
|
440
|
-
"Identify the subsystems, files, tests, docs, and runtime/configuration areas most likely to answer the question.",
|
|
441
|
-
`Propose at most ${partitionCap} independent investigation partitions that can be assigned to parallel specialists.`,
|
|
442
|
-
"Ground codebase claims in concrete paths, symbols, commands, or docs when possible.",
|
|
443
|
-
"If evidence is missing or uncertain, say so explicitly instead of guessing.",
|
|
444
|
-
].join("\n"),
|
|
445
|
-
],
|
|
446
|
-
[
|
|
447
|
-
"output_format",
|
|
448
|
-
[
|
|
449
|
-
"Markdown with these headings:",
|
|
450
|
-
"1. Executive orientation",
|
|
451
|
-
"2. Key paths and why they matter",
|
|
452
|
-
"3. Suggested partitions",
|
|
453
|
-
"4. Known unknowns / risks",
|
|
454
|
-
].join("\n"),
|
|
455
|
-
],
|
|
456
|
-
]),
|
|
457
|
-
...fileOnlyOutput(scoutPath),
|
|
458
|
-
...plannerModelConfig,
|
|
459
|
-
},
|
|
460
|
-
{
|
|
461
|
-
name: "history-locator",
|
|
462
|
-
task: taggedPrompt([
|
|
463
|
-
["role", "You locate prior project research and decision history."],
|
|
464
|
-
[
|
|
465
|
-
"objective",
|
|
466
|
-
"Find existing docs, specs, ADRs, issues/PR notes, TODOs, and research artifacts relevant to the task.",
|
|
467
|
-
],
|
|
468
|
-
["task", "{task}"],
|
|
469
|
-
["codebase_skills", codebaseSkillGuidance("researchLocator")],
|
|
470
|
-
[
|
|
471
|
-
"instructions",
|
|
472
|
-
[
|
|
473
|
-
"Search broadly before narrowing.",
|
|
474
|
-
"Prefer exact file paths, section names, and short relevance notes.",
|
|
475
|
-
"Separate strong evidence from weak/possibly stale evidence.",
|
|
476
|
-
"If no prior research exists, state that plainly and list where you looked.",
|
|
477
|
-
].join("\n"),
|
|
478
|
-
],
|
|
479
|
-
[
|
|
480
|
-
"output_format",
|
|
481
|
-
"A markdown table with columns: Path, Evidence, Relevance, Confidence.",
|
|
482
|
-
],
|
|
483
|
-
]),
|
|
484
|
-
...fileOnlyOutput(historyLocatorPath),
|
|
485
|
-
...explorerModelConfig,
|
|
486
|
-
},
|
|
487
|
-
],
|
|
488
|
-
{ task: prompt, concurrency: maxConcurrency },
|
|
489
|
-
);
|
|
490
|
-
|
|
491
|
-
const scout =
|
|
492
|
-
findResult(initialDiscovery, "codebase-scout") ?? initialDiscovery[0]!;
|
|
493
|
-
const historyLocator =
|
|
494
|
-
findResult(initialDiscovery, "history-locator") ?? initialDiscovery[1]!;
|
|
495
|
-
await ctx.chain(
|
|
496
|
-
[
|
|
497
|
-
{
|
|
498
|
-
name: "history-analyzer",
|
|
499
|
-
task: taggedPrompt([
|
|
500
|
-
[
|
|
501
|
-
"role",
|
|
502
|
-
"You synthesize prior project research for downstream investigators.",
|
|
503
|
-
],
|
|
504
|
-
[
|
|
505
|
-
"objective",
|
|
506
|
-
`Extract reusable historical context. Research question: ${prompt}`,
|
|
507
|
-
],
|
|
508
|
-
["prior_research_locator_output", "{previous}"],
|
|
509
|
-
["codebase_skills", codebaseSkillGuidance("researchAnalyzer")],
|
|
510
|
-
[
|
|
511
|
-
"instructions",
|
|
512
|
-
[
|
|
513
|
-
"Cluster related prior decisions and unresolved questions.",
|
|
514
|
-
"Identify which findings are still likely valid and which may be stale.",
|
|
515
|
-
"Quote or cite paths from the locator output for every important claim.",
|
|
516
|
-
"Do not invent history that is not supported by the locator output.",
|
|
517
|
-
].join("\n"),
|
|
518
|
-
],
|
|
519
|
-
[
|
|
520
|
-
"output_format",
|
|
521
|
-
[
|
|
522
|
-
"Markdown with headings:",
|
|
523
|
-
"1. Prior decisions",
|
|
524
|
-
"2. Relevant research artifacts",
|
|
525
|
-
"3. Open questions",
|
|
526
|
-
"4. How this should steer the new investigation",
|
|
527
|
-
].join("\n"),
|
|
528
|
-
],
|
|
529
|
-
]),
|
|
530
|
-
previous: historyLocator,
|
|
531
|
-
reads: [historyLocatorPath],
|
|
532
|
-
...fileOnlyOutput(historyAnalyzerPath),
|
|
533
|
-
...plannerModelConfig,
|
|
534
|
-
},
|
|
535
|
-
],
|
|
536
|
-
{ task: prompt },
|
|
537
|
-
);
|
|
335
|
+
export default defineWorkflow("deep-research-codebase")
|
|
336
|
+
.description(
|
|
337
|
+
"Scout + research-history chain → parallel specialist waves → aggregator for deep codebase research.",
|
|
338
|
+
)
|
|
339
|
+
.input("prompt", Type.String({ description: "Research question or investigation focus for the codebase." }))
|
|
340
|
+
.input("max_partitions", Type.Number({
|
|
341
|
+
default: DEFAULT_MAX_PARTITIONS,
|
|
342
|
+
description:
|
|
343
|
+
"Maximum number of codebase partitions to explore in parallel. Actual partitions scale by one per 10K LoC, capped by this value.",
|
|
344
|
+
}))
|
|
345
|
+
.input("max_concurrency", Type.Number({
|
|
346
|
+
default: DEFAULT_MAX_CONCURRENCY,
|
|
347
|
+
description: "Maximum number of workflow stages to run concurrently during deep research.",
|
|
348
|
+
}))
|
|
349
|
+
.output("result", Type.Optional(Type.String({ description: "Final Markdown research report text, matching findings." })))
|
|
350
|
+
.output("findings", Type.Optional(Type.String({ description: "Final Markdown research report text." })))
|
|
351
|
+
.output("research_doc_path", Type.Optional(Type.String({ description: "Public report path under research/<date>-<topic>.md." })))
|
|
352
|
+
.output("artifact_dir", Type.Optional(Type.String({ description: "Hidden per-run handoff directory containing deep-research artifacts." })))
|
|
353
|
+
.output("manifest_path", Type.Optional(Type.String({ description: "Manifest JSON path inside the hidden artifact directory." })))
|
|
354
|
+
.output("partitions", Type.Optional(Type.Array(Type.String(), { description: "Codebase partitions the specialists explored." })))
|
|
355
|
+
.output("explorer_count", Type.Optional(Type.Number({ description: "Number of partition explorer groups used." })))
|
|
356
|
+
.output("specialist_count", Type.Optional(Type.Number({ description: "Number of specialist stages run across the research waves." })))
|
|
357
|
+
.output("max_concurrency", Type.Optional(Type.Number({ description: "Concurrency limit used for the run." })))
|
|
358
|
+
.output("history", Type.Optional(Type.String({ description: "Prior-research/history overview included in the final synthesis." })))
|
|
359
|
+
.run(async (ctx) => {
|
|
360
|
+
const inputs = ctx.inputs;
|
|
361
|
+
const prompt = inputs.prompt;
|
|
362
|
+
const requestedMaxPartitions = positiveInteger(
|
|
363
|
+
inputs.max_partitions,
|
|
364
|
+
DEFAULT_MAX_PARTITIONS,
|
|
365
|
+
);
|
|
366
|
+
const maxConcurrency = positiveInteger(
|
|
367
|
+
inputs.max_concurrency,
|
|
368
|
+
DEFAULT_MAX_CONCURRENCY,
|
|
369
|
+
);
|
|
370
|
+
const startedAt = new Date();
|
|
371
|
+
const workflowCwd = ctx.cwd ?? process.cwd();
|
|
372
|
+
const finalResearchDocPath = defaultResearchDocPath(prompt, workflowCwd, startedAt);
|
|
373
|
+
const codebaseLines = countCodebaseLines(workflowCwd);
|
|
374
|
+
const partitionCap = calculatePartitionCap(
|
|
375
|
+
requestedMaxPartitions,
|
|
376
|
+
codebaseLines,
|
|
377
|
+
);
|
|
378
|
+
const { runId, artifactRoot } = await createArtifactRoot(startedAt, workflowCwd);
|
|
379
|
+
const artifactPathsByStage = new Map<string, string>();
|
|
380
|
+
const addArtifact = (stage: string, path: string) => {
|
|
381
|
+
artifactPathsByStage.set(stage, path);
|
|
382
|
+
return path;
|
|
383
|
+
};
|
|
384
|
+
const fileOnlyOutput = (
|
|
385
|
+
output: string,
|
|
386
|
+
): {
|
|
387
|
+
output: string;
|
|
388
|
+
outputMode: WorkflowOutputMode;
|
|
389
|
+
} => ({
|
|
390
|
+
output,
|
|
391
|
+
outputMode: FILE_ONLY_OUTPUT,
|
|
392
|
+
});
|
|
393
|
+
const displayWorkflowPath = (path: string): string =>
|
|
394
|
+
displayRelativePath(path, workflowCwd);
|
|
395
|
+
const displayWorkflowPaths = (paths: readonly string[]): string =>
|
|
396
|
+
paths.map(displayWorkflowPath).join(", ");
|
|
397
|
+
|
|
398
|
+
const scoutPath = addArtifact(
|
|
399
|
+
"codebase-scout",
|
|
400
|
+
join(artifactRoot, "00-codebase-scout.md"),
|
|
401
|
+
);
|
|
402
|
+
const partitionPlanPath = addArtifact(
|
|
403
|
+
"partition",
|
|
404
|
+
join(artifactRoot, "01-partition-plan.md"),
|
|
405
|
+
);
|
|
406
|
+
const historyLocatorPath = addArtifact(
|
|
407
|
+
"history-locator",
|
|
408
|
+
join(artifactRoot, "01-history-locator.md"),
|
|
409
|
+
);
|
|
410
|
+
const historyAnalyzerPath = addArtifact(
|
|
411
|
+
"history-analyzer",
|
|
412
|
+
join(artifactRoot, "02-history-analyzer.md"),
|
|
413
|
+
);
|
|
538
414
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
[
|
|
542
|
-
|
|
543
|
-
"
|
|
544
|
-
|
|
415
|
+
const plannerModelConfig = {
|
|
416
|
+
model: "openai/gpt-5.5",
|
|
417
|
+
fallbackModels: [
|
|
418
|
+
"openai-codex/gpt-5.5",
|
|
419
|
+
"github-copilot/gpt-5.5",
|
|
420
|
+
"anthropic/claude-opus-4-8",
|
|
421
|
+
"github-copilot/claude-opus-4.7",
|
|
545
422
|
],
|
|
546
|
-
|
|
547
|
-
[
|
|
548
|
-
|
|
549
|
-
|
|
423
|
+
thinkingLevel: "high" as const,
|
|
424
|
+
excludedTools: ["ask_user_question"],
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
const explorerModelConfig = {
|
|
428
|
+
model: "openai/gpt-5.4-mini",
|
|
429
|
+
fallbackModels: [
|
|
430
|
+
"openai-codex/gpt-5.4-mini",
|
|
431
|
+
"github-copilot/gpt-5.4-mini",
|
|
432
|
+
"anthropic/claude-haiku-4-5",
|
|
433
|
+
"github-copilot/claude-haiku-4.5",
|
|
550
434
|
],
|
|
435
|
+
thinkingLevel: "low" as const,
|
|
436
|
+
excludedTools: ["ask_user_question"],
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
const initialDiscovery = await ctx.parallel(
|
|
551
440
|
[
|
|
552
|
-
"instructions",
|
|
553
|
-
[
|
|
554
|
-
"Each partition must be concrete enough for one specialist to investigate independently.",
|
|
555
|
-
"Prefer boundaries based on files, subsystems, runtime layers, or documented concepts.",
|
|
556
|
-
"Do not include bullets, numbering, markdown fences, explanations, or duplicate partitions.",
|
|
557
|
-
].join("\n"),
|
|
558
|
-
],
|
|
559
|
-
["output_format", "Plain text only: one partition per line."],
|
|
560
|
-
]),
|
|
561
|
-
previous: scout,
|
|
562
|
-
output: partitionPlanPath,
|
|
563
|
-
reads: [scoutPath],
|
|
564
|
-
...plannerModelConfig,
|
|
565
|
-
});
|
|
566
|
-
|
|
567
|
-
const partitions = parsePartitions(partitionPlan.text, partitionCap);
|
|
568
|
-
const locatorArtifactPaths = new Map<number, string>();
|
|
569
|
-
|
|
570
|
-
const wave1Steps: WorkflowTaskStep[] = partitions.flatMap(
|
|
571
|
-
(partition, index) => {
|
|
572
|
-
const i = index + 1;
|
|
573
|
-
const locatorPath = addArtifact(
|
|
574
|
-
`locator-${i}`,
|
|
575
|
-
join(artifactRoot, `locator-${i}.md`),
|
|
576
|
-
);
|
|
577
|
-
const patternFinderPath = addArtifact(
|
|
578
|
-
`pattern-finder-${i}`,
|
|
579
|
-
join(artifactRoot, `pattern-finder-${i}.md`),
|
|
580
|
-
);
|
|
581
|
-
locatorArtifactPaths.set(i, locatorPath);
|
|
582
|
-
return [
|
|
583
441
|
{
|
|
584
|
-
name:
|
|
442
|
+
name: "codebase-scout",
|
|
585
443
|
task: taggedPrompt([
|
|
586
|
-
["role", "You are a codebase locator specialist."],
|
|
587
|
-
["assignment", `Partition ${i}/${partitions.length}: ${partition}`],
|
|
588
|
-
["research_question", prompt],
|
|
589
444
|
[
|
|
590
|
-
"
|
|
591
|
-
|
|
592
|
-
],
|
|
593
|
-
["codebase_skills", codebaseSkillGuidance("locator")],
|
|
594
|
-
[
|
|
595
|
-
"instructions",
|
|
596
|
-
[
|
|
597
|
-
"Find the highest-signal files, tests, docs, commands, configs, and symbols for this partition.",
|
|
598
|
-
"Explain why each path matters for the research question.",
|
|
599
|
-
"Prioritize exact paths and symbol names over broad descriptions.",
|
|
600
|
-
"Flag areas that look relevant but could not be verified.",
|
|
601
|
-
].join("\n"),
|
|
602
|
-
],
|
|
603
|
-
[
|
|
604
|
-
"output_format",
|
|
605
|
-
[
|
|
606
|
-
"Markdown with headings:",
|
|
607
|
-
"1. Must-read paths",
|
|
608
|
-
"2. Supporting paths",
|
|
609
|
-
"3. Entry points / symbols",
|
|
610
|
-
"4. Gaps or uncertainty",
|
|
611
|
-
].join("\n"),
|
|
445
|
+
"role",
|
|
446
|
+
"You are a senior codebase research scout preparing work for specialist agents.",
|
|
612
447
|
],
|
|
613
|
-
|
|
614
|
-
previous: scout,
|
|
615
|
-
reads: [scoutPath],
|
|
616
|
-
...fileOnlyOutput(locatorPath),
|
|
617
|
-
...explorerModelConfig,
|
|
618
|
-
},
|
|
619
|
-
{
|
|
620
|
-
name: `pattern-finder-${i}`,
|
|
621
|
-
task: taggedPrompt([
|
|
622
|
-
["role", "You are a codebase pattern-finding specialist."],
|
|
623
|
-
["assignment", `Partition ${i}/${partitions.length}: ${partition}`],
|
|
624
|
-
["research_question", prompt],
|
|
448
|
+
["objective", `Map the repository. Research question: ${prompt}`],
|
|
625
449
|
[
|
|
626
|
-
"
|
|
627
|
-
|
|
450
|
+
"codebase_skills",
|
|
451
|
+
codebaseSkillGuidance("locator", "analyzer", "patternFinder"),
|
|
628
452
|
],
|
|
629
|
-
["codebase_skills", codebaseSkillGuidance("patternFinder")],
|
|
630
453
|
[
|
|
631
454
|
"instructions",
|
|
632
455
|
[
|
|
633
|
-
"Identify
|
|
634
|
-
|
|
635
|
-
"
|
|
636
|
-
"
|
|
456
|
+
"Identify the subsystems, files, tests, docs, and runtime/configuration areas most likely to answer the question.",
|
|
457
|
+
`Propose at most ${partitionCap} independent investigation partitions that can be assigned to parallel specialists.`,
|
|
458
|
+
"Ground codebase claims in concrete paths, symbols, commands, or docs when possible.",
|
|
459
|
+
"If evidence is missing or uncertain, say so explicitly instead of guessing.",
|
|
637
460
|
].join("\n"),
|
|
638
461
|
],
|
|
639
462
|
[
|
|
640
463
|
"output_format",
|
|
641
464
|
[
|
|
642
|
-
"Markdown with headings:",
|
|
643
|
-
"1.
|
|
644
|
-
"2.
|
|
645
|
-
"3.
|
|
646
|
-
"4.
|
|
465
|
+
"Markdown with these headings:",
|
|
466
|
+
"1. Executive orientation",
|
|
467
|
+
"2. Key paths and why they matter",
|
|
468
|
+
"3. Suggested partitions",
|
|
469
|
+
"4. Known unknowns / risks",
|
|
647
470
|
].join("\n"),
|
|
648
471
|
],
|
|
649
472
|
]),
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
...fileOnlyOutput(patternFinderPath),
|
|
653
|
-
...explorerModelConfig,
|
|
473
|
+
...fileOnlyOutput(scoutPath),
|
|
474
|
+
...plannerModelConfig,
|
|
654
475
|
},
|
|
655
|
-
];
|
|
656
|
-
},
|
|
657
|
-
);
|
|
658
|
-
|
|
659
|
-
const wave1 = await ctx.parallel(wave1Steps, {
|
|
660
|
-
task: prompt,
|
|
661
|
-
concurrency: maxConcurrency,
|
|
662
|
-
});
|
|
663
|
-
|
|
664
|
-
const wave2Steps: WorkflowTaskStep[] = partitions.flatMap(
|
|
665
|
-
(partition, index) => {
|
|
666
|
-
const i = index + 1;
|
|
667
|
-
const locator = findResult(wave1, `locator-${i}`);
|
|
668
|
-
const locatorPath =
|
|
669
|
-
locator === undefined ? undefined : locatorArtifactPaths.get(i);
|
|
670
|
-
const analyzerReads =
|
|
671
|
-
locatorPath === undefined ? [scoutPath] : [scoutPath, locatorPath];
|
|
672
|
-
const onlineResearcherReads =
|
|
673
|
-
locatorPath === undefined ? [scoutPath] : [locatorPath];
|
|
674
|
-
const onlineResearcherLocalContext =
|
|
675
|
-
locatorPath === undefined
|
|
676
|
-
? `Read scout context before researching: ${displayWorkflowPath(scoutPath)}\nCompact saved-output reference: {previous}`
|
|
677
|
-
: `Read local artifact context before researching: ${displayWorkflowPath(locatorPath)}\nCompact saved-output reference: {previous}`;
|
|
678
|
-
const analyzerPath = addArtifact(
|
|
679
|
-
`analyzer-${i}`,
|
|
680
|
-
join(artifactRoot, `analyzer-${i}.md`),
|
|
681
|
-
);
|
|
682
|
-
const onlineResearcherPath = addArtifact(
|
|
683
|
-
`online-${i}`,
|
|
684
|
-
join(artifactRoot, `online-${i}.md`),
|
|
685
|
-
);
|
|
686
|
-
return [
|
|
687
476
|
{
|
|
688
|
-
name:
|
|
477
|
+
name: "history-locator",
|
|
689
478
|
task: taggedPrompt([
|
|
690
|
-
["role", "You
|
|
691
|
-
["assignment", `Partition ${i}/${partitions.length}: ${partition}`],
|
|
692
|
-
["research_question", prompt],
|
|
479
|
+
["role", "You locate prior project research and decision history."],
|
|
693
480
|
[
|
|
694
|
-
"
|
|
695
|
-
|
|
481
|
+
"objective",
|
|
482
|
+
"Find existing docs, specs, ADRs, issues/PR notes, TODOs, and research artifacts relevant to the task.",
|
|
696
483
|
],
|
|
697
|
-
["
|
|
484
|
+
["task", "{task}"],
|
|
485
|
+
["codebase_skills", codebaseSkillGuidance("researchLocator")],
|
|
698
486
|
[
|
|
699
487
|
"instructions",
|
|
700
488
|
[
|
|
701
|
-
"
|
|
702
|
-
"
|
|
703
|
-
"
|
|
704
|
-
"If
|
|
489
|
+
"Search broadly before narrowing.",
|
|
490
|
+
"Prefer exact file paths, section names, and short relevance notes.",
|
|
491
|
+
"Separate strong evidence from weak/possibly stale evidence.",
|
|
492
|
+
"If no prior research exists, state that plainly and list where you looked.",
|
|
705
493
|
].join("\n"),
|
|
706
494
|
],
|
|
707
495
|
[
|
|
708
496
|
"output_format",
|
|
709
|
-
|
|
710
|
-
"Markdown with headings:",
|
|
711
|
-
"1. Behavioral model",
|
|
712
|
-
"2. Key flows and invariants",
|
|
713
|
-
"3. Tests / validation",
|
|
714
|
-
"4. Risks, unknowns, and verification steps",
|
|
715
|
-
].join("\n"),
|
|
497
|
+
"A markdown table with columns: Path, Evidence, Relevance, Confidence.",
|
|
716
498
|
],
|
|
717
499
|
]),
|
|
718
|
-
|
|
719
|
-
reads: analyzerReads,
|
|
720
|
-
...fileOnlyOutput(analyzerPath),
|
|
500
|
+
...fileOnlyOutput(historyLocatorPath),
|
|
721
501
|
...explorerModelConfig,
|
|
722
502
|
},
|
|
503
|
+
],
|
|
504
|
+
{ task: prompt, concurrency: maxConcurrency },
|
|
505
|
+
);
|
|
506
|
+
|
|
507
|
+
const scout =
|
|
508
|
+
findResult(initialDiscovery, "codebase-scout") ?? initialDiscovery[0]!;
|
|
509
|
+
const historyLocator =
|
|
510
|
+
findResult(initialDiscovery, "history-locator") ?? initialDiscovery[1]!;
|
|
511
|
+
await ctx.chain(
|
|
512
|
+
[
|
|
723
513
|
{
|
|
724
|
-
name:
|
|
514
|
+
name: "history-analyzer",
|
|
725
515
|
task: taggedPrompt([
|
|
726
516
|
[
|
|
727
517
|
"role",
|
|
728
|
-
"You
|
|
518
|
+
"You synthesize prior project research for downstream investigators.",
|
|
519
|
+
],
|
|
520
|
+
[
|
|
521
|
+
"objective",
|
|
522
|
+
`Extract reusable historical context. Research question: ${prompt}`,
|
|
729
523
|
],
|
|
730
|
-
["
|
|
731
|
-
["
|
|
732
|
-
["local_context", onlineResearcherLocalContext],
|
|
733
|
-
["codebase_skills", codebaseSkillGuidance("onlineResearcher")],
|
|
524
|
+
["prior_research_locator_output", "{previous}"],
|
|
525
|
+
["codebase_skills", codebaseSkillGuidance("researchAnalyzer")],
|
|
734
526
|
[
|
|
735
527
|
"instructions",
|
|
736
528
|
[
|
|
737
|
-
"
|
|
738
|
-
"
|
|
739
|
-
"
|
|
740
|
-
"
|
|
529
|
+
"Cluster related prior decisions and unresolved questions.",
|
|
530
|
+
"Identify which findings are still likely valid and which may be stale.",
|
|
531
|
+
"Quote or cite paths from the locator output for every important claim.",
|
|
532
|
+
"Do not invent history that is not supported by the locator output.",
|
|
741
533
|
].join("\n"),
|
|
742
534
|
],
|
|
743
535
|
[
|
|
744
536
|
"output_format",
|
|
745
537
|
[
|
|
746
538
|
"Markdown with headings:",
|
|
747
|
-
"1.
|
|
748
|
-
"2.
|
|
749
|
-
"3.
|
|
750
|
-
"4.
|
|
539
|
+
"1. Prior decisions",
|
|
540
|
+
"2. Relevant research artifacts",
|
|
541
|
+
"3. Open questions",
|
|
542
|
+
"4. How this should steer the new investigation",
|
|
751
543
|
].join("\n"),
|
|
752
544
|
],
|
|
753
545
|
]),
|
|
754
|
-
previous:
|
|
755
|
-
reads:
|
|
756
|
-
...fileOnlyOutput(
|
|
757
|
-
...
|
|
546
|
+
previous: historyLocator,
|
|
547
|
+
reads: [historyLocatorPath],
|
|
548
|
+
...fileOnlyOutput(historyAnalyzerPath),
|
|
549
|
+
...plannerModelConfig,
|
|
758
550
|
},
|
|
759
|
-
]
|
|
760
|
-
|
|
761
|
-
|
|
551
|
+
],
|
|
552
|
+
{ task: prompt },
|
|
553
|
+
);
|
|
762
554
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
555
|
+
const partitionPlan = await ctx.task("partition", {
|
|
556
|
+
prompt: taggedPrompt([
|
|
557
|
+
["role", "You turn scout research into clean work partitions."],
|
|
558
|
+
[
|
|
559
|
+
"objective",
|
|
560
|
+
`Return at most ${partitionCap} independent partitions for this research question: ${prompt}`,
|
|
561
|
+
],
|
|
562
|
+
["scout_output", "{previous}"],
|
|
563
|
+
[
|
|
564
|
+
"codebase_skills",
|
|
565
|
+
codebaseSkillGuidance("locator", "analyzer", "patternFinder"),
|
|
566
|
+
],
|
|
567
|
+
[
|
|
568
|
+
"instructions",
|
|
569
|
+
[
|
|
570
|
+
"Each partition must be concrete enough for one specialist to investigate independently.",
|
|
571
|
+
"Prefer boundaries based on files, subsystems, runtime layers, or documented concepts.",
|
|
572
|
+
"Do not include bullets, numbering, markdown fences, explanations, or duplicate partitions.",
|
|
573
|
+
].join("\n"),
|
|
574
|
+
],
|
|
575
|
+
["output_format", "Plain text only: one partition per line."],
|
|
576
|
+
]),
|
|
577
|
+
previous: scout,
|
|
578
|
+
output: partitionPlanPath,
|
|
579
|
+
reads: [scoutPath],
|
|
580
|
+
...plannerModelConfig,
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
const partitions = parsePartitions(partitionPlan.text, partitionCap);
|
|
584
|
+
const locatorArtifactPaths = new Map<number, string>();
|
|
585
|
+
|
|
586
|
+
const wave1Steps: WorkflowTaskStep[] = partitions.flatMap(
|
|
587
|
+
(partition, index) => {
|
|
588
|
+
const i = index + 1;
|
|
589
|
+
const locatorPath = addArtifact(
|
|
590
|
+
`locator-${i}`,
|
|
591
|
+
join(artifactRoot, `locator-${i}.md`),
|
|
592
|
+
);
|
|
593
|
+
const patternFinderPath = addArtifact(
|
|
594
|
+
`pattern-finder-${i}`,
|
|
595
|
+
join(artifactRoot, `pattern-finder-${i}.md`),
|
|
596
|
+
);
|
|
597
|
+
locatorArtifactPaths.set(i, locatorPath);
|
|
598
|
+
return [
|
|
599
|
+
{
|
|
600
|
+
name: `locator-${i}`,
|
|
601
|
+
task: taggedPrompt([
|
|
602
|
+
["role", "You are a codebase locator specialist."],
|
|
603
|
+
["assignment", `Partition ${i}/${partitions.length}: ${partition}`],
|
|
604
|
+
["research_question", prompt],
|
|
605
|
+
[
|
|
606
|
+
"scout_context",
|
|
607
|
+
`Read the scout artifact before making evidence claims: ${displayWorkflowPath(scoutPath)}\nCompact saved-output reference: {previous}`,
|
|
608
|
+
],
|
|
609
|
+
["codebase_skills", codebaseSkillGuidance("locator")],
|
|
610
|
+
[
|
|
611
|
+
"instructions",
|
|
612
|
+
[
|
|
613
|
+
"Find the highest-signal files, tests, docs, commands, configs, and symbols for this partition.",
|
|
614
|
+
"Explain why each path matters for the research question.",
|
|
615
|
+
"Prioritize exact paths and symbol names over broad descriptions.",
|
|
616
|
+
"Flag areas that look relevant but could not be verified.",
|
|
617
|
+
].join("\n"),
|
|
618
|
+
],
|
|
619
|
+
[
|
|
620
|
+
"output_format",
|
|
621
|
+
[
|
|
622
|
+
"Markdown with headings:",
|
|
623
|
+
"1. Must-read paths",
|
|
624
|
+
"2. Supporting paths",
|
|
625
|
+
"3. Entry points / symbols",
|
|
626
|
+
"4. Gaps or uncertainty",
|
|
627
|
+
].join("\n"),
|
|
628
|
+
],
|
|
629
|
+
]),
|
|
630
|
+
previous: scout,
|
|
631
|
+
reads: [scoutPath],
|
|
632
|
+
...fileOnlyOutput(locatorPath),
|
|
633
|
+
...explorerModelConfig,
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
name: `pattern-finder-${i}`,
|
|
637
|
+
task: taggedPrompt([
|
|
638
|
+
["role", "You are a codebase pattern-finding specialist."],
|
|
639
|
+
["assignment", `Partition ${i}/${partitions.length}: ${partition}`],
|
|
640
|
+
["research_question", prompt],
|
|
641
|
+
[
|
|
642
|
+
"scout_context",
|
|
643
|
+
`Read the scout artifact before making evidence claims: ${displayWorkflowPath(scoutPath)}\nCompact saved-output reference: {previous}`,
|
|
644
|
+
],
|
|
645
|
+
["codebase_skills", codebaseSkillGuidance("patternFinder")],
|
|
646
|
+
[
|
|
647
|
+
"instructions",
|
|
648
|
+
[
|
|
649
|
+
"Identify recurring implementation patterns, abstractions, naming conventions, and anti-patterns in this partition.",
|
|
650
|
+
"Use concrete examples with paths, symbols, or test names.",
|
|
651
|
+
"Distinguish established conventions from one-off implementation details.",
|
|
652
|
+
"Avoid generic advice that is not grounded in the repository.",
|
|
653
|
+
].join("\n"),
|
|
654
|
+
],
|
|
655
|
+
[
|
|
656
|
+
"output_format",
|
|
657
|
+
[
|
|
658
|
+
"Markdown with headings:",
|
|
659
|
+
"1. Established patterns",
|
|
660
|
+
"2. Variations / exceptions",
|
|
661
|
+
"3. Anti-patterns or risks",
|
|
662
|
+
"4. Evidence index",
|
|
663
|
+
].join("\n"),
|
|
664
|
+
],
|
|
665
|
+
]),
|
|
666
|
+
previous: scout,
|
|
667
|
+
reads: [scoutPath],
|
|
668
|
+
...fileOnlyOutput(patternFinderPath),
|
|
669
|
+
...explorerModelConfig,
|
|
670
|
+
},
|
|
671
|
+
];
|
|
672
|
+
},
|
|
673
|
+
);
|
|
674
|
+
|
|
675
|
+
const wave1 = await ctx.parallel(wave1Steps, {
|
|
676
|
+
task: prompt,
|
|
677
|
+
concurrency: maxConcurrency,
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
const wave2Steps: WorkflowTaskStep[] = partitions.flatMap(
|
|
681
|
+
(partition, index) => {
|
|
682
|
+
const i = index + 1;
|
|
683
|
+
const locator = findResult(wave1, `locator-${i}`);
|
|
684
|
+
const locatorPath =
|
|
685
|
+
locator === undefined ? undefined : locatorArtifactPaths.get(i);
|
|
686
|
+
const analyzerReads =
|
|
687
|
+
locatorPath === undefined ? [scoutPath] : [scoutPath, locatorPath];
|
|
688
|
+
const onlineResearcherReads =
|
|
689
|
+
locatorPath === undefined ? [scoutPath] : [locatorPath];
|
|
690
|
+
const onlineResearcherLocalContext =
|
|
691
|
+
locatorPath === undefined
|
|
692
|
+
? `Read scout context before researching: ${displayWorkflowPath(scoutPath)}\nCompact saved-output reference: {previous}`
|
|
693
|
+
: `Read local artifact context before researching: ${displayWorkflowPath(locatorPath)}\nCompact saved-output reference: {previous}`;
|
|
694
|
+
const analyzerPath = addArtifact(
|
|
695
|
+
`analyzer-${i}`,
|
|
696
|
+
join(artifactRoot, `analyzer-${i}.md`),
|
|
697
|
+
);
|
|
698
|
+
const onlineResearcherPath = addArtifact(
|
|
699
|
+
`online-${i}`,
|
|
700
|
+
join(artifactRoot, `online-${i}.md`),
|
|
701
|
+
);
|
|
702
|
+
return [
|
|
703
|
+
{
|
|
704
|
+
name: `analyzer-${i}`,
|
|
705
|
+
task: taggedPrompt([
|
|
706
|
+
["role", "You are a codebase behavior and architecture analyzer."],
|
|
707
|
+
["assignment", `Partition ${i}/${partitions.length}: ${partition}`],
|
|
708
|
+
["research_question", prompt],
|
|
709
|
+
[
|
|
710
|
+
"context",
|
|
711
|
+
`Read these artifacts before analyzing: ${displayWorkflowPaths(analyzerReads)}\nCompact saved-output reference: {previous}`,
|
|
712
|
+
],
|
|
713
|
+
["codebase_skills", codebaseSkillGuidance("analyzer")],
|
|
714
|
+
[
|
|
715
|
+
"instructions",
|
|
716
|
+
[
|
|
717
|
+
"Analyze behavior, control flow, data flow, lifecycle, error handling, and test coverage for this partition.",
|
|
718
|
+
"Build on the locator output; do not repeat file discovery except where needed as evidence.",
|
|
719
|
+
"Call out edge cases, invariants, and coupling to other partitions.",
|
|
720
|
+
"If evidence is incomplete, explain what remains unknown and how to verify it.",
|
|
721
|
+
].join("\n"),
|
|
722
|
+
],
|
|
723
|
+
[
|
|
724
|
+
"output_format",
|
|
725
|
+
[
|
|
726
|
+
"Markdown with headings:",
|
|
727
|
+
"1. Behavioral model",
|
|
728
|
+
"2. Key flows and invariants",
|
|
729
|
+
"3. Tests / validation",
|
|
730
|
+
"4. Risks, unknowns, and verification steps",
|
|
731
|
+
].join("\n"),
|
|
732
|
+
],
|
|
733
|
+
]),
|
|
734
|
+
previous: locator === undefined ? scout : [scout, locator],
|
|
735
|
+
reads: analyzerReads,
|
|
736
|
+
...fileOnlyOutput(analyzerPath),
|
|
737
|
+
...explorerModelConfig,
|
|
738
|
+
},
|
|
739
|
+
{
|
|
740
|
+
name: `online-researcher-${i}`,
|
|
741
|
+
task: taggedPrompt([
|
|
742
|
+
[
|
|
743
|
+
"role",
|
|
744
|
+
"You are an ecosystem and documentation research specialist.",
|
|
745
|
+
],
|
|
746
|
+
["assignment", `Partition ${i}/${partitions.length}: ${partition}`],
|
|
747
|
+
["research_question", prompt],
|
|
748
|
+
["local_context", onlineResearcherLocalContext],
|
|
749
|
+
["codebase_skills", codebaseSkillGuidance("onlineResearcher")],
|
|
750
|
+
[
|
|
751
|
+
"instructions",
|
|
752
|
+
[
|
|
753
|
+
"Identify external library/framework behavior, standards, or docs that materially affect the local interpretation.",
|
|
754
|
+
"Cite sources, package names, API names, versions, or documentation titles when available.",
|
|
755
|
+
"Explain how each external fact applies to this repository.",
|
|
756
|
+
"If external research is unnecessary or unavailable, say so and focus on local implications.",
|
|
757
|
+
].join("\n"),
|
|
758
|
+
],
|
|
759
|
+
[
|
|
760
|
+
"output_format",
|
|
761
|
+
[
|
|
762
|
+
"Markdown with headings:",
|
|
763
|
+
"1. Relevant external facts",
|
|
764
|
+
"2. Local implications",
|
|
765
|
+
"3. Version/API assumptions",
|
|
766
|
+
"4. Unverified or unnecessary research",
|
|
767
|
+
].join("\n"),
|
|
768
|
+
],
|
|
769
|
+
]),
|
|
770
|
+
previous: locator === undefined ? scout : locator,
|
|
771
|
+
reads: onlineResearcherReads,
|
|
772
|
+
...fileOnlyOutput(onlineResearcherPath),
|
|
773
|
+
...explorerModelConfig,
|
|
774
|
+
},
|
|
775
|
+
];
|
|
776
|
+
},
|
|
777
|
+
);
|
|
778
|
+
|
|
779
|
+
const wave2 = await ctx.parallel(wave2Steps, {
|
|
780
|
+
task: prompt,
|
|
781
|
+
concurrency: maxConcurrency,
|
|
782
|
+
});
|
|
783
|
+
const historyOverview = await readArtifactText(historyAnalyzerPath, "");
|
|
784
|
+
const explorerPaths = await Promise.all(
|
|
785
|
+
partitions.map(async (partition, index) => {
|
|
786
|
+
const i = index + 1;
|
|
787
|
+
const explorerPath = addArtifact(
|
|
788
|
+
`explorer-${i}`,
|
|
789
|
+
join(artifactRoot, `explorer-${i}.md`),
|
|
790
|
+
);
|
|
791
|
+
const explorer = await specialistHandoffFromArtifacts(
|
|
792
|
+
partition,
|
|
793
|
+
index,
|
|
794
|
+
artifactPathsByStage,
|
|
795
|
+
);
|
|
796
|
+
await writeFile(explorerPath, explorer, "utf8");
|
|
797
|
+
return explorerPath;
|
|
798
|
+
}),
|
|
799
|
+
);
|
|
800
|
+
const aggregatorReadPaths = [
|
|
801
|
+
scoutPath,
|
|
802
|
+
partitionPlanPath,
|
|
803
|
+
...(historyOverview === "" ? [] : [historyAnalyzerPath]),
|
|
804
|
+
...explorerPaths,
|
|
805
|
+
];
|
|
806
|
+
|
|
807
|
+
const aggregate = await ctx.task("aggregator", {
|
|
808
|
+
prompt: taggedPrompt([
|
|
809
|
+
["role", "You are the final deep-research aggregator."],
|
|
810
|
+
["objective", `Answer the research question comprehensively: ${prompt}`],
|
|
797
811
|
[
|
|
798
|
-
|
|
799
|
-
|
|
812
|
+
"context_artifacts",
|
|
813
|
+
[
|
|
814
|
+
`Read the scout artifact at ${displayWorkflowPath(scoutPath)}.`,
|
|
815
|
+
`Read the partition plan artifact at ${displayWorkflowPath(partitionPlanPath)}.`,
|
|
816
|
+
historyOverview === ""
|
|
817
|
+
? "No prior research overview artifact is available."
|
|
818
|
+
: `Read the prior research overview artifact at ${displayWorkflowPath(historyAnalyzerPath)}.`,
|
|
819
|
+
].join("\n"),
|
|
820
|
+
],
|
|
821
|
+
[
|
|
822
|
+
"prior_research_overview",
|
|
800
823
|
historyOverview === ""
|
|
801
|
-
? "
|
|
824
|
+
? "(no prior research found)"
|
|
802
825
|
: `Read the prior research overview artifact at ${displayWorkflowPath(historyAnalyzerPath)}.`,
|
|
803
|
-
]
|
|
804
|
-
],
|
|
805
|
-
[
|
|
806
|
-
"prior_research_overview",
|
|
807
|
-
historyOverview === ""
|
|
808
|
-
? "(no prior research found)"
|
|
809
|
-
: `Read the prior research overview artifact at ${displayWorkflowPath(historyAnalyzerPath)}.`,
|
|
810
|
-
],
|
|
811
|
-
[
|
|
812
|
-
"specialist_reports",
|
|
813
|
-
`Read the complete explorer handoff artifact(s) at ${displayWorkflowPaths(explorerPaths)}. They preserve every partition's Locator, Pattern Finder, Analyzer, and Online Researcher output from the original inline specialist handoff while keeping this prompt bounded.`,
|
|
814
|
-
],
|
|
815
|
-
[
|
|
816
|
-
"codebase_skills",
|
|
817
|
-
codebaseSkillGuidance(
|
|
818
|
-
"analyzer",
|
|
819
|
-
"researchAnalyzer",
|
|
820
|
-
"onlineResearcher",
|
|
821
|
-
),
|
|
822
|
-
],
|
|
823
|
-
[
|
|
824
|
-
"instructions",
|
|
826
|
+
],
|
|
825
827
|
[
|
|
826
|
-
"
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
"Resolve contradictions explicitly and preserve important uncertainty.",
|
|
830
|
-
"Avoid inventing facts not supported by the supplied reports; state unknowns instead.",
|
|
831
|
-
"End with actionable next steps for a developer who will use this research.",
|
|
832
|
-
].join("\n"),
|
|
833
|
-
],
|
|
834
|
-
[
|
|
835
|
-
"output_format",
|
|
828
|
+
"specialist_reports",
|
|
829
|
+
`Read the complete explorer handoff artifact(s) at ${displayWorkflowPaths(explorerPaths)}. They preserve every partition's Locator, Pattern Finder, Analyzer, and Online Researcher output from the original inline specialist handoff while keeping this prompt bounded.`,
|
|
830
|
+
],
|
|
836
831
|
[
|
|
837
|
-
"
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
]
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
findings: aggregate.text,
|
|
871
|
-
research_doc_path: displayWorkflowPath(writtenResearchDocPath),
|
|
872
|
-
artifact_dir: displayWorkflowPath(artifactRoot),
|
|
873
|
-
manifest_path: displayWorkflowPath(manifestPath),
|
|
874
|
-
partitions,
|
|
875
|
-
explorer_count: partitions.length,
|
|
876
|
-
specialist_count: wave1.length + wave2.length,
|
|
877
|
-
max_concurrency: maxConcurrency,
|
|
878
|
-
history: historyOverview,
|
|
879
|
-
};
|
|
880
|
-
return result;
|
|
881
|
-
}
|
|
832
|
+
"codebase_skills",
|
|
833
|
+
codebaseSkillGuidance(
|
|
834
|
+
"analyzer",
|
|
835
|
+
"researchAnalyzer",
|
|
836
|
+
"onlineResearcher",
|
|
837
|
+
),
|
|
838
|
+
],
|
|
839
|
+
[
|
|
840
|
+
"instructions",
|
|
841
|
+
[
|
|
842
|
+
"Synthesize; do not merely concatenate specialist reports.",
|
|
843
|
+
"Use the supplied input files as the source of detailed scout, partition, history, and specialist evidence instead of relying on inline transcripts.",
|
|
844
|
+
"Prioritize claims supported by concrete paths, symbols, tests, docs, or cited external references.",
|
|
845
|
+
"Resolve contradictions explicitly and preserve important uncertainty.",
|
|
846
|
+
"Avoid inventing facts not supported by the supplied reports; state unknowns instead.",
|
|
847
|
+
"End with actionable next steps for a developer who will use this research.",
|
|
848
|
+
].join("\n"),
|
|
849
|
+
],
|
|
850
|
+
[
|
|
851
|
+
"output_format",
|
|
852
|
+
[
|
|
853
|
+
"Markdown with headings:",
|
|
854
|
+
"1. Executive answer",
|
|
855
|
+
"2. Architecture / behavior findings",
|
|
856
|
+
"3. Evidence by partition",
|
|
857
|
+
"4. Risks and unknowns",
|
|
858
|
+
"5. Recommended next steps",
|
|
859
|
+
].join("\n"),
|
|
860
|
+
],
|
|
861
|
+
]),
|
|
862
|
+
reads: aggregatorReadPaths,
|
|
863
|
+
...explorerModelConfig,
|
|
864
|
+
});
|
|
882
865
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
866
|
+
const writtenResearchDocPath = await writeResearchDoc(
|
|
867
|
+
finalResearchDocPath,
|
|
868
|
+
aggregate.text,
|
|
869
|
+
);
|
|
870
|
+
const manifestPath = join(artifactRoot, "manifest.json");
|
|
871
|
+
const completedAt = new Date();
|
|
872
|
+
await writeManifest(manifestPath, {
|
|
873
|
+
runId,
|
|
874
|
+
startedAt: startedAt.toISOString(),
|
|
875
|
+
completedAt: completedAt.toISOString(),
|
|
876
|
+
researchQuestion: prompt,
|
|
877
|
+
finalAsset: displayWorkflowPath(writtenResearchDocPath),
|
|
878
|
+
artifacts: manifestArtifactPaths(
|
|
879
|
+
artifactPathsByStage,
|
|
880
|
+
manifestPath,
|
|
881
|
+
displayWorkflowPath,
|
|
882
|
+
),
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
const result: DeepResearchCodebaseResult = {
|
|
886
|
+
result: aggregate.text,
|
|
887
|
+
findings: aggregate.text,
|
|
888
|
+
research_doc_path: displayWorkflowPath(writtenResearchDocPath),
|
|
889
|
+
artifact_dir: displayWorkflowPath(artifactRoot),
|
|
890
|
+
manifest_path: displayWorkflowPath(manifestPath),
|
|
891
|
+
partitions: [...partitions],
|
|
892
|
+
explorer_count: partitions.length,
|
|
893
|
+
specialist_count: wave1.length + wave2.length,
|
|
894
|
+
max_concurrency: maxConcurrency,
|
|
895
|
+
history: historyOverview,
|
|
896
|
+
};
|
|
897
|
+
return result;
|
|
903
898
|
})
|
|
904
|
-
.run(async (ctx) => runDeepResearchCodebaseWorkflow(ctx, ctx.cwd))
|
|
905
899
|
.compile();
|