/** * Zod schema for .lyse.yaml — addresses T2 security gap: * both loadConfig sites previously cast YAML via `as` without validation. * * Structurally compatible with LyseConfig in ../types.ts. * The schema intentionally does NOT use .strict() so future fields in * .lyse.yaml don't cause hard failures — unknown keys are stripped silently. */ import { z } from "zod"; import type { LyseConfig } from "../types.js"; export type { LyseConfig } from "../types.js"; export declare const LyseConfigSchema: z.ZodObject<{ designSystem: z.ZodEffects; elements: z.ZodOptional>; excludePaths: z.ZodOptional>; }, "strip", z.ZodTypeAny, { componentsModule?: string | undefined; elements?: Record | undefined; excludePaths?: string[] | undefined; }, { componentsModule?: string | undefined; elements?: Record | undefined; excludePaths?: string[] | undefined; }>>>, { componentsModule?: string | undefined; elements?: Record | undefined; excludePaths?: string[] | undefined; } | undefined, { componentsModule?: string | undefined; elements?: Record | undefined; excludePaths?: string[] | undefined; } | null | undefined>; rules: z.ZodOptional, z.ZodObject<{ severity: z.ZodOptional>; tolerance: z.ZodOptional; disable: z.ZodOptional>; }, "strip", z.ZodTypeAny, { severity?: "error" | "warning" | "info" | "off" | undefined; disable?: string[] | undefined; tolerance?: number | undefined; }, { severity?: "error" | "warning" | "info" | "off" | undefined; disable?: string[] | undefined; tolerance?: number | undefined; }>]>>>; scoring: z.ZodEffects; model: z.ZodOptional>; minSampleSize: z.ZodOptional; }, "strip", z.ZodTypeAny, { aiGovernanceGraceWindow?: number | undefined; model?: "v2" | "v3" | undefined; minSampleSize?: number | undefined; }, { aiGovernanceGraceWindow?: number | undefined; model?: "v2" | "v3" | undefined; minSampleSize?: number | undefined; }>>>, { aiGovernanceGraceWindow?: number | undefined; model?: "v2" | "v3" | undefined; minSampleSize?: number | undefined; } | undefined, { aiGovernanceGraceWindow?: number | undefined; model?: "v2" | "v3" | undefined; minSampleSize?: number | undefined; } | null | undefined>; i18n: z.ZodEffects>; vocabulary: z.ZodOptional>; disclaimerPhrases: z.ZodOptional>; controlLabels: z.ZodOptional>; gatePhrases: z.ZodOptional>; loadingPhrases: z.ZodOptional>; }, "strip", z.ZodTypeAny, { aiNouns?: string[] | undefined; disclaimerPhrases?: string[] | undefined; controlLabels?: string[] | undefined; gatePhrases?: string[] | undefined; loadingPhrases?: string[] | undefined; }, { aiNouns?: string[] | undefined; disclaimerPhrases?: string[] | undefined; controlLabels?: string[] | undefined; gatePhrases?: string[] | undefined; loadingPhrases?: string[] | undefined; }>>; }, "strip", z.ZodTypeAny, { locales?: string[] | undefined; vocabulary?: { aiNouns?: string[] | undefined; disclaimerPhrases?: string[] | undefined; controlLabels?: string[] | undefined; gatePhrases?: string[] | undefined; loadingPhrases?: string[] | undefined; } | undefined; }, { locales?: string[] | undefined; vocabulary?: { aiNouns?: string[] | undefined; disclaimerPhrases?: string[] | undefined; controlLabels?: string[] | undefined; gatePhrases?: string[] | undefined; loadingPhrases?: string[] | undefined; } | undefined; }>>>, { locales?: string[] | undefined; vocabulary?: { aiNouns?: string[] | undefined; disclaimerPhrases?: string[] | undefined; controlLabels?: string[] | undefined; gatePhrases?: string[] | undefined; loadingPhrases?: string[] | undefined; } | undefined; } | undefined, { locales?: string[] | undefined; vocabulary?: { aiNouns?: string[] | undefined; disclaimerPhrases?: string[] | undefined; controlLabels?: string[] | undefined; gatePhrases?: string[] | undefined; loadingPhrases?: string[] | undefined; } | undefined; } | null | undefined>; llm: z.ZodOptional>; model: z.ZodOptional; endpoint: z.ZodOptional; connector: z.ZodOptional>; costCapUsd: z.ZodOptional; cacheMaxAgeDays: z.ZodOptional; staticOnly: z.ZodOptional; }, "strip", z.ZodTypeAny, { model?: string | undefined; provider?: "anthropic" | "openai" | "openai-compatible" | "mcp" | "none" | "auto" | "agent-cli" | undefined; endpoint?: string | undefined; connector?: "auto" | "agent-cli" | "mcp-host" | "openrouter" | "direct-api-key" | "ollama" | undefined; costCapUsd?: number | undefined; cacheMaxAgeDays?: number | undefined; staticOnly?: boolean | undefined; }, { model?: string | undefined; provider?: "anthropic" | "openai" | "openai-compatible" | "mcp" | "none" | "auto" | "agent-cli" | undefined; endpoint?: string | undefined; connector?: "auto" | "agent-cli" | "mcp-host" | "openrouter" | "direct-api-key" | "ollama" | undefined; costCapUsd?: number | undefined; cacheMaxAgeDays?: number | undefined; staticOnly?: boolean | undefined; }>>; advisory: z.ZodOptional; }, "strip", z.ZodTypeAny, { migrationScaleFileCount?: number | undefined; }, { migrationScaleFileCount?: number | undefined; }>>; handoff: z.ZodOptional; }, "strip", z.ZodTypeAny, { review?: boolean | undefined; }, { review?: boolean | undefined; }>>; }, "strip", z.ZodTypeAny, { rules?: Record | undefined; designSystem?: { componentsModule?: string | undefined; elements?: Record | undefined; excludePaths?: string[] | undefined; } | undefined; scoring?: { aiGovernanceGraceWindow?: number | undefined; model?: "v2" | "v3" | undefined; minSampleSize?: number | undefined; } | undefined; i18n?: { locales?: string[] | undefined; vocabulary?: { aiNouns?: string[] | undefined; disclaimerPhrases?: string[] | undefined; controlLabels?: string[] | undefined; gatePhrases?: string[] | undefined; loadingPhrases?: string[] | undefined; } | undefined; } | undefined; llm?: { model?: string | undefined; provider?: "anthropic" | "openai" | "openai-compatible" | "mcp" | "none" | "auto" | "agent-cli" | undefined; endpoint?: string | undefined; connector?: "auto" | "agent-cli" | "mcp-host" | "openrouter" | "direct-api-key" | "ollama" | undefined; costCapUsd?: number | undefined; cacheMaxAgeDays?: number | undefined; staticOnly?: boolean | undefined; } | undefined; advisory?: { migrationScaleFileCount?: number | undefined; } | undefined; handoff?: { review?: boolean | undefined; } | undefined; }, { rules?: Record | undefined; designSystem?: { componentsModule?: string | undefined; elements?: Record | undefined; excludePaths?: string[] | undefined; } | null | undefined; scoring?: { aiGovernanceGraceWindow?: number | undefined; model?: "v2" | "v3" | undefined; minSampleSize?: number | undefined; } | null | undefined; i18n?: { locales?: string[] | undefined; vocabulary?: { aiNouns?: string[] | undefined; disclaimerPhrases?: string[] | undefined; controlLabels?: string[] | undefined; gatePhrases?: string[] | undefined; loadingPhrases?: string[] | undefined; } | undefined; } | null | undefined; llm?: { model?: string | undefined; provider?: "anthropic" | "openai" | "openai-compatible" | "mcp" | "none" | "auto" | "agent-cli" | undefined; endpoint?: string | undefined; connector?: "auto" | "agent-cli" | "mcp-host" | "openrouter" | "direct-api-key" | "ollama" | undefined; costCapUsd?: number | undefined; cacheMaxAgeDays?: number | undefined; staticOnly?: boolean | undefined; } | undefined; advisory?: { migrationScaleFileCount?: number | undefined; } | undefined; handoff?: { review?: boolean | undefined; } | undefined; }>; export type LyseConfigValidated = z.infer; /** * Validate raw YAML output as a LyseConfig without throwing. * Returns { ok: true, value } on success or { ok: false, error } with a * semicolon-separated list of validation issues on failure. */ export declare function safeParseLyseConfig(raw: unknown): { ok: true; value: LyseConfigValidated; } | { ok: false; error: string; }; export interface LoadConfigOptions { /** * Error handling strategy: * - "throw" (default): throw on invalid YAML or Zod validation failure. * - "degrade": log to stderr and return empty config on any error. */ onError?: "throw" | "degrade"; } /** * Load and validate .lyse.yaml for a given repository root. * * Respects the LYSE_CONFIG_PATH env var (set by --config flag) to override * the default `.lyse.yaml` discovery path. * * @param repoRoot - Absolute path to the repository root. * @param opts - Options. Default: { onError: "throw" }. */ export declare function loadConfig(repoRoot: string, opts?: LoadConfigOptions): LyseConfig; /** * Resolve where the .lyse.yaml WOULD be loaded from for this repo root, if at all. * Returns the absolute path when a config file is discoverable, or `null` when * no config file is present. Does NOT parse or validate the contents. * * Mirrors the discovery logic of `loadConfig` (LYSE_CONFIG_PATH > .lyse.yaml at root) * so the value reported in `AuditResult.meta.coverage.configPath` matches the file * `loadConfig` would actually read. */ export declare function resolveConfigPath(repoRoot: string): string | null;