@agentv/core 0.23.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/evaluation/validation/file-type.ts","../../../src/evaluation/validation/eval-validator.ts","../../../src/evaluation/validation/targets-validator.ts","../../../src/evaluation/validation/config-validator.ts","../../../src/evaluation/validation/file-reference-validator.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from 'yaml';\n\nimport type { FileType } from './types.js';\n\nconst SCHEMA_EVAL_V2 = 'agentv-eval-v2';\nconst SCHEMA_TARGETS_V2 = 'agentv-targets-v2.2';\nconst SCHEMA_CONFIG_V2 = 'agentv-config-v2';\n\n/**\n * Detect file type by reading $schema field from YAML file.\n * If $schema is missing, infers type from filename/path:\n * - config.yaml under .agentv folder → 'config'\n * - targets.yaml under .agentv folder → 'targets'\n * - All other YAML files → 'eval' (default)\n */\nexport async function detectFileType(filePath: string): Promise<FileType> {\n try {\n const content = await readFile(filePath, 'utf8');\n const parsed = parse(content) as unknown;\n\n if (typeof parsed !== 'object' || parsed === null) {\n return inferFileTypeFromPath(filePath);\n }\n\n const record = parsed as Record<string, unknown>;\n const schema = record.$schema;\n\n if (typeof schema !== 'string') {\n // No $schema field - infer from path\n return inferFileTypeFromPath(filePath);\n }\n\n switch (schema) {\n case SCHEMA_EVAL_V2:\n return 'eval';\n case SCHEMA_TARGETS_V2:\n return 'targets';\n case SCHEMA_CONFIG_V2:\n return 'config';\n default:\n // Unknown schema - infer from path\n return inferFileTypeFromPath(filePath);\n }\n } catch {\n return inferFileTypeFromPath(filePath);\n }\n}\n\n/**\n * Infer file type from filename and directory path.\n */\nfunction inferFileTypeFromPath(filePath: string): FileType {\n const normalized = path.normalize(filePath).replace(/\\\\/g, '/');\n const basename = path.basename(filePath);\n\n // Check if file is under .agentv folder\n if (normalized.includes('/.agentv/')) {\n if (basename === 'config.yaml' || basename === 'config.yml') {\n return 'config';\n }\n if (basename === 'targets.yaml' || basename === 'targets.yml') {\n return 'targets';\n }\n }\n\n // Default to eval file\n return 'eval';\n}\n\n/**\n * Check if a schema value is a valid AgentV schema identifier.\n */\nexport function isValidSchema(schema: unknown): boolean {\n return schema === SCHEMA_EVAL_V2 || schema === SCHEMA_TARGETS_V2 || schema === SCHEMA_CONFIG_V2;\n}\n\n/**\n * Get the expected schema for a file type.\n */\nexport function getExpectedSchema(fileType: FileType): string | undefined {\n switch (fileType) {\n case 'eval':\n return SCHEMA_EVAL_V2;\n case 'targets':\n return SCHEMA_TARGETS_V2;\n case 'config':\n return SCHEMA_CONFIG_V2;\n default:\n return undefined;\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from 'yaml';\n\nimport type { ValidationError, ValidationResult } from './types.js';\n\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\ntype JsonObject = { readonly [key: string]: JsonValue };\ntype JsonArray = readonly JsonValue[];\n\nfunction isObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Validate an eval file (agentv-eval-v2 schema).\n */\nexport async function validateEvalFile(filePath: string): Promise<ValidationResult> {\n const errors: ValidationError[] = [];\n const absolutePath = path.resolve(filePath);\n\n let parsed: unknown;\n try {\n const content = await readFile(absolutePath, 'utf8');\n parsed = parse(content);\n } catch (error) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: `Failed to parse YAML: ${(error as Error).message}`,\n });\n return {\n valid: false,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\n };\n }\n\n if (!isObject(parsed)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: 'File must contain a YAML object',\n });\n return {\n valid: false,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\n };\n }\n\n // Validate evalcases array\n const evalcases = parsed.evalcases;\n if (!Array.isArray(evalcases)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: 'evalcases',\n message: \"Missing or invalid 'evalcases' field (must be an array)\",\n });\n return {\n valid: errors.length === 0,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\n };\n }\n\n // Validate each eval case\n for (let i = 0; i < evalcases.length; i++) {\n const evalCase = evalcases[i];\n const location = `evalcases[${i}]`;\n\n if (!isObject(evalCase)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: 'Eval case must be an object',\n });\n continue;\n }\n\n // Required fields: id, input_messages, expected_messages\n const id = evalCase.id;\n if (typeof id !== 'string' || id.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.id`,\n message: \"Missing or invalid 'id' field (must be a non-empty string)\",\n });\n }\n\n // Optional: expected_outcome or outcome for backward compatibility\n const expectedOutcome = evalCase.expected_outcome ?? evalCase.outcome;\n if (\n expectedOutcome !== undefined &&\n (typeof expectedOutcome !== 'string' || expectedOutcome.trim().length === 0)\n ) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.expected_outcome`,\n message:\n \"Invalid 'expected_outcome' or 'outcome' field (must be a non-empty string if provided)\",\n });\n }\n\n const inputMessages = evalCase.input_messages;\n if (!Array.isArray(inputMessages)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.input_messages`,\n message: \"Missing or invalid 'input_messages' field (must be an array)\",\n });\n } else {\n validateMessages(inputMessages, `${location}.input_messages`, absolutePath, errors);\n }\n\n // expected_messages is optional - for outcome-only evaluation\n const expectedMessages = evalCase.expected_messages;\n if (expectedMessages !== undefined && !Array.isArray(expectedMessages)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.expected_messages`,\n message: \"Invalid 'expected_messages' field (must be an array if provided)\",\n });\n } else if (Array.isArray(expectedMessages)) {\n validateMessages(expectedMessages, `${location}.expected_messages`, absolutePath, errors);\n }\n }\n\n return {\n valid: errors.length === 0,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\n };\n}\n\nfunction validateMessages(\n messages: JsonArray,\n location: string,\n filePath: string,\n errors: ValidationError[],\n): void {\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i];\n const msgLocation = `${location}[${i}]`;\n\n if (!isObject(message)) {\n errors.push({\n severity: 'error',\n filePath,\n location: msgLocation,\n message: 'Message must be an object',\n });\n continue;\n }\n\n // Validate role field\n const role = message.role;\n const validRoles = ['system', 'user', 'assistant'];\n if (!validRoles.includes(role as string)) {\n errors.push({\n severity: 'error',\n filePath,\n location: `${msgLocation}.role`,\n message: `Invalid role '${role}'. Must be one of: ${validRoles.join(', ')}`,\n });\n }\n\n // Validate content field (can be string or array)\n const content = message.content;\n if (typeof content === 'string') {\n validateContentForRoleMarkers(content, `${msgLocation}.content`, filePath, errors);\n } else if (Array.isArray(content)) {\n // Array content - validate each element\n for (let j = 0; j < content.length; j++) {\n const contentItem = content[j];\n const contentLocation = `${msgLocation}.content[${j}]`;\n\n if (typeof contentItem === 'string') {\n validateContentForRoleMarkers(contentItem, contentLocation, filePath, errors);\n } else if (isObject(contentItem)) {\n const type = contentItem.type;\n if (typeof type !== 'string') {\n errors.push({\n severity: 'error',\n filePath,\n location: `${contentLocation}.type`,\n message: \"Content object must have a 'type' field\",\n });\n }\n\n // For 'file' type, we'll validate existence later in file-reference-validator\n // For 'text' type, require 'value' field\n if (type === 'text') {\n const value = contentItem.value;\n if (typeof value !== 'string') {\n errors.push({\n severity: 'error',\n filePath,\n location: `${contentLocation}.value`,\n message: \"Content with type 'text' must have a 'value' field\",\n });\n } else {\n validateContentForRoleMarkers(value, `${contentLocation}.value`, filePath, errors);\n }\n }\n } else {\n errors.push({\n severity: 'error',\n filePath,\n location: contentLocation,\n message: 'Content array items must be strings or objects',\n });\n }\n }\n } else {\n errors.push({\n severity: 'error',\n filePath,\n location: `${msgLocation}.content`,\n message: \"Missing or invalid 'content' field (must be a string or array)\",\n });\n }\n }\n}\n\nfunction validateContentForRoleMarkers(\n content: string,\n location: string,\n filePath: string,\n errors: ValidationError[],\n): void {\n // Check for standard role markers that might confuse agentic providers\n const markers = ['@[System]:', '@[User]:', '@[Assistant]:', '@[Tool]:'];\n for (const marker of markers) {\n if (content.toLowerCase().includes(marker.toLowerCase())) {\n errors.push({\n severity: 'warning',\n filePath,\n location,\n message: `Content contains potential role marker '${marker}'. This may confuse agentic providers or cause prompt injection.`,\n });\n }\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from 'yaml';\n\nimport { CLI_PLACEHOLDERS } from '../providers/targets.js';\nimport { KNOWN_PROVIDERS, PROVIDER_ALIASES, TARGETS_SCHEMA_V2 } from '../providers/types.js';\nimport type { ValidationError, ValidationResult } from './types.js';\n\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\ntype JsonObject = { readonly [key: string]: JsonValue };\ntype JsonArray = readonly JsonValue[];\n\nfunction isObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n// Known settings properties for each provider type\nconst COMMON_SETTINGS = new Set(['provider_batching', 'providerBatching']);\n\nconst RETRY_SETTINGS = new Set([\n 'max_retries',\n 'maxRetries',\n 'retry_initial_delay_ms',\n 'retryInitialDelayMs',\n 'retry_max_delay_ms',\n 'retryMaxDelayMs',\n 'retry_backoff_factor',\n 'retryBackoffFactor',\n 'retry_status_codes',\n 'retryStatusCodes',\n]);\n\nconst AZURE_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n ...RETRY_SETTINGS,\n 'endpoint',\n 'resource',\n 'resourceName',\n 'api_key',\n 'apiKey',\n 'deployment',\n 'deploymentName',\n 'model',\n 'version',\n 'api_version',\n 'temperature',\n 'max_output_tokens',\n 'maxTokens',\n]);\n\nconst ANTHROPIC_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n ...RETRY_SETTINGS,\n 'api_key',\n 'apiKey',\n 'model',\n 'deployment',\n 'variant',\n 'temperature',\n 'max_output_tokens',\n 'maxTokens',\n 'thinking_budget',\n 'thinkingBudget',\n]);\n\nconst GEMINI_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n ...RETRY_SETTINGS,\n 'api_key',\n 'apiKey',\n 'model',\n 'deployment',\n 'variant',\n 'temperature',\n 'max_output_tokens',\n 'maxTokens',\n]);\n\nconst CODEX_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'executable',\n 'command',\n 'binary',\n 'args',\n 'arguments',\n 'cwd',\n 'timeout_seconds',\n 'timeoutSeconds',\n 'log_dir',\n 'logDir',\n 'log_directory',\n 'logDirectory',\n 'log_format',\n 'logFormat',\n 'log_output_format',\n 'logOutputFormat',\n]);\n\nconst VSCODE_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'workspace_template',\n 'workspaceTemplate',\n 'vscode_cmd',\n 'command',\n 'wait',\n 'dry_run',\n 'dryRun',\n 'subagent_root',\n 'subagentRoot',\n]);\n\nconst MOCK_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'response',\n 'delayMs',\n 'delayMinMs',\n 'delayMaxMs',\n]);\n\nconst CLI_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'command_template',\n 'commandTemplate',\n 'files_format',\n 'filesFormat',\n 'attachments_format',\n 'attachmentsFormat',\n 'cwd',\n 'env',\n 'timeout_seconds',\n 'timeoutSeconds',\n 'healthcheck',\n]);\n\nfunction getKnownSettings(provider: string): Set<string> | null {\n const normalizedProvider = provider.toLowerCase();\n switch (normalizedProvider) {\n case 'azure':\n case 'azure-openai':\n return AZURE_SETTINGS;\n case 'anthropic':\n return ANTHROPIC_SETTINGS;\n case 'gemini':\n case 'google':\n case 'google-gemini':\n return GEMINI_SETTINGS;\n case 'codex':\n case 'codex-cli':\n return CODEX_SETTINGS;\n case 'vscode':\n case 'vscode-insiders':\n return VSCODE_SETTINGS;\n case 'mock':\n return MOCK_SETTINGS;\n case 'cli':\n return CLI_SETTINGS;\n default:\n return null; // Unknown provider, can't validate settings\n }\n}\n\nfunction validateUnknownSettings(\n target: JsonObject,\n provider: string,\n absolutePath: string,\n location: string,\n errors: ValidationError[],\n): void {\n const knownSettings = getKnownSettings(provider);\n if (!knownSettings) {\n // Unknown provider, skip settings validation\n return;\n }\n\n // Known base target fields that aren't settings\n const baseFields = new Set(['name', 'provider', 'judge_target', 'workers', '$schema', 'targets']);\n\n for (const key of Object.keys(target)) {\n if (!baseFields.has(key) && !knownSettings.has(key)) {\n errors.push({\n severity: 'warning',\n filePath: absolutePath,\n location: `${location}.${key}`,\n message: `Unknown setting '${key}' for ${provider} provider. This property will be ignored.`,\n });\n }\n }\n}\n\n/**\n * Validate a targets file (agentv-targets-v2.1 schema).\n */\nexport async function validateTargetsFile(filePath: string): Promise<ValidationResult> {\n const errors: ValidationError[] = [];\n const absolutePath = path.resolve(filePath);\n\n let parsed: unknown;\n try {\n const content = await readFile(absolutePath, 'utf8');\n parsed = parse(content);\n } catch (error) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: `Failed to parse YAML: ${(error as Error).message}`,\n });\n return {\n valid: false,\n filePath: absolutePath,\n fileType: 'targets',\n errors,\n };\n }\n\n function validateCliSettings(\n target: JsonObject,\n absolutePath: string,\n location: string,\n errors: ValidationError[],\n ): void {\n const commandTemplate = target.command_template ?? target.commandTemplate;\n if (typeof commandTemplate !== 'string' || commandTemplate.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.commandTemplate`,\n message: \"CLI provider requires 'commandTemplate' as a non-empty string\",\n });\n } else {\n recordUnknownPlaceholders(\n commandTemplate,\n absolutePath,\n `${location}.commandTemplate`,\n errors,\n );\n }\n\n const attachmentsFormat = target.attachments_format ?? target.attachmentsFormat;\n if (attachmentsFormat !== undefined && typeof attachmentsFormat !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.attachmentsFormat`,\n message: \"'attachmentsFormat' must be a string when provided\",\n });\n }\n\n const filesFormat = target.files_format ?? target.filesFormat;\n if (filesFormat !== undefined && typeof filesFormat !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.filesFormat`,\n message: \"'filesFormat' must be a string when provided\",\n });\n }\n\n const cwd = target.cwd;\n if (cwd !== undefined && typeof cwd !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.cwd`,\n message: \"'cwd' must be a string when provided\",\n });\n }\n\n const timeoutSeconds = target.timeout_seconds ?? target.timeoutSeconds;\n if (timeoutSeconds !== undefined) {\n const numericTimeout = Number(timeoutSeconds);\n if (!Number.isFinite(numericTimeout) || numericTimeout <= 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.timeoutSeconds`,\n message: \"'timeoutSeconds' must be a positive number when provided\",\n });\n }\n }\n\n const healthcheck = target.healthcheck;\n if (healthcheck !== undefined) {\n validateCliHealthcheck(healthcheck, absolutePath, `${location}.healthcheck`, errors);\n }\n }\n\n function validateCliHealthcheck(\n healthcheck: unknown,\n absolutePath: string,\n location: string,\n errors: ValidationError[],\n ): void {\n if (!isObject(healthcheck)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: \"'healthcheck' must be an object when provided\",\n });\n return;\n }\n\n const type = healthcheck.type;\n if (type !== 'http' && type !== 'command') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.type`,\n message: \"healthcheck.type must be either 'http' or 'command'\",\n });\n return;\n }\n\n const timeoutSeconds = healthcheck.timeout_seconds ?? healthcheck.timeoutSeconds;\n if (timeoutSeconds !== undefined) {\n const numericTimeout = Number(timeoutSeconds);\n if (!Number.isFinite(numericTimeout) || numericTimeout <= 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.timeoutSeconds`,\n message: 'healthcheck.timeoutSeconds must be a positive number when provided',\n });\n }\n }\n\n if (type === 'http') {\n const url = healthcheck.url;\n if (typeof url !== 'string' || url.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.url`,\n message: 'healthcheck.url must be a non-empty string for http checks',\n });\n }\n return;\n }\n\n const commandTemplate = healthcheck.command_template ?? healthcheck.commandTemplate;\n if (typeof commandTemplate !== 'string' || commandTemplate.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.commandTemplate`,\n message: 'healthcheck.commandTemplate must be a non-empty string for command checks',\n });\n } else {\n recordUnknownPlaceholders(\n commandTemplate,\n absolutePath,\n `${location}.commandTemplate`,\n errors,\n );\n }\n\n const cwd = healthcheck.cwd;\n if (cwd !== undefined && typeof cwd !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.cwd`,\n message: 'healthcheck.cwd must be a string when provided',\n });\n }\n }\n\n function recordUnknownPlaceholders(\n template: string,\n absolutePath: string,\n location: string,\n errors: ValidationError[],\n ): void {\n const placeholders = extractPlaceholders(template);\n for (const placeholder of placeholders) {\n if (!CLI_PLACEHOLDERS.has(placeholder)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: `Unknown CLI placeholder '{${placeholder}}'. Supported placeholders: ${Array.from(CLI_PLACEHOLDERS).join(', ')}`,\n });\n }\n }\n }\n\n function extractPlaceholders(template: string): string[] {\n const matches = template.matchAll(/\\{([A-Z_]+)\\}/g);\n const result: string[] = [];\n for (const match of matches) {\n const placeholder = match[1];\n if (placeholder) {\n result.push(placeholder);\n }\n }\n return result;\n }\n\n if (!isObject(parsed)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: 'File must contain a YAML object',\n });\n return {\n valid: false,\n filePath: absolutePath,\n fileType: 'targets',\n errors,\n };\n }\n\n // Validate targets array\n const targets = parsed.targets;\n if (!Array.isArray(targets)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: 'targets',\n message: \"Missing or invalid 'targets' field (must be an array)\",\n });\n return {\n valid: errors.length === 0,\n filePath: absolutePath,\n fileType: 'targets',\n errors,\n };\n }\n\n // Validate each target definition\n const knownProviders = [...KNOWN_PROVIDERS, ...PROVIDER_ALIASES];\n\n for (let i = 0; i < targets.length; i++) {\n const target = targets[i];\n const location = `targets[${i}]`;\n\n if (!isObject(target)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: 'Target must be an object',\n });\n continue;\n }\n\n // Required field: name\n const name = target.name;\n if (typeof name !== 'string' || name.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.name`,\n message: \"Missing or invalid 'name' field (must be a non-empty string)\",\n });\n }\n\n // Required field: provider\n const provider = target.provider;\n const providerValue = typeof provider === 'string' ? provider.trim().toLowerCase() : undefined;\n if (typeof provider !== 'string' || provider.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.provider`,\n message: \"Missing or invalid 'provider' field (must be a non-empty string)\",\n });\n } else if (!knownProviders.includes(provider)) {\n // Warning for unknown providers (non-fatal)\n errors.push({\n severity: 'warning',\n filePath: absolutePath,\n location: `${location}.provider`,\n message: `Unknown provider '${provider}'. Known providers: ${knownProviders.join(', ')}`,\n });\n }\n\n // Validate CLI provider fields\n if (providerValue === 'cli') {\n validateCliSettings(target, absolutePath, location, errors);\n }\n\n // Check for unknown settings properties on target object\n if (typeof provider === 'string') {\n validateUnknownSettings(target, provider, absolutePath, location, errors);\n }\n\n // Optional field: judge_target (must be string if present)\n const judgeTarget = target.judge_target;\n if (judgeTarget !== undefined && typeof judgeTarget !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.judge_target`,\n message: \"Invalid 'judge_target' field (must be a string)\",\n });\n }\n }\n\n return {\n valid: errors.filter((e) => e.severity === 'error').length === 0,\n filePath: absolutePath,\n fileType: 'targets',\n errors,\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport { parse } from 'yaml';\n\nimport type { ValidationError, ValidationResult } from './types.js';\n\nconst SCHEMA_CONFIG_V2 = 'agentv-config-v2';\n\n/**\n * Validate a config.yaml file for schema compliance and structural correctness.\n */\nexport async function validateConfigFile(filePath: string): Promise<ValidationResult> {\n const errors: ValidationError[] = [];\n\n try {\n const content = await readFile(filePath, 'utf8');\n const parsed = parse(content) as unknown;\n\n // Check if parsed content is an object\n if (typeof parsed !== 'object' || parsed === null) {\n errors.push({\n severity: 'error',\n filePath,\n message: 'Config file must contain a valid YAML object',\n });\n return { valid: false, filePath, fileType: 'config', errors };\n }\n\n const config = parsed as Record<string, unknown>;\n\n // Validate $schema field (optional, but if present must be correct)\n const schema = config.$schema;\n if (schema !== undefined && schema !== SCHEMA_CONFIG_V2) {\n const message = `Invalid $schema value '${schema}'. Expected '${SCHEMA_CONFIG_V2}' or omit the field.`;\n errors.push({\n severity: 'error',\n filePath,\n location: '$schema',\n message,\n });\n }\n\n // Validate guideline_patterns if present\n const guidelinePatterns = config.guideline_patterns;\n if (guidelinePatterns !== undefined) {\n if (!Array.isArray(guidelinePatterns)) {\n errors.push({\n severity: 'error',\n filePath,\n location: 'guideline_patterns',\n message: \"Field 'guideline_patterns' must be an array\",\n });\n } else if (!guidelinePatterns.every((p) => typeof p === 'string')) {\n errors.push({\n severity: 'error',\n filePath,\n location: 'guideline_patterns',\n message: \"All entries in 'guideline_patterns' must be strings\",\n });\n } else if (guidelinePatterns.length === 0) {\n errors.push({\n severity: 'warning',\n filePath,\n location: 'guideline_patterns',\n message: \"Field 'guideline_patterns' is empty. Consider removing it or adding patterns.\",\n });\n }\n }\n\n // Check for unexpected fields\n const allowedFields = new Set(['$schema', 'guideline_patterns']);\n const unexpectedFields = Object.keys(config).filter((key) => !allowedFields.has(key));\n\n if (unexpectedFields.length > 0) {\n errors.push({\n severity: 'warning',\n filePath,\n message: `Unexpected fields: ${unexpectedFields.join(', ')}`,\n });\n }\n\n return {\n valid: errors.filter((e) => e.severity === 'error').length === 0,\n filePath,\n fileType: 'config',\n errors,\n };\n } catch (error) {\n errors.push({\n severity: 'error',\n filePath,\n message: `Failed to parse config file: ${(error as Error).message}`,\n });\n return { valid: false, filePath, fileType: 'config', errors };\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from 'yaml';\n\nimport { buildSearchRoots, findGitRoot, resolveFileReference } from '../file-utils.js';\nimport type { ValidationError } from './types.js';\n\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\ntype JsonObject = { readonly [key: string]: JsonValue };\ntype JsonArray = readonly JsonValue[];\n\nfunction isObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Validate that file references in eval file content exist.\n * Checks content blocks with type: \"file\" and validates the referenced file exists.\n * Also checks that referenced files are not empty.\n */\nexport async function validateFileReferences(\n evalFilePath: string,\n): Promise<readonly ValidationError[]> {\n const errors: ValidationError[] = [];\n const absolutePath = path.resolve(evalFilePath);\n\n // Find git root and build search roots (same as yaml-parser does at runtime)\n const gitRoot = await findGitRoot(absolutePath);\n if (!gitRoot) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: 'Cannot validate file references: git repository root not found',\n });\n return errors;\n }\n\n const searchRoots = buildSearchRoots(absolutePath, gitRoot);\n\n let parsed: unknown;\n try {\n const content = await readFile(absolutePath, 'utf8');\n parsed = parse(content);\n } catch {\n // Parse errors are already caught by eval-validator\n return errors;\n }\n\n if (!isObject(parsed)) {\n return errors;\n }\n\n const evalcases = parsed.evalcases;\n if (!Array.isArray(evalcases)) {\n return errors;\n }\n\n for (let i = 0; i < evalcases.length; i++) {\n const evalCase = evalcases[i];\n if (!isObject(evalCase)) {\n continue;\n }\n\n // Check input_messages\n const inputMessages = evalCase.input_messages;\n if (Array.isArray(inputMessages)) {\n await validateMessagesFileRefs(\n inputMessages,\n `evalcases[${i}].input_messages`,\n searchRoots,\n absolutePath,\n errors,\n );\n }\n\n // Check expected_messages\n const expectedMessages = evalCase.expected_messages;\n if (Array.isArray(expectedMessages)) {\n await validateMessagesFileRefs(\n expectedMessages,\n `evalcases[${i}].expected_messages`,\n searchRoots,\n absolutePath,\n errors,\n );\n }\n }\n\n return errors;\n}\n\nasync function validateMessagesFileRefs(\n messages: JsonArray,\n location: string,\n searchRoots: readonly string[],\n filePath: string,\n errors: ValidationError[],\n): Promise<void> {\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i];\n if (!isObject(message)) {\n continue;\n }\n\n const content = message.content;\n if (typeof content === 'string') {\n continue;\n }\n\n if (!Array.isArray(content)) {\n continue;\n }\n\n for (let j = 0; j < content.length; j++) {\n const contentItem = content[j];\n if (!isObject(contentItem)) {\n continue;\n }\n\n const type = contentItem.type;\n if (type !== 'file') {\n continue;\n }\n\n const value = contentItem.value;\n if (typeof value !== 'string') {\n errors.push({\n severity: 'error',\n filePath,\n location: `${location}[${i}].content[${j}].value`,\n message: \"File reference must have a 'value' field with the file path\",\n });\n continue;\n }\n\n // Use the same file resolution logic as yaml-parser at runtime\n const { resolvedPath } = await resolveFileReference(value, searchRoots);\n\n if (!resolvedPath) {\n errors.push({\n severity: 'error',\n filePath,\n location: `${location}[${i}].content[${j}]`,\n message: `Referenced file not found: ${value}`,\n });\n } else {\n // Check that file is not empty\n try {\n const fileContent = await readFile(resolvedPath, 'utf8');\n if (fileContent.trim().length === 0) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${location}[${i}].content[${j}]`,\n message: `Referenced file is empty: ${value}`,\n });\n }\n } catch (error) {\n errors.push({\n severity: 'error',\n filePath,\n location: `${location}[${i}].content[${j}]`,\n message: `Cannot read referenced file: ${value} (${(error as Error).message})`,\n });\n }\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;AAAA,SAAS,gBAAgB;AACzB,OAAO,UAAU;AACjB,SAAS,aAAa;AAItB,IAAM,iBAAiB;AACvB,IAAM,oBAAoB;AAC1B,IAAM,mBAAmB;AASzB,eAAsB,eAAe,UAAqC;AACxE,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,UAAU,MAAM;AAC/C,UAAM,SAAS,MAAM,OAAO;AAE5B,QAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,aAAO,sBAAsB,QAAQ;AAAA,IACvC;AAEA,UAAM,SAAS;AACf,UAAM,SAAS,OAAO;AAEtB,QAAI,OAAO,WAAW,UAAU;AAE9B,aAAO,sBAAsB,QAAQ;AAAA,IACvC;AAEA,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AAEE,eAAO,sBAAsB,QAAQ;AAAA,IACzC;AAAA,EACF,QAAQ;AACN,WAAO,sBAAsB,QAAQ;AAAA,EACvC;AACF;AAKA,SAAS,sBAAsB,UAA4B;AACzD,QAAM,aAAa,KAAK,UAAU,QAAQ,EAAE,QAAQ,OAAO,GAAG;AAC9D,QAAM,WAAW,KAAK,SAAS,QAAQ;AAGvC,MAAI,WAAW,SAAS,WAAW,GAAG;AACpC,QAAI,aAAa,iBAAiB,aAAa,cAAc;AAC3D,aAAO;AAAA,IACT;AACA,QAAI,aAAa,kBAAkB,aAAa,eAAe;AAC7D,aAAO;AAAA,IACT;AAAA,EACF;AAGA,SAAO;AACT;AAKO,SAAS,cAAc,QAA0B;AACtD,SAAO,WAAW,kBAAkB,WAAW,qBAAqB,WAAW;AACjF;AAKO,SAAS,kBAAkB,UAAwC;AACxE,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;;;AC5FA,SAAS,YAAAA,iBAAgB;AACzB,OAAOC,WAAU;AACjB,SAAS,SAAAC,cAAa;AAQtB,SAAS,SAAS,OAAqC;AACrD,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAKA,eAAsB,iBAAiB,UAA6C;AAClF,QAAM,SAA4B,CAAC;AACnC,QAAM,eAAeD,MAAK,QAAQ,QAAQ;AAE1C,MAAI;AACJ,MAAI;AACF,UAAM,UAAU,MAAMD,UAAS,cAAc,MAAM;AACnD,aAASE,OAAM,OAAO;AAAA,EACxB,SAAS,OAAO;AACd,WAAO,KAAK;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,SAAS,yBAA0B,MAAgB,OAAO;AAAA,IAC5D,CAAC;AACD,WAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,SAAS,MAAM,GAAG;AACrB,WAAO,KAAK;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC;AACD,WAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAGA,QAAM,YAAY,OAAO;AACzB,MAAI,CAAC,MAAM,QAAQ,SAAS,GAAG;AAC7B,WAAO,KAAK;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC;AACD,WAAO;AAAA,MACL,OAAO,OAAO,WAAW;AAAA,MACzB,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAGA,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,UAAM,WAAW,UAAU,CAAC;AAC5B,UAAM,WAAW,aAAa,CAAC;AAE/B,QAAI,CAAC,SAAS,QAAQ,GAAG;AACvB,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,QACV;AAAA,QACA,SAAS;AAAA,MACX,CAAC;AACD;AAAA,IACF;AAGA,UAAM,KAAK,SAAS;AACpB,QAAI,OAAO,OAAO,YAAY,GAAG,KAAK,EAAE,WAAW,GAAG;AACpD,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAGA,UAAM,kBAAkB,SAAS,oBAAoB,SAAS;AAC9D,QACE,oBAAoB,WACnB,OAAO,oBAAoB,YAAY,gBAAgB,KAAK,EAAE,WAAW,IAC1E;AACA,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SACE;AAAA,MACJ,CAAC;AAAA,IACH;AAEA,UAAM,gBAAgB,SAAS;AAC/B,QAAI,CAAC,MAAM,QAAQ,aAAa,GAAG;AACjC,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SAAS;AAAA,MACX,CAAC;AAAA,IACH,OAAO;AACL,uBAAiB,eAAe,GAAG,QAAQ,mBAAmB,cAAc,MAAM;AAAA,IACpF;AAGA,UAAM,mBAAmB,SAAS;AAClC,QAAI,qBAAqB,UAAa,CAAC,MAAM,QAAQ,gBAAgB,GAAG;AACtE,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SAAS;AAAA,MACX,CAAC;AAAA,IACH,WAAW,MAAM,QAAQ,gBAAgB,GAAG;AAC1C,uBAAiB,kBAAkB,GAAG,QAAQ,sBAAsB,cAAc,MAAM;AAAA,IAC1F;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB,UAAU;AAAA,IACV,UAAU;AAAA,IACV;AAAA,EACF;AACF;AAEA,SAAS,iBACP,UACA,UACA,UACA,QACM;AACN,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,UAAU,SAAS,CAAC;AAC1B,UAAM,cAAc,GAAG,QAAQ,IAAI,CAAC;AAEpC,QAAI,CAAC,SAAS,OAAO,GAAG;AACtB,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV;AAAA,QACA,UAAU;AAAA,QACV,SAAS;AAAA,MACX,CAAC;AACD;AAAA,IACF;AAGA,UAAM,OAAO,QAAQ;AACrB,UAAM,aAAa,CAAC,UAAU,QAAQ,WAAW;AACjD,QAAI,CAAC,WAAW,SAAS,IAAc,GAAG;AACxC,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV;AAAA,QACA,UAAU,GAAG,WAAW;AAAA,QACxB,SAAS,iBAAiB,IAAI,sBAAsB,WAAW,KAAK,IAAI,CAAC;AAAA,MAC3E,CAAC;AAAA,IACH;AAGA,UAAM,UAAU,QAAQ;AACxB,QAAI,OAAO,YAAY,UAAU;AAC/B,oCAA8B,SAAS,GAAG,WAAW,YAAY,UAAU,MAAM;AAAA,IACnF,WAAW,MAAM,QAAQ,OAAO,GAAG;AAEjC,eAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,cAAM,cAAc,QAAQ,CAAC;AAC7B,cAAM,kBAAkB,GAAG,WAAW,YAAY,CAAC;AAEnD,YAAI,OAAO,gBAAgB,UAAU;AACnC,wCAA8B,aAAa,iBAAiB,UAAU,MAAM;AAAA,QAC9E,WAAW,SAAS,WAAW,GAAG;AAChC,gBAAM,OAAO,YAAY;AACzB,cAAI,OAAO,SAAS,UAAU;AAC5B,mBAAO,KAAK;AAAA,cACV,UAAU;AAAA,cACV;AAAA,cACA,UAAU,GAAG,eAAe;AAAA,cAC5B,SAAS;AAAA,YACX,CAAC;AAAA,UACH;AAIA,cAAI,SAAS,QAAQ;AACnB,kBAAM,QAAQ,YAAY;AAC1B,gBAAI,OAAO,UAAU,UAAU;AAC7B,qBAAO,KAAK;AAAA,gBACV,UAAU;AAAA,gBACV;AAAA,gBACA,UAAU,GAAG,eAAe;AAAA,gBAC5B,SAAS;AAAA,cACX,CAAC;AAAA,YACH,OAAO;AACL,4CAA8B,OAAO,GAAG,eAAe,UAAU,UAAU,MAAM;AAAA,YACnF;AAAA,UACF;AAAA,QACF,OAAO;AACL,iBAAO,KAAK;AAAA,YACV,UAAU;AAAA,YACV;AAAA,YACA,UAAU;AAAA,YACV,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,OAAO;AACL,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV;AAAA,QACA,UAAU,GAAG,WAAW;AAAA,QACxB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,SAAS,8BACP,SACA,UACA,UACA,QACM;AAEN,QAAM,UAAU,CAAC,cAAc,YAAY,iBAAiB,UAAU;AACtE,aAAW,UAAU,SAAS;AAC5B,QAAI,QAAQ,YAAY,EAAE,SAAS,OAAO,YAAY,CAAC,GAAG;AACxD,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACA,SAAS,2CAA2C,MAAM;AAAA,MAC5D,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AC7PA,SAAS,YAAAC,iBAAgB;AACzB,OAAOC,WAAU;AACjB,SAAS,SAAAC,cAAa;AAUtB,SAASC,UAAS,OAAqC;AACrD,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAGA,IAAM,kBAAkB,oBAAI,IAAI,CAAC,qBAAqB,kBAAkB,CAAC;AAEzE,IAAM,iBAAiB,oBAAI,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,iBAAiB,oBAAI,IAAI;AAAA,EAC7B,GAAG;AAAA,EACH,GAAG;AAAA,EACH;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACjC,GAAG;AAAA,EACH,GAAG;AAAA,EACH;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,kBAAkB,oBAAI,IAAI;AAAA,EAC9B,GAAG;AAAA,EACH,GAAG;AAAA,EACH;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,iBAAiB,oBAAI,IAAI;AAAA,EAC7B,GAAG;AAAA,EACH;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,kBAAkB,oBAAI,IAAI;AAAA,EAC9B,GAAG;AAAA,EACH;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,gBAAgB,oBAAI,IAAI;AAAA,EAC5B,GAAG;AAAA,EACH;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,eAAe,oBAAI,IAAI;AAAA,EAC3B,GAAG;AAAA,EACH;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,iBAAiB,UAAsC;AAC9D,QAAM,qBAAqB,SAAS,YAAY;AAChD,UAAQ,oBAAoB;AAAA,IAC1B,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,wBACP,QACA,UACA,cACA,UACA,QACM;AACN,QAAM,gBAAgB,iBAAiB,QAAQ;AAC/C,MAAI,CAAC,eAAe;AAElB;AAAA,EACF;AAGA,QAAM,aAAa,oBAAI,IAAI,CAAC,QAAQ,YAAY,gBAAgB,WAAW,WAAW,SAAS,CAAC;AAEhG,aAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACrC,QAAI,CAAC,WAAW,IAAI,GAAG,KAAK,CAAC,cAAc,IAAI,GAAG,GAAG;AACnD,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU,GAAG,QAAQ,IAAI,GAAG;AAAA,QAC5B,SAAS,oBAAoB,GAAG,SAAS,QAAQ;AAAA,MACnD,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAKA,eAAsB,oBAAoB,UAA6C;AACrF,QAAM,SAA4B,CAAC;AACnC,QAAM,eAAeC,MAAK,QAAQ,QAAQ;AAE1C,MAAI;AACJ,MAAI;AACF,UAAM,UAAU,MAAMC,UAAS,cAAc,MAAM;AACnD,aAASC,OAAM,OAAO;AAAA,EACxB,SAAS,OAAO;AACd,WAAO,KAAK;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,SAAS,yBAA0B,MAAgB,OAAO;AAAA,IAC5D,CAAC;AACD,WAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,WAAS,oBACP,QACAC,eACA,UACAC,SACM;AACN,UAAM,kBAAkB,OAAO,oBAAoB,OAAO;AAC1D,QAAI,OAAO,oBAAoB,YAAY,gBAAgB,KAAK,EAAE,WAAW,GAAG;AAC9E,MAAAA,QAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAUD;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SAAS;AAAA,MACX,CAAC;AAAA,IACH,OAAO;AACL;AAAA,QACE;AAAA,QACAA;AAAA,QACA,GAAG,QAAQ;AAAA,QACXC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,oBAAoB,OAAO,sBAAsB,OAAO;AAC9D,QAAI,sBAAsB,UAAa,OAAO,sBAAsB,UAAU;AAC5E,MAAAA,QAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAUD;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,UAAM,cAAc,OAAO,gBAAgB,OAAO;AAClD,QAAI,gBAAgB,UAAa,OAAO,gBAAgB,UAAU;AAChE,MAAAC,QAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAUD;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,UAAM,MAAM,OAAO;AACnB,QAAI,QAAQ,UAAa,OAAO,QAAQ,UAAU;AAChD,MAAAC,QAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAUD;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,UAAM,iBAAiB,OAAO,mBAAmB,OAAO;AACxD,QAAI,mBAAmB,QAAW;AAChC,YAAM,iBAAiB,OAAO,cAAc;AAC5C,UAAI,CAAC,OAAO,SAAS,cAAc,KAAK,kBAAkB,GAAG;AAC3D,QAAAC,QAAO,KAAK;AAAA,UACV,UAAU;AAAA,UACV,UAAUD;AAAA,UACV,UAAU,GAAG,QAAQ;AAAA,UACrB,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,cAAc,OAAO;AAC3B,QAAI,gBAAgB,QAAW;AAC7B,6BAAuB,aAAaA,eAAc,GAAG,QAAQ,gBAAgBC,OAAM;AAAA,IACrF;AAAA,EACF;AAEA,WAAS,uBACP,aACAD,eACA,UACAC,SACM;AACN,QAAI,CAACL,UAAS,WAAW,GAAG;AAC1B,MAAAK,QAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAUD;AAAA,QACV;AAAA,QACA,SAAS;AAAA,MACX,CAAC;AACD;AAAA,IACF;AAEA,UAAM,OAAO,YAAY;AACzB,QAAI,SAAS,UAAU,SAAS,WAAW;AACzC,MAAAC,QAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAUD;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SAAS;AAAA,MACX,CAAC;AACD;AAAA,IACF;AAEA,UAAM,iBAAiB,YAAY,mBAAmB,YAAY;AAClE,QAAI,mBAAmB,QAAW;AAChC,YAAM,iBAAiB,OAAO,cAAc;AAC5C,UAAI,CAAC,OAAO,SAAS,cAAc,KAAK,kBAAkB,GAAG;AAC3D,QAAAC,QAAO,KAAK;AAAA,UACV,UAAU;AAAA,UACV,UAAUD;AAAA,UACV,UAAU,GAAG,QAAQ;AAAA,UACrB,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI,SAAS,QAAQ;AACnB,YAAM,MAAM,YAAY;AACxB,UAAI,OAAO,QAAQ,YAAY,IAAI,KAAK,EAAE,WAAW,GAAG;AACtD,QAAAC,QAAO,KAAK;AAAA,UACV,UAAU;AAAA,UACV,UAAUD;AAAA,UACV,UAAU,GAAG,QAAQ;AAAA,UACrB,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAEA,UAAM,kBAAkB,YAAY,oBAAoB,YAAY;AACpE,QAAI,OAAO,oBAAoB,YAAY,gBAAgB,KAAK,EAAE,WAAW,GAAG;AAC9E,MAAAC,QAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAUD;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SAAS;AAAA,MACX,CAAC;AAAA,IACH,OAAO;AACL;AAAA,QACE;AAAA,QACAA;AAAA,QACA,GAAG,QAAQ;AAAA,QACXC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,MAAM,YAAY;AACxB,QAAI,QAAQ,UAAa,OAAO,QAAQ,UAAU;AAChD,MAAAA,QAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAUD;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAEA,WAAS,0BACP,UACAA,eACA,UACAC,SACM;AACN,UAAM,eAAe,oBAAoB,QAAQ;AACjD,eAAW,eAAe,cAAc;AACtC,UAAI,CAAC,iBAAiB,IAAI,WAAW,GAAG;AACtC,QAAAA,QAAO,KAAK;AAAA,UACV,UAAU;AAAA,UACV,UAAUD;AAAA,UACV;AAAA,UACA,SAAS,6BAA6B,WAAW,+BAA+B,MAAM,KAAK,gBAAgB,EAAE,KAAK,IAAI,CAAC;AAAA,QACzH,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,WAAS,oBAAoB,UAA4B;AACvD,UAAM,UAAU,SAAS,SAAS,gBAAgB;AAClD,UAAM,SAAmB,CAAC;AAC1B,eAAW,SAAS,SAAS;AAC3B,YAAM,cAAc,MAAM,CAAC;AAC3B,UAAI,aAAa;AACf,eAAO,KAAK,WAAW;AAAA,MACzB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,MAAI,CAACJ,UAAS,MAAM,GAAG;AACrB,WAAO,KAAK;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC;AACD,WAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAGA,QAAM,UAAU,OAAO;AACvB,MAAI,CAAC,MAAM,QAAQ,OAAO,GAAG;AAC3B,WAAO,KAAK;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC;AACD,WAAO;AAAA,MACL,OAAO,OAAO,WAAW;AAAA,MACzB,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAGA,QAAM,iBAAiB,CAAC,GAAG,iBAAiB,GAAG,gBAAgB;AAE/D,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,SAAS,QAAQ,CAAC;AACxB,UAAM,WAAW,WAAW,CAAC;AAE7B,QAAI,CAACA,UAAS,MAAM,GAAG;AACrB,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,QACV;AAAA,QACA,SAAS;AAAA,MACX,CAAC;AACD;AAAA,IACF;AAGA,UAAM,OAAO,OAAO;AACpB,QAAI,OAAO,SAAS,YAAY,KAAK,KAAK,EAAE,WAAW,GAAG;AACxD,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAGA,UAAM,WAAW,OAAO;AACxB,UAAM,gBAAgB,OAAO,aAAa,WAAW,SAAS,KAAK,EAAE,YAAY,IAAI;AACrF,QAAI,OAAO,aAAa,YAAY,SAAS,KAAK,EAAE,WAAW,GAAG;AAChE,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SAAS;AAAA,MACX,CAAC;AAAA,IACH,WAAW,CAAC,eAAe,SAAS,QAAQ,GAAG;AAE7C,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SAAS,qBAAqB,QAAQ,uBAAuB,eAAe,KAAK,IAAI,CAAC;AAAA,MACxF,CAAC;AAAA,IACH;AAGA,QAAI,kBAAkB,OAAO;AAC3B,0BAAoB,QAAQ,cAAc,UAAU,MAAM;AAAA,IAC5D;AAGA,QAAI,OAAO,aAAa,UAAU;AAChC,8BAAwB,QAAQ,UAAU,cAAc,UAAU,MAAM;AAAA,IAC1E;AAGA,UAAM,cAAc,OAAO;AAC3B,QAAI,gBAAgB,UAAa,OAAO,gBAAgB,UAAU;AAChE,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU,GAAG,QAAQ;AAAA,QACrB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO,EAAE,WAAW;AAAA,IAC/D,UAAU;AAAA,IACV,UAAU;AAAA,IACV;AAAA,EACF;AACF;;;ACzfA,SAAS,YAAAM,iBAAgB;AACzB,SAAS,SAAAC,cAAa;AAItB,IAAMC,oBAAmB;AAKzB,eAAsB,mBAAmB,UAA6C;AACpF,QAAM,SAA4B,CAAC;AAEnC,MAAI;AACF,UAAM,UAAU,MAAMF,UAAS,UAAU,MAAM;AAC/C,UAAM,SAASC,OAAM,OAAO;AAG5B,QAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV;AAAA,QACA,SAAS;AAAA,MACX,CAAC;AACD,aAAO,EAAE,OAAO,OAAO,UAAU,UAAU,UAAU,OAAO;AAAA,IAC9D;AAEA,UAAM,SAAS;AAGf,UAAM,SAAS,OAAO;AACtB,QAAI,WAAW,UAAa,WAAWC,mBAAkB;AACvD,YAAM,UAAU,0BAA0B,MAAM,gBAAgBA,iBAAgB;AAChF,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV;AAAA,QACA,UAAU;AAAA,QACV;AAAA,MACF,CAAC;AAAA,IACH;AAGA,UAAM,oBAAoB,OAAO;AACjC,QAAI,sBAAsB,QAAW;AACnC,UAAI,CAAC,MAAM,QAAQ,iBAAiB,GAAG;AACrC,eAAO,KAAK;AAAA,UACV,UAAU;AAAA,UACV;AAAA,UACA,UAAU;AAAA,UACV,SAAS;AAAA,QACX,CAAC;AAAA,MACH,WAAW,CAAC,kBAAkB,MAAM,CAAC,MAAM,OAAO,MAAM,QAAQ,GAAG;AACjE,eAAO,KAAK;AAAA,UACV,UAAU;AAAA,UACV;AAAA,UACA,UAAU;AAAA,UACV,SAAS;AAAA,QACX,CAAC;AAAA,MACH,WAAW,kBAAkB,WAAW,GAAG;AACzC,eAAO,KAAK;AAAA,UACV,UAAU;AAAA,UACV;AAAA,UACA,UAAU;AAAA,UACV,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF;AAGA,UAAM,gBAAgB,oBAAI,IAAI,CAAC,WAAW,oBAAoB,CAAC;AAC/D,UAAM,mBAAmB,OAAO,KAAK,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,cAAc,IAAI,GAAG,CAAC;AAEpF,QAAI,iBAAiB,SAAS,GAAG;AAC/B,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV;AAAA,QACA,SAAS,sBAAsB,iBAAiB,KAAK,IAAI,CAAC;AAAA,MAC5D,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO,EAAE,WAAW;AAAA,MAC/D;AAAA,MACA,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,WAAO,KAAK;AAAA,MACV,UAAU;AAAA,MACV;AAAA,MACA,SAAS,gCAAiC,MAAgB,OAAO;AAAA,IACnE,CAAC;AACD,WAAO,EAAE,OAAO,OAAO,UAAU,UAAU,UAAU,OAAO;AAAA,EAC9D;AACF;;;AC9FA,SAAS,YAAAC,iBAAgB;AACzB,OAAOC,WAAU;AACjB,SAAS,SAAAC,cAAa;AAStB,SAASC,UAAS,OAAqC;AACrD,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAOA,eAAsB,uBACpB,cACqC;AACrC,QAAM,SAA4B,CAAC;AACnC,QAAM,eAAeC,MAAK,QAAQ,YAAY;AAG9C,QAAM,UAAU,MAAM,YAAY,YAAY;AAC9C,MAAI,CAAC,SAAS;AACZ,WAAO,KAAK;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC;AACD,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,iBAAiB,cAAc,OAAO;AAE1D,MAAI;AACJ,MAAI;AACF,UAAM,UAAU,MAAMC,UAAS,cAAc,MAAM;AACnD,aAASC,OAAM,OAAO;AAAA,EACxB,QAAQ;AAEN,WAAO;AAAA,EACT;AAEA,MAAI,CAACH,UAAS,MAAM,GAAG;AACrB,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,OAAO;AACzB,MAAI,CAAC,MAAM,QAAQ,SAAS,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,UAAM,WAAW,UAAU,CAAC;AAC5B,QAAI,CAACA,UAAS,QAAQ,GAAG;AACvB;AAAA,IACF;AAGA,UAAM,gBAAgB,SAAS;AAC/B,QAAI,MAAM,QAAQ,aAAa,GAAG;AAChC,YAAM;AAAA,QACJ;AAAA,QACA,aAAa,CAAC;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAGA,UAAM,mBAAmB,SAAS;AAClC,QAAI,MAAM,QAAQ,gBAAgB,GAAG;AACnC,YAAM;AAAA,QACJ;AAAA,QACA,aAAa,CAAC;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAe,yBACb,UACA,UACA,aACA,UACA,QACe;AACf,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,UAAU,SAAS,CAAC;AAC1B,QAAI,CAACA,UAAS,OAAO,GAAG;AACtB;AAAA,IACF;AAEA,UAAM,UAAU,QAAQ;AACxB,QAAI,OAAO,YAAY,UAAU;AAC/B;AAAA,IACF;AAEA,QAAI,CAAC,MAAM,QAAQ,OAAO,GAAG;AAC3B;AAAA,IACF;AAEA,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,YAAM,cAAc,QAAQ,CAAC;AAC7B,UAAI,CAACA,UAAS,WAAW,GAAG;AAC1B;AAAA,MACF;AAEA,YAAM,OAAO,YAAY;AACzB,UAAI,SAAS,QAAQ;AACnB;AAAA,MACF;AAEA,YAAM,QAAQ,YAAY;AAC1B,UAAI,OAAO,UAAU,UAAU;AAC7B,eAAO,KAAK;AAAA,UACV,UAAU;AAAA,UACV;AAAA,UACA,UAAU,GAAG,QAAQ,IAAI,CAAC,aAAa,CAAC;AAAA,UACxC,SAAS;AAAA,QACX,CAAC;AACD;AAAA,MACF;AAGA,YAAM,EAAE,aAAa,IAAI,MAAM,qBAAqB,OAAO,WAAW;AAEtE,UAAI,CAAC,cAAc;AACjB,eAAO,KAAK;AAAA,UACV,UAAU;AAAA,UACV;AAAA,UACA,UAAU,GAAG,QAAQ,IAAI,CAAC,aAAa,CAAC;AAAA,UACxC,SAAS,8BAA8B,KAAK;AAAA,QAC9C,CAAC;AAAA,MACH,OAAO;AAEL,YAAI;AACF,gBAAM,cAAc,MAAME,UAAS,cAAc,MAAM;AACvD,cAAI,YAAY,KAAK,EAAE,WAAW,GAAG;AACnC,mBAAO,KAAK;AAAA,cACV,UAAU;AAAA,cACV;AAAA,cACA,UAAU,GAAG,QAAQ,IAAI,CAAC,aAAa,CAAC;AAAA,cACxC,SAAS,6BAA6B,KAAK;AAAA,YAC7C,CAAC;AAAA,UACH;AAAA,QACF,SAAS,OAAO;AACd,iBAAO,KAAK;AAAA,YACV,UAAU;AAAA,YACV;AAAA,YACA,UAAU,GAAG,QAAQ,IAAI,CAAC,aAAa,CAAC;AAAA,YACxC,SAAS,gCAAgC,KAAK,KAAM,MAAgB,OAAO;AAAA,UAC7E,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":["readFile","path","parse","readFile","path","parse","isObject","path","readFile","parse","absolutePath","errors","readFile","parse","SCHEMA_CONFIG_V2","readFile","path","parse","isObject","path","readFile","parse"]}
1
+ {"version":3,"sources":["../../../src/evaluation/validation/file-type.ts","../../../src/evaluation/validation/eval-validator.ts","../../../src/evaluation/validation/targets-validator.ts","../../../src/evaluation/validation/config-validator.ts","../../../src/evaluation/validation/file-reference-validator.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\r\nimport path from 'node:path';\r\nimport { parse } from 'yaml';\r\n\r\nimport type { FileType } from './types.js';\r\n\r\nconst SCHEMA_EVAL_V2 = 'agentv-eval-v2';\r\nconst SCHEMA_TARGETS_V2 = 'agentv-targets-v2.2';\r\nconst SCHEMA_CONFIG_V2 = 'agentv-config-v2';\r\n\r\n/**\r\n * Detect file type by reading $schema field from YAML file.\r\n * If $schema is missing, infers type from filename/path:\r\n * - config.yaml under .agentv folder → 'config'\r\n * - targets.yaml under .agentv folder → 'targets'\r\n * - All other YAML files → 'eval' (default)\r\n */\r\nexport async function detectFileType(filePath: string): Promise<FileType> {\r\n try {\r\n const content = await readFile(filePath, 'utf8');\r\n const parsed = parse(content) as unknown;\r\n\r\n if (typeof parsed !== 'object' || parsed === null) {\r\n return inferFileTypeFromPath(filePath);\r\n }\r\n\r\n const record = parsed as Record<string, unknown>;\r\n const schema = record.$schema;\r\n\r\n if (typeof schema !== 'string') {\r\n // No $schema field - infer from path\r\n return inferFileTypeFromPath(filePath);\r\n }\r\n\r\n switch (schema) {\r\n case SCHEMA_EVAL_V2:\r\n return 'eval';\r\n case SCHEMA_TARGETS_V2:\r\n return 'targets';\r\n case SCHEMA_CONFIG_V2:\r\n return 'config';\r\n default:\r\n // Unknown schema - infer from path\r\n return inferFileTypeFromPath(filePath);\r\n }\r\n } catch {\r\n return inferFileTypeFromPath(filePath);\r\n }\r\n}\r\n\r\n/**\r\n * Infer file type from filename and directory path.\r\n */\r\nfunction inferFileTypeFromPath(filePath: string): FileType {\r\n const normalized = path.normalize(filePath).replace(/\\\\/g, '/');\r\n const basename = path.basename(filePath);\r\n\r\n // Check if file is under .agentv folder\r\n if (normalized.includes('/.agentv/')) {\r\n if (basename === 'config.yaml' || basename === 'config.yml') {\r\n return 'config';\r\n }\r\n if (basename === 'targets.yaml' || basename === 'targets.yml') {\r\n return 'targets';\r\n }\r\n }\r\n\r\n // Default to eval file\r\n return 'eval';\r\n}\r\n\r\n/**\r\n * Check if a schema value is a valid AgentV schema identifier.\r\n */\r\nexport function isValidSchema(schema: unknown): boolean {\r\n return schema === SCHEMA_EVAL_V2 || schema === SCHEMA_TARGETS_V2 || schema === SCHEMA_CONFIG_V2;\r\n}\r\n\r\n/**\r\n * Get the expected schema for a file type.\r\n */\r\nexport function getExpectedSchema(fileType: FileType): string | undefined {\r\n switch (fileType) {\r\n case 'eval':\r\n return SCHEMA_EVAL_V2;\r\n case 'targets':\r\n return SCHEMA_TARGETS_V2;\r\n case 'config':\r\n return SCHEMA_CONFIG_V2;\r\n default:\r\n return undefined;\r\n }\r\n}\r\n","import { readFile } from 'node:fs/promises';\r\nimport path from 'node:path';\r\nimport { parse } from 'yaml';\r\n\r\nimport type { ValidationError, ValidationResult } from './types.js';\r\n\r\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\r\ntype JsonObject = { readonly [key: string]: JsonValue };\r\ntype JsonArray = readonly JsonValue[];\r\n\r\nfunction isObject(value: unknown): value is JsonObject {\r\n return typeof value === 'object' && value !== null && !Array.isArray(value);\r\n}\r\n\r\n/**\r\n * Validate an eval file (agentv-eval-v2 schema).\r\n */\r\nexport async function validateEvalFile(filePath: string): Promise<ValidationResult> {\r\n const errors: ValidationError[] = [];\r\n const absolutePath = path.resolve(filePath);\r\n\r\n let parsed: unknown;\r\n try {\r\n const content = await readFile(absolutePath, 'utf8');\r\n parsed = parse(content);\r\n } catch (error) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n message: `Failed to parse YAML: ${(error as Error).message}`,\r\n });\r\n return {\r\n valid: false,\r\n filePath: absolutePath,\r\n fileType: 'eval',\r\n errors,\r\n };\r\n }\r\n\r\n if (!isObject(parsed)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n message: 'File must contain a YAML object',\r\n });\r\n return {\r\n valid: false,\r\n filePath: absolutePath,\r\n fileType: 'eval',\r\n errors,\r\n };\r\n }\r\n\r\n // Validate evalcases array\r\n const evalcases = parsed.evalcases;\r\n if (!Array.isArray(evalcases)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: 'evalcases',\r\n message: \"Missing or invalid 'evalcases' field (must be an array)\",\r\n });\r\n return {\r\n valid: errors.length === 0,\r\n filePath: absolutePath,\r\n fileType: 'eval',\r\n errors,\r\n };\r\n }\r\n\r\n // Validate each eval case\r\n for (let i = 0; i < evalcases.length; i++) {\r\n const evalCase = evalcases[i];\r\n const location = `evalcases[${i}]`;\r\n\r\n if (!isObject(evalCase)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location,\r\n message: 'Eval case must be an object',\r\n });\r\n continue;\r\n }\r\n\r\n // Required fields: id, input_messages, expected_messages\r\n const id = evalCase.id;\r\n if (typeof id !== 'string' || id.trim().length === 0) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.id`,\r\n message: \"Missing or invalid 'id' field (must be a non-empty string)\",\r\n });\r\n }\r\n\r\n // Optional: expected_outcome or outcome for backward compatibility\r\n const expectedOutcome = evalCase.expected_outcome ?? evalCase.outcome;\r\n if (\r\n expectedOutcome !== undefined &&\r\n (typeof expectedOutcome !== 'string' || expectedOutcome.trim().length === 0)\r\n ) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.expected_outcome`,\r\n message:\r\n \"Invalid 'expected_outcome' or 'outcome' field (must be a non-empty string if provided)\",\r\n });\r\n }\r\n\r\n const inputMessages = evalCase.input_messages;\r\n if (!Array.isArray(inputMessages)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.input_messages`,\r\n message: \"Missing or invalid 'input_messages' field (must be an array)\",\r\n });\r\n } else {\r\n validateMessages(inputMessages, `${location}.input_messages`, absolutePath, errors);\r\n }\r\n\r\n // expected_messages is optional - for outcome-only evaluation\r\n const expectedMessages = evalCase.expected_messages;\r\n if (expectedMessages !== undefined && !Array.isArray(expectedMessages)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.expected_messages`,\r\n message: \"Invalid 'expected_messages' field (must be an array if provided)\",\r\n });\r\n } else if (Array.isArray(expectedMessages)) {\r\n validateMessages(expectedMessages, `${location}.expected_messages`, absolutePath, errors);\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n filePath: absolutePath,\r\n fileType: 'eval',\r\n errors,\r\n };\r\n}\r\n\r\nfunction validateMessages(\r\n messages: JsonArray,\r\n location: string,\r\n filePath: string,\r\n errors: ValidationError[],\r\n): void {\r\n for (let i = 0; i < messages.length; i++) {\r\n const message = messages[i];\r\n const msgLocation = `${location}[${i}]`;\r\n\r\n if (!isObject(message)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: msgLocation,\r\n message: 'Message must be an object',\r\n });\r\n continue;\r\n }\r\n\r\n // Validate role field\r\n const role = message.role;\r\n const validRoles = ['system', 'user', 'assistant'];\r\n if (!validRoles.includes(role as string)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: `${msgLocation}.role`,\r\n message: `Invalid role '${role}'. Must be one of: ${validRoles.join(', ')}`,\r\n });\r\n }\r\n\r\n // Validate tool_calls field for assistant messages\r\n const toolCalls = message.tool_calls;\r\n if (toolCalls !== undefined) {\r\n if (role !== 'assistant') {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: `${msgLocation}.tool_calls`,\r\n message: 'tool_calls can only be specified on assistant messages',\r\n });\r\n } else if (!Array.isArray(toolCalls)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: `${msgLocation}.tool_calls`,\r\n message: 'tool_calls must be an array',\r\n });\r\n } else {\r\n validateToolCalls(toolCalls, `${msgLocation}.tool_calls`, filePath, errors);\r\n }\r\n }\r\n\r\n // Validate content field (can be string or array)\r\n const content = message.content;\r\n if (typeof content === 'string') {\r\n validateContentForRoleMarkers(content, `${msgLocation}.content`, filePath, errors);\r\n } else if (Array.isArray(content)) {\r\n // Array content - validate each element\r\n for (let j = 0; j < content.length; j++) {\r\n const contentItem = content[j];\r\n const contentLocation = `${msgLocation}.content[${j}]`;\r\n\r\n if (typeof contentItem === 'string') {\r\n validateContentForRoleMarkers(contentItem, contentLocation, filePath, errors);\r\n } else if (isObject(contentItem)) {\r\n const type = contentItem.type;\r\n if (typeof type !== 'string') {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: `${contentLocation}.type`,\r\n message: \"Content object must have a 'type' field\",\r\n });\r\n }\r\n\r\n // For 'file' type, we'll validate existence later in file-reference-validator\r\n // For 'text' type, require 'value' field\r\n if (type === 'text') {\r\n const value = contentItem.value;\r\n if (typeof value !== 'string') {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: `${contentLocation}.value`,\r\n message: \"Content with type 'text' must have a 'value' field\",\r\n });\r\n } else {\r\n validateContentForRoleMarkers(value, `${contentLocation}.value`, filePath, errors);\r\n }\r\n }\r\n } else {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: contentLocation,\r\n message: 'Content array items must be strings or objects',\r\n });\r\n }\r\n }\r\n } else {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: `${msgLocation}.content`,\r\n message: \"Missing or invalid 'content' field (must be a string or array)\",\r\n });\r\n }\r\n }\r\n}\r\n\r\nfunction validateContentForRoleMarkers(\r\n content: string,\r\n location: string,\r\n filePath: string,\r\n errors: ValidationError[],\r\n): void {\r\n // Check for standard role markers that might confuse agentic providers\r\n const markers = ['@[System]:', '@[User]:', '@[Assistant]:', '@[Tool]:'];\r\n for (const marker of markers) {\r\n if (content.toLowerCase().includes(marker.toLowerCase())) {\r\n errors.push({\r\n severity: 'warning',\r\n filePath,\r\n location,\r\n message: `Content contains potential role marker '${marker}'. This may confuse agentic providers or cause prompt injection.`,\r\n });\r\n }\r\n }\r\n}\r\n\r\nfunction validateToolCalls(\r\n toolCalls: JsonArray,\r\n location: string,\r\n filePath: string,\r\n errors: ValidationError[],\r\n): void {\r\n for (let i = 0; i < toolCalls.length; i++) {\r\n const toolCall = toolCalls[i];\r\n const callLocation = `${location}[${i}]`;\r\n\r\n if (!isObject(toolCall)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: callLocation,\r\n message: 'Tool call must be an object',\r\n });\r\n continue;\r\n }\r\n\r\n // Required: tool field\r\n const tool = toolCall.tool;\r\n if (typeof tool !== 'string' || tool.trim().length === 0) {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: `${callLocation}.tool`,\r\n message: \"Missing or invalid 'tool' field (must be a non-empty string)\",\r\n });\r\n }\r\n\r\n // Optional: input field (any JSON value is valid)\r\n // Optional: output field (any JSON value is valid)\r\n // No additional validation needed for input/output - they're flexible\r\n }\r\n}\r\n","import { readFile } from 'node:fs/promises';\r\nimport path from 'node:path';\r\nimport { parse } from 'yaml';\r\n\r\nimport { CLI_PLACEHOLDERS } from '../providers/targets.js';\r\nimport { KNOWN_PROVIDERS, PROVIDER_ALIASES, TARGETS_SCHEMA_V2 } from '../providers/types.js';\r\nimport type { ValidationError, ValidationResult } from './types.js';\r\n\r\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\r\ntype JsonObject = { readonly [key: string]: JsonValue };\r\ntype JsonArray = readonly JsonValue[];\r\n\r\nfunction isObject(value: unknown): value is JsonObject {\r\n return typeof value === 'object' && value !== null && !Array.isArray(value);\r\n}\r\n\r\n// Known settings properties for each provider type\r\nconst COMMON_SETTINGS = new Set(['provider_batching', 'providerBatching']);\r\n\r\nconst RETRY_SETTINGS = new Set([\r\n 'max_retries',\r\n 'maxRetries',\r\n 'retry_initial_delay_ms',\r\n 'retryInitialDelayMs',\r\n 'retry_max_delay_ms',\r\n 'retryMaxDelayMs',\r\n 'retry_backoff_factor',\r\n 'retryBackoffFactor',\r\n 'retry_status_codes',\r\n 'retryStatusCodes',\r\n]);\r\n\r\nconst AZURE_SETTINGS = new Set([\r\n ...COMMON_SETTINGS,\r\n ...RETRY_SETTINGS,\r\n 'endpoint',\r\n 'resource',\r\n 'resourceName',\r\n 'api_key',\r\n 'apiKey',\r\n 'deployment',\r\n 'deploymentName',\r\n 'model',\r\n 'version',\r\n 'api_version',\r\n 'temperature',\r\n 'max_output_tokens',\r\n 'maxTokens',\r\n]);\r\n\r\nconst ANTHROPIC_SETTINGS = new Set([\r\n ...COMMON_SETTINGS,\r\n ...RETRY_SETTINGS,\r\n 'api_key',\r\n 'apiKey',\r\n 'model',\r\n 'deployment',\r\n 'variant',\r\n 'temperature',\r\n 'max_output_tokens',\r\n 'maxTokens',\r\n 'thinking_budget',\r\n 'thinkingBudget',\r\n]);\r\n\r\nconst GEMINI_SETTINGS = new Set([\r\n ...COMMON_SETTINGS,\r\n ...RETRY_SETTINGS,\r\n 'api_key',\r\n 'apiKey',\r\n 'model',\r\n 'deployment',\r\n 'variant',\r\n 'temperature',\r\n 'max_output_tokens',\r\n 'maxTokens',\r\n]);\r\n\r\nconst CODEX_SETTINGS = new Set([\r\n ...COMMON_SETTINGS,\r\n 'executable',\r\n 'command',\r\n 'binary',\r\n 'args',\r\n 'arguments',\r\n 'cwd',\r\n 'timeout_seconds',\r\n 'timeoutSeconds',\r\n 'log_dir',\r\n 'logDir',\r\n 'log_directory',\r\n 'logDirectory',\r\n 'log_format',\r\n 'logFormat',\r\n 'log_output_format',\r\n 'logOutputFormat',\r\n]);\r\n\r\nconst VSCODE_SETTINGS = new Set([\r\n ...COMMON_SETTINGS,\r\n 'workspace_template',\r\n 'workspaceTemplate',\r\n 'vscode_cmd',\r\n 'command',\r\n 'wait',\r\n 'dry_run',\r\n 'dryRun',\r\n 'subagent_root',\r\n 'subagentRoot',\r\n]);\r\n\r\nconst MOCK_SETTINGS = new Set([\r\n ...COMMON_SETTINGS,\r\n 'response',\r\n 'delayMs',\r\n 'delayMinMs',\r\n 'delayMaxMs',\r\n 'trace', // For testing tool_trajectory evaluator\r\n]);\r\n\r\nconst CLI_SETTINGS = new Set([\r\n ...COMMON_SETTINGS,\r\n 'command_template',\r\n 'commandTemplate',\r\n 'files_format',\r\n 'filesFormat',\r\n 'attachments_format',\r\n 'attachmentsFormat',\r\n 'cwd',\r\n 'env',\r\n 'timeout_seconds',\r\n 'timeoutSeconds',\r\n 'healthcheck',\r\n]);\r\n\r\nfunction getKnownSettings(provider: string): Set<string> | null {\r\n const normalizedProvider = provider.toLowerCase();\r\n switch (normalizedProvider) {\r\n case 'azure':\r\n case 'azure-openai':\r\n return AZURE_SETTINGS;\r\n case 'anthropic':\r\n return ANTHROPIC_SETTINGS;\r\n case 'gemini':\r\n case 'google':\r\n case 'google-gemini':\r\n return GEMINI_SETTINGS;\r\n case 'codex':\r\n case 'codex-cli':\r\n return CODEX_SETTINGS;\r\n case 'vscode':\r\n case 'vscode-insiders':\r\n return VSCODE_SETTINGS;\r\n case 'mock':\r\n return MOCK_SETTINGS;\r\n case 'cli':\r\n return CLI_SETTINGS;\r\n default:\r\n return null; // Unknown provider, can't validate settings\r\n }\r\n}\r\n\r\nfunction validateUnknownSettings(\r\n target: JsonObject,\r\n provider: string,\r\n absolutePath: string,\r\n location: string,\r\n errors: ValidationError[],\r\n): void {\r\n const knownSettings = getKnownSettings(provider);\r\n if (!knownSettings) {\r\n // Unknown provider, skip settings validation\r\n return;\r\n }\r\n\r\n // Known base target fields that aren't settings\r\n const baseFields = new Set(['name', 'provider', 'judge_target', 'workers', '$schema', 'targets']);\r\n\r\n for (const key of Object.keys(target)) {\r\n if (!baseFields.has(key) && !knownSettings.has(key)) {\r\n errors.push({\r\n severity: 'warning',\r\n filePath: absolutePath,\r\n location: `${location}.${key}`,\r\n message: `Unknown setting '${key}' for ${provider} provider. This property will be ignored.`,\r\n });\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Validate a targets file (agentv-targets-v2.1 schema).\r\n */\r\nexport async function validateTargetsFile(filePath: string): Promise<ValidationResult> {\r\n const errors: ValidationError[] = [];\r\n const absolutePath = path.resolve(filePath);\r\n\r\n let parsed: unknown;\r\n try {\r\n const content = await readFile(absolutePath, 'utf8');\r\n parsed = parse(content);\r\n } catch (error) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n message: `Failed to parse YAML: ${(error as Error).message}`,\r\n });\r\n return {\r\n valid: false,\r\n filePath: absolutePath,\r\n fileType: 'targets',\r\n errors,\r\n };\r\n }\r\n\r\n function validateCliSettings(\r\n target: JsonObject,\r\n absolutePath: string,\r\n location: string,\r\n errors: ValidationError[],\r\n ): void {\r\n const commandTemplate = target.command_template ?? target.commandTemplate;\r\n if (typeof commandTemplate !== 'string' || commandTemplate.trim().length === 0) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.commandTemplate`,\r\n message: \"CLI provider requires 'commandTemplate' as a non-empty string\",\r\n });\r\n } else {\r\n recordUnknownPlaceholders(\r\n commandTemplate,\r\n absolutePath,\r\n `${location}.commandTemplate`,\r\n errors,\r\n );\r\n }\r\n\r\n const attachmentsFormat = target.attachments_format ?? target.attachmentsFormat;\r\n if (attachmentsFormat !== undefined && typeof attachmentsFormat !== 'string') {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.attachmentsFormat`,\r\n message: \"'attachmentsFormat' must be a string when provided\",\r\n });\r\n }\r\n\r\n const filesFormat = target.files_format ?? target.filesFormat;\r\n if (filesFormat !== undefined && typeof filesFormat !== 'string') {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.filesFormat`,\r\n message: \"'filesFormat' must be a string when provided\",\r\n });\r\n }\r\n\r\n const cwd = target.cwd;\r\n if (cwd !== undefined && typeof cwd !== 'string') {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.cwd`,\r\n message: \"'cwd' must be a string when provided\",\r\n });\r\n }\r\n\r\n const timeoutSeconds = target.timeout_seconds ?? target.timeoutSeconds;\r\n if (timeoutSeconds !== undefined) {\r\n const numericTimeout = Number(timeoutSeconds);\r\n if (!Number.isFinite(numericTimeout) || numericTimeout <= 0) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.timeoutSeconds`,\r\n message: \"'timeoutSeconds' must be a positive number when provided\",\r\n });\r\n }\r\n }\r\n\r\n const healthcheck = target.healthcheck;\r\n if (healthcheck !== undefined) {\r\n validateCliHealthcheck(healthcheck, absolutePath, `${location}.healthcheck`, errors);\r\n }\r\n }\r\n\r\n function validateCliHealthcheck(\r\n healthcheck: unknown,\r\n absolutePath: string,\r\n location: string,\r\n errors: ValidationError[],\r\n ): void {\r\n if (!isObject(healthcheck)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location,\r\n message: \"'healthcheck' must be an object when provided\",\r\n });\r\n return;\r\n }\r\n\r\n const type = healthcheck.type;\r\n if (type !== 'http' && type !== 'command') {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.type`,\r\n message: \"healthcheck.type must be either 'http' or 'command'\",\r\n });\r\n return;\r\n }\r\n\r\n const timeoutSeconds = healthcheck.timeout_seconds ?? healthcheck.timeoutSeconds;\r\n if (timeoutSeconds !== undefined) {\r\n const numericTimeout = Number(timeoutSeconds);\r\n if (!Number.isFinite(numericTimeout) || numericTimeout <= 0) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.timeoutSeconds`,\r\n message: 'healthcheck.timeoutSeconds must be a positive number when provided',\r\n });\r\n }\r\n }\r\n\r\n if (type === 'http') {\r\n const url = healthcheck.url;\r\n if (typeof url !== 'string' || url.trim().length === 0) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.url`,\r\n message: 'healthcheck.url must be a non-empty string for http checks',\r\n });\r\n }\r\n return;\r\n }\r\n\r\n const commandTemplate = healthcheck.command_template ?? healthcheck.commandTemplate;\r\n if (typeof commandTemplate !== 'string' || commandTemplate.trim().length === 0) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.commandTemplate`,\r\n message: 'healthcheck.commandTemplate must be a non-empty string for command checks',\r\n });\r\n } else {\r\n recordUnknownPlaceholders(\r\n commandTemplate,\r\n absolutePath,\r\n `${location}.commandTemplate`,\r\n errors,\r\n );\r\n }\r\n\r\n const cwd = healthcheck.cwd;\r\n if (cwd !== undefined && typeof cwd !== 'string') {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.cwd`,\r\n message: 'healthcheck.cwd must be a string when provided',\r\n });\r\n }\r\n }\r\n\r\n function recordUnknownPlaceholders(\r\n template: string,\r\n absolutePath: string,\r\n location: string,\r\n errors: ValidationError[],\r\n ): void {\r\n const placeholders = extractPlaceholders(template);\r\n for (const placeholder of placeholders) {\r\n if (!CLI_PLACEHOLDERS.has(placeholder)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location,\r\n message: `Unknown CLI placeholder '{${placeholder}}'. Supported placeholders: ${Array.from(CLI_PLACEHOLDERS).join(', ')}`,\r\n });\r\n }\r\n }\r\n }\r\n\r\n function extractPlaceholders(template: string): string[] {\r\n const matches = template.matchAll(/\\{([A-Z_]+)\\}/g);\r\n const result: string[] = [];\r\n for (const match of matches) {\r\n const placeholder = match[1];\r\n if (placeholder) {\r\n result.push(placeholder);\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n if (!isObject(parsed)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n message: 'File must contain a YAML object',\r\n });\r\n return {\r\n valid: false,\r\n filePath: absolutePath,\r\n fileType: 'targets',\r\n errors,\r\n };\r\n }\r\n\r\n // Validate targets array\r\n const targets = parsed.targets;\r\n if (!Array.isArray(targets)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: 'targets',\r\n message: \"Missing or invalid 'targets' field (must be an array)\",\r\n });\r\n return {\r\n valid: errors.length === 0,\r\n filePath: absolutePath,\r\n fileType: 'targets',\r\n errors,\r\n };\r\n }\r\n\r\n // Validate each target definition\r\n const knownProviders = [...KNOWN_PROVIDERS, ...PROVIDER_ALIASES];\r\n\r\n for (let i = 0; i < targets.length; i++) {\r\n const target = targets[i];\r\n const location = `targets[${i}]`;\r\n\r\n if (!isObject(target)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location,\r\n message: 'Target must be an object',\r\n });\r\n continue;\r\n }\r\n\r\n // Required field: name\r\n const name = target.name;\r\n if (typeof name !== 'string' || name.trim().length === 0) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.name`,\r\n message: \"Missing or invalid 'name' field (must be a non-empty string)\",\r\n });\r\n }\r\n\r\n // Required field: provider\r\n const provider = target.provider;\r\n const providerValue = typeof provider === 'string' ? provider.trim().toLowerCase() : undefined;\r\n if (typeof provider !== 'string' || provider.trim().length === 0) {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.provider`,\r\n message: \"Missing or invalid 'provider' field (must be a non-empty string)\",\r\n });\r\n } else if (!knownProviders.includes(provider)) {\r\n // Warning for unknown providers (non-fatal)\r\n errors.push({\r\n severity: 'warning',\r\n filePath: absolutePath,\r\n location: `${location}.provider`,\r\n message: `Unknown provider '${provider}'. Known providers: ${knownProviders.join(', ')}`,\r\n });\r\n }\r\n\r\n // Validate CLI provider fields\r\n if (providerValue === 'cli') {\r\n validateCliSettings(target, absolutePath, location, errors);\r\n }\r\n\r\n // Check for unknown settings properties on target object\r\n if (typeof provider === 'string') {\r\n validateUnknownSettings(target, provider, absolutePath, location, errors);\r\n }\r\n\r\n // Optional field: judge_target (must be string if present)\r\n const judgeTarget = target.judge_target;\r\n if (judgeTarget !== undefined && typeof judgeTarget !== 'string') {\r\n errors.push({\r\n severity: 'error',\r\n filePath: absolutePath,\r\n location: `${location}.judge_target`,\r\n message: \"Invalid 'judge_target' field (must be a string)\",\r\n });\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.filter((e) => e.severity === 'error').length === 0,\r\n filePath: absolutePath,\r\n fileType: 'targets',\r\n errors,\r\n };\r\n}\r\n","import { readFile } from 'node:fs/promises';\r\nimport { parse } from 'yaml';\r\n\r\nimport type { ValidationError, ValidationResult } from './types.js';\r\n\r\nconst SCHEMA_CONFIG_V2 = 'agentv-config-v2';\r\n\r\n/**\r\n * Validate a config.yaml file for schema compliance and structural correctness.\r\n */\r\nexport async function validateConfigFile(filePath: string): Promise<ValidationResult> {\r\n const errors: ValidationError[] = [];\r\n\r\n try {\r\n const content = await readFile(filePath, 'utf8');\r\n const parsed = parse(content) as unknown;\r\n\r\n // Check if parsed content is an object\r\n if (typeof parsed !== 'object' || parsed === null) {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n message: 'Config file must contain a valid YAML object',\r\n });\r\n return { valid: false, filePath, fileType: 'config', errors };\r\n }\r\n\r\n const config = parsed as Record<string, unknown>;\r\n\r\n // Validate $schema field (optional, but if present must be correct)\r\n const schema = config.$schema;\r\n if (schema !== undefined && schema !== SCHEMA_CONFIG_V2) {\r\n const message = `Invalid $schema value '${schema}'. Expected '${SCHEMA_CONFIG_V2}' or omit the field.`;\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: '$schema',\r\n message,\r\n });\r\n }\r\n\r\n // Validate guideline_patterns if present\r\n const guidelinePatterns = config.guideline_patterns;\r\n if (guidelinePatterns !== undefined) {\r\n if (!Array.isArray(guidelinePatterns)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: 'guideline_patterns',\r\n message: \"Field 'guideline_patterns' must be an array\",\r\n });\r\n } else if (!guidelinePatterns.every((p) => typeof p === 'string')) {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: 'guideline_patterns',\r\n message: \"All entries in 'guideline_patterns' must be strings\",\r\n });\r\n } else if (guidelinePatterns.length === 0) {\r\n errors.push({\r\n severity: 'warning',\r\n filePath,\r\n location: 'guideline_patterns',\r\n message: \"Field 'guideline_patterns' is empty. Consider removing it or adding patterns.\",\r\n });\r\n }\r\n }\r\n\r\n // Check for unexpected fields\r\n const allowedFields = new Set(['$schema', 'guideline_patterns']);\r\n const unexpectedFields = Object.keys(config).filter((key) => !allowedFields.has(key));\r\n\r\n if (unexpectedFields.length > 0) {\r\n errors.push({\r\n severity: 'warning',\r\n filePath,\r\n message: `Unexpected fields: ${unexpectedFields.join(', ')}`,\r\n });\r\n }\r\n\r\n return {\r\n valid: errors.filter((e) => e.severity === 'error').length === 0,\r\n filePath,\r\n fileType: 'config',\r\n errors,\r\n };\r\n } catch (error) {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n message: `Failed to parse config file: ${(error as Error).message}`,\r\n });\r\n return { valid: false, filePath, fileType: 'config', errors };\r\n }\r\n}\r\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from 'yaml';\n\nimport { buildSearchRoots, findGitRoot, resolveFileReference } from '../file-utils.js';\nimport type { ValidationError } from './types.js';\n\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\ntype JsonObject = { readonly [key: string]: JsonValue };\ntype JsonArray = readonly JsonValue[];\n\nfunction isObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Validate that file references in eval file content exist.\n * Checks content blocks with type: \"file\" and validates the referenced file exists.\n * Also checks that referenced files are not empty.\n */\nexport async function validateFileReferences(\n evalFilePath: string,\n): Promise<readonly ValidationError[]> {\n const errors: ValidationError[] = [];\n const absolutePath = path.resolve(evalFilePath);\n\n // Find git root and build search roots (same as yaml-parser does at runtime)\n const gitRoot = await findGitRoot(absolutePath);\n if (!gitRoot) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: 'Cannot validate file references: git repository root not found',\n });\n return errors;\n }\n\n const searchRoots = buildSearchRoots(absolutePath, gitRoot);\n\n let parsed: unknown;\n try {\n const content = await readFile(absolutePath, 'utf8');\n parsed = parse(content);\n } catch {\n // Parse errors are already caught by eval-validator\n return errors;\n }\n\n if (!isObject(parsed)) {\n return errors;\n }\n\n const evalcases = parsed.evalcases;\n if (!Array.isArray(evalcases)) {\n return errors;\n }\n\n for (let i = 0; i < evalcases.length; i++) {\n const evalCase = evalcases[i];\n if (!isObject(evalCase)) {\n continue;\n }\n\n // Check input_messages\n const inputMessages = evalCase.input_messages;\n if (Array.isArray(inputMessages)) {\n await validateMessagesFileRefs(\n inputMessages,\n `evalcases[${i}].input_messages`,\n searchRoots,\n absolutePath,\n errors,\n );\n }\n\n // Check expected_messages\n const expectedMessages = evalCase.expected_messages;\n if (Array.isArray(expectedMessages)) {\n await validateMessagesFileRefs(\n expectedMessages,\n `evalcases[${i}].expected_messages`,\n searchRoots,\n absolutePath,\n errors,\n );\n }\n }\n\n return errors;\n}\n\nasync function validateMessagesFileRefs(\n messages: JsonArray,\n location: string,\n searchRoots: readonly string[],\n filePath: string,\n errors: ValidationError[],\n): Promise<void> {\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i];\n if (!isObject(message)) {\n continue;\n }\n\n const content = message.content;\n if (typeof content === 'string') {\n continue;\n }\n\n if (!Array.isArray(content)) {\n continue;\n }\n\n for (let j = 0; j < content.length; j++) {\n const contentItem = content[j];\n if (!isObject(contentItem)) {\n continue;\n }\n\n const type = contentItem.type;\n if (type !== 'file') {\n continue;\n }\n\n const value = contentItem.value;\n if (typeof value !== 'string') {\n errors.push({\n severity: 'error',\n filePath,\n location: `${location}[${i}].content[${j}].value`,\n message: \"File reference must have a 'value' field with the file path\",\n });\n continue;\n }\n\n // Use the same file resolution logic as yaml-parser at runtime\n const { resolvedPath } = await resolveFileReference(value, searchRoots);\n\n if (!resolvedPath) {\n errors.push({\n severity: 'error',\n filePath,\n location: `${location}[${i}].content[${j}]`,\n message: `Referenced file not found: ${value}`,\n });\n } else {\n // Check that file is not empty\n try {\n const fileContent = await readFile(resolvedPath, 'utf8');\n if (fileContent.trim().length === 0) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${location}[${i}].content[${j}]`,\n message: `Referenced file is empty: ${value}`,\n });\n }\n } catch (error) {\n errors.push({\n severity: 'error',\n filePath,\n location: `${location}[${i}].content[${j}]`,\n message: `Cannot read referenced file: ${value} (${(error as Error).message})`,\n });\n }\n }\n }\n }\n}\n"],"mappings":"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","names":["readFile","path","parse","readFile","path","parse","isObject","path","readFile","parse","absolutePath","errors","readFile","parse","SCHEMA_CONFIG_V2","readFile","path","parse","isObject","path","readFile","parse"]}