/**
 * @sanity/ailf-core — Canary task-set schemas.
 *
 * The canary task set is the curated subset of evaluation tasks the Tier 3
 * nightly workflow runs against live LLMs. Each entry pins a `taskId` and
 * `mode` together with a one-paragraph rationale documenting why the task
 * earned a slot — the rationale is the canary set's single most important
 * field; without it, future maintainers can't reason about whether a
 * regression is meaningful or whether the slot has lost value.
 *
 * Validation that canary IDs map to real tasks lives in
 * `scripts/check-canary-tasks.ts` (run by `pnpm check`); it can't live in
 * Zod because the inventory comes from the repo task glob, not the schema.
 *
 * @see docs/design-docs/testing-strategy.md — "Tier 3 — Live LLMs"
 * @see packages/eval/config/canary-tasks.ts — authored config
 */
import { z } from "zod";
import { RAW_EVAL_MODES } from "../../ailf-shared/index.js";
// ---------------------------------------------------------------------------
// Canary entry
// ---------------------------------------------------------------------------
export const CanaryTaskEntrySchema = z.object({
    taskId: z.string().min(1, "canary entries must have a non-empty taskId"),
    mode: z.enum(RAW_EVAL_MODES),
    rationale: z
        .string()
        .min(40, "canary rationale must be at least one informative sentence"),
});
// ---------------------------------------------------------------------------
// Canary set config
// ---------------------------------------------------------------------------
export const CanaryTaskSetConfigSchema = z
    .object({
    tasks: z.array(CanaryTaskEntrySchema),
})
    .refine((config) => {
    const seen = new Set();
    for (const entry of config.tasks) {
        const key = `${entry.mode}:${entry.taskId}`;
        if (seen.has(key))
            return false;
        seen.add(key);
    }
    return true;
}, { message: "duplicate (mode, taskId) entries in canary set" });
