@bastani/atomic 0.6.3 → 0.6.4
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/.agents/skills/ast-grep/SKILL.md +323 -0
- package/.agents/skills/ast-grep/references/rule_reference.md +297 -0
- package/.agents/skills/ripgrep/SKILL.md +382 -0
- package/.mcp.json +5 -6
- package/dist/commands/cli/claude-inflight-hook.d.ts +100 -0
- package/dist/commands/cli/claude-inflight-hook.d.ts.map +1 -0
- package/dist/commands/cli/claude-stop-hook.d.ts +2 -0
- package/dist/commands/cli/claude-stop-hook.d.ts.map +1 -1
- package/dist/lib/spawn.d.ts +1 -1
- package/dist/lib/spawn.d.ts.map +1 -1
- package/dist/sdk/providers/claude.d.ts +36 -0
- package/dist/sdk/providers/claude.d.ts.map +1 -1
- package/dist/sdk/providers/copilot.d.ts +17 -1
- package/dist/sdk/providers/copilot.d.ts.map +1 -1
- package/dist/sdk/runtime/executor.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts +49 -34
- package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts +18 -16
- package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/batching.d.ts +43 -0
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/batching.d.ts.map +1 -0
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.d.ts +30 -0
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/scout.d.ts +2 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/scout.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts +18 -16
- package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts.map +1 -1
- package/dist/services/config/additional-instructions.d.ts +67 -0
- package/dist/services/config/additional-instructions.d.ts.map +1 -0
- package/package.json +3 -1
- package/src/cli.ts +18 -1
- package/src/commands/cli/chat/index.ts +52 -2
- package/src/commands/cli/claude-inflight-hook.test.ts +598 -0
- package/src/commands/cli/claude-inflight-hook.ts +359 -0
- package/src/commands/cli/claude-stop-hook.ts +40 -4
- package/src/commands/cli/init/index.ts +9 -0
- package/src/lib/spawn.ts +6 -2
- package/src/sdk/providers/claude.ts +131 -0
- package/src/sdk/providers/copilot.ts +30 -1
- package/src/sdk/runtime/executor.ts +43 -2
- package/src/sdk/workflows/builtin/deep-research-codebase/claude/index.ts +318 -158
- package/src/sdk/workflows/builtin/deep-research-codebase/copilot/index.ts +253 -129
- package/src/sdk/workflows/builtin/deep-research-codebase/helpers/batching.ts +65 -0
- package/src/sdk/workflows/builtin/deep-research-codebase/helpers/ignore-by-default.d.ts +8 -0
- package/src/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.ts +203 -12
- package/src/sdk/workflows/builtin/deep-research-codebase/helpers/scout.ts +248 -78
- package/src/sdk/workflows/builtin/deep-research-codebase/opencode/index.ts +258 -146
- package/src/services/config/additional-instructions.ts +273 -0
- package/src/services/system/auto-sync.ts +10 -1
|
@@ -1,33 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* deep-research-codebase / opencode
|
|
3
3
|
*
|
|
4
|
-
* OpenCode replica of the Claude deep-research-codebase workflow
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* OpenCode replica of the Claude deep-research-codebase workflow with the
|
|
5
|
+
* same **batched** Task-tool fan-out. Specialist sub-agents run inside batch
|
|
6
|
+
* sessions: each batch is a single `ctx.stage()` whose orchestrator turn
|
|
7
|
+
* dispatches up to MAX_TASKS_PER_BATCH (≈10) specialists in parallel via
|
|
8
|
+
* OpenCode's `task` tool. The default agent must have `task: "allow"` in
|
|
9
|
+
* its permission ruleset (see `.opencode/agents/worker.md` for the
|
|
10
|
+
* canonical example).
|
|
11
|
+
*
|
|
12
|
+
* See claude/index.ts for the full design rationale and topology diagram.
|
|
8
13
|
*
|
|
9
14
|
* OpenCode-specific concerns baked in (see references/failure-modes.md):
|
|
10
15
|
*
|
|
11
|
-
* •
|
|
12
|
-
*
|
|
13
|
-
*
|
|
16
|
+
* • F3 — `result.data!.parts` is heterogenous. Batch sessions don't read
|
|
17
|
+
* `extractResponseText` for orchestrator output (sub-agents write to
|
|
18
|
+
* disk; the orchestrator reply is just a short tally), but the history
|
|
19
|
+
* pipeline still uses it.
|
|
14
20
|
*
|
|
15
|
-
* •
|
|
16
|
-
*
|
|
17
|
-
* concatenating raw `parts` produces `[object Object]` strings.
|
|
21
|
+
* • F5 — every `ctx.stage()` is a FRESH session. Batch session prompts
|
|
22
|
+
* embed everything the orchestrator needs in the first turn.
|
|
18
23
|
*
|
|
19
|
-
* • F6 —
|
|
20
|
-
*
|
|
24
|
+
* • F6 — orchestrator prompt requires a single-line tally as the trailing
|
|
25
|
+
* turn so transcripts are never empty.
|
|
21
26
|
*
|
|
22
27
|
* • F9 — `s.save()` receives the unwrapped `{ info, parts }` payload from
|
|
23
|
-
* `result.data
|
|
24
|
-
* breaks downstream `transcript()` reads.
|
|
25
|
-
*
|
|
26
|
-
* See claude/index.ts for the full design rationale and topology diagram.
|
|
28
|
+
* `result.data!`.
|
|
27
29
|
*/
|
|
28
30
|
|
|
29
31
|
import { defineWorkflow } from "../../../index.ts";
|
|
30
|
-
import { mkdir } from "node:fs/promises";
|
|
32
|
+
import { mkdir, readFile } from "node:fs/promises";
|
|
31
33
|
import path from "node:path";
|
|
32
34
|
|
|
33
35
|
import {
|
|
@@ -42,6 +44,7 @@ import {
|
|
|
42
44
|
import {
|
|
43
45
|
buildAggregatorPrompt,
|
|
44
46
|
buildAnalyzerPrompt,
|
|
47
|
+
buildBatchOrchestratorPrompt,
|
|
45
48
|
buildHistoryAnalyzerPrompt,
|
|
46
49
|
buildHistoryLocatorPrompt,
|
|
47
50
|
buildLocatorPrompt,
|
|
@@ -49,8 +52,16 @@ import {
|
|
|
49
52
|
buildPatternFinderPrompt,
|
|
50
53
|
buildScoutPrompt,
|
|
51
54
|
slugifyPrompt,
|
|
55
|
+
wrapPromptForTaskDispatch,
|
|
52
56
|
} from "../helpers/prompts.ts";
|
|
53
57
|
import { writeExplorerScratchFile } from "../helpers/scratch.ts";
|
|
58
|
+
import {
|
|
59
|
+
chunkBatches,
|
|
60
|
+
MAX_TASKS_PER_BATCH,
|
|
61
|
+
SUBAGENT_TYPE,
|
|
62
|
+
type Layer1Task,
|
|
63
|
+
type Layer2Task,
|
|
64
|
+
} from "../helpers/batching.ts";
|
|
54
65
|
|
|
55
66
|
/** Filter for text parts only — non-text parts produce [object Object]. */
|
|
56
67
|
function extractResponseText(
|
|
@@ -62,6 +73,31 @@ function extractResponseText(
|
|
|
62
73
|
.join("\n");
|
|
63
74
|
}
|
|
64
75
|
|
|
76
|
+
/** Read a file as UTF-8, returning empty string if missing or unreadable. */
|
|
77
|
+
async function safeReadFile(absPath: string): Promise<string> {
|
|
78
|
+
try {
|
|
79
|
+
return await readFile(absPath, "utf8");
|
|
80
|
+
} catch {
|
|
81
|
+
return "";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Log Promise.allSettled rejection reasons to stderr so an all-failed wave
|
|
87
|
+
* leaves a debugging trail instead of silently producing an empty report.
|
|
88
|
+
*/
|
|
89
|
+
function logBatchRejections(
|
|
90
|
+
label: string,
|
|
91
|
+
results: PromiseSettledResult<unknown>[],
|
|
92
|
+
): void {
|
|
93
|
+
for (let i = 0; i < results.length; i++) {
|
|
94
|
+
const r = results[i];
|
|
95
|
+
if (r?.status === "rejected") {
|
|
96
|
+
console.error(`[deep-research-codebase] ${label} batch ${i + 1} failed:`, r.reason);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
65
101
|
export default defineWorkflow({
|
|
66
102
|
name: "deep-research-codebase",
|
|
67
103
|
description:
|
|
@@ -98,7 +134,9 @@ export default defineWorkflow({
|
|
|
98
134
|
if (data.units.length === 0) {
|
|
99
135
|
throw new Error(
|
|
100
136
|
`deep-research-codebase: scout found no source files under ${root}. ` +
|
|
101
|
-
`Run from inside a code repository or
|
|
137
|
+
`Run from inside a code repository, or verify your files use a ` +
|
|
138
|
+
`recognized programming-language extension (sourced from GitHub ` +
|
|
139
|
+
`Linguist + sql/graphql/proto).`,
|
|
102
140
|
);
|
|
103
141
|
}
|
|
104
142
|
|
|
@@ -209,151 +247,225 @@ export default defineWorkflow({
|
|
|
209
247
|
|
|
210
248
|
const scoutOverview = (await ctx.transcript(scout)).content;
|
|
211
249
|
|
|
212
|
-
// ── Stage 2:
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
250
|
+
// ── Stage 2: batched specialist fan-out ───────────────────────────────
|
|
251
|
+
//
|
|
252
|
+
// Same two-wave batched design as claude/index.ts. Each batch session
|
|
253
|
+
// pins the dispatcher to the `orchestrator` agent (.opencode/agents/
|
|
254
|
+
// orchestrator.md) — its system prompt is purpose-built to delegate
|
|
255
|
+
// everything via the `task` tool, so the dispatcher cannot wander off
|
|
256
|
+
// and start doing the specialists' work itself.
|
|
217
257
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
258
|
+
// Per-partition output paths, computed once and reused across both wave
|
|
259
|
+
// task-list construction and synthesis.
|
|
260
|
+
const partitionPaths = partitions.map((_, idx) => {
|
|
261
|
+
const i = idx + 1;
|
|
262
|
+
return {
|
|
263
|
+
locator: path.join(scratchDir, `locator-${i}.md`),
|
|
264
|
+
patternFinder: path.join(scratchDir, `pattern-finder-${i}.md`),
|
|
265
|
+
analyzer: path.join(scratchDir, `analyzer-${i}.md`),
|
|
266
|
+
online: path.join(scratchDir, `online-${i}.md`),
|
|
267
|
+
explorer: path.join(scratchDir, `explorer-${i}.md`),
|
|
268
|
+
};
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
const wave1Tasks: Layer1Task[] = partitions.flatMap((partition, idx) => {
|
|
272
|
+
const i = idx + 1;
|
|
273
|
+
const paths = partitionPaths[idx]!;
|
|
274
|
+
return [
|
|
275
|
+
{
|
|
276
|
+
kind: "locator" as const,
|
|
277
|
+
partitionIndex: i,
|
|
278
|
+
partition,
|
|
279
|
+
outputPath: paths.locator,
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
kind: "pattern-finder" as const,
|
|
283
|
+
partitionIndex: i,
|
|
284
|
+
partition,
|
|
285
|
+
outputPath: paths.patternFinder,
|
|
286
|
+
},
|
|
287
|
+
];
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const wave1Batches = chunkBatches(wave1Tasks, MAX_TASKS_PER_BATCH);
|
|
291
|
+
|
|
292
|
+
const wave1Results = await Promise.allSettled(
|
|
293
|
+
wave1Batches.map((batch, batchIdx) => {
|
|
294
|
+
const batchNumber = batchIdx + 1;
|
|
295
|
+
return ctx.stage(
|
|
296
|
+
{
|
|
297
|
+
name: `wave1-batch-${batchNumber}`,
|
|
298
|
+
headless: true,
|
|
299
|
+
description: `Layer 1 dispatch (${batch.length} tasks)`,
|
|
300
|
+
},
|
|
301
|
+
{},
|
|
302
|
+
{ title: `wave1-batch-${batchNumber}` },
|
|
303
|
+
async (s) => {
|
|
304
|
+
const taskSpecs = batch.map((t) => {
|
|
305
|
+
const builder =
|
|
306
|
+
t.kind === "locator" ? buildLocatorPrompt : buildPatternFinderPrompt;
|
|
307
|
+
const specialistPrompt = builder({
|
|
308
|
+
question: prompt,
|
|
309
|
+
partition: t.partition,
|
|
310
|
+
scoutOverview,
|
|
311
|
+
index: t.partitionIndex,
|
|
312
|
+
total: explorerCount,
|
|
273
313
|
});
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
314
|
+
return {
|
|
315
|
+
subagentType: SUBAGENT_TYPE[t.kind],
|
|
316
|
+
outputPath: t.outputPath,
|
|
317
|
+
prompt: wrapPromptForTaskDispatch({
|
|
318
|
+
specialistPrompt,
|
|
319
|
+
outputPath: t.outputPath,
|
|
320
|
+
agentLabel: t.kind.toUpperCase().replaceAll("-", "_"),
|
|
321
|
+
}),
|
|
322
|
+
};
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
const result = await s.client.session.prompt({
|
|
326
|
+
sessionID: s.session.id,
|
|
327
|
+
parts: [
|
|
328
|
+
{
|
|
329
|
+
type: "text",
|
|
330
|
+
text: buildBatchOrchestratorPrompt({
|
|
331
|
+
wave: 1,
|
|
332
|
+
batchIndex: batchNumber,
|
|
333
|
+
totalBatches: wave1Batches.length,
|
|
334
|
+
tasks: taskSpecs,
|
|
335
|
+
}),
|
|
336
|
+
},
|
|
337
|
+
],
|
|
338
|
+
agent: "orchestrator",
|
|
339
|
+
});
|
|
340
|
+
s.save(result.data!);
|
|
341
|
+
},
|
|
342
|
+
);
|
|
343
|
+
}),
|
|
344
|
+
);
|
|
345
|
+
logBatchRejections("wave1", wave1Results);
|
|
279
346
|
|
|
280
|
-
|
|
281
|
-
|
|
347
|
+
const locatorOutputs: Map<number, string> = new Map();
|
|
348
|
+
await Promise.all(
|
|
349
|
+
partitions.map(async (_p, idx) => {
|
|
350
|
+
const i = idx + 1;
|
|
351
|
+
locatorOutputs.set(i, await safeReadFile(partitionPaths[idx]!.locator));
|
|
352
|
+
}),
|
|
353
|
+
);
|
|
282
354
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
355
|
+
const wave2Tasks: Layer2Task[] = partitions.flatMap((partition, idx) => {
|
|
356
|
+
const i = idx + 1;
|
|
357
|
+
const paths = partitionPaths[idx]!;
|
|
358
|
+
const locatorOutput = locatorOutputs.get(i) ?? "";
|
|
359
|
+
return [
|
|
360
|
+
{
|
|
361
|
+
kind: "analyzer" as const,
|
|
362
|
+
partitionIndex: i,
|
|
363
|
+
partition,
|
|
364
|
+
outputPath: paths.analyzer,
|
|
365
|
+
locatorOutput,
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
kind: "online-researcher" as const,
|
|
369
|
+
partitionIndex: i,
|
|
370
|
+
partition,
|
|
371
|
+
outputPath: paths.online,
|
|
372
|
+
locatorOutput,
|
|
373
|
+
},
|
|
374
|
+
];
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
const wave2Batches = chunkBatches(wave2Tasks, MAX_TASKS_PER_BATCH);
|
|
378
|
+
|
|
379
|
+
const wave2Results = await Promise.allSettled(
|
|
380
|
+
wave2Batches.map((batch, batchIdx) => {
|
|
381
|
+
const batchNumber = batchIdx + 1;
|
|
382
|
+
return ctx.stage(
|
|
383
|
+
{
|
|
384
|
+
name: `wave2-batch-${batchNumber}`,
|
|
385
|
+
headless: true,
|
|
386
|
+
description: `Layer 2 dispatch (${batch.length} tasks)`,
|
|
387
|
+
},
|
|
388
|
+
{},
|
|
389
|
+
{ title: `wave2-batch-${batchNumber}` },
|
|
390
|
+
async (s) => {
|
|
391
|
+
const taskSpecs = batch.map((t) => {
|
|
392
|
+
const specialistPrompt =
|
|
393
|
+
t.kind === "analyzer"
|
|
394
|
+
? buildAnalyzerPrompt({
|
|
300
395
|
question: prompt,
|
|
301
|
-
partition,
|
|
302
|
-
locatorOutput,
|
|
396
|
+
partition: t.partition,
|
|
397
|
+
locatorOutput: t.locatorOutput,
|
|
303
398
|
scoutOverview,
|
|
304
|
-
index:
|
|
399
|
+
index: t.partitionIndex,
|
|
305
400
|
total: explorerCount,
|
|
306
|
-
})
|
|
307
|
-
|
|
308
|
-
],
|
|
309
|
-
agent: "codebase-analyzer",
|
|
310
|
-
});
|
|
311
|
-
s.save(result.data!);
|
|
312
|
-
return extractResponseText(result.data!.parts);
|
|
313
|
-
},
|
|
314
|
-
),
|
|
315
|
-
ctx.stage(
|
|
316
|
-
{
|
|
317
|
-
name: `online-researcher-${i}`,
|
|
318
|
-
headless: true,
|
|
319
|
-
description: `codebase-online-researcher over partition ${i}`,
|
|
320
|
-
},
|
|
321
|
-
{},
|
|
322
|
-
{ title: `online-researcher-${i}` },
|
|
323
|
-
async (s) => {
|
|
324
|
-
const result = await s.client.session.prompt({
|
|
325
|
-
sessionID: s.session.id,
|
|
326
|
-
parts: [
|
|
327
|
-
{
|
|
328
|
-
type: "text",
|
|
329
|
-
text: buildOnlineResearcherPrompt({
|
|
401
|
+
})
|
|
402
|
+
: buildOnlineResearcherPrompt({
|
|
330
403
|
question: prompt,
|
|
331
|
-
partition,
|
|
332
|
-
locatorOutput,
|
|
333
|
-
index:
|
|
404
|
+
partition: t.partition,
|
|
405
|
+
locatorOutput: t.locatorOutput,
|
|
406
|
+
index: t.partitionIndex,
|
|
334
407
|
total: explorerCount,
|
|
335
|
-
})
|
|
336
|
-
|
|
337
|
-
],
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
408
|
+
});
|
|
409
|
+
return {
|
|
410
|
+
subagentType: SUBAGENT_TYPE[t.kind],
|
|
411
|
+
outputPath: t.outputPath,
|
|
412
|
+
prompt: wrapPromptForTaskDispatch({
|
|
413
|
+
specialistPrompt,
|
|
414
|
+
outputPath: t.outputPath,
|
|
415
|
+
agentLabel: t.kind.toUpperCase().replaceAll("-", "_"),
|
|
416
|
+
}),
|
|
417
|
+
};
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
const result = await s.client.session.prompt({
|
|
421
|
+
sessionID: s.session.id,
|
|
422
|
+
parts: [
|
|
423
|
+
{
|
|
424
|
+
type: "text",
|
|
425
|
+
text: buildBatchOrchestratorPrompt({
|
|
426
|
+
wave: 2,
|
|
427
|
+
batchIndex: batchNumber,
|
|
428
|
+
totalBatches: wave2Batches.length,
|
|
429
|
+
tasks: taskSpecs,
|
|
430
|
+
}),
|
|
431
|
+
},
|
|
432
|
+
],
|
|
433
|
+
agent: "orchestrator",
|
|
434
|
+
});
|
|
435
|
+
s.save(result.data!);
|
|
436
|
+
},
|
|
437
|
+
);
|
|
438
|
+
}),
|
|
439
|
+
);
|
|
440
|
+
logBatchRejections("wave2", wave2Results);
|
|
441
|
+
|
|
442
|
+
// Synthesis: read all four specialist files per partition and write the
|
|
443
|
+
// consolidated explorer scratch file. Missing files fall back to "" so
|
|
444
|
+
// partial batch failures degrade gracefully.
|
|
445
|
+
const explorerHandles = await Promise.all(
|
|
446
|
+
partitions.map(async (partition, idx) => {
|
|
447
|
+
const i = idx + 1;
|
|
448
|
+
const paths = partitionPaths[idx]!;
|
|
449
|
+
|
|
450
|
+
const [locatorOutput, patternsOutput, analyzerOutput, onlineOutput] =
|
|
451
|
+
await Promise.all([
|
|
452
|
+
Promise.resolve(locatorOutputs.get(i) ?? ""),
|
|
453
|
+
safeReadFile(paths.patternFinder),
|
|
454
|
+
safeReadFile(paths.analyzer),
|
|
455
|
+
safeReadFile(paths.online),
|
|
456
|
+
]);
|
|
345
457
|
|
|
346
|
-
await writeExplorerScratchFile(
|
|
458
|
+
await writeExplorerScratchFile(paths.explorer, {
|
|
347
459
|
index: i,
|
|
348
460
|
total: explorerCount,
|
|
349
461
|
partition,
|
|
350
462
|
locatorOutput,
|
|
351
463
|
patternsOutput,
|
|
352
|
-
analyzerOutput
|
|
353
|
-
onlineOutput
|
|
464
|
+
analyzerOutput,
|
|
465
|
+
onlineOutput,
|
|
354
466
|
});
|
|
355
467
|
|
|
356
|
-
return { index: i, scratchPath, partition };
|
|
468
|
+
return { index: i, scratchPath: paths.explorer, partition };
|
|
357
469
|
}),
|
|
358
470
|
);
|
|
359
471
|
|