/**
 * 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 blocks shared with `RepoConfigSchema` (.ailf/config.yaml) are
 * composed from `./config-blocks.ts` (D0060) — defined once, drift is a
 * compile error. Run-only selectors (areas/tasks/mode/compare/…) stay
 * local to this wrapper; `source` accepts a named-source string or the
 * shared inline-location object.
 *
 * 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";
import { AgenticConfigSchema, ArtifactsConfigSchema, ExecutionConfigSchema, GraderConfigSchema, OutputConfigSchema, PublishConfigSchema, ReportStoreConfigSchema, SourceSettingSchema, SummaryConfigSchema, TaskSourceConfigSchema, } from "./config-blocks.js";
import { GeneralizedDocRefSchema } from "./doc-ref.js";
export const EvalConfigSchema = z
    .object({
    /**
     * Optional JSON-Schema annotation (D0090). A committed config may set
     * `"$schema": "…/docs/schemas/eval-config.schema.json"` so editors give
     * autocomplete + validation. The schema is `.strict()`, so this field is
     * declared explicitly to keep that editor annotation from failing the
     * runtime parse; it carries no runtime meaning and is ignored downstream.
     * It is also emitted into the published JSON Schema's properties, so a
     * config carrying `$schema` validates against the schema it points at.
     */
    $schema: z.string().optional(),
    /**
     * Agentic-mode configuration — shared block (see config-blocks.ts).
     * Replaces the top-level `headers` and `allowedOrigins` fields.
     */
    agentic: AgenticConfigSchema.optional(),
    /**
     * Artifact-writer configuration — shared block (see config-blocks.ts).
     * Replaces the retired `--no-artifacts`, `--artifacts-dir`, and
     * `--artifacts-exclude` CLI flags.
     */
    artifacts: ArtifactsConfigSchema.optional(),
    /**
     * Task-source configuration — shared block (see config-blocks.ts).
     * Replaces the retired `--task-source` and `--repo-tasks-path` CLI
     * flags.
     */
    taskSource: TaskSourceConfigSchema.optional(),
    /** Feature area filter (comma-separated or array) */
    areas: z.array(z.string()).optional(),
    /**
     * Changed documents for impact scoping (D0090). A `string` entry keeps
     * exact slug-match semantics; a `GeneralizedDocRef` entry matches on its
     * strongest key (id → path → slug) in `filterByChangedDocs`. This is the
     * SAME widened union `PipelineRequest.changedDocs` accepts, so a committed
     * `--config` file and the API body carry identical references. A legacy
     * bare-slug array (`["groq-intro"]`) validates unchanged.
     */
    changedDocs: z
        .array(z.union([z.string(), GeneralizedDocRefSchema]))
        .optional(),
    /**
     * Robust document references injected into every selected task's context
     * (D0090). Additive per-task context injection — distinct from the
     * `changedDocs` task-pool filter. Same `GeneralizedDocRef[]` type
     * `PipelineRequest.injectContextDocs` accepts; each entry may carry an
     * optional embedded `SourceLocator` for cross-source / cross-project
     * pinning. Omitted means no injection (back-compat for every existing
     * config).
     */
    injectContextDocs: z.array(GeneralizedDocRefSchema).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 — shared block (see config-blocks.ts).
     * Replaces the top-level `concurrency`, `gapAnalysis`, and
     * `graderReplications` fields and adds `apiUrl` to the same group.
     */
    execution: ExecutionConfigSchema.optional(),
    /** Grader configuration — shared block (see config-blocks.ts). */
    grader: GraderConfigSchema.optional(),
    /**
     * Output configuration — shared block (see config-blocks.ts).
     * 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: OutputConfigSchema.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 — shared block (see config-blocks.ts). The CLI
     * `--publish` and `--no-publish` flags override the policy at runtime;
     * this field controls behavior when no explicit flag is passed.
     */
    publish: PublishConfigSchema.optional(),
    /**
     * Report store configuration — shared field set (see
     * config-blocks.ts) with `.partial()` applied: unlike
     * `RepoConfigSchema`, both fields are optional here. Replaces the
     * top-level `reportDataset` and `reportProjectId` fields.
     */
    reportStore: ReportStoreConfigSchema.partial().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 — shared union block (see config-blocks.ts):
     * either the NAME of a registered source (string) or the same
     * inline-location object `RepoConfig.source` uses (D0060 mitigation
     * #2), so a source block copied from `.ailf/ailf.config.ts` into a
     * `--config` file stays valid. The `--config` resolver branches on
     * the type: a string sets `ResolvedConfig.source`; an object routes
     * into the `*Override` fields read by `configToSourceOverrides`.
     */
    source: SourceSettingSchema.optional(),
    /**
     * Post-run diagnosis summary policy — shared block (see
     * config-blocks.ts). Precedence resolved at the CLI layer by
     * `shouldRunPostSummary()`.
     */
    summary: SummaryConfigSchema.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();
