diff --git a/packages/docker-doctor/src/agents/sanitize.ts b/packages/docker-doctor/src/agents/sanitize.ts index 671d491..fe59113 100644 --- a/packages/docker-doctor/src/agents/sanitize.ts +++ b/packages/docker-doctor/src/agents/sanitize.ts @@ -25,7 +25,7 @@ const flatten = (value: string, maxLength: number): string => { export const sanitizeMessage = (message: string): string => flatten(message, MAX_MESSAGE_LENGTH); -// Paths are attacker-controlled in the same way messages are -- a filename -// may legally contain newlines and ANSI escapes on every platform we run on. +// Paths are attacker-controlled in the same way messages are. On Linux and +// macOS a filename may contain newlines and ANSI escapes. export const sanitizePath = (filePath: string): string => flatten(filePath, MAX_PATH_LENGTH); diff --git a/packages/docker-doctor/src/agents/skill-install.ts b/packages/docker-doctor/src/agents/skill-install.ts index 36a7006..9b7fb7e 100644 --- a/packages/docker-doctor/src/agents/skill-install.ts +++ b/packages/docker-doctor/src/agents/skill-install.ts @@ -31,7 +31,7 @@ export const getSkillSourceDirectory = (): string | null => { // default, or each agent's global dir (e.g. ~/.claude/skills; universal // agents share ~/.agents/skills) when `global`. // Best-effort: returns null when the bundled skill is missing or the install -// throws — callers treat that as "skill not installed", never as a failure. +// throws. export const installSkillForAgents = async ( agents: SkillAgentType[], options: { projectRoot: string; global?: boolean } diff --git a/packages/docker-doctor/src/cli.ts b/packages/docker-doctor/src/cli.ts index 1db76c3..bcfbd46 100644 --- a/packages/docker-doctor/src/cli.ts +++ b/packages/docker-doctor/src/cli.ts @@ -583,7 +583,6 @@ const runRulesEngine = async ( await setTimeout(100); } - // 1. Scan Dockerfiles in parallel const dockerfileResults = await Promise.all( project.dockerfiles.map(async (df): Promise => { const fullPath = path.join(rootDir, df); @@ -623,7 +622,6 @@ const runRulesEngine = async ( await setTimeout(100); } - // 2. Scan Compose files in parallel const composeResults = await Promise.all( project.composeFiles.map(async (cf): Promise => { const fullPath = path.join(rootDir, cf); @@ -675,7 +673,6 @@ const WHITESPACE_RUN = /\s+/gu; const flattenMessage = (message: string): string => message.replaceAll(WHITESPACE_RUN, " ").trim(); -// Exit 2 wins over 1 whenever any file went unanalyzed, in every output mode. const scanExitCode = (scanIncomplete: boolean, failing: boolean): number => { if (scanIncomplete) { return SCAN_FAILURE_EXIT_CODE; @@ -830,7 +827,6 @@ const writeMachineReport = ( console.log(JSON.stringify(report, null, 2)); }; -// Prints the result in the requested output mode and returns the exit code. const writeScanOutput = async ( scan: ScanOutcome, options: OutputOptions @@ -953,7 +949,6 @@ program .description("Static analysis for Dockerfile and Docker Compose files") .version(packageJson.version, "-V, --version", "display the version number"); -// The default scan command's options, as commander parses them. interface ScanOptions { config?: string; json: boolean; @@ -961,7 +956,6 @@ interface ScanOptions { verbose: boolean; } -// Default scan command program .argument("[dir]", "directory to scan", ".") .option("-v, --verbose", "show verbose diagnostics description", false) @@ -1034,7 +1028,6 @@ program } setStatus("Loading configuration..."); - // Load config first // Warnings go to stderr so the --json and --score stdout contracts // stay machine-readable. const configPath = await resolveConfigPath(options.config, rootDir); @@ -1045,7 +1038,6 @@ program setStatus("Scanning workspace files..."); - // Project discovery, minus anything the config ignores const project = await discoverProject(rootDir, { ignoreFiles: config.ignore?.files, onSkippedDirectory: (skippedDir) => { @@ -1055,7 +1047,6 @@ program }, }); - // Collect all diagnostics const fileContents: Record = {}; const projectFilesList = [ @@ -1247,7 +1238,6 @@ program process.exitCode = result.failed.length > 0 ? 1 : 0; }); -// Rules subcommand group const rules = program .command("rules") .description("manage and list configuration rules"); diff --git a/packages/docker-doctor/src/formatters/terminal.ts b/packages/docker-doctor/src/formatters/terminal.ts index faae156..56c1f69 100644 --- a/packages/docker-doctor/src/formatters/terminal.ts +++ b/packages/docker-doctor/src/formatters/terminal.ts @@ -10,8 +10,6 @@ import chalk from "chalk"; import { hasText } from "../text"; -// True for a line number a code frame can point at. A missing, zero or NaN -// line gets no frame, as the truthiness test before it decided. const isLineNumber = (line: number | undefined): line is number => line !== undefined && line !== 0 && !Number.isNaN(line); @@ -56,7 +54,6 @@ const printDiscoveredFiles = (project: ProjectInfo): void => { }; const printMigrationWarning = (diagnostics: Diagnostic[]): void => { - // Migration-scale checks: the same rule firing many times. const findingsByRule = new Map< string, { count: number; files: Set } @@ -137,7 +134,6 @@ const printDiagnosticsByFile = ( ): void => { console.log(`\nFound ${chalk.bold(diagnostics.length)} issue(s):`); - // Group by file const filesGrouped = new Map(); for (const d of diagnostics) { @@ -168,7 +164,6 @@ const printDiagnosticsByFile = ( const lineInfo = isLineNumber(d.line) ? `:${d.line}` : ""; console.log(` ${sevColor(prefix)} [${chalk.dim(d.rule)}]${lineInfo}`); - // Print Code Frame const content = fileContents[file]; printCodeFrame(content, d.line, sevColor); @@ -380,7 +375,6 @@ export const formatTerminal = async ( printDiscoveredFiles(project); } - // Calculate scores per category once const categoryIssueCounts = { "Best Practices": 0, Compose: 0, diff --git a/packages/docker-doctor/src/index.ts b/packages/docker-doctor/src/index.ts index bb585e7..080f056 100644 --- a/packages/docker-doctor/src/index.ts +++ b/packages/docker-doctor/src/index.ts @@ -1,6 +1,5 @@ import packageJson from "../package.json" with { type: "json" }; -// Re-export core programmatic API export { discoverProject, parseDockerfile, diff --git a/packages/docker-doctor/src/text.ts b/packages/docker-doctor/src/text.ts index d033f34..99b8e4b 100644 --- a/packages/docker-doctor/src/text.ts +++ b/packages/docker-doctor/src/text.ts @@ -1,4 +1,2 @@ -// True for a string with at least one character, which is what a truthiness -// test on a string that may be missing checked. export const hasText = (value: string | null | undefined): value is string => value !== undefined && value !== null && value !== ""; diff --git a/packages/docker-doctor/src/workflow-scaffold.ts b/packages/docker-doctor/src/workflow-scaffold.ts index 5a5d2dc..24666c3 100644 --- a/packages/docker-doctor/src/workflow-scaffold.ts +++ b/packages/docker-doctor/src/workflow-scaffold.ts @@ -15,7 +15,6 @@ const fileExists = async (filePath: string): Promise => { } }; -// `dir` and each of its ancestors, nearest first. const selfAndAncestors = (dir: string): string[] => { const dirs = [dir]; let parent = path.dirname(dir); @@ -51,8 +50,6 @@ const findRepositoryRoot = async (dir: string): Promise => { // workflow without consent. GitHub only runs workflows from the repository // root, so a scan of a subdirectory writes the workflow at that root and // passes the subdirectory as the action's `directory` input. -// confirmOverwrite is injected so the caller owns the prompt and the -// function is testable without a TTY. export const scaffoldActionWorkflow = async (options: { actionRef: string; confirmOverwrite: () => Promise;