import chalk from "chalk"; import { APP_PATHS } from "../paths"; import type { CheckError, SyncCheckResult } from "./shared"; export function formatSyncCheckReport(result: SyncCheckResult): string { const lines: string[] = []; lines.push(chalk.bold("docs-sync-check: Checking source-documentation correspondence...\n")); const checked = result.filesChecked; if (result.errors.length > 0) { lines.push(chalk.red.bold("Errors:\n")); const byCategory = new Map(); for (const error of result.errors) { const existing = byCategory.get(error.category) ?? []; existing.push(error); byCategory.set(error.category, existing); } for (const [category, categoryErrors] of byCategory) { lines.push(chalk.cyan(` Category: ${category}\n`)); for (const error of categoryErrors) { if (error.type === "missing-doc") { lines.push(` ${chalk.red(error.sourcePath)}`); lines.push(` ${chalk.yellow("Missing documentation for:")} ${error.expectedBasename}`); } else if (error.type === "orphaned-doc") { lines.push(` ${chalk.red(error.docPath)}`); lines.push( ` ${chalk.yellow("Orphaned documentation:")} no source file for ${error.expectedBasename}`, ); } else if (error.type === "missing-test-case") { lines.push(` ${chalk.red(error.sourcePath)}`); lines.push( ` ${chalk.yellow("Missing test case:")} "${error.expectedBasename}" is in doc but not in test`, ); } else if (error.type === "extra-test-case") { lines.push(` ${chalk.red(error.sourcePath)}`); lines.push( ` ${chalk.yellow("Extra test case:")} "${error.expectedBasename}" is in test but not in doc`, ); } else if (error.type === "missing-test-file") { lines.push(` ${chalk.red(error.docPath)}`); lines.push(` ${chalk.yellow("Missing test file:")} ${error.expectedBasename}`); } else if (error.type === "orphaned-spec") { lines.push(` ${chalk.red(error.sourcePath)}`); lines.push( ` ${chalk.yellow("Orphaned spec file:")} no matching business flow for ${error.expectedBasename}`, ); } else if (error.type === "missing-actor-doc") { lines.push(` ${chalk.red(error.sourcePath)}`); lines.push( ` ${chalk.yellow("Missing actor doc:")} no ${APP_PATHS.docs.actor}/${error.expectedBasename} for fixture actor`, ); } else if (error.type === "missing-actor-fixture") { lines.push(` ${chalk.red(error.docPath)}`); lines.push( ` ${chalk.yellow("Missing actor fixture:")} no e2e fixture for actor "${error.expectedBasename}"`, ); } else if (error.type === "missing-page-object") { lines.push(` ${chalk.red(error.docPath)}`); lines.push( ` ${chalk.yellow("Missing page object:")} no e2e page object for ${error.expectedBasename}`, ); } else if (error.type === "missing-spec-fixture") { lines.push(` ${chalk.red(error.sourcePath)}`); lines.push( ` ${chalk.yellow("Missing spec fixture:")} no e2e/fixtures/${error.expectedBasename} for spec file`, ); } lines.push(""); } } } else if (checked === 0) { lines.push(chalk.yellow("No files were checked — verify the path.\n")); } else { lines.push(chalk.green("All source files have corresponding documentation.\n")); } lines.push(chalk.bold("Summary:")); lines.push(` Files checked: ${checked}`); lines.push(` Errors: ${result.errors.length}`); lines.push(""); if (result.errors.length > 0) { lines.push(chalk.red.bold(`docs-sync-check failed with ${result.errors.length} error(s).`)); } else if (checked === 0) { lines.push(chalk.red.bold("docs-sync-check failed: no files were checked.")); } else { lines.push(chalk.green.bold("docs-sync-check passed.")); } return lines.join("\n"); }