"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.publishCompletedWorkerExecution = publishCompletedWorkerExecution;
const control_plane_config_1 = require("../../../config/control-plane-config");
const types_1 = require("../../../platform/ticket-tracker/types");
const constants_1 = require("../../../worker/constants");
const types_2 = require("../../../worker/types");
const assignee_resolution_1 = require("../../../workflows/assignee-resolution");
const pending_planning_support_1 = require("../../../workflows/pending-planning-support");
const types_3 = require("../../../workflows/types");
const workflow_state_read_support_1 = require("../../../workflows/workflow-state-read-support");
const log_text_1 = require("../../log-text");
const plan_progress_1 = require("../../../workflows/plan-progress");
const effects_1 = require("../effects");
const issue_branch_target_1 = require("../issue-branch-target");
const freshness_1 = require("../freshness");
const pull_request_auto_merge_1 = require("../pull-request-auto-merge");
const results_1 = require("../results");
const shared_1 = require("../shared");
const unplanned_1 = require("../spawn-child/unplanned");
const spawn_child_controller_1 = require("../spawn-child-controller");
const start_approval_review_1 = require("../start-approval-review");
const transition_summary_1 = require("../transition-summary");
const transitions_1 = require("../transitions");
const types_4 = require("../types");
const workflow_template_root_1 = require("../workflow-template-root");
const interruption_1 = require("./interruption");
const merge_finalization_1 = require("./merge-finalization");
const workflow_closing_1 = require("../workflow-closing");
async function publishCompletedWorkerExecution(input) {
    const { context, claimedIssue, logger, workflowLabels, workspace, cursorBefore, freshnessPass, latestIssue, workerExecution, syncPlannedIssueDependencies, } = input;
    let effectiveWorkflowState = workerExecution.workflowState;
    if (workerExecution.runMode !== types_2.WORKER_RUN_MODES.workflowPlan) {
        try {
            await (0, merge_finalization_1.commitAndPushWorkerChanges)({
                gitRepository: context.gitRepository,
                workspacePath: workspace.path,
                branchName: workspace.branchName,
                baseBranch: (0, issue_branch_target_1.resolveIssueRunBaseBranch)(workerExecution.workflowState),
                issueDisplayId: claimedIssue.originalIssue.displayId,
                issue: latestIssue,
                commitMessage: workerExecution.commitMessage,
                mergeContext: workerExecution.mergeContext,
                workerOutcome: workerExecution.workerOutcome,
                responseLanguage: workerExecution.responseLanguage,
            });
        }
        catch (error) {
            if (error instanceof merge_finalization_1.MergeCommitFinalizationError) {
                return publishMergeCommitFinalizationFailure({
                    context,
                    claimedIssue,
                    logger,
                    workflowLabels,
                    workspace,
                    workerExecution,
                    summary: error.message,
                });
            }
            throw error;
        }
        effectiveWorkflowState =
            clearCompletedMergeWorkflowContext(workerExecution);
    }
    const postPublishFreshness = await (0, freshness_1.loadFreshnessSnapshot)(context.freshTicketTracker, claimedIssue.originalIssue.id);
    await logger.appendSection((0, log_text_1.issueLogSection)("freshnessRefresh"), (0, freshness_1.renderFreshnessRefreshSection)({
        workflowLabels,
        pass: freshnessPass,
        maxPasses: shared_1.MAX_FRESHNESS_PASSES,
        latestIssue: postPublishFreshness.latestIssue,
        commentCount: postPublishFreshness.comments.length,
        currentConsecutiveAiRuns: postPublishFreshness.currentConsecutiveAiRuns,
        currentTotalAiRunHours: postPublishFreshness.currentTotalAiRunHours,
        cursor: postPublishFreshness.cursor,
        note: workerExecution.runMode === types_2.WORKER_RUN_MODES.workflowPlan
            ? "post_publish"
            : "post_push",
    }));
    const postPublishInterrupt = await (0, interruption_1.handlePostPublishFreshnessInterrupt)({
        context,
        claimedIssue,
        logger,
        workflowLabels,
        cursorBefore,
        freshnessPass,
        freshnessAfter: postPublishFreshness,
    });
    if (postPublishInterrupt.kind === "interrupt") {
        return postPublishInterrupt.summary;
    }
    if (postPublishInterrupt.kind === "rerun") {
        return null;
    }
    const publishedWorkerExecution = await buildPublishedWorkerExecution({
        context,
        workspace,
        workerExecution,
        effectiveWorkflowState,
    });
    let terminalWorkerExecution = publishedWorkerExecution;
    if ((0, workflow_closing_1.shouldRunWorkflowClosingForTerminalIssue)(publishedWorkerExecution)) {
        terminalWorkerExecution = await (0, workflow_closing_1.runWorkflowClosingWorker)({
            context,
            logger,
            workspace,
            previousConsecutiveAiRuns: claimedIssue.previousConsecutiveAiRuns,
            latestIssue: postPublishFreshness.latestIssue,
            comments: postPublishFreshness.comments,
            workerExecution: publishedWorkerExecution,
        });
    }
    if (terminalWorkerExecution.continuation?.strategy === "spawn_child_issue") {
        return (0, unplanned_1.publishSpawnChildContinuation)({
            context,
            claimedIssue,
            logger,
            workflowLabels,
            workspace,
            workerExecution: terminalWorkerExecution,
        });
    }
    const transitionState = (0, transitions_1.buildSuccessfulTransitionState)(context.config, claimedIssue, terminalWorkerExecution);
    const publishedSummary = await publishPublishedWorkerExecution({
        context,
        claimedIssue,
        logger,
        workflowLabels,
        workspace,
        postPublishFreshnessComments: postPublishFreshness.comments,
        publishedWorkerExecution: terminalWorkerExecution,
        transitionState,
    });
    return ((await syncPlannedIssueDependenciesIfNeeded({
        context,
        claimedIssue,
        publishedWorkerExecution,
        transitionState,
        syncPlannedIssueDependencies,
    })) ?? publishedSummary);
}
async function publishMergeCommitFinalizationFailure(input) {
    const routing = await (0, effects_1.collectRoutingFacts)(input.context, input.workspace.path, input.workspace.branchName, (0, issue_branch_target_1.resolveIssueRunBaseBranch)(input.workerExecution.workflowState));
    const blockedWorkerExecution = {
        ...input.workerExecution,
        workerOutcome: constants_1.WORKER_OUTCOMES.waitHuman,
        result: (0, types_3.buildWorkflowResultFieldsWithDefaults)({
            ...input.workerExecution.result,
            resultSummary: input.summary,
            evidence: [],
            humanComment: input.summary,
        }),
        facts: routing.facts,
        pullRequestUrl: routing.pullRequestUrl,
        continuation: null,
        needsHumanReason: types_4.WORKER_NEEDS_HUMAN_REASONS.question,
    };
    const transitionState = (0, transitions_1.buildSuccessfulTransitionState)(input.context.config, input.claimedIssue, blockedWorkerExecution);
    return publishResolvedTransition({
        context: input.context,
        claimedIssue: input.claimedIssue,
        logger: input.logger,
        workflowLabels: input.workflowLabels,
        transitionState,
        resolvedFacts: blockedWorkerExecution.facts,
    });
}
async function publishResolvedTransition(input) {
    return (0, transition_summary_1.publishTransitionSummary)({
        repoRoot: (0, workflow_template_root_1.getWorkflowTemplateRepoRoot)(input.context),
        config: input.context.config,
        currentUserLogin: input.context.currentUserLogin,
        repositoryHost: input.context.repositoryHost,
        ticketTracker: input.context.ticketTracker,
        issueId: input.claimedIssue.originalIssue.id,
        transitionState: input.transitionState,
        logger: input.logger,
        workflowLabels: input.workflowLabels,
        fromStatus: input.claimedIssue.aiRunningSnapshot.status,
        resolvedFacts: input.resolvedFacts,
        worker: input.context.worker,
        ...(input.context.logHomeDirectory !== undefined
            ? { homeDirectory: input.context.logHomeDirectory }
            : {}),
    });
}
async function publishPublishedWorkerExecution(input) {
    const revisePlanContext = (0, start_approval_review_1.isRevisePlanContext)(input.postPublishFreshnessComments);
    const shouldSkipRevisePlanWorkflowUpdate = revisePlanContext &&
        (0, start_approval_review_1.isSemanticallyUnchangedRevisePlan)({
            comments: input.postPublishFreshnessComments,
            workflowState: input.transitionState.workflowState,
            responseLanguage: input.publishedWorkerExecution.responseLanguage,
        });
    const workflowStartApprovalRequired = resolveWorkflowStartApprovalDecision(input.claimedIssue.originalIssue, input.transitionState, input.publishedWorkerExecution, input.context.config);
    const isControllerChildContinuation = input.publishedWorkerExecution.runMode === types_2.WORKER_RUN_MODES.workflowPlan &&
        input.publishedWorkerExecution.workerOutcome === constants_1.WORKER_OUTCOMES.proceed &&
        (0, plan_progress_1.hasControllerChildIssueControlPlaneAction)(input.publishedWorkerExecution.workflowState);
    if (workflowStartApprovalRequired !== "not_required") {
        return publishWorkflowStartApprovalDecision({
            ...input,
            workflowStartApprovalDecision: workflowStartApprovalRequired,
            shouldSkipRevisePlanWorkflowUpdate,
        });
    }
    if (isControllerChildContinuation) {
        return (0, spawn_child_controller_1.publishControllerChildIssues)({
            context: input.context,
            claimedIssue: input.claimedIssue,
            logger: input.logger,
            workflowLabels: input.workflowLabels,
            workerExecution: input.publishedWorkerExecution,
        });
    }
    const autoMergeSummary = await maybePublishPullRequestAutoMergeContinuation(input);
    if (autoMergeSummary !== null) {
        return autoMergeSummary;
    }
    return publishResolvedTransition({
        context: input.context,
        claimedIssue: input.claimedIssue,
        logger: input.logger,
        workflowLabels: input.workflowLabels,
        transitionState: input.transitionState,
        resolvedFacts: input.publishedWorkerExecution.facts,
    });
}
async function maybePublishPullRequestAutoMergeContinuation(input) {
    if (input.claimedIssue.originalIssue.kind !== types_1.TRACKER_ITEM_KINDS.pullRequest ||
        !(0, results_1.isTerminalWorkflowSuccess)(input.transitionState)) {
        return null;
    }
    const effectiveConfig = (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.context.config, input.publishedWorkerExecution.workflowState);
    if (!(0, control_plane_config_1.isIssueCompletionAutoMergeEnabled)(effectiveConfig)) {
        return null;
    }
    const workflowState = input.transitionState.workflowState;
    return (0, pull_request_auto_merge_1.continuePullRequestAutoMerge)({
        context: input.context,
        issue: input.claimedIssue.originalIssue,
        logger: input.logger,
        branchName: input.publishedWorkerExecution.branchName,
        responseLanguage: input.publishedWorkerExecution.responseLanguage,
        workflowState,
        publishAutoMergePendingUpdateWhenWaiting: true,
    });
}
async function buildPublishedWorkerExecution(input) {
    const routing = input.workerExecution.runMode === types_2.WORKER_RUN_MODES.workflowPlan
        ? await (0, effects_1.collectExistingPullRequestResolution)(input.context.ticketTracker, input.context.repositoryHost, input.workspace.branchName, (0, issue_branch_target_1.resolveIssueRunBaseBranch)(input.effectiveWorkflowState))
        : await (0, effects_1.collectRoutingFacts)(input.context, input.workspace.path, input.workspace.branchName, (0, issue_branch_target_1.resolveIssueRunBaseBranch)(input.effectiveWorkflowState));
    return {
        ...input.workerExecution,
        workflowState: input.effectiveWorkflowState,
        facts: routing.facts,
        pullRequestUrl: routing.pullRequestUrl,
    };
}
function clearCompletedMergeWorkflowContext(workerExecution) {
    if (workerExecution.mergeContext === null ||
        workerExecution.workflowState === null ||
        workerExecution.workerOutcome !== constants_1.WORKER_OUTCOMES.proceed) {
        return workerExecution.workflowState;
    }
    const { mergeContext: _mergeContext, ...workflowState } = workerExecution.workflowState;
    return workflowState;
}
async function syncPlannedIssueDependenciesIfNeeded(input) {
    if (input.claimedIssue.originalIssue.kind !== types_1.TRACKER_ITEM_KINDS.issue ||
        input.publishedWorkerExecution.runMode !== types_2.WORKER_RUN_MODES.workflowPlan ||
        input.transitionState.finalOutcome !== constants_1.WORKER_OUTCOMES.proceed) {
        return null;
    }
    const currentWorkflowState = await (0, workflow_state_read_support_1.resolvePersistedIssueWorkflowState)(input.context.ticketTracker, input.claimedIssue.originalIssue.id);
    if (currentWorkflowState === null) {
        return null;
    }
    const dependencySummary = await input.syncPlannedIssueDependencies({
        context: input.context,
        issue: input.claimedIssue.originalIssue,
        workflowState: currentWorkflowState,
    });
    return dependencySummary.summary;
}
async function publishWorkflowStartApprovalDecision(input) {
    const startApprovalTransitionState = buildStartApprovalPublishTransition(input);
    return publishResolvedTransition({
        context: input.context,
        claimedIssue: input.claimedIssue,
        logger: input.logger,
        workflowLabels: input.workflowLabels,
        transitionState: startApprovalTransitionState,
        resolvedFacts: input.publishedWorkerExecution.facts,
    });
}
function buildStartApprovalPublishTransition(input) {
    const assigneeResolution = resolveStartApprovalAssigneeResolution(input.workflowStartApprovalDecision);
    const summary = assigneeResolution === null
        ? input.publishedWorkerExecution.result.resultSummary
        : (0, assignee_resolution_1.buildAssigneeResolutionSummary)(input.publishedWorkerExecution.responseLanguage, assigneeResolution);
    return applyStartApprovalTransitionOverrides(buildStartApprovalWaitHumanTransitionState({
        config: input.context.config,
        claimedIssue: input.claimedIssue,
        workspace: input.workspace,
        publishedWorkerExecution: input.publishedWorkerExecution,
        summary,
        assigneeResolution,
        workflowState: buildStartApprovalWorkflowState(input.transitionState.workflowState, input.transitionState.planningIntent, input.publishedWorkerExecution.startedWithWorkflowStartApprovalIntent),
    }), {
        transitionState: input.transitionState,
        shouldSkipRevisePlanWorkflowUpdate: input.shouldSkipRevisePlanWorkflowUpdate,
    });
}
function resolveStartApprovalAssigneeResolution(workflowStartApprovalDecision) {
    return workflowStartApprovalDecision === "start_approval"
        ? null
        : workflowStartApprovalDecision;
}
function buildStartApprovalWorkflowState(workflowState, planningIntent, startedWithWorkflowStartApprovalIntent) {
    if (workflowState === null) {
        return null;
    }
    const pendingWorkflowStartApprovalIntent = workflowState.pendingWorkflowStartApprovalIntent ??
        startedWithWorkflowStartApprovalIntent ??
        (planningIntent === "new_plan" || planningIntent === "replan"
            ? planningIntent
            : undefined);
    const startApprovalWorkflowState = (0, pending_planning_support_1.withoutPendingPlanningState)(workflowState);
    return pendingWorkflowStartApprovalIntent === undefined
        ? startApprovalWorkflowState
        : {
            ...startApprovalWorkflowState,
            pendingWorkflowStartApprovalIntent,
        };
}
function buildStartApprovalWaitHumanTransitionState(input) {
    const waitHumanStateInput = {
        config: input.config,
        previousSnapshot: input.claimedIssue.aiRunningSnapshot,
        readySnapshot: input.claimedIssue.aiReadySnapshot,
        issue: input.publishedWorkerExecution.issue,
        runMode: input.publishedWorkerExecution.runMode,
        summary: input.summary,
        needsHumanReason: input.assigneeResolution === null
            ? "start_approval"
            : "assignee_resolution",
        facts: input.publishedWorkerExecution.facts,
        branchName: input.workspace.branchName,
        baseBranch: input.workflowState === null
            ? input.config.repositoryHost.baseBranch
            : (0, issue_branch_target_1.resolveIssueRunBaseBranch)(input.workflowState),
        pullRequestThreadId: input.publishedWorkerExecution.facts.pullRequestThreadId,
        pullRequestUrl: input.publishedWorkerExecution.pullRequestUrl,
        workflowTemplateName: input.publishedWorkerExecution.workflowTemplateName,
        workflowState: input.workflowState,
        consecutiveAiRuns: input.publishedWorkerExecution.consecutiveAiRuns,
        responseLanguage: input.publishedWorkerExecution.responseLanguage,
    };
    if (input.assigneeResolution !== null) {
        waitHumanStateInput.assigneeResolution = input.assigneeResolution;
    }
    return (0, transitions_1.buildWaitHumanTransitionState)(waitHumanStateInput);
}
function applyStartApprovalTransitionOverrides(waitHumanState, input) {
    const transitionState = {
        ...waitHumanState,
        planningIntent: input.transitionState.planningIntent,
        completedPendingReplan: input.transitionState.completedPendingReplan,
        continuation: input.transitionState.continuation,
        plannedIssueTitle: input.transitionState.plannedIssueTitle,
        incrementsConsecutiveAiRuns: input.transitionState.incrementsConsecutiveAiRuns,
        recordsRunOutcome: input.transitionState.recordsRunOutcome,
    };
    if (input.shouldSkipRevisePlanWorkflowUpdate) {
        transitionState.skipWorkflowUpdateComment = true;
    }
    if (input.transitionState.labelProjection !== undefined) {
        transitionState.labelProjection = input.transitionState.labelProjection;
    }
    return transitionState;
}
function resolveWorkflowStartApprovalDecision(issue, transitionState, workerExecution, config) {
    if (workerExecution.runMode !== types_2.WORKER_RUN_MODES.workflowPlan ||
        workerExecution.workerOutcome !== constants_1.WORKER_OUTCOMES.proceed ||
        transitionState.finalOutcome !== constants_1.WORKER_OUTCOMES.proceed) {
        return "not_required";
    }
    const assigneeGate = (0, assignee_resolution_1.resolveWorkflowAssigneeGate)({
        assignees: issue.assignees,
    });
    const effectiveConfig = (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(config, workerExecution.workflowState);
    const workflowStartApprovalIntent = workerExecution.workflowState?.pendingWorkflowStartApprovalIntent ??
        workerExecution.startedWithWorkflowStartApprovalIntent ??
        undefined;
    if (workerExecution.planningIntent === null) {
        throw new Error("Workflow planning intent is required for start approval.");
    }
    const startApprovalIntentField = workflowStartApprovalIntent === undefined
        ? {}
        : { startApprovalIntent: workflowStartApprovalIntent };
    const workflowStartApprovalMode = (0, control_plane_config_1.resolveWorkflowStartApprovalModeForPlanningIntent)({
        target: issue.kind === types_1.TRACKER_ITEM_KINDS.pullRequest
            ? "pull_request"
            : "issue",
        planningIntent: workerExecution.planningIntent,
        ...startApprovalIntentField,
        config: effectiveConfig,
    });
    if (workflowStartApprovalMode === "auto") {
        return "not_required";
    }
    if (workflowStartApprovalMode === "confirm") {
        return assigneeGate.kind === "ok" ? "start_approval" : assigneeGate.kind;
    }
    if (workerExecution.workflowStartApproval === null) {
        throw new Error(`Workflow start approval decision is required for ${workflowStartApprovalMode} mode.`);
    }
    return workerExecution.workflowStartApproval.required
        ? assigneeGate.kind === "ok"
            ? "start_approval"
            : assigneeGate.kind
        : "not_required";
}
