@halecraft/verify 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -0
- package/README.md +314 -0
- package/bin/verify.mjs +176 -0
- package/dist/index.d.ts +532 -0
- package/dist/index.js +1796 -0
- package/dist/index.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/discovery.ts","../src/init/detect.ts","../src/init/generate.ts","../src/init/prompts.ts","../src/init/write.ts","../src/init/index.ts","../src/parsers/biome.ts","../src/parsers/generic.ts","../src/parsers/gotest.ts","../src/parsers/tsc.ts","../src/parsers/vitest.ts","../src/parsers/index.ts","../src/spinner.ts","../src/reporter.ts","../src/runner.ts","../src/index.ts"],"sourcesContent":["import { existsSync } from \"node:fs\"\nimport { join, resolve } from \"node:path\"\nimport { pathToFileURL } from \"node:url\"\nimport type { VerificationNode, VerifyConfig, VerifyOptions } from \"./types.js\"\n\n/**\n * Helper function for defining config with type inference\n */\nexport function defineConfig(config: VerifyConfig): VerifyConfig {\n return config\n}\n\n/**\n * Helper function for defining a single verification task\n */\nexport function defineTask(task: VerificationNode): VerificationNode {\n return task\n}\n\n/**\n * Config file names to search for (in order of priority)\n */\nconst CONFIG_FILES = [\n \"verify.config.ts\",\n \"verify.config.mts\",\n \"verify.config.js\",\n \"verify.config.mjs\",\n]\n\n/**\n * Find config file in directory\n */\nexport function findConfigFile(cwd: string): string | null {\n for (const filename of CONFIG_FILES) {\n const filepath = join(cwd, filename)\n if (existsSync(filepath)) {\n return filepath\n }\n }\n return null\n}\n\n/**\n * Load config from file\n */\nexport async function loadConfig(\n configPath: string,\n): Promise<VerifyConfig | null> {\n const absolutePath = resolve(configPath)\n\n if (!existsSync(absolutePath)) {\n return null\n }\n\n // Use dynamic import with file URL for cross-platform compatibility\n const fileUrl = pathToFileURL(absolutePath).href\n const module = (await import(fileUrl)) as { default?: VerifyConfig }\n\n if (!module.default) {\n throw new Error(`Config file ${configPath} must have a default export`)\n }\n\n return module.default\n}\n\n/**\n * Load config from cwd or specified path\n */\nexport async function loadConfigFromCwd(\n cwd: string,\n configPath?: string,\n): Promise<VerifyConfig | null> {\n if (configPath) {\n return loadConfig(configPath)\n }\n\n const foundPath = findConfigFile(cwd)\n if (!foundPath) {\n return null\n }\n\n return loadConfig(foundPath)\n}\n\n/**\n * Helper type that requires all keys to be present but preserves original value types.\n * This is used to ensure mergeOptions handles all VerifyOptions properties.\n */\ntype AllKeys<T> = { [K in keyof Required<T>]: T[K] }\n\n/**\n * Merge options with defaults.\n *\n * NOTE: The `satisfies AllKeys<VerifyOptions>` ensures this function handles\n * all properties of VerifyOptions. If you add a new option to VerifyOptions,\n * TypeScript will error here until you add it to the return object.\n */\nexport function mergeOptions(\n configOptions?: VerifyOptions,\n cliOptions?: Partial<VerifyOptions>,\n): VerifyOptions {\n return {\n logs: cliOptions?.logs ?? configOptions?.logs ?? \"failed\",\n format: cliOptions?.format ?? configOptions?.format ?? \"human\",\n filter: cliOptions?.filter ?? configOptions?.filter,\n cwd: cliOptions?.cwd ?? configOptions?.cwd ?? process.cwd(),\n noColor: cliOptions?.noColor ?? configOptions?.noColor ?? false,\n topLevelOnly:\n cliOptions?.topLevelOnly ?? configOptions?.topLevelOnly ?? false,\n noTty: cliOptions?.noTty ?? configOptions?.noTty ?? false,\n } satisfies AllKeys<VerifyOptions>\n}\n","import { existsSync, readdirSync, statSync } from \"node:fs\"\nimport { join, relative } from \"node:path\"\nimport { findConfigFile, loadConfig } from \"./config.js\"\nimport type { PackageDiscoveryOptions, VerifyConfig } from \"./types.js\"\n\n/**\n * Discovered package with its config\n */\nexport interface DiscoveredPackage {\n /** Package name from package.json */\n name: string\n /** Relative path from root */\n path: string\n /** Absolute path */\n absolutePath: string\n /** Loaded verify config (if exists) */\n config: VerifyConfig | null\n}\n\n/**\n * Default glob patterns for package discovery\n */\nconst DEFAULT_PATTERNS = [\"packages/*\", \"apps/*\"]\n\n/**\n * Find directories matching patterns\n */\nfunction findMatchingDirs(rootDir: string, patterns: string[]): string[] {\n const results: string[] = []\n\n for (const pattern of patterns) {\n // Handle simple patterns like \"packages/*\"\n if (pattern.endsWith(\"/*\")) {\n const parentDir = pattern.slice(0, -2)\n const parentPath = join(rootDir, parentDir)\n\n if (existsSync(parentPath) && statSync(parentPath).isDirectory()) {\n const entries = readdirSync(parentPath)\n for (const entry of entries) {\n const entryPath = join(parentPath, entry)\n if (statSync(entryPath).isDirectory()) {\n results.push(entryPath)\n }\n }\n }\n } else {\n // Direct path\n const dirPath = join(rootDir, pattern)\n if (existsSync(dirPath) && statSync(dirPath).isDirectory()) {\n results.push(dirPath)\n }\n }\n }\n\n return results\n}\n\n/**\n * Read package name from package.json\n */\nfunction getPackageName(packageDir: string): string | null {\n const packageJsonPath = join(packageDir, \"package.json\")\n if (!existsSync(packageJsonPath)) {\n return null\n }\n\n try {\n const content = require(packageJsonPath) as { name?: string }\n return content.name ?? null\n } catch {\n return null\n }\n}\n\n/**\n * Discover packages in a monorepo\n */\nexport async function discoverPackages(\n rootDir: string,\n options: PackageDiscoveryOptions = {},\n): Promise<DiscoveredPackage[]> {\n const patterns = options.patterns ?? DEFAULT_PATTERNS\n const matchingDirs = findMatchingDirs(rootDir, patterns)\n\n const packages: DiscoveredPackage[] = []\n\n for (const dir of matchingDirs) {\n const name = getPackageName(dir)\n if (!name) continue // Skip directories without package.json\n\n // Check filter\n if (options.filter && options.filter.length > 0) {\n const matches = options.filter.some(\n f =>\n name === f || name.includes(f) || relative(rootDir, dir).includes(f),\n )\n if (!matches) continue\n }\n\n // Try to load verify config\n const configPath = findConfigFile(dir)\n const config = configPath ? await loadConfig(configPath) : null\n\n packages.push({\n name,\n path: relative(rootDir, dir),\n absolutePath: dir,\n config,\n })\n }\n\n return packages\n}\n\n/**\n * Check if a package has changed (git-aware)\n * This is a placeholder - full implementation would use git diff\n */\nexport async function hasPackageChanged(\n _packagePath: string,\n _baseBranch = \"main\",\n): Promise<boolean> {\n // TODO: Implement git-aware change detection\n // For now, always return true (include all packages)\n return true\n}\n","import { existsSync, readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\n\n/**\n * A detected task candidate from package.json\n */\nexport interface DetectedTask {\n /** Suggested key for the task */\n key: string\n /** Human-readable name */\n name: string\n /** The npm script name that was detected */\n scriptName: string\n /** The command to run (optimized direct path when possible) */\n command: string\n /** Category for grouping (format, types, logic, build) */\n category: \"format\" | \"types\" | \"logic\" | \"build\" | \"other\"\n /** Parser to use for this task */\n parser?: string\n /**\n * Tasks that must pass for this task's failure to be reported.\n * Auto-populated based on category (types/logic/build depend on format).\n */\n reportingDependsOn?: string[]\n}\n\n/**\n * Tool detection patterns - maps script content to optimized commands\n */\ninterface ToolPattern {\n /** Regex to match in script content */\n pattern: RegExp\n /** Binary name in node_modules/.bin */\n binary: string\n /** Arguments to append (extracted from script or default) */\n getArgs: (match: RegExpMatchArray, scriptContent: string) => string\n /** Parser to use */\n parser?: string\n}\n\nconst TOOL_PATTERNS: ToolPattern[] = [\n // Biome\n {\n pattern: /\\bbiome\\s+(check|lint|format)/,\n binary: \"biome\",\n getArgs: (match, content) => {\n // Extract the full biome command with args\n const biomeMatch = content.match(/biome\\s+([^&|;]+)/)\n return biomeMatch ? biomeMatch[1].trim() : \"check .\"\n },\n parser: \"biome\",\n },\n // ESLint\n {\n pattern: /\\beslint\\b/,\n binary: \"eslint\",\n getArgs: (_, content) => {\n const eslintMatch = content.match(/eslint\\s+([^&|;]+)/)\n return eslintMatch ? eslintMatch[1].trim() : \".\"\n },\n },\n // Prettier\n {\n pattern: /\\bprettier\\b/,\n binary: \"prettier\",\n getArgs: (_, content) => {\n const prettierMatch = content.match(/prettier\\s+([^&|;]+)/)\n return prettierMatch ? prettierMatch[1].trim() : \"--check .\"\n },\n },\n // TypeScript\n {\n pattern: /\\btsc\\b/,\n binary: \"tsc\",\n getArgs: (_, content) => {\n const tscMatch = content.match(/tsc\\s+([^&|;]+)/)\n return tscMatch ? tscMatch[1].trim() : \"--noEmit\"\n },\n parser: \"tsc\",\n },\n // tsgo\n {\n pattern: /\\btsgo\\b/,\n binary: \"tsgo\",\n getArgs: (_, content) => {\n const tsgoMatch = content.match(/tsgo\\s+([^&|;]+)/)\n return tsgoMatch ? tsgoMatch[1].trim() : \"--noEmit\"\n },\n parser: \"tsc\",\n },\n // Vitest\n {\n pattern: /\\bvitest\\b/,\n binary: \"vitest\",\n getArgs: (_, content) => {\n // Check if it's watch mode or run mode\n if (content.includes(\"vitest run\")) return \"run\"\n if (content.includes(\"vitest watch\")) return \"run\" // Convert watch to run for verify\n return \"run\"\n },\n parser: \"vitest\",\n },\n // Jest\n {\n pattern: /\\bjest\\b/,\n binary: \"jest\",\n getArgs: () => \"\",\n },\n // Mocha\n {\n pattern: /\\bmocha\\b/,\n binary: \"mocha\",\n getArgs: () => \"\",\n },\n // tsup\n {\n pattern: /\\btsup\\b/,\n binary: \"tsup\",\n getArgs: (_, content) => {\n const tsupMatch = content.match(/tsup\\s+([^&|;]+)/)\n return tsupMatch ? tsupMatch[1].trim() : \"\"\n },\n },\n // esbuild\n {\n pattern: /\\besbuild\\b/,\n binary: \"esbuild\",\n getArgs: (_, content) => {\n const esbuildMatch = content.match(/esbuild\\s+([^&|;]+)/)\n return esbuildMatch ? esbuildMatch[1].trim() : \"\"\n },\n },\n]\n\n/**\n * Patterns to detect verification-related scripts by name\n */\nconst SCRIPT_NAME_PATTERNS: Array<{\n pattern: RegExp\n key: string\n name: string\n category: DetectedTask[\"category\"]\n}> = [\n // Format/Lint patterns\n {\n pattern: /^(lint|eslint|biome|prettier|format)$/i,\n key: \"format\",\n name: \"Format & Lint\",\n category: \"format\",\n },\n {\n pattern: /^(lint:fix|format:fix|fix)$/i,\n key: \"format\",\n name: \"Format & Lint\",\n category: \"format\",\n },\n {\n pattern: /^verify:format$/i,\n key: \"format\",\n name: \"Format\",\n category: \"format\",\n },\n\n // Type checking patterns\n {\n pattern: /^(typecheck|type-check|tsc|types|check-types)$/i,\n key: \"types\",\n name: \"Type Check\",\n category: \"types\",\n },\n {\n pattern: /^verify:types$/i,\n key: \"types\",\n name: \"Types\",\n category: \"types\",\n },\n\n // Test patterns\n {\n pattern: /^(test|tests|vitest|jest|mocha|ava)$/i,\n key: \"test\",\n name: \"Tests\",\n category: \"logic\",\n },\n {\n pattern: /^test:(unit|integration|e2e)$/i,\n key: \"test\",\n name: \"Tests\",\n category: \"logic\",\n },\n {\n pattern: /^verify:logic$/i,\n key: \"logic\",\n name: \"Logic Tests\",\n category: \"logic\",\n },\n\n // Build patterns\n {\n pattern: /^(build|compile)$/i,\n key: \"build\",\n name: \"Build\",\n category: \"build\",\n },\n]\n\n/**\n * Read and parse package.json from a directory\n */\nfunction readPackageJson(\n cwd: string,\n): { scripts?: Record<string, string> } | null {\n const packageJsonPath = join(cwd, \"package.json\")\n\n if (!existsSync(packageJsonPath)) {\n return null\n }\n\n try {\n const content = readFileSync(packageJsonPath, \"utf-8\")\n return JSON.parse(content) as { scripts?: Record<string, string> }\n } catch {\n return null\n }\n}\n\n/**\n * Check if a binary exists in node_modules/.bin\n */\nfunction binaryExists(cwd: string, binary: string): boolean {\n return existsSync(join(cwd, \"node_modules\", \".bin\", binary))\n}\n\n/**\n * Try to extract an optimized direct command from script content\n */\nfunction extractOptimizedCommand(\n cwd: string,\n scriptContent: string,\n): { command: string; parser?: string } | null {\n for (const tool of TOOL_PATTERNS) {\n const match = scriptContent.match(tool.pattern)\n if (match && binaryExists(cwd, tool.binary)) {\n const args = tool.getArgs(match, scriptContent)\n const command = args\n ? `./node_modules/.bin/${tool.binary} ${args}`\n : `./node_modules/.bin/${tool.binary}`\n return { command, parser: tool.parser }\n }\n }\n return null\n}\n\n/**\n * Detect verification tasks from package.json scripts\n */\nexport function detectFromPackageJson(cwd: string): DetectedTask[] {\n const pkg = readPackageJson(cwd)\n\n if (!pkg?.scripts) {\n return []\n }\n\n const detected: DetectedTask[] = []\n const seenKeys = new Set<string>()\n\n for (const [scriptName, scriptContent] of Object.entries(pkg.scripts)) {\n // Skip scripts that are just running other scripts (like \"verify\": \"run-s ...\")\n if (\n scriptContent.includes(\"run-s\") ||\n scriptContent.includes(\"run-p\") ||\n scriptContent.includes(\"npm-run-all\")\n ) {\n continue\n }\n\n // Check against detection patterns\n for (const { pattern, key, name, category } of SCRIPT_NAME_PATTERNS) {\n if (pattern.test(scriptName)) {\n // Avoid duplicates for the same key\n const uniqueKey = seenKeys.has(key) ? `${key}-${scriptName}` : key\n if (!seenKeys.has(uniqueKey)) {\n seenKeys.add(uniqueKey)\n\n // Try to extract optimized command\n const optimized = extractOptimizedCommand(cwd, scriptContent)\n\n detected.push({\n key: uniqueKey,\n name,\n scriptName,\n command: optimized?.command ?? `npm run ${scriptName}`,\n category,\n parser: optimized?.parser,\n })\n }\n break\n }\n }\n }\n\n // Sort by category priority: format -> types -> logic -> build -> other\n const categoryOrder: Record<DetectedTask[\"category\"], number> = {\n format: 0,\n types: 1,\n logic: 2,\n build: 3,\n other: 4,\n }\n\n detected.sort((a, b) => categoryOrder[a.category] - categoryOrder[b.category])\n\n // Add reportingDependsOn for non-format tasks if a format task exists\n // This reduces noise when a syntax error causes multiple tools to fail\n const hasFormatTask = detected.some(t => t.category === \"format\")\n if (hasFormatTask) {\n for (const task of detected) {\n if (task.category !== \"format\" && task.category !== \"other\") {\n task.reportingDependsOn = [\"format\"]\n }\n }\n }\n\n return detected\n}\n\n/**\n * Detect the package manager being used\n */\nexport function detectPackageManager(cwd: string): \"npm\" | \"pnpm\" | \"yarn\" {\n if (existsSync(join(cwd, \"pnpm-lock.yaml\"))) {\n return \"pnpm\"\n }\n if (existsSync(join(cwd, \"yarn.lock\"))) {\n return \"yarn\"\n }\n return \"npm\"\n}\n\n/**\n * Get the run command for a package manager\n */\nexport function getRunCommand(\n packageManager: \"npm\" | \"pnpm\" | \"yarn\",\n scriptName: string,\n): string {\n switch (packageManager) {\n case \"pnpm\":\n return `pnpm ${scriptName}`\n case \"yarn\":\n return `yarn ${scriptName}`\n default:\n return `npm run ${scriptName}`\n }\n}\n\n/**\n * Detect tasks with proper package manager commands\n * Uses optimized direct paths when possible, falls back to package manager\n */\nexport function detectTasks(cwd: string): DetectedTask[] {\n const packageManager = detectPackageManager(cwd)\n const tasks = detectFromPackageJson(cwd)\n\n // For tasks without optimized commands, use package manager\n return tasks.map(task => {\n // If command is already optimized (starts with ./), keep it\n if (task.command.startsWith(\"./\")) {\n return task\n }\n // Otherwise use package manager command\n return {\n ...task,\n command: getRunCommand(packageManager, task.scriptName),\n }\n })\n}\n","import type { DetectedTask } from \"./detect.js\"\n\n/**\n * Output format for the generated config\n */\nexport type OutputFormat = \"ts\" | \"mts\" | \"js\" | \"mjs\"\n\n/**\n * Determine output format from file path\n */\nexport function getOutputFormat(filePath: string): OutputFormat {\n if (filePath.endsWith(\".mts\")) return \"mts\"\n if (filePath.endsWith(\".mjs\")) return \"mjs\"\n if (filePath.endsWith(\".js\")) return \"js\"\n return \"ts\" // Default to TypeScript\n}\n\n/**\n * Generate the import statement based on format\n */\nfunction generateImport(format: OutputFormat): string {\n // All formats use ESM import syntax\n return `import { defineConfig } from \"@halecraft/verify\"`\n}\n\n/**\n * Generate a task object as a string\n */\nfunction generateTask(task: DetectedTask, indent: string): string {\n const parts = [`key: \"${task.key}\"`, `run: \"${task.command}\"`]\n if (task.parser) {\n parts.push(`parser: \"${task.parser}\"`)\n }\n if (task.reportingDependsOn && task.reportingDependsOn.length > 0) {\n const deps = task.reportingDependsOn.map(d => `\"${d}\"`).join(\", \")\n parts.push(`reportingDependsOn: [${deps}]`)\n }\n return `${indent}{ ${parts.join(\", \")} }`\n}\n\n/**\n * Generate the skeleton config when no tasks are detected\n */\nfunction generateSkeleton(format: OutputFormat): string {\n const importStatement = generateImport(format)\n\n return `${importStatement}\n\nexport default defineConfig({\n tasks: [\n // Add your verification tasks here\n // Example:\n // { key: \"format\", run: \"pnpm lint\" },\n // { key: \"types\", run: \"pnpm typecheck\" },\n // { key: \"test\", run: \"pnpm test\" },\n ],\n})\n`\n}\n\n/**\n * Generate config content from selected tasks\n */\nexport function generateConfigContent(\n tasks: DetectedTask[],\n format: OutputFormat,\n): string {\n // If no tasks, generate skeleton\n if (tasks.length === 0) {\n return generateSkeleton(format)\n }\n\n const importStatement = generateImport(format)\n const indent = \" \"\n\n // Group tasks by category for better organization\n const taskLines = tasks.map(task => generateTask(task, indent))\n\n return `${importStatement}\n\nexport default defineConfig({\n tasks: [\n${taskLines.join(\",\\n\")},\n ],\n})\n`\n}\n\n/**\n * Get the default config filename\n */\nexport function getDefaultConfigPath(): string {\n return \"verify.config.ts\"\n}\n","import type { DetectedTask } from \"./detect.js\"\n\n/**\n * Options for the prompt flow\n */\nexport interface PromptOptions {\n /** Skip interactive prompts and auto-accept all */\n yes: boolean\n /** Whether we're in a TTY environment */\n isTTY: boolean\n}\n\n/**\n * Result of the prompt flow\n */\nexport interface PromptResult {\n /** Selected tasks */\n tasks: DetectedTask[]\n /** Whether the user cancelled */\n cancelled: boolean\n}\n\n/**\n * Check if we should skip prompts\n */\nexport function shouldSkipPrompts(options: PromptOptions): boolean {\n return options.yes || !options.isTTY\n}\n\n/**\n * Run the interactive task selection prompt\n */\nexport async function promptForTasks(\n detectedTasks: DetectedTask[],\n options: PromptOptions,\n): Promise<PromptResult> {\n // If no tasks detected, return empty (will use skeleton)\n if (detectedTasks.length === 0) {\n if (!shouldSkipPrompts(options)) {\n console.log(\n \"\\nā ļø No verification scripts detected in package.json.\\n A skeleton config will be created.\\n\",\n )\n }\n return { tasks: [], cancelled: false }\n }\n\n // If skipping prompts, return all detected tasks\n if (shouldSkipPrompts(options)) {\n console.log(`\\nā Auto-selecting ${detectedTasks.length} detected task(s)\\n`)\n return { tasks: detectedTasks, cancelled: false }\n }\n\n // Dynamic import of @inquirer/prompts to avoid loading it when not needed\n try {\n const { checkbox } = await import(\"@inquirer/prompts\")\n\n console.log(\"\\nš Detected verification scripts in package.json:\\n\")\n\n const choices = detectedTasks.map(task => ({\n name: `${task.name} (${task.command})`,\n value: task,\n checked: true, // Pre-select all by default\n }))\n\n const selected = await checkbox<DetectedTask>({\n message: \"Select tasks to include in your config:\",\n choices,\n instructions: false,\n })\n\n if (selected.length === 0) {\n console.log(\n \"\\nā ļø No tasks selected. A skeleton config will be created.\\n\",\n )\n }\n\n return { tasks: selected, cancelled: false }\n } catch (error) {\n // Handle Ctrl+C or other cancellation\n if (\n error instanceof Error &&\n (error.message.includes(\"User force closed\") ||\n error.name === \"ExitPromptError\")\n ) {\n return { tasks: [], cancelled: true }\n }\n throw error\n }\n}\n","import { existsSync, writeFileSync } from \"node:fs\"\nimport { resolve } from \"node:path\"\nimport type { DetectedTask } from \"./detect.js\"\n\n/**\n * Result of checking if a file exists\n */\nexport interface FileCheckResult {\n exists: boolean\n path: string\n}\n\n/**\n * Check if the config file already exists\n */\nexport function checkConfigExists(\n cwd: string,\n configPath: string,\n): FileCheckResult {\n const absolutePath = resolve(cwd, configPath)\n return {\n exists: existsSync(absolutePath),\n path: absolutePath,\n }\n}\n\n/**\n * Write the config file\n */\nexport function writeConfigFile(\n cwd: string,\n configPath: string,\n content: string,\n): void {\n const absolutePath = resolve(cwd, configPath)\n writeFileSync(absolutePath, content, \"utf-8\")\n}\n\n/**\n * Print warning about existing file\n */\nexport function printExistsWarning(path: string): void {\n console.error(`\\nā ļø Config file already exists: ${path}`)\n console.error(\" Use --force to overwrite.\\n\")\n}\n\n/**\n * Options for success message\n */\nexport interface SuccessOptions {\n /** Path to the created config file */\n configPath: string\n /** Tasks that were configured */\n tasks: DetectedTask[]\n /** Whether optimized commands were used */\n hasOptimizedCommands: boolean\n /** Script names that can potentially be removed */\n removableScripts: string[]\n}\n\n/**\n * Print success message with educational notes\n */\nexport function printSuccess(options: SuccessOptions): void {\n const { configPath, tasks, hasOptimizedCommands, removableScripts } = options\n\n console.log(`\\nā
Created ${configPath}`)\n console.log(\"\")\n\n // Quick start\n console.log(\" Quick start:\")\n console.log(\" $ verify # Run all verifications\")\n console.log(\" $ verify --top-level # Show only top-level tasks\")\n console.log(\" $ verify format # Run only 'format' task\")\n console.log(\"\")\n\n // Performance note if optimized commands were used\n if (hasOptimizedCommands) {\n console.log(\n \" ā” Performance: Using direct tool paths for faster execution\",\n )\n console.log(\n \" (avoids ~250ms overhead per command from package manager)\",\n )\n console.log(\"\")\n }\n\n // Cleanup suggestion if there are removable scripts\n if (removableScripts.length > 0) {\n console.log(\" š” Optional cleanup:\")\n console.log(\n \" You can remove these scripts from package.json if you only\",\n )\n console.log(\" run them via 'verify' (keeps package.json cleaner):\")\n for (const script of removableScripts) {\n console.log(` - \"${script}\"`)\n }\n console.log(\"\")\n }\n\n // Parser note if parsers were detected\n const tasksWithParsers = tasks.filter(t => t.parser)\n if (tasksWithParsers.length > 0) {\n console.log(\" š Rich output: Parsers detected for detailed summaries:\")\n for (const task of tasksWithParsers) {\n console.log(` - ${task.key}: ${task.parser}`)\n }\n console.log(\"\")\n }\n\n console.log(\" š Docs: https://github.com/halecraft/verify\")\n console.log(\"\")\n}\n","import { detectTasks } from \"./detect.js\"\nimport {\n generateConfigContent,\n getDefaultConfigPath,\n getOutputFormat,\n} from \"./generate.js\"\nimport { promptForTasks, shouldSkipPrompts } from \"./prompts.js\"\nimport {\n checkConfigExists,\n printExistsWarning,\n printSuccess,\n writeConfigFile,\n} from \"./write.js\"\n\n/**\n * Options for the init command\n */\nexport interface InitOptions {\n /** Custom config output path */\n config?: string\n /** Force overwrite existing file */\n force: boolean\n /** Skip interactive prompts */\n yes: boolean\n /** Working directory */\n cwd: string\n}\n\n/**\n * Result of the init command\n */\nexport interface InitResult {\n /** Whether init succeeded */\n success: boolean\n /** Path to the created config file (if successful) */\n configPath?: string\n /** Error message (if failed) */\n error?: string\n}\n\n/**\n * Run the init command\n */\nexport async function runInit(options: InitOptions): Promise<InitResult> {\n const configPath = options.config ?? getDefaultConfigPath()\n const format = getOutputFormat(configPath)\n\n // Check if file already exists\n const fileCheck = checkConfigExists(options.cwd, configPath)\n if (fileCheck.exists && !options.force) {\n printExistsWarning(fileCheck.path)\n return {\n success: false,\n error: \"Config file already exists. Use --force to overwrite.\",\n }\n }\n\n // Detect tasks from package.json\n const detectedTasks = detectTasks(options.cwd)\n\n // Determine if we should skip prompts\n const isTTY = process.stdout.isTTY ?? false\n const promptOptions = {\n yes: options.yes,\n isTTY,\n }\n\n // If not skipping prompts, show what we're doing\n if (!shouldSkipPrompts(promptOptions)) {\n console.log(\"\\nš Initializing @halecraft/verify config...\\n\")\n }\n\n // Run interactive prompts (or auto-select)\n const promptResult = await promptForTasks(detectedTasks, promptOptions)\n\n if (promptResult.cancelled) {\n console.log(\"\\nā Cancelled.\\n\")\n return {\n success: false,\n error: \"User cancelled\",\n }\n }\n\n // Generate config content\n const content = generateConfigContent(promptResult.tasks, format)\n\n // Determine if optimized commands were used\n const hasOptimizedCommands = promptResult.tasks.some(t =>\n t.command.startsWith(\"./node_modules/.bin/\"),\n )\n\n // Determine which scripts could be removed (those that were detected and optimized)\n const removableScripts = promptResult.tasks\n .filter(t => t.command.startsWith(\"./node_modules/.bin/\"))\n .map(t => t.scriptName)\n\n // Write the file\n try {\n writeConfigFile(options.cwd, configPath, content)\n printSuccess({\n configPath,\n tasks: promptResult.tasks,\n hasOptimizedCommands,\n removableScripts,\n })\n return {\n success: true,\n configPath,\n }\n } catch (error) {\n const message =\n error instanceof Error ? error.message : \"Failed to write config file\"\n console.error(`\\nā Error: ${message}\\n`)\n return {\n success: false,\n error: message,\n }\n }\n}\n\n// Re-export types and utilities\nexport type { DetectedTask } from \"./detect.js\"\nexport { detectTasks } from \"./detect.js\"\nexport type { OutputFormat } from \"./generate.js\"\nexport { generateConfigContent, getOutputFormat } from \"./generate.js\"\n","import type { OutputParser, ParsedResult } from \"../types.js\"\n\n/**\n * Parser for Biome linter/formatter output\n * Extracts issue counts and file counts from biome check output\n */\nexport const biomeParser: OutputParser = {\n id: \"biome\",\n parse(output: string, exitCode: number): ParsedResult | null {\n // Extract file count from \"Checked N files in Xms\"\n const filesMatch = output.match(\n /Checked\\s+(\\d+)\\s+files?\\s+in\\s+[\\d.]+(?:ms|s)/i,\n )\n const fileCount = filesMatch\n ? Number.parseInt(filesMatch[1], 10)\n : undefined\n\n // Check for warnings in output like \"Found 1 warning.\"\n const warningMatch = output.match(/Found\\s+(\\d+)\\s+warning/i)\n const warnings = warningMatch ? Number.parseInt(warningMatch[1], 10) : 0\n\n if (exitCode === 0) {\n const filesPart = fileCount ? `passed ${fileCount} files` : \"passed\"\n const warningSuffix =\n warnings > 0 ? `, ${warnings} warning${warnings === 1 ? \"\" : \"s\"}` : \"\"\n return {\n summary: `${filesPart}${warningSuffix}`,\n metrics: { errors: 0, warnings, total: fileCount },\n }\n }\n\n // Biome outputs something like \"Found 5 errors and 2 warnings\"\n // or individual diagnostics\n const summaryMatch = output.match(\n /Found\\s+(\\d+)\\s+error(?:s)?(?:\\s+and\\s+(\\d+)\\s+warning(?:s)?)?/i,\n )\n\n if (summaryMatch) {\n const errors = Number.parseInt(summaryMatch[1], 10)\n const parsedWarnings = summaryMatch[2]\n ? Number.parseInt(summaryMatch[2], 10)\n : warnings\n\n const fileSuffix = fileCount ? ` in ${fileCount} files` : \"\"\n return {\n summary: `${errors} error${errors === 1 ? \"\" : \"s\"}${parsedWarnings > 0 ? `, ${parsedWarnings} warning${parsedWarnings === 1 ? \"\" : \"s\"}` : \"\"}${fileSuffix}`,\n metrics: { errors, warnings: parsedWarnings, total: fileCount },\n }\n }\n\n // Count individual error markers if no summary found\n // Biome uses \"error\" prefix for diagnostics\n const errorLines = output.match(/^\\s*error\\[/gm)\n const warningLines = output.match(/^\\s*warning\\[/gm)\n\n const errors = errorLines ? errorLines.length : 0\n const countedWarnings = warningLines ? warningLines.length : warnings\n\n if (errors > 0 || countedWarnings > 0) {\n const fileSuffix = fileCount ? ` in ${fileCount} files` : \"\"\n return {\n summary: `${errors} error${errors === 1 ? \"\" : \"s\"}${countedWarnings > 0 ? `, ${countedWarnings} warning${countedWarnings === 1 ? \"\" : \"s\"}` : \"\"}${fileSuffix}`,\n metrics: { errors, warnings: countedWarnings, total: fileCount },\n }\n }\n\n // No errors found but still have file count\n if (fileCount) {\n return {\n summary: `passed ${fileCount} files`,\n metrics: { errors: 0, warnings: 0, total: fileCount },\n }\n }\n\n return null\n },\n}\n","import type { ParsedResult } from \"../types.js\"\n\n/**\n * Generic fallback parser - just reports exit code\n * This parser always returns a result (never null)\n */\nexport const genericParser = {\n id: \"generic\",\n parse(_output: string, exitCode: number): ParsedResult {\n return {\n summary: exitCode === 0 ? \"passed\" : `failed (exit code ${exitCode})`,\n }\n },\n} as const\n","import type { OutputParser, ParsedResult } from \"../types.js\"\n\n/**\n * Parser for Go test output\n * Counts packages passed/failed from go test output\n */\nexport const gotestParser: OutputParser = {\n id: \"gotest\",\n parse(output: string, exitCode: number): ParsedResult | null {\n // Match \"ok\" and \"FAIL\" lines for packages\n // ok github.com/user/pkg 0.123s\n // FAIL github.com/user/pkg 0.456s\n const okMatches = output.match(/^ok\\s+\\S+/gm)\n const failMatches = output.match(/^FAIL\\s+\\S+/gm)\n\n const passed = okMatches ? okMatches.length : 0\n const failed = failMatches ? failMatches.length : 0\n const total = passed + failed\n\n if (total === 0) {\n // Try to detect \"no test files\" case\n if (output.includes(\"no test files\")) {\n return {\n summary: \"no test files\",\n metrics: { passed: 0, failed: 0, total: 0 },\n }\n }\n return null\n }\n\n // Extract total duration if present\n // \"PASS\" or \"FAIL\" at the end with duration\n const durationMatch = output.match(/(?:PASS|FAIL)\\s*$[\\s\\S]*?(\\d+\\.?\\d*s)/m)\n const duration = durationMatch ? durationMatch[1] : undefined\n\n if (exitCode === 0) {\n return {\n summary: `${passed} package${passed === 1 ? \"\" : \"s\"} passed${duration ? ` in ${duration}` : \"\"}`,\n metrics: { passed, failed: 0, total: passed, duration },\n }\n }\n\n return {\n summary: `${failed}/${total} package${total === 1 ? \"\" : \"s\"} failed`,\n metrics: { passed, failed, total, duration },\n }\n },\n}\n","import type { OutputParser, ParsedResult } from \"../types.js\"\n\n/**\n * Parser for TypeScript compiler (tsc/tsgo) output\n * Counts type errors and extracts diagnostics info\n */\nexport const tscParser: OutputParser = {\n id: \"tsc\",\n parse(output: string, exitCode: number): ParsedResult | null {\n // Extract file count from diagnostics output: \"Files: 277\"\n const filesMatch = output.match(/^Files:\\s+(\\d+)/m)\n const fileCount = filesMatch\n ? Number.parseInt(filesMatch[1], 10)\n : undefined\n\n if (exitCode === 0) {\n const filesPart = fileCount ? `passed ${fileCount} files` : \"passed\"\n return {\n summary: filesPart,\n metrics: { errors: 0, total: fileCount },\n }\n }\n\n // Count error lines: \"src/file.ts(10,5): error TS2345: ...\"\n const errorMatches = output.match(/error TS\\d+:/g)\n const errorCount = errorMatches ? errorMatches.length : 0\n\n if (errorCount === 0) {\n // No recognizable errors but still failed\n return null\n }\n\n const fileSuffix = fileCount ? ` in ${fileCount} files` : \"\"\n return {\n summary: `${errorCount} type error${errorCount === 1 ? \"\" : \"s\"}${fileSuffix}`,\n metrics: { errors: errorCount, total: fileCount },\n }\n },\n}\n","import type { OutputParser, ParsedResult } from \"../types.js\"\n\n/**\n * Strip ANSI escape codes from string\n */\nfunction stripAnsi(str: string): string {\n // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape codes use control characters\n return str.replace(/\\x1b\\[[0-9;]*m/g, \"\")\n}\n\n/**\n * Parser for vitest output\n * Extracts test counts from vitest summary\n */\nexport const vitestParser: OutputParser = {\n id: \"vitest\",\n parse(output: string, exitCode: number): ParsedResult | null {\n // Strip ANSI codes for reliable parsing\n const cleanOutput = stripAnsi(output)\n\n // Match: \"Tests 26 passed (26)\" with flexible whitespace\n // Vitest v4 format: \" Tests 26 passed (26)\"\n const testsMatch = cleanOutput.match(/Tests\\s+(\\d+)\\s+passed\\s*\\((\\d+)\\)/m)\n\n // Match: \"Duration 192ms\" or \"Duration 1.72s\"\n const durationMatch = cleanOutput.match(/Duration\\s+([\\d.]+(?:ms|s))\\b/m)\n\n if (!testsMatch) {\n return null\n }\n\n const passed = Number.parseInt(testsMatch[1], 10)\n const total = Number.parseInt(testsMatch[2], 10)\n const duration = durationMatch ? durationMatch[1] : undefined\n\n // Don't include duration in summary - the reporter adds wall-clock time\n return {\n summary:\n exitCode === 0\n ? `passed ${passed}/${total} tests`\n : `passed ${passed}/${total} tests (some failed)`,\n metrics: {\n passed,\n total,\n failed: total - passed,\n duration,\n },\n }\n },\n}\n","import type { OutputParser, ParsedResult } from \"../types.js\"\nimport { biomeParser } from \"./biome.js\"\nimport { genericParser } from \"./generic.js\"\nimport { gotestParser } from \"./gotest.js\"\nimport { tscParser } from \"./tsc.js\"\nimport { vitestParser } from \"./vitest.js\"\n\n/**\n * Registry for output parsers\n */\nexport class ParserRegistry {\n private parsers = new Map<string, OutputParser>()\n\n constructor() {\n // Register built-in parsers\n this.register(genericParser)\n this.register(vitestParser)\n this.register(tscParser)\n this.register(biomeParser)\n this.register(gotestParser)\n }\n\n /**\n * Register a custom parser\n */\n register(parser: OutputParser): void {\n this.parsers.set(parser.id, parser)\n }\n\n /**\n * Get a parser by ID\n */\n get(id: string): OutputParser | undefined {\n return this.parsers.get(id)\n }\n\n /**\n * Auto-detect parser based on command\n */\n detectParser(cmd: string): string {\n const cmdLower = cmd.toLowerCase()\n\n if (cmdLower.includes(\"vitest\") || cmdLower.includes(\"jest\")) {\n return \"vitest\"\n }\n if (cmdLower.includes(\"tsc\") || cmdLower.includes(\"tsgo\")) {\n return \"tsc\"\n }\n if (cmdLower.includes(\"biome\") || cmdLower.includes(\"eslint\")) {\n return \"biome\"\n }\n if (\n cmdLower.includes(\"go test\") ||\n (cmdLower.includes(\"go\") && cmdLower.includes(\"test\"))\n ) {\n return \"gotest\"\n }\n\n return \"generic\"\n }\n\n /**\n * Parse output using the specified or auto-detected parser\n */\n parse(\n output: string,\n exitCode: number,\n parserId?: string,\n cmd?: string,\n ): ParsedResult {\n const id = parserId ?? (cmd ? this.detectParser(cmd) : \"generic\")\n const parser = this.parsers.get(id) ?? genericParser\n\n const result = parser.parse(output, exitCode)\n if (result) {\n return result\n }\n\n // Fallback to generic if parser returns null\n // genericParser.parse always returns a result, never null\n const fallback = genericParser.parse(output, exitCode)\n if (!fallback) {\n throw new Error(\"genericParser unexpectedly returned null\")\n }\n return fallback\n }\n}\n\n// Default registry instance\nexport const defaultRegistry = new ParserRegistry()\n\n// Re-export individual parsers\nexport { biomeParser } from \"./biome.js\"\nexport { genericParser } from \"./generic.js\"\nexport { gotestParser } from \"./gotest.js\"\nexport { tscParser } from \"./tsc.js\"\nexport { vitestParser } from \"./vitest.js\"\n","/**\n * Arc spinner frames for terminal animation\n */\nconst SPINNER_FRAMES = [\"ā\", \"ā \", \"ā\", \"ā\", \"ā”\", \"ā\"]\n\n/**\n * Spinner animation interval in milliseconds\n */\nconst SPINNER_INTERVAL = 80\n\n/**\n * Manages spinner animation for terminal output\n */\nexport class SpinnerManager {\n private frames = SPINNER_FRAMES\n private frameIndex = 0\n private interval: ReturnType<typeof setInterval> | null = null\n\n /**\n * Start the spinner animation\n * @param onTick - Callback called on each frame update\n */\n start(onTick: () => void): void {\n if (this.interval) return\n\n this.interval = setInterval(() => {\n this.frameIndex = (this.frameIndex + 1) % this.frames.length\n onTick()\n }, SPINNER_INTERVAL)\n }\n\n /**\n * Stop the spinner animation\n */\n stop(): void {\n if (this.interval) {\n clearInterval(this.interval)\n this.interval = null\n }\n }\n\n /**\n * Get the current spinner frame character\n */\n getFrame(): string {\n return this.frames[this.frameIndex]\n }\n\n /**\n * Check if spinner is currently running\n */\n isRunning(): boolean {\n return this.interval !== null\n }\n}\n","import { SpinnerManager } from \"./spinner.js\"\nimport type {\n TaskResult,\n VerificationNode,\n VerifyOptions,\n VerifyResult,\n} from \"./types.js\"\n\n/**\n * ANSI color codes\n */\nconst ansi = {\n reset: \"\\u001b[0m\",\n dim: \"\\u001b[2m\",\n red: \"\\u001b[31m\",\n green: \"\\u001b[32m\",\n yellow: \"\\u001b[33m\",\n cyan: \"\\u001b[36m\",\n bold: \"\\u001b[1m\",\n}\n\n/**\n * ANSI cursor control codes\n */\nconst cursor = {\n hide: \"\\u001b[?25l\",\n show: \"\\u001b[?25h\",\n moveUp: (n: number) => `\\u001b[${n}A`,\n moveToStart: \"\\u001b[0G\",\n clearLine: \"\\u001b[2K\",\n}\n\n/**\n * Reporter interface\n */\nexport interface Reporter {\n /** Called before any tasks start - initialize display */\n onStart?(tasks: VerificationNode[]): void\n /** Called when a task starts */\n onTaskStart(path: string, key: string): void\n /** Called when a task completes */\n onTaskComplete(result: TaskResult): void\n /** Called when all tasks complete - cleanup display */\n onFinish?(): void\n /** Called to output task logs */\n outputLogs(results: TaskResult[], logsMode: \"all\" | \"failed\" | \"none\"): void\n /** Called to output final summary */\n outputSummary(result: VerifyResult): void\n}\n\n/**\n * Check if colors should be enabled\n */\nfunction shouldUseColors(options: VerifyOptions): boolean {\n if (options.noColor) return false\n if (options.format === \"json\") return false\n if (!process.stdout.isTTY) return false\n if (\"NO_COLOR\" in process.env) return false\n if (process.env.TERM === \"dumb\") return false\n return true\n}\n\n/**\n * Base Reporter - common functionality for all reporters\n */\nexport abstract class BaseReporter implements Reporter {\n protected colorEnabled: boolean\n protected stream: NodeJS.WriteStream\n protected taskDepths: Map<string, number> = new Map()\n\n constructor(options: VerifyOptions = {}) {\n this.colorEnabled = shouldUseColors(options)\n this.stream = options.format === \"json\" ? process.stderr : process.stdout\n }\n\n /**\n * Apply ANSI color code to string (if colors enabled)\n */\n protected c(code: string, s: string): string {\n return this.colorEnabled ? `${code}${s}${ansi.reset}` : s\n }\n\n /**\n * Get success mark (ā or OK)\n */\n protected okMark(): string {\n return this.colorEnabled ? this.c(ansi.green, \"ā\") : \"OK\"\n }\n\n /**\n * Get failure mark (ā or FAIL)\n */\n protected failMark(): string {\n return this.colorEnabled ? this.c(ansi.red, \"ā\") : \"FAIL\"\n }\n\n /**\n * Get suppressed mark (ā or SUPPRESSED)\n */\n protected suppressedMark(): string {\n return this.colorEnabled ? this.c(ansi.yellow, \"ā\") : \"SUPPRESSED\"\n }\n\n /**\n * Get arrow symbol (ā or ->)\n */\n protected arrow(): string {\n return this.colorEnabled ? this.c(ansi.cyan, \"ā\") : \"->\"\n }\n\n /**\n * Get indentation string for a given depth\n */\n protected getIndent(depth: number): string {\n return \" \".repeat(depth)\n }\n\n /**\n * Get task depth from path\n */\n protected getTaskDepth(path: string): number {\n return this.taskDepths.get(path) ?? 0\n }\n\n /**\n * Recursively collect task depths from verification tree\n */\n protected collectTaskDepths(\n nodes: VerificationNode[],\n parentPath: string,\n depth: number,\n ): void {\n for (const node of nodes) {\n const path = parentPath ? `${parentPath}:${node.key}` : node.key\n this.taskDepths.set(path, depth)\n\n if (node.children) {\n this.collectTaskDepths(node.children, path, depth + 1)\n }\n }\n }\n\n /**\n * Extract summary from task result\n */\n protected extractSummary(result: TaskResult): string {\n // Use the parsed summary from summaryLine (strip the \"key: \" prefix if present)\n // The parsers already format summaries nicely with file counts, test counts, etc.\n if (result.summaryLine) {\n const colonIndex = result.summaryLine.indexOf(\": \")\n if (colonIndex !== -1) {\n return result.summaryLine.slice(colonIndex + 2)\n }\n return result.summaryLine\n }\n\n return result.ok ? \"passed\" : \"failed\"\n }\n\n /**\n * Flatten nested task results into a single array\n */\n protected flattenResults(results: TaskResult[]): TaskResult[] {\n const flat: TaskResult[] = []\n for (const r of results) {\n flat.push(r)\n if (r.children) {\n flat.push(...this.flattenResults(r.children))\n }\n }\n return flat\n }\n\n /**\n * Output task logs\n */\n outputLogs(results: TaskResult[], logsMode: \"all\" | \"failed\" | \"none\"): void {\n if (logsMode === \"none\") return\n\n const flatResults = this.flattenResults(results)\n\n for (const r of flatResults) {\n if (r.children) continue\n if (logsMode === \"failed\" && r.ok) continue\n // Skip suppressed tasks - their output is hidden to reduce noise\n if (r.suppressed) continue\n\n const status = r.ok ? this.c(ansi.green, \"OK\") : this.c(ansi.red, \"FAIL\")\n\n this.stream.write(\n `\\n${this.c(ansi.bold, \"====\")} ${this.c(ansi.bold, r.path.toUpperCase())} ${status} ${this.c(ansi.bold, \"====\")}\\n`,\n )\n this.stream.write(r.output || \"(no output)\\n\")\n }\n }\n\n /**\n * Output final summary\n */\n outputSummary(result: VerifyResult): void {\n const finalMessage = result.ok\n ? this.c(ansi.green, \"\\n== verification: All correct ==\")\n : this.c(ansi.red, \"\\n== verification: Failed ==\")\n this.stream.write(`${finalMessage}\\n`)\n }\n\n // Abstract methods that subclasses must implement\n abstract onStart(tasks: VerificationNode[]): void\n abstract onTaskStart(path: string, key: string): void\n abstract onTaskComplete(result: TaskResult): void\n abstract onFinish(): void\n}\n\n/**\n * Task state for live dashboard\n */\ninterface TaskState {\n key: string\n path: string\n depth: number\n status: \"pending\" | \"running\" | \"completed\"\n result?: TaskResult\n}\n\n/**\n * Live Dashboard Reporter - animated in-place updates for TTY\n */\nexport class LiveDashboardReporter extends BaseReporter {\n private topLevelOnly: boolean\n private tasks: Map<string, TaskState> = new Map()\n private taskOrder: string[] = []\n private spinner: SpinnerManager\n private lineCount = 0\n\n constructor(options: VerifyOptions = {}) {\n super(options)\n this.topLevelOnly = options.topLevelOnly ?? false\n this.spinner = new SpinnerManager()\n\n // Handle Ctrl+C to restore cursor\n const cleanup = () => {\n this.spinner.stop()\n this.stream.write(cursor.show)\n process.exit(130)\n }\n process.on(\"SIGINT\", cleanup)\n process.on(\"SIGTERM\", cleanup)\n }\n\n /**\n * Initialize task list from verification nodes\n */\n onStart(tasks: VerificationNode[]): void {\n this.collectTasks(tasks, \"\", 0)\n this.stream.write(cursor.hide)\n this.spinner.start(() => this.redraw())\n }\n\n /**\n * Recursively collect tasks from verification tree\n */\n private collectTasks(\n nodes: VerificationNode[],\n parentPath: string,\n depth: number,\n ): void {\n for (const node of nodes) {\n const path = parentPath ? `${parentPath}:${node.key}` : node.key\n this.tasks.set(path, {\n key: node.key,\n path,\n depth,\n status: \"pending\",\n })\n this.taskOrder.push(path)\n // Also store in base class for consistency\n this.taskDepths.set(path, depth)\n\n if (node.children) {\n this.collectTasks(node.children, path, depth + 1)\n }\n }\n }\n\n /**\n * Get display key - shows :key for nested, key for root\n */\n private getDisplayKey(task: TaskState): string {\n if (task.depth === 0) {\n return task.key\n }\n return `:${task.key}`\n }\n\n /**\n * Check if task should be displayed based on topLevelOnly flag\n */\n private shouldDisplay(task: TaskState): boolean {\n if (this.topLevelOnly) return task.depth === 0\n return true\n }\n\n /**\n * Format a single task line\n */\n private formatLine(task: TaskState): string {\n const indent = this.getIndent(task.depth)\n const displayKey = this.getDisplayKey(task)\n\n if (task.status === \"running\") {\n const spinnerChar = this.c(ansi.dim, `(${this.spinner.getFrame()})`)\n return `${indent}${this.arrow()} verifying ${this.c(ansi.bold, displayKey)} ${spinnerChar}`\n }\n\n if (task.status === \"completed\" && task.result) {\n const duration = this.c(ansi.dim, `${task.result.durationMs}ms`)\n\n // Handle suppressed tasks\n if (task.result.suppressed) {\n const reason = task.result.suppressedBy\n ? `${task.result.suppressedBy} failed`\n : \"dependency failed\"\n return `${indent}${this.suppressedMark()} suppressed ${this.c(ansi.bold, displayKey)} ${this.c(ansi.dim, `(${reason}, ${duration})`)}`\n }\n\n const summary = this.extractSummary(task.result)\n\n if (task.result.ok) {\n return ` ${indent}${this.okMark()} verified ${this.c(ansi.bold, displayKey)} ${this.c(ansi.dim, `(${summary}, ${duration})`)}`\n }\n return `${indent}${this.failMark()} failed ${this.c(ansi.bold, displayKey)} ${this.c(ansi.dim, `(${summary}, ${duration})`)}`\n }\n\n // Pending - don't show\n return \"\"\n }\n\n /**\n * Redraw all visible task lines\n */\n private redraw(): void {\n // Move cursor up to overwrite previous lines\n if (this.lineCount > 0) {\n this.stream.write(cursor.moveUp(this.lineCount))\n }\n\n // Build new output\n const lines: string[] = []\n for (const path of this.taskOrder) {\n const task = this.tasks.get(path)\n if (!task) continue\n if (!this.shouldDisplay(task)) continue\n if (task.status === \"pending\") continue\n\n const line = this.formatLine(task)\n if (line) {\n lines.push(line)\n }\n }\n\n // Write lines with clear\n for (const line of lines) {\n this.stream.write(`${cursor.clearLine}${cursor.moveToStart}${line}\\n`)\n }\n\n this.lineCount = lines.length\n }\n\n onTaskStart(path: string, _key: string): void {\n const task = this.tasks.get(path)\n if (task) {\n task.status = \"running\"\n }\n // Redraw happens on spinner tick\n }\n\n onTaskComplete(result: TaskResult): void {\n const task = this.tasks.get(result.path)\n if (task) {\n task.status = \"completed\"\n task.result = result\n }\n // Redraw happens on spinner tick, but do one now for immediate feedback\n this.redraw()\n }\n\n onFinish(): void {\n this.spinner.stop()\n this.redraw() // Final redraw\n this.stream.write(cursor.show)\n }\n}\n\n/**\n * Sequential Reporter - line-by-line output for non-TTY\n * No indentation since parallel execution means output order doesn't reflect hierarchy\n */\nexport class SequentialReporter extends BaseReporter {\n private topLevelOnly: boolean\n\n constructor(options: VerifyOptions = {}) {\n super(options)\n this.topLevelOnly = options.topLevelOnly ?? false\n }\n\n onStart(tasks: VerificationNode[]): void {\n // Collect task depths from the config tree\n this.collectTaskDepths(tasks, \"\", 0)\n }\n\n /**\n * Check if task should be displayed based on topLevelOnly flag\n */\n private shouldDisplay(path: string): boolean {\n if (this.topLevelOnly) return this.getTaskDepth(path) === 0\n return true\n }\n\n onTaskStart(path: string, _key: string): void {\n if (!this.shouldDisplay(path)) return\n this.stream.write(`${this.arrow()} verifying ${this.c(ansi.bold, path)}\\n`)\n }\n\n onTaskComplete(result: TaskResult): void {\n if (!this.shouldDisplay(result.path)) return\n const duration = this.c(ansi.dim, `${result.durationMs}ms`)\n\n // Handle suppressed tasks\n if (result.suppressed) {\n const reason = result.suppressedBy\n ? `${result.suppressedBy} failed`\n : \"dependency failed\"\n this.stream.write(\n `${this.suppressedMark()} suppressed ${this.c(ansi.bold, result.path)} ${this.c(ansi.dim, `(${reason}, ${duration})`)}\\n`,\n )\n return\n }\n\n const mark = result.ok ? this.okMark() : this.failMark()\n const verb = result.ok ? \"verified\" : \"failed\"\n const summary = this.extractSummary(result)\n this.stream.write(\n `${mark} ${verb} ${this.c(ansi.bold, result.path)} ${this.c(ansi.dim, `(${summary}, ${duration})`)}\\n`,\n )\n }\n\n onFinish(): void {\n // No cleanup needed for sequential output\n }\n}\n\n/**\n * JSON Reporter - machine-readable output\n */\nexport class JSONReporter implements Reporter {\n onStart(_tasks: VerificationNode[]): void {\n // No output during execution in JSON mode\n }\n\n onTaskStart(_path: string, _key: string): void {\n // No output during execution in JSON mode\n }\n\n onTaskComplete(_result: TaskResult): void {\n // No output during execution in JSON mode\n }\n\n onFinish(): void {\n // No cleanup needed for JSON output\n }\n\n outputLogs(\n _results: TaskResult[],\n _logsMode: \"all\" | \"failed\" | \"none\",\n ): void {\n // Logs are included in the JSON output\n }\n\n outputSummary(result: VerifyResult): void {\n const summary = {\n ok: result.ok,\n startedAt: result.startedAt,\n finishedAt: result.finishedAt,\n durationMs: result.durationMs,\n tasks: this.serializeTasks(result.tasks),\n }\n\n process.stdout.write(`${JSON.stringify(summary)}\\n`)\n }\n\n private serializeTasks(tasks: TaskResult[]): Array<{\n key: string\n path: string\n ok: boolean\n code: number\n durationMs: number\n summaryLine: string\n suppressed?: boolean\n suppressedBy?: string\n children?: ReturnType<JSONReporter[\"serializeTasks\"]>\n }> {\n return tasks.map(t => ({\n key: t.key,\n path: t.path,\n ok: t.ok,\n code: t.code,\n durationMs: t.durationMs,\n summaryLine: t.summaryLine,\n ...(t.suppressed ? { suppressed: t.suppressed } : {}),\n ...(t.suppressedBy ? { suppressedBy: t.suppressedBy } : {}),\n ...(t.children ? { children: this.serializeTasks(t.children) } : {}),\n }))\n }\n}\n\n/**\n * Quiet Reporter - minimal output (summary only)\n */\nexport class QuietReporter extends BaseReporter {\n onStart(_tasks: VerificationNode[]): void {\n // No output\n }\n\n onTaskStart(_path: string, _key: string): void {\n // No output\n }\n\n onTaskComplete(_result: TaskResult): void {\n // No output\n }\n\n onFinish(): void {\n // No cleanup needed\n }\n\n outputLogs(\n _results: TaskResult[],\n _logsMode: \"all\" | \"failed\" | \"none\",\n ): void {\n // No logs in quiet mode\n }\n\n outputSummary(result: VerifyResult): void {\n const message = result.ok\n ? this.c(ansi.green, \"ā All verifications passed\")\n : this.c(ansi.red, \"ā Some verifications failed\")\n process.stdout.write(`${message}\\n`)\n }\n}\n\n/**\n * Create appropriate reporter based on options\n */\nexport function createReporter(options: VerifyOptions): Reporter {\n if (options.format === \"json\") {\n return new JSONReporter()\n }\n\n // Use LiveDashboardReporter for TTY (unless --no-tty is set)\n if (process.stdout.isTTY && !options.noTty) {\n return new LiveDashboardReporter(options)\n }\n\n return new SequentialReporter(options)\n}\n\n// Keep TTYReporter as alias for backwards compatibility\nexport { SequentialReporter as TTYReporter }\n","import { type ChildProcess, spawn } from \"node:child_process\"\nimport treeKill from \"tree-kill\"\nimport { defaultRegistry, type ParserRegistry } from \"./parsers/index.js\"\nimport type {\n ParsedResult,\n TaskResult,\n VerificationCommand,\n VerificationNode,\n VerifyOptions,\n VerifyResult,\n} from \"./types.js\"\n\n/**\n * Normalize command to VerificationCommand format\n */\nfunction normalizeCommand(\n run: VerificationCommand | string | [string, string[]],\n): VerificationCommand {\n if (typeof run === \"string\") {\n // Parse string command: \"pnpm verify:format\" -> { cmd: \"pnpm\", args: [\"verify:format\"] }\n const parts = run.split(/\\s+/)\n return {\n cmd: parts[0],\n args: parts.slice(1),\n }\n }\n\n if (Array.isArray(run)) {\n return {\n cmd: run[0],\n args: run[1],\n }\n }\n\n return run\n}\n\n/**\n * Tracks reporting dependencies between tasks and coordinates result emission.\n * Allows tasks to wait for their dependencies to complete before emitting results,\n * and determines if a task's failure should be suppressed.\n * Also handles early termination by killing dependent processes when a dependency fails.\n */\nexport class ReportingDependencyTracker {\n /** Map of task path/key to their results */\n private results: Map<string, TaskResult> = new Map()\n\n /** Map of task path/key to waiters (callbacks to resolve when result is available) */\n private waiters: Map<string, Array<() => void>> = new Map()\n\n /** Map of task path to its key (for key-based lookups) */\n private pathToKey: Map<string, string> = new Map()\n\n /** Map of task key to its path (for key-based lookups) */\n private keyToPath: Map<string, string> = new Map()\n\n /** Map of task path to its reportingDependsOn array */\n private dependencies: Map<string, string[]> = new Map()\n\n /** Reverse map: task path ā list of tasks that depend on it */\n private reverseDeps: Map<string, string[]> = new Map()\n\n /** Map of task path to its running ChildProcess */\n private processes: Map<string, ChildProcess> = new Map()\n\n /** Set of task paths that have been killed */\n private killedPaths: Set<string> = new Set()\n\n /**\n * Initialize the tracker with all tasks from the verification tree.\n * Also validates for circular dependencies and builds reverse dependency map.\n */\n initialize(nodes: VerificationNode[], parentPath = \"\"): void {\n for (const node of nodes) {\n const path = parentPath ? `${parentPath}:${node.key}` : node.key\n this.pathToKey.set(path, node.key)\n this.keyToPath.set(node.key, path)\n\n if (node.reportingDependsOn && node.reportingDependsOn.length > 0) {\n this.dependencies.set(path, node.reportingDependsOn)\n }\n\n if (node.children) {\n this.initialize(node.children, path)\n }\n }\n\n // Only validate cycles and build reverse deps once at the root level\n if (parentPath === \"\") {\n this.validateNoCycles()\n this.buildReverseDeps()\n }\n }\n\n /**\n * Build reverse dependency map (task ā tasks that depend on it)\n */\n private buildReverseDeps(): void {\n for (const [path, deps] of this.dependencies.entries()) {\n for (const dep of deps) {\n const resolvedDep = this.resolveDependency(dep)\n if (resolvedDep) {\n const existing = this.reverseDeps.get(resolvedDep) ?? []\n existing.push(path)\n this.reverseDeps.set(resolvedDep, existing)\n }\n }\n }\n }\n\n /**\n * Validate that there are no circular dependencies using DFS with coloring.\n * Throws an error with the cycle path if a cycle is detected.\n */\n private validateNoCycles(): void {\n const WHITE = 0 // Not visited\n const GRAY = 1 // Currently visiting (in stack)\n const BLACK = 2 // Fully visited\n\n const colors = new Map<string, number>()\n const parent = new Map<string, string>()\n\n // Initialize all nodes as white\n for (const path of this.pathToKey.keys()) {\n colors.set(path, WHITE)\n }\n\n const dfs = (path: string): string | null => {\n colors.set(path, GRAY)\n\n const deps = this.dependencies.get(path) ?? []\n for (const dep of deps) {\n const depPath = this.resolveDependency(dep)\n if (!depPath) continue // Unknown dependency, skip\n\n const color = colors.get(depPath) ?? WHITE\n\n if (color === GRAY) {\n // Found a cycle - reconstruct the path\n const cycle: string[] = [depPath]\n let current = path\n while (current !== depPath) {\n cycle.unshift(current)\n current = parent.get(current) ?? \"\"\n }\n cycle.unshift(depPath)\n return cycle.join(\" ā \")\n }\n\n if (color === WHITE) {\n parent.set(depPath, path)\n const cyclePath = dfs(depPath)\n if (cyclePath) return cyclePath\n }\n }\n\n colors.set(path, BLACK)\n return null\n }\n\n for (const path of this.pathToKey.keys()) {\n if (colors.get(path) === WHITE) {\n const cyclePath = dfs(path)\n if (cyclePath) {\n throw new Error(\n `Circular reporting dependency detected: ${cyclePath}`,\n )\n }\n }\n }\n }\n\n /**\n * Resolve a dependency identifier to a task path.\n * Tries exact path match first, then key match.\n */\n private resolveDependency(dep: string): string | null {\n // Try exact path match first\n if (this.pathToKey.has(dep)) {\n return dep\n }\n\n // Try key match\n if (this.keyToPath.has(dep)) {\n return this.keyToPath.get(dep) ?? null\n }\n\n return null\n }\n\n /**\n * Record a task result and notify any waiters.\n * If the task failed, kills all dependent processes for early termination.\n */\n recordResult(result: TaskResult): void {\n // Store by path\n this.results.set(result.path, result)\n\n // If this task failed, kill all dependent processes\n if (!result.ok) {\n this.killDependents(result.path)\n }\n\n // Notify waiters for this path\n const pathWaiters = this.waiters.get(result.path) ?? []\n for (const waiter of pathWaiters) {\n waiter()\n }\n this.waiters.delete(result.path)\n\n // Also notify waiters for the key (if different from path)\n const key = result.key\n if (key !== result.path) {\n const keyWaiters = this.waiters.get(key) ?? []\n for (const waiter of keyWaiters) {\n waiter()\n }\n this.waiters.delete(key)\n }\n }\n\n /**\n * Wait for all dependencies of a task to complete.\n */\n async waitForDependencies(path: string): Promise<void> {\n const deps = this.dependencies.get(path)\n if (!deps || deps.length === 0) {\n return\n }\n\n const waitPromises = deps.map(dep => this.waitForResult(dep))\n await Promise.all(waitPromises)\n }\n\n /**\n * Wait for a specific task result to be available.\n */\n private waitForResult(pathOrKey: string): Promise<void> {\n // Check if result already exists\n const resolvedPath = this.resolveDependency(pathOrKey)\n if (resolvedPath && this.results.has(resolvedPath)) {\n return Promise.resolve()\n }\n\n // Also check by the original identifier\n if (this.results.has(pathOrKey)) {\n return Promise.resolve()\n }\n\n // Register a waiter\n return new Promise<void>(resolve => {\n const waiters = this.waiters.get(pathOrKey) ?? []\n waiters.push(resolve)\n this.waiters.set(pathOrKey, waiters)\n })\n }\n\n /**\n * Check if any dependency of a task has failed.\n * Returns the path of the first failed dependency, or null if all passed.\n */\n getFailedDependency(path: string): string | null {\n const deps = this.dependencies.get(path)\n if (!deps || deps.length === 0) {\n return null\n }\n\n for (const dep of deps) {\n const resolvedPath = this.resolveDependency(dep)\n if (!resolvedPath) continue\n\n const result = this.results.get(resolvedPath)\n if (result && !result.ok) {\n return resolvedPath\n }\n }\n\n return null\n }\n\n /**\n * Check if a task has any reporting dependencies.\n */\n hasDependencies(path: string): boolean {\n const deps = this.dependencies.get(path)\n return deps !== undefined && deps.length > 0\n }\n\n /**\n * Register a running process for a task.\n */\n registerProcess(path: string, proc: ChildProcess): void {\n this.processes.set(path, proc)\n }\n\n /**\n * Unregister a process (called when it completes naturally).\n */\n unregisterProcess(path: string): void {\n this.processes.delete(path)\n }\n\n /**\n * Check if a task was killed.\n */\n wasKilled(path: string): boolean {\n return this.killedPaths.has(path)\n }\n\n /**\n * Kill all processes that depend on the failed task.\n * Called when a task fails to terminate dependent tasks early.\n */\n killDependents(failedPath: string): void {\n const dependents = this.reverseDeps.get(failedPath) ?? []\n\n for (const depPath of dependents) {\n const proc = this.processes.get(depPath)\n if (proc?.pid) {\n this.killedPaths.add(depPath)\n // Use tree-kill to kill the process and all its children\n treeKill(proc.pid, \"SIGTERM\", err => {\n if (err) {\n // Process may have already exited, ignore errors\n }\n })\n }\n }\n }\n}\n\n/**\n * Execute a single command and capture output.\n * Optionally registers the process with a tracker for early termination support.\n */\nasync function executeCommand(\n command: VerificationCommand,\n cwd: string,\n tracker?: ReportingDependencyTracker,\n path?: string,\n): Promise<{\n code: number\n output: string\n durationMs: number\n killed: boolean\n}> {\n const start = Date.now()\n\n return new Promise(resolve => {\n const proc = spawn(command.cmd, command.args, {\n shell: process.platform === \"win32\",\n cwd: command.cwd ?? cwd,\n env: { ...process.env, NO_COLOR: \"1\", ...command.env },\n })\n\n // Register process for early termination\n if (tracker && path) {\n tracker.registerProcess(path, proc)\n }\n\n let output = \"\"\n\n proc.stdout.on(\"data\", (data: Buffer) => {\n output += data.toString()\n })\n\n proc.stderr.on(\"data\", (data: Buffer) => {\n output += data.toString()\n })\n\n proc.on(\"close\", (code, signal) => {\n // Unregister process\n if (tracker && path) {\n tracker.unregisterProcess(path)\n }\n\n const durationMs = Date.now() - start\n // Check if process was killed (SIGTERM = 15, exit code 143 = 128 + 15)\n const killed =\n signal === \"SIGTERM\" ||\n code === 143 ||\n (tracker?.wasKilled(path ?? \"\") ?? false)\n\n resolve({\n code: code ?? 1,\n output,\n durationMs,\n killed,\n })\n })\n\n proc.on(\"error\", err => {\n // Unregister process\n if (tracker && path) {\n tracker.unregisterProcess(path)\n }\n\n const durationMs = Date.now() - start\n resolve({\n code: 1,\n output: `Failed to execute command: ${err.message}`,\n durationMs,\n killed: false,\n })\n })\n })\n}\n\n/**\n * Build full path for a node\n */\nfunction buildPath(parentPath: string, key: string): string {\n return parentPath ? `${parentPath}:${key}` : key\n}\n\n/**\n * Check if a path matches the filter\n */\nfunction matchesFilter(path: string, filters?: string[]): boolean {\n if (!filters || filters.length === 0) {\n return true\n }\n\n return filters.some(filter => {\n // Exact match or prefix match\n return path === filter || path.startsWith(`${filter}:`)\n })\n}\n\n/**\n * Check if any descendant matches the filter\n */\nfunction hasMatchingDescendant(\n node: VerificationNode,\n parentPath: string,\n filters?: string[],\n): boolean {\n const path = buildPath(parentPath, node.key)\n\n if (matchesFilter(path, filters)) {\n return true\n }\n\n if (node.children) {\n return node.children.some(child =>\n hasMatchingDescendant(child, path, filters),\n )\n }\n\n return false\n}\n\nexport interface RunnerCallbacks {\n onTaskStart?: (path: string, key: string) => void\n onTaskComplete?: (result: TaskResult) => void\n}\n\n/**\n * Verification runner\n */\nexport class VerificationRunner {\n private registry: ParserRegistry\n private options: VerifyOptions\n private callbacks: RunnerCallbacks\n private dependencyTracker: ReportingDependencyTracker\n\n constructor(\n options: VerifyOptions = {},\n registry: ParserRegistry = defaultRegistry,\n callbacks: RunnerCallbacks = {},\n ) {\n this.options = options\n this.registry = registry\n this.callbacks = callbacks\n this.dependencyTracker = new ReportingDependencyTracker()\n }\n\n /**\n * Run all verification tasks\n */\n async run(tasks: VerificationNode[]): Promise<VerifyResult> {\n const startedAt = new Date().toISOString()\n const wallStart = Date.now()\n\n // Initialize dependency tracker with all tasks (validates cycles)\n this.dependencyTracker.initialize(tasks)\n\n const results = await this.runNodes(tasks, \"\")\n\n const finishedAt = new Date().toISOString()\n const durationMs = Date.now() - wallStart\n\n const allOk = results.every(r => r.ok)\n\n return {\n ok: allOk,\n startedAt,\n finishedAt,\n durationMs,\n tasks: results,\n }\n }\n\n /**\n * Run a list of nodes with the appropriate strategy\n */\n private async runNodes(\n nodes: VerificationNode[],\n parentPath: string,\n strategy: \"parallel\" | \"sequential\" | \"fail-fast\" = \"parallel\",\n ): Promise<TaskResult[]> {\n // Filter nodes based on filter option\n const filteredNodes = nodes.filter(node =>\n hasMatchingDescendant(node, parentPath, this.options.filter),\n )\n\n if (filteredNodes.length === 0) {\n return []\n }\n\n switch (strategy) {\n case \"parallel\":\n return Promise.all(\n filteredNodes.map(node => this.runNode(node, parentPath)),\n )\n\n case \"sequential\": {\n const results: TaskResult[] = []\n for (const node of filteredNodes) {\n results.push(await this.runNode(node, parentPath))\n }\n return results\n }\n\n case \"fail-fast\": {\n const results: TaskResult[] = []\n for (const node of filteredNodes) {\n const result = await this.runNode(node, parentPath)\n results.push(result)\n if (!result.ok) {\n break\n }\n }\n return results\n }\n }\n }\n\n /**\n * Run a single node (leaf or group)\n */\n private async runNode(\n node: VerificationNode,\n parentPath: string,\n ): Promise<TaskResult> {\n const path = buildPath(parentPath, node.key)\n\n // Notify start\n this.callbacks.onTaskStart?.(path, node.key)\n\n // If this is a group node (has children), run children\n if (node.children && node.children.length > 0) {\n const start = Date.now()\n const childResults = await this.runNodes(\n node.children,\n path,\n node.strategy ?? \"parallel\",\n )\n const durationMs = Date.now() - start\n\n const allOk = childResults.every(r => r.ok || r.suppressed)\n\n // Propagate suppressed status from children to parent\n const allSuppressed =\n childResults.length > 0 && childResults.every(r => r.suppressed)\n const anySuppressed = childResults.some(r => r.suppressed)\n\n const result: TaskResult = {\n key: node.key,\n path,\n ok: allOk,\n code: allOk ? 0 : 1,\n durationMs,\n output: \"\",\n summaryLine: allOk\n ? (node.successLabel ?? `${node.key}: all passed`)\n : (node.failureLabel ?? `${node.key}: some failed`),\n children: childResults,\n }\n\n // If all children are suppressed, parent is also suppressed\n if (allSuppressed) {\n result.suppressed = true\n result.suppressedBy = childResults[0].suppressedBy\n } else if (anySuppressed && !allOk) {\n // Mixed: some suppressed, some failed - don't suppress parent\n // The parent shows as failed with the actual failures visible\n }\n\n // Record result in tracker before emitting\n this.dependencyTracker.recordResult(result)\n this.callbacks.onTaskComplete?.(result)\n return result\n }\n\n // Leaf node - execute command\n if (!node.run) {\n const result: TaskResult = {\n key: node.key,\n path,\n ok: true,\n code: 0,\n durationMs: 0,\n output: \"\",\n summaryLine: `${node.key}: no command specified`,\n }\n this.dependencyTracker.recordResult(result)\n this.callbacks.onTaskComplete?.(result)\n return result\n }\n\n const command = normalizeCommand(node.run)\n const cwd = this.options.cwd ?? process.cwd()\n\n // Pass tracker and path for early termination support\n const { code, output, durationMs, killed } = await executeCommand(\n command,\n cwd,\n this.dependencyTracker,\n path,\n )\n\n const ok = code === 0\n\n // If process was killed, mark as suppressed immediately\n if (killed) {\n // Wait for dependencies to get the failed dependency path\n await this.dependencyTracker.waitForDependencies(path)\n const failedDep = this.dependencyTracker.getFailedDependency(path)\n\n const result: TaskResult = {\n key: node.key,\n path,\n ok: false,\n code,\n durationMs,\n output,\n summaryLine: `${node.key}: terminated`,\n suppressed: true,\n suppressedBy: failedDep ?? \"unknown\",\n }\n\n this.dependencyTracker.recordResult(result)\n this.callbacks.onTaskComplete?.(result)\n return result\n }\n\n // Parse output\n const cmdString = `${command.cmd} ${command.args.join(\" \")}`\n const parsed: ParsedResult = this.registry.parse(\n output,\n code,\n node.parser,\n cmdString,\n )\n\n // Build summary line\n let summaryLine: string\n if (ok) {\n summaryLine = node.successLabel\n ? `${node.key}: ${node.successLabel}`\n : `${node.key}: ${parsed.summary}`\n } else {\n summaryLine = node.failureLabel\n ? `${node.key}: ${node.failureLabel}`\n : `${node.key}: ${parsed.summary}`\n }\n\n let result: TaskResult = {\n key: node.key,\n path,\n ok,\n code,\n durationMs,\n output,\n summaryLine,\n metrics: parsed.metrics,\n }\n\n // If this task has reporting dependencies, wait for them and check for suppression\n if (this.dependencyTracker.hasDependencies(path)) {\n await this.dependencyTracker.waitForDependencies(path)\n\n // Check if any dependency failed - if so, suppress this task's failure\n if (!ok) {\n const failedDep = this.dependencyTracker.getFailedDependency(path)\n if (failedDep) {\n result = {\n ...result,\n suppressed: true,\n suppressedBy: failedDep,\n }\n }\n }\n }\n\n // Record result in tracker before emitting\n this.dependencyTracker.recordResult(result)\n this.callbacks.onTaskComplete?.(result)\n return result\n }\n}\n","// Types\n\n// Config helpers\nexport {\n defineConfig,\n defineTask,\n findConfigFile,\n loadConfig,\n loadConfigFromCwd,\n mergeOptions,\n} from \"./config.js\"\n// Discovery\nexport {\n type DiscoveredPackage,\n discoverPackages,\n hasPackageChanged,\n} from \"./discovery.js\"\n// Init\nexport {\n type DetectedTask,\n detectTasks,\n generateConfigContent,\n type InitOptions,\n type InitResult,\n type OutputFormat,\n runInit,\n} from \"./init/index.js\"\n// Parsers\nexport {\n biomeParser,\n defaultRegistry,\n genericParser,\n gotestParser,\n ParserRegistry,\n tscParser,\n vitestParser,\n} from \"./parsers/index.js\"\n\n// Reporter\nexport {\n createReporter,\n JSONReporter,\n LiveDashboardReporter,\n QuietReporter,\n type Reporter,\n SequentialReporter,\n TTYReporter,\n} from \"./reporter.js\"\n// Runner\nexport { type RunnerCallbacks, VerificationRunner } from \"./runner.js\"\nexport type {\n ExecutionStrategy,\n OutputParser,\n PackageDiscoveryOptions,\n ParsedResult,\n TaskResult,\n VerificationCommand,\n VerificationNode,\n VerifyConfig,\n VerifyOptions,\n VerifyResult,\n} from \"./types.js\"\n\nimport { loadConfigFromCwd, mergeOptions } from \"./config.js\"\nimport { createReporter } from \"./reporter.js\"\nimport { VerificationRunner } from \"./runner.js\"\n// Main verify function\nimport type { VerifyConfig, VerifyOptions, VerifyResult } from \"./types.js\"\n\n/**\n * Run verification with the given config and options\n */\nexport async function verify(\n config: VerifyConfig,\n cliOptions?: Partial<VerifyOptions>,\n): Promise<VerifyResult> {\n const options = mergeOptions(config.options, cliOptions)\n const reporter = createReporter(options)\n\n // Initialize reporter with task list (for live dashboard)\n reporter.onStart?.(config.tasks)\n\n const runner = new VerificationRunner(options, undefined, {\n onTaskStart: (path, key) => reporter.onTaskStart(path, key),\n onTaskComplete: result => reporter.onTaskComplete(result),\n })\n\n const result = await runner.run(config.tasks)\n\n // Cleanup reporter (stop spinner, restore cursor)\n reporter.onFinish?.()\n\n reporter.outputLogs(result.tasks, options.logs ?? \"failed\")\n reporter.outputSummary(result)\n\n return result\n}\n\n/**\n * Run verification from config file in cwd\n */\nexport async function verifyFromConfig(\n cwd: string = process.cwd(),\n cliOptions?: Partial<VerifyOptions>,\n): Promise<VerifyResult> {\n const config = await loadConfigFromCwd(cwd, cliOptions?.cwd)\n\n if (!config) {\n throw new Error(\n `No verify config found in ${cwd}. Create a verify.config.ts file.`,\n )\n }\n\n return verify(config, { ...cliOptions, cwd })\n}\n"],"mappings":"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","names":["existsSync","join","join","existsSync","existsSync","join","existsSync","resolve","errors","resolve","durationMs","result","result"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@halecraft/verify",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Hierarchical verification runner with parallel execution and terse output",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"bin": {
|
|
13
|
+
"verify": "./bin/verify.mjs"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"bin"
|
|
18
|
+
],
|
|
19
|
+
"keywords": [
|
|
20
|
+
"verify",
|
|
21
|
+
"test",
|
|
22
|
+
"lint",
|
|
23
|
+
"monorepo",
|
|
24
|
+
"parallel"
|
|
25
|
+
],
|
|
26
|
+
"author": "Duane Johnson <duane.johnson@gmail.com>",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/halecraft/verify"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/halecraft/verify#readme",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/halecraft/verify/issues"
|
|
34
|
+
},
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@inquirer/prompts": "^7.0.0",
|
|
38
|
+
"tree-kill": "^1.2.2"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@biomejs/biome": "^2.3.11",
|
|
42
|
+
"@types/node": "^25.0.6",
|
|
43
|
+
"@typescript/native-preview": "7.0.0-dev.20260103.1",
|
|
44
|
+
"tsup": "^8.5.0",
|
|
45
|
+
"typescript": "~5.8.3",
|
|
46
|
+
"vitest": "^4.0.16"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"typescript": ">=5.0.0"
|
|
50
|
+
},
|
|
51
|
+
"peerDependenciesMeta": {
|
|
52
|
+
"typescript": {
|
|
53
|
+
"optional": true
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=18.0.0"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"build": "tsup",
|
|
61
|
+
"verify": "./bin/verify.mjs"
|
|
62
|
+
}
|
|
63
|
+
}
|