@learning-commons/evaluators 0.3.0 → 0.5.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/telemetry/client.ts","../../src/telemetry/utils.ts","../../src/errors.ts","../../src/logger.ts","../../src/providers/ai-sdk-provider.ts","../../src/evaluators/base.ts","../../src/schemas/outputs.ts","../../src/schemas/vocabulary.ts","../../src/features/readability.ts","../../src/features/sentence-features.ts","../../src/features/preprocessing.ts","../../../../evals/prompts/vocabulary/background-knowledge.txt","../../src/prompts/vocabulary/background-knowledge.ts","../../../../evals/prompts/vocabulary/grades-3-4-system.txt","../../../../evals/prompts/vocabulary/other-grades-system.txt","../../src/prompts/vocabulary/system.ts","../../../../evals/prompts/vocabulary/grades-3-4-user.txt","../../../../evals/prompts/vocabulary/other-grades-user.txt","../../src/prompts/vocabulary/user.ts","../../src/evaluators/vocabulary.ts","../../src/schemas/sentence-structure.ts","../../../../evals/prompts/sentence-structure/analysis-system.txt","../../../../evals/prompts/sentence-structure/analysis-user.txt","../../src/prompts/sentence-structure/analysis.ts","../../../../evals/prompts/sentence-structure/complexity-system.txt","../../../../evals/prompts/sentence-structure/complexity-user.txt","../../../../evals/prompts/sentence-structure/rubric-grade-3.txt","../../../../evals/prompts/sentence-structure/rubric-grade-4.txt","../../../../evals/prompts/sentence-structure/rubric-grades-5-12.txt","../../src/prompts/sentence-structure/complexity.ts","../../src/evaluators/sentence-structure.ts","../../src/schemas/grade-level-appropriateness.ts","../../../../evals/prompts/grade-level-appropriateness/system.txt","../../../../evals/prompts/grade-level-appropriateness/user.txt","../../src/prompts/grade-level-appropriateness/index.ts","../../src/evaluators/grade-level-appropriateness.ts","../../src/schemas/smk.ts","../../../../evals/prompts/subject-matter-knowledge/system.txt","../../../../evals/prompts/subject-matter-knowledge/user.txt","../../src/prompts/subject-matter-knowledge/index.ts","../../src/evaluators/smk.ts","../../src/schemas/conventionality.ts","../../../../evals/prompts/conventionality/system.txt","../../../../evals/prompts/conventionality/user.txt","../../src/prompts/conventionality/index.ts","../../src/evaluators/conventionality.ts","../../src/schemas/purpose.ts","../../../../evals/prompts/purpose/system.txt","../../../../evals/prompts/purpose/user.txt","../../../../evals/prompts/purpose/config.json","../../src/prompts/purpose/index.ts","../../../../evals/prompts/purpose/input_schema.json","../../src/evaluators/purpose.ts","../../src/batch/evaluator.ts","../../src/batch/csv.ts","../../src/batch/report-template.html","../../src/batch/formatters.ts"],"names":["__filename","fileURLToPath","__dirname","dirname","readFileSync","randomUUID","mkdirSync","writeFileSync","join","homedir","aiGenerateText","Output","Provider","z","nlp","syllable","textReadability","getSystemPrompt","getUserPrompt","system_default","user_default","STEP_ID","_step","pLimit","fs","parse","_"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","file":"index.cjs","sourcesContent":["import type { TelemetryConfig, TelemetryEvent } from './types.js';\nimport type { Logger } from '../logger.js';\n\n/**\n * Telemetry client for sending analytics events\n *\n * Fire-and-forget implementation that never blocks SDK operations.\n * Errors are logged but don't fail evaluations.\n */\nexport class TelemetryClient {\n private config: TelemetryConfig;\n private logger: Logger;\n\n constructor(config: TelemetryConfig) {\n this.config = config;\n this.logger = config.logger;\n }\n\n /**\n * Send telemetry event to analytics service\n *\n * Fire-and-forget: Errors are logged but don't throw.\n */\n async send(event: TelemetryEvent): Promise<void> {\n // Skip if telemetry disabled\n if (!this.config.enabled) {\n return;\n }\n\n try {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-Client-ID': this.config.clientId,\n };\n\n // Add partner key if provided\n if (this.config.partnerKey) {\n headers['X-API-Key'] = this.config.partnerKey;\n }\n\n const response = await fetch(this.config.endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(event),\n // Don't block SDK operations on slow networks\n signal: AbortSignal.timeout(5000), // 5 second timeout\n });\n\n if (!response.ok) {\n this.logger.warn(\n `[Telemetry] Failed to send event: ${response.status} ${response.statusText}`\n );\n }\n } catch (error) {\n // Log error but never throw (fire-and-forget)\n if (error instanceof Error) {\n // Don't log timeout errors (expected on slow networks)\n if (error.name !== 'TimeoutError' && error.name !== 'AbortError') {\n this.logger.warn(`[Telemetry] Error sending event: ${error.message}`);\n }\n }\n }\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { homedir } from 'node:os';\nimport { fileURLToPath } from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/** Cached client ID — populated on first call, reused for process lifetime */\nlet cachedClientId: string | undefined;\n\n/**\n * Get or create a persistent client ID for anonymous tracking.\n *\n * On first run, generates a UUID and tries to save it to:\n * - Windows: %APPDATA%\\learning-commons\\config.json\n * - macOS/Linux: ~/.config/learning-commons/config.json\n *\n * On subsequent runs, reads the saved UUID from disk.\n * Falls back to an in-memory UUID (per-process) if the filesystem\n * is unavailable (e.g., serverless, read-only containers).\n */\nexport function generateClientId(): string {\n if (cachedClientId) {\n return cachedClientId;\n }\n\n const configFile = getConfigFilePath();\n\n // Try to read existing client ID from disk\n try {\n const data = JSON.parse(readFileSync(configFile, 'utf-8')) as {\n telemetry?: { clientId?: string };\n };\n if (data?.telemetry?.clientId) {\n cachedClientId = data.telemetry.clientId;\n return cachedClientId;\n }\n } catch {\n // File doesn't exist yet — fall through to generate\n }\n\n // Generate new UUID and try to persist it\n const clientId = randomUUID();\n try {\n mkdirSync(dirname(configFile), { recursive: true });\n writeFileSync(configFile, JSON.stringify({ telemetry: { clientId } }, null, 2));\n } catch {\n // Filesystem unavailable — use in-memory UUID for this process\n }\n\n cachedClientId = clientId;\n return cachedClientId;\n}\n\nfunction getConfigFilePath(): string {\n const configDir =\n process.platform === 'win32'\n ? join(process.env.APPDATA ?? homedir(), 'learning-commons')\n : join(homedir(), '.config', 'learning-commons');\n return join(configDir, 'config.json');\n}\n\nlet cachedVersion: string | undefined;\n\n/**\n * Get SDK version from package.json\n */\nexport function getSDKVersion(): string {\n if (cachedVersion) {\n return cachedVersion;\n }\n\n const possiblePaths = [\n join(__dirname, '../../package.json'), // From src/\n join(__dirname, '../package.json'), // From dist/\n ];\n\n for (const path of possiblePaths) {\n try {\n const pkg = JSON.parse(readFileSync(path, 'utf-8')) as { version?: string };\n cachedVersion = pkg.version || '0.0.0';\n return cachedVersion;\n } catch {\n continue;\n }\n }\n\n // Fallback if no package.json found\n cachedVersion = '0.0.0';\n return cachedVersion;\n}\n","/**\n * Custom error types for the Evaluators SDK\n *\n * This module provides a hierarchy of error types to help users\n * distinguish between different error scenarios and implement\n * appropriate error handling strategies.\n */\n\n/**\n * Base error class for all evaluator errors\n */\nexport class EvaluatorError extends Error {\n constructor(\n message: string,\n public readonly code?: string\n ) {\n super(message);\n this.name = 'EvaluatorError';\n // Maintains proper stack trace for where error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Configuration error - thrown when the evaluator is misconfigured\n * These are developer errors (e.g. missing API keys) that should NOT be retried\n *\n * @example\n * ```typescript\n * try {\n * const evaluator = new VocabularyEvaluator({ googleApiKey: '' });\n * } catch (error) {\n * if (error instanceof ConfigurationError) {\n * console.error('Check your evaluator config:', error.message);\n * }\n * }\n * ```\n */\nexport class ConfigurationError extends EvaluatorError {\n constructor(message: string) {\n super(message, 'CONFIGURATION_ERROR');\n this.name = 'ConfigurationError';\n }\n}\n\n/**\n * Validation error - thrown when input validation fails\n * These are client-side errors that should NOT be retried\n *\n * @example\n * ```typescript\n * try {\n * await evaluator.evaluate('', '5');\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * // Show user-friendly error message\n * console.error('Invalid input:', error.message);\n * }\n * }\n * ```\n */\nexport class ValidationError extends EvaluatorError {\n constructor(message: string) {\n super(message, 'VALIDATION_ERROR');\n this.name = 'ValidationError';\n }\n}\n\n/**\n * Base API error - thrown when LLM API calls fail\n * Contains additional context about the API error\n */\nexport class APIError extends EvaluatorError {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly retryable: boolean = false,\n code?: string\n ) {\n super(message, code);\n this.name = 'APIError';\n }\n}\n\n/**\n * Authentication error - thrown when API keys are invalid or missing\n * HTTP 401 or 403 responses\n * Should NOT be retried\n *\n * @example\n * ```typescript\n * try {\n * await evaluator.evaluate(text, grade);\n * } catch (error) {\n * if (error instanceof AuthenticationError) {\n * // Prompt user to check API keys\n * console.error('Invalid API keys. Please check your credentials.');\n * }\n * }\n * ```\n */\nexport class AuthenticationError extends APIError {\n constructor(message: string, statusCode?: number) {\n super(message, statusCode, false, 'AUTHENTICATION_ERROR');\n this.name = 'AuthenticationError';\n }\n}\n\n/**\n * Rate limit error - thrown when API rate limits are exceeded\n * HTTP 429 responses\n * Should be retried with exponential backoff\n *\n * @example\n * ```typescript\n * try {\n * await evaluator.evaluate(text, grade);\n * } catch (error) {\n * if (error instanceof RateLimitError) {\n * // Wait and retry\n * await sleep(error.retryAfter || 5000);\n * // retry...\n * }\n * }\n * ```\n */\nexport class RateLimitError extends APIError {\n constructor(\n message: string,\n public readonly retryAfter?: number // milliseconds\n ) {\n super(message, 429, true, 'RATE_LIMIT_ERROR');\n this.name = 'RateLimitError';\n }\n}\n\n/**\n * Network error - thrown when network requests fail\n * Connection timeouts, DNS failures, etc.\n * May be retryable depending on the scenario\n *\n * @example\n * ```typescript\n * try {\n * await evaluator.evaluate(text, grade);\n * } catch (error) {\n * if (error instanceof NetworkError) {\n * // Check network connection and retry\n * console.error('Network error:', error.message);\n * }\n * }\n * ```\n */\nexport class NetworkError extends APIError {\n constructor(message: string, retryable: boolean = true) {\n super(message, undefined, retryable, 'NETWORK_ERROR');\n this.name = 'NetworkError';\n }\n}\n\n/**\n * Timeout error - thrown when requests exceed timeout limits\n * Should be retried with caution\n *\n * @example\n * ```typescript\n * try {\n * await evaluator.evaluate(text, grade);\n * } catch (error) {\n * if (error instanceof TimeoutError) {\n * // Retry with longer timeout or smaller text\n * console.error('Request timed out');\n * }\n * }\n * ```\n */\nexport class TimeoutError extends APIError {\n constructor(message: string = 'Request timed out') {\n super(message, 408, true, 'TIMEOUT_ERROR');\n this.name = 'TimeoutError';\n }\n}\n\n/**\n * Parse structured output from LLM provider error\n */\nfunction parseProviderError(error: unknown): { message: string; statusCode?: number; code?: string } {\n if (error instanceof Error) {\n const message = error.message;\n const err = error as Error & { statusCode?: number; status?: number };\n\n // Prefer a statusCode/status property (Vercel AI SDK's APICallError sets these)\n // then fall back to parsing from the message string\n const statusMatch = message.match(/\\b(4\\d{2}|5\\d{2})\\b/);\n const statusCode =\n err.statusCode ??\n err.status ??\n (statusMatch ? parseInt(statusMatch[1]) : undefined);\n\n return {\n message,\n statusCode,\n code: error.name !== 'Error' ? error.name : undefined,\n };\n }\n\n return {\n message: String(error),\n };\n}\n\n/**\n * Wrap a provider error into the appropriate error type.\n *\n * Returns `ConfigurationError` for model-not-found responses (HTTP 404, or HTTP 400\n * with a model-related message), since those indicate a bad model ID in configuration.\n * Returns the appropriate `APIError` subclass for all other provider errors.\n *\n * @internal\n */\nexport function wrapProviderError(error: unknown, defaultMessage: string = 'API request failed'): EvaluatorError {\n const { message, statusCode, code } = parseProviderError(error);\n\n // Detect model-not-found errors (404, or 400 with model-related message)\n if (\n statusCode === 404 ||\n (statusCode === 400 && /\\bmodel\\b.*(not found|does not exist|invalid)/i.test(message))\n ) {\n return new ConfigurationError(\n `Model not found or invalid: ${message}. Check the model ID passed to the provider.`\n );\n }\n\n // Detect authentication errors (401, 403)\n if (statusCode === 401 || statusCode === 403) {\n return new AuthenticationError(\n message.includes('API key') ? message : 'Invalid API key',\n statusCode\n );\n }\n\n // Detect rate limit errors (429)\n if (statusCode === 429) {\n // Try to extract retry-after if present\n const retryAfterMatch = message.match(/retry[- ]after[:\\s]+(\\d+)/i);\n const retryAfter = retryAfterMatch ? parseInt(retryAfterMatch[1]) * 1000 : undefined;\n\n return new RateLimitError(\n message.includes('rate limit') ? message : 'Rate limit exceeded',\n retryAfter\n );\n }\n\n // Detect network errors\n if (\n message.includes('ECONNREFUSED') ||\n message.includes('ENOTFOUND') ||\n message.includes('ETIMEDOUT') ||\n message.includes('network') ||\n message.includes('Network')\n ) {\n return new NetworkError(message);\n }\n\n // Detect timeout errors\n if (message.includes('timeout') || message.includes('timed out')) {\n return new TimeoutError(message);\n }\n\n // Generic API error for everything else\n return new APIError(\n message || defaultMessage,\n statusCode,\n statusCode ? statusCode >= 500 : false, // 5xx errors are retryable\n code\n );\n}\n","/**\n * Logging interface for the Evaluators SDK\n *\n * Provides structured logging with verbosity levels.\n * Users can inject custom loggers or use the default console logger.\n */\n\n/**\n * Log levels in order of verbosity\n */\nexport enum LogLevel {\n /** Debug messages - very verbose, for development */\n DEBUG = 0,\n /** Informational messages - normal operations */\n INFO = 1,\n /** Warning messages - potentially problematic situations */\n WARN = 2,\n /** Error messages - errors that need attention */\n ERROR = 3,\n /** Silent - no logging */\n SILENT = 4,\n}\n\n/**\n * Context object for structured logging\n */\nexport interface LogContext {\n /** Evaluator type (vocabulary, sentence-structure, etc.) */\n evaluator?: string;\n /** Current operation or stage */\n operation?: string;\n /** Error object if applicable */\n error?: Error;\n /** Additional metadata */\n [key: string]: unknown;\n}\n\n/**\n * Logger interface\n *\n * Implement this interface to provide custom logging behavior.\n *\n * @example\n * ```typescript\n * const customLogger: Logger = {\n * debug: (msg, ctx) => myLogger.debug(msg, ctx),\n * info: (msg, ctx) => myLogger.info(msg, ctx),\n * warn: (msg, ctx) => myLogger.warn(msg, ctx),\n * error: (msg, ctx) => myLogger.error(msg, ctx),\n * };\n *\n * const evaluator = new VocabularyEvaluator({\n * googleApiKey: '...',\n * openaiApiKey: '...',\n * logger: customLogger,\n * logLevel: LogLevel.INFO,\n * });\n * ```\n */\nexport interface Logger {\n /**\n * Log debug message\n * Used for detailed debugging information\n */\n debug(message: string, context?: LogContext): void;\n\n /**\n * Log informational message\n * Used for normal operations\n */\n info(message: string, context?: LogContext): void;\n\n /**\n * Log warning message\n * Used for potentially problematic situations\n */\n warn(message: string, context?: LogContext): void;\n\n /**\n * Log error message\n * Used for errors that need attention\n */\n error(message: string, context?: LogContext): void;\n}\n\n/**\n * Default console logger implementation\n */\nclass ConsoleLogger implements Logger {\n constructor(private level: LogLevel = LogLevel.WARN) {}\n\n debug(message: string, context?: LogContext): void {\n if (this.level <= LogLevel.DEBUG) {\n console.debug(`[DEBUG] ${message}`, context || '');\n }\n }\n\n info(message: string, context?: LogContext): void {\n if (this.level <= LogLevel.INFO) {\n console.info(`[INFO] ${message}`, context || '');\n }\n }\n\n warn(message: string, context?: LogContext): void {\n if (this.level <= LogLevel.WARN) {\n console.warn(`[WARN] ${message}`, context || '');\n }\n }\n\n error(message: string, context?: LogContext): void {\n if (this.level <= LogLevel.ERROR) {\n console.error(`[ERROR] ${message}`, context || '');\n }\n }\n}\n\n/**\n * Silent logger - logs nothing\n */\nclass SilentLogger implements Logger {\n debug(): void {}\n info(): void {}\n warn(): void {}\n error(): void {}\n}\n\n/**\n * Create a logger instance\n *\n * @param customLogger - Optional custom logger implementation\n * @param level - Log level (default: WARN)\n * @returns Logger instance\n */\nexport function createLogger(customLogger?: Logger, level: LogLevel = LogLevel.WARN): Logger {\n // Use custom logger if provided\n if (customLogger) {\n return customLogger;\n }\n\n // Use silent logger if level is SILENT\n if (level === LogLevel.SILENT) {\n return new SilentLogger();\n }\n\n // Use console logger with specified level\n return new ConsoleLogger(level);\n}\n\n/**\n * Format error for logging\n *\n * @internal\n */\nexport function formatError(error: unknown): string {\n if (error instanceof Error) {\n return `${error.name}: ${error.message}`;\n }\n return String(error);\n}\n","import { generateText as aiGenerateText, Output } from 'ai';\nimport type {\n LLMProvider,\n LLMRequest,\n LLMResponse,\n Message,\n ProviderConfig,\n} from './base.js';\n\n/**\n * Vercel AI SDK provider implementation\n * Supports OpenAI, Anthropic, and Google Gemini\n */\nexport class VercelAIProvider implements LLMProvider {\n readonly label: string;\n private readonly model: string;\n\n constructor(private config: ProviderConfig) {\n if (config.type === 'custom') {\n throw new Error(\n 'VercelAIProvider does not support custom type. Use config.customProvider directly.'\n );\n }\n if (!config.model || config.model.trim() === '') {\n throw new Error(\n `model is required for VercelAIProvider (type: \"${config.type}\"). No default is assumed.`\n );\n }\n this.model = config.model;\n this.label = `${config.type}:${config.model}`;\n }\n\n /**\n * Generate structured output using Vercel AI SDK's generateText with output\n */\n async generateStructured<T>(request: LLMRequest<T>): Promise<LLMResponse<T>> {\n const model = await this.getModel();\n const startTime = Date.now();\n\n const { output, usage } = await aiGenerateText({\n model,\n messages: request.messages,\n output: Output.object({ schema: request.schema }),\n temperature: request.temperature ?? 0,\n maxRetries: this.config.maxRetries ?? 0,\n ...(request.maxTokens !== undefined ? { maxTokens: request.maxTokens } : {}),\n });\n\n return {\n data: output as T,\n model: this.model,\n usage: {\n inputTokens: usage.inputTokens || 0,\n outputTokens: usage.outputTokens || 0,\n },\n latencyMs: Date.now() - startTime,\n };\n }\n\n /**\n * Generate plain text using Vercel AI SDK's generateText\n */\n async generateText(messages: Message[], temperature?: number): Promise<import('./base.js').TextGenerationResponse> {\n const model = await this.getModel();\n const startTime = Date.now();\n\n const { text, usage } = await aiGenerateText({\n model,\n messages,\n temperature: temperature ?? this.config.temperature ?? 0,\n maxRetries: this.config.maxRetries ?? 0,\n });\n\n return {\n text,\n usage: {\n inputTokens: usage.inputTokens || 0,\n outputTokens: usage.outputTokens || 0,\n },\n latencyMs: Date.now() - startTime,\n };\n }\n\n /**\n * Get the configured language model.\n * Uses dynamic imports so consumers only need to install the provider packages they use.\n */\n private async getModel() {\n const apiKey = this.config.apiKey;\n\n switch (this.config.type) {\n case 'openai': {\n const { createOpenAI } = await import('@ai-sdk/openai').catch(() => {\n throw new Error(\n 'To use the OpenAI provider, install its adapter: npm install @ai-sdk/openai'\n );\n });\n return createOpenAI(apiKey ? { apiKey } : {})(this.model);\n }\n case 'anthropic': {\n const { createAnthropic } = await import('@ai-sdk/anthropic').catch(() => {\n throw new Error(\n 'To use the Anthropic provider, install its adapter: npm install @ai-sdk/anthropic'\n );\n });\n return createAnthropic(apiKey ? { apiKey } : {})(this.model);\n }\n case 'google': {\n const { createGoogleGenerativeAI } = await import('@ai-sdk/google').catch(() => {\n throw new Error(\n 'To use the Google provider, install its adapter: npm install @ai-sdk/google'\n );\n });\n return createGoogleGenerativeAI(apiKey ? { apiKey } : {})(this.model);\n }\n default:\n throw new Error(`Unsupported provider type: ${this.config.type}`);\n }\n }\n}\n\n/**\n * Factory function to create a provider instance\n */\nexport function createProvider(config: ProviderConfig): LLMProvider {\n if (config.type === 'custom' && config.customProvider) {\n return config.customProvider;\n }\n\n return new VercelAIProvider(config);\n}\n","import {\n TelemetryClient,\n generateClientId,\n getSDKVersion,\n type TelemetryMetadata,\n type TokenUsage,\n} from '../telemetry/index.js';\nimport { ConfigurationError, ValidationError } from '../errors.js';\nimport { createLogger, LogLevel, type Logger } from '../logger.js';\nimport { createProvider } from '../providers/index.js';\nimport type { LLMProvider } from '../providers/index.js';\n\n/**\n * Validation constants for input text\n */\nexport const VALIDATION_LIMITS = {\n /** Minimum text length in characters */\n MIN_TEXT_LENGTH: 10,\n /** Maximum text length in characters (100K chars ≈ 25K tokens) */\n MAX_TEXT_LENGTH: 100_000,\n} as const;\n\n/**\n * Supported LLM providers\n */\nexport enum Provider {\n OpenAI = 'openai',\n Google = 'google',\n Anthropic = 'anthropic',\n}\n\n/**\n * Granular telemetry configuration options\n */\nexport interface TelemetryOptions {\n /** Enable telemetry (default: true) */\n enabled?: boolean;\n\n /** Record input text in telemetry (default: false) */\n recordInputs?: boolean;\n}\n\n/**\n * Override the provider and model used by an evaluator.\n *\n * When set, all LLM calls use this provider and model instead of the defaults.\n * The evaluator's normal key requirements are bypassed — provide the key for\n * the chosen provider via the matching top-level config field\n * (e.g. `anthropicApiKey` for `Provider.Anthropic`).\n *\n * Both `provider` and `model` are required. An empty or missing `model` throws\n * `ConfigurationError` at construction time. An unrecognised model ID throws\n * `ConfigurationError` at evaluation time when the provider rejects it.\n *\n * Results may vary; evaluators are validated against their recommended models.\n */\nexport interface ModelOverride {\n provider: Provider;\n model: string;\n}\n\n/**\n * Base configuration for all evaluators\n */\nexport interface BaseEvaluatorConfig {\n /** Google API key (for evaluators using Gemini) */\n googleApiKey?: string;\n\n /** OpenAI API key (for evaluators using GPT) */\n openaiApiKey?: string;\n\n /** Anthropic API key (for evaluators using Claude) */\n anthropicApiKey?: string;\n\n /** Learning Commons partner key for authenticated telemetry (optional) */\n partnerKey?: string;\n\n /**\n * Override the provider and model used by this evaluator.\n * When set, all LLM calls use this provider and model instead of the defaults.\n * See {@link ModelOverride} for details.\n */\n modelOverride?: ModelOverride;\n\n /**\n * Maximum number of retries for failed API calls (default: 2)\n * Set to 0 to disable retries.\n *\n * Note: With maxRetries=2, a failed call will be attempted up to 3 times total\n * (1 initial attempt + 2 retries)\n */\n maxRetries?: number;\n\n /**\n * Telemetry configuration (default: all enabled)\n *\n * Can be:\n * - `true`: Enable with defaults (recordInputs: false)\n * - `false`: Disable completely\n * - `TelemetryOptions`: Granular control\n */\n telemetry?: boolean | TelemetryOptions;\n\n /**\n * Custom logger implementation (optional)\n * If not provided, uses console logger with specified logLevel\n */\n logger?: Logger;\n\n /**\n * Log level for default console logger (default: WARN)\n * Only used if custom logger is not provided\n *\n * - DEBUG: Very verbose, shows all operations\n * - INFO: Normal operations\n * - WARN: Warnings only (default)\n * - ERROR: Errors only\n * - SILENT: No logging\n */\n logLevel?: LogLevel;\n}\n\n/**\n * Evaluator metadata interface\n * Each evaluator must provide this metadata as static properties\n */\nexport interface EvaluatorMetadata {\n /** Unique identifier for the evaluator (e.g., 'vocabulary', 'sentence-structure') */\n readonly id: string;\n /** Human-readable name (e.g., 'Vocabulary', 'Sentence Structure') */\n readonly name: string;\n /** Brief description of what the evaluator does */\n readonly description: string;\n /** Supported grade levels (e.g., ['3', '4', '5', ...]) */\n readonly supportedGrades: readonly string[];\n /** Providers required by this evaluator's default configuration */\n readonly defaultProviders: readonly Provider[];\n}\n\n/**\n * Abstract base class for all evaluators\n *\n * Provides common functionality:\n * - Telemetry setup and event sending\n * - Text validation\n * - Grade validation (with overridable default)\n * - Metadata creation\n *\n * Concrete evaluators must implement:\n * - static metadata: Provide evaluator metadata (see EvaluatorMetadata interface)\n */\nexport abstract class BaseEvaluator {\n protected telemetryClient?: TelemetryClient;\n protected logger: Logger;\n protected config: Required<Pick<BaseEvaluatorConfig, 'maxRetries'>> & {\n telemetry: Required<TelemetryOptions>;\n modelOverride?: ModelOverride;\n googleApiKey?: string;\n openaiApiKey?: string;\n anthropicApiKey?: string;\n };\n\n /**\n * Static metadata for the evaluator\n *\n * Concrete evaluators MUST define this property.\n *\n * @example\n * ```typescript\n * class MyEvaluator extends BaseEvaluator {\n * static readonly metadata = {\n * id: 'my-evaluator',\n * name: 'My Evaluator',\n * description: 'Does something useful',\n * supportedGrades: ['3', '4', '5'],\n * defaultProviders: [Provider.Google],\n * };\n * }\n * ```\n */\n static readonly metadata: EvaluatorMetadata;\n\n /**\n * @throws {ConfigurationError} If the subclass has not defined static metadata\n * @throws {ConfigurationError} If modelOverride has an invalid provider or empty model\n * @throws {ConfigurationError} If a required API key is missing\n */\n constructor(config: BaseEvaluatorConfig) {\n // Initialize logger\n this.logger = createLogger(config.logger, config.logLevel ?? LogLevel.WARN);\n\n // Validate modelOverride shape before key checks\n this.validateModelOverride(config);\n\n // Validate required API keys based on metadata\n this.validateApiKeys(config);\n\n // Normalize telemetry config\n const telemetryConfig = this.normalizeTelemetryConfig(config.telemetry);\n\n // Set defaults for common config\n this.config = {\n maxRetries: config.maxRetries ?? 2,\n telemetry: telemetryConfig,\n modelOverride: config.modelOverride,\n googleApiKey: config.googleApiKey,\n openaiApiKey: config.openaiApiKey,\n anthropicApiKey: config.anthropicApiKey,\n };\n\n if (config.modelOverride) {\n this.logger.warn(\n `modelOverride is active: using ${config.modelOverride.provider}:${config.modelOverride.model} instead of the default model. ` +\n 'Evaluation quality may differ from recommended defaults.'\n );\n }\n\n // Initialize telemetry if enabled\n if (this.config.telemetry.enabled) {\n this.telemetryClient = new TelemetryClient({\n endpoint: 'https://api.learningcommons.org/evaluators-telemetry/v1/events',\n partnerKey: config.partnerKey,\n clientId: generateClientId(),\n enabled: true,\n logger: this.logger,\n });\n }\n }\n\n /**\n * Get metadata for this evaluator instance\n * @throws {ConfigurationError} If the subclass has not defined static metadata\n */\n protected get metadata(): EvaluatorMetadata {\n const meta = (this.constructor as typeof BaseEvaluator).metadata;\n if (!meta) {\n throw new ConfigurationError(\n `${this.constructor.name} must define a static readonly metadata block.`\n );\n }\n return meta;\n }\n\n /**\n * Validate modelOverride shape: provider must be a known Provider value and\n * model must be a non-empty string.\n * @throws {ConfigurationError} If the override is malformed\n */\n private validateModelOverride(config: BaseEvaluatorConfig): void {\n if (!config.modelOverride) return;\n\n const validProviders = Object.values(Provider) as string[];\n if (!validProviders.includes(config.modelOverride.provider as string)) {\n throw new ConfigurationError(\n `Invalid provider \"${config.modelOverride.provider}\" in modelOverride. Valid providers are: ${validProviders.join(', ')}.`\n );\n }\n\n if (!config.modelOverride.model || config.modelOverride.model.trim() === '') {\n throw new ConfigurationError(\n `modelOverride.model is required. Specify the model ID for provider \"${config.modelOverride.provider}\".`\n );\n }\n }\n\n /**\n * Validate that the required API key is present.\n * When modelOverride is set, checks the override provider's key.\n * Otherwise checks the keys required by the evaluator's default providers.\n * @throws {ConfigurationError} If a required key is missing\n */\n private validateApiKeys(config: BaseEvaluatorConfig): void {\n const keyFor: Record<Provider, string | undefined> = {\n [Provider.OpenAI]: config.openaiApiKey?.trim() || undefined,\n [Provider.Google]: config.googleApiKey?.trim() || undefined,\n [Provider.Anthropic]: config.anthropicApiKey?.trim() || undefined,\n };\n const humanName: Record<Provider, string> = {\n [Provider.OpenAI]: 'OpenAI API key',\n [Provider.Google]: 'Google API key',\n [Provider.Anthropic]: 'Anthropic API key',\n };\n const configKey: Record<Provider, string> = {\n [Provider.OpenAI]: 'openaiApiKey',\n [Provider.Google]: 'googleApiKey',\n [Provider.Anthropic]: 'anthropicApiKey',\n };\n\n if (config.modelOverride) {\n if (!keyFor[config.modelOverride.provider]) {\n throw new ConfigurationError(\n `${humanName[config.modelOverride.provider]} is required when using modelOverride with provider \"${config.modelOverride.provider}\". Pass ${configKey[config.modelOverride.provider]} in config.`\n );\n }\n return;\n }\n\n for (const provider of this.metadata.defaultProviders) {\n if (!keyFor[provider]) {\n throw new ConfigurationError(\n `${humanName[provider]} is required for ${this.metadata.name} evaluator. Pass ${configKey[provider]} in config.`\n );\n }\n }\n }\n\n /**\n * Normalize telemetry config to standard format\n */\n private normalizeTelemetryConfig(\n telemetry: boolean | TelemetryOptions | undefined\n ): Required<TelemetryOptions> {\n // Handle boolean shortcuts\n if (telemetry === false) {\n return {\n enabled: false,\n recordInputs: false,\n };\n }\n\n if (telemetry === true || telemetry === undefined) {\n return {\n enabled: true,\n recordInputs: false,\n };\n }\n\n // Handle granular config object\n return {\n enabled: telemetry.enabled ?? true,\n recordInputs: telemetry.recordInputs ?? false,\n };\n }\n\n /**\n * Get the evaluator type identifier from metadata\n * @returns The evaluator type ID (e.g., \"vocabulary\", \"sentence-structure\")\n */\n protected getEvaluatorType(): string {\n return this.metadata.id;\n }\n\n /**\n * Validate text meets requirements\n * Default implementation - can be overridden by concrete evaluators\n *\n * @throws {ValidationError} If text is invalid\n */\n protected validateText(text: string): void {\n this.logger.debug('Validating text input', {\n evaluator: this.getEvaluatorType(),\n operation: 'validateText',\n textLength: text.length,\n });\n\n // Check if text is empty or only whitespace\n const trimmedText = text.trim();\n if (!trimmedText) {\n throw new ValidationError('Text cannot be empty or contain only whitespace');\n }\n\n // Check minimum length\n if (trimmedText.length < VALIDATION_LIMITS.MIN_TEXT_LENGTH) {\n throw new ValidationError(\n `Text is too short. Minimum length is ${VALIDATION_LIMITS.MIN_TEXT_LENGTH} characters, received ${trimmedText.length} characters`\n );\n }\n\n // Check maximum length\n if (trimmedText.length > VALIDATION_LIMITS.MAX_TEXT_LENGTH) {\n throw new ValidationError(\n `Text is too long. Maximum length is ${VALIDATION_LIMITS.MAX_TEXT_LENGTH.toLocaleString()} characters, received ${trimmedText.length.toLocaleString()} characters`\n );\n }\n }\n\n /**\n * Validate grade is in supported range\n * Default implementation - can be overridden by concrete evaluators\n *\n * @param grade - Grade level to validate\n * @param validGrades - Set of valid grades for this evaluator\n * @throws {ValidationError} If grade is invalid\n */\n protected validateGrade(grade: string, validGrades: Set<string>): void {\n this.logger.debug('Validating grade input', {\n evaluator: this.getEvaluatorType(),\n operation: 'validateGrade',\n grade,\n });\n\n // Check if grade is in valid set\n if (!validGrades.has(grade)) {\n const validList = Array.from(validGrades).sort((a, b) => {\n // Sort K first, then numerically\n if (a === 'K') return -1;\n if (b === 'K') return 1;\n return parseInt(a, 10) - parseInt(b, 10);\n }).join(', ');\n\n throw new ValidationError(\n `Invalid grade \"${grade}\". Supported grades for this evaluator: ${validList}`\n );\n }\n }\n\n /**\n * Create an LLM provider, honouring modelOverride if set.\n * When override is active, the key for the override provider is resolved\n * from the matching top-level config field (e.g. anthropicApiKey for Anthropic).\n */\n protected createConfiguredProvider(\n defaultType: Provider,\n defaultModel: string,\n defaultApiKey: string | undefined,\n ): LLMProvider {\n const override = this.config.modelOverride;\n if (override) {\n const apiKeyFor: Record<Provider, string | undefined> = {\n [Provider.OpenAI]: this.config.openaiApiKey,\n [Provider.Google]: this.config.googleApiKey,\n [Provider.Anthropic]: this.config.anthropicApiKey,\n };\n return createProvider({\n type: override.provider,\n model: override.model,\n apiKey: apiKeyFor[override.provider],\n maxRetries: this.config.maxRetries,\n });\n }\n return createProvider({\n type: defaultType,\n model: defaultModel,\n apiKey: defaultApiKey,\n maxRetries: this.config.maxRetries,\n });\n }\n\n /**\n * Send telemetry event to analytics service\n * Common helper for all evaluators\n */\n protected async sendTelemetry(params: {\n status: 'success' | 'error';\n latencyMs: number;\n textLength: number;\n grade?: string;\n provider: string;\n errorCode?: string;\n tokenUsage?: TokenUsage;\n metadata?: TelemetryMetadata;\n inputText?: string;\n }): Promise<void> {\n if (!this.telemetryClient) {\n return;\n }\n\n await this.telemetryClient.send({\n timestamp: new Date().toISOString(),\n sdk_version: getSDKVersion(),\n evaluator_type: this.getEvaluatorType(),\n grade: params.grade,\n status: params.status,\n error_code: params.errorCode,\n latency_ms: params.latencyMs,\n text_length_chars: params.textLength,\n provider: params.provider,\n token_usage: params.tokenUsage,\n metadata: params.metadata,\n model_override: this.config.modelOverride ? true : undefined,\n // Include input text only if recording is enabled\n input_text: this.config.telemetry.recordInputs ? params.inputText : undefined,\n });\n }\n}\n","import { z } from 'zod';\n\n/**\n * Shared complexity levels used across all text complexity evaluators\n * (Vocabulary, Sentence Structure, and any future sub-evaluators)\n */\nexport const TextComplexityLevel = z.enum([\n 'Slightly complex',\n 'Moderately complex',\n 'Very complex',\n 'Exceedingly complex',\n]);\n\nexport type TextComplexityLevel = z.infer<typeof TextComplexityLevel>;\n\n/**\n * Metadata attached to all evaluation results\n */\nexport interface EvaluationMetadata {\n model: string;\n processingTimeMs: number;\n}\n\n/**\n * Base evaluation result structure\n */\nexport interface EvaluationResult<TScore = string, TInternal = unknown> {\n score: TScore;\n reasoning: string;\n metadata: EvaluationMetadata;\n _internal?: TInternal;\n}\n\n/**\n * Batch evaluation summary statistics\n */\nexport interface BatchSummary {\n total: number;\n successful: number;\n failed: number;\n averageProcessingTimeMs: number;\n}\n\n/**\n * Error type for failed evaluations\n */\nexport interface EvaluationError {\n error: string;\n input: {\n text: string;\n grade?: string;\n };\n}\n\n/**\n * Batch evaluation result\n */\nexport interface BatchEvaluationResult<T = EvaluationResult> {\n results: Array<T | EvaluationError>;\n summary: BatchSummary;\n}\n","import { z } from 'zod';\nimport { TextComplexityLevel } from './outputs.js';\n\n/**\n * Vocabulary evaluation output schema\n */\nexport const VocabularyComplexitySchema = z.object({\n tier_2_words: z.string().describe('List of Tier 2 words (academic words)'),\n tier_3_words: z.string().describe('List of Tier 3 words (domain-specific)'),\n archaic_words: z.string().describe('List of Archaic words'),\n other_complex_words: z.string().describe('List of Other Complex words'),\n complexity_score: TextComplexityLevel.describe(\n 'The complexity of the text vocabulary'\n ),\n reasoning: z.string().describe('Detailed reasoning for the complexity rating'),\n});\n\nexport type VocabularyInternal = z.infer<typeof VocabularyComplexitySchema>;\n\n/**\n * Background knowledge assumption for a student at a given grade level\n * This is generated in Stage 1 and used as input for Stage 2\n */\nexport interface BackgroundKnowledge {\n assumption: string;\n grade: string;\n}\n","import nlp from 'compromise';\nimport { syllable } from 'syllable';\n\n/**\n * Calculate Flesch-Kincaid Grade Level\n * Equivalent to Python's textstat.flesch_kincaid_grade()\n */\nexport function calculateFleschKincaidGrade(text: string): number {\n return calculateReadabilityMetrics(text).fleschKincaidGrade;\n}\n\n/**\n * Additional readability metrics\n */\nexport interface ReadabilityMetrics {\n sentenceCount: number;\n wordCount: number;\n characterCount: number;\n syllableCount: number;\n avgWordsPerSentence: number;\n avgSyllablesPerWord: number;\n fleschKincaidGrade: number;\n}\n\nexport function calculateReadabilityMetrics(text: string): ReadabilityMetrics {\n const doc = nlp(text);\n\n const sentences = doc.sentences().length;\n const terms = doc.terms();\n const words = terms.length;\n const characters = text.replace(/\\s/g, '').length;\n\n const allWords = terms.out('array');\n const totalSyllables = allWords.reduce((sum: number, word: string) => sum + syllable(word), 0);\n\n const avgWordsPerSentence = sentences > 0 ? words / sentences : 0;\n const avgSyllablesPerWord = words > 0 ? totalSyllables / words : 0;\n const fkGrade = 0.39 * avgWordsPerSentence + 11.8 * avgSyllablesPerWord - 15.59;\n\n return {\n sentenceCount: sentences,\n wordCount: words,\n characterCount: characters,\n syllableCount: totalSyllables,\n avgWordsPerSentence,\n avgSyllablesPerWord,\n fleschKincaidGrade: Math.round(Math.max(0, fkGrade) * 100) / 100,\n };\n}\n","import type { SentenceAnalysis, SentenceFeatures } from '../schemas/sentence-structure.js';\n\n/**\n * Safe division helper (avoids division by zero)\n */\nfunction safeDivision(numerator: number, denominator: number): number {\n return denominator === 0 ? 0 : numerator / denominator;\n}\n\n/**\n * Calculate standard deviation of an array of numbers\n */\nfunction standardDeviation(values: number[]): number {\n if (values.length <= 1) return 0;\n\n const mean = values.reduce((sum, val) => sum + val, 0) / values.length;\n const squaredDiffs = values.map((val) => Math.pow(val - mean, 2));\n const variance = squaredDiffs.reduce((sum, val) => sum + val, 0) / values.length;\n\n return Math.sqrt(variance);\n}\n\n/**\n * Categorize sentence lengths into short/medium/long/very long\n */\nfunction categorizeSentenceLengths(wordCounts: number[]) {\n if (!wordCounts || wordCounts.length === 0) {\n return {\n percent_short_sentences: 0,\n percent_medium_sentences: 0,\n percent_long_sentences: 0,\n percent_very_long_sentences: 0,\n };\n }\n\n let short = 0,\n medium = 0,\n long = 0,\n veryLong = 0;\n\n for (const count of wordCounts) {\n if (count <= 10) short++;\n else if (count <= 20) medium++;\n else if (count <= 30) long++;\n else veryLong++;\n }\n\n const total = wordCounts.length;\n\n return {\n percent_short_sentences: (short / total) * 100,\n percent_medium_sentences: (medium / total) * 100,\n percent_long_sentences: (long / total) * 100,\n percent_very_long_sentences: (veryLong / total) * 100,\n };\n}\n\n/**\n * Add engineered features to sentence analysis output\n * Ported from Python add_engineered_features function\n */\nexport function addEngineeredFeatures(analysis: SentenceAnalysis): SentenceFeatures {\n const numSentences = analysis.num_sentences;\n const numWords = analysis.num_words;\n\n // Foundational Metrics\n const avg_words_per_sentence = safeDivision(numWords, numSentences);\n const sentence_length_variation = standardDeviation(analysis.sentence_word_counts);\n const lengthCategories = categorizeSentenceLengths(analysis.sentence_word_counts);\n\n // Sentence Structure Percentages\n const percent_simple_sentences = safeDivision(analysis.num_simple_sentences, numSentences) * 100;\n const percent_compound_sentences =\n safeDivision(analysis.num_compound_sentences, numSentences) * 100;\n const percent_complex_sentences = safeDivision(analysis.num_complex_sentences, numSentences) * 100;\n const percent_compound_complex_sentences =\n safeDivision(analysis.num_compound_complex_sentences, numSentences) * 100;\n const percent_other_sentences = safeDivision(analysis.num_other_sentences, numSentences) * 100;\n\n // Word Distribution Percentages\n const percent_words_in_simple_sentences =\n safeDivision(analysis.words_in_simple_sentences, numWords) * 100;\n const percent_words_in_compound_sentences =\n safeDivision(analysis.words_in_compound_sentences, numWords) * 100;\n const percent_words_in_complex_sentences =\n safeDivision(analysis.words_in_complex_sentences, numWords) * 100;\n const percent_words_in_compound_complex_sentences =\n safeDivision(analysis.words_in_compound_complex_sentences, numWords) * 100;\n const percent_words_in_other_sentences =\n safeDivision(analysis.words_in_other_sentences, numWords) * 100;\n\n // Subordination and Clausal Complexity\n const avg_subordinates_per_sentence = safeDivision(analysis.num_subordinate_clauses, numSentences);\n const avg_clauses_per_sentence = safeDivision(analysis.num_total_clauses, numSentences);\n const percent_sentences_with_subordinate =\n safeDivision(analysis.num_sentences_with_subordinate, numSentences) * 100;\n const percent_sentences_with_multiple_subordinates =\n safeDivision(analysis.num_sentences_with_multiple_subordinates, numSentences) * 100;\n const percent_sentences_with_embedded_clauses =\n safeDivision(analysis.num_sentences_with_embedded_clauses, numSentences) * 100;\n\n // Phrase Density (per 100 words)\n const prep_phrase_density = safeDivision(analysis.num_prepositional_phrases, numWords) * 100;\n const participle_phrase_density = safeDivision(analysis.num_participle_phrases, numWords) * 100;\n const appositive_phrase_density = safeDivision(analysis.num_appositive_phrases, numWords) * 100;\n\n // Cohesion and Transitions\n const total_transitions = analysis.num_simple_transitions + analysis.num_sophisticated_transitions;\n const avg_transitions_per_sentence = safeDivision(total_transitions, numSentences);\n const percent_sophisticated_transitions =\n safeDivision(analysis.num_sophisticated_transitions, total_transitions) * 100;\n\n // Conceptual & Other\n const percent_sentences_w_one_concept =\n safeDivision(analysis.num_one_concept_sentences, numSentences) * 100;\n const percent_sentences_w_multi_concept =\n safeDivision(analysis.num_multi_concept_sentences, numSentences) * 100;\n const percent_cleft_sentences = safeDivision(analysis.num_cleft_sentences, numSentences) * 100;\n\n return {\n ...analysis,\n avg_words_per_sentence,\n sentence_length_variation,\n ...lengthCategories,\n percent_simple_sentences,\n percent_compound_sentences,\n percent_complex_sentences,\n percent_compound_complex_sentences,\n percent_other_sentences,\n percent_words_in_simple_sentences,\n percent_words_in_compound_sentences,\n percent_words_in_complex_sentences,\n percent_words_in_compound_complex_sentences,\n percent_words_in_other_sentences,\n avg_subordinates_per_sentence,\n avg_clauses_per_sentence,\n percent_sentences_with_subordinate,\n percent_sentences_with_multiple_subordinates,\n percent_sentences_with_embedded_clauses,\n prep_phrase_density,\n participle_phrase_density,\n appositive_phrase_density,\n avg_transitions_per_sentence,\n percent_sophisticated_transitions,\n percent_sentences_w_one_concept,\n percent_sentences_w_multi_concept,\n percent_cleft_sentences,\n };\n}\n\n/**\n * Feature columns used for complexity classification\n * Must match the order and names from Python FEATURE_COLS\n */\nexport const FEATURE_COLS = [\n // Foundational & Distributional\n 'avg_words_per_sentence',\n 'sentence_length_variation',\n 'percent_short_sentences',\n 'percent_medium_sentences',\n 'percent_long_sentences',\n 'percent_very_long_sentences',\n 'flesch_kincaid_grade',\n // Sentence Structure (Grammatical Type)\n 'percent_simple_sentences',\n 'percent_compound_sentences',\n 'percent_complex_sentences',\n 'percent_compound_complex_sentences',\n 'percent_other_sentences',\n // Word Distribution\n 'percent_words_in_simple_sentences',\n 'percent_words_in_complex_sentences',\n 'percent_words_in_compound_sentences',\n 'percent_words_in_compound_complex_sentences',\n 'percent_words_in_other_sentences',\n // Clausal & Subordination\n 'avg_subordinates_per_sentence',\n 'avg_clauses_per_sentence',\n 'percent_sentences_with_subordinate',\n 'percent_sentences_with_multiple_subordinates',\n 'percent_sentences_with_embedded_clauses',\n // Phrase Density\n 'prep_phrase_density',\n 'participle_phrase_density',\n 'appositive_phrase_density',\n // Cohesion & Transitions\n 'avg_transitions_per_sentence',\n 'percent_sophisticated_transitions',\n // Conceptual & Other\n 'percent_sentences_w_one_concept',\n 'percent_sentences_w_multi_concept',\n 'percent_cleft_sentences',\n 'max_clauses_in_any_sentence',\n // Grades 5-12\n 'num_sentences',\n 'num_simple_sentences',\n 'num_compound',\n 'num_basic_complex',\n 'num_advanced_complex',\n 'percentage_simple',\n 'percentage_compound',\n 'percentage_basic_complex',\n 'percentage_advanced_complex',\n] as const;\n\n/**\n * Convert sentence features to JSON string for LLM prompt\n * Ported from Python row_to_features_json\n */\nexport function featuresToJSON(\n features: SentenceFeatures,\n decimals = 1,\n castToInt = true\n): string {\n const payload: Record<string, number | null> = {};\n\n for (const col of FEATURE_COLS) {\n const value = features[col as keyof SentenceFeatures];\n if (typeof value === 'number') {\n const rounded = Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals);\n payload[col] = castToInt ? Math.round(rounded) : rounded;\n } else {\n payload[col] = null;\n }\n }\n\n return JSON.stringify(payload, null, 2);\n}\n","import textReadability from 'text-readability';\n\nexport interface PostTransformConfig {\n type: string;\n precision?: number;\n}\n\nexport interface PreprocessingImplementation {\n library: string;\n function: string;\n post_transform?: PostTransformConfig;\n}\n\n// ---------------------------------------------------------------------------\n// Library adapters\n// To add support for a new library: add one entry here.\n// ---------------------------------------------------------------------------\n\ninterface LibraryAdapter {\n call(fnName: string, text: string): number;\n}\n\nconst LIBRARY_ADAPTERS: Partial<Record<string, LibraryAdapter>> = {\n 'text-readability': {\n call(fnName, text) {\n const fn = textReadability[fnName];\n if (typeof fn !== 'function') {\n throw new Error(`Function \"${fnName}\" not found in text-readability.`);\n }\n return fn.call(textReadability, text);\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Post-transform handlers\n// To add a new transform type: add one entry here.\n// ---------------------------------------------------------------------------\n\ntype PostTransformHandler = (value: number, config: PostTransformConfig) => number;\n\nconst POST_TRANSFORMS: Partial<Record<string, PostTransformHandler>> = {\n round(value, { precision = 0 }) {\n const factor = 10 ** precision;\n return Math.round(value * factor) / factor;\n },\n};\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Runs a single config-declared preprocessing step against `text`.\n * Pass the language-specific implementation block (e.g. config.implementation.typescript).\n *\n * Throws if the library or post_transform type is not registered above.\n */\nexport function runPreprocessingStep(text: string, impl: PreprocessingImplementation): number {\n const adapter = LIBRARY_ADAPTERS[impl.library];\n if (!adapter) {\n const supported = Object.keys(LIBRARY_ADAPTERS).join(', ');\n throw new Error(\n `Unsupported preprocessing library \"${impl.library}\". Supported: ${supported}.`,\n );\n }\n\n let result = adapter.call(impl.function, text);\n\n if (impl.post_transform) {\n const transform = POST_TRANSFORMS[impl.post_transform.type];\n if (!transform) {\n const supported = Object.keys(POST_TRANSFORMS).join(', ');\n throw new Error(\n `Unsupported post_transform type \"${impl.post_transform.type}\". Supported: ${supported}.`,\n );\n }\n result = transform(result, impl.post_transform);\n }\n\n return result;\n}\n","\nReview the following text, which is an educational text written for students in the following grade band: {grade}.\n\nYour job is to give me a background knowledge assumption; that is: what topics, if any, from the text students are likely to be familiar with based on a standard progression of topics in US public school education, as well as topics, if any the student is not likely to be familiar with.\n\nMake sure your response is concise (between 1 - 3 lines max) and is about the topics themselves, not about any other aspect of the text (e.g. flowery language, complicated sentence structure, etc.).\n\nHere's an example:\n[START EXAMPLE]\nGrade Band: 11th\nText: I went to the woods because I wished to live deliberately, to front only the essential facts of life, and see if I could not\nlearn what it had to teach, and not, when I came to die, discover that I had not lived. I did not wish to live what was\nnot life, living is so dear; nor did I wish to practise resignation, unless it was quite necessary. I wanted to live deep and suck out all the marrow of life, to live so sturdily and Spartan-like as to put to rout all that was not life, to cut a broad swath and shave close, to drive life into a corner, and reduce it to its lowest terms, and, if it proved to be mean, why then to get the whole and genuine meanness of it, and publish its meanness to the world; or if it were sublime, to\nknow it by experience, and be able to give a true account of it in my next excursion. For most men, it appears to me,\nare in a strange uncertainty about it, whether it is of the devil or of God, and have somewhat hastily concluded that it\nis the chief end of man here to \"glorify God and enjoy him forever.\"\n\nBackground Knowledge Assumption: Assume they've studied American Transcendentalists like Thoreau and Emerson, including the mid-19th-century context of nature-focused philosophy.\n[END EXAMPLE]\n\nYou should assume that the student is an average US public school who is learning from common core curriculum. When you respond, just respond with the background knowledge assumption and nothing else.\n\nYou can use the following list of topics that we know are covered for each grade level, although use your best judgement if you know there are other topics out there that students are likely to have covered. And this doesn't cover higher grade levels, so you'll have to again use your judgement for, say, what background knowledge a 9th grader is likely to have:\n[BEGIN TOPICS]\n[\n K: [\n \"Toys and Play\", \"Weather Wonders\", \"Trees are Alive\", \"Enjoying and Appreciating Trees\",\n \"The Five Senses: How do our senses help us learn?\", \"Once Upon a Farm: What makes a good story?\",\n \"America, Then and Now: How has life in America changed over time?\", \"The Continents: What makes the world fascinating?\",\n \"Needs of Plants and Animals\", \"Pushes and Pulls\", \"Sunlight and Weather\", \"Learning and Working Together\",\n \"How Do People Learn and Work Together?\", \"Where Do We Live?\", \"What Does it Mean to Be an American?\",\n \"How Has Our World Changed?\", \"Why Do People Have Jobs?\"\n ],\n 1: [\n \"Tools and Work\", \"A Study of the Sun, Moon, and Stars\", \"Birds' Amazing Bodies\", \"Caring for Birds\",\n \"A World of Books: How do books change lives around the world?\", \"Creature Features: What can we discover about animals' unique features?\",\n \"Powerful Forces: How do people respond to the powerful force of the wind?\", \"Cinderella Stories: Why do people around the world admire Cinderella?\",\n \"Animal and Plant Defenses\", \"Light and Sounds\", \"Spinning Earth\", \"Our Place in the World\",\n \"What Are the Rights and Responsibilities of Citizens?\", \"How Can We Describe Where We Live?\",\n \"How Do We Celebrate Our Country?\", \"How Does the Past Shape Our Lives?\", \"Why Do People Work?\"\n ],\n 2: [\n \"Schools and Community\", \"Fossils Tell of Earth's Changes\", \"The Secret World of Pollination\", \"Providing for Pollinators\",\n \"A Season of Change: How does change impact people and nature?\", \"The American West: What was life like in the West for early Americans?\",\n \"Civil Rights Heroes: How can people respond to injustice?\", \"Good Eating: How does food nourish us?\",\n \"Plant and Animal Relationships\", \"Properties of Matter\", \"Changing Landforms\", \"Exploring Who We Are\",\n \"Why Is It Important to Learn About the Past?\", \"How Does Geography Help Us Understand Our World?\",\n \"How Do We Get What We Want and Need?\", \"Why Do We Need Government?\", \"How Can People Make a Difference in Our World?\"\n ],\n \"3\": [\n \"Overcoming Learning Challenges Near and Far\", \"Adaptations and the Wide World of Frogs\", \"Exploring Literary Classics\",\n \"Water Around the World\", \"Ocean/Sea Exploration\", \"Outer Space\", \"Immigration\", \"Art/Being an Artist\",\n \"Balancing Forces\", \"Inheritance and Traits\", \"Environments and Survival\", \"Weather and Climate\",\n \"Communities\", \"Why Does It Matter Where We Live?\", \"What Is Our Relationship With Our Environment?\",\n \"What Makes a Community Unique?\", \"How Does the Past Impact the Present?\", \"Why Do Governments and Citizens Need Each Other?\",\n \"How Do People in a Community Meet Their Wants and Needs?\"\n ],\n 4: [\n \"Poetry\", \"Animal Defense Mechanisms\", \"The American Revolution\",\n \"Responding to Inequality: Ratifying the 19th Amendment (covers gender and racial inequality)\",\n \"A Great Heart: What does it mean to have a great heart, literally and figuratively?\",\n \"Extreme Settings: How does a challenging setting or physical environment change a person?\",\n \"American Revolution/Multiple Perspectives\", \"Myths/Myth Making\", \"Energy Conversions\", \"Vision and Light\",\n \"Earth's Features\", \"Waves, Energy, and Information\", \"Regions of the United States\",\n \"How Does America Use Its Strengths and Face Its Challenges?\", \"Why Have People Moved to and From the Northeast?\",\n \"How Has the Southeast Changed Over Time?\", \"How Does the Midwest Reflect the Spirit of America?\",\n \"How Does the Southwest Reflect Its Diverse Past and Unique Environment?\", \"What Draws People to the West?\"\n ],\n 5: [\n \"Human Rights\", \"Biodiversity in the Rainforest\", \"Athlete Leaders of Social Change\",\n \"Impact of Natural Disasters\", \"Cultures in Conflict: How do cultural beliefs and values guide people?\",\n \"Word Play: How and why do writers play with words?\", \"A War Between Us: How did the Civil War impact people?\",\n \"Breaking Barriers: How can sports influence individuals and societies?\", \"Patterns of Earth and Sky\",\n \"Modeling Matter\", \"The Earth System\", \"Ecosystem Restoration\", \"U.S. History: Making a New Nation\",\n \"How Were the Lives of Native Peoples Influenced by Where They Lived?\",\n \"What Happened When Diverse Cultures Crossed Paths?\", \"What Is the Impact of People Settling in a New Place?\",\n \"Why Would a Nation Want to Become Independent?\", \"What Does the Revolutionary Era Tell Us About Our Nation Today?\",\n \"How Does the Constitution Help Us Understand What It Means to Be an American?\",\n \"What Do the Early Years of the United States Reveal About the Character of the Nation?\",\n \"What Was the Effect of the Civil War on U.S. Society?\"\n ],\n 6: [\n \"Greek Mythology\", \"Critical Problems and Design Solutions\", \"American Indian Boarding Schools\",\n \"Remarkable Accomplishments in Space Science\", \"Resilience in the Great Depression: How can enduring tremendous hardship contribute to personal transformation?\",\n \"A Hero's Journey: What is the significance and power of the hero's journey?\",\n \"Narrating the Unknown: How did the social and environmental factors in the unknown world of Jamestown shape its development and decline?\",\n \"Courage in Crisis: How can the challenges of a hostile environment inspire heroism?\",\n \"Microbiome\", \"Metabolism\", \"Metabolism Engineering\", \"Traits and Reproduction\", \"Thermal Energy\",\n \"Ocean, Atmosphere, and Climate\", \"Weather Patterns\", \"Earth's Changing Climate\",\n \"Earth's Changing Climate: Engineering Internship\", \"The First Americans (up to 1492)\",\n \"Exploration and Colonization\", \"English Colonies\", \"American Revolution\", \"First Governments and the Constitution\",\n \"The Early American Republic\", \"Political and Geographic Changes (1828-1850)\", \"Life in the North and South (1820-1860)\",\n \"Division and Civil War (1821-1865)\", \"Reconstruction (1865-1896)\", \"The West (1858-1896)\",\n \"New Industry and a Changing Society\", \"Expansion and War\", \"The 1920s and 1930s\", \"World War II\",\n \"The Cold War\", \"Civil Rights and American Society\", \"America Since the 1970s\"\n ],\n 7: [\n \"The Lost Children of Sudan (Genocide, Genocide in Sudan)\", \"Epidemics\", \"Harlem Renaissance\", \"Plastic Pollution\",\n \"Identity in the Middle Ages: How does society both support and limit the development of identity?\",\n \"Americans All: How did World War II affect individuals?\", \"Language and Power: What is the power of language?\",\n \"Fever: How can times of crisis affect citizens and society?\", \"Geology on Mars\", \"Plane Motion\", \"Plane Motion Engineering\",\n \"Rock Formations\", \"Phase Change\", \"Phase Change Engineering\", \"Chemical Reactions\", \"Populations and Resources\",\n \"Matter and Energy in Ecosystems\", \"Early Humans and Agricultural Revolution\", \"Fertile Crescent\",\n \"Ancient Egypt and Kush\", \"The Israelites\", \"Ancient Greece\", \"Ancient South Asia\", \"Early China, Korea, and Japan\",\n \"Ancient Rome\", \"Rise of Christian Kingdoms\", \"The Americas\", \"Medieval Europe\", \"The Rise of Islamic Empires\",\n \"China in the Middle Ages\", \"Korea and Japan in the Middle Ages\", \"African Civilizations\", \"New Ways of Thinking\",\n \"Age of Exploration and Trade\", \"Revolutions and Empires\", \"The Modern World\"\n ],\n 8: [\n \"Folklore of Latin America\", \"Food Choices\", \"The Holocaust\", \"Japanese American Internment\",\n \"The Poetics and Power of Storytelling: What is the power of storytelling?\",\n \"The Great War: How do literature and art illuminate the effects of World War I?\", \"What Is Love?\",\n \"Teens as Change Agents: How do people effect social change?\", \"Harnessing Human Energy\",\n \"Force and Motion\", \"Force and Motion Engineering\", \"Magnetic Fields\", \"Light Waves\", \"Earth, Moon, and Sun\",\n \"Natural Selection\", \"Natural Selection Engineering\", \"Evolutionary History\", \"The World in Spatial Terms\",\n \"Places and Regions\", \"Physical Geography\", \"Population Geography\", \"Economic Geography\",\n \"Political Geography\", \"Human-Environment Geography\", \"What is Economics?\", \"Markets, Money, and Businesses\",\n \"Government and the Economy\", \"The Global Economy\"\n ]\n]\n[END TOPICS]\n\nHere is the text:\n[BEGIN TEXT]\n{text}\n[END TEXT]\n","import BACKGROUND_KNOWLEDGE_TEMPLATE from '../../../../../evals/prompts/vocabulary/background-knowledge.txt';\n\n/**\n * Generate the background knowledge prompt for a given text and grade level\n */\nexport function getBackgroundKnowledgePrompt(text: string, grade: string): string {\n return BACKGROUND_KNOWLEDGE_TEMPLATE\n .replaceAll('{grade}', grade)\n .replaceAll('{text}', text);\n}\n","\nYou are an expert curriculum designer. Your job is to rate the complexity of a text's vocabulary relative to the grade level.\n\nYou will be given a rubric (with levels from least to most complex: slightly complex, moderately complex, very complex, exceedingly complex) as well as guidelines for interpreting the rubric.\nIMPORTANT: You should only pay attention to the vocabulary. Do not evaluate any other element of the text's complexity (e.g. sentence structure, meaning, etc.)\n\n**Resource 1: Qualitative Text Complexity rubric (SAP)**\n1. **Level 1: Slightly complex**\n * Original Definition: Vocabulary that is almost entirely not complex: contemporary, conversational, and/or familiar. A very low proportion of complex words (archaic, subject-specific, academic) is OK -- i.e. doesn't need to be 0.\n * Summary definition: Overall, vocabulary is easy to understand and does not impede comprehension of the bulk of the text (including main idea and supporting claims). 1-2 quick pauses for processing by the student are ok here!\n2. **Level 2: Moderately complex**\n * Original Definition: Vocabulary that is mostly not complex: contemporary, conversational, and/or familiar. A low proportion of complex words (archaic, subject-specific, academic) is OK\n * Summary definition: Overall, vocabulary generally allows students to comprehend the bulk of the text with little difficulty, though there may be occasional pauses for clarification. Several quick pauses or occasional prolonged pauses may occur.\n3. **Level 3: Very complex**\n * Original Definition: Vocabulary that is often complex: unfamiliar, archaic, subject-specific, and/or overly academic\n * Summary definition: Overall, vocabulary often presents challenges that may slow down comprehension but does not completely block the comprehension of the bulk of the text.\n4. **Level 4: Exceedingly complex**\n * Original Definition: Vocabulary that is mostly complex: unfamiliar, archaic, subject-specific, and/or overly academic. May be ambiguous or purposefully misleading.\n * Summary definition: Overall, vocabulary is so complex that it makes comprehension of the bulk of the text very challenging and requires careful effort to interpret.\n\n**Resource 2: Flesch-Kincaid Grade Level**\nUse the Flesch-Kincaid (FK) Grade Level as light guidance of the approximate grade level based on readability. The metric alone does not provide final information of vocabulary complexity, but a ballpark of the difficulty of the entire text.\n* grade 2-3: 1.98-5.34\n* grade 4-5: 4.51-7.73\n* grade 6-8: 6.51-10.34\n* grade 9-10: 8.32-12.12\n* grade 11-College: 10.34-14.2\n\n**Guidelines for Interpretation and Reasoning**\n\nYour reasoning is the most critical part of your analysis. It's not enough to simply count complex words. You must analyze their impact on a student at the specified grade level. Use the following principles to guide your judgment:\n\n1. **Density and Cumulative Effect:** Do not just count complex words; evaluate their concentration. A short text with a high density of challenging Tier 2 words (e.g., `peculiar`, `mischievous`, `courageous` for a 4th grader) can be more overwhelming than a longer text with a few scattered Tier 3 words. A constant barrage of unfamiliar words can elevate complexity from `very` to `exceedingly`.\n2. **Contextual Scaffolding:** Assess how the text supports new vocabulary.\n * Are new, complex terms explicitly defined or explained with simple examples (e.g., \"volume... to see if it is big enough to hold a liter of food\")?\n * Is the surrounding language simple and conversational, making the meaning of new words easier to infer?\n * Strong scaffolding can lower the complexity rating. A text with many Tier 3 words that are well-explained might only be `moderately complex`.\n3. **Abstract vs. Concrete Vocabulary:** Differentiate between words for abstract concepts and words for concrete things. A text built on abstract Tier 2 words (e.g., `relationships`, `performance`, `non-physical`) can be more challenging than a text that introduces Tier 3 labels for concrete things or people (e.g., `Sumerians`, `polonium`).\n4. **Conceptual Load:** Consider the cognitive load of the vocabulary. A list of many new, multi-syllabic, conceptually-heavy terms (e.g., `Paleolithic`, `Mesolithic`, `Neolithic` for a 3rd grader) can be `very complex` even if the terms are briefly defined, because the student must process multiple new concepts at once.\n5. **Calibrating the Top Levels:** Be precise in your use of `very complex` vs. `exceedingly complex`.\n * **Very complex:** The vocabulary creates significant hurdles and slows the reader down, but the main ideas of the text are still accessible with effort.\n * **Exceedingly complex:** The vocabulary is so dense, technical, or abstract that it acts as a barrier, making it nearly impossible for the target student to grasp the bulk of the text's meaning without extensive outside help. Reserve this for texts saturated with advanced terminology.\n6. **Consider Background Knowledge:** Pay close attention to the provided `student_background_knowledge`. Do not classify a word as complex if the student is likely to be familiar with it (e.g., 'oxygen' for a 3rd grader who has learned about the human body).\n\n**Final Analysis Format**\n\nProvide these information as your final analysis:\n1. **Complex vocabulary:**\n * Tier 2 words: Words that are commonly used in academic settings and more complex than colloquial, or everyday language and often have multiple meanings.\n * Tier 3 words: Overly academic or domain-specific words.\n * Archaic words: Words, or uses of words that are not commonly used in modern conversational language. E.g., \"The jury retired to deliberate on their verdict.\" The use of \"retire\" to mean withdrawing to a private place is an archaic use.\n * Other complex words: All other words that can increase complexity of the text (e.g., idioms, unfamiliar proper nouns that function as vocabulary).\n2. **Vocabulary complexity:** one of: slightly complex, moderately complex, very complex, exceedingly complex\n3. **Your reasoning of the complexity:** A detailed explanation of your rating, referencing the principles above.\n","\nYou are an expert curriculum designer. Your job involves reading text snippets intended for students in K-12 and evaluating the complexity of the vocabulary in each text.\n\nYou will be given a rubric (with options 1, 2, 3, 4) as well as guidelines for interpreting the rubric.\n\nIMPORTANT: You should only pay attention to the vocabulary. Do not evaluate any other element of the text's complexity (e.g. sentence structure, meainng, etc.)\nIMPORTANT: Rely on the supplied rubric and annotation guidelines along. Do not introduce any new crtieria for evaluating the complexity of a text's vocabulary.\n\nPlease first reason out loud about the vocabulary complexity of the text and then provide an answer between 1 and 4 (whole numbers only). Provide the answer as an integer (not a float).\n","import SYSTEM_PROMPT_GRADES_3_4 from '../../../../../evals/prompts/vocabulary/grades-3-4-system.txt';\nimport SYSTEM_PROMPT_OTHER_GRADES from '../../../../../evals/prompts/vocabulary/other-grades-system.txt';\n\n/**\n * Get the appropriate system prompt based on grade level\n * @param grade - The target grade level (3-12)\n * @returns The system prompt for the grade level\n */\nexport function getSystemPrompt(grade: string): string {\n // Grades 3-4 use the GRADES_3_4 prompt\n if (grade === '3' || grade === '4') {\n return SYSTEM_PROMPT_GRADES_3_4;\n }\n\n // All other grades (5-12) use OTHER_GRADES prompt\n return SYSTEM_PROMPT_OTHER_GRADES;\n}\n","\nBelow is the text you need to evaluate. Let's think step by step in order to predict the output of the vocabulary complexity task.\n\n- It is intended for grade {student_grade_level}.\n\n- You can assume the student has the following background knowledge about the text — this background knowledge influences which words from the text are familiar versus unfamiliar for the student: {student_background_knowledge}\n\n- Text Flesch-Kincaid grade level: {fk_level}\n\n- Text to evaluate: [BEGIN TEXT]\n{text}\n[END TEXT]\n","\nYour job is to rate the complexity of a text's vocabulary (relative to the intended level of the text) according to a rubric and annotation guide. Stick to the rubric and annotation guide exactly — do not introduce any additional criteria or lenses for judging the complexity of the text.\n\n[BEGIN ANNOTATION GUIDE AND RUBRIC]\nInstructions\nFor the following task, please assume that:\n - The student is on grade level and proficient in all core content areas, including reading fluency, comprehension, science, & social studies. (example).\n - The student is moving through a common progression of topics (detailed here).\n - The student is fluent in speaking English.\n - The student has an \"average\" amount of background knowledge on topics not commonly covered in curriculum.\n - The student will use this material for independent reading/work, without direct instruction.\n - The text is reasonable for the given grade level.\n\nPlease do not consider the presence of figurative language when scoring Vocabulary. For example: with a phrase like \"kicked the bucket,\" consider only the qualities of the words themselves (\"kicked\", \"the\" and \"bucket\").\n\nPlease do be sure to consider:\n- all of the different types of vocabulary (listed below)\n- the overall proportion of complex words in the text - including repeated complex words.\n- the resulting holistic complexity of the vocabulary (described in the Summary section below).\n\nLevel 1:\nRubric: Vocabulary that is almost entirely not complex: contemporary, conversational, and/or familiar. That said, a very low proportion of complex words (archaic, subject-specific, academic) is OK -- i.e. doesn't need to be 0.\n\nLevel 2:\nRubric: Vocabulary that is mostly not complex: contemporary, conversational, and/or familiar. A low proportion of complex words (archaic, subject-specific, academic) is OK, but if it's very low, the text is probably level 1.\n\nLevel 3:\nRubric: Vocabulary that is often complex: unfamiliar, archaic, subject-specific, and/or overly academic\n\nLevel 4:\nRubric: Vocabulary that is mostly complex: unfamiliar, archaic, subject-specific, and/or overly academic. May be ambiguous or purposefully misleading\n\nAnd here are some relevant definitions:\n - Conversational: Everyday language.\n - Familiar: Words that the student is likely to have seen/heard, from everyday life or their curriculum. Reminder: assume an \"average\" level of background knowledge.\n - Unfamiliar: Words the student has probably not heard, or are being used in an unfamiliar way.\n - For ex: 4th graders are familiar with the word \"table\" but may not be familiar with the use of the word with respect to data (\"a table of data\").\n - Note:\n - Words with in-line definitions (via appositives, or because they can be easily inferred from other parts of the text) should be evaluated as less unfamiliar.\n - For ex: \"The pharaoh, a powerful ruler of ancient Egypt, was buried in a grand tomb.\"\n - The word \"pharaoh\" might be unfamiliar or subject-specific, but since is defined within the text, you can consider it a more familiar word.\n - Unfamiliar proper nouns:\n - A person's name, even if unfamiliar, generally does not add to complexity.\n - Other unfamiliar proper nouns (eg locations, organizations) do add to complexity.\n\n- Subject-specific: Words that are specific to a subject or field of study that are essential for understanding concepts and engaging with the content.\n- Overly-academic: Words that are excessively formal, complex, or specialized.\n - For ex: \"The agrarian societal structure of the Neolithic Revolution precipitated a paradigm shift in agriculture\"\n- Archaic: A word that was common in the past but is now rarely/almost never used. Could also be a word used in an archaic way.\n - For ex: \"After a long day of court proceedings, the jury 'retired' to deliberate on their verdict.\"\n - The word \"retire\" meaning to stop working may be familiar to a student, but \"retire\" meaning \"withdrawing to a private place\" is an archaic use.\n\n\nExamples\nThe student is on-grade-level:\n- Consider a 6th grade passage about earth systems. Per NGSS standards, students are introduced to earth systems starting in 2nd grade. They encounter words like: wind, water, river, lake, solids, and liquids. For our rating purposes, we would assume most students following 2nd have encountered these words. In 5th grade, they dive more fully into earth systems concepts, learning vocabulary words like geosphere, sediment, biosphere, atmosphere, ecosystems, organisms and climate. While rating, we would consider the words listed in the NGSS standards as more familiar following that grade level. If the same passage were intended for 3rd graders, though, then the subject-specific vocabulary is likely to be unfamiliar.\n\nFigurative Language\n- Kicked the bucket.\n- The pen is mightier than the sword.\n- The classroom was a zoo.\n- He ran faster than the speed of light.\n[END ANNOTATION GUIDE AND RUBRIC]\n\nHere are a couple examples of texts that have already been scored along with justification for their scores, which you can use as exemplars:\n[BEGIN EXAMPLES]\n\n*** EXAMPLE 1 ***\nThe following text was intended for grade level 11 and received a complexity level of 1.\n\nHere is the background knowledge assumption for that text: N/A\n\nHere is the text:\n// START TEXT //\n\"In a recent lecture, \"Is Nothing Sacred?\", Salman Rushdie, one of the most censored authors of our time, talked about the importance of books. He grew up in a household in India where books were as sacred as bread. If anyone in the household dropped a piece of bread or a book, the person not only picked it up, but also kissed the object by way of apologizing for clumsy disrespect.\n\nHe goes on to say that he had kissed many books before he had kissed a girl. Bread and books were for his household, and for many like his, food for the body and the soul. This image of the kissing of the book one had accidentally dropped made an impression on me. It speaks to the love and respect many people have for them.\n\nI grew up in a small town in New Mexico, and we had very few books in our household. The first one I remember reading was my catechism book. Before I went to school to learn English, my mother taught me catechism in Spanish.\n\nI remember the questions and answers I had to learn, and I remember the well-thumbed, frayed volume which was sacred to me.\n\nGrowing up with few books in the house created in me a desire and a need for them. When I started school, I remember visiting the one room library of our town and standing in front of the dusty shelves. In reality there were only a few shelves and not over a thousand books, but I wanted to read them all. There was food for my soul in the books, that much I realized.\"\n// END TEXT //\n\nHere is the reasoning for that complexity level:\n// START REASONING //\nThis text is a 1 for vocabulary, because the vocabulary that is used is familiar and accessible for a proficient 11th grader. Most of the words used in the text are very common everyday vocabulary for describing growing up, family life, and the importance of reading. A few examples of these very common words are: small town, book, school, learn, food, kissed, image, respect, love, speaks. There are many more in the text. In this text there are only a few \"juicier\" or more complex words, you can think of those as words that are less familiar, have a more abstract or nuanced meaning, or carry a very large concept. Less commonly spoken words that were used in the text were: frayed, volume, censored, clumsy, sacred. These are still well within reach of a proficient 11th grader, and would still be considered familiar, because they will have encountered them in past reading or academic studies. In the text there are a couple of words that are outliers, but they are not essential to the understanding of the larger text. One of these words or hyphenated compound phrase is well-frayed. A compound phrase is a phrase consisting of multiple words that work together to create a specific meaning or idea, often acting as a single unit in a sentence. If the meaning of individual words is familiar, it is typically quite easy for proficient readers to generalize the larger meaning that the author is implying with their word choice. In this case, proficient students will be accustomed to the phrase well, with the secondary meaning of very, rather than a description of positivity or health; and they will be accustomed to the use frayed, as in worn, aged, or damaged from use. Making the leap to identify the meaning of \"well-frayed\" as a book that is very used, will take only moments for a proficient 11th grader. Another word that stands out in the text is the word catechism, which might be new for many students based on their personal background or location, but a full understanding of what a catechism book contains is not essential for understanding the paragraph or whole text. The reader can make it through using minimum context clues to know that the catechism must be something important to his family. The type of book he learned to read before going to school is not critical for comprehension, it's enough to understand that reading was so important in his family, his mother started instruction before he even started school. Additionally, it's important to know that having one unknown word for an 11th grade reading, does not merit a rating higher than one.\n\nIt is worth noting that another reason this text is a 1, is that the content or topic of the passage is so familiar and covered extensively in K-12 education, i.e. reading is important, loving books, growing up; that coupled with the simple vocabulary choices, getting to the meaning of the overall text, and even the paragraphs, would be incredibly easy for a proficient 11th grader.\n// END REASONING //\n*** EXAMPLE 2 ***\nThe following text was intended for grade level 5 and received a complexity level of 2.\n\nHere is the background knowledge assumption for that text: Background Knowledge Assumption: Students are likely familiar with the concept of natural disasters, including hurricanes, and basic atmospheric concepts like high and low pressure from their studies on weather and climate. They may not be familiar with the specific formation processes of hurricanes or the global terminology differences (hurricane, typhoon, cyclone).\n\nHere is the text:\n// START TEXT //\nGreat whirling storms roar out of the oceans in many parts of the world. They are called by several names—hurricane, typhoon, and cyclone are the three most familiar ones. But no matter what they are called, they are all the same sort of storm. They are born in the same way, in tropical waters. They develop the same way, feeding on warm, moist air. And they do the same kind of damage, both ashore and at sea. Other storms may cover a bigger area or have higher winds, but none can match both the size and the fury of hurricanes. They are earth's mightiest storms.\n\nLike all storms, they take place in the atmosphere, the envelope of air that surrounds the earth and presses on its surface. The pressure at any one place is always changing. There are days when air is sinking and the atmosphere presses harder on the surface. These are the times of high pressure. There are days when a lot of air is rising and the atmosphere does not press down as hard. These are times of low pressure. Low-pressure areas over warm oceans give birth to hurricanes.\n// END TEXT //\n\nHere is the reasoning for that complexity level:\n// START REASONING //\nI scored this a 2 because of the density of subject-specific vocabulary related to weather and climate, which is often covered in lower grade levels. This adds to the complexity above a 1, but it is not a level 3 because of the familiarity with the topic, which implies some familiarity with the vocabulary as well. The specific formation process and the vocabulary used to explain the processes are also subject-specfiic but not famliar, which would make the second paragraph a level 3 in the rubric language, but when considering the language used in the overall SUMMARY below the rubric, this new content and vocabulary would cause quick pauses and/or occasional prolonged pauses but would not cause the reader to slow down to due to challenging overall comprehension of the key ideas and supporting claims. This is especially the case because the second paragraph builds upon prior knowledge and familiar vocabulary use, so it is not entirely new information and vocabulary. While there is subject-specific vocabulary used, overly academic vocabulary is NOT used and is more conversational in nature, such as \"great whiring storms\" and \"born\" / \"giving birth\" to storm (although this is the way storms are described!) rather than more technical terms which made comprehension easier due to the accessibility of the vocabulary (even if used in other contexts before reading this text). Words such as \"a lot\" and \"bigger\" are more conversational, and while technical, unfamiliar words are provided, such as \"hurricane,\" \"typhoon,\" and \"cyclone,\" knowing and understanding their differences is not necessary to grasp the main idea. The processes by which they are formed are what need to be retained while reading the entire text, and familiarity with the bulk of the vocabulary used would allow for that to happen without too much struggle to make meaning of it. Additionally, the text does not contain any archaic vocabulary or ambiguous words, which prevents it from reaching a rating of 4, although it is not necessary that they text have such vocabulary to meet a level 4, the frequent inclusion of such vocabulary makes it more likely to land at least a 3 or 4.\n// END REASONING //\n\n*** EXAMPLE 3 ***\nThe following text was intended for grade level 6 and received a complexity level of 3.\n\nHere is the background knowledge assumption for that text: Background Knowledge Assumption: Students are likely familiar with basic Earth science concepts such as rocks, minerals, and fossils, as well as natural processes like volcanic eruptions and earthquakes. They may not be familiar with more advanced topics like plate tectonics or the specific branches of geology such as mineralogy, petrology, and seismology.\n\nHere is the text:\n// START TEXT //\nGeology is the scientific study of Earth. Geologists study the planet—its formation, its internal structure, its materials, its chemical and physical processes, and its history. Mountains, valleys, plains, sea floors, minerals, rocks, fossils, and the processes that create and destroy each of these are all the domain of the geologist. Geology is divided into two broad categories of study: physical geology and historical geology.\n\nPhysical geology is concerned with the processes occurring on or below the surface of Earth and the materials on which they operate. These processes include volcanic eruptions, landslides, earthquakes, and floods. Materials include rocks, air, seawater, soils, and sediment. Physical geology further divides into more specific branches, each of which deals with its own part of Earth's materials, landforms, and processes. Mineralogy and petrology investigate the composition and origin of minerals and rocks. Volcanologists study lava, rocks, and gases on live, dormant, and extinct volcanoes. Seismologists use instruments to monitor and predict earthquakes and volcanic eruptions.\n\nHistorical geology is concerned with the chronology of events, both physical and biological, that have taken place in Earth's history. Paleontologists study fossils (remains of ancient life) for evidence of the evolution of life on Earth. Fossils not only relate evolution, but also speak of the environment in which the organism lived. Corals in rocks at the top of the Grand Canyon in Arizona, for example, show a shallow sea flooded the area around 290 million years ago. In addition, by determining the ages and types of rocks around the world, geologists piece together continental and oceanic history over the past few billion years. Plate tectonics (the study of the movement of the sections of Earth's crust) adds to Earth's story with details of the changing configuration of the continents and oceans.\n// END TEXT //\n\nHere is the reasoning for that complexity level:\n// START REASONING //\nTo determine the complexity rating of this text based on the vocabulary present, I used the annotation guide, scoring rubric, and examples to set the expectations for rating. During the first read of the text, I \"bolded\" and categorized the more challenging vocabulary words according to the following complexity groupings: archaic, unfamiliar, archaic, subject-specific, and/or overly academic. On the second read, I considered the main idea or \"gist\" that students need to acquire understanding of. I then referenced the previously mentioned tools–annotation guide, scoring rubric, and examples to remind myself of the expectations for rating. I agreed that readers would have familiarity with basic concepts of geology; however, I also considered the definitions provided for words such as Geology, Geologists, Physical Geology, Historical Geology, Mineralogy, and Petrology. I considered how students might pause for clarification and for how long. After reviewing the Annotation Guide while considering, I narrowed the rating down because the definitions provided throughout the text of more complex words should make the meaning of the text more accessible for readers, which is why although the words are subject-specific, I rated this text as a 3 instead of a 2-less complex or a 4–more complex. I read the text one final time to ensure clarity around my rating, scored and wrote the justification.\n// END REASONING //\n[END EXAMPLES]\n\nBelow is the text you need to evaluate. It is intended for grade {student_grade_level}.\n\nAs you read the text, you can assume the student has the following background knowledge about the text — this background knowledge influences which words from the text are familiar versus unfamiliar for the student: {student_background_knowledge}\n\n[BEGIN TEXT]\n{text}\n[END TEXT]\n\nIn your response, when specifying the level of complexity, be sure to use only a single integer (e.g. 2) and don't include any other text (e.g. don't say \"level 2\").\n","import USER_PROMPT_TEMPLATE_GRADES_3_4 from '../../../../../evals/prompts/vocabulary/grades-3-4-user.txt';\nimport USER_PROMPT_TEMPLATE_OTHER_GRADES from '../../../../../evals/prompts/vocabulary/other-grades-user.txt';\n\n/**\n * Generate the user prompt for vocabulary complexity evaluation\n * @param text - The text to evaluate\n * @param studentGradeLevel - The student's grade level\n * @param studentBackgroundKnowledge - Background knowledge assumption\n * @param fkLevel - Flesch-Kincaid grade level\n * @returns The formatted user prompt\n */\nexport function getUserPrompt(\n text: string,\n studentGradeLevel: string,\n studentBackgroundKnowledge: string,\n fkLevel: number\n): string {\n // Select the appropriate template based on grade\n const template = studentGradeLevel === '3' || studentGradeLevel === '4'\n ? USER_PROMPT_TEMPLATE_GRADES_3_4\n : USER_PROMPT_TEMPLATE_OTHER_GRADES;\n\n return template\n .replaceAll('{student_grade_level}', studentGradeLevel)\n .replaceAll('{student_background_knowledge}', studentBackgroundKnowledge)\n .replaceAll('{fk_level}', fkLevel.toString())\n .replaceAll('{text}', text);\n}\n","import type { LLMProvider } from '../providers/index.js';\nimport {\n VocabularyComplexitySchema,\n type VocabularyInternal,\n type BackgroundKnowledge,\n} from '../schemas/vocabulary.js';\nimport { calculateFleschKincaidGrade } from '../features/index.js';\nimport {\n getBackgroundKnowledgePrompt,\n getSystemPrompt,\n getUserPrompt,\n} from '../prompts/vocabulary/index.js';\nimport type { EvaluationResult, TextComplexityLevel } from '../schemas/index.js';\nimport { BaseEvaluator, Provider, type BaseEvaluatorConfig } from './base.js';\nimport type { StageDetail } from '../telemetry/index.js';\nimport { ValidationError, wrapProviderError } from '../errors.js';\n\n/**\n * Vocabulary Evaluator\n *\n * Evaluates vocabulary complexity of educational texts relative to grade level.\n * Uses a 2-stage process:\n * 1. Generate background knowledge assumption for the student's grade level\n * 2. Evaluate vocabulary complexity using that background knowledge\n *\n * Based on Qual Text Complexity rubric (SAP) with 4 levels:\n * - Slightly complex\n * - Moderately complex\n * - Very complex\n * - Exceedingly complex\n *\n * @example\n * ```typescript\n * const evaluator = new VocabularyEvaluator({\n * googleApiKey: process.env.GOOGLE_API_KEY,\n * openaiApiKey: process.env.OPENAI_API_KEY\n * });\n *\n * const result = await evaluator.evaluate(text, \"3\");\n * console.log(result.score); // \"Moderately complex\"\n * console.log(result.reasoning);\n * ```\n */\nexport class VocabularyEvaluator extends BaseEvaluator {\n static readonly metadata = {\n id: 'vocabulary',\n name: 'Vocabulary',\n description: 'Evaluates vocabulary complexity of educational texts relative to grade level',\n supportedGrades: ['3', '4', '5', '6', '7', '8', '9', '10', '11', '12'] as const,\n defaultProviders: [Provider.Google, Provider.OpenAI] as const,\n };\n\n private grades34ComplexityProvider: LLMProvider;\n private otherGradesComplexityProvider: LLMProvider;\n private backgroundKnowledgeProvider: LLMProvider;\n\n constructor(config: BaseEvaluatorConfig) {\n // Call base constructor for common setup (telemetry, API key validation, etc.)\n super(config);\n\n // Create Google Gemini provider for complexity evaluation (grades 3-4)\n this.grades34ComplexityProvider = this.createConfiguredProvider(\n Provider.Google, 'gemini-2.5-pro', config.googleApiKey\n );\n\n // Create OpenAI GPT-4.1 provider for complexity evaluation (grades 5-12)\n this.otherGradesComplexityProvider = this.createConfiguredProvider(\n Provider.OpenAI, 'gpt-4.1-2025-04-14', config.openaiApiKey\n );\n\n // Create OpenAI GPT-4o provider for background knowledge generation\n this.backgroundKnowledgeProvider = this.createConfiguredProvider(\n Provider.OpenAI, 'gpt-4o-2024-11-20', config.openaiApiKey\n );\n }\n\n /**\n * Evaluate vocabulary complexity for a given text and grade level\n *\n * @param text - The text to evaluate\n * @param grade - The target grade level (3-12)\n * @returns Evaluation result with complexity score and detailed analysis\n * @throws {ValidationError} If text is empty, too short/long, or grade is invalid\n * @throws {ConfigurationError} If modelOverride specifies a model ID that the provider rejects\n * @throws {APIError} If LLM API calls fail (includes AuthenticationError, RateLimitError, NetworkError, TimeoutError)\n */\n async evaluate(\n text: string,\n grade: string\n ): Promise<EvaluationResult<TextComplexityLevel, VocabularyInternal>> {\n this.logger.info('Starting vocabulary evaluation', {\n evaluator: 'vocabulary',\n operation: 'evaluate',\n grade,\n textLength: text.length,\n });\n\n const startTime = Date.now();\n const stageDetails: StageDetail[] = [];\n const complexityProviderLabel = (grade === '3' || grade === '4')\n ? this.grades34ComplexityProvider.label\n : this.otherGradesComplexityProvider.label;\n const backgroundProviderLabel = this.backgroundKnowledgeProvider.label;\n // When override is active all providers resolve to the same model — show a single label.\n const modelLabel = this.config.modelOverride\n ? backgroundProviderLabel\n : `${backgroundProviderLabel}+${complexityProviderLabel}`;\n\n try {\n // Validate inputs — inside try so validation errors are telemetered.\n // If partners consistently pass invalid grades/text, telemetry will surface documentation gaps.\n this.validateText(text);\n this.validateGrade(grade, new Set(VocabularyEvaluator.metadata.supportedGrades));\n this.logger.debug('Stage 1: Generating background knowledge', {\n evaluator: 'vocabulary',\n operation: 'background_knowledge',\n });\n // Stage 1: Generate background knowledge assumption\n const bgResponse = await this.getBackgroundKnowledgeAssumption(text, grade);\n\n stageDetails.push({\n stage: 'background_knowledge',\n provider: backgroundProviderLabel,\n latency_ms: bgResponse.latencyMs,\n token_usage: {\n input_tokens: bgResponse.usage.inputTokens,\n output_tokens: bgResponse.usage.outputTokens,\n },\n });\n\n // Calculate Flesch-Kincaid grade level\n const fkLevel = calculateFleschKincaidGrade(text);\n\n // Stage 2: Evaluate vocabulary complexity\n const complexityResponse = await this.evaluateComplexity(\n text,\n grade,\n bgResponse.knowledge.assumption,\n fkLevel\n );\n\n stageDetails.push({\n stage: 'complexity_evaluation',\n provider: complexityProviderLabel,\n latency_ms: complexityResponse.latencyMs,\n token_usage: {\n input_tokens: complexityResponse.usage.inputTokens,\n output_tokens: complexityResponse.usage.outputTokens,\n },\n });\n\n const latencyMs = Date.now() - startTime;\n\n // Aggregate token usage\n const totalTokenUsage = {\n input_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.input_tokens || 0), 0),\n output_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.output_tokens || 0), 0),\n };\n\n const result = {\n score: complexityResponse.data.complexity_score,\n reasoning: complexityResponse.data.reasoning,\n metadata: {\n model: modelLabel,\n processingTimeMs: latencyMs,\n },\n _internal: complexityResponse.data,\n };\n\n // Send success telemetry (fire-and-forget)\n this.sendTelemetry({\n status: 'success',\n latencyMs,\n textLength: text.length,\n grade,\n provider: modelLabel,\n tokenUsage: totalTokenUsage,\n metadata: {\n stage_details: stageDetails,\n },\n inputText: text,\n }).catch(() => {\n // Ignore telemetry errors\n });\n\n this.logger.info('Vocabulary evaluation completed successfully', {\n evaluator: 'vocabulary',\n operation: 'evaluate',\n grade,\n score: result.score,\n processingTimeMs: latencyMs,\n });\n\n return result;\n } catch (error) {\n const latencyMs = Date.now() - startTime;\n\n // Log the error\n this.logger.error('Vocabulary evaluation failed', {\n evaluator: 'vocabulary',\n operation: 'evaluate',\n grade,\n error: error instanceof Error ? error : undefined,\n processingTimeMs: latencyMs,\n completedStages: stageDetails.length,\n });\n\n // Aggregate metrics from completed stages\n const totalTokenUsage = stageDetails.length > 0 ? {\n input_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.input_tokens || 0), 0),\n output_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.output_tokens || 0), 0),\n } : undefined;\n\n // Send failure telemetry (fire-and-forget)\n this.sendTelemetry({\n status: 'error',\n latencyMs,\n textLength: text.length,\n grade,\n provider: modelLabel,\n tokenUsage: totalTokenUsage,\n errorCode: error instanceof Error ? error.name : 'UnknownError',\n metadata: stageDetails.length > 0 ? { stage_details: stageDetails } : undefined,\n inputText: text,\n }).catch(() => {\n // Ignore telemetry errors\n });\n\n // Re-throw validation errors as-is\n if (error instanceof ValidationError) {\n throw error;\n }\n\n // Wrap provider errors into appropriate error types\n throw wrapProviderError(error, 'Vocabulary evaluation failed');\n }\n }\n\n /**\n * Stage 1: Generate background knowledge assumption\n *\n * Estimates what topics the student at the given grade level would be familiar with\n * based on Common Core curriculum progression.\n */\n private async getBackgroundKnowledgeAssumption(\n text: string,\n grade: string\n ): Promise<{ knowledge: BackgroundKnowledge; usage: { inputTokens: number; outputTokens: number }; latencyMs: number }> {\n const prompt = getBackgroundKnowledgePrompt(text, grade);\n\n const response = await this.backgroundKnowledgeProvider.generateText(\n [{ role: 'user', content: prompt }],\n 0 // temperature = 0 for consistency\n );\n\n return {\n knowledge: {\n assumption: response.text.trim(),\n grade,\n },\n usage: response.usage,\n latencyMs: response.latencyMs,\n };\n }\n\n /**\n * Stage 2: Evaluate vocabulary complexity\n *\n * Uses the Qual Text Complexity rubric (SAP) and background knowledge to evaluate vocabulary complexity.\n * Grades 3-4 use Gemini 2.5 Pro; grades 5-12 use GPT-4.1.\n */\n private async evaluateComplexity(\n text: string,\n grade: string,\n backgroundKnowledge: string,\n fkLevel: number\n ): Promise<{ data: VocabularyInternal; usage: { inputTokens: number; outputTokens: number }; latencyMs: number }> {\n const systemPrompt = getSystemPrompt(grade);\n const userPrompt = getUserPrompt(text, grade, backgroundKnowledge, fkLevel);\n\n const provider = (grade === '3' || grade === '4')\n ? this.grades34ComplexityProvider\n : this.otherGradesComplexityProvider;\n\n const response = await provider.generateStructured({\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt },\n ],\n schema: VocabularyComplexitySchema,\n temperature: 0,\n });\n\n return {\n data: response.data,\n usage: response.usage,\n latencyMs: response.latencyMs,\n };\n }\n\n}\n\n/**\n * Functional API for vocabulary evaluation\n *\n * @example\n * ```typescript\n * const result = await evaluateVocabulary(\n * \"The mitochondria is the powerhouse of the cell.\",\n * \"3\",\n * {\n * googleApiKey: process.env.GOOGLE_API_KEY,\n * openaiApiKey: process.env.OPENAI_API_KEY\n * }\n * );\n * ```\n */\nexport async function evaluateVocabulary(\n text: string,\n grade: string,\n config: BaseEvaluatorConfig\n): Promise<EvaluationResult<TextComplexityLevel, VocabularyInternal>> {\n const evaluator = new VocabularyEvaluator(config);\n return evaluator.evaluate(text, grade);\n}\n","import { z } from 'zod';\nimport { TextComplexityLevel } from './outputs.js';\n\n/**\n * Stage 1: Detailed sentence analysis output (40+ metrics)\n * Ported from Python SentenceAnalysesEvaluatorOutput\n */\nexport const SentenceAnalysisSchema = z.object({\n reasoning: z.string().describe('Step-by-step reasoning for the analysis'),\n\n // Foundational\n num_sentences: z.number().int().describe('Total number of sentences in the text'),\n num_words: z.number().int().describe('Total number of words in the text'),\n flesch_kincaid_grade: z.number().describe('Flesch-Kincaid Grade Level number'),\n\n // Sentence Type\n num_simple_sentences: z.number().int().describe('Number of simple sentences'),\n num_compound_sentences: z.number().int().describe('Number of compound sentences'),\n num_complex_sentences: z.number().int().describe('Number of complex sentences'),\n num_compound_complex_sentences: z.number().int().describe('Number of compound-complex sentences'),\n num_other_sentences: z.number().int().describe('Number of other sentence types'),\n\n // Subordination\n num_independent_clauses: z.number().int(),\n num_subordinate_clauses: z.number().int(),\n num_total_clauses: z.number().int(),\n num_sentences_with_subordinate: z.number().int(),\n num_sentences_with_multiple_subordinates: z.number().int(),\n num_sentences_with_embedded_clauses: z.number().int(),\n\n // Informational Phrases\n num_prepositional_phrases: z.number().int(),\n num_participle_phrases: z.number().int(),\n num_appositive_phrases: z.number().int(),\n\n // Cohesion\n num_simple_transitions: z.number().int(),\n num_sophisticated_transitions: z.number().int(),\n\n // Sentence Type Density\n words_in_simple_sentences: z.number().int(),\n words_in_compound_sentences: z.number().int(),\n words_in_complex_sentences: z.number().int(),\n words_in_compound_complex_sentences: z.number().int(),\n words_in_other_sentences: z.number().int(),\n\n // Additional Features\n sentence_word_counts: z.array(z.number().int()),\n num_one_concept_sentences: z.number().int(),\n num_multi_concept_sentences: z.number().int(),\n num_cleft_sentences: z.number().int(),\n max_clauses_in_any_sentence: z.number().int(),\n\n // Grades 5-12 specific\n num_compound: z.number().int().describe('Number of compound sentences'),\n num_basic_complex: z.number().int().describe('Number of basic complex sentences'),\n num_advanced_complex: z.number().int().describe('Number of advanced complex sentences'),\n percentage_simple: z.number().describe('Percentage of simple sentences'),\n percentage_compound: z.number().describe('Percentage of compound sentences'),\n percentage_basic_complex: z.number().describe('Percentage of basic complex sentences'),\n percentage_advanced_complex: z.number().describe('Percentage of advanced complex sentences'),\n});\n\nexport type SentenceAnalysis = z.infer<typeof SentenceAnalysisSchema>;\n\n/**\n * Stage 2: Final complexity classification\n * Ported from Python ComplexityClassificationOutput\n */\nexport const ComplexityClassificationSchema = z.object({\n reasoning: z.string().describe('Detailed pedagogically appropriate reasoning'),\n answer: TextComplexityLevel,\n});\n\nexport type ComplexityClassification = z.infer<typeof ComplexityClassificationSchema>;\n\n/**\n * Internal data structure for sentence structure evaluation\n */\nexport interface SentenceStructureInternal {\n sentenceAnalysis: SentenceAnalysis;\n features: SentenceFeatures;\n complexity: ComplexityClassification;\n}\n\n/**\n * Engineered features computed from sentence analysis\n * These are calculated in TypeScript, not requested from LLM\n */\nexport interface SentenceFeatures extends SentenceAnalysis {\n // Foundational & Distributional\n avg_words_per_sentence: number;\n sentence_length_variation: number;\n percent_short_sentences: number;\n percent_medium_sentences: number;\n percent_long_sentences: number;\n percent_very_long_sentences: number;\n\n // Sentence Structure (Grammatical Type)\n percent_simple_sentences: number;\n percent_compound_sentences: number;\n percent_complex_sentences: number;\n percent_compound_complex_sentences: number;\n percent_other_sentences: number;\n\n // Word Distribution\n percent_words_in_simple_sentences: number;\n percent_words_in_complex_sentences: number;\n percent_words_in_compound_sentences: number;\n percent_words_in_compound_complex_sentences: number;\n percent_words_in_other_sentences: number;\n\n // Clausal & Subordination\n avg_subordinates_per_sentence: number;\n avg_clauses_per_sentence: number;\n percent_sentences_with_subordinate: number;\n percent_sentences_with_multiple_subordinates: number;\n percent_sentences_with_embedded_clauses: number;\n\n // Phrase Density\n prep_phrase_density: number;\n participle_phrase_density: number;\n appositive_phrase_density: number;\n\n // Cohesion & Transitions\n avg_transitions_per_sentence: number;\n percent_sophisticated_transitions: number;\n\n // Conceptual & Other\n percent_sentences_w_one_concept: number;\n percent_sentences_w_multi_concept: number;\n percent_cleft_sentences: number;\n}\n","You are an expert in grammar and literacy.","\n# Task\nI am going to give you a text, and I need you to look through the text sentence-by-sentence to perform a comprehensive grammatical analysis. Use the computational counts as a reference; they can be incorrect in ambiguous cases.\n\n# Definitions\n* Sentences: Count a complete grammatical unit ending in a terminal punctuation mark.\n* Words: Count any sequence of characters separated by a space as one word. Treat hyphenated words (e.g., \"state-of-the-art\") and numbers (e.g., \"2025\") as single words.\n* Independent Clauses: Clauses that can stand alone as a complete sentence.\n* Subordinate Clauses: Clauses that are dependent on the main clause and cannot stand alone as a complete sentence.\n* Simple Sentences: Sentences with one independent clause and no subordinate clauses.\n* Compound Sentences: Sentences with two or more independent clauses and no subordinate clauses.\n* Complex Sentences: Sentences with one independent clause and at least one subordinate clause.\n* Compound-Complex Sentences: Sentences with two or more independent clauses and at least one subordinate clause.\n* Other / Non-Canonical Sentences: Sentences that cannot be reliably classified as simple, compound, complex, or compound-complex (e.g., sentence fragments, run-ons, elliptical responses, headlines, imperatives lacking an explicit subject, or stylized dialogue tags).\n* Subordinate Clauses: Clauses that are dependent on the main clause and cannot stand alone as a complete sentence.\n* Embedded Clauses: Clauses that are nested within another clause.\n* Prepositional Phrases: Phrases that begin with a preposition and end with a noun phrase.\n* Participle Phrases: Phrases that begin with a participle and end with a noun phrase.\n* Appositive Phrases: Phrases that rename or identify a noun phrase.\n* Simple Transitions: Basic coordinating conjunctions and chronological adverbs. Examples: 'and', 'but', 'or', 'so', 'then', 'next', 'first'.\n* Sophisticated Transitions: Conjunctive adverbs and phrases signaling logical relationships. Examples: 'however', 'therefore', 'consequently', 'as a result', 'for example', 'although'.\n* One-Concept Sentence: A sentence with ZERO subordinate clauses AND ZERO transition words/phrases (neither simple nor sophisticated).\n* Multi-Concept Sentence: Any sentence that has ≥1 subordinate clause OR ≥1 transition word/phrase (or both).\n* Basic Complex Sentences: Sentences with exactly one independent clause and at one dependent (subordinate) clause.\n* Advanced Complex Sentences: Sentences with two or more of any of those following (can include a mix, doesn't have to be two of the same type) subordinate phrases, clauses, transition words, or any other meaningful \"interruptions\" to the flow of the sentence (like not-only-but-also constructions, dashes, semicolons, and lengthy appositives). A sentence can be advanced complex if it has just one subordinate phrase or clause alongside a transition phrase, like: \"For example, the British favored trade with Hong Kong, assuming favorable trade conditions.\n\n# Computational Counts\nUse these as reference, your internal heuristics can be more reliable.\n{ground_truth_counts}\n\n# Text to Analyze\n[BEGIN TEXT]\n{text}\n[END TEXT]\n\nIMPORTANT: Your response should be a single JSON object with the following structure. Do not produce anything outside of the JSON object.\n\n{format_instructions}\n","import SYSTEM_PROMPT_ANALYSIS_TEMPLATE from '../../../../../evals/prompts/sentence-structure/analysis-system.txt';\nimport USER_PROMPT_ANALYSIS_TEMPLATE from '../../../../../evals/prompts/sentence-structure/analysis-user.txt';\n\n/**\n * Get the system prompt for sentence grammatical analysis\n * @returns The system prompt\n */\nexport function getSystemPromptAnalysis(): string {\n return SYSTEM_PROMPT_ANALYSIS_TEMPLATE;\n}\n\n/**\n * Generate the user prompt for sentence analysis\n * @param text - The text to analyze\n * @param groundTruthCounts - Ground truth counts from readability metrics\n * @returns The formatted user prompt\n */\nexport function getUserPromptAnalysis(text: string, groundTruthCounts: string): string {\n return USER_PROMPT_ANALYSIS_TEMPLATE\n .replace('{text}', text)\n .replace('{ground_truth_counts}', groundTruthCounts)\n .replace('{format_instructions}', '');\n}\n","You are an expert in grammar and literacy, and understand K-12 and Qualitative Text Complexity rubric (SAP).","\nYour task is to perform a text complexity analysis for a Grade {grade} student. You will be given a text excerpt and a set of quantitative sentence-level statistics for that text.\n\nYou must integrate both the qualitative aspects of the text and the quantitative statistics to make your final judgment. Do not rely on the numbers alone.\n\n1. Read the TEXT EXCERPT to understand its topic, conceptual load, and overall structure.\n2. Review the TEXT STATISTICS as a guide for complexity level.\n3. Synthesize your findings in your reasoning. Explain how the structure (qualitative) interact with the text statistics (quantitative) to determine the complexity. For example, a text with simple sentences might still be complex if the topic is very dense or abstract.\n\nYour final answer must be one of [\"Slightly Complex,\" \"Moderately Complex,\" \"Very Complex\", \"Exceedingly Complex\"].\n\n# GRADE {grade} RUBRIC\n{rubric}\n\n# TEXT EXCERPT\n[BEGIN TEXT]\n{excerpt}\n[END TEXT]\n\n# TEXT STATISTICS\n{sentence_features}\n\n# OUTPUT FORMAT\n{format_instructions}\n","\n **Instructions for Analysis:** First, evaluate if the text meets the criteria for \"Slightly Complex\" or \"Exceedingly Complex\". If it does not fit into these categories, then decide between \"Moderately Complex\" and \"Very Complex\".\n\n **Slightly Complex:**\n * **Description:** The text consists of simple, straightforward language and sentence structures.\n * **Statistical Guidelines:** The text is likely \"Slightly Complex\" if it meets at least TWO of the following criteria:\n * **Sentence Type:** Primarily simple sentences. (`percent_simple_sentences` is typically > 60%).\n * **Sentence Length:** Short sentences. (`avg_sentence_length` is typically < 12 words).\n * **Subordination:** Very low use of clauses. (`percent_sentences_with_subordinate` is typically < 25%).\n\n **Moderately Complex:**\n * **Description:** The text shows a mix of simple and more complex sentences, introducing some variety in structure without being overly demanding.\n * **Statistical Guidelines:** If the text is not \"Slightly Complex\", consider \"Moderately Complex\" if it generally aligns with these ranges:\n * **Sentence Type:** A balanced mix of sentence types. (`percent_simple_sentences` is typically between 40% and 60%).\n * **Sentence Length:** Medium length sentences. (`avg_sentence_length` is typically between 12 and 16 words).\n * **Subordination:** A moderate use of clauses. (`percent_sentences_with_subordinate` is typically between 25% and 45%).\n\n **Very Complex:**\n * **Description:** The text features more elaborate sentences with multiple clauses and ideas, requiring more effort from the reader to parse. This is often the default category for grade-level text that isn't simple or exceptionally difficult.\n * **Statistical Guidelines:** If the text is more complex than \"Moderately\" but does not meet the \"Exceedingly\" criteria, it is likely \"Very Complex\". Key indicators include:\n * **Sentence Type:** Complex structures are common. (`percent_simple_sentences` is a minority, typically < 40%).\n * **Sentence Length:** Longer sentences are frequent. (`avg_sentence_length` is typically between 16 and 19 words).\n * **Subordination:** Subordinate clauses are a key feature. (`percent_sentences_with_subordinate` is typically > 45%).\n\n **Exceedingly Complex:**\n * **Description:** The text is dense with very long, intricate sentences and a high degree of subordination, making it exceptionally challenging for this grade level.\n * **Statistical Guidelines:** The text is \"Exceedingly Complex\" if it shows an extreme combination of sentence length and structural density. It should meet at least **TWO** of the following criteria, including at least **ONE** from the \"Structural Density\" group.\n * **Structural Density Indicators:**\n * High Subordination: `percent_sentences_with_subordinate` is extensive (typically > 50%).\n * Multiple Subordinates: `percent_sentences_with_multiple_subordinates` is consistently present (typically > 12%).\n * High Syntactic Complexity: `percent_compound_complex_sentences` is significant (typically > 15%).\n * **Length Indicators:**\n * Extreme Sentence Length: `avg_sentence_length` is very long (typically > 19 words).\n * Low Simplicity: `percent_simple_sentences` is very low (typically < 30%).\n * Concentrated Length: `percent_very_long_sentences` is notable (typically > 10%).\n","\n **Instructions for Analysis:** First, evaluate if the text meets the criteria for \"Slightly Complex\" or \"Exceedingly Complex\". If it does not fit into these categories, then decide between \"Moderately Complex\" and \"Very Complex\".\n\n **Slightly Complex:**\n * **Description:** The text uses clear, direct language with basic sentence structures appropriate for developing readers.\n * **Statistical Guidelines:** The text is likely \"Slightly Complex\" if it meets at least TWO of the following criteria:\n * **Sentence Type:** Dominated by simple sentences. (`percent_simple_sentences` is typically > 55%).\n * **Sentence Length:** Short to medium sentences. (`avg_sentence_length` is typically < 13 words).\n * **Subordination:** Infrequent use of clauses. (`percent_sentences_with_subordinate` is typically < 30%).\n\n **Moderately Complex:**\n * **Description:** The text contains a variety of sentence structures, including compound and complex sentences, but remains accessible.\n * **Statistical Guidelines:** If the text is not \"Slightly Complex\", consider \"Moderately Complex\" if it generally aligns with these ranges:\n * **Sentence Type:** A healthy mix of sentence types. (`percent_simple_sentences` is typically between 40% and 55%).\n * **Sentence Length:** Medium length sentences. (`avg_sentence_length` is typically between 13 and 17 words).\n * **Subordination:** A moderate number of clauses. (`percent_sentences_with_subordinate` is typically between 30% and 50%).\n\n **Very Complex:**\n * **Description:** The text is characterized by longer sentences and the regular use of dependent clauses, requiring readers to track multiple ideas. This is the default for challenging, on-grade-level texts.\n * **Statistical Guidelines:** If the text is more complex than \"Moderately\" but does not meet the \"Exceedingly\" criteria, it is likely \"Very Complex\". Key indicators include:\n * **Sentence Type:** Simple sentences are a clear minority. (`percent_simple_sentences` is typically < 40%).\n * **Sentence Length:** Sentences are consistently long. (`avg_sentence_length` is typically between 17 and 22 words).\n * **Subordination:** Subordination is a major feature. (`percent_sentences_with_subordinate` is typically > 50%).\n * **Multiple Subordination:** Sentences with multiple clauses appear more often. (`percent_sentences_with_multiple_subordinates` is typically > 8%).\n\n **Exceedingly Complex:**\n * **Description:** The text's structure is highly sophisticated and dense, marked by extensive use of embedded clauses and long, flowing sentences that are well above grade-level expectations.\n * **Statistical Guidelines:** A text is \"Exceedingly Complex\" if its structure is highly sophisticated and dense. It should meet at least **TWO** of the following criteria, including at least **ONE** from the \"Structural Density\" group.\n * **Structural Density Indicators:**\n * High Subordination: `percent_sentences_with_subordinate` is very high (typically > 60%).\n * Multiple Subordinates: `percent_sentences_with_multiple_subordinates` is high and consistent (typically > 15%).\n * High Syntactic Complexity: `percent_compound_complex_sentences` is a notable feature (typically > 20%).\n * **Length Indicators:**\n * Extreme Sentence Length: `avg_sentence_length` is exceptionally long (typically > 22 words).\n * Low Simplicity: `percent_simple_sentences` is very low (typically < 25%).\n * Concentrated Length: `percent_very_long_sentences` is significant (typically > 15%).\n","\n **Slightly Complex:** A text is in the Slightly Complex bucket if it has at least 50% simple sentences. If it doesn't, the text is a higher level of complexity. If the % of simple sentences is >= 50% and the % of compound sentences is >= 20%, the text is Moderately Complex, otherwise, the text is Slightly Complex. Slightly Complex texts NEVER have advanced complex sentences — the presence of an advanced complex sentence always leads to a higher level of complexity than Slightly.\n **For Moderately Complex:** These texts can take on any distribution of sentence types as long as there aren't more than 2 advanced complex sentences and as long as there aren't so many simple sentences that the text becomes Slightly Complex. That means Moderately Complex texts may have many simple sentences (although not so many that the text is Slightly Complex), compound sentences, and/or basic complex sentences. It's also possible for a moderately complex text to contain one or two advanced complex sentences, as long as there aren't more than 2. If there are more than 2, then the text is either Very or Exceedingly complex.\n **Very Complex:** These texts contain 3 or more advanced complex sentences (unless the percentage of advanced complex sentences is >= 65)%, in which case the text becomes Exceedingly Complex). They may still contain many simple, compound, and basic complex sentences, but a text is not Very Complex unless there are 3 or more advanced complex sentences.\n **Exceedingly Complex:** These texts have 65%+ of their sentences being advanced complex sentences.\n","import SYSTEM_PROMPT_COMPLEXITY_TEMPLATE from '../../../../../evals/prompts/sentence-structure/complexity-system.txt';\nimport USER_PROMPT_COMPLEXITY_TEMPLATE from '../../../../../evals/prompts/sentence-structure/complexity-user.txt';\nimport RUBRIC_GRADE_3 from '../../../../../evals/prompts/sentence-structure/rubric-grade-3.txt';\nimport RUBRIC_GRADE_4 from '../../../../../evals/prompts/sentence-structure/rubric-grade-4.txt';\nimport RUBRIC_GRADES_5_12 from '../../../../../evals/prompts/sentence-structure/rubric-grades-5-12.txt';\n\n/**\n * Get the system prompt for sentence structure complexity evaluation\n * @returns The system prompt\n */\nexport function getSystemPromptComplexity(): string {\n return SYSTEM_PROMPT_COMPLEXITY_TEMPLATE;\n}\n\n/**\n * Get the appropriate rubric based on grade level\n * @param grade - The target grade level (3-12)\n * @returns The rubric text for the grade level\n */\nexport function getRubricForGrade(grade: string): string {\n if (grade === '3') {\n return RUBRIC_GRADE_3;\n } else if (grade === '4') {\n return RUBRIC_GRADE_4;\n } else {\n return RUBRIC_GRADES_5_12;\n }\n}\n\n/**\n * Generate the user prompt for complexity evaluation\n * @param sentenceFeatures - JSON string of sentence features\n * @param grade - The target grade level\n * @param excerpt - The original text excerpt\n * @returns The formatted user prompt\n */\nexport function getUserPromptComplexity(\n sentenceFeatures: string,\n grade: string,\n excerpt: string\n): string {\n const rubric = getRubricForGrade(grade);\n\n return USER_PROMPT_COMPLEXITY_TEMPLATE\n .replace('{sentence_features}', sentenceFeatures)\n .replace('{grade}', grade)\n .replace('{rubric}', rubric)\n .replace('{excerpt}', excerpt)\n .replace('{format_instructions}', '');\n}\n","import type { LLMProvider } from '../providers/index.js';\nimport {\n SentenceAnalysisSchema,\n ComplexityClassificationSchema,\n type SentenceAnalysis,\n type SentenceFeatures,\n type ComplexityClassification,\n type SentenceStructureInternal,\n} from '../schemas/sentence-structure.js';\nimport { calculateReadabilityMetrics, addEngineeredFeatures, featuresToJSON } from '../features/index.js';\nimport {\n getSystemPromptAnalysis,\n getUserPromptAnalysis,\n getSystemPromptComplexity,\n getUserPromptComplexity,\n} from '../prompts/sentence-structure/index.js';\nimport type { EvaluationResult, TextComplexityLevel } from '../schemas/index.js';\nimport { BaseEvaluator, Provider, type BaseEvaluatorConfig } from './base.js';\nimport type { StageDetail } from '../telemetry/index.js';\nimport { ValidationError, wrapProviderError } from '../errors.js';\n\n/**\n * Normalize complexity label to handle LLM output variations\n */\nfunction normalizeLabel(label: string | null | undefined): TextComplexityLevel | null {\n if (!label) {\n return null;\n }\n\n const normalized = label.trim().toLowerCase().replace(/_/g, ' ');\n const mapping: Record<string, TextComplexityLevel> = {\n 'slightly complex': 'Slightly complex',\n 'moderately complex': 'Moderately complex',\n 'very complex': 'Very complex',\n 'exceedingly complex': 'Exceedingly complex',\n 'extremely complex': 'Exceedingly complex',\n };\n\n return mapping[normalized] ?? null;\n}\n\n/**\n * Sentence Structure Evaluator\n *\n * Evaluates sentence structure complexity of educational texts relative to grade level.\n * Uses a 2-stage process:\n * 1. Analyze grammatical structure (sentence types, clauses, phrases, etc.)\n * 2. Classify complexity using features and grade-specific rubric\n *\n * Based on Qualitative Text Complexity rubric with 4 levels:\n * - Slightly complex\n * - Moderately complex\n * - Very complex\n * - Exceedingly complex\n *\n * @example\n * ```typescript\n * const evaluator = new SentenceStructureEvaluator({\n * openaiApiKey: process.env.OPENAI_API_KEY\n * });\n *\n * const result = await evaluator.evaluate(text, \"3\");\n * console.log(result.score); // \"Moderately complex\"\n * console.log(result.reasoning);\n * ```\n */\nexport class SentenceStructureEvaluator extends BaseEvaluator {\n static readonly metadata = {\n id: 'sentence-structure',\n name: 'Sentence Structure',\n description: 'Evaluates sentence structure complexity based on grammatical features',\n supportedGrades: ['3', '4', '5', '6', '7', '8', '9', '10', '11', '12'] as const,\n defaultProviders: [Provider.OpenAI] as const,\n };\n\n private provider: LLMProvider;\n\n constructor(config: BaseEvaluatorConfig) {\n // Call base constructor for common setup (telemetry, API key validation, etc.)\n super(config);\n\n // Both stages use the same model — share a single provider instance\n this.provider = this.createConfiguredProvider(Provider.OpenAI, 'gpt-4o', config.openaiApiKey);\n }\n\n /**\n * Evaluate sentence structure complexity for a given text and grade level\n *\n * @param text - The text to evaluate\n * @param grade - The target grade level (3-12)\n * @returns Evaluation result with complexity score and detailed analysis\n * @throws {ValidationError} If text is empty, too short/long, or grade is invalid\n * @throws {ConfigurationError} If modelOverride specifies a model ID that the provider rejects\n * @throws {APIError} If LLM API calls fail (includes AuthenticationError, RateLimitError, NetworkError, TimeoutError)\n */\n async evaluate(\n text: string,\n grade: string\n ): Promise<EvaluationResult<TextComplexityLevel, SentenceStructureInternal>> {\n this.logger.info('Starting sentence structure evaluation', {\n evaluator: 'sentence-structure',\n operation: 'evaluate',\n grade,\n textLength: text.length,\n });\n\n const startTime = Date.now();\n const stageDetails: StageDetail[] = [];\n\n try {\n // Validate inputs — inside try so validation errors are telemetered.\n this.validateText(text);\n this.validateGrade(grade, new Set(SentenceStructureEvaluator.metadata.supportedGrades));\n this.logger.debug('Stage 1: Analyzing sentence structure', {\n evaluator: 'sentence-structure',\n operation: 'sentence_analysis',\n });\n // Stage 1: Analyze sentence structure\n const analysisResponse = await this.analyzeSentenceStructure(text);\n\n stageDetails.push({\n stage: 'sentence_analysis',\n provider: this.provider.label,\n latency_ms: analysisResponse.latencyMs,\n token_usage: {\n input_tokens: analysisResponse.usage.inputTokens,\n output_tokens: analysisResponse.usage.outputTokens,\n },\n });\n\n // Compute engineered features\n const features = addEngineeredFeatures(analysisResponse.data);\n\n this.logger.debug('Stage 2: Classifying complexity', {\n evaluator: 'sentence-structure',\n operation: 'complexity_classification',\n });\n // Stage 2: Classify complexity\n const complexityResponse = await this.classifyComplexity(features, grade, text);\n\n stageDetails.push({\n stage: 'complexity_classification',\n provider: this.provider.label,\n latency_ms: complexityResponse.latencyMs,\n token_usage: {\n input_tokens: complexityResponse.usage.inputTokens,\n output_tokens: complexityResponse.usage.outputTokens,\n },\n });\n\n const latencyMs = Date.now() - startTime;\n\n // Aggregate token usage\n const totalTokenUsage = {\n input_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.input_tokens || 0), 0),\n output_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.output_tokens || 0), 0),\n };\n\n const result = {\n score: complexityResponse.data.answer,\n reasoning: complexityResponse.data.reasoning,\n metadata: {\n model: this.provider.label,\n processingTimeMs: latencyMs,\n },\n _internal: {\n sentenceAnalysis: analysisResponse.data,\n features,\n complexity: complexityResponse.data,\n },\n };\n\n // Send success telemetry (fire-and-forget)\n this.sendTelemetry({\n status: 'success',\n latencyMs,\n textLength: text.length,\n grade,\n provider: this.provider.label,\n tokenUsage: totalTokenUsage,\n metadata: {\n stage_details: stageDetails,\n },\n inputText: text,\n }).catch(() => {\n // Ignore telemetry errors\n });\n\n this.logger.info('Sentence structure evaluation completed successfully', {\n evaluator: 'sentence-structure',\n operation: 'evaluate',\n grade,\n score: result.score,\n processingTimeMs: latencyMs,\n });\n\n return result;\n } catch (error) {\n const latencyMs = Date.now() - startTime;\n\n // Log the error\n this.logger.error('Sentence structure evaluation failed', {\n evaluator: 'sentence-structure',\n operation: 'evaluate',\n grade,\n error: error instanceof Error ? error : undefined,\n processingTimeMs: latencyMs,\n completedStages: stageDetails.length,\n });\n\n // Aggregate metrics from completed stages\n const totalTokenUsage = stageDetails.length > 0 ? {\n input_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.input_tokens || 0), 0),\n output_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.output_tokens || 0), 0),\n } : undefined;\n\n // Send failure telemetry (fire-and-forget)\n this.sendTelemetry({\n status: 'error',\n latencyMs,\n textLength: text.length,\n grade,\n provider: this.provider.label,\n tokenUsage: totalTokenUsage,\n errorCode: error instanceof Error ? error.name : 'UnknownError',\n metadata: stageDetails.length > 0 ? { stage_details: stageDetails } : undefined,\n inputText: text,\n }).catch(() => {\n // Ignore telemetry errors\n });\n\n // Re-throw validation errors as-is\n if (error instanceof ValidationError) {\n throw error;\n }\n\n // Wrap provider errors into appropriate error types\n throw wrapProviderError(error, 'Sentence structure evaluation failed');\n }\n }\n\n /**\n * Stage 1: Analyze sentence grammatical structure\n *\n * Analyzes sentence types, clauses, phrases, transitions, and other grammatical features\n */\n private async analyzeSentenceStructure(\n text: string\n ): Promise<{ data: SentenceAnalysis; usage: { inputTokens: number; outputTokens: number }; latencyMs: number }> {\n // Compute ground truth counts\n const metrics = calculateReadabilityMetrics(text);\n\n const gtCountsStr = [\n `num_sentences: ${metrics.sentenceCount}`,\n `num_words: ${metrics.wordCount}`,\n `num_char: ${metrics.characterCount}`,\n `num_syllable: ${metrics.syllableCount}`,\n `flesch_kincaid_grade: ${metrics.fleschKincaidGrade}`,\n ].join('\\n');\n\n const userPrompt = getUserPromptAnalysis(text, gtCountsStr);\n\n const response = await this.provider.generateStructured({\n messages: [\n { role: 'system', content: getSystemPromptAnalysis() },\n { role: 'user', content: userPrompt },\n ],\n schema: SentenceAnalysisSchema,\n temperature: 0,\n });\n\n return {\n data: response.data,\n usage: response.usage,\n latencyMs: response.latencyMs,\n };\n }\n\n /**\n * Stage 2: Classify sentence structure complexity\n *\n * Uses engineered features and grade-specific rubric to classify complexity level\n */\n private async classifyComplexity(\n features: SentenceFeatures,\n grade: string,\n excerpt: string\n ): Promise<{ data: ComplexityClassification; usage: { inputTokens: number; outputTokens: number }; latencyMs: number }> {\n // Convert features to JSON string (cast to int by default, matching Python)\n const featuresJSON = featuresToJSON(features, 1, true);\n\n const userPrompt = getUserPromptComplexity(featuresJSON, grade, excerpt);\n\n const response = await this.provider.generateStructured({\n messages: [\n { role: 'system', content: getSystemPromptComplexity() },\n { role: 'user', content: userPrompt },\n ],\n schema: ComplexityClassificationSchema,\n temperature: 0,\n });\n\n // Normalize label to handle LLM output variations\n const normalizedAnswer = normalizeLabel(response.data.answer);\n\n if (!normalizedAnswer) {\n throw new Error(\n `Failed to normalize complexity label. Received unexpected value: \"${response.data.answer}\". ` +\n `Expected one of: Slightly Complex, Moderately Complex, Very Complex, Exceedingly Complex, Extremely Complex.`\n );\n }\n\n return {\n data: {\n ...response.data,\n answer: normalizedAnswer,\n },\n usage: response.usage,\n latencyMs: response.latencyMs,\n };\n }\n}\n\n/**\n * Functional API for sentence structure evaluation\n *\n * @example\n * ```typescript\n * const result = await evaluateSentenceStructure(\n * \"The cat sat on the mat. It was sleeping peacefully.\",\n * \"3\",\n * {\n * openaiApiKey: process.env.OPENAI_API_KEY\n * }\n * );\n * ```\n */\nexport async function evaluateSentenceStructure(\n text: string,\n grade: string,\n config: BaseEvaluatorConfig\n): Promise<EvaluationResult<TextComplexityLevel, SentenceStructureInternal>> {\n const evaluator = new SentenceStructureEvaluator(config);\n return evaluator.evaluate(text, grade);\n}\n","import { z } from 'zod';\n\n/**\n * Valid grade bands for grade level appropriateness evaluation\n */\nexport const GradeBand = z.enum(['K-1', '2-3', '4-5', '6-8', '9-10', '11-CCR']);\n\nexport type GradeBand = z.infer<typeof GradeBand>;\n\n/**\n * Output schema for Grade Level Appropriateness evaluation\n * Matches Python OutputRanges model\n */\nexport const GradeLevelAppropriatenessSchema = z.object({\n reasoning: z\n .string()\n .describe(\n 'Your reasoning for your answer in numbered bullet points for 4 steps with a 4th bullet point for synthesis.'\n ),\n grade: GradeBand.describe('The appropriate grade level for the text'),\n alternative_grade: GradeBand.describe('An alternative grade level for the text'),\n scaffolding_needed: z\n .string()\n .describe('Scaffolding needed for the text to be appropriate for the alternative grade'),\n});\n\nexport type GradeLevelAppropriatenessInternal = z.infer<typeof GradeLevelAppropriatenessSchema>;\n","\nYou are an expert in English literature education for K-12.\nYour job is to help evaluate the grade level appropriateness of a given text.\n\nYou will be given a text and you should determine which grade level the text is appropriate for (grade levels include: K-1, 2-3, 4-5, 6-8, 9-10, 11-CCR)\n\nIMPORTANT: You should pay attention to the vocabulary used, topics of the text and readability of text.\n\nPlease first reason out loud about the vocabulary complexity of the text and then provide an answer between grade level options: K-1, 2-3, 4-5, 6-8, 9-10, 11-CCR.\n\n","\nUse these steps to determine appropriate grade level for a text:\n1. Calculate word count and Flesch-Kincaid Grade Level of the text, and generate a grade band.\nHere are the bands guideline for word count\n\n2-3: 200-800 words\n4-5: 200-800 words\n6-8: 400-1000 words\n9-10: 500-1500 words\n11-12: 1501 words and more\n\nHere is the formula for Flesch-Kincaid Grade Level:\nFlesch-Kincaid Grade Level = 0.39 * (total words / total sentences) + 11.8 * (total syllables / total words) - 15.59\n\n\n2. Determine the qualitative complexity using this text complexity rubric:\nTEXT STRUCTURE\n\nExceedingly Complex\n •\tDeep, intricate, often ambiguous connections between many ideas/processes/events\n •\tOrganization is intricate or discipline-specific\n •\tText features are essential for understanding\n •\tGraphics are intricate, extensive, and integral to meaning; may convey unique information\n\nVery Complex\n •\tExpanded ideas/processes/events with implicit or subtle connections\n •\tOrganization may have multiple pathways or discipline-specific traits\n •\tText features directly enhance understanding\n •\tGraphics support or are integral to understanding\n\nModerately Complex\n •\tSome implicit/subtle connections between ideas/events\n •\tOrganization is evident and generally sequential or chronological\n •\tText features enhance understanding\n •\tGraphics are mostly supplementary\n\nSlightly Complex\n •\tExplicit and clear connections between ideas/events\n •\tOrganization is chronological, sequential, or predictable\n •\tText features help navigation but are not essential\n •\tGraphics are simple, not necessary, but may assist understanding\n\n⸻\n\nLANGUAGE FEATURES\n\nExceedingly Complex\n •\tDense, abstract, ironic, and/or figurative language\n •\tComplex, unfamiliar, archaic, subject-specific, or ambiguous vocabulary\n •\tMainly complex sentences with multiple subordinate clauses and transitions\n\nVery Complex\n •\tFairly complex; some abstract, ironic, and/or figurative language\n •\tSome unfamiliar, archaic, or overly academic vocabulary\n •\tMany complex sentences with subordinate phrases/clauses\n\nModerately Complex\n •\tMostly explicit language with some complex meaning\n •\tMostly familiar and conversational vocabulary\n •\tPrimarily simple and compound sentences, with some complex ones\n\nSlightly Complex\n •\tExplicit, literal, straightforward language\n •\tContemporary, familiar, conversational vocabulary\n •\tMainly simple sentences\n\n⸻\n\nPURPOSE\n\nExceedingly Complex\n •\tSubtle, intricate, and difficult to determine\n •\tIncludes many theoretical or abstract elements\n\nVery Complex\n •\tImplicit or subtle, fairly easy to infer\n •\tMore theoretical or abstract than concrete\n\nModerately Complex\n •\tImplied but easy to identify based on context or source\n\nSlightly Complex\n •\tExplicitly stated, clear, concrete, and narrowly focused\n\n⸻\n\nKNOWLEDGE DEMANDS\n\nExceedingly Complex\n •\tRequires extensive discipline-specific or theoretical knowledge\n •\tMany references/allusions to other texts or ideas\n\nVery Complex\n •\tRequires moderate discipline-specific knowledge\n •\tSome references/allusions to other texts or ideas\n\nModerately Complex\n •\tRequires common knowledge and some discipline-specific knowledge\n •\tFew references/allusions\n\nSlightly Complex\n •\tRequires everyday, practical knowledge\n •\tNo references/allusions\n\n3. Background knowledge:\nAt which grade level would student have enough background knowledge to understand the text?\n\n4. Use your judgement of the above three steps. First use the quantitative signal to get first signal of the appropriate grade level range, then use qualitative analysis to refine your decisions and consider if student at such grade will have enough background knowledge to arrive at a final grade level band. Also consider if the text can be for a lower grade with additional scaffolding.\n\n<begin of text to evaluate>\n<text>{text}</text>\n<end of text to evaluate>\n\nWhen providing your response, first think out loud of your reasoning and then provide your answer from one of the grade band options above. Your reasoning and answer needs to be in JSON format. Strictly follow the following format for your response.\n\nYour final answer should be in the \"grade\" property for the target grade band for the text aimed for independent reading. If there is alternative appropriate grade students can read and comprehend with scaffold (eg. picture, graph, additional context, etc) or for read-aloud purposes for lower grade, provide it in the \"alternative_grade\" property and provide the types of scaffolding in the \"scaffolding_needed\" property.\n\nIn your reasoning, provide numbered bullet points for each of the analyses in each of the 3 steps. At the end, give me the 4th bullet point called \"synthesis\" to summarize your analysis from the above 3 steps that help you arrive at the final decision.\n\n{format_instructions}\n","import SYSTEM_PROMPT_TEMPLATE from '../../../../../evals/prompts/grade-level-appropriateness/system.txt';\nimport USER_PROMPT_TEMPLATE from '../../../../../evals/prompts/grade-level-appropriateness/user.txt';\n\n/**\n * Get the system prompt for grade level appropriateness evaluation\n * @returns The system prompt\n */\nexport function getSystemPrompt(): string {\n return SYSTEM_PROMPT_TEMPLATE;\n}\n\n/**\n * Get the user prompt with the text to evaluate\n * @param text - The text to evaluate for grade level appropriateness\n * @returns The formatted user prompt\n */\nexport function getUserPrompt(text: string): string {\n return USER_PROMPT_TEMPLATE\n .replace('{text}', text)\n .replace('{format_instructions}', '');\n}\n","import type { LLMProvider } from '../providers/index.js';\nimport {\n GradeLevelAppropriatenessSchema,\n type GradeLevelAppropriatenessInternal,\n} from '../schemas/grade-level-appropriateness.js';\nimport { getSystemPrompt, getUserPrompt } from '../prompts/grade-level-appropriateness/index.js';\nimport type { EvaluationResult, GradeBand } from '../schemas/index.js';\nimport { BaseEvaluator, Provider, type BaseEvaluatorConfig } from './base.js';\nimport { ValidationError, wrapProviderError } from '../errors.js';\n\n/**\n * Grade Level Appropriateness Evaluator\n *\n * Evaluates whether AI-generated text is suitable for a given grade band.\n * Uses a structured 4-step analysis process:\n * 1. Quantitative analysis (word count, Flesch-Kincaid)\n * 2. Qualitative complexity (text structure, language, purpose, knowledge demands)\n * 3. Background knowledge assessment\n * 4. Synthesis and final recommendation\n *\n * Returns:\n * - Target grade band (K-1, 2-3, 4-5, 6-8, 9-10, 11-CCR)\n * - Alternative grade band (with scaffolding)\n * - Specific scaffolding recommendations\n *\n * @example\n * ```typescript\n * const evaluator = new GradeLevelAppropriatenessEvaluator({\n * googleApiKey: process.env.GOOGLE_API_KEY\n * });\n *\n * const result = await evaluator.evaluate(text);\n * console.log(result.score); // \"9-10\"\n * console.log(result._internal.alternative_grade); // \"6-8\"\n * console.log(result._internal.scaffolding_needed);\n * ```\n */\nexport class GradeLevelAppropriatenessEvaluator extends BaseEvaluator {\n static readonly metadata = {\n id: 'grade-level-appropriateness',\n name: 'Grade Level Appropriateness',\n description: 'Determines appropriate grade level for text with scaffolding recommendations',\n supportedGrades: [] as const, // No grade parameter required - evaluates what grade the text is appropriate for\n defaultProviders: [Provider.Google] as const,\n };\n\n private provider: LLMProvider;\n\n constructor(config: BaseEvaluatorConfig) {\n // Call base constructor for common setup (telemetry, API key validation, etc.)\n super(config);\n\n this.provider = this.createConfiguredProvider(\n Provider.Google, 'gemini-2.5-pro', config.googleApiKey\n );\n }\n\n /**\n * Evaluate grade level appropriateness for a given text\n *\n * @param text - The text to evaluate\n * @returns Evaluation result with grade recommendations and scaffolding suggestions\n * @throws {ValidationError} If text is empty or too short/long\n * @throws {ConfigurationError} If modelOverride specifies a model ID that the provider rejects\n * @throws {APIError} If LLM API calls fail (includes AuthenticationError, RateLimitError, NetworkError, TimeoutError)\n */\n async evaluate(text: string): Promise<EvaluationResult<GradeBand, GradeLevelAppropriatenessInternal>> {\n this.logger.info('Starting grade level appropriateness evaluation', {\n evaluator: 'grade-level-appropriateness',\n operation: 'evaluate',\n textLength: text.length,\n });\n\n const startTime = Date.now();\n\n try {\n // Validate inputs — inside try so validation errors are telemetered.\n this.validateText(text);\n this.logger.debug('Evaluating grade level appropriateness', {\n evaluator: 'grade-level-appropriateness',\n operation: 'grade_evaluation',\n });\n const userPrompt = getUserPrompt(text);\n\n const response = await this.provider.generateStructured({\n messages: [\n { role: 'system', content: getSystemPrompt() },\n { role: 'user', content: userPrompt },\n ],\n schema: GradeLevelAppropriatenessSchema,\n temperature: 0.25,\n });\n\n const latencyMs = Date.now() - startTime;\n\n const tokenUsage = {\n input_tokens: response.usage.inputTokens,\n output_tokens: response.usage.outputTokens,\n };\n\n const result = {\n score: response.data.grade,\n reasoning: response.data.reasoning,\n metadata: {\n model: this.provider.label,\n processingTimeMs: latencyMs,\n },\n _internal: response.data,\n };\n\n // Send success telemetry (fire-and-forget)\n this.sendTelemetry({\n status: 'success',\n latencyMs,\n textLength: text.length,\n provider: this.provider.label,\n tokenUsage,\n // No metadata.stage_details for single-stage evaluator\n inputText: text,\n }).catch(() => {\n // Ignore telemetry errors\n });\n\n this.logger.info('Grade level appropriateness evaluation completed successfully', {\n evaluator: 'grade-level-appropriateness',\n operation: 'evaluate',\n grade: result.score,\n processingTimeMs: latencyMs,\n });\n\n return result;\n } catch (error) {\n const latencyMs = Date.now() - startTime;\n\n // Log the error\n this.logger.error('Grade level appropriateness evaluation failed', {\n evaluator: 'grade-level-appropriateness',\n operation: 'evaluate',\n error: error instanceof Error ? error : undefined,\n processingTimeMs: latencyMs,\n });\n\n // Send failure telemetry (fire-and-forget)\n this.sendTelemetry({\n status: 'error',\n latencyMs,\n textLength: text.length,\n provider: this.provider.label,\n errorCode: error instanceof Error ? error.name : 'UnknownError',\n inputText: text,\n }).catch(() => {\n // Ignore telemetry errors\n });\n\n // Re-throw validation errors as-is\n if (error instanceof ValidationError) {\n throw error;\n }\n\n // Wrap provider errors into appropriate error types\n throw wrapProviderError(error, 'Grade level appropriateness evaluation failed');\n }\n }\n}\n\n/**\n * Functional API for grade level appropriateness evaluation\n *\n * @example\n * ```typescript\n * const result = await evaluateGradeLevelAppropriateness(\n * \"Tides are the rise and fall of sea levels...\",\n * {\n * googleApiKey: process.env.GOOGLE_API_KEY\n * }\n * );\n * ```\n */\nexport async function evaluateGradeLevelAppropriateness(\n text: string,\n config: BaseEvaluatorConfig\n): Promise<EvaluationResult<GradeBand, GradeLevelAppropriatenessInternal>> {\n const evaluator = new GradeLevelAppropriatenessEvaluator(config);\n return evaluator.evaluate(text);\n}\n","import { z } from 'zod';\nimport { TextComplexityLevel } from './outputs.js';\n\n/**\n * Subject Matter Knowledge evaluation output schema\n */\nexport const SmkOutputSchema = z.object({\n identified_topics: z.array(z.string()).describe('List of major subjects/concepts found in the text.'),\n curriculum_check: z.string().describe('Whether the topics are standard K-8 or specialized high school level.'),\n assumptions_and_scaffolding: z.string().describe('What the author assumes the reader knows vs. what is explained.'),\n friction_analysis: z.string().describe('Whether difficulty comes from vocabulary/structure or actual knowledge demands.'),\n complexity_score: TextComplexityLevel.describe('The subject matter knowledge complexity level of the text'),\n reasoning: z.string().describe('A brief synthesis of why the text fits the chosen complexity level.'),\n});\n\nexport type SmkInternal = z.infer<typeof SmkOutputSchema>;\n","\nTo perform the task of evaluating text complexity based on Subject Matter Knowledge (SMK), strictly adhere to the following instructions.\nRole\nYou are an expert K-12 Literacy Pedagogue and Text Complexity Evaluator. Your specific focus is analyzing Subject Matter Knowledge (SMK) demands according to the Common Core Qualitative Text Complexity Rubric.\nObjective\nAnalyze a provided text relative to a target grade_level. You must determine the extent of background knowledge required to comprehend the text. You must distinguish between Common/Standard knowledge (generally lower/moderate complexity) and Specialized/Theoretical knowledge (generally higher complexity).\nInput Data\ntext: The passage to analyze.\ngrade_level: The target student grade (integer).\nfk_score: Flesch-Kincaid Grade Level. Note: Use this only as a loose proxy for sentence structure. Do not let a high FK score artificially inflate the Subject Matter Knowledge score if the concepts remain simple.\n\n1. The Rubric: Subject Matter Knowledge (SMK)\n1. Slightly Complex\nScope: Everyday, practical knowledge, and Introduction to Skills.\nConcept Type: Concrete, directly observable, and familiar.\nKey Indicator: \"How-to\" texts involving familiar objects (e.g., drawing a cupboard, playing a game, family life). Even if specific terms (like \"scale\" or \"measure\") are used, if the application is on a common object, it remains Slightly Complex.\n2. Moderately Complex\nScope: Common Discipline-Specific Knowledge or Narrative History.\nDefinition: Topics widely introduced in K-8 curricula (Basic American History, Geography, Earth Science, Biology).\nKey Characteristic: The text bridges concrete descriptions with abstract themes (e.g., using farming to discuss justice), OR narrates historical events via sensory details.\nSpatial Reasoning: Texts requiring mental manipulation of maps/routes are generally Moderate, unless the object is a familiar household item (see Slightly Complex).\n3. Very Complex\nScope: Specialized Discipline-Specific, Engineering Mechanics, or Political Theory.\nDefinition: Topics characteristic of High School (9-12) curricula requiring abstract mental models.\nKey Characteristic: Requires understanding mechanisms (how physics works/propulsion), chemical composition, or undefined political stakes (specific treaties, alliances, or secularization without context).\n4. Exceedingly Complex\nScope: Professional or Academic knowledge.\n\n2. The Expert Mental Model (Decision Logic)\nUse these refined rules to categorize cases.\nRule A: The \"Layers of Meaning\" Check\nConcrete -> Abstract (Moderate): The text describes concrete things (farming) to argue an abstract point (justice, rights).\nConcrete -> Concrete (Slightly): The text describes concrete things (lines, paper) to achieve a concrete result (drawing a cupboard). Do not over-rank practical instructions.\nRule B: The Science & Engineering Boundary\nObservational (Moderate): Habitats, Water Cycle, observable traits, simple definitions.\nMechanistic/Theoretical (Very): Engineering mechanics (how propulsion works via reaction), Instrumentation (using a spectroscope), or Chemical/Atomic theory.\nTest: Does the text explain how a machine functions using physical principles? If yes, it is Very Complex.\nRule C: The History/Social Studies Boundary\nGeneral/Narrative (Moderate):\nSensory: Battle descriptions focusing on sights/sounds (flashes, smoke).\nStandard Topics: Immigration, Slavery, Government, Geography. Lists of nationalities or religions are \"Common Knowledge\" for Grades 6-8.\nPolitical/Contextual (Very):\nImplicit Context: Texts assuming knowledge of specific political factions, treaties, or the causes of events without explanation (e.g., \"The Allies,\" \"The Front,\" \"The secularization of the clergy\").\nTest: If the reader must know why two groups are fighting or the specific political history of a revolution to understand the text, it is Very Complex.\nRule D: The \"Technical vs. Practical\" Trap\nScenario: A text teaches a technical skill (e.g., Technical Drawing/Technology) but applies it to a familiar object (a cupboard).\nDecision: Slightly Complex.\nReasoning: Do not confuse \"Technical Vocabulary\" (scale, thick lines) with \"Theoretical Complexity.\" If the underlying concept is familiar (furniture), the SMK load is low.\n\n3. Critical Calibration Examples\nText: \"Make a rough sketch... How many shelves should the cupboard have?\" (Grade 2) -> Slightly Complex.\nReasoning: (Rule D/Rule A) Although it mentions \"scale\" and \"technology,\" the task is concrete and relies on everyday knowledge.\nText: \"Hydraulic propulsion works by sucking water at the bow and forcing it sternward.\" (Grade 10) -> Very Complex.\nReasoning: (Rule B) Explains a mechanism using physics principles.\nText: \"The Allies fight the enemy's cavalry; we remember the hospitality to priests during the Revolution.\" (Grade 6) -> Very Complex.\nReasoning: (Rule C) Assumes undefined knowledge of WWI alliances and the specific political history of the French Revolution.\nText: \"Immigrants from Poland, Italy, and Russia arrived. Most were Catholic or Orthodox.\" (Grade 7) -> Moderately Complex.\nReasoning: (Rule C) Standard K-8 topic. Lists of nationalities are content vocabulary, not specialized theory.\n\n4. Output Format\nReturn your analysis in a valid JSON object. Do not include markdown formatting.\nKeys:\n- identified_topics: List[str] identifying the core subjects.\n- curriculum_check: String explaining if the topics are \"Standard/General\" (typical for K-8) or \"Specialized/High School\" (typical for 9-12).\n- assumptions_and_scaffolding: String analyzing what the author assumes the reader knows vs what is explained.\n- friction_analysis: String discussing the gap between Concrete description and Abstract meaning.\n- complexity_score: String (One of: slightly_complex, moderately_complex, very_complex, exceedingly_complex).\n- reasoning: String synthesizing the decision.\n\n","Analyze:\nText: {text}\nGrade: {grade}\nFK Score: {fk_score}","import SYSTEM_PROMPT from '../../../../../evals/prompts/subject-matter-knowledge/system.txt';\nimport USER_PROMPT_TEMPLATE from '../../../../../evals/prompts/subject-matter-knowledge/user.txt';\n\n/**\n * Get the SMK evaluator system prompt\n */\nexport function getSystemPrompt(): string {\n return SYSTEM_PROMPT;\n}\n\n/**\n * Generate the user prompt for SMK evaluation\n * @param text - The text to evaluate\n * @param grade - The target grade level\n * @param fkScore - Flesch-Kincaid grade level score\n */\nexport function getUserPrompt(text: string, grade: string, fkScore: number): string {\n return USER_PROMPT_TEMPLATE\n .replaceAll('{text}', text)\n .replaceAll('{grade}', grade)\n .replaceAll('{fk_score}', fkScore.toString());\n}\n","import type { LLMProvider } from '../providers/index.js';\nimport { SmkOutputSchema, type SmkInternal } from '../schemas/smk.js';\nimport { calculateFleschKincaidGrade } from '../features/index.js';\nimport { getSystemPrompt, getUserPrompt } from '../prompts/subject-matter-knowledge/index.js';\nimport type { EvaluationResult, TextComplexityLevel } from '../schemas/index.js';\nimport { BaseEvaluator, Provider, type BaseEvaluatorConfig } from './base.js';\nimport type { StageDetail } from '../telemetry/index.js';\nimport { ValidationError, wrapProviderError } from '../errors.js';\n\n/**\n * Subject Matter Knowledge (SMK) Evaluator\n *\n * Evaluates the background knowledge demands of educational texts relative to grade level.\n * Determines how much prior subject knowledge a student needs to comprehend the text.\n *\n * Based on the Common Core Qualitative Text Complexity Rubric with 4 levels:\n * - Slightly complex\n * - Moderately complex\n * - Very complex\n * - Exceedingly complex\n *\n * @example\n * ```typescript\n * const evaluator = new SmkEvaluator({\n * googleApiKey: process.env.GOOGLE_API_KEY\n * });\n *\n * const result = await evaluator.evaluate(text, \"6\");\n * console.log(result.score); // \"Moderately complex\"\n * console.log(result.reasoning);\n * ```\n */\nexport class SmkEvaluator extends BaseEvaluator {\n static readonly metadata = {\n id: 'subject-matter-knowledge',\n name: 'Subject Matter Knowledge',\n description: 'Evaluates background knowledge demands of educational texts relative to grade level',\n supportedGrades: ['3', '4', '5', '6', '7', '8', '9', '10', '11', '12'] as const,\n defaultProviders: [Provider.Google] as const,\n };\n\n private provider: LLMProvider;\n\n constructor(config: BaseEvaluatorConfig) {\n super(config);\n\n this.provider = this.createConfiguredProvider(\n Provider.Google, 'gemini-3-flash-preview', config.googleApiKey\n );\n }\n\n /**\n * Evaluate subject matter knowledge complexity for a given text and grade level\n *\n * @param text - The text to evaluate\n * @param grade - The target grade level (3-12)\n * @returns Evaluation result with complexity score and detailed analysis\n * @throws {ValidationError} If text is empty, too short/long, or grade is invalid\n * @throws {ConfigurationError} If modelOverride specifies a model ID that the provider rejects\n * @throws {APIError} If LLM API calls fail (includes AuthenticationError, RateLimitError, NetworkError, TimeoutError)\n */\n async evaluate(\n text: string,\n grade: string\n ): Promise<EvaluationResult<TextComplexityLevel, SmkInternal>> {\n this.logger.info('Starting SMK evaluation', {\n evaluator: 'subject-matter-knowledge',\n operation: 'evaluate',\n grade,\n textLength: text.length,\n });\n\n const startTime = Date.now();\n const stageDetails: StageDetail[] = [];\n\n try {\n // Validate inputs — inside try so validation errors are telemetered.\n this.validateText(text);\n this.validateGrade(grade, new Set(SmkEvaluator.metadata.supportedGrades));\n\n this.logger.debug('Evaluating subject matter knowledge complexity', {\n evaluator: 'subject-matter-knowledge',\n operation: 'smk_evaluation',\n });\n\n const fkScore = calculateFleschKincaidGrade(text);\n const response = await this.evaluateSmk(text, grade, fkScore);\n\n stageDetails.push({\n stage: 'smk_evaluation',\n provider: this.provider.label,\n latency_ms: response.latencyMs,\n token_usage: {\n input_tokens: response.usage.inputTokens,\n output_tokens: response.usage.outputTokens,\n },\n });\n\n const latencyMs = Date.now() - startTime;\n\n // Aggregate token usage\n const totalTokenUsage = {\n input_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.input_tokens || 0), 0),\n output_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.output_tokens || 0), 0),\n };\n\n const result = {\n score: response.data.complexity_score,\n reasoning: response.data.reasoning,\n metadata: {\n model: this.provider.label,\n processingTimeMs: latencyMs,\n },\n _internal: response.data,\n };\n\n // Send success telemetry (fire-and-forget)\n this.sendTelemetry({\n status: 'success',\n latencyMs,\n textLength: text.length,\n grade,\n provider: this.provider.label,\n tokenUsage: totalTokenUsage,\n metadata: {\n stage_details: stageDetails,\n },\n inputText: text,\n }).catch(() => {\n // Ignore telemetry errors\n });\n\n this.logger.info('SMK evaluation completed successfully', {\n evaluator: 'subject-matter-knowledge',\n operation: 'evaluate',\n grade,\n score: result.score,\n processingTimeMs: latencyMs,\n });\n\n return result;\n } catch (error) {\n const latencyMs = Date.now() - startTime;\n\n this.logger.error('SMK evaluation failed', {\n evaluator: 'subject-matter-knowledge',\n operation: 'evaluate',\n grade,\n error: error instanceof Error ? error : undefined,\n processingTimeMs: latencyMs,\n completedStages: stageDetails.length,\n });\n\n const totalTokenUsage = stageDetails.length > 0 ? {\n input_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.input_tokens || 0), 0),\n output_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.output_tokens || 0), 0),\n } : undefined;\n\n this.sendTelemetry({\n status: 'error',\n latencyMs,\n textLength: text.length,\n grade,\n provider: this.provider.label,\n tokenUsage: totalTokenUsage,\n errorCode: error instanceof Error ? error.name : 'UnknownError',\n metadata: stageDetails.length > 0 ? { stage_details: stageDetails } : undefined,\n inputText: text,\n }).catch(() => {\n // Ignore telemetry errors\n });\n\n if (error instanceof ValidationError) {\n throw error;\n }\n\n throw wrapProviderError(error, 'SMK evaluation failed');\n }\n }\n\n /**\n * Run the SMK evaluation LLM call\n */\n private async evaluateSmk(\n text: string,\n grade: string,\n fkScore: number\n ): Promise<{ data: SmkInternal; usage: { inputTokens: number; outputTokens: number }; latencyMs: number }> {\n const response = await this.provider.generateStructured({\n messages: [\n { role: 'system', content: getSystemPrompt() },\n { role: 'user', content: getUserPrompt(text, grade, fkScore) },\n ],\n schema: SmkOutputSchema,\n temperature: 0,\n });\n\n return {\n data: response.data,\n usage: response.usage,\n latencyMs: response.latencyMs,\n };\n }\n}\n\n/**\n * Functional API for SMK evaluation\n *\n * @example\n * ```typescript\n * const result = await evaluateSmk(\n * \"Hydraulic propulsion works by sucking water at the bow and forcing it sternward.\",\n * \"10\",\n * { googleApiKey: process.env.GOOGLE_API_KEY }\n * );\n * ```\n */\nexport async function evaluateSmk(\n text: string,\n grade: string,\n config: BaseEvaluatorConfig\n): Promise<EvaluationResult<TextComplexityLevel, SmkInternal>> {\n const evaluator = new SmkEvaluator(config);\n return evaluator.evaluate(text, grade);\n}\n","import { z } from 'zod';\nimport { TextComplexityLevel } from './outputs.js';\n\n/**\n * Conventionality evaluation output schema\n */\nexport const ConventionalityOutputSchema = z.object({\n conventionality_features: z.array(z.string()).describe('The specific language features driving the complexity (e.g., literal narrative, concrete actions, sustained irony, abstract qualities) with direct quotes from the text.'),\n grade_context: z.string().describe('How the conventionality demands compare to general expectations for the provided target grade.'),\n instructional_insights: z.string().describe('Actionable pedagogical suggestions for scaffolding the conventionality features in the classroom.'),\n complexity_score: TextComplexityLevel.describe('The conventionality complexity level of the text'),\n reasoning: z.string().describe('A detailed explanation of the rating, citing specific features in the text and referencing the expert guardrails.'),\n});\n\nexport type ConventionalityInternal = z.infer<typeof ConventionalityOutputSchema>;\n","Role\nYou are an expert reading teacher and text complexity evaluator. Your task is to evaluate the \"Conventionality\" of a text and assign it a complexity level based on a 4-point scale, carefully factoring in the target grade level.\n\nObjective\nMeasure how explicit, literal, and straightforward the text's meaning is, versus how abstract, ironic, figurative, or archaic it is. Focus on the hiddenness of the meaning, the use of conceptual framing, the reliance on abstract reasoning, and the familiarity of the expression for the target grade.\n\nComplexity Levels\n- Slightly Complex: Explicit, literal, straightforward, easy to understand. Meaning is entirely on the surface. The language is concrete, and the meaning is clear and procedural, mostly referring to observable materials and actions. Contains no symbolic or ironic language, and conceptual interpretation is not required. Contains limited figurative language that is common and easy to comprehend at the target grade level.\n- Moderately Complex: Largely explicit and easy to understand with some occasions for more complex meaning. May contain a noticeable amount of archaic/dated phrasing, formal historical prose, vocabulary demands, background knowledge requirements, or expressions that are less familiar to the target grade level, which might make the text feel vague or slightly challenging.\n- Very Complex: Fairly complex; contains sustained abstract language, conceptual framing, rhetorical idealization, ironic comparisons, or central metaphors that drive the meaning of the text. Addresses concepts, beliefs, and abstract qualities rather than just concrete objects. The tone or underlying message requires interpretation, even if the surface message is clear.\n- Exceedingly Complex: Dense and complex; contains considerable abstract, ironic, and/or figurative language. Meaning is heavily hidden, deeply conceptual, or relies heavily on complex rhetorical devices.\n\nEssential Evaluation Rules\n1. Concrete & Procedural Texts: Texts that are highly concrete, clear, and procedural (e.g., describing observable materials, mechanical processes, or physical actions) should typically be rated \"Slightly Complex.\"\n\n2. Grade-Level Anchoring and Vague Narratives: Always consider the target grade. A literal historical narrative that might be straightforward for older students can be \"Moderately Complex\" for younger students (e.g., 4th graders) if it involves less familiar expressions, older contexts (e.g., wagon loads, traveling by horseback), vocabulary demands, and background knowledge requirements that make the text feel vague or slightly demanding for that age group.\n\n3. Rhetorical Idealization and Abstract Qualities: If an entire argument or narrative is built around abstract qualities (e.g., national character, bravery, liberty) and uses repeated figurative language or personification to portray a subject in a certain idealized way, rate the text as \"Very Complex.\" Even if the figurative language is easy to interpret, the need to interpret the rhetorical tone and sustained abstract focus elevates the complexity beyond level two.\n\n4. Common Idioms and Grade-Level Appropriateness: Do NOT elevate a text to \"Moderately Complex\" simply because it contains a few common idiomatic expressions. If these expressions are widely known and easy for the target grade to understand without making the text feel vague, the text remains \"Slightly Complex.\"\n\n5. Conversational and Hypothetical Framing: Using a second-person conversational hook (e.g., \"Imagine you are...\") to explain a concept is a standard, literal device for engaging readers. It does not constitute complex conceptual framing.\n\n6. Sustained vs. Occasional Impact: If abstract language, figurative phrasing, irony, or conceptual framing is sustained throughout the text and central to the argument/meaning, the text is Very Complex. Reserve Moderately Complex for texts where the explicit meaning dominates but the expression, vocabulary, or archaic language provides a moderate conventionality challenge.\n\n7. Central Metaphors and Conceptual Framing: When an author uses a central metaphor to explain a concept or uses figurative phrasing to explain how things \"work,\" this abstract reasoning drives the meaning, elevating the text to Very Complex.\n\n8. Irony and Abstract Comparisons: Texts that rely on sustained irony, especially through comparative arguments, are inherently Very Complex for younger students.\n\n9. Isolate Conventionality from Vocabulary: Do not inflate the Conventionality score just because the text uses archaic, dated, or highly academic vocabulary. \n\nInput Format\nYou will receive:\n- text: The passage to evaluate.\n- grade_level: The target student grade level.\n- fk_score: The Flesch-Kincaid readability score.\n\nOutput Format\nProvide a JSON object containing ONLY the following keys:\n- complexity_score: (String) One of the 4 scale levels exactly as formatted: 'slightly_complex', 'moderately_complex', 'very_complex', or 'exceedingly_complex'.\n- reasoning: (String) A detailed explanation of the rating, citing specific features in the text and referencing the expert guardrails (e.g., noting if the text relies on abstract qualities/rhetorical idealization, if vocabulary/background knowledge demands make a literal text vague for the grade level, or if it is strictly concrete/procedural).\n- conventionality_features: (List of Strings) The specific language features driving the complexity (e.g., literal narrative, concrete actions, less familiar expressions, sustained irony, abstract qualities, rhetorical idealization, archaic phrasing) with direct quotes from the text.\n- grade_context: (String) How the conventionality demands compare to general expectations for the provided target grade.\n- instructional_insights: (String) Actionable pedagogical suggestions for scaffolding the conventionality features in the classroom.","Analyze:\nText: {text}\nGrade: {grade}\nFK Score: {fk_score}","import SYSTEM_PROMPT from '../../../../../evals/prompts/conventionality/system.txt';\nimport USER_PROMPT_TEMPLATE from '../../../../../evals/prompts/conventionality/user.txt';\n\n/**\n * Get the Conventionality evaluator system prompt\n */\nexport function getSystemPrompt(): string {\n return SYSTEM_PROMPT;\n}\n\n/**\n * Generate the user prompt for Conventionality evaluation\n * @param text - The text to evaluate\n * @param grade - The target grade level\n * @param fkScore - Flesch-Kincaid grade level score\n */\nexport function getUserPrompt(text: string, grade: string, fkScore: number): string {\n return USER_PROMPT_TEMPLATE\n .replaceAll('{text}', text)\n .replaceAll('{grade}', grade)\n .replaceAll('{fk_score}', fkScore.toString());\n}\n","import type { LLMProvider } from '../providers/index.js';\nimport { ConventionalityOutputSchema, type ConventionalityInternal } from '../schemas/conventionality.js';\nimport { calculateFleschKincaidGrade } from '../features/index.js';\nimport { getSystemPrompt, getUserPrompt } from '../prompts/conventionality/index.js';\nimport type { EvaluationResult, TextComplexityLevel } from '../schemas/index.js';\nimport { BaseEvaluator, Provider, type BaseEvaluatorConfig } from './base.js';\nimport type { StageDetail } from '../telemetry/index.js';\nimport { ValidationError, wrapProviderError } from '../errors.js';\n\n/**\n * Conventionality Evaluator\n *\n * Evaluates how explicit, literal, and straightforward a text's meaning is versus\n * how abstract, ironic, figurative, or archaic it is for the target grade level.\n *\n * Based on the Common Core Qualitative Text Complexity Rubric with 4 levels:\n * - Slightly complex\n * - Moderately complex\n * - Very complex\n * - Exceedingly complex\n *\n * @example\n * ```typescript\n * const evaluator = new ConventionalityEvaluator({\n * googleApiKey: process.env.GOOGLE_API_KEY\n * });\n *\n * const result = await evaluator.evaluate(text, \"6\");\n * console.log(result.score); // \"Moderately complex\"\n * console.log(result.reasoning);\n * ```\n */\nexport class ConventionalityEvaluator extends BaseEvaluator {\n static readonly metadata = {\n id: 'conventionality',\n name: 'Conventionality',\n description: 'Evaluates how explicit, literal, and straightforward a text\\'s meaning is relative to grade level',\n supportedGrades: ['3', '4', '5', '6', '7', '8', '9', '10', '11', '12'] as const,\n defaultProviders: [Provider.Google] as const,\n };\n\n private provider: LLMProvider;\n\n constructor(config: BaseEvaluatorConfig) {\n super(config);\n\n this.provider = this.createConfiguredProvider(\n Provider.Google, 'gemini-3-flash-preview', config.googleApiKey\n );\n }\n\n /**\n * Evaluate conventionality complexity for a given text and grade level\n *\n * @param text - The text to evaluate\n * @param grade - The target grade level (3-12)\n * @returns Evaluation result with complexity score and detailed analysis\n * @throws {ValidationError} If text is empty, too short/long, or grade is invalid\n * @throws {ConfigurationError} If modelOverride specifies a model ID that the provider rejects\n * @throws {APIError} If LLM API calls fail (includes AuthenticationError, RateLimitError, NetworkError, TimeoutError)\n */\n async evaluate(\n text: string,\n grade: string\n ): Promise<EvaluationResult<TextComplexityLevel, ConventionalityInternal>> {\n this.logger.info('Starting Conventionality evaluation', {\n evaluator: 'conventionality',\n operation: 'evaluate',\n grade,\n textLength: text.length,\n });\n\n const startTime = Date.now();\n const stageDetails: StageDetail[] = [];\n\n try {\n // Validate inputs — inside try so validation errors are telemetered.\n this.validateText(text);\n this.validateGrade(grade, new Set(ConventionalityEvaluator.metadata.supportedGrades));\n\n this.logger.debug('Evaluating conventionality complexity', {\n evaluator: 'conventionality',\n operation: 'conventionality_evaluation',\n });\n\n const fkScore = calculateFleschKincaidGrade(text);\n const response = await this.evaluateConventionality(text, grade, fkScore);\n\n stageDetails.push({\n stage: 'conventionality_evaluation',\n provider: this.provider.label,\n latency_ms: response.latencyMs,\n token_usage: {\n input_tokens: response.usage.inputTokens,\n output_tokens: response.usage.outputTokens,\n },\n });\n\n const latencyMs = Date.now() - startTime;\n\n // Aggregate token usage\n const totalTokenUsage = {\n input_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.input_tokens || 0), 0),\n output_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.output_tokens || 0), 0),\n };\n\n const result = {\n score: response.data.complexity_score,\n reasoning: response.data.reasoning,\n metadata: {\n model: this.provider.label,\n processingTimeMs: latencyMs,\n },\n _internal: response.data,\n };\n\n // Send success telemetry (fire-and-forget)\n this.sendTelemetry({\n status: 'success',\n latencyMs,\n textLength: text.length,\n grade,\n provider: this.provider.label,\n tokenUsage: totalTokenUsage,\n metadata: {\n stage_details: stageDetails,\n },\n inputText: text,\n }).catch(() => {\n // Ignore telemetry errors\n });\n\n this.logger.info('Conventionality evaluation completed successfully', {\n evaluator: 'conventionality',\n operation: 'evaluate',\n grade,\n score: result.score,\n processingTimeMs: latencyMs,\n });\n\n return result;\n } catch (error) {\n const latencyMs = Date.now() - startTime;\n\n this.logger.error('Conventionality evaluation failed', {\n evaluator: 'conventionality',\n operation: 'evaluate',\n grade,\n error: error instanceof Error ? error : undefined,\n processingTimeMs: latencyMs,\n completedStages: stageDetails.length,\n });\n\n const totalTokenUsage = stageDetails.length > 0 ? {\n input_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.input_tokens || 0), 0),\n output_tokens: stageDetails.reduce((sum, s) => sum + (s.token_usage?.output_tokens || 0), 0),\n } : undefined;\n\n this.sendTelemetry({\n status: 'error',\n latencyMs,\n textLength: text.length,\n grade,\n provider: this.provider.label,\n tokenUsage: totalTokenUsage,\n errorCode: error instanceof Error ? error.name : 'UnknownError',\n metadata: stageDetails.length > 0 ? { stage_details: stageDetails } : undefined,\n inputText: text,\n }).catch(() => {\n // Ignore telemetry errors\n });\n\n if (error instanceof ValidationError) {\n throw error;\n }\n\n throw wrapProviderError(error, 'Conventionality evaluation failed');\n }\n }\n\n /**\n * Run the Conventionality evaluation LLM call\n */\n private async evaluateConventionality(\n text: string,\n grade: string,\n fkScore: number\n ): Promise<{ data: ConventionalityInternal; usage: { inputTokens: number; outputTokens: number }; latencyMs: number }> {\n const response = await this.provider.generateStructured({\n messages: [\n { role: 'system', content: getSystemPrompt() },\n { role: 'user', content: getUserPrompt(text, grade, fkScore) },\n ],\n schema: ConventionalityOutputSchema,\n temperature: 0,\n });\n\n return {\n data: response.data,\n usage: response.usage,\n latencyMs: response.latencyMs,\n };\n }\n}\n\n/**\n * Functional API for Conventionality evaluation\n *\n * @example\n * ```typescript\n * const result = await evaluateConventionality(\n * \"The author uses sustained irony to critique societal norms.\",\n * \"10\",\n * { googleApiKey: process.env.GOOGLE_API_KEY }\n * );\n * ```\n */\nexport async function evaluateConventionality(\n text: string,\n grade: string,\n config: BaseEvaluatorConfig\n): Promise<EvaluationResult<TextComplexityLevel, ConventionalityInternal>> {\n const evaluator = new ConventionalityEvaluator(config);\n return evaluator.evaluate(text, grade);\n}\n","// GENERATED — do not edit directly.\n// Source: ../../evals/prompts/purpose/output_schema.json\n// Regenerate: npm run generate:schemas\n\nimport { z } from 'zod';\n\n// prettier-ignore\nexport const PurposeOutputSchema = z.object({ \"complexity_score\": z.enum([\"slightly_complex\",\"moderately_complex\",\"very_complex\",\"exceedingly_complex\",\"more_context_needed\"]).describe(\"The Purpose complexity level for the target grade.\"), \"reasoning\": z.string().describe(\"A high-level summary of why the text is at this complexity level for the target grade.\"), \"details\": z.object({ \"detailed_summary\": z.array(z.object({ \"factor\": z.string().describe(\"The specific text complexity factor identified.\"), \"description\": z.string().describe(\"How this factor manifests in the text.\"), \"effect_on_complexity_dimension\": z.string().describe(\"How this factor affects the reader's ability to understand the text's specific complexity dimension.\") }).strict()).describe(\"Individual complexity factors with descriptions and their effects.\"), \"adjustment_and_scaffolding\": z.array(z.object({ \"scaffolding_need\": z.string().describe(\"The complexity factor that requires scaffolding.\"), \"suggestion\": z.string().describe(\"A specific instructional strategy to support students with this factor.\") }).strict()).describe(\"Scaffolding strategies to make the text accessible at the target grade.\"), \"recommended_use_cases\": z.array(z.object({ \"opportunity\": z.string().describe(\"An instructional opportunity related to the text.\"), \"suggestion\": z.string().describe(\"A specific way to leverage this text for that instructional purpose.\") }).strict()).describe(\"Additional instructional opportunities for using this text.\") }).strict().describe(\"Practical instructional details including scaffolding strategies and recommended use cases.\") }).strict();\n\nexport type PurposeInternal = z.infer<typeof PurposeOutputSchema>;\n","\n Role\n You are an expert reading assessment evaluator. Your task is to determine the Text Complexity of a given passage based exclusively on the Purpose dimension of the qualitative measures rubric.\n\n Task Details\n You will be provided with an informational or literary `text`, along with its `grade_level` and `fk_score` (Flesch-Kincaid). You must analyze the text and determine how difficult it is for a reader to identify the author's purpose. \n\n Crucially, you must distinguish between the text's *topic* (what it is about) and its *purpose* (why the author wrote it). \n\n Rubric: Purpose Complexity\n Exceedingly Complex: Subtle and intricate, difficult to determine; includes many theoretical or abstract elements.\n Very Complex: Implicit or subtle but fairly easy to infer; more theoretical or abstract than concrete.\n Moderately Complex: Implied but easy to identify based upon context or source.\n Slightly Complex: Explicitly stated, clear, concrete, narrowly focused.\n More Context Needed: The text is a fragment or lacks necessary introductory context, making the true purpose impossible to determine accurately without external background knowledge.\n\n Expert Rules for Evaluating Purpose\n Based on expert consensus and historical grading corrections, you must apply the following heuristics:\n\n 1. The \"Slightly Complex\" Benchmark (Straightforward and Explicit)\n A text is Slightly Complex if its purpose is explicitly stated or if its informative intent is straightforward, clear, concrete, and directly answers what the text is immediately about. If the text opens by clearly identifying a concrete topic (e.g., \"Pins are made of either brass or iron wire\") and rigidly follows through by explaining factual, practical information or a process (like manufacturing steps or geographic facts), the purpose is considered explicit and straightforward. It does *not* require a literal statement like \"The purpose of this text is to...\" as long as the delivery of information is direct, clear, and unadorned by persuasive elements or complex framing.\n\n 2. Moderately Complex via Guiding Questions & Inquiry Formats\n If a text begins with a general introduction and uses guiding questions (e.g., \"Have you ever wondered how clouds are formed?\") to transition into an explanation, the purpose is implied rather than explicitly stated upfront. Because the reader must recognize the question as the pivot point for the author's intent, it is Moderately Complex.\n\n 3. Moderately Complex via Multiple Distinct Informational Goals\n If a text covers a broad topic but jumps between several distinct scientific or informational objectives without an overarching framing device or explicit thesis (e.g., talking about measuring ice sheets, then mapping, then finding meteorites), the reader must synthesize these diverse facts to recognize the broader purpose, making it Moderately Complex.\n\n 4. Moderately Complex via Arguments Disguised as Information\n If an author is arguing a specific point, correcting a misconception, or defending a stance, but the text could initially be mistaken by students as purely informative factual text, it is Moderately Complex. The reader must infer the persuasive intent or argumentative purpose beneath the informative tone.\n\n 5. \"More Context Needed\" for Fragments\n If a text is a fragment missing a crucial introduction or context, and identifying the author's purpose beyond a simple surface-level description would be exceptionally difficult for a reader in the target grade level without that external background, score it as `more_context_needed`. \n\n Output Format\n Provide your evaluation in the following structure:\n reasoning:\n - Surface Analysis: Identify if the text clearly identifies its topic and delivers straightforward facts, or if it utilizes structural cues, titles, or direct thesis statements.\n - Subtlety & Framing: Is the informative purpose straightforward and concrete? Does it use guiding questions? Is it an argument disguised as pure information? Are there multiple distinct informational goals requiring synthesis?\n - Context Check: Is this text a fragment missing crucial context that obscures the deeper purpose for the target grade level?\n - Rubric Alignment: Explain how the text aligns with the specific language of the rubric, explicitly referencing the expert rules above. Justify why it isn't one level simpler or more complex.\n\n answer:\n - complexity_score: (slightly_complex, moderately_complex, very_complex, exceedingly_complex, more_context_needed)\n - reasoning: A brief summary of your final decision.\n - details: Structured breakdown of PurposeDetails including detailed_summary, adjustment_and_scaffolding, and recommended_use_cases.\n","Analyze:\nText: {text}\nGrade: {grade_level}\nFK Score: {fk_score}","{\n \"spec_version\": \"1.0\",\n \"evaluator\": {\n \"id\": \"literacy.gla.purpose\",\n \"name\": \"Purpose Dimension Text Complexity Evaluator\",\n \"description\": \"Evaluates the Purpose dimension of qualitative text complexity for K-12 reading assessment, producing a 5-level rubric rating with structured pedagogical detail.\"\n },\n \"input_schema\": {\n \"$ref\": \"input_schema.json\"\n },\n \"preprocessing\": [\n {\n \"id\": \"fk_score\",\n \"kind\": \"flesch_kincaid_grade\",\n \"description\": \"Compute the Flesch-Kincaid Grade Level for the input text and bind it to {fk_score} in the prompt.\",\n \"input\": \"text\",\n \"output\": \"fk_score\",\n \"implementation\": {\n \"python\": {\n \"library\": \"textstat\",\n \"function\": \"flesch_kincaid_grade\",\n \"post_transform\": {\n \"type\": \"round\",\n \"precision\": 2\n }\n },\n \"typescript\": {\n \"library\": \"text-readability\",\n \"function\": \"fleschKincaidGrade\",\n \"post_transform\": {\n \"type\": \"round\",\n \"precision\": 2\n }\n }\n }\n }\n ],\n \"steps\": [\n {\n \"id\": \"evaluate_purpose\",\n \"description\": \"Single-call LLM step that produces the EvaluatorOutput JSON.\",\n \"prompt\": {\n \"type\": \"chat\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"source_path\": \"system.txt\",\n \"sha256\": \"745b95b7d54dc845b99363c9d3360355381883c22a5f6a0f305d7349cae38a54\"\n },\n {\n \"role\": \"user\",\n \"source_path\": \"user.txt\",\n \"sha256\": \"cd8e6347db1a55d104e34436f8f66e833bd6583645d4786a554aaefdd26479b2\"\n }\n ],\n \"placeholders\": {\n \"text\": {\n \"required\": true,\n \"source\": \"input\"\n },\n \"grade_level\": {\n \"required\": true,\n \"source\": \"input\"\n },\n \"fk_score\": {\n \"required\": true,\n \"source\": \"preprocessing.fk_score\"\n }\n }\n },\n \"model\": {\n \"provider\": \"google\",\n \"name\": \"gemini-3-flash-preview\"\n },\n \"generation\": {\n \"temperature\": 0\n },\n \"parser\": {\n \"kind\": \"structured_output\"\n },\n \"output_binding\": \"formatted_output\"\n }\n ],\n \"output_schema\": {\n \"$ref\": \"output_schema.json\"\n },\n \"fixtures\": {\n \"sniff_test_path\": \"fixtures.json\",\n \"tolerance\": {\n \"allow_adjacent_levels\": true,\n \"notes\": \"If allow_adjacent_levels is true, predictions within one rubric step of the expected label count as a pass. Slightly Complex < Moderately Complex < Very Complex < Exceedingly Complex; more_context_needed has no adjacency.\"\n },\n \"schema\": {\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"fixtures_schema.json\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\n \"id\",\n \"input\",\n \"expected\"\n ],\n \"additionalProperties\": false,\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"description\": {\n \"type\": \"string\"\n },\n \"source\": {\n \"type\": \"string\",\n \"description\": \"Optional provenance label (e.g., the source CSV or dataset). Not required.\"\n },\n \"input\": {\n \"$ref\": \"input_schema.json\"\n },\n \"expected\": {\n \"type\": \"object\",\n \"required\": [\n \"complexity_level\"\n ],\n \"additionalProperties\": false,\n \"properties\": {\n \"complexity_level\": {\n \"$ref\": \"output_schema.json#/properties/complexity_score\",\n \"description\": \"Expected complexity rating for this fixture. Renamed from the runtime field 'complexity_score' for clarity in the test file -- only the level itself is being tested; reasoning is non-deterministic across LLM runs.\"\n }\n }\n }\n }\n }\n }\n }\n}\n","import SYSTEM_PROMPT from '../../../../../evals/prompts/purpose/system.txt';\nimport USER_PROMPT_TEMPLATE from '../../../../../evals/prompts/purpose/user.txt';\nimport CONFIG from '../../../../../evals/prompts/purpose/config.json';\n\nconst STEP_ID = `evaluate_${CONFIG.evaluator.id.split('.').pop()}`;\nconst _step = CONFIG.steps.find(s => s.id === STEP_ID);\nif (!_step) throw new Error(`Step \"${STEP_ID}\" not found in purpose config.json`);\nconst PLACEHOLDER_KEYS = Object.keys(_step.prompt.placeholders);\n\nfunction applyPlaceholders(template: string, inputs: Record<string, string>): string {\n return PLACEHOLDER_KEYS.reduce(\n (text, key) => key in inputs ? text.replaceAll(`{${key}}`, inputs[key]) : text,\n template,\n );\n}\n\nexport function getSystemPrompt(inputs: Record<string, string>): string {\n return applyPlaceholders(SYSTEM_PROMPT, inputs);\n}\n\nexport function getUserPrompt(inputs: Record<string, string>): string {\n return applyPlaceholders(USER_PROMPT_TEMPLATE, inputs);\n}\n","{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"input_schema.json\",\n \"title\": \"EvaluatorInput\",\n \"type\": \"object\",\n \"required\": [\"text\", \"grade_level\"],\n \"additionalProperties\": false,\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"The passage to evaluate.\"\n },\n \"grade_level\": {\n \"type\": \"integer\",\n \"minimum\": 3,\n \"maximum\": 12,\n \"description\": \"Target student grade level.\"\n }\n }\n}\n","import type { LLMProvider } from '../providers/index.js';\nimport { PurposeOutputSchema, type PurposeInternal } from '../schemas/purpose.js';\nimport { runPreprocessingStep } from '../features/preprocessing.js';\nimport { getSystemPrompt, getUserPrompt } from '../prompts/purpose/index.js';\nimport type { EvaluationResult, TextComplexityLevel } from '../schemas/index.js';\nimport { BaseEvaluator, Provider, type BaseEvaluatorConfig } from './base.js';\nimport type { StageDetail } from '../telemetry/index.js';\nimport { ValidationError, wrapProviderError } from '../errors.js';\nimport CONFIG from '../../../../evals/prompts/purpose/config.json';\nimport INPUT_SCHEMA from '../../../../evals/prompts/purpose/input_schema.json';\n\n// Step ID convention: \"evaluate_{slug}\" where slug is the last segment of evaluator.id.\nconst STEP_ID = `evaluate_${CONFIG.evaluator.id.split('.').pop()}`;\nconst _step = CONFIG.steps.find(s => s.id === STEP_ID);\nif (!_step) throw new Error(`Step \"${STEP_ID}\" not found in purpose config.json`);\nconst STEP = _step;\n\n// Grade range from input_schema — needed for static metadata, so defined at module level.\nconst GRADE_MIN = INPUT_SCHEMA.properties.grade_level.minimum;\nconst GRADE_MAX = INPUT_SCHEMA.properties.grade_level.maximum;\nconst SUPPORTED_GRADES = Array.from({ length: GRADE_MAX - GRADE_MIN + 1 }, (_, i) => String(GRADE_MIN + i));\n\nexport type PurposeComplexityLevel = TextComplexityLevel | 'More context needed';\n\n// Maps snake_case LLM output → SDK-standard sentence case score.\nconst COMPLEXITY_SCORE_DISPLAY: Record<PurposeInternal['complexity_score'], PurposeComplexityLevel> = {\n 'slightly_complex': 'Slightly complex',\n 'moderately_complex': 'Moderately complex',\n 'very_complex': 'Very complex',\n 'exceedingly_complex': 'Exceedingly complex',\n 'more_context_needed': 'More context needed',\n};\n\nexport class PurposeEvaluator extends BaseEvaluator {\n static readonly metadata = {\n id: CONFIG.evaluator.id,\n name: CONFIG.evaluator.name,\n description: CONFIG.evaluator.description,\n supportedGrades: SUPPORTED_GRADES,\n defaultProviders: [Provider.Google] as const,\n };\n\n private static readonly TEMPERATURE = STEP.generation.temperature;\n\n private static computeFkScore(text: string): number {\n const fkStep = CONFIG.preprocessing.find(p => p.id === 'fk_score');\n if (!fkStep) throw new Error('fk_score preprocessing step not found in purpose config.json');\n return runPreprocessingStep(text, fkStep.implementation.typescript);\n }\n\n private provider: LLMProvider;\n\n constructor(config: BaseEvaluatorConfig) {\n super(config);\n\n this.provider = this.createConfiguredProvider(\n Provider.Google, STEP.model.name, config.googleApiKey\n );\n }\n\n /**\n * Evaluate purpose complexity for a given text and grade level\n *\n * @param text - The text to evaluate\n * @param grade - The target grade level (3-12)\n * @returns Evaluation result with complexity score and detailed analysis\n * @throws {ValidationError} If text is empty, too short/long, or grade is invalid\n * @throws {ConfigurationError} If modelOverride specifies a model ID that the provider rejects\n * @throws {APIError} If LLM API calls fail (includes AuthenticationError, RateLimitError, NetworkError, TimeoutError)\n */\n async evaluate(text: string, grade: string): Promise<EvaluationResult<PurposeComplexityLevel, PurposeInternal>> {\n this.logger.info('Starting Purpose evaluation', {\n evaluator: PurposeEvaluator.metadata.id,\n operation: 'evaluate',\n grade,\n textLength: text.length,\n });\n\n const startTime = Date.now();\n const stageDetails: StageDetail[] = [];\n\n try {\n this.validateText(text);\n const gradeNum = this.parseAndValidateGrade(grade);\n\n const fkScore = PurposeEvaluator.computeFkScore(text);\n const inputs: Record<string, string> = {\n text,\n grade_level: String(gradeNum),\n fk_score: String(fkScore),\n };\n const response = await this.callLLM(inputs);\n\n const latencyMs = Date.now() - startTime;\n const tokenUsage = {\n input_tokens: response.usage.inputTokens,\n output_tokens: response.usage.outputTokens,\n };\n\n stageDetails.push({\n stage: STEP.id,\n provider: this.provider.label,\n latency_ms: response.latencyMs,\n token_usage: tokenUsage,\n });\n\n const result: EvaluationResult<PurposeComplexityLevel, PurposeInternal> = {\n score: COMPLEXITY_SCORE_DISPLAY[response.data.complexity_score],\n reasoning: response.data.reasoning,\n metadata: {\n model: this.provider.label,\n processingTimeMs: latencyMs,\n },\n _internal: response.data,\n };\n\n this.sendTelemetry({\n status: 'success',\n latencyMs,\n textLength: text.length,\n grade: String(gradeNum),\n provider: this.provider.label,\n tokenUsage,\n metadata: { stage_details: stageDetails },\n inputText: text,\n }).catch(() => undefined);\n\n this.logger.info('Purpose evaluation completed successfully', {\n evaluator: PurposeEvaluator.metadata.id,\n operation: 'evaluate',\n grade: gradeNum,\n score: result.score,\n processingTimeMs: latencyMs,\n });\n\n return result;\n } catch (error) {\n const latencyMs = Date.now() - startTime;\n\n this.logger.error('Purpose evaluation failed', {\n evaluator: PurposeEvaluator.metadata.id,\n operation: 'evaluate',\n grade,\n error: error instanceof Error ? error : undefined,\n processingTimeMs: latencyMs,\n });\n\n const tokenUsage = stageDetails.length > 0\n ? {\n input_tokens: stageDetails.reduce((s, d) => s + (d.token_usage?.input_tokens ?? 0), 0),\n output_tokens: stageDetails.reduce((s, d) => s + (d.token_usage?.output_tokens ?? 0), 0),\n }\n : undefined;\n\n this.sendTelemetry({\n status: 'error',\n latencyMs,\n textLength: text.length,\n grade: String(grade),\n provider: this.provider.label,\n tokenUsage,\n errorCode: error instanceof Error ? error.name : 'UnknownError',\n metadata: stageDetails.length > 0 ? { stage_details: stageDetails } : undefined,\n inputText: text,\n }).catch(() => undefined);\n\n if (error instanceof ValidationError) throw error;\n throw wrapProviderError(error, 'Purpose evaluation failed');\n }\n }\n\n private parseAndValidateGrade(grade: string): number {\n const num = Number(grade.trim());\n if (!Number.isInteger(num) || num < GRADE_MIN || num > GRADE_MAX) {\n throw new ValidationError(\n `Invalid grade \"${grade}\". Purpose evaluator supports integer grades ${GRADE_MIN}–${GRADE_MAX}.`,\n );\n }\n return num;\n }\n\n private async callLLM(\n inputs: Record<string, string>,\n ): Promise<{ data: PurposeInternal; usage: { inputTokens: number; outputTokens: number }; latencyMs: number }> {\n const response = await this.provider.generateStructured({\n messages: [\n { role: 'system', content: getSystemPrompt(inputs) },\n { role: 'user', content: getUserPrompt(inputs) },\n ],\n schema: PurposeOutputSchema,\n temperature: PurposeEvaluator.TEMPERATURE,\n });\n\n return { data: response.data, usage: response.usage, latencyMs: response.latencyMs };\n }\n}\n\nexport async function evaluatePurpose(\n text: string,\n grade: string,\n config: BaseEvaluatorConfig,\n): Promise<EvaluationResult<PurposeComplexityLevel, PurposeInternal>> {\n return new PurposeEvaluator(config).evaluate(text, grade);\n}\n","import pLimit from 'p-limit';\nimport {\n VocabularyEvaluator,\n SentenceStructureEvaluator,\n GradeLevelAppropriatenessEvaluator,\n SmkEvaluator,\n ConventionalityEvaluator,\n PurposeEvaluator,\n} from '../evaluators/index.js';\nimport type { BaseEvaluatorConfig } from '../evaluators/base.js';\nimport type { EvaluationResult } from '../schemas/index.js';\nimport type {\n BatchInput,\n BatchTask,\n BatchResult,\n BatchOutput,\n BatchConfig,\n BatchSummary,\n EvaluatorGroup,\n} from './types.js';\n\ninterface SimpleEvaluator {\n evaluate(text: string, grade: string): Promise<EvaluationResult<string, unknown>>;\n}\n\ntype EvaluatorConstructor = new (config: BaseEvaluatorConfig) => SimpleEvaluator;\n\n/**\n * Map of evaluator IDs to their constructors — internal to this module.\n */\nconst EVALUATOR_MAP = new Map<string, EvaluatorConstructor>([\n [GradeLevelAppropriatenessEvaluator.metadata.id, GradeLevelAppropriatenessEvaluator],\n [SmkEvaluator.metadata.id, SmkEvaluator],\n [VocabularyEvaluator.metadata.id, VocabularyEvaluator],\n [SentenceStructureEvaluator.metadata.id, SentenceStructureEvaluator],\n [ConventionalityEvaluator.metadata.id, ConventionalityEvaluator],\n [PurposeEvaluator.metadata.id, PurposeEvaluator],\n]);\n\n/**\n * Evaluator groups available for batch processing.\n * Each group runs a fixed set of evaluators and maps to a specific HTML report format.\n */\n// Note: this batch group is a superset of TextComplexityEvaluator — it also includes\n// GradeLevelAppropriateness and Purpose (early access), which the programmatic evaluator\n// does not expose. This is intentional: the batch surface evolves independently.\nconst EVALUATOR_GROUPS: EvaluatorGroup[] = [\n {\n id: 'text-complexity',\n name: 'Text Complexity Analysis',\n description: 'Evaluates all dimensions of the Qualitative Text Complexity rubric',\n evaluatorIds: [\n GradeLevelAppropriatenessEvaluator.metadata.id,\n SmkEvaluator.metadata.id,\n VocabularyEvaluator.metadata.id,\n SentenceStructureEvaluator.metadata.id,\n ConventionalityEvaluator.metadata.id,\n PurposeEvaluator.metadata.id,\n ],\n requiresGoogleKey: true,\n requiresOpenAIKey: true,\n maxInputRows: 50,\n },\n];\n\n/**\n * Returns the available evaluator groups.\n */\nexport function getAvailableGroups(): EvaluatorGroup[] {\n return [...EVALUATOR_GROUPS];\n}\n\n/**\n * Batch evaluator class\n *\n * Processes multiple texts in parallel using all evaluators in a group.\n */\nexport class BatchEvaluator {\n private config: BatchConfig;\n private limit: ReturnType<typeof pLimit>;\n private evaluatorInstances = new Map<string, SimpleEvaluator>();\n private isCancelled = false;\n private completedResults: BatchResult[] = [];\n\n constructor(config: BatchConfig) {\n this.config = {\n concurrency: 3,\n maxRetries: 2,\n telemetry: false,\n ...config,\n };\n\n this.limit = pLimit(this.config.concurrency!);\n }\n\n /**\n * Cancel ongoing evaluation.\n * Returns partial results collected so far.\n */\n cancel(): BatchResult[] {\n this.isCancelled = true;\n return [...this.completedResults];\n }\n\n /**\n * Initialize evaluator instances for the given IDs\n */\n private initializeEvaluators(evaluatorIds: readonly string[]): void {\n for (const id of evaluatorIds) {\n if (this.evaluatorInstances.has(id)) continue;\n\n const EvaluatorClass = EVALUATOR_MAP.get(id);\n if (!EvaluatorClass) {\n throw new Error(`Unknown evaluator: ${id}`);\n }\n\n const evaluator = new EvaluatorClass({\n googleApiKey: this.config.googleApiKey,\n openaiApiKey: this.config.openaiApiKey,\n maxRetries: this.config.maxRetries,\n telemetry: this.config.telemetry,\n });\n\n this.evaluatorInstances.set(id, evaluator);\n }\n }\n\n /**\n * Create tasks from inputs and evaluator IDs\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private createTasks(inputs: BatchInput[], evaluatorIds: readonly string[]): Array<BatchTask & { originalRow: Record<string, unknown> }> {\n const tasks: Array<BatchTask & { originalRow: Record<string, unknown> }> = [];\n\n for (const input of inputs) {\n for (const evaluatorId of evaluatorIds) {\n tasks.push({\n text: input.text,\n grade: input.grade,\n evaluatorId,\n rowIndex: input.rowIndex,\n originalRow: input.originalRow,\n });\n }\n }\n\n return tasks;\n }\n\n /**\n * Execute a single evaluation task\n */\n private async executeTask(\n task: BatchTask & { originalRow: Record<string, unknown> },\n onProgress?: (result: BatchResult) => void\n ): Promise<BatchResult> {\n // Check if cancelled before starting\n if (this.isCancelled) {\n const batchResult: BatchResult = {\n rowIndex: task.rowIndex,\n text: task.text,\n grade: task.grade,\n evaluatorId: task.evaluatorId,\n status: 'error',\n error: 'Cancelled by user',\n processingTimeMs: 0,\n originalRow: task.originalRow,\n };\n return batchResult;\n }\n\n const startTime = Date.now();\n const evaluator = this.evaluatorInstances.get(task.evaluatorId);\n\n if (!evaluator) {\n const batchResult: BatchResult = {\n rowIndex: task.rowIndex,\n text: task.text,\n grade: task.grade,\n evaluatorId: task.evaluatorId,\n status: 'error',\n error: `Evaluator not initialized: ${task.evaluatorId}`,\n processingTimeMs: 0,\n originalRow: task.originalRow,\n };\n this.completedResults.push(batchResult);\n if (onProgress) onProgress(batchResult);\n return batchResult;\n }\n\n try {\n const result = await evaluator.evaluate(task.text, task.grade);\n\n const batchResult: BatchResult = {\n rowIndex: task.rowIndex,\n text: task.text,\n grade: task.grade,\n evaluatorId: task.evaluatorId,\n status: 'success',\n score: result.score,\n reasoning: result.reasoning,\n processingTimeMs: Date.now() - startTime,\n originalRow: task.originalRow,\n };\n\n // Store completed result\n this.completedResults.push(batchResult);\n\n // Report progress\n if (onProgress) onProgress(batchResult);\n\n return batchResult;\n } catch (error) {\n const batchResult: BatchResult = {\n rowIndex: task.rowIndex,\n text: task.text,\n grade: task.grade,\n evaluatorId: task.evaluatorId,\n status: 'error',\n error: error instanceof Error ? error.message : String(error),\n processingTimeMs: Date.now() - startTime,\n originalRow: task.originalRow,\n };\n\n // Store completed result (even errors)\n this.completedResults.push(batchResult);\n\n // Report progress\n if (onProgress) onProgress(batchResult);\n\n return batchResult;\n }\n }\n\n /**\n * Calculate summary statistics\n */\n private calculateSummary(results: BatchResult[], durationMs: number): BatchSummary {\n const summary: BatchSummary = {\n totalTasks: results.length,\n successful: results.filter((r) => r.status === 'success').length,\n failed: results.filter((r) => r.status === 'error').length,\n durationMs,\n resultsPerEvaluator: {},\n };\n\n // Calculate per-evaluator stats\n const evaluatorIds = Array.from(new Set(results.map((r) => r.evaluatorId)));\n for (const id of evaluatorIds) {\n const evalResults = results.filter((r) => r.evaluatorId === id);\n summary.resultsPerEvaluator[id] = {\n successful: evalResults.filter((r) => r.status === 'success').length,\n failed: evalResults.filter((r) => r.status === 'error').length,\n };\n }\n\n return summary;\n }\n\n /**\n * Run batch evaluation for an evaluator group.\n *\n * @param inputs - Array of input rows\n * @param groupId - The evaluator group to run (see getAvailableGroups())\n * @param onProgress - Optional callback invoked after each task completes\n * @returns Batch evaluation results and summary\n */\n async evaluate(\n inputs: BatchInput[],\n groupId: string,\n onProgress?: (result: BatchResult) => void\n ): Promise<BatchOutput> {\n const startTime = Date.now();\n\n // Resolve group\n const group = EVALUATOR_GROUPS.find((g) => g.id === groupId);\n if (!group) {\n throw new Error(\n `Unknown evaluator group: \"${groupId}\". Available: ${EVALUATOR_GROUPS.map((g) => g.id).join(', ')}`\n );\n }\n\n // Enforce per-group row limit\n if (inputs.length > group.maxInputRows) {\n throw new Error(\n `Input exceeds limit for \"${group.id}\": ${inputs.length} rows (max ${group.maxInputRows}). Split into smaller batches.`\n );\n }\n\n // Reset state\n this.isCancelled = false;\n this.completedResults = [];\n\n // Initialize evaluator instances\n this.initializeEvaluators(group.evaluatorIds);\n\n // Create all tasks (flattened: inputs × evaluators)\n const tasks = this.createTasks(inputs, group.evaluatorIds);\n\n // Execute all tasks with concurrency control\n // Use allSettled to get partial results even if cancelled\n const settledResults = await Promise.allSettled(\n tasks.map((task) => this.limit(() => this.executeTask(task, onProgress)))\n );\n\n // Extract fulfilled results (skip rejected)\n const results = settledResults\n .filter((r): r is PromiseFulfilledResult<BatchResult> => r.status === 'fulfilled')\n .map((r) => r.value);\n\n // Calculate summary\n const durationMs = Date.now() - startTime;\n const summary = this.calculateSummary(results, durationMs);\n\n return { results, summary };\n }\n}\n","import * as fs from 'fs';\nimport { parse } from 'csv-parse/sync';\nimport type { BatchInput } from './types.js';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction findColumn(row: Record<string, any>, columnName: string): string | undefined {\n const normalizedTarget = columnName.toLowerCase().trim();\n for (const key of Object.keys(row)) {\n if (key.toLowerCase().trim() === normalizedTarget) {\n return key;\n }\n }\n return undefined;\n}\n\n/**\n * Parse a CSV file into BatchInput rows.\n *\n * Requires columns named \"text\" and \"grade\" (case-insensitive, whitespace-trimmed).\n * Rows missing either value are silently skipped.\n *\n * @throws {Error} If the file does not exist, is empty, or is missing required columns\n */\nexport function parseCSV(csvPath: string): BatchInput[] {\n if (!fs.existsSync(csvPath)) {\n throw new Error(`CSV file not found: ${csvPath}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const records = parse(fs.readFileSync(csvPath, 'utf-8'), {\n columns: true,\n skip_empty_lines: true,\n trim: true,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n }) as Record<string, any>[];\n\n if (records.length === 0) {\n throw new Error('CSV file is empty');\n }\n\n const firstRow = records[0];\n const textColumn = findColumn(firstRow, 'text');\n const gradeColumn = findColumn(firstRow, 'grade');\n\n if (!textColumn) {\n throw new Error('CSV must have a \"text\" column (case-insensitive)');\n }\n if (!gradeColumn) {\n throw new Error('CSV must have a \"grade\" column (case-insensitive)');\n }\n\n const inputs: BatchInput[] = [];\n\n for (let i = 0; i < records.length; i++) {\n const row = records[i];\n const text = row[textColumn];\n const grade = row[gradeColumn];\n\n if (!text || !grade) {\n console.warn(`Warning: skipping row ${i + 2} — missing text or grade`);\n continue;\n }\n\n inputs.push({\n text: String(text).trim(),\n grade: String(grade).trim(),\n rowIndex: i + 2, // 1-based, offset by 1 for the header row\n originalRow: row,\n });\n }\n\n return inputs;\n}\n","<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>Evaluation Report</title>\n <style>\n :root {\n --primary: #242423;\n --secondary: #6B6A64;\n --informational: #125B3A;\n --informational-bg: #E0F5EC;\n --border: #e2e8f0;\n --neutral-bg: #f1f5f9;\n --neutral-muted: #64748b;\n --on-band: #177A4D;\n --within-reach: #B79F15;\n --off-target: #C4352D;\n --card-bg: rgba(255,255,255,0.6);\n --card-shadow: 0 4px 10px 0 rgba(36,36,35,0.1);\n --radius: 8px;\n }\n\n * { box-sizing: border-box; margin: 0; padding: 0; }\n\n body {\n font-family: system-ui, -apple-system, sans-serif;\n background: #F4F6F8;\n color: var(--primary);\n font-size: 14px;\n line-height: 1.5;\n }\n\n .container { max-width: 1200px; margin: 0 auto; padding: 32px 40px; }\n\n /* ── Header ── */\n header.report-header { margin-bottom: 24px; }\n header.report-header h1 { font-size: 20px; font-weight: 600; margin: 0 0 4px 0; color: var(--primary); }\n header.report-header .subtitle { font-size: 14px; color: var(--secondary); }\n\n /* ── Cards ── */\n .card { background: var(--card-bg); border-radius: var(--radius); box-shadow: var(--card-shadow); margin-bottom: 20px; overflow: hidden; }\n .card-body { padding: 16px 20px; }\n .card-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--secondary); margin-bottom: 16px; }\n .card-label-sm { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--secondary); }\n\n /* ── Tabs ── */\n .tabs { display: flex; border-bottom: 1px solid var(--border); }\n .tab-btn { padding: 12px 20px; font-size: 14px; font-weight: 500; background: none; border: none; border-bottom: 2px solid transparent; margin-bottom: -1px; cursor: pointer; color: var(--secondary); transition: color 0.15s, border-color 0.15s; }\n .tab-btn:hover { color: var(--primary); }\n .tab-btn.active { color: var(--primary); border-bottom-color: var(--on-band); }\n .tab-panel { display: none; }\n .tab-panel.active { display: block; }\n .tab-content { padding: 20px 28px; }\n\n /* ── Layout grids ── */\n .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px; }\n .grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 20px; }\n .grid-4 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px 32px; }\n .flex-col { display: flex; flex-direction: column; gap: 4px; }\n\n /* ── Tags ── */\n .tag { display: inline-block; padding: 4px 10px; border-radius: 6px; font-size: 12px; font-weight: 600; }\n .tag-on-band { background: var(--on-band); color: #fff; }\n .tag-within-reach { background: var(--within-reach); color: #fff; }\n .tag-off-target { background: var(--off-target); color: #fff; }\n .tag-informational{ background: var(--neutral-bg); color: var(--neutral-muted); }\n\n /* ── GLA stat cards ── */\n .gla-card .top-stripe { height: 4px; }\n .gla-card.on-band .top-stripe { background: var(--on-band); }\n .gla-card.within-reach .top-stripe { background: var(--within-reach); }\n .gla-card.off-target .top-stripe { background: var(--off-target); }\n .gla-card.on-band .card-label-sm { color: var(--on-band); }\n .gla-card.within-reach .card-label-sm { color: var(--within-reach); }\n .gla-card.off-target .card-label-sm { color: var(--off-target); }\n .gla-card .big-num { font-size: 28px; font-weight: 700; margin: 6px 0; }\n .gla-card.on-band .big-num { color: var(--on-band); }\n .gla-card.within-reach .big-num { color: var(--within-reach); }\n .gla-card.off-target .big-num { color: var(--off-target); }\n .gla-card .desc { font-size: 13px; color: var(--secondary); }\n\n /* ── Complexity dimension summary bars ── */\n .cx-dim-track { height: 10px; background: var(--border); border-radius: 99px; overflow: hidden; }\n .cx-dim-fill { height: 100%; border-radius: 99px; background: var(--neutral-muted); transition: width 0.4s ease; }\n\n /* ── Insights ── */\n .number-icon { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; background: var(--primary); color: #fff; font-size: 14px; font-weight: 600; flex-shrink: 0; }\n .insight-row { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 10px; }\n .insight-text { flex: 1; font-size: 14px; color: var(--primary); }\n .disclaimer { font-size: 13px; color: var(--secondary); margin-top: 12px; }\n\n /* ── Grade level distribution (CSS bars) ── */\n .dist-chart { margin-top: 8px; }\n .dist-row { display: flex; align-items: center; margin-bottom: 10px; }\n .dist-row .band { width: 60px; font-size: 12px; font-weight: 600; color: var(--primary); flex-shrink: 0; }\n .dist-row .bars { flex: 1; height: 24px; display: flex; }\n .dist-row .bar-on { background: var(--on-band); }\n .dist-row .bar-wr { background: var(--within-reach); }\n .dist-row .bar-off { background: var(--off-target); }\n .dist-row .bars > .bar-seg:first-child { border-radius: 4px 0 0 4px; }\n .dist-row .bars > .bar-seg:last-child { border-radius: 0 4px 4px 4px; }\n .dist-row .bars > .bar-seg.bar-off:last-child { border-radius: 0 4px 4px 0; }\n .dist-row .bars > .bar-seg.bar-off:only-child { border-radius: 4px; }\n .dist-row .bars > .bar-seg:only-child { border-radius: 4px; }\n .dist-legend { display: flex; justify-content: center; gap: 24px; margin-top: 16px; font-size: 12px; color: var(--primary); }\n .dist-legend span { display: inline-flex; align-items: center; gap: 6px; }\n .dist-legend .dot { width: 10px; height: 10px; border-radius: 2px; flex-shrink: 0; }\n\n /* ── Bar segment tooltips ── */\n .bar-seg { position: relative; cursor: default; }\n .bar-seg::after {\n content: attr(data-tip);\n position: absolute;\n bottom: calc(100% + 6px);\n left: 50%;\n transform: translateX(-50%);\n background: var(--primary);\n color: #fff;\n padding: 5px 9px;\n border-radius: 5px;\n font-size: 12px;\n white-space: nowrap;\n pointer-events: none;\n opacity: 0;\n transition: opacity 0.12s;\n z-index: 20;\n }\n .bar-seg::before {\n content: '';\n position: absolute;\n bottom: calc(100% + 1px);\n left: 50%;\n transform: translateX(-50%);\n border: 5px solid transparent;\n border-top-color: var(--primary);\n opacity: 0;\n transition: opacity 0.12s;\n pointer-events: none;\n z-index: 20;\n }\n .bar-seg:hover::after,\n .bar-seg:hover::before { opacity: 1; }\n\n /* ── Heatmap ── */\n .heatmap-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n .heatmap-table th { padding: 10px 16px; text-align: left; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--neutral-muted); border-bottom: 2px solid var(--border); }\n .heatmap-table td { padding: 10px 16px; border-bottom: 1px solid var(--border); }\n .heatmap-table td:first-child { font-weight: 600; color: var(--primary); }\n .heatmap-table .cell-num { text-align: center; }\n .heatmap-table tr:last-child td { border-bottom: none; }\n .heatmap-cell { display: inline-block; padding: 5px 12px; border-radius: 6px; font-size: 13px; font-weight: 600; background: var(--neutral-bg); color: var(--neutral-muted); }\n\n /* ── Full results table ── */\n .results-scroll { overflow-x: auto; overflow-y: auto; max-height: 600px; }\n table.data-table { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 100%; white-space: nowrap; }\n table.data-table th {\n padding: 10px 16px; text-align: left; font-size: 12px; font-weight: 600;\n color: var(--primary); background: var(--neutral-bg);\n border-bottom: 2px solid var(--border);\n position: sticky; top: 0; z-index: 3; white-space: nowrap;\n }\n table.data-table td {\n padding: 10px 16px; border-bottom: 1px solid var(--border);\n vertical-align: top; white-space: normal;\n color: var(--primary);\n }\n table.data-table tr:last-child td { border-bottom: none; }\n table.data-table tbody tr:hover td { background: rgba(0,0,0,0.02); }\n table.data-table tbody tr:hover td.frozen { background: var(--neutral-bg); }\n /* Frozen (sticky-left) columns */\n table.data-table th.frozen,\n table.data-table td.frozen { position: sticky; background: var(--neutral-bg); z-index: 2; }\n table.data-table td.frozen { background: #fff; }\n table.data-table th.frozen { z-index: 4; }\n table.data-table th.frozen-last,\n table.data-table td.frozen-last { border-right: 2px solid var(--border); }\n table.data-table th.group-start,\n table.data-table td.group-start { border-left: 2px solid var(--border); }\n /* Text cell — 3-line clamp, full text on hover */\n table.data-table .cell-text { cursor: help; }\n table.data-table .cell-text-inner {\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n white-space: normal;\n }\n /* Reasoning cells — 2-line clamp, full text on hover */\n table.data-table .cell-reasoning { font-size: 12px; color: var(--secondary); cursor: help; }\n table.data-table .cell-reasoning-inner {\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n white-space: normal;\n }\n\n /* ── Empty / no-data ── */\n .no-data { padding: 40px; text-align: center; color: var(--secondary); font-size: 15px; }\n </style>\n</head>\n<body>\n\n <div class=\"container\">\n <header class=\"report-header\" id=\"app-header\"></header>\n <div class=\"card\" style=\"margin-bottom:0; overflow:visible;\">\n <div class=\"tabs\" id=\"tab-bar\"></div>\n <div id=\"tab-summary\" class=\"tab-panel active\"></div>\n <div id=\"tab-results\" class=\"tab-panel\"></div>\n </div>\n </div>\n\n <script>\n // ---------------------------------------------------------------------------\n // MOCK DATA — used when the template is opened directly in a browser so\n // designers can see a realistic preview without running the CLI.\n // This constant is never referenced when real data has been injected.\n // ---------------------------------------------------------------------------\n const MOCK_REPORT_DATA = {\n meta: {\n reportId: 'sample_content_batch_20260301T1430',\n generatedAt: 'Mar 1, 2026 2:30 PM',\n csvPath: '/Users/designer/Documents/interventionhelper_content_batch_03-01.csv',\n evaluatorIds: ['grade-level-appropriateness', 'subject-matter-knowledge', 'vocabulary', 'sentence-structure', 'conventionality'],\n evaluatorNames: ['Grade Level Appropriateness', 'Subject Matter Knowledge', 'Vocabulary', 'Sentence Structure', 'Conventionality'],\n totalRows: 300,\n processedRows: 287,\n erroredRows: 13,\n },\n gradeLevelStats: {\n onBand: 172, adjacent: 85, offTarget: 30,\n onBandPct: 60, adjacentPct: 30, offTargetPct: 10,\n hasData: true,\n },\n complexityStats: [\n {\n evaluatorId: 'subject-matter-knowledge', name: 'Subject Matter Knowledge',\n average: 2.6, label: 'Moderately complex',\n distribution: [28, 98, 110, 51],\n },\n {\n evaluatorId: 'vocabulary', name: 'Vocabulary',\n average: 2.4, label: 'Moderately complex',\n distribution: [45, 120, 95, 27],\n },\n {\n evaluatorId: 'sentence-structure', name: 'Sentence Structure',\n average: 1.9, label: 'Slightly complex',\n distribution: [88, 105, 72, 22],\n },\n {\n evaluatorId: 'conventionality', name: 'Conventionality',\n average: 1.7, label: 'Slightly complex',\n distribution: [112, 118, 45, 12],\n },\n ],\n gradeBandDistribution: {\n bands: ['K-1', '2-3', '4-5', '6-8', '9-10', '11-CCR'],\n data: [\n { onBand: 0, adjacent: 0, offTarget: 0, total: 0 },\n { onBand: 32, adjacent: 18, offTarget: 5, total: 55 },\n { onBand: 58, adjacent: 22, offTarget: 8, total: 88 },\n { onBand: 48, adjacent: 25, offTarget: 10, total: 83 },\n { onBand: 22, adjacent: 14, offTarget: 5, total: 41 },\n { onBand: 12, adjacent: 6, offTarget: 2, total: 20 },\n ],\n },\n complexityHeatmap: {\n bands: ['K-1', '2-3', '4-5', '6-8', '9-10', '11-CCR'],\n evaluators: ['Subject Matter Knowledge', 'Vocabulary', 'Sentence Structure', 'Conventionality'],\n evaluatorIds: ['subject-matter-knowledge', 'vocabulary', 'sentence-structure', 'conventionality'],\n values: [\n [null, null, null, null],\n [1.8, 1.6, 1.4, 1.3 ],\n [2.3, 2.1, 1.8, 1.7 ],\n [2.7, 2.5, 2.2, 2.0 ],\n [3.1, 2.9, 2.6, 2.4 ],\n [3.4, 3.2, 2.8, 2.6 ],\n ],\n },\n insights: [\n 'Review texts marked as Off Target — they may need content revision or grade-level adjustment before distribution.',\n 'Texts evaluated as Adjacent may benefit from light scaffolding strategies such as vocabulary pre-teaching.',\n 'Higher grade bands tend to show greater text complexity. Consider whether complexity aligns with instructional goals.',\n ],\n fullResults: {\n originalColumns: ['row_id', 'text', 'grade', 'source'],\n hasGLA: true,\n complexityEvaluators: [\n { evaluatorId: 'subject-matter-knowledge', name: 'Subject Matter Knowledge', prefix: 'subject_matter_knowledge' },\n { evaluatorId: 'vocabulary', name: 'Vocabulary', prefix: 'vocabulary' },\n { evaluatorId: 'sentence-structure', name: 'Sentence Structure', prefix: 'sentence_structure' },\n { evaluatorId: 'conventionality', name: 'Conventionality', prefix: 'conventionality' },\n ],\n rows: [\n {\n row_id: '1', grade: '5', source: 'science_unit_3',\n text: 'The water cycle describes how water evaporates from surfaces, rises into the atmosphere, cools and condenses into clouds, and falls back to the ground as precipitation.',\n __gla_status: 'On Band', __gla_band: '4-5',\n __gla_reasoning: 'Uses grade-appropriate science vocabulary with a clear explanatory structure suitable for grades 4–5.',\n __subject_matter_knowledge_score: 'Moderately complex',\n __subject_matter_knowledge_reasoning: 'Requires familiarity with basic Earth science concepts; grade 5 students may need prior exposure to the water cycle.',\n __vocabulary_score: 'Moderately complex',\n __vocabulary_reasoning: 'Contains domain-specific terms (evaporates, condenses, precipitation) that require pre-teaching for grade 5 students.',\n __sentence_structure_score: 'Slightly complex',\n __sentence_structure_reasoning: 'Primarily compound sentences with clear connective structure appropriate for grade 5.',\n __conventionality_score: 'Slightly complex',\n __conventionality_reasoning: 'Language is largely literal and explicit; no figurative or idiomatic usage that would increase comprehension demand.',\n },\n {\n row_id: '2', grade: '6', source: 'science_unit_1',\n text: 'Photosynthesis is the process by which green plants use sunlight, water and carbon dioxide to produce food and oxygen.',\n __gla_status: 'Adjacent', __gla_band: '4-5',\n __gla_reasoning: 'Content is accessible but slightly below typical grade 6 complexity expectations.',\n __subject_matter_knowledge_score: 'Slightly complex',\n __subject_matter_knowledge_reasoning: 'Core concept of photosynthesis is introduced in upper elementary science; low prior knowledge demand for grade 6.',\n __vocabulary_score: 'Moderately complex',\n __vocabulary_reasoning: 'Key scientific terms are present but relatively straightforward for grade 6 readers.',\n __sentence_structure_score: 'Slightly complex',\n __sentence_structure_reasoning: 'Single main clause with a relative clause; well within grade 6 reading ability.',\n __conventionality_score: 'Slightly complex',\n __conventionality_reasoning: 'Entirely literal and direct; meaning is fully transparent with no figurative language.',\n },\n {\n row_id: '3', grade: '8', source: 'biology_unit_2',\n text: 'The mitochondria, often described as the powerhouse of the cell, are organelles found in the cytoplasm of eukaryotic cells, where they generate most of the adenosine triphosphate used for cellular energy.',\n __gla_status: 'Off Target', __gla_band: '11-CCR',\n __gla_reasoning: 'Text uses advanced biochemical terminology (adenosine triphosphate, eukaryotic) more appropriate for upper secondary or college-level readers.',\n __subject_matter_knowledge_score: 'Very complex',\n __subject_matter_knowledge_reasoning: 'Assumes familiarity with cell biology, organelle function, and biochemical energy systems well beyond typical grade 8 expectations.',\n __vocabulary_score: 'Exceedingly complex',\n __vocabulary_reasoning: 'High density of Tier 3 domain-specific words significantly exceeds typical grade 8 vocabulary expectations.',\n __sentence_structure_score: 'Very complex',\n __sentence_structure_reasoning: 'Long, embedded clauses with multiple modifying phrases create significant syntactic complexity for grade 8.',\n __conventionality_score: 'Moderately complex',\n __conventionality_reasoning: '\"Powerhouse of the cell\" is a well-known metaphor but requires understanding of the underlying analogy; otherwise literal.',\n },\n {\n row_id: '4', grade: '3', source: 'science_unit_3',\n text: 'Rain falls from clouds when tiny water droplets join together and become heavy enough to fall to the ground.',\n __gla_status: 'On Band', __gla_band: '2-3',\n __gla_reasoning: 'Simple vocabulary and sentence structure are appropriate for grades 2–3.',\n __subject_matter_knowledge_score: 'Slightly complex',\n __subject_matter_knowledge_reasoning: 'Everyday weather phenomenon; no specialized prior knowledge required for grade 3 students.',\n __vocabulary_score: 'Slightly complex',\n __vocabulary_reasoning: 'Common everyday vocabulary with no domain-specific terms requiring pre-teaching.',\n __sentence_structure_score: 'Slightly complex',\n __sentence_structure_reasoning: 'Short simple sentences with basic connective structure.',\n __conventionality_score: 'Slightly complex',\n __conventionality_reasoning: 'Entirely conventional and literal; straightforward causal explanation with no figurative language.',\n },\n {\n row_id: '5', grade: '9', source: 'biology_unit_1',\n text: 'Ecosystems are communities of organisms that interact with each other and their physical environment, shaped by both biotic and abiotic factors that influence population dynamics over time.',\n __gla_status: 'On Band', __gla_band: '9-10',\n __gla_reasoning: 'Appropriate complexity and terminology for a grade 9–10 biology curriculum.',\n __subject_matter_knowledge_score: 'Very complex',\n __subject_matter_knowledge_reasoning: 'Requires understanding of ecological concepts (biotic/abiotic factors, population dynamics) typical of secondary-level biology coursework.',\n __vocabulary_score: 'Very complex',\n __vocabulary_reasoning: 'Multiple Tier 3 terms (biotic, abiotic, population dynamics) require strong background knowledge.',\n __sentence_structure_score: 'Moderately complex',\n __sentence_structure_reasoning: 'Compound-complex sentence with a relative clause; manageable for grade 9 readers.',\n __conventionality_score: 'Slightly complex',\n __conventionality_reasoning: 'Technical but literal throughout; no irony or figurative usage that would obscure meaning.',\n },\n {\n row_id: '6', grade: '4', source: 'social_studies_unit_2',\n text: 'Ancient Egyptians built pyramids as tombs for their pharaohs and used a picture-based writing system called hieroglyphics.',\n __gla_status: 'On Band', __gla_band: '4-5',\n __gla_reasoning: 'Vocabulary and sentence length are well-matched to grade 4–5 social studies content.',\n __subject_matter_knowledge_score: 'Moderately complex',\n __subject_matter_knowledge_reasoning: 'Ancient Egypt is a common grade 4 social studies topic; some prior exposure to civilizations is expected.',\n __vocabulary_score: 'Moderately complex',\n __vocabulary_reasoning: 'Domain-specific proper nouns (pharaohs, hieroglyphics) may need brief glossing.',\n __sentence_structure_score: 'Slightly complex',\n __sentence_structure_reasoning: 'Two coordinated independent clauses; clear and accessible structure.',\n __conventionality_score: 'Slightly complex',\n __conventionality_reasoning: 'Descriptive and informational; meaning is explicit and no non-literal language is used.',\n },\n {\n row_id: '7', grade: '11', source: 'lit_unit_4',\n text: 'Shakespeare\\'s use of dramatic irony in Othello functions as a mechanism of tragic inevitability, positioning the audience as unwilling witnesses to the protagonist\\'s epistemological collapse.',\n __gla_status: 'On Band', __gla_band: '11-CCR',\n __gla_reasoning: 'Sophisticated literary analysis vocabulary and complex syntax are well-suited to grades 11–CCR.',\n __subject_matter_knowledge_score: 'Exceedingly complex',\n __subject_matter_knowledge_reasoning: 'Requires familiarity with Shakespearean drama, literary theory, and epistemological concepts; assumes high prior exposure to canonical literature.',\n __vocabulary_score: 'Exceedingly complex',\n __vocabulary_reasoning: 'Tier 3 literary and philosophical vocabulary (epistemological, dramatic irony, tragic inevitability) demands high reading proficiency.',\n __sentence_structure_score: 'Exceedingly complex',\n __sentence_structure_reasoning: 'Noun phrase and participial phrase stacking creates a dense, highly embedded syntactic structure.',\n __conventionality_score: 'Very complex',\n __conventionality_reasoning: 'Analytical prose employs abstract and figurative constructs; \"epistemological collapse\" and \"mechanism of tragic inevitability\" are non-literal formulations requiring interpretive inference.',\n },\n {\n row_id: '8', grade: '7', source: 'history_unit_1',\n text: 'The Industrial Revolution transformed European societies by shifting labor from farms to factories, driving rapid urban growth and fundamentally changing how goods were produced and traded.',\n __gla_status: 'Adjacent', __gla_band: '9-10',\n __gla_reasoning: 'Vocabulary and conceptual density exceed typical grade 7 expectations; better suited for grades 9–10.',\n __subject_matter_knowledge_score: 'Moderately complex',\n __subject_matter_knowledge_reasoning: 'Industrial Revolution is introduced in middle school; grade 7 students likely have foundational context, though economic concepts add demand.',\n __vocabulary_score: 'Very complex',\n __vocabulary_reasoning: 'Abstract economic and historical vocabulary (urban growth, fundamentally) adds significant reading demand.',\n __sentence_structure_score: 'Moderately complex',\n __sentence_structure_reasoning: 'Participial phrases and coordinated verb phrases add structural complexity but remain readable.',\n __conventionality_score: 'Slightly complex',\n __conventionality_reasoning: 'Primarily literal and informational; \"transformed\" is used in its conventional sense with no figurative layering.',\n },\n ],\n },\n };\n\n // ---------------------------------------------------------------------------\n // DATA — this line is replaced by the formatter at report generation time.\n // When opening the template directly in a browser, MOCK_REPORT_DATA is used.\n // ---------------------------------------------------------------------------\n var REPORT_DATA = null; // __REPLACED_BY_FORMATTER__\n REPORT_DATA = REPORT_DATA || MOCK_REPORT_DATA;\n\n // ---------------------------------------------------------------------------\n // Canonical evaluator order\n // ---------------------------------------------------------------------------\n\n const EVALUATOR_ORDER = [\n 'grade-level-appropriateness',\n 'subject-matter-knowledge',\n 'vocabulary',\n 'sentence-structure',\n 'conventionality',\n ];\n\n function evalSortIndex(id) {\n const i = EVALUATOR_ORDER.indexOf(id);\n return i === -1 ? 999 : i;\n }\n\n // Sort meta.evaluatorIds / evaluatorNames in tandem\n const _metaPairs = REPORT_DATA.meta.evaluatorIds\n .map((id, i) => ({ id, name: REPORT_DATA.meta.evaluatorNames[i] }))\n .sort((a, b) => evalSortIndex(a.id) - evalSortIndex(b.id));\n REPORT_DATA.meta.evaluatorIds = _metaPairs.map(x => x.id);\n REPORT_DATA.meta.evaluatorNames = _metaPairs.map(x => x.name);\n\n // Sort complexityStats\n REPORT_DATA.complexityStats = [...REPORT_DATA.complexityStats]\n .sort((a, b) => evalSortIndex(a.evaluatorId) - evalSortIndex(b.evaluatorId));\n\n // Sort complexityHeatmap evaluators and their value columns\n const _hmPairs = REPORT_DATA.complexityHeatmap.evaluators\n .map((name, i) => ({ name, id: REPORT_DATA.complexityHeatmap.evaluatorIds[i], i }))\n .sort((a, b) => evalSortIndex(a.id) - evalSortIndex(b.id));\n REPORT_DATA.complexityHeatmap.evaluators = _hmPairs.map(x => x.name);\n REPORT_DATA.complexityHeatmap.evaluatorIds = _hmPairs.map(x => x.id);\n REPORT_DATA.complexityHeatmap.values = REPORT_DATA.complexityHeatmap.values\n .map(row => _hmPairs.map(x => row[x.i]));\n\n // Sort fullResults.complexityEvaluators\n REPORT_DATA.fullResults.complexityEvaluators = [...REPORT_DATA.fullResults.complexityEvaluators]\n .sort((a, b) => evalSortIndex(a.evaluatorId) - evalSortIndex(b.evaluatorId));\n\n // ---------------------------------------------------------------------------\n // Utilities\n // ---------------------------------------------------------------------------\n\n function esc(str) {\n return String(str ?? '')\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n }\n\n function statusBadge(status) {\n const cls = {\n 'On Band': 'tag-on-band',\n 'Adjacent': 'tag-within-reach',\n 'Off Target':'tag-off-target',\n }[status] || '';\n const display = status === 'Adjacent' ? 'Within Reach' : status;\n return `<span class=\"tag ${cls}\">${esc(display)}</span>`;\n }\n\n // ---------------------------------------------------------------------------\n // Tab switching\n // ---------------------------------------------------------------------------\n\n function switchTab(tab) {\n document.querySelectorAll('.tab-btn').forEach(b =>\n b.classList.toggle('active', b.dataset.tab === tab)\n );\n document.getElementById('tab-summary').classList.toggle('active', tab === 'summary');\n document.getElementById('tab-results').classList.toggle('active', tab === 'results');\n }\n\n // ---------------------------------------------------------------------------\n // Header\n // ---------------------------------------------------------------------------\n\n function renderHeader() {\n const { meta } = REPORT_DATA;\n document.getElementById('app-header').innerHTML = `\n <h1>Evaluation Report</h1>\n <p class=\"subtitle\">Generated: ${esc(meta.generatedAt)} &bull; Report ID: ${esc(meta.reportId)}</p>\n `;\n document.title = `Report: ${meta.reportId}`;\n }\n\n // ---------------------------------------------------------------------------\n // Tab bar\n // ---------------------------------------------------------------------------\n\n function renderTabs() {\n document.getElementById('tab-bar').innerHTML = `\n <button class=\"tab-btn active\" data-tab=\"summary\" onclick=\"switchTab('summary')\">Summary</button>\n <button class=\"tab-btn\" data-tab=\"results\" onclick=\"switchTab('results')\">Full Results</button>\n `;\n }\n\n // ---------------------------------------------------------------------------\n // Summary tab\n // ---------------------------------------------------------------------------\n\n function renderSummary() {\n const { meta, gradeLevelStats: gls, complexityStats, insights,\n gradeBandDistribution, complexityHeatmap } = REPORT_DATA;\n\n // ── Snapshot ──\n const snapshotHtml = `\n <div class=\"card\">\n <div class=\"card-body\">\n <div class=\"card-label\">Snapshot</div>\n <div style=\"display:flex; flex-direction:column; gap:14px;\">\n <div class=\"flex-col\">\n <span class=\"card-label-sm\">Evaluators</span>\n <div style=\"margin-top:6px; display:flex; flex-wrap:wrap; gap:6px;\">\n ${meta.evaluatorNames.map(n => `<span class=\"tag tag-informational\">${esc(n)}</span>`).join('')}\n </div>\n </div>\n <div style=\"display:grid; grid-template-columns:1fr 1fr 3fr; gap:12px 32px;\">\n <div class=\"flex-col\">\n <span class=\"card-label-sm\">Rows Processed</span>\n <span style=\"font-weight:500; margin-top:4px;\">${meta.processedRows} of ${meta.totalRows}</span>\n </div>\n <div class=\"flex-col\">\n <span class=\"card-label-sm\">Errors / Skipped</span>\n <span style=\"font-weight:500; margin-top:4px;\">${meta.erroredRows}</span>\n </div>\n <div class=\"flex-col\">\n <span class=\"card-label-sm\">Source File</span>\n <span style=\"font-size:12px; font-family:monospace; word-break:break-all; color:var(--secondary); margin-top:4px;\" title=\"${esc(meta.csvPath)}\">${esc(meta.csvPath)}</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n `;\n\n // ── GLA stat cards ──\n const glsHtml = gls.hasData ? `\n <div class=\"grid-3\">\n <div class=\"card gla-card on-band\" style=\"margin-bottom:0;\">\n <div class=\"top-stripe\"></div>\n <div class=\"card-body\">\n <div class=\"card-label-sm\">On Band</div>\n <div class=\"big-num\">${gls.onBandPct}%</div>\n <div class=\"desc\">${gls.onBand} of ${meta.processedRows} rows where the evaluated grade band matches intended</div>\n </div>\n </div>\n <div class=\"card gla-card within-reach\" style=\"margin-bottom:0;\">\n <div class=\"top-stripe\"></div>\n <div class=\"card-body\">\n <div class=\"card-label-sm\">Within Reach</div>\n <div class=\"big-num\">${gls.adjacentPct}%</div>\n <div class=\"desc\">${gls.adjacent} rows where the alternative grade band aligns with intended</div>\n </div>\n </div>\n <div class=\"card gla-card off-target\" style=\"margin-bottom:0;\">\n <div class=\"top-stripe\"></div>\n <div class=\"card-body\">\n <div class=\"card-label-sm\">Off Target</div>\n <div class=\"big-num\">${gls.offTargetPct}%</div>\n <div class=\"desc\">${gls.offTarget} rows where neither evaluated nor alternative matches intended</div>\n </div>\n </div>\n </div>\n ` : '';\n\n // ── Complexity dimension summary card ──\n const cxHtml = complexityStats.length > 0 ? (() => {\n const totalRows = meta.processedRows || meta.totalRows;\n const items = complexityStats.map(cs => {\n const pct = Math.round((cs.average / 4.0) * 100);\n const labelText = cs.average > 0\n ? `${esc(cs.label)} (${cs.average.toFixed(1)} / 4.0)`\n : '—';\n return `\n <div style=\"display:flex; flex-direction:column; gap:8px;\">\n <span style=\"font-size:13px; font-weight:500; color:var(--primary);\">${esc(cs.name)}</span>\n <div class=\"cx-dim-track\"><div class=\"cx-dim-fill\" style=\"width:${pct}%\"></div></div>\n <span style=\"font-size:12px; color:var(--secondary);\">${labelText}</span>\n </div>\n `;\n }).join('');\n return `\n <div class=\"card\">\n <div class=\"card-body\">\n <div class=\"card-label\">Text Complexity Dimensions (avg. across ${totalRows} rows)</div>\n <div style=\"display:grid; grid-template-columns:repeat(3,1fr); gap:16px 24px;\">\n ${items}\n </div>\n </div>\n </div>\n `;\n })() : '';\n\n // ── Insights ──\n const insightsHtml = `\n <div class=\"card\" style=\"display: none;\">\n <div class=\"card-body\">\n <div class=\"card-label\" style=\"display:flex; align-items:center; gap:8px;\">\n Insights\n <span class=\"tag tag-informational\" style=\"font-size:10px; letter-spacing:0.06em; padding:2px 8px;\">Early Access</span>\n </div>\n <div style=\"display:flex; flex-direction:column; gap:10px;\">\n ${insights.map((text, idx) => `\n <div class=\"insight-row\">\n <span class=\"number-icon\" aria-label=\"Insight ${idx + 1}\">${idx + 1}</span>\n <span class=\"insight-text\">${esc(text)}</span>\n </div>\n `).join('')}\n </div>\n <p class=\"disclaimer\">These insights are automatically generated and may not reflect the full context of your data.</p>\n </div>\n </div>\n `;\n\n // ── Grade level distribution (CSS stacked bars) ──\n const distHtml = (() => {\n const toPct = (n, total) => total > 0 ? Math.round((n / total) * 100) : 0;\n const activeBands = gradeBandDistribution.bands.filter((_, i) => gradeBandDistribution.data[i].total > 0);\n const activeData = gradeBandDistribution.data.filter(d => d.total > 0);\n if (activeBands.length === 0) return '';\n\n const rows = activeBands.map((band, i) => {\n const d = activeData[i];\n const onPct = toPct(d.onBand, d.total);\n const adjPct = toPct(d.adjacent, d.total);\n const offPct = toPct(d.offTarget, d.total);\n const onSeg = d.onBand > 0 ? `<div class=\"bar-seg bar-on\" style=\"width:${onPct}%\" data-tip=\"On Band: ${d.onBand} (${onPct}%)\"></div>` : '';\n const adjSeg = d.adjacent > 0 ? `<div class=\"bar-seg bar-wr\" style=\"width:${adjPct}%\" data-tip=\"Within Reach: ${d.adjacent} (${adjPct}%)\"></div>` : '';\n const offSeg = d.offTarget > 0 ? `<div class=\"bar-seg bar-off\" style=\"width:${offPct}%\" data-tip=\"Off Target: ${d.offTarget} (${offPct}%)\"></div>` : '';\n return `\n <div class=\"dist-row\">\n <span class=\"band\">${esc(band)}</span>\n <div class=\"bars\">${onSeg}${adjSeg}${offSeg}</div>\n </div>\n `;\n }).join('');\n\n return `\n <div class=\"card\">\n <div class=\"card-body\">\n <div class=\"card-label\">Grade Band Alignment by Intended Grade</div>\n <div class=\"dist-chart\">${rows}</div>\n <div class=\"dist-legend\">\n <span><span class=\"dot\" style=\"background:var(--on-band)\"></span>On Band</span>\n <span><span class=\"dot\" style=\"background:var(--within-reach)\"></span>Within Reach</span>\n <span><span class=\"dot\" style=\"background:var(--off-target)\"></span>Off Target</span>\n </div>\n </div>\n </div>\n `;\n })();\n\n // ── Heatmap ──\n const heatmapHtml = complexityStats.length > 0 && complexityHeatmap.evaluators.length > 0 ? `\n <div class=\"card\">\n <div class=\"card-body\">\n <div class=\"card-label\">Text Complexity Dimensions by Intended Grade</div>\n <div style=\"overflow-x:auto;\">\n <table class=\"heatmap-table\">\n <thead>\n <tr>\n <th>Dimension</th>\n ${complexityHeatmap.bands.map(b => `<th style=\"text-align:center; padding:8px 10px; white-space:nowrap; min-width:56px;\">${esc(b)}</th>`).join('')}\n </tr>\n </thead>\n <tbody>\n ${complexityHeatmap.evaluators.map((evaluator, ei) => `\n <tr>\n <td>${esc(evaluator)}</td>\n ${complexityHeatmap.bands.map((band, bi) => {\n const val = complexityHeatmap.values[bi][ei];\n const label = val !== null ? val.toFixed(1) : '—';\n return `<td class=\"cell-num\" style=\"padding:8px 10px;\"><span class=\"heatmap-cell\" style=\"padding:4px 8px;\">${label}</span></td>`;\n }).join('')}\n </tr>\n `).join('')}\n </tbody>\n </table>\n </div>\n </div>\n </div>\n ` : '';\n\n document.getElementById('tab-summary').innerHTML = `\n <div class=\"tab-content\">\n ${snapshotHtml}${glsHtml}${cxHtml}${insightsHtml}${distHtml}${heatmapHtml}\n </div>\n `;\n }\n\n // ---------------------------------------------------------------------------\n // Full Results tab\n // ---------------------------------------------------------------------------\n\n function renderResults() {\n const { fullResults } = REPORT_DATA;\n const { originalColumns, hasGLA, complexityEvaluators, rows } = fullResults;\n\n const KEPT_COLS = ['row_id', 'text', 'grade'];\n const visibleColumns = originalColumns.filter(col => KEPT_COLS.includes(col.toLowerCase()));\n const frozenCount = 1; // only Row # is sticky\n\n function colLabel(col) {\n const c = col.toLowerCase();\n if (c === 'row_id') return 'Row #';\n if (c === 'text') return 'Text';\n if (c === 'grade') return 'Grade';\n return col;\n }\n function colWidth(col) {\n const c = col.toLowerCase();\n if (c === 'row_id') return 60;\n if (c === 'text') return 340;\n if (c === 'grade') return 70;\n return 160;\n }\n\n const thOriginal = visibleColumns.map((col, i) => {\n const isFrozen = i === 0;\n return `<th class=\"${isFrozen ? 'frozen frozen-last' : ''}\" ${isFrozen ? 'data-frozen=\"0\" style=\"min-width:' + colWidth(col) + 'px; left:0; z-index:4;\"' : 'style=\"min-width:' + colWidth(col) + 'px;\"'}>${colLabel(col)}</th>`;\n }).join('');\n\n const thGLA = hasGLA ? `\n <th class=\"group-start\" style=\"min-width:120px\">Grade Level Status</th>\n <th style=\"min-width:110px\">GLA Grade Band</th>\n <th style=\"min-width:260px\">GLA Reasoning</th>\n ` : '';\n\n const thCX = complexityEvaluators.map(e => `\n <th class=\"group-start\" style=\"min-width:150px\">${esc(e.name)} Score</th>\n <th style=\"min-width:260px\">${esc(e.name)} Reasoning</th>\n `).join('');\n\n const bodyRows = rows.map(row => {\n const tdOriginal = visibleColumns.map((col, i) => {\n const isFrozen = i === 0;\n const isTextCol = col.toLowerCase() === 'text';\n const content = isTextCol\n ? `<div class=\"cell-text-inner\">${esc(row[col])}</div>`\n : esc(row[col]);\n const classes = [\n isFrozen ? 'frozen frozen-last' : '',\n isTextCol ? 'cell-text' : '',\n ].filter(Boolean).join(' ');\n const style = `min-width:${colWidth(col)}px;${isFrozen ? ' left:0; z-index:2;' : ''}`;\n return `<td${classes ? ` class=\"${classes}\"` : ''} ${isFrozen ? 'data-frozen=\"0\"' : ''} style=\"${style}\"${isTextCol ? ` title=\"${esc(row[col])}\"` : ''}>${content}</td>`;\n }).join('');\n\n const glaStatus = row['__gla_status'] || '';\n const tdGLA = hasGLA ? `\n <td class=\"group-start\">${statusBadge(glaStatus)}</td>\n <td>${esc(row['__gla_band'])}</td>\n <td class=\"cell-reasoning\" title=\"${esc(row['__gla_reasoning'])}\"><div class=\"cell-reasoning-inner\">${esc(row['__gla_reasoning'])}</div></td>\n ` : '';\n\n const tdCX = complexityEvaluators.map(e => {\n const prefix = `__${e.prefix}`;\n return `\n <td class=\"group-start\">${esc(row[prefix + '_score'])}</td>\n <td class=\"cell-reasoning\" title=\"${esc(row[prefix + '_reasoning'])}\"><div class=\"cell-reasoning-inner\">${esc(row[prefix + '_reasoning'])}</div></td>\n `;\n }).join('');\n\n return `<tr>${tdOriginal}${tdGLA}${tdCX}</tr>`;\n }).join('');\n\n document.getElementById('tab-results').innerHTML = `\n <div class=\"tab-content\" style=\"max-width:100%;\">\n <div class=\"results-scroll\">\n <table class=\"data-table\" id=\"results-table\">\n <thead><tr>${thOriginal}${thGLA}${thCX}</tr></thead>\n <tbody>${bodyRows}</tbody>\n </table>\n </div>\n </div>\n `;\n\n requestAnimationFrame(() => applyFrozenOffsets('results-table', frozenCount));\n }\n\n /**\n * Reads the rendered widths of frozen header cells and applies correct\n * `left` offsets to all frozen <th> and <td> cells in the table.\n */\n function applyFrozenOffsets(tableId, frozenCount) {\n const table = document.getElementById(tableId);\n if (!table) return;\n\n const headerCells = table.querySelectorAll('thead th.frozen');\n const offsets = [];\n let cumLeft = 0;\n headerCells.forEach(th => {\n offsets.push(cumLeft);\n cumLeft += th.offsetWidth;\n });\n\n table.querySelectorAll('tr').forEach(row => {\n const cells = row.querySelectorAll('td.frozen, th.frozen');\n cells.forEach((cell, i) => {\n if (i < frozenCount) cell.style.left = (offsets[i] ?? 0) + 'px';\n });\n });\n }\n\n // ---------------------------------------------------------------------------\n // Bootstrap\n // ---------------------------------------------------------------------------\n\n renderHeader();\n renderTabs();\n renderSummary();\n renderResults();\n </script>\n</body>\n</html>\n","import type { BatchOutput, BatchResult } from './types.js';\nimport reportTemplate from './report-template.html';\n\n// ---- Constants ----\n\nconst GLA_EVALUATOR_ID = 'grade-level-appropriateness';\n\nconst GRADE_BANDS = ['K-1', '2-3', '4-5', '6-8', '9-10', '11-CCR'] as const;\ntype GradeBand = typeof GRADE_BANDS[number];\n\n// Complexity string scores → numeric\nconst COMPLEXITY_SCORE_MAP: Record<string, number> = {\n 'slightly complex': 1,\n 'moderately complex': 2,\n 'very complex': 3,\n 'exceedingly complex': 4,\n // 'more context needed' has no numeric equivalent — rows with this score appear as N/A\n // in individual results and are excluded from aggregate stats, same as failed evaluations.\n};\n\n// ---- Helpers ----\n\nfunction evaluatorDisplayName(id: string): string {\n return id.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');\n}\n\n/** Maps a raw grade string (K, 1, 2 … 12, CCR) to a GRADE_BANDS index (0–5). */\nfunction gradeToBandIndex(grade: string): number {\n const g = String(grade).trim().toUpperCase().replace(/^0+/, '');\n if (g === 'K' || g === 'KINDERGARTEN') return 0;\n if (g === '1') return 0;\n if (g === '2' || g === '3') return 1;\n if (g === '4' || g === '5') return 2;\n if (g === '6' || g === '7' || g === '8') return 3;\n if (g === '9' || g === '10') return 4;\n if (g === '11' || g === '12' || g === 'CCR') return 5;\n return -1;\n}\n\n/** Maps a GLA score string (e.g. \"4-5\") to a GRADE_BANDS index. */\nfunction glaBandToIndex(band: string): number {\n return GRADE_BANDS.indexOf(band as GradeBand);\n}\n\nfunction getGLAStatus(inputGrade: string, glaBand: string): 'on-band' | 'adjacent' | 'off-target' {\n const inputIdx = gradeToBandIndex(inputGrade);\n const glaIdx = glaBandToIndex(glaBand);\n if (inputIdx === -1 || glaIdx === -1) return 'off-target';\n const diff = Math.abs(inputIdx - glaIdx);\n if (diff === 0) return 'on-band';\n if (diff === 1) return 'adjacent';\n return 'off-target';\n}\n\nfunction complexityToNumeric(score: string): number | undefined {\n return COMPLEXITY_SCORE_MAP[score.toLowerCase().trim()];\n}\n\nfunction complexityScoreLabel(avg: number): string {\n if (avg < 1.5) return 'Slightly Complex';\n if (avg < 2.5) return 'Moderately Complex';\n if (avg < 3.5) return 'Very Complex';\n return 'Exceedingly Complex';\n}\n\n/** Stub — returns hard-coded insights. Replace with real logic later. */\nfunction generateInsights(): string[] {\n return [\n 'Review texts marked as Off Target — they may need content revision or grade-level adjustment before distribution.',\n 'Texts evaluated as Adjacent may benefit from light scaffolding strategies such as vocabulary pre-teaching.',\n 'Higher grade bands tend to show greater text complexity. Consider whether complexity aligns with instructional goals.',\n ];\n}\n\n// ---- Shared grouping utility ----\n\nfunction groupResultsByRow(results: BatchResult[]): Map<number, BatchResult[]> {\n const grouped = new Map<number, BatchResult[]>();\n for (const result of results) {\n if (!grouped.has(result.rowIndex)) {\n grouped.set(result.rowIndex, []);\n }\n grouped.get(result.rowIndex)!.push(result);\n }\n return grouped;\n}\n\n// ---- CSV Formatter ----\n\nfunction formatEvaluatorPrefix(evaluatorId: string): string {\n const slug = evaluatorId.includes('.') ? evaluatorId.split('.').pop()! : evaluatorId;\n return slug.replace(/-/g, '_');\n}\n\nfunction escapeCSV(field: string): string {\n if (field.includes(',') || field.includes('\"') || field.includes('\\n')) {\n return `\"${field.replace(/\"/g, '\"\"')}\"`;\n }\n return field;\n}\n\nexport function formatAsCSV(output: BatchOutput): string {\n if (output.results.length === 0) {\n return '';\n }\n\n const groupedByRow = groupResultsByRow(output.results);\n const evaluatorIds = Array.from(new Set(output.results.map(r => r.evaluatorId))).sort();\n const firstResult = output.results[0];\n const originalColumns = Object.keys(firstResult.originalRow);\n\n const evaluatorColumns: string[] = [];\n for (const evalId of evaluatorIds) {\n const prefix = formatEvaluatorPrefix(evalId);\n evaluatorColumns.push(`${prefix}_score`);\n evaluatorColumns.push(`${prefix}_reasoning`);\n evaluatorColumns.push(`${prefix}_status`);\n }\n const headers = [...originalColumns, ...evaluatorColumns];\n\n const rows: string[][] = [];\n const sortedRowIndices = Array.from(groupedByRow.keys()).sort((a, b) => a - b);\n\n for (const rowIndex of sortedRowIndices) {\n const resultsForRow = groupedByRow.get(rowIndex)!;\n const firstResultForRow = resultsForRow[0];\n\n const originalValues = originalColumns.map(col =>\n escapeCSV(String(firstResultForRow.originalRow[col] || ''))\n );\n\n const evaluatorValues: string[] = [];\n for (const evalId of evaluatorIds) {\n const result = resultsForRow.find(r => r.evaluatorId === evalId);\n if (result) {\n evaluatorValues.push(result.status === 'success' ? escapeCSV(result.score || '') : '');\n evaluatorValues.push(result.status === 'success'\n ? escapeCSV(result.reasoning || '')\n : escapeCSV(result.error || ''));\n evaluatorValues.push(result.status);\n } else {\n evaluatorValues.push('', '', 'not_run');\n }\n }\n\n rows.push([...originalValues, ...evaluatorValues]);\n }\n\n return [headers, ...rows].map(row => row.join(',')).join('\\n');\n}\n\n// ---- HTML Formatter ----\n\nexport interface ReportMeta {\n csvPath: string;\n groupId: string;\n reportId: string;\n generatedAt: Date;\n totalInputRows: number;\n}\n\nexport function formatAsHTML(output: BatchOutput, meta: ReportMeta): string {\n const { results } = output;\n const byRow = groupResultsByRow(results);\n const allRowIndices = Array.from(byRow.keys()).sort((a, b) => a - b);\n\n const allEvaluatorIds = Array.from(new Set(results.map(r => r.evaluatorId))).sort();\n const hasGLA = allEvaluatorIds.includes(GLA_EVALUATOR_ID);\n const complexityIds = allEvaluatorIds.filter(id => id !== GLA_EVALUATOR_ID);\n\n // ---- Snapshot ----\n let processedRows = 0;\n let erroredRows = 0;\n for (const rowResults of byRow.values()) {\n if (rowResults.some(r => r.status === 'error')) erroredRows++;\n else processedRows++;\n }\n\n // ---- GLA stats ----\n const glaCounts = { onBand: 0, adjacent: 0, offTarget: 0 };\n const rowGLAStatus = new Map<number, {\n status: 'on-band' | 'adjacent' | 'off-target';\n band: string;\n reasoning: string;\n }>();\n\n if (hasGLA) {\n for (const [rowIndex, rowResults] of byRow) {\n const glaResult = rowResults.find(r => r.evaluatorId === GLA_EVALUATOR_ID);\n if (glaResult && glaResult.status === 'success' && glaResult.score) {\n const status = getGLAStatus(glaResult.grade, glaResult.score);\n rowGLAStatus.set(rowIndex, { status, band: glaResult.score, reasoning: glaResult.reasoning || '' });\n if (status === 'on-band') glaCounts.onBand++;\n else if (status === 'adjacent') glaCounts.adjacent++;\n else glaCounts.offTarget++;\n }\n }\n }\n\n const glaTotal = glaCounts.onBand + glaCounts.adjacent + glaCounts.offTarget;\n const pct = (n: number) => glaTotal > 0 ? Math.round((n / glaTotal) * 100) : 0;\n\n // ---- Complexity stats per evaluator ----\n const complexityStats = complexityIds.map(evalId => {\n const scores: number[] = [];\n const distribution: [number, number, number, number] = [0, 0, 0, 0];\n\n for (const rowResults of byRow.values()) {\n const r = rowResults.find(x => x.evaluatorId === evalId);\n if (r && r.status === 'success' && r.score) {\n const num = complexityToNumeric(r.score);\n if (num !== undefined) {\n scores.push(num);\n distribution[num - 1]++;\n }\n }\n }\n\n const avg = scores.length > 0 ? scores.reduce((a, b) => a + b, 0) / scores.length : 0;\n return {\n evaluatorId: evalId,\n name: evaluatorDisplayName(evalId),\n average: Math.round(avg * 10) / 10,\n label: avg > 0 ? complexityScoreLabel(avg) : 'N/A',\n distribution,\n };\n });\n\n // ---- Grade band distribution (GLA status per input grade band) ----\n const bandDist = GRADE_BANDS.map(() => ({ onBand: 0, adjacent: 0, offTarget: 0, total: 0 }));\n\n for (const [rowIndex, rowResults] of byRow) {\n const firstResult = rowResults[0];\n if (!firstResult) continue;\n const bandIdx = gradeToBandIndex(firstResult.grade);\n if (bandIdx === -1) continue;\n\n const glaStatus = rowGLAStatus.get(rowIndex);\n if (glaStatus) {\n bandDist[bandIdx].total++;\n if (glaStatus.status === 'on-band') bandDist[bandIdx].onBand++;\n else if (glaStatus.status === 'adjacent') bandDist[bandIdx].adjacent++;\n else bandDist[bandIdx].offTarget++;\n }\n }\n\n // ---- Complexity heatmap: avg score per [grade band][evaluator] ----\n const hmSums: number[][] = GRADE_BANDS.map(() => complexityIds.map(() => 0));\n const hmCounts: number[][] = GRADE_BANDS.map(() => complexityIds.map(() => 0));\n\n for (const rowResults of byRow.values()) {\n const firstResult = rowResults[0];\n if (!firstResult) continue;\n const bandIdx = gradeToBandIndex(firstResult.grade);\n if (bandIdx === -1) continue;\n\n complexityIds.forEach((evalId, evalIdx) => {\n const r = rowResults.find(x => x.evaluatorId === evalId);\n if (r && r.status === 'success' && r.score) {\n const num = complexityToNumeric(r.score);\n if (num !== undefined) {\n hmSums[bandIdx][evalIdx] += num;\n hmCounts[bandIdx][evalIdx]++;\n }\n }\n });\n }\n\n const heatmapValues: (number | null)[][] = GRADE_BANDS.map((_, bi) =>\n complexityIds.map((_, ei) => {\n const count = hmCounts[bi][ei];\n return count > 0 ? Math.round((hmSums[bi][ei] / count) * 10) / 10 : null;\n })\n );\n\n // ---- Full results rows ----\n const firstRowResults = allRowIndices.length > 0 ? (byRow.get(allRowIndices[0]) ?? []) : [];\n const originalColumns = firstRowResults.length > 0 ? Object.keys(firstRowResults[0].originalRow) : [];\n\n const fullResultsRows = allRowIndices.map(rowIndex => {\n const rowResults = byRow.get(rowIndex)!;\n const firstResult = rowResults[0];\n const row: Record<string, string> = {};\n\n for (const col of originalColumns) {\n row[col] = String(firstResult.originalRow[col] ?? '');\n }\n\n const glaStatus = rowGLAStatus.get(rowIndex);\n const glaLabels = { 'on-band': 'On Band', 'adjacent': 'Adjacent', 'off-target': 'Off Target' } as const;\n row['__gla_status'] = glaStatus ? glaLabels[glaStatus.status] : (hasGLA ? 'Error' : '');\n row['__gla_band'] = glaStatus?.band ?? '';\n row['__gla_reasoning'] = glaStatus?.reasoning ?? '';\n\n for (const evalId of complexityIds) {\n const r = rowResults.find(x => x.evaluatorId === evalId);\n const prefix = `__${evalId.replace(/-/g, '_')}`;\n row[`${prefix}_score`] = r?.status === 'success' ? (r.score ?? '') : (r?.status === 'error' ? 'Error' : '');\n row[`${prefix}_reasoning`] = r?.status === 'success' ? (r.reasoning ?? '') : (r?.error ?? '');\n }\n\n return row;\n });\n\n // ---- Assemble report data ----\n const reportData = {\n meta: {\n reportId: meta.reportId,\n generatedAt: meta.generatedAt.toLocaleString('en-US', {\n month: 'short', day: 'numeric', year: 'numeric',\n hour: 'numeric', minute: '2-digit', hour12: true,\n }),\n csvPath: meta.csvPath,\n groupId: meta.groupId,\n evaluatorIds: allEvaluatorIds,\n evaluatorNames: allEvaluatorIds.map(evaluatorDisplayName),\n totalRows: meta.totalInputRows,\n processedRows,\n erroredRows,\n },\n gradeLevelStats: {\n onBand: glaCounts.onBand,\n adjacent: glaCounts.adjacent,\n offTarget: glaCounts.offTarget,\n onBandPct: pct(glaCounts.onBand),\n adjacentPct: pct(glaCounts.adjacent),\n offTargetPct: pct(glaCounts.offTarget),\n hasData: glaTotal > 0,\n },\n complexityStats,\n gradeBandDistribution: {\n bands: [...GRADE_BANDS],\n data: bandDist,\n },\n complexityHeatmap: {\n bands: [...GRADE_BANDS],\n evaluators: complexityIds.map(evaluatorDisplayName),\n evaluatorIds: complexityIds,\n values: heatmapValues,\n },\n insights: generateInsights(),\n fullResults: {\n originalColumns,\n hasGLA,\n complexityEvaluators: complexityIds.map(id => ({\n evaluatorId: id,\n name: evaluatorDisplayName(id),\n prefix: id.replace(/-/g, '_'),\n })),\n rows: fullResultsRows,\n },\n };\n\n // Inject serialized data into the template.\n // Unicode-escape < > & so the JSON is safe inside a <script> tag even if\n // the data contains HTML-like strings (prevents </script> injection).\n const safeJson = JSON.stringify(reportData)\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026');\n\n const INJECTION_MARKER = 'var REPORT_DATA = null; // __REPLACED_BY_FORMATTER__';\n if (!reportTemplate.includes(INJECTION_MARKER)) {\n throw new Error('Report template injection marker not found — template may be corrupted');\n }\n\n return reportTemplate.replace(INJECTION_MARKER, `var REPORT_DATA = ${safeJson};`);\n}\n"]}