pi-cohort 7.3.1 → 7.4.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 +8 -0
- package/README.md +2 -2
- package/package.json +1 -1
- package/src/runs/background/async-execution.ts +12 -6
- package/src/runs/background/subagent-runner.ts +53 -31
- package/src/runs/foreground/chain-execution.ts +515 -498
- package/src/runs/foreground/execution.ts +1 -1
- package/src/runs/shared/acceptance.ts +4 -2
- package/src/runs/shared/chain-outputs.ts +73 -12
- package/src/runs/shared/parallel-utils.ts +1 -0
- package/src/runs/shared/worktree.ts +32 -0
- package/src/shared/types.ts +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [7.4.0] - 2026-10-19
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Chains can use `{outputs.name.treePath}` in a later child's `cwd` to review a worktree task's base commit plus captured patch in a lazy detached checkout. Trees are shared per named output and cleaned up at chain end; only `treePath` output references are allowed in `cwd`, and not on `worktree: true` steps.
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
- Children with both acceptance and `outputSchema` are instructed to write their acceptance report before calling `structured_output`, so both contracts can be satisfied.
|
|
10
|
+
|
|
3
11
|
## [7.3.1] - 2026-10-18
|
|
4
12
|
|
|
5
13
|
### Fixed
|
package/README.md
CHANGED
|
@@ -126,8 +126,8 @@ subagent({ async: false, chain: [
|
|
|
126
126
|
{ agent: "implementer", as: "impl_2", task: "Implement task 2", outputSchema: statusSchema },
|
|
127
127
|
], worktree: true, stopOn: { path: "/status", in: ["NEEDS_CONTEXT", "BLOCKED"] } },
|
|
128
128
|
{ parallel: [
|
|
129
|
-
{ agent: "spec-reviewer", as: "sr_1", task: "Review {outputs.impl_1.patchPath}", outputSchema: verdictSchema },
|
|
130
|
-
{ agent: "spec-reviewer", as: "sr_2", task: "Review {outputs.impl_2.patchPath}", outputSchema: verdictSchema },
|
|
129
|
+
{ agent: "spec-reviewer", as: "sr_1", cwd: "{outputs.impl_1.treePath}", acceptance: { level: "attested" }, task: "Review {outputs.impl_1.patchPath}", outputSchema: verdictSchema },
|
|
130
|
+
{ agent: "spec-reviewer", as: "sr_2", cwd: "{outputs.impl_2.treePath}", acceptance: { level: "attested" }, task: "Review {outputs.impl_2.patchPath}", outputSchema: verdictSchema },
|
|
131
131
|
], stopOn: { path: "/verdict", in: ["FAIL"] } },
|
|
132
132
|
]})
|
|
133
133
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-cohort",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.4.0",
|
|
4
4
|
"description": "Delegate Pi work to focused child agents: code review, scouting, implementation, parallel audits, saved chains, and background jobs.",
|
|
5
5
|
"author": "Jacek Juraszek",
|
|
6
6
|
"license": "MIT",
|
|
@@ -446,13 +446,16 @@ export function executeAsyncChain(
|
|
|
446
446
|
...(s.model ? { model: s.model } : {}),
|
|
447
447
|
};
|
|
448
448
|
};
|
|
449
|
-
const buildSeqStep = (s: SequentialStep, sessionFile?: string, behaviorCwd?: string, progressPrecreated = false, resolvedBehavior?: ResolvedStepBehavior, isolatedLeaf?: { runDir: string; index: number }) => {
|
|
449
|
+
const buildSeqStep = (s: SequentialStep, sessionFile?: string, behaviorCwd?: string, progressPrecreated = false, resolvedBehavior?: ResolvedStepBehavior, isolatedLeaf?: { runDir: string; index: number }, groupCwd?: string) => {
|
|
450
450
|
const a = agents.find((x) => x.name === s.agent)!;
|
|
451
|
-
const
|
|
452
|
-
const
|
|
451
|
+
const effectiveCwd = s.cwd ?? groupCwd;
|
|
452
|
+
const templatedCwd = effectiveCwd?.includes("{outputs.");
|
|
453
|
+
const stepCwd = templatedCwd ? effectiveCwd : resolveChildCwd(runnerCwd, effectiveCwd);
|
|
454
|
+
const preparationCwd = templatedCwd ? runnerCwd : stepCwd;
|
|
455
|
+
const instructionCwd = behaviorCwd ?? preparationCwd;
|
|
453
456
|
const behavior = suppressProgressForReadOnlyTask(resolvedBehavior ?? resolveStepBehavior(a, buildStepOverrides(s), chainSkills), s.task, originalTask);
|
|
454
457
|
const skillNames = behavior.skills === false ? [] : behavior.skills;
|
|
455
|
-
const { resolved: resolvedSkills, missing: missingSkills } = resolveSkillsWithFallback(skillNames,
|
|
458
|
+
const { resolved: resolvedSkills, missing: missingSkills } = resolveSkillsWithFallback(skillNames, preparationCwd, ctx.cwd);
|
|
456
459
|
if (missingSkills.includes("pi-cohort")) throw new UnavailableSubagentSkillError(UNAVAILABLE_SUBAGENT_SKILL_ERROR);
|
|
457
460
|
|
|
458
461
|
let systemPrompt = a.systemPrompt?.trim() ?? "";
|
|
@@ -536,13 +539,14 @@ export function executeAsyncChain(
|
|
|
536
539
|
try {
|
|
537
540
|
steps = chain.map((s, stepIndex) => {
|
|
538
541
|
if (isParallelStep(s)) {
|
|
542
|
+
const groupCwd = s.cwd?.includes("{outputs.") ? runnerCwd : resolveChildCwd(runnerCwd, s.cwd);
|
|
539
543
|
const parallelBehaviors = s.parallel.map((task) => {
|
|
540
544
|
const agent = agents.find((candidate) => candidate.name === task.agent)!;
|
|
541
545
|
return suppressProgressForReadOnlyTask(resolveStepBehavior(agent, buildStepOverrides(task), chainSkills), task.task, originalTask);
|
|
542
546
|
});
|
|
543
547
|
const progressPrecreated = parallelBehaviors.some((behavior) => behavior.progress);
|
|
544
548
|
if (progressPrecreated) {
|
|
545
|
-
if (!s.worktree) writeInitialProgressFile(
|
|
549
|
+
if (!s.worktree) writeInitialProgressFile(groupCwd);
|
|
546
550
|
progressInstructionCreated = true;
|
|
547
551
|
}
|
|
548
552
|
return {
|
|
@@ -550,7 +554,7 @@ export function executeAsyncChain(
|
|
|
550
554
|
let behaviorCwd: string | undefined;
|
|
551
555
|
if (s.worktree) {
|
|
552
556
|
try {
|
|
553
|
-
behaviorCwd = resolveExpectedWorktreeAgentCwd(
|
|
557
|
+
behaviorCwd = resolveExpectedWorktreeAgentCwd(groupCwd, `${id}-s${stepIndex}`, taskIndex);
|
|
554
558
|
} catch {
|
|
555
559
|
behaviorCwd = undefined;
|
|
556
560
|
}
|
|
@@ -562,8 +566,10 @@ export function executeAsyncChain(
|
|
|
562
566
|
progressPrecreated,
|
|
563
567
|
parallelBehaviors[taskIndex],
|
|
564
568
|
s.worktree ? { runDir: path.join(asyncDir, `step-${stepIndex}`), index: taskIndex } : undefined,
|
|
569
|
+
s.cwd,
|
|
565
570
|
);
|
|
566
571
|
}),
|
|
572
|
+
cwd: s.cwd,
|
|
567
573
|
concurrency: s.concurrency,
|
|
568
574
|
failFast: s.failFast,
|
|
569
575
|
worktree: s.worktree,
|
|
@@ -46,14 +46,14 @@ import {
|
|
|
46
46
|
MAX_PARALLEL_CONCURRENCY,
|
|
47
47
|
} from "../shared/parallel-utils.ts";
|
|
48
48
|
import { buildPiArgs, cleanupTempDir, runDirEnv } from "../shared/pi-args.ts";
|
|
49
|
-
import { ChainOutputValidationError, outputEntryFromAsyncResult, resolveOutputReferences } from "../shared/chain-outputs.ts";
|
|
49
|
+
import { ChainOutputValidationError, TreeRegistry, outputEntryFromAsyncResult, resolveOutputReferences } from "../shared/chain-outputs.ts";
|
|
50
50
|
import { buildStopRecord, evaluateStopCondition } from "../shared/stop-conditions.ts";
|
|
51
51
|
import { createStructuredOutputRuntime, readStructuredOutput } from "../shared/structured-output.ts";
|
|
52
52
|
import { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection } from "../shared/dynamic-fanout.ts";
|
|
53
53
|
import { nestedSummaryFromAsyncStatus, writeNestedEvent } from "../shared/nested-events.ts";
|
|
54
54
|
import { formatModelAttemptNote, isRetryableModelFailure } from "../shared/model-fallback.ts";
|
|
55
55
|
import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.ts";
|
|
56
|
-
import { detectSubagentError, extractTextFromContent, extractToolArgsPreview, getFinalOutput } from "../../shared/utils.ts";
|
|
56
|
+
import { detectSubagentError, extractTextFromContent, extractToolArgsPreview, getFinalOutput, resolveChildCwd } from "../../shared/utils.ts";
|
|
57
57
|
import { blockedLine, evaluateCompletionMutationGuard } from "../shared/completion-guard.ts";
|
|
58
58
|
import {
|
|
59
59
|
createMutatingFailureState,
|
|
@@ -70,6 +70,7 @@ import { parseSessionTokens } from "../../shared/session-tokens.ts";
|
|
|
70
70
|
import type { TokenUsage } from "../../shared/types.ts";
|
|
71
71
|
import {
|
|
72
72
|
cleanupWorktrees,
|
|
73
|
+
removeTrees,
|
|
73
74
|
createWorktrees,
|
|
74
75
|
diffWorktrees,
|
|
75
76
|
findWorktreeTaskCwdConflict,
|
|
@@ -570,6 +571,7 @@ function writeRunLog(
|
|
|
570
571
|
export interface SingleStepContext {
|
|
571
572
|
previousOutput: string;
|
|
572
573
|
outputs?: ChainOutputMap;
|
|
574
|
+
trees?: TreeRegistry;
|
|
573
575
|
placeholder: string;
|
|
574
576
|
cwd: string;
|
|
575
577
|
sessionEnabled: boolean;
|
|
@@ -612,10 +614,20 @@ export async function runSingleStep(
|
|
|
612
614
|
acceptance?: import("../../shared/types.ts").AcceptanceLedger;
|
|
613
615
|
executionSurface?: ExecutionSurfaceResult;
|
|
614
616
|
}> {
|
|
617
|
+
let childCwd: string;
|
|
618
|
+
const placeholderRegex = new RegExp(ctx.placeholder.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g");
|
|
619
|
+
let task = step.task.replace(placeholderRegex, () => ctx.previousOutput);
|
|
620
|
+
try {
|
|
621
|
+
childCwd = resolveChildCwd(ctx.cwd, resolveOutputReferences(step.cwd ?? ctx.cwd, ctx.outputs ?? {}, ctx.trees));
|
|
622
|
+
task = resolveOutputReferences(task, ctx.outputs ?? {}, ctx.trees);
|
|
623
|
+
} catch (error) {
|
|
624
|
+
if (!(error instanceof ChainOutputValidationError)) throw error;
|
|
625
|
+
return { agent: step.agent, output: error.message, exitCode: 1, error: error.message, sessionFile: step.sessionFile };
|
|
626
|
+
}
|
|
615
627
|
let backendSelection: import("../../execution-backend/selection.ts").ExecutionBackendSelectionResult;
|
|
616
628
|
try {
|
|
617
629
|
backendSelection = await selectConfiguredExecutionBackend({
|
|
618
|
-
cwd:
|
|
630
|
+
cwd: childCwd,
|
|
619
631
|
userConfig: { executionBackend: ctx.executionBackendConfig?.userPreference },
|
|
620
632
|
preparation: ctx.executionBackendCoordinator,
|
|
621
633
|
});
|
|
@@ -635,17 +647,9 @@ export async function runSingleStep(
|
|
|
635
647
|
const effectiveStructuredOutput = step.structuredOutput ?? (step.structuredOutputSchema
|
|
636
648
|
? createStructuredOutputRuntime(step.structuredOutputSchema, path.join(path.dirname(ctx.outputFile), "structured-output"))
|
|
637
649
|
: undefined);
|
|
638
|
-
const placeholderRegex = new RegExp(ctx.placeholder.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g");
|
|
639
|
-
let task = step.task.replace(placeholderRegex, () => ctx.previousOutput);
|
|
640
|
-
try {
|
|
641
|
-
task = resolveOutputReferences(task, ctx.outputs ?? {});
|
|
642
|
-
} catch (error) {
|
|
643
|
-
if (!(error instanceof ChainOutputValidationError)) throw error;
|
|
644
|
-
return { agent: step.agent, output: error.message, exitCode: 1, error: error.message, sessionFile: step.sessionFile };
|
|
645
|
-
}
|
|
646
650
|
const taskForCompletionGuard = task;
|
|
647
651
|
if (step.effectiveAcceptance) {
|
|
648
|
-
const acceptancePrompt = formatAcceptancePrompt(step.effectiveAcceptance);
|
|
652
|
+
const acceptancePrompt = formatAcceptancePrompt(step.effectiveAcceptance, { structuredOutput: Boolean(effectiveStructuredOutput) });
|
|
649
653
|
if (acceptancePrompt) task = `${task}\n${acceptancePrompt}`;
|
|
650
654
|
}
|
|
651
655
|
const sessionEnabled = Boolean(step.sessionFile) || ctx.sessionEnabled;
|
|
@@ -689,7 +693,7 @@ export async function runSingleStep(
|
|
|
689
693
|
runId: ctx.id,
|
|
690
694
|
childId: `${step.agent}-${ctx.flatIndex}`,
|
|
691
695
|
backend: selection.backend,
|
|
692
|
-
cwd:
|
|
696
|
+
cwd: childCwd,
|
|
693
697
|
title: step.agent,
|
|
694
698
|
signal: ownerController.signal,
|
|
695
699
|
});
|
|
@@ -735,7 +739,7 @@ export async function runSingleStep(
|
|
|
735
739
|
extensions: step.extensions,
|
|
736
740
|
systemPrompt: step.systemPrompt,
|
|
737
741
|
systemPromptMode: step.systemPromptMode,
|
|
738
|
-
cwd:
|
|
742
|
+
cwd: childCwd,
|
|
739
743
|
promptFileStem: step.agent,
|
|
740
744
|
runId: ctx.id,
|
|
741
745
|
childAgentName: step.agent,
|
|
@@ -760,7 +764,7 @@ export async function runSingleStep(
|
|
|
760
764
|
attemptId: `${ctx.id}-${ctx.flatIndex}-attempt-${index}`,
|
|
761
765
|
args,
|
|
762
766
|
environment: mergedEnv,
|
|
763
|
-
cwd:
|
|
767
|
+
cwd: childCwd,
|
|
764
768
|
sessionFile: attemptSessionFile,
|
|
765
769
|
interruptSignal: interruptController.signal,
|
|
766
770
|
onChildEvent: ctx.onChildEvent,
|
|
@@ -881,7 +885,7 @@ export async function runSingleStep(
|
|
|
881
885
|
extensions: step.extensions,
|
|
882
886
|
systemPrompt: step.systemPrompt,
|
|
883
887
|
systemPromptMode: step.systemPromptMode,
|
|
884
|
-
cwd:
|
|
888
|
+
cwd: childCwd,
|
|
885
889
|
promptFileStem: step.agent,
|
|
886
890
|
runId: ctx.id,
|
|
887
891
|
childAgentName: step.agent,
|
|
@@ -897,7 +901,7 @@ export async function runSingleStep(
|
|
|
897
901
|
try {
|
|
898
902
|
run = await runPiStreaming(
|
|
899
903
|
args,
|
|
900
|
-
|
|
904
|
+
childCwd,
|
|
901
905
|
ctx.outputFile,
|
|
902
906
|
env,
|
|
903
907
|
ctx.runtime,
|
|
@@ -1014,7 +1018,7 @@ export async function runSingleStep(
|
|
|
1014
1018
|
? await evaluateAcceptance({
|
|
1015
1019
|
acceptance: step.effectiveAcceptance,
|
|
1016
1020
|
output: outputForAcceptance,
|
|
1017
|
-
cwd:
|
|
1021
|
+
cwd: childCwd,
|
|
1018
1022
|
})
|
|
1019
1023
|
: undefined;
|
|
1020
1024
|
const acceptanceFailure = acceptance ? acceptanceFailureMessage(acceptance) : undefined;
|
|
@@ -1204,8 +1208,9 @@ function prepareParallelTaskRun(
|
|
|
1204
1208
|
cwd: string,
|
|
1205
1209
|
worktreeSetup: WorktreeSetup | undefined,
|
|
1206
1210
|
taskIndex: number,
|
|
1211
|
+
groupCwd?: string,
|
|
1207
1212
|
): { taskForRun: SubagentStep; taskCwd: string } {
|
|
1208
|
-
if (!worktreeSetup) return { taskForRun: task, taskCwd: cwd };
|
|
1213
|
+
if (!worktreeSetup) return { taskForRun: { ...task, cwd: task.cwd ?? groupCwd }, taskCwd: cwd };
|
|
1209
1214
|
return {
|
|
1210
1215
|
taskForRun: { ...task, cwd: undefined },
|
|
1211
1216
|
taskCwd: worktreeSetup.worktrees[taskIndex]!.agentCwd,
|
|
@@ -1251,6 +1256,7 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
1251
1256
|
const overallStartTime = Date.now();
|
|
1252
1257
|
const shareEnabled = config.share === true;
|
|
1253
1258
|
const asyncDir = config.asyncDir;
|
|
1259
|
+
const trees = new TreeRegistry(asyncDir);
|
|
1254
1260
|
const executionBackendConfig = config.executionBackends ?? {
|
|
1255
1261
|
protocolVersion: 1 as const,
|
|
1256
1262
|
registrations: [],
|
|
@@ -1669,7 +1675,6 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
1669
1675
|
if (interrupted || statusPayload.state !== "running") return;
|
|
1670
1676
|
interrupted = true;
|
|
1671
1677
|
const now = Date.now();
|
|
1672
|
-
statusPayload.state = "paused";
|
|
1673
1678
|
currentActivityState = undefined;
|
|
1674
1679
|
statusPayload.activityState = undefined;
|
|
1675
1680
|
statusPayload.lastUpdate = now;
|
|
@@ -1683,11 +1688,6 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
1683
1688
|
}
|
|
1684
1689
|
}
|
|
1685
1690
|
writeStatusPayload();
|
|
1686
|
-
appendJsonl(eventsPath, JSON.stringify({
|
|
1687
|
-
type: "subagent.run.paused",
|
|
1688
|
-
ts: now,
|
|
1689
|
-
runId: id,
|
|
1690
|
-
}));
|
|
1691
1691
|
activeChildInterrupt?.();
|
|
1692
1692
|
};
|
|
1693
1693
|
process.on(ASYNC_INTERRUPT_SIGNAL, interruptRunner);
|
|
@@ -1705,6 +1705,7 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
1705
1705
|
|
|
1706
1706
|
let flatIndex = 0;
|
|
1707
1707
|
|
|
1708
|
+
try {
|
|
1708
1709
|
for (let stepIndex = 0; stepIndex < steps.length; stepIndex++) {
|
|
1709
1710
|
if (interrupted) break;
|
|
1710
1711
|
const step = steps[stepIndex];
|
|
@@ -1884,6 +1885,7 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
1884
1885
|
const singleResult = await runSingleStep(task, {
|
|
1885
1886
|
previousOutput, placeholder, cwd, sessionEnabled,
|
|
1886
1887
|
outputs,
|
|
1888
|
+
trees,
|
|
1887
1889
|
sessionDir: config.sessionDir ? path.join(config.sessionDir, `dynamic-${stepIndex}-${taskIdx}`) : undefined,
|
|
1888
1890
|
artifactsDir, artifactConfig, id,
|
|
1889
1891
|
flatIndex: fi, flatStepCount: Math.max(statusPayload.steps.length, 1),
|
|
@@ -2022,13 +2024,14 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
2022
2024
|
|
|
2023
2025
|
if (isParallelGroup(step)) {
|
|
2024
2026
|
const group = step;
|
|
2027
|
+
const groupCwd = group.cwd?.includes("{outputs.") ? group.cwd : resolveChildCwd(cwd, group.cwd);
|
|
2025
2028
|
const concurrency = group.concurrency ?? MAX_PARALLEL_CONCURRENCY;
|
|
2026
2029
|
const failFast = group.failFast ?? false;
|
|
2027
2030
|
const groupStartFlatIndex = flatIndex;
|
|
2028
2031
|
let aborted = false;
|
|
2029
2032
|
let worktreeSetup: WorktreeSetup | undefined;
|
|
2030
2033
|
if (group.worktree) {
|
|
2031
|
-
const worktreeTaskCwdConflict = findWorktreeTaskCwdConflict(group.parallel,
|
|
2034
|
+
const worktreeTaskCwdConflict = findWorktreeTaskCwdConflict(group.parallel, groupCwd);
|
|
2032
2035
|
if (worktreeTaskCwdConflict) {
|
|
2033
2036
|
const failedAt = Date.now();
|
|
2034
2037
|
markParallelGroupSetupFailure({
|
|
@@ -2036,7 +2039,7 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
2036
2039
|
results,
|
|
2037
2040
|
group,
|
|
2038
2041
|
groupStartFlatIndex,
|
|
2039
|
-
setupError: formatWorktreeTaskCwdConflict(worktreeTaskCwdConflict,
|
|
2042
|
+
setupError: formatWorktreeTaskCwdConflict(worktreeTaskCwdConflict, groupCwd),
|
|
2040
2043
|
failedAt,
|
|
2041
2044
|
statusPath,
|
|
2042
2045
|
eventsPath,
|
|
@@ -2048,7 +2051,7 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
2048
2051
|
break;
|
|
2049
2052
|
}
|
|
2050
2053
|
try {
|
|
2051
|
-
worktreeSetup = createWorktrees(
|
|
2054
|
+
worktreeSetup = createWorktrees(groupCwd, `${id}-s${stepIndex}`, group.parallel.length, {
|
|
2052
2055
|
agents: group.parallel.map((task) => task.agent),
|
|
2053
2056
|
setupHook: config.worktreeSetupHook
|
|
2054
2057
|
? { hookPath: config.worktreeSetupHook, timeoutMs: config.worktreeSetupHookTimeoutMs }
|
|
@@ -2076,7 +2079,7 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
2076
2079
|
}
|
|
2077
2080
|
|
|
2078
2081
|
try {
|
|
2079
|
-
if (group.worktree) ensureParallelProgressFile(
|
|
2082
|
+
if (group.worktree) ensureParallelProgressFile(groupCwd, group);
|
|
2080
2083
|
const groupStartTime = Date.now();
|
|
2081
2084
|
markParallelGroupRunning({
|
|
2082
2085
|
statusPayload,
|
|
@@ -2133,11 +2136,12 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
2133
2136
|
const taskSessionDir = config.sessionDir
|
|
2134
2137
|
? path.join(config.sessionDir, `parallel-${fi}`)
|
|
2135
2138
|
: undefined;
|
|
2136
|
-
const { taskForRun, taskCwd } = prepareParallelTaskRun(task, cwd, worktreeSetup, taskIdx);
|
|
2139
|
+
const { taskForRun, taskCwd } = prepareParallelTaskRun(task, cwd, worktreeSetup, taskIdx, group.cwd);
|
|
2137
2140
|
|
|
2138
2141
|
const singleResult = await runSingleStep(taskForRun, {
|
|
2139
2142
|
previousOutput, placeholder, cwd: taskCwd, sessionEnabled,
|
|
2140
2143
|
outputs,
|
|
2144
|
+
trees,
|
|
2141
2145
|
sessionDir: taskSessionDir,
|
|
2142
2146
|
artifactsDir, artifactConfig, id,
|
|
2143
2147
|
flatIndex: fi, flatStepCount: flatSteps.length,
|
|
@@ -2247,7 +2251,12 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
2247
2251
|
agent: parallelResults[t]!.agent,
|
|
2248
2252
|
output: parallelResults[t]!.output,
|
|
2249
2253
|
structuredOutput: parallelResults[t]!.structuredOutput,
|
|
2250
|
-
}, stepIndex,
|
|
2254
|
+
}, stepIndex, worktreeSetup ? {
|
|
2255
|
+
...patchInfoForDiff(diffs[t]),
|
|
2256
|
+
taskIndex: t,
|
|
2257
|
+
baseCommit: worktreeSetup.baseCommit,
|
|
2258
|
+
repoCwd: worktreeSetup.cwd,
|
|
2259
|
+
} : undefined);
|
|
2251
2260
|
}
|
|
2252
2261
|
statusPayload.outputs = outputs;
|
|
2253
2262
|
if (!interrupted && group.stopOn) {
|
|
@@ -2310,6 +2319,7 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
2310
2319
|
const singleResult = await runSingleStep(seqStep, {
|
|
2311
2320
|
previousOutput, placeholder, cwd, sessionEnabled,
|
|
2312
2321
|
outputs,
|
|
2322
|
+
trees,
|
|
2313
2323
|
sessionDir: config.sessionDir ? path.join(config.sessionDir, `parallel-${flatIndex}`) : undefined,
|
|
2314
2324
|
artifactsDir, artifactConfig, id,
|
|
2315
2325
|
flatIndex, flatStepCount: flatSteps.length,
|
|
@@ -2423,6 +2433,18 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
2423
2433
|
}
|
|
2424
2434
|
}
|
|
2425
2435
|
|
|
2436
|
+
} finally {
|
|
2437
|
+
removeTrees(trees.created);
|
|
2438
|
+
}
|
|
2439
|
+
|
|
2440
|
+
if (interrupted) {
|
|
2441
|
+
const pausedAt = Date.now();
|
|
2442
|
+
statusPayload.state = "paused";
|
|
2443
|
+
statusPayload.lastUpdate = pausedAt;
|
|
2444
|
+
writeStatusPayload();
|
|
2445
|
+
appendJsonl(eventsPath, JSON.stringify({ type: "subagent.run.paused", ts: pausedAt, runId: id }));
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2426
2448
|
let summary = results.map((r) => `${r.agent}:\n${r.output}`).join("\n\n");
|
|
2427
2449
|
let truncated = false;
|
|
2428
2450
|
|