/**
 * EvalConfigSchema — Zod schema for JSON/YAML evaluation config files.
 *
 * This defines the shape of config files loaded via `--config <path>`.
 * It's a user-facing subset of ResolvedConfig — fields that make sense
 * to persist in a file. Runtime-computed fields (rootDir, promptfooUrl)
 * are not included.
 *
 * The same schema will be used by the future ContentLakeConfigAdapter
 * (studio-eval-config) so Content Lake documents validate identically.
 */
import { z } from "zod";
import { RAW_EVAL_MODES } from "../../ailf-shared/index.js";
export const EvalConfigSchema = z
    .object({
    /**
     * Agentic-mode configuration (W0077 Phase 6f). Replaces the top-level
     * `headers` and `allowedOrigins` fields. Mirrors `RepoConfigSchema`'s
     * `agentic` block for the auto-loaded `.ailf/config.yaml` path.
     *
     * - `headers`         — custom HTTP headers for doc fetching (key/value object)
     * - `allowedOrigins`  — origin globs for agentic-mode sandbox
     */
    agentic: z
        .object({
        headers: z.record(z.string(), z.string()).optional(),
        allowedOrigins: z.array(z.string()).optional(),
    })
        .optional(),
    /**
     * Artifact-writer configuration (W0077 Phase 6g). Replaces the retired
     * `--no-artifacts`, `--artifacts-dir`, and `--artifacts-exclude` CLI
     * flags. Mirrors `RepoConfigSchema.artifacts`.
     *
     * - `enabled`  — false to disable all writers (legacy --no-artifacts)
     * - `dir`      — root for local writer (default .ailf/results/captures/)
     * - `exclude`  — list of artifact-type names to skip
     */
    artifacts: z
        .object({
        enabled: z.boolean().optional(),
        dir: z.string().min(1).optional(),
        exclude: z.array(z.string().min(1)).optional(),
    })
        .optional(),
    /**
     * Task-source configuration (W0077 Phase 6h). Replaces the retired
     * `--task-source` and `--repo-tasks-path` CLI flags. Mirrors
     * `RepoConfigSchema.taskSource`.
     *
     * - `type`           — `content-lake` (default) or `repo`
     * - `repoTasksPath`  — optional path; default `<cwd>/.ailf/tasks/` when
     *                      type is `repo`
     */
    taskSource: z
        .object({
        type: z.enum(["content-lake", "repo"]).optional(),
        repoTasksPath: z.string().min(1).optional(),
    })
        .optional(),
    /** Feature area filter (comma-separated or array) */
    areas: z.array(z.string()).optional(),
    /** Changed doc slugs for impact scoping */
    changedDocs: z.array(z.string()).optional(),
    /** Enable comparison against baseline */
    compare: z.boolean().optional(),
    /** Specific baseline file to compare against */
    compareBaseline: z.string().optional(),
    /** Comparison noise threshold */
    compareThreshold: z.number().min(0).optional(),
    /** Debug mode */
    debug: z
        .union([
        z.boolean(),
        z.object({
            enabled: z.boolean().optional(),
            firstN: z.number().int().positive().optional(),
            pattern: z.string().optional(),
            sample: z.number().int().positive().optional(),
        }),
    ])
        .optional(),
    /**
     * Execution-tier configuration (W0077 Phase 6b). Replaces the top-level
     * `concurrency`, `gapAnalysis`, and `graderReplications` fields and adds
     * `apiUrl` to the same group.
     *
     * - `concurrency`             — max parallel API calls
     * - `graderReplications`      — grader consistency replications
     * - `borderlineReplications`  — replications per borderline judgment
     *                               for the GRAD-04 intra-grader consensus
     *                               pass (default 3 in composition-root)
     * - `gapAnalysis`             — enable failure-mode + impact analysis (default true)
     * - `apiUrl`                  — AILF API base URL (default https://ailf-api.sanity.build)
     */
    execution: z
        .object({
        concurrency: z.number().int().positive().optional(),
        graderReplications: z.number().int().positive().optional(),
        borderlineReplications: z.number().int().positive().optional(),
        gapAnalysis: z.boolean().optional(),
        apiUrl: z.string().url().optional(),
    })
        .optional(),
    /**
     * Grader configuration.
     *
     * - `context: "rubric-only"` — the grader sees only the rubric template
     *   + criteria + candidate response.
     * - `context: "with-docs"` — canonical reference content for each task
     *   is injected into the assertion's `rubricPrompt` so the grader has
     *   authoritative ground truth.
     */
    grader: z
        .object({
        context: z.enum(["rubric-only", "with-docs"]).optional(),
    })
        .optional(),
    /**
     * Output configuration (W0077 Phase 6c). Replaces the retired
     * `--output-dir` CLI flag. Path is resolved relative to the caller's
     * cwd. When unset, defaults to `<cwd>/.ailf/results/latest/`.
     */
    output: z
        .object({
        dir: z.string().min(1).optional(),
    })
        .optional(),
    /**
     * Evaluation mode — accepts both canonical and legacy names.
     * Legacy names ("baseline", "agentic", "observed", "full") must pass
     * through normalizeMode() before entering typed pipeline code.
     */
    mode: z.enum(RAW_EVAL_MODES).optional(),
    /** Disable release-aware auto-scoping */
    noAutoScope: z.boolean().optional(),
    /** Disable local cache */
    noCache: z.boolean().optional(),
    /** Disable remote cache */
    noRemoteCache: z.boolean().optional(),
    /**
     * Publish policy. The CLI `--publish` and `--no-publish` flags override
     * the policy at runtime; this field controls behavior when no explicit
     * flag is passed.
     *
     * - `auto: "always"`     — publish whenever a report store is configured
     * - `auto: "full-runs"`  — publish non-debug runs (default; preserves
     *                          the historical smart default)
     * - `auto: "never"`      — never auto-publish (must opt in via --publish)
     *
     * `tag` is a default value for `--publish-tag` when not passed at the CLI.
     */
    publish: z
        .object({
        auto: z.enum(["always", "full-runs", "never"]).optional(),
        tag: z.string().optional(),
    })
        .optional(),
    /**
     * Report store configuration (W0077 Phase 6e). Replaces the top-level
     * `reportDataset` and `reportProjectId` fields. Mirrors `RepoConfigSchema`'s
     * `reportStore` block for the auto-loaded `.ailf/config.yaml` path.
     */
    reportStore: z
        .object({
        projectId: z.string().optional(),
        dataset: z.string().optional(),
    })
        .optional(),
    /** Search mode for agentic mode */
    searchMode: z.enum(["off", "open", "origin-only"]).optional(),
    /** Skip eval step */
    skipEval: z.boolean().optional(),
    /** Skip fetch-docs step */
    skipFetch: z.boolean().optional(),
    /** Documentation source name */
    source: z.string().optional(),
    /**
     * Post-run diagnosis summary policy (Phase 6 / DIAG-06). Mirrors
     * `RepoConfigSchema`'s `summary` block for `--config <path>` parity.
     * Precedence resolved at the CLI layer by `shouldRunPostSummary()`.
     */
    summary: z
        .object({ onRun: z.enum(["auto", "always", "never"]).optional() })
        .optional(),
    /** Task ID filter */
    tasks: z.array(z.string()).optional(),
    /** Doc source URL overrides */
    urls: z.array(z.string().url()).optional(),
    /**
     * External presets to load — file paths or npm package names.
     *
     * Each entry is resolved as:
     *   - Relative path (./foo or ../foo): loaded from disk via jiti
     *   - Package name: resolved via Node require
     *
     * Presets are registered in order after built-in presets.
     */
    presets: z.array(z.string()).optional(),
})
    .strict();
