lean-spec 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp-server.ts","../src/spec-loader.ts","../src/config.ts","../src/commands/create.ts","../src/utils/path-helpers.ts","../src/utils/variable-resolver.ts","../src/commands/check.ts","../src/utils/ui.ts","../src/utils/safe-output.ts","../src/commands/archive.ts","../src/commands/list.ts","../src/utils/pattern-detection.ts","../src/utils/colors.ts","../src/commands/update.ts","../src/commands/backfill.ts","../src/utils/git-timestamps.ts","../src/commands/templates.ts","../src/commands/init.ts","../src/utils/template-helpers.ts","../src/commands/files.ts","../src/commands/validate.ts","../src/validators/line-count.ts","../src/validators/frontmatter.ts","../src/validators/structure.ts","../src/validators/corruption.ts","../src/validators/sub-spec.ts","../src/utils/validate-formatter.ts","../src/commands/migrate.ts","../src/commands/board.ts","../src/utils/completion.ts","../src/utils/velocity.ts","../src/commands/stats.ts","../src/utils/spec-stats.ts","../src/utils/insights.ts","../src/commands/search.ts","../src/commands/deps.ts","../src/commands/timeline.ts","../src/commands/gantt.ts","../src/commands/viewer.ts","../src/commands/mcp.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * LeanSpec MCP Server\n * \n * Model Context Protocol server that exposes LeanSpec functionality to AI assistants.\n * This enables AI agents to interact with LeanSpec projects directly from their environment.\n */\n\nimport { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { loadAllSpecs, getSpec } from './spec-loader.js';\nimport { loadConfig } from './config.js';\nimport { createSpec, listSpecs, updateSpec, archiveSpec, checkSpecs, validateCommand, backfillTimestamps, filesCommand } from './commands/index.js';\nimport { readSpecContent } from './commands/viewer.js';\nimport { parseFrontmatter } from './frontmatter.js';\nimport type { SpecStatus, SpecPriority, SpecFilterOptions } from './frontmatter.js';\nimport { resolveSpecPath } from './utils/path-helpers.js';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\n// Type definitions for better type safety\ntype SpecData = {\n name: string;\n path: string;\n status: SpecStatus;\n created: string;\n title?: string;\n tags?: string[];\n priority?: SpecPriority;\n assignee?: string;\n description?: string;\n customFields?: Record<string, unknown>;\n};\n\ntype StatsData = {\n total: number;\n byStatus: Record<SpecStatus, number>;\n byPriority: Record<SpecPriority, number>;\n byTag: Record<string, number>;\n recentlyUpdated: SpecData[];\n};\n\ntype BoardData = {\n columns: {\n [key in SpecStatus]: SpecData[];\n };\n};\n\n/**\n * Helper function to format error messages\n */\nfunction formatErrorMessage(prefix: string, error: unknown): string {\n const errorMsg = error instanceof Error ? error.message : String(error);\n return `${prefix}: ${errorMsg}`;\n}\n\n/**\n * Helper function to convert spec info to serializable format\n */\nfunction specToData(spec: any): SpecData {\n return {\n name: spec.name,\n path: spec.path,\n status: spec.frontmatter.status,\n created: spec.frontmatter.created,\n title: spec.frontmatter.title,\n tags: spec.frontmatter.tags,\n priority: spec.frontmatter.priority,\n assignee: spec.frontmatter.assignee,\n description: spec.frontmatter.description,\n customFields: spec.frontmatter.custom,\n };\n}\n\n/**\n * List specs with optional filtering\n */\nasync function listSpecsData(options: {\n status?: SpecStatus | SpecStatus[];\n tags?: string[];\n priority?: SpecPriority | SpecPriority[];\n assignee?: string;\n customFields?: Record<string, unknown>;\n includeArchived?: boolean;\n}): Promise<SpecData[]> {\n const filter: SpecFilterOptions = {};\n if (options.status) filter.status = options.status;\n if (options.tags) filter.tags = options.tags;\n if (options.priority) filter.priority = options.priority;\n if (options.assignee) filter.assignee = options.assignee;\n if (options.customFields) filter.customFields = options.customFields;\n\n const specs = await loadAllSpecs({\n includeArchived: options.includeArchived || false,\n filter,\n });\n\n return specs.map(specToData);\n}\n\n/**\n * Search specs for a query\n */\nasync function searchSpecsData(query: string, options: {\n status?: SpecStatus;\n tags?: string[];\n priority?: SpecPriority;\n assignee?: string;\n customFields?: Record<string, unknown>;\n}): Promise<Array<{ spec: SpecData; matches: string[] }>> {\n const filter: SpecFilterOptions = {};\n if (options.status) filter.status = options.status;\n if (options.tags) filter.tags = options.tags;\n if (options.priority) filter.priority = options.priority;\n if (options.assignee) filter.assignee = options.assignee;\n if (options.customFields) filter.customFields = options.customFields;\n\n const specs = await loadAllSpecs({\n includeArchived: true,\n includeContent: true,\n filter,\n });\n\n const results: Array<{ spec: SpecData; matches: string[] }> = [];\n const queryLower = query.toLowerCase();\n\n for (const spec of specs) {\n if (!spec.content) continue;\n\n const matches: string[] = [];\n const lines = spec.content.split('\\n');\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line.toLowerCase().includes(queryLower)) {\n matches.push(line.trim());\n if (matches.length >= 5) break; // Limit matches per spec\n }\n }\n\n if (matches.length > 0) {\n results.push({ spec: specToData(spec), matches });\n }\n }\n\n return results;\n}\n\n/**\n * Read full spec content (supports sub-spec files like \"045/DESIGN.md\")\n */\nasync function readSpecData(specPath: string): Promise<{ spec: SpecData; content: string }> {\n const cwd = process.cwd();\n \n // Use readSpecContent which handles both main specs and sub-spec files\n const specContent = await readSpecContent(specPath, cwd);\n \n if (!specContent) {\n throw new Error(`Spec not found: ${specPath}`);\n }\n\n return {\n spec: {\n name: specContent.name,\n path: specContent.path,\n status: specContent.frontmatter.status,\n created: String(specContent.frontmatter.created),\n priority: specContent.frontmatter.priority,\n tags: specContent.frontmatter.tags,\n assignee: specContent.frontmatter.assignee,\n },\n content: specContent.content,\n };\n}\n\n/**\n * Get project statistics\n */\nasync function getStatsData(): Promise<StatsData> {\n const specs = await loadAllSpecs({\n includeArchived: false,\n });\n\n const byStatus: Record<SpecStatus, number> = {\n planned: 0,\n 'in-progress': 0,\n complete: 0,\n archived: 0,\n };\n\n const byPriority: Record<SpecPriority, number> = {\n low: 0,\n medium: 0,\n high: 0,\n critical: 0,\n };\n\n const byTag: Record<string, number> = {};\n\n for (const spec of specs) {\n byStatus[spec.frontmatter.status] = (byStatus[spec.frontmatter.status] || 0) + 1;\n if (spec.frontmatter.priority) {\n byPriority[spec.frontmatter.priority] = (byPriority[spec.frontmatter.priority] || 0) + 1;\n }\n if (spec.frontmatter.tags) {\n for (const tag of spec.frontmatter.tags) {\n byTag[tag] = (byTag[tag] || 0) + 1;\n }\n }\n }\n\n // Get recently updated (sort by path which includes date in many configs)\n const recentlyUpdated = specs\n .sort((a, b) => b.path.localeCompare(a.path))\n .slice(0, 5)\n .map(specToData);\n\n return {\n total: specs.length,\n byStatus,\n byPriority,\n byTag,\n recentlyUpdated,\n };\n}\n\n/**\n * Get Kanban board view\n */\nasync function getBoardData(): Promise<BoardData> {\n const specs = await loadAllSpecs({\n includeArchived: false,\n });\n\n const columns: BoardData['columns'] = {\n planned: [],\n 'in-progress': [],\n complete: [],\n archived: [],\n };\n\n for (const spec of specs) {\n columns[spec.frontmatter.status].push(specToData(spec));\n }\n\n return { columns };\n}\n\n/**\n * Regex pattern for detecting spec references in content.\n * Matches patterns like:\n * - \"spec: 001-feature\"\n * - \"specs: 023-something\"\n * - \"depends on: 042-dependency\"\n * The pattern expects at least 3 digits followed by optional hyphens and word characters.\n */\nconst SPEC_REFERENCE_REGEX = /(?:spec[s]?[:\\s]+|depends on[:\\s]+)([0-9]{3,}[-\\w]+)/gi;\n\n/**\n * Get spec dependencies\n */\nasync function getDepsData(specPath: string): Promise<{\n spec: SpecData;\n dependencies: string[];\n dependents: string[];\n}> {\n const { spec, content } = await readSpecData(specPath);\n \n // Simple dependency parsing - looks for references to other specs\n const dependencies: string[] = [];\n let match;\n \n while ((match = SPEC_REFERENCE_REGEX.exec(content)) !== null) {\n dependencies.push(match[1]);\n }\n\n // For now, we'll skip finding dependents (would require scanning all specs)\n const dependents: string[] = [];\n\n return {\n spec,\n dependencies: [...new Set(dependencies)],\n dependents,\n };\n}\n\n/**\n * Create the MCP server\n */\nasync function createMcpServer(): Promise<McpServer> {\n const server = new McpServer({\n name: 'lean-spec',\n version: '0.1.0',\n });\n\n // ===== TOOLS =====\n\n // Tool: list\n server.registerTool(\n 'list',\n {\n title: 'List Specs',\n description: 'List all specifications with optional filtering. Use this to get an overview of the project, find specs by status/priority, or discover what specs exist. Returns basic metadata for each spec.',\n inputSchema: {\n status: z.enum(['planned', 'in-progress', 'complete', 'archived']).optional().describe('Filter by spec status. Use to find specs in a specific state.'),\n tags: z.array(z.string()).optional().describe('Filter by tags (e.g., [\"api\", \"frontend\"]). Only specs with ALL specified tags will be returned.'),\n priority: z.enum(['low', 'medium', 'high', 'critical']).optional().describe('Filter by priority level. Use to find urgent or important specs.'),\n assignee: z.string().optional().describe('Filter by assignee name. Use to find specs assigned to a specific person.'),\n includeArchived: z.boolean().optional().describe('Include archived specs in results (default: false). Set to true to see completed/archived work.'),\n },\n outputSchema: {\n specs: z.array(z.any()),\n },\n },\n async (input) => {\n try {\n const specs = await listSpecsData({\n status: input.status as SpecStatus | undefined,\n tags: input.tags,\n priority: input.priority as SpecPriority | undefined,\n assignee: input.assignee,\n includeArchived: input.includeArchived,\n });\n\n const output = { specs };\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } catch (error) {\n const errorMessage = formatErrorMessage('Error listing specs', error);\n return {\n content: [{ type: 'text', text: errorMessage }],\n isError: true,\n };\n }\n }\n );\n\n // Tool: search\n server.registerTool(\n 'search',\n {\n title: 'Search Specs',\n description: 'Full-text search across all specification content. Use this when you need to find specs by keyword, topic, or concept. Returns matching specs with relevant excerpts.',\n inputSchema: {\n query: z.string().describe('Search term or phrase to find in spec content. Searches across titles, descriptions, and body text.'),\n status: z.enum(['planned', 'in-progress', 'complete', 'archived']).optional().describe('Limit search to specs with this status.'),\n tags: z.array(z.string()).optional().describe('Limit search to specs with these tags.'),\n priority: z.enum(['low', 'medium', 'high', 'critical']).optional().describe('Limit search to specs with this priority.'),\n },\n outputSchema: {\n results: z.array(z.any()),\n },\n },\n async (input) => {\n try {\n const results = await searchSpecsData(input.query, {\n status: input.status as SpecStatus | undefined,\n tags: input.tags,\n priority: input.priority as SpecPriority | undefined,\n });\n\n const output = { results };\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } catch (error) {\n const errorMessage = formatErrorMessage('Error searching specs', error);\n return {\n content: [{ type: 'text', text: errorMessage }],\n isError: true,\n };\n }\n }\n );\n\n // Tool: view\n server.registerTool(\n 'view',\n {\n title: 'View Spec',\n description: 'Read the complete content of a specification. Use this to understand spec details, review design decisions, or check implementation status. Returns metadata and full content.',\n inputSchema: {\n specPath: z.string().describe('The spec to view. Can be: spec name (e.g., \"unified-dashboard\"), sequence number (e.g., \"045\" or \"45\"), full folder name (e.g., \"045-unified-dashboard\"), or sub-spec file (e.g., \"045/DESIGN.md\" or \"unified-dashboard/TESTING.md\").'),\n raw: z.boolean().optional().describe('Output raw markdown instead of formatted'),\n json: z.boolean().optional().describe('Output as JSON instead of formatted'),\n },\n outputSchema: {\n spec: z.any(),\n content: z.string(),\n },\n },\n async (input) => {\n try {\n const result = await readSpecData(input.specPath);\n \n // If json flag is set, return structured data\n if (input.json) {\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n structuredContent: result,\n };\n }\n \n // If raw flag is set, return raw markdown but include structured content\n if (input.raw) {\n const rawMarkdown = `---\\nstatus: ${result.spec.status}\\ncreated: ${result.spec.created}\\n${result.spec.priority ? `priority: ${result.spec.priority}\\n` : ''}${result.spec.tags ? `tags:\\n${result.spec.tags.map(t => ` - ${t}`).join('\\n')}\\n` : ''}${result.spec.assignee ? `assignee: ${result.spec.assignee}\\n` : ''}---\\n\\n${result.content}`;\n return {\n content: [{ type: 'text', text: rawMarkdown }],\n structuredContent: result,\n };\n }\n \n // Default: formatted output with structured content\n const formatted = `# ${result.spec.name}\\n\\nStatus: ${result.spec.status}\\nCreated: ${result.spec.created}\\n${result.spec.priority ? `Priority: ${result.spec.priority}\\n` : ''}${result.spec.tags ? `Tags: ${result.spec.tags.join(', ')}\\n` : ''}${result.spec.assignee ? `Assignee: ${result.spec.assignee}\\n` : ''}\\n\\n${result.content}`;\n return {\n content: [{ type: 'text', text: formatted }],\n structuredContent: result,\n };\n } catch (error) {\n const errorMessage = formatErrorMessage('Error viewing spec', error);\n return {\n content: [{ type: 'text', text: errorMessage }],\n isError: true,\n };\n }\n }\n );\n\n // Tool: create\n server.registerTool(\n 'create',\n {\n title: 'Create Spec',\n description: 'Create a new specification for a feature, design, or project. Use this when starting new work that needs documentation. The system auto-generates the sequence number.',\n inputSchema: {\n name: z.string().describe('The spec name/slug only (e.g., \"unified-dashboard\"). Do NOT include sequence numbers like \"045-\". The system automatically prepends the next sequence number.'),\n title: z.string().optional().describe('Human-readable title for the spec. If omitted, the name is used as the title.'),\n description: z.string().optional().describe('Initial description text to add to the Overview section.'),\n tags: z.array(z.string()).optional().describe('Tags to categorize the spec (e.g., [\"api\", \"frontend\", \"v2.0\"]).'),\n priority: z.enum(['low', 'medium', 'high', 'critical']).optional().describe('Priority level for the spec. Defaults to \"medium\" if not specified.'),\n assignee: z.string().optional().describe('Person responsible for this spec.'),\n template: z.string().optional().describe('Template name to use (e.g., \"minimal\", \"enterprise\"). Uses default template if omitted.'),\n },\n outputSchema: {\n success: z.boolean(),\n path: z.string(),\n message: z.string(),\n },\n },\n async (input) => {\n const originalLog = console.log;\n try {\n // Capture output\n let capturedOutput = '';\n console.log = (...args: any[]) => {\n capturedOutput += args.join(' ') + '\\n';\n };\n\n await createSpec(input.name, {\n title: input.title,\n description: input.description,\n tags: input.tags,\n priority: input.priority as SpecPriority | undefined,\n assignee: input.assignee,\n template: input.template,\n });\n\n const output = {\n success: true,\n path: capturedOutput.includes('Created:') ? capturedOutput.split('Created:')[1].split('\\n')[0].trim() : '',\n message: `Spec '${input.name}' created successfully`,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } catch (error) {\n const output = {\n success: false,\n path: '',\n message: formatErrorMessage('Error creating spec', error),\n };\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } finally {\n console.log = originalLog;\n }\n }\n );\n\n // Tool: update\n server.registerTool(\n 'update',\n {\n title: 'Update Spec',\n description: 'Update specification metadata (status, priority, tags, assignee). Use this to track progress, change priorities, or reassign work. Does NOT modify the spec content itself.',\n inputSchema: {\n specPath: z.string().describe('The spec to update. Can be: spec name (e.g., \"unified-dashboard\"), sequence number (e.g., \"045\" or \"45\"), or full folder name (e.g., \"045-unified-dashboard\").'),\n status: z.enum(['planned', 'in-progress', 'complete', 'archived']).optional().describe('Update the spec status. Use \"in-progress\" when work starts, \"complete\" when done.'),\n priority: z.enum(['low', 'medium', 'high', 'critical']).optional().describe('Update the priority level.'),\n tags: z.array(z.string()).optional().describe('Replace tags entirely with this new array. To add/remove individual tags, read first then update.'),\n assignee: z.string().optional().describe('Update who is responsible for this spec.'),\n },\n outputSchema: {\n success: z.boolean(),\n message: z.string(),\n },\n },\n async (input) => {\n const originalLog = console.log;\n try {\n // Capture output\n let capturedOutput = '';\n console.log = (...args: any[]) => {\n capturedOutput += args.join(' ') + '\\n';\n };\n\n // Filter out undefined values to prevent YAML serialization errors\n const updates: Record<string, unknown> = {};\n if (input.status !== undefined) updates.status = input.status as SpecStatus;\n if (input.priority !== undefined) updates.priority = input.priority as SpecPriority;\n if (input.tags !== undefined) updates.tags = input.tags;\n if (input.assignee !== undefined) updates.assignee = input.assignee;\n\n await updateSpec(input.specPath, updates);\n\n const output = {\n success: true,\n message: `Spec updated successfully`,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } catch (error) {\n const output = {\n success: false,\n message: formatErrorMessage('Error updating spec', error),\n };\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } finally {\n console.log = originalLog;\n }\n }\n );\n\n // Tool: stats\n server.registerTool(\n 'stats',\n {\n title: 'Get Statistics',\n description: 'Get project statistics and metrics. Use this to understand project completion, workload distribution, or get a high-level overview. Returns counts by status, priority, tags, and recent activity.',\n inputSchema: {},\n outputSchema: {\n stats: z.any(),\n },\n },\n async () => {\n try {\n const stats = await getStatsData();\n const output = { stats };\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } catch (error) {\n const errorMessage = formatErrorMessage('Error getting stats', error);\n return {\n content: [{ type: 'text', text: errorMessage }],\n isError: true,\n };\n }\n }\n );\n\n // Tool: board\n server.registerTool(\n 'board',\n {\n title: 'Get Kanban Board',\n description: 'Get Kanban board view of all specs organized by status. Use this to visualize workflow, see what\\'s in progress, or identify bottlenecks. Returns specs grouped into planned/in-progress/complete/archived columns.',\n inputSchema: {},\n outputSchema: {\n board: z.any(),\n },\n },\n async () => {\n try {\n const board = await getBoardData();\n const output = { board };\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } catch (error) {\n const errorMessage = formatErrorMessage('Error getting board', error);\n return {\n content: [{ type: 'text', text: errorMessage }],\n isError: true,\n };\n }\n }\n );\n\n // Tool: deps\n server.registerTool(\n 'deps',\n {\n title: 'Get Dependencies',\n description: 'Analyze spec dependencies and relationships. Use this to understand which specs depend on or are referenced by a given spec. Helps identify impact of changes and work order.',\n inputSchema: {\n specPath: z.string().describe('The spec to analyze. Can be: spec name (e.g., \"unified-dashboard\"), sequence number (e.g., \"045\" or \"45\"), or full folder name (e.g., \"045-unified-dashboard\").'),\n },\n outputSchema: {\n dependencies: z.any(),\n },\n },\n async (input) => {\n try {\n const deps = await getDepsData(input.specPath);\n const output = { dependencies: deps };\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } catch (error) {\n const errorMessage = formatErrorMessage('Error getting dependencies', error);\n return {\n content: [{ type: 'text', text: errorMessage }],\n isError: true,\n };\n }\n }\n );\n\n // Tool: archive\n server.registerTool(\n 'archive',\n {\n title: 'Archive Spec',\n description: 'Move a specification to the archived/ directory. Use this when a spec is complete or no longer active. The spec will be moved but not deleted.',\n inputSchema: {\n specPath: z.string().describe('The spec to archive. Can be: spec name (e.g., \"unified-dashboard\"), sequence number (e.g., \"045\" or \"45\"), or full folder name (e.g., \"045-unified-dashboard\").'),\n },\n outputSchema: {\n success: z.boolean(),\n message: z.string(),\n },\n },\n async (input) => {\n const originalLog = console.log;\n try {\n let capturedOutput = '';\n console.log = (...args: any[]) => {\n capturedOutput += args.join(' ') + '\\n';\n };\n\n await archiveSpec(input.specPath);\n\n const output = {\n success: true,\n message: `Spec archived successfully`,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } catch (error) {\n const output = {\n success: false,\n message: formatErrorMessage('Error archiving spec', error),\n };\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } finally {\n console.log = originalLog;\n }\n }\n );\n\n // Tool: files\n server.registerTool(\n 'files',\n {\n title: 'List Spec Files',\n description: 'List all files in a specification directory. Use this to explore sub-specs, assets, or supplementary documentation in complex specs.',\n inputSchema: {\n specPath: z.string().describe('The spec to list files for. Can be: spec name (e.g., \"unified-dashboard\"), sequence number (e.g., \"045\" or \"45\"), or full folder name (e.g., \"045-unified-dashboard\").'),\n type: z.enum(['docs', 'assets']).optional().describe('Filter by file type: \"docs\" for markdown files, \"assets\" for images/diagrams.'),\n },\n outputSchema: {\n files: z.array(z.any()),\n },\n },\n async (input) => {\n const originalLog = console.log;\n const originalError = console.error;\n try {\n let capturedOutput = '';\n console.log = (...args: any[]) => {\n capturedOutput += args.join(' ') + '\\n';\n };\n console.error = (...args: any[]) => {\n capturedOutput += args.join(' ') + '\\n';\n };\n\n await filesCommand(input.specPath, {\n type: input.type as 'docs' | 'assets' | undefined,\n tree: false,\n });\n\n // Parse the captured output to extract file list\n const lines = capturedOutput.split('\\n').filter(l => l.trim());\n const files = lines\n .filter(l => l.includes('├──') || l.includes('└──') || l.match(/^\\s*[-•]/))\n .map(l => l.replace(/[├└│─•-]\\s*/g, '').trim());\n\n const output = { files };\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } catch (error) {\n const errorMessage = formatErrorMessage('Error listing files', error);\n return {\n content: [{ type: 'text', text: errorMessage }],\n isError: true,\n };\n } finally {\n console.log = originalLog;\n console.error = originalError;\n }\n }\n );\n\n // Tool: check\n server.registerTool(\n 'check',\n {\n title: 'Check Sequence Conflicts',\n description: 'Check for sequence number conflicts in the specs directory. Use this to detect duplicate sequence numbers or naming issues. Returns list of conflicts if any.',\n inputSchema: {},\n outputSchema: {\n hasConflicts: z.boolean(),\n conflicts: z.array(z.any()).optional(),\n message: z.string(),\n },\n },\n async () => {\n const originalLog = console.log;\n const originalError = console.error;\n try {\n let capturedOutput = '';\n console.log = (...args: any[]) => {\n capturedOutput += args.join(' ') + '\\n';\n };\n console.error = (...args: any[]) => {\n capturedOutput += args.join(' ') + '\\n';\n };\n\n const hasNoConflicts = await checkSpecs({ quiet: false });\n\n const output = {\n hasConflicts: !hasNoConflicts,\n message: hasNoConflicts ? 'No sequence conflicts found' : 'Sequence conflicts detected',\n conflicts: !hasNoConflicts ? capturedOutput.split('\\n').filter(l => l.trim()) : undefined,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } catch (error) {\n const errorMessage = formatErrorMessage('Error checking specs', error);\n return {\n content: [{ type: 'text', text: errorMessage }],\n isError: true,\n };\n } finally {\n console.log = originalLog;\n console.error = originalError;\n }\n }\n );\n\n // Tool: validate\n server.registerTool(\n 'validate',\n {\n title: 'Validate Specs',\n description: 'Validate specifications for quality issues like excessive length, missing sections, or complexity problems. Use this before committing changes or for project health checks.',\n inputSchema: {\n specs: z.array(z.string()).optional().describe('Specific specs to validate. If omitted, validates all specs in the project.'),\n maxLines: z.number().optional().describe('Custom line limit for complexity checks (default: 400 lines).'),\n },\n outputSchema: {\n passed: z.boolean(),\n issues: z.array(z.any()).optional(),\n message: z.string(),\n },\n },\n async (input) => {\n const originalLog = console.log;\n const originalError = console.error;\n try {\n let capturedOutput = '';\n console.log = (...args: any[]) => {\n capturedOutput += args.join(' ') + '\\n';\n };\n console.error = (...args: any[]) => {\n capturedOutput += args.join(' ') + '\\n';\n };\n\n const passed = await validateCommand({\n maxLines: input.maxLines,\n specs: input.specs,\n });\n\n const output = {\n passed,\n message: passed ? 'All specs passed validation' : 'Some specs have validation issues',\n issues: !passed ? capturedOutput.split('\\n').filter(l => l.trim()) : undefined,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } catch (error) {\n const errorMessage = formatErrorMessage('Error validating specs', error);\n return {\n content: [{ type: 'text', text: errorMessage }],\n isError: true,\n };\n } finally {\n console.log = originalLog;\n console.error = originalError;\n }\n }\n );\n\n // Tool: backfill\n server.registerTool(\n 'backfill',\n {\n title: 'Backfill Timestamps',\n description: 'Backfill missing timestamps and metadata from git history. Use this to populate created/completed dates, assignees, or status transitions for specs that lack this data.',\n inputSchema: {\n specs: z.array(z.string()).optional().describe('Specific specs to backfill. If omitted, processes all specs.'),\n dryRun: z.boolean().optional().describe('Preview changes without applying them (default: false).'),\n force: z.boolean().optional().describe('Overwrite existing timestamp values (default: false).'),\n includeAssignee: z.boolean().optional().describe('Backfill assignee from first commit author (default: false).'),\n includeTransitions: z.boolean().optional().describe('Include full status transition history (default: false).'),\n },\n outputSchema: {\n success: z.boolean(),\n updated: z.array(z.string()).optional(),\n message: z.string(),\n },\n },\n async (input) => {\n const originalLog = console.log;\n const originalError = console.error;\n try {\n let capturedOutput = '';\n console.log = (...args: any[]) => {\n capturedOutput += args.join(' ') + '\\n';\n };\n console.error = (...args: any[]) => {\n capturedOutput += args.join(' ') + '\\n';\n };\n\n await backfillTimestamps({\n specs: input.specs,\n dryRun: input.dryRun,\n force: input.force,\n includeAssignee: input.includeAssignee,\n includeTransitions: input.includeTransitions,\n });\n\n // Parse output to extract updated specs\n const updated = capturedOutput\n .split('\\n')\n .filter(l => l.includes('Updated:') || l.includes('✓'))\n .map(l => l.replace(/.*Updated:\\s*/, '').replace(/✓\\s*/, '').trim())\n .filter(Boolean);\n\n const output = {\n success: true,\n updated: updated.length > 0 ? updated : undefined,\n message: input.dryRun \n ? `Dry run complete. ${updated.length} specs would be updated`\n : `Backfill complete. ${updated.length} specs updated`,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n structuredContent: output,\n };\n } catch (error) {\n const errorMessage = formatErrorMessage('Error backfilling timestamps', error);\n return {\n content: [{ type: 'text', text: errorMessage }],\n isError: true,\n };\n } finally {\n console.log = originalLog;\n console.error = originalError;\n }\n }\n );\n\n // ===== RESOURCES =====\n\n // Resource: spec://<spec-name>\n server.registerResource(\n 'spec',\n new ResourceTemplate('spec://{specPath}', { list: undefined }),\n {\n title: 'Spec Content',\n description: 'Read individual specification content by path or name',\n },\n async (uri, { specPath }) => {\n try {\n const pathString = Array.isArray(specPath) ? specPath[0] : specPath;\n const { spec, content } = await readSpecData(pathString);\n return {\n contents: [\n {\n uri: uri.href,\n text: `# ${spec.name}\\n\\nStatus: ${spec.status}\\nCreated: ${spec.created}\\n${spec.priority ? `Priority: ${spec.priority}\\n` : ''}${spec.tags ? `Tags: ${spec.tags.join(', ')}\\n` : ''}\\n\\n${content}`,\n mimeType: 'text/markdown',\n },\n ],\n };\n } catch (error) {\n throw new Error(formatErrorMessage('Failed to read spec resource', error));\n }\n }\n );\n\n // Resource: board://kanban\n server.registerResource(\n 'board',\n new ResourceTemplate('board://kanban', { list: undefined }),\n {\n title: 'Kanban Board',\n description: 'Current Kanban board state organized by status',\n },\n async (uri) => {\n try {\n const board = await getBoardData();\n const text = Object.entries(board.columns)\n .map(([status, specs]) => {\n const header = `## ${status.toUpperCase()} (${specs.length})`;\n const items = specs.map(s => `- ${s.name} ${s.priority ? `[${s.priority}]` : ''}`).join('\\n');\n return `${header}\\n${items || '(empty)'}`;\n })\n .join('\\n\\n');\n\n return {\n contents: [\n {\n uri: uri.href,\n text,\n mimeType: 'text/markdown',\n },\n ],\n };\n } catch (error) {\n throw new Error(formatErrorMessage('Failed to get board resource', error));\n }\n }\n );\n\n // Resource: stats://overview\n server.registerResource(\n 'stats',\n new ResourceTemplate('stats://overview', { list: undefined }),\n {\n title: 'Project Statistics',\n description: 'Overview of project statistics',\n },\n async (uri) => {\n try {\n const stats = await getStatsData();\n \n const statusSection = Object.entries(stats.byStatus)\n .map(([status, count]) => `- ${status}: ${count}`)\n .join('\\n');\n \n const prioritySection = Object.entries(stats.byPriority)\n .filter(([_, count]) => count > 0)\n .map(([priority, count]) => `- ${priority}: ${count}`)\n .join('\\n');\n \n const tagSection = Object.entries(stats.byTag)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 10)\n .map(([tag, count]) => `- ${tag}: ${count}`)\n .join('\\n');\n\n const text = `# Project Statistics\n\n## Total Specs: ${stats.total}\n\n## By Status\n${statusSection}\n\n## By Priority\n${prioritySection || '(none)'}\n\n## Top Tags\n${tagSection || '(none)'}\n\n## Recently Updated\n${stats.recentlyUpdated.map(s => `- ${s.name} (${s.status})`).join('\\n') || '(none)'}`;\n\n return {\n contents: [\n {\n uri: uri.href,\n text,\n mimeType: 'text/markdown',\n },\n ],\n };\n } catch (error) {\n throw new Error(formatErrorMessage('Failed to get stats resource', error));\n }\n }\n );\n\n // ===== PROMPTS =====\n\n // Prompt: Create feature spec\n server.registerPrompt(\n 'create-feature-spec',\n {\n title: 'Create Feature Spec',\n description: 'Guided workflow to create a new feature specification',\n argsSchema: {\n featureName: z.string(),\n description: z.string().optional(),\n },\n },\n ({ featureName, description }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Create a new feature specification for: ${featureName}${description ? `\\n\\nDescription: ${description}` : ''}\\n\\nPlease create this spec with appropriate metadata (status, priority, tags) and include standard sections like Overview, Design, Plan, and Test.`,\n },\n },\n ],\n })\n );\n\n // Prompt: Update spec status\n server.registerPrompt(\n 'update-spec-status',\n {\n title: 'Update Spec Status',\n description: 'Quick workflow to update specification status',\n argsSchema: {\n specPath: z.string(),\n newStatus: z.enum(['planned', 'in-progress', 'complete', 'archived']),\n },\n },\n ({ specPath, newStatus }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Update the status of spec \"${specPath}\" to \"${newStatus}\". Use the update tool to make this change.`,\n },\n },\n ],\n })\n );\n\n // Prompt: Find related specs\n server.registerPrompt(\n 'find-related-specs',\n {\n title: 'Find Related Specs',\n description: 'Discover specifications related to a topic or feature',\n argsSchema: {\n topic: z.string(),\n },\n },\n ({ topic }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Find all specifications related to: ${topic}\\n\\nPlease search for this topic and show me the dependencies between related specs.`,\n },\n },\n ],\n })\n );\n\n return server;\n}\n\n/**\n * Main entry point\n */\nasync function main() {\n try {\n const server = await createMcpServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n \n // Log to stderr so it doesn't interfere with MCP protocol on stdout\n console.error('LeanSpec MCP Server started successfully');\n } catch (error) {\n console.error('Failed to start LeanSpec MCP Server:', error);\n process.exit(1);\n }\n}\n\nexport { createMcpServer };\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { loadConfig } from './config.js';\nimport { parseFrontmatter, getSpecFile, matchesFilter, type SpecFrontmatter, type SpecFilterOptions } from './frontmatter.js';\n\nexport interface SpecInfo {\n path: string; // Relative path like \"20251101/003-pm-visualization-tools\"\n fullPath: string; // Absolute path to spec directory\n filePath: string; // Absolute path to spec file (README.md)\n name: string; // Just the spec name like \"003-pm-visualization-tools\"\n date: string; // Date folder like \"20251101\"\n frontmatter: SpecFrontmatter;\n content?: string; // Full file content (optional, for search)\n subFiles?: SubFileInfo[]; // Sub-documents and assets\n}\n\nexport interface SubFileInfo {\n name: string; // e.g., \"TESTING.md\" or \"diagram.png\"\n path: string; // Absolute path to the file\n size: number; // File size in bytes\n type: 'document' | 'asset'; // Classification based on file type\n content?: string; // Optional content for documents\n}\n\n// Load sub-files for a spec (all files except README.md)\nexport async function loadSubFiles(\n specDir: string,\n options: { includeContent?: boolean } = {}\n): Promise<SubFileInfo[]> {\n const subFiles: SubFileInfo[] = [];\n\n try {\n const entries = await fs.readdir(specDir, { withFileTypes: true });\n\n for (const entry of entries) {\n // Skip README.md (main spec file)\n if (entry.name === 'README.md') continue;\n\n // Skip directories for now (could be assets folder)\n if (entry.isDirectory()) continue;\n\n const filePath = path.join(specDir, entry.name);\n const stat = await fs.stat(filePath);\n\n // Determine type based on extension\n const ext = path.extname(entry.name).toLowerCase();\n const isDocument = ext === '.md';\n\n const subFile: SubFileInfo = {\n name: entry.name,\n path: filePath,\n size: stat.size,\n type: isDocument ? 'document' : 'asset',\n };\n\n // Load content for documents if requested\n if (isDocument && options.includeContent) {\n subFile.content = await fs.readFile(filePath, 'utf-8');\n }\n\n subFiles.push(subFile);\n }\n } catch (error) {\n // Directory doesn't exist or can't be read - return empty array\n // This is expected for specs without sub-files\n return [];\n }\n\n // Sort: documents first, then alphabetically\n return subFiles.sort((a, b) => {\n if (a.type !== b.type) {\n return a.type === 'document' ? -1 : 1;\n }\n return a.name.localeCompare(b.name);\n });\n}\n\n// Load all specs from the specs directory\nexport async function loadAllSpecs(options: {\n includeArchived?: boolean;\n includeContent?: boolean;\n includeSubFiles?: boolean;\n filter?: SpecFilterOptions;\n sortBy?: string;\n sortOrder?: 'asc' | 'desc';\n} = {}): Promise<SpecInfo[]> {\n const config = await loadConfig();\n const cwd = process.cwd();\n const specsDir = path.join(cwd, config.specsDir);\n\n const specs: SpecInfo[] = [];\n\n // Check if specs directory exists\n try {\n await fs.access(specsDir);\n } catch {\n return [];\n }\n\n // Pattern to match spec directories (2 or more digits followed by dash)\n const specPattern = /^(\\d{2,})-/;\n\n // Recursively load all specs from the directory structure\n async function loadSpecsFromDir(dir: string, relativePath: string = ''): Promise<void> {\n try {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n \n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n \n // Skip archived directory in main scan (handle separately)\n if (entry.name === 'archived' && relativePath === '') continue;\n \n const entryPath = path.join(dir, entry.name);\n const entryRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;\n \n // Check if this is a spec directory (NNN-name format)\n if (specPattern.test(entry.name)) {\n const specFile = await getSpecFile(entryPath, config.structure.defaultFile);\n \n if (specFile) {\n const frontmatter = await parseFrontmatter(specFile, config);\n \n if (frontmatter) {\n // Apply filter if provided\n if (options.filter && !matchesFilter(frontmatter, options.filter)) {\n continue;\n }\n \n // Extract date from path or frontmatter\n const dateMatch = entryRelativePath.match(/(\\d{8})/);\n let date: string;\n \n if (dateMatch) {\n date = dateMatch[1];\n } else if (typeof frontmatter.created === 'string') {\n date = frontmatter.created;\n } else if (frontmatter.created) {\n date = String(frontmatter.created);\n } else {\n date = '';\n }\n \n const specInfo: SpecInfo = {\n path: entryRelativePath,\n fullPath: entryPath,\n filePath: specFile,\n name: entry.name,\n date: date,\n frontmatter,\n };\n \n // Load content if requested\n if (options.includeContent) {\n specInfo.content = await fs.readFile(specFile, 'utf-8');\n }\n \n // Load sub-files if requested\n if (options.includeSubFiles) {\n specInfo.subFiles = await loadSubFiles(entryPath, {\n includeContent: options.includeContent,\n });\n }\n \n specs.push(specInfo);\n }\n }\n } else {\n // Not a spec directory, scan recursively for nested structure\n await loadSpecsFromDir(entryPath, entryRelativePath);\n }\n }\n } catch {\n // Directory doesn't exist or can't be read\n }\n }\n \n // Load active specs\n await loadSpecsFromDir(specsDir);\n\n // Load archived specs if requested\n if (options.includeArchived) {\n const archivedPath = path.join(specsDir, 'archived');\n await loadSpecsFromDir(archivedPath, 'archived');\n }\n\n // Sort specs based on options (default: id desc)\n const sortBy = options.sortBy || 'id';\n const sortOrder = options.sortOrder || 'desc';\n \n specs.sort((a, b) => {\n let comparison = 0;\n \n switch (sortBy) {\n case 'id':\n case 'number': { // Keep 'number' for backwards compatibility\n // Extract leading digits from spec name\n const aNum = parseInt(a.name.match(/^(\\d+)/)?.[1] || '0', 10);\n const bNum = parseInt(b.name.match(/^(\\d+)/)?.[1] || '0', 10);\n comparison = aNum - bNum;\n break;\n }\n case 'created': {\n // Sort by created date from frontmatter\n const aDate = String(a.frontmatter.created || '');\n const bDate = String(b.frontmatter.created || '');\n comparison = aDate.localeCompare(bDate);\n break;\n }\n case 'name': {\n comparison = a.name.localeCompare(b.name);\n break;\n }\n case 'status': {\n comparison = a.frontmatter.status.localeCompare(b.frontmatter.status);\n break;\n }\n case 'priority': {\n // Priority order: critical > high > medium > low > (none)\n const priorityOrder = { critical: 4, high: 3, medium: 2, low: 1 };\n const aPriority = a.frontmatter.priority ? priorityOrder[a.frontmatter.priority] : 0;\n const bPriority = b.frontmatter.priority ? priorityOrder[b.frontmatter.priority] : 0;\n comparison = aPriority - bPriority;\n break;\n }\n default:\n // Default to created date\n const aDate = String(a.frontmatter.created || '');\n const bDate = String(b.frontmatter.created || '');\n comparison = aDate.localeCompare(bDate);\n }\n \n // Apply sort order\n return sortOrder === 'desc' ? -comparison : comparison;\n });\n\n return specs;\n}\n\n// Get a specific spec by path\nexport async function getSpec(specPath: string): Promise<SpecInfo | null> {\n const config = await loadConfig();\n const cwd = process.cwd();\n const specsDir = path.join(cwd, config.specsDir);\n\n // Resolve the full path\n let fullPath: string;\n if (path.isAbsolute(specPath)) {\n fullPath = specPath;\n } else {\n fullPath = path.join(specsDir, specPath);\n }\n\n // Check if directory exists\n try {\n await fs.access(fullPath);\n } catch {\n return null;\n }\n\n const specFile = await getSpecFile(fullPath, config.structure.defaultFile);\n if (!specFile) return null;\n\n const frontmatter = await parseFrontmatter(specFile, config);\n if (!frontmatter) return null;\n\n const content = await fs.readFile(specFile, 'utf-8');\n\n // Parse path components\n const relativePath = path.relative(specsDir, fullPath);\n const parts = relativePath.split(path.sep);\n const date = parts[0] === 'archived' ? parts[1] : parts[0];\n const name = parts[parts.length - 1];\n\n return {\n path: relativePath,\n fullPath,\n filePath: specFile,\n name,\n date,\n frontmatter,\n content,\n };\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nexport interface LeanSpecConfig {\n template: string;\n templates?: Record<string, string>; // Maps template name to filename\n specsDir: string;\n autoCheck?: boolean; // Enable/disable auto-check for sequence conflicts (default: true)\n structure: {\n pattern: 'flat' | 'custom' | string; // 'flat' or 'custom', or legacy pattern string\n dateFormat: string;\n sequenceDigits: number;\n defaultFile: string;\n prefix?: string; // For flat pattern: \"{YYYYMMDD}-\" or \"spec-\" (optional, default: empty for global numbering)\n groupExtractor?: string; // For custom pattern: \"{YYYYMMDD}\" or \"milestone-{milestone}\"\n groupFallback?: string; // Fallback folder if field missing (only for non-date extractors)\n };\n features?: {\n aiAgents?: boolean;\n examples?: boolean;\n collaboration?: boolean;\n compliance?: boolean;\n approvals?: boolean;\n apiDocs?: boolean;\n };\n frontmatter?: {\n required?: string[];\n optional?: string[];\n custom?: Record<string, 'string' | 'number' | 'boolean' | 'array'>;\n };\n variables?: Record<string, string>;\n}\n\nconst DEFAULT_CONFIG: LeanSpecConfig = {\n template: 'spec-template.md',\n templates: {\n default: 'spec-template.md',\n },\n specsDir: 'specs',\n structure: {\n pattern: 'flat', // Default to flat for new projects\n prefix: '', // No prefix by default - global sequence numbers only\n dateFormat: 'YYYYMMDD',\n sequenceDigits: 3,\n defaultFile: 'README.md',\n },\n features: {\n aiAgents: true,\n examples: true,\n },\n};\n\nexport async function loadConfig(cwd: string = process.cwd()): Promise<LeanSpecConfig> {\n const configPath = path.join(cwd, '.lean-spec', 'config.json');\n\n try {\n const content = await fs.readFile(configPath, 'utf-8');\n const userConfig = JSON.parse(content);\n const merged = { ...DEFAULT_CONFIG, ...userConfig };\n \n // Normalize legacy pattern format\n normalizeLegacyPattern(merged);\n \n return merged;\n } catch {\n // No config file, use defaults\n return DEFAULT_CONFIG;\n }\n}\n\nexport async function saveConfig(\n config: LeanSpecConfig,\n cwd: string = process.cwd(),\n): Promise<void> {\n const configDir = path.join(cwd, '.lean-spec');\n const configPath = path.join(configDir, 'config.json');\n\n await fs.mkdir(configDir, { recursive: true });\n await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');\n}\n\nexport function getToday(format: string = 'YYYYMMDD'): string {\n const now = new Date();\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n\n switch (format) {\n case 'YYYYMMDD':\n return `${year}${month}${day}`;\n case 'YYYY-MM-DD':\n return `${year}-${month}-${day}`;\n case 'YYYY-MM':\n return `${year}-${month}`;\n case 'YYYY/MM':\n return `${year}/${month}`;\n case 'YYYY':\n return String(year);\n case 'MM':\n return month;\n case 'DD':\n return day;\n default:\n return `${year}${month}${day}`;\n }\n}\n\n/**\n * Detect if a config uses legacy pattern format and convert it\n */\nexport function normalizeLegacyPattern(config: LeanSpecConfig): void {\n const pattern = config.structure.pattern;\n \n // If pattern contains {date}/{seq}-{name}/, convert to custom with date grouping\n if (pattern && pattern.includes('{date}') && pattern.includes('{seq}') && pattern.includes('{name}')) {\n config.structure.pattern = 'custom';\n config.structure.groupExtractor = `{${config.structure.dateFormat}}`;\n }\n}\n\n/**\n * Resolve prefix string for flat pattern (e.g., \"{YYYYMMDD}-\" becomes \"20251103-\")\n */\nexport function resolvePrefix(\n prefix: string,\n dateFormat: string = 'YYYYMMDD'\n): string {\n const dateReplacements: Record<string, () => string> = {\n '{YYYYMMDD}': () => getToday('YYYYMMDD'),\n '{YYYY-MM-DD}': () => getToday('YYYY-MM-DD'),\n '{YYYY-MM}': () => getToday('YYYY-MM'),\n '{YYYY}': () => getToday('YYYY'),\n '{MM}': () => getToday('MM'),\n '{DD}': () => getToday('DD'),\n };\n\n let result = prefix;\n for (const [pattern, fn] of Object.entries(dateReplacements)) {\n result = result.replace(pattern, fn());\n }\n\n return result;\n}\n\n/**\n * Extract group folder from extractor pattern\n */\nexport function extractGroup(\n extractor: string,\n dateFormat: string = 'YYYYMMDD',\n fields?: Record<string, unknown>,\n fallback?: string\n): string {\n const dateReplacements: Record<string, () => string> = {\n '{YYYYMMDD}': () => getToday('YYYYMMDD'),\n '{YYYY-MM-DD}': () => getToday('YYYY-MM-DD'),\n '{YYYY-MM}': () => getToday('YYYY-MM'),\n '{YYYY}': () => getToday('YYYY'),\n '{MM}': () => getToday('MM'),\n '{DD}': () => getToday('DD'),\n };\n\n let result = extractor;\n\n // Replace date functions first\n for (const [pattern, fn] of Object.entries(dateReplacements)) {\n result = result.replace(pattern, fn());\n }\n\n // Replace frontmatter fields: {fieldname}\n const fieldMatches = result.match(/\\{([^}]+)\\}/g);\n if (fieldMatches) {\n for (const match of fieldMatches) {\n const fieldName = match.slice(1, -1); // Remove { }\n const fieldValue = fields?.[fieldName];\n\n if (fieldValue === undefined) {\n if (!fallback) {\n throw new Error(`Custom field '${fieldName}' required but not provided. Set structure.groupFallback in config or provide --field ${fieldName}=<value>`);\n }\n return fallback;\n }\n\n result = result.replace(match, String(fieldValue));\n }\n }\n\n return result;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport chalk from 'chalk';\nimport matter from 'gray-matter';\nimport yaml from 'js-yaml';\nimport { loadConfig, extractGroup, resolvePrefix } from '../config.js';\nimport { getGlobalNextSeq } from '../utils/path-helpers.js';\nimport { buildVariableContext, resolveVariables } from '../utils/variable-resolver.js';\nimport type { SpecPriority } from '../frontmatter.js';\nimport { normalizeDateFields } from '../frontmatter.js';\nimport { autoCheckIfEnabled } from './check.js';\nimport { sanitizeUserInput } from '../utils/ui.js';\n\nexport async function createSpec(name: string, options: { \n title?: string; \n description?: string;\n tags?: string[];\n priority?: SpecPriority;\n assignee?: string;\n template?: string;\n customFields?: Record<string, unknown>;\n noPrefix?: boolean;\n} = {}): Promise<void> {\n const config = await loadConfig();\n const cwd = process.cwd();\n const specsDir = path.join(cwd, config.specsDir);\n\n // Ensure specs directory exists\n await fs.mkdir(specsDir, { recursive: true });\n\n // Get global next sequence number\n const seq = await getGlobalNextSeq(specsDir, config.structure.sequenceDigits);\n \n // Resolve the spec path based on pattern\n let specRelativePath: string;\n \n if (config.structure.pattern === 'flat') {\n // Flat pattern: optional prefix on folder name\n const prefix = options.noPrefix \n ? ''\n : config.structure.prefix \n ? resolvePrefix(config.structure.prefix, config.structure.dateFormat)\n : '';\n specRelativePath = `${prefix}${seq}-${name}`;\n } else if (config.structure.pattern === 'custom') {\n // Custom pattern: extract group from extractor string\n if (!config.structure.groupExtractor) {\n throw new Error('Custom pattern requires structure.groupExtractor in config');\n }\n \n const group = extractGroup(\n config.structure.groupExtractor,\n config.structure.dateFormat,\n options.customFields,\n config.structure.groupFallback\n );\n \n specRelativePath = `${group}/${seq}-${name}`;\n } else {\n // Unknown pattern\n throw new Error(`Unknown pattern: ${config.structure.pattern}`);\n }\n\n const specDir = path.join(specsDir, specRelativePath);\n const specFile = path.join(specDir, config.structure.defaultFile);\n\n // Check if directory exists\n try {\n await fs.access(specDir);\n // If we get here, directory exists\n throw new Error(`Spec already exists: ${sanitizeUserInput(specDir)}`);\n } catch (error: any) {\n // If error is ENOENT, directory doesn't exist - that's good, continue\n if (error.code === 'ENOENT') {\n // Directory doesn't exist, continue\n } else {\n // Some other error or the \"already exists\" error we threw\n throw error;\n }\n }\n\n // Create spec directory\n await fs.mkdir(specDir, { recursive: true });\n\n // Resolve template path from .lean-spec/templates/\n const templatesDir = path.join(cwd, '.lean-spec', 'templates');\n let templateName: string;\n \n // Determine which template to use\n if (options.template) {\n // User specified a template\n if (config.templates?.[options.template]) {\n templateName = config.templates[options.template];\n } else {\n const available = Object.keys(config.templates || {}).join(', ');\n throw new Error(`Template not found: ${options.template}. Available templates: ${available}`);\n }\n } else {\n // Use default template\n templateName = config.template || 'spec-template.md';\n }\n \n const templatePath = path.join(templatesDir, templateName);\n\n // Load spec template from .lean-spec/templates/\n let content: string;\n \n try {\n const template = await fs.readFile(templatePath, 'utf-8');\n const date = new Date().toISOString().split('T')[0];\n const title = options.title || name;\n \n // Build variable context and resolve all variables in template\n const varContext = await buildVariableContext(config, { name: title, date });\n content = resolveVariables(template, varContext);\n \n // Parse frontmatter to get the resolved values (always needed for variable resolution)\n // Even with no custom options, we need to parse frontmatter to resolve variables like\n // {status}, {priority} in the body content with their default values from the template\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 // Ensure date fields remain as strings (gray-matter auto-parses YYYY-MM-DD as Date objects)\n normalizeDateFields(parsed.data);\n \n // Update frontmatter with provided metadata and custom fields (if any)\n if (options.tags && options.tags.length > 0) {\n parsed.data.tags = options.tags;\n }\n \n if (options.priority) {\n parsed.data.priority = options.priority;\n }\n \n if (options.assignee) {\n parsed.data.assignee = options.assignee;\n }\n \n if (options.customFields) {\n for (const [key, value] of Object.entries(options.customFields)) {\n parsed.data[key] = value;\n }\n }\n \n // Resolve frontmatter variables in the body content\n // This ensures that variables like {status}, {priority}, {tags} in the body\n // are replaced with the actual frontmatter values\n const contextWithFrontmatter = {\n ...varContext,\n frontmatter: parsed.data,\n };\n parsed.content = resolveVariables(parsed.content, contextWithFrontmatter);\n \n // Enrich with timestamps (created_at, etc.)\n const { enrichWithTimestamps } = await import('../frontmatter.js');\n enrichWithTimestamps(parsed.data);\n \n // Stringify back with updated frontmatter and resolved body content\n content = matter.stringify(parsed.content, parsed.data);\n \n // Add description to Overview section if provided\n if (options.description) {\n content = content.replace(\n /## Overview\\s+<!-- What are we solving\\? Why now\\? -->/,\n `## Overview\\n\\n${options.description}`\n );\n }\n } catch (error) {\n throw new Error(`Template not found: ${templatePath}. Run: lean-spec init`);\n }\n\n await fs.writeFile(specFile, content, 'utf-8');\n\n console.log(chalk.green(`✓ Created: ${sanitizeUserInput(specDir)}/`));\n console.log(chalk.gray(` Edit: ${sanitizeUserInput(specFile)}`));\n \n // Auto-check for conflicts after creation\n await autoCheckIfEnabled();\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\n/**\n * Create a regex pattern to match spec directories with sequence numbers\n * Handles optional date prefixes like 20251103-001-name\n */\nexport function createSpecDirPattern(): RegExp {\n // Match spec directories, handling optional date prefix\n // Patterns:\n // - 001-name (simple sequence)\n // - 20251103-001-name (date prefix + sequence)\n // - spec-001-name (custom prefix + sequence)\n // We look for: optional-prefix + NNN + dash + name\n // The sequence is 2-4 digits (to avoid matching 8-digit dates as sequences)\n // Requires dash followed by letter to ensure this is a spec directory name\n return /(?:^|\\D)(\\d{2,4})-[a-z]/i;\n}\n\n/**\n * Get next global sequence number across entire specs directory\n */\nexport async function getGlobalNextSeq(specsDir: string, digits: number): Promise<string> {\n try {\n // Recursively find all spec directories with sequence numbers\n const seqNumbers: number[] = [];\n const specPattern = createSpecDirPattern();\n \n async function scanDirectory(dir: string): Promise<void> {\n try {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n \n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n \n // Check if this is a spec directory (NNN-name format)\n const match = entry.name.match(specPattern);\n if (match) {\n const seqNum = parseInt(match[1], 10);\n if (!isNaN(seqNum) && seqNum > 0) {\n seqNumbers.push(seqNum);\n }\n }\n \n // Skip archived directory to avoid confusion\n if (entry.name === 'archived') continue;\n \n // Recursively scan subdirectories (for custom pattern grouping)\n const subDir = path.join(dir, entry.name);\n await scanDirectory(subDir);\n }\n } catch {\n // Directory doesn't exist or can't be read\n }\n }\n \n await scanDirectory(specsDir);\n \n if (seqNumbers.length === 0) {\n return '1'.padStart(digits, '0');\n }\n \n const maxSeq = Math.max(...seqNumbers);\n return String(maxSeq + 1).padStart(digits, '0');\n } catch {\n return '1'.padStart(digits, '0');\n }\n}\n\n/**\n * Get next sequence number for a date directory (legacy, kept for backward compatibility)\n */\nexport async function getNextSeq(dateDir: string, digits: number): Promise<string> {\n try {\n const specPattern = createSpecDirPattern();\n const entries = await fs.readdir(dateDir, { withFileTypes: true });\n const seqNumbers = entries\n .filter((e) => e.isDirectory() && specPattern.test(e.name))\n .map((e) => {\n const match = e.name.match(specPattern);\n return match ? parseInt(match[1], 10) : NaN;\n })\n .filter((n) => !isNaN(n));\n\n if (seqNumbers.length === 0) {\n return '1'.padStart(digits, '0');\n }\n\n const maxSeq = Math.max(...seqNumbers);\n return String(maxSeq + 1).padStart(digits, '0');\n } catch {\n return '1'.padStart(digits, '0');\n }\n}\n\n/**\n * Resolve spec path in multiple ways:\n * 1. Absolute path as given\n * 2. Relative to current directory\n * 3. Relative to specs directory\n * 4. Search by spec name in all subdirectories (flat or grouped)\n * 5. Search by sequence number only\n */\nexport async function resolveSpecPath(\n specPath: string,\n cwd: string,\n specsDir: string\n): Promise<string | null> {\n // Try absolute path\n if (path.isAbsolute(specPath)) {\n try {\n await fs.access(specPath);\n return specPath;\n } catch {\n return null;\n }\n }\n\n // Try relative to cwd\n const cwdPath = path.resolve(cwd, specPath);\n try {\n await fs.access(cwdPath);\n return cwdPath;\n } catch {\n // Continue to next method\n }\n\n // Try relative to specs directory\n const specsPath = path.join(specsDir, specPath);\n try {\n await fs.access(specsPath);\n return specsPath;\n } catch {\n // Continue to next method\n }\n\n // Search by sequence number only (e.g., \"5\" or \"005\")\n const seqMatch = specPath.match(/^0*(\\d+)$/);\n if (seqMatch) {\n const seqNum = parseInt(seqMatch[1], 10);\n const result = await searchBySequence(specsDir, seqNum);\n if (result) return result;\n }\n\n // Last resort: search for spec name in all subdirectories\n const specName = specPath.replace(/^.*\\//, ''); // Get last part\n const result = await searchInAllDirectories(specsDir, specName);\n return result;\n}\n\n/**\n * Search for a spec by sequence number across all directories\n */\nasync function searchBySequence(specsDir: string, seqNum: number): Promise<string | null> {\n const specPattern = createSpecDirPattern();\n \n async function scanDirectory(dir: string): Promise<string | null> {\n try {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n \n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n \n // Check if this matches the sequence number\n const match = entry.name.match(specPattern);\n if (match) {\n const entrySeq = parseInt(match[1], 10);\n if (entrySeq === seqNum) {\n return path.join(dir, entry.name);\n }\n }\n \n // Recursively search subdirectories (including archived)\n const subDir = path.join(dir, entry.name);\n const result = await scanDirectory(subDir);\n if (result) return result;\n }\n } catch {\n // Directory doesn't exist or can't be read\n }\n \n return null;\n }\n \n return scanDirectory(specsDir);\n}\n\n/**\n * Search for a spec by name in all subdirectories\n */\nasync function searchInAllDirectories(specsDir: string, specName: string): Promise<string | null> {\n async function scanDirectory(dir: string): Promise<string | null> {\n try {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n \n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n \n // Check if this matches the spec name\n if (entry.name === specName) {\n return path.join(dir, entry.name);\n }\n \n // Recursively search subdirectories (including archived)\n const subDir = path.join(dir, entry.name);\n const result = await scanDirectory(subDir);\n if (result) return result;\n }\n } catch {\n // Directory doesn't exist or can't be read\n }\n \n return null;\n }\n \n return scanDirectory(specsDir);\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport type { LeanSpecConfig } from '../config.js';\n\nexport interface GitInfo {\n user: string;\n email: string;\n repo: string;\n}\n\nexport interface VariableContext {\n name?: string;\n date?: string;\n projectName?: string;\n gitInfo?: GitInfo;\n customVariables?: Record<string, string>;\n frontmatter?: Record<string, unknown>;\n}\n\n/**\n * Get git information from the repository\n */\nexport async function getGitInfo(): Promise<GitInfo | null> {\n try {\n const user = execSync('git config user.name', { encoding: 'utf-8' }).trim();\n const email = execSync('git config user.email', { encoding: 'utf-8' }).trim();\n \n // Get repository name from remote URL\n let repo = '';\n try {\n const remoteUrl = execSync('git config --get remote.origin.url', { encoding: 'utf-8' }).trim();\n // Extract repo name from various formats:\n // https://github.com/user/repo.git -> repo\n // git@github.com:user/repo.git -> repo\n const match = remoteUrl.match(/\\/([^/]+?)(?:\\.git)?$/);\n if (match) {\n repo = match[1];\n }\n } catch {\n // No remote configured\n repo = '';\n }\n \n return { user, email, repo };\n } catch {\n // Git not configured or not in a git repository\n return null;\n }\n}\n\n/**\n * Get project name from package.json\n */\nexport async function getProjectName(cwd: string = process.cwd()): Promise<string | null> {\n try {\n const packageJsonPath = path.join(cwd, 'package.json');\n const content = await fs.readFile(packageJsonPath, 'utf-8');\n const packageJson = JSON.parse(content);\n return packageJson.name || null;\n } catch {\n // No package.json or invalid JSON\n return null;\n }\n}\n\n/**\n * Format status for display (with emoji and label)\n */\nfunction formatStatus(status: string): string {\n const statusMap: Record<string, string> = {\n 'planned': '📅 Planned',\n 'in-progress': '⏳ In progress',\n 'complete': '✅ Complete',\n 'archived': '📦 Archived',\n };\n return statusMap[status] || status;\n}\n\n/**\n * Format priority for display (capitalize)\n */\nfunction formatPriority(priority: string): string {\n return priority.charAt(0).toUpperCase() + priority.slice(1);\n}\n\n/**\n * Format a frontmatter value for display in template body\n */\nfunction formatFrontmatterValue(key: string, value: unknown): string {\n if (value === null || value === undefined) {\n return '';\n }\n \n // Handle special formatting for status\n if (key === 'status' && typeof value === 'string') {\n return formatStatus(value);\n }\n \n // Handle special formatting for priority\n if (key === 'priority' && typeof value === 'string') {\n return formatPriority(value);\n }\n \n // Handle arrays (e.g., tags)\n if (Array.isArray(value)) {\n return value.join(', ');\n }\n \n // Handle objects - convert to JSON string\n if (typeof value === 'object') {\n return JSON.stringify(value);\n }\n \n // Convert everything else to string\n return String(value);\n}\n\n/**\n * Resolve variables in a string\n */\nexport function resolveVariables(\n template: string,\n context: VariableContext\n): string {\n let result = template;\n \n // Built-in variables\n if (context.name) {\n result = result.replace(/{name}/g, context.name);\n }\n \n if (context.date) {\n result = result.replace(/{date}/g, context.date);\n }\n \n if (context.projectName) {\n result = result.replace(/{project_name}/g, context.projectName);\n }\n \n // Git variables\n if (context.gitInfo) {\n result = result.replace(/{author}/g, context.gitInfo.user);\n result = result.replace(/{git_user}/g, context.gitInfo.user);\n result = result.replace(/{git_email}/g, context.gitInfo.email);\n result = result.replace(/{git_repo}/g, context.gitInfo.repo);\n }\n \n // Custom variables from config\n if (context.customVariables) {\n for (const [key, value] of Object.entries(context.customVariables)) {\n // Escape special regex characters in key to prevent RegExp injection\n const escapedKey = key.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const pattern = new RegExp(`\\\\{${escapedKey}\\\\}`, 'g');\n result = result.replace(pattern, value);\n }\n }\n \n // Frontmatter field variables\n if (context.frontmatter) {\n for (const [key, value] of Object.entries(context.frontmatter)) {\n const formattedValue = formatFrontmatterValue(key, value);\n // Escape special regex characters in key to prevent RegExp injection\n const escapedKey = key.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const pattern = new RegExp(`\\\\{${escapedKey}\\\\}`, 'g');\n result = result.replace(pattern, formattedValue);\n }\n }\n \n return result;\n}\n\n/**\n * Build a complete variable context\n */\nexport async function buildVariableContext(\n config: LeanSpecConfig,\n options: {\n name?: string;\n date?: string;\n } = {}\n): Promise<VariableContext> {\n const context: VariableContext = {\n name: options.name,\n date: options.date || new Date().toISOString().split('T')[0],\n customVariables: config.variables || {},\n };\n \n // Load project name\n context.projectName = (await getProjectName()) ?? undefined;\n \n // Load git info\n context.gitInfo = (await getGitInfo()) ?? undefined;\n \n return context;\n}\n","import * as path from 'node:path';\nimport chalk from 'chalk';\nimport { loadConfig } from '../config.js';\nimport { loadAllSpecs } from '../spec-loader.js';\nimport { createSpecDirPattern } from '../utils/path-helpers.js';\nimport { sanitizeUserInput } from '../utils/ui.js';\n\n/**\n * Check for sequence conflicts in specs\n */\nexport async function checkSpecs(options: {\n quiet?: boolean;\n silent?: boolean;\n} = {}): Promise<boolean> {\n const config = await loadConfig();\n const cwd = process.cwd();\n const specsDir = path.join(cwd, config.specsDir);\n \n // Find all specs with sequence numbers\n const specs = await loadAllSpecs();\n const sequenceMap = new Map<number, string[]>();\n const specPattern = createSpecDirPattern();\n \n for (const spec of specs) {\n // Extract sequence number from spec name\n const specName = path.basename(spec.path);\n // Use the same pattern as path-helpers to ensure consistency\n const match = specName.match(specPattern);\n \n if (match) {\n const seq = parseInt(match[1], 10);\n if (!isNaN(seq) && seq > 0) {\n if (!sequenceMap.has(seq)) {\n sequenceMap.set(seq, []);\n }\n sequenceMap.get(seq)!.push(spec.path);\n }\n }\n }\n \n // Find conflicts (sequences with multiple specs)\n const conflicts = Array.from(sequenceMap.entries())\n .filter(([_, paths]) => paths.length > 1)\n .sort(([a], [b]) => a - b);\n \n if (conflicts.length === 0) {\n if (!options.quiet && !options.silent) {\n console.log(chalk.green('✓ No sequence conflicts detected'));\n }\n return true;\n }\n \n // Report conflicts\n if (!options.silent) {\n if (!options.quiet) {\n // Full output\n console.log('');\n console.log(chalk.yellow('⚠️ Sequence conflicts detected:\\n'));\n \n for (const [seq, paths] of conflicts) {\n console.log(chalk.red(` Sequence ${String(seq).padStart(config.structure.sequenceDigits, '0')}:`));\n for (const p of paths) {\n console.log(chalk.gray(` - ${sanitizeUserInput(p)}`));\n }\n console.log('');\n }\n \n console.log(chalk.cyan('Tip: Use date prefix to prevent conflicts:'));\n console.log(chalk.gray(' Edit .lean-spec/config.json → structure.prefix: \"{YYYYMMDD}-\"'));\n console.log('');\n console.log(chalk.cyan('Or rename folders manually to resolve.'));\n console.log('');\n } else {\n // Brief warning (for auto-check)\n console.log('');\n console.log(chalk.yellow(`⚠️ Conflict warning: ${conflicts.length} sequence conflict(s) detected`));\n console.log(chalk.gray('Run: lean-spec check'));\n console.log('');\n }\n }\n \n return false;\n}\n\n/**\n * Helper for auto-check in other commands\n */\nexport async function autoCheckIfEnabled(): Promise<void> {\n const config = await loadConfig();\n \n // Check if auto-check is disabled\n if (config.autoCheck === false) {\n return;\n }\n \n // Run check in quiet mode (brief warning only)\n try {\n await checkSpecs({ quiet: true });\n } catch {\n // Ignore errors in auto-check\n }\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","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 * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport chalk from 'chalk';\nimport { loadConfig } from '../config.js';\nimport { resolveSpecPath } from '../utils/path-helpers.js';\nimport { autoCheckIfEnabled } from './check.js';\nimport { sanitizeUserInput } from '../utils/ui.js';\nimport { getSpecFile, updateFrontmatter } from '../frontmatter.js';\n\nexport async function archiveSpec(specPath: string): Promise<void> {\n // Auto-check for conflicts before archive\n await autoCheckIfEnabled();\n \n const config = await loadConfig();\n const cwd = process.cwd();\n const specsDir = path.join(cwd, config.specsDir);\n \n // Resolve the spec path using the helper\n const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);\n \n if (!resolvedPath) {\n throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}`);\n }\n\n // Update frontmatter to archived status before moving\n const specFile = await getSpecFile(resolvedPath, config.structure.defaultFile);\n if (specFile) {\n await updateFrontmatter(specFile, { status: 'archived' });\n }\n\n // Archive to flat structure in specs/archived/ regardless of original pattern\n const archiveDir = path.join(specsDir, 'archived');\n await fs.mkdir(archiveDir, { recursive: true });\n\n const specName = path.basename(resolvedPath);\n const archivePath = path.join(archiveDir, specName);\n\n await fs.rename(resolvedPath, archivePath);\n\n console.log(chalk.green(`✓ Archived: ${sanitizeUserInput(archivePath)}`));\n}\n","import chalk from 'chalk';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { loadConfig } from '../config.js';\nimport { withSpinner, sanitizeUserInput } from '../utils/ui.js';\nimport { loadAllSpecs } from '../spec-loader.js';\nimport type { SpecInfo } from '../spec-loader.js';\nimport type { SpecFilterOptions, SpecStatus, SpecPriority } from '../frontmatter.js';\nimport { autoCheckIfEnabled } from './check.js';\nimport { detectPatternType } from '../utils/pattern-detection.js';\nimport { PRIORITY_CONFIG, getStatusEmoji, getPriorityEmoji } from '../utils/colors.js';\n\nexport async function listSpecs(options: {\n showArchived?: boolean;\n status?: SpecStatus | SpecStatus[];\n tags?: string[];\n priority?: SpecPriority | SpecPriority[];\n assignee?: string;\n customFields?: Record<string, unknown>;\n sortBy?: string;\n sortOrder?: 'asc' | 'desc';\n} = {}): Promise<void> {\n // Auto-check for conflicts before listing\n await autoCheckIfEnabled();\n \n const config = await loadConfig();\n const cwd = process.cwd();\n const specsDir = path.join(cwd, config.specsDir);\n \n try {\n await fs.access(specsDir);\n } catch {\n console.log('');\n console.log('No specs directory found. Initialize with: lean-spec init');\n console.log('');\n return;\n }\n\n // Build filter options\n const filter: SpecFilterOptions = {};\n if (options.status) filter.status = options.status;\n if (options.tags) filter.tags = options.tags;\n if (options.priority) filter.priority = options.priority;\n if (options.assignee) filter.assignee = options.assignee;\n if (options.customFields) filter.customFields = options.customFields;\n\n const specs = await withSpinner(\n 'Loading specs...',\n () => loadAllSpecs({\n includeArchived: options.showArchived || false,\n filter,\n sortBy: options.sortBy || 'id',\n sortOrder: options.sortOrder || 'desc',\n })\n );\n\n if (specs.length === 0) {\n console.log(chalk.dim('No specs found.'));\n return;\n }\n\n // Display header\n console.log(chalk.bold.cyan('📄 Spec List'));\n \n // Filter info\n const filterParts: string[] = [];\n if (options.status) {\n const statusStr = Array.isArray(options.status) ? options.status.join(',') : options.status;\n filterParts.push(`status=${statusStr}`);\n }\n if (options.tags) filterParts.push(`tags=${options.tags.join(',')}`);\n if (options.priority) {\n const priorityStr = Array.isArray(options.priority) ? options.priority.join(',') : options.priority;\n filterParts.push(`priority=${priorityStr}`);\n }\n if (options.assignee) filterParts.push(`assignee=${options.assignee}`);\n \n if (filterParts.length > 0) {\n console.log(chalk.dim(`Filtered by: ${filterParts.join(', ')}`));\n }\n console.log('');\n\n // Detect pattern type and decide whether to group specs\n const patternInfo = detectPatternType(config);\n\n if (patternInfo.shouldGroup && patternInfo.groupExtractor) {\n renderGroupedList(specs, patternInfo.groupExtractor);\n } else {\n renderFlatList(specs);\n }\n\n console.log('');\n console.log(chalk.bold(`Total: ${chalk.green(specs.length)} spec${specs.length !== 1 ? 's' : ''}`));\n}\n\nfunction renderFlatList(specs: SpecInfo[]): void {\n // Simple flat list - no grouping\n for (const spec of specs) {\n const statusEmoji = getStatusEmoji(spec.frontmatter.status);\n const priorityEmoji = getPriorityEmoji(spec.frontmatter.priority);\n \n let assigneeStr = '';\n if (spec.frontmatter.assignee) {\n assigneeStr = ' ' + chalk.cyan(`@${sanitizeUserInput(spec.frontmatter.assignee)}`);\n }\n \n let tagsStr = '';\n if (spec.frontmatter.tags?.length) {\n const tags = Array.isArray(spec.frontmatter.tags) ? spec.frontmatter.tags : [];\n if (tags.length > 0) {\n const tagStr = tags.map(tag => `#${sanitizeUserInput(tag)}`).join(' ');\n tagsStr = ' ' + chalk.dim(chalk.magenta(tagStr));\n }\n }\n\n const priorityPrefix = priorityEmoji ? `${priorityEmoji} ` : '';\n console.log(`${priorityPrefix}${statusEmoji} ${chalk.cyan(sanitizeUserInput(spec.path))}${assigneeStr}${tagsStr}`);\n }\n}\n\nfunction renderGroupedList(specs: SpecInfo[], groupExtractor: string): void {\n // Extract group pattern (e.g., \"{YYYYMMDD}\" or \"milestone-{milestone}\")\n const isDatePattern = groupExtractor.match(/\\{YYYY/);\n\n // Group specs by their folder/group\n const groups = new Map<string, SpecInfo[]>();\n \n for (const spec of specs) {\n // Extract group from path (first part before spec name)\n const pathParts = spec.path.split('/');\n let group = 'unknown';\n \n if (pathParts.length > 1) {\n // Has a parent folder (e.g., \"20251103/001-spec\" or \"milestone-1/001-spec\")\n group = pathParts[0];\n } else if (isDatePattern && spec.date) {\n // No folder but we have date metadata\n group = spec.date;\n }\n \n if (!groups.has(group)) {\n groups.set(group, []);\n }\n groups.get(group)!.push(spec);\n }\n\n // Sort groups (dates descending, others ascending)\n const sortedGroups = Array.from(groups.keys()).sort((a, b) => {\n // If looks like dates (8 digits), sort descending (newest first)\n if (/^\\d{8}$/.test(a) && /^\\d{8}$/.test(b)) {\n return b.localeCompare(a);\n }\n // Otherwise alphabetically ascending\n return a.localeCompare(b);\n });\n\n // Render each group\n for (let i = 0; i < sortedGroups.length; i++) {\n const groupName = sortedGroups[i];\n const groupSpecs = groups.get(groupName)!;\n\n // Group header\n const groupEmoji = /^\\d{8}$/.test(groupName) ? '📅' : \n groupName.startsWith('milestone') ? '🎯' :\n '📁';\n console.log(`${chalk.bold.cyan(`${groupEmoji} ${groupName}/`)} ${chalk.dim(`(${groupSpecs.length})`)}`);\n console.log('');\n\n // Render specs in this group - simple flat list\n for (const spec of groupSpecs) {\n const statusEmoji = getStatusEmoji(spec.frontmatter.status);\n const priorityEmoji = getPriorityEmoji(spec.frontmatter.priority);\n \n // Remove group prefix from display path\n const displayPath = spec.path.includes('/') \n ? spec.path.split('/').slice(1).join('/')\n : spec.path;\n \n let assigneeStr = '';\n if (spec.frontmatter.assignee) {\n assigneeStr = ' ' + chalk.cyan(`@${sanitizeUserInput(spec.frontmatter.assignee)}`);\n }\n \n let tagsStr = '';\n if (spec.frontmatter.tags?.length) {\n const tags = Array.isArray(spec.frontmatter.tags) ? spec.frontmatter.tags : [];\n if (tags.length > 0) {\n const tagStr = tags.map(tag => `#${sanitizeUserInput(tag)}`).join(' ');\n tagsStr = ' ' + chalk.dim(chalk.magenta(tagStr));\n }\n }\n\n const priorityPrefix = priorityEmoji ? `${priorityEmoji} ` : '';\n console.log(` ${priorityPrefix}${statusEmoji} ${chalk.cyan(sanitizeUserInput(displayPath))}${assigneeStr}${tagsStr}`);\n }\n\n // Spacing between groups\n if (i < sortedGroups.length - 1) {\n console.log('');\n }\n }\n}\n","import type { LeanSpecConfig } from '../config.js';\n\n/**\n * Detect the type of folder pattern being used\n */\nexport type PatternType = 'flat' | 'date-grouped' | 'custom-grouped';\n\nexport interface PatternInfo {\n type: PatternType;\n shouldGroup: boolean;\n groupExtractor?: string;\n isDateBased?: boolean;\n}\n\n/**\n * Analyze the configured pattern and determine how specs should be displayed\n * \n * @param config - The LeanSpec configuration\n * @returns {PatternInfo} Object containing:\n * - type: Pattern type ('flat', 'date-grouped', 'custom-grouped')\n * - shouldGroup: Whether specs should be displayed in groups\n * - groupExtractor: Optional group extraction pattern\n * - isDateBased: Optional flag indicating if grouping is date-based\n */\nexport function detectPatternType(config: LeanSpecConfig): PatternInfo {\n const { pattern, groupExtractor } = config.structure;\n\n // Case 1: Explicit flat pattern\n if (pattern === 'flat') {\n return {\n type: 'flat',\n shouldGroup: false,\n };\n }\n\n // Case 2: Custom pattern with grouping\n if (pattern === 'custom' && groupExtractor) {\n // Detect if it's date-based grouping\n // Matches any date format in braces: {YYYYMMDD}, {YYYY-MM-DD}, {YYYY-MM}, {YYYY}, etc.\n const isDateBased = /\\{YYYY[^}]*\\}/.test(groupExtractor);\n \n return {\n type: isDateBased ? 'date-grouped' : 'custom-grouped',\n shouldGroup: true,\n groupExtractor,\n isDateBased,\n };\n }\n\n // Case 3: Legacy or unknown pattern - default to flat\n return {\n type: 'flat',\n shouldGroup: false,\n };\n}\n\n/**\n * Check if a pattern uses date-based grouping\n * \n * @param config - The LeanSpec configuration\n * @returns true if the pattern groups specs by date\n */\nexport function isDateGroupedPattern(config: LeanSpecConfig): boolean {\n const info = detectPatternType(config);\n return info.type === 'date-grouped';\n}\n\n/**\n * Check if specs should be grouped when listed\n * \n * @param config - The LeanSpec configuration\n * @returns true if specs should be displayed in groups\n */\nexport function shouldGroupSpecs(config: LeanSpecConfig): boolean {\n const info = detectPatternType(config);\n return info.shouldGroup;\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","import * as path from 'node:path';\nimport chalk from 'chalk';\nimport { loadConfig } from '../config.js';\nimport { getSpecFile, updateFrontmatter } from '../frontmatter.js';\nimport { resolveSpecPath } from '../utils/path-helpers.js';\nimport type { SpecStatus, SpecPriority } from '../frontmatter.js';\nimport { autoCheckIfEnabled } from './check.js';\nimport { sanitizeUserInput } from '../utils/ui.js';\n\nexport async function updateSpec(\n specPath: string,\n updates: {\n status?: SpecStatus;\n priority?: SpecPriority;\n tags?: string[];\n assignee?: string;\n customFields?: Record<string, unknown>;\n }\n): Promise<void> {\n // Auto-check for conflicts before update\n await autoCheckIfEnabled();\n \n const config = await loadConfig();\n const cwd = process.cwd();\n const specsDir = path.join(cwd, config.specsDir);\n \n const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);\n\n if (!resolvedPath) {\n throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}. Tried: ${sanitizeUserInput(specPath)}, specs/${sanitizeUserInput(specPath)}, and searching in date directories`);\n }\n\n // Get spec file\n const specFile = await getSpecFile(resolvedPath, config.structure.defaultFile);\n if (!specFile) {\n throw new Error(`No spec file found in: ${sanitizeUserInput(specPath)}`);\n }\n\n // Merge custom fields into updates object, filtering out undefined values\n const allUpdates: Record<string, unknown> = {};\n \n // Only add defined values\n if (updates.status !== undefined) allUpdates.status = updates.status;\n if (updates.priority !== undefined) allUpdates.priority = updates.priority;\n if (updates.tags !== undefined) allUpdates.tags = updates.tags;\n if (updates.assignee !== undefined) allUpdates.assignee = updates.assignee;\n \n if (updates.customFields) {\n Object.entries(updates.customFields).forEach(([key, value]) => {\n if (value !== undefined) {\n allUpdates[key] = value;\n }\n });\n }\n\n // Update frontmatter\n await updateFrontmatter(specFile, allUpdates);\n\n console.log(chalk.green(`✓ Updated: ${sanitizeUserInput(path.relative(cwd, resolvedPath))}`));\n \n // Show what was updated\n const updatedFields = Object.keys(updates).filter(k => k !== 'customFields');\n if (updates.customFields) {\n updatedFields.push(...Object.keys(updates.customFields));\n }\n console.log(chalk.gray(` Fields: ${updatedFields.join(', ')}`));\n}\n","import * as path from 'node:path';\nimport { loadAllSpecs, getSpec, type SpecInfo } from '../spec-loader.js';\nimport { updateFrontmatter, type SpecFrontmatter } from '../frontmatter.js';\nimport { loadConfig } from '../config.js';\nimport { \n isGitRepository,\n extractGitTimestamps,\n fileExistsInGit,\n type GitTimestampData,\n} from '../utils/git-timestamps.js';\nimport { resolveSpecPath } from '../utils/path-helpers.js';\n\nexport interface BackfillResult {\n specPath: string;\n specName: string;\n created_at?: string;\n updated_at?: string;\n completed_at?: string;\n assignee?: string;\n transitionsCount?: number;\n source: 'git' | 'existing' | 'skipped';\n reason?: string;\n}\n\nexport interface BackfillOptions {\n dryRun?: boolean;\n force?: boolean;\n includeAssignee?: boolean;\n includeTransitions?: boolean;\n specs?: string[]; // specific specs to target\n}\n\n/**\n * Backfill timestamps from git history for all or specific specs\n */\nexport async function backfillTimestamps(options: BackfillOptions = {}): Promise<BackfillResult[]> {\n const results: BackfillResult[] = [];\n \n // Check if we're in a git repository\n if (!isGitRepository()) {\n console.error('\\x1b[31mError:\\x1b[0m Not in a git repository');\n console.error('Git history is required for backfilling timestamps');\n process.exit(1);\n }\n \n // Load specs to process\n let specs: SpecInfo[];\n \n if (options.specs && options.specs.length > 0) {\n // Load specific specs\n specs = [];\n const config = await loadConfig();\n const cwd = process.cwd();\n const specsDir = path.join(cwd, config.specsDir);\n \n for (const specPath of options.specs) {\n const resolved = await resolveSpecPath(specPath, cwd, specsDir);\n if (!resolved) {\n console.warn(`\\x1b[33mWarning:\\x1b[0m Spec not found: ${specPath}`);\n continue;\n }\n const spec = await getSpec(resolved);\n if (spec) {\n specs.push(spec);\n }\n }\n } else {\n // Load all specs (including archived)\n specs = await loadAllSpecs({ includeArchived: true });\n }\n \n if (specs.length === 0) {\n console.log('No specs found to backfill');\n return results;\n }\n \n // Show what we're doing\n if (options.dryRun) {\n console.log('\\x1b[36m🔍 Dry run mode - no changes will be made\\x1b[0m\\n');\n }\n \n console.log(`Analyzing git history for ${specs.length} spec${specs.length === 1 ? '' : 's'}...\\n`);\n \n // Process each spec\n for (const spec of specs) {\n const result = await backfillSpecTimestamps(spec, options);\n results.push(result);\n }\n \n // Print summary\n printSummary(results, options);\n \n return results;\n}\n\n/**\n * Backfill timestamps for a single spec\n */\nasync function backfillSpecTimestamps(\n spec: SpecInfo,\n options: BackfillOptions\n): Promise<BackfillResult> {\n const result: BackfillResult = {\n specPath: spec.path,\n specName: spec.name,\n source: 'skipped',\n };\n \n // Check if file exists in git history\n if (!fileExistsInGit(spec.filePath)) {\n result.reason = 'Not in git history';\n console.log(`\\x1b[33m⊘\\x1b[0m ${spec.name} - Not in git history`);\n return result;\n }\n \n // Extract git timestamps\n const gitData = extractGitTimestamps(spec.filePath, {\n includeAssignee: options.includeAssignee,\n includeTransitions: options.includeTransitions,\n });\n \n // Determine what needs to be updated\n const updates: Partial<SpecFrontmatter> = {};\n let hasUpdates = false;\n \n // Check created_at\n if (gitData.created_at && (options.force || !spec.frontmatter.created_at)) {\n updates.created_at = gitData.created_at;\n result.created_at = gitData.created_at;\n result.source = 'git';\n hasUpdates = true;\n } else if (spec.frontmatter.created_at) {\n result.created_at = spec.frontmatter.created_at;\n result.source = 'existing';\n }\n \n // Check updated_at\n if (gitData.updated_at && (options.force || !spec.frontmatter.updated_at)) {\n updates.updated_at = gitData.updated_at;\n result.updated_at = gitData.updated_at;\n result.source = 'git';\n hasUpdates = true;\n } else if (spec.frontmatter.updated_at) {\n result.updated_at = spec.frontmatter.updated_at;\n result.source = 'existing';\n }\n \n // Check completed_at\n if (gitData.completed_at && (options.force || !spec.frontmatter.completed_at)) {\n updates.completed_at = gitData.completed_at;\n result.completed_at = gitData.completed_at;\n result.source = 'git';\n hasUpdates = true;\n } else if (spec.frontmatter.completed_at) {\n result.completed_at = spec.frontmatter.completed_at;\n result.source = 'existing';\n }\n \n // Check assignee (optional)\n if (options.includeAssignee && gitData.assignee && (options.force || !spec.frontmatter.assignee)) {\n updates.assignee = gitData.assignee;\n result.assignee = gitData.assignee;\n result.source = 'git';\n hasUpdates = true;\n } else if (spec.frontmatter.assignee) {\n result.assignee = spec.frontmatter.assignee;\n }\n \n // Check transitions (optional)\n if (options.includeTransitions && gitData.transitions && gitData.transitions.length > 0) {\n if (options.force || !spec.frontmatter.transitions || spec.frontmatter.transitions.length === 0) {\n updates.transitions = gitData.transitions;\n result.transitionsCount = gitData.transitions.length;\n result.source = 'git';\n hasUpdates = true;\n } else {\n // Merge with existing transitions (optional: could implement smart merge)\n result.transitionsCount = spec.frontmatter.transitions.length;\n }\n }\n \n // Sync updated date field with updated_at timestamp\n if (updates.updated_at && !updates.updated) {\n updates.updated = updates.updated_at.split('T')[0];\n }\n \n if (!hasUpdates) {\n result.reason = 'Already has complete data';\n console.log(`\\x1b[90m✓\\x1b[0m ${spec.name} - Already complete`);\n return result;\n }\n \n // Apply updates (unless dry run)\n if (!options.dryRun) {\n try {\n await updateFrontmatter(spec.filePath, updates);\n console.log(`\\x1b[32m✓\\x1b[0m ${spec.name} - Updated`);\n } catch (error) {\n result.source = 'skipped';\n result.reason = `Error: ${error instanceof Error ? error.message : String(error)}`;\n console.log(`\\x1b[31m✗\\x1b[0m ${spec.name} - Failed: ${result.reason}`);\n }\n } else {\n console.log(`\\x1b[36m→\\x1b[0m ${spec.name} - Would update`);\n // Show what would be updated\n if (updates.created_at) console.log(` created_at: ${updates.created_at} (git)`);\n if (updates.updated_at) console.log(` updated_at: ${updates.updated_at} (git)`);\n if (updates.completed_at) console.log(` completed_at: ${updates.completed_at} (git)`);\n if (updates.assignee) console.log(` assignee: ${updates.assignee} (git)`);\n if (updates.transitions) console.log(` transitions: ${updates.transitions.length} status changes (git)`);\n }\n \n return result;\n}\n\n/**\n * Print summary of backfill results\n */\nfunction printSummary(results: BackfillResult[], options: BackfillOptions): void {\n console.log('\\n' + '─'.repeat(60));\n console.log('\\x1b[1mSummary:\\x1b[0m\\n');\n \n const total = results.length;\n const updated = results.filter(r => r.source === 'git').length;\n const existing = results.filter(r => r.source === 'existing').length;\n const skipped = results.filter(r => r.source === 'skipped').length;\n \n const timestampUpdates = results.filter(r => \n r.source === 'git' && (r.created_at || r.updated_at || r.completed_at)\n ).length;\n \n const assigneeUpdates = results.filter(r => \n r.source === 'git' && r.assignee\n ).length;\n \n const transitionUpdates = results.filter(r => \n r.source === 'git' && r.transitionsCount\n ).length;\n \n console.log(` ${total} specs analyzed`);\n \n if (options.dryRun) {\n console.log(` ${updated} would be updated`);\n if (timestampUpdates > 0) {\n console.log(` └─ ${timestampUpdates} with timestamps`);\n }\n if (options.includeAssignee && assigneeUpdates > 0) {\n console.log(` └─ ${assigneeUpdates} with assignee`);\n }\n if (options.includeTransitions && transitionUpdates > 0) {\n console.log(` └─ ${transitionUpdates} with transitions`);\n }\n } else {\n console.log(` ${updated} updated`);\n }\n \n console.log(` ${existing} already complete`);\n console.log(` ${skipped} skipped`);\n \n // Show reasons for skipped specs\n const skipReasons = results\n .filter(r => r.source === 'skipped' && r.reason)\n .map(r => r.reason);\n \n if (skipReasons.length > 0) {\n console.log('\\n\\x1b[33mSkipped reasons:\\x1b[0m');\n const uniqueReasons = [...new Set(skipReasons)];\n for (const reason of uniqueReasons) {\n const count = skipReasons.filter(r => r === reason).length;\n console.log(` - ${reason} (${count})`);\n }\n }\n \n // Guidance\n if (options.dryRun) {\n console.log('\\n\\x1b[36mℹ\\x1b[0m Run without --dry-run to apply changes');\n \n if (!options.includeAssignee || !options.includeTransitions) {\n console.log('\\x1b[36mℹ\\x1b[0m Use --all to include optional fields (assignee, transitions)');\n }\n } else if (updated > 0) {\n console.log('\\n\\x1b[32m✓\\x1b[0m Backfill complete!');\n console.log(' Run \\x1b[36mlspec stats\\x1b[0m to see velocity metrics');\n }\n}\n","import { execSync } from 'node:child_process';\nimport * as path from 'node:path';\nimport type { SpecStatus, StatusTransition } from '../frontmatter.js';\n\nexport interface GitTimestampData {\n created_at?: string;\n updated_at?: string;\n completed_at?: string;\n assignee?: string;\n transitions?: StatusTransition[];\n}\n\n/**\n * Check if the current directory is a git repository\n */\nexport function isGitRepository(): boolean {\n try {\n execSync('git rev-parse --is-inside-work-tree', { \n stdio: 'ignore',\n encoding: 'utf-8' \n });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the timestamp of the first commit that created a file\n */\nexport function getFirstCommitTimestamp(filePath: string): string | null {\n try {\n // Use --follow to track file renames\n // Use --diff-filter=A to find the commit that added the file\n // Format as ISO 8601 timestamp\n const timestamp = execSync(\n `git log --follow --format=\"%aI\" --diff-filter=A -- \"${filePath}\" | tail -1`,\n { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }\n ).trim();\n \n return timestamp || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the timestamp of the most recent commit that modified a file\n */\nexport function getLastCommitTimestamp(filePath: string): string | null {\n try {\n const timestamp = execSync(\n `git log --format=\"%aI\" -n 1 -- \"${filePath}\"`,\n { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }\n ).trim();\n \n return timestamp || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the timestamp when a spec was marked as complete\n * Searches git history for status changes to \"complete\"\n */\nexport function getCompletionTimestamp(filePath: string): string | null {\n try {\n // Get all commits that modified the file, with patch output\n const gitLog = execSync(\n `git log --format=\"%H|%aI\" -p -- \"${filePath}\"`,\n { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }\n );\n \n // Parse commits to find status change to complete\n const commits = gitLog.split('\\ndiff --git').map(section => section.trim());\n \n for (const commit of commits) {\n if (!commit) continue;\n \n // Extract commit hash and timestamp from header\n const headerMatch = commit.match(/^([a-f0-9]{40})\\|([^\\n]+)/);\n if (!headerMatch) continue;\n \n const [, , timestamp] = headerMatch;\n \n // Look for status: complete in the diff\n // Check for both YAML frontmatter and inline status changes\n if (\n /^\\+status:\\s*['\"]?complete['\"]?/m.test(commit) ||\n /^\\+\\*\\*Status\\*\\*:.*complete/mi.test(commit)\n ) {\n return timestamp;\n }\n }\n \n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the author of the first commit (for assignee inference)\n */\nexport function getFirstCommitAuthor(filePath: string): string | null {\n try {\n const author = execSync(\n `git log --follow --format=\"%an\" --diff-filter=A -- \"${filePath}\" | tail -1`,\n { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }\n ).trim();\n \n return author || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Parse all status transitions from git history\n * Reconstructs the full status change timeline\n */\nexport function parseStatusTransitions(filePath: string): StatusTransition[] {\n const transitions: StatusTransition[] = [];\n \n try {\n // Get all commits that modified the file, with patch output\n const gitLog = execSync(\n `git log --format=\"%H|%aI\" -p --reverse -- \"${filePath}\"`,\n { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }\n );\n \n // Parse commits in chronological order (--reverse)\n const commits = gitLog.split('\\ndiff --git').map(section => section.trim());\n \n const validStatuses: SpecStatus[] = ['planned', 'in-progress', 'complete', 'archived'];\n \n for (const commit of commits) {\n if (!commit) continue;\n \n // Extract commit hash and timestamp from header\n const headerMatch = commit.match(/^([a-f0-9]{40})\\|([^\\n]+)/);\n if (!headerMatch) continue;\n \n const [, , timestamp] = headerMatch;\n \n // Look for status changes in the diff\n // Match: +status: complete or +status: 'complete'\n const statusMatch = commit.match(/^\\+status:\\s*['\"]?(\\w+(?:-\\w+)?)['\"]?/m);\n if (statusMatch) {\n const status = statusMatch[1] as SpecStatus;\n \n // Only record valid status values\n if (validStatuses.includes(status)) {\n // Avoid duplicate consecutive transitions\n const lastTransition = transitions[transitions.length - 1];\n if (!lastTransition || lastTransition.status !== status) {\n transitions.push({ status, at: timestamp });\n }\n }\n }\n }\n \n return transitions;\n } catch {\n return [];\n }\n}\n\n/**\n * Extract all git timestamp data for a spec file\n */\nexport function extractGitTimestamps(\n filePath: string,\n options: {\n includeAssignee?: boolean;\n includeTransitions?: boolean;\n } = {}\n): GitTimestampData {\n const data: GitTimestampData = {};\n \n // Core timestamps (always extracted)\n data.created_at = getFirstCommitTimestamp(filePath) ?? undefined;\n data.updated_at = getLastCommitTimestamp(filePath) ?? undefined;\n data.completed_at = getCompletionTimestamp(filePath) ?? undefined;\n \n // Optional fields\n if (options.includeAssignee) {\n const author = getFirstCommitAuthor(filePath);\n if (author) {\n data.assignee = author;\n }\n }\n \n if (options.includeTransitions) {\n const transitions = parseStatusTransitions(filePath);\n if (transitions.length > 0) {\n data.transitions = transitions;\n }\n }\n \n return data;\n}\n\n/**\n * Validate that a file exists in git history\n */\nexport function fileExistsInGit(filePath: string): boolean {\n try {\n execSync(\n `git log -n 1 -- \"${filePath}\"`,\n { stdio: 'ignore', encoding: 'utf-8' }\n );\n return true;\n } catch {\n return false;\n }\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport chalk from 'chalk';\nimport { loadConfig, saveConfig } from '../config.js';\n\nexport async function listTemplates(cwd: string = process.cwd()): Promise<void> {\n const config = await loadConfig(cwd);\n const templatesDir = path.join(cwd, '.lean-spec', 'templates');\n\n console.log('');\n console.log(chalk.green('=== Project Templates ==='));\n console.log('');\n\n try {\n await fs.access(templatesDir);\n } catch {\n console.log(chalk.yellow('No templates directory found.'));\n console.log(chalk.gray('Run: lean-spec init'));\n console.log('');\n return;\n }\n\n const files = await fs.readdir(templatesDir);\n const templateFiles = files.filter((f) => f.endsWith('.md'));\n\n if (templateFiles.length === 0) {\n console.log(chalk.yellow('No templates found.'));\n console.log('');\n return;\n }\n\n // Show registered templates first\n if (config.templates && Object.keys(config.templates).length > 0) {\n console.log(chalk.cyan('Registered:'));\n for (const [name, file] of Object.entries(config.templates)) {\n const isDefault = config.template === file;\n const marker = isDefault ? chalk.green('✓ (default)') : '';\n console.log(` ${chalk.bold(name)}: ${file} ${marker}`);\n }\n console.log('');\n }\n\n // Show all available template files\n console.log(chalk.cyan('Available files:'));\n for (const file of templateFiles) {\n const filePath = path.join(templatesDir, file);\n const stat = await fs.stat(filePath);\n const sizeKB = (stat.size / 1024).toFixed(1);\n console.log(` ${file} (${sizeKB} KB)`);\n }\n\n console.log('');\n console.log(chalk.gray('Use templates with: lean-spec create <name> --template=<template-name>'));\n console.log('');\n}\n\nexport async function showTemplate(\n templateName: string,\n cwd: string = process.cwd(),\n): Promise<void> {\n const config = await loadConfig(cwd);\n\n if (!config.templates?.[templateName]) {\n console.error(chalk.red(`Template not found: ${templateName}`));\n console.error(chalk.gray(`Available: ${Object.keys(config.templates || {}).join(', ')}`));\n process.exit(1);\n }\n\n const templatesDir = path.join(cwd, '.lean-spec', 'templates');\n const templateFile = config.templates[templateName];\n const templatePath = path.join(templatesDir, templateFile);\n\n try {\n const content = await fs.readFile(templatePath, 'utf-8');\n console.log('');\n console.log(chalk.cyan(`=== Template: ${templateName} (${templateFile}) ===`));\n console.log('');\n console.log(content);\n console.log('');\n } catch (error) {\n console.error(chalk.red(`Error reading template: ${templateFile}`));\n console.error(error);\n process.exit(1);\n }\n}\n\nexport async function addTemplate(\n name: string,\n file: string,\n cwd: string = process.cwd(),\n): Promise<void> {\n const config = await loadConfig(cwd);\n const templatesDir = path.join(cwd, '.lean-spec', 'templates');\n const templatePath = path.join(templatesDir, file);\n\n // Check if file exists\n try {\n await fs.access(templatePath);\n } catch {\n console.error(chalk.red(`Template file not found: ${file}`));\n console.error(chalk.gray(`Expected at: ${templatePath}`));\n console.error(\n chalk.yellow('Create the file first or use: lean-spec templates copy <source> <target>'),\n );\n process.exit(1);\n }\n\n // Add to config\n if (!config.templates) {\n config.templates = {};\n }\n\n if (config.templates[name]) {\n console.log(chalk.yellow(`Warning: Template '${name}' already exists, updating...`));\n }\n\n config.templates[name] = file;\n await saveConfig(config, cwd);\n\n console.log(chalk.green(`✓ Added template: ${name} → ${file}`));\n console.log(chalk.gray(` Use with: lean-spec create <spec-name> --template=${name}`));\n}\n\nexport async function removeTemplate(name: string, cwd: string = process.cwd()): Promise<void> {\n const config = await loadConfig(cwd);\n\n if (!config.templates?.[name]) {\n console.error(chalk.red(`Template not found: ${name}`));\n console.error(chalk.gray(`Available: ${Object.keys(config.templates || {}).join(', ')}`));\n process.exit(1);\n }\n\n if (name === 'default') {\n console.error(chalk.red('Cannot remove default template'));\n process.exit(1);\n }\n\n const file = config.templates[name];\n delete config.templates[name];\n await saveConfig(config, cwd);\n\n console.log(chalk.green(`✓ Removed template: ${name}`));\n console.log(chalk.gray(` Note: Template file ${file} still exists in .lean-spec/templates/`));\n}\n\nexport async function copyTemplate(\n source: string,\n target: string,\n cwd: string = process.cwd(),\n): Promise<void> {\n const config = await loadConfig(cwd);\n const templatesDir = path.join(cwd, '.lean-spec', 'templates');\n\n // Resolve source template\n let sourceFile: string;\n if (config.templates?.[source]) {\n sourceFile = config.templates[source];\n } else {\n sourceFile = source;\n }\n\n const sourcePath = path.join(templatesDir, sourceFile);\n\n // Check if source exists\n try {\n await fs.access(sourcePath);\n } catch {\n console.error(chalk.red(`Source template not found: ${source}`));\n console.error(chalk.gray(`Expected at: ${sourcePath}`));\n process.exit(1);\n }\n\n // Determine target filename\n const targetFile = target.endsWith('.md') ? target : `${target}.md`;\n const targetPath = path.join(templatesDir, targetFile);\n\n // Copy file\n await fs.copyFile(sourcePath, targetPath);\n console.log(chalk.green(`✓ Copied: ${sourceFile} → ${targetFile}`));\n\n // Optionally register the new template\n if (!config.templates) {\n config.templates = {};\n }\n\n const templateName = target.replace(/\\.md$/, '');\n config.templates[templateName] = targetFile;\n await saveConfig(config, cwd);\n\n console.log(chalk.green(`✓ Registered template: ${templateName}`));\n console.log(chalk.gray(` Edit: ${targetPath}`));\n console.log(chalk.gray(` Use with: lean-spec create <spec-name> --template=${templateName}`));\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport chalk from 'chalk';\nimport { select } from '@inquirer/prompts';\nimport { saveConfig, type LeanSpecConfig } from '../config.js';\nimport {\n detectExistingSystemPrompts,\n handleExistingFiles,\n copyDirectory,\n getProjectName,\n} from '../utils/template-helpers.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst TEMPLATES_DIR = path.join(__dirname, '..', 'templates');\n\nexport async function initProject(): Promise<void> {\n const cwd = process.cwd();\n\n // Check if already initialized\n try {\n await fs.access(path.join(cwd, '.lean-spec', 'config.json'));\n console.log(chalk.yellow('⚠ LeanSpec already initialized in this directory.'));\n console.log(chalk.gray('To reinitialize, delete .lean-spec/ directory first.'));\n return;\n } catch {\n // Not initialized, continue\n }\n\n console.log('');\n console.log(chalk.green('Welcome to LeanSpec!'));\n console.log('');\n\n // Main question: How to set up?\n const setupMode = await select({\n message: 'How would you like to set up?',\n choices: [\n {\n name: 'Quick start (recommended)',\n value: 'quick',\n description: 'Use standard template, start immediately',\n },\n {\n name: 'Choose template',\n value: 'template',\n description: 'Pick from: minimal, standard, enterprise',\n },\n // TODO: Re-enable when custom setup mode is implemented\n // {\n // name: 'Customize everything',\n // value: 'custom',\n // description: 'Full control over structure and settings',\n // },\n ],\n });\n\n let templateName = 'standard';\n\n if (setupMode === 'template') {\n // Let user choose template\n templateName = await select({\n message: 'Select template:',\n choices: [\n { name: 'minimal', value: 'minimal', description: 'Just folder structure, no extras' },\n { name: 'standard', value: 'standard', description: 'Recommended - includes AGENTS.md' },\n {\n name: 'enterprise',\n value: 'enterprise',\n description: 'Governance with approvals and compliance',\n },\n ],\n });\n }\n // Note: setupMode === 'custom' branch removed - will be implemented in future\n\n // Load template config\n const templateDir = path.join(TEMPLATES_DIR, templateName);\n const templateConfigPath = path.join(templateDir, 'config.json');\n\n let templateConfig: LeanSpecConfig;\n try {\n const content = await fs.readFile(templateConfigPath, 'utf-8');\n templateConfig = JSON.parse(content).config;\n } catch {\n console.error(chalk.red(`Error: Template not found: ${templateName}`));\n process.exit(1);\n }\n\n // Pattern selection (skip for quick start)\n let patternChoice = 'simple'; // Default for quick start\n\n if (setupMode !== 'quick') {\n patternChoice = await select({\n message: 'Select folder pattern:',\n choices: [\n {\n name: 'Simple: 001-my-spec/',\n value: 'simple',\n description: 'Global sequential numbering (recommended)',\n },\n {\n name: 'Date-grouped: 20251105/001-my-spec/',\n value: 'date-grouped',\n description: 'Group specs by creation date (good for teams)',\n },\n {\n name: 'Flat with date: 20251105-001-my-spec/',\n value: 'date-prefix',\n description: 'Date prefix with global numbering',\n },\n {\n name: 'Custom pattern',\n value: 'custom',\n description: 'Enter your own pattern',\n },\n ],\n });\n }\n\n // Apply pattern choice to config\n if (patternChoice === 'simple') {\n // Default: flat pattern with no prefix\n templateConfig.structure.pattern = 'flat';\n templateConfig.structure.prefix = '';\n } else if (patternChoice === 'date-grouped') {\n // Custom pattern with date grouping\n templateConfig.structure.pattern = 'custom';\n templateConfig.structure.groupExtractor = '{YYYYMMDD}';\n templateConfig.structure.prefix = undefined;\n } else if (patternChoice === 'date-prefix') {\n // Flat pattern with date prefix\n templateConfig.structure.pattern = 'flat';\n templateConfig.structure.prefix = '{YYYYMMDD}-';\n } else if (patternChoice === 'custom') {\n // Custom pattern not yet implemented - fall back to simple\n console.log('');\n console.log(chalk.yellow('⚠ Custom pattern input is not yet implemented.'));\n console.log(chalk.gray(' You can manually edit .lean-spec/config.json after initialization.'));\n console.log(chalk.gray(' Using simple pattern for now.'));\n console.log('');\n templateConfig.structure.pattern = 'flat';\n templateConfig.structure.prefix = '';\n }\n\n // Create .lean-spec/templates/ directory\n const templatesDir = path.join(cwd, '.lean-spec', 'templates');\n try {\n await fs.mkdir(templatesDir, { recursive: true });\n } catch (error) {\n console.error(chalk.red('Error creating templates directory:'), error);\n process.exit(1);\n }\n \n // Copy chosen template to .lean-spec/templates/spec-template.md\n const templateSpecPath = path.join(templateDir, 'spec-template.md');\n const targetSpecPath = path.join(templatesDir, 'spec-template.md');\n try {\n await fs.copyFile(templateSpecPath, targetSpecPath);\n console.log(chalk.green('✓ Created .lean-spec/templates/spec-template.md'));\n } catch (error) {\n console.error(chalk.red('Error copying template:'), error);\n process.exit(1);\n }\n \n // Update config to use new template structure\n templateConfig.template = 'spec-template.md';\n templateConfig.templates = {\n default: 'spec-template.md',\n };\n\n // Save config\n await saveConfig(templateConfig, cwd);\n console.log(chalk.green('✓ Created .lean-spec/config.json'));\n\n // Check for existing system prompt files\n const existingFiles = await detectExistingSystemPrompts(cwd);\n let skipFiles: string[] = [];\n\n if (existingFiles.length > 0) {\n console.log('');\n console.log(chalk.yellow(`Found existing: ${existingFiles.join(', ')}`));\n\n const action = await select<'merge-ai' | 'merge-append' | 'overwrite' | 'skip'>({\n message: 'How would you like to handle existing AGENTS.md?',\n choices: [\n {\n name: 'AI-Assisted Merge (recommended)',\n value: 'merge-ai',\n description: 'Creates prompt for AI to intelligently consolidate both files',\n },\n {\n name: 'Simple Append',\n value: 'merge-append',\n description: 'Quickly appends LeanSpec section (may be verbose)',\n },\n {\n name: 'Replace with LeanSpec',\n value: 'overwrite',\n description: 'Backs up existing, creates fresh AGENTS.md from template',\n },\n {\n name: 'Keep Existing Only',\n value: 'skip',\n description: 'Skips AGENTS.md, only adds .lean-spec config and specs/',\n },\n ],\n });\n\n // Get project name for variable substitution\n const projectName = await getProjectName(cwd);\n \n await handleExistingFiles(action, existingFiles, templateDir, cwd, { project_name: projectName });\n\n if (action === 'skip') {\n skipFiles = existingFiles;\n }\n }\n\n // Get project name for variable substitution\n const projectName = await getProjectName(cwd);\n\n // Copy template files (excluding those we're skipping)\n const filesDir = path.join(templateDir, 'files');\n try {\n await copyDirectory(filesDir, cwd, skipFiles, { project_name: projectName });\n console.log(chalk.green('✓ Initialized project structure'));\n } catch (error) {\n console.error(chalk.red('Error copying template files:'), error);\n process.exit(1);\n }\n\n console.log('');\n console.log(chalk.green('✓ LeanSpec initialized!'));\n console.log('');\n console.log('Next steps:');\n console.log(chalk.gray(' - Review and customize AGENTS.md'));\n console.log(chalk.gray(' - Check out example spec in specs/'));\n console.log(chalk.gray(' - Create your first spec: lean-spec create my-feature'));\n console.log('');\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport chalk from 'chalk';\n\n/**\n * Detect common system prompt files in a directory\n */\nexport async function detectExistingSystemPrompts(cwd: string): Promise<string[]> {\n const commonFiles = [\n 'AGENTS.md',\n '.cursorrules',\n '.github/copilot-instructions.md',\n ];\n\n const found: string[] = [];\n for (const file of commonFiles) {\n try {\n await fs.access(path.join(cwd, file));\n found.push(file);\n } catch {\n // File doesn't exist\n }\n }\n return found;\n}\n\n/**\n * Handle existing system prompt files based on user's chosen action\n */\nexport async function handleExistingFiles(\n action: 'merge-ai' | 'merge-append' | 'overwrite' | 'skip',\n existingFiles: string[],\n templateDir: string,\n cwd: string,\n variables: Record<string, string> = {}\n): Promise<void> {\n for (const file of existingFiles) {\n const filePath = path.join(cwd, file);\n const templateFilePath = path.join(templateDir, 'files', file);\n\n // Check if template has this file\n try {\n await fs.access(templateFilePath);\n } catch {\n // Template doesn't have this file, skip\n continue;\n }\n\n if (action === 'merge-ai' && file === 'AGENTS.md') {\n // Create consolidation prompt for AI to merge intelligently\n const existing = await fs.readFile(filePath, 'utf-8');\n let template = await fs.readFile(templateFilePath, 'utf-8');\n \n // Replace variables in template\n for (const [key, value] of Object.entries(variables)) {\n template = template.replace(new RegExp(`\\\\{${key}\\\\}`, 'g'), value);\n }\n\n // Create AI consolidation prompt file\n const promptPath = path.join(cwd, '.lean-spec', 'MERGE-AGENTS-PROMPT.md');\n const aiPrompt = `# AI Prompt: Consolidate AGENTS.md\n\n## Task\nConsolidate the existing AGENTS.md with LeanSpec instructions into a single, coherent document.\n\n## Instructions\n1. Read both documents below\n2. Merge them intelligently:\n - Preserve ALL existing project-specific information (workflows, SOPs, architecture, conventions)\n - Integrate LeanSpec sections where they fit naturally\n - Remove redundancy and ensure coherent flow\n - Keep the tone and style consistent\n3. Replace the existing AGENTS.md with the consolidated version\n\n## Existing AGENTS.md\n\\`\\`\\`markdown\n${existing}\n\\`\\`\\`\n\n## LeanSpec Instructions to Integrate\n\\`\\`\\`markdown\n${template}\n\\`\\`\\`\n\n## Output\nCreate a single consolidated AGENTS.md that:\n- Keeps all existing project context and workflows\n- Adds LeanSpec commands and principles where appropriate\n- Maintains clear structure and readability\n- Removes any duplicate or conflicting guidance\n`;\n\n await fs.mkdir(path.dirname(promptPath), { recursive: true });\n await fs.writeFile(promptPath, aiPrompt, 'utf-8');\n \n console.log(chalk.green(`✓ Created AI consolidation prompt`));\n console.log(chalk.cyan(` → ${promptPath}`));\n console.log('');\n console.log(chalk.yellow('📝 Next steps:'));\n console.log(chalk.gray(' 1. Open .lean-spec/MERGE-AGENTS-PROMPT.md'));\n console.log(chalk.gray(' 2. Send it to your AI coding assistant (GitHub Copilot, Cursor, etc.)'));\n console.log(chalk.gray(' 3. Let AI create the consolidated AGENTS.md'));\n console.log(chalk.gray(' 4. Review and commit the result'));\n console.log('');\n } else if (action === 'merge-append' && file === 'AGENTS.md') {\n // Simple append: add LeanSpec section to existing AGENTS.md\n const existing = await fs.readFile(filePath, 'utf-8');\n let template = await fs.readFile(templateFilePath, 'utf-8');\n \n // Replace variables in template\n for (const [key, value] of Object.entries(variables)) {\n template = template.replace(new RegExp(`\\\\{${key}\\\\}`, 'g'), value);\n }\n\n const merged = `${existing}\n\n---\n\n## LeanSpec Integration\n\n${template.split('\\n').slice(1).join('\\n')}`;\n\n await fs.writeFile(filePath, merged, 'utf-8');\n console.log(chalk.green(`✓ Appended LeanSpec section to ${file}`));\n console.log(chalk.yellow(' ⚠ Note: May be verbose. Consider consolidating later.'));\n } else if (action === 'overwrite') {\n // Backup existing file and create fresh one\n const backupPath = `${filePath}.backup`;\n await fs.rename(filePath, backupPath);\n console.log(chalk.yellow(`✓ Backed up ${file} → ${file}.backup`));\n\n // Copy template file with variable substitution\n let content = await fs.readFile(templateFilePath, 'utf-8');\n \n // Replace variables in content\n for (const [key, value] of Object.entries(variables)) {\n content = content.replace(new RegExp(`\\\\{${key}\\\\}`, 'g'), value);\n }\n \n await fs.writeFile(filePath, content, 'utf-8');\n console.log(chalk.green(`✓ Created new ${file}`));\n console.log(chalk.gray(` 💡 Your original content is preserved in ${file}.backup`));\n }\n // If skip, do nothing with this file\n }\n}\n\n/**\n * Recursively copy directory with variable substitution and skip list\n */\nexport async function copyDirectory(\n src: string,\n dest: string,\n skipFiles: string[] = [],\n variables: Record<string, string> = {}\n): Promise<void> {\n await fs.mkdir(dest, { recursive: true });\n\n const entries = await fs.readdir(src, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name);\n const destPath = path.join(dest, entry.name);\n\n // Check if this file should be skipped\n if (skipFiles.includes(entry.name)) {\n continue;\n }\n\n if (entry.isDirectory()) {\n await copyDirectory(srcPath, destPath, skipFiles, variables);\n } else {\n // Only copy if file doesn't exist\n try {\n await fs.access(destPath);\n // File exists, skip it\n } catch {\n // File doesn't exist, copy it with variable substitution\n let content = await fs.readFile(srcPath, 'utf-8');\n \n // Replace variables in content\n for (const [key, value] of Object.entries(variables)) {\n content = content.replace(new RegExp(`\\\\{${key}\\\\}`, 'g'), value);\n }\n \n await fs.writeFile(destPath, content, 'utf-8');\n }\n }\n }\n}\n\n/**\n * Get project name from package.json or directory name\n */\nexport async function getProjectName(cwd: string): Promise<string> {\n try {\n const packageJsonPath = path.join(cwd, 'package.json');\n const content = await fs.readFile(packageJsonPath, 'utf-8');\n const pkg = JSON.parse(content);\n if (pkg.name) {\n return pkg.name;\n }\n } catch {\n // package.json not found or invalid\n }\n \n // Fallback to directory name\n return path.basename(cwd);\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport chalk from 'chalk';\nimport { getSpec, loadSubFiles } from '../spec-loader.js';\nimport { resolveSpecPath } from '../utils/path-helpers.js';\nimport { loadConfig } from '../config.js';\nimport { autoCheckIfEnabled } from './check.js';\nimport { sanitizeUserInput } from '../utils/ui.js';\n\nexport async function filesCommand(\n specPath: string,\n options: {\n type?: 'docs' | 'assets';\n tree?: boolean;\n } = {}\n): Promise<void> {\n // Auto-check for conflicts before display\n await autoCheckIfEnabled();\n \n const config = await loadConfig();\n const cwd = process.cwd();\n const specsDir = path.join(cwd, config.specsDir);\n\n // Resolve spec path\n const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);\n if (!resolvedPath) {\n throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}. Try using the full path or spec name (e.g., 001-my-spec)`);\n }\n\n // Load spec info\n const spec = await getSpec(resolvedPath);\n if (!spec) {\n throw new Error(`Could not load spec: ${sanitizeUserInput(specPath)}`);\n }\n\n // Load sub-files\n const subFiles = await loadSubFiles(spec.fullPath);\n\n console.log('');\n console.log(chalk.cyan(`📄 Files in ${sanitizeUserInput(spec.name)}`));\n console.log('');\n\n // Show README.md (required)\n console.log(chalk.green('Required:'));\n const readmeStat = await fs.stat(spec.filePath);\n const readmeSize = formatSize(readmeStat.size);\n console.log(chalk.green(` ✓ README.md (${readmeSize}) Main spec`));\n console.log('');\n\n // Filter by type if requested\n let filteredFiles = subFiles;\n if (options.type === 'docs') {\n filteredFiles = subFiles.filter((f) => f.type === 'document');\n } else if (options.type === 'assets') {\n filteredFiles = subFiles.filter((f) => f.type === 'asset');\n }\n\n if (filteredFiles.length === 0) {\n console.log(chalk.gray('No additional files'));\n console.log('');\n return;\n }\n\n // Group by type\n const documents = filteredFiles.filter((f) => f.type === 'document');\n const assets = filteredFiles.filter((f) => f.type === 'asset');\n\n if (documents.length > 0 && (!options.type || options.type === 'docs')) {\n console.log(chalk.cyan('Documents:'));\n for (const file of documents) {\n const size = formatSize(file.size);\n console.log(chalk.cyan(` ✓ ${sanitizeUserInput(file.name).padEnd(20)} (${size})`));\n }\n console.log('');\n }\n\n if (assets.length > 0 && (!options.type || options.type === 'assets')) {\n console.log(chalk.yellow('Assets:'));\n for (const file of assets) {\n const size = formatSize(file.size);\n console.log(chalk.yellow(` ✓ ${sanitizeUserInput(file.name).padEnd(20)} (${size})`));\n }\n console.log('');\n }\n\n // Show totals\n const totalFiles = filteredFiles.length + 1; // +1 for README.md\n const totalSize = formatSize(\n readmeStat.size + filteredFiles.reduce((sum, f) => sum + f.size, 0)\n );\n console.log(chalk.gray(`Total: ${totalFiles} files, ${totalSize}`));\n console.log('');\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n } else if (bytes < 1024 * 1024) {\n return `${(bytes / 1024).toFixed(1)} KB`;\n } else {\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\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 { 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 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 rule?: string; // Filter by specific rule name\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 specs for quality issues\n */\nexport async function validateCommand(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 LineCountValidator({ maxLines: options.maxLines }),\n new FrontmatterValidator(),\n new StructureValidator(),\n new CorruptionValidator(),\n new SubSpecValidator({ maxLines: options.maxLines }),\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 const result = await validator.validate(spec, content);\n results.push({ \n spec, \n validatorName: validator.name,\n result, \n content,\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 (any errors = failed)\n const hasErrors = results.some(r => !r.result.passed);\n return !hasErrors;\n}\n","/**\n * Line count validator - enforces Context Economy principle\n * \n * Specs must fit in working memory:\n * - <300 lines: ✓ Ideal\n * - 300-400 lines: ⚠️ Warning (approaching limit)\n * - >400 lines: ✗ Error (exceeds limit)\n */\n\nimport type { ValidationRule, ValidationResult } from '../utils/validation-framework.js';\nimport type { SpecInfo } from '../spec-loader.js';\n\nexport interface LineCountOptions {\n maxLines?: number; // Default: 400\n warningThreshold?: number; // Default: 300\n}\n\nexport class LineCountValidator implements ValidationRule {\n name = 'max-lines';\n description = 'Enforce Context Economy: specs must be <400 lines';\n\n private maxLines: number;\n private warningThreshold: number;\n\n constructor(options: LineCountOptions = {}) {\n this.maxLines = options.maxLines ?? 400;\n this.warningThreshold = options.warningThreshold ?? 300;\n }\n\n validate(_spec: SpecInfo, content: string): ValidationResult {\n const lines = content.split('\\n').length;\n\n // Error: exceeds limit\n if (lines > this.maxLines) {\n return {\n passed: false,\n errors: [{\n message: `Spec exceeds ${this.maxLines} lines (${lines} lines)`,\n suggestion: 'Consider splitting into sub-specs using spec 012 pattern',\n }],\n warnings: [],\n };\n }\n\n // Warning: approaching limit\n if (lines > this.warningThreshold) {\n return {\n passed: true,\n errors: [],\n warnings: [{\n message: `Spec approaching limit (${lines}/${this.maxLines} lines)`,\n suggestion: 'Consider simplification or splitting',\n }],\n };\n }\n\n // Pass: under threshold\n return {\n passed: true,\n errors: [],\n warnings: [],\n };\n }\n}\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 // Check for required sections (H2 level)\n for (const requiredSection of this.requiredSections) {\n const found = headings.some(\n h => h.level === 2 && h.text.toLowerCase() === requiredSection.toLowerCase()\n );\n if (!found) {\n if (this.strict) {\n errors.push({\n message: `Missing required section: ## ${requiredSection}`,\n suggestion: `Add ## ${requiredSection} section to the spec`,\n });\n } else {\n warnings.push({\n message: `Recommended section missing: ## ${requiredSection}`,\n suggestion: `Consider adding ## ${requiredSection} section`,\n });\n }\n }\n }\n\n // Check for empty sections\n const emptySections = this.findEmptySections(body, headings);\n for (const section of emptySections) {\n // Only warn about empty required sections\n if (this.requiredSections.some(req => req.toLowerCase() === section.toLowerCase())) {\n warnings.push({\n message: `Empty required section: ## ${section}`,\n suggestion: 'Add content to this section or remove it',\n });\n }\n }\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 * 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 line counts per sub-spec file (<400 lines)\n * - Detects orphaned sub-spec files (not linked from README)\n * - Validates cross-document references\n */\n\nimport * as fs from 'node:fs/promises';\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 { loadSubFiles, type SubFileInfo } from '../spec-loader.js';\n\nexport interface SubSpecOptions {\n maxLines?: number; // Default: 400\n warningThreshold?: number; // Default: 300\n checkCrossReferences?: boolean; // Default: true\n}\n\nexport class SubSpecValidator implements ValidationRule {\n name = 'sub-specs';\n description = 'Validate sub-spec files per spec 012 conventions';\n\n private maxLines: number;\n private warningThreshold: number;\n private checkCrossReferences: boolean;\n\n constructor(options: SubSpecOptions = {}) {\n this.maxLines = options.maxLines ?? 400;\n this.warningThreshold = options.warningThreshold ?? 300;\n this.checkCrossReferences = 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 line counts for each sub-spec\n await this.validateLineCounts(subSpecs, errors, warnings);\n\n // Check for orphaned sub-specs (not referenced in README.md)\n this.checkOrphanedSubSpecs(subSpecs, content, warnings);\n\n // Validate cross-references\n if (this.checkCrossReferences) {\n await this.validateCrossReferences(subSpecs, spec, 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 line counts for each sub-spec file\n */\n private async validateLineCounts(\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').length;\n\n // Error: exceeds limit\n if (lines > this.maxLines) {\n errors.push({\n message: `Sub-spec ${subSpec.name} exceeds ${this.maxLines} lines (${lines} lines)`,\n suggestion: 'Consider further splitting or simplification',\n });\n }\n // Warning: approaching limit\n else if (lines > this.warningThreshold) {\n warnings.push({\n message: `Sub-spec ${subSpec.name} approaching limit (${lines}/${this.maxLines} lines)`,\n suggestion: 'Consider simplification',\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 * Validate cross-document references between sub-specs\n */\n private async validateCrossReferences(\n subSpecs: SubFileInfo[],\n spec: SpecInfo,\n warnings: ValidationWarning[]\n ): Promise<void> {\n // Build a set of all valid sub-spec filenames\n const validFileNames = new Set(subSpecs.map(s => s.name));\n validFileNames.add('README.md'); // README is also valid\n\n for (const subSpec of subSpecs) {\n if (!subSpec.content) {\n continue;\n }\n\n // Find all markdown links in the content with optional ./ prefix\n // Match any characters except closing paren to support various filename patterns\n const linkRegex = /\\[([^\\]]+)\\]\\((?:\\.\\/)?(([^)]+)\\.md)\\)/g;\n let match;\n\n while ((match = linkRegex.exec(subSpec.content)) !== null) {\n const referencedFile = match[2];\n \n // Check if referenced file exists\n if (!validFileNames.has(referencedFile)) {\n warnings.push({\n message: `Broken reference in ${subSpec.name}: ${referencedFile} not found`,\n suggestion: `Check if ${referencedFile} exists or update the link`,\n });\n }\n }\n }\n }\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","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { loadConfig } from '../config.js';\n\nexport interface MigrationOptions {\n inputPath: string;\n aiProvider?: 'copilot' | 'claude' | 'gemini';\n dryRun?: boolean;\n batchSize?: number;\n skipValidation?: boolean;\n backfill?: boolean;\n}\n\nexport interface DocumentInfo {\n path: string;\n name: string;\n size: number;\n}\n\n/**\n * Main migration command - generates instructions for migrating specs from other tools\n */\nexport async function migrateCommand(inputPath: string, options: Partial<MigrationOptions> = {}): Promise<void> {\n const config = await loadConfig();\n \n // Validate input path exists\n try {\n const stats = await fs.stat(inputPath);\n if (!stats.isDirectory()) {\n console.error('\\x1b[31m❌ Error:\\x1b[0m Input path must be a directory');\n process.exit(1);\n }\n } catch (error) {\n console.error(`\\x1b[31m❌ Error:\\x1b[0m Path not found: ${inputPath}`);\n process.exit(1);\n }\n \n // Scan for documents\n console.log(`\\x1b[36mScanning:\\x1b[0m ${inputPath}\\n`);\n const documents = await scanDocuments(inputPath);\n \n if (documents.length === 0) {\n console.error(`\\x1b[31m❌ Error:\\x1b[0m No documents found in ${inputPath}`);\n console.error(' Check path and try again');\n process.exit(1);\n }\n \n console.log(`\\x1b[32m✓\\x1b[0m Found ${documents.length} document${documents.length === 1 ? '' : 's'}\\n`);\n \n // If AI provider specified, verify and execute\n if (options.aiProvider) {\n await migrateWithAI(inputPath, documents, options as MigrationOptions);\n } else {\n // Default: Output manual migration instructions\n await outputManualInstructions(inputPath, documents, config);\n }\n}\n\n/**\n * Scan directory for markdown documents (format-agnostic)\n */\nexport async function scanDocuments(dirPath: string): Promise<DocumentInfo[]> {\n const documents: DocumentInfo[] = [];\n \n async function scanRecursive(currentPath: string): Promise<void> {\n const entries = await fs.readdir(currentPath, { withFileTypes: true });\n \n for (const entry of entries) {\n const fullPath = path.join(currentPath, entry.name);\n \n if (entry.isDirectory()) {\n // Skip node_modules, .git, etc.\n if (!entry.name.startsWith('.') && entry.name !== 'node_modules') {\n await scanRecursive(fullPath);\n }\n } else if (entry.isFile()) {\n // Look for markdown files\n if (entry.name.endsWith('.md') || entry.name.endsWith('.markdown')) {\n const stats = await fs.stat(fullPath);\n documents.push({\n path: fullPath,\n name: entry.name,\n size: stats.size,\n });\n }\n }\n }\n }\n \n await scanRecursive(dirPath);\n return documents;\n}\n\n/**\n * Output manual migration instructions (default mode)\n */\nasync function outputManualInstructions(\n inputPath: string,\n documents: DocumentInfo[],\n config: any\n): Promise<void> {\n const specsDir = config.specsDir || 'specs';\n \n console.log('═'.repeat(70));\n console.log('\\x1b[1m\\x1b[36m📋 LeanSpec Migration Instructions\\x1b[0m');\n console.log('═'.repeat(70));\n console.log();\n console.log('\\x1b[1mSource Location:\\x1b[0m');\n console.log(` ${inputPath} (${documents.length} documents found)`);\n console.log();\n console.log('\\x1b[1mMigration Prompt:\\x1b[0m');\n console.log(' Copy this prompt to your AI assistant (Copilot, Claude, ChatGPT, etc.):');\n console.log();\n console.log('─'.repeat(70));\n console.log();\n console.log('You are helping migrate specification documents to LeanSpec format.');\n console.log();\n console.log(`\\x1b[1mSource:\\x1b[0m ${inputPath}`);\n console.log();\n console.log('\\x1b[1mYour Task:\\x1b[0m');\n console.log('1. Analyze the source documents to understand their format and structure');\n console.log('2. For each document, extract:');\n console.log(' - Title/name');\n console.log(' - Status (map to: planned, in-progress, complete, archived)');\n console.log(' - Creation date');\n console.log(' - Priority (if present)');\n console.log(' - Main content sections');\n console.log(' - Relationships to other documents');\n console.log();\n console.log('3. Migrate each document by running these commands:');\n console.log();\n console.log(' # Create spec');\n console.log(' lean-spec create <name>');\n console.log();\n console.log(' # Set metadata (NEVER edit frontmatter manually)');\n console.log(' lean-spec update <name> --status <status>');\n console.log(' lean-spec update <name> --priority <priority>');\n console.log(' lean-spec update <name> --tags <tag1,tag2>');\n console.log();\n console.log(' # Edit content with your preferred tool');\n console.log(' # Map original sections to LeanSpec structure:');\n console.log(' # - Overview: Problem statement and context');\n console.log(' # - Design: Technical approach and decisions');\n console.log(' # - Plan: Implementation steps (if applicable)');\n console.log(' # - Test: Validation criteria (if applicable)');\n console.log(' # - Notes: Additional context, trade-offs, alternatives');\n console.log();\n console.log('4. After migration, run:');\n console.log();\n console.log(' lean-spec validate # Check for issues');\n console.log(' lean-spec board # Verify migration');\n console.log();\n console.log('\\x1b[1mImportant Rules:\\x1b[0m');\n console.log('- Preserve decision rationale and context');\n console.log('- Map status appropriately to LeanSpec states');\n console.log('- Link related specs using `related` field (manual frontmatter edit)');\n console.log('- Follow LeanSpec first principles: clarity over completeness');\n console.log('- Keep specs under 400 lines (split if needed)');\n console.log();\n console.log('─'.repeat(70));\n console.log();\n console.log('\\x1b[36mℹ\\x1b[0m \\x1b[1mTip:\\x1b[0m For AI-assisted migration, use:');\n console.log(' \\x1b[90mlean-spec migrate <path> --with copilot\\x1b[0m');\n console.log();\n}\n\n/**\n * AI-assisted migration (when --with flag specified)\n */\nasync function migrateWithAI(\n inputPath: string,\n documents: DocumentInfo[],\n options: MigrationOptions\n): Promise<void> {\n const provider = options.aiProvider!;\n \n console.log(`\\x1b[36m🤖 AI-Assisted Migration:\\x1b[0m ${provider}\\n`);\n \n // Verify AI CLI tool\n const tool = await verifyAITool(provider);\n \n if (!tool.installed) {\n console.error(`\\x1b[31m❌ ${tool.name} CLI not found\\x1b[0m`);\n console.error(` Install: ${tool.installCmd}`);\n console.error(' Or run without --with flag for manual instructions');\n process.exit(1);\n }\n \n if (!tool.compatible) {\n console.error(`\\x1b[31m❌ ${tool.name} version ${tool.version} too old\\x1b[0m`);\n console.error(` Required: >=${tool.minVersion}`);\n console.error(` Update: ${tool.updateCmd}`);\n process.exit(1);\n }\n \n console.log(`\\x1b[32m✓\\x1b[0m ${tool.name} CLI verified (v${tool.version})\\n`);\n \n // AI-assisted mode is a placeholder for future implementation\n console.log('\\x1b[33m⚠ AI-assisted migration is not yet fully implemented\\x1b[0m');\n console.log(' This feature will automatically execute migration via AI CLI tools.');\n console.log();\n console.log(' For now, use manual mode (without --with flag) to get migration instructions.');\n console.log();\n}\n\n/**\n * AI CLI tool definitions\n */\ninterface AICliTool {\n name: string;\n cliCommand: string;\n installCmd: string;\n updateCmd: string;\n versionCmd: string;\n minVersion: string;\n installed: boolean;\n version?: string;\n compatible: boolean;\n}\n\n/**\n * Verify AI CLI tool is installed and compatible\n */\nasync function verifyAITool(provider: 'copilot' | 'claude' | 'gemini'): Promise<AICliTool> {\n const tools: Record<string, Omit<AICliTool, 'installed' | 'version' | 'compatible'>> = {\n copilot: {\n name: 'GitHub Copilot CLI',\n cliCommand: 'github-copilot-cli',\n installCmd: 'npm install -g @githubnext/github-copilot-cli',\n updateCmd: 'npm update -g @githubnext/github-copilot-cli',\n versionCmd: 'github-copilot-cli --version',\n minVersion: '0.1.0',\n },\n claude: {\n name: 'Claude CLI',\n cliCommand: 'claude',\n installCmd: 'pip install claude-cli',\n updateCmd: 'pip install --upgrade claude-cli',\n versionCmd: 'claude --version',\n minVersion: '1.0.0',\n },\n gemini: {\n name: 'Gemini CLI',\n cliCommand: 'gemini-cli',\n installCmd: 'npm install -g @google/gemini-cli',\n updateCmd: 'npm update -g @google/gemini-cli',\n versionCmd: 'gemini-cli --version',\n minVersion: '1.0.0',\n },\n };\n \n const toolDef = tools[provider];\n \n // Check if installed\n let installed = false;\n let version: string | undefined;\n \n try {\n const { execSync } = await import('node:child_process');\n // Check if command exists\n execSync(`which ${toolDef.cliCommand}`, { stdio: 'ignore' });\n installed = true;\n \n // Get version\n try {\n const versionOutput = execSync(toolDef.versionCmd, { \n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'ignore']\n });\n const versionMatch = versionOutput.match(/(\\d+\\.\\d+\\.\\d+)/);\n if (versionMatch) {\n version = versionMatch[1];\n }\n } catch {\n // Version check failed, but tool is installed\n version = 'unknown';\n }\n } catch {\n // Command not found\n installed = false;\n }\n \n // Check compatibility\n const compatible = installed && (version === 'unknown' || (version !== undefined && satisfiesVersion(version, toolDef.minVersion)));\n \n return {\n ...toolDef,\n installed,\n version,\n compatible,\n };\n}\n\n/**\n * Simple semver comparison\n */\nfunction satisfiesVersion(version: string, minVersion: string): boolean {\n const vParts = version.split('.').map(Number);\n const minParts = minVersion.split('.').map(Number);\n \n for (let i = 0; i < 3; i++) {\n const v = vParts[i] || 0;\n const min = minParts[i] || 0;\n \n if (v > min) return true;\n if (v < min) return false;\n }\n \n return true; // equal\n}\n","import chalk from 'chalk';\nimport { loadAllSpecs } from '../spec-loader.js';\nimport type { SpecInfo } from '../spec-loader.js';\nimport type { SpecFilterOptions, SpecStatus, SpecPriority } from '../frontmatter.js';\nimport { withSpinner } from '../utils/ui.js';\nimport { autoCheckIfEnabled } from './check.js';\nimport { sanitizeUserInput } from '../utils/ui.js';\nimport { calculateCompletion, getCompletionStatus } from '../utils/completion.js';\nimport { calculateVelocityMetrics } from '../utils/velocity.js';\nimport { STATUS_CONFIG, PRIORITY_CONFIG } from '../utils/colors.js';\n\nexport async function boardCommand(options: {\n showComplete?: boolean;\n simple?: boolean;\n completionOnly?: boolean;\n tag?: string;\n assignee?: string;\n}): Promise<void> {\n // Auto-check for conflicts before display\n await autoCheckIfEnabled();\n \n // Build filter\n const filter: SpecFilterOptions = {};\n if (options.tag) {\n filter.tags = [options.tag];\n }\n if (options.assignee) {\n filter.assignee = options.assignee;\n }\n\n // Load all specs with spinner (include archived for accurate metrics, but don't display in columns)\n const specs = await withSpinner(\n 'Loading specs...',\n () => loadAllSpecs({\n includeArchived: true,\n filter,\n })\n );\n\n if (specs.length === 0) {\n console.log(chalk.dim('No specs found.'));\n return;\n }\n\n // Group specs by status (we loaded archived for metrics, but don't show them in board columns)\n const columns: Record<SpecStatus, SpecInfo[]> = {\n planned: [],\n 'in-progress': [],\n complete: [],\n archived: [],\n };\n\n for (const spec of specs) {\n // Handle invalid status by treating as 'planned'\n const status = columns[spec.frontmatter.status] !== undefined \n ? spec.frontmatter.status \n : 'planned';\n \n // Only add to columns if not archived (archived specs are included in metrics but not displayed)\n if (status !== 'archived') {\n columns[status].push(spec);\n }\n }\n\n // Display header\n console.log(chalk.bold.cyan('📋 Spec Kanban Board'));\n \n // Filter info\n if (options.tag || options.assignee) {\n const filterParts: string[] = [];\n if (options.tag) filterParts.push(`tag=${options.tag}`);\n if (options.assignee) filterParts.push(`assignee=${options.assignee}`);\n console.log(chalk.dim(`Filtered by: ${filterParts.join(', ')}`));\n }\n console.log('');\n\n // Show completion summary unless --simple flag is set\n if (!options.simple) {\n const completionMetrics = calculateCompletion(specs);\n const velocityMetrics = calculateVelocityMetrics(specs);\n const completionStatus = getCompletionStatus(completionMetrics.score);\n \n // Health summary box\n const boxWidth = 62;\n const topBorder = '╔' + '═'.repeat(boxWidth - 2) + '╗';\n const bottomBorder = '╚' + '═'.repeat(boxWidth - 2) + '╝';\n \n // Helper to pad line with ANSI code awareness\n const padLine = (content: string): string => {\n const visibleLength = stripAnsi(content).length;\n const padding = boxWidth - 2 - visibleLength;\n return content + ' '.repeat(Math.max(0, padding));\n };\n \n console.log(chalk.dim(topBorder));\n \n const headerLine = chalk.bold(' Project Overview');\n console.log(chalk.dim('║') + padLine(headerLine) + chalk.dim('║'));\n \n // Completion rate percentage\n const percentageColor = completionMetrics.score >= 70 ? chalk.green : \n completionMetrics.score >= 40 ? chalk.yellow : \n chalk.red;\n \n const line1 = ` ${completionMetrics.totalSpecs} total · ${completionMetrics.activeSpecs} active · ${completionMetrics.completeSpecs} complete ${percentageColor('(' + completionMetrics.score + '%)')}`;\n console.log(chalk.dim('║') + padLine(line1) + chalk.dim('║'));\n \n // Alerts line\n if (completionMetrics.criticalIssues.length > 0 || completionMetrics.warnings.length > 0) {\n const alerts: string[] = [];\n if (completionMetrics.criticalIssues.length > 0) {\n alerts.push(`${completionMetrics.criticalIssues.length} critical overdue`);\n }\n if (completionMetrics.warnings.length > 0) {\n alerts.push(`${completionMetrics.warnings.length} specs WIP > 7 days`);\n }\n const alertLine = ` ${chalk.yellow('⚠️ ' + alerts.join(' · '))}`;\n console.log(chalk.dim('║') + padLine(alertLine) + chalk.dim('║'));\n }\n \n // Velocity line\n const velocityLine = ` ${chalk.cyan('🚀 Velocity:')} ${velocityMetrics.cycleTime.average.toFixed(1)}d avg cycle · ${(velocityMetrics.throughput.perWeek / 7 * 7).toFixed(1)}/wk throughput`;\n console.log(chalk.dim('║') + padLine(velocityLine) + chalk.dim('║'));\n \n console.log(chalk.dim(bottomBorder));\n console.log('');\n\n // If --completion-only, stop here\n if (options.completionOnly) {\n return;\n }\n } // Render columns\n renderColumn(STATUS_CONFIG.planned.label, STATUS_CONFIG.planned.emoji, columns.planned, true, STATUS_CONFIG.planned.colorFn);\n \n // Separator between status sections\n console.log(chalk.dim('━'.repeat(70)));\n console.log('');\n \n renderColumn(STATUS_CONFIG['in-progress'].label, STATUS_CONFIG['in-progress'].emoji, columns['in-progress'], true, STATUS_CONFIG['in-progress'].colorFn);\n \n // Separator between status sections\n console.log(chalk.dim('━'.repeat(70)));\n console.log('');\n \n renderColumn(STATUS_CONFIG.complete.label, STATUS_CONFIG.complete.emoji, columns.complete, options.showComplete || false, STATUS_CONFIG.complete.colorFn);\n}\n\nfunction renderColumn(\n title: string,\n emoji: string,\n specs: SpecInfo[],\n expanded: boolean,\n colorFn: (s: string) => string\n): void {\n // Column header\n console.log(`${emoji} ${colorFn(chalk.bold(`${title} (${specs.length})`))}`);\n console.log('');\n\n if (expanded && specs.length > 0) {\n // Group specs by priority\n const priorityGroups: Record<string, SpecInfo[]> = {\n critical: [],\n high: [],\n medium: [],\n low: [],\n none: []\n };\n\n for (const spec of specs) {\n const priority = spec.frontmatter.priority || 'none';\n priorityGroups[priority].push(spec);\n }\n\n // Render each priority group\n const priorityOrder: Array<keyof typeof priorityGroups> = ['critical', 'high', 'medium', 'low', 'none'];\n let firstGroup = true;\n\n for (const priority of priorityOrder) {\n const groupSpecs = priorityGroups[priority];\n if (groupSpecs.length === 0) continue;\n\n // Add spacing between groups\n if (!firstGroup) {\n console.log('');\n }\n firstGroup = false;\n\n // Priority group header - minimal, modern style\n const priorityLabel = priority === 'none' ? 'No Priority' : priority.charAt(0).toUpperCase() + priority.slice(1);\n const priorityEmoji = priority === 'none' ? '⚪' : PRIORITY_CONFIG[priority as SpecPriority].emoji;\n const priorityColor = priority === 'none' ? chalk.dim : PRIORITY_CONFIG[priority as SpecPriority].colorFn;\n \n console.log(` ${priorityColor(`${priorityEmoji} ${chalk.bold(priorityLabel)} ${chalk.dim(`(${groupSpecs.length})`)}`)}`);;\n\n for (const spec of groupSpecs) {\n // Build spec line with metadata\n let assigneeStr = '';\n if (spec.frontmatter.assignee) {\n assigneeStr = ' ' + chalk.cyan(`@${sanitizeUserInput(spec.frontmatter.assignee)}`);\n }\n \n let tagsStr = '';\n if (spec.frontmatter.tags?.length) {\n // Defensive check: ensure tags is an array\n const tags = Array.isArray(spec.frontmatter.tags) ? spec.frontmatter.tags : [];\n if (tags.length > 0) {\n const tagStr = tags.map(tag => `#${sanitizeUserInput(tag)}`).join(' ');\n tagsStr = ' ' + chalk.dim(chalk.magenta(tagStr));\n }\n }\n\n console.log(` ${chalk.cyan(sanitizeUserInput(spec.path))}${assigneeStr}${tagsStr}`);\n }\n }\n\n console.log('');\n } else if (!expanded && specs.length > 0) {\n console.log(` ${chalk.dim('(collapsed, use --complete to expand)')}`);\n console.log('');\n } else {\n console.log(` ${chalk.dim('(empty)')}`);\n console.log('');\n }\n}\n\n// Helper function to strip ANSI codes for accurate length calculation\nfunction stripAnsi(str: string): string {\n return str.replace(/\\u001b\\[\\d+m/g, '');\n}\n","import dayjs from 'dayjs';\nimport type { SpecInfo } from '../spec-loader.js';\n\nexport interface CompletionMetrics {\n score: number; // 0-100 (simple completion rate: complete/total * 100)\n totalSpecs: number;\n activeSpecs: number;\n completeSpecs: number;\n criticalIssues: string[];\n warnings: string[];\n}\n\n/**\n * Check if a spec is critical and overdue\n */\nfunction isCriticalOverdue(spec: SpecInfo): boolean {\n if (spec.frontmatter.status === 'complete' || spec.frontmatter.status === 'archived') {\n return false;\n }\n \n if (!spec.frontmatter.due) {\n return false;\n }\n \n const isOverdue = dayjs(spec.frontmatter.due).isBefore(dayjs(), 'day');\n const isCritical = spec.frontmatter.priority === 'critical' || spec.frontmatter.priority === 'high';\n \n return isOverdue && isCritical;\n}\n\n/**\n * Check if a spec has been in progress for too long (> 7 days)\n */\nfunction isLongRunning(spec: SpecInfo): boolean {\n if (spec.frontmatter.status !== 'in-progress') {\n return false;\n }\n \n const updatedAt = spec.frontmatter.updated || spec.frontmatter.updated_at || spec.frontmatter.created || spec.frontmatter.created_at;\n \n if (!updatedAt) {\n return false;\n }\n \n const daysSinceUpdate = dayjs().diff(dayjs(updatedAt), 'day');\n return daysSinceUpdate > 7;\n}\n\n/**\n * Calculate completion metrics for a set of specs\n * Score is simple completion rate: (complete / total) * 100\n */\nexport function calculateCompletion(specs: SpecInfo[]): CompletionMetrics {\n const criticalIssues: string[] = [];\n const warnings: string[] = [];\n \n // Filter out archived specs (by path or status)\n // Specs in archived/ folder may have status: complete, so check path too\n const activeAndCompleteSpecs = specs.filter(s => \n s.frontmatter.status !== 'archived' && \n !s.path.startsWith('archived/')\n );\n \n for (const spec of activeAndCompleteSpecs) {\n // Detect critical issues\n if (isCriticalOverdue(spec)) {\n criticalIssues.push(spec.path);\n }\n \n // Detect warnings (long-running WIP)\n if (isLongRunning(spec)) {\n warnings.push(spec.path);\n }\n }\n \n // Count active and complete specs (excluding archived by path and status)\n const activeSpecs = specs.filter(\n s => (s.frontmatter.status === 'planned' || s.frontmatter.status === 'in-progress') &&\n !s.path.startsWith('archived/')\n );\n const completeSpecs = specs.filter(s => \n s.frontmatter.status === 'complete' && \n !s.path.startsWith('archived/')\n );\n \n // Calculate simple completion rate (avoid division by zero)\n const totalSpecs = activeAndCompleteSpecs.length;\n const score = totalSpecs > 0 ? Math.round((completeSpecs.length / totalSpecs) * 100) : 0;\n \n return {\n score,\n totalSpecs,\n activeSpecs: activeSpecs.length,\n completeSpecs: completeSpecs.length,\n criticalIssues,\n warnings,\n };\n}\n\n/**\n * Get a completion status indicator based on score\n */\nexport function getCompletionStatus(score: number): { emoji: string; label: string; color: string } {\n if (score >= 70) {\n return { emoji: '✓', label: 'Good', color: 'green' };\n } else if (score >= 40) {\n return { emoji: '⚠', label: 'Fair', color: 'yellow' };\n } else {\n return { emoji: '✗', label: 'Needs Attention', color: 'red' };\n }\n}\n","import dayjs from 'dayjs';\nimport type { SpecInfo } from '../spec-loader.js';\n\n/**\n * Velocity metrics for measuring SDD effectiveness\n */\nexport interface VelocityMetrics {\n cycleTime: {\n average: number; // Average days from created to completed\n median: number;\n p90: number; // 90th percentile\n };\n leadTime: {\n plannedToInProgress: number; // Average days in planned\n inProgressToComplete: number; // Average days in progress\n };\n throughput: {\n perWeek: number;\n perMonth: number;\n trend: 'up' | 'down' | 'stable';\n };\n wip: {\n current: number; // Current work in progress\n average: number; // Average WIP over time\n };\n}\n\n/**\n * Calculate cycle time (created → completed) in days\n */\nexport function calculateCycleTime(spec: SpecInfo): number | null {\n if (spec.frontmatter.status !== 'complete' && spec.frontmatter.status !== 'archived') {\n return null;\n }\n\n const createdAt = spec.frontmatter.created_at || spec.frontmatter.created;\n const completedAt = spec.frontmatter.completed_at || spec.frontmatter.completed;\n\n if (!createdAt || !completedAt) {\n return null;\n }\n\n const created = dayjs(createdAt);\n const completed = dayjs(completedAt);\n\n return completed.diff(created, 'day', true);\n}\n\n/**\n * Calculate lead time for a specific stage\n */\nexport function calculateLeadTime(\n spec: SpecInfo,\n fromStatus: string,\n toStatus: string\n): number | null {\n const transitions = spec.frontmatter.transitions;\n if (!transitions || !Array.isArray(transitions)) {\n return null;\n }\n\n const fromTransition = transitions.find((t) => t.status === fromStatus);\n const toTransition = transitions.find((t) => t.status === toStatus);\n\n if (!fromTransition || !toTransition) {\n return null;\n }\n\n const from = dayjs(fromTransition.at);\n const to = dayjs(toTransition.at);\n\n return to.diff(from, 'day', true);\n}\n\n/**\n * Calculate throughput (completed specs in a time period)\n */\nexport function calculateThroughput(specs: SpecInfo[], days: number): number {\n const cutoff = dayjs().subtract(days, 'day');\n\n return specs.filter((s) => {\n if (s.frontmatter.status !== 'complete' && s.frontmatter.status !== 'archived') {\n return false;\n }\n\n const completedAt = s.frontmatter.completed_at || s.frontmatter.completed;\n if (!completedAt) {\n return false;\n }\n\n return dayjs(completedAt).isAfter(cutoff);\n }).length;\n}\n\n/**\n * Calculate work in progress at a specific point in time\n */\nexport function calculateWIP(specs: SpecInfo[], date: dayjs.Dayjs = dayjs()): number {\n return specs.filter((s) => {\n const createdAt = s.frontmatter.created_at || s.frontmatter.created;\n const created = dayjs(createdAt);\n\n // Must be created before the target date\n if (created.isAfter(date)) {\n return false;\n }\n\n // Check if completed after the target date (or not completed)\n const completedAt = s.frontmatter.completed_at || s.frontmatter.completed;\n if (completedAt) {\n const completed = dayjs(completedAt);\n return completed.isAfter(date);\n }\n\n // Not completed yet - check if still active\n return s.frontmatter.status !== 'complete' && s.frontmatter.status !== 'archived';\n }).length;\n}\n\n/**\n * Calculate comprehensive velocity metrics\n */\nexport function calculateVelocityMetrics(specs: SpecInfo[]): VelocityMetrics {\n // Calculate cycle times for completed specs\n const cycleTimes = specs\n .map((s) => calculateCycleTime(s))\n .filter((t): t is number => t !== null)\n .sort((a, b) => a - b);\n\n const averageCycleTime = cycleTimes.length > 0\n ? cycleTimes.reduce((sum, t) => sum + t, 0) / cycleTimes.length\n : 0;\n\n const medianCycleTime = cycleTimes.length > 0\n ? cycleTimes.length % 2 === 0\n ? (cycleTimes[cycleTimes.length / 2 - 1] + cycleTimes[cycleTimes.length / 2]) / 2\n : cycleTimes[Math.floor(cycleTimes.length / 2)]\n : 0;\n\n const p90CycleTime = cycleTimes.length > 0\n ? cycleTimes[Math.min(Math.floor(cycleTimes.length * 0.9), cycleTimes.length - 1)]\n : 0;\n\n // Calculate lead times (if transition data available)\n const plannedToInProgressTimes = specs\n .map((s) => calculateLeadTime(s, 'planned', 'in-progress'))\n .filter((t): t is number => t !== null);\n\n const inProgressToCompleteTimes = specs\n .map((s) => calculateLeadTime(s, 'in-progress', 'complete'))\n .filter((t): t is number => t !== null);\n\n const avgPlannedToInProgress = plannedToInProgressTimes.length > 0\n ? plannedToInProgressTimes.reduce((sum, t) => sum + t, 0) / plannedToInProgressTimes.length\n : 0;\n\n const avgInProgressToComplete = inProgressToCompleteTimes.length > 0\n ? inProgressToCompleteTimes.reduce((sum, t) => sum + t, 0) / inProgressToCompleteTimes.length\n : 0;\n\n // Calculate throughput\n const throughputWeek = calculateThroughput(specs, 7);\n const throughputMonth = calculateThroughput(specs, 30);\n \n // Calculate throughput for previous week for trend\n const prevWeekStart = dayjs().subtract(14, 'day');\n const prevWeekEnd = dayjs().subtract(7, 'day');\n const throughputPrevWeek = specs.filter((s) => {\n const completedAt = s.frontmatter.completed_at || s.frontmatter.completed;\n if (!completedAt) return false;\n const completed = dayjs(completedAt);\n return completed.isAfter(prevWeekStart) && !completed.isAfter(prevWeekEnd);\n }).length;\n\n const throughputTrend: 'up' | 'down' | 'stable' =\n throughputWeek > throughputPrevWeek ? 'up' :\n throughputWeek < throughputPrevWeek ? 'down' : 'stable';\n\n // Calculate WIP\n const currentWIP = calculateWIP(specs);\n\n // Calculate average WIP over last 30 days\n const wipSamples: number[] = [];\n for (let i = 0; i < 30; i++) {\n const sampleDate = dayjs().subtract(i, 'day');\n wipSamples.push(calculateWIP(specs, sampleDate));\n }\n const avgWIP = wipSamples.length > 0\n ? wipSamples.reduce((sum, w) => sum + w, 0) / wipSamples.length\n : 0;\n\n return {\n cycleTime: {\n average: Math.round(averageCycleTime * 10) / 10,\n median: Math.round(medianCycleTime * 10) / 10,\n p90: Math.round(p90CycleTime * 10) / 10,\n },\n leadTime: {\n plannedToInProgress: Math.round(avgPlannedToInProgress * 10) / 10,\n inProgressToComplete: Math.round(avgInProgressToComplete * 10) / 10,\n },\n throughput: {\n perWeek: throughputWeek,\n perMonth: throughputMonth,\n trend: throughputTrend,\n },\n wip: {\n current: currentWIP,\n average: Math.round(avgWIP * 10) / 10,\n },\n };\n}\n","import chalk from 'chalk';\nimport dayjs from 'dayjs';\nimport { loadAllSpecs } from '../spec-loader.js';\nimport type { SpecStatus, SpecPriority, SpecFilterOptions } from '../frontmatter.js';\nimport { withSpinner } from '../utils/ui.js';\nimport { autoCheckIfEnabled } from './check.js';\nimport { calculateVelocityMetrics } from '../utils/velocity.js';\nimport { countSpecsByStatusAndPriority } from '../utils/spec-stats.js';\nimport { calculateCompletion, getCompletionStatus } from '../utils/completion.js';\nimport { generateInsights, getSpecInsightDetails } from '../utils/insights.js';\n\nexport async function statsCommand(options: {\n tag?: string;\n assignee?: string;\n full?: boolean;\n timeline?: boolean;\n velocity?: boolean;\n json?: boolean;\n}): Promise<void> {\n // Auto-check for conflicts before stats\n await autoCheckIfEnabled();\n \n // Build filter\n const filter: SpecFilterOptions = {};\n if (options.tag) {\n filter.tags = [options.tag];\n }\n if (options.assignee) {\n filter.assignee = options.assignee;\n }\n\n // Load all specs with spinner (including archived for total count)\n const specs = await withSpinner(\n 'Loading specs...',\n () => loadAllSpecs({\n includeArchived: true,\n filter,\n })\n );\n\n if (specs.length === 0) {\n console.log('No specs found.');\n return;\n }\n\n // Determine what sections to show\n // --full shows everything (like old analytics)\n // --timeline or --velocity shows specific section\n // Default (no flags): show simplified view with insights\n const showFull = options.full || false;\n const showStats = options.full || (!options.timeline && !options.velocity);\n const showTimeline = options.timeline || options.full;\n const showVelocity = options.velocity || options.full;\n const showSimplified = !options.full && !options.timeline && !options.velocity;\n\n // Calculate all metrics upfront\n const { statusCounts, priorityCounts, tagCounts } = countSpecsByStatusAndPriority(specs);\n const velocityMetrics = calculateVelocityMetrics(specs);\n const completionMetrics = calculateCompletion(specs);\n const insights = generateInsights(specs);\n\n // JSON output\n if (options.json) {\n const data = {\n total: specs.length,\n status: statusCounts,\n priority: priorityCounts,\n tags: tagCounts,\n completion: completionMetrics,\n velocity: velocityMetrics,\n insights: insights,\n filter,\n };\n console.log(JSON.stringify(data, null, 2));\n return;\n }\n\n // Display statistics\n console.log(chalk.bold.cyan('📊 Spec Stats'));\n console.log('');\n\n // Filter info\n if (options.tag || options.assignee) {\n const filterParts: string[] = [];\n if (options.tag) filterParts.push(`tag=${options.tag}`);\n if (options.assignee) filterParts.push(`assignee=${options.assignee}`);\n console.log(chalk.dim(`Filtered by: ${filterParts.join(', ')}`));\n console.log('');\n }\n\n // ============================================================\n // SIMPLIFIED VIEW (Default)\n // ============================================================\n if (showSimplified) {\n // Overview with completion rate\n console.log(chalk.bold('📈 Overview'));\n console.log('');\n \n const completionStatus = getCompletionStatus(completionMetrics.score);\n const completionColor = completionStatus.color === 'green' ? chalk.green : \n completionStatus.color === 'yellow' ? chalk.yellow : \n chalk.red;\n \n console.log(` Total Specs ${chalk.cyan(completionMetrics.totalSpecs)}`);\n console.log(` Active (Planned+WIP) ${chalk.yellow(completionMetrics.activeSpecs)}`);\n console.log(` Complete ${chalk.green(completionMetrics.completeSpecs)}`);\n console.log(` Completion Rate ${completionColor(`${completionMetrics.score}% ${completionStatus.emoji}`)}`);\n console.log('');\n\n // Status (simplified)\n console.log(chalk.bold('📊 Status'));\n console.log('');\n \n const labelWidth = 15;\n const barWidth = 20;\n const maxStatusCount = Math.max(...Object.values(statusCounts));\n const createBar = (count: number, maxCount: number, char: string = '█') => {\n const width = Math.round((count / maxCount) * barWidth);\n const filledWidth = Math.min(width, barWidth);\n const emptyWidth = barWidth - filledWidth;\n return char.repeat(filledWidth) + chalk.dim('░').repeat(emptyWidth);\n };\n \n console.log(` 📅 ${'Planned'.padEnd(labelWidth)} ${chalk.cyan(createBar(statusCounts.planned, maxStatusCount))} ${chalk.cyan(statusCounts.planned)}`);\n console.log(` ⏳ ${'In Progress'.padEnd(labelWidth)} ${chalk.yellow(createBar(statusCounts['in-progress'], maxStatusCount))} ${chalk.yellow(statusCounts['in-progress'])}`);\n console.log(` ✅ ${'Complete'.padEnd(labelWidth)} ${chalk.green(createBar(statusCounts.complete, maxStatusCount))} ${chalk.green(statusCounts.complete)}`);\n if (statusCounts.archived > 0) {\n console.log(` 📦 ${'Archived'.padEnd(labelWidth)} ${chalk.dim(createBar(statusCounts.archived, maxStatusCount))} ${chalk.dim(statusCounts.archived)}`);\n }\n console.log('');\n\n // Priority Focus (only critical/high with issues)\n const criticalCount = priorityCounts.critical || 0;\n const highCount = priorityCounts.high || 0;\n \n if (criticalCount > 0 || highCount > 0) {\n console.log(chalk.bold('🎯 Priority Focus'));\n console.log('');\n \n if (criticalCount > 0) {\n const criticalPlanned = specs.filter(s => s.frontmatter.priority === 'critical' && s.frontmatter.status === 'planned').length;\n const criticalInProgress = specs.filter(s => s.frontmatter.priority === 'critical' && s.frontmatter.status === 'in-progress').length;\n const criticalComplete = specs.filter(s => s.frontmatter.priority === 'critical' && s.frontmatter.status === 'complete').length;\n const criticalOverdue = specs.filter(s => \n s.frontmatter.priority === 'critical' && \n s.frontmatter.due && \n dayjs(s.frontmatter.due).isBefore(dayjs(), 'day') &&\n s.frontmatter.status !== 'complete'\n ).length;\n \n const parts = [];\n if (criticalPlanned > 0) parts.push(chalk.dim(`${criticalPlanned} planned`));\n if (criticalInProgress > 0) parts.push(`${criticalInProgress} in-progress`);\n if (criticalComplete > 0) parts.push(chalk.green(`${criticalComplete} complete`));\n if (criticalOverdue > 0) parts.push(chalk.red(`${criticalOverdue} overdue!`));\n \n console.log(` 🔴 Critical ${chalk.red(criticalCount)} specs${parts.length > 0 ? ` (${parts.join(', ')})` : ''}`);\n }\n \n if (highCount > 0) {\n const highPlanned = specs.filter(s => s.frontmatter.priority === 'high' && s.frontmatter.status === 'planned').length;\n const highInProgress = specs.filter(s => s.frontmatter.priority === 'high' && s.frontmatter.status === 'in-progress').length;\n const highComplete = specs.filter(s => s.frontmatter.priority === 'high' && s.frontmatter.status === 'complete').length;\n const highOverdue = specs.filter(s => \n s.frontmatter.priority === 'high' && \n s.frontmatter.due && \n dayjs(s.frontmatter.due).isBefore(dayjs(), 'day') &&\n s.frontmatter.status !== 'complete'\n ).length;\n \n const parts = [];\n if (highPlanned > 0) parts.push(chalk.dim(`${highPlanned} planned`));\n if (highInProgress > 0) parts.push(`${highInProgress} in-progress`);\n if (highComplete > 0) parts.push(chalk.green(`${highComplete} complete`));\n if (highOverdue > 0) parts.push(chalk.yellow(`${highOverdue} overdue`));\n \n console.log(` 🟠 High ${chalk.hex('#FFA500')(highCount)} specs${parts.length > 0 ? ` (${parts.join(', ')})` : ''}`);\n }\n \n console.log('');\n }\n\n // Needs Attention (insights)\n if (insights.length > 0) {\n console.log(chalk.bold.yellow('⚠️ Needs Attention'));\n console.log('');\n \n for (const insight of insights) {\n const color = insight.severity === 'critical' ? chalk.red :\n insight.severity === 'warning' ? chalk.yellow :\n chalk.cyan;\n \n console.log(` ${color('•')} ${insight.message}`);\n \n // Show up to 3 spec examples\n for (const specPath of insight.specs.slice(0, 3)) {\n const spec = specs.find(s => s.path === specPath);\n const details = spec ? getSpecInsightDetails(spec) : null;\n console.log(` ${chalk.dim(specPath)}${details ? chalk.dim(` (${details})`) : ''}`);\n }\n \n if (insight.specs.length > 3) {\n console.log(` ${chalk.dim(`...and ${insight.specs.length - 3} more`)}`);\n }\n }\n \n console.log('');\n } else if (completionMetrics.activeSpecs === 0 && completionMetrics.completeSpecs > 0) {\n // Celebrate completion!\n console.log(chalk.bold.green('🎉 All Specs Complete!'));\n console.log('');\n console.log(` ${chalk.dim('Great work! All active specs are complete.')}`);\n console.log('');\n } else if (completionMetrics.activeSpecs > 0) {\n // Positive message\n console.log(chalk.bold.green('✨ All Clear!'));\n console.log('');\n console.log(` ${chalk.dim('No critical issues detected. Keep up the good work!')}`);\n console.log('');\n }\n\n // Velocity Summary\n console.log(chalk.bold('🚀 Velocity Summary'));\n console.log('');\n \n const cycleTimeStatus = velocityMetrics.cycleTime.average <= 7 ? chalk.green('✓') : chalk.yellow('⚠');\n const throughputTrend = velocityMetrics.throughput.trend === 'up' ? chalk.green('↑') : \n velocityMetrics.throughput.trend === 'down' ? chalk.red('↓') : \n chalk.yellow('→');\n \n console.log(` Avg Cycle Time ${chalk.cyan(velocityMetrics.cycleTime.average.toFixed(1))} days ${cycleTimeStatus}${velocityMetrics.cycleTime.average <= 7 ? chalk.dim(' (target: 7d)') : ''}`);\n console.log(` Throughput ${chalk.cyan((velocityMetrics.throughput.perWeek / 7 * 7).toFixed(1))}/week ${throughputTrend}`);\n console.log(` WIP ${chalk.yellow(velocityMetrics.wip.current)} specs`);\n console.log('');\n\n // Prompt for full view\n console.log(chalk.dim('💡 Use `lean-spec stats --full` for detailed analytics'));\n console.log(chalk.dim(' Use `lean-spec stats --velocity` for velocity breakdown'));\n console.log(chalk.dim(' Use `lean-spec stats --timeline` for activity timeline'));\n console.log('');\n \n return;\n }\n\n // ============================================================\n // FULL VIEW (--full or specific flags)\n // ============================================================\n // Common layout constants\n const labelWidth = 20;\n const barWidth = 20;\n const valueWidth = 5;\n\n // Helper to create bars\n const createBar = (count: number, maxCount: number, char: string = '━') => {\n const width = Math.round((count / maxCount) * barWidth);\n return char.repeat(width);\n };\n\n // ============================================================\n // STATS SECTION\n // ============================================================\n if (showStats) {\n // Overview\n const totalWithPriority = Object.values(priorityCounts).reduce(\n (sum, count) => sum + count,\n 0\n );\n console.log(chalk.bold('📈 Overview'));\n console.log('');\n\n console.log(\n ` ${'Metric'.padEnd(labelWidth)} ${'Value'.padStart(valueWidth)}`\n );\n console.log(\n ` ${chalk.dim('─'.repeat(labelWidth))} ${chalk.dim('─'.repeat(valueWidth))}`\n );\n console.log(\n ` ${'Total Specs'.padEnd(labelWidth)} ${chalk.green(specs.length.toString().padStart(valueWidth))}`\n );\n console.log(\n ` ${'With Priority'.padEnd(labelWidth)} ${chalk.cyan(totalWithPriority.toString().padStart(valueWidth))}`\n );\n console.log(\n ` ${'Unique Tags'.padEnd(labelWidth)} ${chalk.magenta(Object.keys(tagCounts).length.toString().padStart(valueWidth))}`\n );\n console.log('');\n\n // Status Distribution\n console.log(chalk.bold('📊 Status Distribution'));\n console.log('');\n\n const maxStatusCount = Math.max(...Object.values(statusCounts));\n const colWidth = barWidth + 3;\n\n console.log(\n ` ${'Status'.padEnd(labelWidth)} ${chalk.cyan('Count'.padEnd(colWidth))}`\n );\n console.log(\n ` ${chalk.dim('─'.repeat(labelWidth))} ${chalk.dim('─'.repeat(colWidth))}`\n );\n console.log(\n ` 📋 ${'Planned'.padEnd(labelWidth - 3)} ${chalk.cyan(createBar(statusCounts.planned, maxStatusCount).padEnd(barWidth))}${chalk.cyan(statusCounts.planned.toString().padStart(3))}`\n );\n console.log(\n ` ⏳ ${'In Progress'.padEnd(labelWidth - 3)} ${chalk.yellow(createBar(statusCounts['in-progress'], maxStatusCount).padEnd(barWidth))}${chalk.yellow(statusCounts['in-progress'].toString().padStart(3))}`\n );\n console.log(\n ` ✅ ${'Complete'.padEnd(labelWidth - 3)} ${chalk.green(createBar(statusCounts.complete, maxStatusCount).padEnd(barWidth))}${chalk.green(statusCounts.complete.toString().padStart(3))}`\n );\n console.log(\n ` 📦 ${'Archived'.padEnd(labelWidth - 3)} ${chalk.dim(createBar(statusCounts.archived, maxStatusCount).padEnd(barWidth))}${chalk.dim(statusCounts.archived.toString().padStart(3))}`\n );\n console.log('');\n\n // Priority Breakdown\n if (totalWithPriority > 0) {\n console.log(chalk.bold('🎯 Priority Breakdown'));\n console.log('');\n\n const maxPriorityCount = Math.max(\n ...Object.values(priorityCounts).filter((c) => c > 0)\n );\n\n console.log(\n ` ${'Priority'.padEnd(labelWidth)} ${chalk.cyan('Count'.padEnd(colWidth))}`\n );\n console.log(\n ` ${chalk.dim('─'.repeat(labelWidth))} ${chalk.dim('─'.repeat(colWidth))}`\n );\n\n if (priorityCounts.critical > 0) {\n console.log(\n ` 🔴 ${'Critical'.padEnd(labelWidth - 3)} ${chalk.red(createBar(priorityCounts.critical, maxPriorityCount).padEnd(barWidth))}${chalk.red(priorityCounts.critical.toString().padStart(3))}`\n );\n }\n if (priorityCounts.high > 0) {\n console.log(\n ` 🟠 ${'High'.padEnd(labelWidth - 3)} ${chalk.hex('#FFA500')(createBar(priorityCounts.high, maxPriorityCount).padEnd(barWidth))}${chalk.hex('#FFA500')(priorityCounts.high.toString().padStart(3))}`\n );\n }\n if (priorityCounts.medium > 0) {\n console.log(\n ` 🟡 ${'Medium'.padEnd(labelWidth - 3)} ${chalk.yellow(createBar(priorityCounts.medium, maxPriorityCount).padEnd(barWidth))}${chalk.yellow(priorityCounts.medium.toString().padStart(3))}`\n );\n }\n if (priorityCounts.low > 0) {\n console.log(\n ` 🟢 ${'Low'.padEnd(labelWidth - 3)} ${chalk.green(createBar(priorityCounts.low, maxPriorityCount).padEnd(barWidth))}${chalk.green(priorityCounts.low.toString().padStart(3))}`\n );\n }\n console.log('');\n }\n\n // Top Tags\n const topTags = Object.entries(tagCounts)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 5);\n\n if (topTags.length > 0) {\n console.log(chalk.bold('🏷️ Popular Tags'));\n console.log('');\n\n const maxTagCount = Math.max(...topTags.map(([, count]) => count));\n\n console.log(\n ` ${'Tag'.padEnd(labelWidth)} ${chalk.magenta('Count'.padEnd(colWidth))}`\n );\n console.log(\n ` ${chalk.dim('─'.repeat(labelWidth))} ${chalk.dim('─'.repeat(colWidth))}`\n );\n\n for (const [tag, count] of topTags) {\n const truncatedTag =\n tag.length > labelWidth ? tag.substring(0, labelWidth - 1) + '…' : tag;\n const bar = createBar(count, maxTagCount);\n console.log(\n ` ${truncatedTag.padEnd(labelWidth)} ${chalk.magenta(bar.padEnd(barWidth))}${chalk.magenta(count.toString().padStart(3))}`\n );\n }\n console.log('');\n }\n }\n\n // ============================================================\n // TIMELINE SECTION\n // ============================================================\n if (showTimeline) {\n const days = 30;\n const today = dayjs();\n const startDate = today.subtract(days, 'day');\n\n // Count specs by date\n const createdByDate: Record<string, number> = {};\n const completedByDate: Record<string, number> = {};\n\n for (const spec of specs) {\n const created = dayjs(spec.frontmatter.created);\n\n // Count created specs within date range\n if (created.isAfter(startDate)) {\n const dateKey = created.format('YYYY-MM-DD');\n createdByDate[dateKey] = (createdByDate[dateKey] || 0) + 1;\n }\n\n // Count completed specs\n if (spec.frontmatter.completed) {\n const completed = dayjs(spec.frontmatter.completed);\n if (completed.isAfter(startDate)) {\n const dateKey = completed.format('YYYY-MM-DD');\n completedByDate[dateKey] = (completedByDate[dateKey] || 0) + 1;\n }\n }\n }\n\n // Display timeline\n const allDates = new Set([\n ...Object.keys(createdByDate),\n ...Object.keys(completedByDate),\n ]);\n const sortedDates = Array.from(allDates).sort();\n\n if (sortedDates.length > 0) {\n console.log(chalk.bold(`📅 Activity (Last ${days} Days)`));\n console.log('');\n\n const colWidth = barWidth + 3;\n\n console.log(\n ` ${'Date'.padEnd(15)} ${chalk.cyan('Created'.padEnd(colWidth))} ${chalk.green('Completed'.padEnd(colWidth))}`\n );\n console.log(\n ` ${chalk.dim('─'.repeat(15))} ${chalk.dim('─'.repeat(colWidth))} ${chalk.dim('─'.repeat(colWidth))}`\n );\n\n const maxCount = Math.max(\n ...Object.values(createdByDate),\n ...Object.values(completedByDate)\n );\n\n // Show only last 10 days with activity\n for (const date of sortedDates.slice(-10)) {\n const created = createdByDate[date] || 0;\n const completed = completedByDate[date] || 0;\n\n const createdBar = createBar(created, maxCount, '━');\n const completedBar = createBar(completed, maxCount, '━');\n\n const createdCol = `${createdBar.padEnd(barWidth)}${created.toString().padStart(3)}`;\n const completedCol = `${completedBar.padEnd(barWidth)}${completed.toString().padStart(3)}`;\n\n console.log(\n ` ${chalk.dim(date.padEnd(15))} ${chalk.cyan(createdCol)} ${chalk.green(completedCol)}`\n );\n }\n console.log('');\n }\n }\n\n // ============================================================\n // VELOCITY SECTION\n // ============================================================\n if (showVelocity) {\n console.log(chalk.bold('🚀 Velocity Metrics'));\n console.log('');\n\n // Cycle Time\n console.log(chalk.bold('⏱️ Cycle Time (Created → Completed)'));\n console.log('');\n console.log(\n ` ${'Metric'.padEnd(labelWidth)} ${'Days'.padStart(valueWidth)}`\n );\n console.log(\n ` ${chalk.dim('─'.repeat(labelWidth))} ${chalk.dim('─'.repeat(valueWidth))}`\n );\n console.log(\n ` ${'Average'.padEnd(labelWidth)} ${chalk.cyan(velocityMetrics.cycleTime.average.toFixed(1).padStart(valueWidth))}`\n );\n console.log(\n ` ${'Median'.padEnd(labelWidth)} ${chalk.cyan(velocityMetrics.cycleTime.median.toFixed(1).padStart(valueWidth))}`\n );\n console.log(\n ` ${'90th Percentile'.padEnd(labelWidth)} ${chalk.yellow(velocityMetrics.cycleTime.p90.toFixed(1).padStart(valueWidth))}`\n );\n console.log('');\n\n // Throughput\n console.log(chalk.bold('📦 Throughput'));\n console.log('');\n console.log(\n ` ${'Period'.padEnd(labelWidth)} ${'Specs'.padStart(valueWidth)}`\n );\n console.log(\n ` ${chalk.dim('─'.repeat(labelWidth))} ${chalk.dim('─'.repeat(valueWidth))}`\n );\n console.log(\n ` ${'Last 7 days'.padEnd(labelWidth)} ${chalk.green(velocityMetrics.throughput.perWeek.toString().padStart(valueWidth))}`\n );\n console.log(\n ` ${'Last 30 days'.padEnd(labelWidth)} ${chalk.green(velocityMetrics.throughput.perMonth.toString().padStart(valueWidth))}`\n );\n\n const trendColor =\n velocityMetrics.throughput.trend === 'up'\n ? chalk.green\n : velocityMetrics.throughput.trend === 'down'\n ? chalk.red\n : chalk.yellow;\n const trendSymbol =\n velocityMetrics.throughput.trend === 'up'\n ? '↑'\n : velocityMetrics.throughput.trend === 'down'\n ? '↓'\n : '→';\n console.log(\n ` ${'Trend'.padEnd(labelWidth)} ${trendColor(trendSymbol + ' ' + velocityMetrics.throughput.trend.padStart(valueWidth - 2))}`\n );\n console.log('');\n\n // WIP\n console.log(chalk.bold('🔄 Work In Progress'));\n console.log('');\n console.log(\n ` ${'Metric'.padEnd(labelWidth)} ${'Specs'.padStart(valueWidth)}`\n );\n console.log(\n ` ${chalk.dim('─'.repeat(labelWidth))} ${chalk.dim('─'.repeat(valueWidth))}`\n );\n console.log(\n ` ${'Current'.padEnd(labelWidth)} ${chalk.yellow(velocityMetrics.wip.current.toString().padStart(valueWidth))}`\n );\n console.log(\n ` ${'30-day Average'.padEnd(labelWidth)} ${chalk.cyan(velocityMetrics.wip.average.toFixed(1).padStart(valueWidth))}`\n );\n console.log('');\n\n // Lead Time (if available)\n if (\n velocityMetrics.leadTime.plannedToInProgress > 0 ||\n velocityMetrics.leadTime.inProgressToComplete > 0\n ) {\n console.log(chalk.bold('🔀 Lead Time by Stage'));\n console.log('');\n console.log(\n ` ${'Stage'.padEnd(labelWidth)} ${'Days'.padStart(valueWidth)}`\n );\n console.log(\n ` ${chalk.dim('─'.repeat(labelWidth))} ${chalk.dim('─'.repeat(valueWidth))}`\n );\n if (velocityMetrics.leadTime.plannedToInProgress > 0) {\n console.log(\n ` ${'Planned → In Progress'.padEnd(labelWidth)} ${chalk.cyan(velocityMetrics.leadTime.plannedToInProgress.toFixed(1).padStart(valueWidth))}`\n );\n }\n if (velocityMetrics.leadTime.inProgressToComplete > 0) {\n console.log(\n ` ${'In Progress → Complete'.padEnd(labelWidth)} ${chalk.green(velocityMetrics.leadTime.inProgressToComplete.toFixed(1).padStart(valueWidth))}`\n );\n }\n console.log('');\n }\n }\n}\n","import type { SpecInfo } from '../spec-loader.js';\nimport type { SpecStatus, SpecPriority } from '../frontmatter.js';\n\n/**\n * Count specs by status and priority\n * Shared utility to avoid duplication between analytics and dashboard\n */\nexport function countSpecsByStatusAndPriority(specs: SpecInfo[]): {\n statusCounts: Record<SpecStatus, number>;\n priorityCounts: Record<SpecPriority, number>;\n tagCounts: Record<string, number>;\n} {\n const statusCounts: Record<SpecStatus, number> = {\n planned: 0,\n 'in-progress': 0,\n complete: 0,\n archived: 0,\n };\n\n const priorityCounts: Record<SpecPriority, number> = {\n low: 0,\n medium: 0,\n high: 0,\n critical: 0,\n };\n\n const tagCounts: Record<string, number> = {};\n\n for (const spec of specs) {\n // Specs in archived/ folder should be counted as archived, regardless of frontmatter status\n const isInArchivedFolder = spec.path.startsWith('archived/');\n const status = isInArchivedFolder ? 'archived' : spec.frontmatter.status;\n \n if (status && status in statusCounts) {\n statusCounts[status]++;\n }\n\n const priority = spec.frontmatter.priority;\n if (priority && priority in priorityCounts) {\n priorityCounts[priority]++;\n }\n\n if (spec.frontmatter.tags) {\n for (const tag of spec.frontmatter.tags) {\n tagCounts[tag] = (tagCounts[tag] || 0) + 1;\n }\n }\n }\n\n return { statusCounts, priorityCounts, tagCounts };\n}\n","import dayjs from 'dayjs';\nimport type { SpecInfo } from '../spec-loader.js';\n\nexport interface Insight {\n severity: 'critical' | 'warning' | 'info';\n message: string;\n specs: string[];\n}\n\n/**\n * Generate smart insights for specs that need attention\n * Returns top 5 most important insights\n */\nexport function generateInsights(specs: SpecInfo[]): Insight[] {\n const insights: Insight[] = [];\n \n // 1. Critical overdue specs\n const criticalOverdue = specs.filter(s => \n s.frontmatter.priority === 'critical' &&\n s.frontmatter.due && \n dayjs(s.frontmatter.due).isBefore(dayjs(), 'day') &&\n s.frontmatter.status !== 'complete' &&\n s.frontmatter.status !== 'archived'\n );\n \n if (criticalOverdue.length > 0) {\n insights.push({\n severity: 'critical',\n message: `${criticalOverdue.length} critical spec${criticalOverdue.length > 1 ? 's' : ''} overdue`,\n specs: criticalOverdue.map(s => s.path),\n });\n }\n \n // 2. High priority overdue specs\n const highOverdue = specs.filter(s => \n s.frontmatter.priority === 'high' &&\n s.frontmatter.due && \n dayjs(s.frontmatter.due).isBefore(dayjs(), 'day') &&\n s.frontmatter.status !== 'complete' &&\n s.frontmatter.status !== 'archived'\n );\n \n if (highOverdue.length > 0) {\n insights.push({\n severity: 'warning',\n message: `${highOverdue.length} high priority spec${highOverdue.length > 1 ? 's' : ''} overdue`,\n specs: highOverdue.map(s => s.path),\n });\n }\n \n // 3. Long-running WIP (in-progress > 7 days)\n const longRunning = specs.filter(s => {\n if (s.frontmatter.status !== 'in-progress') {\n return false;\n }\n \n const updatedAt = s.frontmatter.updated || s.frontmatter.updated_at || s.frontmatter.created || s.frontmatter.created_at;\n \n if (!updatedAt) {\n return false;\n }\n \n const daysSinceUpdate = dayjs().diff(dayjs(updatedAt), 'day');\n return daysSinceUpdate > 7;\n });\n \n if (longRunning.length > 0) {\n insights.push({\n severity: 'warning',\n message: `${longRunning.length} spec${longRunning.length > 1 ? 's' : ''} in-progress > 7 days`,\n specs: longRunning.map(s => s.path),\n });\n }\n \n // 4. Critical specs not started\n const criticalNotStarted = specs.filter(s =>\n s.frontmatter.priority === 'critical' &&\n s.frontmatter.status === 'planned'\n );\n \n if (criticalNotStarted.length > 0) {\n insights.push({\n severity: 'warning',\n message: `${criticalNotStarted.length} critical spec${criticalNotStarted.length > 1 ? 's' : ''} not started`,\n specs: criticalNotStarted.map(s => s.path),\n });\n }\n \n // 5. High priority specs not started (if we have room)\n const highNotStarted = specs.filter(s =>\n s.frontmatter.priority === 'high' &&\n s.frontmatter.status === 'planned'\n );\n \n if (highNotStarted.length > 0 && insights.length < 5) {\n insights.push({\n severity: 'info',\n message: `${highNotStarted.length} high priority spec${highNotStarted.length > 1 ? 's' : ''} not started`,\n specs: highNotStarted.map(s => s.path),\n });\n }\n \n // Return top 5 insights\n return insights.slice(0, 5);\n}\n\n/**\n * Get detailed insight for a specific spec (with days overdue, etc.)\n */\nexport function getSpecInsightDetails(spec: SpecInfo): string | null {\n // Check if overdue\n if (spec.frontmatter.due && \n dayjs(spec.frontmatter.due).isBefore(dayjs(), 'day') &&\n spec.frontmatter.status !== 'complete' &&\n spec.frontmatter.status !== 'archived') {\n const daysOverdue = dayjs().diff(dayjs(spec.frontmatter.due), 'day');\n return `overdue by ${daysOverdue} day${daysOverdue > 1 ? 's' : ''}`;\n }\n \n // Check if long-running\n if (spec.frontmatter.status === 'in-progress') {\n const updatedAt = spec.frontmatter.updated || spec.frontmatter.updated_at || spec.frontmatter.created || spec.frontmatter.created_at;\n \n if (updatedAt) {\n const daysSinceUpdate = dayjs().diff(dayjs(updatedAt), 'day');\n if (daysSinceUpdate > 7) {\n return `in-progress for ${daysSinceUpdate} days`;\n }\n }\n }\n \n return null;\n}\n","import React from 'react';\nimport { render } from 'ink';\nimport chalk from 'chalk';\nimport { loadAllSpecs } from '../spec-loader.js';\nimport type { SpecStatus, SpecPriority, SpecFilterOptions } from '../frontmatter.js';\nimport { withSpinner } from '../utils/ui.js';\nimport { autoCheckIfEnabled } from './check.js';\nimport { sanitizeUserInput } from '../utils/ui.js';\n\nexport async function searchCommand(query: string, options: {\n status?: SpecStatus;\n tag?: string;\n priority?: SpecPriority;\n assignee?: string;\n customFields?: Record<string, unknown>;\n}): Promise<void> {\n // Auto-check for conflicts before search\n await autoCheckIfEnabled();\n \n // Build filter\n const filter: SpecFilterOptions = {};\n if (options.status) filter.status = options.status;\n if (options.tag) filter.tags = [options.tag];\n if (options.priority) filter.priority = options.priority;\n if (options.assignee) filter.assignee = options.assignee;\n if (options.customFields) filter.customFields = options.customFields;\n\n // Load all specs with content and spinner\n const specs = await withSpinner(\n 'Searching specs...',\n () => loadAllSpecs({\n includeArchived: true,\n includeContent: true,\n filter,\n })\n );\n\n if (specs.length === 0) {\n console.log('No specs found matching filters.');\n return;\n }\n\n // Search for query in content\n const results: Array<{\n spec: typeof specs[0];\n matches: string[];\n }> = [];\n\n const queryLower = query.toLowerCase();\n\n for (const spec of specs) {\n if (!spec.content) continue;\n\n const matches: string[] = [];\n \n // Search in content\n const lines = spec.content.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line.toLowerCase().includes(queryLower)) {\n // Get context: current line with some surrounding context\n const contextStart = Math.max(0, i - 1);\n const contextEnd = Math.min(lines.length - 1, i + 1);\n const context = lines.slice(contextStart, contextEnd + 1);\n \n // Highlight the matching line\n const matchLine = context[i - contextStart];\n const highlighted = highlightMatch(matchLine, query);\n \n matches.push(highlighted);\n }\n }\n\n if (matches.length > 0) {\n results.push({ spec, matches });\n }\n }\n\n // Display results\n if (results.length === 0) {\n console.log('');\n console.log(chalk.yellow(`🔍 No specs found matching \"${sanitizeUserInput(query)}\"`));\n \n // Show active filters\n if (Object.keys(filter).length > 0) {\n const filters: string[] = [];\n if (options.status) filters.push(`status=${sanitizeUserInput(options.status)}`);\n if (options.tag) filters.push(`tag=${sanitizeUserInput(options.tag)}`);\n if (options.priority) filters.push(`priority=${sanitizeUserInput(options.priority)}`);\n if (options.assignee) filters.push(`assignee=${sanitizeUserInput(options.assignee)}`);\n console.log(chalk.gray(`With filters: ${filters.join(', ')}`));\n }\n console.log('');\n return;\n }\n\n // Show summary header\n console.log('');\n console.log(chalk.green(`🔍 Found ${results.length} spec${results.length === 1 ? '' : 's'} matching \"${sanitizeUserInput(query)}\"`));\n \n // Show active filters\n if (Object.keys(filter).length > 0) {\n const filters: string[] = [];\n if (options.status) filters.push(`status=${sanitizeUserInput(options.status)}`);\n if (options.tag) filters.push(`tag=${sanitizeUserInput(options.tag)}`);\n if (options.priority) filters.push(`priority=${sanitizeUserInput(options.priority)}`);\n if (options.assignee) filters.push(`assignee=${sanitizeUserInput(options.assignee)}`);\n console.log(chalk.gray(`With filters: ${filters.join(', ')}`));\n }\n console.log('');\n\n // Display each result with matches\n for (const result of results) {\n const { spec, matches } = result;\n \n // Spec header\n console.log(chalk.cyan(`${spec.frontmatter.status === 'in-progress' ? '🔨' : spec.frontmatter.status === 'complete' ? '✅' : '📅'} ${sanitizeUserInput(spec.path)}`));\n \n // Metadata\n const meta: string[] = [];\n if (spec.frontmatter.priority) {\n const priorityEmoji = spec.frontmatter.priority === 'critical' ? '🔴' : \n spec.frontmatter.priority === 'high' ? '🟡' :\n spec.frontmatter.priority === 'medium' ? '🟠' : '🟢';\n meta.push(`${priorityEmoji} ${sanitizeUserInput(spec.frontmatter.priority)}`);\n }\n if (spec.frontmatter.tags && spec.frontmatter.tags.length > 0) {\n meta.push(`[${spec.frontmatter.tags.map(tag => sanitizeUserInput(tag)).join(', ')}]`);\n }\n if (meta.length > 0) {\n console.log(chalk.gray(` ${meta.join(' • ')}`));\n }\n \n // Show first few matches (limit to 3 per spec)\n const maxMatches = 3;\n for (let i = 0; i < Math.min(matches.length, maxMatches); i++) {\n console.log(` ${chalk.gray('Match:')} ${matches[i].trim()}`);\n }\n \n if (matches.length > maxMatches) {\n console.log(chalk.gray(` ... and ${matches.length - maxMatches} more match${matches.length - maxMatches === 1 ? '' : 'es'}`));\n }\n \n console.log('');\n }\n}\n\nfunction highlightMatch(text: string, query: string): string {\n const regex = new RegExp(`(${escapeRegex(query)})`, 'gi');\n return text.replace(regex, chalk.yellow('$1'));\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","import chalk from 'chalk';\nimport { getSpec, loadAllSpecs, type SpecInfo } from '../spec-loader.js';\nimport { autoCheckIfEnabled } from './check.js';\nimport { sanitizeUserInput } from '../utils/ui.js';\nimport { resolveSpecPath } from '../utils/path-helpers.js';\nimport { loadConfig } from '../config.js';\nimport * as path from 'node:path';\nimport { getStatusIndicator } from '../utils/colors.js';\n\nexport async function depsCommand(specPath: string, options: {\n depth?: number;\n graph?: boolean;\n json?: boolean;\n}): Promise<void> {\n // Auto-check for conflicts before display\n await autoCheckIfEnabled();\n \n // Resolve spec path (handles numbers like \"14\" or \"014\")\n const config = await loadConfig();\n const cwd = process.cwd();\n const specsDir = path.join(cwd, config.specsDir);\n const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);\n \n if (!resolvedPath) {\n throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}`);\n }\n \n const spec = await getSpec(resolvedPath);\n \n if (!spec) {\n throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}`);\n }\n\n // Load all specs to resolve dependencies\n const allSpecs = await loadAllSpecs({ includeArchived: true });\n const specMap = new Map<string, SpecInfo>();\n for (const s of allSpecs) {\n specMap.set(s.path, s);\n }\n\n // Find dependencies\n const dependsOn = findDependencies(spec, specMap);\n const blocks = findBlocking(spec, allSpecs);\n \n // Find related specs bidirectionally (merge both directions)\n const relatedSpecs = findAllRelated(spec, specMap, allSpecs);\n\n // Output as JSON if requested\n if (options.json) {\n const data = {\n spec: spec.path,\n dependsOn: dependsOn.map(s => ({ path: s.path, status: s.frontmatter.status })),\n blocks: blocks.map(s => ({ path: s.path, status: s.frontmatter.status })),\n related: relatedSpecs.map(s => ({ path: s.path, status: s.frontmatter.status })),\n chain: buildDependencyChain(spec, specMap, options.depth || 3),\n };\n console.log(JSON.stringify(data, null, 2));\n return;\n }\n\n // Display dependencies\n console.log('');\n console.log(chalk.green(`📦 Dependencies for ${chalk.cyan(sanitizeUserInput(spec.path))}`));\n console.log('');\n\n // Check if there are any relationships at all\n const hasAnyRelationships = dependsOn.length > 0 || blocks.length > 0 || relatedSpecs.length > 0;\n \n if (!hasAnyRelationships) {\n console.log(chalk.gray(' No dependencies or relationships'));\n console.log('');\n return;\n }\n\n // Depends On section\n if (dependsOn.length > 0) {\n console.log(chalk.bold('Depends On:'));\n for (const dep of dependsOn) {\n const status = getStatusIndicator(dep.frontmatter.status);\n console.log(` → ${sanitizeUserInput(dep.path)} ${status}`);\n }\n console.log('');\n }\n\n // Required By section\n if (blocks.length > 0) {\n console.log(chalk.bold('Required By:'));\n for (const blocked of blocks) {\n const status = getStatusIndicator(blocked.frontmatter.status);\n console.log(` ← ${sanitizeUserInput(blocked.path)} ${status}`);\n }\n console.log('');\n }\n\n // Related Specs section (bidirectional)\n if (relatedSpecs.length > 0) {\n console.log(chalk.bold('Related Specs:'));\n for (const rel of relatedSpecs) {\n const status = getStatusIndicator(rel.frontmatter.status);\n console.log(` ⟷ ${sanitizeUserInput(rel.path)} ${status}`);\n }\n console.log('');\n }\n\n // Dependency chain (tree view)\n if (options.graph || dependsOn.length > 0) {\n console.log(chalk.bold('Dependency Chain:'));\n const chain = buildDependencyChain(spec, specMap, options.depth || 3);\n displayChain(chain, 0);\n console.log('');\n }\n}\n\ninterface DependencyNode {\n spec: SpecInfo;\n dependencies: DependencyNode[];\n}\n\nfunction findDependencies(spec: SpecInfo, specMap: Map<string, SpecInfo>): SpecInfo[] {\n if (!spec.frontmatter.depends_on) return [];\n \n const deps: SpecInfo[] = [];\n for (const depPath of spec.frontmatter.depends_on) {\n const dep = specMap.get(depPath);\n if (dep) {\n deps.push(dep);\n } else {\n // Try to find by name only (in case of relative path)\n for (const [path, s] of specMap.entries()) {\n if (path.includes(depPath)) {\n deps.push(s);\n break;\n }\n }\n }\n }\n \n return deps;\n}\n\nfunction findBlocking(spec: SpecInfo, allSpecs: SpecInfo[]): SpecInfo[] {\n const blocks: SpecInfo[] = [];\n \n for (const other of allSpecs) {\n if (other.path === spec.path) continue;\n \n if (other.frontmatter.depends_on) {\n for (const depPath of other.frontmatter.depends_on) {\n if (depPath === spec.path || spec.path.includes(depPath)) {\n blocks.push(other);\n break;\n }\n }\n }\n }\n \n return blocks;\n}\n\nfunction findRelated(spec: SpecInfo, specMap: Map<string, SpecInfo>): SpecInfo[] {\n if (!spec.frontmatter.related) return [];\n \n const related: SpecInfo[] = [];\n for (const relPath of spec.frontmatter.related) {\n const rel = specMap.get(relPath);\n if (rel) {\n related.push(rel);\n } else {\n // Try to find by name only\n for (const [path, s] of specMap.entries()) {\n if (path.includes(relPath)) {\n related.push(s);\n break;\n }\n }\n }\n }\n \n return related;\n}\n\nfunction findRelatedBy(spec: SpecInfo, allSpecs: SpecInfo[]): SpecInfo[] {\n const relatedBy: SpecInfo[] = [];\n \n for (const other of allSpecs) {\n if (other.path === spec.path) continue;\n \n if (other.frontmatter.related) {\n for (const relPath of other.frontmatter.related) {\n if (relPath === spec.path || spec.path.includes(relPath)) {\n relatedBy.push(other);\n break;\n }\n }\n }\n }\n \n return relatedBy;\n}\n\n/**\n * Find all related specs bidirectionally - combines specs that this spec\n * relates to AND specs that relate to this spec, deduplicated.\n */\nfunction findAllRelated(\n spec: SpecInfo, \n specMap: Map<string, SpecInfo>, \n allSpecs: SpecInfo[]\n): SpecInfo[] {\n const outgoing = findRelated(spec, specMap);\n const incoming = findRelatedBy(spec, allSpecs);\n \n // Merge and deduplicate by path\n const seenPaths = new Set<string>();\n const merged: SpecInfo[] = [];\n \n for (const s of [...outgoing, ...incoming]) {\n if (!seenPaths.has(s.path)) {\n seenPaths.add(s.path);\n merged.push(s);\n }\n }\n \n return merged;\n}\n\nfunction buildDependencyChain(\n spec: SpecInfo,\n specMap: Map<string, SpecInfo>,\n maxDepth: number,\n currentDepth: number = 0,\n visited: Set<string> = new Set()\n): DependencyNode {\n const node: DependencyNode = {\n spec,\n dependencies: [],\n };\n \n // Prevent infinite loops\n if (visited.has(spec.path)) {\n return node;\n }\n visited.add(spec.path);\n \n // Stop at max depth\n if (currentDepth >= maxDepth) {\n return node;\n }\n \n // Find dependencies\n const deps = findDependencies(spec, specMap);\n for (const dep of deps) {\n node.dependencies.push(buildDependencyChain(dep, specMap, maxDepth, currentDepth + 1, visited));\n }\n \n return node;\n}\n\nfunction displayChain(node: DependencyNode, level: number): void {\n const indent = ' '.repeat(level);\n const status = getStatusIndicator(node.spec.frontmatter.status);\n const name = level === 0 ? chalk.cyan(node.spec.path) : node.spec.path;\n \n console.log(`${indent}${name} ${status}`);\n \n for (const dep of node.dependencies) {\n const prefix = ' '.repeat(level) + '└─ ';\n const depStatus = getStatusIndicator(dep.spec.frontmatter.status);\n console.log(`${prefix}${dep.spec.path} ${depStatus}`);\n \n // Recursively display nested dependencies with increased indent\n for (const nestedDep of dep.dependencies) {\n displayChain(nestedDep, level + 2);\n }\n }\n}\n","import chalk from 'chalk';\nimport dayjs from 'dayjs';\nimport { loadAllSpecs } from '../spec-loader.js';\nimport type { SpecFilterOptions } from '../frontmatter.js';\nimport { autoCheckIfEnabled } from './check.js';\n\nexport async function timelineCommand(options: {\n days?: number;\n byTag?: boolean;\n byAssignee?: boolean;\n}): Promise<void> {\n // Auto-check for conflicts before display\n await autoCheckIfEnabled();\n \n // Helper to create bars\n const createBar = (count: number, maxCount: number, width: number, char: string = '━') => {\n const barLen = Math.round((count / maxCount) * width);\n return char.repeat(barLen);\n };\n \n const days = options.days || 30;\n \n // Load all specs (including archived for completion history)\n const specs = await loadAllSpecs({\n includeArchived: true,\n });\n\n if (specs.length === 0) {\n console.log('No specs found.');\n return;\n }\n\n // Calculate date range\n const today = dayjs();\n const startDate = today.subtract(days, 'day');\n\n // Count specs by date\n const createdByDate: Record<string, number> = {};\n const completedByDate: Record<string, number> = {};\n const createdByMonth: Record<string, number> = {};\n\n for (const spec of specs) {\n const created = dayjs(spec.frontmatter.created);\n \n // Count created specs within date range\n if (created.isAfter(startDate)) {\n const dateKey = created.format('YYYY-MM-DD');\n createdByDate[dateKey] = (createdByDate[dateKey] || 0) + 1;\n }\n\n // Count by month for all time\n const monthKey = created.format('MMM YYYY');\n createdByMonth[monthKey] = (createdByMonth[monthKey] || 0) + 1;\n\n // Count completed specs\n if (spec.frontmatter.completed) {\n const completed = dayjs(spec.frontmatter.completed);\n if (completed.isAfter(startDate)) {\n const dateKey = completed.format('YYYY-MM-DD');\n completedByDate[dateKey] = (completedByDate[dateKey] || 0) + 1;\n }\n }\n }\n\n // Display timeline\n console.log(chalk.bold.cyan('📈 Spec Timeline'));\n console.log('');\n\n // Show daily activity (only days with activity)\n const allDates = new Set([...Object.keys(createdByDate), ...Object.keys(completedByDate)]);\n const sortedDates = Array.from(allDates).sort();\n\n if (sortedDates.length > 0) {\n console.log(chalk.bold(`📅 Activity (Last ${days} Days)`));\n console.log('');\n \n // Column headers - aligned with stats.ts\n const labelWidth = 15;\n const barWidth = 20;\n const specsWidth = 3;\n const colWidth = barWidth + specsWidth;\n \n console.log(` ${'Date'.padEnd(labelWidth)} ${chalk.cyan('Created'.padEnd(colWidth))} ${chalk.green('Completed'.padEnd(colWidth))}`);\n console.log(` ${chalk.dim('─'.repeat(labelWidth))} ${chalk.dim('─'.repeat(colWidth))} ${chalk.dim('─'.repeat(colWidth))}`);\n \n const maxCount = Math.max(...Object.values(createdByDate), ...Object.values(completedByDate));\n \n for (const date of sortedDates) {\n const created = createdByDate[date] || 0;\n const completed = completedByDate[date] || 0;\n \n const createdBar = createBar(created, maxCount, barWidth);\n const completedBar = createBar(completed, maxCount, barWidth);\n \n const createdCol = `${createdBar.padEnd(barWidth)}${created.toString().padStart(specsWidth)}`;\n const completedCol = `${completedBar.padEnd(barWidth)}${completed.toString().padStart(specsWidth)}`;\n \n console.log(` ${chalk.dim(date.padEnd(labelWidth))} ${chalk.cyan(createdCol)} ${chalk.green(completedCol)}`);\n }\n console.log('');\n }\n\n // Show creation by month (all time)\n const sortedMonths = Object.entries(createdByMonth)\n .sort((a, b) => {\n const dateA = dayjs(a[0], 'MMM YYYY');\n const dateB = dayjs(b[0], 'MMM YYYY');\n return dateB.diff(dateA);\n })\n .slice(0, 6); // Last 6 months\n\n if (sortedMonths.length > 0) {\n console.log(chalk.bold('📊 Monthly Overview'));\n console.log('');\n \n // Aligned with stats.ts\n const labelWidth = 15;\n const barWidth = 20;\n const specsWidth = 3;\n const colWidth = barWidth + specsWidth;\n \n console.log(` ${'Month'.padEnd(labelWidth)} ${chalk.magenta('Specs'.padEnd(colWidth))}`);\n console.log(` ${chalk.dim('─'.repeat(labelWidth))} ${chalk.dim('─'.repeat(colWidth))}`);\n \n const maxCount = Math.max(...sortedMonths.map(([, count]) => count));\n for (const [month, count] of sortedMonths) {\n const bar = createBar(count, maxCount, barWidth);\n console.log(` ${month.padEnd(labelWidth)} ${chalk.magenta(bar.padEnd(barWidth))}${chalk.magenta(count.toString().padStart(specsWidth))}`);\n }\n console.log('');\n }\n\n // Completion rate\n const last7Days = specs.filter(s => {\n if (!s.frontmatter.completed) return false;\n const completed = dayjs(s.frontmatter.completed);\n return completed.isAfter(today.subtract(7, 'day'));\n }).length;\n\n const last30Days = specs.filter(s => {\n if (!s.frontmatter.completed) return false;\n const completed = dayjs(s.frontmatter.completed);\n return completed.isAfter(today.subtract(30, 'day'));\n }).length;\n\n console.log(chalk.bold('✅ Completion Rate'));\n console.log('');\n \n // Aligned with stats.ts\n const labelWidth = 15;\n const valueWidth = 5;\n \n console.log(` ${'Period'.padEnd(labelWidth)} ${'Specs'.padStart(valueWidth)}`);\n console.log(` ${chalk.dim('─'.repeat(labelWidth))} ${chalk.dim('─'.repeat(valueWidth))}`);\n console.log(` ${'Last 7 days'.padEnd(labelWidth)} ${chalk.green(last7Days.toString().padStart(valueWidth))}`);\n console.log(` ${'Last 30 days'.padEnd(labelWidth)} ${chalk.green(last30Days.toString().padStart(valueWidth))}`);\n console.log('');\n\n // By tag breakdown (if requested)\n if (options.byTag) {\n const tagStats: Record<string, { created: number; completed: number }> = {};\n \n for (const spec of specs) {\n const created = dayjs(spec.frontmatter.created);\n const isInRange = created.isAfter(startDate);\n \n if (isInRange && spec.frontmatter.tags) {\n for (const tag of spec.frontmatter.tags) {\n if (!tagStats[tag]) tagStats[tag] = { created: 0, completed: 0 };\n tagStats[tag].created++;\n \n if (spec.frontmatter.completed) {\n const completed = dayjs(spec.frontmatter.completed);\n if (completed.isAfter(startDate)) {\n tagStats[tag].completed++;\n }\n }\n }\n }\n }\n \n const sortedTags = Object.entries(tagStats)\n .sort((a, b) => b[1].created - a[1].created)\n .slice(0, 10);\n \n if (sortedTags.length > 0) {\n console.log(chalk.bold('🏷️ By Tag'));\n for (const [tag, stats] of sortedTags) {\n console.log(` ${chalk.dim('#')}${tag.padEnd(20)} ${chalk.cyan(stats.created)} created · ${chalk.green(stats.completed)} completed`);\n }\n console.log('');\n }\n }\n\n // By assignee breakdown (if requested)\n if (options.byAssignee) {\n const assigneeStats: Record<string, { created: number; completed: number }> = {};\n \n for (const spec of specs) {\n if (!spec.frontmatter.assignee) continue;\n \n const created = dayjs(spec.frontmatter.created);\n const isInRange = created.isAfter(startDate);\n \n if (isInRange) {\n const assignee = spec.frontmatter.assignee;\n if (!assigneeStats[assignee]) assigneeStats[assignee] = { created: 0, completed: 0 };\n assigneeStats[assignee].created++;\n \n if (spec.frontmatter.completed) {\n const completed = dayjs(spec.frontmatter.completed);\n if (completed.isAfter(startDate)) {\n assigneeStats[assignee].completed++;\n }\n }\n }\n }\n \n const sortedAssignees = Object.entries(assigneeStats)\n .sort((a, b) => b[1].created - a[1].created);\n \n if (sortedAssignees.length > 0) {\n console.log(chalk.bold('👤 By Assignee'));\n for (const [assignee, stats] of sortedAssignees) {\n console.log(` ${chalk.dim('@')}${assignee.padEnd(20)} ${chalk.cyan(stats.created)} created · ${chalk.green(stats.completed)} completed`);\n }\n console.log('');\n }\n }\n}\n","import chalk from 'chalk';\nimport dayjs from 'dayjs';\nimport { loadAllSpecs } from '../spec-loader.js';\nimport type { SpecInfo } from '../spec-loader.js';\nimport type { SpecStatus, SpecPriority } from '../frontmatter.js';\nimport { withSpinner } from '../utils/ui.js';\nimport { autoCheckIfEnabled } from './check.js';\n\n// Column width constants (aligned with stats.ts and timeline.ts)\nconst SPEC_COLUMN_WIDTH = 43; // Includes status emoji + 1 space + spec name\nconst COLUMN_SEPARATOR = ' '; // 2 spaces between columns\nconst SPEC_INDENT = ' '; // 2 spaces for spec indentation within priority groups\n\n// Timeline bar characters\nconst FILLED_BAR_CHAR = '█';\nconst EMPTY_BAR_CHAR = '░';\n\nconst STATUS_CONFIG: Record<SpecStatus, { emoji: string; color: string }> = {\n planned: { emoji: '📅', color: 'gray' },\n 'in-progress': { emoji: '⏳', color: 'yellow' },\n complete: { emoji: '✅', color: 'green' },\n archived: { emoji: '📦', color: 'gray' },\n};\n\nconst PRIORITY_CONFIG: Record<SpecPriority, { emoji: string; label: string; colorFn: (s: string) => string }> = {\n critical: { emoji: '🔴', label: 'CRITICAL', colorFn: chalk.red },\n high: { emoji: '🟠', label: 'HIGH', colorFn: chalk.hex('#FFA500') },\n medium: { emoji: '🟡', label: 'MEDIUM', colorFn: chalk.yellow },\n low: { emoji: '🟢', label: 'LOW', colorFn: chalk.green },\n};\n\nexport async function ganttCommand(options: {\n weeks?: number;\n showComplete?: boolean;\n criticalPath?: boolean;\n}): Promise<void> {\n // Auto-check for conflicts before display\n await autoCheckIfEnabled();\n \n const weeks = options.weeks || 4;\n const timelineColumnWidth = weeks * 8; // 8 chars per week\n \n // Load all specs with spinner\n const specs = await withSpinner(\n 'Loading specs...',\n () => loadAllSpecs({\n includeArchived: false,\n })\n );\n\n if (specs.length === 0) {\n console.log('No specs found.');\n return;\n }\n\n // Filter relevant specs\n const relevantSpecs = specs.filter(spec => {\n // Hide completed specs unless explicitly requested\n if (!options.showComplete && spec.frontmatter.status === 'complete') {\n return false;\n }\n // Show all non-archived specs (planned, in-progress, complete with flag)\n return spec.frontmatter.status !== 'archived';\n });\n\n if (relevantSpecs.length === 0) {\n console.log(chalk.dim('No active specs found.'));\n console.log(chalk.dim('Tip: Use --show-complete to include completed specs.'));\n return;\n }\n\n // Group specs by priority\n const groupedSpecs: Record<SpecPriority, SpecInfo[]> = {\n critical: [],\n high: [],\n medium: [],\n low: [],\n };\n \n const noPrioritySpecs: SpecInfo[] = [];\n \n for (const spec of relevantSpecs) {\n if (spec.frontmatter.priority && spec.frontmatter.priority in groupedSpecs) {\n groupedSpecs[spec.frontmatter.priority].push(spec);\n } else {\n noPrioritySpecs.push(spec);\n }\n }\n \n // Sort specs within each group by status (in-progress first), then by due date\n const sortSpecs = (specs: SpecInfo[]) => {\n return [...specs].sort((a, b) => {\n const statusOrder = { 'in-progress': 0, 'planned': 1, 'complete': 2 };\n const aOrder = statusOrder[a.frontmatter.status as keyof typeof statusOrder] ?? 3;\n const bOrder = statusOrder[b.frontmatter.status as keyof typeof statusOrder] ?? 3;\n \n if (aOrder !== bOrder) return aOrder - bOrder;\n \n if (a.frontmatter.due && !b.frontmatter.due) return -1;\n if (!a.frontmatter.due && b.frontmatter.due) return 1;\n if (a.frontmatter.due && b.frontmatter.due) {\n return dayjs(a.frontmatter.due).diff(dayjs(b.frontmatter.due));\n }\n \n return 0;\n });\n };\n\n // Calculate date range (start from today)\n const today = dayjs();\n const startDate = today.startOf('week');\n const endDate = startDate.add(weeks, 'week');\n\n // Calculate stats\n const inProgress = relevantSpecs.filter(s => s.frontmatter.status === 'in-progress').length;\n const planned = relevantSpecs.filter(s => s.frontmatter.status === 'planned').length;\n const overdue = relevantSpecs.filter(s => \n s.frontmatter.due && \n dayjs(s.frontmatter.due).isBefore(today) && \n s.frontmatter.status !== 'complete'\n ).length;\n\n // Display header\n console.log(chalk.bold.cyan(`📅 Gantt Chart (${weeks} weeks from ${startDate.format('MMM D, YYYY')})`));\n console.log('');\n\n // Column headers\n const specHeader = 'Spec'.padEnd(SPEC_COLUMN_WIDTH);\n const timelineHeader = 'Timeline';\n console.log(specHeader + COLUMN_SEPARATOR + timelineHeader);\n \n // Calendar dates in timeline header (right-aligned to column)\n const calendarDates: string[] = [];\n for (let i = 0; i < weeks; i++) {\n const date = startDate.add(i, 'week');\n const dateStr = date.format('MMM D').padEnd(8);\n calendarDates.push(dateStr);\n }\n const dateRow = ' '.repeat(SPEC_COLUMN_WIDTH) + COLUMN_SEPARATOR + calendarDates.join('');\n console.log(chalk.dim(dateRow));\n \n // Separator line\n const specSeparator = '─'.repeat(SPEC_COLUMN_WIDTH);\n const timelineSeparator = '─'.repeat(timelineColumnWidth);\n console.log(chalk.dim(specSeparator + COLUMN_SEPARATOR + timelineSeparator));\n \n // Today marker (aligned to current week)\n const todayWeekOffset = today.diff(startDate, 'week');\n const todayMarkerPos = todayWeekOffset * 8;\n let todayMarker = ' '.repeat(SPEC_COLUMN_WIDTH) + COLUMN_SEPARATOR;\n if (todayMarkerPos >= 0 && todayMarkerPos < timelineColumnWidth) {\n todayMarker += ' '.repeat(todayMarkerPos) + '│ Today';\n }\n console.log(chalk.dim(todayMarker));\n console.log('');\n\n // Display priority groups\n const priorities: SpecPriority[] = ['critical', 'high', 'medium', 'low'];\n \n for (const priority of priorities) {\n const specsInGroup = sortSpecs(groupedSpecs[priority]);\n \n // Skip empty priority groups\n if (specsInGroup.length === 0) {\n continue;\n }\n \n const config = PRIORITY_CONFIG[priority];\n \n // Show priority header with count\n console.log(config.colorFn(`${config.emoji} ${config.label} (${specsInGroup.length})`));\n \n // Display specs in this priority group\n for (const spec of specsInGroup) {\n renderSpecRow(spec, startDate, endDate, weeks, today);\n }\n \n console.log('');\n }\n\n // Summary\n const summaryParts: string[] = [];\n if (inProgress > 0) summaryParts.push(`${inProgress} in-progress`);\n if (planned > 0) summaryParts.push(`${planned} planned`);\n if (overdue > 0) summaryParts.push(chalk.red(`${overdue} overdue`));\n \n console.log(chalk.bold('Summary: ') + summaryParts.join(' · '));\n console.log(chalk.dim('💡 Tip: Add \"due: YYYY-MM-DD\" to frontmatter for timeline planning'));\n}\n\nfunction renderSpecRow(\n spec: SpecInfo,\n startDate: dayjs.Dayjs,\n endDate: dayjs.Dayjs,\n weeks: number,\n today: dayjs.Dayjs\n): void {\n const statusConfig = STATUS_CONFIG[spec.frontmatter.status];\n const timelineColumnWidth = weeks * 8;\n \n // Format spec name with status emoji\n // Format: {emoji} {spec-name} (must be exactly SPEC_COLUMN_WIDTH chars)\n const emoji = statusConfig.emoji;\n const maxNameLength = SPEC_COLUMN_WIDTH - 2; // 2 chars for emoji + space\n let specName = spec.name; // Use spec.name instead of spec.path\n \n // Truncate name if too long\n if (specName.length > maxNameLength) {\n specName = specName.substring(0, maxNameLength - 1) + '…';\n }\n \n const specColumn = `${SPEC_INDENT}${emoji} ${specName}`.padEnd(SPEC_COLUMN_WIDTH);\n \n // Build timeline column\n let timelineColumn: string;\n \n if (!spec.frontmatter.due) {\n // No due date set\n timelineColumn = chalk.dim('(no due date set)');\n } else {\n // Render timeline bar\n timelineColumn = renderTimelineBar(spec, startDate, endDate, weeks, today);\n }\n \n console.log(specColumn + COLUMN_SEPARATOR + timelineColumn);\n}\n\nfunction renderTimelineBar(\n spec: SpecInfo,\n startDate: dayjs.Dayjs,\n endDate: dayjs.Dayjs,\n weeks: number,\n today: dayjs.Dayjs\n): string {\n const charsPerWeek = 8;\n const totalChars = weeks * charsPerWeek;\n \n const due = dayjs(spec.frontmatter.due!);\n const specStart = today; // Start from today, not creation date\n \n // Calculate bar position\n const startDaysFromStart = specStart.diff(startDate, 'day');\n const dueDaysFromStart = due.diff(startDate, 'day');\n \n const startPos = Math.max(0, Math.floor((startDaysFromStart / 7) * charsPerWeek));\n const duePos = Math.floor((dueDaysFromStart / 7) * charsPerWeek);\n \n // Clamp to visible range\n const barStart = Math.max(0, startPos);\n const barEnd = Math.min(totalChars, Math.max(barStart, duePos));\n const barLength = Math.max(0, barEnd - barStart);\n \n // Build bar string\n let result = '';\n \n // Leading space\n if (barStart > 0) {\n result += ' '.repeat(barStart);\n }\n \n // Bar content based on status\n if (spec.frontmatter.status === 'complete') {\n result += chalk.green(FILLED_BAR_CHAR.repeat(barLength));\n } else if (spec.frontmatter.status === 'in-progress') {\n // Half-filled bar\n const halfLength = Math.floor(barLength / 2);\n result += chalk.yellow(FILLED_BAR_CHAR.repeat(halfLength));\n result += chalk.dim(EMPTY_BAR_CHAR.repeat(barLength - halfLength));\n } else {\n // Planned - light shade bar\n result += chalk.dim(EMPTY_BAR_CHAR.repeat(barLength));\n }\n \n // Trailing space\n const trailingSpace = totalChars - barEnd;\n if (trailingSpace > 0) {\n result += ' '.repeat(trailingSpace);\n }\n \n return result;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport chalk from 'chalk';\nimport { marked } from 'marked';\nimport { markedTerminal } from 'marked-terminal';\nimport { loadConfig } from '../config.js';\nimport { resolveSpecPath } from '../utils/path-helpers.js';\nimport { getSpecFile, parseFrontmatter } from '../frontmatter.js';\nimport type { SpecFrontmatter } from '../frontmatter.js';\nimport { spawn } from 'node:child_process';\n\n// Configure marked for terminal output\nmarked.use(markedTerminal() as Parameters<typeof marked.use>[0]);\n\ninterface SpecContent {\n frontmatter: SpecFrontmatter;\n content: string;\n rawContent: string;\n path: string;\n name: string;\n}\n\n/**\n * Read and parse a spec by path/name/number\n * Supports sub-spec files like: \"045/DESIGN.md\" or \"045-dashboard/TESTING.md\"\n */\nexport async function readSpecContent(\n specPath: string,\n cwd: string = process.cwd()\n): Promise<SpecContent | null> {\n const config = await loadConfig(cwd);\n const specsDir = path.join(cwd, config.specsDir);\n\n // Check if specPath includes a sub-file (e.g., \"045/DESIGN.md\" or \"045-dashboard/TESTING.md\")\n let resolvedPath: string | null = null;\n let targetFile: string | null = null;\n \n // Split path to check for sub-file\n const pathParts = specPath.split('/').filter(p => p);\n \n if (pathParts.length > 1 && pathParts[pathParts.length - 1].endsWith('.md')) {\n // Last part looks like a file, try to resolve the directory\n const specPart = pathParts.slice(0, -1).join('/');\n const filePart = pathParts[pathParts.length - 1];\n \n resolvedPath = await resolveSpecPath(specPart, cwd, specsDir);\n if (resolvedPath) {\n targetFile = path.join(resolvedPath, filePart);\n \n // Verify the sub-file exists\n try {\n await fs.access(targetFile);\n } catch {\n // Sub-file doesn't exist\n return null;\n }\n }\n }\n \n // If no sub-file detected or resolution failed, try normal spec resolution\n if (!resolvedPath) {\n resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);\n \n if (!resolvedPath) {\n return null;\n }\n\n // Get the default spec file (README.md)\n targetFile = await getSpecFile(resolvedPath, config.structure.defaultFile);\n \n if (!targetFile) {\n return null;\n }\n }\n\n // Ensure targetFile is not null before proceeding\n if (!targetFile) {\n return null;\n }\n\n // Read file content\n const rawContent = await fs.readFile(targetFile, 'utf-8');\n const fileName = path.basename(targetFile);\n const isSubSpec = fileName !== config.structure.defaultFile;\n\n // Parse frontmatter (only exists in main spec file)\n let frontmatter: SpecFrontmatter | null = null;\n \n if (!isSubSpec) {\n frontmatter = await parseFrontmatter(targetFile, config);\n if (!frontmatter) {\n return null;\n }\n } else {\n // Sub-spec files don't have frontmatter, load from main spec\n const mainSpecFile = await getSpecFile(resolvedPath, config.structure.defaultFile);\n if (mainSpecFile) {\n frontmatter = await parseFrontmatter(mainSpecFile, config);\n }\n \n // If we still can't get frontmatter, create a minimal one\n if (!frontmatter) {\n frontmatter = {\n status: 'planned',\n created: new Date().toISOString().split('T')[0],\n };\n }\n }\n\n // Extract content without frontmatter (if present)\n const lines = rawContent.split('\\n');\n let contentStartIndex = 0;\n \n // Skip frontmatter if present (only in main spec)\n if (!isSubSpec && lines[0] === '---') {\n const closingIndex = lines.findIndex((line, i) => i > 0 && line === '---');\n if (closingIndex > 0) {\n contentStartIndex = closingIndex + 1;\n }\n }\n \n const content = lines.slice(contentStartIndex).join('\\n').trim();\n const specName = path.basename(resolvedPath);\n const displayName = isSubSpec ? `${specName}/${fileName}` : specName;\n\n return {\n frontmatter,\n content,\n rawContent,\n path: resolvedPath,\n name: displayName,\n };\n}\n\n/**\n * Format frontmatter for display\n */\nfunction formatFrontmatter(frontmatter: SpecFrontmatter): string {\n const lines: string[] = [];\n \n // Status with emoji\n const statusEmojis = {\n planned: '📅',\n 'in-progress': '🔨',\n complete: '✅',\n blocked: '🚫',\n cancelled: '❌',\n archived: '📦',\n };\n const statusEmoji = statusEmojis[frontmatter.status] || '📄';\n lines.push(chalk.bold(`${statusEmoji} Status: `) + chalk.cyan(frontmatter.status));\n\n // Priority with emoji\n if (frontmatter.priority) {\n const priorityEmojis = {\n low: '🟢',\n medium: '🟠',\n high: '🟡',\n critical: '🔴',\n };\n const priorityEmoji = priorityEmojis[frontmatter.priority] || '';\n lines.push(chalk.bold(`${priorityEmoji} Priority: `) + chalk.yellow(frontmatter.priority));\n }\n\n // Created date\n if (frontmatter.created) {\n lines.push(chalk.bold('📆 Created: ') + chalk.gray(String(frontmatter.created)));\n }\n\n // Tags\n if (frontmatter.tags && frontmatter.tags.length > 0) {\n const tagStr = frontmatter.tags.map(tag => chalk.blue(`#${tag}`)).join(' ');\n lines.push(chalk.bold('🏷️ Tags: ') + tagStr);\n }\n\n // Assignee\n if (frontmatter.assignee) {\n lines.push(chalk.bold('👤 Assignee: ') + chalk.green(frontmatter.assignee));\n }\n\n // Custom fields\n const standardFields = ['status', 'priority', 'created', 'tags', 'assignee'];\n const customFields = Object.entries(frontmatter)\n .filter(([key]) => !standardFields.includes(key))\n .filter(([_, value]) => value !== undefined && value !== null);\n\n if (customFields.length > 0) {\n lines.push('');\n lines.push(chalk.bold('Custom Fields:'));\n for (const [key, value] of customFields) {\n lines.push(` ${chalk.gray(key)}: ${chalk.white(String(value))}`);\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Display spec with formatted output\n */\nfunction displayFormattedSpec(spec: SpecContent): string {\n const output: string[] = [];\n \n // Header\n output.push('');\n output.push(chalk.bold.cyan(`━━━ ${spec.name} ━━━`));\n output.push('');\n \n // Frontmatter\n output.push(formatFrontmatter(spec.frontmatter));\n output.push('');\n output.push(chalk.gray('─'.repeat(60)));\n output.push('');\n \n return output.join('\\n');\n}\n\n/**\n * lean-spec view <spec-name>\n * Display spec with rendered markdown, or output raw/json\n */\nexport async function viewCommand(\n specPath: string,\n options: {\n raw?: boolean;\n json?: boolean;\n noColor?: boolean;\n } = {}\n): Promise<void> {\n const spec = await readSpecContent(specPath, process.cwd());\n \n if (!spec) {\n throw new Error(`Spec not found: ${specPath}. Try: lean-spec list`);\n }\n\n // Handle JSON output\n if (options.json) {\n const jsonOutput = {\n name: spec.name,\n path: spec.path,\n frontmatter: spec.frontmatter,\n content: spec.content,\n };\n console.log(JSON.stringify(jsonOutput, null, 2));\n return;\n }\n\n // Handle raw markdown output\n if (options.raw) {\n console.log(spec.rawContent);\n return;\n }\n\n // Default: Display formatted header and frontmatter\n console.log(displayFormattedSpec(spec));\n \n // Render markdown content\n const rendered = await marked(spec.content);\n console.log(rendered);\n}\n\n/**\n * lean-spec open <spec-name>\n * Open spec in editor\n */\nexport async function openCommand(\n specPath: string,\n options: {\n editor?: string;\n } = {}\n): Promise<void> {\n const cwd = process.cwd();\n const config = await loadConfig(cwd);\n const specsDir = path.join(cwd, config.specsDir);\n\n // Check if specPath includes a sub-file\n let resolvedPath: string | null = null;\n let targetFile: string | null = null;\n \n const pathParts = specPath.split('/').filter(p => p);\n \n if (pathParts.length > 1 && pathParts[pathParts.length - 1].endsWith('.md')) {\n // Last part looks like a file\n const specPart = pathParts.slice(0, -1).join('/');\n const filePart = pathParts[pathParts.length - 1];\n \n resolvedPath = await resolveSpecPath(specPart, cwd, specsDir);\n if (resolvedPath) {\n targetFile = path.join(resolvedPath, filePart);\n \n // Verify the sub-file exists\n try {\n await fs.access(targetFile);\n } catch {\n targetFile = null;\n }\n }\n }\n \n // If no sub-file detected, use default file\n if (!resolvedPath) {\n resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);\n \n if (!resolvedPath) {\n throw new Error(`Spec not found: ${specPath}`);\n }\n\n targetFile = await getSpecFile(resolvedPath, config.structure.defaultFile);\n \n if (!targetFile) {\n throw new Error(`Spec file not found in: ${resolvedPath}`);\n }\n } else if (!targetFile) {\n throw new Error(`Sub-spec file not found: ${specPath}`);\n }\n \n const specFile = targetFile;\n\n // Determine editor\n let editor = options.editor;\n \n if (!editor) {\n // Check environment variables\n editor = process.env.VISUAL || process.env.EDITOR;\n }\n\n if (!editor) {\n // Fall back to system defaults\n const platform = process.platform;\n if (platform === 'darwin') {\n editor = 'open';\n } else if (platform === 'win32') {\n editor = 'start';\n } else {\n editor = 'xdg-open';\n }\n }\n\n console.log(chalk.gray(`Opening ${targetFile} with ${editor}...`));\n\n // Spawn editor process - wrap in promise to handle errors properly\n const child = spawn(editor, [targetFile], {\n stdio: 'inherit',\n shell: true,\n });\n\n // Don't wait for editor to close for GUI editors\n const guiEditors = ['open', 'start', 'xdg-open', 'code', 'atom', 'subl'];\n const editorCommand = editor.trim().split(' ')[0];\n if (editorCommand && guiEditors.includes(editorCommand)) {\n // For GUI editors, handle spawn errors but don't wait for close\n return new Promise<void>((resolve, reject) => {\n child.on('error', (error) => {\n reject(new Error(`Error opening editor: ${error.message}`));\n });\n // Resolve immediately after spawn for GUI editors\n child.unref();\n resolve();\n });\n } else {\n // Wait for terminal editors\n return new Promise<void>((resolve, reject) => {\n child.on('error', (error) => {\n reject(new Error(`Error opening editor: ${error.message}`));\n });\n child.on('close', (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`Editor exited with code ${code}`));\n }\n });\n });\n }\n}\n\n","/**\n * MCP Server Command\n * \n * Starts the LeanSpec MCP (Model Context Protocol) server for integration\n * with AI assistants like Claude Desktop, Cline, and other MCP clients.\n */\n\nimport { createMcpServer } from '../mcp-server.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\n\nexport async function mcpCommand(): Promise<void> {\n try {\n const server = await createMcpServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n \n // Log to stderr so it doesn't interfere with MCP protocol on stdout\n console.error('LeanSpec MCP Server started successfully');\n } catch (error) {\n console.error('Failed to start LeanSpec MCP Server:', error);\n process.exit(1);\n }\n}\n"],"mappings":"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","names":["StdioServerTransport","fs","path","stat","aDate","bDate","fs","path","chalk","fs","path","result","fs","path","path","chalk","chalk","chalk","chalk","fs","path","chalk","chalk","chalk","fs","path","chalk","chalk","path","chalk","chalk","path","execSync","fs","path","chalk","chalk","stat","fs","path","chalk","fs","path","chalk","getProjectName","__dirname","chalk","projectName","getProjectName","fs","path","chalk","chalk","fs","path","chalk","matter","yaml","matter","path","chalk","chalk","errorCount","warningCount","chalk","fs","path","execSync","chalk","dayjs","chalk","stripAnsi","chalk","dayjs","dayjs","chalk","labelWidth","barWidth","createBar","dayjs","chalk","chalk","chalk","path","chalk","path","chalk","dayjs","dayjs","chalk","labelWidth","chalk","dayjs","STATUS_CONFIG","PRIORITY_CONFIG","chalk","specs","dayjs","fs","path","chalk","chalk","resolve"]}
|