// engine/sdd-flow/gates.ts — SPEC-583: Gate decision logic per controlMode
import { enterPlanModeIfSupported } from '../../hosts/claude-code/runtime/plan-mode-gate.js';
function buildWavePlanQuestion(wavePlan, routing) {
    const waveDesc = wavePlan.waves
        .map((w) => `Wave ${w.index + 1}: [${w.specIds.join(', ')}] (${w.teammates.map((t) => t.model).join(', ')})`)
        .join(' | ');
    return {
        question: `Planu proposes ${wavePlan.waves.length} wave(s) with models [${routing.planner}, ${routing.executor}, ...]. Est. cost: $${wavePlan.estimatedCost.toFixed(2)}. Plan: ${waveDesc}. Accept?`,
        header: 'Wave Plan',
        options: [
            {
                label: 'Accept (Recommended)',
                description: 'Proceed with the proposed wave plan and model assignments.',
            },
            {
                label: 'Override models',
                description: 'Choose a different model for one or more teammates.',
            },
            { label: 'Override waves', description: 'Manually define the wave groupings.' },
            { label: 'Abort', description: 'Cancel the SDD flow.' },
        ],
        multiSelect: false,
    };
}
function buildReviewerQuestion(specIds) {
    return {
        question: `Review stage complete for specs [${specIds.join(', ')}]. Proceed to execution?`,
        header: 'Review Gate',
        options: [
            {
                label: 'Accept (Recommended)',
                description: 'Spawn teammates and begin implementation.',
            },
            { label: 'Skip execution', description: 'Stop after review without executing.' },
            { label: 'Abort', description: 'Cancel the SDD flow.' },
        ],
        multiSelect: false,
    };
}
function buildExecutorQuestion(teammates) {
    const done = teammates.filter((t) => t.status === 'completed').length;
    return {
        question: `Execution complete: ${done}/${teammates.length} teammates finished. Proceed to validation?`,
        header: 'Executor Gate',
        options: [
            {
                label: 'Accept (Recommended)',
                description: 'Run validation on all completed worktrees.',
            },
            { label: 'Abort', description: 'Cancel the SDD flow.' },
        ],
        multiSelect: false,
    };
}
function buildValidatorFailQuestion(failed) {
    return {
        question: `Validation failed for: [${failed.join(', ')}]. What should Planu do?`,
        header: 'Validator Fail',
        options: [
            {
                label: 'Rollback failed (Recommended)',
                description: 'Roll back only the failing worktrees. Others proceed to merge.',
            },
            { label: 'Retry', description: 'Retry validation for the failing specs.' },
            { label: 'Abort all', description: 'Roll back all worktrees and cancel the flow.' },
        ],
        multiSelect: false,
    };
}
function buildMergerQuestion(specIds) {
    return {
        question: `Ready to merge [${specIds.join(', ')}] to develop with --ff-only. Proceed?`,
        header: 'Merge Gate',
        options: [
            {
                label: 'Accept (Recommended)',
                description: 'Merge all validated branches to develop.',
            },
            { label: 'Abort', description: 'Skip merge and end the flow.' },
        ],
        multiSelect: false,
    };
}
function buildReleaserQuestion() {
    return {
        question: 'Proceed to generate changelog and bump version via create_release?',
        header: 'Release Gate',
        options: [
            {
                label: 'Accept (Recommended)',
                description: 'Generate changelog entry and bump version.',
            },
            { label: 'Skip release', description: 'End flow without bumping version.' },
        ],
        multiSelect: false,
    };
}
function buildQuestionsForStage(ctx, stage) {
    switch (stage) {
        case 'planner':
            return ctx.wavePlan && ctx.modelRouting
                ? [buildWavePlanQuestion(ctx.wavePlan, ctx.modelRouting)]
                : [];
        case 'reviewer':
            return ctx.specIds ? [buildReviewerQuestion(ctx.specIds)] : [];
        case 'executor':
            return ctx.teammates ? [buildExecutorQuestion(ctx.teammates)] : [];
        case 'validator':
            return ctx.validationFailed && ctx.validationFailed.length > 0
                ? [buildValidatorFailQuestion(ctx.validationFailed)]
                : [];
        case 'merger':
            return ctx.specIds ? [buildMergerQuestion(ctx.specIds)] : [];
        case 'releaser':
            return [buildReleaserQuestion()];
    }
}
export function evaluateGate(ctx) {
    const { stage, controlMode } = ctx;
    if (controlMode === 'full-auto') {
        return { action: 'proceed' };
    }
    if (controlMode === 'preview') {
        return { action: 'exit', reason: 'preview mode: plan generated, no execution' };
    }
    // SPEC-587: Enter Claude Code plan mode at merger/planner gate when spec is not yet approved.
    // enterPlanModeIfSupported returns entered:false outside Claude Code → no behavioural change.
    if (stage === 'merger' || stage === 'planner') {
        const firstSpecId = ctx.specIds?.[0] ?? 'unknown';
        const planModeResult = enterPlanModeIfSupported({
            stage,
            specId: firstSpecId,
            specApproved: false, // gate runs before approval is confirmed
            hostSupportsPlanMode: Boolean(process.env.CLAUDE_CODE_PLAN_MODE_SUPPORTED),
        });
        if (planModeResult.entered) {
            // Signal the host to enter plan mode; the tool response layer picks up modeHint.
            const questions = buildQuestionsForStage(ctx, stage);
            return {
                action: 'pause',
                questions,
                // modeHint is carried as extra metadata on the decision for the caller
                ...(planModeResult.modeHint !== undefined ? { modeHint: planModeResult.modeHint } : {}),
            };
        }
    }
    // interactive mode — validator with no failures proceeds automatically
    if (stage === 'validator' && (!ctx.validationFailed || ctx.validationFailed.length === 0)) {
        return { action: 'proceed' };
    }
    const questions = buildQuestionsForStage(ctx, stage);
    if (questions.length > 0) {
        return { action: 'pause', questions };
    }
    return { action: 'proceed' };
}
//# sourceMappingURL=gates.js.map