lean-spec 0.2.8 → 0.2.9-dev.20251205030455

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/utils/safe-output.ts","../src/utils/ui.ts","../src/validators/frontmatter.ts","../src/validators/structure.ts","../src/validators/corruption.ts","../../core/src/parsers/frontmatter.ts","../../core/src/parsers/markdown-parser.ts","../../core/src/utils/token-counter.ts","../../core/src/validators/complexity.ts","../../core/src/utils/dependency-graph.ts","../../core/src/search/scoring.ts","../../core/src/search/context.ts","../../core/src/search/query-parser.ts","../../core/src/search/engine.ts","../src/validators/sub-spec.ts","../src/validators/dependency-alignment.ts","../src/utils/colors.ts","../src/utils/validate-formatter.ts","../src/commands/validate.ts"],"names":["matter","yaml","path","highlights","start","path2","chalk","errorCount","warningCount","path3","fs2"],"mappings":"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","file":"chunk-CJMVV46H.js","sourcesContent":["import chalk from 'chalk';\nimport stripAnsi from 'strip-ansi';\n\n/**\n * Sanitizes user input by stripping all ANSI escape sequences\n * and control characters that could be used for injection attacks.\n * \n * This prevents:\n * - ANSI injection attacks\n * - Terminal escape sequence abuse\n * - Output manipulation\n * \n * @param input - The untrusted user input to sanitize\n * @returns Sanitized string safe for display\n */\nexport function sanitizeUserInput(input: string): string {\n // Handle non-string or falsy values explicitly\n if (typeof input !== 'string') {\n return '';\n }\n \n if (!input) {\n return '';\n }\n \n // First strip any existing ANSI codes\n let sanitized = stripAnsi(input);\n \n // Remove control characters (except newlines, tabs, and carriage returns which might be intended)\n // This regex removes characters in ranges:\n // \\x00-\\x08 (NULL through BACKSPACE)\n // \\x0B-\\x0C (vertical tab, form feed)\n // \\x0E-\\x1F (shift out through unit separator)\n // \\x7F (DELETE)\n sanitized = sanitized.replace(/[\\x00-\\x08\\x0B-\\x0C\\x0E-\\x1F\\x7F]/g, '');\n \n return sanitized;\n}\n\n/**\n * Strips ANSI escape sequences from a string.\n * This is a direct wrapper around strip-ansi for convenience.\n * \n * @param text - The text to strip ANSI codes from\n * @returns Text without ANSI codes\n */\nexport function stripAnsiCodes(text: string): string {\n return stripAnsi(text);\n}\n\n/**\n * Safely logs a message with optional user content.\n * \n * @param message - The message to log (can include user content that will be sanitized)\n */\nexport function safeLog(message: string): void {\n // Sanitize the entire message to handle any user content within it\n console.log(sanitizeUserInput(message));\n}\n\n/**\n * Safely displays a success message with optional user content\n * \n * @param message - The static message template\n * @param userContent - Optional user-provided content to sanitize\n */\nexport function safeSuccess(message: string, userContent?: string): void {\n const fullMessage = userContent \n ? `${message} ${sanitizeUserInput(userContent)}`\n : message;\n console.log(chalk.green(`✓ ${fullMessage}`));\n}\n\n/**\n * Safely displays an error message with optional user content\n * \n * @param message - The static message template\n * @param userContent - Optional user-provided content to sanitize\n */\nexport function safeError(message: string, userContent?: string): void {\n const fullMessage = userContent \n ? `${message} ${sanitizeUserInput(userContent)}`\n : message;\n console.error(chalk.red(`✗ ${fullMessage}`));\n}\n\n/**\n * Safely displays a warning message with optional user content\n * \n * @param message - The static message template\n * @param userContent - Optional user-provided content to sanitize\n */\nexport function safeWarn(message: string, userContent?: string): void {\n const fullMessage = userContent \n ? `${message} ${sanitizeUserInput(userContent)}`\n : message;\n console.log(chalk.yellow(`⚠ ${fullMessage}`));\n}\n\n/**\n * Safely displays an info message with optional user content\n * \n * @param message - The static message template\n * @param userContent - Optional user-provided content to sanitize\n */\nexport function safeInfo(message: string, userContent?: string): void {\n const fullMessage = userContent \n ? `${message} ${sanitizeUserInput(userContent)}`\n : message;\n console.log(chalk.blue(`ℹ ${fullMessage}`));\n}\n\n/**\n * Safely displays a heading with user content\n * \n * @param text - The heading text (should be sanitized if user-provided)\n * @param isUserProvided - Whether the text comes from user input\n */\nexport function safeHeading(text: string, isUserProvided = false): void {\n const safeText = isUserProvided ? sanitizeUserInput(text) : text;\n console.log('');\n console.log(chalk.green.bold(safeText));\n console.log('');\n}\n\n/**\n * Safely displays a subheading with user content\n * \n * @param text - The subheading text (should be sanitized if user-provided)\n * @param isUserProvided - Whether the text comes from user input\n */\nexport function safeSubheading(text: string, isUserProvided = false): void {\n const safeText = isUserProvided ? sanitizeUserInput(text) : text;\n console.log(chalk.cyan.bold(safeText));\n}\n\n/**\n * Safely displays a hint/tip with user content\n * \n * @param message - The hint message (should be sanitized if user-provided)\n * @param isUserProvided - Whether the message comes from user input\n */\nexport function safeHint(message: string, isUserProvided = false): void {\n const safeMessage = isUserProvided ? sanitizeUserInput(message) : message;\n console.log(chalk.gray(`💡 Tip: ${safeMessage}`));\n}\n","import ora, { Ora } from 'ora';\nimport chalk from 'chalk';\nimport { sanitizeUserInput } from './safe-output.js';\n\n/**\n * Show a spinner while executing an async operation\n */\nexport async function withSpinner<T>(\n text: string,\n fn: () => Promise<T>,\n options?: {\n successText?: string;\n failText?: string;\n }\n): Promise<T> {\n const spinner = ora(text).start();\n \n try {\n const result = await fn();\n spinner.succeed(options?.successText || text);\n return result;\n } catch (error) {\n spinner.fail(options?.failText || `${text} failed`);\n throw error;\n }\n}\n\n/**\n * Create a spinner instance for manual control\n */\nexport function createSpinner(text: string): Ora {\n return ora(text);\n}\n\n/**\n * Display a success message\n * Note: If message contains user input, it should be pre-sanitized or passed separately\n */\nexport function success(message: string): void {\n console.log(chalk.green(`✓ ${message}`));\n}\n\n/**\n * Display an error message\n * Note: If message contains user input, it should be pre-sanitized or passed separately\n */\nexport function error(message: string): void {\n console.error(chalk.red(`✗ ${message}`));\n}\n\n/**\n * Display a warning message\n * Note: If message contains user input, it should be pre-sanitized or passed separately\n */\nexport function warning(message: string): void {\n console.log(chalk.yellow(`⚠ ${message}`));\n}\n\n/**\n * Display an info message\n * Note: If message contains user input, it should be pre-sanitized or passed separately\n */\nexport function info(message: string): void {\n console.log(chalk.blue(`ℹ ${message}`));\n}\n\n/**\n * Display a heading\n * Note: If text contains user input, it should be pre-sanitized or passed separately\n */\nexport function heading(text: string): void {\n console.log('');\n console.log(chalk.green.bold(text));\n console.log('');\n}\n\n/**\n * Display a subheading\n * Note: If text contains user input, it should be pre-sanitized or passed separately\n */\nexport function subheading(text: string): void {\n console.log(chalk.cyan.bold(text));\n}\n\n/**\n * Display a hint/tip\n * Note: If message contains user input, it should be pre-sanitized or passed separately\n */\nexport function hint(message: string): void {\n console.log(chalk.gray(`💡 Tip: ${message}`));\n}\n\n/**\n * Helper to sanitize user input before display\n * This is exported for convenience when building messages that include user input\n */\nexport { sanitizeUserInput };\n","/**\n * Frontmatter validator - validates spec frontmatter for quality issues\n * \n * Phase 1b: Frontmatter Validation\n * - Required fields: status, created\n * - Valid status values: planned, in-progress, complete, archived\n * - Valid priority values: low, medium, high, critical\n * - Date format validation (ISO 8601)\n * - Tags format validation (array of strings)\n */\n\nimport type { ValidationRule, ValidationResult, ValidationError, ValidationWarning } from '../utils/validation-framework.js';\nimport type { SpecInfo } from '../spec-loader.js';\nimport type { SpecStatus, SpecPriority } from '../frontmatter.js';\nimport matter from 'gray-matter';\nimport yaml from 'js-yaml';\n\nexport interface FrontmatterOptions {\n // Allow customization of valid values (future use)\n validStatuses?: SpecStatus[];\n validPriorities?: SpecPriority[];\n}\n\nexport class FrontmatterValidator implements ValidationRule {\n name = 'frontmatter';\n description = 'Validate spec frontmatter for required fields and valid values';\n\n private validStatuses: SpecStatus[];\n private validPriorities: SpecPriority[];\n\n constructor(options: FrontmatterOptions = {}) {\n this.validStatuses = options.validStatuses ?? ['planned', 'in-progress', 'complete', 'archived'];\n this.validPriorities = options.validPriorities ?? ['low', 'medium', 'high', 'critical'];\n }\n\n validate(spec: SpecInfo, content: string): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n // Parse frontmatter\n let parsed;\n try {\n parsed = matter(content, {\n engines: {\n yaml: (str) => yaml.load(str, { schema: yaml.FAILSAFE_SCHEMA }) as Record<string, unknown>\n }\n });\n } catch (error) {\n errors.push({\n message: 'Failed to parse frontmatter YAML',\n suggestion: 'Check for YAML syntax errors in frontmatter',\n });\n return { passed: false, errors, warnings };\n }\n\n const frontmatter = parsed.data;\n\n // Check if frontmatter exists\n if (!frontmatter || Object.keys(frontmatter).length === 0) {\n errors.push({\n message: 'No frontmatter found',\n suggestion: 'Add YAML frontmatter at the top of the file between --- delimiters',\n });\n return { passed: false, errors, warnings };\n }\n\n // Required field: status\n if (!frontmatter.status) {\n errors.push({\n message: 'Missing required field: status',\n suggestion: 'Add status field (valid values: planned, in-progress, complete, archived)',\n });\n } else {\n // Validate status value\n const statusStr = String(frontmatter.status);\n if (!this.validStatuses.includes(statusStr as SpecStatus)) {\n errors.push({\n message: `Invalid status: \"${statusStr}\"`,\n suggestion: `Valid values: ${this.validStatuses.join(', ')}`,\n });\n }\n }\n\n // Required field: created\n if (!frontmatter.created) {\n errors.push({\n message: 'Missing required field: created',\n suggestion: 'Add created field with date in YYYY-MM-DD format',\n });\n } else {\n // Validate created date format\n const dateValidation = this.validateDateField(frontmatter.created, 'created');\n if (!dateValidation.valid) {\n errors.push({\n message: dateValidation.message!,\n suggestion: dateValidation.suggestion,\n });\n }\n }\n\n // Optional field: priority (validate if present)\n if (frontmatter.priority) {\n const priorityStr = String(frontmatter.priority);\n if (!this.validPriorities.includes(priorityStr as SpecPriority)) {\n errors.push({\n message: `Invalid priority: \"${priorityStr}\"`,\n suggestion: `Valid values: ${this.validPriorities.join(', ')}`,\n });\n }\n }\n\n // Optional field: tags (validate if present)\n if (frontmatter.tags !== undefined && frontmatter.tags !== null) {\n if (!Array.isArray(frontmatter.tags)) {\n errors.push({\n message: 'Field \"tags\" must be an array',\n suggestion: 'Use array format: tags: [tag1, tag2]',\n });\n }\n // Note: We don't strictly validate tag types as YAML may parse numbers/booleans\n // This is acceptable as they'll be coerced to strings when used\n }\n\n // Validate other date fields if present\n const dateFields = ['updated', 'completed', 'due'];\n for (const field of dateFields) {\n if (frontmatter[field]) {\n const dateValidation = this.validateDateField(frontmatter[field], field);\n if (!dateValidation.valid) {\n warnings.push({\n message: dateValidation.message!,\n suggestion: dateValidation.suggestion,\n });\n }\n }\n }\n\n return {\n passed: errors.length === 0,\n errors,\n warnings,\n };\n }\n\n /**\n * Validate date field format (ISO 8601: YYYY-MM-DD or full timestamp)\n */\n private validateDateField(value: unknown, fieldName: string): {\n valid: boolean;\n message?: string;\n suggestion?: string;\n } {\n // Handle Date objects (gray-matter auto-parses dates)\n if (value instanceof Date) {\n return { valid: true };\n }\n\n if (typeof value !== 'string') {\n return {\n valid: false,\n message: `Field \"${fieldName}\" must be a string or date`,\n suggestion: 'Use YYYY-MM-DD format (e.g., 2025-11-05)',\n };\n }\n\n // Check for ISO 8601 date format (YYYY-MM-DD) or full timestamp\n // Be lenient: accept YYYY-MM-DD or timestamps with/without milliseconds and timezone\n const isoDateRegex = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,3})?(Z|[+-]\\d{2}:\\d{2})?)?$/;\n if (!isoDateRegex.test(value)) {\n return {\n valid: false,\n message: `Field \"${fieldName}\" has invalid date format: \"${value}\"`,\n suggestion: 'Use ISO 8601 format: YYYY-MM-DD (e.g., 2025-11-05)',\n };\n }\n\n // Validate the date is actually valid (not 2025-99-99)\n const date = new Date(value);\n if (isNaN(date.getTime())) {\n return {\n valid: false,\n message: `Field \"${fieldName}\" has invalid date: \"${value}\"`,\n suggestion: 'Ensure date is valid (e.g., month 01-12, day 01-31)',\n };\n }\n\n return { valid: true };\n }\n}\n","/**\n * Structure validator - validates spec structure and required sections\n * \n * Phase 2: Structure Validation\n * - Must have title (H1 heading)\n * - Must have required sections\n * - No empty required sections\n * - No duplicate section headers at same level\n */\n\nimport * as path from 'node:path';\nimport type { ValidationRule, ValidationResult, ValidationError, ValidationWarning } from '../utils/validation-framework.js';\nimport type { SpecInfo } from '../spec-loader.js';\nimport matter from 'gray-matter';\n\nexport interface StructureOptions {\n // Required section names (H2 level)\n requiredSections?: string[];\n // Allow custom section validation\n strict?: boolean;\n}\n\nexport class StructureValidator implements ValidationRule {\n name = 'structure';\n description = 'Validate spec structure and required sections';\n\n private requiredSections: string[];\n private strict: boolean;\n\n constructor(options: StructureOptions = {}) {\n // Default required sections based on common spec patterns\n this.requiredSections = options.requiredSections ?? ['Overview', 'Design'];\n this.strict = options.strict ?? false;\n }\n\n async validate(spec: SpecInfo, content: string): Promise<ValidationResult> {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n // Parse content to separate frontmatter from body\n let parsed;\n try {\n parsed = matter(content);\n } catch (error) {\n errors.push({\n message: 'Failed to parse frontmatter',\n suggestion: 'Check YAML frontmatter syntax',\n });\n return { passed: false, errors, warnings };\n }\n\n const body = parsed.content;\n\n // Check for H1 title\n const h1Match = body.match(/^#\\s+(.+)$/m);\n if (!h1Match) {\n errors.push({\n message: 'Missing H1 title (# Heading)',\n suggestion: 'Add a title as the first heading in the spec',\n });\n }\n\n // Extract all headings\n const headings = this.extractHeadings(body);\n\n // Skip checking for required sections - too verbose and not critical\n // Skip checking for empty sections - too verbose and not critical\n\n // Check for duplicate headers at same level\n const duplicates = this.findDuplicateHeaders(headings);\n for (const dup of duplicates) {\n errors.push({\n message: `Duplicate section header: ${'#'.repeat(dup.level)} ${dup.text}`,\n suggestion: 'Remove or rename duplicate section headers',\n });\n }\n\n return {\n passed: errors.length === 0,\n errors,\n warnings,\n };\n }\n\n /**\n * Extract all headings from markdown content (excluding code blocks)\n */\n private extractHeadings(content: string): Array<{ level: number; text: string; line: number }> {\n const headings: Array<{ level: number; text: string; line: number }> = [];\n const lines = content.split('\\n');\n \n let inCodeBlock = false;\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n \n // Track code block boundaries\n if (line.trim().startsWith('```')) {\n inCodeBlock = !inCodeBlock;\n continue;\n }\n \n // Skip lines inside code blocks\n if (inCodeBlock) {\n continue;\n }\n \n const match = line.match(/^(#{1,6})\\s+(.+)$/);\n if (match) {\n headings.push({\n level: match[1].length,\n text: match[2].trim(),\n line: i + 1,\n });\n }\n }\n \n return headings;\n }\n\n /**\n * Find empty sections (sections with no content until next heading)\n */\n private findEmptySections(content: string, headings: Array<{ level: number; text: string; line: number }>): string[] {\n const emptySections: string[] = [];\n const lines = content.split('\\n');\n\n for (let i = 0; i < headings.length; i++) {\n const heading = headings[i];\n \n // Only check H2 sections\n if (heading.level !== 2) {\n continue;\n }\n\n // Find the next heading at the same or higher level (end of this section)\n let nextSameLevelIndex = i + 1;\n while (nextSameLevelIndex < headings.length && headings[nextSameLevelIndex].level > heading.level) {\n nextSameLevelIndex++;\n }\n \n const nextHeading = headings[nextSameLevelIndex];\n \n // Get content between this heading and next same-level heading\n const startLine = heading.line;\n const endLine = nextHeading ? nextHeading.line - 1 : lines.length;\n \n // Extract content lines (excluding the heading itself)\n const sectionLines = lines.slice(startLine, endLine);\n \n // Check if section has any subsections\n const hasSubsections = headings.some((h, idx) => \n idx > i && \n idx < nextSameLevelIndex && \n h.level > heading.level\n );\n \n // If there are subsections, the section is not empty\n if (hasSubsections) {\n continue;\n }\n \n // Check if section is empty (only whitespace or comments)\n const hasContent = sectionLines.some(line => {\n const trimmed = line.trim();\n return trimmed.length > 0 && !trimmed.startsWith('<!--') && !trimmed.startsWith('//');\n });\n\n if (!hasContent) {\n emptySections.push(heading.text);\n }\n }\n\n return emptySections;\n }\n\n /**\n * Find duplicate headers at the same level\n */\n private findDuplicateHeaders(headings: Array<{ level: number; text: string; line: number }>): Array<{ level: number; text: string }> {\n const seen = new Map<string, number>();\n const duplicates: Array<{ level: number; text: string }> = [];\n\n for (const heading of headings) {\n const key = `${heading.level}:${heading.text.toLowerCase()}`;\n const count = seen.get(key) ?? 0;\n seen.set(key, count + 1);\n\n if (count === 1) {\n // Found a duplicate (second occurrence)\n duplicates.push({ level: heading.level, text: heading.text });\n }\n }\n\n return duplicates;\n }\n}\n","/**\n * Corruption validator - detects file corruption from failed edits\n * \n * Focus on visually apparent corruption that breaks rendering:\n * - Unclosed code blocks (breaks syntax highlighting)\n * - Unclosed formatting in actual content (not code blocks)\n * - Duplicate content blocks (merge artifacts, failed edits)\n * \n * Intentionally excludes:\n * - YAML/JSON validation (code examples often show invalid syntax)\n */\n\nimport type { ValidationRule, ValidationResult, ValidationError, ValidationWarning } from '../utils/validation-framework.js';\nimport type { SpecInfo } from '../spec-loader.js';\n\n/**\n * Represents a code block range in the document\n */\ninterface CodeBlockRange {\n start: number; // Line number (1-indexed)\n end: number; // Line number (1-indexed)\n}\n\nexport interface CorruptionOptions {\n // Enable/disable specific checks\n checkCodeBlocks?: boolean;\n checkMarkdownStructure?: boolean;\n checkDuplicateContent?: boolean;\n // Duplicate detection tuning (reduced false positives)\n duplicateBlockSize?: number; // Lines to match (default: 8)\n duplicateMinLength?: number; // Min chars (default: 200)\n}\n\nexport class CorruptionValidator implements ValidationRule {\n name = 'corruption';\n description = 'Detect file corruption from failed edits';\n\n private options: Required<CorruptionOptions>;\n\n constructor(options: CorruptionOptions = {}) {\n this.options = {\n checkCodeBlocks: options.checkCodeBlocks ?? true,\n checkMarkdownStructure: options.checkMarkdownStructure ?? true,\n checkDuplicateContent: options.checkDuplicateContent ?? true,\n duplicateBlockSize: options.duplicateBlockSize ?? 8,\n duplicateMinLength: options.duplicateMinLength ?? 200,\n };\n }\n\n validate(_spec: SpecInfo, content: string): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n // Parse code block ranges once for reuse\n const codeBlockRanges = this.parseCodeBlockRanges(content);\n\n // Check code blocks (unclosed blocks)\n if (this.options.checkCodeBlocks) {\n const codeBlockErrors = this.validateCodeBlocks(content);\n errors.push(...codeBlockErrors);\n }\n\n // Check markdown structure (but exclude code blocks)\n if (this.options.checkMarkdownStructure) {\n const markdownErrors = this.validateMarkdownStructure(content, codeBlockRanges);\n errors.push(...markdownErrors);\n }\n\n // Check for duplicate content (but exclude code blocks)\n if (this.options.checkDuplicateContent) {\n const duplicateWarnings = this.detectDuplicateContent(content);\n warnings.push(...duplicateWarnings);\n }\n\n return {\n passed: errors.length === 0,\n errors,\n warnings,\n };\n }\n\n /**\n * Parse all code block ranges in the document\n * Returns array of {start, end} line numbers (1-indexed)\n */\n private parseCodeBlockRanges(content: string): CodeBlockRange[] {\n const ranges: CodeBlockRange[] = [];\n const lines = content.split('\\n');\n \n let inCodeBlock = false;\n let blockStart = -1;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line.trim().startsWith('```')) {\n if (!inCodeBlock) {\n inCodeBlock = true;\n blockStart = i + 1; // 1-indexed\n } else {\n ranges.push({\n start: blockStart,\n end: i + 1 // 1-indexed, inclusive\n });\n inCodeBlock = false;\n blockStart = -1;\n }\n }\n }\n\n return ranges;\n }\n\n /**\n * Check if a line number is inside a code block\n */\n private isInCodeBlock(lineNumber: number, codeBlockRanges: CodeBlockRange[]): boolean {\n return codeBlockRanges.some(\n range => lineNumber >= range.start && lineNumber <= range.end\n );\n }\n\n /**\n * Get content outside code blocks for analysis\n */\n private getContentOutsideCodeBlocks(content: string, codeBlockRanges: CodeBlockRange[]): string {\n const lines = content.split('\\n');\n const filteredLines = lines.filter((_, index) => {\n const lineNumber = index + 1; // 1-indexed\n return !this.isInCodeBlock(lineNumber, codeBlockRanges);\n });\n return filteredLines.join('\\n');\n }\n\n /**\n * Validate code blocks are properly closed\n * This is the #1 indicator of corruption - causes visible syntax highlighting issues\n */\n private validateCodeBlocks(content: string): ValidationError[] {\n const errors: ValidationError[] = [];\n const lines = content.split('\\n');\n \n let inCodeBlock = false;\n let codeBlockStartLine = -1;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line.trim().startsWith('```')) {\n if (!inCodeBlock) {\n inCodeBlock = true;\n codeBlockStartLine = i + 1;\n } else {\n inCodeBlock = false;\n codeBlockStartLine = -1;\n }\n }\n }\n\n // If still in code block at end, it's unclosed\n if (inCodeBlock) {\n errors.push({\n message: `Unclosed code block starting at line ${codeBlockStartLine}`,\n suggestion: 'Add closing ``` to complete the code block',\n });\n }\n\n return errors;\n }\n\n /**\n * Detect duplicate content blocks\n * Improved tuning to reduce false positives\n * \n * Thresholds:\n * - Block size: 8 lines - requires substantial duplication\n * - Min length: 200 chars - ignores short similar sections\n * - Filters overlapping windows - prevents adjacent line false positives\n */\n private detectDuplicateContent(content: string): ValidationWarning[] {\n const warnings: ValidationWarning[] = [];\n \n const lines = content.split('\\n');\n \n // Look for significant duplicate blocks\n const blockSize = this.options.duplicateBlockSize!;\n const minLength = this.options.duplicateMinLength!;\n const blocks = new Map<string, number[]>();\n\n for (let i = 0; i <= lines.length - blockSize; i++) {\n const block = lines.slice(i, i + blockSize)\n .map(l => l.trim())\n .filter(l => l.length > 0)\n .join('\\n');\n\n if (block.length >= minLength) { // Only check substantial blocks\n if (!blocks.has(block)) {\n blocks.set(block, []);\n }\n blocks.get(block)!.push(i + 1); // Store 1-indexed line number\n }\n }\n\n // Report blocks that appear multiple times\n // Filter out overlapping detections (false positives from sliding window)\n for (const [block, lineNumbers] of blocks.entries()) {\n if (lineNumbers.length > 1) {\n // Remove line numbers that are within blockSize of each other\n // (these are overlapping windows, not true duplicates)\n const nonOverlapping: number[] = [];\n for (const lineNum of lineNumbers) {\n const isOverlapping = nonOverlapping.some(\n existing => Math.abs(existing - lineNum) < blockSize\n );\n if (!isOverlapping) {\n nonOverlapping.push(lineNum);\n }\n }\n \n // Only report if we still have multiple non-overlapping occurrences\n if (nonOverlapping.length > 1) {\n warnings.push({\n message: `Duplicate content block found at lines: ${nonOverlapping.join(', ')}`,\n suggestion: 'Check for merge artifacts or failed edits',\n });\n }\n }\n }\n\n return warnings;\n }\n\n /**\n * Validate markdown structure (excluding code blocks)\n * Only checks actual content for formatting issues\n */\n private validateMarkdownStructure(content: string, codeBlockRanges: CodeBlockRange[]): ValidationError[] {\n const errors: ValidationError[] = [];\n\n // Get content outside code blocks\n const contentOutsideCodeBlocks = this.getContentOutsideCodeBlocks(content, codeBlockRanges);\n\n // Remove list markers first (before checking asterisks)\n const lines = contentOutsideCodeBlocks.split('\\n');\n const linesWithoutListMarkers = lines.map(line => {\n const trimmed = line.trim();\n // Replace list markers: \"- item\" or \"* item\" or \"+ item\"\n if (trimmed.match(/^[-*+]\\s/)) {\n return line.replace(/^(\\s*)([-*+]\\s)/, '$1 '); // Replace marker with spaces\n }\n return line;\n });\n let contentWithoutListMarkers = linesWithoutListMarkers.join('\\n');\n\n // Also remove inline code (backticks) which might contain asterisks\n // Replace `code` with empty string to exclude from asterisk counting\n contentWithoutListMarkers = contentWithoutListMarkers.replace(/`[^`]*`/g, '');\n\n // Check for unclosed formatting\n const boldMatches = contentWithoutListMarkers.match(/\\*\\*/g) || [];\n \n // For italic, count single asterisks that are not part of bold\n // Split by ** first, then count * in the remaining text\n const withoutBold = contentWithoutListMarkers.split('**').join('');\n const italicMatches = withoutBold.match(/\\*/g) || [];\n \n if (boldMatches.length % 2 !== 0) {\n errors.push({\n message: 'Unclosed bold formatting (**)',\n suggestion: 'Check for missing closing ** in markdown content (not code blocks)',\n });\n }\n\n if (italicMatches.length % 2 !== 0) {\n errors.push({\n message: 'Unclosed italic formatting (*)',\n suggestion: 'Check for missing closing * in markdown content (not code blocks)',\n });\n }\n\n return errors;\n }\n}\n","/**\n * Frontmatter parsing and manipulation (platform-independent)\n */\nimport matter from 'gray-matter';\nimport yaml from 'js-yaml';\nimport type { SpecFrontmatter, SpecStatus, SpecPriority, StatusTransition, SpecFilterOptions, LeanSpecConfig } from '../types/index.js';\n\n/**\n * Convert Date objects to YYYY-MM-DD string format\n * (gray-matter auto-parses YYYY-MM-DD strings as Date objects)\n */\nexport function normalizeDateFields(data: Record<string, unknown>): void {\n const dateFields = ['created', 'completed', 'updated', 'due'];\n \n for (const field of dateFields) {\n if (data[field] instanceof Date) {\n data[field] = (data[field] as Date).toISOString().split('T')[0];\n }\n }\n}\n\n/**\n * Enrich frontmatter with timestamps for velocity tracking\n * Auto-generates timestamps when missing and tracks status transitions\n */\nexport function enrichWithTimestamps(\n data: Record<string, unknown>,\n previousData?: Record<string, unknown>\n): void {\n const now = new Date().toISOString();\n\n // Set created_at if missing - always use current timestamp\n // Do NOT infer from created date field since that's just YYYY-MM-DD without time\n if (!data.created_at) {\n data.created_at = now;\n }\n\n // Update updated_at on any change (if previousData exists)\n if (previousData) {\n data.updated_at = now;\n }\n\n // Set completed_at when status changes to complete\n if (\n data.status === 'complete' &&\n previousData?.status !== 'complete' &&\n !data.completed_at\n ) {\n data.completed_at = now;\n // Also set the completed date field\n if (!data.completed) {\n data.completed = new Date().toISOString().split('T')[0];\n }\n }\n\n // Track status transition (optional)\n if (previousData && data.status !== previousData.status) {\n if (!Array.isArray(data.transitions)) {\n data.transitions = [];\n }\n (data.transitions as StatusTransition[]).push({\n status: data.status as SpecStatus,\n at: now,\n });\n }\n}\n\n/**\n * Normalize tags field - parse JSON strings into arrays\n * Handles cases where AI accidentally creates tags as '[\"..\",\"..\"]' strings\n */\nexport function normalizeTagsField(data: Record<string, unknown>): void {\n if (data.tags && typeof data.tags === 'string') {\n try {\n // Try to parse as JSON array\n const parsed = JSON.parse(data.tags as string);\n if (Array.isArray(parsed)) {\n data.tags = parsed;\n }\n } catch {\n // If not valid JSON, treat as comma-separated string\n data.tags = (data.tags as string).split(',').map(t => t.trim());\n }\n }\n}\n\n/**\n * Validate and coerce custom field types\n */\nexport function validateCustomField(\n value: unknown,\n expectedType: 'string' | 'number' | 'boolean' | 'array'\n): { valid: boolean; coerced?: unknown; error?: string } {\n switch (expectedType) {\n case 'string':\n if (typeof value === 'string') {\n return { valid: true, coerced: value };\n }\n // Coerce to string\n return { valid: true, coerced: String(value) };\n \n case 'number':\n if (typeof value === 'number') {\n return { valid: true, coerced: value };\n }\n // Try to coerce to number\n const num = Number(value);\n if (!isNaN(num)) {\n return { valid: true, coerced: num };\n }\n return { valid: false, error: `Cannot convert '${value}' to number` };\n \n case 'boolean':\n if (typeof value === 'boolean') {\n return { valid: true, coerced: value };\n }\n // Coerce string to boolean\n if (value === 'true' || value === 'yes' || value === '1') {\n return { valid: true, coerced: true };\n }\n if (value === 'false' || value === 'no' || value === '0') {\n return { valid: true, coerced: false };\n }\n return { valid: false, error: `Cannot convert '${value}' to boolean` };\n \n case 'array':\n if (Array.isArray(value)) {\n return { valid: true, coerced: value };\n }\n return { valid: false, error: `Expected array but got ${typeof value}` };\n \n default:\n return { valid: false, error: `Unknown type: ${expectedType}` };\n }\n}\n\n/**\n * Validate custom fields according to config\n */\nexport function validateCustomFields(\n frontmatter: Record<string, unknown>,\n config?: LeanSpecConfig\n): Record<string, unknown> {\n if (!config?.frontmatter?.custom) {\n return frontmatter;\n }\n \n const result = { ...frontmatter };\n \n for (const [fieldName, expectedType] of Object.entries(config.frontmatter.custom)) {\n if (fieldName in result) {\n const validation = validateCustomField(result[fieldName], expectedType);\n if (validation.valid) {\n result[fieldName] = validation.coerced;\n } else {\n console.warn(`Warning: Invalid custom field '${fieldName}': ${validation.error}`);\n }\n }\n }\n \n return result;\n}\n\n/**\n * Parse frontmatter from markdown content string\n */\nexport function parseFrontmatterFromString(\n content: string,\n filePath?: string,\n config?: LeanSpecConfig\n): SpecFrontmatter | null {\n try {\n const parsed = matter(content, {\n engines: {\n yaml: (str) => yaml.load(str, { schema: yaml.FAILSAFE_SCHEMA }) as Record<string, unknown>\n }\n });\n\n if (!parsed.data || Object.keys(parsed.data).length === 0) {\n // No frontmatter found, try fallback to inline fields\n return parseFallbackFields(content);\n }\n\n // Validate required fields\n if (!parsed.data.status) {\n if (filePath) console.warn(`Warning: Missing required field 'status' in ${filePath}`);\n return null;\n }\n\n if (!parsed.data.created) {\n if (filePath) console.warn(`Warning: Missing required field 'created' in ${filePath}`);\n return null;\n }\n\n // Validate status enum\n const validStatuses: SpecStatus[] = ['planned', 'in-progress', 'complete', 'archived'];\n if (!validStatuses.includes(parsed.data.status)) {\n if (filePath) {\n console.warn(`Warning: Invalid status '${parsed.data.status}' in ${filePath}. Valid values: ${validStatuses.join(', ')}`);\n }\n }\n\n // Validate priority enum if present\n if (parsed.data.priority) {\n const validPriorities: SpecPriority[] = ['low', 'medium', 'high', 'critical'];\n if (!validPriorities.includes(parsed.data.priority)) {\n if (filePath) {\n console.warn(`Warning: Invalid priority '${parsed.data.priority}' in ${filePath}. Valid values: ${validPriorities.join(', ')}`);\n }\n }\n }\n\n // Normalize tags field (parse JSON strings to arrays)\n normalizeTagsField(parsed.data);\n \n // Warn about unknown fields (informational only)\n const knownFields = [\n 'status', 'created', 'tags', 'priority', 'related', 'depends_on',\n 'updated', 'completed', 'assignee', 'reviewer', 'issue', 'pr', 'epic', 'breaking', 'due',\n 'created_at', 'updated_at', 'completed_at', 'transitions'\n ];\n \n // Add custom fields from config to known fields\n const customFields = config?.frontmatter?.custom ? Object.keys(config.frontmatter.custom) : [];\n const allKnownFields = [...knownFields, ...customFields];\n \n const unknownFields = Object.keys(parsed.data).filter(k => !allKnownFields.includes(k));\n if (unknownFields.length > 0 && filePath) {\n console.warn(`Info: Unknown fields in ${filePath}: ${unknownFields.join(', ')}`);\n }\n \n // Validate and coerce custom fields\n const validatedData = validateCustomFields(parsed.data, config);\n\n return validatedData as SpecFrontmatter;\n } catch (error) {\n console.error(`Error parsing frontmatter${filePath ? ` from ${filePath}` : ''}:`, error);\n return null;\n }\n}\n\n/**\n * Fallback: Parse inline fields from older specs\n */\nfunction parseFallbackFields(content: string): SpecFrontmatter | null {\n const statusMatch = content.match(/\\*\\*Status\\*\\*:\\s*(?:📅\\s*)?(\\w+(?:-\\w+)?)/i);\n const createdMatch = content.match(/\\*\\*Created\\*\\*:\\s*(\\d{4}-\\d{2}-\\d{2})/);\n\n if (statusMatch && createdMatch) {\n const status = statusMatch[1].toLowerCase().replace(/\\s+/g, '-') as SpecStatus;\n const created = createdMatch[1];\n\n return {\n status,\n created,\n };\n }\n\n return null;\n}\n\n/**\n * Create updated frontmatter with changes\n */\nexport function createUpdatedFrontmatter(\n existingContent: string,\n updates: Partial<SpecFrontmatter>\n): { content: string; frontmatter: SpecFrontmatter } {\n const parsed = matter(existingContent, {\n engines: {\n yaml: (str) => yaml.load(str, { schema: yaml.FAILSAFE_SCHEMA }) as Record<string, unknown>\n }\n });\n\n // Store previous data for timestamp enrichment\n const previousData = { ...parsed.data };\n\n // Merge updates with existing data\n const newData = { ...parsed.data, ...updates };\n\n // Ensure date fields remain as strings (gray-matter auto-parses YYYY-MM-DD as Date objects)\n normalizeDateFields(newData);\n\n // Enrich with timestamps\n enrichWithTimestamps(newData, previousData);\n\n // Auto-update timestamps if fields exist (legacy behavior)\n if (updates.status === 'complete' && !newData.completed) {\n newData.completed = new Date().toISOString().split('T')[0];\n }\n\n if ('updated' in parsed.data) {\n newData.updated = new Date().toISOString().split('T')[0];\n }\n\n // Update visual metadata badges in content\n let updatedContent = parsed.content;\n updatedContent = updateVisualMetadata(updatedContent, newData as SpecFrontmatter);\n\n // Stringify back to markdown\n const newContent = matter.stringify(updatedContent, newData);\n \n return {\n content: newContent,\n frontmatter: newData as SpecFrontmatter\n };\n}\n\n/**\n * Update visual metadata badges in content\n */\nfunction updateVisualMetadata(content: string, frontmatter: SpecFrontmatter): string {\n const statusEmoji = getStatusEmojiPlain(frontmatter.status);\n const statusLabel = frontmatter.status.charAt(0).toUpperCase() + frontmatter.status.slice(1).replace('-', ' ');\n \n // Use the created date as-is (already in YYYY-MM-DD format)\n const created = frontmatter.created;\n \n // Build metadata line\n let metadataLine = `> **Status**: ${statusEmoji} ${statusLabel}`;\n \n if (frontmatter.priority) {\n const priorityLabel = frontmatter.priority.charAt(0).toUpperCase() + frontmatter.priority.slice(1);\n metadataLine += ` · **Priority**: ${priorityLabel}`;\n }\n \n metadataLine += ` · **Created**: ${created}`;\n \n if (frontmatter.tags && frontmatter.tags.length > 0) {\n metadataLine += ` · **Tags**: ${frontmatter.tags.join(', ')}`;\n }\n \n // For enterprise template with assignee/reviewer\n let secondLine = '';\n if (frontmatter.assignee || frontmatter.reviewer) {\n const assignee = frontmatter.assignee || 'TBD';\n const reviewer = frontmatter.reviewer || 'TBD';\n secondLine = `\\n> **Assignee**: ${assignee} · **Reviewer**: ${reviewer}`;\n }\n \n // Replace existing metadata block or add after title\n const metadataPattern = /^>\\s+\\*\\*Status\\*\\*:.*(?:\\n>\\s+\\*\\*Assignee\\*\\*:.*)?/m;\n \n if (metadataPattern.test(content)) {\n // Replace existing metadata\n return content.replace(metadataPattern, metadataLine + secondLine);\n } else {\n // Add after title (# title)\n const titleMatch = content.match(/^#\\s+.+$/m);\n if (titleMatch) {\n const insertPos = titleMatch.index! + titleMatch[0].length;\n return content.slice(0, insertPos) + '\\n\\n' + metadataLine + secondLine + '\\n' + content.slice(insertPos);\n }\n }\n \n return content;\n}\n\nfunction getStatusEmojiPlain(status: string): string {\n switch (status) {\n case 'planned': return '📅';\n case 'in-progress': return '⏳';\n case 'complete': return '✅';\n case 'archived': return '📦';\n default: return '📄';\n }\n}\n\n/**\n * Filter specs by criteria\n */\nexport function matchesFilter(frontmatter: SpecFrontmatter, filter: SpecFilterOptions): boolean {\n // Status filter\n if (filter.status) {\n const statuses = Array.isArray(filter.status) ? filter.status : [filter.status];\n if (!statuses.includes(frontmatter.status)) {\n return false;\n }\n }\n\n // Tags filter (spec must have ALL specified tags)\n if (filter.tags && filter.tags.length > 0) {\n if (!frontmatter.tags || frontmatter.tags.length === 0) {\n return false;\n }\n const hasAllTags = filter.tags.every(tag => frontmatter.tags!.includes(tag));\n if (!hasAllTags) {\n return false;\n }\n }\n\n // Priority filter\n if (filter.priority) {\n const priorities = Array.isArray(filter.priority) ? filter.priority : [filter.priority];\n if (!frontmatter.priority || !priorities.includes(frontmatter.priority)) {\n return false;\n }\n }\n\n // Assignee filter\n if (filter.assignee) {\n if (frontmatter.assignee !== filter.assignee) {\n return false;\n }\n }\n\n return true;\n}\n","/**\n * Markdown parser for programmatic spec management\n * \n * Implements spec 059: Programmatic Spec Management\n * \n * This module provides mechanical parsing of markdown structure:\n * - Section detection (headings and their line ranges)\n * - Line extraction/removal/replacement\n * - Basic structure analysis\n * \n * NO semantic analysis - just mechanical operations on text\n */\n\n/**\n * Represents a section in the markdown document\n */\nexport interface Section {\n /** Section title (without the # prefix) */\n title: string;\n /** Heading level (1-6) */\n level: number;\n /** Start line number (1-indexed) */\n startLine: number;\n /** End line number (1-indexed, inclusive) */\n endLine: number;\n /** Line count */\n lineCount: number;\n /** Direct subsections */\n subsections: Section[];\n}\n\n/**\n * Parse markdown content and extract section structure\n */\nexport function parseMarkdownSections(content: string): Section[] {\n const lines = content.split('\\n');\n const sections: Section[] = [];\n const sectionStack: Section[] = [];\n \n let inCodeBlock = false;\n let currentLineNum = 1;\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n currentLineNum = i + 1;\n \n // Track code blocks to ignore headings inside them\n if (line.trimStart().startsWith('```')) {\n inCodeBlock = !inCodeBlock;\n continue;\n }\n \n if (inCodeBlock) {\n continue;\n }\n \n // Detect headings (ATX-style: # heading)\n const headingMatch = line.match(/^(#{1,6})\\s+(.+)$/);\n if (headingMatch) {\n const level = headingMatch[1].length;\n const title = headingMatch[2].trim();\n \n // Close previous sections at same or higher level\n while (sectionStack.length > 0 && sectionStack[sectionStack.length - 1].level >= level) {\n const closedSection = sectionStack.pop()!;\n closedSection.endLine = currentLineNum - 1;\n closedSection.lineCount = closedSection.endLine - closedSection.startLine + 1;\n }\n \n // Create new section\n const newSection: Section = {\n title,\n level,\n startLine: currentLineNum,\n endLine: lines.length, // Will be updated when section closes\n lineCount: 0, // Will be calculated when section closes\n subsections: [],\n };\n \n // Add to parent or root\n if (sectionStack.length > 0) {\n sectionStack[sectionStack.length - 1].subsections.push(newSection);\n } else {\n sections.push(newSection);\n }\n \n sectionStack.push(newSection);\n }\n }\n \n // Close remaining sections\n while (sectionStack.length > 0) {\n const closedSection = sectionStack.pop()!;\n closedSection.endLine = lines.length;\n closedSection.lineCount = closedSection.endLine - closedSection.startLine + 1;\n }\n \n return sections;\n}\n\n/**\n * Find a section by title (case-insensitive, partial match)\n */\nexport function findSection(sections: Section[], titlePattern: string): Section | null {\n const pattern = titlePattern.toLowerCase();\n \n for (const section of sections) {\n if (section.title.toLowerCase().includes(pattern)) {\n return section;\n }\n \n // Search subsections recursively\n const found = findSection(section.subsections, titlePattern);\n if (found) {\n return found;\n }\n }\n \n return null;\n}\n\n/**\n * Flatten section tree to array (depth-first)\n */\nexport function flattenSections(sections: Section[]): Section[] {\n const result: Section[] = [];\n \n for (const section of sections) {\n result.push(section);\n result.push(...flattenSections(section.subsections));\n }\n \n return result;\n}\n\n/**\n * Extract lines from content\n * @param content Full markdown content\n * @param startLine Start line (1-indexed, inclusive)\n * @param endLine End line (1-indexed, inclusive)\n */\nexport function extractLines(content: string, startLine: number, endLine: number): string {\n const lines = content.split('\\n');\n \n // Validate bounds\n if (startLine < 1 || endLine < startLine || startLine > lines.length || endLine > lines.length) {\n throw new Error(`Invalid line range: ${startLine}-${endLine}`);\n }\n \n // Extract (convert to 0-indexed)\n const extracted = lines.slice(startLine - 1, endLine);\n return extracted.join('\\n');\n}\n\n/**\n * Remove lines from content\n * @param content Full markdown content\n * @param startLine Start line (1-indexed, inclusive)\n * @param endLine End line (1-indexed, inclusive)\n */\nexport function removeLines(content: string, startLine: number, endLine: number): string {\n const lines = content.split('\\n');\n \n // Validate bounds\n if (startLine < 1 || endLine < startLine || startLine > lines.length) {\n throw new Error(`Invalid line range: ${startLine}-${endLine}`);\n }\n \n // Remove (convert to 0-indexed)\n lines.splice(startLine - 1, endLine - startLine + 1);\n return lines.join('\\n');\n}\n\n/**\n * Replace lines in content\n * @param content Full markdown content\n * @param startLine Start line (1-indexed, inclusive)\n * @param endLine End line (1-indexed, inclusive)\n * @param replacement Replacement text (can be multi-line)\n */\nexport function replaceLines(content: string, startLine: number, endLine: number, replacement: string): string {\n const lines = content.split('\\n');\n \n // Validate bounds\n if (startLine < 1 || endLine < startLine || startLine > lines.length) {\n throw new Error(`Invalid line range: ${startLine}-${endLine}`);\n }\n \n // Split replacement into lines\n const replacementLines = replacement.split('\\n');\n \n // Replace (convert to 0-indexed)\n lines.splice(startLine - 1, endLine - startLine + 1, ...replacementLines);\n return lines.join('\\n');\n}\n\n/**\n * Count lines in content\n */\nexport function countLines(content: string): number {\n return content.split('\\n').length;\n}\n\n/**\n * Get line at specific line number (1-indexed)\n */\nexport function getLine(content: string, lineNumber: number): string {\n const lines = content.split('\\n');\n \n if (lineNumber < 1 || lineNumber > lines.length) {\n throw new Error(`Invalid line number: ${lineNumber}`);\n }\n \n return lines[lineNumber - 1];\n}\n\n/**\n * Parse markdown structure for analysis\n */\nexport interface MarkdownStructure {\n /** Total line count */\n lines: number;\n /** Section hierarchy */\n sections: Section[];\n /** Flattened sections */\n allSections: Section[];\n /** Section count by level */\n sectionsByLevel: {\n h1: number;\n h2: number;\n h3: number;\n h4: number;\n h5: number;\n h6: number;\n total: number;\n };\n /** Code block count */\n codeBlocks: number;\n /** Maximum nesting depth */\n maxNesting: number;\n}\n\n/**\n * Analyze markdown structure\n */\nexport function analyzeMarkdownStructure(content: string): MarkdownStructure {\n const lines = content.split('\\n');\n const sections = parseMarkdownSections(content);\n const allSections = flattenSections(sections);\n \n // Count sections by level\n const levelCounts = { h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0, total: 0 };\n for (const section of allSections) {\n levelCounts[`h${section.level}` as keyof typeof levelCounts]++;\n levelCounts.total++;\n }\n \n // Count code blocks\n let codeBlocks = 0;\n let inCodeBlock = false;\n for (const line of lines) {\n if (line.trimStart().startsWith('```')) {\n if (!inCodeBlock) {\n codeBlocks++;\n }\n inCodeBlock = !inCodeBlock;\n }\n }\n \n // Calculate max nesting\n let maxNesting = 0;\n function calculateNesting(secs: Section[], depth: number): void {\n for (const section of secs) {\n maxNesting = Math.max(maxNesting, depth);\n calculateNesting(section.subsections, depth + 1);\n }\n }\n calculateNesting(sections, 1);\n \n return {\n lines: lines.length,\n sections,\n allSections,\n sectionsByLevel: levelCounts,\n codeBlocks,\n maxNesting,\n };\n}\n","/**\n * Token counting utilities for LLM context management\n * \n * Implements spec 069: Token Counting Utilities\n * \n * Uses tiktoken (official OpenAI tokenizer) for exact token counts.\n * Token count is the primary metric for Context Economy because:\n * - Predicts AI performance better than line count\n * - Research shows 39% performance drop in multi-turn contexts\n * - Quality degradation starts well before 50K token limits\n * \n * See spec 066 for research findings and threshold rationale.\n */\n\n// Lazy import tiktoken to avoid WASM loading issues in Next.js\nlet encoding: any = null;\nasync function getEncoding() {\n if (!encoding) {\n const { encoding_for_model } = await import('tiktoken');\n encoding = encoding_for_model('gpt-4');\n }\n return encoding;\n}\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport matter from 'gray-matter';\n\nexport interface TokenCount {\n total: number;\n files: {\n path: string;\n tokens: number;\n lines?: number;\n }[];\n breakdown?: {\n code: number; // Tokens in code blocks\n prose: number; // Tokens in prose\n tables: number; // Tokens in tables\n frontmatter: number; // Tokens in frontmatter\n };\n}\n\nexport interface TokenCounterOptions {\n detailed?: boolean; // Include breakdown by file and type\n includeSubSpecs?: boolean; // Count sub-spec files\n}\n\n/**\n * Token counter using tiktoken for exact token counts\n */\nexport class TokenCounter {\n private encoding: any = null;\n\n async getEncoding() {\n if (!this.encoding) {\n const { encoding_for_model } = await import('tiktoken');\n this.encoding = encoding_for_model('gpt-4');\n }\n return this.encoding;\n }\n\n /**\n * Clean up resources (important to prevent memory leaks)\n */\n dispose(): void {\n if (this.encoding) {\n this.encoding.free();\n }\n }\n\n /**\n * Count tokens in a string\n */\n async countString(text: string): Promise<number> {\n const encoding = await this.getEncoding();\n const tokens = encoding.encode(text);\n return tokens.length;\n }\n\n /**\n * Count tokens in content (convenience method for analyze command)\n * Alias for countString - provided for clarity in command usage\n */\n async countTokensInContent(content: string): Promise<number> {\n return this.countString(content);\n }\n\n /**\n * Count tokens in a single file\n */\n async countFile(filePath: string, options: TokenCounterOptions = {}): Promise<TokenCount> {\n const content = await fs.readFile(filePath, 'utf-8');\n const tokens = await this.countString(content);\n const lines = content.split('\\n').length;\n\n const result: TokenCount = {\n total: tokens,\n files: [{\n path: filePath,\n tokens,\n lines,\n }],\n };\n\n if (options.detailed) {\n result.breakdown = await this.analyzeBreakdown(content);\n }\n\n return result;\n }\n\n /**\n * Count tokens in a spec (including sub-specs if requested)\n */\n async countSpec(specPath: string, options: TokenCounterOptions = {}): Promise<TokenCount> {\n // Determine if specPath is a directory or file\n const stats = await fs.stat(specPath);\n \n if (stats.isFile()) {\n // Single file - count it\n return this.countFile(specPath, options);\n }\n\n // Directory - find all markdown files\n const files = await fs.readdir(specPath);\n const mdFiles = files.filter(f => f.endsWith('.md'));\n\n // Always include README.md if it exists\n const filesToCount: string[] = [];\n if (mdFiles.includes('README.md')) {\n filesToCount.push('README.md');\n }\n\n // Include sub-specs if requested\n if (options.includeSubSpecs) {\n mdFiles.forEach(f => {\n if (f !== 'README.md') {\n filesToCount.push(f);\n }\n });\n }\n\n // Count tokens for each file\n const fileCounts: TokenCount['files'] = [];\n let totalTokens = 0;\n let totalBreakdown: TokenCount['breakdown'] | undefined;\n\n if (options.detailed) {\n totalBreakdown = {\n code: 0,\n prose: 0,\n tables: 0,\n frontmatter: 0,\n };\n }\n\n for (const file of filesToCount) {\n const filePath = path.join(specPath, file);\n const content = await fs.readFile(filePath, 'utf-8');\n const tokens = await this.countString(content);\n const lines = content.split('\\n').length;\n\n fileCounts.push({\n path: file,\n tokens,\n lines,\n });\n\n totalTokens += tokens;\n\n if (options.detailed && totalBreakdown) {\n const breakdown = await this.analyzeBreakdown(content);\n totalBreakdown.code += breakdown.code;\n totalBreakdown.prose += breakdown.prose;\n totalBreakdown.tables += breakdown.tables;\n totalBreakdown.frontmatter += breakdown.frontmatter;\n }\n }\n\n return {\n total: totalTokens,\n files: fileCounts,\n breakdown: totalBreakdown,\n };\n }\n\n /**\n * Analyze token breakdown by content type\n */\n async analyzeBreakdown(content: string): Promise<NonNullable<TokenCount['breakdown']>> {\n const breakdown = {\n code: 0,\n prose: 0,\n tables: 0,\n frontmatter: 0,\n };\n\n // Parse frontmatter\n let body = content;\n let frontmatterContent = '';\n \n try {\n const parsed = matter(content);\n body = parsed.content;\n frontmatterContent = parsed.matter;\n breakdown.frontmatter = await this.countString(frontmatterContent);\n } catch {\n // No frontmatter or parsing error\n }\n\n // Track what we're in\n let inCodeBlock = false;\n let inTable = false;\n const lines = body.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trim();\n\n // Track code blocks\n if (trimmed.startsWith('```')) {\n inCodeBlock = !inCodeBlock;\n breakdown.code += await this.countString(line + '\\n');\n continue;\n }\n\n if (inCodeBlock) {\n breakdown.code += await this.countString(line + '\\n');\n continue;\n }\n\n // Track tables (lines with pipes and separators)\n const isTableSeparator = trimmed.includes('|') && /[-:]{3,}/.test(trimmed);\n const isTableRow = trimmed.includes('|') && trimmed.startsWith('|');\n \n if (isTableSeparator || (inTable && isTableRow)) {\n inTable = true;\n breakdown.tables += await this.countString(line + '\\n');\n continue;\n } else if (inTable && !isTableRow) {\n inTable = false;\n }\n\n // Everything else is prose\n breakdown.prose += await this.countString(line + '\\n');\n }\n\n return breakdown;\n }\n\n /**\n * Check if content fits within token limit\n */\n isWithinLimit(count: TokenCount, limit: number): boolean {\n return count.total <= limit;\n }\n\n /**\n * Format token count for display\n */\n formatCount(count: TokenCount, verbose: boolean = false): string {\n if (!verbose) {\n return `${count.total.toLocaleString()} tokens`;\n }\n\n const lines: string[] = [\n `Total: ${count.total.toLocaleString()} tokens`,\n '',\n 'Files:',\n ];\n\n for (const file of count.files) {\n const lineInfo = file.lines ? ` (${file.lines} lines)` : '';\n lines.push(` ${file.path}: ${file.tokens.toLocaleString()} tokens${lineInfo}`);\n }\n\n if (count.breakdown) {\n const b = count.breakdown;\n const total = b.code + b.prose + b.tables + b.frontmatter;\n \n lines.push('');\n lines.push('Content Breakdown:');\n lines.push(` Prose: ${b.prose.toLocaleString()} tokens (${Math.round(b.prose / total * 100)}%)`);\n lines.push(` Code: ${b.code.toLocaleString()} tokens (${Math.round(b.code / total * 100)}%)`);\n lines.push(` Tables: ${b.tables.toLocaleString()} tokens (${Math.round(b.tables / total * 100)}%)`);\n lines.push(` Frontmatter: ${b.frontmatter.toLocaleString()} tokens (${Math.round(b.frontmatter / total * 100)}%)`);\n }\n\n return lines.join('\\n');\n }\n\n /**\n * Get performance indicators based on token count\n * Based on research from spec 066\n */\n getPerformanceIndicators(tokenCount: number): {\n level: 'excellent' | 'good' | 'warning' | 'problem';\n costMultiplier: number;\n effectiveness: number; // Estimated AI effectiveness (0-100%)\n recommendation: string;\n } {\n const baselineTokens = 1200;\n const costMultiplier = Math.round((tokenCount / baselineTokens) * 10) / 10;\n\n // Thresholds from spec 066 (hypothesis values)\n if (tokenCount < 2000) {\n return {\n level: 'excellent',\n costMultiplier,\n effectiveness: 100,\n recommendation: 'Optimal size for Context Economy',\n };\n } else if (tokenCount < 3500) {\n return {\n level: 'good',\n costMultiplier,\n effectiveness: 95,\n recommendation: 'Good size, no action needed',\n };\n } else if (tokenCount < 5000) {\n return {\n level: 'warning',\n costMultiplier,\n effectiveness: 85,\n recommendation: 'Consider simplification or sub-specs',\n };\n } else {\n return {\n level: 'problem',\n costMultiplier,\n effectiveness: 70,\n recommendation: 'Should split - elevated token count',\n };\n }\n }\n}\n\n/**\n * Convenience function to create, use, and dispose of a TokenCounter\n */\nexport async function countTokens(\n input: string | { content: string } | { filePath: string } | { specPath: string },\n options?: TokenCounterOptions\n): Promise<TokenCount> {\n const counter = new TokenCounter();\n \n try {\n if (typeof input === 'string') {\n // String content\n return {\n total: await counter.countString(input),\n files: [],\n };\n } else if ('content' in input) {\n // Content object\n return {\n total: await counter.countString(input.content),\n files: [],\n };\n } else if ('filePath' in input) {\n // File path\n return await counter.countFile(input.filePath, options);\n } else if ('specPath' in input) {\n // Spec path (directory)\n return await counter.countSpec(input.specPath, options);\n }\n \n throw new Error('Invalid input type');\n } finally {\n counter.dispose();\n }\n}\n","/**\n * Complexity validator - direct token threshold validation\n * \n * Implements spec 071: Simplified Token-Based Validation\n * \n * Uses direct, independent checks instead of derived scores:\n * 1. Token count (primary check) - direct thresholds\n * 2. Structure quality (independent feedback) - sub-specs and sectioning\n * 3. Line count (backstop only) - for extreme cases\n * \n * Research-backed findings:\n * - Token count predicts AI performance better than line count\n * - Quality degradation starts before 50K token limits\n * - Sub-specs enable progressive disclosure (Context Economy)\n * - Good sectioning enables cognitive chunking (7±2 rule)\n */\n\nimport type { ValidationRule, ValidationResult, ValidationError, ValidationWarning } from '../utils/validation-framework.js';\nimport type { SpecInfo } from '../types/index.js';\nimport { TokenCounter } from '../utils/token-counter.js';\nimport matter from 'gray-matter';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nexport interface ComplexityOptions {\n // Token thresholds (hypothesis values, to be validated)\n excellentThreshold?: number; // Default: 2000 tokens\n goodThreshold?: number; // Default: 3500 tokens\n warningThreshold?: number; // Default: 5000 tokens\n \n // Line count backstop (safety net)\n maxLines?: number; // Default: 500 lines\n warningLines?: number; // Default: 400 lines\n}\n\nexport interface ComplexityMetrics {\n lineCount: number;\n tokenCount: number;\n sectionCount: number;\n codeBlockCount: number;\n listItemCount: number;\n tableCount: number;\n hasSubSpecs: boolean;\n subSpecCount: number;\n averageSectionLength: number;\n}\n\n// Deprecated - kept for backward compatibility only\nexport interface ComplexityScore {\n score: number; // 0-100 (lower is better) - DEPRECATED\n factors: {\n tokens: number; // Primary: token-based score (0-60) - DEPRECATED\n structure: number; // Modifier: structure quality (-30 to +20) - DEPRECATED\n };\n recommendation: 'excellent' | 'good' | 'review' | 'split'; // DEPRECATED\n metrics: ComplexityMetrics;\n costMultiplier: number; // vs 1,200 token baseline\n}\n\nexport class ComplexityValidator implements ValidationRule {\n name = 'complexity';\n description = 'Direct token threshold validation with independent structure checks';\n\n private excellentThreshold: number;\n private goodThreshold: number;\n private warningThreshold: number;\n private maxLines: number;\n private warningLines: number;\n\n constructor(options: ComplexityOptions = {}) {\n // Token thresholds (hypothesis values based on research)\n this.excellentThreshold = options.excellentThreshold ?? 2000;\n this.goodThreshold = options.goodThreshold ?? 3500;\n this.warningThreshold = options.warningThreshold ?? 5000;\n \n // Line count backstop\n this.maxLines = options.maxLines ?? 500;\n this.warningLines = options.warningLines ?? 400;\n }\n\n async validate(spec: SpecInfo, content: string): Promise<ValidationResult> {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n // Analyze complexity\n const metrics = await this.analyzeComplexity(content, spec);\n\n // PRIMARY CHECK: Direct token thresholds\n const tokenValidation = this.validateTokens(metrics.tokenCount);\n if (tokenValidation.level === 'error') {\n errors.push({\n message: tokenValidation.message,\n suggestion: 'Consider splitting for Context Economy (attention and cognitive load)',\n });\n } else if (tokenValidation.level === 'warning') {\n warnings.push({\n message: tokenValidation.message,\n suggestion: 'Consider simplification or splitting into sub-specs',\n });\n }\n\n // INDEPENDENT CHECKS: Structure feedback\n const structureChecks = this.checkStructure(metrics);\n for (const check of structureChecks) {\n if (!check.passed && check.message) {\n warnings.push({\n message: check.message,\n suggestion: check.suggestion,\n });\n }\n }\n\n // LINE COUNT BACKSTOP: catch extremely long specs even if tokens are fine\n const lineWarning = this.checkLineCounts(metrics.lineCount);\n if (lineWarning) {\n warnings.push(lineWarning);\n }\n\n return {\n passed: errors.length === 0,\n errors,\n warnings,\n };\n }\n\n /**\n * Validate token count with direct thresholds\n */\n private validateTokens(tokens: number): { level: 'excellent' | 'good' | 'info' | 'warning' | 'error'; message: string } {\n if (tokens > this.warningThreshold) {\n return {\n level: 'error',\n message: `Spec has ${tokens.toLocaleString()} tokens (threshold: ${this.warningThreshold.toLocaleString()}) - should split`,\n };\n }\n \n if (tokens > this.goodThreshold) {\n return {\n level: 'warning',\n message: `Spec has ${tokens.toLocaleString()} tokens (threshold: ${this.goodThreshold.toLocaleString()})`,\n };\n }\n \n if (tokens > this.excellentThreshold) {\n return {\n level: 'info',\n message: `Spec has ${tokens.toLocaleString()} tokens - acceptable, watch for growth`,\n };\n }\n \n return {\n level: 'excellent',\n message: `Spec has ${tokens.toLocaleString()} tokens - excellent`,\n };\n }\n\n /**\n * Check structure quality independently\n */\n private checkStructure(metrics: ComplexityMetrics): Array<{ passed: boolean; message?: string; suggestion?: string }> {\n const checks: Array<{ passed: boolean; message?: string; suggestion?: string }> = [];\n \n // Sub-specs presence (positive feedback when helpful)\n if (metrics.hasSubSpecs) {\n // Only show positive feedback if spec is large enough that sub-specs help\n if (metrics.tokenCount > this.excellentThreshold) {\n checks.push({\n passed: true,\n message: `Uses ${metrics.subSpecCount} sub-spec file${metrics.subSpecCount > 1 ? 's' : ''} for progressive disclosure`,\n });\n }\n } else if (metrics.tokenCount > this.goodThreshold) {\n checks.push({\n passed: false,\n message: 'Consider using sub-spec files (DESIGN.md, IMPLEMENTATION.md, etc.)',\n suggestion: 'Progressive disclosure reduces cognitive load for large specs',\n });\n }\n \n // Section organization\n if (metrics.sectionCount >= 15 && metrics.sectionCount <= 35) {\n // Only show positive feedback if structure is helping manage complexity\n if (metrics.tokenCount > this.excellentThreshold) {\n checks.push({\n passed: true,\n message: `Good sectioning (${metrics.sectionCount} sections) enables cognitive chunking`,\n });\n }\n } else if (metrics.sectionCount < 8 && metrics.lineCount > 200) {\n checks.push({\n passed: false,\n message: `Only ${metrics.sectionCount} sections - too monolithic`,\n suggestion: 'Break into 15-35 sections for better readability (7±2 cognitive chunks)',\n });\n }\n \n // Code block density\n if (metrics.codeBlockCount > 20) {\n checks.push({\n passed: false,\n message: `High code block density (${metrics.codeBlockCount} blocks)`,\n suggestion: 'Consider moving examples to separate files or sub-specs',\n });\n }\n \n return checks;\n }\n\n /**\n * Provide warnings when line counts exceed backstop thresholds\n */\n private checkLineCounts(lineCount: number): ValidationWarning | null {\n if (lineCount > this.maxLines) {\n return {\n message: `Spec is very long at ${lineCount.toLocaleString()} lines (limit ${this.maxLines.toLocaleString()})`,\n suggestion: 'Split the document or move details to sub-spec files to keep context manageable',\n };\n }\n\n if (lineCount > this.warningLines) {\n return {\n message: `Spec is ${lineCount.toLocaleString()} lines — approaching the ${this.warningLines.toLocaleString()} line backstop`,\n suggestion: 'Watch size growth and consider progressive disclosure before hitting hard limits',\n };\n }\n\n return null;\n }\n\n /**\n * Analyze complexity metrics from spec content\n */\n private async analyzeComplexity(content: string, spec: SpecInfo): Promise<ComplexityMetrics> {\n // Parse to separate frontmatter from body\n let body: string;\n try {\n const parsed = matter(content);\n body = parsed.content;\n } catch {\n body = content;\n }\n\n const lines = content.split('\\n');\n const lineCount = lines.length;\n\n // Count sections (## headings, excluding code blocks)\n let sectionCount = 0;\n let inCodeBlock = false;\n for (const line of lines) {\n if (line.trim().startsWith('```')) {\n inCodeBlock = !inCodeBlock;\n continue;\n }\n if (!inCodeBlock && line.match(/^#{2,4}\\s/)) {\n sectionCount++;\n }\n }\n\n // Count code blocks\n const codeBlockCount = Math.floor((content.match(/```/g) || []).length / 2);\n\n // Count list items (-, *, or numbered)\n const listItemCount = lines.filter(line => line.match(/^[\\s]*[-*]\\s/) || line.match(/^[\\s]*\\d+\\.\\s/)).length;\n\n // Count tables (lines with table separators)\n const tableCount = lines.filter(line => line.includes('|') && line.match(/[-:]{3,}/)).length;\n\n // Count tokens using tiktoken\n const counter = new TokenCounter();\n const tokenCount = await counter.countString(content);\n counter.dispose();\n\n // Detect sub-specs by checking actual files in the spec directory\n let hasSubSpecs = false;\n let subSpecCount = 0;\n \n try {\n // Get the directory path (parent of README.md)\n const specDir = path.dirname(spec.filePath);\n const files = await fs.readdir(specDir);\n \n // Count markdown files excluding README.md\n // Sub-specs are markdown files other than README.md\n const mdFiles = files.filter(f => \n f.endsWith('.md') && \n f !== 'README.md'\n );\n \n hasSubSpecs = mdFiles.length > 0;\n subSpecCount = mdFiles.length;\n } catch (error) {\n // If we can't read the directory, fall back to content-based detection\n // This preserves backwards compatibility if there are permission issues\n hasSubSpecs = /\\b(DESIGN|IMPLEMENTATION|TESTING|CONFIGURATION|API|MIGRATION)\\.md\\b/.test(content);\n const subSpecMatches = content.match(/\\b[A-Z-]+\\.md\\b/g) || [];\n const uniqueSubSpecs = new Set(subSpecMatches.filter(m => m !== 'README.md'));\n subSpecCount = uniqueSubSpecs.size;\n }\n\n // Calculate average section length\n const averageSectionLength = sectionCount > 0 ? Math.round(lineCount / sectionCount) : 0;\n\n return {\n lineCount,\n tokenCount,\n sectionCount,\n codeBlockCount,\n listItemCount,\n tableCount,\n hasSubSpecs,\n subSpecCount,\n averageSectionLength,\n };\n }\n}\n","/**\n * Dependency Graph for LeanSpec\n * \n * Builds an in-memory graph of all spec dependencies for efficient querying.\n * Handles two types of relationships:\n * - dependsOn: Upstream dependencies (current spec depends on these)\n * - requiredBy: Downstream dependents (these specs depend on current)\n */\n\nimport type { SpecInfo } from '../types/spec.js';\n\n/**\n * A node in the dependency graph\n */\ninterface DependencyNode {\n dependsOn: Set<string>; // Upstream (current depends on these)\n requiredBy: Set<string>; // Downstream (these depend on current)\n}\n\n/**\n * Complete dependency information for a spec\n */\nexport interface CompleteDependencyGraph {\n current: SpecInfo;\n dependsOn: SpecInfo[]; // Upstream (current depends on these)\n requiredBy: SpecInfo[]; // Downstream (these depend on current)\n}\n\n/**\n * Impact radius showing all specs affected by changes\n */\nexport interface ImpactRadius {\n current: SpecInfo;\n upstream: SpecInfo[]; // What this spec needs\n downstream: SpecInfo[]; // What needs this spec\n}\n\n/**\n * Manages the dependency graph for all specs\n */\nexport class SpecDependencyGraph {\n private graph: Map<string, DependencyNode>;\n private specs: Map<string, SpecInfo>;\n\n constructor(allSpecs: SpecInfo[]) {\n this.graph = new Map();\n this.specs = new Map();\n this.buildGraph(allSpecs);\n }\n\n /**\n * Build the complete dependency graph from all specs\n */\n private buildGraph(specs: SpecInfo[]): void {\n // First pass: Initialize all nodes and store spec metadata\n for (const spec of specs) {\n this.specs.set(spec.path, spec);\n this.graph.set(spec.path, {\n dependsOn: new Set(spec.frontmatter.depends_on || []),\n requiredBy: new Set(),\n });\n }\n\n // Second pass: Build reverse edges\n for (const [specPath, node] of this.graph.entries()) {\n // For each dependsOn, add reverse requiredBy edge\n for (const dep of node.dependsOn) {\n const depNode = this.graph.get(dep);\n if (depNode) {\n depNode.requiredBy.add(specPath);\n }\n }\n }\n }\n\n /**\n * Get complete dependency graph for a spec\n */\n getCompleteGraph(specPath: string): CompleteDependencyGraph {\n const spec = this.specs.get(specPath);\n if (!spec) {\n throw new Error(`Spec not found: ${specPath}`);\n }\n\n const node = this.graph.get(specPath);\n if (!node) {\n throw new Error(`Graph node not found: ${specPath}`);\n }\n\n return {\n current: spec,\n dependsOn: this.getSpecsByPaths(Array.from(node.dependsOn)),\n requiredBy: this.getSpecsByPaths(Array.from(node.requiredBy)),\n };\n }\n\n /**\n * Get upstream dependencies (specs this one depends on)\n * Recursively traverses the dependsOn chain up to maxDepth\n */\n getUpstream(specPath: string, maxDepth: number = 3): SpecInfo[] {\n const visited = new Set<string>();\n const result: SpecInfo[] = [];\n \n const traverse = (path: string, depth: number) => {\n if (visited.has(path)) {\n return;\n }\n \n visited.add(path);\n const node = this.graph.get(path);\n if (!node) return;\n \n for (const dep of node.dependsOn) {\n if (!visited.has(dep)) {\n // Only add and traverse if we haven't exceeded maxDepth\n if (depth < maxDepth) {\n const spec = this.specs.get(dep);\n if (spec) {\n result.push(spec);\n traverse(dep, depth + 1);\n }\n }\n }\n }\n };\n \n traverse(specPath, 0);\n return result;\n }\n\n /**\n * Get downstream dependents (specs that depend on this one)\n * Recursively traverses the requiredBy chain up to maxDepth\n */\n getDownstream(specPath: string, maxDepth: number = 3): SpecInfo[] {\n const visited = new Set<string>();\n const result: SpecInfo[] = [];\n \n const traverse = (path: string, depth: number) => {\n if (visited.has(path)) {\n return;\n }\n \n visited.add(path);\n const node = this.graph.get(path);\n if (!node) return;\n \n for (const dep of node.requiredBy) {\n if (!visited.has(dep)) {\n // Only add and traverse if we haven't exceeded maxDepth\n if (depth < maxDepth) {\n const spec = this.specs.get(dep);\n if (spec) {\n result.push(spec);\n traverse(dep, depth + 1);\n }\n }\n }\n }\n };\n \n traverse(specPath, 0);\n return result;\n }\n\n /**\n * Get impact radius - all specs affected by changes to this spec\n * Includes upstream dependencies and downstream dependents\n */\n getImpactRadius(specPath: string, maxDepth: number = 3): ImpactRadius {\n const spec = this.specs.get(specPath);\n if (!spec) {\n throw new Error(`Spec not found: ${specPath}`);\n }\n\n return {\n current: spec,\n upstream: this.getUpstream(specPath, maxDepth),\n downstream: this.getDownstream(specPath, maxDepth),\n };\n }\n\n /**\n * Check if a circular dependency exists\n */\n hasCircularDependency(specPath: string): boolean {\n const visited = new Set<string>();\n const recursionStack = new Set<string>();\n \n const hasCycle = (path: string): boolean => {\n if (recursionStack.has(path)) {\n return true;\n }\n \n if (visited.has(path)) {\n return false;\n }\n \n visited.add(path);\n recursionStack.add(path);\n \n const node = this.graph.get(path);\n if (node) {\n for (const dep of node.dependsOn) {\n if (hasCycle(dep)) {\n return true;\n }\n }\n }\n \n recursionStack.delete(path);\n return false;\n };\n \n return hasCycle(specPath);\n }\n\n /**\n * Get all specs in the graph\n */\n getAllSpecs(): SpecInfo[] {\n return Array.from(this.specs.values());\n }\n\n /**\n * Get specs by their paths\n */\n private getSpecsByPaths(paths: string[]): SpecInfo[] {\n return paths\n .map(path => this.specs.get(path))\n .filter((spec): spec is SpecInfo => spec !== undefined);\n }\n}\n","/**\n * Relevance scoring algorithms for search results\n */\n\nimport type { SearchMatch } from './types.js';\n\n/**\n * Field weights for scoring (higher = more relevant)\n */\nexport const FIELD_WEIGHTS = {\n title: 100,\n name: 70,\n tags: 70,\n description: 50,\n content: 10,\n} as const;\n\n/**\n * Calculate relevance score for a match\n * \n * Scoring factors:\n * - Field weight (title > name > tags > description > content)\n * - Exact word match bonus (2x)\n * - Position bonus (earlier = more relevant)\n * - Frequency penalty (many matches = less specific)\n * \n * @param match - The search match to score\n * @param queryTerms - Individual query terms\n * @param totalMatches - Total matches found in the field\n * @param matchPosition - Position of this match (0-based)\n * @returns Score between 0-100\n */\nexport function calculateMatchScore(\n match: Pick<SearchMatch, 'field' | 'text' | 'occurrences'>,\n queryTerms: string[],\n totalMatches: number,\n matchPosition: number\n): number {\n // Start with field weight\n let score = FIELD_WEIGHTS[match.field];\n\n // Exact word match bonus (2x)\n const textLower = match.text.toLowerCase();\n const hasExactMatch = queryTerms.some(term => {\n // Check for word boundaries\n const regex = new RegExp(`\\\\b${escapeRegex(term)}\\\\b`, 'i');\n return regex.test(match.text);\n });\n \n if (hasExactMatch) {\n score *= 2;\n }\n\n // Position bonus (first match is 1.5x, decreases linearly)\n const positionBonus = Math.max(1.0, 1.5 - (matchPosition * 0.1));\n score *= positionBonus;\n\n // Frequency penalty (many matches = less specific)\n // Cap at 3 to avoid over-penalizing\n const frequencyFactor = Math.min(1.0, 3.0 / totalMatches);\n score *= frequencyFactor;\n\n // Normalize to 0-100 scale (multiply by 10 to get reasonable range)\n return Math.min(100, score * 10);\n}\n\n/**\n * Calculate overall relevance score for a spec\n * \n * Uses the highest scoring match from each field type,\n * weighted by field importance.\n * \n * @param matches - All matches for the spec\n * @returns Overall score between 0-100\n */\nexport function calculateSpecScore(matches: SearchMatch[]): number {\n if (matches.length === 0) return 0;\n\n // Group matches by field\n const fieldScores: Record<string, number> = {};\n \n for (const match of matches) {\n const field = match.field;\n const currentScore = fieldScores[field] || 0;\n fieldScores[field] = Math.max(currentScore, match.score);\n }\n\n // Calculate weighted average of best scores per field\n let totalScore = 0;\n let totalWeight = 0;\n\n for (const [field, score] of Object.entries(fieldScores)) {\n const weight = FIELD_WEIGHTS[field as keyof typeof FIELD_WEIGHTS] || 1;\n totalScore += score * weight;\n totalWeight += weight;\n }\n\n return totalWeight > 0 ? Math.round(totalScore / totalWeight) : 0;\n}\n\n/**\n * Check if text contains all query terms (AND logic)\n * \n * @param text - Text to search\n * @param queryTerms - Terms to find\n * @returns True if all terms are found\n */\nexport function containsAllTerms(text: string, queryTerms: string[]): boolean {\n const textLower = text.toLowerCase();\n return queryTerms.every(term => textLower.includes(term));\n}\n\n/**\n * Check if text contains any query term (OR logic)\n * \n * @param text - Text to search\n * @param queryTerms - Terms to find\n * @returns True if any term is found, false for empty queryTerms\n */\nexport function containsAnyTerm(text: string, queryTerms: string[]): boolean {\n // Note: returns false for empty queryTerms (no terms to match)\n const textLower = text.toLowerCase();\n return queryTerms.some(term => textLower.includes(term));\n}\n\n/**\n * Count occurrences of query terms in text\n * \n * @param text - Text to search\n * @param queryTerms - Terms to count\n * @returns Number of occurrences\n */\nexport function countOccurrences(text: string, queryTerms: string[]): number {\n const textLower = text.toLowerCase();\n let count = 0;\n \n for (const term of queryTerms) {\n const regex = new RegExp(escapeRegex(term), 'gi');\n const matches = textLower.match(regex);\n count += matches ? matches.length : 0;\n }\n \n return count;\n}\n\n/**\n * Escape special regex characters\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Find all match positions in text for query terms\n * \n * @param text - Text to search\n * @param queryTerms - Terms to find\n * @returns Array of [start, end] positions\n */\nexport function findMatchPositions(\n text: string,\n queryTerms: string[]\n): Array<[number, number]> {\n const positions: Array<[number, number]> = [];\n const textLower = text.toLowerCase();\n\n for (const term of queryTerms) {\n const termLower = term.toLowerCase();\n let index = 0;\n\n while ((index = textLower.indexOf(termLower, index)) !== -1) {\n positions.push([index, index + term.length]);\n index += term.length;\n }\n }\n\n // Sort by position and merge overlapping ranges\n positions.sort((a, b) => a[0] - b[0]);\n \n const merged: Array<[number, number]> = [];\n for (const pos of positions) {\n if (merged.length === 0) {\n merged.push(pos);\n } else {\n const last = merged[merged.length - 1];\n if (pos[0] <= last[1]) {\n // Overlapping, merge\n last[1] = Math.max(last[1], pos[1]);\n } else {\n merged.push(pos);\n }\n }\n }\n\n return merged;\n}\n","/**\n * Context extraction for search matches\n */\n\nimport type { SearchMatch } from './types.js';\nimport { findMatchPositions } from './scoring.js';\n\n/**\n * Extract context around a match with smart boundaries\n * \n * @param text - Full text content\n * @param matchIndex - Index of the line/position where match occurs\n * @param queryTerms - Query terms to highlight\n * @param contextLength - Characters before/after (default: 80)\n * @returns Context text with match highlighted\n */\nexport function extractContext(\n text: string,\n matchIndex: number,\n queryTerms: string[],\n contextLength: number = 80\n): { text: string; highlights: Array<[number, number]> } {\n const lines = text.split('\\n');\n const matchLine = lines[matchIndex] || '';\n\n // For short lines, just return the line\n if (matchLine.length <= contextLength * 2) {\n const highlights = findMatchPositions(matchLine, queryTerms);\n return { text: matchLine, highlights };\n }\n\n // Find first occurrence of any query term\n const matchLineLower = matchLine.toLowerCase();\n let firstMatchPos = matchLine.length;\n \n for (const term of queryTerms) {\n const pos = matchLineLower.indexOf(term.toLowerCase());\n if (pos !== -1 && pos < firstMatchPos) {\n firstMatchPos = pos;\n }\n }\n\n // Extract context around the match\n const start = Math.max(0, firstMatchPos - contextLength);\n const end = Math.min(matchLine.length, firstMatchPos + contextLength);\n \n let contextText = matchLine.substring(start, end);\n \n // Add ellipsis if truncated\n if (start > 0) contextText = '...' + contextText;\n if (end < matchLine.length) contextText = contextText + '...';\n\n // Adjust highlight positions for context\n const highlights = findMatchPositions(contextText, queryTerms);\n\n return { text: contextText, highlights };\n}\n\n/**\n * Extract context with sentence boundaries\n * \n * @param text - Full text content\n * @param matchIndex - Index where match occurs\n * @param queryTerms - Query terms to highlight\n * @param contextLength - Target characters before/after\n * @returns Context text respecting sentence boundaries\n */\nexport function extractSmartContext(\n text: string,\n matchIndex: number,\n queryTerms: string[],\n contextLength: number = 80\n): { text: string; highlights: Array<[number, number]> } {\n const lines = text.split('\\n');\n const matchLine = lines[matchIndex] || '';\n\n // For short content, use simple extraction\n if (matchLine.length <= contextLength * 2) {\n return extractContext(text, matchIndex, queryTerms, contextLength);\n }\n\n // Try to find sentence boundaries\n const matchLineLower = matchLine.toLowerCase();\n let firstMatchPos = matchLine.length;\n \n for (const term of queryTerms) {\n const pos = matchLineLower.indexOf(term.toLowerCase());\n if (pos !== -1 && pos < firstMatchPos) {\n firstMatchPos = pos;\n }\n }\n\n // Look for sentence boundaries (., !, ?)\n const sentenceEnd = /[.!?]\\s+/g;\n let start = Math.max(0, firstMatchPos - contextLength);\n let end = Math.min(matchLine.length, firstMatchPos + contextLength);\n\n // Try to expand to sentence boundaries if close\n const beforeText = matchLine.substring(0, start);\n const lastSentence = beforeText.lastIndexOf('. ');\n if (lastSentence !== -1 && start - lastSentence < 20) {\n start = lastSentence + 2; // Skip \". \"\n }\n\n const afterText = matchLine.substring(end);\n const nextSentence = afterText.indexOf('. ');\n if (nextSentence !== -1 && nextSentence < 20) {\n end = end + nextSentence + 1; // Include \".\"\n }\n\n let contextText = matchLine.substring(start, end);\n \n // Add ellipsis if truncated\n if (start > 0) contextText = '...' + contextText;\n if (end < matchLine.length) contextText = contextText + '...';\n\n const highlights = findMatchPositions(contextText, queryTerms);\n\n return { text: contextText, highlights };\n}\n\n/**\n * Deduplicate nearby matches\n * \n * If matches are within a certain distance, keep only the best scoring one.\n * \n * @param matches - All matches for a spec\n * @param minDistance - Minimum line distance between matches (default: 3)\n * @returns Deduplicated matches\n */\nexport function deduplicateMatches(\n matches: SearchMatch[],\n minDistance: number = 3\n): SearchMatch[] {\n if (matches.length === 0) return matches;\n\n // Sort by score (descending) then by line number\n const sorted = [...matches].sort((a, b) => {\n if (b.score !== a.score) return b.score - a.score;\n return (a.lineNumber || 0) - (b.lineNumber || 0);\n });\n\n const deduplicated: SearchMatch[] = [];\n const usedLines = new Set<number>();\n\n for (const match of sorted) {\n // Non-content fields always included\n if (match.field !== 'content') {\n deduplicated.push(match);\n continue;\n }\n\n // Check if too close to an existing match\n const lineNum = match.lineNumber || 0;\n let tooClose = false;\n\n for (let i = lineNum - minDistance; i <= lineNum + minDistance; i++) {\n if (usedLines.has(i)) {\n tooClose = true;\n break;\n }\n }\n\n if (!tooClose) {\n deduplicated.push(match);\n usedLines.add(lineNum);\n }\n }\n\n // Sort by field priority and score for final output\n return deduplicated.sort((a, b) => {\n const fieldOrder = { title: 0, name: 1, tags: 2, description: 3, content: 4 };\n const orderA = fieldOrder[a.field];\n const orderB = fieldOrder[b.field];\n \n if (orderA !== orderB) return orderA - orderB;\n return b.score - a.score;\n });\n}\n\n/**\n * Limit matches per spec\n * \n * @param matches - All matches\n * @param maxMatches - Maximum matches to keep (default: 5)\n * @returns Limited matches (best scoring)\n */\nexport function limitMatches(\n matches: SearchMatch[],\n maxMatches: number = 5\n): SearchMatch[] {\n if (matches.length <= maxMatches) return matches;\n\n // Separate by field type\n const fieldMatches: Record<string, SearchMatch[]> = {\n title: [],\n name: [],\n tags: [],\n description: [],\n content: [],\n };\n\n for (const match of matches) {\n fieldMatches[match.field].push(match);\n }\n\n // Always include non-content matches\n const nonContent: SearchMatch[] = [\n ...fieldMatches.title,\n ...fieldMatches.name,\n ...fieldMatches.tags,\n ...fieldMatches.description,\n ];\n\n // Fill remaining slots with best content matches\n const contentMatches = fieldMatches.content\n .sort((a, b) => b.score - a.score)\n .slice(0, Math.max(0, maxMatches - nonContent.length));\n\n return [...nonContent, ...contentMatches];\n}\n","/**\n * Advanced query parser for search\n * \n * Supports:\n * - Boolean operators: AND, OR, NOT\n * - Field-specific search: status:in-progress, tag:api, priority:high\n * - Date range filters: created:>2025-11-01, created:2025-11-01..2025-11-15\n * - Fuzzy matching: term~\n * - Quoted phrases: \"exact phrase\"\n */\n\n/**\n * Token types for the query lexer\n */\nexport type TokenType =\n | 'TERM'\n | 'PHRASE'\n | 'FIELD'\n | 'AND'\n | 'OR'\n | 'NOT'\n | 'LPAREN'\n | 'RPAREN'\n | 'FUZZY'\n | 'EOF';\n\n/**\n * A token from the lexer\n */\nexport interface Token {\n type: TokenType;\n value: string;\n position: number;\n}\n\n/**\n * AST node types\n */\nexport type ASTNodeType = 'AND' | 'OR' | 'NOT' | 'TERM' | 'PHRASE' | 'FIELD' | 'FUZZY';\n\n/**\n * Abstract Syntax Tree node\n */\nexport interface ASTNode {\n type: ASTNodeType;\n value?: string;\n field?: string;\n left?: ASTNode;\n right?: ASTNode;\n children?: ASTNode[];\n}\n\n/**\n * Parsed query result\n */\nexport interface ParsedQuery {\n ast: ASTNode | null;\n /** Plain text terms for simple matching */\n terms: string[];\n /** Field filters extracted from query */\n fields: FieldFilter[];\n /** Date range filters */\n dateFilters: DateFilter[];\n /** Fuzzy terms */\n fuzzyTerms: string[];\n /** Whether the query has advanced syntax */\n hasAdvancedSyntax: boolean;\n /** Original query string */\n originalQuery: string;\n /** Parse errors if any */\n errors: string[];\n}\n\n/**\n * Field filter (e.g., status:in-progress)\n */\nexport interface FieldFilter {\n field: string;\n value: string;\n /** Whether to match exactly or as substring */\n exact: boolean;\n}\n\n/**\n * Date range filter\n */\nexport interface DateFilter {\n field: string;\n operator: '>' | '<' | '>=' | '<=' | '=' | 'range';\n value: string;\n endValue?: string; // For range queries\n}\n\n/**\n * Supported field prefixes for field-specific search\n */\nexport const SUPPORTED_FIELDS = [\n 'status',\n 'tag',\n 'tags',\n 'priority',\n 'assignee',\n 'title',\n 'name',\n 'created',\n 'updated',\n] as const;\n\nexport type SupportedField = (typeof SUPPORTED_FIELDS)[number];\n\n/**\n * Tokenize a query string\n */\nexport function tokenize(query: string): Token[] {\n const tokens: Token[] = [];\n let position = 0;\n\n while (position < query.length) {\n // Skip whitespace\n if (/\\s/.test(query[position])) {\n position++;\n continue;\n }\n\n // Quoted phrase\n if (query[position] === '\"') {\n const start = position;\n position++; // Skip opening quote\n let phrase = '';\n while (position < query.length && query[position] !== '\"') {\n phrase += query[position];\n position++;\n }\n position++; // Skip closing quote\n tokens.push({ type: 'PHRASE', value: phrase, position: start });\n continue;\n }\n\n // Parentheses\n if (query[position] === '(') {\n tokens.push({ type: 'LPAREN', value: '(', position });\n position++;\n continue;\n }\n if (query[position] === ')') {\n tokens.push({ type: 'RPAREN', value: ')', position });\n position++;\n continue;\n }\n\n // Word or operator\n const start = position;\n let word = '';\n while (position < query.length && !/[\\s()\"]/.test(query[position])) {\n word += query[position];\n position++;\n }\n\n if (word.length === 0) continue;\n\n // Check for boolean operators (case-insensitive)\n const upperWord = word.toUpperCase();\n if (upperWord === 'AND') {\n tokens.push({ type: 'AND', value: word, position: start });\n continue;\n }\n if (upperWord === 'OR') {\n tokens.push({ type: 'OR', value: word, position: start });\n continue;\n }\n if (upperWord === 'NOT') {\n tokens.push({ type: 'NOT', value: word, position: start });\n continue;\n }\n\n // Check for field prefix (e.g., status:planned)\n const colonIndex = word.indexOf(':');\n if (colonIndex > 0) {\n const fieldName = word.substring(0, colonIndex).toLowerCase();\n if (SUPPORTED_FIELDS.includes(fieldName as SupportedField)) {\n tokens.push({ type: 'FIELD', value: word, position: start });\n continue;\n }\n }\n\n // Check for fuzzy suffix (e.g., term~)\n if (word.endsWith('~')) {\n tokens.push({ type: 'FUZZY', value: word.slice(0, -1), position: start });\n continue;\n }\n\n // Regular term\n tokens.push({ type: 'TERM', value: word, position: start });\n }\n\n tokens.push({ type: 'EOF', value: '', position: query.length });\n return tokens;\n}\n\n/**\n * Parser for query tokens\n */\nclass QueryParser {\n private tokens: Token[];\n private current = 0;\n private errors: string[] = [];\n\n constructor(tokens: Token[]) {\n this.tokens = tokens;\n }\n\n parse(): { ast: ASTNode | null; errors: string[] } {\n if (this.tokens.length <= 1) {\n // Only EOF\n return { ast: null, errors: [] };\n }\n\n try {\n const ast = this.parseExpression();\n return { ast, errors: this.errors };\n } catch {\n return { ast: null, errors: this.errors };\n }\n }\n\n private parseExpression(): ASTNode | null {\n return this.parseOr();\n }\n\n private parseOr(): ASTNode | null {\n let left = this.parseAnd();\n if (!left) return null;\n\n while (this.check('OR')) {\n this.advance();\n const right = this.parseAnd();\n if (!right) {\n this.errors.push('Expected term after OR');\n break;\n }\n left = { type: 'OR', left, right };\n }\n\n return left;\n }\n\n private parseAnd(): ASTNode | null {\n let left = this.parseNot();\n if (!left) return null;\n\n // AND can be explicit or implicit (terms next to each other)\n while (this.check('AND') || this.isTermStart()) {\n if (this.check('AND')) {\n this.advance();\n }\n const right = this.parseNot();\n if (!right) break;\n left = { type: 'AND', left, right };\n }\n\n return left;\n }\n\n private parseNot(): ASTNode | null {\n if (this.check('NOT')) {\n this.advance();\n const operand = this.parsePrimary();\n if (!operand) {\n this.errors.push('Expected term after NOT');\n return null;\n }\n return { type: 'NOT', left: operand };\n }\n return this.parsePrimary();\n }\n\n private parsePrimary(): ASTNode | null {\n const token = this.peek();\n\n if (token.type === 'LPAREN') {\n this.advance();\n const expr = this.parseExpression();\n if (!this.check('RPAREN')) {\n this.errors.push('Expected closing parenthesis');\n } else {\n this.advance();\n }\n return expr;\n }\n\n if (token.type === 'TERM') {\n this.advance();\n return { type: 'TERM', value: token.value };\n }\n\n if (token.type === 'PHRASE') {\n this.advance();\n return { type: 'PHRASE', value: token.value };\n }\n\n if (token.type === 'FIELD') {\n this.advance();\n const colonIndex = token.value.indexOf(':');\n const field = token.value.substring(0, colonIndex).toLowerCase();\n const value = token.value.substring(colonIndex + 1);\n return { type: 'FIELD', field, value };\n }\n\n if (token.type === 'FUZZY') {\n this.advance();\n return { type: 'FUZZY', value: token.value };\n }\n\n return null;\n }\n\n private isTermStart(): boolean {\n const type = this.peek().type;\n return (\n type === 'TERM' ||\n type === 'PHRASE' ||\n type === 'FIELD' ||\n type === 'FUZZY' ||\n type === 'LPAREN' ||\n type === 'NOT'\n );\n }\n\n private peek(): Token {\n return this.tokens[this.current] || { type: 'EOF', value: '', position: 0 };\n }\n\n private check(type: TokenType): boolean {\n return this.peek().type === type;\n }\n\n private advance(): Token {\n if (!this.isAtEnd()) {\n this.current++;\n }\n return this.tokens[this.current - 1];\n }\n\n private isAtEnd(): boolean {\n return this.peek().type === 'EOF';\n }\n}\n\n/**\n * Extract field filters from AST\n */\nfunction extractFieldFilters(ast: ASTNode | null): FieldFilter[] {\n if (!ast) return [];\n\n const filters: FieldFilter[] = [];\n\n function traverse(node: ASTNode): void {\n if (node.type === 'FIELD' && node.field && node.value !== undefined) {\n filters.push({\n field: node.field,\n value: node.value,\n exact: true,\n });\n }\n if (node.left) traverse(node.left);\n if (node.right) traverse(node.right);\n if (node.children) {\n for (const child of node.children) {\n traverse(child);\n }\n }\n }\n\n traverse(ast);\n return filters;\n}\n\n/**\n * Extract date filters from field filters\n */\nfunction extractDateFilters(fieldFilters: FieldFilter[]): DateFilter[] {\n const dateFields = ['created', 'updated'];\n const dateFilters: DateFilter[] = [];\n\n for (const filter of fieldFilters) {\n if (!dateFields.includes(filter.field)) continue;\n\n const value = filter.value;\n\n // Range: 2025-11-01..2025-11-15\n if (value.includes('..')) {\n const [start, end] = value.split('..');\n dateFilters.push({\n field: filter.field,\n operator: 'range',\n value: start,\n endValue: end,\n });\n continue;\n }\n\n // Comparison operators\n if (value.startsWith('>=')) {\n dateFilters.push({\n field: filter.field,\n operator: '>=',\n value: value.substring(2),\n });\n } else if (value.startsWith('<=')) {\n dateFilters.push({\n field: filter.field,\n operator: '<=',\n value: value.substring(2),\n });\n } else if (value.startsWith('>')) {\n dateFilters.push({\n field: filter.field,\n operator: '>',\n value: value.substring(1),\n });\n } else if (value.startsWith('<')) {\n dateFilters.push({\n field: filter.field,\n operator: '<',\n value: value.substring(1),\n });\n } else {\n dateFilters.push({\n field: filter.field,\n operator: '=',\n value,\n });\n }\n }\n\n return dateFilters;\n}\n\n/**\n * Extract plain terms from AST\n */\nfunction extractTerms(ast: ASTNode | null): string[] {\n if (!ast) return [];\n\n const terms: string[] = [];\n\n function traverse(node: ASTNode): void {\n if (node.type === 'TERM' && node.value) {\n terms.push(node.value.toLowerCase());\n }\n if (node.type === 'PHRASE' && node.value) {\n terms.push(node.value.toLowerCase());\n }\n if (node.left) traverse(node.left);\n if (node.right) traverse(node.right);\n if (node.children) {\n for (const child of node.children) {\n traverse(child);\n }\n }\n }\n\n traverse(ast);\n return terms;\n}\n\n/**\n * Extract fuzzy terms from AST\n */\nfunction extractFuzzyTerms(ast: ASTNode | null): string[] {\n if (!ast) return [];\n\n const fuzzyTerms: string[] = [];\n\n function traverse(node: ASTNode): void {\n if (node.type === 'FUZZY' && node.value) {\n fuzzyTerms.push(node.value.toLowerCase());\n }\n if (node.left) traverse(node.left);\n if (node.right) traverse(node.right);\n if (node.children) {\n for (const child of node.children) {\n traverse(child);\n }\n }\n }\n\n traverse(ast);\n return fuzzyTerms;\n}\n\n/**\n * Check if query has advanced syntax\n */\nfunction hasAdvancedSyntax(tokens: Token[]): boolean {\n for (const token of tokens) {\n if (\n token.type === 'AND' ||\n token.type === 'OR' ||\n token.type === 'NOT' ||\n token.type === 'FIELD' ||\n token.type === 'FUZZY' ||\n token.type === 'PHRASE' ||\n token.type === 'LPAREN'\n ) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Parse a search query string into a structured query object\n * \n * @param query - The search query string\n * @returns Parsed query with AST, terms, filters, etc.\n */\nexport function parseQuery(query: string): ParsedQuery {\n const trimmed = query.trim();\n \n if (!trimmed) {\n return {\n ast: null,\n terms: [],\n fields: [],\n dateFilters: [],\n fuzzyTerms: [],\n hasAdvancedSyntax: false,\n originalQuery: query,\n errors: [],\n };\n }\n\n const tokens = tokenize(trimmed);\n const parser = new QueryParser(tokens);\n const { ast, errors } = parser.parse();\n\n const fields = extractFieldFilters(ast);\n const dateFilters = extractDateFilters(fields);\n const terms = extractTerms(ast);\n const fuzzyTerms = extractFuzzyTerms(ast);\n\n return {\n ast,\n terms,\n fields,\n dateFilters,\n fuzzyTerms,\n hasAdvancedSyntax: hasAdvancedSyntax(tokens),\n originalQuery: query,\n errors,\n };\n}\n\n/**\n * Calculate Levenshtein distance between two strings\n * Used for fuzzy matching\n */\nexport function levenshteinDistance(a: string, b: string): number {\n if (a.length === 0) return b.length;\n if (b.length === 0) return a.length;\n\n const matrix: number[][] = [];\n\n // Initialize matrix\n for (let i = 0; i <= b.length; i++) {\n matrix[i] = [i];\n }\n for (let j = 0; j <= a.length; j++) {\n matrix[0][j] = j;\n }\n\n // Fill matrix\n for (let i = 1; i <= b.length; i++) {\n for (let j = 1; j <= a.length; j++) {\n if (b.charAt(i - 1) === a.charAt(j - 1)) {\n matrix[i][j] = matrix[i - 1][j - 1];\n } else {\n matrix[i][j] = Math.min(\n matrix[i - 1][j - 1] + 1, // substitution\n matrix[i][j - 1] + 1, // insertion\n matrix[i - 1][j] + 1 // deletion\n );\n }\n }\n }\n\n return matrix[b.length][a.length];\n}\n\n/**\n * Check if a term fuzzy matches a text\n * \n * @param term - The search term\n * @param text - The text to search in\n * @param maxDistance - Maximum edit distance (default: auto based on term length)\n * @returns True if the term fuzzy matches any word in the text\n */\nexport function fuzzyMatch(term: string, text: string, maxDistance?: number): boolean {\n const termLower = term.toLowerCase();\n const textLower = text.toLowerCase();\n \n // Auto-calculate max distance based on term length\n // Short terms (<=4): 1, medium terms (5-8): 2\n // This is more conservative to reduce false positives\n const autoDistance = termLower.length <= 4 ? 1 : 2;\n const threshold = maxDistance ?? autoDistance;\n\n // Check each word in the text\n const words = textLower.split(/\\s+/);\n for (const word of words) {\n if (levenshteinDistance(termLower, word) <= threshold) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Generate search syntax help text\n */\nexport function getSearchSyntaxHelp(): string {\n return `\nSearch Syntax:\n term Simple term search\n \"exact phrase\" Match exact phrase\n term1 AND term2 Both terms must match (AND is optional)\n term1 OR term2 Either term matches\n NOT term Exclude specs with term\n\nField Filters:\n status:in-progress Filter by status (planned, in-progress, complete, archived)\n tag:api Filter by tag\n priority:high Filter by priority (low, medium, high, critical)\n assignee:marvin Filter by assignee\n title:dashboard Search in title only\n name:oauth Search in spec name\n\nDate Filters:\n created:>2025-11-01 Created after date\n created:<2025-11-15 Created before date\n created:2025-11-01..2025-11-15 Created in date range\n updated:>=2025-11-01 Updated on or after date\n\nFuzzy Matching:\n authetication~ Matches \"authentication\" (typo-tolerant)\n\nExamples:\n api authentication Find specs with both terms\n tag:api status:planned API specs that are planned\n \"user session\" OR \"token refresh\" Either phrase\n dashboard NOT deprecated Dashboard specs, exclude deprecated\n authetication~ Find despite typo\n`.trim();\n}\n","/**\n * Core search engine implementation\n */\n\nimport type {\n SearchOptions,\n SearchResult,\n SearchResponse,\n SearchMatch,\n SearchResultSpec,\n} from './types.js';\nimport {\n calculateMatchScore,\n calculateSpecScore,\n containsAllTerms,\n containsAnyTerm,\n countOccurrences,\n findMatchPositions,\n} from './scoring.js';\nimport {\n extractSmartContext,\n deduplicateMatches,\n limitMatches,\n} from './context.js';\nimport {\n parseQuery,\n fuzzyMatch,\n type ParsedQuery,\n type FieldFilter,\n type DateFilter,\n type ASTNode,\n} from './query-parser.js';\n\n/**\n * Spec data structure for search\n */\nexport interface SearchableSpec {\n path: string;\n name: string;\n status: string;\n priority?: string;\n tags?: string[];\n title?: string;\n description?: string;\n content?: string;\n /** Created date (ISO string) */\n created?: string;\n /** Updated date (ISO string) */\n updated?: string;\n /** Assignee */\n assignee?: string;\n}\n\n/**\n * Check if spec contains all query terms across any combination of fields\n * \n * This enables cross-field matching: term A can be in title, term B in content\n * \n * @param spec - Spec to check\n * @param queryTerms - Terms that must all be present\n * @returns True if all terms are found somewhere in the spec, false for empty queryTerms\n */\nexport function specContainsAllTerms(spec: SearchableSpec, queryTerms: string[]): boolean {\n // Return false for empty query to match main search function behavior\n if (queryTerms.length === 0) {\n return false;\n }\n \n // Combine all searchable text from the spec\n const allText = [\n spec.title || '',\n spec.name || '',\n spec.tags?.join(' ') || '',\n spec.description || '',\n spec.content || '',\n ].join(' ').toLowerCase();\n \n return queryTerms.every(term => allText.includes(term));\n}\n\n/**\n * Search specs with intelligent relevance ranking\n * \n * @param query - Search query string\n * @param specs - Specs to search\n * @param options - Search options\n * @returns Search results with relevance scoring\n */\nexport function searchSpecs(\n query: string,\n specs: SearchableSpec[],\n options: SearchOptions = {}\n): SearchResponse {\n const startTime = Date.now();\n\n // Parse query into terms (split on whitespace)\n const queryTerms = query\n .trim()\n .toLowerCase()\n .split(/\\s+/)\n .filter(term => term.length > 0);\n\n if (queryTerms.length === 0) {\n return {\n results: [],\n metadata: {\n totalResults: 0,\n searchTime: Date.now() - startTime,\n query,\n specsSearched: specs.length,\n },\n };\n }\n\n // Search options\n const maxMatchesPerSpec = options.maxMatchesPerSpec || 5;\n const contextLength = options.contextLength || 80;\n\n // Search each spec\n const results: SearchResult[] = [];\n\n for (const spec of specs) {\n // First check: does the spec contain all query terms (across any fields)?\n if (!specContainsAllTerms(spec, queryTerms)) {\n continue; // Skip specs that don't have all terms somewhere\n }\n \n // Collect matches from fields that contain ANY query term\n // This provides context/highlighting even for partial field matches\n const matches = searchSpec(spec, queryTerms, contextLength);\n \n if (matches.length > 0) {\n // Deduplicate and limit matches\n let processedMatches = deduplicateMatches(matches, 3);\n processedMatches = limitMatches(processedMatches, maxMatchesPerSpec);\n\n // Calculate overall score\n const score = calculateSpecScore(processedMatches);\n\n results.push({\n spec: specToSearchResult(spec),\n score,\n totalMatches: matches.length,\n matches: processedMatches,\n });\n }\n }\n\n // Sort by relevance score (descending)\n results.sort((a, b) => b.score - a.score);\n\n return {\n results,\n metadata: {\n totalResults: results.length,\n searchTime: Date.now() - startTime,\n query,\n specsSearched: specs.length,\n },\n };\n}\n\n/**\n * Search a single spec for query terms\n * \n * Returns matches from fields containing ANY query terms (for context/highlighting)\n * when doing cross-field search where spec-level matching is already confirmed\n */\nfunction searchSpec(\n spec: SearchableSpec,\n queryTerms: string[],\n contextLength: number\n): SearchMatch[] {\n const matches: SearchMatch[] = [];\n\n // Search title - include if it has ANY query terms\n if (spec.title && containsAnyTerm(spec.title, queryTerms)) {\n const occurrences = countOccurrences(spec.title, queryTerms);\n const highlights = findMatchPositions(spec.title, queryTerms);\n const score = calculateMatchScore(\n { field: 'title', text: spec.title, occurrences },\n queryTerms,\n 1,\n 0\n );\n\n matches.push({\n field: 'title',\n text: spec.title,\n score,\n highlights,\n occurrences,\n });\n }\n\n // Search name - include if it has ANY query terms\n if (spec.name && containsAnyTerm(spec.name, queryTerms)) {\n const occurrences = countOccurrences(spec.name, queryTerms);\n const highlights = findMatchPositions(spec.name, queryTerms);\n const score = calculateMatchScore(\n { field: 'name', text: spec.name, occurrences },\n queryTerms,\n 1,\n 0\n );\n\n matches.push({\n field: 'name',\n text: spec.name,\n score,\n highlights,\n occurrences,\n });\n }\n\n // Search tags - include tags that have ANY query terms\n if (spec.tags && spec.tags.length > 0) {\n for (const tag of spec.tags) {\n if (containsAnyTerm(tag, queryTerms)) {\n const occurrences = countOccurrences(tag, queryTerms);\n const highlights = findMatchPositions(tag, queryTerms);\n const score = calculateMatchScore(\n { field: 'tags', text: tag, occurrences },\n queryTerms,\n spec.tags.length,\n spec.tags.indexOf(tag)\n );\n\n matches.push({\n field: 'tags',\n text: tag,\n score,\n highlights,\n occurrences,\n });\n }\n }\n }\n\n // Search description - include if it has ANY query terms\n if (spec.description && containsAnyTerm(spec.description, queryTerms)) {\n const occurrences = countOccurrences(spec.description, queryTerms);\n const highlights = findMatchPositions(spec.description, queryTerms);\n const score = calculateMatchScore(\n { field: 'description', text: spec.description, occurrences },\n queryTerms,\n 1,\n 0\n );\n\n matches.push({\n field: 'description',\n text: spec.description,\n score,\n highlights,\n occurrences,\n });\n }\n\n // Search content\n if (spec.content) {\n const contentMatches = searchContent(\n spec.content,\n queryTerms,\n contextLength\n );\n matches.push(...contentMatches);\n }\n\n return matches;\n}\n\n/**\n * Search content with context extraction\n * \n * Returns matches from lines containing ANY query terms\n */\nfunction searchContent(\n content: string,\n queryTerms: string[],\n contextLength: number\n): SearchMatch[] {\n const matches: SearchMatch[] = [];\n const lines = content.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n \n // Include lines with ANY query terms (not all terms)\n if (containsAnyTerm(line, queryTerms)) {\n const occurrences = countOccurrences(line, queryTerms);\n const { text, highlights } = extractSmartContext(\n content,\n i,\n queryTerms,\n contextLength\n );\n\n const score = calculateMatchScore(\n { field: 'content', text: line, occurrences },\n queryTerms,\n lines.length,\n i\n );\n\n matches.push({\n field: 'content',\n text,\n lineNumber: i + 1, // 1-based line numbers\n score,\n highlights,\n occurrences,\n });\n }\n }\n\n return matches;\n}\n\n/**\n * Convert spec to search result format\n */\nfunction specToSearchResult(spec: SearchableSpec): SearchResultSpec {\n return {\n name: spec.name,\n path: spec.path,\n status: spec.status,\n priority: spec.priority,\n tags: spec.tags,\n title: spec.title,\n description: spec.description,\n };\n}\n\n/**\n * Check if a spec matches field filters\n */\nfunction specMatchesFieldFilters(spec: SearchableSpec, filters: FieldFilter[]): boolean {\n for (const filter of filters) {\n const field = filter.field;\n const filterValue = filter.value.toLowerCase();\n\n switch (field) {\n case 'status':\n if (spec.status.toLowerCase() !== filterValue) return false;\n break;\n case 'tag':\n case 'tags':\n if (!spec.tags?.some(tag => tag.toLowerCase() === filterValue)) return false;\n break;\n case 'priority':\n if (spec.priority?.toLowerCase() !== filterValue) return false;\n break;\n case 'assignee':\n if (spec.assignee?.toLowerCase() !== filterValue) return false;\n break;\n case 'title':\n if (!spec.title?.toLowerCase().includes(filterValue)) return false;\n break;\n case 'name':\n if (!spec.name.toLowerCase().includes(filterValue)) return false;\n break;\n // Date filters are handled separately\n case 'created':\n case 'updated':\n break;\n }\n }\n return true;\n}\n\n/**\n * Check if a spec matches date filters\n */\nfunction specMatchesDateFilters(spec: SearchableSpec, filters: DateFilter[]): boolean {\n for (const filter of filters) {\n const field = filter.field;\n const specDate = field === 'created' ? spec.created : spec.updated;\n \n if (!specDate) return false;\n \n // Normalize dates for comparison (just the date part)\n const specDateStr = specDate.substring(0, 10);\n const filterDateStr = filter.value.substring(0, 10);\n \n switch (filter.operator) {\n case '>':\n if (specDateStr <= filterDateStr) return false;\n break;\n case '>=':\n if (specDateStr < filterDateStr) return false;\n break;\n case '<':\n if (specDateStr >= filterDateStr) return false;\n break;\n case '<=':\n if (specDateStr > filterDateStr) return false;\n break;\n case '=':\n if (!specDateStr.startsWith(filterDateStr)) return false;\n break;\n case 'range':\n if (filter.endValue) {\n const endDateStr = filter.endValue.substring(0, 10);\n if (specDateStr < filterDateStr || specDateStr > endDateStr) return false;\n }\n break;\n }\n }\n return true;\n}\n\n/**\n * Evaluate AST against a spec (for boolean logic)\n */\nfunction evaluateAST(node: ASTNode | null, spec: SearchableSpec): boolean {\n if (!node) return true;\n\n switch (node.type) {\n case 'AND':\n return evaluateAST(node.left!, spec) && evaluateAST(node.right!, spec);\n case 'OR':\n return evaluateAST(node.left!, spec) || evaluateAST(node.right!, spec);\n case 'NOT':\n return !evaluateAST(node.left!, spec);\n case 'TERM':\n case 'PHRASE':\n return specContainsAllTerms(spec, [node.value!.toLowerCase()]);\n case 'FUZZY':\n return specContainsFuzzyTerm(spec, node.value!);\n case 'FIELD':\n return specMatchesFieldFilters(spec, [\n { field: node.field!, value: node.value!, exact: true },\n ]);\n default:\n return true;\n }\n}\n\n/**\n * Check if a spec contains a fuzzy term\n */\nfunction specContainsFuzzyTerm(spec: SearchableSpec, term: string): boolean {\n const allText = [\n spec.title || '',\n spec.name || '',\n spec.tags?.join(' ') || '',\n spec.description || '',\n spec.content || '',\n ].join(' ');\n\n return fuzzyMatch(term, allText);\n}\n\n/**\n * Advanced search with query syntax support\n * \n * @param query - Search query string with optional advanced syntax\n * @param specs - Specs to search\n * @param options - Search options\n * @returns Search results with relevance scoring\n */\nexport function advancedSearchSpecs(\n query: string,\n specs: SearchableSpec[],\n options: SearchOptions = {}\n): SearchResponse {\n const startTime = Date.now();\n const parsedQuery = parseQuery(query);\n\n // If no advanced syntax, delegate to regular search\n if (!parsedQuery.hasAdvancedSyntax && parsedQuery.errors.length === 0) {\n return searchSpecs(query, specs, options);\n }\n\n // Search options\n const maxMatchesPerSpec = options.maxMatchesPerSpec || 5;\n const contextLength = options.contextLength || 80;\n\n // Build combined query terms for highlighting (excluding field filters)\n const queryTerms = [\n ...parsedQuery.terms,\n ...parsedQuery.fuzzyTerms,\n ];\n\n // Filter by field and date filters first\n const nonDateFieldFilters = parsedQuery.fields.filter(\n f => f.field !== 'created' && f.field !== 'updated'\n );\n\n // Search each spec\n const results: SearchResult[] = [];\n\n for (const spec of specs) {\n // Check field filters\n if (!specMatchesFieldFilters(spec, nonDateFieldFilters)) {\n continue;\n }\n\n // Check date filters\n if (!specMatchesDateFilters(spec, parsedQuery.dateFilters)) {\n continue;\n }\n\n // Evaluate AST for boolean logic\n if (parsedQuery.ast && !evaluateAST(parsedQuery.ast, spec)) {\n continue;\n }\n\n // For specs that match the AST, collect matches for context\n const matches = queryTerms.length > 0\n ? searchSpec(spec, queryTerms, contextLength)\n : [];\n\n // Include spec if it matched the AST (already verified above)\n // Even if no highlighting matches found, the spec matched the query criteria\n let processedMatches = deduplicateMatches(matches, 3);\n processedMatches = limitMatches(processedMatches, maxMatchesPerSpec);\n\n const score = matches.length > 0 ? calculateSpecScore(processedMatches) : 50;\n\n results.push({\n spec: specToSearchResult(spec),\n score,\n totalMatches: matches.length || 1,\n matches: processedMatches,\n });\n }\n\n // Sort by relevance score (descending)\n results.sort((a, b) => b.score - a.score);\n\n return {\n results,\n metadata: {\n totalResults: results.length,\n searchTime: Date.now() - startTime,\n query,\n specsSearched: specs.length,\n },\n };\n}\n\n/**\n * Search specs with intelligent relevance ranking, with support for advanced query syntax\n * \n * Automatically detects advanced syntax (AND, OR, NOT, field:value, etc.) and uses\n * the appropriate search method.\n * \n * @param query - Search query string (supports advanced syntax)\n * @param specs - Specs to search\n * @param options - Search options\n * @returns Search results with relevance scoring\n */\nexport function searchSpecsAdvanced(\n query: string,\n specs: SearchableSpec[],\n options: SearchOptions = {}\n): SearchResponse {\n return advancedSearchSpecs(query, specs, options);\n}\n","/**\n * Sub-spec validator - validates sub-spec files per spec 012 conventions\n * \n * Phase 3.5: Sub-Spec Validation\n * - Validates sub-spec naming conventions\n * - Checks README.md references all sub-specs\n * - Validates complexity (token count + structure) per sub-spec file\n * - Detects orphaned sub-spec files (not linked from README)\n * - Validates cross-document references\n * \n * Updated per spec 066: Uses complexity scoring instead of line counts\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { countTokens } from '@leanspec/core';\nimport matter from 'gray-matter';\nimport type { ValidationRule, ValidationResult, ValidationError, ValidationWarning } from '../utils/validation-framework.js';\nimport type { SpecInfo } from '../spec-loader.js';\nimport { loadSubFiles, type SubFileInfo } from '../spec-loader.js';\n\nexport interface SubSpecOptions {\n // Token thresholds (same as ComplexityValidator)\n excellentThreshold?: number; // Default: 2000 tokens\n goodThreshold?: number; // Default: 3500 tokens\n warningThreshold?: number; // Default: 5000 tokens\n \n // Line count backstop (safety net)\n maxLines?: number; // Default: 500 lines\n\n // Cross-reference validation toggle\n checkCrossReferences?: boolean; // Default: true\n}\n\nexport class SubSpecValidator implements ValidationRule {\n name = 'sub-specs';\n description = 'Validate sub-spec files using direct token thresholds (spec 071)';\n\n private excellentThreshold: number;\n private goodThreshold: number;\n private warningThreshold: number;\n private maxLines: number;\n private checkCrossRefs: boolean;\n\n constructor(options: SubSpecOptions = {}) {\n // Token thresholds (hypothesis values based on research)\n this.excellentThreshold = options.excellentThreshold ?? 2000;\n this.goodThreshold = options.goodThreshold ?? 3500;\n this.warningThreshold = options.warningThreshold ?? 5000;\n \n // Line count backstop\n this.maxLines = options.maxLines ?? 500;\n\n // Cross-reference validation toggle\n this.checkCrossRefs = options.checkCrossReferences ?? true;\n }\n\n async validate(spec: SpecInfo, content: string): Promise<ValidationResult> {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n // Load sub-files for this spec\n const subFiles = await loadSubFiles(spec.fullPath, { includeContent: true });\n \n // Filter to only markdown documents (sub-specs)\n const subSpecs = subFiles.filter(f => f.type === 'document');\n\n // If no sub-specs, validation passes (nothing to check)\n if (subSpecs.length === 0) {\n return { passed: true, errors, warnings };\n }\n\n // Validate naming conventions\n this.validateNamingConventions(subSpecs, warnings);\n\n // Validate complexity (token count + structure) for each sub-spec\n await this.validateComplexity(subSpecs, errors, warnings);\n\n // Check for orphaned sub-specs (not referenced in README.md)\n this.checkOrphanedSubSpecs(subSpecs, content, warnings);\n\n if (this.checkCrossRefs) {\n this.validateCrossReferences(subSpecs, warnings);\n }\n\n return {\n passed: errors.length === 0,\n errors,\n warnings,\n };\n }\n\n /**\n * Validate sub-spec naming conventions\n * Convention: Uppercase filenames (e.g., DESIGN.md, TESTING.md, IMPLEMENTATION.md)\n */\n private validateNamingConventions(subSpecs: SubFileInfo[], warnings: ValidationWarning[]): void {\n for (const subSpec of subSpecs) {\n const baseName = path.basename(subSpec.name, '.md');\n \n // Check if filename follows uppercase convention\n if (baseName !== baseName.toUpperCase()) {\n warnings.push({\n message: `Sub-spec filename should be uppercase: ${subSpec.name}`,\n suggestion: `Consider renaming to ${baseName.toUpperCase()}.md`,\n });\n }\n }\n }\n\n /**\n * Validate complexity for each sub-spec file using direct token thresholds\n * Same approach as ComplexityValidator (spec 071)\n */\n private async validateComplexity(\n subSpecs: SubFileInfo[], \n errors: ValidationError[], \n warnings: ValidationWarning[]\n ): Promise<void> {\n for (const subSpec of subSpecs) {\n if (!subSpec.content) {\n continue;\n }\n\n const lines = subSpec.content.split('\\n');\n const lineCount = lines.length;\n\n // Count sections (## headings, excluding code blocks)\n let sectionCount = 0;\n let inCodeBlock = false;\n for (const line of lines) {\n if (line.trim().startsWith('```')) {\n inCodeBlock = !inCodeBlock;\n continue;\n }\n if (!inCodeBlock && line.match(/^#{2,4}\\s/)) {\n sectionCount++;\n }\n }\n\n // Count tokens (async, accurate)\n const tokenResult = await countTokens(subSpec.content);\n const tokenCount = tokenResult.total;\n\n // PRIMARY CHECK: Direct token thresholds\n if (tokenCount > this.warningThreshold) {\n errors.push({\n message: `Sub-spec ${subSpec.name} has ${tokenCount.toLocaleString()} tokens (threshold: ${this.warningThreshold.toLocaleString()}) - should split`,\n suggestion: 'Consider splitting for Context Economy (attention and cognitive load)',\n });\n } else if (tokenCount > this.goodThreshold) {\n warnings.push({\n message: `Sub-spec ${subSpec.name} has ${tokenCount.toLocaleString()} tokens (threshold: ${this.goodThreshold.toLocaleString()})`,\n suggestion: 'Consider simplification or further splitting',\n });\n }\n\n // STRUCTURE CHECK: Sectioning\n if (sectionCount < 8 && lineCount > 200) {\n warnings.push({\n message: `Sub-spec ${subSpec.name} has only ${sectionCount} sections - too monolithic`,\n suggestion: 'Break into 15-35 sections for better readability (7±2 cognitive chunks)',\n });\n }\n }\n }\n\n /**\n * Check for orphaned sub-specs not referenced in README.md\n */\n private checkOrphanedSubSpecs(\n subSpecs: SubFileInfo[], \n readmeContent: string,\n warnings: ValidationWarning[]\n ): void {\n for (const subSpec of subSpecs) {\n // Check if sub-spec is referenced in README\n // Look for markdown links like [text](./FILENAME.md) or [text](FILENAME.md)\n const fileName = subSpec.name;\n // Escape special regex characters in filename\n const escapedFileName = fileName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n // Match with optional ./ prefix\n const linkPattern = new RegExp(`\\\\[([^\\\\]]+)\\\\]\\\\((?:\\\\.\\\\/)?${escapedFileName}\\\\)`, 'gi');\n const isReferenced = linkPattern.test(readmeContent);\n\n if (!isReferenced) {\n warnings.push({\n message: `Orphaned sub-spec: ${fileName} (not linked from README.md)`,\n suggestion: `Add a link to ${fileName} in README.md to document its purpose`,\n });\n }\n }\n }\n\n /**\n * Detect cross-document references that point to missing files\n */\n private validateCrossReferences(\n subSpecs: SubFileInfo[],\n warnings: ValidationWarning[]\n ): void {\n const availableFiles = new Set<string>(\n subSpecs.map(subSpec => subSpec.name.toLowerCase())\n );\n availableFiles.add('readme.md');\n\n const linkPattern = /\\[[^\\]]+\\]\\(([^)]+)\\)/gi;\n\n for (const subSpec of subSpecs) {\n if (!subSpec.content) continue;\n\n for (const match of subSpec.content.matchAll(linkPattern)) {\n const rawTarget = match[1].split('#')[0]?.trim();\n if (!rawTarget || !rawTarget.toLowerCase().endsWith('.md')) {\n continue;\n }\n\n const normalized = rawTarget.replace(/^\\.\\//, '');\n const normalizedLower = normalized.toLowerCase();\n\n if (availableFiles.has(normalizedLower)) {\n continue;\n }\n\n warnings.push({\n message: `Broken reference in ${subSpec.name}: ${normalized}`,\n suggestion: `Ensure ${normalized} exists or update the link`,\n });\n }\n }\n }\n\n}\n","/**\n * Dependency Alignment Validator\n * \n * Detects when spec content references other specs but those references\n * are not reflected in frontmatter depends_on fields.\n * \n * This catches a common AI agent failure mode: writing content that mentions\n * dependencies but forgetting to use `lean-spec link` to add them to frontmatter.\n */\n\nimport type { ValidationRule, ValidationResult, ValidationError, ValidationWarning } from '../utils/validation-framework.js';\nimport type { SpecInfo } from '../spec-loader.js';\nimport matter from 'gray-matter';\nimport yaml from 'js-yaml';\n\nexport interface DependencyAlignmentOptions {\n /** Treat misalignment as errors instead of warnings */\n strict?: boolean;\n /** Set of existing spec numbers to validate against (only warn about refs to existing specs) */\n existingSpecNumbers?: Set<string>;\n}\n\n/**\n * Patterns to detect spec references in content\n */\nconst SPEC_REF_PATTERNS = [\n // \"spec 045\", \"Spec 045\", \"spec-045\"\n /\\bspec[- ]?(\\d{3})\\b/gi,\n // \"045-unified-dashboard\" (full spec folder name)\n /\\b(\\d{3})-[a-z][a-z0-9-]+\\b/gi,\n];\n\n/**\n * Patterns that indicate blocking dependencies (depends_on)\n */\nconst DEPENDS_ON_PATTERNS = [\n /depends on[:\\s]+.*?\\b(\\d{3})\\b/gi,\n /blocked by[:\\s]+.*?\\b(\\d{3})\\b/gi,\n /requires[:\\s]+.*?spec[:\\s]*(\\d{3})\\b/gi,\n /prerequisite[:\\s]+.*?\\b(\\d{3})\\b/gi,\n /after[:\\s]+.*?spec[:\\s]*(\\d{3})\\b/gi,\n /builds on[:\\s]+.*?\\b(\\d{3})\\b/gi,\n /extends[:\\s]+.*?\\b(\\d{3})\\b/gi,\n];\n\ninterface DetectedRef {\n specNumber: string;\n type: 'depends_on';\n context: string;\n}\n\nexport class DependencyAlignmentValidator implements ValidationRule {\n name = 'dependency-alignment';\n description = 'Detect content references to specs not linked in frontmatter';\n\n private strict: boolean;\n private existingSpecNumbers: Set<string> | null;\n\n constructor(options: DependencyAlignmentOptions = {}) {\n this.strict = options.strict ?? false;\n this.existingSpecNumbers = options.existingSpecNumbers ?? null;\n }\n\n /**\n * Set the existing spec numbers to validate against\n */\n setExistingSpecNumbers(numbers: Set<string>): void {\n this.existingSpecNumbers = numbers;\n }\n\n validate(spec: SpecInfo, content: string): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n // Parse frontmatter to get current deps\n let parsed;\n try {\n parsed = matter(content, {\n engines: {\n yaml: (str) => yaml.load(str, { schema: yaml.FAILSAFE_SCHEMA }) as Record<string, unknown>\n }\n });\n } catch {\n // If frontmatter parsing fails, skip this validator (frontmatter validator will catch it)\n return { passed: true, errors: [], warnings: [] };\n }\n\n const frontmatter = parsed.data;\n const bodyContent = parsed.content;\n\n // Get current frontmatter dependencies\n const currentDependsOn = this.normalizeDeps(frontmatter.depends_on);\n\n // Get this spec's number to exclude self-references\n const selfNumber = this.extractSpecNumber(spec.name);\n\n // Detect references in content\n const detectedRefs = this.detectReferences(bodyContent, selfNumber);\n\n // Find missing dependencies (only for specs that exist)\n const missingDependsOn: DetectedRef[] = [];\n\n for (const ref of detectedRefs) {\n // Skip if already linked\n if (currentDependsOn.includes(ref.specNumber)) continue;\n \n // Skip if we have existing spec numbers and this one doesn't exist\n if (this.existingSpecNumbers && !this.existingSpecNumbers.has(ref.specNumber)) continue;\n\n missingDependsOn.push(ref);\n }\n\n // Generate warnings/errors for missing deps\n if (missingDependsOn.length > 0) {\n const specNumbers = [...new Set(missingDependsOn.map(r => r.specNumber))];\n const issue = {\n message: `Content references dependencies not in frontmatter: ${specNumbers.join(', ')}`,\n suggestion: `Run: lean-spec link ${spec.name} --depends-on ${specNumbers.join(',')}`,\n };\n if (this.strict) {\n errors.push(issue);\n } else {\n warnings.push(issue);\n }\n }\n\n return {\n passed: errors.length === 0,\n errors,\n warnings,\n };\n }\n\n /**\n * Normalize dependency field to array of spec numbers\n */\n private normalizeDeps(deps: unknown): string[] {\n if (!deps) return [];\n \n const depArray = Array.isArray(deps) ? deps : [deps];\n return depArray.map(d => {\n const str = String(d);\n // Extract just the number part\n const match = str.match(/(\\d{3})/);\n return match ? match[1] : str;\n }).filter(Boolean);\n }\n\n /**\n * Extract spec number from spec name (e.g., \"045-unified-dashboard\" -> \"045\")\n */\n private extractSpecNumber(specName: string): string | null {\n const match = specName.match(/^(\\d{3})/);\n return match ? match[1] : null;\n }\n\n /**\n * Detect spec references in content that indicate dependencies\n */\n private detectReferences(content: string, selfNumber: string | null): DetectedRef[] {\n const refs: DetectedRef[] = [];\n const seenNumbers = new Set<string>();\n\n // Check for explicit dependency patterns\n for (const pattern of DEPENDS_ON_PATTERNS) {\n const matches = content.matchAll(new RegExp(pattern));\n for (const match of matches) {\n const specNumber = match[1];\n if (specNumber && specNumber !== selfNumber && !seenNumbers.has(specNumber)) {\n seenNumbers.add(specNumber);\n refs.push({\n specNumber,\n type: 'depends_on',\n context: match[0].substring(0, 50),\n });\n }\n }\n }\n\n return refs;\n }\n}\n","/**\n * Shared color scheme for status and priority across all commands\n * Ensures consistent visual representation throughout the CLI\n */\n\nimport chalk from 'chalk';\nimport type { SpecStatus, SpecPriority } from '../frontmatter.js';\n\n/**\n * Status color and display configuration\n * Colors: planned (blue), in-progress (yellow), complete (green), archived (gray)\n */\nexport const STATUS_CONFIG: Record<SpecStatus, { \n emoji: string; \n label: string; \n colorFn: (s: string) => string;\n badge: (s?: string) => string;\n}> = {\n planned: { \n emoji: '📅', \n label: 'Planned', \n colorFn: chalk.blue,\n badge: (s = 'planned') => chalk.blue(`[${s}]`),\n },\n 'in-progress': { \n emoji: '⏳', \n label: 'In Progress', \n colorFn: chalk.yellow,\n badge: (s = 'in-progress') => chalk.yellow(`[${s}]`),\n },\n complete: { \n emoji: '✅', \n label: 'Complete', \n colorFn: chalk.green,\n badge: (s = 'complete') => chalk.green(`[${s}]`),\n },\n archived: { \n emoji: '📦', \n label: 'Archived', \n colorFn: chalk.gray,\n badge: (s = 'archived') => chalk.gray(`[${s}]`),\n },\n};\n\n/**\n * Priority color and display configuration\n * Colors: critical (red bold), high (red), medium (yellow), low (gray)\n */\nexport const PRIORITY_CONFIG: Record<SpecPriority, { \n emoji: string; \n colorFn: (s: string) => string;\n badge: (s?: string) => string;\n}> = {\n critical: { \n emoji: '🔴', \n colorFn: chalk.red.bold,\n badge: (s = 'critical') => chalk.red.bold(`[${s}]`),\n },\n high: { \n emoji: '🟠', \n colorFn: chalk.hex('#FFA500'),\n badge: (s = 'high') => chalk.hex('#FFA500')(`[${s}]`),\n },\n medium: { \n emoji: '🟡', \n colorFn: chalk.yellow,\n badge: (s = 'medium') => chalk.yellow(`[${s}]`),\n },\n low: { \n emoji: '🟢', \n colorFn: chalk.gray,\n badge: (s = 'low') => chalk.gray(`[${s}]`),\n },\n};\n\n/**\n * Get status badge (e.g., [planned], [in-progress])\n */\nexport function formatStatusBadge(status: SpecStatus): string {\n return STATUS_CONFIG[status]?.badge() || chalk.white(`[${status}]`);\n}\n\n/**\n * Get priority badge (e.g., [critical], [high])\n */\nexport function formatPriorityBadge(priority: SpecPriority): string {\n return PRIORITY_CONFIG[priority]?.badge() || chalk.white(`[${priority}]`);\n}\n\n/**\n * Get status indicator with emoji (for deps command)\n */\nexport function getStatusIndicator(status: SpecStatus): string {\n const config = STATUS_CONFIG[status];\n if (!config) return chalk.gray('[unknown]');\n return config.colorFn(`[${status}]`);\n}\n\n/**\n * Get status emoji\n */\nexport function getStatusEmoji(status: SpecStatus): string {\n return STATUS_CONFIG[status]?.emoji || '📄';\n}\n\n/**\n * Get priority emoji\n */\nexport function getPriorityEmoji(priority?: SpecPriority): string {\n return priority ? (PRIORITY_CONFIG[priority]?.emoji || '') : '';\n}\n","/**\n * Validate output formatter - ESLint/TypeScript style formatting\n * \n * Implements file-centric, severity-first output format for spec validation.\n */\n\nimport chalk from 'chalk';\nimport type { ValidationResult } from './validation-framework.js';\nimport type { SpecInfo } from '../spec-loader.js';\nimport { formatStatusBadge, formatPriorityBadge } from './colors.js';\n\nexport interface ValidationIssue {\n severity: 'error' | 'warning';\n message: string;\n suggestion?: string;\n ruleName: string;\n filePath: string; // Full path to the spec file or sub-spec file\n spec?: SpecInfo; // Reference to spec for metadata display\n}\n\nexport interface FileValidationResult {\n filePath: string; // Display path (relative to specs directory)\n issues: ValidationIssue[];\n spec?: SpecInfo; // Reference to spec for metadata display\n}\n\nexport interface FormatOptions {\n verbose?: boolean; // Show passing specs\n quiet?: boolean; // Suppress warnings and only show errors\n format?: 'default' | 'json' | 'compact';\n rule?: string; // Filter by specific rule name\n}\n\n/**\n * Convert validation results to issue format grouped by file\n */\nexport function groupIssuesByFile(\n results: Array<{\n spec: SpecInfo;\n validatorName: string;\n result: ValidationResult;\n content: string;\n }>\n): FileValidationResult[] {\n const fileMap = new Map<string, { issues: ValidationIssue[], spec?: SpecInfo }>();\n\n // Helper function to add issue to fileMap\n const addIssue = (filePath: string, issue: ValidationIssue, spec: SpecInfo) => {\n if (!fileMap.has(filePath)) {\n fileMap.set(filePath, { issues: [], spec });\n }\n fileMap.get(filePath)!.issues.push(issue);\n };\n\n for (const { spec, validatorName, result } of results) {\n // Process errors - they are associated with the main spec file\n for (const error of result.errors) {\n addIssue(spec.filePath, {\n severity: 'error',\n message: error.message,\n suggestion: error.suggestion,\n ruleName: validatorName,\n filePath: spec.filePath,\n spec,\n }, spec);\n }\n\n // Process warnings - they are associated with the main spec file\n for (const warning of result.warnings) {\n addIssue(spec.filePath, {\n severity: 'warning',\n message: warning.message,\n suggestion: warning.suggestion,\n ruleName: validatorName,\n filePath: spec.filePath,\n spec,\n }, spec);\n }\n }\n\n // Convert map to array and sort\n const fileResults: FileValidationResult[] = [];\n for (const [filePath, data] of fileMap.entries()) {\n // Sort issues: errors first, then warnings\n data.issues.sort((a, b) => {\n if (a.severity === b.severity) return 0;\n return a.severity === 'error' ? -1 : 1;\n });\n\n fileResults.push({ filePath, issues: data.issues, spec: data.spec });\n }\n\n // Sort files by spec name (natural order)\n fileResults.sort((a, b) => {\n if (a.spec?.name && b.spec?.name) {\n return a.spec.name.localeCompare(b.spec.name);\n }\n return a.filePath.localeCompare(b.filePath);\n });\n\n return fileResults;\n}\n\n/**\n * Normalize file path to be relative to current working directory\n */\nfunction normalizeFilePath(filePath: string): string {\n const cwd = process.cwd();\n \n if (filePath.startsWith(cwd)) {\n // Remove cwd prefix and leading slash\n return filePath.substring(cwd.length + 1);\n } else if (filePath.includes('/specs/')) {\n // Extract from /specs/ onwards\n const specsIndex = filePath.indexOf('/specs/');\n return filePath.substring(specsIndex + 1);\n }\n \n return filePath;\n}\n\n/**\n * Format issues for a single file (ESLint-style)\n */\nexport function formatFileIssues(fileResult: FileValidationResult, specsDir: string): string {\n const lines: string[] = [];\n \n // Display path (relative to current working directory or specs directory)\n const relativePath = normalizeFilePath(fileResult.filePath);\n \n // Check if this is a main spec file (ends with README.md)\n const isMainSpec = relativePath.endsWith('README.md');\n \n if (isMainSpec && fileResult.spec) {\n // For main spec: Show spec name with metadata\n const specName = fileResult.spec.name;\n const status = fileResult.spec.frontmatter.status;\n const priority = fileResult.spec.frontmatter.priority || 'medium';\n \n const statusBadge = formatStatusBadge(status);\n const priorityBadge = formatPriorityBadge(priority);\n \n lines.push(chalk.bold.cyan(`${specName} ${statusBadge} ${priorityBadge}`));\n } else {\n // For sub-specs: Show relative path\n lines.push(chalk.cyan.underline(relativePath));\n }\n\n // Format each issue with aligned columns\n for (const issue of fileResult.issues) {\n const severityColor = issue.severity === 'error' ? chalk.red : chalk.yellow;\n const severityText = severityColor(issue.severity.padEnd(9)); // \"error \" or \"warning \"\n const ruleText = chalk.gray(issue.ruleName);\n \n lines.push(` ${severityText}${issue.message.padEnd(60)} ${ruleText}`);\n \n if (issue.suggestion) {\n lines.push(chalk.gray(` → ${issue.suggestion}`));\n }\n }\n\n lines.push(''); // Empty line after each file\n return lines.join('\\n');\n}\n\n/**\n * Format summary line\n */\nexport function formatSummary(\n totalSpecs: number,\n errorCount: number,\n warningCount: number,\n cleanCount: number\n): string {\n if (errorCount > 0) {\n const errorText = errorCount === 1 ? 'error' : 'errors';\n const warningText = warningCount === 1 ? 'warning' : 'warnings';\n return chalk.red.bold(\n `✖ ${errorCount} ${errorText}, ${warningCount} ${warningText} (${totalSpecs} specs checked, ${cleanCount} clean)`\n );\n } else if (warningCount > 0) {\n const warningText = warningCount === 1 ? 'warning' : 'warnings';\n return chalk.yellow.bold(\n `⚠ ${warningCount} ${warningText} (${totalSpecs} specs checked, ${cleanCount} clean)`\n );\n } else {\n return chalk.green.bold(`✓ All ${totalSpecs} specs passed`);\n }\n}\n\n/**\n * Format passing specs list (for --verbose mode)\n */\nexport function formatPassingSpecs(specs: SpecInfo[], specsDir: string): string {\n const lines: string[] = [];\n lines.push(chalk.green.bold(`\\n✓ ${specs.length} specs passed:`));\n \n for (const spec of specs) {\n const relativePath = normalizeFilePath(spec.filePath);\n lines.push(chalk.gray(` ${relativePath}`));\n }\n \n return lines.join('\\n');\n}\n\n/**\n * Format validation results in JSON format\n */\nexport function formatJson(\n fileResults: FileValidationResult[],\n totalSpecs: number,\n errorCount: number,\n warningCount: number\n): string {\n const output = {\n summary: {\n totalSpecs,\n errorCount,\n warningCount,\n cleanCount: totalSpecs - fileResults.length,\n },\n files: fileResults.map(fr => ({\n filePath: fr.filePath,\n issues: fr.issues.map(issue => ({\n severity: issue.severity,\n message: issue.message,\n suggestion: issue.suggestion,\n rule: issue.ruleName,\n })),\n })),\n };\n\n return JSON.stringify(output, null, 2);\n}\n\n/**\n * Main formatting function\n */\nexport function formatValidationResults(\n results: Array<{\n spec: SpecInfo;\n validatorName: string;\n result: ValidationResult;\n content: string;\n }>,\n specs: SpecInfo[],\n specsDir: string,\n options: FormatOptions = {}\n): string {\n const fileResults = groupIssuesByFile(results);\n \n // Filter by rule if specified\n const filteredResults = options.rule\n ? fileResults\n .map(fr => ({\n ...fr,\n issues: fr.issues.filter(issue => issue.ruleName === options.rule),\n }))\n .filter(fr => fr.issues.length > 0)\n : fileResults;\n\n // Filter by quiet mode (only errors)\n const displayResults = options.quiet\n ? filteredResults.map(fr => ({\n ...fr,\n issues: fr.issues.filter(issue => issue.severity === 'error'),\n })).filter(fr => fr.issues.length > 0)\n : filteredResults;\n\n // JSON format\n if (options.format === 'json') {\n const errorCount = displayResults.reduce(\n (sum, fr) => sum + fr.issues.filter(i => i.severity === 'error').length,\n 0\n );\n const warningCount = displayResults.reduce(\n (sum, fr) => sum + fr.issues.filter(i => i.severity === 'warning').length,\n 0\n );\n return formatJson(displayResults, specs.length, errorCount, warningCount);\n }\n\n // Default format\n const lines: string[] = [];\n \n // Header\n lines.push(chalk.bold(`\\nValidating ${specs.length} specs...\\n`));\n\n // Track previous spec to add separators\n let previousSpecName: string | undefined;\n\n // File issues\n for (const fileResult of displayResults) {\n // Add separator between different specs\n if (fileResult.spec && previousSpecName && fileResult.spec.name !== previousSpecName) {\n lines.push(chalk.gray('─'.repeat(80)));\n lines.push('');\n }\n \n lines.push(formatFileIssues(fileResult, specsDir));\n \n if (fileResult.spec) {\n previousSpecName = fileResult.spec.name;\n }\n }\n\n // Summary\n const errorCount = displayResults.reduce(\n (sum, fr) => sum + fr.issues.filter(i => i.severity === 'error').length,\n 0\n );\n const warningCount = displayResults.reduce(\n (sum, fr) => sum + fr.issues.filter(i => i.severity === 'warning').length,\n 0\n );\n const cleanCount = specs.length - fileResults.length;\n\n lines.push(formatSummary(specs.length, errorCount, warningCount, cleanCount));\n\n // Verbose mode: show passing specs\n if (options.verbose && cleanCount > 0) {\n const specsWithIssues = new Set(fileResults.map(fr => fr.filePath));\n const passingSpecs = specs.filter(spec => !specsWithIssues.has(spec.filePath));\n lines.push(formatPassingSpecs(passingSpecs, specsDir));\n }\n\n // Add hint for verbose mode if not already in verbose mode\n if (!options.verbose && cleanCount > 0 && displayResults.length > 0) {\n lines.push(chalk.gray('\\nRun with --verbose to see passing specs.'));\n }\n\n return lines.join('\\n');\n}\n","/**\n * Validate command - validates specs for quality issues\n * \n * Phase 1a: Basic framework + line count validation\n * Phase 1b: Frontmatter validation\n * Phase 2: Structure validation\n * Phase 3: Corruption detection\n * Phase 3.5: Sub-spec validation\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config.js';\nimport { loadAllSpecs, type SpecInfo } from '../spec-loader.js';\nimport { withSpinner } from '../utils/ui.js';\nimport { LineCountValidator } from '../validators/line-count.js';\nimport { FrontmatterValidator } from '../validators/frontmatter.js';\nimport { StructureValidator } from '../validators/structure.js';\nimport { CorruptionValidator } from '../validators/corruption.js';\nimport { SubSpecValidator } from '../validators/sub-spec.js';\nimport { ComplexityValidator } from '../validators/complexity.js';\nimport { DependencyAlignmentValidator } from '../validators/dependency-alignment.js';\nimport type { ValidationRule, ValidationResult } from '../utils/validation-framework.js';\nimport { formatValidationResults, type FormatOptions } from '../utils/validate-formatter.js';\n\nexport interface ValidateOptions {\n maxLines?: number; // Custom line limit (default: 400)\n specs?: string[]; // Specific specs to validate, or all if not provided\n verbose?: boolean; // Show passing specs\n quiet?: boolean; // Suppress warnings, only show errors\n format?: 'default' | 'json' | 'compact'; // Output format\n json?: boolean; // Shorthand for --format json\n rule?: string; // Filter by specific rule name\n warningsOnly?: boolean; // Treat all issues as warnings, never fail (useful for CI)\n checkDeps?: boolean; // Include dependency alignment check\n}\n\ninterface ValidationResultWithSpec {\n spec: SpecInfo;\n validatorName: string;\n result: ValidationResult;\n content: string; // Store content to avoid duplicate reads\n}\n\n/**\n * Validate command - validate specs for quality issues\n */\nexport function validateCommand(): Command {\n return new Command('validate')\n .description('Validate specs for quality issues')\n .argument('[specs...]', 'Specific specs to validate (optional)')\n .option('--max-lines <number>', 'Custom line limit (default: 400)', parseInt)\n .option('--verbose', 'Show passing specs')\n .option('--quiet', 'Suppress warnings, only show errors')\n .option('--format <format>', 'Output format: default, json, compact', 'default')\n .option('--json', 'Output as JSON (shorthand for --format json)')\n .option('--rule <rule>', 'Filter by specific rule name (e.g., max-lines, frontmatter)')\n .option('--warnings-only', 'Treat all issues as warnings, never fail (useful for CI pre-release checks)')\n .option('--check-deps', 'Check for content/frontmatter dependency alignment')\n .action(async (specs: string[] | undefined, options: ValidateOptions) => {\n const passed = await validateSpecs({\n maxLines: options.maxLines,\n specs: specs && specs.length > 0 ? specs : undefined,\n verbose: options.verbose,\n quiet: options.quiet,\n format: options.json ? 'json' : options.format,\n rule: options.rule,\n warningsOnly: options.warningsOnly,\n checkDeps: options.checkDeps,\n });\n process.exit(passed ? 0 : 1);\n });\n}\n\n/**\n * Validate specs for quality issues\n */\nexport async function validateSpecs(options: ValidateOptions = {}): Promise<boolean> {\n const config = await loadConfig();\n\n // Load specs to validate\n let specs: SpecInfo[];\n if (options.specs && options.specs.length > 0) {\n // Validate specific specs - load all specs once and filter\n const allSpecs = await loadAllSpecs();\n specs = [];\n for (const specPath of options.specs) {\n const spec = allSpecs.find(s => \n s.path.includes(specPath) || \n path.basename(s.path).includes(specPath)\n );\n if (spec) {\n specs.push(spec);\n } else {\n console.error(chalk.red(`Error: Spec not found: ${specPath}`));\n return false;\n }\n }\n } else {\n // Validate all specs\n specs = await withSpinner(\n 'Loading specs...',\n () => loadAllSpecs({ includeArchived: false })\n );\n }\n\n if (specs.length === 0) {\n console.log('No specs found to validate.');\n return true;\n }\n\n // Initialize validators\n const validators: ValidationRule[] = [\n new ComplexityValidator({ maxLines: options.maxLines }), // Token-based complexity (primary), line count (backstop)\n new FrontmatterValidator(),\n new StructureValidator(),\n new CorruptionValidator(),\n new SubSpecValidator({ maxLines: options.maxLines }),\n ];\n\n // Add dependency alignment validator if requested\n if (options.checkDeps) {\n // Collect existing spec numbers for validation (only active specs, not archived)\n const activeSpecs = await loadAllSpecs({ includeArchived: false });\n const existingSpecNumbers = new Set<string>();\n for (const s of activeSpecs) {\n const match = s.name.match(/^(\\d{3})/);\n if (match) {\n existingSpecNumbers.add(match[1]);\n }\n }\n validators.push(new DependencyAlignmentValidator({ existingSpecNumbers }));\n }\n\n // Run validation\n const results: ValidationResultWithSpec[] = [];\n \n for (const spec of specs) {\n // Read spec content once\n let content: string;\n try {\n content = await fs.readFile(spec.filePath, 'utf-8');\n } catch (error) {\n console.error(chalk.red(`Error reading ${spec.filePath}:`), error);\n continue;\n }\n\n // Run all validators\n for (const validator of validators) {\n try {\n const result = await validator.validate(spec, content);\n results.push({ \n spec, \n validatorName: validator.name,\n result, \n content,\n });\n } catch (error) {\n console.error(chalk.yellow(`Warning: Validator ${validator.name} failed:`), error instanceof Error ? error.message : error);\n }\n }\n }\n\n // Format and display results using new formatter\n const formatOptions: FormatOptions = {\n verbose: options.verbose,\n quiet: options.quiet,\n format: options.format,\n rule: options.rule,\n };\n\n const output = formatValidationResults(results, specs, config.specsDir, formatOptions);\n console.log(output);\n\n // Determine if validation passed\n if (options.warningsOnly) {\n // In warnings-only mode, always pass (just report issues)\n return true;\n }\n \n // Normal mode: any errors = failed\n const hasErrors = results.some(r => !r.result.passed);\n return !hasErrors;\n}\n"]}