@d3lm/lint-preset 1.4.6 → 1.5.1
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/README.md +166 -0
- package/dist/bin/comments.js +3215 -0
- package/dist/bin/comments.js.map +1 -0
- package/dist/{chunk-AWWQD6SG.cjs → chunk-M3BAUCCR.cjs} +19 -27
- package/dist/chunk-M3BAUCCR.cjs.map +1 -0
- package/dist/{chunk-HEPSJI2W.js → chunk-SMTCD6GW.js} +19 -27
- package/dist/chunk-SMTCD6GW.js.map +1 -0
- package/dist/comments.cjs +1462 -0
- package/dist/comments.cjs.map +1 -0
- package/dist/comments.d.cts +257 -0
- package/dist/comments.d.ts +257 -0
- package/dist/comments.js +1460 -0
- package/dist/comments.js.map +1 -0
- package/dist/eslint.cjs +9 -9
- package/dist/eslint.js +1 -1
- package/dist/oxlint.cjs +10 -12
- package/dist/oxlint.cjs.map +1 -1
- package/dist/oxlint.js +6 -8
- package/dist/oxlint.js.map +1 -1
- package/dist/rules.cjs +50 -11
- package/dist/rules.cjs.map +1 -1
- package/dist/rules.js +50 -11
- package/dist/rules.js.map +1 -1
- package/package.json +13 -1
- package/dist/chunk-AWWQD6SG.cjs.map +0 -1
- package/dist/chunk-HEPSJI2W.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/comments/cli.ts","../../src/comments/agent.ts","../../src/comments/analyze.ts","../../src/comments/style.ts","../../src/comments/wrap.ts","../../src/comments/config.ts","../../src/comments/flow.ts","../../src/comments/git.ts","../../src/comments/project.ts","../../src/comments/terminal.ts","../../src/comments/bin.ts"],"sourcesContent":["import { existsSync, realpathSync, statSync } from 'node:fs';\nimport path from 'node:path';\nimport { parseArgs } from 'node:util';\nimport { CHILD_ENV } from './agent.js';\nimport {\n hasVerdictIssues,\n isSuspicious,\n rewrapComment,\n type CommentReport,\n type IssueReport,\n type IssueTier,\n} from './analyze.js';\nimport { loadConfig, type AgentRunner, type AgentScope, type CommentsConfig, type HookMode } from './config.js';\nimport {\n createLogReporter,\n describeSkipped,\n describeSummary,\n runFlow,\n skippedFiles,\n type FlowOptions,\n type FlowSummary,\n} from './flow.js';\nimport { findRepoRoot } from './git.js';\nimport { Project, type FileAnalysis, type Scope } from './project.js';\nimport { isLiveTerminal, TerminalUI } from './terminal.js';\n\nconst HELP = `\nUsage: comments <command> [targets...] [options]\n\nFinds comments in JavaScript and TypeScript files and measures how their prose fits the configured width.\nOnly agent and hook change files, by applying the exact rewrap to comments that still have layout issues.\n\nCommands:\n list Print comments in scope with their line lengths, issues, and rewrap suggestions\n check Print comments with layout violations and exit with code 1 if any remain\n wrap Print the exact rewrap of the comment at each file:line target\n agent Hand comments in scope to an agent, then report any that still have issues\n hook Stop-hook entry point for agents (reads the hook payload from stdin)\n\nTargets are files, directories, file:line, or file:start-end. Without targets, only comments\noverlapping uncommitted changes (and untracked files) are considered.\n\nOptions:\n --staged Only consider staged changes\n --base <ref> Consider changes since the merge base with <ref>\n --repo Consider every file in the repository\n --suspicious Only comments with layout issues (overflow, early line ends, last lines of one or two words)\n or hints (possible orphans, em-dashes, banners, ...). For agent and hook (the default), only\n comments with hints or with issues in parts the tool never rewraps, a triage, not a full review\n --all agent, hook: hand every comment in scope to the agent for a full review of its wording\n --verbose agent, hook: print every agent's reply (otherwise a terminal offers to open them)\n --no-interactive agent: show the agents while they run, then exit without offering to open their replies\n --json Print JSON\n --config <path> Use this config file instead of searching for one\n --cwd <dir> Run as if started in <dir> (targets and --config resolve against it)\n --host <host> hook: the agent running the hook (cursor, claude, codex)\n --runner <name> agent, hook: the agent CLI to spawn (claude, codex, cursor)\n --mode <mode> hook: agent, report, or off\n -h, --help Show this help\n\nConfig overrides (take precedence over the config file):\n --width <n> Preferred comment line length\n --max-width <n> Hard limit for prose (default: 120, never below width)\n --single-line-width <n> Longest line a one-paragraph comment may stay on (default: 120)\n --tolerance <n> Legacy hard limit of width + n, unless max-width is set\n --[no-]orphans Keep a sentence's first word off the end of a line, and end the first of two lines\n with a sentence when the second is no longer than the first (default: on)\n --[no-]style Look for possible semicolons, em-dashes, dashes, label colons, emphasis, and banners\n as hints (default: on). The agent's rules apply either way\n --ignore <glob> Skip matching files, repeatable\n --model <name> agent, hook: model for the agent\n --timeout <seconds> agent, hook: how long to wait for each agent (default: 300)\n --batch-size <n> agent, hook: most comments per agent (default: 20)\n --max-files <n> agent, hook: most files per agent (default: 10)\n --max-agents <n> agent, hook: most agents running at once (default: 6)\n --instructions <text> agent, hook: extra instructions appended to the rules\n`.trim();\n\nconst RUNNERS = new Set<string>(['claude', 'codex', 'cursor']);\nconst MODES = new Set<string>(['agent', 'report', 'off']);\n\nconst OPTIONS = {\n tolerance: { type: 'string' },\n orphans: { type: 'boolean' },\n style: { type: 'boolean' },\n ignore: { type: 'string', multiple: true },\n model: { type: 'string' },\n timeout: { type: 'string' },\n 'batch-size': { type: 'string' },\n 'max-files': { type: 'string' },\n 'max-agents': { type: 'string' },\n instructions: { type: 'string' },\n staged: { type: 'boolean' },\n base: { type: 'string' },\n repo: { type: 'boolean' },\n suspicious: { type: 'boolean' },\n all: { type: 'boolean' },\n verbose: { type: 'boolean' },\n interactive: { type: 'boolean' },\n json: { type: 'boolean' },\n width: { type: 'string' },\n 'max-width': { type: 'string' },\n 'single-line-width': { type: 'string' },\n config: { type: 'string' },\n cwd: { type: 'string' },\n host: { type: 'string' },\n runner: { type: 'string' },\n mode: { type: 'string' },\n help: { type: 'boolean', short: 'h' },\n} as const;\n\nfunction parse(argv: readonly string[]) {\n return parseArgs({ args: [...argv], allowPositionals: true, allowNegative: true, options: OPTIONS });\n}\n\ntype Values = ReturnType<typeof parse>['values'];\n\n/**\n * Reads the command, the host, and the help flag without failing on arguments that `parse` rejects,\n * so that the hook can report them in the format of its host.\n */\nfunction peek(argv: readonly string[]): { command?: string; host?: string; help: boolean } {\n const { values, positionals } = parseArgs({\n args: [...argv],\n allowPositionals: true,\n allowNegative: true,\n options: OPTIONS,\n strict: false,\n });\n\n return {\n command: positionals.at(0),\n host: typeof values.host === 'string' ? values.host : undefined,\n help: values.help === true,\n };\n}\n\nexport function log(message: string): void {\n process.stderr.write(`${message}\\n`);\n}\n\n/**\n * Returns the directory without symlinks, like `process.cwd()` and the repository root that git\n * reports. A path through a symlink would otherwise seem to lie outside of the repository.\n */\nfunction resolveCwd(directory: string, source = '--cwd'): string {\n const resolved = path.resolve(directory);\n\n if (!existsSync(resolved) || !statSync(resolved).isDirectory()) {\n throw new Error(`comments: ${source} ${directory} is not a directory`);\n }\n\n return realpathSync(resolved);\n}\n\nfunction parseInteger(name: string, value: string | undefined, minimum: number): number | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n const number = Number(value);\n\n if (!Number.isInteger(number) || number < minimum) {\n throw new Error(`comments: --${name} must be an integer of at least ${minimum}, got ${value}`);\n }\n\n return number;\n}\n\nfunction defined<T extends object>(object: T): Partial<T> {\n return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== undefined)) as Partial<T>;\n}\n\nfunction applyOverrides(config: CommentsConfig, values: Values): CommentsConfig {\n const overrides = defined({\n width: parseInteger('width', values.width, 1),\n maxWidth: parseInteger('max-width', values['max-width'], 1),\n singleLineWidth: parseInteger('single-line-width', values['single-line-width'], 1),\n tolerance: parseInteger('tolerance', values.tolerance, 0),\n avoidSentenceOrphans: values.orphans,\n style: values.style,\n ignore: values.ignore ? [...(config.ignore ?? []), ...values.ignore] : undefined,\n });\n\n const agent = defined({\n model: values.model,\n timeout: parseInteger('timeout', values.timeout, 1),\n batchSize: parseInteger('batch-size', values['batch-size'], 1),\n maxFiles: parseInteger('max-files', values['max-files'], 1),\n maxAgents: parseInteger('max-agents', values['max-agents'], 1),\n instructions: values.instructions,\n });\n\n return { ...config, ...overrides, agent: { ...config.agent, ...agent } };\n}\n\nasync function createProject(cwd: string, values: Values) {\n const repoRoot = findRepoRoot(cwd);\n const root = repoRoot ?? cwd;\n const loaded = await loadConfig(cwd, { explicitPath: values.config, stopDir: root });\n const config = applyOverrides(loaded.config, values);\n const project = new Project(root, config, { isGitRepo: repoRoot !== undefined, cwd });\n\n return { project, configPath: loaded.filepath };\n}\n\nfunction scopeFrom(positionals: readonly string[], values: Values): Scope {\n return { targets: positionals, staged: values.staged, base: values.base, repo: values.repo };\n}\n\nfunction selectFrom(values: Values, project: Project): AgentScope {\n if (values.all) {\n return 'all';\n }\n\n return values.suspicious ? 'suspicious' : (project.config.agent?.scope ?? 'suspicious');\n}\n\nfunction formatIssue(issue: IssueReport): string {\n return issue.tier === 'hint' ? `${issue.type} (hint)` : issue.type;\n}\n\nfunction formatComment(comment: CommentReport): string {\n const issueList = comment.paragraphs.flatMap((paragraph) => paragraph.issues);\n const issues = new Map<number, string[]>();\n\n for (const issue of issueList) {\n issues.set(issue.line, [...(issues.get(issue.line) ?? []), formatIssue(issue)]);\n }\n\n const typesOf = (tier: IssueTier): string[] => {\n return [...new Set(issueList.filter((issue) => issue.tier === tier).map((issue) => issue.type))];\n };\n\n const verdicts = typesOf('verdict');\n const hints = typesOf('hint');\n\n const labels = [\n ...(verdicts.length > 0 ? [`suspicious: ${verdicts.join(', ')}`] : []),\n ...(hints.length > 0 ? [`hints: ${hints.join(', ')}`] : []),\n ];\n\n const status = labels.length > 0 ? labels.join(', ') : 'ok';\n const range = `${comment.startLine}-${comment.endLine}`;\n const location = comment.startLine === comment.endLine ? comment.startLine : range;\n const maximum = comment.maxWidth === undefined ? '' : `, maximum ${comment.maxWidth}`;\n const output = [`${comment.file}:${location} ${comment.kind}, width ${comment.width}, ${status}${maximum}`];\n const lines = comment.text.split('\\n');\n const numberWidth = String(comment.endLine).length;\n\n for (const [offset, text] of lines.entries()) {\n const line = comment.startLine + offset;\n const marks = issues.get(line);\n const length = String(comment.lengths[offset]).padStart(3);\n\n output.push(\n ` ${String(line).padStart(numberWidth)} ${length} | ${text}${marks ? ` <- ${marks.join(', ')}` : ''}`,\n );\n }\n\n return output.join('\\n');\n}\n\nfunction printComments(comments: readonly CommentReport[], values: Values): void {\n if (values.json) {\n process.stdout.write(`${JSON.stringify(comments, null, 2)}\\n`);\n return;\n }\n\n for (const comment of comments) {\n process.stdout.write(`${formatComment(comment)}\\n\\n`);\n }\n}\n\nfunction commentsOf(analyses: readonly FileAnalysis[]): CommentReport[] {\n return analyses.flatMap((analysis) => analysis.comments);\n}\n\n/**\n * An empty result from the default scope is easy to mistake for a bug.\n */\nfunction hintEmptyScope(analyses: readonly FileAnalysis[], scope: Scope): void {\n const isDefaultScope = (scope.targets ?? []).length === 0 && !scope.repo && !scope.base;\n\n if (analyses.length === 0 && isDefaultScope) {\n const changes = scope.staged ? 'staged changes' : 'uncommitted changes';\n\n log(\n `comments: no ${changes} in JavaScript or TypeScript files. Pass --repo, --base <ref>, or files to widen the scope.`,\n );\n }\n}\n\n/**\n * A file without any output looks like a file whose comments are fine, so a skipped file is named.\n */\nfunction warnSkipped(analyses: readonly FileAnalysis[]): void {\n for (const skipped of skippedFiles(analyses)) {\n log(`comments: ${describeSkipped(skipped)}`);\n }\n}\n\nfunction parseRunner(value: string | undefined): AgentRunner | undefined {\n if (value !== undefined && !RUNNERS.has(value)) {\n throw new Error(`comments: unknown runner ${value}, expected claude, codex, or cursor`);\n }\n\n return value as AgentRunner | undefined;\n}\n\nasync function runWrap(project: Project, targets: readonly string[], values: Values): Promise<number> {\n if (targets.length === 0 || targets.some((target) => !/:\\d+(?:-\\d+)?$/.test(target))) {\n throw new Error('comments: wrap expects file:line targets, e.g. `comments wrap src/a.ts:12`');\n }\n\n const results: { file: string; startLine: number; endLine: number; text: string }[] = [];\n\n for (const target of targets) {\n const analyses = await project.analyze({ targets: [target] });\n const comments = commentsOf(analyses);\n const skipped = skippedFiles(analyses).at(0);\n\n if (skipped) {\n throw new Error(`comments: ${describeSkipped(skipped)}`);\n }\n\n if (comments.length === 0) {\n throw new Error(`comments: no comment at ${target}`);\n }\n\n for (const comment of comments) {\n results.push({\n file: comment.file,\n startLine: comment.startLine,\n endLine: comment.endLine,\n text: rewrapComment(comment),\n });\n }\n }\n\n if (values.json) {\n process.stdout.write(`${JSON.stringify(results, null, 2)}\\n`);\n } else {\n process.stdout.write(`${results.map((result) => result.text).join('\\n\\n')}\\n`);\n }\n\n return 0;\n}\n\nasync function readStdin(): Promise<string> {\n if (process.stdin.isTTY) {\n return '';\n }\n\n const chunks: Buffer[] = [];\n\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n\n return Buffer.concat(chunks).toString('utf8');\n}\n\ninterface HookPayload {\n readonly cwd?: string;\n readonly workspace_roots?: readonly string[];\n readonly status?: string;\n}\n\nfunction hookOutput(host: string, message: string | undefined): string {\n // cursor's stop hook has no field for user-facing messages, so the summary only goes to stderr\n if (host === 'cursor' || !message) {\n return '{}';\n }\n\n return JSON.stringify({ systemMessage: message });\n}\n\nfunction parsePayload(raw: string): HookPayload {\n const payload: unknown = raw.trim() ? JSON.parse(raw) : {};\n\n return payload !== null && typeof payload === 'object' ? payload : {};\n}\n\nfunction payloadDirectory(payload: HookPayload): string | undefined {\n const roots: unknown = payload.workspace_roots;\n const candidates: unknown[] = [Array.isArray(roots) ? roots.at(0) : undefined, payload.cwd];\n\n return candidates.find((candidate): candidate is string => typeof candidate === 'string' && candidate !== '');\n}\n\n/**\n * Never throws, not even for arguments it can't parse. Hosts read a failing stop hook as a reason\n * to keep the agent going, so every error becomes a message instead.\n */\nasync function runHook(argv: readonly string[]): Promise<void> {\n const host = peek(argv).host ?? 'claude';\n\n let message: string | undefined;\n\n try {\n const { values, positionals } = parse(argv);\n\n if (!RUNNERS.has(host)) {\n throw new Error(`comments: unknown host ${host}, expected cursor, claude, or codex`);\n }\n\n const payload = parsePayload(await readStdin());\n\n if (process.env[CHILD_ENV] || (payload.status !== undefined && payload.status !== 'completed')) {\n return;\n }\n\n const directory = values.cwd ?? payloadDirectory(payload);\n const source = values.cwd === undefined ? 'the hook directory' : '--cwd';\n const cwd = directory === undefined ? process.cwd() : resolveCwd(directory, source);\n const { project, configPath } = await createProject(cwd, values);\n const mode = (values.mode ?? project.config.hook?.mode ?? 'agent') as HookMode;\n\n if (!MODES.has(mode)) {\n throw new Error(`comments: unknown mode ${mode}`);\n }\n\n if (mode === 'off') {\n return;\n }\n\n const summary = await runFlow(project, scopeFrom(positionals.slice(1), values), {\n mode,\n select: selectFrom(values, project),\n runner: parseRunner(values.runner) ?? project.config.agent?.runner ?? (host as AgentRunner),\n configPath,\n reporter: createLogReporter(log, { verbose: values.verbose }),\n });\n\n message = describeSummary(summary);\n } catch (error) {\n message = `comments: ${(error as Error).message.replace(/^comments: /, '')}`;\n } finally {\n if (message) {\n log(message);\n }\n\n process.stdout.write(`${hookOutput(host, message)}\\n`);\n }\n}\n\nexport async function main(argv: readonly string[]): Promise<number> {\n const peeked = peek(argv);\n\n if (peeked.command === 'hook' && !peeked.help) {\n await runHook(argv);\n return 0;\n }\n\n const { values, positionals } = parse(argv);\n const [command, ...targets] = positionals;\n\n if (values.help || !command || command === 'help') {\n process.stdout.write(HELP);\n return 0;\n }\n\n const cwd = values.cwd ? resolveCwd(values.cwd) : process.cwd();\n const { project, configPath } = await createProject(cwd, values);\n const scope = scopeFrom(targets, values);\n\n switch (command) {\n case 'list': {\n const analyses = await project.analyze(scope);\n\n const comments = commentsOf(analyses);\n\n printComments(values.suspicious ? comments.filter((comment) => isSuspicious(comment)) : comments, values);\n warnSkipped(analyses);\n hintEmptyScope(analyses, scope);\n return 0;\n }\n case 'check': {\n const analyses = await project.analyze(scope);\n\n const comments = commentsOf(analyses).filter((comment) => hasVerdictIssues(comment));\n\n printComments(comments, values);\n warnSkipped(analyses);\n hintEmptyScope(analyses, scope);\n\n if (!values.json) {\n log(comments.length > 0 ? `${comments.length} comment(s) with layout issues` : 'all comments fit the width');\n }\n\n return comments.length > 0 ? 1 : 0;\n }\n case 'wrap': {\n return runWrap(project, targets, values);\n }\n case 'agent': {\n const options: FlowOptions = {\n mode: 'agent',\n select: selectFrom(values, project),\n runner: parseRunner(values.runner) ?? project.config.agent?.runner ?? 'claude',\n configPath,\n };\n\n let summary: FlowSummary;\n\n if (isLiveTerminal()) {\n const ui = new TerminalUI();\n\n ui.begin('comments agent');\n\n try {\n summary = await runFlow(project, scope, { ...options, reporter: ui.reporter });\n } catch (error) {\n ui.dispose();\n throw error;\n }\n\n await ui.finish(summary, {\n interactive: process.stdin.isTTY && values.interactive !== false,\n verbose: values.verbose,\n });\n } else {\n summary = await runFlow(project, scope, {\n ...options,\n reporter: createLogReporter(log, { verbose: values.verbose }),\n });\n\n log(describeSummary(summary) ?? 'comments: nothing to do');\n }\n\n const failed = summary.remaining.length > 0 || summary.codeChanged.length > 0 || summary.agentError;\n\n return failed ? 1 : 0;\n }\n default: {\n log(`comments: unknown command ${command}\\n`);\n process.stderr.write(HELP);\n return 2;\n }\n }\n}\n","import { spawn } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport type { CommentReport, IssueReport, IssueType, ParagraphReport } from './analyze.js';\nimport type { AgentConfig, AgentRunner } from './config.js';\n\n/**\n * This variable is set in the agent's environment so that the agent's own stop hook doesn't\n * spawn another agent.\n */\nexport const CHILD_ENV = 'COMMENTS_HOOK_CHILD';\n\nexport const DEFAULT_RULES = `\n# Comment rules\n\n## Priorities\n\nWhen rules pull in different directions, the earlier one wins.\n\n1. Keep code and exact text byte for byte, including every punctuation character in it. That covers code blocks, \\`@example\\`, code spans, identifiers, string literals like error messages, regexes, globs and other patterns like \\`*test*\\`, URLs, quoted text, titles, and notation like \\`host:port\\`.\n2. Keep the meaning. An edit may make a comment clearer, never different.\n3. Follow the style preferences below.\n4. Change as little as possible. Wording that already reads clearly stays, even when a note points at it.\n\n## Layout\n\n- After you finish, the tool rewraps prose paragraphs, list items, and JSDoc tag descriptions. The width is a preferred target. A parenthetical may extend a line up to the configured maximum so it stays together. In longer paragraphs, balanced lines take priority over keeping every parenthetical on one line. The tool also avoids short last lines where possible. Leave these line breaks to the tool, except for the sentence-orphan case below.\n- Don't end a line with the first word of a new sentence, clause, or parenthetical, like \\`This\\` after a period, \\`the\\` after a comma, or \\`(the\\`. Move it to the next line instead.\n- In a paragraph of two lines, the first line ends with a sentence whenever the rest fits on the second line and is no longer than the first. Don't end it with the start of the next sentence, like \\`A wrap\\` in \\`...lay out differently. A wrap\\`. Move those words to the second line instead.\n- A comment whose whole text is one paragraph stays on a single line when that line fits a separate, larger single-line width, even past the width. Only a longer comment wraps to the width.\n- Separate paragraphs with an empty comment line.\n- Never split a backtick code span across lines.\n- Keep code blocks, \\`@example\\`, lists, tables, box drawings, aligned columns, and Markdown hard line breaks (a line that ends with two spaces or a backslash) laid out as they are. List items wrap with their continuation lines indented to the item text, and a JSDoc tag description that doesn't fit continues on the next line without indentation.\n- The tool measures every line, taking the tolerance and the parts it keeps as written into account, and the notes on each comment list what is still wrong. Act on those notes. Don't count columns, and don't apply a stricter limit than the notes show.\n- The maximum is a hard limit for measured prose, including long tokens. If a URL, code span, or other exact text exceeds it, preserve that text and explain the unresolved overflow instead of changing its contents.\n- The tool never rewraps the parts it keeps as written, like a single-line block comment, a paragraph with hard line breaks, or lines that may be laid out by hand. When a note says one of their prose lines is too long, break or shorten it yourself. Exact text and intentional layout win over the width, so keep code, code spans, and the layout in them intact, and if a note can only be fixed by changing them, leave it and say why in your reply.\n\n## Style\n\nThese are preferences for comment prose. They never apply to code or exact text (see the priorities above), and a punctuation character on its own is never a reason to edit prose that already reads clearly.\n\n- Write clear sentences that flow. Descriptions read best as complete sentences with a subject and a verb, so prefer \"Returns the bytes the guest sent\" over a fragment like \\`Bytes from the guest.\\` or \\`Optional.\\` Imperative or third-person verb phrases like \"Resolve a hostname...\" or \"Aborts every channel...\" are fine, since the preference is against verb-less fragments, not against concise sentences.\n- Prefer plain sentence punctuation. Where a semicolon, an em-dash (—), or a spaced hyphen, en-dash, or double hyphen standing in for one only joins two thoughts, a period, a comma, parentheses, or a word like \"and\", \"so\", or \"because\" usually reads better. Keep the punctuation where it carries meaning or reads more clearly than the alternatives.\n- Prefer a sentence over a \"Label: explanation\" fragment, like \\`...the socket. Optional: without it...\\` or \\`Default: refuse\\` in the middle of prose. A colon is fine where it introduces a list, code block, or example, in a term's definition, in notation, in a quotation, and in a \\`Note:\\` or \\`Optional:\\` that starts a comment. A JSDoc tag like \\`@note\\` or \\`@todo\\` can replace a label, and \\`@default\\` fits a default value, not a description.\n- Avoid asterisk emphasis like \\`*this*\\`, and use plain wording instead. A name or pattern in asterisks, like \\`*test*\\` or \\`*.spec.ts\\`, is a pattern, so keep its asterisks and wrap it in a code span, like \\`\\` \\`*test*\\` \\`\\`.\n- Avoid section banner comments, i.e. dividers or headings made of dashes, equals signs, asterisks, or other repeated characters that split a file into visual sections. Let the code structure carry the grouping, or write one short, plain sentence comment (e.g. \\`// handlers for control mode\\`). Rules that belong to a diagram, a table, a box drawing, a Markdown document, an example, or a legal header aren't banners.\n- Block and JSDoc comments are capitalized and end with punctuation.\n- Never turn a block or JSDoc comment into \\`//\\` line comments, and never write a run of consecutive \\`//\\` lines.\n\n## Editing\n\n- Keep the wording unless it goes against a rule above. Then reword as little as needed and keep the meaning.\n- Don't reword anything else unless the instructions below allow it.\n`.trim();\n\nconst DEFAULT_TIMEOUT_SECONDS = 300;\nconst DEFAULT_CLAUDE_MODEL = 'haiku';\n\n/**\n * Sets the longest time an agent gets to exit after its timeout before it is killed.\n */\nconst KILL_GRACE_MS = 5000;\n\n/**\n * Sets how long to wait for the rest of the output after the agent exited. A process that the agent\n * left behind keeps the pipes open for as long as it runs.\n */\nconst DRAIN_GRACE_MS = 1000;\n\nconst RUNNER_COMMANDS: Record<AgentRunner, string> = {\n claude: 'claude',\n codex: 'codex',\n cursor: 'cursor-agent',\n};\n\nexport interface AgentInvocation {\n readonly command: string;\n readonly args: readonly string[];\n readonly stdin?: string;\n}\n\nexport interface AgentResult {\n readonly ok: boolean;\n readonly output: string;\n readonly error?: string;\n}\n\n// hints are phrased as possibilities, since they come from heuristics that the agent may reject\nconst ISSUE_DESCRIPTIONS: Record<Exclude<IssueType, 'overflow'>, string> = {\n underfill: 'ends early, and words from the next line fit on it',\n widow: 'leaves fewer than three words on the last line of its paragraph',\n unbalanced: 'is in a paragraph whose lines are less even than the suggested rewrap',\n orphan:\n 'may end with the start of a new sentence, clause, or parenthetical, which belongs on the next line (leave it if the period or comma before it is part of an abbreviation, a name, or notation like `No. 3`)',\n 'em-dash':\n \"may use an em-dash to join two thoughts (leave it if it's in a quotation, a title, or a string literal, or reads more clearly than the alternatives)\",\n banner:\n \"may be a section banner (leave it if it's part of a diagram, a table, a box, a Markdown rule, a separator in an example, or legal text)\",\n semicolon:\n \"may join clauses with a semicolon (leave it if it's code, a literal, not a clause join, or reads more clearly than a period or a joining word)\",\n 'label-colon':\n 'may use a colon after a label (leave it if it introduces a list or code, defines a term, is notation like a time or `key: value`, or is a `Note:` or `Optional:` that starts the comment)',\n emphasis:\n 'may use asterisk emphasis (leave the asterisks of a name or pattern like `*test*`, which belongs in a code span with its asterisks)',\n dash: \"may use a spaced hyphen, en-dash, or double hyphen as an em-dash (leave it if it's a range, a CLI argument, arithmetic, code, a term's definition, or reads more clearly than the alternatives)\",\n};\n\nconst HINT_MARKER = 'possible:';\n\nfunction describeIssue(issue: IssueReport, width: number, maxWidth?: number): string {\n if (issue.type === 'overflow') {\n const limit = maxWidth ?? width;\n const name = maxWidth === undefined ? 'width' : 'maximum';\n\n return `line ${issue.line} is ${issue.length} columns, over the ${name} of ${limit}`;\n }\n\n const description = `line ${issue.line} ${ISSUE_DESCRIPTIONS[issue.type]}`;\n\n return issue.tier === 'hint' ? `${HINT_MARKER} ${description}` : description;\n}\n\nfunction describeIssues(paragraph: ParagraphReport, width: number, maxWidth?: number): string[] {\n return paragraph.issues.map((issue) => describeIssue(issue, width, maxWidth));\n}\n\nfunction describeComment(comment: CommentReport): string {\n const notes: string[] = [];\n\n for (const paragraph of comment.paragraphs) {\n const issues = describeIssues(paragraph, comment.width, comment.maxWidth);\n\n if (issues.length > 0 && !paragraph.reflowable) {\n const range = `lines ${paragraph.startLine}-${paragraph.endLine}`;\n\n issues.push(\n `${range} are kept as written (${paragraph.reason ?? 'layout'}), so the tool never rewraps them and any fix to them is yours`,\n );\n }\n\n notes.push(...issues);\n }\n\n const fence = comment.text.includes('```') ? '~~~~' : '```';\n\n return [\n `### ${comment.file}:${comment.startLine}-${comment.endLine} (width ${comment.width}${comment.maxWidth === undefined ? '' : `, maximum ${comment.maxWidth}`})`,\n '',\n ...(notes.length > 0 ? notes.map((note) => `- ${note}`) : ['- no measured issues; review the wording and flow']),\n '',\n `${fence}ts`,\n comment.text,\n fence,\n ].join('\\n');\n}\n\nexport function loadRules(agent: AgentConfig, configPath: string | undefined): string {\n let rules = DEFAULT_RULES;\n\n if (agent.rules) {\n const base = configPath ? path.dirname(configPath) : process.cwd();\n\n rules = readFileSync(path.resolve(base, agent.rules), 'utf8');\n }\n\n return agent.instructions ? `${rules.trimEnd()}\\n\\n## Instructions\\n\\n${agent.instructions.trim()}\\n` : rules;\n}\n\nexport function buildPrompt(options: {\n readonly rules: string;\n readonly root: string;\n readonly comments: readonly CommentReport[];\n}): string {\n return [\n options.rules.trimEnd(),\n '',\n '## Task',\n '',\n `Fix the formatting of the comments below, following the rules above. Paths are relative to ${options.root}. Widths include indentation and the comment prefix. The notes under each comment come from the tool's measurements, so never count columns yourself.`,\n '',\n '- After you finish, the tool rewraps every prose paragraph as described under Layout, so a layout note on a prose paragraph needs no change from you. Change only the wording there, and leave its line breaks to the tool.',\n '- A note that a line may end with the start of a sentence, clause, or parenthetical is the exception. Only you can tell whether it does, so if it does, move those words to the start of the next line.',\n '- Parts kept as written are never rewrapped, and their notes say so. Fix those notes by hand, for example by breaking an overflowing prose line or by turning a long single-line comment into a multi-line one. Keep code, code spans, tables, box drawings, hard line breaks, and other intentional layout in them exactly as they are. If a note can only be fixed by changing those, leave it and say why in your reply.',\n `- Notes marked \\`${HINT_MARKER}\\` come from heuristics. If the rule doesn't actually apply, don't change anything for that note.`,\n '- Notes only point at places worth a look. Review each comment against the rules, and leave it as it is when it already follows them.',\n \"- Edit only these comments. Don't change code, other comments, or other files.\",\n '- When done, reply with one line per comment saying what you changed or why you left it.',\n '',\n ...options.comments.map((comment) => describeComment(comment)).flatMap((section) => [section, '']),\n ].join('\\n');\n}\n\nexport function shellQuote(value: string): string {\n return /^[\\w./:@=-]+$/.test(value) ? value : `'${value.replaceAll(\"'\", String.raw`'\\''`)}'`;\n}\n\nexport function buildInvocation(options: {\n readonly agent: AgentConfig;\n readonly runner: AgentRunner;\n readonly prompt: string;\n readonly root: string;\n}): AgentInvocation {\n const { agent, prompt, root } = options;\n const extra = agent.args ?? [];\n\n if (agent.command && agent.command.length > 0) {\n const [command, ...args] = agent.command;\n const hasPlaceholder = args.some((arg) => arg.includes('{prompt}'));\n\n return {\n command,\n // a function keeps the prompt as it is, while a string would expand `$&` or `$'` in a comment's text\n args: args.map((arg) => arg.replaceAll('{prompt}', () => prompt)),\n stdin: hasPlaceholder ? undefined : prompt,\n };\n }\n\n const model = agent.model ? ['--model', agent.model] : [];\n\n // the agent only reads and edits files, so it gets no shell\n if (options.runner === 'claude') {\n return {\n command: 'claude',\n args: [\n '-p',\n '--no-session-persistence',\n '--model',\n agent.model ?? DEFAULT_CLAUDE_MODEL,\n '--permission-mode',\n 'acceptEdits',\n '--allowedTools',\n 'Read',\n 'Edit',\n 'Grep',\n 'Glob',\n ...extra,\n ],\n stdin: prompt,\n };\n }\n\n if (options.runner === 'codex') {\n return {\n command: 'codex',\n args: [\n 'exec',\n '--ephemeral',\n '--sandbox',\n 'workspace-write',\n '--cd',\n root,\n '-c',\n 'features.hooks=false',\n ...model,\n ...extra,\n '-',\n ],\n stdin: prompt,\n };\n }\n\n // cursor-agent has no flag to skip hooks, so the child relies on the `COMMENTS_HOOK_CHILD` guard\n return {\n command: 'cursor-agent',\n args: ['-p', '--trust', '--force', '--workspace', root, ...model, ...extra, prompt],\n };\n}\n\nexport function describeAgent(agent: AgentConfig, runner: AgentRunner): string {\n if (agent.command && agent.command.length > 0) {\n return path.basename(agent.command[0]);\n }\n\n const model = runner === 'claude' ? (agent.model ?? DEFAULT_CLAUDE_MODEL) : agent.model;\n\n return model ? `${RUNNER_COMMANDS[runner]}, model ${model}` : RUNNER_COMMANDS[runner];\n}\n\nexport function formatInvocation(invocation: AgentInvocation): string {\n const args = invocation.args.map((arg) => (arg.length > 80 ? '<prompt>' : shellQuote(arg)));\n\n return [invocation.command, ...args].join(' ');\n}\n\nexport function runAgent(\n invocation: AgentInvocation,\n options: { root: string; timeout?: number },\n): Promise<AgentResult> {\n const timeout = options.timeout ?? DEFAULT_TIMEOUT_SECONDS;\n\n return new Promise((resolve) => {\n const child = spawn(invocation.command, invocation.args, {\n cwd: options.root,\n env: { ...process.env, [CHILD_ENV]: '1' },\n });\n\n const timers: NodeJS.Timeout[] = [];\n\n let stdout = '';\n let stderr = '';\n let timedOut = false;\n let settled = false;\n\n const settle = (result: Omit<AgentResult, 'output'>): void => {\n if (settled) {\n return;\n }\n\n settled = true;\n\n for (const timer of timers) {\n clearTimeout(timer);\n }\n\n // pipes that a process left behind by the agent still holds would keep this process from exiting\n child.stdout.destroy();\n child.stderr.destroy();\n child.unref();\n\n resolve({ ...result, output: `${stdout}${stderr}`.trim() });\n };\n\n const finish = (code: number | null, signal: NodeJS.Signals | null): void => {\n if (timedOut) {\n settle({ ok: false, error: `the agent timed out after ${timeout}s` });\n } else if (code === 0) {\n settle({ ok: true });\n } else {\n settle({ ok: false, error: `the agent exited with code ${code ?? signal}` });\n }\n };\n\n timers.push(\n setTimeout(() => {\n timedOut = true;\n\n child.kill();\n\n // an agent that ignores the signal is killed, and it counts as stopped even if that fails too\n timers.push(\n setTimeout(\n () => {\n child.kill('SIGKILL');\n finish(null, 'SIGKILL');\n },\n Math.min(KILL_GRACE_MS, timeout * 1000),\n ),\n );\n }, timeout * 1000),\n );\n\n child.stdout.setEncoding('utf8').on('data', (chunk: string) => {\n stdout += chunk;\n });\n\n child.stderr.setEncoding('utf8').on('data', (chunk: string) => {\n stderr += chunk;\n });\n\n child.on('error', (error: NodeJS.ErrnoException) => {\n settle({\n ok: false,\n error: error.code === 'ENOENT' ? `\\`${invocation.command}\\` is not installed` : error.message,\n });\n });\n\n child.on('close', finish);\n\n // `close` waits for the pipes, so it may come long after the agent exited, or never\n child.on('exit', (code, signal) => {\n timers.push(\n setTimeout(() => {\n finish(code, signal);\n }, DRAIN_GRACE_MS),\n );\n });\n\n // an agent that exits without reading its stdin would otherwise crash the process with EPIPE\n child.stdin.on('error', () => {});\n child.stdin.end(invocation.stdin ?? '');\n });\n}\n","import { parseSync, type OxcError, type Statement } from 'oxc-parser';\nimport {\n CODE_SPAN,\n findStyleIssues,\n isBanner,\n LIST_MARKER,\n replaceKeepingLines,\n stripNonProse,\n type StyleIssueType,\n} from './style.js';\nimport {\n bindLineStarts,\n breakAfterSentence,\n findLineIssues,\n hasWidow,\n layoutTokens,\n startsBlock,\n tokenize,\n type LayoutOptions,\n type LineIssue,\n type LineIssueType,\n type WrapOptions,\n} from './wrap.js';\n\nexport type CommentKind = 'jsdoc' | 'block';\n\nexport type ParagraphKind = 'prose' | 'list' | 'tag' | 'code' | 'other';\n\nexport interface AnalyzeOptions extends WrapOptions {\n /**\n * Sets the preferred line length, including indentation and the comment prefix.\n */\n readonly width: number;\n\n /**\n * Sets the hard limit for measured prose. Parentheticals may exceed `width` up to this limit.\n * When omitted, the existing width and tolerance behavior is retained.\n */\n readonly maxWidth?: number;\n\n /**\n * Sets the maximum length of the line that holds a comment whose whole text is one\n * prose paragraph. Such a comment stays on one line up to this length, even past\n * `width`. It defaults to `width`.\n */\n readonly singleLineWidth?: number;\n\n readonly tabWidth: number;\n\n /**\n * Whether to report prose style issues like semicolons, em-dashes, and section banners.\n */\n readonly style: boolean;\n}\n\nexport type IssueType = LineIssueType | StyleIssueType;\n\nexport type IssueTier = 'verdict' | 'hint';\n\nconst ISSUE_TIERS: Record<IssueType, IssueTier> = {\n overflow: 'verdict',\n underfill: 'verdict',\n widow: 'verdict',\n unbalanced: 'verdict',\n orphan: 'hint',\n banner: 'hint',\n 'em-dash': 'hint',\n semicolon: 'hint',\n 'label-colon': 'hint',\n emphasis: 'hint',\n dash: 'hint',\n};\n\nexport interface IssueReport {\n readonly type: IssueType;\n readonly tier: IssueTier;\n readonly line: number;\n readonly length: number;\n}\n\nexport interface ParagraphReport {\n readonly kind: ParagraphKind;\n readonly startLine: number;\n readonly endLine: number;\n\n /**\n * Whether the paragraph is prose that can be rewrapped. When `false`, `reason` says why.\n */\n readonly reflowable: boolean;\n readonly reason?: string;\n readonly issues: readonly IssueReport[];\n\n /**\n * Holds the exact source lines for `startLine` through `endLine` when the paragraph is\n * greedily wrapped to the width, or `null` when the paragraph isn't prose, e.g. code,\n * a table, a diagram, or `@example`.\n */\n readonly suggestion: readonly string[] | null;\n}\n\nexport interface CommentReport {\n readonly file: string;\n readonly kind: CommentKind;\n readonly startLine: number;\n readonly endLine: number;\n readonly indent: string;\n readonly width: number;\n readonly maxWidth?: number;\n\n /**\n * Holds the length of each source line from `startLine` through `endLine`, with tabs expanded.\n */\n readonly lengths: readonly number[];\n readonly text: string;\n readonly paragraphs: readonly ParagraphReport[];\n}\n\nexport interface SyntaxFailure {\n readonly message: string;\n\n /**\n * Holds the 1-based line of the error, when the parser names one.\n */\n readonly line?: number;\n}\n\nexport interface SourceAnalysis {\n readonly comments: CommentReport[];\n\n /**\n * Describes the syntax error that the parser stopped at. The parser never sees the comments after\n * one, so such a source has no comments at all instead of only those before the error.\n */\n readonly syntaxError?: SyntaxFailure;\n}\n\ninterface BodyLine {\n /**\n * Holds the 0-based index of the line in the file.\n */\n readonly index: number;\n readonly prefix: string;\n readonly text: string;\n readonly verbatim: boolean;\n\n /**\n * Whether the source line ends with Markdown hard line break syntax, which `text` no longer\n * holds after trimming.\n */\n readonly hardBreak: boolean;\n}\n\ninterface RawParagraph {\n kind: ParagraphKind;\n lines: BodyLine[];\n marker: string;\n reason?: string;\n}\n\ninterface ParsedComment {\n readonly type: 'Line' | 'Block';\n readonly value: string;\n readonly start: number;\n readonly end: number;\n}\n\nconst IGNORE_DIRECTIVE = 'comments-ignore';\n\nconst FENCE = /^(?:`{3,}(?!.*`)|~{3,})/;\nconst JSDOC_TAG = /^@([A-Za-z]+)/;\nconst NESTED_LIST_MARKER = /^\\s+(?:[-*+]|\\d+[.)])\\s+/;\n\n/**\n * Tags whose content is a prose description, while others like `@example` hold code and\n * are never rewrapped.\n */\nconst PROSE_TAGS = new Set([\n 'arg',\n 'argument',\n 'deprecated',\n 'description',\n 'exception',\n 'note',\n 'param',\n 'prop',\n 'property',\n 'remarks',\n 'return',\n 'returns',\n 'see',\n 'since',\n 'summary',\n 'template',\n 'throws',\n 'todo',\n 'typeParam',\n 'yields',\n]);\n\n// tags whose content is code that runs until the next tag, empty lines included, like a multi-part `@example`\nconst CODE_TAGS = new Set(['default', 'defaultValue', 'example']);\n\n// tags followed by a name, as in `@param {Type} name - description`\nconst NAMED_TAGS = new Set(['arg', 'argument', 'param', 'prop', 'property', 'template', 'typeParam']);\n\n/**\n * Tool directives take effect in any comment line, so a JSDoc line that starts with one is kept\n * as it is. Each is the exact name of a directive, since prose can start a line with a package\n * name like `eslint-config-prettier`.\n */\nconst LINE_DIRECTIVE =\n /^\\s*(?:(?:eslint|oxlint|stylelint)-(?:disable(?:-next-line|-line)?|enable)\\b|eslint-env\\b|@ts-(?:ignore|expect-error|nocheck|check)\\b|@jsx\\w*\\b|@vite-ignore\\b|[@#]__[A-Z_]+__|@(?:vitest|jest)-environment\\b|(?:istanbul|c8|v8)\\s+ignore\\b|prettier-ignore\\b|biome-ignore\\b|deno-(?:lint-ignore|fmt-ignore)(?:-file)?\\b|tslint:|(?:c[sS]pell|spell-?checker)\\s*:|(?:webpack|turbopack)[A-Z][a-zA-Z]*\\s*:|vim?:\\s|#(?:region|endregion)\\b|<reference\\s)/;\n\n/**\n * These directives are only read from a whole block comment, like `/* global foo *\\/`\n * or `/* eslint quotes: 1 *\\/`. Their markers are ordinary words, so they never count\n * as directives on a single line of a longer comment.\n */\nconst BLOCK_DIRECTIVE = /^\\s*(?:eslint\\s|globals?\\s|exported\\s|jshint\\s|jslint\\s|type\\s*:)/;\n\n/**\n * Legal comments are kept as they are. A comment is legal when it uses the same markers\n * as bundlers like esbuild (`/*!`, `//!`, `@license`, and `@preserve`), or when it is a\n * copyright notice like `Copyright (c) 2020 Foo`.\n */\nconst LEGAL_COMMENT = /^!|@license\\b|@preserve\\b|\\bcopyright\\s+(?:\\(c\\)|©|\\d{4})/i;\n\n// a term of one or two words or a code span (stripped to two backticks), then a dash or colon and its definition\nconst DEFINITION = /^(?:``|[\\w$.[\\]]+(?:[ -][\\w$.[\\]]+)?)(?: [-–]|:) \\S/;\n\nconst BOX_DRAWING = /[\\u2500-\\u257F]/;\n\n// a Markdown table delimiter row like `--- | ---` or `|:--|--:|`, which needs no leading pipe\nconst TABLE_DELIMITER = /^\\|?\\s*:?-+:?\\s*(?:\\|\\s*:?-+:?\\s*)+\\|?$/;\n\nconst ARROWS_OR_RULES = /[▲▼◀▶→←↑↓]|-->|<--|\\+-{2,}|-{3,}|={4,}/;\n\n// two or more spaces after text, or a backslash that another backslash doesn't escape\nconst HARD_BREAK = /\\S {2,}$|(?<!\\\\)\\\\(?:\\\\\\\\)*$/;\n\n/**\n * Describes how a paragraph that the tool keeps as written is checked.\n *\n * - `code`: code that the parser accepts, which gets no checks besides banners\n * - `code-like`: a paragraph with a line that may be code, like one that ends with `{`, which gets\n * no style hints, since they would point at the code, but must still fit the width\n * - `layout`: documented layout syntax like a table row, which gets style hints but no verdicts\n * - `manual`: text that is or may be laid out by hand or may be markup, like a Markdown hard line\n * break, arrows, or a heading, which gets style hints and must still fit the width.\n */\ntype StructureTier = 'code' | 'code-like' | 'layout' | 'manual';\n\ninterface Structure {\n readonly tier: StructureTier;\n readonly reason: string;\n}\n\n/**\n * Whether a statement is something prose also parses as, like a single word (`Done`),\n * a code span, a word before a code span (`Returns \\`null\\``, a tagged template), or a\n * label (`Default: refuse`). A label that ends with a semicolon, like the commented-out\n * CSS declaration `display: none;`, is code.\n */\nfunction isProseLike(statement: Statement, source: string): boolean {\n if (statement.type === 'LabeledStatement') {\n return source[statement.end - 1] !== ';';\n }\n\n if (statement.type === 'EmptyStatement') {\n return true;\n }\n\n if (statement.type !== 'ExpressionStatement') {\n return false;\n }\n\n let { expression } = statement;\n\n while (expression.type === 'ParenthesizedExpression') {\n expression = expression.expression;\n }\n\n if (expression.type === 'TaggedTemplateExpression') {\n return expression.tag.type === 'Identifier';\n }\n\n return expression.type === 'Identifier' || expression.type === 'Literal' || expression.type === 'TemplateLiteral';\n}\n\nfunction parsesAsStatements(text: string): boolean {\n if (!/[()[\\]{}=;<>]/.test(text)) {\n return false;\n }\n\n // a generator body accepts `return`, `await`, and `yield`, which are common in commented-out code\n const source = `async function* comment() {\\n${text}\\n}`;\n const { program, errors } = parseSync('comment.tsx', source);\n const wrapper = program.body.at(0);\n\n if (errors.length > 0 || wrapper?.type !== 'FunctionDeclaration' || !wrapper.body) {\n return false;\n }\n\n const statements = wrapper.body.body;\n\n return statements.length > 0 && !statements.every((statement) => isProseLike(statement, source));\n}\n\nconst CODE_VALUES = new Set([\n 'Literal',\n 'ArrayExpression',\n 'ObjectExpression',\n 'CallExpression',\n 'NewExpression',\n 'ArrowFunctionExpression',\n 'FunctionExpression',\n 'UnaryExpression',\n 'MemberExpression',\n]);\n\n/**\n * A lone property whose value is a word or code span, like `Default: refuse`, reads as a label in\n * prose rather than as commented-out options.\n */\nfunction parsesAsProperties(text: string): boolean {\n if (!text.includes(':')) {\n return false;\n }\n\n const { program, errors } = parseSync('comment.ts', `({\\n${text}\\n})`);\n const statement = program.body.at(0);\n\n if (errors.length > 0 || program.body.length !== 1 || statement?.type !== 'ExpressionStatement') {\n return false;\n }\n\n let { expression } = statement;\n\n while (expression.type === 'ParenthesizedExpression') {\n expression = expression.expression;\n }\n\n if (expression.type !== 'ObjectExpression' || expression.properties.length === 0) {\n return false;\n }\n\n const { properties } = expression;\n\n if (!properties.every((property) => property.type === 'Property' && !property.shorthand && !property.method)) {\n return false;\n }\n\n return (\n properties.length > 1 ||\n text.trimEnd().endsWith(',') ||\n properties.some((property) => property.type === 'Property' && CODE_VALUES.has(property.value.type))\n );\n}\n\n/**\n * Prose almost never parses as JavaScript, since two words in a row are a syntax error.\n */\nfunction isCode(texts: readonly string[]): boolean {\n const text = texts.map((line) => line.replace(LIST_MARKER, '')).join('\\n');\n\n return parsesAsStatements(text) || parsesAsProperties(text);\n}\n\n/**\n * A prose clause can end with a semicolon too, which is a style issue.\n * So `;` only ends code with code around it.\n */\nfunction isCodeLine(text: string): boolean {\n return (\n text.endsWith('{') ||\n (text.endsWith(';') && (/[()[\\]{}=<>]/.test(text) || !/\\s/.test(text))) ||\n /^[}\\])]/.test(text) ||\n /^(?:const|let|var)\\s+[\\w$]+\\s*[:=]/.test(text) ||\n /^(?:import|export)\\s.*(?:\\sfrom\\s|[{}])/.test(text)\n );\n}\n\nfunction layoutReason(prose: string, raw: string): string | undefined {\n if (prose.startsWith('|') || TABLE_DELIMITER.test(prose)) {\n return 'table row';\n }\n\n if (BOX_DRAWING.test(prose)) {\n return 'box drawing';\n }\n\n // a rule or border, like the `***` lines of a box, would be joined into the prose around it\n if (isBanner(raw)) {\n return 'repeated characters';\n }\n\n return undefined;\n}\n\n/**\n * Headings, link definitions, HTML, and quotes are markup, since joining them with the next line\n * would turn them into prose. Prose can start a line like that too, like `<T> is the type` or\n * `# of retries`, so markup is only kept as written and still has to fit the width.\n */\nfunction isMarkup(prose: string): boolean {\n return /^#{1,6}\\s/.test(prose) || /^\\[[^\\]]+\\]:/.test(prose) || /^<\\/?[a-z]/i.test(prose) || /^>(?:\\s|$)/.test(prose);\n}\n\nfunction mask(text: string): string {\n return text.replaceAll(/[^\\n]/g, 'x');\n}\n\nfunction maskCode(text: string): string {\n let masked = text.replaceAll(CODE_SPAN, mask);\n\n for (let previous = ''; previous !== masked; ) {\n previous = masked;\n masked = masked.replaceAll(/\\{[^{}]*\\}/g, mask);\n }\n\n return masked;\n}\n\n/**\n * Two spaces after a sentence are an old typing convention, and a gap on a single line is a typo,\n * so neither is a column.\n */\nfunction hasAlignedColumns(lines: readonly BodyLine[]): boolean {\n const masked = maskCode(lines.map((body) => body.text).join('\\n')).split('\\n');\n const seen = new Set<number>();\n\n for (const line of masked) {\n const columns = new Set([...line.matchAll(/[^\\s.!?][^\\S\\n]{2,}(?=\\S)/g)].map((gap) => gap.index + gap[0].length));\n\n if ([...columns].some((column) => seen.has(column))) {\n return true;\n }\n\n for (const column of columns) {\n seen.add(column);\n }\n }\n\n return false;\n}\n\nfunction structureOf(lines: readonly BodyLine[]): Structure | undefined {\n const trimmed = lines.map((line) => line.text.trim()).join('\\n');\n const texts = replaceKeepingLines(trimmed, CODE_SPAN, '``').split('\\n');\n\n /**\n * Types like `{string | null}`, links like `{@link a | b}`, and URLs hold pipes and dashes\n * that aren't layout.\n */\n const proseLines = stripNonProse(trimmed).split('\\n');\n\n // the parser only accepts a whole paragraph as code when it is code, since two words in a row are a syntax error\n if (isCode(lines.map((line) => line.text.trim()))) {\n return { tier: 'code', reason: 'code' };\n }\n\n let layout: string | undefined;\n let codeLike = false;\n\n // a hard break on the last line of a paragraph ends the paragraph instead, as in Markdown\n let manual = lines.slice(0, -1).some((line) => line.hardBreak) ? 'hard line break' : undefined;\n\n for (const [position, line] of texts.entries()) {\n const prose = proseLines[position].trim();\n\n layout ??= layoutReason(prose, lines[position]?.text ?? '');\n\n // a single line that looks like code may be prose, like one that starts with `import them from`\n if (isCodeLine(line.trim())) {\n codeLike = true;\n } else if (isMarkup(prose)) {\n manual ??= 'markup';\n } else if ((prose.match(/\\|/g)?.length ?? 0) >= 2) {\n manual ??= 'pipes';\n } else if (ARROWS_OR_RULES.test(prose)) {\n manual ??= 'arrows or rules';\n }\n }\n\n layout ??= hasAlignedColumns(lines) ? 'aligned columns' : undefined;\n\n if (layout) {\n return { tier: 'layout', reason: layout };\n }\n\n if (codeLike) {\n return { tier: 'code-like', reason: 'code-like line' };\n }\n\n /**\n * One term per line, like `width - the maximum width` above `height - the maximum height`, may be\n * a definition list.\n */\n if (texts.filter((text) => DEFINITION.test(text.trim())).length >= 2) {\n manual ??= 'definition-like lines';\n }\n\n return manual ? { tier: 'manual', reason: manual } : undefined;\n}\n\n/**\n * A Markdown code fence closes only with the character it opened with, repeated at least as\n * often. A tilde fence inside a backtick block, or three backticks inside a four-backtick\n * block, doesn't end it.\n */\nclass FenceTracker {\n private _open: string | undefined;\n\n isInside(): boolean {\n return this._open !== undefined;\n }\n\n next(text: string): boolean {\n const trimmed = text.trim();\n\n if (this._open === undefined) {\n this._open = FENCE.exec(trimmed)?.[0];\n\n return this._open !== undefined;\n }\n\n if (trimmed.startsWith(this._open) && new RegExp(`^\\\\${this._open[0]}+$`).test(trimmed)) {\n this._open = undefined;\n }\n\n return true;\n }\n}\n\nfunction segment(lines: readonly BodyLine[]): RawParagraph[] {\n const paragraphs: RawParagraph[] = [];\n const fence = new FenceTracker();\n\n let current: RawParagraph | undefined;\n let inCodeTag = false;\n\n const flush = (): void => {\n if (current) {\n while (current.lines.length > 1 && !current.lines.at(-1)?.text.trim()) {\n current.lines.pop();\n }\n\n paragraphs.push(current);\n\n current = undefined;\n }\n };\n\n const start = (kind: ParagraphKind, line: BodyLine, marker = '', reason?: string): void => {\n flush();\n\n current = { kind, lines: [line], marker, reason };\n };\n\n for (const line of lines) {\n const { text } = line;\n\n if (inCodeTag) {\n /**\n * A fence inside the example may hold a line like `@decorator()`, which only starts a tag\n * outside of it.\n */\n if (fence.isInside() || !JSDOC_TAG.test(text)) {\n fence.next(text);\n current?.lines.push(line);\n\n continue;\n }\n\n inCodeTag = false;\n }\n\n if (fence.isInside()) {\n current?.lines.push(line);\n fence.next(text);\n\n if (!fence.isInside()) {\n flush();\n }\n\n continue;\n }\n\n if (line.verbatim) {\n start('code', line, '', 'directive');\n flush();\n\n continue;\n }\n\n if (!text.trim()) {\n flush();\n\n continue;\n }\n\n if (fence.next(text)) {\n start('code', line, '', 'code block');\n\n continue;\n }\n\n if (/^\\s/.test(text)) {\n const holdsProse = current?.kind === 'list' || (current?.kind === 'tag' && !current.reason);\n const nested = holdsProse ? NESTED_LIST_MARKER.exec(text) : null;\n\n if (nested) {\n start('list', line, nested[0]);\n } else if (current && (current.kind === 'list' || current.kind === 'tag' || current.reason === 'indented')) {\n current.lines.push(line);\n } else {\n start('code', line, '', 'indented');\n }\n\n continue;\n }\n\n const tag = JSDOC_TAG.exec(text);\n\n if (tag) {\n start('tag', line, '', PROSE_TAGS.has(tag[1]) ? undefined : `@${tag[1]} tag`);\n\n inCodeTag = CODE_TAGS.has(tag[1]);\n\n continue;\n }\n\n const marker = LIST_MARKER.exec(text);\n\n if (marker) {\n start('list', line, marker[0]);\n\n continue;\n }\n\n // like Markdown, an unindented line right after a list item lazily continues it\n if (current && (current.kind === 'prose' || current.kind === 'tag' || current.kind === 'list')) {\n current.lines.push(line);\n\n continue;\n }\n\n start('prose', line);\n }\n\n flush();\n\n return paragraphs;\n}\n\nfunction startsLine(token: string, next: string | undefined): boolean {\n return startsBlock(token) || LINE_DIRECTIVE.test(next === undefined ? token : `${token} ${next}`);\n}\n\nfunction visualLength(text: string, tabWidth: number): number {\n return text.replaceAll('\\t', ' '.repeat(tabWidth)).length;\n}\n\nfunction sourceLineLength(line: BodyLine, tabWidth: number): number {\n // the text holds the indentation for comments without a prefix, like `other` block comments\n return visualLength(`${line.prefix}${line.text.trimEnd()}`, tabWidth);\n}\n\n/**\n * In legacy width/tolerance mode, an indivisible token is exempt because wrapping cannot\n * make it fit.\n */\nfunction overflowIssues(lines: readonly BodyLine[], options: AnalyzeOptions): IssueReport[] {\n const issues: IssueReport[] = [];\n const limit = options.maxWidth ?? options.width + options.tolerance;\n\n for (const line of lines) {\n const length = sourceLineLength(line, options.tabWidth);\n\n if (length <= limit) {\n continue;\n }\n\n if (options.maxWidth !== undefined) {\n issues.push(lineIssue('overflow', line, options));\n\n continue;\n }\n\n const prefixLength = visualLength(`${line.prefix}${/^\\s*/.exec(line.text)?.[0] ?? ''}`, options.tabWidth);\n const tokens = bindLineStarts(tokenize(line.text), startsLine);\n\n if (tokens.length > 1 && tokens.every((token) => prefixLength + token.length <= limit)) {\n issues.push(lineIssue('overflow', line, options));\n }\n }\n\n return issues;\n}\n\nfunction lineIssue(type: IssueType, line: BodyLine, options: AnalyzeOptions): IssueReport {\n return { type, tier: ISSUE_TIERS[type], line: line.index + 1, length: sourceLineLength(line, options.tabWidth) };\n}\n\nfunction stripBlockSyntax(text: string): string {\n return text\n .replace(/^\\s*\\/\\*+/, '')\n .replace(/\\*+\\/\\s*$/, '')\n .replace(/^\\s*\\*(?=\\s|$)/, '');\n}\n\nfunction bannerIssues(paragraph: RawParagraph, options: AnalyzeOptions): IssueReport[] {\n const verbatim = ['code block', 'indented', 'legal comment'];\n\n if (!options.style || (paragraph.reason !== undefined && verbatim.includes(paragraph.reason))) {\n return [];\n }\n\n const banners = paragraph.lines.filter((line) => {\n const text = paragraph.kind === 'other' ? stripBlockSyntax(line.text) : line.text;\n\n return isBanner(text) || (paragraph.kind === 'other' && /^\\s*\\/\\*{3,}|\\*{3,}\\/\\s*$/.test(line.text));\n });\n\n return banners.map((line) => lineIssue('banner', line, options));\n}\n\nfunction styleIssues(paragraph: RawParagraph, options: AnalyzeOptions): IssueReport[] {\n if (!options.style) {\n return [];\n }\n\n const byIndex = new Map(paragraph.lines.map((line) => [line.index, line]));\n\n const lines = paragraph.lines.map((line) => {\n return { index: line.index, text: paragraph.kind === 'other' ? stripBlockSyntax(line.text) : line.text };\n });\n\n return findStyleIssues(lines).flatMap((issue) => {\n const line = byIndex.get(issue.index);\n\n return line ? [lineIssue(issue.type, line, options)] : [];\n });\n}\n\nfunction bindTagHead(tokens: readonly string[]): string[] {\n let end = 1;\n\n if (tokens[end]?.startsWith('{')) {\n end += 1;\n }\n\n if (NAMED_TAGS.has(tokens[0].slice(1)) && end < tokens.length) {\n end += 1;\n }\n\n if (tokens[end] === '-') {\n end += 1;\n }\n\n return [tokens.slice(0, end).join(' '), ...tokens.slice(end)];\n}\n\n/**\n * A paragraph without a structure, like a single-line block comment, is prose that just can't be\n * rewrapped, so it's checked like text laid out by hand.\n */\nfunction keptIssues(paragraph: RawParagraph, structure: Structure | undefined, options: AnalyzeOptions): IssueReport[] {\n const tier = structure?.tier ?? 'manual';\n\n return byLine([\n ...(tier === 'manual' || tier === 'code-like' ? overflowIssues(paragraph.lines, options) : []),\n ...(tier === 'code' || tier === 'code-like' ? [] : styleIssues(paragraph, options)),\n ...bannerIssues(paragraph, options),\n ]);\n}\n\nfunction byLine(issues: readonly IssueReport[]): IssueReport[] {\n const unique = new Map(issues.map((issue) => [`${issue.line}:${issue.type}`, issue]));\n\n return [...unique.values()].toSorted((a, b) => a.line - b.line);\n}\n\nfunction sameLayout(a: readonly (readonly string[])[], b: readonly (readonly string[])[]): boolean {\n return a.length === b.length && a.every((words, position) => words.join(' ') === b[position].join(' '));\n}\n\nfunction analyzeParagraph(paragraph: RawParagraph, options: AnalyzeOptions): ParagraphReport {\n const first = paragraph.lines[0];\n const last = paragraph.lines.at(-1) ?? first;\n const base = { kind: paragraph.kind, startLine: first.index + 1, endLine: last.index + 1 };\n\n if (paragraph.kind === 'code') {\n return {\n ...base,\n reflowable: false,\n reason: paragraph.reason,\n issues: bannerIssues(paragraph, options),\n suggestion: null,\n };\n }\n\n if (paragraph.kind === 'tag' && paragraph.reason) {\n const codeTag = CODE_TAGS.has(JSDOC_TAG.exec(first.text)?.[1] ?? '');\n const issues = codeTag ? [] : overflowIssues(paragraph.lines, options);\n\n return { ...base, reflowable: false, reason: paragraph.reason, issues, suggestion: null };\n }\n\n if (paragraph.kind === 'other') {\n const fence = new FenceTracker();\n\n const prose = {\n ...paragraph,\n lines: paragraph.lines.filter((line) => !fence.next(stripBlockSyntax(line.text))),\n };\n\n const structure = structureOf(\n prose.lines.map((line) => {\n return { ...line, text: stripBlockSyntax(line.text) };\n }),\n );\n\n const issues = keptIssues(prose, structure, options);\n\n return { ...base, reflowable: false, reason: paragraph.reason, issues, suggestion: null };\n }\n\n const keep = (structure: Structure): ParagraphReport => {\n const issues = keptIssues(paragraph, structure, options);\n\n return { ...base, reflowable: false, reason: structure.reason, issues, suggestion: null };\n };\n\n const structure = structureOf(paragraph.lines);\n\n if (structure) {\n return keep(structure);\n }\n\n const prefix = first.prefix;\n const prefixLength = visualLength(prefix, options.tabWidth);\n const hang = ' '.repeat(paragraph.marker.length);\n const firstLimit = options.width - prefixLength - paragraph.marker.length;\n const restLimit = options.width - prefixLength - hang.length;\n\n const currentLines = paragraph.lines.map((line, position) =>\n bindLineStarts(tokenize(position === 0 ? line.text.slice(paragraph.marker.length) : line.text), startsLine),\n );\n\n const tokens = tokenize(currentLines.flat().join(' '));\n\n const layoutOptions = {\n ...options,\n tolerance:\n options.maxWidth === undefined\n ? options.tolerance\n : Math.min(options.tolerance, options.maxWidth - options.width),\n parentheticalOverflow: options.maxWidth === undefined ? undefined : options.maxWidth - options.width,\n keepFirstLine: paragraph.kind === 'tag',\n };\n\n const layOut = (from: readonly string[], settings: LayoutOptions) => {\n const even = layoutTokens(from, firstLimit, restLimit, settings);\n\n return { even, wrapped: breakAfterSentence(even, firstLimit, restLimit, settings) };\n };\n\n const units = bindLineStarts(paragraph.kind === 'tag' ? bindTagHead(tokens) : tokens, startsLine);\n\n // the first and the other lines have the same limit, since the hanging indent is as long as the marker\n const hardLimit = restLimit + (options.maxWidth === undefined ? options.tolerance : options.maxWidth - options.width);\n const written = currentLines.map((words) => ` ${words.join(' ')} `);\n\n /**\n * Text that stays on one line, like a code span, may only be longer than the limit when it\n * already is on one line, so a rewrap never adds a line that is too long.\n */\n const staysInLimit = (unit: string): boolean => {\n return unit.length <= hardLimit || written.some((line) => line.includes(` ${unit} `));\n };\n\n // a code span or `{...}` group that continues on the next line would be joined into one line that is too long\n if (!units.every((unit) => staysInLimit(unit))) {\n return keep({ tier: 'manual', reason: 'unbreakable text across lines' });\n }\n\n const bodyOf = (lines: readonly (readonly string[])[]): BodyLine[] => {\n return lines.map((words, position) => {\n const text = `${position === 0 ? paragraph.marker : hang}${words.join(' ')}`;\n\n return { ...first, text, verbatim: false, hardBreak: HARD_BREAK.test(text) };\n });\n };\n\n /**\n * Analyzing the rewrap must find the same prose, so when a new line's start or end would read as\n * structure, like two lines that start with `term - `, the first word of the line that tips it\n * moves up a line. Without such a layout, or when the text reads as structure on a single line,\n * no rewrap reads as the same prose, and the paragraph is kept as written.\n */\n const settle = (settings: LayoutOptions): { even: string[][]; wrapped: string[][] } | Structure => {\n let current = units;\n let { even, wrapped } = layOut(current, settings);\n\n for (;;) {\n const body = bodyOf(wrapped);\n const rewrap = structureOf(body);\n\n if (!rewrap) {\n return { even, wrapped };\n }\n\n // the first line has no line to move a word up to, so the first word of the second line joins it instead\n const tipping = body.findIndex((_, position) => structureOf(body.slice(0, position + 1)) !== undefined);\n const start = wrapped.slice(0, Math.max(tipping, 1)).flat().length;\n const pair = `${current[start - 1]} ${current[start]}`;\n\n if (body.length < 2 || !staysInLimit(pair)) {\n const reading = rewrap.tier === 'code-like' ? 'code' : rewrap.reason;\n\n return { tier: 'manual', reason: `rewrap would read as ${reading}` };\n }\n\n current = current.toSpliced(start - 1, 2, pair);\n ({ even, wrapped } = layOut(current, settings));\n }\n };\n\n const settled = settle(layoutOptions);\n\n // the extra lines that keep a line from sticking out can read as structure where the fewest lines don't\n const layout = 'wrapped' in settled ? settled : settle({ ...layoutOptions, keepSteps: true });\n\n if (!('wrapped' in layout)) {\n return keep(layout);\n }\n\n const { even, wrapped } = layout;\n const matchesLayout = sameLayout(wrapped, currentLines);\n\n const lineIssues: LineIssue[] = [];\n const overflow: IssueReport[] = options.maxWidth === undefined ? [] : overflowIssues(paragraph.lines, options);\n\n if (!matchesLayout) {\n const hasExtraLines = currentLines.length > wrapped.length;\n\n if (options.maxWidth === undefined) {\n overflow.push(...overflowIssues(paragraph.lines, options));\n }\n\n lineIssues.push(\n ...findLineIssues(currentLines, firstLimit, restLimit, layoutOptions).filter(\n (issue) => issue.type !== 'overflow' && (issue.type !== 'underfill' || hasExtraLines),\n ),\n );\n\n if (hasWidow(currentLines) && !hasWidow(wrapped)) {\n lineIssues.push({ type: 'widow', line: currentLines.length - 1 });\n }\n\n /**\n * Lines that only miss the break after a sentence are a hint, since a heuristic decides where\n * a sentence ends.\n */\n if (\n lineIssues.length === 0 &&\n overflow.length === 0 &&\n (currentLines.length === wrapped.length || options.maxWidth !== undefined)\n ) {\n const line = wrapped.findIndex((words, position) => words.join(' ') !== currentLines[position]?.join(' '));\n\n lineIssues.push({ type: sameLayout(even, currentLines) ? 'orphan' : 'unbalanced', line: Math.max(line, 0) });\n }\n }\n\n const suggestion = wrapped.map(\n (words, position) => `${prefix}${position === 0 ? paragraph.marker : hang}${words.join(' ')}`,\n );\n\n const wrapIssues = lineIssues.map((issue) => lineIssue(issue.type, paragraph.lines[issue.line], options));\n const issues = byLine([...overflow, ...wrapIssues, ...styleIssues(paragraph, options)]);\n\n return { ...base, reflowable: true, issues, suggestion };\n}\n\nfunction computeLineStarts(source: string): number[] {\n const starts = [0];\n\n for (let index = 0; index < source.length; index += 1) {\n if (source.codePointAt(index) === 0x0a) {\n starts.push(index + 1);\n }\n }\n\n return starts;\n}\n\nfunction lineOf(lineStarts: readonly number[], offset: number): number {\n let low = 0;\n let high = lineStarts.length - 1;\n\n while (low < high) {\n const middle = Math.ceil((low + high) / 2);\n\n if (lineStarts[middle] <= offset) {\n low = middle;\n } else {\n high = middle - 1;\n }\n }\n\n return low;\n}\n\ninterface CommentShape {\n readonly kind: CommentKind;\n readonly startLine: number;\n readonly endLine: number;\n readonly paragraphs: RawParagraph[];\n}\n\nfunction stripCarriageReturn(line: string): string {\n return line.endsWith('\\r') ? line.slice(0, -1) : line;\n}\n\nfunction shapeBlock(\n comment: ParsedComment,\n sourceLines: readonly string[],\n lineStarts: readonly number[],\n): CommentShape {\n const startLine = lineOf(lineStarts, comment.start);\n const endLine = lineOf(lineStarts, comment.end - 1);\n const kind: CommentKind = comment.value.startsWith('*') ? 'jsdoc' : 'block';\n const lines = sourceLines.slice(startLine, endLine + 1);\n\n const wholeComment = (paragraphKind: ParagraphKind, reason: string): CommentShape => {\n const otherLines = lines.map((text, offset) => {\n return { index: startLine + offset, prefix: '', text, verbatim: false, hardBreak: false };\n });\n\n return { kind, startLine, endLine, paragraphs: [{ kind: paragraphKind, marker: '', reason, lines: otherLines }] };\n };\n\n const value = comment.value.replace(/^\\*/, '');\n\n // a code span only names a marker, like the `@license` in a comment that explains legal comments\n if (LEGAL_COMMENT.test(replaceKeepingLines(comment.value, CODE_SPAN, '``'))) {\n return wholeComment('code', 'legal comment');\n }\n\n if (LINE_DIRECTIVE.test(value) || BLOCK_DIRECTIVE.test(value)) {\n return wholeComment('code', 'directive');\n }\n\n const other = (): CommentShape => {\n return wholeComment(\n 'other',\n startLine === endLine ? 'single-line block comment' : 'unsupported block comment layout',\n );\n };\n\n if (startLine === endLine || !/^\\s*\\/\\*\\*?$/.test(lines[0]) || !/^\\s*\\*\\/$/.test(lines.at(-1) ?? '')) {\n return other();\n }\n\n const body: BodyLine[] = [];\n const inner = lines.slice(1, -1);\n\n for (const [offset, line] of inner.entries()) {\n const match = /^(\\s*\\*)( ?)(.*)$/.exec(line);\n\n if (!match) {\n return other();\n }\n\n const [, star, space, text] = match;\n\n body.push({\n index: startLine + 1 + offset,\n prefix: `${star} `,\n text: text.trimEnd(),\n verbatim: (!space && text.length > 0) || LINE_DIRECTIVE.test(text),\n hardBreak: HARD_BREAK.test(text),\n });\n }\n\n return { kind, startLine, endLine, paragraphs: segment(body) };\n}\n\nfunction ownsLines(comment: ParsedComment, source: string, lineStarts: readonly number[]): boolean {\n const startLine = lineOf(lineStarts, comment.start);\n const before = source.slice(lineStarts[startLine], comment.start);\n const endLine = lineOf(lineStarts, comment.end - 1);\n const lineEnd = lineStarts[endLine + 1] ?? source.length;\n const after = source.slice(comment.end, lineEnd);\n\n return /^[\\t ]*$/.test(before) && /^[\\t ]*\\r?\\n?$/.test(after);\n}\n\n/**\n * Only a single-line block comment or prose without structure can stay on one line past the width.\n */\nfunction singleLineLength(paragraph: RawParagraph, options: AnalyzeOptions): number {\n const [first] = paragraph.lines;\n\n if (paragraph.kind === 'other' && paragraph.reason === 'single-line block comment') {\n return sourceLineLength(first, options.tabWidth);\n }\n\n if (paragraph.kind !== 'prose' || structureOf(paragraph.lines)) {\n return Infinity;\n }\n\n const text = tokenize(paragraph.lines.map((line) => line.text).join(' ')).join(' ');\n\n return visualLength(first.prefix, options.tabWidth) + text.length;\n}\n\nexport const BYTE_ORDER_MARK = '\\uFEFF';\n\n/**\n * Most toolchains accept JSX in a `.js` file, and a file without JSX parses the same either way.\n */\nfunction parseSource(filename: string, source: string): ReturnType<typeof parseSync> {\n return parseSync(filename, source, filename.endsWith('.js') ? { lang: 'jsx' } : undefined);\n}\n\nfunction describeFailure(errors: readonly OxcError[], lineStarts: readonly number[]): SyntaxFailure {\n const [first] = errors;\n const offset = first.labels.at(0)?.start;\n\n return { message: first.message, line: offset === undefined ? undefined : lineOf(lineStarts, offset) + 1 };\n}\n\n/**\n * Finds all own-line block and JSDoc comments in a JavaScript or TypeScript source file and reports\n * how each paragraph deviates from a greedy wrap at `options.width`. Line comments (`//`) are never\n * analyzed. A source with a syntax error that stops the parser has no reports.\n */\nexport function analyzeSource(source: string, filename: string, options: AnalyzeOptions): CommentReport[] {\n return inspectSource(source, filename, options).comments;\n}\n\n/**\n * Analyzes a source like `analyzeSource`, and also tells a source without comments apart from one\n * that the parser can't read.\n */\nexport function inspectSource(source: string, filename: string, options: AnalyzeOptions): SourceAnalysis {\n if (options.maxWidth !== undefined && (!Number.isInteger(options.maxWidth) || options.maxWidth < options.width)) {\n throw new Error('comments: maxWidth must be an integer at least as large as width');\n }\n\n // a byte order mark is no text, so a comment on the first line owns its lines and is measured without the mark\n const text = source.startsWith(BYTE_ORDER_MARK) ? source.slice(1) : source;\n const { program, comments, errors } = parseSource(filename, text);\n const lineStarts = computeLineStarts(text);\n\n /**\n * The parser returns an empty program when it stops at a syntax error, and it has only seen\n * the comments before that error. An error that it recovers from, like a `return` outside of\n * a function, leaves the program and its comments complete.\n */\n if (errors.length > 0 && program.body.length === 0) {\n return { comments: [], syntaxError: describeFailure(errors, lineStarts) };\n }\n\n const sourceLines = text.split('\\n').map((line) => stripCarriageReturn(line));\n\n // drop a leading hashbang, which some parser versions report as a comment\n const parsed = (comments as ParsedComment[]).filter((comment) => !(comment.start === 0 && text.startsWith('#!')));\n const reports: CommentReport[] = [];\n\n const blocks = parsed.filter((comment) => {\n return (\n comment.type === 'Block' && ownsLines(comment, text, lineStarts) && !comment.value.includes(IGNORE_DIRECTIVE)\n );\n });\n\n for (const block of blocks) {\n const shape = shapeBlock(block, sourceLines, lineStarts);\n\n const singleLineWidth = Math.max(\n options.width,\n Math.min(options.singleLineWidth ?? options.width, options.maxWidth ?? Infinity),\n );\n\n const paragraphOptions =\n shape.paragraphs.length === 1 && singleLineLength(shape.paragraphs[0], options) <= singleLineWidth\n ? { ...options, width: singleLineWidth }\n : options;\n\n const lines = sourceLines.slice(shape.startLine, shape.endLine + 1);\n\n reports.push({\n file: filename,\n kind: shape.kind,\n startLine: shape.startLine + 1,\n endLine: shape.endLine + 1,\n indent: /^[\\t ]*/.exec(lines[0])?.[0] ?? '',\n width: options.width,\n maxWidth: options.maxWidth,\n lengths: lines.map((line) => visualLength(line.trimEnd(), options.tabWidth)),\n text: lines.join('\\n'),\n paragraphs: shape.paragraphs.map((paragraph) => analyzeParagraph(paragraph, paragraphOptions)),\n });\n }\n\n return { comments: reports };\n}\n\n/**\n * Whether the comment has any issue, including hints, which makes it worth handing to the agent.\n */\nexport function isSuspicious(report: CommentReport): boolean {\n return report.paragraphs.some((paragraph) => paragraph.issues.length > 0);\n}\n\n/**\n * Whether the comment has an issue that isn't a hint, so it breaks the rules no matter what\n * the agent decided.\n */\nexport function hasVerdictIssues(report: CommentReport): boolean {\n return report.paragraphs.some((paragraph) => paragraph.issues.some((issue) => issue.tier === 'verdict'));\n}\n\n/**\n * Returns the comment's source text with every prose paragraph replaced by its suggestion.\n * Code, tables, diagrams, and similar paragraphs are kept as they are.\n */\nexport function rewrapComment(report: CommentReport): string {\n const lines = report.text.split('\\n');\n\n const paragraphs = report.paragraphs\n .filter((paragraph) => paragraph.suggestion !== null)\n .toSorted((a, b) => b.startLine - a.startLine);\n\n for (const paragraph of paragraphs) {\n const start = paragraph.startLine - report.startLine;\n\n lines.splice(start, paragraph.endLine - paragraph.startLine + 1, ...(paragraph.suggestion ?? []));\n }\n\n return lines.join('\\n');\n}\n\nconst POSITION_KEYS = new Set(['start', 'end', 'range', 'loc']);\n\n/**\n * Returns the syntax tree of the source as JSON, without positions or comments, used to verify\n * that only comments changed. Moving or rewording a comment keeps it the same, while any change\n * to a string, template, regex, JSX text, or where a statement ends changes it. A source that\n * doesn't parse has no tree to compare, so all of its text counts.\n */\nexport function codeFingerprint(source: string, filename: string): string {\n const { program, errors } = parseSource(filename, source);\n\n if (errors.length > 0) {\n return JSON.stringify({ source, errors: errors.map((error) => error.message) });\n }\n\n // a BigInt literal's value is a `bigint`, which JSON can't hold, but its `raw` text already tells it apart\n return JSON.stringify(program, (key, value: unknown) =>\n POSITION_KEYS.has(key) || typeof value === 'bigint' ? undefined : value,\n );\n}\n","export type StyleIssueType = 'semicolon' | 'em-dash' | 'dash' | 'label-colon' | 'emphasis' | 'banner';\n\nexport interface StyleLine {\n /**\n * This is the 0-based line in the file.\n */\n readonly index: number;\n readonly text: string;\n}\n\nexport interface StyleIssue {\n readonly type: StyleIssueType;\n readonly index: number;\n}\n\n/**\n * Matches four or more repeated characters at the start or end of a line, since three like `===`,\n * `---`, or `~~~` are operators, rules, and fences in prose. A run in the middle of a line is a\n * table rule like `| ---- |` or an arrow like `---->`, and a Markdown heading like `#### Examples`\n * isn't a banner either.\n */\nconst BANNER = /^(?!#{1,6}\\s)([-=*#_~+/\\\\])\\1{3,}|([-=*#_~])\\2{3,}\\s*$/;\n\n/**\n * Runs of the same character separated only by spaces, like `-------- -----`, underline the\n * columns of a table.\n */\nconst COLUMN_RULE = /^([-=_~])\\1*(?:\\s+\\1+)+$/;\n\n/**\n * Matches an en-dash, a spaced hyphen, or a double hyphen between words, which may stand in for an\n * em-dash. An en-dash or hyphen between numbers, like `10 – 20`, is a range, and a double hyphen\n * next to a CLI flag, like `--watch -- file` or `npm test -- --watch`, separates arguments.\n */\nconst DASH = /(?<!\\d)\\s[–-]\\s(?!\\d)|(?<!(?:^|\\s)-[\\w-]*)\\s--\\s(?!-)/;\nconst SEMICOLON = /;(?:\\s|$)/;\n\n/**\n * Matches `*emphasis*` or `**bold**`, which starts with a letter or digit and whose\n * closing asterisks end the word, so that globs like `*foo*.ts` or `*.test.*` aren't\n * emphasis. Asterisks in quotes, like `'*foo*'`, are a string or glob.\n */\nconst EMPHASIS = /(?:^|[\\s(])(\\*\\*?)(?=[\\p{L}\\p{N}])[^*]+?(?<!\\s)\\1(?=$|[\\s)\"']|[.,;:!?](?:$|[\\s)\"']))/u;\n\nexport const LIST_MARKER = /^(?:[-*+]|\\d+[.)])\\s+/;\n\n/**\n * A code span, as in Markdown, closes with a run of as many backticks as it opened with,\n * like ``` `` `a` `` ```, and may continue on the next line.\n */\nexport const CODE_SPAN = /(?<!`)(`+)(?!`)[\\s\\S]*?(?<!`)\\1(?!`)/g;\n\n/**\n * Matches a colon after a word with more text after it on the same line, like `Optional: skips it`\n * or `...through its presets: the rules that...`. A colon that ends a line introduces what's below\n * it. Markers like `TODO:` or `WARNING:` that start a sentence are conventions read by tooling,\n * and a colon after a code span or `{@link}` (replaced by `code` in prose) introduces a definition,\n * like `` `width`: the maximum width ``, so neither counts. Neither does an identifier in camel or\n * snake case, like `maxRetries: 3`, which is a property.\n */\nconst COLON =\n /(?<=[\\w)\\]'\"’])(?<!(?:^|[.!?]\\s+)(?:[A-Z]{2,}|[Tt]odo|[Ff]ixme|[Hh]ack|[Xx]xx))(?<!\\b(?:code|url|entity|[A-Za-z][a-z\\d]*[A-Z]\\w*|\\w*_\\w*)):\\s+\\S/;\n\nexport function replaceKeepingLines(text: string, pattern: RegExp, replacement: string): string {\n return text.replaceAll(pattern, (match) => `${replacement}${'\\n'.repeat(match.split('\\n').length - 1)}`);\n}\n\nexport function stripNonProse(text: string): string {\n let stripped = replaceKeepingLines(text, CODE_SPAN, 'code');\n\n for (let previous = ''; previous !== stripped; ) {\n previous = stripped;\n stripped = replaceKeepingLines(stripped, /\\{[^{}]*\\}/g, 'code');\n }\n\n return stripped\n .replaceAll(/\\b[a-z][\\w+.-]*:\\/\\/\\S+/gi, 'url')\n .replaceAll(/&(?:[a-z][a-z\\d]*|#\\d+|#x[\\da-f]+);/gi, 'entity');\n}\n\nfunction hasExplanatoryColon(text: string): boolean {\n return COLON.test(text.replace(LIST_MARKER, ''));\n}\n\nexport function isBanner(text: string): boolean {\n const prose = stripNonProse(text.trim());\n\n return BANNER.test(prose) && !COLUMN_RULE.test(prose);\n}\n\nexport function findStyleIssues(lines: readonly StyleLine[]): StyleIssue[] {\n const issues: StyleIssue[] = [];\n const prose = stripNonProse(lines.map((line) => line.text.trim()).join('\\n'));\n\n /**\n * A JSDoc tag's description starts a sentence after its `@param name -` style head.\n * The head, including its type, may wrap across lines.\n */\n const proseLines = replaceKeepingLines(prose, /^@\\w+\\s+(?:code\\s+)?(?:\\S+\\s+-\\s+)?/gm, '').split('\\n');\n\n for (const [position, line] of lines.entries()) {\n const text = proseLines[position].trim();\n\n const report = (type: StyleIssueType): void => {\n issues.push({ type, index: line.index });\n };\n\n if (isBanner(line.text)) {\n report('banner');\n } else {\n if (SEMICOLON.test(text)) {\n report('semicolon');\n }\n\n if (text.includes('—')) {\n report('em-dash');\n }\n\n if (DASH.test(text)) {\n report('dash');\n }\n\n if (hasExplanatoryColon(text)) {\n report('label-colon');\n }\n\n if (EMPHASIS.test(text)) {\n report('emphasis');\n }\n }\n }\n\n return issues;\n}\n","export interface WrapOptions {\n /**\n * Sets whether a line may not end with the first word of a sentence, clause, or parenthetical,\n * like `This`, `the` after a comma, or `(the`. Such a word moves to the next line instead.\n * It also sets whether the first of two lines ends with a sentence instead of the start of the\n * next one, as long as the second line is then no longer than the first.\n */\n readonly avoidSentenceOrphans: boolean;\n\n /**\n * Sets how many columns a line may exceed its limit before it counts as overflowing.\n */\n readonly tolerance: number;\n\n /**\n * Sets how many extra columns a complete parenthetical may use beyond the preferred line limit.\n */\n readonly parentheticalOverflow?: number;\n}\n\nexport type LineIssueType = 'overflow' | 'underfill' | 'orphan' | 'widow' | 'unbalanced';\n\nexport interface LineIssue {\n readonly type: LineIssueType;\n\n /**\n * Holds the index of the offending line within the paragraph.\n */\n readonly line: number;\n}\n\n// punctuation inside a code span, like `,` or `?.`, is code and doesn't end a clause or sentence\nconst CLAUSE_END = /[.!?,;:][\"')\\]*_]*$/;\nconst SENTENCE_END = /[.!?][\"')\\]*_]*$/;\n\n/**\n * Holds only abbreviations that never end a sentence, unlike `no.` or `max.`, which can also be the\n * last word of one.\n */\nconst ABBREVIATIONS = new Set([\n 'e.g.',\n 'i.e.',\n 'etc.',\n 'vs.',\n 'cf.',\n 'approx.',\n 'incl.',\n 'resp.',\n 'al.',\n 'viz.',\n 'esp.',\n 'ca.',\n 'fig.',\n 'figs.',\n 'eq.',\n 'vol.',\n 'pp.',\n 'mr.',\n 'mrs.',\n 'ms.',\n 'dr.',\n 'prof.',\n 'st.',\n]);\n\nexport function isAbbreviation(word: string): boolean {\n const bare = word\n .replace(/^[([\"']+/, '')\n .replace(/[)\\]\"']+$/, '')\n .toLowerCase();\n\n return ABBREVIATIONS.has(bare) || /^(?:[a-z]\\.){2,}$/.test(bare);\n}\n\nfunction findClosingBrace(text: string, start: number): number {\n let depth = 0;\n\n for (let index = start; index < text.length; index += 1) {\n if (text[index] === '{') {\n depth += 1;\n } else if (text[index] === '}') {\n depth -= 1;\n\n if (depth === 0) {\n return index;\n }\n }\n }\n\n return -1;\n}\n\nfunction backtickRun(text: string, start: number): number {\n let end = start;\n\n while (text[end] === '`') {\n end += 1;\n }\n\n return end - start;\n}\n\n/**\n * As in Markdown, a code span opened by a run of backticks only closes with a run of the same\n * length, like the two in ``` `` `a` `` ```.\n */\nfunction findCodeSpanEnd(text: string, start: number): number {\n const run = backtickRun(text, start);\n\n for (let index = text.indexOf('`', start + run); index !== -1; ) {\n const length = backtickRun(text, index);\n\n if (length === run) {\n return index + length - 1;\n }\n\n index = text.indexOf('`', index + length);\n }\n\n return -1;\n}\n\n/**\n * JSDoc writes types and `{@link ...}` tags as `{...}` groups, so they stay intact like code spans.\n */\nexport function tokenize(text: string): string[] {\n const tokens: string[] = [];\n\n let current = '';\n let index = 0;\n\n while (index < text.length) {\n const char = text[index];\n const close = char === '`' ? findCodeSpanEnd(text, index) : char === '{' ? findClosingBrace(text, index) : -1;\n\n // a run of backticks that never closes is literal text, and none of its backticks open a span\n if (char === '`' && close === -1) {\n const run = backtickRun(text, index);\n\n current += text.slice(index, index + run);\n index += run;\n\n continue;\n }\n\n if (close !== -1) {\n current += text.slice(index, close + 1);\n index = close + 1;\n\n continue;\n }\n\n if (/\\s/.test(char)) {\n if (current) {\n tokens.push(current);\n\n current = '';\n }\n\n index += 1;\n\n continue;\n }\n\n current += char;\n index += 1;\n }\n\n if (current) {\n tokens.push(current);\n }\n\n return tokens;\n}\n\nfunction parentheticalEnd(text: string): number {\n let depth = 0;\n\n for (let index = 0; index < text.length; index += 1) {\n const char = text[index];\n\n if (char === '\\\\') {\n index += 1;\n\n continue;\n }\n\n const close = char === '`' ? findCodeSpanEnd(text, index) : char === '{' ? findClosingBrace(text, index) : -1;\n\n if (close !== -1) {\n index = close;\n } else if (char === '(') {\n depth += 1;\n } else if (char === ')' && --depth === 0) {\n return index;\n }\n }\n\n return -1;\n}\n\nfunction isParenthetical(token: string): boolean {\n return token.startsWith('(') && parentheticalEnd(token) !== -1;\n}\n\ninterface ParentheticalGroup {\n readonly start: number;\n readonly end: number;\n}\n\nfunction parentheticalGroups(tokens: readonly string[], limit: number): ParentheticalGroup[] {\n const groups: ParentheticalGroup[] = [];\n\n for (let index = 0; index < tokens.length; index += 1) {\n if (tokens[index].startsWith('(')) {\n const end = parentheticalEnd(tokens.slice(index).join(' '));\n\n let last = index;\n let length = tokens[index].length;\n\n while (length <= end && last + 1 < tokens.length) {\n length += 1 + tokens[++last].length;\n }\n\n if (end !== -1 && length <= limit) {\n groups.push({ start: index, end: last + 1 });\n\n index = last;\n\n continue;\n }\n }\n }\n\n return groups;\n}\n\nexport function bindParentheticals(tokens: readonly string[], limit: number): string[] {\n const groups = new Map(parentheticalGroups(tokens, limit).map((group) => [group.start, group.end]));\n const units: string[] = [];\n\n for (let index = 0; index < tokens.length; index += 1) {\n const end = groups.get(index) ?? index + 1;\n\n units.push(tokens.slice(index, end).join(' '));\n\n index = end - 1;\n }\n\n return units;\n}\n\nfunction endsClause(token: string): boolean {\n return CLAUSE_END.test(token) && !isAbbreviation(token);\n}\n\nfunction endsSentence(token: string): boolean {\n return SENTENCE_END.test(token) && !isAbbreviation(token);\n}\n\nfunction opensAside(token: string): boolean {\n return /^[([]/.test(token) && !/[)\\]][\"'`.,;:!?]*$/.test(token);\n}\n\nfunction isOrphan(previous: string, token: string): boolean {\n return opensAside(token) || (endsClause(previous) && !CLAUSE_END.test(token));\n}\n\n/**\n * Returns whether Markdown or JSDoc reads a word as the start of a block when it begins a line,\n * like a list marker (`-`, `1.`), a heading (`#`), a quote (`>`), a fence, a table row, an HTML\n * tag, or a JSDoc tag like `@param`. Wrapping must never move such a word to the start of a line,\n * or the paragraph would turn into something else.\n */\nexport function startsBlock(token: string): boolean {\n return /^(?:[-*+>]|\\d+[.)]|#{1,6})$/.test(token) || /^(?:@[A-Za-z]|`{3}|~{3}|\\||<\\/?[A-Za-z])/.test(token);\n}\n\nexport function bindLineStarts(\n tokens: readonly string[],\n startsLine: (token: string, next: string | undefined) => boolean = startsBlock,\n): string[] {\n const units: string[] = [];\n\n for (const [index, token] of tokens.entries()) {\n if (units.length > 0 && startsLine(token, tokens[index + 1])) {\n units[units.length - 1] += ` ${token}`;\n } else {\n units.push(token);\n }\n }\n\n return units;\n}\n\nfunction breaksBefore(previous: string, last: string, next: string, options: WrapOptions): boolean {\n return (options.avoidSentenceOrphans && isOrphan(previous, last)) || startsBlock(next);\n}\n\nfunction lineLength(tokens: readonly string[]): number {\n let length = 0;\n\n for (const token of tokens) {\n length += token.length;\n }\n\n return length + Math.max(0, tokens.length - 1);\n}\n\n/**\n * The first line can have a different limit than the rest, e.g. when a list marker takes up space\n * only on the first line.\n */\nexport function wrapTokens(\n tokens: readonly string[],\n firstLimit: number,\n restLimit: number,\n options: WrapOptions,\n): string[][] {\n return wrapFrom(tokens, 0, firstLimit, restLimit, options, Infinity);\n}\n\n/**\n * Wraps the tokens from the one at `from` on, and stops after `maxLines` lines. A line\n * never depends on the lines after it, so the first lines of a wrap are the same with or\n * without the rest.\n */\nfunction wrapFrom(\n tokens: readonly string[],\n from: number,\n firstLimit: number,\n restLimit: number,\n options: WrapOptions,\n maxLines: number,\n): string[][] {\n const lines: string[][] = [];\n\n let line: string[] = [];\n let length = 0;\n\n for (let index = from; index < tokens.length; index += 1) {\n const token = tokens[index];\n\n while (line.length > 0) {\n const limit = lines.length === 0 ? firstLimit : restLimit;\n const nextLength = length + 1 + token.length;\n const extra = isParenthetical(token) ? (options.parentheticalOverflow ?? 0) : 0;\n\n if (nextLength <= limit + extra) {\n break;\n }\n\n const carry: string[] = [];\n\n while (line.length >= 2 && breaksBefore(line.at(-2) ?? '', line.at(-1) ?? '', carry[0] ?? token, options)) {\n carry.unshift(line.pop() ?? '');\n }\n\n lines.push(line);\n\n if (lines.length >= maxLines) {\n return lines;\n }\n\n line = carry;\n length = lineLength(carry);\n }\n\n line.push(token);\n\n length = lineLength(line);\n }\n\n if (line.length > 0) {\n lines.push(line);\n }\n\n return lines;\n}\n\nconst MIN_LAST_LINE_WORDS = 3;\n\nexport function hasWidow(lines: readonly (readonly string[])[]): boolean {\n const last = lines.at(-1) ?? [];\n const words = last.reduce((count, token) => count + (isParenthetical(token) ? tokenize(token).length : 1), 0);\n\n return lines.length >= 2 && words < MIN_LAST_LINE_WORDS;\n}\n\nexport interface LayoutOptions extends WrapOptions {\n /**\n * Keeps the first line out of the balancing, e.g. for a JSDoc tag whose first\n * line holds `@param {Type} name -`.\n */\n readonly keepFirstLine?: boolean;\n\n /**\n * Keeps the fewest lines even when a line sticks out far past the line before it.\n */\n readonly keepSteps?: boolean;\n}\n\n/**\n * Sets how heavily lines that come close to the width count against lines that are even. With too\n * much weight, lines of 86 and 89 columns beat two of 86 at a width of 100, which leaves a word\n * like `as` at the end of the longer line, away from the words that it belongs to.\n */\nconst FULLNESS_WEIGHT = 0.07;\nconst PARENTHETICAL_SPLIT_WEIGHT = 2;\n\n/**\n * Sets how many columns a line may stick out past the line before it.\n */\nconst MAX_STEP = 15;\n\n/**\n * Sets how many lines more than its fewest a layout may take to keep a line from sticking out.\n */\nconst EXTRA_LINES = 2;\n\n/**\n * Holds what the cost of a line depends on, besides the length that the lines aim for.\n */\ninterface BalanceInput {\n /**\n * Holds the column that each token starts at when all tokens share a line, and the column after\n * the last token.\n */\n readonly starts: readonly number[];\n readonly count: number;\n\n /**\n * Holds how many fewer columns the first line has than the other lines.\n */\n readonly offset: number;\n\n /**\n * Holds for each token whether it may not start a line.\n */\n readonly blockStarts: readonly boolean[];\n\n /**\n * Holds for each token whether a line of two or more tokens may not end before it.\n */\n readonly afterOrphan: readonly boolean[];\n readonly splitCosts: ReadonlyMap<number, number>;\n}\n\n/**\n * Holds the cheapest layouts that end one line, one for each token that the line can end before.\n */\ninterface LineCosts {\n /**\n * Holds the token that the first entry of `costs` and `origins` ends before.\n */\n readonly base: number;\n readonly costs: readonly number[];\n\n /**\n * Holds the token that the line starts with in the layout of each entry of `costs`.\n */\n readonly origins: readonly number[];\n\n /**\n * Holds the first token that the line can end before.\n */\n readonly low: number;\n\n /**\n * Holds the last token that the line can end before.\n */\n readonly high: number;\n}\n\n/**\n * Returns, for each token, the fewest lines of at most `target` columns that hold the tokens from\n * it on. No token is longer than `target`.\n */\nfunction fewestLines(starts: readonly number[], target: number): Int32Array {\n const total = starts.length - 1;\n const fewest = new Int32Array(total + 1);\n\n let end = total;\n\n for (let index = total - 1; index >= 0; index -= 1) {\n while (starts[end] - starts[index] - 1 > target) {\n end -= 1;\n }\n\n fewest[index] = fewest[end] + 1;\n }\n\n return fewest;\n}\n\n/**\n * Returns the first index from `from` on whose value is at most `limit`. The values never grow as\n * the index rises, so a binary search can find it.\n */\nfunction firstAtMost(values: Int32Array, limit: number, from: number): number {\n let low = from;\n let high = values.length - 1;\n\n while (low < high) {\n const middle = Math.floor((low + high) / 2);\n\n if (values[middle] <= limit) {\n high = middle;\n } else {\n low = middle + 1;\n }\n }\n\n return low;\n}\n\n/**\n * Returns the cheapest layouts that end the given line, or `undefined` when the line can't end\n * anywhere. It only looks at the ends that a whole layout can use. The lines before it reach up\n * to an end, and the lines after it can hold the rest from an end on, which leaves a narrow band\n * of tokens instead of all of them.\n */\nfunction costsOfLine(\n input: BalanceInput,\n target: number,\n line: number,\n previous: LineCosts,\n fewest: Int32Array,\n): LineCosts | undefined {\n const { starts, afterOrphan } = input;\n const offset = line === 1 ? input.offset : 0;\n const linesLeft = input.count - line;\n\n // each line after this one needs a token\n const last = starts.length - 1 - linesLeft;\n const base = firstAtMost(fewest, linesLeft, Math.max(line, previous.low + 1));\n const costs: number[] = [];\n const origins: number[] = [];\n\n let low = -1;\n let high = -1;\n\n for (let end = base; end <= last; end += 1) {\n const nearest = Math.min(end - 1, previous.high);\n\n // from here on, a line is too long even when it starts at the last end of the line before it\n if (end > previous.high && starts[end] - starts[nearest] - 1 + offset > target) {\n break;\n }\n\n let cost = Infinity;\n let origin = -1;\n\n if (!input.blockStarts[end]) {\n const splitCost = input.splitCosts.get(end) ?? 0;\n\n for (let start = nearest; start >= previous.low; start -= 1) {\n const length = starts[end] - starts[start] - 1 + offset;\n\n if (length > target) {\n break;\n }\n\n const before = previous.costs[start - previous.base];\n\n if (before === Infinity || (afterOrphan[end] && end - start >= 2)) {\n continue;\n }\n\n const candidate = before + (target - length) ** 2 + splitCost;\n\n if (candidate <= cost) {\n cost = candidate;\n origin = start;\n }\n }\n }\n\n costs.push(cost);\n origins.push(origin);\n\n if (cost !== Infinity) {\n low = low === -1 ? end : low;\n high = end;\n }\n }\n\n return low === -1 ? undefined : { base, costs, origins, low, high };\n}\n\n/**\n * Lays the tokens out in `count` lines that are as even as possible. It tries every length that\n * the lines can aim for and keeps the layout with the lowest cost. Of two layouts with the same\n * cost, it keeps the one that aims for longer lines, and then the one with the longer last line.\n */\nfunction balanceTokens(\n tokens: readonly string[],\n firstLimit: number,\n restLimit: number,\n count: number,\n options: WrapOptions,\n preferredLimit = restLimit,\n splitCosts: ReadonlyMap<number, number> = new Map(),\n): string[][] | undefined {\n const total = tokens.length;\n const starts = [0];\n\n let longest = -Infinity;\n\n for (const token of tokens) {\n starts.push((starts.at(-1) ?? 0) + token.length + 1);\n\n longest = Math.max(longest, token.length);\n }\n\n const input: BalanceInput = {\n starts,\n count,\n offset: restLimit - firstLimit,\n blockStarts: tokens.map((token) => startsBlock(token)),\n afterOrphan: tokens.map((_, index) => {\n return options.avoidSentenceOrphans && index >= 2 && isOrphan(tokens[index - 2], tokens[index - 1]);\n }),\n splitCosts,\n };\n\n const targets: number[] = [];\n\n for (let target = restLimit; target >= Math.max(longest, Math.floor(restLimit / 2)); target -= 1) {\n targets.push(target);\n }\n\n // the lines before the last one hold at most this many columns together, which is when the last line is empty\n const most = starts[total] - count + input.offset;\n\n let best: { cost: number; target: number; breaks: number[] } | undefined;\n\n /**\n * Short targets come first. They rule most layouts out, so they are cheap, and their cost lets\n * the loop skip the long targets, whose lines can't all be full.\n */\n for (const target of targets.toReversed()) {\n const fullness = FULLNESS_WEIGHT * (count - 1) * (preferredLimit - target) ** 2;\n const spare = (count - 1) * target - most;\n\n // lines that are `spare` columns short together cost the least when they are all equally short\n const least = count > 1 && spare > 0 ? Math.max(spare ** 2 / (count - 1) - 1, 0) : 0;\n\n if (best !== undefined && least + fullness > best.cost) {\n continue;\n }\n\n const fewest = fewestLines(starts, target);\n const rows: LineCosts[] = [{ base: 0, costs: [0], origins: [-1], low: 0, high: 0 }];\n\n for (let line = 1; line < count; line += 1) {\n const row = costsOfLine(input, target, line, rows[line - 1], fewest);\n\n if (!row) {\n break;\n }\n\n rows.push(row);\n }\n\n if (rows.length < count) {\n continue;\n }\n\n const row = rows[count - 1];\n\n for (let start = row.low; start <= row.high; start += 1) {\n const score = row.costs[start - row.base] + fullness;\n\n const improves = score < (best?.cost ?? Infinity) || (score === best?.cost && target > best.target);\n\n if (!improves || starts[total] - starts[start] - 1 > target || hasWidow([[], tokens.slice(start)])) {\n continue;\n }\n\n const breaks = [start];\n\n for (let line = count - 1; line > 1; line -= 1) {\n breaks.unshift(rows[line].origins[breaks[0] - rows[line].base]);\n }\n\n best = { cost: score, target, breaks };\n }\n }\n\n if (!best) {\n return undefined;\n }\n\n const bounds = [0, ...best.breaks, total];\n\n return bounds.slice(0, -1).map((start, index) => tokens.slice(start, bounds[index + 1]));\n}\n\n/**\n * Returns whether a line sticks out more than `MAX_STEP` columns past the line before it. The first\n * line starts `offset` columns after the others, so it ends that much later too.\n */\nfunction hasStep(lines: readonly (readonly string[])[], offset = 0): boolean {\n return lines.some((line, index) => {\n if (index === 0) {\n return false;\n }\n\n const before = lineLength(lines[index - 1]) + (index === 1 ? offset : 0);\n\n return lineLength(line) - before > MAX_STEP;\n });\n}\n\nfunction splitCostsOf(tokens: readonly string[], limit: number): Map<number, number> {\n const splitCosts = new Map<number, number>();\n\n for (const group of parentheticalGroups(tokens, limit)) {\n const length = lineLength(tokens.slice(group.start, group.end));\n\n for (let at = group.start + 1; at < group.end; at += 1) {\n splitCosts.set(at, length * PARENTHETICAL_SPLIT_WEIGHT);\n }\n }\n\n return splitCosts;\n}\n\nfunction hasParentheticals(tokens: readonly string[], restLimit: number, options: WrapOptions): boolean {\n if (options.parentheticalOverflow === undefined) {\n return false;\n }\n\n return bindParentheticals(tokens, restLimit + options.parentheticalOverflow).some((token) => isParenthetical(token));\n}\n\n/**\n * Lays the tokens out in even lines. When a line sticks out far past the line before it, like a\n * full second line after a first line that the orphan rule keeps short, the layout takes up to\n * `EXTRA_LINES` more lines if those avoid the step.\n */\nexport function layoutTokens(\n tokens: readonly string[],\n firstLimit: number,\n restLimit: number,\n options: LayoutOptions,\n): string[][] {\n const lines = layoutLines(tokens, firstLimit, restLimit, options);\n const offset = restLimit - firstLimit;\n\n // the first line of a JSDoc tag is never balanced, and the lines after it get their own layout\n if (options.keepFirstLine || options.keepSteps || !hasStep(lines, offset)) {\n return lines;\n }\n\n const overflow = hasParentheticals(tokens, restLimit, options) ? (options.parentheticalOverflow ?? 0) : 0;\n const splitCosts = overflow > 0 ? splitCostsOf(tokens, restLimit + overflow) : new Map<number, number>();\n\n for (let count = lines.length + 1; count <= lines.length + EXTRA_LINES; count += 1) {\n const even = balanceTokens(\n tokens,\n firstLimit + overflow,\n restLimit + overflow,\n count,\n options,\n restLimit,\n splitCosts,\n );\n\n if (even && !hasStep(even, offset)) {\n return even;\n }\n }\n\n return lines;\n}\n\nfunction layoutLines(\n tokens: readonly string[],\n firstLimit: number,\n restLimit: number,\n options: LayoutOptions,\n): string[][] {\n if (options.parentheticalOverflow !== undefined) {\n const grouped = bindParentheticals(tokens, restLimit + options.parentheticalOverflow);\n\n if (grouped.some((token) => isParenthetical(token))) {\n const minimumLines = Math.max(\n 2,\n Math.ceil((lineLength(tokens) + 1 + restLimit - firstLimit) / Math.max(1, restLimit + 1)),\n );\n\n let preserved = wrapTokens(grouped, firstLimit, restLimit, options);\n\n if (minimumLines === 2 && preserved.length > 2) {\n const wide = wrapTokens(\n grouped,\n firstLimit + options.parentheticalOverflow,\n restLimit + options.parentheticalOverflow,\n { ...options, parentheticalOverflow: undefined },\n );\n\n if (wide.length === 2 && !hasWidow(wide)) {\n preserved = wide;\n }\n }\n\n if (preserved.length <= 2 && !hasWidow(preserved)) {\n let cursor = 0;\n\n return preserved.map((line) => {\n const expanded: string[] = [];\n const length = lineLength(line);\n\n let used = -1;\n\n while (cursor < tokens.length && used < length) {\n const token = tokens[cursor++];\n\n expanded.push(token);\n\n used += token.length + 1;\n }\n\n return expanded;\n });\n }\n\n const splitCosts = splitCostsOf(tokens, restLimit + options.parentheticalOverflow);\n const preferred = wrapTokens(tokens, firstLimit, restLimit, { ...options, parentheticalOverflow: undefined });\n\n for (let count = minimumLines; count <= Math.max(preferred.length + 1, preserved.length); count += 1) {\n const balanced = balanceTokens(\n tokens,\n firstLimit + options.parentheticalOverflow,\n restLimit + options.parentheticalOverflow,\n count,\n options,\n restLimit,\n splitCosts,\n );\n\n if (balanced) {\n return balanced;\n }\n }\n }\n }\n\n const greedy = wrapTokens(tokens, firstLimit, restLimit, options);\n\n if (greedy.length < 2) {\n return greedy;\n }\n\n if (options.keepFirstLine) {\n const [head] = greedy;\n const rest = layoutTokens(tokens.slice(head.length), restLimit, restLimit, { ...options, keepFirstLine: false });\n const lines = [head, ...rest];\n\n if (!hasWidow(lines)) {\n return lines;\n }\n }\n\n const balanced = balanceTokens(tokens, firstLimit, restLimit, greedy.length, options);\n\n if (balanced) {\n return balanced;\n }\n\n const stretched = wrapTokens(tokens, firstLimit + options.tolerance, restLimit + options.tolerance, options);\n\n return hasWidow(stretched) ? greedy : stretched;\n}\n\n/**\n * Ends the first of two lines with a sentence when the rest fits on the second line without\n * sticking out past the first. A second line that would stick out keeps the lines as they are.\n */\nexport function breakAfterSentence(\n lines: string[][],\n firstLimit: number,\n restLimit: number,\n options: WrapOptions,\n): string[][] {\n if (lines.length !== 2 || !options.avoidSentenceOrphans) {\n return lines;\n }\n\n const tokens = lines.flat();\n\n // the first line starts this many columns after the second, so it ends that much later too\n const offset = restLimit - firstLimit;\n\n for (let end = tokens.length - 1; end > 0; end -= 1) {\n const first = tokens.slice(0, end);\n const second = tokens.slice(end);\n\n // a second line that is no longer than a first line within its limit is within its own limit too\n if (\n endsSentence(tokens[end - 1]) &&\n !hasWidow([first, second]) &&\n !breaksBefore(tokens[end - 2] ?? '', tokens[end - 1], tokens[end], options) &&\n lineLength(first) <= firstLimit &&\n lineLength(second) <= lineLength(first) + offset\n ) {\n return [first, second];\n }\n }\n\n return lines;\n}\n\n/**\n * A wrap produced by `wrapTokens` with the same arguments never has issues, unless a single token\n * is wider than the limit.\n */\nexport function findLineIssues(\n lines: readonly (readonly string[])[],\n firstLimit: number,\n restLimit: number,\n options: WrapOptions,\n): LineIssue[] {\n const issues: LineIssue[] = [];\n const tokens = lines.flat();\n\n let next = 0;\n\n for (const [index, line] of lines.entries()) {\n const limit = index === 0 ? firstLimit : restLimit;\n const length = lineLength(line);\n const start = next;\n\n next += line.length;\n\n if (line.length > 1 && length > limit + options.tolerance) {\n issues.push({ type: 'overflow', line: index });\n }\n\n if (index === lines.length - 1 || line.length === 0) {\n continue;\n }\n\n if (options.avoidSentenceOrphans && line.length >= 2 && isOrphan(line.at(-2) ?? '', line.at(-1) ?? '')) {\n issues.push({ type: 'orphan', line: index });\n }\n\n /**\n * Only the first line of a wrap of the rest counts. A line that may end with the start of a\n * sentence is measured too, because the words that fit on it don't depend on its last word.\n */\n const [expected] = wrapFrom(tokens, start, limit, restLimit, options, 1);\n\n if (expected.length > line.length) {\n issues.push({ type: 'underfill', line: index });\n }\n }\n\n return issues;\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nexport type AgentRunner = 'claude' | 'codex' | 'cursor';\nexport type HookMode = 'agent' | 'report' | 'off';\nexport type AgentScope = 'suspicious' | 'all';\n\nexport interface AgentConfig {\n /**\n * Names the agent CLI to spawn. Defaults to the host that triggered the hook, or `claude`\n * when run standalone.\n */\n readonly runner?: AgentRunner;\n\n /**\n * Names the model passed to the runner. Defaults to `haiku` for Claude Code and to the\n * CLI's default otherwise.\n */\n readonly model?: string;\n\n /**\n * Lists extra arguments appended to the runner's command line.\n */\n readonly args?: readonly string[];\n\n /**\n * Sets a fully custom command, e.g. `['my-agent', '--prompt', '{prompt}']`. Without a `{prompt}`\n * placeholder, the prompt is written to stdin. Overrides `runner`, `model`, and `args`.\n */\n readonly command?: readonly string[];\n\n /**\n * Sets how many seconds to wait for each agent before giving up. Defaults to 300.\n */\n readonly timeout?: number;\n\n /**\n * Sets the most comments to hand to one agent. More comments are split across several agents.\n * A file's comments always go to the same agent, since parallel agents editing one file would\n * overwrite each other's edits, so a file with more comments than this gets an agent of its\n * own. Defaults to 20.\n */\n readonly batchSize?: number;\n\n /**\n * Sets the most files to hand to one agent, since an agent editing many files is slower and less\n * careful. More files are split across several agents. Defaults to 10.\n */\n readonly maxFiles?: number;\n\n /**\n * Caps how many agents run at once. The other agents wait, and each one starts when a running\n * agent finishes. Defaults to 6.\n */\n readonly maxAgents?: number;\n\n /**\n * Points to a Markdown file with formatting rules, relative to the config file.\n * Replaces the built-in rules.\n */\n readonly rules?: string;\n\n /**\n * Holds extra instructions appended to the rules.\n */\n readonly instructions?: string;\n\n /**\n * Selects which comments the agent sees. `suspicious` (default) is a triage, not a full review.\n * It only sends comments with hints, like a possible semicolon or a line that may end with the\n * first word of a sentence, and comments with issues in parts the tool never rewraps, so most\n * runs never call the agent. The tool fixes the layout of prose itself. `all` sends every comment\n * in changed lines, so that the agent reviews the wording of each against its rules.\n */\n readonly scope?: AgentScope;\n}\n\nexport interface HookConfig {\n /**\n * Sets what the stop hook does with comments in changed lines.\n *\n * - `agent` (default): hand them to an agent and report any that still don't fit afterwards.\n * - `report`: only report suspicious comments.\n * - `off`: do nothing.\n */\n readonly mode?: HookMode;\n}\n\nexport interface CommentsConfig {\n /**\n * Sets the preferred line length for comments, including indentation and the comment prefix.\n * Defaults to prettier's `printWidth`, or 80.\n */\n readonly width?: number;\n\n /**\n * Sets the hard limit for measured prose. Defaults to 120, or `width` when it is larger.\n * Parentheticals may use the space between `width` and this limit to stay together.\n */\n readonly maxWidth?: number;\n\n /**\n * Sets the maximum length of the line that holds a comment whose whole text is one prose\n * paragraph. Such a comment stays on one line up to this length, even past `width`, and is\n * wrapped to `width` beyond it. Defaults to 120 and never exceeds `maxWidth`.\n */\n readonly singleLineWidth?: number;\n\n /**\n * Sets a legacy hard limit of `width + tolerance` when `maxWidth` is omitted.\n * An explicit `maxWidth` takes precedence.\n */\n readonly tolerance?: number;\n\n /**\n * Keep the first word of a new sentence or parenthetical off the end of a line, e.g.\n * `...the module. This` or `...reflows (the` followed by the rest on the next line.\n * A paragraph of two lines also ends its first line with a sentence when the rest fits\n * on the second line and is no longer than the first, instead of with the start of the\n * next sentence, like `...the module. This one`. Defaults to `true`.\n */\n readonly avoidSentenceOrphans?: boolean;\n\n /**\n * Looks for possible style issues (semicolons, em-dashes and dashes, `label: explanation` colons,\n * asterisk emphasis, and section banners) and reports them as hints, so that the `suspicious` scope\n * hands those comments to the agent too. It only controls this search, and the agent's rules apply\n * to every comment the agent sees either way. Defaults to `true`.\n */\n readonly style?: boolean;\n\n /**\n * Lists the file extensions to process. Defaults to JavaScript and TypeScript extensions.\n */\n readonly extensions?: readonly string[];\n\n /**\n * Lists glob patterns, relative to the repository root, of files to skip.\n */\n readonly ignore?: readonly string[];\n readonly agent?: AgentConfig;\n readonly hook?: HookConfig;\n}\n\nexport interface LoadedConfig {\n readonly config: CommentsConfig;\n readonly filepath?: string;\n}\n\nexport const DEFAULT_EXTENSIONS = Object.freeze(['.js', '.jsx', '.mjs', '.cjs', '.ts', '.tsx', '.mts', '.cts']);\n\nconst CONFIG_FILES = [\n 'comments.config.ts',\n 'comments.config.mts',\n 'comments.config.js',\n 'comments.config.mjs',\n 'comments.config.cjs',\n '.commentsrc',\n '.commentsrc.json',\n];\n\nconst PACKAGE_JSON_KEY = 'comments';\n\nexport function defineConfig(config: CommentsConfig): CommentsConfig {\n return config;\n}\n\nfunction readJson(filepath: string): unknown {\n try {\n return JSON.parse(readFileSync(filepath, 'utf8'));\n } catch (error) {\n throw new Error(`comments: failed to parse ${filepath}: ${(error as Error).message}`, { cause: error });\n }\n}\n\nasync function readConfigFile(filepath: string): Promise<unknown> {\n if (filepath.endsWith('rc') || filepath.endsWith('.json')) {\n return readJson(filepath);\n }\n\n const module = (await import(pathToFileURL(filepath).href)) as { default?: unknown };\n\n return module.default ?? module;\n}\n\nfunction assertType(value: unknown, type: string, key: string, filepath: string): void {\n const actual = Array.isArray(value) ? 'array' : typeof value;\n\n if (value !== undefined && actual !== type) {\n throw new Error(`comments: \\`${key}\\` in ${filepath} must be a ${type}, got ${actual}`);\n }\n}\n\nfunction assertStrings(value: unknown, key: string, filepath: string): void {\n if (Array.isArray(value) && !value.every((item) => typeof item === 'string')) {\n throw new Error(`comments: \\`${key}\\` in ${filepath} must only hold strings`);\n }\n}\n\nexport function validateConfig(raw: unknown, filepath: string): CommentsConfig {\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n throw new Error(`comments: ${filepath} must export an object`);\n }\n\n const config = raw as Record<string, unknown>;\n\n assertType(config.width, 'number', 'width', filepath);\n assertType(config.maxWidth, 'number', 'maxWidth', filepath);\n assertType(config.singleLineWidth, 'number', 'singleLineWidth', filepath);\n assertType(config.tolerance, 'number', 'tolerance', filepath);\n assertType(config.avoidSentenceOrphans, 'boolean', 'avoidSentenceOrphans', filepath);\n assertType(config.style, 'boolean', 'style', filepath);\n assertType(config.extensions, 'array', 'extensions', filepath);\n assertType(config.ignore, 'array', 'ignore', filepath);\n assertType(config.agent, 'object', 'agent', filepath);\n assertType(config.hook, 'object', 'hook', filepath);\n assertStrings(config.extensions, 'extensions', filepath);\n assertStrings(config.ignore, 'ignore', filepath);\n\n for (const key of ['width', 'maxWidth', 'singleLineWidth', 'tolerance'] as const) {\n const value = config[key];\n const minimum = key === 'tolerance' ? 0 : 1;\n\n if (value !== undefined && (!Number.isInteger(value) || (value as number) < minimum)) {\n throw new Error(`comments: \\`${key}\\` in ${filepath} must be an integer of at least ${minimum}`);\n }\n }\n\n if (typeof config.width === 'number' && typeof config.maxWidth === 'number' && config.maxWidth < config.width) {\n throw new Error(`comments: \\`maxWidth\\` in ${filepath} must be at least \\`width\\``);\n }\n\n const agent = (config.agent ?? {}) as Record<string, unknown>;\n\n if (agent.runner !== undefined && !['claude', 'codex', 'cursor'].includes(agent.runner as string)) {\n throw new Error(`comments: \\`agent.runner\\` in ${filepath} must be one of claude, codex, cursor`);\n }\n\n assertType(agent.model, 'string', 'agent.model', filepath);\n assertType(agent.args, 'array', 'agent.args', filepath);\n assertType(agent.command, 'array', 'agent.command', filepath);\n assertType(agent.timeout, 'number', 'agent.timeout', filepath);\n assertStrings(agent.args, 'agent.args', filepath);\n assertStrings(agent.command, 'agent.command', filepath);\n\n // a timeout of zero would stop every agent right away, and `NaN` is a number too\n if (agent.timeout !== undefined && !((agent.timeout as number) > 0)) {\n throw new Error(`comments: \\`agent.timeout\\` in ${filepath} must be a positive number`);\n }\n\n for (const key of ['batchSize', 'maxFiles', 'maxAgents'] as const) {\n const value = agent[key];\n\n if (value !== undefined && (!Number.isInteger(value) || (value as number) < 1)) {\n throw new Error(`comments: \\`agent.${key}\\` in ${filepath} must be a positive integer`);\n }\n }\n\n assertType(agent.rules, 'string', 'agent.rules', filepath);\n assertType(agent.instructions, 'string', 'agent.instructions', filepath);\n\n if (agent.scope !== undefined && agent.scope !== 'suspicious' && agent.scope !== 'all') {\n throw new Error(`comments: \\`agent.scope\\` in ${filepath} must be \"suspicious\" or \"all\"`);\n }\n\n const hook = (config.hook ?? {}) as Record<string, unknown>;\n\n if (hook.mode !== undefined && !['agent', 'report', 'off'].includes(hook.mode as string)) {\n throw new Error(`comments: \\`hook.mode\\` in ${filepath} must be one of agent, report, off`);\n }\n\n return config as CommentsConfig;\n}\n\nexport async function loadConfig(cwd: string, options: { explicitPath?: string; stopDir?: string } = {}) {\n if (options.explicitPath) {\n const filepath = path.resolve(cwd, options.explicitPath);\n\n return { config: validateConfig(await readConfigFile(filepath), filepath), filepath } satisfies LoadedConfig;\n }\n\n let directory = path.resolve(cwd);\n\n for (;;) {\n for (const name of CONFIG_FILES) {\n const filepath = path.join(directory, name);\n\n if (existsSync(filepath)) {\n return { config: validateConfig(await readConfigFile(filepath), filepath), filepath } satisfies LoadedConfig;\n }\n }\n\n const packageJsonPath = path.join(directory, 'package.json');\n\n if (existsSync(packageJsonPath)) {\n const value = (readJson(packageJsonPath) as Record<string, unknown>)[PACKAGE_JSON_KEY];\n\n if (value !== undefined) {\n return { config: validateConfig(value, packageJsonPath), filepath: packageJsonPath } satisfies LoadedConfig;\n }\n }\n\n const parent = path.dirname(directory);\n\n if (directory === options.stopDir || parent === directory) {\n return { config: {} } satisfies LoadedConfig;\n }\n\n directory = parent;\n }\n}\n\ninterface PrettierOptions {\n readonly printWidth?: number;\n readonly tabWidth?: number;\n}\n\ninterface PrettierModule {\n resolveConfig: (file: string) => Promise<PrettierOptions | null>;\n}\n\nconst PRETTIER_FILES = ['.prettierrc', '.prettierrc.json', '.prettierrc.json5'];\n\nfunction readPrettierFile(directory: string, stopDir: string): PrettierOptions | undefined {\n let current = directory;\n\n for (;;) {\n for (const name of PRETTIER_FILES) {\n const filepath = path.join(current, name);\n\n if (!existsSync(filepath)) {\n continue;\n }\n\n const text = readFileSync(filepath, 'utf8');\n\n // `.prettierrc` may be YAML, so fall back to plain key lookups\n const printWidth = /[\"']?printWidth[\"']?\\s*:\\s*(\\d+)/.exec(text)?.[1];\n const tabWidth = /[\"']?tabWidth[\"']?\\s*:\\s*(\\d+)/.exec(text)?.[1];\n\n return {\n printWidth: printWidth === undefined ? undefined : Number(printWidth),\n tabWidth: tabWidth === undefined ? undefined : Number(tabWidth),\n };\n }\n\n const packageJsonPath = path.join(current, 'package.json');\n\n if (existsSync(packageJsonPath)) {\n const prettier = (readJson(packageJsonPath) as { prettier?: unknown }).prettier;\n\n if (prettier && typeof prettier === 'object') {\n return prettier as PrettierOptions;\n }\n }\n\n const parent = path.dirname(current);\n\n if (current === stopDir || parent === current) {\n return undefined;\n }\n\n current = parent;\n }\n}\n\nexport class PrettierOptionsResolver {\n private _prettier: PrettierModule | null | undefined;\n private readonly _cache = new Map<string, PrettierOptions>();\n\n constructor(private readonly _root: string) {}\n\n private async _loadPrettier(): Promise<PrettierModule | null> {\n if (this._prettier !== undefined) {\n return this._prettier;\n }\n\n try {\n const require = createRequire(path.join(this._root, 'package.json'));\n const resolved = require.resolve('prettier');\n\n this._prettier = (await import(pathToFileURL(resolved).href)) as PrettierModule;\n } catch {\n this._prettier = null;\n }\n\n return this._prettier;\n }\n\n async resolve(file: string): Promise<PrettierOptions> {\n const prettier = await this._loadPrettier();\n\n /**\n * Prettier resolves per file, since `overrides` can give files in the same\n * directory different widths.\n */\n if (prettier) {\n try {\n const options = await prettier.resolveConfig(file);\n\n if (options) {\n return options;\n }\n } catch {\n // fall back to reading the config files directly\n }\n }\n\n const directory = path.dirname(file);\n const cached = this._cache.get(directory);\n\n if (cached) {\n return cached;\n }\n\n const options = readPrettierFile(directory, this._root) ?? {};\n\n this._cache.set(directory, options);\n\n return options;\n }\n}\n","import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { buildInvocation, buildPrompt, describeAgent, formatInvocation, loadRules, runAgent } from './agent.js';\nimport {\n BYTE_ORDER_MARK,\n codeFingerprint,\n hasVerdictIssues,\n rewrapComment,\n type CommentReport,\n type SyntaxFailure,\n} from './analyze.js';\nimport type { AgentRunner, AgentScope } from './config.js';\nimport type { FileAnalysis, Project, Scope } from './project.js';\n\nexport interface FlowOptions {\n readonly mode: 'agent' | 'report';\n readonly select: AgentScope;\n readonly runner: AgentRunner;\n readonly configPath?: string;\n readonly reporter?: FlowReporter;\n}\n\nexport interface AgentPlan {\n readonly name: string;\n readonly files: readonly string[];\n readonly comments: number;\n}\n\nexport interface AgentRunReport extends AgentPlan {\n readonly ok: boolean;\n readonly error?: string;\n readonly output: string;\n readonly durationMs: number;\n}\n\nexport interface FlowPlan {\n readonly agent: string;\n readonly command: string;\n readonly comments: number;\n readonly files: number;\n readonly maxAgents: number;\n readonly agents: readonly AgentPlan[];\n}\n\nexport interface FlowReporter {\n start(plan: FlowPlan): void;\n agentStarted(index: number): void;\n agentFinished(index: number, report: AgentRunReport): void;\n stop(): void;\n}\n\nexport interface FlowSummary {\n readonly sentToAgent: number;\n readonly agents?: number;\n\n /**\n * Lists every agent that ran, in the order they were planned.\n */\n readonly runs?: readonly AgentRunReport[];\n readonly codeChanged: readonly string[];\n\n /**\n * Lists the files that no agent was given and that changed while the agents ran. Only a git\n * repository shows which files those are. An agent's edit looks the same as one that somebody\n * else made in that time, so this is a report and not a failure.\n */\n readonly changedElsewhere: readonly string[];\n readonly rewrapped?: number;\n\n /**\n * Hints don't count, since the agent may have rightly kept what a heuristic flagged.\n */\n readonly remaining: readonly CommentReport[];\n\n /**\n * Lists the files in scope whose comments weren't read because of a syntax error.\n */\n readonly skipped: readonly SkippedFile[];\n readonly agentError?: string;\n}\n\nexport interface SkippedFile {\n readonly file: string;\n readonly syntaxError: SyntaxFailure;\n}\n\nconst DEFAULT_BATCH_SIZE = 20;\nconst DEFAULT_MAX_FILES = 10;\nconst DEFAULT_MAX_AGENTS = 6;\nconst PROGRESS_INTERVAL_MS = 30_000;\nconst LISTED_FILES = 3;\n\nfunction withVerdictIssues(analyses: readonly FileAnalysis[]): CommentReport[] {\n return analyses.flatMap((analysis) => analysis.comments).filter((comment) => hasVerdictIssues(comment));\n}\n\nexport function skippedFiles(analyses: readonly FileAnalysis[]): SkippedFile[] {\n return analyses.flatMap(({ file, syntaxError }) => (syntaxError ? [{ file, syntaxError }] : []));\n}\n\nexport function describeSkipped({ file, syntaxError }: SkippedFile): string {\n const line = syntaxError.line === undefined ? '' : ` on line ${syntaxError.line}`;\n\n return `skipped ${file} because of a syntax error${line} (${syntaxError.message})`;\n}\n\nexport function describeChangedElsewhere(files: readonly string[]): string {\n return `${files.length} file(s) that no agent was given changed during the run: ${listFiles(files)}`;\n}\n\n/**\n * Lists the files whose state differs between two snapshots, including files that only one\n * of them holds.\n */\nfunction changedBetween(before: ReadonlyMap<string, string>, after: ReadonlyMap<string, string>): string[] {\n const files = new Set([...before.keys(), ...after.keys()]);\n\n return [...files].filter((file) => before.get(file) !== after.get(file)).toSorted();\n}\n\n/**\n * A paragraph without a suggestion is in a part the tool keeps as written, like an overflowing\n * single-line block comment, so only the agent can fix it.\n */\nfunction needsAgent(comment: CommentReport): boolean {\n return comment.paragraphs.some((paragraph) =>\n paragraph.issues.some((issue) => issue.tier === 'hint' || paragraph.suggestion === null),\n );\n}\n\nfunction seconds(milliseconds: number): string {\n return `${Math.round(milliseconds / 1000)}s`;\n}\n\nfunction listFiles(files: readonly string[]): string {\n const more = files.length > LISTED_FILES ? `, and ${files.length - LISTED_FILES} more` : '';\n\n return `${files.slice(0, LISTED_FILES).join(', ')}${more}`;\n}\n\nconst SILENT_REPORTER: FlowReporter = {\n start: () => {},\n agentStarted: () => {},\n agentFinished: () => {},\n stop: () => {},\n};\n\n/**\n * Reports progress as plain log lines, for hooks, CI, and output that isn't a terminal.\n */\nexport function createLogReporter(log: (message: string) => void, options: { verbose?: boolean } = {}): FlowReporter {\n let plan: FlowPlan | undefined;\n let heartbeat: NodeJS.Timeout | undefined;\n let started = 0;\n let running = 0;\n let finished = 0;\n\n return {\n start(next) {\n plan = next;\n started = Date.now();\n\n const count = next.agents.length;\n const agents = `${count} agent${count > 1 ? 's' : ''} (${next.agent})`;\n const queueing = count > next.maxAgents ? `, ${next.maxAgents} at a time,` : '';\n\n log(`spawning ${agents}${queueing} for ${next.comments} comment(s) in ${next.files} file(s)`);\n log(` command: ${next.command}`);\n\n if (count > 1) {\n for (const agent of next.agents) {\n log(` ${agent.name}: ${agent.comments} comment(s) in ${listFiles(agent.files)}`);\n }\n }\n\n heartbeat = setInterval(() => {\n const queued = count - finished - running;\n const waiting = count > 1 ? `${count - finished} of ${count} agents` : 'the agent';\n\n log(`still waiting for ${waiting}${queued > 0 ? `, ${queued} queued` : ''} (${seconds(Date.now() - started)})`);\n }, PROGRESS_INTERVAL_MS);\n },\n agentStarted(index) {\n running += 1;\n\n if (plan && index >= plan.maxAgents) {\n log(`${plan.agents[index].name} started`);\n }\n },\n agentFinished(_index, report) {\n running -= 1;\n finished += 1;\n\n const count = plan?.agents.length ?? 1;\n const took = seconds(report.durationMs);\n const status = report.ok ? `finished in ${took}` : `failed after ${took}`;\n const progress = count > 1 ? ` (${finished} of ${count} done)` : '';\n\n log(`${report.name} ${status}${progress}${report.ok ? '' : `: ${report.error}`}`);\n\n if (report.output && (options.verbose || !report.ok)) {\n log(report.output);\n }\n },\n stop() {\n clearInterval(heartbeat);\n },\n };\n}\n\nexport function batchFiles<T extends { readonly comments: readonly unknown[] }>(\n files: readonly T[],\n batchSize: number,\n maxFiles = Infinity,\n): T[][] {\n const total = files.reduce((sum, file) => sum + file.comments.length, 0);\n const order = files.map((_, index) => index).toSorted((a, b) => files[b].comments.length - files[a].comments.length);\n const minimum = Math.max(Math.ceil(total / batchSize), Math.ceil(files.length / maxFiles));\n\n for (let count = Math.min(files.length, minimum); ; count += 1) {\n const sizes = Array.from<number>({ length: count }).fill(0);\n const indices = Array.from({ length: count }, (): number[] => []);\n\n for (const index of order) {\n const open = sizes.map((size, batch) => (indices[batch].length < maxFiles ? size : Infinity));\n const smallest = open.indexOf(Math.min(...open));\n\n indices[smallest].push(index);\n\n sizes[smallest] += files[index].comments.length;\n }\n\n const fits = indices.every((batch, index) => batch.length === 1 || sizes[index] <= batchSize);\n\n if (fits || count >= files.length) {\n return indices.map((batch) => batch.toSorted((a, b) => a - b).map((index) => files[index]));\n }\n }\n}\n\nasync function runPool<T, R>(\n items: readonly T[],\n limit: number,\n worker: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = Array.from({ length: items.length });\n\n let next = 0;\n\n const lane = async (): Promise<void> => {\n while (next < items.length) {\n const index = next;\n\n next += 1;\n\n results[index] = await worker(items[index], index);\n }\n };\n\n await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => lane()));\n\n return results;\n}\n\nfunction applyRewraps(analyses: readonly FileAnalysis[], skip: ReadonlySet<string>): number {\n let count = 0;\n\n for (const analysis of analyses) {\n const comments = analysis.comments.filter((comment) => hasVerdictIssues(comment));\n\n if (comments.length === 0 || skip.has(analysis.file)) {\n continue;\n }\n\n const lines = analysis.source.split('\\n');\n\n let rewrapped = 0;\n\n for (const comment of comments.toReversed()) {\n const text = rewrapComment(comment);\n\n // a comment whose only issues are in parts that are kept as written has nothing to apply\n if (text === comment.text) {\n continue;\n }\n\n /**\n * A report holds the comment without the file's byte order mark and without carriage returns,\n * so the first line of the file and the lines of a CRLF file get theirs back.\n */\n const first = lines[comment.startLine - 1];\n const mark = first.startsWith(BYTE_ORDER_MARK) ? BYTE_ORDER_MARK : '';\n const ending = first.endsWith('\\r') ? '\\r' : '';\n const replacement = text.split('\\n').map((line, index) => `${index === 0 ? mark : ''}${line}${ending}`);\n\n lines.splice(comment.startLine - 1, comment.endLine - comment.startLine + 1, ...replacement);\n\n rewrapped += 1;\n }\n\n const output = lines.join('\\n');\n\n if (rewrapped === 0 || codeFingerprint(output, analysis.file) !== codeFingerprint(analysis.source, analysis.file)) {\n continue;\n }\n\n writeFileSync(analysis.absolute, output);\n\n count += rewrapped;\n }\n\n return count;\n}\n\nexport async function runFlow(project: Project, scope: Scope, options: FlowOptions): Promise<FlowSummary> {\n const reporter = options.reporter ?? SILENT_REPORTER;\n const analyses = await project.analyze(scope);\n\n // the tool changes files in between, so the files are measured again for what remains\n const measure = async (): Promise<Pick<FlowSummary, 'remaining' | 'skipped'>> => {\n const current = await project.analyze(scope);\n\n return { remaining: withVerdictIssues(current), skipped: skippedFiles(current) };\n };\n\n if (options.mode === 'report') {\n return {\n sentToAgent: 0,\n codeChanged: [],\n changedElsewhere: [],\n remaining: withVerdictIssues(analyses),\n skipped: skippedFiles(analyses),\n };\n }\n\n const pending = analyses\n .map((analysis) => {\n const selected =\n options.select === 'all' ? analysis.comments : analysis.comments.filter((comment) => needsAgent(comment));\n\n return { ...analysis, comments: selected };\n })\n .filter((analysis) => analysis.comments.length > 0);\n\n const comments = pending.flatMap((analysis) => analysis.comments);\n\n if (comments.length === 0) {\n const rewrapped = applyRewraps(analyses, new Set());\n\n return { sentToAgent: 0, codeChanged: [], changedElsewhere: [], rewrapped, ...(await measure()) };\n }\n\n const agentConfig = project.config.agent ?? {};\n const rules = loadRules(agentConfig, options.configPath);\n\n const batches = batchFiles(\n pending,\n agentConfig.batchSize ?? DEFAULT_BATCH_SIZE,\n agentConfig.maxFiles ?? DEFAULT_MAX_FILES,\n );\n\n const maxAgents = agentConfig.maxAgents ?? DEFAULT_MAX_AGENTS;\n\n const runs = batches.map((batch, index) => {\n const batchComments = batch.flatMap((analysis) => analysis.comments);\n\n const prompt = buildPrompt({ rules, root: project.root, comments: batchComments });\n const invocation = buildInvocation({ agent: agentConfig, runner: options.runner, prompt, root: project.root });\n\n return {\n name: batches.length > 1 ? `agent ${index + 1}` : 'the agent',\n files: batch.map((analysis) => analysis.file),\n comments: batchComments.length,\n invocation,\n };\n });\n\n reporter.start({\n agent: describeAgent(agentConfig, options.runner),\n command: formatInvocation(runs[0].invocation),\n comments: comments.length,\n files: pending.length,\n maxAgents,\n agents: runs.map(({ name, files, comments }) => {\n return { name, files, comments };\n }),\n });\n\n const before = project.snapshot();\n\n let reports: AgentRunReport[];\n\n try {\n reports = await runPool(runs, maxAgents, async (run, index) => {\n const start = Date.now();\n\n reporter.agentStarted(index);\n\n const result = await runAgent(run.invocation, { root: project.root, timeout: agentConfig.timeout });\n\n const report: AgentRunReport = {\n name: run.name,\n files: run.files,\n comments: run.comments,\n ok: result.ok,\n error: result.error,\n output: result.output,\n durationMs: Date.now() - start,\n };\n\n reporter.agentFinished(index, report);\n\n return report;\n });\n } finally {\n reporter.stop();\n }\n\n const agentErrors = reports.flatMap((report, index) => {\n if (report.ok) {\n return [];\n }\n\n return [reports.length > 1 ? `agent ${index + 1} of ${reports.length}: ${report.error}` : (report.error ?? '')];\n });\n\n // taken before the tool rewraps anything itself\n const after = project.snapshot();\n const handedOver = new Set(pending.map((analysis) => analysis.file));\n\n const changedElsewhere = before && after ? changedBetween(before, after).filter((file) => !handedOver.has(file)) : [];\n\n const codeChanged = pending\n .filter((analysis) => {\n if (!existsSync(analysis.absolute)) {\n return true;\n }\n\n const current = readFileSync(analysis.absolute, 'utf8');\n\n return codeFingerprint(current, analysis.file) !== codeFingerprint(analysis.source, analysis.file);\n })\n .map((analysis) => analysis.file);\n\n const rewrapped = applyRewraps(await project.analyze(scope), new Set(codeChanged));\n\n return {\n sentToAgent: comments.length,\n agents: runs.length,\n runs: reports,\n codeChanged,\n changedElsewhere,\n rewrapped,\n ...(await measure()),\n agentError: agentErrors.length > 0 ? agentErrors.join(', ') : undefined,\n };\n}\n\nconst LISTED_COMMENTS = 5;\n\nfunction describeRemaining(remaining: readonly CommentReport[]): string {\n const listed = remaining.slice(0, LISTED_COMMENTS).map((comment) => {\n const issues = comment.paragraphs.flatMap((paragraph) => paragraph.issues);\n const types = new Set(issues.filter((issue) => issue.tier === 'verdict').map((issue) => issue.type));\n\n return `${comment.file}:${comment.startLine} (${[...types].join(', ')})`;\n });\n\n const more = remaining.length > LISTED_COMMENTS ? `, and ${remaining.length - LISTED_COMMENTS} more` : '';\n\n return `${remaining.length} comment(s) still have issues: ${listed.join(', ')}${more}`;\n}\n\nexport function describeSummary(summary: FlowSummary): string | undefined {\n const parts: string[] = [];\n\n if (summary.sentToAgent > 0) {\n const agents = (summary.agents ?? 1) > 1 ? `${summary.agents} agents` : 'the agent';\n\n parts.push(`sent ${summary.sentToAgent} comment(s) to ${agents}`);\n }\n\n if (summary.rewrapped) {\n parts.push(`rewrapped ${summary.rewrapped} comment(s)`);\n }\n\n if (summary.agentError) {\n parts.push(`agent failed: ${summary.agentError}`);\n }\n\n if (summary.codeChanged.length > 0) {\n parts.push(`the agent changed code, not just comments, in ${summary.codeChanged.join(', ')}`);\n }\n\n if (summary.changedElsewhere.length > 0) {\n parts.push(describeChangedElsewhere(summary.changedElsewhere));\n }\n\n if (summary.remaining.length > 0) {\n parts.push(describeRemaining(summary.remaining));\n }\n\n parts.push(...summary.skipped.map((skipped) => describeSkipped(skipped)));\n\n return parts.length > 0 ? `comments: ${parts.join('; ')}` : undefined;\n}\n","import { spawnSync } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport { readFileSync, statSync } from 'node:fs';\nimport path from 'node:path';\n\n/**\n * Maps each file to its changed lines (1-based), or to `all` when every line counts as changed,\n * e.g. for untracked files.\n */\nexport type ChangedLines = Map<string, Set<number> | 'all'>;\n\nexport interface DiffScope {\n readonly staged?: boolean;\n\n /**\n * Compare the working tree against the merge base with this ref instead of `HEAD`.\n */\n readonly base?: string;\n}\n\nfunction git(cwd: string, args: readonly string[]): { ok: boolean; stdout: string; stderr: string } {\n const result = spawnSync('git', ['-c', 'core.quotePath=false', ...args], {\n cwd,\n encoding: 'utf8',\n maxBuffer: 256 * 1024 * 1024,\n });\n\n // both are null when git itself could not be spawned\n const stdout = (result.stdout as string | null) ?? '';\n const stderr = (result.stderr as string | null) ?? '';\n\n return { ok: result.status === 0, stdout, stderr };\n}\n\nfunction gitOrThrow(cwd: string, args: readonly string[]): string {\n const result = git(cwd, args);\n\n if (!result.ok) {\n throw new Error(`comments: \\`git ${args.join(' ')}\\` failed: ${result.stderr.trim()}`);\n }\n\n return result.stdout;\n}\n\n/**\n * Splits `-z` output, whose paths are never quoted, unlike line output for names with quotes\n * or control characters.\n */\nfunction splitPaths(output: string): string[] {\n return output.split('\\0').filter(Boolean);\n}\n\n/**\n * Unquotes a path that git wrote as a C-style string, like `\"b/say \\\"hi\\\".ts\"`.\n * `core.quotePath=false` only stops quoting of non-ASCII names, so quotes,\n * backslashes, and control characters still get quoted.\n */\nfunction unquotePath(value: string): string {\n if (!value.startsWith('\"')) {\n return value;\n }\n\n try {\n return JSON.parse(value) as string;\n } catch {\n return value;\n }\n}\n\nexport function findRepoRoot(cwd: string): string | undefined {\n const result = git(cwd, ['rev-parse', '--show-toplevel']);\n\n return result.ok ? result.stdout.trim() : undefined;\n}\n\n/**\n * A pure deletion marks the lines on both sides of the removed range, since it changes the comment\n * it was part of.\n */\nexport function parseUnifiedDiff(diff: string): ChangedLines {\n const changed: ChangedLines = new Map();\n\n let lines: Set<number> | undefined;\n\n /**\n * Counts lines left in the hunk, since an added line like `++ x` shows up as `+++ x` and looks\n * like a header.\n */\n let oldPending = 0;\n let newPending = 0;\n\n for (const line of diff.split('\\n')) {\n if (oldPending > 0 || newPending > 0) {\n if (line.startsWith('+')) {\n newPending -= 1;\n } else if (line.startsWith('-')) {\n oldPending -= 1;\n } else if (line.startsWith(' ')) {\n oldPending -= 1;\n newPending -= 1;\n }\n\n continue;\n }\n\n if (line.startsWith('+++ ')) {\n const target = unquotePath(line.slice(4).replace(/\\t$/, ''));\n\n if (target === '/dev/null') {\n lines = undefined;\n\n continue;\n }\n\n const file = target.startsWith('b/') ? target.slice(2) : target;\n\n lines = new Set();\n\n changed.set(file, lines);\n\n continue;\n }\n\n const hunk = /^@@ -\\d+(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@/.exec(line);\n\n if (!hunk) {\n continue;\n }\n\n const start = Number(hunk[2]);\n const count = hunk[3] ? Number(hunk[3]) : 1;\n\n oldPending = hunk[1] ? Number(hunk[1]) : 1;\n newPending = count;\n\n if (!lines) {\n continue;\n }\n\n if (count === 0) {\n lines.add(start);\n lines.add(start + 1);\n\n continue;\n }\n\n for (let offset = 0; offset < count; offset += 1) {\n lines.add(start + offset);\n }\n }\n\n return changed;\n}\n\nfunction hasHead(root: string): boolean {\n return git(root, ['rev-parse', '--verify', '--quiet', 'HEAD']).ok;\n}\n\nexport function listUntrackedFiles(root: string): string[] {\n return splitPaths(gitOrThrow(root, ['ls-files', '-z', '--others', '--exclude-standard']));\n}\n\nexport function listFiles(root: string, paths: readonly string[] = []): string[] {\n return splitPaths(gitOrThrow(root, ['ls-files', '-z', '--cached', '--others', '--exclude-standard', '--', ...paths]));\n}\n\nconst MAX_HASHED_BYTES = 1024 * 1024;\n\n/**\n * Describes a file by its content, so that saving it again without a change doesn't count as an\n * edit. A file that is too large to read for that is described by its size and the time of its\n * last change instead.\n */\nfunction fileState(absolute: string): string {\n try {\n const stats = statSync(absolute);\n\n if (!stats.isFile()) {\n return 'no file';\n }\n\n return stats.size > MAX_HASHED_BYTES\n ? `${stats.size} bytes, changed at ${stats.mtimeMs}`\n : createHash('sha1').update(readFileSync(absolute)).digest('hex');\n } catch {\n return 'missing';\n }\n}\n\n/**\n * Maps every file that differs from `HEAD` or is untracked to its state. Any edit to the working\n * tree shows up as a difference between two of these snapshots, including an edit that brings a file\n * back to its committed text, since that file is then missing from the later snapshot. Returns\n * `undefined` when git can't list the files.\n */\nexport function snapshotChanges(root: string): Map<string, string> | undefined {\n try {\n const tracked = hasHead(root)\n ? splitPaths(gitOrThrow(root, ['diff', '-z', '--name-only', '--no-renames', 'HEAD']))\n : splitPaths(gitOrThrow(root, ['ls-files', '-z', '--cached']));\n\n const files = new Set([...tracked, ...listUntrackedFiles(root)]);\n\n return new Map([...files].map((file) => [file, fileState(path.join(root, file))]));\n } catch {\n return undefined;\n }\n}\n\n/**\n * Uses explicit prefixes, since `diff.noprefix` or `diff.mnemonicPrefix` would\n * otherwise change `+++ b/<file>`.\n */\nconst DIFF_FLAGS = ['diff', '-U0', '--no-color', '--no-ext-diff', '--no-renames', '--src-prefix=a/', '--dst-prefix=b/'];\n\nexport function getChangedLines(root: string, scope: DiffScope = {}): ChangedLines {\n if (!hasHead(root)) {\n const files = scope.staged\n ? splitPaths(gitOrThrow(root, ['diff', '-z', '--cached', '--name-only', '--diff-filter=d']))\n : listFiles(root);\n\n return new Map(files.map((file) => [file, 'all'] as const));\n }\n\n let args: string[];\n\n if (scope.staged) {\n args = [...DIFF_FLAGS, '--cached', 'HEAD'];\n } else if (scope.base) {\n const mergeBase = gitOrThrow(root, ['merge-base', scope.base, 'HEAD']).trim();\n\n args = [...DIFF_FLAGS, mergeBase];\n } else {\n args = [...DIFF_FLAGS, 'HEAD'];\n }\n\n const changed = parseUnifiedDiff(gitOrThrow(root, args));\n\n if (!scope.staged) {\n for (const file of listUntrackedFiles(root)) {\n changed.set(file, 'all');\n }\n }\n\n return changed;\n}\n","import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';\nimport path from 'node:path';\nimport { inspectSource, type CommentReport, type SyntaxFailure } from './analyze.js';\nimport { DEFAULT_EXTENSIONS, PrettierOptionsResolver, type CommentsConfig } from './config.js';\nimport { getChangedLines, listFiles, snapshotChanges } from './git.js';\n\nexport interface Scope {\n /**\n * Lists files, directories, `file:line`, or `file:start-end` targets.\n * When empty, the git scope below applies.\n */\n readonly targets?: readonly string[];\n readonly staged?: boolean;\n readonly base?: string;\n\n /**\n * Considers every file in the repository instead of only changed lines.\n */\n readonly repo?: boolean;\n}\n\nexport interface FileAnalysis {\n /**\n * Holds the path relative to the project root, with forward slashes.\n */\n readonly file: string;\n readonly absolute: string;\n readonly source: string;\n readonly comments: readonly CommentReport[];\n\n /**\n * Set when the file was skipped because the parser stopped at a syntax error.\n * It has no comments then.\n */\n readonly syntaxError?: SyntaxFailure;\n}\n\ntype LineFilter = Set<number> | 'all';\n\nconst DEFAULT_WIDTH = 80;\nconst DEFAULT_MAX_WIDTH = 120;\nconst DEFAULT_SINGLE_LINE_WIDTH = 120;\nconst DEFAULT_TAB_WIDTH = 2;\nconst SKIPPED_DIRECTORIES = new Set(['node_modules', '.git', 'dist', 'build', 'coverage']);\n\nfunction toPosix(file: string): string {\n return file.split(path.sep).join('/');\n}\n\nfunction mergeFilter(existing: LineFilter | undefined, next: LineFilter): LineFilter {\n if (existing === 'all' || next === 'all') {\n return 'all';\n }\n\n return existing ? new Set([...existing, ...next]) : next;\n}\n\nfunction walkDirectory(directory: string, files: string[] = []): string[] {\n const entries = readdirSync(directory, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n if (!SKIPPED_DIRECTORIES.has(entry.name)) {\n walkDirectory(path.join(directory, entry.name), files);\n }\n } else if (entry.isFile()) {\n files.push(path.join(directory, entry.name));\n }\n }\n\n return files;\n}\n\nfunction overlaps(comment: CommentReport, filter: LineFilter): boolean {\n if (filter === 'all') {\n return true;\n }\n\n for (let line = comment.startLine; line <= comment.endLine; line += 1) {\n if (filter.has(line)) {\n return true;\n }\n }\n\n return false;\n}\n\nexport class Project {\n private readonly _prettier: PrettierOptionsResolver;\n private readonly _extensions: ReadonlySet<string>;\n\n constructor(\n readonly root: string,\n readonly config: CommentsConfig,\n private readonly _options: { readonly isGitRepo: boolean; readonly cwd: string; readonly width?: number },\n ) {\n this._prettier = new PrettierOptionsResolver(root);\n this._extensions = new Set(config.extensions ?? DEFAULT_EXTENSIONS);\n }\n\n relative(absolute: string): string {\n return toPosix(path.relative(this.root, absolute));\n }\n\n private _isIncluded(absolute: string): boolean {\n if (!this._extensions.has(path.extname(absolute))) {\n return false;\n }\n\n const relative = this.relative(absolute);\n\n return !(this.config.ignore ?? []).some((pattern) => path.matchesGlob(relative, pattern));\n }\n\n private _filesIn(directory: string): string[] {\n if (!this._options.isGitRepo) {\n return walkDirectory(directory);\n }\n\n return listFiles(this.root, [path.relative(this.root, directory) || '.']).map((file) => path.join(this.root, file));\n }\n\n collect(scope: Scope): Map<string, LineFilter> {\n const files = new Map<string, LineFilter>();\n\n const add = (absolute: string, filter: LineFilter): void => {\n if (this._isIncluded(absolute) && existsSync(absolute)) {\n files.set(absolute, mergeFilter(files.get(absolute), filter));\n }\n };\n\n if (scope.targets && scope.targets.length > 0) {\n for (const target of scope.targets) {\n const range = /^(.+):(\\d+)(?:-(\\d+))?$/.exec(target);\n const absolute = path.resolve(this._options.cwd, range ? range[1] : target);\n\n if (!existsSync(absolute)) {\n throw new Error(`comments: ${target} does not exist`);\n }\n\n if (statSync(absolute).isDirectory()) {\n for (const file of this._filesIn(absolute)) {\n add(file, 'all');\n }\n\n continue;\n }\n\n if (!range) {\n add(absolute, 'all');\n\n continue;\n }\n\n const start = Number(range[2]);\n const end = range[3] ? Number(range[3]) : start;\n\n add(absolute, new Set(Array.from({ length: Math.max(0, end - start + 1) }, (_, offset) => start + offset)));\n }\n\n return files;\n }\n\n if (scope.repo) {\n for (const file of this._filesIn(this.root)) {\n add(file, 'all');\n }\n\n return files;\n }\n\n if (!this._options.isGitRepo) {\n throw new Error('comments: not a git repository, so pass files or directories explicitly');\n }\n\n for (const [file, lines] of getChangedLines(this.root, scope)) {\n add(path.join(this.root, file), lines);\n }\n\n return files;\n }\n\n async analyzeFile(absolute: string, filter: LineFilter = 'all'): Promise<FileAnalysis> {\n const source = readFileSync(absolute, 'utf8');\n const prettier = await this._prettier.resolve(absolute);\n const file = this.relative(absolute);\n const width = this._options.width ?? this.config.width ?? prettier.printWidth ?? DEFAULT_WIDTH;\n\n const maxWidth =\n this.config.maxWidth ??\n Math.max(width, this.config.tolerance === undefined ? DEFAULT_MAX_WIDTH : width + this.config.tolerance);\n\n const { comments, syntaxError } = inspectSource(source, file, {\n width,\n maxWidth,\n singleLineWidth: this.config.singleLineWidth ?? DEFAULT_SINGLE_LINE_WIDTH,\n tabWidth: prettier.tabWidth ?? DEFAULT_TAB_WIDTH,\n tolerance: Math.min(this.config.tolerance ?? 0, maxWidth - width),\n avoidSentenceOrphans: this.config.avoidSentenceOrphans ?? true,\n style: this.config.style ?? true,\n });\n\n return { file, absolute, source, comments: comments.filter((comment) => overlaps(comment, filter)), syntaxError };\n }\n\n /**\n * Records the state of every file with uncommitted changes, to compare it with a later\n * snapshot. Returns `undefined` outside of a git repository, where only reading every\n * file would show which ones changed.\n */\n snapshot(): ReadonlyMap<string, string> | undefined {\n return this._options.isGitRepo ? snapshotChanges(this.root) : undefined;\n }\n\n async analyze(scope: Scope): Promise<FileAnalysis[]> {\n const results: FileAnalysis[] = [];\n\n for (const [absolute, filter] of this.collect(scope)) {\n results.push(await this.analyzeFile(absolute, filter));\n }\n\n return results.toSorted((a, b) => a.file.localeCompare(b.file));\n }\n}\n","import {\n intro,\n isCancel,\n isCI,\n log,\n note,\n S_BAR,\n S_BAR_END,\n S_RADIO_INACTIVE,\n S_STEP_ERROR,\n S_STEP_SUBMIT,\n select,\n spinner,\n unicode,\n unicodeOr,\n type SpinnerResult,\n} from '@clack/prompts';\nimport { spawnSync } from 'node:child_process';\nimport { Writable } from 'node:stream';\nimport { styleText } from 'node:util';\nimport type { CommentReport } from './analyze.js';\nimport {\n describeSkipped,\n type AgentPlan,\n type AgentRunReport,\n type FlowPlan,\n type FlowReporter,\n type FlowSummary,\n} from './flow.js';\n\ntype Style = Parameters<typeof styleText>[0];\n\nconst FRAMES = unicode ? ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'] : ['|', '/', '-', '\\\\'];\nconst FRAME_MS = 80;\nconst S_DONE = unicodeOr('✔', '√');\nconst S_FAILED = unicodeOr('✖', 'x');\nconst HIDE_CURSOR = '\\u001B[?25l';\nconst SHOW_CURSOR = '\\u001B[?25h';\nconst LISTED_REMAINING = 10;\nconst CTRL_C = 0x03;\nconst MIN_FILES_WIDTH = 12;\n\ntype AgentState = 'queued' | 'running' | 'done' | 'failed';\n\nconst ICONS: Record<Exclude<AgentState, 'running'>, readonly [Style, string]> = {\n queued: ['dim', S_RADIO_INACTIVE],\n done: ['green', S_DONE],\n failed: ['red', S_FAILED],\n};\n\ninterface AgentRow {\n readonly plan: AgentPlan;\n state: AgentState;\n startedAt?: number;\n durationMs?: number;\n}\n\nexport function isLiveTerminal(output: NodeJS.WriteStream = process.stderr): boolean {\n return output.isTTY && !isCI() && process.env.TERM !== 'dumb';\n}\n\nfunction plural(count: number, noun: string): string {\n return `${count} ${noun}${count === 1 ? '' : 's'}`;\n}\n\nfunction formatDuration(milliseconds: number): string {\n const total = Math.round(milliseconds / 1000);\n const minutes = Math.floor(total / 60);\n\n return minutes > 0 ? `${minutes}m ${String(total % 60).padStart(2, '0')}s` : `${total}s`;\n}\n\nfunction fitFiles(files: readonly string[], width: number): string {\n for (let shown = files.length; shown > 0; shown -= 1) {\n const more = files.length - shown;\n const text = `${files.slice(0, shown).join(', ')}${more > 0 ? `, +${more} more` : ''}`;\n\n if (text.length <= width) {\n return text;\n }\n }\n\n return width > 1 ? `…${files[0].slice(-(width - 1))}` : '';\n}\n\nfunction truncate(text: string, width: number): string {\n return text.length > width ? `${text.slice(0, Math.max(width - 1, 0))}…` : text;\n}\n\nfunction agentLabel(index: number): string {\n return `agent ${index + 1}`;\n}\n\nfunction formatReply(text: string, paint: (style: Style, text: string) => string): string {\n return text\n .replaceAll(/\\*\\*([^*\\n]+)\\*\\*/g, (_, inner: string) => paint('bold', inner))\n .replaceAll(/`([^`\\n]+)`/g, (_, inner: string) => paint('cyan', inner));\n}\n\nclass AgentTable {\n private _rows: AgentRow[] = [];\n private _title = '';\n private _drawn = 0;\n private _frame = 0;\n private _startedAt = 0;\n private _timer: NodeJS.Timeout | undefined;\n\n constructor(\n private readonly _output: NodeJS.WriteStream,\n private readonly _paint: (style: Style, text: string) => string,\n ) {}\n\n private readonly _restoreCursor = (): void => {\n this._output.write(SHOW_CURSOR);\n };\n\n private readonly _interrupt = (): void => {\n this._restoreCursor();\n process.off('exit', this._restoreCursor);\n\n // without a listener left, the signal ends the process the way it would have without this one\n process.kill(process.pid, 'SIGINT');\n };\n\n start(plan: FlowPlan, title: string): void {\n this._rows = plan.agents.map((agent) => {\n return { plan: agent, state: 'queued' };\n });\n\n this._title = title;\n this._startedAt = Date.now();\n\n process.once('SIGINT', this._interrupt);\n process.once('exit', this._restoreCursor);\n\n this._output.write(`${this._paint('gray', S_BAR)}\\n${HIDE_CURSOR}`);\n this._draw(false);\n\n this._timer = setInterval(() => {\n this._frame = (this._frame + 1) % FRAMES.length;\n\n this._draw(false);\n }, FRAME_MS);\n }\n\n started(index: number): void {\n this._rows[index].state = 'running';\n this._rows[index].startedAt = Date.now();\n }\n\n finished(index: number, report: AgentRunReport): void {\n this._rows[index].state = report.ok ? 'done' : 'failed';\n this._rows[index].durationMs = report.durationMs;\n }\n\n stop(): void {\n if (this._timer === undefined) {\n return;\n }\n\n clearInterval(this._timer);\n\n this._timer = undefined;\n\n this._draw(true);\n this._restoreCursor();\n\n process.off('SIGINT', this._interrupt);\n process.off('exit', this._restoreCursor);\n }\n\n private _draw(final: boolean): void {\n const lines = this._render(final);\n const clear = this._drawn > 0 ? `\\u001B[${this._drawn}F\\u001B[J` : '';\n\n this._output.write(`${clear}${lines.join('\\n')}\\n`);\n\n this._drawn = lines.length;\n }\n\n private _count(state: AgentState): number {\n return this._rows.filter((row) => row.state === state).length;\n }\n\n private _render(final: boolean): string[] {\n const columns = Math.max((this._output.columns || 80) - 1, 20);\n const elapsed = formatDuration(Date.now() - this._startedAt);\n const failed = this._count('failed');\n const finished = this._count('done') + failed;\n\n let header: string;\n\n if (final) {\n const outcome = `${plural(this._rows.length, 'agent')} finished in ${elapsed}${failed > 0 ? `, ${failed} failed` : ''}`;\n const symbol = failed > 0 ? this._paint('yellow', S_STEP_ERROR) : this._paint('green', S_STEP_SUBMIT);\n\n header = `${symbol} ${truncate(outcome, columns - 3)}`;\n } else {\n const progress = `${finished} of ${this._rows.length} done, ${elapsed}`;\n const text = truncate(`${this._title} ${progress}`, columns - 3);\n\n header = `${this._paint('magenta', FRAMES[this._frame])} ${text.replace(progress, this._paint('dim', progress))}`;\n }\n\n return [header, ...this._renderRows(columns, final)];\n }\n\n private _renderRows(columns: number, final: boolean): string[] {\n const bar = this._paint('gray', S_BAR);\n const nameWidth = agentLabel(this._rows.length - 1).length;\n const commentsWidth = Math.max(...this._rows.map((row) => plural(row.plan.comments, 'comment').length));\n const statusWidth = Math.max(...this._rows.map((row) => this._status(row).length));\n const filesWidth = columns - (3 + 2 + nameWidth + 2 + commentsWidth + 2 + statusWidth + 2);\n\n // a table taller than the terminal can't be redrawn in place, so only rows that change are listed\n const height = (this._output.rows || 24) - 3;\n const compact = !final && this._rows.length + 1 > height;\n\n const visible = this._rows\n .map((row, index) => {\n return { row, index };\n })\n .filter(({ row }) => !compact || row.state === 'running' || row.state === 'failed')\n .slice(0, Math.max(height - 1, 1));\n\n const lines = visible.map(({ row, index }) => {\n const status = this._status(row).padEnd(statusWidth);\n\n const files =\n filesWidth >= MIN_FILES_WIDTH ? ` ${this._paint('dim', fitFiles(row.plan.files, filesWidth))}` : '';\n\n return (\n [\n `${bar} ${this._icon(row)} ${agentLabel(index).padEnd(nameWidth)}`,\n this._paint('dim', plural(row.plan.comments, 'comment').padEnd(commentsWidth)),\n this._paint(this._statusStyle(row), status),\n ].join(' ') + files\n );\n });\n\n if (compact) {\n const done = this._count('done');\n const queued = this._count('queued');\n\n lines.push(`${bar} ${this._paint('dim', `${S_DONE} ${done} done, ${S_RADIO_INACTIVE} ${queued} queued`)}`);\n }\n\n return lines;\n }\n\n private _icon(row: AgentRow): string {\n if (row.state === 'running') {\n return this._paint('magenta', FRAMES[this._frame]);\n }\n\n const [style, symbol] = ICONS[row.state];\n\n return this._paint(style, symbol);\n }\n\n private _status(row: AgentRow): string {\n if (row.state === 'queued') {\n return 'queued';\n }\n\n if (row.state === 'running') {\n return formatDuration(Date.now() - (row.startedAt ?? this._startedAt));\n }\n\n return formatDuration(row.durationMs ?? 0);\n }\n\n private _statusStyle(row: AgentRow): Style {\n switch (row.state) {\n case 'running': {\n return 'cyan';\n }\n case 'failed': {\n return 'red';\n }\n default: {\n return 'dim';\n }\n }\n }\n}\n\nexport interface FinishOptions {\n /**\n * Offers to open each agent's reply, which needs a terminal on stdin to read the choice.\n */\n readonly interactive: boolean;\n\n /**\n * Prints every agent's reply instead of offering to open them.\n */\n readonly verbose?: boolean;\n}\n\nexport class TerminalUI {\n readonly reporter: FlowReporter;\n private readonly _table: AgentTable;\n private _busy: SpinnerResult | undefined;\n private _muted = false;\n\n constructor(private readonly _output: NodeJS.WriteStream & { readonly fd: number } = process.stderr) {\n this._table = new AgentTable(_output, this._paint);\n\n this.reporter = {\n start: (plan) => {\n const queueing = plan.agents.length > plan.maxAgents ? `, ${plan.maxAgents} at a time` : '';\n\n this._stopSpinner(`Found ${plural(plan.comments, 'comment')} to review in ${plural(plan.files, 'file')}`);\n\n // only after the spinner stopped, since it blocks input itself and turns raw mode off when it stops\n this._muteInput();\n this._table.start(plan, `Running ${plural(plan.agents.length, 'agent')} (${plan.agent})${queueing}`);\n },\n agentStarted: (index) => {\n this._table.started(index);\n },\n agentFinished: (index, report) => {\n this._table.finished(index, report);\n },\n stop: () => {\n this._table.stop();\n this._unmuteInput();\n },\n };\n }\n\n private readonly _paint = (style: Style, text: string): string => {\n return styleText(style, text, { stream: this._output });\n };\n\n begin(title: string): void {\n intro(this._paint('inverse', ` ${title} `), { output: this._output });\n this._startSpinner('Finding comments');\n }\n\n dispose(): void {\n this._unmuteInput();\n this._table.stop();\n this._stopSpinner();\n }\n\n async finish(summary: FlowSummary, options: FinishOptions): Promise<void> {\n const output = this._output;\n const runs = summary.runs ?? [];\n\n if (summary.sentToAgent === 0) {\n this._stopSpinner('No comment in scope needs an agent');\n\n if (summary.rewrapped) {\n log.info(`Rewrapped ${plural(summary.rewrapped, 'comment')} to fix their layout`, { output });\n }\n\n if (summary.remaining.length > 0) {\n log.warn(this._describeRemaining(summary.remaining), { output });\n }\n\n this._warnSkipped(summary);\n this._outro(summary.rewrapped ? 'Done' : 'Nothing to do');\n return;\n }\n\n for (const [index, run] of runs.entries()) {\n if (!run.ok) {\n log.error(`${agentLabel(index)} failed: ${run.error}`, { output });\n }\n }\n\n if (summary.codeChanged.length > 0) {\n log.warn(`The agents changed code, not just comments, in ${summary.codeChanged.join(', ')}`, { output });\n }\n\n if (summary.changedElsewhere.length > 0) {\n const files = plural(summary.changedElsewhere.length, 'file');\n\n log.warn(`${files} that no agent was given changed during the run: ${summary.changedElsewhere.join(', ')}`, {\n output,\n });\n }\n\n if (summary.rewrapped) {\n log.info(`Rewrapped ${plural(summary.rewrapped, 'comment')} to fix their layout`, { output });\n }\n\n if (summary.remaining.length > 0) {\n log.warn(this._describeRemaining(summary.remaining), { output });\n } else {\n log.success('Every comment passes the check now', { output });\n }\n\n this._warnSkipped(summary);\n\n if (options.verbose) {\n for (const [index, run] of runs.entries()) {\n this._showReply(run, index, summary.remaining);\n }\n } else if (options.interactive) {\n await this._browse(runs, summary.remaining);\n }\n\n const clean = summary.remaining.length === 0 && summary.codeChanged.length === 0 && !summary.agentError;\n\n this._outro(clean ? 'Done' : 'Done, but some comments need a look');\n }\n\n private _warnSkipped(summary: FlowSummary): void {\n for (const skipped of summary.skipped) {\n const text = describeSkipped(skipped);\n\n log.warn(`${text.charAt(0).toUpperCase()}${text.slice(1)}`, { output: this._output });\n }\n }\n\n /**\n * Closes the guide like clack's `outro`, which always ends with an empty line.\n */\n private _outro(message: string): void {\n this._output.write(`${this._paint('gray', S_BAR)}\\n${this._paint('gray', S_BAR_END)} ${message}\\n`);\n }\n\n /**\n * Keeps the terminal from echoing keys, like `^[[B` for the down arrow, into the output while\n * it redraws. Raw mode also stops the terminal from turning Ctrl-C into a signal, so the input\n * handler sends it instead.\n */\n private _muteInput(): void {\n const { stdin } = process;\n\n if (!stdin.isTTY || this._muted) {\n return;\n }\n\n this._muted = true;\n\n stdin.setRawMode(true);\n stdin.on('data', this._discardInput);\n stdin.resume();\n }\n\n private _unmuteInput(): void {\n const { stdin } = process;\n\n if (!this._muted) {\n return;\n }\n\n this._muted = false;\n\n stdin.off('data', this._discardInput);\n stdin.setRawMode(false);\n stdin.pause();\n }\n\n private readonly _discardInput = (data: Buffer): void => {\n if (!data.includes(CTRL_C)) {\n return;\n }\n\n this._unmuteInput();\n\n // like the terminal, signal the whole process group, so that the agents stop too\n try {\n process.kill(0, 'SIGINT');\n } catch {\n process.kill(process.pid, 'SIGINT');\n }\n };\n\n private _startSpinner(message: string): void {\n this._busy = spinner({ output: this._output, frames: FRAMES, delay: FRAME_MS });\n\n this._busy.start(message);\n }\n\n private _stopSpinner(message?: string): void {\n if (message === undefined) {\n this._busy?.clear();\n } else {\n this._busy?.stop(message);\n }\n\n this._busy = undefined;\n }\n\n private _describeRemaining(remaining: readonly CommentReport[]): string {\n const locations = remaining.map((comment) => `${comment.file}:${comment.startLine}`);\n const width = Math.max(...locations.slice(0, LISTED_REMAINING).map((location) => location.length));\n\n const listed = remaining.slice(0, LISTED_REMAINING).map((comment, index) => {\n const issues = comment.paragraphs.flatMap((paragraph) => paragraph.issues);\n const types = new Set(issues.filter((issue) => issue.tier === 'verdict').map((issue) => issue.type));\n\n return ` ${locations[index].padEnd(width)} ${this._paint('dim', [...types].join(', '))}`;\n });\n\n const more =\n remaining.length > LISTED_REMAINING\n ? [this._paint('dim', ` and ${remaining.length - LISTED_REMAINING} more`)]\n : [];\n\n return [\n `${plural(remaining.length, 'comment')} still ${remaining.length === 1 ? 'has' : 'have'} issues`,\n ...listed,\n ...more,\n ].join('\\n');\n }\n\n private _remainingIn(run: AgentRunReport, remaining: readonly CommentReport[]): number {\n return remaining.filter((comment) => run.files.includes(comment.file)).length;\n }\n\n private _describeRun(run: AgentRunReport, remaining: readonly CommentReport[]): string {\n if (!run.ok) {\n return `failed after ${formatDuration(run.durationMs)}`;\n }\n\n const left = this._remainingIn(run, remaining);\n\n return [\n plural(run.comments, 'comment'),\n formatDuration(run.durationMs),\n ...(left > 0 ? [`${left} still ${left === 1 ? 'has' : 'have'} issues`] : []),\n ].join(', ');\n }\n\n private _showReply(\n run: AgentRunReport,\n index: number,\n remaining: readonly CommentReport[],\n output: Writable = this._output,\n ): void {\n const reply = run.output ? formatReply(run.output, this._paint) : this._paint('dim', 'The agent printed nothing.');\n const error = run.ok ? [] : [this._paint('red', run.error ?? 'The agent failed.'), ''];\n const files = this._paint('dim', run.files.join(', '));\n const title = `${agentLabel(index)}, ${this._describeRun(run, remaining)}`;\n\n note([files, '', ...error, reply].join('\\n'), title, { output, withGuide: output === this._output });\n }\n\n /**\n * Opens an agent's reply in `less`, which shows it on the alternate screen and restores the\n * terminal when it quits, so that opening replies doesn't pile them up in the scrollback.\n */\n private _openReply(run: AgentRunReport, index: number, remaining: readonly CommentReport[]): void {\n let text = '';\n\n const capture = Object.assign(\n new Writable({\n write(chunk: Buffer | string, _encoding, callback) {\n text += String(chunk);\n\n callback();\n },\n }),\n { columns: this._output.columns || 80 },\n );\n\n this._showReply(run, index, remaining, capture);\n\n const prompt = `${agentLabel(index)}, press q to go back`.replaceAll(/[?:.%\\\\]/g, String.raw`\\$&`);\n\n // `-+` resets options that a user's `LESS` variable may set to quit early or skip the alternate screen\n const result = spawnSync('less', ['-R', '-c', '-~', '-+F', '-+E', '-+X', `-Ps${prompt}`], {\n input: text,\n stdio: ['pipe', this._output.fd, 'inherit'],\n });\n\n if (result.error) {\n this._showReply(run, index, remaining);\n }\n }\n\n /**\n * Erases what a closed `select` prompt left behind, its guide line, message, and choice, plus a\n * closing guide line when it was cancelled.\n */\n private _erasePrompt(cancelled: boolean): void {\n const lines = cancelled ? 4 : 3;\n\n this._output.write(`\\u001B[${lines}F\\u001B[J`);\n }\n\n private async _browse(runs: readonly AgentRunReport[], remaining: readonly CommentReport[]): Promise<void> {\n const done = -1;\n const columns = (this._output.columns || 80) - 1;\n const nameWidth = agentLabel(runs.length - 1).length;\n\n const options = runs.map((run, index) => {\n const icon = run.ok ? this._paint('green', S_DONE) : this._paint('red', S_FAILED);\n const hint = this._describeRun(run, remaining);\n\n // the prompt's guide, radio, icon, and spaces take 9 columns, and the hint shows in parentheses\n const filesWidth = Math.max(columns - 9 - nameWidth - 2 - (hint.length + 3), MIN_FILES_WIDTH);\n\n return {\n value: index,\n label: `${icon} ${agentLabel(index).padEnd(nameWidth)} ${fitFiles(run.files, filesWidth)}`,\n hint,\n };\n });\n\n let initial = done;\n\n for (;;) {\n const choice = await select<number>({\n message: \"Open an agent's reply\",\n options: [...options, { value: done, label: 'Done' }],\n initialValue: initial,\n output: this._output,\n });\n\n this._erasePrompt(isCancel(choice));\n\n if (isCancel(choice) || choice === done) {\n return;\n }\n\n this._openReply(runs[choice], choice, remaining);\n\n initial = choice;\n }\n }\n}\n","#!/usr/bin/env node\nimport { log, main } from './cli.js';\n\ntry {\n process.exitCode = await main(process.argv.slice(2));\n} catch (error) {\n log((error as Error).message);\n\n process.exitCode = 2;\n}\n"],"mappings":"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","names":["existsSync","statSync","path","note","startsLine","row","balanced","issues","structure","even","wrapped","readFileSync","path","readFileSync","path","require","options","existsSync","readFileSync","log","rewrapped","comments","existsSync","readFileSync","readFileSync","path","listFiles","existsSync","readFileSync","statSync","path","path","listFiles","existsSync","statSync","readFileSync","spawnSync","spawnSync","log","path","existsSync","statSync","log"]}
|