{"version":3,"file":"chain-execution.d.ts","sourceRoot":"","sources":["../../../../src/runs/foreground/chain-execution.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAK1D,OAAO,EAGN,KAAK,SAAS,EAkBd,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACN,KAAK,aAAa,EAElB,KAAK,cAAc,EAGnB,KAAK,YAAY,EACjB,KAAK,OAAO,EACZ,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EAErB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EAEvB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,MAAM,uBAAuB,CAAC;AAgB/B,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,iCAAiC,CAAC;AAOzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAS7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AASjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAyejE,UAAU,oBAAoB;IAC7B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,GAAG,EAAE,gBAAgB,CAAC;IACtB,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;IACtB,kBAAkB,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACzD,mBAAmB,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC3D,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACrG,uBAAuB,CAAC,EAAE,CACzB,SAAS,EAAE,MAAM,EACjB,GAAG,CAAC,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,MAAM,KAClB,WAAW,CAAC,UAAU,CAAC,GAAG,SAAS,CAAC;IACzC,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,WAAW,CAAC;IACrD,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,cAAc,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IACjD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/C,aAAa,EAAE,qBAAqB,CAAC;IACrC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC3E,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,iBAAiB,CAAC,EAAE,oBAAoB,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/D,qFAAqF;IACrF,wBAAwB,CAAC,EAAE,MAAM,IAAI,CAAC;IACtC,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,kHAAkH;IAClH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iBAAiB,CAAC,EAAE,iCAAiC,CAAC;CACtD;AAED,UAAU,oBAAoB;IAC7B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2FAA2F;IAC3F,cAAc,CAAC,EAAE;QAChB,KAAK,EAAE,SAAS,EAAE,CAAC;QACnB,WAAW,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC;CACF;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA2rC9F","sourcesContent":["/**\n * Chain execution logic for subagent tool\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { AgentToolResult } from \"@lpb-work/pi-agent-core\";\nimport type { ExtensionContext } from \"@lpb-work/pi-coding-agent\";\nimport type { AgentConfig } from \"../../agents/agents.ts\";\nimport { discoverAvailableSkills, normalizeSkillInput } from \"../../agents/skills.ts\";\nimport { INTERCOM_BRIDGE_MARKER } from \"../../intercom/intercom-bridge.ts\";\nimport { buildChainSummary } from \"../../shared/formatters.ts\";\nimport { type ModelInfo, resolveEffectiveThinking, toModelInfo } from \"../../shared/model-info.ts\";\nimport {\n\taggregateParallelOutputs,\n\tbuildChainInstructions,\n\ttype ChainStep,\n\tcreateChainDir,\n\tcreateParallelDirs,\n\tisCheckpointStep,\n\tisDynamicParallelStep,\n\tisParallelStep,\n\ttype ParallelStep,\n\ttype ParallelTaskResult,\n\ttype ResolvedStepBehavior,\n\ttype ResolvedTemplates,\n\tremoveChainDir,\n\tresolveChainTemplates,\n\tresolveParallelBehaviors,\n\tresolveStepBehavior,\n\ttype SequentialStep,\n\ttype StepOverrides,\n\tsuppressProgressForReadOnlyTask,\n\twriteInitialProgressFile,\n} from \"../../shared/settings.ts\";\nimport type { ChainOutputMap } from \"../../shared/types.ts\";\nimport {\n\ttype AgentContract,\n\ttype AgentProgress,\n\ttype ArtifactConfig,\n\ttype ArtifactPaths,\n\ttype ChainCheckpointState,\n\ttype ControlEvent,\n\ttype Details,\n\ttype ForegroundRunControl,\n\ttype IntercomEventBus,\n\tMAX_CONCURRENCY,\n\ttype NestedRouteInfo,\n\ttype ResolvedControlConfig,\n\ttype ResolvedToolBudget,\n\ttype ResolvedTurnBudget,\n\tresolveChildMaxSubagentDepth,\n\ttype SingleResult,\n\ttype ToolBudgetConfig,\n\ttype UsageBudgetConfig,\n} from \"../../shared/types.ts\";\nimport {\n\tcompactForegroundDetails,\n\tgetSingleResultOutput,\n\tmapConcurrent,\n\tresolveChildCwd,\n\tsumResultsCost,\n\tsumResultsUsage,\n} from \"../../shared/utils.ts\";\nimport {\n\tacceptanceFailureMessage,\n\taggregateAcceptanceReport,\n\tevaluateAcceptance,\n\tresolveEffectiveAcceptance,\n} from \"../shared/acceptance.ts\";\nimport { isAgentContractV1 } from \"../shared/agent-contract.ts\";\nimport type { ResolvedSubagentCapabilityCeiling } from \"../shared/capability-ceiling.ts\";\nimport {\n\tChainOutputValidationError,\n\toutputEntryFromResult,\n\tresolveOutputReferences,\n\tvalidateChainOutputBindings,\n} from \"../shared/chain-outputs.ts\";\nimport type { ContextMode } from \"../shared/context-mode.ts\";\nimport {\n\tcollectDynamicResults,\n\ttype DynamicCollectedResult,\n\tDynamicFanoutError,\n\tmaterializeDynamicParallelStep,\n\tvalidateDynamicCollection,\n} from \"../shared/dynamic-fanout.ts\";\nimport { resolveEffectiveSubagentModel } from \"../shared/model-fallback.ts\";\nimport type { ModelScopeConfig } from \"../shared/model-scope.ts\";\nimport {\n\tformatParallelHandoffError,\n\tformatParallelHandoffReference,\n\tparallelHandoffPath,\n\twriteParallelHandoffGroup,\n\twritePendingParallelHandoff,\n} from \"../shared/parallel-handoff.ts\";\nimport { DEFAULT_GLOBAL_CONCURRENCY_LIMIT, Semaphore } from \"../shared/parallel-utils.ts\";\nimport type { PermissionConfig } from \"../shared/permissions.ts\";\nimport { recordRun } from \"../shared/run-history.ts\";\nimport { injectSingleOutputInstruction, validateFileOnlyOutputMode } from \"../shared/single-output.ts\";\nimport { createStructuredOutputRuntime } from \"../shared/structured-output.ts\";\nimport { validateToolBudgetConfig } from \"../shared/tool-budget.ts\";\nimport { usageBudgetExceededMessage, usageBudgetState } from \"../shared/usage-budget.ts\";\nimport { buildWorkflowGraphSnapshot } from \"../shared/workflow-graph.ts\";\nimport {\n\tcleanupWorktrees,\n\tcreateWorktrees,\n\tdiffWorktrees,\n\tfindWorktreeTaskCwdConflict,\n\tformatWorktreeDiffSummary,\n\tformatWorktreeTaskCwdConflict,\n\ttype WorktreeSetup,\n} from \"../shared/worktree.ts\";\nimport { type BehaviorOverride, ChainClarifyComponent, type ChainClarifyResult } from \"./chain-clarify.ts\";\nimport { runSync } from \"./execution.ts\";\nimport {\n\tbeginForegroundChild,\n\tfinishForegroundChild,\n\tretainForegroundSchedulingOwner,\n\tsettleForegroundSchedulingOwner,\n\tupdateForegroundChild,\n} from \"./foreground-control.ts\";\n\ninterface ChainExecutionDetailsInput {\n\tresults: SingleResult[];\n\tincludeProgress?: boolean;\n\tallProgress: AgentProgress[];\n\tallArtifactPaths: ArtifactPaths[];\n\tartifactsDir: string;\n\tchainAgents: string[];\n\tchainSteps: ChainStep[];\n\ttotalSteps: number;\n\tcurrentStepIndex?: number;\n\trunId: string;\n\toutputs?: ChainOutputMap;\n\tcurrentFlatIndex?: number;\n\tdynamicChildren?: Record<\n\t\tnumber,\n\t\tArray<{\n\t\t\tagent: string;\n\t\t\tlabel?: string;\n\t\t\tflatIndex: number;\n\t\t\titemKey: string;\n\t\t\toutputName?: string;\n\t\t\tstructured?: boolean;\n\t\t\terror?: string;\n\t\t}>\n\t>;\n\tdynamicGroupStatuses?: Record<\n\t\tnumber,\n\t\t{\n\t\t\tstatus: \"pending\" | \"running\" | \"completed\" | \"failed\" | \"paused\" | \"stopped\" | \"detached\";\n\t\t\terror?: string;\n\t\t\tacceptance?: SingleResult[\"acceptance\"];\n\t\t}\n\t>;\n\tparallelHandoff?: Details[\"parallelHandoff\"];\n\tcheckpoint?: ChainCheckpointState;\n\tusageBudget?: UsageBudgetConfig;\n}\n\ninterface ParallelChainRunInput {\n\tstep: ParallelStep;\n\tparallelTemplates: string[];\n\tparallelBehaviors: ResolvedStepBehavior[];\n\tagents: AgentConfig[];\n\tstepIndex: number;\n\tavailableModels: ModelInfo[];\n\tmodelScope?: ModelScopeConfig;\n\tchainDir: string;\n\tprev: string;\n\toriginalTask: string;\n\tctx: ExtensionContext;\n\tintercomEvents?: IntercomEventBus;\n\tcwd?: string;\n\trunId: string;\n\tglobalTaskIndex: number;\n\tsessionDirForIndex: (idx?: number) => string | undefined;\n\tsessionFileForIndex?: (idx?: number) => string | undefined;\n\tsessionFileForTask?: (agentName: string, idx?: number, modelOverride?: string) => string | undefined;\n\tthinkingOverrideForTask?: (\n\t\tagentName: string,\n\t\tidx?: number,\n\t\tmodelOverride?: string,\n\t) => AgentConfig[\"thinking\"] | undefined;\n\tcontextForAgent?: (agentName: string) => ContextMode;\n\tshareEnabled: boolean;\n\tartifactConfig: ArtifactConfig;\n\tartifactsDir: string;\n\tsignal?: AbortSignal;\n\tonUpdate?: (r: AgentToolResult<Details>) => void;\n\tonControlEvent?: (event: ControlEvent) => void;\n\tcontrolConfig: ResolvedControlConfig;\n\tagentContract?: AgentContract;\n\tchildIntercomTarget?: (agent: string, index: number) => string | undefined;\n\torchestratorIntercomTarget?: string;\n\tforegroundControl?: ForegroundRunControl;\n\tresults: SingleResult[];\n\tallProgress: AgentProgress[];\n\toutputs: ChainOutputMap;\n\tchainAgents: string[];\n\tchainSteps: ChainStep[];\n\ttotalSteps: number;\n\tdynamicChildren?: ChainExecutionDetailsInput[\"dynamicChildren\"];\n\tdynamicGroupStatuses?: ChainExecutionDetailsInput[\"dynamicGroupStatuses\"];\n\tworktreeSetup?: WorktreeSetup;\n\tmaxSubagentDepth: number;\n\tnestedRoute?: NestedRouteInfo;\n\ttimeoutMs?: number;\n\tdeadlineAt?: number;\n\tturnBudget?: ResolvedTurnBudget;\n\tusageBudget?: UsageBudgetConfig;\n\tonDetachedExit?: (index: number, result: SingleResult) => void;\n\t/** Called after an attached child releases its foreground ownership. */\n\tonForegroundChildSettled?: () => void;\n\ttoolBudget?: ResolvedToolBudget;\n\tconfigToolBudget?: ToolBudgetConfig;\n\tglobalSemaphore?: Semaphore;\n\tcapabilityCeiling?: ResolvedSubagentCapabilityCeiling;\n\tpermissions?: PermissionConfig;\n\tdynamic?: boolean;\n}\n\nfunction buildChainExecutionDetails(input: ChainExecutionDetailsInput): Details {\n\treturn compactForegroundDetails({\n\t\tmode: \"chain\",\n\t\tresults: input.results,\n\t\tprogress: input.includeProgress ? input.allProgress : undefined,\n\t\tartifacts: input.allArtifactPaths.length ? { dir: input.artifactsDir, files: input.allArtifactPaths } : undefined,\n\t\tchainAgents: input.chainAgents,\n\t\ttotalSteps: input.totalSteps,\n\t\tcurrentStepIndex: input.currentStepIndex,\n\t\toutputs: input.outputs,\n\t\ttotalChildUsage: sumResultsUsage(input.results),\n\t\ttotalCost: sumResultsCost(input.results),\n\t\tusageBudget: usageBudgetState(input.usageBudget, sumResultsCost(input.results)),\n\t\t...(input.checkpoint ? { checkpoint: input.checkpoint } : {}),\n\t\t...(input.parallelHandoff ? { parallelHandoff: input.parallelHandoff } : {}),\n\t\tworkflowGraph: buildWorkflowGraphSnapshot({\n\t\t\trunId: input.runId,\n\t\t\tmode: \"chain\",\n\t\t\tsteps: input.chainSteps,\n\t\t\tresults: input.results,\n\t\t\tcurrentStepIndex: input.currentStepIndex,\n\t\t\tcurrentFlatIndex: input.currentFlatIndex,\n\t\t\tdynamicChildren: input.dynamicChildren,\n\t\t\tdynamicGroupStatuses: input.dynamicGroupStatuses,\n\t\t}),\n\t});\n}\n\nfunction buildChainExecutionErrorResult(message: string, input: ChainExecutionDetailsInput): ChainExecutionResult {\n\treturn {\n\t\tcontent: [{ type: \"text\", text: message }],\n\t\tisError: true,\n\t\tdetails: buildChainExecutionDetails(input),\n\t};\n}\n\nfunction ensureParallelProgressFile(\n\tchainDir: string,\n\tprogressCreated: boolean,\n\tparallelBehaviors: ResolvedStepBehavior[],\n): boolean {\n\tif (progressCreated || !parallelBehaviors.some((behavior) => behavior.progress)) {\n\t\treturn progressCreated;\n\t}\n\twriteInitialProgressFile(chainDir);\n\treturn true;\n}\n\nfunction finalizeParallelWorktreeHandoff(input: {\n\toutput: string;\n\tworktreeSetup: WorktreeSetup;\n\tartifactsDir: string;\n\trunId: string;\n\tcwd: string;\n\tstepIndex: number;\n\tflatStartIndex: number;\n\tagents: string[];\n\tresults: SingleResult[];\n}): { output: string; reference?: NonNullable<Details[\"parallelHandoff\"]> } {\n\tconst diffs = diffWorktrees(\n\t\tinput.worktreeSetup,\n\t\tinput.agents,\n\t\tpath.join(input.artifactsDir, \"worktree-diffs\", input.runId, `step-${input.stepIndex}`),\n\t);\n\tconst diffSummary = formatWorktreeDiffSummary(diffs);\n\tconst manifestPath = parallelHandoffPath(input.artifactsDir, input.runId);\n\tconst handoff = {\n\t\tmanifestPath,\n\t\trunId: input.runId,\n\t\tmode: \"chain\" as const,\n\t\tsource: \"foreground\" as const,\n\t\tcwd: input.cwd,\n\t\tstepIndex: input.stepIndex,\n\t\tflatStartIndex: input.flatStartIndex,\n\t\tsetup: input.worktreeSetup,\n\t\tdiffs,\n\t\tresults: input.results.map((result) => ({\n\t\t\tagent: result.agent,\n\t\t\tstatus: result.stopped\n\t\t\t\t? (\"stopped\" as const)\n\t\t\t\t: result.detached\n\t\t\t\t\t? (\"detached\" as const)\n\t\t\t\t\t: result.interrupted\n\t\t\t\t\t\t? (\"paused\" as const)\n\t\t\t\t\t\t: result.exitCode === 0\n\t\t\t\t\t\t\t? (\"completed\" as const)\n\t\t\t\t\t\t\t: (\"failed\" as const),\n\t\t\tsummary: getSingleResultOutput(result) || result.error || \"(no output)\",\n\t\t\t...(result.artifactPaths?.outputPath ? { outputPath: result.artifactPaths.outputPath } : {}),\n\t\t\t...(result.structuredOutput !== undefined ? { structuredOutput: result.structuredOutput } : {}),\n\t\t\t...(result.structuredOutputPath ? { structuredOutputPath: result.structuredOutputPath } : {}),\n\t\t\t...(result.sessionFile ? { sessionPath: result.sessionFile } : {}),\n\t\t})),\n\t};\n\ttry {\n\t\twriteParallelHandoffGroup(handoff);\n\t\tconst cleanup = cleanupWorktrees(input.worktreeSetup, {\n\t\t\tkind: \"preserve\",\n\t\t\tcapturedDiffs: diffs,\n\t\t\thandoffManifestPath: manifestPath,\n\t\t});\n\t\tconst reference = writeParallelHandoffGroup({ ...handoff, cleanup });\n\t\tconst suffix = [diffSummary, formatParallelHandoffReference(reference)].filter(Boolean).join(\"\\n\\n\");\n\t\treturn { output: suffix ? `${input.output}\\n\\n${suffix}` : input.output, reference };\n\t} catch (error) {\n\t\tconst suffix = [diffSummary, formatParallelHandoffError(error)].filter(Boolean).join(\"\\n\\n\");\n\t\treturn { output: suffix ? `${input.output}\\n\\n${suffix}` : input.output };\n\t}\n}\n\nfunction resolveChainToolBudget(input: {\n\tstepBudget?: ToolBudgetConfig;\n\trunBudget?: ResolvedToolBudget;\n\tagentBudget?: ToolBudgetConfig;\n\tconfigBudget?: ToolBudgetConfig;\n}): { toolBudget?: ResolvedToolBudget; error?: string } {\n\tif (input.stepBudget !== undefined) {\n\t\tconst resolved = validateToolBudgetConfig(input.stepBudget, \"toolBudget\");\n\t\treturn { toolBudget: resolved.budget, error: resolved.error };\n\t}\n\tif (input.runBudget !== undefined) return { toolBudget: input.runBudget };\n\tif (input.agentBudget !== undefined) {\n\t\tconst resolved = validateToolBudgetConfig(input.agentBudget, \"agent.toolBudget\");\n\t\treturn { toolBudget: resolved.budget, error: resolved.error };\n\t}\n\tconst resolved = validateToolBudgetConfig(input.configBudget, \"config.toolBudget\");\n\treturn { toolBudget: resolved.budget, error: resolved.error };\n}\n\nasync function runParallelChainTasks(input: ParallelChainRunInput): Promise<SingleResult[]> {\n\tconst concurrency = input.step.concurrency ?? MAX_CONCURRENCY;\n\tconst failFast = input.step.failFast ?? false;\n\tlet aborted = false;\n\tconst effectiveModels = input.step.parallel.map((task) => {\n\t\tconst taskAgentConfig = input.agents.find((agent) => agent.name === task.agent);\n\t\treturn resolveEffectiveSubagentModel(\n\t\t\ttask.model,\n\t\t\ttaskAgentConfig?.model,\n\t\t\tinput.ctx.model,\n\t\t\tinput.availableModels,\n\t\t\tinput.ctx.model?.provider,\n\t\t\t{ scope: input.modelScope },\n\t\t);\n\t});\n\tfor (let taskIndex = 0; taskIndex < input.step.parallel.length; taskIndex++) {\n\t\tconst task = input.step.parallel[taskIndex]!;\n\t\tinput.sessionFileForTask?.(task.agent, input.globalTaskIndex + taskIndex, effectiveModels[taskIndex]);\n\t}\n\n\tconst completedResults: SingleResult[] = [];\n\tif (input.foregroundControl) retainForegroundSchedulingOwner(input.foregroundControl);\n\tconst parallelResults = await mapConcurrent(\n\t\tinput.step.parallel,\n\t\tconcurrency,\n\t\tasync (task, taskIndex) => {\n\t\t\tconst childIndex = input.globalTaskIndex + taskIndex;\n\t\t\tconst budgetState = usageBudgetState(\n\t\t\t\tinput.usageBudget,\n\t\t\t\tsumResultsCost(input.results.concat(completedResults)),\n\t\t\t);\n\t\t\tif (budgetState?.exhausted) {\n\t\t\t\treturn {\n\t\t\t\t\tindex: childIndex,\n\t\t\t\t\tagent: task.agent,\n\t\t\t\t\ttask: input.parallelTemplates[taskIndex] ?? \"(skipped)\",\n\t\t\t\t\texitCode: 1,\n\t\t\t\t\tmessages: [],\n\t\t\t\t\tusage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 },\n\t\t\t\t\terror: usageBudgetExceededMessage(budgetState),\n\t\t\t\t\tskipped: true,\n\t\t\t\t} as SingleResult;\n\t\t\t}\n\t\t\tif (aborted && failFast) {\n\t\t\t\treturn {\n\t\t\t\t\tindex: childIndex,\n\t\t\t\t\tagent: task.agent,\n\t\t\t\t\ttask: \"(skipped)\",\n\t\t\t\t\texitCode: -1,\n\t\t\t\t\tmessages: [],\n\t\t\t\t\tusage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 },\n\t\t\t\t\terror: \"Skipped due to fail-fast\",\n\t\t\t\t} as SingleResult;\n\t\t\t}\n\n\t\t\tconst taskTemplate = input.parallelTemplates[taskIndex] ?? \"{previous}\";\n\t\t\tconst behavior = suppressProgressForReadOnlyTask(\n\t\t\t\tinput.parallelBehaviors[taskIndex]!,\n\t\t\t\ttaskTemplate,\n\t\t\t\tinput.originalTask,\n\t\t\t);\n\t\t\tconst taskAgentConfig = input.agents.find((agent) => agent.name === task.agent);\n\t\t\tconst templateHasPrevious = taskTemplate.includes(\"{previous}\");\n\t\t\tconst { prefix, suffix } = buildChainInstructions(\n\t\t\t\t{ ...behavior, output: false },\n\t\t\t\tinput.chainDir,\n\t\t\t\tfalse,\n\t\t\t\ttemplateHasPrevious ? undefined : input.prev,\n\t\t\t);\n\n\t\t\tlet taskStr = resolveOutputReferences(taskTemplate, input.outputs);\n\t\t\ttaskStr = taskStr.replace(/\\{task\\}/g, input.originalTask);\n\t\t\ttaskStr = taskStr.replace(/\\{previous\\}/g, input.prev);\n\t\t\ttaskStr = taskStr.replace(/\\{chain_dir\\}/g, input.chainDir);\n\t\t\tconst cleanTask = taskStr;\n\t\t\ttaskStr = prefix + taskStr + suffix;\n\n\t\t\tconst effectiveModel = effectiveModels[taskIndex];\n\t\t\tconst maxSubagentDepth = resolveChildMaxSubagentDepth(\n\t\t\t\tinput.maxSubagentDepth,\n\t\t\t\ttaskAgentConfig?.maxSubagentDepth,\n\t\t\t);\n\t\t\tconst toolBudget = resolveChainToolBudget({\n\t\t\t\tstepBudget: task.toolBudget,\n\t\t\t\trunBudget: input.toolBudget,\n\t\t\t\tagentBudget: taskAgentConfig?.toolBudget,\n\t\t\t\tconfigBudget: input.configToolBudget,\n\t\t\t});\n\t\t\tif (toolBudget.error) throw new Error(toolBudget.error);\n\n\t\t\tconst taskCwd = input.worktreeSetup\n\t\t\t\t? input.worktreeSetup.worktrees[taskIndex]!.agentCwd\n\t\t\t\t: resolveChildCwd(input.cwd ?? input.ctx.cwd, task.cwd);\n\n\t\t\tconst outputPath =\n\t\t\t\ttypeof behavior.output === \"string\"\n\t\t\t\t\t? path.isAbsolute(behavior.output)\n\t\t\t\t\t\t? behavior.output\n\t\t\t\t\t\t: path.join(input.chainDir, behavior.output)\n\t\t\t\t\t: undefined;\n\t\t\ttaskStr = injectSingleOutputInstruction(taskStr, outputPath, taskAgentConfig);\n\t\t\tconst interruptController = new AbortController();\n\t\t\tif (input.foregroundControl) {\n\t\t\t\tconst thinking = resolveEffectiveThinking(\n\t\t\t\t\teffectiveModel,\n\t\t\t\t\tinput.thinkingOverrideForTask?.(task.agent, childIndex, effectiveModel),\n\t\t\t\t);\n\t\t\t\tbeginForegroundChild(input.foregroundControl, {\n\t\t\t\t\tindex: childIndex,\n\t\t\t\t\tagent: task.agent,\n\t\t\t\t\tdescription: cleanTask.trim(),\n\t\t\t\t\t...(effectiveModel ? { model: effectiveModel } : {}),\n\t\t\t\t\t...(thinking ? { thinking } : {}),\n\t\t\t\t\tinterrupt: () => {\n\t\t\t\t\t\tif (interruptController.signal.aborted) return false;\n\t\t\t\t\t\tinterruptController.abort();\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst structuredRuntime = task.outputSchema\n\t\t\t\t? createStructuredOutputRuntime(task.outputSchema, path.join(input.chainDir, \"structured-output\"))\n\t\t\t\t: undefined;\n\t\t\tconst agentContract = task.agentContract ?? input.step.agentContract ?? input.agentContract;\n\t\t\tlet result!: SingleResult;\n\t\t\ttry {\n\t\t\t\tresult = await runSync(input.ctx.cwd, input.agents, task.agent, taskStr, {\n\t\t\t\t\tpermissions: input.permissions,\n\t\t\t\t\tparentSessionId: input.ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\t\t\tcapabilityCeiling: input.capabilityCeiling,\n\t\t\t\t\tcontext: input.contextForAgent?.(task.agent),\n\t\t\t\t\tcwd: taskCwd,\n\t\t\t\t\tsignal: input.signal,\n\t\t\t\t\tinterruptSignal: interruptController.signal,\n\t\t\t\t\tallowIntercomDetach: taskAgentConfig?.systemPrompt?.includes(INTERCOM_BRIDGE_MARKER) === true,\n\t\t\t\t\tintercomEvents: input.intercomEvents,\n\t\t\t\t\trunId: input.runId,\n\t\t\t\t\tindex: childIndex,\n\t\t\t\t\tsessionDir: input.sessionDirForIndex(childIndex),\n\t\t\t\t\tsessionFile:\n\t\t\t\t\t\tinput.sessionFileForTask?.(task.agent, childIndex, effectiveModel) ??\n\t\t\t\t\t\tinput.sessionFileForIndex?.(childIndex),\n\t\t\t\t\tthinkingOverride: input.thinkingOverrideForTask?.(task.agent, childIndex, effectiveModel),\n\t\t\t\t\tshare: input.shareEnabled,\n\t\t\t\t\tartifactsDir: input.artifactConfig.enabled ? input.artifactsDir : undefined,\n\t\t\t\t\tartifactConfig: input.artifactConfig,\n\t\t\t\t\toutputPath,\n\t\t\t\t\toutputMode: behavior.outputMode,\n\t\t\t\t\tmaxSubagentDepth,\n\t\t\t\t\tcontrolConfig: input.controlConfig,\n\t\t\t\t\tonControlEvent: input.onControlEvent,\n\t\t\t\t\tintercomSessionName: input.childIntercomTarget?.(task.agent, childIndex),\n\t\t\t\t\torchestratorIntercomTarget: input.orchestratorIntercomTarget,\n\t\t\t\t\tnestedRoute: input.nestedRoute,\n\t\t\t\t\tmodelOverride: effectiveModel,\n\t\t\t\t\tavailableModels: input.availableModels,\n\t\t\t\t\tpreferredModelProvider: input.ctx.model?.provider,\n\t\t\t\t\tmodelScope: input.modelScope,\n\t\t\t\t\tskills: behavior.skills === false ? [] : behavior.skills,\n\t\t\t\t\tstructuredOutput: structuredRuntime,\n\t\t\t\t\tagentContract,\n\t\t\t\t\tacceptance: task.acceptance,\n\t\t\t\t\tacceptanceContext: { mode: \"chain\", dynamic: input.dynamic && task.acceptance === undefined },\n\t\t\t\t\ttimeoutMs: input.timeoutMs,\n\t\t\t\t\tdeadlineAt: input.deadlineAt,\n\t\t\t\t\tturnBudget: input.turnBudget,\n\t\t\t\t\tonDetachedExit: (result) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (input.foregroundControl) finishForegroundChild(input.foregroundControl, childIndex);\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tinput.onDetachedExit?.(childIndex, result);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\ttoolBudget: toolBudget.toolBudget,\n\t\t\t\t\tonUpdate: input.onUpdate\n\t\t\t\t\t\t? (progressUpdate) => {\n\t\t\t\t\t\t\t\tconst stepResults = progressUpdate.details?.results || [];\n\t\t\t\t\t\t\t\tconst stepProgress = progressUpdate.details?.progress || [];\n\t\t\t\t\t\t\t\tif (input.foregroundControl && stepProgress.length > 0) {\n\t\t\t\t\t\t\t\t\tupdateForegroundChild(input.foregroundControl, childIndex, stepProgress[0]);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tinput.onUpdate?.({\n\t\t\t\t\t\t\t\t\t...progressUpdate,\n\t\t\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\t\t\t\t\tresults: input.results.concat(stepResults),\n\t\t\t\t\t\t\t\t\t\tprogress: input.allProgress.concat(stepProgress),\n\t\t\t\t\t\t\t\t\t\tcontrolEvents: progressUpdate.details?.controlEvents,\n\t\t\t\t\t\t\t\t\t\tchainAgents: input.chainAgents,\n\t\t\t\t\t\t\t\t\t\ttotalSteps: input.totalSteps,\n\t\t\t\t\t\t\t\t\t\tcurrentStepIndex: input.stepIndex,\n\t\t\t\t\t\t\t\t\t\toutputs: input.outputs,\n\t\t\t\t\t\t\t\t\t\tworkflowGraph: buildWorkflowGraphSnapshot({\n\t\t\t\t\t\t\t\t\t\t\trunId: input.runId,\n\t\t\t\t\t\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\t\t\t\t\t\tsteps: input.chainSteps,\n\t\t\t\t\t\t\t\t\t\t\tresults: input.results.concat(stepResults),\n\t\t\t\t\t\t\t\t\t\t\tcurrentStepIndex: input.stepIndex,\n\t\t\t\t\t\t\t\t\t\t\tcurrentFlatIndex: childIndex,\n\t\t\t\t\t\t\t\t\t\t\tdynamicChildren: input.dynamicChildren,\n\t\t\t\t\t\t\t\t\t\t\tdynamicGroupStatuses: input.dynamicGroupStatuses,\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined,\n\t\t\t\t});\n\t\t\t} finally {\n\t\t\t\t// Rejected attached attempts still release their parallel child control;\n\t\t\t\t// detached receipts transfer ownership to onDetachedExit.\n\t\t\t\tif (!result?.detached) {\n\t\t\t\t\tif (input.foregroundControl) finishForegroundChild(input.foregroundControl, childIndex);\n\t\t\t\t\tinput.onForegroundChildSettled?.();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (result.exitCode !== 0 && failFast) {\n\t\t\t\taborted = true;\n\t\t\t}\n\t\t\trecordRun(task.agent, cleanTask, result.exitCode, result.progressSummary?.durationMs ?? 0);\n\t\t\tcompletedResults.push(result);\n\t\t\treturn result;\n\t\t},\n\t\tinput.globalSemaphore,\n\t\t() => {\n\t\t\tif (input.foregroundControl) settleForegroundSchedulingOwner(input.foregroundControl);\n\t\t\tinput.onForegroundChildSettled?.();\n\t\t},\n\t);\n\n\treturn parallelResults;\n}\n\ninterface ChainExecutionParams {\n\tchain: ChainStep[];\n\ttask?: string;\n\tagents: AgentConfig[];\n\tctx: ExtensionContext;\n\tintercomEvents?: IntercomEventBus;\n\tsignal?: AbortSignal;\n\trunId: string;\n\tcwd?: string;\n\tshareEnabled: boolean;\n\tsessionDirForIndex: (idx?: number) => string | undefined;\n\tsessionFileForIndex?: (idx?: number) => string | undefined;\n\tsessionFileForTask?: (agentName: string, idx?: number, modelOverride?: string) => string | undefined;\n\tthinkingOverrideForTask?: (\n\t\tagentName: string,\n\t\tidx?: number,\n\t\tmodelOverride?: string,\n\t) => AgentConfig[\"thinking\"] | undefined;\n\tcontextForAgent?: (agentName: string) => ContextMode;\n\tmodelScope?: ModelScopeConfig;\n\tartifactsDir: string;\n\tartifactConfig: ArtifactConfig;\n\tincludeProgress?: boolean;\n\tclarify?: boolean;\n\tonUpdate?: (r: AgentToolResult<Details>) => void;\n\tonControlEvent?: (event: ControlEvent) => void;\n\tcontrolConfig: ResolvedControlConfig;\n\tagentContract?: AgentContract;\n\tchildIntercomTarget?: (agent: string, index: number) => string | undefined;\n\torchestratorIntercomTarget?: string;\n\tforegroundControl?: ForegroundRunControl;\n\tchainSkills?: string[];\n\tchainDir?: string;\n\tdynamicFanoutMaxItems?: number;\n\tmaxSubagentDepth: number;\n\tnestedRoute?: NestedRouteInfo;\n\tworktreeSetupHook?: string;\n\tworktreeSetupHookTimeoutMs?: number;\n\tworktreeBaseDir?: string;\n\ttimeoutMs?: number;\n\tdeadlineAt?: number;\n\tturnBudget?: ResolvedTurnBudget;\n\tonDetachedExit?: (index: number, result: SingleResult) => void;\n\t/** Ownership callback used when parallel siblings outlive executeChain rejection. */\n\tonForegroundChildSettled?: () => void;\n\ttoolBudget?: ResolvedToolBudget;\n\tusageBudget?: UsageBudgetConfig;\n\tconfigToolBudget?: ToolBudgetConfig;\n\tpermissions?: PermissionConfig;\n\t/** Global cap on simultaneously-running tasks within this chain. Defaults to DEFAULT_GLOBAL_CONCURRENCY_LIMIT. */\n\tglobalConcurrencyLimit?: number;\n\tcapabilityCeiling?: ResolvedSubagentCapabilityCeiling;\n}\n\ninterface ChainExecutionResult {\n\tcontent: Array<{ type: \"text\"; text: string }>;\n\tdetails: Details;\n\tisError?: boolean;\n\t/** User requested async execution via TUI - caller should dispatch to executeAsyncChain */\n\trequestedAsync?: {\n\t\tchain: ChainStep[];\n\t\tchainSkills: string[];\n\t};\n}\n\n/**\n * Execute a chain of subagent steps\n */\nexport async function executeChain(params: ChainExecutionParams): Promise<ChainExecutionResult> {\n\tconst {\n\t\tchain: chainSteps,\n\t\tagents,\n\t\tctx,\n\t\tsignal,\n\t\trunId,\n\t\tcwd,\n\t\tshareEnabled,\n\t\tsessionDirForIndex,\n\t\tsessionFileForIndex,\n\t\tsessionFileForTask,\n\t\tthinkingOverrideForTask,\n\t\tartifactsDir,\n\t\tartifactConfig,\n\t\tincludeProgress,\n\t\tclarify,\n\t\tonUpdate,\n\t\tonControlEvent,\n\t\tcontrolConfig,\n\t\tonDetachedExit,\n\t\tchildIntercomTarget,\n\t\torchestratorIntercomTarget,\n\t\tforegroundControl,\n\t\tintercomEvents,\n\t\tchainSkills: chainSkillsParam,\n\t\tchainDir: chainDirBase,\n\t\tmodelScope,\n\t} = params;\n\tconst chainSkills = chainSkillsParam ?? [];\n\n\tconst results: SingleResult[] = [];\n\tconst outputs: ChainOutputMap = {};\n\tconst dynamicChildren: ChainExecutionDetailsInput[\"dynamicChildren\"] = {};\n\tconst dynamicGroupStatuses: ChainExecutionDetailsInput[\"dynamicGroupStatuses\"] = {};\n\tconst allProgress: AgentProgress[] = [];\n\tconst allArtifactPaths: ArtifactPaths[] = [];\n\tlet parallelHandoff: Details[\"parallelHandoff\"];\n\n\tconst chainAgents: string[] = chainSteps.map((step) =>\n\t\tisCheckpointStep(step)\n\t\t\t? `checkpoint:${step.checkpoint}`\n\t\t\t: isParallelStep(step)\n\t\t\t\t? `[${step.parallel.map((t) => t.agent).join(\"+\")}]`\n\t\t\t\t: isDynamicParallelStep(step)\n\t\t\t\t\t? `expand:${step.parallel.agent}`\n\t\t\t\t\t: (step as SequentialStep).agent,\n\t);\n\tconst totalSteps = chainSteps.length;\n\n\tconst makeDetailsInput = (\n\t\toverrides: Pick<Partial<ChainExecutionDetailsInput>, \"currentStepIndex\" | \"currentFlatIndex\" | \"checkpoint\"> = {},\n\t): ChainExecutionDetailsInput => ({\n\t\tresults,\n\t\t...(includeProgress !== undefined ? { includeProgress } : {}),\n\t\tallProgress,\n\t\tallArtifactPaths,\n\t\tartifactsDir,\n\t\tchainAgents,\n\t\tchainSteps,\n\t\ttotalSteps,\n\t\trunId,\n\t\toutputs,\n\t\tdynamicChildren,\n\t\tdynamicGroupStatuses,\n\t\t...(parallelHandoff ? { parallelHandoff } : {}),\n\t\tusageBudget: params.usageBudget,\n\t\t...overrides,\n\t});\n\n\tconst usageBudgetError = (stepIndex: number, flatIndex: number): ChainExecutionResult | undefined => {\n\t\tconst state = usageBudgetState(params.usageBudget, sumResultsCost(results));\n\t\tif (!state?.exhausted) return undefined;\n\t\treturn buildChainExecutionErrorResult(\n\t\t\tusageBudgetExceededMessage(state),\n\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: flatIndex }),\n\t\t);\n\t};\n\n\tconst firstStep = chainSteps[0]!;\n\tconst originalTask =\n\t\tparams.task ??\n\t\t(isCheckpointStep(firstStep)\n\t\t\t? undefined\n\t\t\t: isParallelStep(firstStep)\n\t\t\t\t? firstStep.parallel[0]!.task\n\t\t\t\t: isDynamicParallelStep(firstStep)\n\t\t\t\t\t? firstStep.parallel.task\n\t\t\t\t\t: (firstStep as SequentialStep).task) ??\n\t\t\"\";\n\ttry {\n\t\tvalidateChainOutputBindings(chainSteps, { maxItems: params.dynamicFanoutMaxItems });\n\t} catch (error) {\n\t\tif (error instanceof ChainOutputValidationError) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: error.message }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput()),\n\t\t\t};\n\t\t}\n\t\tthrow error;\n\t}\n\n\tconst chainDir = createChainDir(runId, chainDirBase);\n\tconst hasParallelSteps = chainSteps.some(\n\t\t(step) => isParallelStep(step) || isDynamicParallelStep(step) || isCheckpointStep(step),\n\t);\n\tlet templates: ResolvedTemplates = resolveChainTemplates(chainSteps);\n\tconst shouldClarify = clarify === true && ctx.hasUI && !hasParallelSteps;\n\tlet tuiBehaviorOverrides: (BehaviorOverride | undefined)[] | undefined;\n\tconst availableModels: ModelInfo[] = ctx.modelRegistry.getAvailable().map(toModelInfo);\n\tconst availableSkills = discoverAvailableSkills(cwd ?? ctx.cwd);\n\n\tif (shouldClarify) {\n\t\tconst seqSteps = chainSteps as SequentialStep[];\n\t\tconst agentConfigs: AgentConfig[] = [];\n\t\tfor (const step of seqSteps) {\n\t\t\tconst config = agents.find((a) => a.name === step.agent);\n\t\t\tif (!config) {\n\t\t\t\tremoveChainDir(chainDir);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Unknown agent: ${step.agent}` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: seqSteps.indexOf(step) })),\n\t\t\t\t};\n\t\t\t}\n\t\t\tagentConfigs.push(config);\n\t\t}\n\n\t\tconst stepOverrides: StepOverrides[] = seqSteps.map((step) => ({\n\t\t\toutput: step.output,\n\t\t\toutputMode: step.outputMode,\n\t\t\treads: step.reads,\n\t\t\tprogress: step.progress,\n\t\t\tskills: normalizeSkillInput(step.skill),\n\t\t\tmodel: step.model,\n\t\t}));\n\n\t\tconst resolvedBehaviors = agentConfigs.map((config, i) =>\n\t\t\tresolveStepBehavior(config, stepOverrides[i]!, chainSkills),\n\t\t);\n\t\tconst flatTemplates = templates as string[];\n\n\t\tconst result = await ctx.ui.custom<ChainClarifyResult>(\n\t\t\t(tui, theme, _kb, done) =>\n\t\t\t\tnew ChainClarifyComponent(\n\t\t\t\t\ttui,\n\t\t\t\t\ttheme,\n\t\t\t\t\tagentConfigs,\n\t\t\t\t\tflatTemplates,\n\t\t\t\t\toriginalTask,\n\t\t\t\t\tchainDir,\n\t\t\t\t\tresolvedBehaviors,\n\t\t\t\t\tavailableModels,\n\t\t\t\t\tctx.model?.provider,\n\t\t\t\t\tavailableSkills,\n\t\t\t\t\tdone,\n\t\t\t\t),\n\t\t\t{\n\t\t\t\toverlay: true,\n\t\t\t\toverlayOptions: { anchor: \"center\", width: 84, maxHeight: \"80%\" },\n\t\t\t},\n\t\t);\n\n\t\tif (!result || !result.confirmed) {\n\t\t\tremoveChainDir(chainDir);\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Chain cancelled\" }],\n\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput()),\n\t\t\t};\n\t\t}\n\n\t\tif (result.runInBackground) {\n\t\t\tremoveChainDir(chainDir);\n\t\t\tconst updatedChain: ChainStep[] = chainSteps.map((step, i) => {\n\t\t\t\tif (isParallelStep(step)) return step;\n\t\t\t\tconst override = result.behaviorOverrides[i];\n\t\t\t\treturn {\n\t\t\t\t\t...step,\n\t\t\t\t\ttask: result.templates[i]!,\n\t\t\t\t\t...(override?.model !== undefined ? { model: override.model } : {}),\n\t\t\t\t\t...(override?.output !== undefined ? { output: override.output } : {}),\n\t\t\t\t\t...(\"outputMode\" in step && step.outputMode !== undefined ? { outputMode: step.outputMode } : {}),\n\t\t\t\t\t...(override?.reads !== undefined ? { reads: override.reads } : {}),\n\t\t\t\t\t...(override?.progress !== undefined ? { progress: override.progress } : {}),\n\t\t\t\t\t...(override?.skills !== undefined ? { skill: override.skills } : {}),\n\t\t\t\t};\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Launching in background...\" }],\n\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput()),\n\t\t\t\trequestedAsync: { chain: updatedChain, chainSkills },\n\t\t\t};\n\t\t}\n\n\t\ttemplates = result.templates;\n\t\ttuiBehaviorOverrides = result.behaviorOverrides;\n\t}\n\n\tconst deadlineAt = params.deadlineAt ?? (params.timeoutMs !== undefined ? Date.now() + params.timeoutMs : undefined);\n\tconst globalSemaphore = new Semaphore(params.globalConcurrencyLimit ?? DEFAULT_GLOBAL_CONCURRENCY_LIMIT);\n\tlet prev = \"\";\n\tlet globalTaskIndex = 0;\n\tlet progressCreated = false;\n\n\tfor (let stepIndex = 0; stepIndex < chainSteps.length; stepIndex++) {\n\t\tconst budgetError = usageBudgetError(stepIndex, globalTaskIndex);\n\t\tif (budgetError) return budgetError;\n\t\tconst step = chainSteps[stepIndex]!;\n\t\tconst stepTemplates = templates[stepIndex]!;\n\n\t\tif (isCheckpointStep(step)) {\n\t\t\tconst checkpoint = {\n\t\t\t\tname: step.checkpoint,\n\t\t\t\t...(step.message ? { message: step.message } : {}),\n\t\t\t\tstatus: \"pending\" as const,\n\t\t\t\tstepIndex,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `Chain paused at checkpoint '${step.checkpoint}'. Approve with subagent({ action: \"approve-checkpoint\", id: \"${runId}\" }) or reject with subagent({ action: \"reject-checkpoint\", id: \"${runId}\" }).${\n\t\t\t\t\t\t\tstep.message\n\t\t\t\t\t\t\t\t? `\n\n${step.message}`\n\t\t\t\t\t\t\t\t: \"\"\n\t\t\t\t\t\t}`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdetails: buildChainExecutionDetails(\n\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex, checkpoint }),\n\t\t\t\t),\n\t\t\t};\n\t\t}\n\n\t\tif (isParallelStep(step)) {\n\t\t\tconst parallelTemplates = stepTemplates as string[];\n\t\t\tconst parallelCwd = resolveChildCwd(cwd ?? ctx.cwd, step.cwd);\n\t\t\tlet worktreeSetup: WorktreeSetup | undefined;\n\t\t\tlet worktreeFinalized = false;\n\t\t\tif (step.worktree) {\n\t\t\t\tconst worktreeTaskCwdConflict = findWorktreeTaskCwdConflict(step.parallel, parallelCwd);\n\t\t\t\tif (worktreeTaskCwdConflict) {\n\t\t\t\t\treturn buildChainExecutionErrorResult(\n\t\t\t\t\t\t`parallel chain step ${stepIndex + 1}: ${formatWorktreeTaskCwdConflict(worktreeTaskCwdConflict, parallelCwd)}`,\n\t\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tworktreeSetup = createWorktrees(parallelCwd, `${runId}-s${stepIndex}`, step.parallel.length, {\n\t\t\t\t\t\tagents: step.parallel.map((task) => task.agent),\n\t\t\t\t\t\tsetupHook: params.worktreeSetupHook\n\t\t\t\t\t\t\t? { hookPath: params.worktreeSetupHook, timeoutMs: params.worktreeSetupHookTimeoutMs }\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\tbaseDir: params.worktreeBaseDir,\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\t\treturn buildChainExecutionErrorResult(\n\t\t\t\t\t\tmessage,\n\t\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tif (worktreeSetup) {\n\t\t\t\t\twritePendingParallelHandoff({\n\t\t\t\t\t\tmanifestPath: parallelHandoffPath(artifactsDir, runId),\n\t\t\t\t\t\trunId,\n\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\tsource: \"foreground\",\n\t\t\t\t\t\tcwd: parallelCwd,\n\t\t\t\t\t\tstepIndex,\n\t\t\t\t\t\tflatStartIndex: globalTaskIndex,\n\t\t\t\t\t\tsetup: worktreeSetup,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst agentNames = step.parallel.map((task) => task.agent);\n\t\t\t\tconst parallelBehaviors = resolveParallelBehaviors(step.parallel, agents, stepIndex, chainSkills).map(\n\t\t\t\t\t(behavior, taskIndex) =>\n\t\t\t\t\t\tsuppressProgressForReadOnlyTask(\n\t\t\t\t\t\t\tbehavior,\n\t\t\t\t\t\t\tparallelTemplates[taskIndex] ?? step.parallel[taskIndex]?.task,\n\t\t\t\t\t\t\toriginalTask,\n\t\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tfor (let taskIndex = 0; taskIndex < step.parallel.length; taskIndex++) {\n\t\t\t\t\tconst behavior = parallelBehaviors[taskIndex]!;\n\t\t\t\t\tconst outputPath =\n\t\t\t\t\t\ttypeof behavior.output === \"string\"\n\t\t\t\t\t\t\t? path.isAbsolute(behavior.output)\n\t\t\t\t\t\t\t\t? behavior.output\n\t\t\t\t\t\t\t\t: path.join(chainDir, behavior.output)\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\tconst validationError = validateFileOnlyOutputMode(\n\t\t\t\t\t\tbehavior.outputMode,\n\t\t\t\t\t\toutputPath,\n\t\t\t\t\t\t`Parallel chain step ${stepIndex + 1} task ${taskIndex + 1} (${step.parallel[taskIndex]!.agent})`,\n\t\t\t\t\t);\n\t\t\t\t\tif (validationError)\n\t\t\t\t\t\treturn buildChainExecutionErrorResult(\n\t\t\t\t\t\t\tvalidationError,\n\t\t\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex + taskIndex }),\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tprogressCreated = ensureParallelProgressFile(chainDir, progressCreated, parallelBehaviors);\n\t\t\t\tcreateParallelDirs(chainDir, stepIndex, step.parallel.length, agentNames);\n\n\t\t\t\tconst parallelResults = await runParallelChainTasks({\n\t\t\t\t\tstep,\n\t\t\t\t\tparallelTemplates,\n\t\t\t\t\tparallelBehaviors,\n\t\t\t\t\tagents,\n\t\t\t\t\tstepIndex,\n\t\t\t\t\tavailableModels,\n\t\t\t\t\tmodelScope,\n\t\t\t\t\tchainDir,\n\t\t\t\t\tprev,\n\t\t\t\t\toriginalTask,\n\t\t\t\t\tctx,\n\t\t\t\t\tintercomEvents,\n\t\t\t\t\tcwd,\n\t\t\t\t\trunId,\n\t\t\t\t\tglobalTaskIndex,\n\t\t\t\t\tsessionDirForIndex,\n\t\t\t\t\tsessionFileForIndex,\n\t\t\t\t\tsessionFileForTask,\n\t\t\t\t\tthinkingOverrideForTask,\n\t\t\t\t\tcontextForAgent: params.contextForAgent,\n\t\t\t\t\tshareEnabled,\n\t\t\t\t\tartifactConfig,\n\t\t\t\t\tartifactsDir,\n\t\t\t\t\tsignal,\n\t\t\t\t\tonUpdate,\n\t\t\t\t\tresults,\n\t\t\t\t\tallProgress,\n\t\t\t\t\toutputs,\n\t\t\t\t\tchainAgents,\n\t\t\t\t\tchainSteps,\n\t\t\t\t\ttotalSteps,\n\t\t\t\t\tdynamicChildren,\n\t\t\t\t\tdynamicGroupStatuses,\n\t\t\t\t\tcontrolConfig,\n\t\t\t\t\tagentContract: params.agentContract,\n\t\t\t\t\tonControlEvent,\n\t\t\t\t\tchildIntercomTarget,\n\t\t\t\t\torchestratorIntercomTarget,\n\t\t\t\t\tforegroundControl,\n\t\t\t\t\tnestedRoute: params.nestedRoute,\n\t\t\t\t\tworktreeSetup,\n\t\t\t\t\tmaxSubagentDepth: params.maxSubagentDepth,\n\t\t\t\t\ttimeoutMs: params.timeoutMs,\n\t\t\t\t\tdeadlineAt,\n\t\t\t\t\tturnBudget: params.turnBudget,\n\t\t\t\t\tusageBudget: params.usageBudget,\n\t\t\t\t\tonDetachedExit,\n\t\t\t\t\tonForegroundChildSettled: params.onForegroundChildSettled,\n\t\t\t\t\ttoolBudget: params.toolBudget,\n\t\t\t\t\tconfigToolBudget: params.configToolBudget,\n\t\t\t\t\tglobalSemaphore,\n\t\t\t\t\tpermissions: params.permissions,\n\t\t\t\t});\n\t\t\t\tglobalTaskIndex += step.parallel.length;\n\n\t\t\t\tfor (const result of parallelResults) {\n\t\t\t\t\tresults.push(result);\n\t\t\t\t\tif (result.progress) allProgress.push(result.progress);\n\t\t\t\t\tif (result.artifactPaths) allArtifactPaths.push(result.artifactPaths);\n\t\t\t\t}\n\t\t\t\tlet worktreeSuffix = \"\";\n\t\t\t\tif (worktreeSetup) {\n\t\t\t\t\tworktreeFinalized = true;\n\t\t\t\t\tconst finalized = finalizeParallelWorktreeHandoff({\n\t\t\t\t\t\toutput: \"\",\n\t\t\t\t\t\tworktreeSetup,\n\t\t\t\t\t\tartifactsDir,\n\t\t\t\t\t\trunId,\n\t\t\t\t\t\tcwd: parallelCwd,\n\t\t\t\t\t\tstepIndex,\n\t\t\t\t\t\tflatStartIndex: globalTaskIndex - step.parallel.length,\n\t\t\t\t\t\tagents: agentNames,\n\t\t\t\t\t\tresults: parallelResults,\n\t\t\t\t\t});\n\t\t\t\t\tif (finalized.reference) parallelHandoff = finalized.reference;\n\t\t\t\t\tworktreeSuffix = finalized.output.trim();\n\t\t\t\t}\n\t\t\t\tconst interruptedIndexInStep = parallelResults.findIndex((result) => result.interrupted);\n\t\t\t\tconst interrupted = interruptedIndexInStep >= 0 ? parallelResults[interruptedIndexInStep] : undefined;\n\t\t\t\tif (interrupted) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\ttext: `Chain paused after interrupt at step ${stepIndex + 1} (${interrupted.agent}). Waiting for explicit next action.`,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdetails: buildChainExecutionDetails(\n\t\t\t\t\t\t\tmakeDetailsInput({\n\t\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\t\tcurrentFlatIndex: globalTaskIndex - step.parallel.length + interruptedIndexInStep,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tconst detachedIndexInStep = parallelResults.findIndex((result) => result.detached);\n\t\t\t\tconst detached = detachedIndexInStep >= 0 ? parallelResults[detachedIndexInStep] : undefined;\n\t\t\t\tif (detached) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\ttext: `Chain detached for intercom coordination at step ${stepIndex + 1} (${detached.agent}). Reply to the supervisor request first, then wait with subagent_wait({ id: \"${runId}\" }). Use subagent({ action: \"status\", id: \"${runId}\" }) to recover the result; do not resume or launch a replacement while it remains detached.`,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdetails: buildChainExecutionDetails(\n\t\t\t\t\t\t\tmakeDetailsInput({\n\t\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\t\tcurrentFlatIndex: globalTaskIndex - step.parallel.length + detachedIndexInStep,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst failures = parallelResults\n\t\t\t\t\t.map((result, originalIndex) => ({ ...result, originalIndex }))\n\t\t\t\t\t.filter((result) => result.exitCode !== 0 && result.exitCode !== -1);\n\t\t\t\tif (failures.length > 0) {\n\t\t\t\t\tconst failureSummary = failures\n\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t(failure) =>\n\t\t\t\t\t\t\t\t`- Task ${failure.originalIndex + 1} (${failure.agent}): ${failure.error || \"failed\"}`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.join(\"\\n\");\n\t\t\t\t\tconst errorMsg = `Parallel step ${stepIndex + 1} failed:\\n${failureSummary}`;\n\t\t\t\t\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"failed\", {\n\t\t\t\t\t\tindex: stepIndex,\n\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t});\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: summary }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\tdetails: buildChainExecutionDetails(\n\t\t\t\t\t\t\tmakeDetailsInput({\n\t\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\t\tcurrentFlatIndex: globalTaskIndex - step.parallel.length + failures[0]!.originalIndex,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tconst acceptanceFailures = parallelResults\n\t\t\t\t\t.map((result, originalIndex) => ({ result, originalIndex, task: step.parallel[originalIndex] }))\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t({ result, task }) =>\n\t\t\t\t\t\t\tisAgentContractV1(task?.agentContract ?? step.agentContract ?? params.agentContract) &&\n\t\t\t\t\t\t\t(task?.gateOn ?? step.gateOn) === \"acceptance\" &&\n\t\t\t\t\t\t\tresult.acceptance?.status === \"rejected\",\n\t\t\t\t\t);\n\t\t\t\tif (acceptanceFailures.length > 0) {\n\t\t\t\t\tconst acceptanceSummary = acceptanceFailures\n\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t({ result, originalIndex }) =>\n\t\t\t\t\t\t\t\t`- Task ${originalIndex + 1} (${result.agent}): ${(result.acceptance ? acceptanceFailureMessage(result.acceptance) : undefined) ?? \"acceptance rejected\"}`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.join(\"\\n\");\n\t\t\t\t\tconst errorMsg = `Parallel step ${stepIndex + 1} acceptance gate failed:\\n${acceptanceSummary}`;\n\t\t\t\t\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"failed\", {\n\t\t\t\t\t\tindex: stepIndex,\n\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t});\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: summary }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\tdetails: buildChainExecutionDetails(\n\t\t\t\t\t\t\tmakeDetailsInput({\n\t\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\t\tcurrentFlatIndex: globalTaskIndex - step.parallel.length + acceptanceFailures[0]!.originalIndex,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tfor (let taskIndex = 0; taskIndex < parallelResults.length; taskIndex++) {\n\t\t\t\t\tconst outputName = step.parallel[taskIndex]?.as;\n\t\t\t\t\tif (outputName) outputs[outputName] = outputEntryFromResult(parallelResults[taskIndex]!, stepIndex);\n\t\t\t\t}\n\n\t\t\t\tconst taskResults: ParallelTaskResult[] = parallelResults.map((result, i) => {\n\t\t\t\t\tconst outputTarget = parallelBehaviors[i]?.output;\n\t\t\t\t\tconst outputTargetPath =\n\t\t\t\t\t\ttypeof outputTarget === \"string\"\n\t\t\t\t\t\t\t? path.isAbsolute(outputTarget)\n\t\t\t\t\t\t\t\t? outputTarget\n\t\t\t\t\t\t\t\t: path.join(chainDir, outputTarget)\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tagent: result.agent,\n\t\t\t\t\t\ttaskIndex: i,\n\t\t\t\t\t\toutput: getSingleResultOutput(result),\n\t\t\t\t\t\texitCode: result.exitCode,\n\t\t\t\t\t\terror: result.error,\n\t\t\t\t\t\ttimedOut: result.timedOut,\n\t\t\t\t\t\toutputTargetPath,\n\t\t\t\t\t\toutputTargetExists: outputTargetPath ? fs.existsSync(outputTargetPath) : undefined,\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t\tprev = aggregateParallelOutputs(taskResults);\n\t\t\t\tif (worktreeSuffix) prev = `${prev}\\n\\n${worktreeSuffix}`;\n\t\t\t} finally {\n\t\t\t\tif (worktreeSetup && !worktreeFinalized) cleanupWorktrees(worktreeSetup);\n\t\t\t}\n\t\t} else if (isDynamicParallelStep(step)) {\n\t\t\tconst dynamicStartIndex = globalTaskIndex;\n\t\t\tconst reservedDynamicItems = step.expand.maxItems ?? params.dynamicFanoutMaxItems ?? 0;\n\t\t\tlet materialized: ReturnType<typeof materializeDynamicParallelStep>;\n\t\t\ttry {\n\t\t\t\tmaterialized = materializeDynamicParallelStep(step, outputs, stepIndex, {\n\t\t\t\t\tmaxItems: params.dynamicFanoutMaxItems,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconst message =\n\t\t\t\t\terror instanceof DynamicFanoutError\n\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t: error instanceof Error\n\t\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t\t: String(error);\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: message };\n\t\t\t\treturn buildChainExecutionErrorResult(\n\t\t\t\t\tmessage,\n\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tdynamicChildren[stepIndex] = materialized.items.map((item, itemIndex) => ({\n\t\t\t\tagent: step.parallel.agent,\n\t\t\t\tlabel: materialized.parallel[itemIndex]?.label,\n\t\t\t\tflatIndex: globalTaskIndex + itemIndex,\n\t\t\t\titemKey: item.key,\n\t\t\t\tstructured: Boolean(step.parallel.outputSchema),\n\t\t\t}));\n\n\t\t\tif (materialized.parallel.length === 0) {\n\t\t\t\tconst collection: DynamicCollectedResult[] = [];\n\t\t\t\ttry {\n\t\t\t\t\tawait validateDynamicCollection(step.collect.outputSchema, collection);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message =\n\t\t\t\t\t\terror instanceof DynamicFanoutError\n\t\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t\t: error instanceof Error\n\t\t\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t\t\t: String(error);\n\t\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: message };\n\t\t\t\t\treturn buildChainExecutionErrorResult(\n\t\t\t\t\t\tmessage,\n\t\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\toutputs[step.collect.as] = {\n\t\t\t\t\ttext: JSON.stringify(collection),\n\t\t\t\t\tstructured: collection,\n\t\t\t\t\tagent: step.parallel.agent,\n\t\t\t\t\tstepIndex,\n\t\t\t\t};\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"completed\" };\n\t\t\t\tif (step.acceptance !== undefined) {\n\t\t\t\t\tconst effectiveGroupAcceptance = resolveEffectiveAcceptance({\n\t\t\t\t\t\texplicit: step.acceptance,\n\t\t\t\t\t\tagentName: step.parallel.agent,\n\t\t\t\t\t\tacceptanceRole: agents.find((agent) => agent.name === step.parallel.agent)?.acceptanceRole,\n\t\t\t\t\t\ttask: (step.parallel.task ?? originalTask ?? \"\").replace(/\\{task\\}/g, originalTask ?? \"\"),\n\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\tdynamicGroup: true,\n\t\t\t\t\t\tagentContract: step.agentContract ?? params.agentContract,\n\t\t\t\t\t});\n\t\t\t\t\tconst groupAcceptance = await evaluateAcceptance({\n\t\t\t\t\t\tacceptance: effectiveGroupAcceptance,\n\t\t\t\t\t\toutput: \"\",\n\t\t\t\t\t\treport: aggregateAcceptanceReport({\n\t\t\t\t\t\t\tresults: [],\n\t\t\t\t\t\t\tnotes: \"Dynamic fanout produced 0 results.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tcwd: cwd ?? ctx.cwd,\n\t\t\t\t\t\treportOptional: isAgentContractV1(step.agentContract ?? params.agentContract),\n\t\t\t\t\t});\n\t\t\t\t\tconst dynamicGroupStatus = dynamicGroupStatuses[stepIndex];\n\t\t\t\t\tif (!dynamicGroupStatus) throw new Error(`Missing dynamic group status at step ${stepIndex}`);\n\t\t\t\t\tdynamicGroupStatus.acceptance = groupAcceptance;\n\t\t\t\t\tconst groupAcceptanceFailure =\n\t\t\t\t\t\t!isAgentContractV1(step.agentContract ?? params.agentContract) || step.gateOn === \"acceptance\"\n\t\t\t\t\t\t\t? acceptanceFailureMessage(groupAcceptance)\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\tif (groupAcceptanceFailure) {\n\t\t\t\t\t\tdynamicGroupStatuses[stepIndex] = {\n\t\t\t\t\t\t\tstatus: \"failed\",\n\t\t\t\t\t\t\terror: groupAcceptanceFailure,\n\t\t\t\t\t\t\tacceptance: groupAcceptance,\n\t\t\t\t\t\t};\n\t\t\t\t\t\treturn buildChainExecutionErrorResult(\n\t\t\t\t\t\t\tgroupAcceptanceFailure,\n\t\t\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tprev = \"Dynamic fanout produced 0 results.\";\n\t\t\t\tglobalTaskIndex = dynamicStartIndex + reservedDynamicItems;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst dynamicParallelStep: ParallelStep = {\n\t\t\t\tparallel: materialized.parallel,\n\t\t\t\tconcurrency: step.concurrency,\n\t\t\t\tfailFast: step.failFast,\n\t\t\t\tagentContract: step.agentContract,\n\t\t\t\tgateOn: step.gateOn,\n\t\t\t};\n\t\t\tconst parallelTemplates = materialized.parallel.map((task) => task.task ?? \"{previous}\");\n\t\t\tconst parallelBehaviors = resolveParallelBehaviors(\n\t\t\t\tdynamicParallelStep.parallel,\n\t\t\t\tagents,\n\t\t\t\tstepIndex,\n\t\t\t\tchainSkills,\n\t\t\t).map((behavior, taskIndex) =>\n\t\t\t\tsuppressProgressForReadOnlyTask(\n\t\t\t\t\tbehavior,\n\t\t\t\t\tparallelTemplates[taskIndex] ?? dynamicParallelStep.parallel[taskIndex]?.task,\n\t\t\t\t\toriginalTask,\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tfor (let taskIndex = 0; taskIndex < dynamicParallelStep.parallel.length; taskIndex++) {\n\t\t\t\tconst behavior = parallelBehaviors[taskIndex]!;\n\t\t\t\tconst outputPath =\n\t\t\t\t\ttypeof behavior.output === \"string\"\n\t\t\t\t\t\t? path.isAbsolute(behavior.output)\n\t\t\t\t\t\t\t? behavior.output\n\t\t\t\t\t\t\t: path.join(chainDir, behavior.output)\n\t\t\t\t\t\t: undefined;\n\t\t\t\tconst validationError = validateFileOnlyOutputMode(\n\t\t\t\t\tbehavior.outputMode,\n\t\t\t\t\toutputPath,\n\t\t\t\t\t`Dynamic chain step ${stepIndex + 1} item ${taskIndex + 1} (${dynamicParallelStep.parallel[taskIndex]!.agent})`,\n\t\t\t\t);\n\t\t\t\tif (validationError) {\n\t\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: validationError };\n\t\t\t\t\treturn buildChainExecutionErrorResult(\n\t\t\t\t\t\tvalidationError,\n\t\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex + taskIndex }),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tprogressCreated = ensureParallelProgressFile(chainDir, progressCreated, parallelBehaviors);\n\t\t\tcreateParallelDirs(\n\t\t\t\tchainDir,\n\t\t\t\tstepIndex,\n\t\t\t\tdynamicParallelStep.parallel.length,\n\t\t\t\tdynamicParallelStep.parallel.map((task) => task.agent),\n\t\t\t);\n\t\t\tconst parallelResults = await runParallelChainTasks({\n\t\t\t\tstep: dynamicParallelStep,\n\t\t\t\tparallelTemplates,\n\t\t\t\tparallelBehaviors,\n\t\t\t\tagents,\n\t\t\t\tstepIndex,\n\t\t\t\tavailableModels,\n\t\t\t\tmodelScope,\n\t\t\t\tchainDir,\n\t\t\t\tprev,\n\t\t\t\toriginalTask,\n\t\t\t\tctx,\n\t\t\t\tintercomEvents,\n\t\t\t\tcwd,\n\t\t\t\trunId,\n\t\t\t\tglobalTaskIndex,\n\t\t\t\tsessionDirForIndex,\n\t\t\t\tsessionFileForIndex,\n\t\t\t\tsessionFileForTask,\n\t\t\t\tthinkingOverrideForTask,\n\t\t\t\tcontextForAgent: params.contextForAgent,\n\t\t\t\tshareEnabled,\n\t\t\t\tartifactConfig,\n\t\t\t\tartifactsDir,\n\t\t\t\tsignal,\n\t\t\t\tonUpdate,\n\t\t\t\tresults,\n\t\t\t\tallProgress,\n\t\t\t\toutputs,\n\t\t\t\tchainAgents,\n\t\t\t\tchainSteps,\n\t\t\t\ttotalSteps,\n\t\t\t\tdynamicChildren,\n\t\t\t\tdynamicGroupStatuses,\n\t\t\t\tcontrolConfig,\n\t\t\t\tagentContract: params.agentContract,\n\t\t\t\tonControlEvent,\n\t\t\t\tchildIntercomTarget,\n\t\t\t\torchestratorIntercomTarget,\n\t\t\t\tforegroundControl,\n\t\t\t\tnestedRoute: params.nestedRoute,\n\t\t\t\tmaxSubagentDepth: params.maxSubagentDepth,\n\t\t\t\ttimeoutMs: params.timeoutMs,\n\t\t\t\tdeadlineAt,\n\t\t\t\tturnBudget: params.turnBudget,\n\t\t\t\tusageBudget: params.usageBudget,\n\t\t\t\tonDetachedExit,\n\t\t\t\tonForegroundChildSettled: params.onForegroundChildSettled,\n\t\t\t\ttoolBudget: params.toolBudget,\n\t\t\t\tconfigToolBudget: params.configToolBudget,\n\t\t\t\tglobalSemaphore,\n\t\t\t\tpermissions: params.permissions,\n\t\t\t\tdynamic: true,\n\t\t\t});\n\t\t\tglobalTaskIndex = dynamicStartIndex + reservedDynamicItems;\n\n\t\t\tfor (const result of parallelResults) {\n\t\t\t\tresults.push(result);\n\t\t\t\tif (result.progress) allProgress.push(result.progress);\n\t\t\t\tif (result.artifactPaths) allArtifactPaths.push(result.artifactPaths);\n\t\t\t}\n\t\t\tconst collected = collectDynamicResults(step, materialized.items, parallelResults);\n\t\t\tconst interruptedIndexInStep = parallelResults.findIndex((result) => result.interrupted);\n\t\t\tconst interrupted = interruptedIndexInStep >= 0 ? parallelResults[interruptedIndexInStep] : undefined;\n\t\t\tif (interrupted) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: `Chain paused after interrupt at step ${stepIndex + 1} (${interrupted.agent}). Waiting for explicit next action.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: buildChainExecutionDetails(\n\t\t\t\t\t\tmakeDetailsInput({\n\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\tcurrentFlatIndex: dynamicStartIndex + interruptedIndexInStep,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst detachedIndexInStep = parallelResults.findIndex((result) => result.detached);\n\t\t\tconst detached = detachedIndexInStep >= 0 ? parallelResults[detachedIndexInStep] : undefined;\n\t\t\tif (detached) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: `Chain detached for intercom coordination at step ${stepIndex + 1} (${detached.agent}). Reply to the supervisor request first, then wait with subagent_wait({ id: \"${runId}\" }). Use subagent({ action: \"status\", id: \"${runId}\" }) to recover the result; do not resume or launch a replacement while it remains detached.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: buildChainExecutionDetails(\n\t\t\t\t\t\tmakeDetailsInput({\n\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\tcurrentFlatIndex: dynamicStartIndex + detachedIndexInStep,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst failures = parallelResults\n\t\t\t\t.map((result, originalIndex) => ({ ...result, originalIndex }))\n\t\t\t\t.filter((result) => result.exitCode !== 0 && result.exitCode !== -1);\n\t\t\tif (failures.length > 0) {\n\t\t\t\tconst failureSummary = failures\n\t\t\t\t\t.map(\n\t\t\t\t\t\t(failure) =>\n\t\t\t\t\t\t\t`- Item ${failure.originalIndex + 1} (${failure.agent}, key ${materialized.items[failure.originalIndex]?.key ?? failure.originalIndex}): ${failure.error || \"failed\"}`,\n\t\t\t\t\t)\n\t\t\t\t\t.join(\"\\n\");\n\t\t\t\tconst errorMsg = `Dynamic step ${stepIndex + 1} failed:\\n${failureSummary}`;\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: errorMsg };\n\t\t\t\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"failed\", {\n\t\t\t\t\tindex: stepIndex,\n\t\t\t\t\terror: errorMsg,\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: summary }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: buildChainExecutionDetails(\n\t\t\t\t\t\tmakeDetailsInput({\n\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\tcurrentFlatIndex: dynamicStartIndex + failures[0]!.originalIndex,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst acceptanceFailures = parallelResults\n\t\t\t\t.map((result, originalIndex) => ({\n\t\t\t\t\tresult,\n\t\t\t\t\toriginalIndex,\n\t\t\t\t\ttask: dynamicParallelStep.parallel[originalIndex],\n\t\t\t\t}))\n\t\t\t\t.filter(\n\t\t\t\t\t({ result, task }) =>\n\t\t\t\t\t\tisAgentContractV1(task?.agentContract ?? dynamicParallelStep.agentContract ?? params.agentContract) &&\n\t\t\t\t\t\t(task?.gateOn ?? dynamicParallelStep.gateOn) === \"acceptance\" &&\n\t\t\t\t\t\tresult.acceptance?.status === \"rejected\",\n\t\t\t\t);\n\t\t\tif (acceptanceFailures.length > 0) {\n\t\t\t\tconst acceptanceSummary = acceptanceFailures\n\t\t\t\t\t.map(\n\t\t\t\t\t\t({ result, originalIndex }) =>\n\t\t\t\t\t\t\t`- Item ${originalIndex + 1} (${result.agent}, key ${materialized.items[originalIndex]?.key ?? originalIndex}): ${(result.acceptance ? acceptanceFailureMessage(result.acceptance) : undefined) ?? \"acceptance rejected\"}`,\n\t\t\t\t\t)\n\t\t\t\t\t.join(\"\\n\");\n\t\t\t\tconst errorMsg = `Dynamic step ${stepIndex + 1} acceptance gate failed:\\n${acceptanceSummary}`;\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: errorMsg };\n\t\t\t\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"failed\", {\n\t\t\t\t\tindex: stepIndex,\n\t\t\t\t\terror: errorMsg,\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: summary }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: buildChainExecutionDetails(\n\t\t\t\t\t\tmakeDetailsInput({\n\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\tcurrentFlatIndex: dynamicStartIndex + acceptanceFailures[0]!.originalIndex,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait validateDynamicCollection(step.collect.outputSchema, collected);\n\t\t\t} catch (error) {\n\t\t\t\tconst message =\n\t\t\t\t\terror instanceof DynamicFanoutError\n\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t: error instanceof Error\n\t\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t\t: String(error);\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: message };\n\t\t\t\treturn buildChainExecutionErrorResult(\n\t\t\t\t\tmessage,\n\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: dynamicStartIndex }),\n\t\t\t\t);\n\t\t\t}\n\t\t\toutputs[step.collect.as] = {\n\t\t\t\ttext: JSON.stringify(collected),\n\t\t\t\tstructured: collected,\n\t\t\t\tagent: step.parallel.agent,\n\t\t\t\tstepIndex,\n\t\t\t};\n\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"completed\" };\n\t\t\tconst effectiveGroupAcceptance = resolveEffectiveAcceptance({\n\t\t\t\texplicit: step.acceptance,\n\t\t\t\tagentName: step.parallel.agent,\n\t\t\t\tacceptanceRole: agents.find((agent) => agent.name === step.parallel.agent)?.acceptanceRole,\n\t\t\t\ttask: materialized.parallel\n\t\t\t\t\t.map((task) => (task.task ?? originalTask ?? \"\").replace(/\\{task\\}/g, originalTask ?? \"\"))\n\t\t\t\t\t.join(\"\\n\"),\n\t\t\t\tmode: \"chain\",\n\t\t\t\tdynamicGroup: true,\n\t\t\t\tagentContract: step.agentContract ?? params.agentContract,\n\t\t\t});\n\t\t\tconst groupAcceptance = await evaluateAcceptance({\n\t\t\t\tacceptance: effectiveGroupAcceptance,\n\t\t\t\toutput: \"\",\n\t\t\t\treport: aggregateAcceptanceReport({\n\t\t\t\t\tresults: parallelResults,\n\t\t\t\t\tnotes: `Dynamic fanout collected ${collected.length} result(s) into ${step.collect.as}.`,\n\t\t\t\t}),\n\t\t\t\tcwd: cwd ?? ctx.cwd,\n\t\t\t\treportOptional: isAgentContractV1(step.agentContract ?? params.agentContract),\n\t\t\t});\n\t\t\tconst dynamicGroupStatus = dynamicGroupStatuses[stepIndex];\n\t\t\tif (!dynamicGroupStatus) throw new Error(`Missing dynamic group status at step ${stepIndex}`);\n\t\t\tdynamicGroupStatus.acceptance = groupAcceptance;\n\t\t\tconst groupAcceptanceFailure =\n\t\t\t\teffectiveGroupAcceptance.explicit &&\n\t\t\t\t(!isAgentContractV1(step.agentContract ?? params.agentContract) || step.gateOn === \"acceptance\")\n\t\t\t\t\t? acceptanceFailureMessage(groupAcceptance)\n\t\t\t\t\t: undefined;\n\t\t\tif (groupAcceptanceFailure) {\n\t\t\t\tdynamicGroupStatuses[stepIndex] = {\n\t\t\t\t\tstatus: \"failed\",\n\t\t\t\t\terror: groupAcceptanceFailure,\n\t\t\t\t\tacceptance: groupAcceptance,\n\t\t\t\t};\n\t\t\t\treturn buildChainExecutionErrorResult(\n\t\t\t\t\tgroupAcceptanceFailure,\n\t\t\t\t\tmakeDetailsInput({\n\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\tcurrentFlatIndex: globalTaskIndex - dynamicParallelStep.parallel.length,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst taskResults: ParallelTaskResult[] = parallelResults.map((result, i) => ({\n\t\t\t\tagent: result.agent,\n\t\t\t\ttaskIndex: i,\n\t\t\t\toutput: getSingleResultOutput(result),\n\t\t\t\texitCode: result.exitCode,\n\t\t\t\terror: result.error,\n\t\t\t\ttimedOut: result.timedOut,\n\t\t\t}));\n\t\t\tprev = aggregateParallelOutputs(\n\t\t\t\ttaskResults,\n\t\t\t\t(i, agent) => `=== Dynamic Item ${i + 1} (${agent}, key ${materialized.items[i]?.key ?? i}) ===`,\n\t\t\t);\n\t\t} else {\n\t\t\tconst seqStep = step as SequentialStep;\n\t\t\tconst stepTemplate = stepTemplates as string;\n\n\t\t\tconst agentConfig = agents.find((a) => a.name === seqStep.agent);\n\t\t\tif (!agentConfig) {\n\t\t\t\tremoveChainDir(chainDir);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Unknown agent: ${seqStep.agent}` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: buildChainExecutionDetails(\n\t\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }),\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst tuiOverride = tuiBehaviorOverrides?.[stepIndex];\n\t\t\tconst stepOverride: StepOverrides = {\n\t\t\t\toutput: tuiOverride?.output !== undefined ? tuiOverride.output : seqStep.output,\n\t\t\t\toutputMode: seqStep.outputMode,\n\t\t\t\treads: tuiOverride?.reads !== undefined ? tuiOverride.reads : seqStep.reads,\n\t\t\t\tprogress: tuiOverride?.progress !== undefined ? tuiOverride.progress : seqStep.progress,\n\t\t\t\tskills: tuiOverride?.skills !== undefined ? tuiOverride.skills : normalizeSkillInput(seqStep.skill),\n\t\t\t};\n\t\t\tconst behavior = suppressProgressForReadOnlyTask(\n\t\t\t\tresolveStepBehavior(agentConfig, stepOverride, chainSkills),\n\t\t\t\tstepTemplate,\n\t\t\t\toriginalTask,\n\t\t\t);\n\n\t\t\tconst isFirstProgress = behavior.progress && !progressCreated;\n\t\t\tif (isFirstProgress) {\n\t\t\t\tprogressCreated = true;\n\t\t\t}\n\n\t\t\tconst templateHasPrevious = stepTemplate.includes(\"{previous}\");\n\t\t\tconst { prefix, suffix } = buildChainInstructions(\n\t\t\t\t{ ...behavior, output: false },\n\t\t\t\tchainDir,\n\t\t\t\tisFirstProgress,\n\t\t\t\ttemplateHasPrevious ? undefined : prev,\n\t\t\t);\n\n\t\t\tlet stepTask = resolveOutputReferences(stepTemplate, outputs);\n\t\t\tstepTask = stepTask.replace(/\\{task\\}/g, originalTask);\n\t\t\tstepTask = stepTask.replace(/\\{previous\\}/g, prev);\n\t\t\tstepTask = stepTask.replace(/\\{chain_dir\\}/g, chainDir);\n\t\t\tconst cleanTask = stepTask;\n\t\t\tstepTask = prefix + stepTask + suffix;\n\n\t\t\tconst explicitStepModel = tuiOverride?.model ?? seqStep.model;\n\t\t\tconst effectiveModel = resolveEffectiveSubagentModel(\n\t\t\t\texplicitStepModel,\n\t\t\t\tagentConfig.model,\n\t\t\t\tctx.model,\n\t\t\t\tavailableModels,\n\t\t\t\tctx.model?.provider,\n\t\t\t\t{ scope: modelScope },\n\t\t\t);\n\n\t\t\tconst outputPath =\n\t\t\t\ttypeof behavior.output === \"string\"\n\t\t\t\t\t? path.isAbsolute(behavior.output)\n\t\t\t\t\t\t? behavior.output\n\t\t\t\t\t\t: path.join(chainDir, behavior.output)\n\t\t\t\t\t: undefined;\n\t\t\tstepTask = injectSingleOutputInstruction(stepTask, outputPath, agentConfig);\n\t\t\tconst validationError = validateFileOnlyOutputMode(\n\t\t\t\tbehavior.outputMode,\n\t\t\t\toutputPath,\n\t\t\t\t`Chain step ${stepIndex + 1} (${seqStep.agent})`,\n\t\t\t);\n\t\t\tif (validationError) {\n\t\t\t\treturn buildChainExecutionErrorResult(\n\t\t\t\t\tvalidationError,\n\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }),\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst maxSubagentDepth = resolveChildMaxSubagentDepth(params.maxSubagentDepth, agentConfig.maxSubagentDepth);\n\t\t\tconst childIndex = globalTaskIndex;\n\t\t\tconst interruptController = new AbortController();\n\t\t\tif (foregroundControl) {\n\t\t\t\tconst thinking = resolveEffectiveThinking(\n\t\t\t\t\teffectiveModel,\n\t\t\t\t\tparams.thinkingOverrideForTask?.(seqStep.agent, childIndex, effectiveModel),\n\t\t\t\t);\n\t\t\t\tbeginForegroundChild(foregroundControl, {\n\t\t\t\t\tindex: childIndex,\n\t\t\t\t\tagent: seqStep.agent,\n\t\t\t\t\tdescription: cleanTask.trim(),\n\t\t\t\t\t...(effectiveModel ? { model: effectiveModel } : {}),\n\t\t\t\t\t...(thinking ? { thinking } : {}),\n\t\t\t\t\tinterrupt: () => {\n\t\t\t\t\t\tif (interruptController.signal.aborted) return false;\n\t\t\t\t\t\tinterruptController.abort();\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst agentContract = seqStep.agentContract ?? params.agentContract;\n\t\t\tlet r!: SingleResult;\n\t\t\ttry {\n\t\t\t\tconst structuredRuntime = seqStep.outputSchema\n\t\t\t\t\t? createStructuredOutputRuntime(seqStep.outputSchema, path.join(chainDir, \"structured-output\"))\n\t\t\t\t\t: undefined;\n\t\t\t\tconst toolBudget = resolveChainToolBudget({\n\t\t\t\t\tstepBudget: seqStep.toolBudget,\n\t\t\t\t\trunBudget: params.toolBudget,\n\t\t\t\t\tagentBudget: agentConfig?.toolBudget,\n\t\t\t\t\tconfigBudget: params.configToolBudget,\n\t\t\t\t});\n\t\t\t\tif (toolBudget.error)\n\t\t\t\t\treturn buildChainExecutionErrorResult(toolBudget.error, {\n\t\t\t\t\t\tresults,\n\t\t\t\t\t\tincludeProgress,\n\t\t\t\t\t\tallProgress,\n\t\t\t\t\t\tallArtifactPaths,\n\t\t\t\t\t\tartifactsDir: params.artifactsDir,\n\t\t\t\t\t\tchainAgents,\n\t\t\t\t\t\tchainSteps,\n\t\t\t\t\t\ttotalSteps,\n\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\trunId: params.runId,\n\t\t\t\t\t\toutputs,\n\t\t\t\t\t\tcurrentFlatIndex: globalTaskIndex,\n\t\t\t\t\t\tdynamicChildren,\n\t\t\t\t\t\tdynamicGroupStatuses,\n\t\t\t\t\t});\n\t\t\t\tr = await runSync(ctx.cwd, agents, seqStep.agent, stepTask, {\n\t\t\t\t\tpermissions: params.permissions,\n\t\t\t\t\tparentSessionId: ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\t\t\tcapabilityCeiling: params.capabilityCeiling,\n\t\t\t\t\tcontext: params.contextForAgent?.(seqStep.agent),\n\t\t\t\t\tcwd: resolveChildCwd(cwd ?? ctx.cwd, seqStep.cwd),\n\t\t\t\t\tsignal,\n\t\t\t\t\tinterruptSignal: interruptController.signal,\n\t\t\t\t\tallowIntercomDetach: agentConfig.systemPrompt?.includes(INTERCOM_BRIDGE_MARKER) === true,\n\t\t\t\t\tintercomEvents,\n\t\t\t\t\trunId,\n\t\t\t\t\tindex: childIndex,\n\t\t\t\t\tsessionDir: sessionDirForIndex(childIndex),\n\t\t\t\t\tsessionFile:\n\t\t\t\t\t\tsessionFileForTask?.(seqStep.agent, childIndex, effectiveModel) ?? sessionFileForIndex?.(childIndex),\n\t\t\t\t\tthinkingOverride: thinkingOverrideForTask?.(seqStep.agent, childIndex, effectiveModel),\n\t\t\t\t\tshare: shareEnabled,\n\t\t\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\t\t\tartifactConfig,\n\t\t\t\t\toutputPath,\n\t\t\t\t\toutputMode: behavior.outputMode,\n\t\t\t\t\tmaxSubagentDepth,\n\t\t\t\t\tcontrolConfig,\n\t\t\t\t\tonControlEvent,\n\t\t\t\t\tintercomSessionName: childIntercomTarget?.(seqStep.agent, childIndex),\n\t\t\t\t\torchestratorIntercomTarget,\n\t\t\t\t\tnestedRoute: params.nestedRoute,\n\t\t\t\t\tmodelOverride: effectiveModel,\n\t\t\t\t\tavailableModels,\n\t\t\t\t\tpreferredModelProvider: ctx.model?.provider,\n\t\t\t\t\tmodelScope,\n\t\t\t\t\tskills: behavior.skills === false ? [] : behavior.skills,\n\t\t\t\t\tstructuredOutput: structuredRuntime,\n\t\t\t\t\tagentContract,\n\t\t\t\t\tacceptance: seqStep.acceptance,\n\t\t\t\t\tacceptanceContext: { mode: \"chain\" },\n\t\t\t\t\ttimeoutMs: params.timeoutMs,\n\t\t\t\t\tdeadlineAt,\n\t\t\t\t\tturnBudget: params.turnBudget,\n\t\t\t\t\tonDetachedExit: (result) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (foregroundControl) finishForegroundChild(foregroundControl, childIndex);\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tonDetachedExit?.(childIndex, result);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\ttoolBudget: toolBudget.toolBudget,\n\t\t\t\t\tonUpdate: onUpdate\n\t\t\t\t\t\t? (p) => {\n\t\t\t\t\t\t\t\tconst stepResults = p.details?.results || [];\n\t\t\t\t\t\t\t\tconst stepProgress = p.details?.progress || [];\n\t\t\t\t\t\t\t\tif (foregroundControl && stepProgress.length > 0) {\n\t\t\t\t\t\t\t\t\tupdateForegroundChild(foregroundControl, childIndex, stepProgress[0]);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tonUpdate({\n\t\t\t\t\t\t\t\t\t...p,\n\t\t\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\t\t\t\t\tresults: results.concat(stepResults),\n\t\t\t\t\t\t\t\t\t\tprogress: allProgress.concat(stepProgress),\n\t\t\t\t\t\t\t\t\t\tcontrolEvents: p.details?.controlEvents,\n\t\t\t\t\t\t\t\t\t\tchainAgents,\n\t\t\t\t\t\t\t\t\t\ttotalSteps,\n\t\t\t\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\t\t\t\toutputs,\n\t\t\t\t\t\t\t\t\t\tworkflowGraph: buildWorkflowGraphSnapshot({\n\t\t\t\t\t\t\t\t\t\t\trunId,\n\t\t\t\t\t\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\t\t\t\t\t\tsteps: chainSteps,\n\t\t\t\t\t\t\t\t\t\t\tresults: results.concat(stepResults),\n\t\t\t\t\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\t\t\t\t\tcurrentFlatIndex: childIndex,\n\t\t\t\t\t\t\t\t\t\t\tdynamicChildren,\n\t\t\t\t\t\t\t\t\t\t\tdynamicGroupStatuses,\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined,\n\t\t\t\t});\n\t\t\t} finally {\n\t\t\t\t// Rejected attempts and early validation returns release the child here.\n\t\t\t\t// A detached receipt transfers cleanup ownership to onDetachedExit.\n\t\t\t\tif (!r?.detached) {\n\t\t\t\t\tif (foregroundControl) finishForegroundChild(foregroundControl, childIndex);\n\t\t\t\t\tparams.onForegroundChildSettled?.();\n\t\t\t\t}\n\t\t\t}\n\t\t\trecordRun(seqStep.agent, cleanTask, r.exitCode, r.progressSummary?.durationMs ?? 0);\n\n\t\t\tglobalTaskIndex++;\n\t\t\tresults.push(r);\n\t\t\tif (r.progress) allProgress.push(r.progress);\n\t\t\tif (r.artifactPaths) allArtifactPaths.push(r.artifactPaths);\n\n\t\t\tif (r.interrupted) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: `Chain paused after interrupt at step ${stepIndex + 1} (${r.agent}). Waiting for explicit next action.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: buildChainExecutionDetails(\n\t\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: childIndex }),\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (r.detached) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: `Chain detached for intercom coordination at step ${stepIndex + 1} (${r.agent}). Reply to the supervisor request first, then wait with subagent_wait({ id: \"${runId}\" }). Use subagent({ action: \"status\", id: \"${runId}\" }) to recover the result; do not resume or launch a replacement while it remains detached.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: buildChainExecutionDetails(\n\t\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: childIndex }),\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (r.exitCode !== 0) {\n\t\t\t\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"failed\", {\n\t\t\t\t\tindex: stepIndex,\n\t\t\t\t\terror: r.error || \"Chain failed\",\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: summary }],\n\t\t\t\t\tdetails: buildChainExecutionDetails(\n\t\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: childIndex }),\n\t\t\t\t\t),\n\t\t\t\t\tisError: true,\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (\n\t\t\t\tisAgentContractV1(agentContract) &&\n\t\t\t\tseqStep.gateOn === \"acceptance\" &&\n\t\t\t\tr.acceptance?.status === \"rejected\"\n\t\t\t) {\n\t\t\t\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"failed\", {\n\t\t\t\t\tindex: stepIndex,\n\t\t\t\t\terror: acceptanceFailureMessage(r.acceptance) ?? \"Chain acceptance gate rejected the step.\",\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: summary }],\n\t\t\t\t\tdetails: buildChainExecutionDetails(\n\t\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: childIndex }),\n\t\t\t\t\t),\n\t\t\t\t\tisError: true,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (behavior.output) {\n\t\t\t\ttry {\n\t\t\t\t\tconst expectedPath = path.isAbsolute(behavior.output)\n\t\t\t\t\t\t? behavior.output\n\t\t\t\t\t\t: path.join(chainDir, behavior.output);\n\t\t\t\t\tif (!fs.existsSync(expectedPath)) {\n\t\t\t\t\t\tconst dirFiles = fs.readdirSync(chainDir);\n\t\t\t\t\t\tconst mdFiles = dirFiles.filter((file) => file.endsWith(\".md\") && file !== \"progress.md\");\n\t\t\t\t\t\tconst warning =\n\t\t\t\t\t\t\tmdFiles.length > 0\n\t\t\t\t\t\t\t\t? `Agent wrote to different file(s): ${mdFiles.join(\", \")} instead of ${behavior.output}`\n\t\t\t\t\t\t\t\t: `Agent did not create expected output file: ${behavior.output}`;\n\t\t\t\t\t\tr.error = r.error ? `${r.error}\\n${warning}` : warning;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore validation errors; this diagnostic should not mask successful chain output.\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (seqStep.as) outputs[seqStep.as] = outputEntryFromResult(r, stepIndex);\n\t\t\tprev = getSingleResultOutput(r);\n\t\t}\n\t}\n\n\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"completed\");\n\n\treturn {\n\t\tcontent: [{ type: \"text\", text: summary }],\n\t\tdetails: buildChainExecutionDetails(makeDetailsInput()),\n\t};\n}\n"]}