"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runWorkerCycle = runWorkerCycle;
// biome-ignore lint/nursery/noExcessiveLinesPerFile: Worker staging and nested workflow routing stay together to keep the run control flow auditable.
const control_plane_config_1 = require("../../config/control-plane-config");
const native_git_cli_1 = require("../../git/native-git-cli");
const catalog_1 = require("../../i18n/catalog");
const errors_1 = require("../../worker/errors");
const types_1 = require("../../worker/types");
const workflow_selection_runtime_support_1 = require("../../worker/workflow-selection-runtime-support");
const default_system_workflows_1 = require("../../workflows/default-system-workflows");
const plan_progress_1 = require("../../workflows/plan-progress");
const recurring_1 = require("../../workflows/recurring");
const required_mcp_1 = require("../../workflows/required-mcp");
const required_skills_1 = require("../../workflows/required-skills");
const run_context_1 = require("../../workflows/run-context");
const state_1 = require("../../workflows/state");
const template_bindings_1 = require("../../workflows/template-bindings");
const template_registry_1 = require("../../workflows/template-registry");
const workflow_selection_support_1 = require("../../workflows/workflow-selection-support");
const workflow_template_targets_1 = require("../../workflows/workflow-template-targets");
const log_text_1 = require("../log-text");
const ai_run_accounting_1 = require("./ai-run-accounting");
const preflight_resolution_marker_1 = require("./preflight-resolution-marker");
const preflight_resolution_plans_1 = require("./preflight-resolution-plans");
const required_mcp_gate_1 = require("./required-mcp-gate");
const required_skill_gate_1 = require("./required-skill-gate");
const shared_1 = require("./shared");
const start_approval_review_1 = require("./start-approval-review");
const worker_prompt_artifacts_1 = require("./worker-prompt-artifacts");
const worker_support_1 = require("./worker-support");
const workflow_plan_review_loop_1 = require("./workflow-plan-review-loop");
const workflow_template_root_1 = require("./workflow-template-root");
const WORKFLOW_TEMPLATE_FIT_REVIEW_MAX_COMMENTS = 12;
const WORKFLOW_TEMPLATE_FIT_REVIEW_MAX_COMMENT_CHARS = 4_000;
const WORKFLOW_PLAN_REVIEW_MAX_COMMENTS = 12;
const WORKFLOW_PLAN_REVIEW_MAX_COMMENT_CHARS = 4_000;
async function runWorkerAttemptStage(input) {
    const meta = await input.beforeAttempt();
    await (0, worker_support_1.appendWorkerStartSection)(input.logger, input.workspace, input.preparation, input.execution.runMode);
    let workerResult;
    try {
        workerResult = await runLoggedWorkerAttempt({
            context: input.context,
            logger: input.logger,
            workspace: input.workspace,
            preparation: input.preparation,
            promptIssue: input.promptIssue,
            promptComments: input.promptComments,
            workflow: input.execution.workflow,
            workflowTemplateName: input.execution.workflowTemplateName,
            workflowState: input.execution.workflowState,
            responseLanguage: input.responseLanguage,
        });
    }
    catch (error) {
        return {
            kind: "state",
            state: (0, worker_support_1.handleWorkerAttemptFailure)({
                error: addPriorStepAttemptDurationToFailure(error, input.execution.workerDurationMs),
                preparation: input.preparation,
                workspace: input.workspace,
                nestedPlanningPass: input.nestedPlanningPass,
                responseLanguage: input.responseLanguage,
            }),
        };
    }
    if (workerResult.kind === "deferred") {
        return {
            kind: "state",
            state: (0, worker_support_1.buildDeferredWorkerState)(input.preparation, input.responseLanguage, input.workspace, addPriorStepAttemptDurationToDeferredResult(workerResult, input.execution.workerDurationMs)),
        };
    }
    await (0, worker_support_1.appendWorkerDecisionSections)(input.logger, workerResult);
    return {
        kind: "continue",
        value: {
            workerResult,
            meta,
        },
    };
}
async function runWorkerCycle(context, logger, workspace, preparation) {
    const promptIssue = preparation.promptIssue ?? preparation.latestIssue;
    const promptComments = preparation.promptComments ?? preparation.comments;
    const scannedInputCursor = (0, shared_1.resolvePreparationScannedInputCursor)(preparation);
    const responseLanguage = context.config.i18n.defaultLanguage;
    const nestedPlanningPass = await resolveNestedWorkflowPlanningPass(context, preparation, responseLanguage);
    if (nestedPlanningPass?.kind === "handoff") {
        return (0, worker_support_1.buildQuestionHandoffState)({
            issue: preparation.latestIssue,
            responseLanguage,
            summary: nestedPlanningPass.summary,
            branchName: workspace.branchName,
            workflowTemplateName: preparation.workflowTemplateName,
            workflowState: preparation.workflowState,
        });
    }
    const initialExecution = {
        workflow: nestedPlanningPass?.workflowForWorker ?? preparation.workflow,
        workflowTemplateName: nestedPlanningPass?.workflowTemplateNameForWorker ??
            preparation.workflowTemplateName,
        workflowState: nestedPlanningPass?.workflowStateForWorker ?? preparation.workflowState,
        planningIntent: preparation.planningIntent,
        runMode: (nestedPlanningPass?.workflowForWorker ?? preparation.workflow)
            .mode,
        workerDurationMs: 0,
    };
    const selectionStage = await runWorkflowSelectionStage({
        context,
        logger,
        workspace,
        preparation,
        promptIssue,
        promptComments,
        responseLanguage,
        nestedPlanningPass,
        execution: initialExecution,
    });
    if (selectionStage.kind === "state") {
        return selectionStage.state;
    }
    const stepBatchState = await maybeRunWorkflowStepBatch({
        context,
        logger,
        workspace,
        preparation,
        promptIssue,
        promptComments,
        responseLanguage,
        scannedInputCursor,
        nestedPlanningPass,
        execution: selectionStage.value,
    });
    if (stepBatchState !== null) {
        return stepBatchState;
    }
    const primaryWorkerStage = await runPrimaryWorkerStage({
        context,
        logger,
        workspace,
        preparation,
        promptIssue,
        promptComments,
        responseLanguage,
        nestedPlanningPass,
        execution: selectionStage.value,
    });
    if (primaryWorkerStage.kind === "state") {
        return primaryWorkerStage.state;
    }
    const planReviewStage = await maybeRunWorkflowPlanReviewLoop({
        context,
        logger,
        workspace,
        preparation,
        promptIssue,
        promptComments,
        responseLanguage,
        nestedPlanningPass,
        primaryStage: primaryWorkerStage.value,
    });
    if (planReviewStage.kind === "state") {
        return planReviewStage.state;
    }
    return finalizeWorkerExecutionState({
        preparation,
        workspace,
        responseLanguage,
        scannedInputCursor,
        nestedPlanningPass: nestedPlanningPass?.kind === "continue" ? nestedPlanningPass : null,
        execution: planReviewStage.value.execution,
        workspaceHeadCommitOidBeforeRun: planReviewStage.value.workspaceHeadCommitOidBeforeRun,
        workerResult: planReviewStage.value.workerResult,
    });
}
async function runWorkflowSelectionStage(input) {
    if (input.execution.runMode !== types_1.WORKER_RUN_MODES.workflowSelect) {
        return {
            kind: "continue",
            value: input.execution,
        };
    }
    const selectionStage = await runWorkerAttemptStage({
        context: input.context,
        logger: input.logger,
        workspace: input.workspace,
        preparation: input.preparation,
        promptIssue: input.promptIssue,
        promptComments: input.promptComments,
        responseLanguage: input.responseLanguage,
        nestedPlanningPass: input.nestedPlanningPass,
        execution: input.execution,
        beforeAttempt: () => null,
    });
    if (selectionStage.kind === "state") {
        return selectionStage;
    }
    const selectionDecision = selectionStage.value.workerResult.launchResult.decision;
    if (selectionDecision.outcome !== types_1.WORKER_OUTCOMES.proceed) {
        const totalAiRunHours = (0, ai_run_accounting_1.addAiRunDurationToTotal)(input.preparation.currentTotalAiRunHours, selectionStage.value.workerResult.workerDurationMs);
        return {
            kind: "state",
            state: (0, worker_support_1.buildQuestionHandoffState)({
                issue: input.preparation.latestIssue,
                responseLanguage: input.responseLanguage,
                summary: selectionDecision.result.resultSummary,
                branchName: input.workspace.branchName,
                workflowTemplateName: input.execution.workflowTemplateName,
                workflowState: input.execution.workflowState,
                totalAiRunHours,
            }),
        };
    }
    return resolveWorkflowSelectionProceedStage({
        context: input.context,
        workspace: input.workspace,
        preparation: input.preparation,
        responseLanguage: input.responseLanguage,
        execution: input.execution,
        selectionDecision,
        selectionWorkerDurationMs: selectionStage.value.workerResult.workerDurationMs ?? 0,
    });
}
async function resolveWorkflowSelectionProceedStage(input) {
    const resolvedSelection = (0, workflow_selection_runtime_support_1.resolveWorkerWorkflowSelectionDecision)({
        workflow: input.execution.workflow,
        decision: input.selectionDecision,
    });
    const selectionContext = input.execution.workflow.selection;
    if (selectionContext === undefined || selectionContext === null) {
        throw new Error("Workflow selection decision requires workflow_select context.");
    }
    const selectedWorkerDurationMs = input.execution.workerDurationMs + input.selectionWorkerDurationMs;
    if (resolvedSelection.requestedTemplate) {
        return resolveWorkflowSelectionTemplateRequestStage({
            workspace: input.workspace,
            preparation: input.preparation,
            responseLanguage: input.responseLanguage,
            execution: input.execution,
            selectionContext,
            summary: input.selectionDecision.result.resultSummary,
            workerDurationMs: selectedWorkerDurationMs,
        });
    }
    const selectedWorkflowState = (0, workflow_selection_runtime_support_1.applyWorkerWorkflowSelectionToState)({
        workflowState: input.execution.workflowState,
        workflowSurface: input.execution.workflow.workflowSurface ?? "issue",
        selectionContext,
        selection: resolvedSelection.selection,
    });
    const selectedEffectiveConfig = (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.context.config, selectedWorkflowState);
    const selectedPlanningContext = await (0, run_context_1.resolveWorkflowPlanningContextForSelection)({
        repoRoot: (0, workflow_template_root_1.getWorkflowTemplateRepoRoot)(input.context),
        workflowState: selectedWorkflowState,
        templateName: resolvedSelection.templateName,
        commandContext: input.execution.workflow.commandContext ?? null,
        locale: input.responseLanguage,
        maxNestedWorkflowDepth: input.context.config.maxNestedWorkflowDepth,
        planningIntent: input.preparation.planningIntent ?? "new_plan",
        issueNotesPath: selectedEffectiveConfig.paths.issueNotes,
        workflowStartApprovalMode: (0, control_plane_config_1.resolveWorkflowStartApprovalModeForPlanningIntent)({
            target: input.preparation.latestIssue.kind === "pull_request"
                ? "pull_request"
                : "issue",
            planningIntent: input.preparation.planningIntent ?? "new_plan",
            startApprovalIntent: selectedWorkflowState.pendingWorkflowStartApprovalIntent ??
                input.preparation.workflowState
                    ?.pendingWorkflowStartApprovalIntent ??
                null,
            config: selectedEffectiveConfig,
        }),
        workflowSurface: selectedWorkflowState.workflowSurface,
    });
    if (selectedPlanningContext.kind === "handoff") {
        return {
            kind: "state",
            state: (0, worker_support_1.buildQuestionHandoffState)({
                issue: input.preparation.latestIssue,
                responseLanguage: input.responseLanguage,
                summary: selectedPlanningContext.summary,
                branchName: input.workspace.branchName,
                workflowTemplateName: selectedPlanningContext.workflowTemplateName,
                workflowState: selectedPlanningContext.workflowState,
            }),
        };
    }
    if (selectedPlanningContext.kind !== "plan") {
        throw new Error("Selection planning must resolve to a plan route");
    }
    const planningIntentAfterSelection = input.execution.planningIntent === "replan"
        ? input.execution.planningIntent
        : resolvePlanningIntentAfterSelection(input.preparation.workflowState, selectedPlanningContext.workflowState);
    let workerDurationMsAfterFitReview = selectedWorkerDurationMs;
    const workflowTemplateFitReviewResolution = await resolveWorkflowTemplateFitReviewState({
        context: input.context,
        preparation: input.preparation,
        workspace: input.workspace,
        responseLanguage: input.responseLanguage,
        selectedPlanningContext,
        selectionContext,
        preSelectionWorkflowState: input.execution.workflowState,
        workerDurationMs: selectedWorkerDurationMs,
        planningIntent: planningIntentAfterSelection,
    });
    if (workflowTemplateFitReviewResolution?.kind === "state") {
        return {
            kind: "state",
            state: workflowTemplateFitReviewResolution.state,
        };
    }
    if (workflowTemplateFitReviewResolution?.kind === "continue") {
        workerDurationMsAfterFitReview =
            workflowTemplateFitReviewResolution.workerDurationMs;
    }
    const postSelectionRequiredCapabilityState = await resolvePostSelectionRequiredCapabilityState({
        context: input.context,
        preparation: input.preparation,
        workspace: input.workspace,
        responseLanguage: input.responseLanguage,
        selectedPlanningContext,
        workerDurationMs: workerDurationMsAfterFitReview,
        planningIntent: planningIntentAfterSelection,
    });
    if (postSelectionRequiredCapabilityState !== null) {
        return {
            kind: "state",
            state: postSelectionRequiredCapabilityState,
        };
    }
    return {
        kind: "continue",
        value: {
            workflow: selectedPlanningContext.workflow,
            workflowTemplateName: selectedPlanningContext.workflowTemplateName,
            workflowState: selectedPlanningContext.workflowState,
            runMode: selectedPlanningContext.workflow.mode,
            workerDurationMs: workerDurationMsAfterFitReview,
            planningIntent: planningIntentAfterSelection,
        },
    };
}
function resolveWorkflowSelectionTemplateRequestStage(input) {
    if (!shouldCreateWorkflowSelectionMissingTemplatePreflight({
        preparation: input.preparation,
        execution: input.execution,
    })) {
        const totalAiRunHours = (0, ai_run_accounting_1.addAiRunDurationToTotal)(input.preparation.currentTotalAiRunHours, input.workerDurationMs);
        return {
            kind: "state",
            state: (0, worker_support_1.buildQuestionHandoffState)({
                issue: input.preparation.latestIssue,
                responseLanguage: input.responseLanguage,
                summary: input.summary,
                branchName: input.workspace.branchName,
                workflowTemplateName: input.execution.workflowTemplateName,
                workflowState: input.execution.workflowState,
                totalAiRunHours,
            }),
        };
    }
    return {
        kind: "state",
        state: buildWorkflowSelectionMissingTemplatePreflightState(input),
    };
}
function shouldCreateWorkflowSelectionMissingTemplatePreflight(input) {
    if ((0, preflight_resolution_marker_1.isPreflightResolutionIssue)(input.preparation.latestIssue)) {
        return false;
    }
    if (input.preparation.linkedIssue !== undefined &&
        input.preparation.linkedIssue !== null &&
        (0, preflight_resolution_marker_1.isPreflightResolutionIssue)(input.preparation.linkedIssue)) {
        return false;
    }
    if ((0, plan_progress_1.hasControllerChildIssueControlPlaneAction)(input.execution.workflowState)) {
        return false;
    }
    if ((0, recurring_1.isRecurringParentWorkflowState)(input.execution.workflowState)) {
        return false;
    }
    return true;
}
function buildWorkflowSelectionMissingTemplatePreflightState(input) {
    const totalAiRunHours = (0, ai_run_accounting_1.addAiRunDurationToTotal)(input.preparation.currentTotalAiRunHours, input.workerDurationMs);
    const target = input.selectionContext.workflowSurface ??
        input.execution.workflow.workflowSurface ??
        "issue";
    const summary = input.summary.trim().length > 0
        ? input.summary
        : (0, catalog_1.translate)(input.responseLanguage, "run.preflight.missingWorkflow.summary", { target });
    return {
        kind: "preflight_resolution_required",
        preparation: {
            kind: "preflight_resolution_required",
            latestIssue: input.preparation.latestIssue,
            comments: input.preparation.comments,
            ...(input.preparation.promptIssue === undefined
                ? {}
                : { promptIssue: input.preparation.promptIssue }),
            ...(input.preparation.promptComments === undefined
                ? {}
                : { promptComments: input.preparation.promptComments }),
            ...(input.preparation.linkedIssue === undefined
                ? {}
                : { linkedIssue: input.preparation.linkedIssue }),
            currentConsecutiveAiRuns: input.preparation.currentConsecutiveAiRuns,
            currentTotalAiRunHours: totalAiRunHours,
            workflow: input.execution.workflow,
            workflowTemplateName: input.execution.workflowTemplateName,
            workflowState: input.execution.workflowState,
            planningIntent: input.execution.planningIntent,
            needsHumanReason: null,
            continuationContext: input.preparation.continuationContext,
            summary,
            resolution: (0, preflight_resolution_plans_1.buildMissingWorkflowTemplatePreflightResolution)({
                parentIssue: input.preparation.latestIssue,
                target,
                summary,
                locale: input.responseLanguage,
            }),
        },
    };
}
async function resolveWorkflowTemplateFitReviewState(input) {
    if (!shouldRunWorkflowTemplateFitReview(input)) {
        return null;
    }
    const templateName = input.selectedPlanningContext.workflowTemplateName;
    if (templateName === null) {
        return null;
    }
    const workflowSurface = input.selectedPlanningContext.workflow.workflowSurface ?? "issue";
    if (!(0, template_bindings_1.isWorkflowTemplateBindingSurface)(workflowSurface)) {
        return null;
    }
    let reviewResult;
    try {
        reviewResult = await input.context.worker.runWorkflowTemplateFitReview(await buildWorkflowTemplateFitReviewInput({
            context: input.context,
            preparation: input.preparation,
            responseLanguage: input.responseLanguage,
            workflowSurface,
            selectedTemplateName: templateName,
        }));
    }
    catch (error) {
        return {
            kind: "state",
            state: (0, worker_support_1.handleWorkerAttemptFailure)({
                error: addPriorStepAttemptDurationToFailure(error, input.workerDurationMs),
                preparation: input.preparation,
                workspace: input.workspace,
                nestedPlanningPass: null,
                responseLanguage: input.responseLanguage,
            }),
        };
    }
    if (reviewResult.kind === "deferred") {
        return {
            kind: "state",
            state: (0, worker_support_1.buildDeferredWorkerState)(input.preparation, input.responseLanguage, input.workspace, addPriorStepAttemptDurationToDeferredResult(reviewResult, input.workerDurationMs)),
        };
    }
    const review = reviewResult.launchResult.review;
    if (review.action === types_1.WORKER_WORKFLOW_TEMPLATE_FIT_REVIEW_ACTIONS.useSelected) {
        return {
            kind: "continue",
            workerDurationMs: input.workerDurationMs + (reviewResult.workerDurationMs ?? 0),
        };
    }
    return {
        kind: "state",
        state: buildWorkflowTemplateFitPreflightState({
            ...input,
            workerDurationMs: input.workerDurationMs + (reviewResult.workerDurationMs ?? 0),
            review,
        }),
    };
}
function shouldRunWorkflowTemplateFitReview(input) {
    if ((0, preflight_resolution_marker_1.isPreflightResolutionIssue)(input.preparation.latestIssue)) {
        return false;
    }
    if (input.preparation.linkedIssue !== undefined &&
        input.preparation.linkedIssue !== null &&
        (0, preflight_resolution_marker_1.isPreflightResolutionIssue)(input.preparation.linkedIssue)) {
        return false;
    }
    const templateSlot = input.selectionContext.templateSlot;
    return ((templateSlot === "auto" || templateSlot === "auto_select") &&
        input.selectionContext.explicitTemplateName == null &&
        input.selectedPlanningContext.workflowTemplateName !== null &&
        !(0, default_system_workflows_1.isDefaultSystemWorkflowTemplatePath)(input.selectedPlanningContext.workflowTemplateName));
}
async function buildWorkflowTemplateFitReviewInput(input) {
    const repoRoot = (0, workflow_template_root_1.getWorkflowTemplateRepoRoot)(input.context);
    const catalog = await (0, template_registry_1.loadWorkflowTemplates)((0, template_registry_1.getWorkflowTemplatesDirectoryPath)(repoRoot), input.responseLanguage);
    const selectedTemplate = catalog.templateByPath.get(input.selectedTemplateName);
    if (selectedTemplate === undefined) {
        throw new Error(`Selected workflow template ${input.selectedTemplateName} was not found for fit review.`);
    }
    const promptIssue = input.preparation.promptIssue ?? input.preparation.latestIssue;
    const linkedIssue = input.preparation.linkedIssue ?? null;
    const candidateTemplates = catalog.templates
        .filter((template) => !template.system &&
        (template.autoSelect ?? true) !== false &&
        (0, workflow_template_targets_1.resolveWorkflowTemplateRecordTargets)(template).includes(input.workflowSurface))
        .map(toWorkerTemplateCatalogEntry);
    const capabilityAvailability = await buildFitReviewCapabilityAvailability({
        repoRoot,
        workers: (0, control_plane_config_1.getConfiguredWorkerProviders)(input.context.config),
        selectedTemplate,
        candidateTemplates,
        outputLanguage: input.responseLanguage,
    });
    return {
        issue: toWorkerWorkflowTemplateFitIssue(input.preparation.latestIssue),
        latestComments: toWorkerWorkflowTemplateFitComments(input.preparation.comments),
        promptIssue: promptIssue.id === input.preparation.latestIssue.id
            ? null
            : toWorkerWorkflowTemplateFitIssue(promptIssue),
        promptComments: toWorkerWorkflowTemplateFitComments(input.preparation.promptComments ?? input.preparation.comments),
        linkedIssue: linkedIssue === null
            ? null
            : toWorkerWorkflowTemplateFitIssue(linkedIssue),
        workflowSurface: input.workflowSurface,
        selectedTemplate: toWorkerWorkflowTemplateFitTemplate(selectedTemplate),
        candidateTemplates,
        capabilityAvailability,
        outputLanguage: input.responseLanguage,
        workspacePath: input.context.cwd,
        repositoryRoot: repoRoot,
    };
}
async function buildFitReviewCapabilityAvailability(input) {
    const requiredSkills = [
        ...(input.selectedTemplate.metadata?.requiredSkills ?? []),
        ...input.candidateTemplates.flatMap((template) => template.requiredSkills),
    ];
    const requiredMcp = [
        ...(input.selectedTemplate.metadata?.requiredMcp ?? []),
        ...input.candidateTemplates.flatMap((template) => template.requiredMcp),
    ];
    const skillReport = await (0, required_skills_1.checkRequiredSkillAvailability)({
        repoRoot: input.repoRoot,
        workers: input.workers,
        skillRefs: requiredSkills,
    });
    const mcpReport = await (0, required_mcp_1.checkRequiredMcpAvailability)({
        repoRoot: input.repoRoot,
        workers: input.workers,
        mcpRefs: requiredMcp,
    });
    return {
        skills: (0, required_skills_1.formatRequiredSkillAvailabilityReport)({
            report: skillReport,
            locale: input.outputLanguage,
        }),
        mcp: (0, required_mcp_1.formatRequiredMcpAvailabilityReport)({
            report: mcpReport,
            locale: input.outputLanguage,
        }),
    };
}
function toWorkerWorkflowTemplateFitIssue(issue) {
    return {
        title: issue.title,
        body: issue.body,
    };
}
function toWorkerWorkflowTemplateFitComments(comments) {
    return comments
        .slice(-WORKFLOW_TEMPLATE_FIT_REVIEW_MAX_COMMENTS)
        .map((comment) => ({
        author: comment.author,
        createdAt: comment.createdAt,
        body: comment.body.length > WORKFLOW_TEMPLATE_FIT_REVIEW_MAX_COMMENT_CHARS
            ? `${comment.body.slice(0, WORKFLOW_TEMPLATE_FIT_REVIEW_MAX_COMMENT_CHARS)}\n[truncated]`
            : comment.body,
    }));
}
function toWorkerWorkflowTemplateFitTemplate(template) {
    return {
        path: template.templatePath,
        description: template.metadata?.description ?? null,
        requiredSkills: template.metadata?.requiredSkills ?? [],
        requiredMcp: template.metadata?.requiredMcp ?? [],
        targets: (0, workflow_template_targets_1.resolveWorkflowTemplateRecordTargets)(template),
        autoSelect: template.autoSelect ?? true,
        body: template.body,
        digest: template.digest,
    };
}
function toWorkerTemplateCatalogEntry(template) {
    return {
        path: template.templatePath,
        description: template.metadata?.description ?? null,
        requiredSkills: template.metadata?.requiredSkills ?? [],
        requiredMcp: template.metadata?.requiredMcp ?? [],
        targets: (0, workflow_template_targets_1.resolveWorkflowTemplateRecordTargets)(template),
        autoSelect: template.autoSelect ?? true,
        body: template.body,
    };
}
function buildWorkflowTemplateFitPreflightState(input) {
    const totalAiRunHours = (0, ai_run_accounting_1.addAiRunDurationToTotal)(input.preparation.currentTotalAiRunHours, input.workerDurationMs);
    const templateName = input.selectedPlanningContext.workflowTemplateName;
    if (templateName === null || input.review.recommendedPrompt === null) {
        throw new Error("Workflow template fit preflight requires a template and prompt.");
    }
    const selectedTemplate = input.selectedPlanningContext.workflow;
    const selectedTemplateBinding = (0, template_bindings_1.getActiveWorkflowTemplateBinding)(input.selectedPlanningContext.workflowState);
    const selectedTemplateDigest = selectedTemplateBinding?.resolution.kind === "template"
        ? selectedTemplateBinding.resolution.digest
        : "unknown";
    const summary = (0, catalog_1.translate)(input.responseLanguage, "run.preflight.workflowFit.summary", {
        template: templateName,
        reason: input.review.reason,
    });
    return {
        kind: "preflight_resolution_required",
        preparation: {
            kind: "preflight_resolution_required",
            latestIssue: input.preparation.latestIssue,
            comments: input.preparation.comments,
            ...(input.preparation.promptIssue === undefined
                ? {}
                : { promptIssue: input.preparation.promptIssue }),
            ...(input.preparation.promptComments === undefined
                ? {}
                : { promptComments: input.preparation.promptComments }),
            ...(input.preparation.linkedIssue === undefined
                ? {}
                : { linkedIssue: input.preparation.linkedIssue }),
            currentConsecutiveAiRuns: input.preparation.currentConsecutiveAiRuns,
            currentTotalAiRunHours: totalAiRunHours,
            workflow: selectedTemplate,
            workflowTemplateName: templateName,
            workflowState: input.preSelectionWorkflowState,
            planningIntent: input.planningIntent,
            needsHumanReason: null,
            continuationContext: input.preparation.continuationContext,
            summary,
            resolution: (0, preflight_resolution_plans_1.buildWorkflowTemplateFitPreflightResolution)({
                parentIssue: input.preparation.latestIssue,
                workflowSurface: selectedTemplate.workflowSurface ?? "issue",
                action: input.review.action ===
                    types_1.WORKER_WORKFLOW_TEMPLATE_FIT_REVIEW_ACTIONS.createNew
                    ? "create_new"
                    : "update_selected",
                selectedTemplatePath: templateName,
                selectedTemplateDigest,
                selectedTemplateBody: selectedTemplate.templateBody ?? "",
                reason: input.review.reason,
                evidence: input.review.evidence,
                recommendedPrompt: input.review.recommendedPrompt,
                summary,
                locale: input.responseLanguage,
            }),
        },
    };
}
async function resolvePostSelectionRequiredCapabilityState(input) {
    const effectiveConfig = (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.context.config, input.selectedPlanningContext.workflowState);
    const requiredSkillGate = await (0, required_skill_gate_1.resolveRequiredSkillPreWorkerGate)({
        repoRoot: (0, workflow_template_root_1.getWorkflowTemplateRepoRoot)(input.context),
        effectiveConfig,
        issue: input.preparation.latestIssue,
        linkedIssue: input.preparation.linkedIssue ?? null,
        workflow: input.selectedPlanningContext.workflow,
        workflowTemplateName: input.selectedPlanningContext.workflowTemplateName,
    });
    if (requiredSkillGate !== null) {
        return buildPostSelectionRequiredGateState(input, requiredSkillGate);
    }
    const requiredMcpGate = await (0, required_mcp_gate_1.resolveRequiredMcpPreWorkerGate)({
        repoRoot: (0, workflow_template_root_1.getWorkflowTemplateRepoRoot)(input.context),
        effectiveConfig,
        issue: input.preparation.latestIssue,
        linkedIssue: input.preparation.linkedIssue ?? null,
        workflow: input.selectedPlanningContext.workflow,
        workflowTemplateName: input.selectedPlanningContext.workflowTemplateName,
    });
    if (requiredMcpGate !== null) {
        return buildPostSelectionRequiredGateState(input, requiredMcpGate);
    }
    return null;
}
function buildPostSelectionRequiredGateState(input, gate) {
    const totalAiRunHours = (0, ai_run_accounting_1.addAiRunDurationToTotal)(input.preparation.currentTotalAiRunHours, input.workerDurationMs);
    if (gate.kind === "handoff") {
        return (0, worker_support_1.buildQuestionHandoffState)({
            issue: input.preparation.latestIssue,
            responseLanguage: input.responseLanguage,
            summary: gate.summary,
            branchName: input.workspace.branchName,
            workflowTemplateName: input.selectedPlanningContext.workflowTemplateName,
            workflowState: input.selectedPlanningContext.workflowState,
            totalAiRunHours,
        });
    }
    return {
        kind: "preflight_resolution_required",
        preparation: {
            kind: "preflight_resolution_required",
            latestIssue: input.preparation.latestIssue,
            comments: input.preparation.comments,
            ...(input.preparation.promptIssue === undefined
                ? {}
                : { promptIssue: input.preparation.promptIssue }),
            ...(input.preparation.promptComments === undefined
                ? {}
                : { promptComments: input.preparation.promptComments }),
            ...(input.preparation.linkedIssue === undefined
                ? {}
                : { linkedIssue: input.preparation.linkedIssue }),
            currentConsecutiveAiRuns: input.preparation.currentConsecutiveAiRuns,
            currentTotalAiRunHours: totalAiRunHours,
            workflow: input.selectedPlanningContext.workflow,
            workflowTemplateName: input.selectedPlanningContext.workflowTemplateName,
            workflowState: input.selectedPlanningContext.workflowState,
            planningIntent: input.planningIntent,
            needsHumanReason: null,
            continuationContext: input.preparation.continuationContext,
            summary: gate.summary,
            resolution: gate.resolution,
        },
    };
}
async function maybeRunWorkflowStepBatch(input) {
    if (input.nestedPlanningPass !== null ||
        input.execution.runMode !== types_1.WORKER_RUN_MODES.workflowExecute ||
        input.execution.workflowState?.plan === null ||
        input.execution.workflowState === null) {
        return null;
    }
    const workerSlotBudget = input.context.workerSlotBudget ?? 1;
    if (workerSlotBudget < 2) {
        return null;
    }
    const stepBatch = (0, plan_progress_1.selectReadyTaskStepBatch)(input.execution.workflowState.plan, workerSlotBudget);
    if (stepBatch.length < 2) {
        return null;
    }
    const preBatchHead = await input.context.gitRepository.getHeadCommitOid(input.workspace.path);
    const stepAttemptResolutions = await Promise.all(stepBatch.map((step) => runStepWorkerAttempt({ ...input, step })));
    const stepAttempts = stepAttemptResolutions.flatMap((resolution) => resolution.kind === "success" ? [resolution.attempt] : []);
    const incompleteStepAttempts = stepAttemptResolutions.filter(isIncompleteStepAttemptResolution);
    await appendStepWorkerAttemptLogs(input.logger, stepAttempts);
    const completedWorkerDurationMs = input.execution.workerDurationMs +
        sumStepAttemptResolutionDurations(stepAttemptResolutions);
    const firstIncompleteStepAttempt = incompleteStepAttempts[0];
    if (firstIncompleteStepAttempt?.kind === "deferred") {
        await appendStepWorkerOutputLogs(input.logger, incompleteStepAttempts);
        return (0, worker_support_1.buildDeferredWorkerState)(input.preparation, input.responseLanguage, input.workspace, addPriorStepAttemptDurationToDeferredResult(firstIncompleteStepAttempt.workerResult, completedWorkerDurationMs -
            readStepAttemptResolutionDuration(firstIncompleteStepAttempt)));
    }
    if (firstIncompleteStepAttempt?.kind === "failure") {
        await appendStepWorkerOutputLogs(input.logger, incompleteStepAttempts);
        return (0, worker_support_1.handleWorkerAttemptFailure)({
            error: addPriorStepAttemptDurationToFailure(firstIncompleteStepAttempt.error, completedWorkerDurationMs -
                readStepAttemptResolutionDuration(firstIncompleteStepAttempt)),
            preparation: input.preparation,
            workspace: input.workspace,
            nestedPlanningPass: null,
            responseLanguage: input.responseLanguage,
        });
    }
    const reconciliationWorkflow = await buildStepBatchReconciliationWorkflow({
        workspace: input.workspace,
        execution: input.execution,
        stepBatch,
        stepAttempts,
        preBatchHead,
    });
    const reconciliationStage = await runWorkerAttemptStage({
        context: input.context,
        logger: input.logger,
        workspace: input.workspace,
        preparation: input.preparation,
        promptIssue: input.promptIssue,
        promptComments: input.promptComments,
        responseLanguage: input.responseLanguage,
        nestedPlanningPass: null,
        execution: {
            ...input.execution,
            workflow: reconciliationWorkflow,
            runMode: types_1.WORKER_RUN_MODES.workflowReconcileStepBatch,
            workerDurationMs: completedWorkerDurationMs,
        },
        beforeAttempt: () => preBatchHead,
    });
    if (reconciliationStage.kind === "state") {
        return reconciliationStage.state;
    }
    const resolvedWorkflow = (0, state_1.resolveWorkerExecutionWorkflow)({
        workflow: reconciliationWorkflow,
        workflowTemplateName: input.execution.workflowTemplateName,
        workflowState: input.execution.workflowState,
    }, reconciliationStage.value.workerResult.launchResult.decision, input.responseLanguage);
    return {
        kind: "completed",
        workerExecution: (0, worker_support_1.buildWorkerExecutionState)(input.preparation.latestIssue, {
            ...buildWorkerExecutionIdentity(reconciliationStage.value.workerResult),
            workerDurationMs: completedWorkerDurationMs +
                (reconciliationStage.value.workerResult.workerDurationMs ?? 0),
            workspaceHeadCommitOidBeforeRun: preBatchHead,
            decision: reconciliationStage.value.workerResult.launchResult.decision,
        }, input.preparation.currentConsecutiveAiRuns + 1, input.responseLanguage, {
            facts: shared_1.EMPTY_FACTS,
            pullRequestUrl: null,
            pullRequestThreadId: null,
        }, input.scannedInputCursor, input.workspace.branchName, types_1.WORKER_RUN_MODES.workflowExecute, resolvedWorkflow.workflowTemplateName, resolvedWorkflow.workflowState, input.execution.planningIntent, {
            mergeContext: input.execution.workflow.mergeContext ?? null,
            startedWithPlanningIntent: input.preparation.workflowState?.pendingPlanningIntent ?? null,
            startedWithWorkflowStartApprovalIntent: input.preparation.workflowState?.pendingWorkflowStartApprovalIntent ??
                null,
        }),
    };
}
function isIncompleteStepAttemptResolution(resolution) {
    return resolution.kind !== "success";
}
function sumStepAttemptResolutionDurations(resolutions) {
    return resolutions.reduce((total, resolution) => total + readStepAttemptResolutionDuration(resolution), 0);
}
function readStepAttemptResolutionDuration(resolution) {
    switch (resolution.kind) {
        case "success":
            return resolution.attempt.workerResult.workerDurationMs ?? 0;
        case "deferred":
            return resolution.workerResult.workerDurationMs;
        case "failure":
            return (0, errors_1.readWorkerFailureDurationMs)(resolution.error);
    }
}
function addPriorStepAttemptDurationToDeferredResult(workerResult, additionalDurationMs) {
    if (additionalDurationMs <= 0) {
        return workerResult;
    }
    return {
        ...workerResult,
        attemptedWorkerExecution: true,
        workerDurationMs: workerResult.workerDurationMs + additionalDurationMs,
    };
}
function addPriorStepAttemptDurationToFailure(error, additionalDurationMs) {
    if (additionalDurationMs <= 0) {
        return error;
    }
    if ((0, errors_1.isWorkerFailureError)(error)) {
        error.attempted = true;
        error.workerDurationMs += additionalDurationMs;
        return error;
    }
    return new errors_1.WorkerExecutionError(error instanceof Error ? error.message : String(error), {
        attempted: true,
        workerDurationMs: additionalDurationMs,
        ...(error instanceof Error ? { cause: error } : {}),
    });
}
async function runStepWorkerAttempt(input) {
    let stdout = "";
    let stderr = "";
    const workflow = {
        ...input.execution.workflow,
        currentStepId: input.step.id,
        parallelExecution: {
            sharedWorkspace: true,
            otherWorkersActive: true,
        },
    };
    let workerResult;
    try {
        workerResult = await input.context.worker.run({
            issue: input.promptIssue,
            comments: input.promptComments,
            responseLanguage: input.responseLanguage,
            workspacePath: input.workspace.path,
            repositoryRoot: input.workspace.path,
            workflow,
            continuationContext: input.preparation.continuationContext,
            onStdoutChunk(chunk) {
                stdout += chunk;
            },
            onStderrChunk(chunk) {
                stderr += chunk;
            },
        });
    }
    catch (error) {
        return {
            kind: "failure",
            step: input.step,
            error,
            stdout,
            stderr,
        };
    }
    if (workerResult.kind !== "success") {
        return {
            kind: "deferred",
            step: input.step,
            workerResult,
            stdout,
            stderr,
        };
    }
    return {
        kind: "success",
        attempt: {
            step: input.step,
            workerResult,
            stdout,
            stderr,
        },
    };
}
async function appendStepWorkerAttemptLogs(logger, attempts) {
    for (const attempt of attempts) {
        await appendStepWorkerOutputLogs(logger, [attempt]);
        await (0, worker_support_1.appendWorkerDecisionSections)(logger, attempt.workerResult);
    }
    await logger.flush();
}
async function appendStepWorkerOutputLogs(logger, attempts) {
    for (const attempt of attempts) {
        await logger.appendText(`\n--- ${(0, log_text_1.issueLogSection)("workerStdout")} (${attempt.step.id}) ---\n`);
        await logger.appendText(attempt.stdout);
        await logger.appendText(`\n--- ${(0, log_text_1.issueLogSection)("workerStderr")} (${attempt.step.id}) ---\n`);
        await logger.appendText(attempt.stderr);
    }
    await logger.flush();
}
async function buildStepBatchReconciliationWorkflow(input) {
    const [gitStatus, diff] = await Promise.all([
        readGitOutput(input.workspace.path, ["status", "--short"]),
        readBatchDiff(input.workspace.path, input.preBatchHead),
    ]);
    return {
        ...input.execution.workflow,
        mode: types_1.WORKER_RUN_MODES.workflowReconcileStepBatch,
        currentStepId: null,
        parallelExecution: null,
        stepBatchReconciliation: {
            steps: input.stepBatch.map((step) => ({
                id: step.id,
                kind: step.kind,
                title: step.title,
                objective: step.objective,
                instructions: step.instructions,
                doneWhen: step.doneWhen,
            })),
            remainingIncompleteSteps: buildRemainingIncompleteStepBatchContext(input.execution.workflow.state?.plan?.steps ?? [], input.stepBatch),
            workerResults: input.stepAttempts.map(toWorkerStepAttemptSummary),
            preBatchHead: input.preBatchHead,
            gitStatus: (0, worker_prompt_artifacts_1.truncatePromptTextArtifact)(gitStatus, worker_prompt_artifacts_1.WORKER_PROMPT_ARTIFACT_LIMITS.gitStatusCharacters),
            diff: (0, worker_prompt_artifacts_1.truncatePromptDiffArtifact)(diff),
        },
    };
}
function buildRemainingIncompleteStepBatchContext(steps, stepBatch) {
    const batchStepIds = new Set(stepBatch.map((step) => step.id));
    return steps
        .filter((step) => !batchStepIds.has(step.id) && !(0, plan_progress_1.isWorkflowStepDone)(step))
        .map((step) => ({
        id: step.id,
        kind: step.kind,
        title: step.title,
        dependsOnStepIds: step.dependsOnStepIds,
    }));
}
function toWorkerStepAttemptSummary(attempt) {
    const decision = attempt.workerResult.launchResult.decision;
    return {
        stepId: attempt.step.id,
        outcome: decision.outcome,
        result: decision.result,
        commitMessage: decision.commitMessage ?? null,
        continuation: decision.continuation ?? null,
        stdout: (0, worker_prompt_artifacts_1.truncatePromptTextArtifact)(attempt.stdout, worker_prompt_artifacts_1.WORKER_PROMPT_ARTIFACT_LIMITS.stdoutCharacters),
        stderr: (0, worker_prompt_artifacts_1.truncatePromptTextArtifact)(attempt.stderr, worker_prompt_artifacts_1.WORKER_PROMPT_ARTIFACT_LIMITS.stderrCharacters),
    };
}
async function readBatchDiff(workspacePath, preBatchHead) {
    const [trackedDiff, untrackedDiffs] = await Promise.all([
        readGitOutput(workspacePath, ["diff", preBatchHead, "--"]),
        readUntrackedFileDiffs(workspacePath),
    ]);
    return [trackedDiff, ...untrackedDiffs]
        .filter((text) => text.trim().length > 0)
        .join("\n\n");
}
async function readUntrackedFileDiffs(workspacePath) {
    const result = await (0, native_git_cli_1.runNativeGitCommand)({
        args: ["ls-files", "--others", "--exclude-standard"],
        cwd: workspacePath,
        allowNonZeroExit: true,
    });
    if (result.exitCode !== 0) {
        return [];
    }
    const files = result.stdout
        .split(/\r?\n/u)
        .map((line) => line.trim())
        .filter((line) => line.length > 0);
    return Promise.all(files.map((file) => readGitOutput(workspacePath, [
        "diff",
        "--no-index",
        "--",
        "/dev/null",
        file,
    ])));
}
async function readGitOutput(workspacePath, args) {
    const result = await (0, native_git_cli_1.runNativeGitCommand)({
        args: [...args],
        cwd: workspacePath,
        allowNonZeroExit: true,
    });
    return [result.stdout.trim(), result.stderr.trim()]
        .filter((text) => text.length > 0)
        .join("\n");
}
async function runPrimaryWorkerStage(input) {
    const execution = withCurrentWorkflowStep(input.execution);
    const workerStage = await runWorkerAttemptStage({
        context: input.context,
        logger: input.logger,
        workspace: input.workspace,
        preparation: input.preparation,
        promptIssue: input.promptIssue,
        promptComments: input.promptComments,
        responseLanguage: input.responseLanguage,
        nestedPlanningPass: input.nestedPlanningPass,
        execution,
        beforeAttempt: () => input.context.gitRepository.getHeadCommitOid(input.workspace.path),
    });
    if (workerStage.kind === "state") {
        return workerStage;
    }
    return {
        kind: "continue",
        value: {
            execution,
            workspaceHeadCommitOidBeforeRun: workerStage.value.meta,
            workerResult: workerStage.value.workerResult,
        },
    };
}
function withCurrentWorkflowStep(execution) {
    if (execution.runMode !== types_1.WORKER_RUN_MODES.workflowExecute ||
        execution.workflow.currentStepId !== undefined ||
        execution.workflowState?.plan === null ||
        execution.workflowState === null) {
        return execution;
    }
    const currentStep = (0, plan_progress_1.selectReadyTaskStepBatch)(execution.workflowState.plan, 1)[0];
    if (currentStep === undefined) {
        return execution;
    }
    return {
        ...execution,
        workflow: {
            ...execution.workflow,
            currentStepId: currentStep.id,
            parallelExecution: null,
        },
    };
}
async function maybeRunWorkflowPlanReviewLoop(input) {
    if (!shouldRunWorkflowPlanReview(input)) {
        return { kind: "continue", value: input.primaryStage };
    }
    return (0, workflow_plan_review_loop_1.runWorkflowPlanReviewLoop)({
        initialStage: input.primaryStage,
        responseLanguage: input.responseLanguage,
        maxRevisions: input.context.config.autoReviews.plan.maxRevisions,
        runReview: ({ candidate, planningIntent, priorWorkerDurationMs }) => runWorkflowPlanReviewAttempt({
            context: input.context,
            workspace: input.workspace,
            preparation: input.preparation,
            responseLanguage: input.responseLanguage,
            candidate,
            planningIntent,
            priorWorkerDurationMs,
        }),
        runRevision: ({ currentStage, candidate, review, reviewRound, planningIntent, workerDurationMs, }) => runPlanReviewRevisionStage({
            context: input.context,
            logger: input.logger,
            workspace: input.workspace,
            preparation: input.preparation,
            promptIssue: input.promptIssue,
            promptComments: input.promptComments,
            responseLanguage: input.responseLanguage,
            nestedPlanningPass: input.nestedPlanningPass,
            currentStage,
            candidate,
            review,
            reviewRound,
            planningIntent,
            workerDurationMs,
        }),
        applyAcceptedStage: ({ stage, carriedFields }) => applyCarriedPlanningFieldsToStage({
            stage,
            carriedFields,
        }),
        buildBlockedState: ({ review, candidate, durationThroughReview }) => (0, worker_support_1.buildQuestionHandoffState)({
            issue: input.preparation.latestIssue,
            responseLanguage: input.responseLanguage,
            summary: buildWorkflowPlanReviewHandoffSummary(review),
            branchName: input.workspace.branchName,
            workflowTemplateName: candidate.workflowTemplateName,
            workflowState: candidate.workflowState,
            totalAiRunHours: (0, ai_run_accounting_1.addAiRunDurationToTotal)(input.preparation.currentTotalAiRunHours, durationThroughReview),
        }),
    });
}
function shouldRunWorkflowPlanReview(input) {
    return (input.nestedPlanningPass === null &&
        input.primaryStage.execution.runMode === types_1.WORKER_RUN_MODES.workflowPlan &&
        input.primaryStage.workerResult.launchResult.decision.outcome ===
            types_1.WORKER_OUTCOMES.proceed);
}
async function runWorkflowPlanReviewAttempt(input) {
    let reviewResult;
    try {
        reviewResult = await input.context.worker.runWorkflowPlanReview(buildWorkflowPlanReviewInput(input));
    }
    catch (error) {
        return {
            kind: "state",
            state: (0, worker_support_1.handleWorkerAttemptFailure)({
                error: addPriorStepAttemptDurationToFailure(error, input.priorWorkerDurationMs),
                preparation: input.preparation,
                workspace: input.workspace,
                nestedPlanningPass: null,
                responseLanguage: input.responseLanguage,
            }),
        };
    }
    if (reviewResult.kind === "deferred") {
        return {
            kind: "state",
            state: (0, worker_support_1.buildDeferredWorkerState)(input.preparation, input.responseLanguage, input.workspace, addPriorStepAttemptDurationToDeferredResult(reviewResult, input.priorWorkerDurationMs)),
        };
    }
    return {
        kind: "continue",
        value: {
            review: reviewResult.launchResult.review,
            workerDurationMs: reviewResult.workerDurationMs ?? 0,
        },
    };
}
function buildWorkflowPlanReviewInput(input) {
    const workflowState = input.candidate.workflowState;
    return {
        issue: {
            title: input.preparation.latestIssue.title,
            body: input.preparation.latestIssue.body,
        },
        latestComments: toWorkerWorkflowPlanReviewComments(input.preparation.comments),
        planningIntent: input.planningIntent,
        workflowSurface: workflowState.workflowSurface,
        templateName: input.candidate.workflowTemplateName,
        reviewedPlanRevision: workflowState.planRevision,
        contract: workflowState.executionContract ?? null,
        plan: input.candidate.plan,
        executionGuidance: workflowState.executionGuidance ?? [],
        predictedTouchedPaths: workflowState.predictedTouchedPaths ?? [],
        issueNotesPath: (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.context.config, workflowState).paths.issueNotes,
        outputLanguage: input.responseLanguage,
        workspacePath: input.workspace.path,
        repositoryRoot: input.workspace.path,
    };
}
function toWorkerWorkflowPlanReviewComments(comments) {
    return comments.slice(-WORKFLOW_PLAN_REVIEW_MAX_COMMENTS).map((comment) => ({
        author: comment.author,
        createdAt: comment.createdAt,
        body: comment.body.length > WORKFLOW_PLAN_REVIEW_MAX_COMMENT_CHARS
            ? `${comment.body.slice(0, WORKFLOW_PLAN_REVIEW_MAX_COMMENT_CHARS)}\n[truncated]`
            : comment.body,
    }));
}
async function runPlanReviewRevisionStage(input) {
    const revisionWorkflow = {
        ...input.currentStage.execution.workflow,
        planningIntent: (0, workflow_plan_review_loop_1.resolvePlanReviewRevisionIntent)(input.planningIntent),
        state: input.candidate.workflowState,
        planReviewFeedback: {
            reviewRound: input.reviewRound,
            review: input.review,
        },
    };
    const revisionStage = await runPrimaryWorkerStage({
        context: input.context,
        logger: input.logger,
        workspace: input.workspace,
        preparation: input.preparation,
        promptIssue: input.promptIssue,
        promptComments: input.promptComments,
        responseLanguage: input.responseLanguage,
        nestedPlanningPass: input.nestedPlanningPass,
        execution: {
            ...input.currentStage.execution,
            workflow: revisionWorkflow,
            workflowTemplateName: input.candidate.workflowTemplateName,
            workflowState: input.candidate.workflowState,
            workerDurationMs: input.workerDurationMs,
        },
    });
    return revisionStage;
}
function applyCarriedPlanningFieldsToStage(input) {
    const decision = input.stage.workerResult.launchResult.decision;
    return {
        ...input.stage,
        workerResult: {
            ...input.stage.workerResult,
            launchResult: {
                ...input.stage.workerResult.launchResult,
                decision: {
                    ...decision,
                    ...(decision.issueTitle === undefined &&
                        input.carriedFields.issueTitle !== undefined
                        ? { issueTitle: input.carriedFields.issueTitle }
                        : {}),
                },
            },
        },
    };
}
function buildWorkflowPlanReviewHandoffSummary(review) {
    const findings = review.findings
        .slice(0, 5)
        .map((finding) => `- [${finding.severity}] ${finding.target.kind}${finding.target.stepId ? ` ${finding.target.stepId}` : ""}: ${finding.problem}`);
    return [
        "Automated plan review blocked execution.",
        review.reason,
        ...(findings.length > 0 ? findings : []),
    ].join("\n");
}
function finalizeWorkerExecutionState(input) {
    if (input.nestedPlanningPass !== null) {
        return (0, worker_support_1.buildNestedWorkflowPlanningState)(input.preparation, input.nestedPlanningPass, input.responseLanguage, input.workspace, input.workspaceHeadCommitOidBeforeRun, input.workerResult, input.scannedInputCursor);
    }
    const resolvedWorkflow = (0, state_1.resolveWorkerExecutionWorkflow)({
        workflow: input.execution.workflow,
        workflowTemplateName: input.execution.workflowTemplateName,
        workflowState: input.execution.workflowState,
    }, input.workerResult.launchResult.decision, input.responseLanguage);
    let planningIntent = input.execution.planningIntent;
    if (input.execution.runMode === types_1.WORKER_RUN_MODES.workflowPlan) {
        planningIntent =
            planningIntent === "replan"
                ? planningIntent
                : resolvePlanningIntentAfterSelection(input.preparation.workflowState, resolvedWorkflow.workflowState);
    }
    const suppressConsecutiveAiRunAccounting = input.execution.runMode === types_1.WORKER_RUN_MODES.workflowPlan &&
        (0, start_approval_review_1.isRevisePlanContext)(input.preparation.comments);
    const plannedIssueTitle = input.execution.runMode === types_1.WORKER_RUN_MODES.workflowPlan
        ? (input.workerResult.launchResult.decision.issueTitle?.trim() ?? null)
        : null;
    return {
        kind: "completed",
        workerExecution: (0, worker_support_1.buildWorkerExecutionState)(input.preparation.latestIssue, {
            ...buildWorkerExecutionIdentity(input.workerResult),
            workerDurationMs: input.execution.workerDurationMs +
                (input.workerResult.workerDurationMs ?? 0),
            workspaceHeadCommitOidBeforeRun: input.workspaceHeadCommitOidBeforeRun,
            decision: input.workerResult.launchResult.decision,
        }, input.preparation.currentConsecutiveAiRuns +
            (suppressConsecutiveAiRunAccounting ? 0 : 1), input.responseLanguage, {
            facts: shared_1.EMPTY_FACTS,
            pullRequestUrl: null,
            pullRequestThreadId: null,
        }, input.scannedInputCursor, input.workspace.branchName, input.execution.runMode, resolvedWorkflow.workflowTemplateName, resolvedWorkflow.workflowState, planningIntent, suppressConsecutiveAiRunAccounting
            ? {
                incrementsConsecutiveAiRuns: false,
                mergeContext: input.execution.workflow.mergeContext ?? null,
                plannedIssueTitle,
                startedWithPlanningIntent: input.preparation.workflowState?.pendingPlanningIntent ?? null,
                startedWithWorkflowStartApprovalIntent: input.preparation.workflowState
                    ?.pendingWorkflowStartApprovalIntent ?? null,
            }
            : {
                mergeContext: input.execution.workflow.mergeContext ?? null,
                plannedIssueTitle,
                startedWithPlanningIntent: input.preparation.workflowState?.pendingPlanningIntent ?? null,
                startedWithWorkflowStartApprovalIntent: input.preparation.workflowState
                    ?.pendingWorkflowStartApprovalIntent ?? null,
            }),
    };
}
function buildWorkerExecutionIdentity(workerResult) {
    return {
        workerId: workerResult.workerId,
        workerName: workerResult.workerName,
        ...(workerResult.authProfileId === undefined
            ? {}
            : { authProfileId: workerResult.authProfileId }),
        ...(workerResult.authProfileKind === undefined
            ? {}
            : { authProfileKind: workerResult.authProfileKind }),
    };
}
async function runLoggedWorkerAttempt(input) {
    let wroteStdoutHeader = false;
    let wroteStderrHeader = false;
    try {
        const workerRunInput = {
            issue: input.promptIssue,
            comments: input.promptComments,
            responseLanguage: input.responseLanguage,
            workspacePath: input.workspace.path,
            repositoryRoot: input.workspace.path,
            workflow: input.workflow,
            continuationContext: input.preparation.continuationContext,
            onStdoutChunk(chunk) {
                if (!wroteStdoutHeader) {
                    wroteStdoutHeader = true;
                    void input.logger.appendText(`\n--- ${(0, log_text_1.issueLogSection)("workerStdout")} ---\n`);
                }
                void input.logger.appendText(chunk);
            },
            onStderrChunk(chunk) {
                if (!wroteStderrHeader) {
                    wroteStderrHeader = true;
                    void input.logger.appendText(`\n--- ${(0, log_text_1.issueLogSection)("workerStderr")} ---\n`);
                }
                void input.logger.appendText(chunk);
            },
        };
        if (input.preparation.linkedIssue) {
            workerRunInput.linkedIssue = input.preparation.linkedIssue;
        }
        if (input.workflow.mode === types_1.WORKER_RUN_MODES.workflowPlan) {
            workerRunInput.validateDecision = (decision) => {
                (0, state_1.resolveWorkerExecutionWorkflow)({
                    workflow: input.workflow,
                    workflowTemplateName: input.workflowTemplateName,
                    workflowState: input.workflowState,
                }, decision, input.responseLanguage);
            };
        }
        return await input.context.worker.run(workerRunInput);
    }
    finally {
        if (!wroteStdoutHeader) {
            await input.logger.appendText(`\n--- ${(0, log_text_1.issueLogSection)("workerStdout")} ---\n`);
        }
        if (!wroteStderrHeader) {
            await input.logger.appendText(`\n--- ${(0, log_text_1.issueLogSection)("workerStderr")} ---\n`);
        }
        await input.logger.flush();
    }
}
async function resolveNestedWorkflowPlanningPass(context, preparation, responseLanguage) {
    if (preparation.workflow.mode !== types_1.WORKER_RUN_MODES.workflowExecute ||
        preparation.workflowState?.plan === null ||
        preparation.workflowState === null) {
        return null;
    }
    const plan = preparation.workflowState.plan;
    const currentStep = (0, plan_progress_1.selectReadyNestedWorkflowPlanningStep)(plan);
    if (currentStep === undefined || currentStep === null) {
        return null;
    }
    const currentStepIndex = (0, plan_progress_1.findWorkflowStepIndexById)(plan, currentStep.id);
    if (currentStepIndex < 0) {
        return null;
    }
    const effectiveConfig = (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(context.config, preparation.workflowState);
    if (currentStep.kind === "workflow_ref" &&
        currentStep.targetTemplateName &&
        currentStep.sourceTemplateName &&
        currentStep.sourceTemplateDigest) {
        const childPlanning = await (0, run_context_1.resolveNestedWorkflowPlanningContext)({
            repoRoot: (0, workflow_template_root_1.getWorkflowTemplateRepoRoot)(context),
            workflowState: preparation.workflowState,
            targetTemplateName: currentStep.targetTemplateName,
            sourceTemplateName: currentStep.sourceTemplateName,
            parentStepTitle: currentStep.title,
            issueNotesPath: effectiveConfig.paths.issueNotes,
            locale: responseLanguage,
            maxNestedWorkflowDepth: context.config.maxNestedWorkflowDepth,
        });
        if (childPlanning.kind === "handoff") {
            return childPlanning;
        }
        return normalizeNestedWorkflowPlanningResolution(childPlanning, preparation.workflowState, currentStep.targetTemplateName, currentStep.targetTemplateName, childPlanning.templateDigest, currentStep.expansionGroupId ?? currentStep.callSiteId ?? currentStep.id, currentStep.originSubtreeKey ??
            currentStep.expansionGroupId ??
            currentStep.callSiteId ??
            currentStep.id, {
            targetTemplateName: currentStep.targetTemplateName,
            callSiteId: currentStep.callSiteId ??
                currentStep.expansionGroupId ??
                currentStep.id,
            sourceTemplateName: currentStep.sourceTemplateName,
            sourceTemplateDigest: childPlanning.sourceTemplateDigest,
            expansionGroupId: currentStep.expansionGroupId ??
                currentStep.callSiteId ??
                currentStep.id,
        }, currentStepIndex, currentStep.title);
    }
    if (currentStep.originWorkflowRef &&
        currentStep.originSubtreeKey &&
        currentStep.sourceTemplateName &&
        currentStep.sourceTemplateDigest) {
        const childPlanning = await (0, run_context_1.resolveNestedWorkflowPlanningContext)({
            repoRoot: (0, workflow_template_root_1.getWorkflowTemplateRepoRoot)(context),
            workflowState: preparation.workflowState,
            targetTemplateName: currentStep.originWorkflowRef.targetTemplateName,
            sourceTemplateName: currentStep.originWorkflowRef.sourceTemplateName,
            parentStepTitle: currentStep.title,
            issueNotesPath: effectiveConfig.paths.issueNotes,
            locale: responseLanguage,
            maxNestedWorkflowDepth: context.config.maxNestedWorkflowDepth,
        });
        if (childPlanning.kind === "handoff") {
            return childPlanning;
        }
        if (childPlanning.templateDigest === currentStep.sourceTemplateDigest &&
            childPlanning.sourceTemplateDigest ===
                currentStep.originWorkflowRef.sourceTemplateDigest) {
            return null;
        }
        const restoredParentWorkflowState = (0, state_1.replaceWorkflowExpansionSubtreeWithWorkflowRef)(preparation.workflowState, {
            originSubtreeKey: currentStep.originSubtreeKey,
            originWorkflowRef: {
                ...currentStep.originWorkflowRef,
                sourceTemplateDigest: childPlanning.sourceTemplateDigest,
            },
            locale: responseLanguage,
        });
        return {
            kind: "continue",
            workflowForWorker: childPlanning.workflow,
            workflowTemplateNameForWorker: childPlanning.workflowTemplateName,
            workflowStateForWorker: childPlanning.workflowState,
            parentWorkflowState: restoredParentWorkflowState,
            targetTemplateName: currentStep.originWorkflowRef.targetTemplateName,
            sourceTemplateName: childPlanning.workflowTemplateName,
            sourceTemplateDigest: childPlanning.templateDigest,
            expansionGroupId: currentStep.originWorkflowRef.expansionGroupId,
            originSubtreeKey: currentStep.originSubtreeKey,
            originWorkflowRef: {
                ...currentStep.originWorkflowRef,
                sourceTemplateDigest: childPlanning.sourceTemplateDigest,
            },
            stepIndex: restoredParentWorkflowState.plan === null
                ? 0
                : (0, plan_progress_1.findWorkflowStepIndexById)(restoredParentWorkflowState.plan, currentStep.originWorkflowRef.expansionGroupId),
            parentStepTitle: currentStep.title,
        };
    }
    return null;
}
function normalizeNestedWorkflowPlanningResolution(resolution, parentWorkflowState, targetTemplateName, sourceTemplateName, sourceTemplateDigest, expansionGroupId, originSubtreeKey, originWorkflowRef, stepIndex, parentStepTitle) {
    if (resolution.kind === "handoff") {
        return resolution;
    }
    return {
        kind: "continue",
        workflowForWorker: resolution.workflow,
        workflowTemplateNameForWorker: resolution.workflowTemplateName,
        workflowStateForWorker: resolution.workflowState,
        parentWorkflowState,
        targetTemplateName,
        sourceTemplateName,
        sourceTemplateDigest,
        expansionGroupId,
        originSubtreeKey,
        originWorkflowRef,
        stepIndex,
        parentStepTitle,
    };
}
function resolvePlanningIntentAfterSelection(previousWorkflowState, nextWorkflowState) {
    if (nextWorkflowState === null || previousWorkflowState === null) {
        return "new_plan";
    }
    if (previousWorkflowState.pendingPlanningIntent !== undefined) {
        return previousWorkflowState.pendingPlanningIntent;
    }
    if ((0, workflow_selection_support_1.hasWorkflowSelectionOrTemplateChanged)((0, template_bindings_1.getActiveWorkflowTemplateBinding)(previousWorkflowState), (0, template_bindings_1.getActiveWorkflowTemplateBinding)(nextWorkflowState))) {
        return (0, state_1.hasPendingWorkflowStartApproval)(previousWorkflowState)
            ? "revise_plan"
            : "replan";
    }
    return "new_plan";
}
