/**
 * Build the step sequence based on resolved config.
 *
 * This is the declarative description of the pipeline — a list of
 * PipelineStep objects determined by config flags like skipFetch,
 * skipEval, compareEnabled, etc.
 */
import { LiteracyVariant } from "../pipeline/normalize-mode.js";
import { CallbackStep } from "./steps/callback-step.js";
import { CalculateScoresStep } from "./steps/calculate-scores-step.js";
import { ComputeAttributionStep } from "./steps/compute-attribution-step.js";
import { CompareStep } from "./steps/compare-step.js";
import { FetchDocsStep } from "./steps/fetch-docs-step.js";
import { FinalizeRunStep } from "./steps/finalize-run-step.js";
import { GapAnalysisStep } from "./steps/gap-analysis-step.js";
import { GenerateConfigsStep } from "./steps/generate-configs-step.js";
import { GraderConsistencyStep } from "./steps/grader-consistency-step.js";
import { ProvenanceGateStep } from "./steps/provenance-gate-step.js";
import { PublishReportStep } from "./steps/publish-report-step.js";
import { ReportStep } from "./steps/report-step.js";
import { RunEvalStep } from "./steps/run-eval-step.js";
import { MirrorRepoTasksStep } from "./steps/mirror-repo-tasks-step.js";
import { ValidateStep } from "./steps/validate-step.js";
import { ValidateTaskViabilityStep } from "./steps/validate-task-viability-step.js";
/**
 * Build the pipeline step sequence based on config.
 *
 * @param ctx - The application context (used for config)
 * @param pipelineStart - Pipeline start timestamp (for publish step)
 */
export function buildStepSequence(ctx, pipelineStart = Date.now()) {
    const config = ctx.config;
    const steps = [];
    // Step 0: Validate configuration
    steps.push(new ValidateStep());
    // Step 0a: Fail fast when explicitly selected tasks are non-viable under the
    // runner's published perspective (no-op unless --task + content-lake source).
    // Runs before fetch-docs so a bad selection aborts up front with a precise,
    // actionable error instead of the late, ambiguous generate-configs message.
    steps.push(new ValidateTaskViabilityStep());
    // Step 0b: Mirror repo tasks to Content Lake (optional, when --repo-tasks-path)
    if (config.repoTasksPath) {
        steps.push(new MirrorRepoTasksStep());
    }
    // Step 1: Fetch documentation (literacy mode only — other modes don't use canonical docs)
    if (config.mode === "literacy") {
        steps.push(new FetchDocsStep());
    }
    // Step 2: Generate Promptfoo configs
    steps.push(new GenerateConfigsStep());
    // Step 3: Run evaluation (steps handle --skip-eval internally)
    //
    // For literacy mode, the variant determines how many eval steps run:
    //   "full" → baseline + agentic (two steps)
    //   "baseline" / "agentic" / "observed" → one step
    //   undefined → defaults to baseline
    //
    // For all other modes, one eval step per mode.
    if (config.mode === "literacy") {
        const variant = config.variant ?? LiteracyVariant.STANDARD;
        if (variant === LiteracyVariant.FULL) {
            for (const submode of [
                LiteracyVariant.STANDARD,
                LiteracyVariant.AGENTIC,
            ]) {
                steps.push(new RunEvalStep(submode));
            }
        }
        else {
            steps.push(new RunEvalStep(variant));
        }
    }
    else {
        steps.push(new RunEvalStep(config.mode));
    }
    // Step 3c: Grader consistency (optional, conditional)
    if (config.graderReplications) {
        steps.push(new GraderConsistencyStep());
    }
    // Step 4: Calculate scores
    steps.push(new CalculateScoresStep());
    // Step 4b: Gap analysis (on by default, opt-out via --no-gap-analysis)
    if (config.gapAnalysisEnabled) {
        steps.push(new GapAnalysisStep());
    }
    // Step 4b2: Per-judgment attribution ensemble (default-on).
    // Depends on documentManifest being enriched onto score-summary.json
    // by gap-analysis. Skipped silently when upstream files are missing.
    steps.push(new ComputeAttributionStep());
    // Step 4c: Finalize the run — write `runs/{runId}/manifest.json` with the
    // catalog of artifacts produced so far. Skipped silently when no
    // artifactWriter is wired (D0032).
    steps.push(new FinalizeRunStep(pipelineStart));
    // Step 4c2: Pre-publish provenance gate (T2). Always runs so non-publishing
    // runs still surface ownership warnings; it only *fails* the run when a
    // publish is actually intended (publishing enabled + a report store wired)
    // and the attribution is invalid — aborting before PublishReportStep writes.
    steps.push(new ProvenanceGateStep());
    // Step 4d: Publish report (optional, when token is configured)
    if (config.publishEnabled) {
        steps.push(new PublishReportStep(pipelineStart, {
            publishTag: config.publishTag,
        }));
    }
    // Step 5: Generate report
    steps.push(new ReportStep());
    // Step 5b: Compare against baseline (optional)
    if (config.compareEnabled) {
        steps.push(new CompareStep());
    }
    // Step 6: Callback delivery (optional, API-triggered evaluations)
    if (config.callback?.url) {
        steps.push(new CallbackStep(config.callback, config.jobId));
    }
    return steps;
}
