@sir_yami/reviewd-core 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/paths.ts", "../src/diff/snapshot.ts", "../src/git/content.ts", "../src/git/run.ts", "../src/git/scope.ts", "../src/git/repo.ts", "../src/diff/manifest.ts", "../src/diff/parse.ts", "../src/diff/glob.ts", "../src/review/ids.ts", "../src/review/events.ts", "../src/review/anchors.ts", "../src/review/coverage.ts", "../src/review/plan.ts", "../src/review/aggregate.ts", "../src/review/outcomes.ts", "../src/review/final.ts", "../src/review/fold.ts", "../src/review/lifecycle.ts", "../src/review/store.ts", "../src/reviewer/fake.ts", "../src/reviewer/command.ts", "../src/reviewer/types.ts", "../src/reviewer/validate.ts", "../src/service/types.ts", "../src/service/feedback.ts", "../src/service/service.ts", "../src/index.ts"],
4
- "sourcesContent": ["import { lstat } from 'node:fs/promises';\nimport { relative, resolve, sep } from 'node:path';\n\nexport class PathEscapeError extends Error {\n constructor(readonly relative: string) {\n super(`path escapes repository root: ${relative}`);\n this.name = 'PathEscapeError';\n }\n}\n\nexport function safeJoin(root: string, relative: string): string {\n if (relative.includes('\\0')) throw new PathEscapeError(relative);\n const absolute = resolve(root, relative);\n if (absolute !== root && !absolute.startsWith(root + sep)) {\n throw new PathEscapeError(relative);\n }\n return absolute;\n}\n\n/**\n * Split a NUL-delimited Git path list. A truncated stream may end without a\n * trailing NUL, leaving an incomplete final token; drop it.\n */\nexport function splitNulPaths(output: string): string[] {\n const paths = output.split('\\0');\n if (!output.endsWith('\\0')) paths.pop();\n return paths.filter((path) => path.length > 0);\n}\n\n/**\n * Detect a symlink in any parent component of a repository-relative path.\n * The final component is excluded: callers inspect it themselves so they can\n * distinguish a symlinked file from a symlinked directory.\n */\nexport async function hasSymlinkParent(root: string, relativePath: string): Promise<boolean> {\n const absolute = safeJoin(root, relativePath);\n const rel = relative(root, absolute);\n if (rel === '') return false;\n\n let current = root;\n const parts = rel.split(sep);\n for (const part of parts.slice(0, -1)) {\n current = resolve(current, part);\n const info = await lstat(current).catch(() => null);\n if (info === null) return false;\n if (info.isSymbolicLink()) return true;\n if (!info.isDirectory()) return false;\n }\n return false;\n}\n", "import { lstat } from 'node:fs/promises';\nimport type {\n DiffHunk,\n FileDiff,\n FileStatus,\n ManifestFile,\n ManifestFileReason,\n ParsedFile,\n Snapshot,\n SnapshotOptions,\n} from '../types.js';\nimport { hasSymlinkParent, safeJoin, splitNulPaths } from '../paths.js';\nimport { readBlob } from '../git/content.js';\nimport { resolveScope } from '../git/scope.js';\nimport { runGit } from '../git/run.js';\nimport type { GitResult } from '../git/run.js';\nimport { manifestFileFromDiff, reviewManifest } from './manifest.js';\nimport { parseDiffHeader, parseUnifiedDiff, stripDiffPrefix } from './parse.js';\nimport { isIgnored } from './glob.js';\n\nconst DEFAULTS = {\n includeUntracked: true,\n includeContent: true,\n maxDiffBytes: 2 * 1024 * 1024,\n maxFileLines: 20_000,\n maxContentBytes: 1024 * 1024,\n maxTotalContentBytes: 64 * 1024 * 1024,\n maxFiles: 500,\n} as const;\n\n/**\n * The changed-path listing is metadata only; this byte cap is a safety valve\n * for pathological repositories. Hitting it is surfaced as a snapshot warning,\n * never as a silent omission.\n */\nconst MAX_MANIFEST_LISTING_BYTES = 64 * 1024 * 1024;\n\ninterface ContentBudget {\n includeContent: boolean;\n maxTotalBytes: number;\n usedBytes: number;\n exhausted: boolean;\n warned: boolean;\n warnings: string[];\n}\n\nfunction fitsContent(budget: ContentBudget, bytes: number): boolean {\n if (!budget.includeContent) return false;\n if (budget.exhausted || budget.usedBytes + bytes > budget.maxTotalBytes) {\n if (!budget.warned) {\n budget.warnings.push('content-budget-truncated');\n budget.warned = true;\n }\n budget.exhausted = true;\n return false;\n }\n budget.usedBytes += bytes;\n return true;\n}\n\nfunction comparePaths(left: string, right: string): number {\n return Buffer.compare(Buffer.from(left, 'utf8'), Buffer.from(right, 'utf8'));\n}\n\nfunction warnUnreadable(warnings: string[], path: string): void {\n const warning = `unreadable:${path}`;\n if (!warnings.includes(warning)) warnings.push(warning);\n}\n\ninterface DiffText {\n text: string;\n truncated: boolean;\n synthetic?: ParsedFile;\n}\n\ntype DiffFormat = 'patch' | 'raw' | 'numstat';\n\nfunction diffArgs(\n scope: Snapshot['scope'],\n format: DiffFormat = 'patch',\n paths?: readonly string[],\n): string[] {\n const common = ['diff', '--no-color', '--no-ext-diff', '--no-textconv'];\n if (format === 'raw') common.push('--raw', '-z');\n else if (format === 'numstat') common.push('--numstat', '-z');\n else common.push('--unified=3');\n common.push('--find-renames=50%', '--src-prefix=a/', '--dst-prefix=b/');\n if (scope.kind === 'worktree') common.push(scope.baseSha);\n else common.push(`${scope.baseSha}..${scope.headSha}`);\n common.push('--');\n if (paths !== undefined) common.push(...paths);\n return common;\n}\n\nfunction truncateAtFileBoundary(text: string, maxBytes: number): DiffText {\n if (Buffer.byteLength(text, 'utf8') <= maxBytes) {\n return { text, truncated: false };\n }\n const cut = Buffer.from(text, 'utf8').subarray(0, maxBytes).toString('utf8');\n const boundary = cut.lastIndexOf('\\ndiff --git ');\n if (boundary > 0) {\n const synthetic = syntheticFileFromCut(cut.slice(boundary + 1));\n return {\n text: cut.slice(0, boundary + 1),\n truncated: true,\n ...(synthetic === undefined ? {} : { synthetic }),\n };\n }\n if (cut.startsWith('diff --git ')) {\n const synthetic = syntheticFileFromCut(cut);\n return { text: '', truncated: true, ...(synthetic === undefined ? {} : { synthetic }) };\n }\n return { text: '', truncated: true };\n}\n\nfunction syntheticFileFromCut(cut: string): ParsedFile | undefined {\n const firstLineEnd = cut.indexOf('\\n');\n const headerLine = firstLineEnd < 0 ? cut : cut.slice(0, firstLineEnd);\n if (!headerLine.startsWith('diff --git ')) return undefined;\n\n const header = parseDiffHeader(headerLine, 1);\n let oldPath = header.oldPath;\n let newPath = header.newPath;\n let status: ParsedFile['status'] = 'modified';\n let oldIsNull = false;\n let newIsNull = false;\n\n for (const line of cut.split('\\n').slice(1)) {\n if (line.startsWith('@@ ') || line === 'GIT binary patch') break;\n if (line.startsWith('new file mode ')) status = 'added';\n else if (line.startsWith('deleted file mode ')) status = 'deleted';\n else if (line.startsWith('rename from ')) {\n oldPath = line.slice('rename from '.length);\n status = 'renamed';\n } else if (line.startsWith('rename to ')) {\n newPath = line.slice('rename to '.length);\n status = 'renamed';\n } else if (line.startsWith('--- ')) {\n const value = line.slice(4);\n if (value === '/dev/null') oldIsNull = true;\n else oldPath = stripDiffPrefix(value);\n } else if (line.startsWith('+++ ')) {\n const value = line.slice(4);\n if (value === '/dev/null') newIsNull = true;\n else newPath = stripDiffPrefix(value);\n }\n }\n\n if (oldIsNull) status = 'added';\n if (newIsNull) status = 'deleted';\n const path = newIsNull ? oldPath : newPath;\n const file: ParsedFile = {\n path,\n status,\n binary: false,\n hunks: [],\n added: 0,\n deleted: 0,\n synthetic: true,\n };\n if (oldPath !== path) file.oldPath = oldPath;\n return file;\n}\n\nfunction candidateKey(entry: ParsedFile): string {\n return `${entry.path}\\0${entry.oldPath ?? ''}`;\n}\n\nfunction rawStatus(letter: string, oldMode: string, newMode: string): ParsedFile['status'] {\n if (letter === 'R') return 'renamed';\n if (oldMode === '160000' || newMode === '160000') return 'submodule';\n if (letter === 'A') return 'added';\n if (letter === 'D') return 'deleted';\n return 'modified';\n}\n\nfunction parseRawDiff(raw: string): ParsedFile[] {\n const tokens = raw.split('\\0');\n const entries: ParsedFile[] = [];\n for (let index = 0; index < tokens.length;) {\n const header = tokens[index++];\n if (header === undefined || !header.startsWith(':')) continue;\n const fields = header.slice(1).split(' ');\n const oldMode = fields[0] ?? '';\n const newMode = fields[1] ?? '';\n const letter = (fields[4] ?? 'M').charAt(0);\n let oldPath: string | undefined;\n let path = tokens[index++] ?? '';\n if (letter === 'R' || letter === 'C') {\n oldPath = path;\n path = tokens[index++] ?? '';\n }\n if (path === '') continue;\n const entry: ParsedFile = {\n path,\n status: rawStatus(letter, oldMode, newMode),\n binary: false,\n hunks: [],\n added: 0,\n deleted: 0,\n };\n if (oldPath !== undefined) entry.oldPath = oldPath;\n entries.push(entry);\n }\n return entries;\n}\n\ninterface RawListing {\n entries: ParsedFile[];\n truncated: boolean;\n}\n\nasync function listRawChanges(\n scope: Snapshot['scope'],\n signal?: AbortSignal,\n paths?: readonly string[],\n): Promise<RawListing> {\n const result = await runGit(scope.repoRoot, diffArgs(scope, 'raw', paths), {\n signal,\n maxBytes: MAX_MANIFEST_LISTING_BYTES,\n truncateOnOverflow: true,\n });\n return { entries: parseRawDiff(result.stdout), truncated: result.truncated === true };\n}\n\ninterface NumstatEntry {\n added: number;\n deleted: number;\n binary: boolean;\n}\n\ninterface NumstatListing {\n entries: Map<string, NumstatEntry>;\n truncated: boolean;\n}\n\n/**\n * Parses `git diff --numstat -z`. A rename record is\n * `added\\tdeleted\\t\\0oldPath\\0newPath\\0`, so the empty path field is followed\n * by two NUL-delimited path tokens; the result is keyed by the new path.\n */\nfunction parseNumstat(raw: string): Map<string, NumstatEntry> {\n const entries = new Map<string, NumstatEntry>();\n const tokens = raw.split('\\0');\n if (!raw.endsWith('\\0')) tokens.pop();\n\n for (let index = 0; index < tokens.length;) {\n const record = tokens[index++];\n if (record === undefined || record === '') continue;\n const fields = record.split('\\t');\n if (fields.length < 3) continue;\n const addedField = fields[0] ?? '';\n const deletedField = fields[1] ?? '';\n let path = fields.slice(2).join('\\t');\n if (path === '') {\n index += 1; // old path; only the new path keys the manifest\n path = tokens[index++] ?? '';\n if (path === '') continue;\n }\n const binary = addedField === '-' || deletedField === '-';\n const added = binary ? 0 : Number.parseInt(addedField, 10);\n const deleted = binary ? 0 : Number.parseInt(deletedField, 10);\n if (!Number.isFinite(added) || !Number.isFinite(deleted)) continue;\n entries.set(path, { added, deleted, binary });\n }\n return entries;\n}\n\nasync function listNumstatChanges(\n scope: Snapshot['scope'],\n signal?: AbortSignal,\n paths?: readonly string[],\n): Promise<NumstatListing> {\n const result = await runGit(scope.repoRoot, diffArgs(scope, 'numstat', paths), {\n signal,\n maxBytes: MAX_MANIFEST_LISTING_BYTES,\n truncateOnOverflow: true,\n });\n return { entries: parseNumstat(result.stdout), truncated: result.truncated === true };\n}\n\ninterface ManifestSeed {\n path: string;\n oldPath?: string;\n status: FileStatus;\n binary: boolean;\n added: number;\n deleted: number;\n ignored: boolean;\n oversized: boolean;\n /** True when `added`/`deleted` came from the exact numstat listing. */\n fromNumstat: boolean;\n reason?: ManifestFileReason;\n}\n\nfunction rawSeeds(\n raw: readonly ParsedFile[],\n numstat: Map<string, NumstatEntry>,\n ignore: readonly string[],\n): Map<string, ManifestSeed> {\n const seeds = new Map<string, ManifestSeed>();\n for (const entry of raw) {\n const counts = numstat.get(entry.path);\n const seed: ManifestSeed = {\n path: entry.path,\n status: entry.status,\n binary: counts?.binary === true,\n added: counts?.added ?? entry.added,\n deleted: counts?.deleted ?? entry.deleted,\n ignored: isIgnored(entry.path, ignore),\n oversized: false,\n fromNumstat: counts !== undefined,\n };\n if (entry.oldPath !== undefined) seed.oldPath = entry.oldPath;\n seeds.set(entry.path, seed);\n }\n return seeds;\n}\n\n/**\n * Builds one complete-manifest entry from the full listing seed and, when the\n * path is inside the render subset, the bounded render data. Manifest-only\n * entries never trigger content reads; their patch fields stay at zero.\n *\n * Exported from the module (not the package index) so the reason precedence\n * for manifest-only paths can be pinned without a synthetic git fixture.\n */\nexport function manifestEntry(input: {\n seed: ManifestSeed;\n file?: FileDiff;\n renderExcluded: boolean;\n}): ManifestFile {\n const mapped = input.file === undefined ? undefined : manifestFileFromDiff(input.file);\n const ignored = input.seed.ignored || mapped?.ignored === true;\n const oversized = input.seed.oversized || mapped?.oversized === true;\n const binary = input.seed.binary || mapped?.binary === true;\n let reason = mapped?.reason ?? input.seed.reason;\n // A binary path has no textual patch regardless of the cap; report the more\n // specific reason. Ignored/unreadable/explicit policy reasons still win.\n if (reason === 'diff-truncated' && binary && !ignored) reason = 'binary';\n if (reason === undefined) {\n if (ignored) reason = 'ignored';\n else if (binary) reason = 'binary';\n else if (oversized) reason = 'per-file-cap';\n else if (input.renderExcluded) reason = 'render-budget';\n }\n const entry: ManifestFile = {\n path: input.seed.path,\n status: mapped?.status ?? input.seed.status,\n binary,\n ignored,\n oversized,\n added: input.seed.fromNumstat ? input.seed.added : (mapped?.added ?? input.seed.added),\n deleted: input.seed.fromNumstat ? input.seed.deleted : (mapped?.deleted ?? input.seed.deleted),\n hunkCount: mapped?.hunkCount ?? 0,\n patchBytes: mapped?.patchBytes ?? 0,\n };\n const oldPath = mapped?.oldPath ?? input.seed.oldPath;\n if (oldPath !== undefined) entry.oldPath = oldPath;\n if (reason !== undefined) entry.reason = reason;\n return entry;\n}\n\ninterface UntrackedListing {\n paths: string[];\n truncated: boolean;\n}\n\nasync function listUntracked(repoRoot: string, signal?: AbortSignal): Promise<UntrackedListing> {\n const result = await runGit(repoRoot, ['ls-files', '--others', '--exclude-standard', '-z'], {\n signal,\n maxBytes: 8 * 1024 * 1024,\n truncateOnOverflow: true,\n });\n return {\n paths: splitNulPaths(result.stdout),\n truncated: result.truncated === true,\n };\n}\n\ninterface ModeListing {\n modes: Map<string, string>;\n available: boolean;\n}\n\nasync function headModes(\n repoRoot: string,\n headSha: string | null,\n signal?: AbortSignal,\n): Promise<ModeListing> {\n let result: GitResult;\n try {\n result = await runGit(\n repoRoot,\n headSha === null ? ['ls-files', '-s', '-z'] : ['ls-tree', '-r', '-z', headSha],\n { allowFailure: true, signal, maxBytes: 8 * 1024 * 1024 },\n );\n } catch (error) {\n if (signal?.aborted === true) throw error;\n return { modes: new Map(), available: false };\n }\n if (result.code !== 0) return { modes: new Map(), available: false };\n\n const modes = new Map<string, string>();\n for (const entry of result.stdout.split('\\0')) {\n const tab = entry.indexOf('\\t');\n if (tab < 0) continue;\n const mode = entry.slice(0, tab).split(' ')[0];\n const path = entry.slice(tab + 1);\n if (mode !== undefined && path !== '') modes.set(path, mode);\n }\n return { modes, available: true };\n}\n\nasync function untrackedFile(\n repoRoot: string,\n path: string,\n maxFileLines: number,\n maxContentBytes: number,\n includeContent: boolean,\n ignored: boolean,\n budget: ContentBudget,\n warnings: string[],\n): Promise<FileDiff | null> {\n const absolute = safeJoin(repoRoot, path);\n if (await hasSymlinkParent(repoRoot, path)) return null;\n const info = await lstat(absolute).catch(() => null);\n if (info === null) {\n warnUnreadable(warnings, path);\n return {\n path,\n status: 'untracked',\n binary: false,\n oversized: false,\n added: 0,\n deleted: 0,\n hunks: [],\n contentHash: null,\n reason: 'unreadable',\n };\n }\n if (info.isSymbolicLink() || !info.isFile()) return null;\n\n const read = await readBlob(repoRoot, null, path, maxFileLines, maxContentBytes);\n if (read.reason === 'unreadable') {\n warnUnreadable(warnings, path);\n return {\n path,\n status: 'untracked',\n binary: false,\n oversized: false,\n added: 0,\n deleted: 0,\n hunks: [],\n contentHash: null,\n reason: 'unreadable',\n };\n }\n\n if (ignored) {\n if (read.lines === null && !read.binary && !read.oversized) return null;\n return {\n path,\n status: 'untracked',\n binary: read.binary,\n oversized: read.oversized,\n ignored: true,\n added: read.lines?.length ?? 0,\n deleted: 0,\n hunks: [],\n contentHash: null,\n };\n }\n\n if (read.lines === null) {\n if (!read.binary && !read.oversized) return null;\n const binaryLike: FileDiff = {\n path,\n status: 'untracked',\n binary: read.binary,\n oversized: read.oversized,\n added: 0,\n deleted: 0,\n hunks: [],\n contentHash: includeContent && !read.oversized ? read.hash : null,\n };\n if (read.encoding !== undefined) binaryLike.encoding = read.encoding;\n return binaryLike;\n }\n\n const truncated = includeContent && !fitsContent(budget, read.bytes);\n const hunk: DiffHunk = {\n oldStart: 0,\n oldLines: 0,\n newStart: 1,\n newLines: read.lines.length,\n header: '',\n lines: read.lines.map((text, index) => ({\n kind: 'add' as const,\n oldNo: null,\n newNo: index + 1,\n text,\n })),\n };\n\n const file: FileDiff = {\n path,\n status: 'untracked',\n binary: false,\n oversized: false,\n added: read.lines.length,\n deleted: 0,\n hunks: truncated || read.lines.length === 0 ? [] : [hunk],\n contentHash: includeContent && !truncated ? read.hash : null,\n };\n if (truncated) file.truncated = true;\n if (includeContent && !truncated) file.newLines = read.lines;\n return file;\n}\n\nexport async function buildSnapshot(options: SnapshotOptions): Promise<Snapshot> {\n const includeContent = options.includeContent ?? DEFAULTS.includeContent;\n const includeUntracked = options.includeUntracked ?? DEFAULTS.includeUntracked;\n const maxDiffBytes = options.maxDiffBytes ?? DEFAULTS.maxDiffBytes;\n const maxFileLines = options.maxFileLines ?? DEFAULTS.maxFileLines;\n const maxContentBytes = options.maxContentBytes ?? DEFAULTS.maxContentBytes;\n const maxTotalContentBytes = options.maxTotalContentBytes ?? DEFAULTS.maxTotalContentBytes;\n const maxFiles = options.maxFiles ?? DEFAULTS.maxFiles;\n const ignore = options.ignore ?? [];\n\n const scope = await resolveScope({\n repoRoot: options.repoRoot,\n scope: options.scope,\n signal: options.signal,\n });\n\n const warnings: string[] = [];\n if (scope.worktreeDigestTruncated === true) warnings.push('worktree-digest-truncated');\n\n // The complete changed-path listing is independent of the render budget.\n // It is metadata only, so it stays cheap even when patch bytes are capped.\n const paths = options.paths;\n const rawListing = await listRawChanges(scope, options.signal, paths);\n const numstatListing = await listNumstatChanges(scope, options.signal, paths);\n const listingTruncated = rawListing.truncated || numstatListing.truncated;\n if (listingTruncated) warnings.push('manifest-listing-truncated');\n const seeds = rawSeeds(rawListing.entries, numstatListing.entries, ignore);\n\n const diff = await runGit(scope.repoRoot, diffArgs(scope, 'patch', paths), {\n signal: options.signal,\n maxBytes: Math.max(maxDiffBytes * 8, 16 * 1024 * 1024),\n truncateOnOverflow: true,\n });\n const diffTruncated = diff.truncated === true;\n if (diffTruncated) warnings.push('diff-truncated');\n const limited = truncateAtFileBoundary(diff.stdout, maxDiffBytes);\n if (limited.truncated && !diffTruncated) warnings.push('diff-truncated');\n if (limited.synthetic !== undefined) {\n warnings.push(`diff-file-truncated:${limited.synthetic.path}`);\n }\n\n const candidates = [\n ...(limited.synthetic === undefined ? [] : [limited.synthetic]),\n ...parseUnifiedDiff(limited.text),\n ].sort((left, right) => comparePaths(left.path, right.path));\n\n let truncated = listingTruncated || diffTruncated || limited.truncated;\n if (truncated) {\n const seen = new Set(candidates.map((entry) => candidateKey(entry)));\n const byKey = new Map(candidates.map((entry) => [candidateKey(entry), entry]));\n for (const listed of rawListing.entries) {\n const key = candidateKey(listed);\n const warning = `diff-file-skipped:${listed.path}`;\n if (seen.has(key)) {\n const existing = byKey.get(key);\n // Every synthetic entry is a file cut by the global diff cap, whether\n // the cut lands in the first file or after a complete prefix.\n if (existing?.synthetic === true) {\n existing.skipped = true;\n if (!warnings.includes(warning)) warnings.push(warning);\n }\n continue;\n }\n // Only this backfill copy carries the marker; the seed above stays plain\n // listing metadata so it is not mistaken for a diff-cap omission.\n const entry: ParsedFile = { ...listed, backfill: true };\n seen.add(key);\n byKey.set(key, entry);\n candidates.push(entry);\n if (!warnings.includes(warning)) warnings.push(warning);\n }\n candidates.sort((left, right) => comparePaths(left.path, right.path));\n }\n\n let renderCapped = false;\n let selected = candidates;\n const reviewableCandidates = candidates.filter((entry) => !isIgnored(entry.path, ignore));\n if (reviewableCandidates.length > maxFiles) {\n const kept = new Set(reviewableCandidates.slice(0, maxFiles));\n selected = candidates.filter((entry) => isIgnored(entry.path, ignore) || kept.has(entry));\n truncated = true;\n renderCapped = true;\n warnings.push('files-truncated');\n }\n\n const modeListing = await headModes(scope.repoRoot, scope.headSha, options.signal);\n if (!modeListing.available) warnings.push('submodule-modes-unavailable');\n\n const budget: ContentBudget = {\n includeContent,\n maxTotalBytes: maxTotalContentBytes,\n usedBytes: 0,\n exhausted: false,\n warned: false,\n warnings,\n };\n const files: FileDiff[] = [];\n for (const entry of selected) {\n if (entry.backfill === true) {\n const seed = seeds.get(entry.path);\n const skipped: FileDiff = {\n path: entry.path,\n status: entry.status,\n binary: seed?.binary === true,\n oversized: false,\n added: 0,\n deleted: 0,\n hunks: [],\n contentHash: null,\n truncated: true,\n reason: 'diff-truncated',\n };\n if (entry.oldPath !== undefined) skipped.oldPath = entry.oldPath;\n if (isIgnored(entry.path, ignore)) skipped.ignored = true;\n files.push(skipped);\n continue;\n }\n if (entry.synthetic === true) {\n const seed = seeds.get(entry.path);\n const synthetic: FileDiff = {\n path: entry.path,\n status: entry.status,\n binary: entry.binary || seed?.binary === true,\n // Nothing measured this file's size; the global diff cap cut it.\n oversized: false,\n added: 0,\n deleted: 0,\n hunks: [],\n contentHash: null,\n truncated: true,\n reason: 'diff-truncated',\n };\n if (entry.oldPath !== undefined) synthetic.oldPath = entry.oldPath;\n if (isIgnored(entry.path, ignore)) synthetic.ignored = true;\n files.push(synthetic);\n continue;\n }\n if (isIgnored(entry.path, ignore)) {\n const ignored: FileDiff = {\n path: entry.path,\n status: entry.status,\n binary: entry.binary,\n oversized: false,\n ignored: true,\n added: entry.added,\n deleted: entry.deleted,\n hunks: [],\n contentHash: null,\n };\n if (entry.oldPath !== undefined) ignored.oldPath = entry.oldPath;\n files.push(ignored);\n continue;\n }\n const oldPath = entry.oldPath ?? entry.path;\n const hasMode =\n entry.oldMode !== undefined || entry.newMode !== undefined || entry.indexMode !== undefined;\n const isGitlink = hasMode\n ? entry.oldMode === '160000' || entry.newMode === '160000' || entry.indexMode === '160000'\n : modeListing.modes.get(entry.path) === '160000';\n if (isGitlink) {\n // A gitlink addresses a commit, not a worktree path: never read content for it.\n const submodule: FileDiff = {\n path: entry.path,\n status: 'submodule',\n binary: false,\n oversized: false,\n added: entry.added,\n deleted: entry.deleted,\n hunks: entry.hunks,\n contentHash: null,\n };\n if (entry.oldPath !== undefined) submodule.oldPath = entry.oldPath;\n files.push(submodule);\n continue;\n }\n const budgetSkipped = includeContent && budget.exhausted;\n const base =\n entry.status === 'added' || !includeContent || budgetSkipped\n ? null\n : await readBlob(scope.repoRoot, scope.baseSha, oldPath, maxFileLines, maxContentBytes);\n const head =\n entry.status === 'deleted' || !includeContent || budgetSkipped\n ? null\n : await readBlob(scope.repoRoot, scope.headSha, entry.path, maxFileLines, maxContentBytes);\n\n const binary = entry.binary || base?.binary === true || head?.binary === true;\n const oversized = base?.oversized === true || head?.oversized === true;\n const encoding =\n base?.encoding === 'unknown' || head?.encoding === 'unknown' ? 'unknown' : undefined;\n const reason =\n base?.reason === 'unreadable' || head?.reason === 'unreadable' ? 'unreadable' : undefined;\n\n let fileTruncated = false;\n let oldLines: string[] | undefined;\n let newLines: string[] | undefined;\n if (reason !== undefined) {\n warnUnreadable(warnings, entry.path);\n } else if (includeContent && !binary && !oversized) {\n if (budgetSkipped) {\n fileTruncated = true;\n } else {\n const bytes =\n (base?.lines === null || base === null ? 0 : base.bytes) +\n (head?.lines === null || head === null ? 0 : head.bytes);\n if (fitsContent(budget, bytes)) {\n oldLines = base?.lines ?? undefined;\n newLines = head?.lines ?? undefined;\n } else {\n fileTruncated = true;\n }\n }\n }\n\n let contentHash: string | null = null;\n if (includeContent && !oversized && reason === undefined && !fileTruncated) {\n if (head !== null && head.hash !== '') contentHash = head.hash;\n else if (base !== null && base.hash !== '') contentHash = base.hash;\n }\n\n const file: FileDiff = {\n path: entry.path,\n status: entry.status,\n binary,\n oversized,\n added: entry.added,\n deleted: entry.deleted,\n hunks: binary || oversized ? [] : entry.hunks,\n contentHash,\n };\n if (entry.oldPath !== undefined) file.oldPath = entry.oldPath;\n if (encoding !== undefined) file.encoding = encoding;\n if (reason !== undefined) file.reason = reason;\n if (fileTruncated) file.truncated = true;\n if (oldLines !== undefined) file.oldLines = oldLines;\n if (newLines !== undefined) file.newLines = newLines;\n files.push(file);\n }\n\n if (scope.kind === 'worktree' && includeUntracked) {\n const listing = await listUntracked(scope.repoRoot, options.signal);\n if (listing.truncated) {\n if (!warnings.includes('untracked-list-truncated')) {\n warnings.push('untracked-list-truncated');\n }\n truncated = true;\n }\n for (const path of listing.paths) {\n const ignored = isIgnored(path, ignore);\n const seed: ManifestSeed = {\n path,\n status: 'untracked',\n binary: false,\n added: 0,\n deleted: 0,\n ignored,\n oversized: false,\n fromNumstat: false,\n };\n seeds.set(path, seed);\n const absolute = safeJoin(scope.repoRoot, path);\n const info = await lstat(absolute).catch(() => null);\n if (info?.isSymbolicLink() === true || (await hasSymlinkParent(scope.repoRoot, path))) {\n // The link target is deliberately not followed. Mark it as a symlink\n // rather than unreadable so coverage can treat it as terminal\n // `no-hunks` instead of pinning every worktree review to `partial`.\n seed.reason = 'symlink';\n warnings.push(`symlink-not-followed:${path}`);\n continue;\n }\n const file = await untrackedFile(\n scope.repoRoot,\n path,\n maxFileLines,\n maxContentBytes,\n includeContent,\n ignored,\n budget,\n warnings,\n );\n if (file !== null) files.push(file);\n }\n }\n\n files.sort((left, right) => comparePaths(left.path, right.path));\n\n // Everything built before the render cap is retained for manifest metadata;\n // culling below only bounds what the snapshot renders.\n const retainedFiles = files.slice();\n const reviewableFiles = files.filter((file) => file.ignored !== true);\n if (reviewableFiles.length > maxFiles) {\n const kept = new Set(reviewableFiles.slice(0, maxFiles));\n files.splice(\n 0,\n files.length,\n ...files.filter((file) => file.ignored === true || kept.has(file)),\n );\n truncated = true;\n renderCapped = true;\n if (!warnings.includes('files-truncated')) warnings.push('files-truncated');\n }\n\n const retainedByPath = new Map(retainedFiles.map((file) => [file.path, file]));\n for (const file of retainedFiles) {\n if (seeds.has(file.path)) continue;\n const seed: ManifestSeed = {\n path: file.path,\n status: file.status,\n binary: file.binary,\n added: file.added,\n deleted: file.deleted,\n ignored: file.ignored === true,\n oversized: file.oversized,\n fromNumstat: false,\n };\n if (file.oldPath !== undefined) seed.oldPath = file.oldPath;\n if (file.reason !== undefined) seed.reason = file.reason;\n seeds.set(file.path, seed);\n }\n\n const renderPaths = new Set(files.map((file) => file.path));\n const manifest = reviewManifest(\n scope,\n [...seeds.values()]\n .map((seed) => {\n const file = retainedByPath.get(seed.path);\n return manifestEntry({\n seed,\n ...(file === undefined ? {} : { file }),\n renderExcluded: !renderPaths.has(seed.path),\n });\n })\n .sort((left, right) => comparePaths(left.path, right.path)),\n warnings,\n );\n\n const manifestTruncated =\n truncated ||\n budget.exhausted ||\n renderCapped ||\n manifest.files.some(\n (file) =>\n file.reason === 'render-budget' ||\n file.reason === 'diff-truncated' ||\n file.reason === 'per-file-cap',\n );\n\n const totals = {\n files: manifest.totals.files,\n added: manifest.totals.added,\n deleted: manifest.totals.deleted,\n truncated: manifestTruncated,\n };\n\n return {\n schemaVersion: 2,\n scope,\n files,\n manifest,\n totals,\n warnings,\n };\n}\n", "import { createHash } from 'node:crypto';\nimport { lstat, readFile, readlink } from 'node:fs/promises';\nimport { hasSymlinkParent, safeJoin } from '../paths.js';\nimport { GitError, runGit } from './run.js';\nimport type { GitResult } from './run.js';\n\nconst DEFAULT_MAX_BYTES = 8 * 1024 * 1024;\n\nexport interface BlobRead {\n lines: string[] | null;\n binary: boolean;\n oversized: boolean;\n symlink: boolean;\n hash: string;\n /** Raw bytes retained for content-budget accounting (0 when no content is kept). */\n bytes: number;\n encoding?: 'unknown';\n reason?: 'unreadable';\n}\n\nconst EMPTY: BlobRead = {\n lines: null,\n binary: false,\n oversized: false,\n symlink: false,\n hash: '',\n bytes: 0,\n};\n\nfunction hashOf(buffer: Buffer): string {\n return createHash('sha256').update(buffer).digest('hex');\n}\n\nfunction splitText(text: string): string[] {\n const lines = text.split('\\n');\n if (lines.length > 0 && lines[lines.length - 1] === '') lines.pop();\n return lines;\n}\n\nfunction decode(buffer: Buffer): string | null {\n try {\n return new TextDecoder('utf-8', { fatal: true }).decode(buffer);\n } catch {\n return null;\n }\n}\n\nfunction readBuffer(buffer: Buffer, maxLines: number, symlink: boolean): BlobRead {\n if (buffer.includes(0)) {\n return { ...EMPTY, binary: true, hash: hashOf(buffer), bytes: buffer.length };\n }\n const text = decode(buffer);\n if (text === null) {\n return {\n ...EMPTY,\n binary: true,\n encoding: 'unknown',\n hash: hashOf(buffer),\n bytes: buffer.length,\n };\n }\n const lines = splitText(text);\n if (lines.length > maxLines) return { ...EMPTY, oversized: true };\n return {\n lines,\n binary: false,\n oversized: false,\n symlink,\n hash: hashOf(buffer),\n bytes: buffer.length,\n };\n}\n\nexport async function readBlob(\n repoRoot: string,\n revision: string | null,\n path: string,\n maxLines: number,\n maxBytes: number = DEFAULT_MAX_BYTES,\n): Promise<BlobRead> {\n let buffer: Buffer;\n\n if (revision === null) {\n const absolute = safeJoin(repoRoot, path);\n if (await hasSymlinkParent(repoRoot, path)) {\n return { ...EMPTY, symlink: true };\n }\n\n let info: Awaited<ReturnType<typeof lstat>>;\n try {\n info = await lstat(absolute);\n } catch {\n return { ...EMPTY, reason: 'unreadable' };\n }\n if (info.isSymbolicLink()) {\n let target: Buffer;\n try {\n target = await readlink(absolute, { encoding: 'buffer' });\n } catch {\n return { ...EMPTY, symlink: true, reason: 'unreadable' };\n }\n if (target.length > maxBytes) return { ...EMPTY, symlink: true, oversized: true };\n return readBuffer(target, maxLines, true);\n }\n if (!info.isFile()) return EMPTY;\n if (info.size > maxBytes) {\n return { ...EMPTY, oversized: true };\n }\n\n try {\n buffer = await readFile(absolute);\n } catch {\n return { ...EMPTY, reason: 'unreadable' };\n }\n } else {\n let result: GitResult;\n try {\n result = await runGit(repoRoot, ['show', `${revision}:${path}`], {\n allowFailure: true,\n maxBytes,\n });\n } catch (error) {\n if (error instanceof GitError && error.message.includes('exceeded')) {\n return { ...EMPTY, oversized: true };\n }\n throw error;\n }\n if (result.code !== 0) return EMPTY;\n if (result.stdoutBytes.length > maxBytes) return { ...EMPTY, oversized: true };\n buffer = result.stdoutBytes;\n }\n\n return readBuffer(buffer, maxLines, false);\n}\n", "import { spawn } from 'node:child_process';\n\nexport type GitErrorCode = 'git-missing' | 'not-a-repo' | 'git-failed';\n\nexport class GitError extends Error {\n constructor(\n readonly code: GitErrorCode,\n message: string,\n readonly stderr = '',\n ) {\n super(message);\n this.name = 'GitError';\n }\n}\n\nexport interface GitRunOptions {\n allowFailure?: boolean;\n maxBytes?: number;\n maxStderrBytes?: number;\n truncateOnOverflow?: boolean;\n signal?: AbortSignal;\n env?: NodeJS.ProcessEnv;\n}\n\nexport interface GitResult {\n stdout: string;\n stdoutBytes: Buffer;\n stderr: string;\n code: number;\n truncated?: boolean;\n}\n\nconst DEFAULT_MAX_BYTES = 16 * 1024 * 1024;\nconst DEFAULT_MAX_STDERR_BYTES = 1024 * 1024;\n\nexport async function runGit(\n cwd: string,\n args: readonly string[],\n options: GitRunOptions = {},\n): Promise<GitResult> {\n const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;\n const maxStderrBytes = options.maxStderrBytes ?? DEFAULT_MAX_STDERR_BYTES;\n if (options.signal?.aborted === true) {\n throw new GitError('git-failed', 'git command aborted');\n }\n\n const env: NodeJS.ProcessEnv = { ...process.env };\n delete env.GIT_DIR;\n delete env.GIT_WORK_TREE;\n delete env.GIT_INDEX_FILE;\n Object.assign(env, {\n GIT_CONFIG_NOSYSTEM: '1',\n GIT_EXTERNAL_DIFF: '',\n GIT_TERMINAL_PROMPT: '0',\n GIT_OPTIONAL_LOCKS: '0',\n LC_ALL: 'C',\n ...options.env,\n });\n\n const gitArgs = [\n '--no-pager',\n '-c',\n 'core.quotePath=false',\n '-c',\n 'core.pager=cat',\n '-c',\n 'diff.external=',\n '-c',\n 'diff.noprefix=false',\n '-c',\n 'diff.mnemonicPrefix=false',\n '-c',\n 'diff.submodule=short',\n ...args,\n ];\n\n return await new Promise<GitResult>((resolve, reject) => {\n const child = spawn('git', gitArgs, {\n cwd,\n shell: false,\n stdio: ['ignore', 'pipe', 'pipe'],\n signal: options.signal,\n env,\n });\n\n const stdout: Buffer[] = [];\n const stderr: Buffer[] = [];\n let bytes = 0;\n let stderrBytes = 0;\n let settled = false;\n\n const fail = (error: GitError): void => {\n if (settled) return;\n settled = true;\n reject(error);\n };\n\n child.on('error', (error: NodeJS.ErrnoException) => {\n if (error.code === 'ENOENT') {\n fail(new GitError('git-missing', 'git executable not found'));\n } else {\n fail(new GitError('git-failed', error.message));\n }\n });\n\n child.stdout.on('data', (chunk: Buffer) => {\n if (settled) return;\n const remaining = maxBytes - bytes;\n if (chunk.length > remaining) {\n if (remaining > 0) {\n stdout.push(chunk.subarray(0, remaining));\n bytes += remaining;\n }\n if (options.truncateOnOverflow === true) {\n child.kill('SIGKILL');\n settled = true;\n const buffer = Buffer.concat(stdout);\n resolve({\n stdout: buffer.toString('utf8'),\n stdoutBytes: buffer,\n stderr: Buffer.concat(stderr).toString('utf8'),\n code: 1,\n truncated: true,\n });\n return;\n }\n child.kill('SIGKILL');\n fail(new GitError('git-failed', `git output exceeded ${maxBytes} bytes`));\n return;\n }\n stdout.push(chunk);\n bytes += chunk.length;\n });\n\n child.stderr.on('data', (chunk: Buffer) => {\n stderrBytes += chunk.length;\n if (stderrBytes > maxStderrBytes) {\n child.kill('SIGKILL');\n fail(new GitError('git-failed', `git stderr exceeded ${maxStderrBytes} bytes`));\n return;\n }\n stderr.push(chunk);\n });\n\n child.on('close', (code) => {\n if (settled) return;\n const buffer = Buffer.concat(stdout);\n const result: GitResult = {\n stdout: buffer.toString('utf8'),\n stdoutBytes: buffer,\n stderr: Buffer.concat(stderr).toString('utf8'),\n code: code ?? 1,\n truncated: false,\n };\n if (result.code !== 0 && options.allowFailure !== true) {\n settled = true;\n reject(\n new GitError(\n 'git-failed',\n `git ${args.join(' ')} failed (${result.code}): ${result.stderr.trim()}`,\n result.stderr,\n ),\n );\n return;\n }\n settled = true;\n resolve(result);\n });\n });\n}\n", "import { createHash, type Hash } from 'node:crypto';\nimport { constants } from 'node:fs';\nimport { lstat, open, readlink, realpath } from 'node:fs/promises';\nimport { isAbsolute, relative, sep } from 'node:path';\nimport type { DiffScope, ResolvedScope } from '../types.js';\nimport { hasSymlinkParent, safeJoin, splitNulPaths } from '../paths.js';\nimport { resolveRepoRoot } from './repo.js';\nimport { GitError, runGit } from './run.js';\n\nexport const EMPTY_TREE_SHA = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';\n\nexport async function resolveDefaultBase(repoRoot: string): Promise<string> {\n const origin = await runGit(repoRoot, ['symbolic-ref', '--short', 'refs/remotes/origin/HEAD'], {\n allowFailure: true,\n });\n if (origin.code === 0 && origin.stdout.trim() !== '') return origin.stdout.trim();\n\n for (const candidate of ['main', 'master']) {\n const result = await runGit(\n repoRoot,\n ['rev-parse', '--verify', '--quiet', `refs/heads/${candidate}`],\n { allowFailure: true },\n );\n if (result.code === 0) return candidate;\n }\n\n const head = await runGit(repoRoot, ['symbolic-ref', '--short', 'HEAD'], { allowFailure: true });\n if (head.code === 0 && head.stdout.trim() !== '') return head.stdout.trim();\n throw new GitError('git-failed', 'cannot determine the default base branch');\n}\n\nexport interface ResolveScopeInput {\n repoRoot: string;\n scope: DiffScope;\n signal?: AbortSignal;\n}\n\nexport async function resolveScope(input: ResolveScopeInput): Promise<ResolvedScope> {\n const root = await resolveRepoRoot(input.repoRoot);\n const signal = input.signal;\n\n if (input.scope.kind === 'range') {\n const headSha = await resolveCommitRef(root, input.scope.headRef, signal);\n const baseSha =\n input.scope.twoDot === true\n ? await resolveCommitRef(root, input.scope.baseRef, signal)\n : (\n await runGit(root, [\n 'merge-base',\n await resolveCommitRef(root, input.scope.baseRef, signal),\n headSha,\n ])\n ).stdout.trim();\n return {\n kind: 'range',\n repoRoot: root,\n baseRef: input.scope.baseRef,\n headRef: input.scope.headRef,\n baseSha,\n headSha,\n label: `${input.scope.baseRef}${input.scope.twoDot === true ? '..' : '...'}${input.scope.headRef}`,\n worktreeDigest: headSha,\n };\n }\n\n if (input.scope.kind === 'worktree') {\n const baseSha = await resolveCommitRef(root, input.scope.baseRef, signal);\n const digest = await worktreeDigestState(root, baseSha, signal);\n const resolved: ResolvedScope = {\n kind: 'worktree',\n repoRoot: root,\n baseRef: input.scope.baseRef,\n baseSha,\n headSha: null,\n label: `${input.scope.baseRef} (worktree)`,\n worktreeDigest: digest.hash,\n };\n if (digest.truncated) resolved.worktreeDigestTruncated = true;\n return resolved;\n }\n\n if (input.scope.kind === 'commits') {\n const shas: unknown = input.scope.shas;\n if (!Array.isArray(shas) || shas.length === 0) {\n throw new GitError('git-failed', 'a commit scope needs at least one commit');\n }\n if (shas.length > MAX_SELECTED_COMMITS) {\n throw new GitError(\n 'git-failed',\n `a commit scope accepts at most ${MAX_SELECTED_COMMITS} commits`,\n );\n }\n const resolved: string[] = [];\n const seen = new Set<string>();\n for (const sha of shas) {\n if (typeof sha !== 'string' || sha.trim() === '') {\n throw new GitError('git-failed', 'every selected commit must be a commit ref');\n }\n const resolvedSha = await resolveCommitRef(root, sha.trim(), signal);\n if (seen.has(resolvedSha)) continue;\n seen.add(resolvedSha);\n resolved.push(resolvedSha);\n }\n for (let index = 1; index < resolved.length; index += 1) {\n const previous = resolved[index - 1] ?? '';\n const current = resolved[index] ?? '';\n const ancestor = await runGit(root, ['merge-base', '--is-ancestor', previous, current], {\n allowFailure: true,\n signal,\n });\n if (ancestor.code !== 0) {\n throw new GitError(\n 'git-failed',\n 'selected commits must be ordered oldest to newest along one ancestry path',\n );\n }\n }\n const oldest = resolved[0] ?? '';\n const headSha = resolved[resolved.length - 1] ?? oldest;\n const baseSha = await resolveParentBase(root, oldest, signal);\n return {\n kind: 'commits',\n repoRoot: root,\n baseSha,\n headSha,\n label:\n resolved.length === 1\n ? `commit ${headSha.slice(0, 8)}`\n : `${resolved.length} commits: ${oldest.slice(0, 8)}..${headSha.slice(0, 8)}`,\n worktreeDigest: headSha,\n shas: resolved,\n };\n }\n\n const headSha = await resolveCommitRef(root, input.scope.sha, signal);\n return {\n kind: 'commit',\n repoRoot: root,\n baseSha: await resolveParentBase(root, headSha, signal),\n headSha,\n label: headSha.slice(0, 12),\n worktreeDigest: headSha,\n };\n}\n\nconst MAX_SELECTED_COMMITS = 200;\n\nasync function resolveCommitRef(\n repoRoot: string,\n ref: string,\n signal?: AbortSignal,\n): Promise<string> {\n const result = await runGit(\n repoRoot,\n ['rev-parse', '--verify', '--end-of-options', `${ref}^{commit}`],\n { signal },\n );\n return result.stdout.trim();\n}\n\nasync function resolveParentBase(\n repoRoot: string,\n headSha: string,\n signal?: AbortSignal,\n): Promise<string> {\n const parentSha = await firstParentSha(repoRoot, headSha, signal);\n if (parentSha === null) return EMPTY_TREE_SHA;\n const available = await runGit(repoRoot, ['cat-file', '-e', `${parentSha}^{commit}`], {\n allowFailure: true,\n signal,\n });\n if (available.code !== 0) {\n throw new GitError(\n 'git-failed',\n `commit ${headSha} has a parent that is not available; fetch/unshallow the repository`,\n );\n }\n return parentSha;\n}\n\nasync function firstParentSha(\n repoRoot: string,\n headSha: string,\n signal?: AbortSignal,\n): Promise<string | null> {\n const listed = await runGit(repoRoot, ['rev-list', '--parents', '-n', '1', headSha], { signal });\n const fields = listed.stdout\n .trim()\n .split(/\\s+/)\n .filter((field) => field !== '');\n if (fields.length > 1) return fields[1] ?? null;\n\n // `rev-list` hides the parent of a shallow boundary. The commit object still\n // records it, so use that to tell a real root commit from an unshallowed edge.\n const object = await runGit(repoRoot, ['cat-file', '-p', headSha], { signal });\n const match = /^parent ([0-9a-f]{40})$/m.exec(object.stdout);\n return match?.[1] ?? null;\n}\n\ninterface WorktreeDigestState {\n hash: string;\n truncated: boolean;\n}\n\nfunction compareBytePaths(left: string, right: string): number {\n return Buffer.compare(Buffer.from(left, 'utf8'), Buffer.from(right, 'utf8'));\n}\n\nfunction abortedError(): GitError {\n return new GitError('git-failed', 'git command aborted');\n}\n\nfunction isAborted(signal?: AbortSignal): boolean {\n return signal?.aborted === true;\n}\n\nconst DIGEST_DOMAIN = Buffer.from('dsh-worktree-digest-v2\\0', 'utf8');\nconst RECORD_DOMAIN = Buffer.from('dsh-untracked-record-v2\\0', 'utf8');\nconst TAG_STATUS = 1;\nconst TAG_DIFF = 2;\nconst TAG_UNTRACKED = 3;\nconst FIELD_TYPE = 1;\nconst FIELD_PATH = 2;\nconst FIELD_CONTENT = 3;\nconst TYPE_FILE = 1;\nconst TYPE_SYMLINK = 2;\nconst TYPE_UNREADABLE = 3;\nconst UNREADABLE = Buffer.from('unreadable', 'utf8');\n\nfunction updateFramedHeader(hash: Hash, tag: number, length: number): void {\n const header = Buffer.alloc(9);\n header.writeUInt8(tag, 0);\n header.writeBigUInt64BE(BigInt(length), 1);\n hash.update(header);\n}\n\nfunction updateFramed(hash: Hash, tag: number, data: Buffer): void {\n updateFramedHeader(hash, tag, data.length);\n hash.update(data);\n}\n\nfunction newRecord(): Hash {\n return createHash('sha256').update(RECORD_DOMAIN);\n}\n\nfunction recordPrefix(type: number, pathBytes: Buffer): Hash {\n const record = newRecord();\n updateFramed(record, FIELD_TYPE, Buffer.from([type]));\n updateFramed(record, FIELD_PATH, pathBytes);\n return record;\n}\n\nfunction unreadableRecord(pathBytes: Buffer): Buffer {\n const record = recordPrefix(TYPE_UNREADABLE, pathBytes);\n updateFramed(record, FIELD_CONTENT, UNREADABLE);\n return record.digest();\n}\n\nfunction symlinkRecord(pathBytes: Buffer, target: Buffer): Buffer {\n const record = recordPrefix(TYPE_SYMLINK, pathBytes);\n updateFramed(record, FIELD_CONTENT, target);\n return record.digest();\n}\n\nfunction fileRecord(pathBytes: Buffer, size: number): Hash {\n const record = recordPrefix(TYPE_FILE, pathBytes);\n updateFramedHeader(record, FIELD_CONTENT, size);\n return record;\n}\n\nasync function openedPath(handle: { readonly fd: number }, absolute: string): Promise<string> {\n try {\n // /proc/self/fd names the opened descriptor, not the current pathname.\n return await readlink(`/proc/self/fd/${handle.fd}`);\n } catch {\n // Non-procfs platforms keep the pathname-based fallback and its TOCTOU window.\n return await realpath(absolute);\n }\n}\n\nasync function untrackedRecord(\n repoRoot: string,\n realRoot: string,\n path: string,\n signal?: AbortSignal,\n): Promise<Buffer> {\n if (isAborted(signal)) throw abortedError();\n const absolute = safeJoin(repoRoot, path);\n const pathBytes = Buffer.from(path, 'utf8');\n if (await hasSymlinkParent(repoRoot, path)) return unreadableRecord(pathBytes);\n\n let info;\n try {\n info = await lstat(absolute);\n } catch {\n return unreadableRecord(pathBytes);\n }\n if (isAborted(signal)) throw abortedError();\n\n if (info.isSymbolicLink()) {\n try {\n const target = await readlink(absolute, { encoding: 'buffer' });\n if (isAborted(signal)) throw abortedError();\n return symlinkRecord(pathBytes, target);\n } catch {\n if (isAborted(signal)) throw abortedError();\n return unreadableRecord(pathBytes);\n }\n }\n\n let handle;\n try {\n handle = await open(absolute, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);\n const stat = await handle.stat();\n if (!stat.isFile()) return unreadableRecord(pathBytes);\n const opened = await openedPath(handle, absolute);\n if (!isAbsolute(opened)) return unreadableRecord(pathBytes);\n const rel = relative(realRoot, opened);\n if (rel === '' || rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {\n return unreadableRecord(pathBytes);\n }\n const record = fileRecord(pathBytes, stat.size);\n if (stat.size > 0) {\n let read = 0;\n const stream = handle.createReadStream({\n start: 0,\n end: stat.size - 1,\n autoClose: false,\n signal,\n });\n for await (const chunk of stream) {\n record.update(chunk);\n read += chunk.length;\n }\n if (read !== stat.size) return unreadableRecord(pathBytes);\n }\n return record.digest();\n } catch {\n if (isAborted(signal)) throw abortedError();\n return unreadableRecord(pathBytes);\n } finally {\n if (handle !== undefined) await handle.close().catch(() => undefined);\n }\n}\n\nasync function worktreeDigestState(\n repoRoot: string,\n baseSha: string,\n signal?: AbortSignal,\n): Promise<WorktreeDigestState> {\n const status = await runGit(\n repoRoot,\n ['status', '--porcelain=v2', '-z', '--untracked-files=all'],\n { signal, maxBytes: 8 * 1024 * 1024, truncateOnOverflow: true },\n );\n const diff = await runGit(\n repoRoot,\n [\n 'diff',\n '--no-color',\n '--no-ext-diff',\n '--no-textconv',\n '--binary',\n '--src-prefix=a/',\n '--dst-prefix=b/',\n baseSha,\n '--',\n ],\n { signal, maxBytes: 8 * 1024 * 1024, truncateOnOverflow: true },\n );\n const untracked = await runGit(repoRoot, ['ls-files', '--others', '--exclude-standard', '-z'], {\n signal,\n maxBytes: 8 * 1024 * 1024,\n truncateOnOverflow: true,\n });\n const hash = createHash('sha256').update(DIGEST_DOMAIN);\n updateFramed(hash, TAG_STATUS, status.stdoutBytes);\n updateFramed(hash, TAG_DIFF, diff.stdoutBytes);\n const realRoot = await realpath(repoRoot);\n const paths = splitNulPaths(untracked.stdout).sort(compareBytePaths);\n for (const path of paths) {\n updateFramed(hash, TAG_UNTRACKED, await untrackedRecord(repoRoot, realRoot, path, signal));\n }\n return {\n hash: hash.digest('hex'),\n truncated: status.truncated === true || diff.truncated === true || untracked.truncated === true,\n };\n}\n\nexport async function worktreeDigest(\n repoRoot: string,\n baseSha: string,\n signal?: AbortSignal,\n): Promise<string> {\n return (await worktreeDigestState(repoRoot, baseSha, signal)).hash;\n}\n", "import { realpath, stat } from 'node:fs/promises';\nimport { GitError, runGit } from './run.js';\n\nexport async function resolveRepoRoot(input: string): Promise<string> {\n const absolute = await realpath(input).catch(() => {\n throw new GitError('not-a-repo', `path does not exist: ${input}`);\n });\n const info = await stat(absolute).catch(() => {\n throw new GitError('not-a-repo', `path does not exist: ${input}`);\n });\n if (!info.isDirectory()) {\n throw new GitError('not-a-repo', `not a directory: ${input}`);\n }\n\n const result = await runGit(absolute, ['rev-parse', '--show-toplevel'], {\n allowFailure: true,\n });\n if (result.code !== 0) {\n throw new GitError('not-a-repo', `not a git repository: ${input}`, result.stderr);\n }\n return await realpath(result.stdout.trim());\n}\n", "import type {\n DiffHunk,\n FileDiff,\n ManifestFile,\n ManifestFileReason,\n ResolvedScope,\n ReviewManifest,\n Snapshot,\n} from '../types.js';\n\nconst LINE_PREFIX: Record<DiffHunk['lines'][number]['kind'], string> = {\n add: '+',\n del: '-',\n context: ' ',\n};\n\nfunction hunkHeaderLine(hunk: DiffHunk): string {\n const section = hunk.header === '' ? '' : ` ${hunk.header}`;\n return `@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@${section}`;\n}\n\n/**\n * UTF-8 byte size of the parsed hunks. This is a lower bound on the full\n * unified-diff bytes for a file (path/mode/index metadata is not retained);\n * use raw diff bytes where an exact budget matters.\n */\nexport function patchBytesFromHunks(hunks: readonly DiffHunk[]): number {\n let bytes = 0;\n for (const hunk of hunks) {\n bytes += Buffer.byteLength(`${hunkHeaderLine(hunk)}\\n`, 'utf8');\n for (const line of hunk.lines) {\n bytes += Buffer.byteLength(`${LINE_PREFIX[line.kind]}${line.text}\\n`, 'utf8');\n }\n }\n return bytes;\n}\n\nfunction reasonForFile(file: FileDiff): ManifestFileReason | undefined {\n if (file.reason !== undefined) return file.reason;\n if (file.ignored === true) return 'ignored';\n if (file.binary) return 'binary';\n if (file.oversized) return 'per-file-cap';\n return undefined;\n}\n\n/**\n * Maps one bounded render entry to its complete-manifest entry.\n *\n * `FileDiff.truncated` and `FileDiff.encoding` are intentionally not manifest\n * fields in R1. A missing `contentBytes` means \"unknown\", never \"no content\".\n */\nexport function manifestFileFromDiff(file: FileDiff): ManifestFile {\n const reason = reasonForFile(file);\n return {\n path: file.path,\n ...(file.oldPath === undefined ? {} : { oldPath: file.oldPath }),\n status: file.status,\n binary: file.binary,\n ignored: file.ignored === true,\n oversized: file.oversized,\n added: file.added,\n deleted: file.deleted,\n hunkCount: file.hunks.length,\n patchBytes: patchBytesFromHunks(file.hunks),\n ...(reason === undefined ? {} : { reason }),\n };\n}\n\n/** Builds a manifest document from already-normalized entries. */\nexport function reviewManifest(\n scope: ResolvedScope,\n files: readonly ManifestFile[],\n warnings: readonly string[] = [],\n): ReviewManifest {\n const totals = files.reduce(\n (accumulator, file) => ({\n files: accumulator.files + 1,\n added: accumulator.added + file.added,\n deleted: accumulator.deleted + file.deleted,\n patchBytes: accumulator.patchBytes + file.patchBytes,\n }),\n { files: 0, added: 0, deleted: 0, patchBytes: 0 },\n );\n return {\n schemaVersion: 1,\n scope,\n files: [...files],\n totals,\n warnings: [...warnings],\n };\n}\n\n/**\n * Builds a complete manifest from the available render entries. Callers that\n * have the full changed-path listing must supply every path here; this helper\n * never applies a file-count cap.\n */\nexport function buildReviewManifest(input: {\n scope: ResolvedScope;\n files: readonly FileDiff[];\n warnings?: readonly string[];\n}): ReviewManifest {\n return reviewManifest(\n input.scope,\n input.files.map((file) => manifestFileFromDiff(file)),\n input.warnings,\n );\n}\n\n/**\n * Returns the snapshot's own manifest when present. Legacy v1 snapshots only\n * retain the bounded render subset, so a truncated one gets a\n * `legacy-truncated` warning; a complete v1 snapshot already lists every path.\n * A v2 snapshot without a manifest is corrupt, so its synthesized manifest is\n * marked `manifest-missing` and coverage cannot treat the render subset as the\n * complete changed-path listing.\n *\n * `totals.truncated` is the only aggregate truncation signal a legacy snapshot\n * retains, and it covers files, diff bytes, and content bytes alike. Keeping\n * the warning for all three is deliberate: we cannot tell from a legacy\n * snapshot whether a path was omitted, only that some budget was applied.\n */\nexport function manifestFromSnapshot(snapshot: Snapshot): ReviewManifest {\n if (snapshot.manifest !== undefined) return snapshot.manifest;\n const warnings = [...snapshot.warnings];\n if (snapshot.schemaVersion === 2) {\n if (!warnings.includes('manifest-missing')) warnings.push('manifest-missing');\n } else if (snapshot.totals.truncated && !warnings.includes('legacy-truncated')) {\n warnings.push('legacy-truncated');\n }\n return buildReviewManifest({ scope: snapshot.scope, files: snapshot.files, warnings });\n}\n", "import type { DiffHunk, DiffLine, ParsedFile } from '../types.js';\n\ninterface MutableFile {\n path: string;\n oldPath?: string;\n status: 'added' | 'modified' | 'deleted' | 'renamed';\n binary: boolean;\n hunks: DiffHunk[];\n added: number;\n deleted: number;\n oldMode?: string;\n newMode?: string;\n indexMode?: string;\n oldIsNull: boolean;\n newIsNull: boolean;\n}\n\nconst FILE_HEADER = /^diff --git a\\/(.+) b\\/(.+)$/;\nconst HUNK_HEADER = /^@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@(?: ?(.*))?$/;\nconst INDEX_LINE = /^index [0-9a-f]+\\.\\.[0-9a-f]+ (\\d{6})$/;\n\nexport interface DiffHeader {\n oldPath: string;\n newPath: string;\n}\n\n/** Parse a `diff --git` line and fail closed on ambiguous paths. */\nexport function parseDiffHeader(line: string, lineNumber = 1): DiffHeader {\n const match = FILE_HEADER.exec(line);\n const separatorCount = line.split(' b/').length - 1;\n if (match === null || separatorCount !== 1) {\n throw new DiffParseError(\n `Malformed or ambiguous diff file header at line ${lineNumber}: expected exactly one \" b/\" separator between a/<path> and b/<path>`,\n lineNumber,\n );\n }\n return { oldPath: match[1], newPath: match[2] };\n}\n\nexport class DiffParseError extends Error {\n readonly line: number;\n\n constructor(message: string, line: number) {\n super(message);\n this.name = 'DiffParseError';\n this.line = line;\n }\n}\n\nexport function parseUnifiedDiff(diff: string): ParsedFile[] {\n const files: ParsedFile[] = [];\n let current: MutableFile | null = null;\n let hunk: DiffHunk | null = null;\n let oldNo = 0;\n let newNo = 0;\n\n const finish = (): void => {\n if (current === null) return;\n if (hunk !== null) current.hunks.push(hunk);\n const hunks = current.hunks.filter((candidate) => candidate.lines.length > 0);\n\n let status = current.status;\n if (current.oldIsNull && !current.newIsNull) status = 'added';\n else if (!current.oldIsNull && current.newIsNull) status = 'deleted';\n else if (current.oldPath !== undefined && current.oldPath !== current.path) status = 'renamed';\n\n const parsed: ParsedFile = {\n path: current.path,\n status,\n binary: current.binary,\n hunks,\n added: current.added,\n deleted: current.deleted,\n };\n if (current.oldPath !== undefined && current.oldPath !== current.path) {\n parsed.oldPath = current.oldPath;\n }\n if (current.oldMode !== undefined) parsed.oldMode = current.oldMode;\n if (current.newMode !== undefined) parsed.newMode = current.newMode;\n if (current.indexMode !== undefined) parsed.indexMode = current.indexMode;\n files.push(parsed);\n\n current = null;\n hunk = null;\n };\n\n for (const [index, line] of diff.split('\\n').entries()) {\n if (line.startsWith('diff --git ')) {\n finish();\n const { oldPath, newPath } = parseDiffHeader(line, index + 1);\n current = {\n path: newPath,\n ...(oldPath !== newPath ? { oldPath } : {}),\n status: 'modified',\n binary: false,\n hunks: [],\n added: 0,\n deleted: 0,\n oldIsNull: false,\n newIsNull: false,\n };\n continue;\n }\n\n if (current === null) continue;\n\n if (line.startsWith('@@ ')) {\n if (hunk !== null) current.hunks.push(hunk);\n const match = HUNK_HEADER.exec(line);\n if (match === null) {\n hunk = null;\n continue;\n }\n const oldStart = Number(match[1]);\n const oldLines = match[2] === undefined ? 1 : Number(match[2]);\n const newStart = Number(match[3]);\n const newLines = match[4] === undefined ? 1 : Number(match[4]);\n hunk = {\n oldStart,\n oldLines,\n newStart,\n newLines,\n header: match[5] ?? '',\n lines: [],\n };\n oldNo = oldStart;\n newNo = newStart;\n continue;\n }\n\n if (hunk === null) {\n if (line.startsWith('new file mode ')) {\n current.status = 'added';\n current.newMode = line.slice('new file mode '.length);\n continue;\n }\n if (line.startsWith('deleted file mode ')) {\n current.status = 'deleted';\n current.oldMode = line.slice('deleted file mode '.length);\n continue;\n }\n if (line.startsWith('old mode ')) {\n current.oldMode = line.slice('old mode '.length);\n continue;\n }\n if (line.startsWith('new mode ')) {\n current.newMode = line.slice('new mode '.length);\n continue;\n }\n if (line.startsWith('index ')) {\n const match = INDEX_LINE.exec(line);\n if (match?.[1] !== undefined) current.indexMode = match[1];\n continue;\n }\n if (line.startsWith('rename from ')) {\n current.oldPath = line.slice('rename from '.length);\n current.status = 'renamed';\n continue;\n }\n if (line.startsWith('rename to ')) {\n current.path = line.slice('rename to '.length);\n current.status = 'renamed';\n continue;\n }\n if (line.startsWith('--- ')) {\n const value = line.slice(4);\n if (value === '/dev/null') {\n current.oldIsNull = true;\n current.status = 'added';\n } else {\n current.oldPath = stripPrefix(value);\n }\n continue;\n }\n if (line.startsWith('+++ ')) {\n const value = line.slice(4);\n if (value === '/dev/null') {\n current.newIsNull = true;\n current.status = 'deleted';\n } else {\n current.path = stripPrefix(value);\n }\n continue;\n }\n if (line.startsWith('Binary files ') || line === 'GIT binary patch') {\n current.binary = true;\n continue;\n }\n continue;\n }\n\n if (line.startsWith('\\\\ No newline')) continue;\n\n if (line.startsWith('+') || line.startsWith('-') || line.startsWith(' ')) {\n const kind: DiffLine['kind'] = line[0] === '+' ? 'add' : line[0] === '-' ? 'del' : 'context';\n const text = line.slice(1);\n hunk.lines.push({\n kind,\n oldNo: kind === 'add' ? null : oldNo,\n newNo: kind === 'del' ? null : newNo,\n text,\n });\n if (kind === 'add') {\n current.added += 1;\n newNo += 1;\n } else if (kind === 'del') {\n current.deleted += 1;\n oldNo += 1;\n } else {\n oldNo += 1;\n newNo += 1;\n }\n }\n }\n\n finish();\n return files;\n}\n\nexport function stripDiffPrefix(path: string): string {\n return path.startsWith('a/') || path.startsWith('b/') ? path.slice(2) : path;\n}\n\nconst stripPrefix = stripDiffPrefix;\n", "function globToRegExp(glob: string): RegExp {\n let pattern = glob.trim();\n if (pattern.endsWith('/')) pattern += '**';\n const anchored = pattern.includes('/');\n let source = '';\n\n for (let index = 0; index < pattern.length; index += 1) {\n const character = pattern[index] ?? '';\n if (character === '*') {\n if (pattern[index + 1] === '*') {\n index += 1;\n if (pattern[index + 1] === '/') {\n index += 1;\n source += '(?:.*/)?';\n } else {\n source += '.*';\n }\n } else {\n source += '[^/]*';\n }\n continue;\n }\n if (character === '?') {\n source += '[^/]';\n continue;\n }\n source += character.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }\n\n return new RegExp(anchored ? `^${source}$` : `(?:^|.*/)${source}$`);\n}\n\nexport function isIgnored(path: string, patterns: readonly string[]): boolean {\n return patterns.some((pattern) => globToRegExp(pattern).test(path));\n}\n", "import { randomBytes } from 'node:crypto';\n\nexport type IdPrefix = 'rev' | 'rnd' | 'cmt' | 'evt' | 'snap' | 'anc' | 'sub' | 'job';\n\nexport type RandomBytes = (length: number) => Uint8Array;\n\nexport class ReviewIdError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ReviewIdError';\n }\n}\n\nconst PREFIXES = new Set<IdPrefix>(['rev', 'rnd', 'cmt', 'evt', 'snap', 'anc', 'sub', 'job']);\nconst CROCKFORD = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst TIME_LENGTH = 10;\nconst RANDOM_LENGTH = 16;\nconst RANDOM_BYTES = 10;\nconst MAX_TIME = 0xffffffffffff;\n\nfunction encodeFixed(value: number, length: number): string {\n let remaining = value;\n let out = '';\n for (let index = 0; index < length; index++) {\n out = CROCKFORD[remaining % 32] + out;\n remaining = Math.floor(remaining / 32);\n }\n return out;\n}\n\nfunction encodeBytes(bytes: Uint8Array): string {\n let accumulator = 0;\n let bits = 0;\n let out = '';\n for (const byte of bytes) {\n accumulator = (accumulator << 8) | byte;\n bits += 8;\n while (bits >= 5) {\n out += CROCKFORD[(accumulator >>> (bits - 5)) & 31];\n bits -= 5;\n }\n }\n if (bits > 0) out += CROCKFORD[(accumulator << (5 - bits)) & 31];\n return out;\n}\n\nfunction defaultRandom(length: number): Uint8Array {\n return randomBytes(length);\n}\n\n/**\n * Creates a ULID-like id: 48-bit millisecond timestamp + 80 bits of randomness,\n * prefixed with a domain tag. Fixed-width Crockford base32 keeps ids sortable.\n */\nexport function createId(\n prefix: IdPrefix,\n now: () => Date = () => new Date(),\n random: RandomBytes = defaultRandom,\n): string {\n if (!PREFIXES.has(prefix)) {\n throw new ReviewIdError(`unknown id prefix: ${String(prefix)}`);\n }\n\n const date = now();\n if (!(date instanceof Date) || !Number.isFinite(date.getTime())) {\n throw new ReviewIdError('clock returned an invalid date');\n }\n const time = date.getTime();\n if (time < 0 || time > MAX_TIME) {\n throw new ReviewIdError(`clock is outside the 48-bit millisecond range: ${time}`);\n }\n\n const bytes = random(RANDOM_BYTES);\n if (!(bytes instanceof Uint8Array) || bytes.length !== RANDOM_BYTES) {\n throw new ReviewIdError(`random source must return ${RANDOM_BYTES} bytes`);\n }\n\n const timePart = encodeFixed(time, TIME_LENGTH);\n const randomPart = encodeBytes(bytes);\n return `${prefix}_${timePart}${randomPart}`;\n}\n\nexport const ID_LENGTHS = {\n time: TIME_LENGTH,\n random: RANDOM_LENGTH,\n total: TIME_LENGTH + RANDOM_LENGTH,\n} as const;\n", "import type {\n AgentReport,\n Finding,\n ReviewerBackendKind,\n ReviewerConfig,\n} from '../reviewer/types.js';\nimport type {\n Actor,\n ActorKind,\n Anchor,\n Comment,\n CommentState,\n FindingDecision,\n FixClaimRecord,\n Outcome,\n SuggestionState,\n Reply,\n ReviewState,\n Round,\n ReviewId,\n ReviewCoverage,\n SubmissionRecord,\n} from './types.js';\nimport { createId } from './ids.js';\nimport type { IdPrefix } from './ids.js';\n\nexport interface ReviewCreatedData {\n review: ReviewState;\n}\n\nexport interface RoundCreatedData {\n round: Round;\n}\n\nexport interface CommentAddedData {\n comment: Comment;\n}\n\nexport interface CommentRepliedData {\n commentId: string;\n reply: Reply;\n}\n\nexport interface CommentStateData {\n commentId: string;\n state: CommentState;\n}\n\nexport interface CommentEditedData {\n commentId: string;\n body: string;\n}\n\nexport interface CommentDeletedData {\n commentId: string;\n}\n\nexport interface ReviewUpdatedData {\n title?: string;\n reviewer?: ReviewerConfig;\n}\n\nexport interface ReviewDeletedData {\n /** Optional human-readable reason retained in the audit log. */\n reason?: string;\n}\n\nexport interface CommentAnchorData {\n commentId: string;\n anchor: Anchor;\n outcome?: Outcome;\n}\n\nexport interface SuggestionStateData {\n commentId: string;\n state: SuggestionState;\n}\n\nexport interface FixClaimData {\n claims: FixClaimRecord[];\n}\n\nexport interface FindingDecisionData {\n decision: FindingDecision;\n /** Present when accepting a finding also creates its comment. */\n comment?: Comment;\n /** Present when dismissing an accepted finding removes its transferred comment. */\n deletedCommentId?: string;\n}\n\nexport interface SuggestionAppliedData {\n commentId: string;\n round: number;\n sha?: string;\n result?: string;\n}\n\nexport interface ReviewClosedData {\n verdict: 'approved' | 'closed';\n}\n\nexport interface ReviewSubmittedData {\n submission: SubmissionRecord;\n feedback: {\n markdown: string;\n json: unknown;\n deliveryKey: string;\n };\n}\n\nexport interface AgentStartedData {\n jobId: string;\n round: number;\n backend: ReviewerBackendKind;\n}\n\nexport interface AgentCoverageData {\n coverage: ReviewCoverage;\n round: number;\n}\n\nexport interface AgentFindingData {\n finding: Finding;\n round: number;\n}\n\nexport interface AgentReportData {\n report: AgentReport;\n /** Explicit coverage for an aggregated multi-shard report. */\n coverage?: ReviewCoverage;\n}\n\nexport interface AgentShardData {\n shardId: string;\n shardIndex: number;\n shardCount: number;\n round: number;\n report: AgentReport;\n /** Paths covered by this shard, used for incremental coverage progress. */\n paths?: string[];\n tier?: 'deep' | 'light';\n}\n\nexport interface AgentFailedData {\n code: string;\n message: string;\n}\n\nexport interface AgentRetryData {\n round: number;\n /** Shards whose work is missing and must run again in the same round. */\n shardIds: string[];\n}\n\nexport interface ReviewEventDataMap {\n 'review/created': ReviewCreatedData;\n 'round/created': RoundCreatedData;\n 'comment/added': CommentAddedData;\n 'comment/replied': CommentRepliedData;\n 'comment/state': CommentStateData;\n 'comment/edited': CommentEditedData;\n 'comment/deleted': CommentDeletedData;\n 'comment/anchor': CommentAnchorData;\n 'suggestion/state': SuggestionStateData;\n 'suggestion/applied': SuggestionAppliedData;\n 'fix/claim': FixClaimData;\n 'finding/decision': FindingDecisionData;\n 'review/updated': ReviewUpdatedData;\n 'review/deleted': ReviewDeletedData;\n 'review/closed': ReviewClosedData;\n 'review/submitted': ReviewSubmittedData;\n 'agent/started': AgentStartedData;\n 'agent/coverage': AgentCoverageData;\n 'agent/shard': AgentShardData;\n 'agent/finding': AgentFindingData;\n 'agent/report': AgentReportData;\n 'agent/failed': AgentFailedData;\n 'agent/retry': AgentRetryData;\n}\n\nexport type ReviewEventType = keyof ReviewEventDataMap;\n\nexport const REVIEW_EVENT_TYPES: readonly ReviewEventType[] = [\n 'review/created',\n 'round/created',\n 'comment/added',\n 'comment/replied',\n 'comment/state',\n 'comment/edited',\n 'comment/deleted',\n 'comment/anchor',\n 'suggestion/state',\n 'suggestion/applied',\n 'fix/claim',\n 'finding/decision',\n 'review/updated',\n 'review/deleted',\n 'review/closed',\n 'review/submitted',\n 'agent/started',\n 'agent/coverage',\n 'agent/shard',\n 'agent/finding',\n 'agent/report',\n 'agent/failed',\n 'agent/retry',\n];\n\nexport interface ReviewEventBase<T extends ReviewEventType = ReviewEventType> {\n v: 1;\n id: string;\n /** 1-based append position in the review's JSONL log. Older logs are backfilled on read. */\n seq?: number;\n reviewId: ReviewId;\n type: T;\n at: string;\n actor: Actor;\n data: ReviewEventDataMap[T];\n}\n\nexport type ReviewEvent = {\n [T in ReviewEventType]: ReviewEventBase<T>;\n}[ReviewEventType];\n\nexport interface CreateEventInput<T extends ReviewEventType> {\n reviewId: ReviewId;\n type: T;\n actor: Actor;\n data: ReviewEventDataMap[T];\n now?: () => Date;\n newId?: (prefix: IdPrefix) => string;\n}\n\nexport type ReviewEventErrorCode =\n 'unknown-type' | 'invalid-actor' | 'invalid-review-id' | 'invalid-event' | 'invalid-id';\n\nexport class ReviewEventError extends Error {\n readonly code: ReviewEventErrorCode;\n\n constructor(code: ReviewEventErrorCode, message: string) {\n super(message);\n this.name = 'ReviewEventError';\n this.code = code;\n }\n}\n\nconst ACTOR_KINDS = new Set<ActorKind>(['human', 'agent', 'system']);\nconst EVENT_TYPE_SET = new Set<string>(REVIEW_EVENT_TYPES);\n\nexport function isReviewEventType(value: unknown): value is ReviewEventType {\n return typeof value === 'string' && EVENT_TYPE_SET.has(value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport function isActor(value: unknown): value is Actor {\n if (!isRecord(value)) return false;\n return (\n typeof value.name === 'string' &&\n value.name.trim().length > 0 &&\n typeof value.kind === 'string' &&\n ACTOR_KINDS.has(value.kind as ActorKind)\n );\n}\n\nfunction isIsoTimestamp(value: unknown): value is string {\n if (typeof value !== 'string') return false;\n const parsed = new Date(value);\n return Number.isFinite(parsed.getTime()) && parsed.toISOString() === value;\n}\n\nfunction isEventId(value: unknown): value is string {\n return typeof value === 'string' && value.startsWith('evt_') && value.length > 4;\n}\n\nexport function createEvent<T extends ReviewEventType>(\n input: CreateEventInput<T>,\n): ReviewEventBase<T> {\n if (!isReviewEventType(input.type)) {\n throw new ReviewEventError('unknown-type', `unknown event type: ${String(input.type)}`);\n }\n if (!isActor(input.actor)) {\n throw new ReviewEventError('invalid-actor', 'event actor must have a non-empty name');\n }\n if (typeof input.reviewId !== 'string' || input.reviewId.trim() === '') {\n throw new ReviewEventError('invalid-review-id', 'event reviewId must be non-empty');\n }\n if (!isRecord(input.data)) {\n throw new ReviewEventError('invalid-event', 'event data must be an object');\n }\n\n const now = input.now ?? (() => new Date());\n const date = now();\n if (!(date instanceof Date) || !Number.isFinite(date.getTime())) {\n throw new ReviewEventError('invalid-event', 'event clock returned an invalid date');\n }\n\n const id = (input.newId ?? ((prefix: IdPrefix) => createId(prefix, now)))('evt');\n if (!isEventId(id)) {\n throw new ReviewEventError('invalid-id', 'event id must start with evt_');\n }\n\n return {\n v: 1,\n id,\n reviewId: input.reviewId,\n type: input.type,\n at: date.toISOString(),\n actor: input.actor,\n data: input.data,\n };\n}\n\nexport function isReviewEvent(value: unknown): value is ReviewEvent {\n if (!isRecord(value)) return false;\n if (value.v !== 1) return false;\n if (!isReviewEventType(value.type)) return false;\n if (!isEventId(value.id)) return false;\n if (typeof value.reviewId !== 'string' || value.reviewId.trim() === '') return false;\n if (!isIsoTimestamp(value.at)) return false;\n if (!isActor(value.actor)) return false;\n if (!isRecord(value.data)) return false;\n if (\n value.seq !== undefined &&\n (typeof value.seq !== 'number' || !Number.isInteger(value.seq) || value.seq < 1)\n ) {\n return false;\n }\n return true;\n}\n", "import { createHash } from 'node:crypto';\nimport { createId } from './ids.js';\nimport type { Anchor, AnchorPosition, Side } from './types.js';\nimport type { DiffHunk, FileDiff, Snapshot } from '../types.js';\n\nexport type AnchorErrorCode = 'missing-path' | 'missing-lines' | 'invalid-range' | 'invalid-round';\n\nexport class AnchorError extends Error {\n readonly code: AnchorErrorCode;\n\n constructor(code: AnchorErrorCode, message: string) {\n super(message);\n this.name = 'AnchorError';\n this.code = code;\n }\n}\n\nexport interface CaptureAnchorInput {\n path: string;\n side: Side;\n lineStart: number;\n lineEnd?: number;\n round: number;\n id?: string;\n}\n\nexport interface ReanchorOptions {\n round: number;\n id?: string;\n window?: number;\n /** When the old quote is gone, look for an applied suggestion replacement. */\n fallbackQuote?: string;\n}\n\nconst DEFAULT_WINDOW = 40;\nconst CONTEXT_LINES = 2;\n\ninterface Candidate {\n start: number;\n score: number;\n distance: number;\n}\n\nfunction normalizeLine(line: string): string {\n return line.replace(/\\r$/, '').replace(/[ \\t]+$/, '');\n}\n\n/**\n * Normalizes a quoted block for comparisons: LF line endings and no trailing\n * horizontal whitespace per line. Internal spacing and indentation are kept.\n */\nexport function normalizeQuote(quote: string): string {\n return quote.split('\\n').map(normalizeLine).join('\\n');\n}\n\nfunction normalizeQuoteLines(quote: string): string[] {\n return normalizeQuote(quote).split('\\n');\n}\n\nfunction hashQuote(quote: string): string {\n return createHash('sha256').update(quote, 'utf8').digest('hex');\n}\n\nfunction position(anchor: Anchor): AnchorPosition {\n return {\n round: anchor.round,\n path: anchor.path,\n lineStart: anchor.lineStart,\n lineEnd: anchor.lineEnd,\n };\n}\n\nfunction linesFor(file: FileDiff, side: Side): string[] | undefined {\n return side === 'new' ? file.newLines : file.oldLines;\n}\n\nfunction hunkHeaderFor(hunks: DiffHunk[], line: number, side: Side): string {\n for (const hunk of hunks) {\n const start = side === 'new' ? hunk.newStart : hunk.oldStart;\n const count = side === 'new' ? hunk.newLines : hunk.oldLines;\n if (count > 0 && line >= start && line < start + count) return hunk.header;\n }\n return '';\n}\n\nfunction contextBefore(lines: string[], lineStart: number): string[] {\n return lines.slice(Math.max(0, lineStart - 1 - CONTEXT_LINES), lineStart - 1);\n}\n\nfunction contextAfter(lines: string[], lineEnd: number): string[] {\n return lines.slice(lineEnd, lineEnd + CONTEXT_LINES);\n}\n\n/**\n * Captures a comment anchor against one side of a snapshot. Invalid input is a\n * caller error; re-anchoring missing content is not (see `reanchor`).\n */\nexport function captureAnchor(snapshot: Snapshot, input: CaptureAnchorInput): Anchor {\n if (!Number.isInteger(input.round) || input.round < 1) {\n throw new AnchorError('invalid-round', `round must be a positive integer: ${input.round}`);\n }\n const file = snapshot.files.find((candidate) => candidate.path === input.path);\n if (file === undefined) {\n throw new AnchorError('missing-path', `file is not present in the snapshot: ${input.path}`);\n }\n\n const lines = linesFor(file, input.side);\n if (lines === undefined || lines.length === 0) {\n if (file.truncated === true) {\n throw new AnchorError('missing-lines', `file content was truncated: ${input.path}`);\n }\n throw new AnchorError(\n 'missing-lines',\n `snapshot has no ${input.side} lines for: ${input.path}`,\n );\n }\n\n const lineEnd = input.lineEnd ?? input.lineStart;\n if (\n !Number.isInteger(input.lineStart) ||\n !Number.isInteger(lineEnd) ||\n input.lineStart < 1 ||\n lineEnd < input.lineStart ||\n lineEnd > lines.length\n ) {\n throw new AnchorError(\n 'invalid-range',\n `range ${input.lineStart}..${lineEnd} is outside 1..${lines.length}`,\n );\n }\n\n const quote = lines.slice(input.lineStart - 1, lineEnd).join('\\n');\n return {\n id: input.id ?? createId('anc'),\n round: input.round,\n path: input.path,\n side: input.side,\n lineStart: input.lineStart,\n lineEnd,\n quote,\n contextBefore: contextBefore(lines, input.lineStart),\n contextAfter: contextAfter(lines, lineEnd),\n hunkHeader: hunkHeaderFor(file.hunks, input.lineStart, input.side),\n contentHash: hashQuote(quote),\n state: 'active',\n };\n}\n\nfunction resolveFile(previous: Anchor, next: Snapshot): FileDiff | undefined {\n return (\n next.files.find((file) => file.path === previous.path) ??\n next.files.find((file) => file.oldPath === previous.path)\n );\n}\n\nfunction expectedOldLine(line: number, hunks: DiffHunk[]): number {\n let delta = 0;\n for (const hunk of hunks) {\n const oldEnd = hunk.oldStart + hunk.oldLines - 1;\n if (hunk.oldLines > 0 && line >= hunk.oldStart && line <= oldEnd) {\n return hunk.newStart + (line - hunk.oldStart);\n }\n if (hunk.oldStart + hunk.oldLines <= line) {\n delta += hunk.newLines - hunk.oldLines;\n }\n }\n return line + delta;\n}\n\nfunction contextMatches(\n lines: string[],\n context: string[],\n start: number,\n quoteLength: number,\n direction: 'before' | 'after',\n): boolean {\n if (context.length === 0) return false;\n for (let index = 0; index < context.length; index += 1) {\n const lineIndex =\n direction === 'before'\n ? start - 2 - (context.length - 1 - index)\n : start + quoteLength - 1 + index;\n const line = lines[lineIndex];\n if (line === undefined || normalizeLine(line) !== normalizeLine(context[index] ?? '')) {\n return false;\n }\n }\n return true;\n}\n\ninterface FoundCandidate extends Candidate {\n tied: boolean;\n}\n\nfunction findCandidate(\n lines: string[],\n quoteLines: string[],\n expected: number,\n window: number,\n previous: Anchor,\n): FoundCandidate | undefined {\n const maxStart = lines.length - quoteLines.length + 1;\n const from = Math.max(1, expected - window);\n const to = Math.min(maxStart, expected + window);\n let best: Candidate | undefined;\n let tied = false;\n\n for (let start = from; start <= to; start += 1) {\n let matches = true;\n for (let offset = 0; offset < quoteLines.length; offset += 1) {\n const line = lines[start - 1 + offset];\n if (line === undefined || normalizeLine(line) !== quoteLines[offset]) {\n matches = false;\n break;\n }\n }\n if (!matches) continue;\n\n const distance = Math.abs(start - expected);\n const score =\n 3 +\n (contextMatches(lines, previous.contextBefore, start, quoteLines.length, 'before') ? 1 : 0) +\n (contextMatches(lines, previous.contextAfter, start, quoteLines.length, 'after') ? 1 : 0) +\n Math.max(0, 1 - distance / (window + 1));\n if (\n best === undefined ||\n score > best.score ||\n (score === best.score && distance < best.distance)\n ) {\n best = { start, score, distance };\n tied = false;\n } else if (score === best.score && distance === best.distance) {\n tied = true;\n }\n }\n\n return best === undefined ? undefined : { ...best, tied };\n}\n\nfunction outdated(previous: Anchor, file: FileDiff | undefined, options: ReanchorOptions): Anchor {\n return {\n id: options.id ?? createId('anc'),\n round: options.round,\n path: file?.path ?? previous.path,\n side: previous.side,\n lineStart: previous.lineStart,\n lineEnd: previous.lineEnd,\n quote: previous.quote,\n contextBefore: [...previous.contextBefore],\n contextAfter: [...previous.contextAfter],\n hunkHeader: previous.hunkHeader,\n contentHash: previous.contentHash,\n state: 'outdated',\n previous: position(previous),\n };\n}\n\n/**\n * Re-anchors a comment against the next round's snapshot. A missing file,\n * missing side or an absent quote degrades to `outdated`; this function never\n * throws for content-level problems.\n */\nexport function reanchor(previous: Anchor, next: Snapshot, options: ReanchorOptions): Anchor {\n const file = resolveFile(previous, next);\n if (file === undefined) return outdated(previous, undefined, options);\n\n // Re-anchoring always searches the post-change side: old-side anchors are\n // mapped through hunks into new line numbers before the search.\n const lines = file.newLines;\n if (lines === undefined || lines.length === 0) return outdated(previous, file, options);\n\n const quoteLines = normalizeQuoteLines(previous.quote);\n if (quoteLines.length === 0 || lines.length < quoteLines.length) {\n return outdated(previous, file, options);\n }\n\n const expectedRaw =\n previous.side === 'old' ? expectedOldLine(previous.lineStart, file.hunks) : previous.lineStart;\n const expected = Math.max(1, expectedRaw);\n const window = Number.isFinite(options.window)\n ? Math.max(0, Math.trunc(options.window as number))\n : DEFAULT_WINDOW;\n\n let quote = previous.quote;\n let best = findCandidate(lines, quoteLines, expected, window, previous);\n if (best === undefined && options.fallbackQuote !== undefined) {\n const fallbackLines = normalizeQuoteLines(options.fallbackQuote);\n if (fallbackLines.length > 0 && lines.length >= fallbackLines.length) {\n best = findCandidate(lines, fallbackLines, expected, window, previous);\n if (best !== undefined) quote = options.fallbackQuote;\n }\n }\n\n if (best === undefined) return outdated(previous, file, options);\n\n const quoteLinesForAnchor = normalizeQuoteLines(quote);\n const lineStart = best.start;\n const lineEnd = lineStart + quoteLinesForAnchor.length - 1;\n return {\n id: options.id ?? createId('anc'),\n round: options.round,\n path: file.path,\n side: previous.side,\n lineStart,\n lineEnd,\n quote,\n contextBefore: contextBefore(lines, lineStart),\n contextAfter: contextAfter(lines, lineEnd),\n hunkHeader: hunkHeaderFor(file.hunks, lineStart, 'new'),\n contentHash: hashQuote(quote),\n state: best.tied ? 'ambiguous' : 'active',\n previous: position(previous),\n };\n}\n", "import type { ManifestFile, ManifestFileReason, ReviewManifest } from '../types.js';\nimport type { CoverageStatus, CoverageTotals, FileCoverage, ReviewCoverage } from './types.js';\n\nexport const COVERAGE_STATUSES: readonly CoverageStatus[] = Object.freeze([\n 'pending',\n 'deep-reviewed',\n 'light-reviewed',\n 'manifest-only',\n 'skipped',\n 'no-hunks',\n 'deferred',\n 'failed',\n]);\n\n/** Statuses that mean work is still owed before a round can be `done`. */\nconst UNRESOLVED_STATUSES = new Set<CoverageStatus>(['pending', 'skipped', 'deferred', 'failed']);\n\n/** Manifest reasons where policy, not the render budget, excluded the content. */\nconst POLICY_REASONS = new Set<ManifestFileReason>(['binary', 'ignored', 'generated']);\n\n/** Manifest reasons that explain why a non-policy file was not reviewed. */\nconst SKIP_REASONS = new Set<ManifestFileReason>([\n 'render-budget',\n 'per-file-cap',\n 'diff-truncated',\n 'unreadable',\n 'legacy-truncated',\n 'symlink',\n]);\n\n/** Warnings that prove the manifest's changed-path listing itself was cut. */\nconst INCOMPLETE_MANIFEST_WARNINGS = new Set([\n 'manifest-listing-truncated',\n 'untracked-list-truncated',\n 'manifest-missing',\n]);\n\n/**\n * Counts file coverage by status without mutating the ledger. `files` counts\n * every ledger entry; unknown persisted statuses are excluded from `byStatus`\n * rather than creating a NaN bucket.\n */\nexport function summarizeCoverage(files: readonly FileCoverage[]): CoverageTotals {\n const byStatus = Object.fromEntries(COVERAGE_STATUSES.map((status) => [status, 0])) as Record<\n CoverageStatus,\n number\n >;\n const known = new Set<string>(COVERAGE_STATUSES);\n for (const file of files) {\n if (!known.has(file.status)) continue;\n byStatus[file.status] += 1;\n }\n return { files: files.length, byStatus };\n}\n\n/**\n * Seeds a coverage ledger from the manifest: every changed file starts as\n * pending so no manifest path can be silently absent from coverage.\n */\nexport function initialCoverage(manifest: ReviewManifest): ReviewCoverage {\n const files: FileCoverage[] = manifest.files.map((file) => ({\n path: file.path,\n status: 'pending',\n }));\n return { files, totals: summarizeCoverage(files) };\n}\n\nfunction policyReason(file: ManifestFile): ManifestFileReason | undefined {\n if (file.reason !== undefined && POLICY_REASONS.has(file.reason)) return file.reason;\n if (file.ignored) return 'ignored';\n if (file.binary) return 'binary';\n return undefined;\n}\n\nfunction skipReason(file: ManifestFile): ManifestFileReason {\n if (file.reason !== undefined && SKIP_REASONS.has(file.reason)) return file.reason;\n return 'render-budget';\n}\n\n/**\n * Builds the R1 coverage bridge from the complete manifest and the paths whose\n * file header made it into the prompt. Policy-excluded content is explicitly\n * `manifest-only`; an included file with a reviewable hunk is `pending` and may\n * at most become `light-reviewed` after the report. A file with no content\n * change (pure rename, mode-only, empty file, or an untracked symlink whose\n * target is deliberately not followed) is terminal `no-hunks`, because there\n * is nothing to inspect and it was not dropped by a budget. Everything else is\n * `skipped` with the manifest reason (or `render-budget` when the prompt\n * dropped it). This never mutates the manifest.\n */\nexport function coverageFromPrompt(\n manifest: ReviewManifest,\n includedPaths: readonly string[],\n): ReviewCoverage {\n const included = new Set(includedPaths);\n const files = manifest.files.map((file): FileCoverage => {\n const policy = policyReason(file);\n if (policy !== undefined) {\n return { path: file.path, status: 'manifest-only', reason: policy };\n }\n if (\n file.reason === 'symlink' &&\n file.hunkCount === 0 &&\n file.added === 0 &&\n file.deleted === 0\n ) {\n return { path: file.path, status: 'no-hunks' };\n }\n if (included.has(file.path)) {\n if (file.hunkCount > 0) return { path: file.path, status: 'pending' };\n if (file.reason === undefined && file.added === 0 && file.deleted === 0) {\n return { path: file.path, status: 'no-hunks' };\n }\n }\n return { path: file.path, status: 'skipped', reason: skipReason(file) };\n });\n const incomplete = manifest.warnings.some((warning) => INCOMPLETE_MANIFEST_WARNINGS.has(warning));\n return {\n files,\n totals: summarizeCoverage(files),\n ...(incomplete ? { incomplete: true } : {}),\n };\n}\n\n/**\n * A round is complete only when every ledger file has a final reviewed or\n * policy-excluded status. Unknown persisted statuses and inconsistent totals\n * are treated as incomplete: they prove the ledger cannot be trusted.\n */\nexport function isCoverageComplete(coverage: ReviewCoverage): boolean {\n if (coverage.incomplete === true) return false;\n const computed = summarizeCoverage(coverage.files);\n const knownCount = COVERAGE_STATUSES.reduce((sum, status) => sum + computed.byStatus[status], 0);\n if (knownCount !== coverage.files.length) return false;\n if (coverage.totals.files !== coverage.files.length) return false;\n for (const status of COVERAGE_STATUSES) {\n if ((coverage.totals.byStatus[status] ?? 0) !== computed.byStatus[status]) return false;\n }\n const persistedCount = COVERAGE_STATUSES.reduce(\n (sum, status) => sum + (coverage.totals.byStatus[status] ?? 0),\n 0,\n );\n if (persistedCount !== coverage.files.length) return false;\n return coverage.files.every((file) => {\n if (UNRESOLVED_STATUSES.has(file.status)) return false;\n if (file.status !== 'manifest-only') return true;\n return file.reason !== undefined && POLICY_REASONS.has(file.reason as ManifestFileReason);\n });\n}\n\n/**\n * Promotes pending files to light-reviewed after an accepted report. The\n * returned ledger and its file entries are new objects; the input is not\n * mutated. Totals are always recomputed from the resulting files.\n */\nexport function promotePendingToLight(coverage: ReviewCoverage): ReviewCoverage {\n const files = coverage.files.map((file): FileCoverage =>\n file.status === 'pending' ? { ...file, status: 'light-reviewed' } : { ...file },\n );\n return {\n files,\n totals: summarizeCoverage(files),\n ...(coverage.incomplete === true ? { incomplete: true } : {}),\n };\n}\n", "import type { ManifestFile, ReviewManifest } from '../types.js';\nimport type { FileCoverage, ReviewCoverage } from './types.js';\nimport { summarizeCoverage } from './coverage.js';\n\nexport type ReviewTier = 'deep' | 'light' | 'manifest-only';\nexport type FileKind =\n | 'source'\n | 'test'\n | 'docs'\n | 'config'\n | 'migration'\n | 'generated'\n | 'binary'\n | 'instructions'\n | 'other';\n\nexport interface ModuleRoot {\n id: string;\n root: string;\n name?: string;\n}\n\nexport interface ModuleInfo extends ModuleRoot {\n source: 'workspace' | 'convention' | 'root';\n}\n\nexport interface ModuleMap {\n modules: ModuleInfo[];\n moduleFor(path: string): string;\n}\n\nconst WORKSPACE_CONTAINERS = new Set([\n 'packages',\n 'apps',\n 'services',\n 'libs',\n 'modules',\n 'plugins',\n]);\n\nconst CONVENTION_ROOTS = new Set([\n 'src',\n 'app',\n 'backend',\n 'frontend',\n 'server',\n 'client',\n 'ui',\n 'web',\n 'api',\n 'docs',\n 'tests',\n 'test',\n 'e2e',\n 'ui-tests',\n 'migrations',\n 'config',\n 'scripts',\n 'tools',\n]);\n\nconst INSTRUCTION_FILES = new Set([\n 'AGENTS.md',\n 'CLAUDE.md',\n 'GEMINI.md',\n '.cursorrules',\n '.github/copilot-instructions.md',\n]);\n\nconst DOC_FILES = new Set([\n 'README.md',\n 'CHANGELOG.md',\n 'ARCHITECTURE.md',\n 'BACKEND_SPEC.md',\n 'CONTRIBUTING.md',\n 'SECURITY.md',\n 'LICENSE.md',\n]);\n\nconst CONFIG_FILES = new Set([\n 'package.json',\n 'pnpm-workspace.yaml',\n 'pnpm-lock.yaml',\n 'package-lock.json',\n 'yarn.lock',\n 'uv.lock',\n 'poetry.lock',\n 'Cargo.lock',\n 'go.sum',\n 'tsconfig.json',\n 'pyproject.toml',\n 'requirements.txt',\n 'go.mod',\n 'Cargo.toml',\n 'pom.xml',\n 'Makefile',\n 'Dockerfile',\n 'docker-compose.yml',\n 'docker-compose.yaml',\n]);\n\nconst SOURCE_EXTENSIONS = new Set([\n '.ts',\n '.tsx',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n '.py',\n '.go',\n '.rs',\n '.java',\n '.kt',\n '.kts',\n '.swift',\n '.c',\n '.cc',\n '.cpp',\n '.h',\n '.hpp',\n '.rb',\n '.php',\n '.cs',\n '.sh',\n '.bash',\n '.zsh',\n '.sql',\n]);\n\nconst DOC_EXTENSIONS = new Set(['.md', '.mdx', '.rst', '.adoc']);\nconst GENERATED_DIRS = new Set([\n 'dist',\n 'build',\n 'coverage',\n 'node_modules',\n '.next',\n 'out',\n 'target',\n '.turbo',\n '.cache',\n]);\n\nfunction basename(path: string): string {\n const parts = path.split('/');\n return parts.at(-1) ?? path;\n}\n\nfunction extension(path: string): string {\n const name = basename(path);\n const dot = name.lastIndexOf('.');\n return dot <= 0 ? '' : name.slice(dot).toLowerCase();\n}\n\nfunction normalizeRoot(root: string): string {\n const normalized = root.replace(/\\\\/g, '/').replace(/^\\/+|\\/+$/g, '');\n return normalized === '' ? '.' : normalized;\n}\n\nfunction isUnder(path: string, root: string): boolean {\n if (root === '.') return true;\n return path === root || path.startsWith(`${root}/`);\n}\n\nfunction conventionRoot(path: string): string {\n const parts = path.split('/');\n if (parts.length === 1) return '.';\n const first = parts[0];\n if (first === undefined) return '.';\n if (WORKSPACE_CONTAINERS.has(first) && parts.length > 2) {\n return `${first}/${parts[1] ?? ''}`;\n }\n if (CONVENTION_ROOTS.has(first)) return first;\n return first;\n}\n\n/**\n * Builds a deterministic path-to-module map. Explicit workspace roots win over\n * convention roots for the same directory; the longest matching root wins for\n * a path. Root-level files belong to the synthetic `.` module.\n */\nexport function buildModuleMap(\n files: readonly ManifestFile[],\n roots: readonly ModuleRoot[] = [],\n): ModuleMap {\n const byRoot = new Map<string, ModuleInfo>();\n const add = (root: string, source: ModuleInfo['source'], info?: ModuleRoot): void => {\n const normalized = normalizeRoot(root);\n if (normalized === '.' && source !== 'root') return;\n const existing = byRoot.get(normalized);\n if (existing !== undefined && !(source === 'workspace' && existing.source === 'convention')) {\n return;\n }\n if (existing !== undefined && source === 'workspace') {\n byRoot.set(normalized, {\n id: info?.id ?? existing.id,\n root: normalized,\n ...(info?.name === undefined && existing.name === undefined\n ? {}\n : { name: info?.name ?? existing.name }),\n source,\n });\n return;\n }\n byRoot.set(normalized, {\n id: info?.id ?? normalized,\n root: normalized,\n ...(info?.name === undefined ? {} : { name: info.name }),\n source,\n });\n };\n\n for (const root of roots) {\n add(root.root, 'workspace', root);\n }\n for (const path of files.map((file) => file.path)) {\n add(conventionRoot(path), 'convention');\n }\n add('.', 'root');\n\n const modules = [...byRoot.values()].sort((left, right) => {\n if (left.id < right.id) return -1;\n if (left.id > right.id) return 1;\n return 0;\n });\n const orderedByRoot = [...modules].sort((left, right) => right.root.length - left.root.length);\n\n return {\n modules,\n moduleFor(path: string): string {\n for (const module of orderedByRoot) {\n if (isUnder(path, module.root)) return module.id;\n }\n return '.';\n },\n };\n}\n\nfunction isGenerated(file: ManifestFile): boolean {\n if (file.reason === 'generated') return true;\n const name = basename(file.path);\n if (\n name === 'pnpm-lock.yaml' ||\n name === 'package-lock.json' ||\n name === 'yarn.lock' ||\n name === 'uv.lock' ||\n name === 'poetry.lock' ||\n name === 'Cargo.lock' ||\n name === 'go.sum'\n ) {\n return true;\n }\n if (/(\\.min\\.|\\.generated\\.)/.test(name)) return true;\n return file.path.split('/').some((part) => GENERATED_DIRS.has(part));\n}\n\nfunction isInstructions(path: string): boolean {\n return INSTRUCTION_FILES.has(path) || path.startsWith('.dsh/');\n}\n\nfunction isMigration(path: string): boolean {\n if (extension(path) === '.sql') return true;\n return /(^|\\/)(migrations?|alembic|migrate)\\//.test(path);\n}\n\nfunction isTest(path: string): boolean {\n if (/(^|\\/)(test|tests|__tests__|e2e|ui-tests|spec|specs)\\//.test(path)) return true;\n return /\\.(test|spec)\\.[^/]+$/.test(path);\n}\n\nfunction isDocs(path: string): boolean {\n if (path.startsWith('docs/')) return true;\n if (DOC_FILES.has(basename(path))) return true;\n return DOC_EXTENSIONS.has(extension(path));\n}\n\nfunction isConfig(path: string): boolean {\n const name = basename(path);\n if (CONFIG_FILES.has(name)) return true;\n if (path.startsWith('.github/')) return true;\n if (\n /^(tsconfig|vite|vitest|eslint|prettier|playwright|jest|rollup|webpack).*\\.(json|js|mjs|cjs|ts)$/.test(\n name,\n )\n ) {\n return true;\n }\n if (/^\\.env(\\..*)?$/.test(name)) return true;\n return extension(path) === '.yml' || extension(path) === '.yaml' || extension(path) === '.toml';\n}\n\nfunction isSource(path: string): boolean {\n return SOURCE_EXTENSIONS.has(extension(path));\n}\n\n/**\n * Classifies a changed path by kind. Manifest policy (`generated`) and binary\n * metadata take priority over the path shape; `ignored` alone does not change\n * the kind because ignore policy is applied by the tier planner.\n */\nexport function classifyFile(file: ManifestFile): FileKind {\n if (isInstructions(file.path)) return 'instructions';\n if (file.binary) return 'binary';\n if (isGenerated(file)) return 'generated';\n if (isMigration(file.path)) return 'migration';\n if (isTest(file.path)) return 'test';\n if (isDocs(file.path)) return 'docs';\n if (isConfig(file.path)) return 'config';\n if (isSource(file.path)) return 'source';\n return 'other';\n}\n\n/**\n * User-facing docs are deep-reviewed because they can change behavior or\n * contracts. Internal notes are still docs, but light.\n */\nexport function isUserFacingDoc(path: string): boolean {\n if (path.startsWith('docs/internal/')) return false;\n if (path.startsWith('docs/')) return true;\n const name = basename(path);\n return DOC_FILES.has(name) || /^README\\./i.test(name);\n}\n\nexport interface ShardLimits {\n maxFiles: number;\n maxPatchBytes: number;\n}\n\nexport const DEFAULT_SHARD_LIMITS: ShardLimits = Object.freeze({\n maxFiles: 12,\n maxPatchBytes: 120_000,\n});\n\nexport interface PlanFile {\n path: string;\n moduleId: string;\n kind: FileKind;\n tier: ReviewTier;\n shardId?: string;\n /** Policy reason for a manifest-only file; absent for reviewed files. */\n reason?: string;\n}\n\nexport interface ReviewShard {\n id: string;\n moduleId: string;\n tier: 'deep' | 'light';\n effort: 'deep' | 'light';\n paths: string[];\n fileCount: number;\n patchBytes: number;\n}\n\nexport interface ReviewPlan {\n schemaVersion: 1;\n files: PlanFile[];\n shards: ReviewShard[];\n coverage: ReviewCoverage;\n coveragePlan: {\n total: number;\n byTier: Record<ReviewTier, number>;\n };\n riskFlags: string[];\n limits: ShardLimits;\n}\n\nconst INCOMPLETE_MANIFEST_WARNINGS = new Set([\n 'manifest-listing-truncated',\n 'untracked-list-truncated',\n 'manifest-missing',\n]);\n\nfunction byteCompare(left: string, right: string): number {\n return Buffer.compare(Buffer.from(left, 'utf8'), Buffer.from(right, 'utf8'));\n}\n\nfunction isNoHunks(file: ManifestFile): boolean {\n return (\n file.reason === undefined &&\n !file.binary &&\n !file.ignored &&\n file.hunkCount === 0 &&\n file.added === 0 &&\n file.deleted === 0\n );\n}\n\nfunction policyReason(file: ManifestFile, kind: FileKind): string | undefined {\n if (file.reason !== undefined && ['generated', 'binary', 'ignored'].includes(file.reason)) {\n return file.reason;\n }\n if (file.ignored) return 'ignored';\n if (file.binary) return 'binary';\n if (kind === 'generated') return 'generated';\n return undefined;\n}\n\nfunction tierFor(file: ManifestFile, kind: FileKind, moduleHasSource: boolean): ReviewTier {\n if (kind === 'binary' || kind === 'generated' || file.ignored) return 'manifest-only';\n switch (kind) {\n case 'source':\n case 'config':\n case 'migration':\n case 'instructions':\n return 'deep';\n case 'test':\n return moduleHasSource ? 'deep' : 'light';\n case 'docs':\n return isUserFacingDoc(file.path) ? 'deep' : 'light';\n case 'other':\n return 'light';\n }\n}\n\nfunction riskFlags(input: {\n manifest: ReviewManifest;\n files: readonly PlanFile[];\n modules: number;\n}): string[] {\n const flags: string[] = [];\n const generated = input.files.filter((file) => file.tier === 'manifest-only').length;\n if (input.manifest.totals.files >= 100 || input.manifest.totals.patchBytes >= 1_000_000) {\n flags.push('large-diff');\n }\n if (input.files.length >= 10 && generated * 10 >= input.files.length) {\n flags.push('generated-heavy');\n }\n if (input.manifest.warnings.some((warning) => INCOMPLETE_MANIFEST_WARNINGS.has(warning))) {\n flags.push('manifest-incomplete');\n }\n if (\n input.files.some((file) => /(^|\\/)(auth|security|crypto|migrations?|config)\\//.test(file.path))\n ) {\n flags.push('security-sensitive');\n }\n if (!input.files.some((file) => file.tier === 'deep' && file.kind === 'source')) {\n flags.push('no-source');\n }\n if (input.modules > 8) flags.push('many-modules');\n return flags;\n}\n\n/**\n * Builds a pure, deterministic review plan. The planner never executes a\n * shard, calls a model, or marks work complete; every deep/light file starts\n * pending in the returned coverage ledger.\n */\nexport function buildReviewPlan(input: {\n manifest: ReviewManifest;\n moduleRoots?: readonly ModuleRoot[];\n limits?: Partial<ShardLimits>;\n}): ReviewPlan {\n const limits: ShardLimits = {\n maxFiles: Math.max(1, Math.trunc(input.limits?.maxFiles ?? DEFAULT_SHARD_LIMITS.maxFiles)),\n maxPatchBytes: Math.max(\n 1,\n Math.trunc(input.limits?.maxPatchBytes ?? DEFAULT_SHARD_LIMITS.maxPatchBytes),\n ),\n };\n const modules = buildModuleMap(input.manifest.files, input.moduleRoots);\n const kinds = new Map<string, FileKind>();\n for (const file of input.manifest.files) {\n kinds.set(file.path, classifyFile(file));\n }\n const sourceModules = new Set<string>();\n for (const file of input.manifest.files) {\n if (kinds.get(file.path) === 'source') sourceModules.add(modules.moduleFor(file.path));\n }\n\n const files: PlanFile[] = input.manifest.files.map((file) => {\n const kind = kinds.get(file.path) ?? 'other';\n const moduleId = modules.moduleFor(file.path);\n const tier = tierFor(file, kind, sourceModules.has(moduleId));\n const reason = tier === 'manifest-only' ? policyReason(file, kind) : undefined;\n return {\n path: file.path,\n moduleId,\n kind,\n tier,\n ...(reason === undefined ? {} : { reason }),\n };\n });\n const byPath = new Map(files.map((file) => [file.path, file]));\n\n const groups = new Map<string, PlanFile[]>();\n for (const file of files) {\n if (file.tier === 'manifest-only') continue;\n const manifestFile = input.manifest.files.find((item) => item.path === file.path);\n if (manifestFile === undefined || isNoHunks(manifestFile)) continue;\n const key = `${file.moduleId}\\0${file.tier}`;\n const group = groups.get(key) ?? [];\n group.push(file);\n groups.set(key, group);\n }\n\n const shards: ReviewShard[] = [];\n const keys = [...groups.keys()].sort(byteCompare);\n for (const key of keys) {\n const group = groups.get(key) ?? [];\n group.sort((left, right) => byteCompare(left.path, right.path));\n let current: PlanFile[] = [];\n let currentBytes = 0;\n const flush = (): void => {\n if (current.length === 0) return;\n const id = `shard_${String(shards.length + 1).padStart(3, '0')}`;\n const first = current[0];\n if (first === undefined) return;\n const shard: ReviewShard = {\n id,\n moduleId: first.moduleId,\n tier: first.tier === 'deep' ? 'deep' : 'light',\n effort: first.tier === 'deep' ? 'deep' : 'light',\n paths: current.map((file) => file.path),\n fileCount: current.length,\n patchBytes: currentBytes,\n };\n shards.push(shard);\n for (const file of current) file.shardId = id;\n current = [];\n currentBytes = 0;\n };\n for (const file of group) {\n const manifestFile = input.manifest.files.find((item) => item.path === file.path);\n const bytes = manifestFile?.patchBytes ?? 0;\n if (\n current.length > 0 &&\n (current.length >= limits.maxFiles || currentBytes + bytes > limits.maxPatchBytes)\n ) {\n flush();\n }\n current.push(file);\n currentBytes += bytes;\n }\n flush();\n }\n\n const coverageFiles: FileCoverage[] = input.manifest.files.map((manifestFile) => {\n const planFile = byPath.get(manifestFile.path);\n if (planFile === undefined) {\n return { path: manifestFile.path, status: 'skipped', reason: 'render-budget' };\n }\n if (planFile.tier === 'manifest-only') {\n return {\n path: planFile.path,\n status: 'manifest-only',\n ...(planFile.reason === undefined ? {} : { reason: planFile.reason }),\n };\n }\n if (isNoHunks(manifestFile)) {\n return { path: planFile.path, status: 'no-hunks' };\n }\n if (planFile.shardId !== undefined) {\n return { path: planFile.path, status: 'pending', shardId: planFile.shardId };\n }\n return { path: planFile.path, status: 'skipped', reason: 'render-budget' };\n });\n const coverage: ReviewCoverage = {\n files: coverageFiles,\n totals: summarizeCoverage(coverageFiles),\n ...(input.manifest.warnings.some((warning) => INCOMPLETE_MANIFEST_WARNINGS.has(warning))\n ? { incomplete: true }\n : {}),\n };\n\n const byTier: Record<ReviewTier, number> = {\n deep: files.filter((file) => file.tier === 'deep').length,\n light: files.filter((file) => file.tier === 'light').length,\n 'manifest-only': files.filter((file) => file.tier === 'manifest-only').length,\n };\n return {\n schemaVersion: 1,\n files,\n shards,\n coverage,\n coveragePlan: { total: files.length, byTier },\n riskFlags: riskFlags({\n manifest: input.manifest,\n files,\n modules: modules.modules.length,\n }),\n limits,\n };\n}\n\n/** Returns a detached copy of the plan's coverage ledger for event persistence. */\nexport function coverageFromPlan(plan: ReviewPlan): ReviewCoverage {\n return {\n files: plan.coverage.files.map((file) => ({ ...file })),\n totals: summarizeCoverage(plan.coverage.files),\n ...(plan.coverage.incomplete === true ? { incomplete: true } : {}),\n };\n}\n", "import type {\n AgentReport,\n Finding,\n ReviewQuestion,\n RiskLevel,\n TestCommand,\n Verification,\n} from '../reviewer/types.js';\nimport type { ReviewPlan } from './plan.js';\nimport { coverageFromPlan } from './plan.js';\nimport { summarizeCoverage } from './coverage.js';\nimport type { FileCoverage, ReviewCoverage, ReviewId, RoundNo } from './types.js';\nimport type { ReviewerBackendKind } from '../reviewer/types.js';\n\nconst RISK_ORDER: Record<RiskLevel, number> = {\n low: 0,\n medium: 1,\n high: 2,\n critical: 3,\n};\n\nexport interface ShardReportInput {\n shardId: string;\n report: AgentReport;\n}\n\nexport interface AggregateShardReportsInput {\n reviewId: ReviewId;\n round: RoundNo;\n backend: ReviewerBackendKind;\n plan: ReviewPlan;\n reports: readonly ShardReportInput[];\n /** Shards known to have failed; missing shards are failed automatically. */\n failedShards?: readonly string[];\n}\n\nexport interface AggregateShardReportsResult {\n report: AgentReport;\n coverage: ReviewCoverage;\n}\n\nfunction findingKey(finding: Finding): string {\n return `${finding.file}\\0${finding.lineStart}\\0${finding.lineEnd}\\0${finding.title}`;\n}\n\nfunction questionKey(question: ReviewQuestion): string {\n return `${question.file}\\0${question.line}\\0${question.question}`;\n}\n\nfunction mergeFindings(reports: readonly ShardReportInput[]): Finding[] {\n const findings: Finding[] = [];\n const seen = new Set<string>();\n for (const report of reports) {\n for (const finding of report.report.findings) {\n const key = findingKey(finding);\n if (seen.has(key)) continue;\n seen.add(key);\n findings.push({ ...finding });\n }\n }\n return findings;\n}\n\nfunction mergeQuestions(reports: readonly ShardReportInput[]): ReviewQuestion[] {\n const questions: ReviewQuestion[] = [];\n const seen = new Set<string>();\n for (const report of reports) {\n for (const question of report.report.questions) {\n const key = questionKey(question);\n if (seen.has(key)) continue;\n seen.add(key);\n questions.push({ ...question });\n }\n }\n return questions;\n}\n\nfunction mergeTests(reports: readonly ShardReportInput[]): AgentReport['tests'] {\n const commands: TestCommand[] = [];\n const seen = new Set<string>();\n for (const report of reports) {\n for (const command of report.report.tests.commands) {\n const key = `${command.command}\\0${command.result}\\0${command.summary}`;\n if (seen.has(key)) continue;\n seen.add(key);\n commands.push({ ...command });\n }\n }\n return { ran: reports.some((report) => report.report.tests.ran), commands };\n}\n\nfunction mergeVerification(reports: readonly ShardReportInput[]): Verification[] {\n const entries: Verification[] = [];\n const seen = new Set<string>();\n for (const report of reports) {\n for (const item of report.report.verification) {\n const key = `${item.commentId}\\0${item.status}\\0${item.evidence}`;\n if (seen.has(key)) continue;\n seen.add(key);\n entries.push({ ...item });\n }\n }\n return entries;\n}\n\nfunction highestRisk(reports: readonly ShardReportInput[]): RiskLevel {\n let result: RiskLevel = 'low';\n for (const report of reports) {\n if (RISK_ORDER[report.report.riskLevel] > RISK_ORDER[result]) {\n result = report.report.riskLevel;\n }\n }\n return result;\n}\n\nfunction updateCoverage(\n plan: ReviewPlan,\n reports: readonly ShardReportInput[],\n failed: ReadonlySet<string>,\n): ReviewCoverage {\n const base = coverageFromPlan(plan);\n const byShard = new Map(reports.map((report) => [report.shardId, report]));\n const files: FileCoverage[] = base.files.map((file) => {\n const planFile = plan.files.find((item) => item.path === file.path);\n const shardId = planFile?.shardId;\n if (shardId === undefined) return { ...file };\n if (failed.has(shardId)) {\n return { ...file, status: 'failed', reason: 'shard-failed' };\n }\n const shard = plan.shards.find((item) => item.id === shardId);\n if (shard === undefined || !byShard.has(shardId)) {\n return { ...file, status: 'failed', reason: 'shard-failed' };\n }\n const status = shard.tier === 'deep' ? 'deep-reviewed' : 'light-reviewed';\n const next: FileCoverage = { ...file, status };\n delete next.reason;\n return next;\n });\n return {\n files,\n totals: summarizeCoverage(files),\n ...(base.incomplete === true ? { incomplete: true } : {}),\n };\n}\n\nexport interface MergeShardReportsInput {\n reviewId: ReviewId;\n round: RoundNo;\n backend: ReviewerBackendKind;\n /**\n * Reports in display order. Callers that have a plan must sort by plan order;\n * live previews sort by shard index before calling this helper.\n */\n reports: readonly ShardReportInput[];\n}\n\n/**\n * Merges completed shard reports without another model call or coverage\n * assumptions. Missing shards are intentionally ignored: this is the live\n * preview path while a round is still running. Final aggregation, which also\n * computes coverage and fails missing shards, uses this helper after ordering\n * reports by the plan.\n */\nexport function mergeShardReports(input: MergeShardReportsInput): AgentReport {\n const findings = mergeFindings(input.reports);\n const summaryParts = input.reports\n .map((report) => report.report.summary.trim())\n .filter((summary) => summary !== '');\n const summary =\n summaryParts.length === 0\n ? 'The review did not produce a shard report.'\n : summaryParts.join('\\n\\n').slice(0, 20_000);\n return {\n schemaVersion: 1,\n summary,\n riskLevel: highestRisk(input.reports),\n findings,\n questions: mergeQuestions(input.reports),\n tests: mergeTests(input.reports),\n verification: mergeVerification(input.reports),\n reviewId: input.reviewId,\n round: input.round,\n backend: input.backend,\n rejected: input.reports.flatMap((item) => item.report.rejected),\n warnings: [...new Set(input.reports.flatMap((report) => report.report.warnings))],\n ...(input.reports.some((item) => item.report.dirtyWorktree === true)\n ? { dirtyWorktree: true }\n : {}),\n skipped: false,\n };\n}\n\n/**\n * Merges shard reports without another model call. Deterministic: reports are\n * ordered by the review plan (not shard completion order), findings dedupe by\n * file/range/title, coverage is derived from the plan and the completed shards.\n * Missing shards are failed, never silently reviewed.\n */\nexport function aggregateShardReports(\n input: AggregateShardReportsInput,\n): AggregateShardReportsResult {\n const failed = new Set(input.failedShards ?? []);\n for (const shard of input.plan.shards) {\n if (!input.reports.some((report) => report.shardId === shard.id)) failed.add(shard.id);\n }\n const shardOrder = new Map(input.plan.shards.map((shard, index) => [shard.id, index]));\n const rank = (shardId: string): number => shardOrder.get(shardId) ?? input.plan.shards.length;\n const reports = [...input.reports].sort(\n (left, right) => rank(left.shardId) - rank(right.shardId),\n );\n const report = mergeShardReports({\n reviewId: input.reviewId,\n round: input.round,\n backend: input.backend,\n reports,\n });\n for (const shardId of [...failed].sort()) {\n report.warnings.push(`shard-failed:${shardId}`);\n }\n return { report, coverage: updateCoverage(input.plan, reports, failed) };\n}\n", "import { normalizeQuote } from './anchors.js';\nimport type { Anchor, Outcome, Suggestion } from './types.js';\nimport type { FileDiff, Snapshot } from '../types.js';\n\nfunction findFile(anchor: Anchor, snapshot: Snapshot): FileDiff | undefined {\n return (\n snapshot.files.find((file) => file.path === anchor.path) ??\n snapshot.files.find((file) => file.oldPath === anchor.path)\n );\n}\n\nfunction contentAt(anchor: Anchor, file: FileDiff): string | null {\n const lines = file.newLines;\n if (lines === undefined || file.truncated === true) return null;\n if (\n !Number.isInteger(anchor.lineStart) ||\n !Number.isInteger(anchor.lineEnd) ||\n anchor.lineStart < 1 ||\n anchor.lineEnd < anchor.lineStart ||\n anchor.lineEnd > lines.length\n ) {\n return null;\n }\n return normalizeQuote(lines.slice(anchor.lineStart - 1, anchor.lineEnd).join('\\n'));\n}\n\nfunction containsBlock(lines: string[] | undefined, block: string): boolean {\n if (lines === undefined || block === '') return false;\n const wanted = normalizeQuote(block).split('\\n');\n if (wanted.length === 0) return false;\n for (let start = 0; start + wanted.length <= lines.length; start += 1) {\n let matches = true;\n for (let offset = 0; offset < wanted.length; offset += 1) {\n const line = lines[start + offset];\n if (line === undefined || normalizeQuote(line) !== wanted[offset]) {\n matches = false;\n break;\n }\n }\n if (matches) return true;\n }\n return false;\n}\n\n/**\n * Derives the deterministic \u201Cfixed / not fixed\u201D guess for one re-anchored\n * comment. This is intentionally a pure, no-LLM signal: the reviewer's\n * verification and the agent's fix/claim are separate inputs in later rounds.\n */\nexport function deriveOutcome(\n previous: Anchor,\n next: Anchor,\n nextSnapshot: Snapshot,\n suggestion?: Suggestion,\n): Outcome {\n const file = findFile(next, nextSnapshot);\n const content = file === undefined ? null : contentAt(next, file);\n if (next.state === 'outdated' || file === undefined || content === null) {\n return { round: next.round, status: 'outdated', confidence: 'high' };\n }\n\n const previousQuote = normalizeQuote(previous.quote);\n const nextQuote = normalizeQuote(next.quote);\n\n if (\n suggestion !== undefined &&\n normalizeQuote(suggestion.original) === previousQuote &&\n content === normalizeQuote(suggestion.replacement) &&\n content !== previousQuote\n ) {\n return { round: next.round, status: 'applied', confidence: 'high' };\n }\n\n if (nextQuote === previousQuote) {\n if (\n next.lineStart === previous.lineStart &&\n next.lineEnd === previous.lineEnd &&\n next.path === previous.path\n ) {\n return { round: next.round, status: 'unchanged', confidence: 'high' };\n }\n return { round: next.round, status: 'moved', confidence: 'high' };\n }\n\n if (next.state === 'active' || next.state === 'ambiguous') {\n const confidence =\n suggestion !== undefined && containsBlock(file.newLines, suggestion.replacement)\n ? 'high'\n : 'medium';\n return { round: next.round, status: 'addressed', confidence };\n }\n\n return { round: next.round, status: 'outdated', confidence: 'low' };\n}\n", "import { isCoverageComplete } from './coverage.js';\nimport type { ReviewState } from './types.js';\n\n/**\n * True when the stored report is the final report for the latest round.\n *\n * A queued, running, failed, skipped or coverage-partial run does not make its\n * report final, even when a previous run left a report in place. Legacy states\n * without an agent still qualify because their report is all we have.\n */\nexport function isFinalReviewReport(\n review: ReviewState,\n report: ReviewState['report'] = review.report,\n): boolean {\n const latestRound = review.rounds.at(-1);\n if (report === undefined || latestRound === undefined || report.round !== latestRound.no) {\n return false;\n }\n const agent = review.agent;\n if (agent === undefined) return true;\n if (agent.status !== 'done') return false;\n return agent.coverage === undefined || isCoverageComplete(agent.coverage);\n}\n", "import { isCoverageComplete, promotePendingToLight, summarizeCoverage } from './coverage.js';\nimport type { ReviewEvent } from './events.js';\nimport type { AgentStatus, Comment, ReviewState } from './types.js';\n\nexport class ReviewFoldError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ReviewFoldError';\n }\n}\n\nfunction findComment(state: ReviewState, commentId: string): Comment {\n const comment = state.comments.find((candidate) => candidate.id === commentId);\n if (comment === undefined) {\n throw new ReviewFoldError(`unknown comment: ${commentId}`);\n }\n return comment;\n}\n\n/**\n * Pure reduction of one event into review state. The input is never mutated;\n * callers replay events in append order. `review/created` seeds the aggregate\n * (and resets the version to 1); every other event advances it by one.\n */\nexport function fold(state: ReviewState, event: ReviewEvent): ReviewState {\n if (event.reviewId !== state.id) {\n throw new ReviewFoldError(`event ${event.id} belongs to ${event.reviewId}, not ${state.id}`);\n }\n\n if (event.type === 'review/created') {\n if (event.data.review.id !== event.reviewId) {\n throw new ReviewFoldError(\n `review payload ${event.data.review.id} belongs to a different review than ${event.reviewId}`,\n );\n }\n return {\n ...structuredClone(event.data.review),\n version: 1,\n warnings: [],\n };\n }\n\n const next = structuredClone(state);\n next.version += 1;\n next.warnings ??= [];\n\n switch (event.type) {\n case 'round/created': {\n if (next.rounds.some((round) => round.no === event.data.round.no)) {\n throw new ReviewFoldError(`duplicate round: ${event.data.round.no}`);\n }\n const expected = next.rounds.length + 1;\n if (event.data.round.no !== expected) {\n throw new ReviewFoldError(`round order: expected ${expected}, got ${event.data.round.no}`);\n }\n next.rounds.push(structuredClone(event.data.round));\n break;\n }\n case 'comment/added': {\n if (next.comments.some((comment) => comment.id === event.data.comment.id)) {\n throw new ReviewFoldError(`duplicate comment: ${event.data.comment.id}`);\n }\n next.comments.push(structuredClone(event.data.comment));\n break;\n }\n case 'comment/replied': {\n const comment = findComment(next, event.data.commentId);\n comment.replies.push(structuredClone(event.data.reply));\n break;\n }\n case 'comment/state': {\n findComment(next, event.data.commentId).state = event.data.state;\n break;\n }\n case 'comment/edited': {\n const comment = findComment(next, event.data.commentId);\n comment.body = event.data.body;\n comment.editedAt = event.at;\n comment.editedBy = structuredClone(event.actor);\n break;\n }\n case 'comment/deleted': {\n const comment = findComment(next, event.data.commentId);\n comment.deletedAt = event.at;\n comment.deletedBy = structuredClone(event.actor);\n break;\n }\n case 'comment/anchor': {\n const comment = findComment(next, event.data.commentId);\n const anchor = structuredClone(event.data.anchor);\n const index = comment.anchors.findIndex((candidate) => candidate.round === anchor.round);\n if (index < 0) comment.anchors.push(anchor);\n else comment.anchors[index] = anchor;\n if (event.data.outcome !== undefined) {\n comment.outcomes.push(structuredClone(event.data.outcome));\n }\n break;\n }\n case 'suggestion/state': {\n findComment(next, event.data.commentId).suggestionState = event.data.state;\n break;\n }\n case 'fix/claim': {\n next.fixClaims ??= [];\n next.fixClaims.push(...structuredClone(event.data.claims));\n break;\n }\n case 'finding/decision': {\n next.findingDecisions ??= [];\n next.findingDecisions.push(structuredClone(event.data.decision));\n if (event.data.comment !== undefined) {\n const comment = event.data.comment;\n if (next.comments.some((candidate) => candidate.id === comment.id)) {\n throw new ReviewFoldError(`duplicate comment: ${comment.id}`);\n }\n next.comments.push(structuredClone(comment));\n }\n if (event.data.deletedCommentId !== undefined) {\n const comment = findComment(next, event.data.deletedCommentId);\n if (comment.deletedAt === undefined) {\n comment.deletedAt = event.at;\n comment.deletedBy = structuredClone(event.actor);\n }\n }\n break;\n }\n case 'review/updated': {\n if (event.data.title !== undefined) next.title = event.data.title;\n if (event.data.reviewer !== undefined) {\n next.reviewer = structuredClone(event.data.reviewer);\n }\n next.updatedAt = event.at;\n next.updatedBy = structuredClone(event.actor);\n break;\n }\n case 'review/deleted': {\n next.deletedAt = event.at;\n next.deletedBy = structuredClone(event.actor);\n break;\n }\n case 'suggestion/applied': {\n const comment = findComment(next, event.data.commentId);\n const alreadyApplied = comment.outcomes.some(\n (outcome) => outcome.round === event.data.round && outcome.status === 'applied',\n );\n if (!alreadyApplied) {\n comment.outcomes.push({\n round: event.data.round,\n status: 'applied',\n confidence: 'high',\n });\n comment.suggestionState = 'applied';\n }\n break;\n }\n case 'review/closed': {\n next.status = 'closed';\n next.closedAt ??= event.at;\n break;\n }\n case 'review/submitted': {\n const submission = structuredClone(event.data.submission);\n next.submissions ??= [];\n if (next.submissions.some((item) => item.submissionId === submission.submissionId)) {\n throw new ReviewFoldError(`duplicate submission: ${submission.submissionId}`);\n }\n next.submissions.push(submission);\n if (submission.verdict === 'approve') {\n next.status = 'closed';\n next.closedAt ??= event.at;\n }\n break;\n }\n case 'agent/coverage': {\n next.agent = {\n status: 'queued',\n round: event.data.round,\n coverage: structuredClone(event.data.coverage),\n findings: [],\n shards: [],\n };\n break;\n }\n case 'agent/started': {\n next.agent = {\n ...(next.agent?.coverage === undefined ? {} : { coverage: next.agent.coverage }),\n ...(next.agent?.shards === undefined ? {} : { shards: next.agent.shards }),\n status: 'running',\n jobId: event.data.jobId,\n round: event.data.round,\n startedAt: event.at,\n findings: [],\n };\n break;\n }\n case 'agent/shard': {\n next.agent ??= { status: 'running', findings: [] };\n next.agent.shards ??= [];\n const index = next.agent.shards.findIndex((shard) => shard.shardId === event.data.shardId);\n const shard = {\n shardId: event.data.shardId,\n shardIndex: event.data.shardIndex,\n shardCount: event.data.shardCount,\n round: event.data.round,\n report: structuredClone(event.data.report),\n };\n if (index < 0) next.agent.shards.push(shard);\n else next.agent.shards[index] = shard;\n if (next.agent.coverage !== undefined && event.data.paths !== undefined) {\n const covered = new Set(event.data.paths);\n const tier = event.data.tier ?? 'deep';\n const files = next.agent.coverage.files.map((file) => {\n if (!covered.has(file.path) || file.status !== 'pending') return file;\n const nextFile = {\n ...file,\n status: tier === 'deep' ? ('deep-reviewed' as const) : ('light-reviewed' as const),\n };\n delete nextFile.reason;\n return nextFile;\n });\n next.agent.coverage = {\n ...next.agent.coverage,\n files,\n totals: summarizeCoverage(files),\n };\n }\n break;\n }\n case 'agent/finding': {\n next.agent ??= { status: 'running', findings: [] };\n next.agent.findings ??= [];\n next.agent.findings.push(structuredClone(event.data.finding));\n break;\n }\n case 'agent/report': {\n const reportSkipped = event.data.report.skipped === true;\n const coverage =\n event.data.coverage !== undefined\n ? structuredClone(event.data.coverage)\n : reportSkipped || next.agent?.coverage === undefined\n ? next.agent?.coverage\n : promotePendingToLight(next.agent.coverage);\n let status: AgentStatus;\n if (reportSkipped) status = 'skipped';\n else if (coverage === undefined) status = 'done';\n else status = isCoverageComplete(coverage) ? 'done' : 'partial';\n next.report = structuredClone(event.data.report);\n next.agent = {\n ...(next.agent ?? {}),\n status,\n round: event.data.report.round,\n findings: structuredClone(event.data.report.findings),\n ...(coverage === undefined ? {} : { coverage }),\n };\n break;\n }\n case 'agent/failed': {\n next.agent = {\n ...(next.agent ?? {}),\n status: 'failed',\n error: event.data.message,\n };\n break;\n }\n case 'agent/retry': {\n const agent = next.agent ?? { status: 'queued' as const, findings: [] };\n const retryShards = new Set(event.data.shardIds);\n let coverage = agent.coverage;\n if (coverage !== undefined) {\n const files = coverage.files.map((file) => {\n if (\n file.shardId === undefined ||\n !retryShards.has(file.shardId) ||\n (file.status !== 'failed' && file.status !== 'pending')\n ) {\n return file;\n }\n const retried = { ...file, status: 'pending' as const };\n delete retried.reason;\n return retried;\n });\n coverage = { ...coverage, files, totals: summarizeCoverage(files) };\n }\n next.agent = {\n ...agent,\n status: 'queued',\n round: event.data.round,\n ...(coverage === undefined ? {} : { coverage }),\n };\n delete next.agent.jobId;\n delete next.agent.startedAt;\n delete next.agent.error;\n break;\n }\n }\n\n return next;\n}\n", "import { createHash } from 'node:crypto';\nimport { captureAnchor, AnchorError, reanchor } from './anchors.js';\nimport { createEvent } from './events.js';\nimport { isFinalReviewReport } from './final.js';\nimport { createId } from './ids.js';\nimport { deriveOutcome } from './outcomes.js';\nimport { ReviewNotFoundError } from './store.js';\nimport type { ReviewStore } from './store.js';\nimport type {\n Actor,\n AddCommentInput,\n Anchor,\n Comment,\n CommentState,\n CreateReviewInput,\n FindingDecision,\n FindingDecisionState,\n ReviewId,\n ReviewState,\n ReviewSummary,\n Round,\n} from './types.js';\nimport type { Snapshot } from '../types.js';\nimport type { Finding, ReviewerConfig } from '../reviewer/types.js';\n\nexport type ReviewLifecycleErrorCode =\n | 'not-found'\n | 'closed'\n | 'no-rounds'\n | 'duplicate-round'\n | 'round-order'\n | 'comment-not-found'\n | 'finding-not-found'\n | 'snapshot-mismatch'\n | 'invalid-input';\n\nexport class ReviewLifecycleError extends Error {\n readonly code: ReviewLifecycleErrorCode;\n readonly reviewId?: ReviewId;\n readonly commentId?: string;\n readonly findingId?: string;\n\n constructor(\n code: ReviewLifecycleErrorCode,\n message: string,\n details: { reviewId?: ReviewId; commentId?: string; findingId?: string } = {},\n ) {\n super(message);\n this.name = 'ReviewLifecycleError';\n this.code = code;\n if (details.reviewId !== undefined) this.reviewId = details.reviewId;\n if (details.commentId !== undefined) this.commentId = details.commentId;\n if (details.findingId !== undefined) this.findingId = details.findingId;\n }\n}\n\nfunction findComment(state: ReviewState, commentId: string): Comment {\n const comment = state.comments.find((candidate) => candidate.id === commentId);\n if (comment === undefined) {\n throw new ReviewLifecycleError('comment-not-found', `unknown comment: ${commentId}`, {\n reviewId: state.id,\n commentId,\n });\n }\n return comment;\n}\n\nfunction requireLatestReport(\n state: ReviewState,\n reviewId: ReviewId,\n): NonNullable<ReviewState['report']> {\n const latestRound = state.rounds.at(-1);\n if (state.report === undefined || latestRound === undefined) {\n throw new ReviewLifecycleError('invalid-input', `review has no reviewer report: ${reviewId}`, {\n reviewId,\n });\n }\n if (state.report.round !== latestRound.no) {\n throw new ReviewLifecycleError(\n 'invalid-input',\n `reviewer report is from round ${state.report.round}, latest is ${latestRound.no}`,\n { reviewId },\n );\n }\n return state.report;\n}\n\nfunction requireFinalReport(\n state: ReviewState,\n reviewId: ReviewId,\n): NonNullable<ReviewState['report']> {\n const report = requireLatestReport(state, reviewId);\n if (!isFinalReviewReport(state)) {\n throw new ReviewLifecycleError('invalid-input', `reviewer report is not final: ${reviewId}`, {\n reviewId,\n });\n }\n return report;\n}\n\nfunction normalizeDecisionInput(\n input: { state: FindingDecisionState; note?: string },\n reviewId: ReviewId,\n): { state: FindingDecisionState; note?: string } {\n if (input.state !== 'accepted' && input.state !== 'dismissed') {\n throw new ReviewLifecycleError('invalid-input', `unknown finding decision: ${input.state}`, {\n reviewId,\n });\n }\n if (input.note !== undefined && typeof input.note !== 'string') {\n throw new ReviewLifecycleError('invalid-input', 'finding decision note must be a string', {\n reviewId,\n });\n }\n const note = input.note?.trim();\n if (note !== undefined && note.length > 4000) {\n throw new ReviewLifecycleError('invalid-input', 'finding decision note is too long', {\n reviewId,\n });\n }\n return {\n state: input.state,\n ...(note === undefined || note === '' ? {} : { note }),\n };\n}\n\nfunction requireFinding(\n report: NonNullable<ReviewState['report']>,\n findingId: string,\n reviewId: ReviewId,\n): Finding {\n const finding = report.findings.find((candidate) => candidate.id === findingId);\n if (finding === undefined) {\n throw new ReviewLifecycleError('finding-not-found', `unknown finding: ${findingId}`, {\n reviewId,\n findingId,\n });\n }\n return finding;\n}\n\nfunction activeFindingComment(state: ReviewState, findingId: string): Comment | undefined {\n return state.comments.find(\n (comment) => comment.sourceFindingId === findingId && comment.deletedAt === undefined,\n );\n}\n\nfunction findingAnchor(finding: Finding, round: number, now: () => Date): Anchor {\n return {\n id: createId('anc', now),\n round,\n path: finding.file,\n side: 'new',\n lineStart: finding.lineStart,\n lineEnd: finding.lineEnd,\n quote: finding.evidence,\n contextBefore: [],\n contextAfter: [],\n hunkHeader: '',\n contentHash: createHash('sha256').update(finding.evidence, 'utf8').digest('hex'),\n state: 'active',\n };\n}\n\nfunction transferredCommentBody(finding: Finding, note: string | undefined): string {\n return [\n finding.title,\n finding.rationale,\n finding.evidence.trim() === '' ? '' : `Evidence:\\n${finding.evidence}`,\n note === undefined ? '' : `Note to the agent: ${note}`,\n ]\n .filter((part) => part !== '')\n .join('\\n\\n');\n}\n\nfunction transferredComment(\n reviewId: ReviewId,\n finding: Finding,\n round: number,\n note: string | undefined,\n now: () => Date,\n): Comment {\n return {\n id: createId('cmt', now),\n reviewId,\n createdAt: now().toISOString(),\n author: { name: 'AI', kind: 'agent' },\n body: transferredCommentBody(finding, note),\n ...(finding.suggestion === undefined\n ? {}\n : { suggestion: structuredClone(finding.suggestion) }),\n state: 'open',\n replies: [],\n anchors: [findingAnchor(finding, round, now)],\n outcomes: [],\n sourceFindingId: finding.id,\n };\n}\n\ninterface DecisionTransfer {\n comment?: Comment;\n deletedCommentId?: string;\n commentId?: string;\n}\n\nfunction decisionTransfer(\n state: ReviewState,\n reviewId: ReviewId,\n finding: Finding,\n round: number,\n decisionState: FindingDecisionState,\n note: string | undefined,\n now: () => Date,\n): DecisionTransfer {\n const existing = activeFindingComment(state, finding.id);\n if (decisionState === 'accepted') {\n if (existing !== undefined) return { commentId: existing.id };\n const comment = transferredComment(reviewId, finding, round, note, now);\n return { comment, commentId: comment.id };\n }\n if (existing === undefined) return {};\n return { deletedCommentId: existing.id, commentId: existing.id };\n}\n\nfunction hasDecision(state: ReviewState, findingId: string, round: number): boolean {\n return (state.findingDecisions ?? []).some(\n (decision) => decision.round === round && decision.findingId === findingId,\n );\n}\n\nexport interface RefreshResult {\n round: Round;\n comments: Comment[];\n}\n\n/**\n * Domain-level mutations for one review. Every method appends an event; the\n * aggregate is always reloaded through the store so callers never observe a\n * state that has not been folded from the log.\n */\nexport class ReviewLifecycle {\n private readonly store: ReviewStore;\n private readonly now: () => Date;\n\n constructor(store: ReviewStore, now: () => Date = () => new Date()) {\n this.store = store;\n this.now = now;\n }\n\n async create(input: CreateReviewInput): Promise<ReviewState> {\n const id = createId('rev', this.now);\n const state: ReviewState = {\n id,\n title: input.title,\n repoRoot: input.repoRoot,\n status: 'open',\n createdAt: this.now().toISOString(),\n createdBy: input.actor,\n ...(input.initiator === undefined ? {} : { initiator: input.initiator }),\n rounds: [],\n comments: [],\n version: 0,\n ...(input.reviewer === undefined ? {} : { reviewer: input.reviewer }),\n };\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'review/created',\n actor: input.actor,\n data: { review: state },\n now: this.now,\n }),\n );\n return this.get(id);\n }\n\n async get(reviewId: ReviewId): Promise<ReviewState> {\n try {\n return await this.store.load(reviewId);\n } catch (error) {\n if (error instanceof ReviewNotFoundError) {\n throw new ReviewLifecycleError('not-found', error.message, { reviewId });\n }\n throw error;\n }\n }\n\n async list(): Promise<ReviewSummary[]> {\n return this.store.list();\n }\n\n async addRound(reviewId: ReviewId, snapshot: Snapshot, actor: Actor): Promise<Round> {\n const state = await this.requireOpen(reviewId);\n const previous = state.rounds.at(-1);\n // A worktree snapshot has no head commit; its identity is the digest.\n const sameScope = (round: Round): boolean =>\n snapshot.scope.headSha !== null &&\n round.baseSha === snapshot.scope.baseSha &&\n round.headSha === snapshot.scope.headSha;\n const earlier = state.rounds.slice(0, -1).find(sameScope);\n if (earlier !== undefined) {\n throw new ReviewLifecycleError(\n 'duplicate-round',\n `snapshot already belongs to round ${earlier.no}`,\n { reviewId },\n );\n }\n if (previous !== undefined && sameScope(previous)) {\n throw new ReviewLifecycleError(\n 'duplicate-round',\n `snapshot already belongs to round ${previous.no}`,\n { reviewId },\n );\n }\n\n const snapshotId = createId('snap', this.now);\n await this.store.writeSnapshot(snapshotId, snapshot);\n const round: Round = {\n no: state.rounds.length + 1,\n snapshotId,\n createdAt: this.now().toISOString(),\n baseSha: snapshot.scope.baseSha,\n headSha: snapshot.scope.headSha,\n path: `snapshots/${snapshotId}.json`,\n };\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'round/created',\n actor,\n data: { round },\n now: this.now,\n }),\n );\n return round;\n }\n\n async latestSnapshot(reviewId: ReviewId): Promise<Snapshot> {\n const state = await this.get(reviewId);\n const round = state.rounds.at(-1);\n if (round === undefined) {\n throw new ReviewLifecycleError('no-rounds', `review has no rounds: ${reviewId}`, {\n reviewId,\n });\n }\n try {\n return await this.store.readSnapshot(round.snapshotId);\n } catch (error) {\n if (error instanceof ReviewNotFoundError) {\n throw new ReviewLifecycleError(\n 'snapshot-mismatch',\n `round ${round.no} snapshot is missing or invalid: ${round.snapshotId}`,\n { reviewId },\n );\n }\n throw error;\n }\n }\n\n async addComment(reviewId: ReviewId, input: AddCommentInput, actor: Actor): Promise<Comment> {\n const state = await this.requireOpen(reviewId);\n const round = state.rounds.at(-1);\n if (round === undefined) {\n throw new ReviewLifecycleError('no-rounds', `review has no rounds: ${reviewId}`, {\n reviewId,\n });\n }\n const snapshot = await this.latestSnapshot(reviewId);\n\n let anchor: Anchor;\n try {\n anchor = captureAnchor(snapshot, {\n path: input.path,\n side: input.side,\n lineStart: input.lineStart,\n ...(input.lineEnd === undefined ? {} : { lineEnd: input.lineEnd }),\n round: round.no,\n id: createId('anc', this.now),\n });\n } catch (error) {\n if (error instanceof AnchorError) {\n throw new ReviewLifecycleError('snapshot-mismatch', error.message, { reviewId });\n }\n throw error;\n }\n\n const comment: Comment = {\n id: createId('cmt', this.now),\n reviewId,\n createdAt: this.now().toISOString(),\n author: actor,\n body: input.body,\n state: 'open',\n replies: [],\n anchors: [anchor],\n outcomes: [],\n ...(input.suggestion === undefined ? {} : { suggestion: structuredClone(input.suggestion) }),\n };\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'comment/added',\n actor,\n data: { comment },\n now: this.now,\n }),\n );\n return this.findComment(await this.get(reviewId), comment.id);\n }\n\n async reply(reviewId: ReviewId, commentId: string, body: string, actor: Actor): Promise<Comment> {\n const state = await this.requireOpen(reviewId);\n const target = findComment(state, commentId);\n if (target.deletedAt !== undefined) {\n throw new ReviewLifecycleError('comment-not-found', `unknown comment: ${commentId}`, {\n reviewId,\n commentId,\n });\n }\n if (body.trim() === '') {\n throw new ReviewLifecycleError('invalid-input', 'reply body must be non-empty', { reviewId });\n }\n\n const reply = {\n id: createId('cmt', this.now),\n author: actor,\n body,\n createdAt: this.now().toISOString(),\n };\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'comment/replied',\n actor,\n data: { commentId, reply },\n now: this.now,\n }),\n );\n return this.findComment(await this.get(reviewId), commentId);\n }\n\n async editComment(\n reviewId: ReviewId,\n commentId: string,\n body: string,\n actor: Actor,\n ): Promise<Comment> {\n const state = await this.requireOpen(reviewId);\n const comment = findComment(state, commentId);\n if (comment.deletedAt !== undefined) {\n throw new ReviewLifecycleError('comment-not-found', `unknown comment: ${commentId}`, {\n reviewId,\n commentId,\n });\n }\n const text = body.trim();\n if (text === '') {\n throw new ReviewLifecycleError('invalid-input', 'comment body must be non-empty', {\n reviewId,\n commentId,\n });\n }\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'comment/edited',\n actor,\n data: { commentId, body: text },\n now: this.now,\n }),\n );\n return findComment(await this.get(reviewId), commentId);\n }\n\n async deleteComment(reviewId: ReviewId, commentId: string, actor: Actor): Promise<Comment> {\n const state = await this.get(reviewId);\n if (state.deletedAt !== undefined) {\n throw new ReviewLifecycleError('not-found', `review not found: ${reviewId}`, { reviewId });\n }\n const comment = findComment(state, commentId);\n if (comment.deletedAt !== undefined) return comment;\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'comment/deleted',\n actor,\n data: { commentId },\n now: this.now,\n }),\n );\n return findComment(await this.get(reviewId), commentId);\n }\n\n async setCommentState(\n reviewId: ReviewId,\n commentId: string,\n state: CommentState,\n actor: Actor,\n ): Promise<Comment> {\n const review = await this.requireOpen(reviewId);\n const comment = findComment(review, commentId);\n if (comment.deletedAt !== undefined) {\n throw new ReviewLifecycleError('comment-not-found', `unknown comment: ${commentId}`, {\n reviewId,\n commentId,\n });\n }\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'comment/state',\n actor,\n data: { commentId, state },\n now: this.now,\n }),\n );\n return this.findComment(await this.get(reviewId), commentId);\n }\n\n async decideFinding(\n reviewId: ReviewId,\n findingId: string,\n input: { state: FindingDecisionState; note?: string },\n actor: Actor,\n ): Promise<FindingDecision> {\n const normalized = normalizeDecisionInput(input, reviewId);\n const state = await this.requireOpen(reviewId);\n const report = requireFinalReport(state, reviewId);\n const finding = requireFinding(report, findingId, reviewId);\n const at = this.now().toISOString();\n const transfer = decisionTransfer(\n state,\n reviewId,\n finding,\n report.round,\n normalized.state,\n normalized.note,\n this.now,\n );\n\n const decision: FindingDecision = {\n findingId,\n round: report.round,\n state: normalized.state,\n ...(normalized.note === undefined ? {} : { note: normalized.note }),\n ...(transfer.commentId === undefined ? {} : { commentId: transfer.commentId }),\n by: actor,\n at,\n };\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'finding/decision',\n actor,\n data: {\n decision,\n ...(transfer.comment === undefined ? {} : { comment: transfer.comment }),\n ...(transfer.deletedCommentId === undefined\n ? {}\n : { deletedCommentId: transfer.deletedCommentId }),\n },\n now: this.now,\n }),\n );\n return decision;\n }\n\n /**\n * Records a decision only when the finding has no decision for the same\n * report round. The existence check and append share the store's per-review\n * critical section, so two concurrent bulk requests cannot both win.\n * Returns null when another writer decided the finding first.\n */\n async decideFindingIfUndecided(\n reviewId: ReviewId,\n findingId: string,\n input: { state: FindingDecisionState },\n actor: Actor,\n ): Promise<FindingDecision | null> {\n const normalized = normalizeDecisionInput(input, reviewId);\n const state = await this.requireOpen(reviewId);\n const report = requireFinalReport(state, reviewId);\n const finding = requireFinding(report, findingId, reviewId);\n const at = this.now().toISOString();\n const transfer = decisionTransfer(\n state,\n reviewId,\n finding,\n report.round,\n normalized.state,\n normalized.note,\n this.now,\n );\n\n const decision: FindingDecision = {\n findingId,\n round: report.round,\n state: normalized.state,\n ...(transfer.commentId === undefined ? {} : { commentId: transfer.commentId }),\n by: actor,\n at,\n };\n const appended = await this.store.appendIf(\n reviewId,\n createEvent({\n reviewId,\n type: 'finding/decision',\n actor,\n data: {\n decision,\n ...(transfer.comment === undefined ? {} : { comment: transfer.comment }),\n ...(transfer.deletedCommentId === undefined\n ? {}\n : { deletedCommentId: transfer.deletedCommentId }),\n },\n now: this.now,\n }),\n (current) => {\n if (current.deletedAt !== undefined) {\n throw new ReviewLifecycleError('not-found', `review not found: ${reviewId}`, {\n reviewId,\n });\n }\n if (current.status === 'closed') {\n throw new ReviewLifecycleError('closed', `review is closed: ${reviewId}`, { reviewId });\n }\n const currentReport = requireFinalReport(current, reviewId);\n if (currentReport.round !== decision.round) {\n throw new ReviewLifecycleError(\n 'invalid-input',\n `reviewer report is from round ${currentReport.round}, expected ${decision.round}`,\n { reviewId },\n );\n }\n requireFinding(currentReport, findingId, reviewId);\n return !hasDecision(current, findingId, decision.round);\n },\n );\n return appended === null ? null : decision;\n }\n\n /**\n * Materializes a comment for accepted findings that predate automatic\n * transfer. It is idempotent: an active source comment suppresses a second\n * append, and `appendIf` re-checks the current state inside the review lock.\n */\n async transferAcceptedFindings(reviewId: ReviewId, actor: Actor): Promise<Comment[]> {\n const state = await this.get(reviewId);\n if (state.deletedAt !== undefined || !isFinalReviewReport(state)) return [];\n const report = state.report;\n if (report === undefined) return [];\n const latest = new Map<string, FindingDecision>();\n for (const decision of state.findingDecisions ?? []) {\n if (decision.round === report.round) latest.set(decision.findingId, decision);\n }\n const accepted = new Set(\n [...latest.values()]\n .filter((decision) => decision.state === 'accepted')\n .map((decision) => decision.findingId),\n );\n const transferred: Comment[] = [];\n for (const finding of report.findings) {\n if (!accepted.has(finding.id) || activeFindingComment(state, finding.id) !== undefined) {\n continue;\n }\n const note = latest.get(finding.id)?.note;\n const comment = transferredComment(reviewId, finding, report.round, note, this.now);\n const appended = await this.store.appendIf(\n reviewId,\n createEvent({\n reviewId,\n type: 'comment/added',\n actor,\n data: { comment },\n now: this.now,\n }),\n (current) => {\n if (current.deletedAt !== undefined) return false;\n if (!isFinalReviewReport(current) || current.report?.round !== report.round) {\n return false;\n }\n const decision = [...(current.findingDecisions ?? [])]\n .reverse()\n .find(\n (candidate) => candidate.round === report.round && candidate.findingId === finding.id,\n );\n return (\n decision?.state === 'accepted' &&\n activeFindingComment(current, finding.id) === undefined\n );\n },\n );\n if (appended !== null) transferred.push(comment);\n }\n return transferred;\n }\n\n async updateReview(\n reviewId: ReviewId,\n input: { title?: string; reviewer?: ReviewerConfig },\n actor: Actor,\n ): Promise<ReviewState> {\n await this.requireOpen(reviewId);\n const title = input.title?.trim();\n if (title === undefined && input.reviewer === undefined) {\n throw new ReviewLifecycleError('invalid-input', 'review update is empty', { reviewId });\n }\n if (title !== undefined && title === '') {\n throw new ReviewLifecycleError('invalid-input', 'review title must be non-empty', {\n reviewId,\n });\n }\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'review/updated',\n actor,\n data: {\n ...(title === undefined ? {} : { title }),\n ...(input.reviewer === undefined ? {} : { reviewer: input.reviewer }),\n },\n now: this.now,\n }),\n );\n return this.get(reviewId);\n }\n\n async deleteReview(reviewId: ReviewId, actor: Actor, reason?: string): Promise<ReviewState> {\n const state = await this.get(reviewId);\n if (state.deletedAt !== undefined) return state;\n if (reason !== undefined && typeof reason !== 'string') {\n throw new ReviewLifecycleError('invalid-input', 'delete reason must be a string', {\n reviewId,\n });\n }\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'review/deleted',\n actor,\n data: reason === undefined || reason.trim() === '' ? {} : { reason: reason.trim() },\n now: this.now,\n }),\n );\n return this.get(reviewId);\n }\n\n async close(\n reviewId: ReviewId,\n verdict: 'approved' | 'closed',\n actor: Actor,\n ): Promise<ReviewState> {\n const state = await this.get(reviewId);\n if (state.deletedAt !== undefined) {\n throw new ReviewLifecycleError('not-found', `review not found: ${reviewId}`, { reviewId });\n }\n if (state.status === 'closed') {\n throw new ReviewLifecycleError('closed', `review is already closed: ${reviewId}`, {\n reviewId,\n });\n }\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'review/closed',\n actor,\n data: { verdict },\n now: this.now,\n }),\n );\n return this.get(reviewId);\n }\n\n async refresh(reviewId: ReviewId, snapshot: Snapshot, actor: Actor): Promise<RefreshResult> {\n const state = await this.requireOpen(reviewId);\n const round = await this.addRound(reviewId, snapshot, actor);\n const comments = structuredClone(state.comments);\n\n for (const comment of comments) {\n const previous = comment.anchors.at(-1);\n if (previous === undefined) continue;\n const anchor = reanchor(previous, snapshot, {\n round: round.no,\n id: createId('anc', this.now),\n ...(comment.suggestion === undefined\n ? {}\n : { fallbackQuote: comment.suggestion.replacement }),\n });\n const outcome = deriveOutcome(previous, anchor, snapshot, comment.suggestion);\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'comment/anchor',\n actor,\n data: { commentId: comment.id, anchor, outcome },\n now: this.now,\n }),\n );\n const index = comment.anchors.findIndex((candidate) => candidate.round === anchor.round);\n if (index < 0) comment.anchors.push(anchor);\n else comment.anchors[index] = anchor;\n comment.outcomes.push(outcome);\n }\n\n return { round, comments };\n }\n\n private async requireOpen(reviewId: ReviewId): Promise<ReviewState> {\n const state = await this.get(reviewId);\n if (state.deletedAt !== undefined) {\n throw new ReviewLifecycleError('not-found', `review not found: ${reviewId}`, { reviewId });\n }\n if (state.status === 'closed') {\n throw new ReviewLifecycleError('closed', `review is closed: ${reviewId}`, { reviewId });\n }\n return state;\n }\n\n private findComment(state: ReviewState, commentId: string): Comment {\n return findComment(state, commentId);\n }\n}\n", "import { randomBytes } from 'node:crypto';\nimport type { Dirent } from 'node:fs';\nimport {\n link,\n open,\n readdir,\n readFile,\n stat,\n mkdir,\n rename,\n rm,\n truncate,\n unlink,\n} from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport { isReviewEvent, ReviewEventError } from './events.js';\nimport type { ReviewEvent } from './events.js';\nimport { fold } from './fold.js';\nimport { manifestFromSnapshot } from '../diff/manifest.js';\nimport type { FileStatus, ManifestFileReason, ReviewManifest, Snapshot } from '../types.js';\nimport type {\n Actor,\n Comment,\n FindingDecision,\n ReviewId,\n ReviewState,\n ReviewStatus,\n ReviewSummary,\n} from './types.js';\n\nexport interface ReviewStoreOptions {\n now?: () => Date;\n newId?: (prefix: string) => string;\n}\n\ninterface CacheEntry {\n state: ReviewState;\n eventCount: number;\n /** Exact byte length of the log prefix this state was folded from. */\n bytes?: number;\n events?: ReviewEvent[];\n}\n\ninterface SnapshotCache {\n reviewId: ReviewId;\n eventCount: number;\n /** Size of events.jsonl when this cache was written; detects a stale cache. */\n eventBytes?: number;\n state: ReviewState;\n}\n\ninterface LockFile {\n pid: number;\n createdAt: string;\n}\n\nexport class ReviewStoreLockedError extends Error {\n readonly pid?: number;\n readonly stale: boolean;\n readonly lockPath: string;\n\n constructor(message: string, options: { pid?: number; stale: boolean; lockPath: string }) {\n super(message);\n this.name = 'ReviewStoreLockedError';\n this.pid = options.pid;\n this.stale = options.stale;\n this.lockPath = options.lockPath;\n }\n}\n\nexport class ReviewStoreCorruptionError extends Error {\n readonly reviewId: ReviewId;\n readonly line: number;\n\n constructor(message: string, reviewId: ReviewId, line: number) {\n super(message);\n this.name = 'ReviewStoreCorruptionError';\n this.reviewId = reviewId;\n this.line = line;\n }\n}\n\nexport class ReviewNotFoundError extends Error {\n readonly reviewId: ReviewId;\n\n constructor(reviewId: ReviewId) {\n super(`review not found: ${reviewId}`);\n this.name = 'ReviewNotFoundError';\n this.reviewId = reviewId;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isTimestamp(value: unknown): value is string {\n if (typeof value !== 'string') return false;\n const parsed = new Date(value);\n return Number.isFinite(parsed.getTime()) && parsed.toISOString() === value;\n}\n\nconst REVIEW_STATUSES = new Set<ReviewStatus>(['open', 'closed']);\n\nfunction isActor(value: unknown): value is Actor {\n if (!isRecord(value)) return false;\n return (\n typeof value.name === 'string' &&\n (value.kind === 'human' || value.kind === 'agent' || value.kind === 'system')\n );\n}\n\nfunction isComment(value: unknown): value is Comment {\n if (!isRecord(value)) return false;\n return (\n typeof value.id === 'string' &&\n typeof value.reviewId === 'string' &&\n isTimestamp(value.createdAt) &&\n typeof value.body === 'string' &&\n (value.state === 'open' || value.state === 'resolved' || value.state === 'dismissed') &&\n Array.isArray(value.replies) &&\n Array.isArray(value.anchors) &&\n Array.isArray(value.outcomes) &&\n (value.editedAt === undefined || isTimestamp(value.editedAt)) &&\n (value.editedBy === undefined || isActor(value.editedBy)) &&\n (value.deletedAt === undefined || isTimestamp(value.deletedAt)) &&\n (value.deletedBy === undefined || isActor(value.deletedBy)) &&\n (value.sourceFindingId === undefined || typeof value.sourceFindingId === 'string')\n );\n}\n\nfunction isFindingDecision(value: unknown): value is FindingDecision {\n if (!isRecord(value)) return false;\n return (\n typeof value.findingId === 'string' &&\n typeof value.round === 'number' &&\n Number.isInteger(value.round) &&\n value.round > 0 &&\n (value.state === 'accepted' || value.state === 'dismissed') &&\n (value.note === undefined || typeof value.note === 'string') &&\n (value.commentId === undefined || typeof value.commentId === 'string') &&\n isRecord(value.by) &&\n typeof value.by.name === 'string' &&\n (value.by.kind === 'human' || value.by.kind === 'agent' || value.by.kind === 'system') &&\n isTimestamp(value.at)\n );\n}\n\nfunction isReviewState(value: unknown): value is ReviewState {\n if (!isRecord(value)) return false;\n return (\n typeof value.id === 'string' &&\n typeof value.title === 'string' &&\n typeof value.repoRoot === 'string' &&\n typeof value.status === 'string' &&\n REVIEW_STATUSES.has(value.status as ReviewStatus) &&\n isTimestamp(value.createdAt) &&\n (value.closedAt === undefined || isTimestamp(value.closedAt)) &&\n (value.updatedAt === undefined || isTimestamp(value.updatedAt)) &&\n (value.updatedBy === undefined || isActor(value.updatedBy)) &&\n (value.deletedAt === undefined || isTimestamp(value.deletedAt)) &&\n (value.deletedBy === undefined || isActor(value.deletedBy)) &&\n Array.isArray(value.rounds) &&\n Array.isArray(value.comments) &&\n value.comments.every(isComment) &&\n (value.findingDecisions === undefined ||\n (Array.isArray(value.findingDecisions) && value.findingDecisions.every(isFindingDecision))) &&\n typeof value.version === 'number' &&\n Number.isInteger(value.version) &&\n value.version >= 0 &&\n (value.warnings === undefined ||\n (Array.isArray(value.warnings) && value.warnings.every((item) => typeof item === 'string')))\n );\n}\n\nfunction safeReviewId(reviewId: ReviewId): string {\n if (\n typeof reviewId !== 'string' ||\n !/^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(reviewId) ||\n reviewId.length > 200\n ) {\n throw new ReviewNotFoundError(reviewId);\n }\n return reviewId;\n}\n\nfunction safeSnapshotId(snapshotId: string): string {\n if (typeof snapshotId !== 'string' || !/^snap_[A-Za-z0-9]+$/.test(snapshotId)) {\n throw new ReviewNotFoundError(snapshotId);\n }\n return snapshotId;\n}\n\nconst FILE_STATUSES = new Set<FileStatus>([\n 'added',\n 'modified',\n 'deleted',\n 'renamed',\n 'submodule',\n 'untracked',\n]);\n\nconst MANIFEST_REASONS = new Set<ManifestFileReason>([\n 'per-file-cap',\n 'binary',\n 'ignored',\n 'generated',\n 'legacy-truncated',\n 'diff-truncated',\n 'render-budget',\n 'unreadable',\n 'symlink',\n]);\n\nfunction isManifestFile(value: unknown): boolean {\n if (!isRecord(value)) return false;\n if (typeof value.path !== 'string') return false;\n if (value.oldPath !== undefined && typeof value.oldPath !== 'string') return false;\n if (typeof value.status !== 'string' || !FILE_STATUSES.has(value.status as FileStatus)) {\n return false;\n }\n if (\n typeof value.binary !== 'boolean' ||\n typeof value.ignored !== 'boolean' ||\n typeof value.oversized !== 'boolean'\n ) {\n return false;\n }\n for (const field of ['added', 'deleted', 'hunkCount', 'patchBytes'] as const) {\n if (typeof value[field] !== 'number' || !Number.isFinite(value[field])) return false;\n }\n if (\n value.contentBytes !== undefined &&\n (typeof value.contentBytes !== 'number' || !Number.isFinite(value.contentBytes))\n ) {\n return false;\n }\n if (\n value.reason !== undefined &&\n (typeof value.reason !== 'string' || !MANIFEST_REASONS.has(value.reason as ManifestFileReason))\n ) {\n return false;\n }\n return true;\n}\n\nfunction isManifest(value: unknown): value is ReviewManifest {\n if (!isRecord(value)) return false;\n if (value.schemaVersion !== 1) return false;\n if (!isRecord(value.scope) || typeof value.scope.baseSha !== 'string') return false;\n if (!Array.isArray(value.files) || !value.files.every(isManifestFile)) return false;\n if (!isRecord(value.totals)) return false;\n for (const field of ['files', 'added', 'deleted', 'patchBytes'] as const) {\n if (typeof value.totals[field] !== 'number' || !Number.isFinite(value.totals[field])) {\n return false;\n }\n }\n return Array.isArray(value.warnings) && value.warnings.every((item) => typeof item === 'string');\n}\n\nfunction isSnapshot(value: unknown): value is Snapshot {\n if (!isRecord(value)) return false;\n if (value.schemaVersion !== 1 && value.schemaVersion !== 2) return false;\n if (!isRecord(value.scope) || typeof value.scope.baseSha !== 'string') return false;\n if (!Array.isArray(value.files)) return false;\n if (!isRecord(value.totals)) return false;\n if (value.schemaVersion === 2 && typeof value.totals.truncated !== 'boolean') return false;\n if (\n value.schemaVersion === 1 &&\n value.totals.truncated !== undefined &&\n typeof value.totals.truncated !== 'boolean'\n ) {\n return false;\n }\n if (!Array.isArray(value.warnings)) return false;\n if (value.manifest !== undefined && !isManifest(value.manifest)) return false;\n return value.files.every(\n (file) => isRecord(file) && typeof file.path === 'string' && Array.isArray(file.hunks),\n );\n}\n\n/**\n * API and job consumers expect a manifest. Legacy v1 snapshots are normalized\n * on read (schemaVersion stays 1 so callers can still recognize them); a v2\n * snapshot that somehow lacks one gets a synthesized manifest marked\n * `manifest-missing`, so coverage can never treat the bounded render subset as\n * the complete changed-path listing. A missing v1 totals.truncated means false\n * before the manifest is synthesized.\n */\nfunction normalizeSnapshot(snapshot: Snapshot): Snapshot {\n // Older v1 snapshots predate totals.truncated; a missing value means false.\n const normalized: Snapshot = {\n ...snapshot,\n totals: { ...snapshot.totals, truncated: snapshot.totals.truncated === true },\n };\n if (normalized.manifest !== undefined) return normalized;\n return { ...normalized, manifest: manifestFromSnapshot(normalized) };\n}\n\nfunction isPidAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return (error as NodeJS.ErrnoException).code === 'EPERM';\n }\n}\n\nfunction parseLock(raw: string): Partial<LockFile> {\n try {\n const value: unknown = JSON.parse(raw);\n if (!isRecord(value)) return {};\n return {\n ...(typeof value.pid === 'number' ? { pid: value.pid } : {}),\n ...(typeof value.createdAt === 'string' ? { createdAt: value.createdAt } : {}),\n };\n } catch {\n return {};\n }\n}\n\nasync function readLock(lockPath: string): Promise<Partial<LockFile> | null> {\n try {\n const raw = await readFile(lockPath, 'utf8');\n return parseLock(raw);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return null;\n return {};\n }\n}\n\nfunction corrupt(reviewId: ReviewId, line: number, detail: string): ReviewStoreCorruptionError {\n return new ReviewStoreCorruptionError(\n `review ${reviewId} is corrupt at line ${line}: ${detail}`,\n reviewId,\n line,\n );\n}\n\nfunction splitEventLines(content: string): string[] {\n if (content === '') return [];\n const lines = content.split('\\n');\n if (content.endsWith('\\n')) lines.pop();\n return lines;\n}\n\nfunction parseEventLog(\n content: string,\n reviewId: ReviewId,\n): { events: ReviewEvent[]; eventCount: number; torn: boolean } {\n const hasTrailingNewline = content.endsWith('\\n');\n const lines = splitEventLines(content);\n if (lines.length === 0) throw new ReviewNotFoundError(reviewId);\n\n const events: ReviewEvent[] = [];\n let torn = false;\n\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? '';\n const lineNo = index + 1;\n const isLast = index === lines.length - 1;\n\n if (line.trim() === '') {\n if (isLast) {\n torn = true;\n continue;\n }\n throw corrupt(reviewId, lineNo, 'empty line');\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n if (isLast) {\n torn = true;\n continue;\n }\n throw corrupt(reviewId, lineNo, 'invalid JSON');\n }\n\n if (!isReviewEvent(parsed) || parsed.reviewId !== reviewId) {\n // A missing newline always means the write was torn. A newline means the\n // line is complete, so invalid event fields are real corruption.\n if (isLast && !hasTrailingNewline) {\n torn = true;\n continue;\n }\n throw corrupt(reviewId, lineNo, 'invalid review event');\n }\n\n parsed.seq ??= lineNo;\n events.push(parsed);\n }\n\n return { events, eventCount: events.length, torn };\n}\n\nfunction parseReview(\n content: string,\n reviewId: ReviewId,\n): { state: ReviewState; eventCount: number; events: ReviewEvent[] } {\n const { events, eventCount, torn } = parseEventLog(content, reviewId);\n\n let state: ReviewState | undefined;\n for (let index = 0; index < events.length; index++) {\n const parsed = events[index] as ReviewEvent;\n const lineNo = index + 1;\n try {\n if (state === undefined) {\n if (parsed.type !== 'review/created') {\n throw new Error('first event must be review/created');\n }\n state = fold(parsed.data.review, parsed);\n } else {\n state = fold(state, parsed);\n }\n } catch (error) {\n throw corrupt(reviewId, lineNo, (error as Error).message);\n }\n }\n\n if (state === undefined) throw new ReviewNotFoundError(reviewId);\n if (torn) state.warnings = [...(state.warnings ?? []), 'torn-tail'];\n return { state, eventCount, events };\n}\n\nfunction shortSha(sha: string | null): string {\n return sha === null ? 'worktree' : sha.slice(0, 8);\n}\n\nfunction summary(state: ReviewState): ReviewSummary {\n const latest = state.rounds.at(-1);\n const comments = state.comments.filter((comment) => comment.deletedAt === undefined);\n const latestClaims = new Map<string, string>();\n for (const claim of state.fixClaims ?? []) latestClaims.set(claim.commentId, claim.status);\n return {\n id: state.id,\n title: state.title,\n repoRoot: state.repoRoot,\n status: state.status,\n createdAt: state.createdAt,\n roundCount: state.rounds.length,\n commentCount: comments.length,\n openCommentCount: comments.filter((comment) => comment.state === 'open').length,\n ...(latest === undefined\n ? { scope: 'no rounds' }\n : { scope: `${shortSha(latest.baseSha)} \u2192 ${shortSha(latest.headSha)}` }),\n ...(state.createdBy === undefined ? {} : { author: state.createdBy.name }),\n notFixedCount: [...latestClaims.values()].filter((status) => status === 'not-fixed').length,\n };\n}\n\n/**\n * One process writes a review store. JSONL is the source of truth; the\n * atomically replaced snapshot.json is only a replay cache.\n */\n\nexport interface GcResult {\n removedReviews: ReviewId[];\n removedSnapshots: number;\n}\n\nexport class ReviewStore {\n readonly root: string;\n readonly lockPath: string;\n private readonly lockCreatedAt: string;\n private readonly entries = new Map<ReviewId, CacheEntry>();\n private readonly locks = new Map<ReviewId, Promise<unknown>>();\n private closed = false;\n\n private constructor(root: string, lockCreatedAt: string) {\n this.root = root;\n this.lockPath = join(root, 'lock');\n this.lockCreatedAt = lockCreatedAt;\n }\n\n static async open(root: string, options: ReviewStoreOptions = {}): Promise<ReviewStore> {\n const absolute = resolve(root);\n await mkdir(absolute, { recursive: true });\n const lockPath = join(absolute, 'lock');\n const createdAt = (options.now ?? (() => new Date()))().toISOString();\n\n let handle;\n try {\n handle = await open(lockPath, 'wx');\n await handle.writeFile(JSON.stringify({ pid: process.pid, createdAt }));\n await handle.sync();\n await handle.close();\n } catch (error) {\n if (handle !== undefined) await handle.close().catch(() => undefined);\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;\n\n const existing = await readLock(lockPath);\n const pid = existing?.pid;\n if (pid !== undefined && isPidAlive(pid)) {\n throw new ReviewStoreLockedError(`review store is locked by pid ${pid}`, {\n pid,\n stale: false,\n lockPath,\n });\n }\n const message =\n pid === undefined\n ? `stale lock: unreadable lock file ${lockPath}; remove it manually`\n : `stale lock: pid ${pid} is not running; remove ${lockPath} manually`;\n throw new ReviewStoreLockedError(message, {\n ...(pid === undefined ? {} : { pid }),\n stale: true,\n lockPath,\n });\n }\n\n return new ReviewStore(absolute, createdAt);\n }\n\n async append(reviewId: ReviewId, event: ReviewEvent): Promise<ReviewEvent> {\n const appended = await this.appendInternal(reviewId, event);\n if (appended === null) throw new Error('unconditional append was skipped');\n return appended;\n }\n\n /**\n * Appends an event only when `accept` returns true for the review state\n * observed inside the per-review critical section. Returning null means the\n * event was not written. This makes existence checks atomic with the append.\n */\n async appendIf(\n reviewId: ReviewId,\n event: ReviewEvent,\n accept: (state: ReviewState) => boolean,\n ): Promise<ReviewEvent | null> {\n return await this.appendInternal(reviewId, event, accept);\n }\n\n private async appendInternal(\n reviewId: ReviewId,\n event: ReviewEvent,\n accept?: (state: ReviewState) => boolean,\n ): Promise<ReviewEvent | null> {\n if (this.closed) throw new Error('review store is closed');\n const id = safeReviewId(reviewId);\n if (!isReviewEvent(event)) {\n throw new ReviewEventError('invalid-event', 'append requires a valid review event');\n }\n if (event.reviewId !== id) {\n throw new ReviewEventError(\n 'invalid-review-id',\n `event belongs to ${event.reviewId}, not ${id}`,\n );\n }\n\n // A review's read-fold-append-cache sequence is one critical section. Two\n // concurrent appends must not both read the same event count and write the\n // same sequence number.\n return await this.withReviewLock(id, async () => {\n const dir = this.reviewDir(id);\n await mkdir(dir, { recursive: true });\n const eventsPath = join(dir, 'events.jsonl');\n await this.repairTornTail(eventsPath);\n\n let fileBytes = 0;\n try {\n fileBytes = (await stat(eventsPath)).size;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n\n let entry: CacheEntry | undefined = this.entries.get(id);\n if (entry === undefined) {\n try {\n entry = await this.readEntry(id);\n } catch (error) {\n if (!(error instanceof ReviewNotFoundError)) throw error;\n }\n }\n if (entry === undefined) {\n if (event.type !== 'review/created') throw new ReviewNotFoundError(id);\n entry = { state: event.data.review, eventCount: 0 };\n }\n\n if (accept !== undefined && !accept(entry.state)) return null;\n\n // Validate against the aggregate before touching the log: a rejected event\n // must not leave a line that makes every later replay fail.\n const state = fold(entry.state, event);\n // The append starts after repairTornTail removed an incomplete final\n // line, so a warning that belonged to that line must not survive in the\n // cache we are about to persist.\n if (state.warnings !== undefined) {\n state.warnings = state.warnings.filter((warning) => warning !== 'torn-tail');\n }\n const sequenced = { ...event, seq: entry.eventCount + 1 } as ReviewEvent;\n const payload = `${JSON.stringify(sequenced)}\\n`;\n const handle = await open(eventsPath, 'a');\n try {\n const result = await handle.write(payload);\n if (result.bytesWritten !== Buffer.byteLength(payload)) {\n throw new Error('short event write');\n }\n await handle.sync();\n } finally {\n await handle.close();\n }\n\n const next = {\n state,\n eventCount: entry.eventCount + 1,\n // The stat is taken after repairing a torn tail, so it is the exact\n // byte offset where this append started. Do not trust a cached byte\n // count that may describe a larger pre-repair file.\n bytes: fileBytes + Buffer.byteLength(payload),\n };\n this.entries.set(id, next);\n // The event log is the source of truth. A cache failure must not turn a\n // committed mutation into an error; the next read rebuilds the cache.\n await this.writeCache(id, next).catch(() => undefined);\n return structuredClone(sequenced);\n });\n }\n\n async load(reviewId: ReviewId): Promise<ReviewState> {\n if (this.closed) throw new Error('review store is closed');\n const id = safeReviewId(reviewId);\n return await this.withReviewLock(id, async () => {\n const entry = await this.readState(id);\n return structuredClone(entry.state);\n });\n }\n\n async events(reviewId: ReviewId, after = 0): Promise<ReviewEvent[]> {\n if (this.closed) throw new Error('review store is closed');\n const id = safeReviewId(reviewId);\n if (!Number.isInteger(after) || after < 0) {\n throw new ReviewEventError('invalid-event', 'after must be a non-negative integer');\n }\n return await this.withReviewLock(id, async () => {\n let content: string;\n try {\n content = await readFile(join(this.reviewDir(id), 'events.jsonl'), 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new ReviewNotFoundError(id);\n }\n throw error;\n }\n const { events } = parseEventLog(content, id);\n return structuredClone(events.filter((event) => (event.seq ?? 0) > after));\n });\n }\n\n async list(): Promise<ReviewSummary[]> {\n if (this.closed) throw new Error('review store is closed');\n const reviewsRoot = join(this.root, 'reviews');\n let entries;\n try {\n entries = await readdir(reviewsRoot, { withFileTypes: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return [];\n throw error;\n }\n\n const summaries: ReviewSummary[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const id = entry.name as ReviewId;\n const cache = await this.readCache(id).catch(() => null);\n const cacheFresh =\n cache !== null &&\n cache.state.id === id &&\n cache.eventBytes !== undefined &&\n (await stat(join(this.reviewDir(id), 'events.jsonl')).catch(() => null))?.size ===\n cache.eventBytes;\n if (cache !== null && cacheFresh) {\n if (cache.state.deletedAt === undefined) summaries.push(summary(cache.state));\n continue;\n }\n // A missing or corrupt cache must not hide the review: replay its JSONL\n // log and write a replacement cache as a side effect.\n const rebuilt = await this.readEntry(id).catch(() => null);\n if (rebuilt === null || rebuilt.state.id !== id) continue;\n this.entries.set(id, rebuilt);\n if (rebuilt.state.deletedAt === undefined) summaries.push(summary(rebuilt.state));\n }\n summaries.sort((left, right) => {\n if (left.createdAt !== right.createdAt) return left.createdAt < right.createdAt ? -1 : 1;\n return left.id < right.id ? -1 : left.id > right.id ? 1 : 0;\n });\n return summaries;\n }\n\n async writeSnapshot(snapshotId: string, snapshot: Snapshot): Promise<void> {\n if (this.closed) throw new Error('review store is closed');\n const id = safeSnapshotId(snapshotId);\n if (!isSnapshot(snapshot)) {\n throw new ReviewNotFoundError(id);\n }\n\n const dir = join(this.root, 'snapshots');\n await mkdir(dir, { recursive: true });\n const target = join(dir, `${id}.json`);\n const temp = join(dir, `.${id}.${process.pid}.${randomBytes(6).toString('hex')}.tmp`);\n const handle = await open(temp, 'wx');\n try {\n await handle.writeFile(JSON.stringify(snapshot));\n await handle.sync();\n } finally {\n await handle.close();\n }\n try {\n // A hard link publishes the finished file atomically and fails with\n // EEXIST when the snapshot id is already taken, so snapshots are immutable.\n await link(temp, target);\n } catch (error) {\n await unlink(temp).catch(() => undefined);\n throw error;\n }\n await unlink(temp).catch(() => undefined);\n }\n\n async readSnapshot(snapshotId: string): Promise<Snapshot> {\n if (this.closed) throw new Error('review store is closed');\n const id = safeSnapshotId(snapshotId);\n let raw: string;\n try {\n raw = await readFile(join(this.root, 'snapshots', `${id}.json`), 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new ReviewNotFoundError(id);\n }\n throw error;\n }\n\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n throw new ReviewNotFoundError(id);\n }\n if (!isSnapshot(value)) throw new ReviewNotFoundError(id);\n return structuredClone(normalizeSnapshot(value));\n }\n\n /**\n * Removes closed reviews older than `olderThanDays` and snapshots that no\n * remaining review references. Open reviews are never touched.\n */\n async gc(olderThanDays: number, now: Date = new Date()): Promise<GcResult> {\n if (this.closed) throw new Error('review store is closed');\n if (!Number.isFinite(olderThanDays) || olderThanDays < 0) {\n throw new RangeError('olderThanDays must be a non-negative number');\n }\n const cutoff = now.getTime() - olderThanDays * 24 * 60 * 60 * 1000;\n const reviewsRoot = join(this.root, 'reviews');\n let reviewEntries: Dirent[] = [];\n try {\n reviewEntries = await readdir(reviewsRoot, { withFileTypes: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n\n // Scan directories directly instead of trusting list(): a missing or stale\n // cache must not make an old review invisible to garbage collection.\n const all = new Map<ReviewId, ReviewState>();\n for (const entry of reviewEntries) {\n if (!entry.isDirectory()) continue;\n const id = entry.name as ReviewId;\n const loaded = await this.readEntry(id).catch(() => null);\n if (loaded === null) continue;\n all.set(id, loaded.state);\n this.entries.set(id, loaded);\n }\n\n const removedReviews: ReviewId[] = [];\n for (const [id, state] of all) {\n if (state.status !== 'closed') continue;\n // Newer logs carry the close time; legacy logs fall back to createdAt so\n // their previous collection behavior is preserved.\n const closedTime = new Date(state.closedAt ?? state.createdAt).getTime();\n if (!Number.isFinite(closedTime) || closedTime >= cutoff) continue;\n removedReviews.push(id);\n await rm(this.reviewDir(id), { recursive: true, force: true });\n this.entries.delete(id);\n all.delete(id);\n }\n\n const referenced = new Set<string>();\n for (const state of all.values()) {\n for (const round of state.rounds) referenced.add(round.snapshotId);\n }\n let removedSnapshots = 0;\n let entries: string[] = [];\n try {\n entries = await readdir(join(this.root, 'snapshots'));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n for (const entry of entries) {\n if (!entry.endsWith('.json')) continue;\n const snapshotId = entry.slice(0, -'.json'.length);\n if (referenced.has(snapshotId)) continue;\n try {\n await unlink(join(this.root, 'snapshots', entry));\n removedSnapshots += 1;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n }\n return { removedReviews, removedSnapshots };\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n this.entries.clear();\n const existing = await readLock(this.lockPath);\n if (existing?.pid === process.pid && existing.createdAt === this.lockCreatedAt) {\n await unlink(this.lockPath).catch((error: unknown) => {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n });\n }\n }\n\n /**\n * Serializes work per review without blocking other reviews. A failed task\n * releases the gate so later appends can still make progress.\n */\n private async withReviewLock<T>(reviewId: ReviewId, task: () => Promise<T>): Promise<T> {\n const previous = this.locks.get(reviewId) ?? Promise.resolve();\n let release!: () => void;\n const gate = new Promise<void>((resolveGate) => {\n release = resolveGate;\n });\n const current: Promise<unknown> = previous.catch(() => undefined).then(() => gate);\n this.locks.set(reviewId, current);\n await previous.catch(() => undefined);\n try {\n return await task();\n } finally {\n release();\n if (this.locks.get(reviewId) === current) this.locks.delete(reviewId);\n }\n }\n\n private reviewDir(reviewId: ReviewId): string {\n return join(this.root, 'reviews', reviewId);\n }\n\n private async repairTornTail(eventsPath: string): Promise<void> {\n let content: string;\n try {\n content = await readFile(eventsPath, 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return;\n throw error;\n }\n if (content === '' || content.endsWith('\\n')) return;\n const lastNewline = content.lastIndexOf('\\n');\n await truncate(eventsPath, lastNewline < 0 ? 0 : lastNewline + 1);\n }\n\n /**\n * Reads state without replaying the log when the event file is unchanged.\n * `snapshot.json` is a replay cache, so a matching byte length and event\n * count prove it describes this log prefix. Mutations still go through\n * `readEntry` when the cache is missing or stale, preserving log validation.\n */\n private async readState(reviewId: ReviewId): Promise<CacheEntry> {\n const eventsPath = join(this.reviewDir(reviewId), 'events.jsonl');\n let eventBytes: number;\n try {\n eventBytes = (await stat(eventsPath)).size;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new ReviewNotFoundError(reviewId);\n }\n throw error;\n }\n\n const cache = await this.readCache(reviewId).catch(() => null);\n if (\n cache !== null &&\n cache.eventBytes === eventBytes &&\n cache.eventCount === cache.state.version &&\n cache.state.id === reviewId\n ) {\n const entry = { state: cache.state, eventCount: cache.eventCount, bytes: eventBytes };\n this.entries.set(reviewId, entry);\n return entry;\n }\n\n const entry = await this.readEntry(reviewId);\n this.entries.set(reviewId, entry);\n return entry;\n }\n\n private async readEntry(reviewId: ReviewId): Promise<CacheEntry> {\n const dir = this.reviewDir(reviewId);\n let content: string;\n try {\n content = await readFile(join(dir, 'events.jsonl'), 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new ReviewNotFoundError(reviewId);\n }\n throw error;\n }\n\n const { state, eventCount, events } = parseReview(content, reviewId);\n const cache = await this.readCache(reviewId);\n const eventBytes = Buffer.byteLength(content);\n if (\n cache !== null &&\n cache.eventCount === eventCount &&\n cache.eventBytes === eventBytes &&\n cache.state.version === state.version &&\n cache.state.id === reviewId\n ) {\n return {\n state: {\n ...structuredClone(cache.state),\n warnings: [...(state.warnings ?? [])],\n },\n eventCount,\n events,\n };\n }\n\n const entry = { state, eventCount, bytes: eventBytes, events };\n await this.writeCache(reviewId, entry).catch(() => undefined);\n return entry;\n }\n\n private async readCache(reviewId: ReviewId): Promise<SnapshotCache | null> {\n let raw: string;\n try {\n raw = await readFile(join(this.reviewDir(reviewId), 'snapshot.json'), 'utf8');\n } catch {\n return null;\n }\n try {\n const value: unknown = JSON.parse(raw);\n if (!isRecord(value)) return null;\n if (value.reviewId !== reviewId) return null;\n if (typeof value.eventCount !== 'number' || !Number.isInteger(value.eventCount)) return null;\n if (value.eventBytes !== undefined && typeof value.eventBytes !== 'number') return null;\n if (!isReviewState(value.state)) return null;\n return {\n reviewId,\n eventCount: value.eventCount,\n ...(typeof value.eventBytes === 'number' ? { eventBytes: value.eventBytes } : {}),\n state: value.state,\n };\n } catch {\n return null;\n }\n }\n\n private async writeCache(reviewId: ReviewId, entry: CacheEntry): Promise<void> {\n const dir = this.reviewDir(reviewId);\n const target = join(dir, 'snapshot.json');\n const temp = join(dir, `.snapshot.${process.pid}.${randomBytes(6).toString('hex')}.tmp`);\n const eventBytes =\n entry.bytes ??\n (await stat(join(dir, 'events.jsonl')).then(\n (info) => info.size,\n () => undefined,\n ));\n const payload: SnapshotCache = {\n reviewId,\n eventCount: entry.eventCount,\n ...(eventBytes === undefined ? {} : { eventBytes }),\n state: entry.state,\n };\n const handle = await open(temp, 'wx');\n try {\n await handle.writeFile(JSON.stringify(payload));\n await handle.sync();\n } finally {\n await handle.close();\n }\n try {\n await rename(temp, target);\n } catch (error) {\n await unlink(temp).catch(() => undefined);\n throw error;\n }\n }\n}\n", "import type {\n Finding,\n FindingSink,\n ReviewerBackend,\n ReviewerJob,\n ReviewerReport,\n} from './types.js';\n\nexport interface FakeReviewerOptions {\n report?: ReviewerReport | ((job: ReviewerJob) => ReviewerReport);\n findings?: Finding[];\n}\n\nfunction emptyReport(job: ReviewerJob): ReviewerReport {\n return {\n schemaVersion: 1,\n summary: `Fake review of ${job.reviewId} round ${job.round}`,\n riskLevel: 'low',\n findings: [],\n questions: [],\n tests: { ran: false, commands: [] },\n verification: [],\n };\n}\n\n/** Deterministic in-process reviewer used by tests and local smoke runs. */\nexport class FakeReviewer implements ReviewerBackend {\n readonly kind = 'fake' as const;\n private readonly options: FakeReviewerOptions;\n\n constructor(options: FakeReviewerOptions = {}) {\n this.options = options;\n }\n\n async run(job: ReviewerJob, sink: FindingSink, signal: AbortSignal): Promise<ReviewerReport> {\n if (signal.aborted) throw new Error('reviewer cancelled');\n const report =\n typeof this.options.report === 'function'\n ? this.options.report(job)\n : (this.options.report ?? emptyReport(job));\n const findings = this.options.findings ?? report.findings;\n for (const finding of findings) {\n if (signal.aborted) throw new Error('reviewer cancelled');\n await sink(finding);\n }\n return {\n ...structuredClone(report),\n findings: structuredClone(findings),\n };\n }\n}\n", "import { spawn } from 'node:child_process';\nimport { mkdtemp, open, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { runGit } from '../git/run.js';\nimport { ReviewerError } from './types.js';\nimport type {\n FindingSink,\n GitStatusRunner,\n ReviewerBackend,\n ReviewerJob,\n ReviewerReport,\n} from './types.js';\n\nexport interface CommandReviewerOptions {\n /** argv array only; never passed through a shell. */\n command: readonly string[];\n runGit?: GitStatusRunner;\n timeoutMs?: number;\n env?: NodeJS.ProcessEnv;\n maxOutputBytes?: number;\n}\n\nconst DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;\nconst DEFAULT_MAX_OUTPUT_BYTES = 4 * 1024 * 1024;\nconst BASE_ENV_KEYS = ['PATH', 'HOME', 'LANG', 'TMPDIR', 'TMP', 'TEMP'] as const;\nconst WINDOWS_ENV_KEYS = [\n 'SystemRoot',\n 'ComSpec',\n 'PATHEXT',\n 'USERPROFILE',\n 'APPDATA',\n 'LOCALAPPDATA',\n] as const;\n\nfunction reviewerEnv(job: ReviewerJob, overrides?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = {};\n const keys =\n process.platform === 'win32' ? [...BASE_ENV_KEYS, ...WINDOWS_ENV_KEYS] : BASE_ENV_KEYS;\n for (const key of keys) {\n const value = process.env[key];\n if (value !== undefined) env[key] = value;\n }\n for (const [key, value] of Object.entries(process.env)) {\n if (value === undefined) continue;\n if (key.startsWith('LC_') || key.startsWith('REVIEW_')) env[key] = value;\n }\n env.REVIEW_ID = job.reviewId;\n env.REVIEW_ROUND = String(job.round);\n env.REVIEW_JOB_ID = job.id;\n env.REVIEW_REPO = job.repoRoot;\n return Object.assign(env, overrides);\n}\n\nfunction killProcess(child: ReturnType<typeof spawn>): void {\n if (child.pid !== undefined && process.platform !== 'win32') {\n try {\n // The child is spawned detached, so a negative pid reaches its whole group.\n process.kill(-child.pid, 'SIGKILL');\n return;\n } catch {\n // Fall through to the direct child if the group is already gone.\n }\n }\n child.kill('SIGKILL');\n}\n\nfunction replacePlaceholders(value: string, values: Record<string, string>): string {\n return value.replace(/\\{(promptFile|repo|outputFile|reviewId)\\}/g, (_match, key: string) => {\n return values[key] ?? '';\n });\n}\n\nfunction lastFencedJson(stdout: string): unknown {\n const matches = [...stdout.matchAll(/```(?:json)?[ \\t]*\\r?\\n([\\s\\S]*?)```/g)];\n const last = matches.at(-1)?.[1];\n if (last === undefined) return undefined;\n try {\n return JSON.parse(last);\n } catch {\n throw new ReviewerError('invalid-output', 'last fenced block is not valid JSON');\n }\n}\n\nasync function readOutputFile(outputFile: string, maxBytes: number): Promise<string | undefined> {\n let handle;\n try {\n handle = await open(outputFile, 'r');\n } catch {\n return undefined;\n }\n try {\n const info = await handle.stat();\n if (!info.isFile()) {\n throw new ReviewerError('invalid-output', 'reviewer output file is not a regular file');\n }\n if (info.size > maxBytes) {\n throw new ReviewerError('invalid-output', `reviewer output file exceeded ${maxBytes} bytes`);\n }\n const raw = await handle.readFile({ encoding: 'utf8' });\n if (Buffer.byteLength(raw) > maxBytes) {\n throw new ReviewerError('invalid-output', `reviewer output file exceeded ${maxBytes} bytes`);\n }\n return raw;\n } finally {\n await handle.close();\n }\n}\n\nasync function parseOutput(outputFile: string, stdout: string, maxBytes: number): Promise<unknown> {\n const raw = await readOutputFile(outputFile, maxBytes);\n if (raw !== undefined && raw.trim() !== '') {\n try {\n return JSON.parse(raw);\n } catch {\n throw new ReviewerError('invalid-output', 'reviewer output file is not valid JSON');\n }\n }\n const fenced = lastFencedJson(stdout);\n if (fenced !== undefined) return fenced;\n const trimmed = stdout.trim();\n if (trimmed.startsWith('{')) {\n try {\n return JSON.parse(trimmed);\n } catch {\n throw new ReviewerError('invalid-output', 'reviewer stdout is not valid JSON');\n }\n }\n throw new ReviewerError('invalid-output', 'reviewer produced no JSON output');\n}\n\nasync function status(\n runner: GitStatusRunner,\n repoRoot: string,\n signal: AbortSignal,\n): Promise<string> {\n try {\n const result = await runner(repoRoot, ['status', '--porcelain'], { signal });\n return result.code === 0 ? result.stdout : '';\n } catch {\n return '';\n }\n}\n\n/** Opt-in backend that runs an external reviewer command in the repo root. */\nexport class CommandReviewer implements ReviewerBackend {\n readonly kind = 'command' as const;\n private readonly options: CommandReviewerOptions;\n private child: ReturnType<typeof spawn> | undefined;\n\n constructor(options: CommandReviewerOptions) {\n this.options = options;\n }\n\n async run(job: ReviewerJob, sink: FindingSink, signal: AbortSignal): Promise<ReviewerReport> {\n if (signal.aborted) throw new ReviewerError('cancelled', 'reviewer was cancelled');\n const temp = await mkdtemp(join(tmpdir(), 'cr-reviewer-'));\n const promptFile = join(temp, 'prompt.md');\n const outputFile = join(temp, 'output.json');\n await writeFile(promptFile, job.prompt, 'utf8');\n\n const runner = this.options.runGit ?? runGit;\n const before = await status(runner, job.repoRoot, signal);\n const values = {\n promptFile,\n repo: job.repoRoot,\n outputFile,\n reviewId: job.reviewId,\n };\n const argv = this.options.command.map((part) => replacePlaceholders(part, values));\n if (argv.length === 0 || argv[0] === '') {\n await rm(temp, { recursive: true, force: true });\n throw new ReviewerError('spawn-failed', 'reviewer command is empty');\n }\n\n try {\n const stdout = await this.execute(argv, job, signal);\n const after = await status(runner, job.repoRoot, signal);\n const parsed = await parseOutput(\n outputFile,\n stdout,\n this.options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES,\n );\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n throw new ReviewerError('invalid-output', 'reviewer JSON must be an object');\n }\n const report = parsed as ReviewerReport;\n for (const finding of Array.isArray(report.findings) ? report.findings : []) {\n await sink(finding);\n }\n if (before !== after) return { ...report, dirtyWorktree: true };\n return report;\n } finally {\n await rm(temp, { recursive: true, force: true });\n }\n }\n\n cancel(): void {\n if (this.child !== undefined) killProcess(this.child);\n }\n\n private async execute(\n argv: readonly string[],\n job: ReviewerJob,\n signal: AbortSignal,\n ): Promise<string> {\n const timeoutMs = this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const maxOutput = this.options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;\n return await new Promise<string>((resolve, reject) => {\n const child = spawn(argv[0] as string, argv.slice(1), {\n cwd: job.repoRoot,\n shell: false,\n stdio: ['pipe', 'pipe', 'pipe'],\n detached: process.platform !== 'win32',\n env: reviewerEnv(job, this.options.env),\n });\n this.child = child;\n const chunks: Buffer[] = [];\n const stderr: Buffer[] = [];\n let bytes = 0;\n let settled = false;\n let timedOut = false;\n\n const finish = (error?: Error, value?: string): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n signal.removeEventListener('abort', onAbort);\n this.child = undefined;\n if (error !== undefined) reject(error);\n else resolve(value ?? '');\n };\n const onAbort = (): void => {\n killProcess(child);\n finish(new ReviewerError('cancelled', 'reviewer was cancelled'));\n };\n const timer = setTimeout(() => {\n timedOut = true;\n killProcess(child);\n finish(new ReviewerError('timeout', `reviewer timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n signal.addEventListener('abort', onAbort, { once: true });\n\n child.on('error', (error: NodeJS.ErrnoException) => {\n finish(\n new ReviewerError(\n 'spawn-failed',\n error.code === 'ENOENT' ? `reviewer command not found: ${argv[0]}` : error.message,\n ),\n );\n });\n child.stdout.on('data', (chunk: Buffer) => {\n bytes += chunk.length;\n if (bytes > maxOutput) {\n killProcess(child);\n finish(\n new ReviewerError('invalid-output', `reviewer stdout exceeded ${maxOutput} bytes`),\n );\n return;\n }\n chunks.push(chunk);\n });\n child.stderr.on('data', (chunk: Buffer) => {\n if (stderr.reduce((sum, item) => sum + item.length, 0) < 1024 * 1024) stderr.push(chunk);\n });\n child.on('close', (code) => {\n if (settled) return;\n if (timedOut) {\n finish(new ReviewerError('timeout', `reviewer timed out after ${timeoutMs}ms`));\n return;\n }\n if (code !== 0) {\n finish(\n new ReviewerError(\n 'nonzero-exit',\n `reviewer exited with ${code}: ${Buffer.concat(stderr).toString('utf8').trim()}`,\n ),\n );\n return;\n }\n finish(undefined, Buffer.concat(chunks).toString('utf8'));\n });\n child.stdin.on('error', () => undefined);\n child.stdin.end(job.prompt);\n });\n }\n}\n", "import type { Actor, ReviewId, RoundNo } from '../review/types.js';\nimport type { ReviewManifest, Snapshot } from '../types.js';\n\nexport type FindingSeverity = 'blocker' | 'major' | 'minor' | 'nit';\nexport type FindingCategory =\n | 'security'\n | 'correctness'\n | 'tests'\n | 'performance'\n | 'maintainability'\n | 'api'\n | 'concurrency'\n | 'docs'\n | 'other';\nexport type FindingKind = 'issue' | 'question' | 'praise';\nexport type ReviewerConfidence = 'high' | 'medium' | 'low';\nexport type RiskLevel = 'low' | 'medium' | 'high' | 'critical';\nexport type TestResult = 'pass' | 'fail' | 'unknown';\nexport type VerificationStatus = 'fixed' | 'not-fixed' | 'unclear';\nexport type ReviewerBackendKind = 'fake' | 'command' | 'none' | 'worker';\n\nexport interface ReviewerConfig {\n backend: ReviewerBackendKind;\n command?: string[];\n timeoutMs?: number;\n}\n\nexport interface ReviewSuggestion {\n original: string;\n replacement: string;\n}\n\nexport interface Finding {\n id: string;\n severity: FindingSeverity;\n category: FindingCategory;\n confidence: ReviewerConfidence;\n kind: FindingKind;\n file: string;\n lineStart: number;\n lineEnd: number;\n title: string;\n rationale: string;\n evidence: string;\n suggestion?: ReviewSuggestion;\n /** Suggestion was supplied but could not be matched against the snapshot. */\n unanchored?: boolean;\n}\n\nexport interface ReviewQuestion {\n id: string;\n file: string;\n line: number;\n question: string;\n why: string;\n}\n\nexport interface TestCommand {\n command: string;\n result: TestResult;\n summary: string;\n}\n\nexport interface TestSummary {\n ran: boolean;\n commands: TestCommand[];\n}\n\nexport interface Verification {\n commentId: string;\n status: VerificationStatus;\n evidence: string;\n}\n\nexport interface ReviewerReport {\n schemaVersion: 1;\n summary: string;\n riskLevel: RiskLevel;\n findings: Finding[];\n questions: ReviewQuestion[];\n tests: TestSummary;\n verification: Verification[];\n /** Set by command backends when the repo changed during the run. */\n dirtyWorktree?: boolean;\n}\n\nexport type RejectedReportKind = 'report' | 'finding' | 'question' | 'test' | 'verification';\n\nexport interface RejectedReportItem {\n kind: RejectedReportKind;\n index?: number;\n id?: string;\n reason: string;\n}\n\nexport interface ValidationResult {\n report: ReviewerReport;\n rejected: RejectedReportItem[];\n warnings: string[];\n}\n\n/** Persisted report: validated content plus provenance and rejected items. */\nexport interface AgentReport extends ReviewerReport {\n reviewId: ReviewId;\n round: RoundNo;\n backend: ReviewerBackendKind;\n rejected: RejectedReportItem[];\n warnings: string[];\n dirtyWorktree?: boolean;\n /** True when the configured backend intentionally did not run. */\n skipped?: boolean;\n}\n\nexport interface ReviewerJob {\n id: string;\n reviewId: ReviewId;\n round: RoundNo;\n kind: 'initial' | 'verify';\n repoRoot: string;\n /** Complete markdown prompt handed to the reviewer. */\n prompt: string;\n snapshot: Snapshot;\n /** Full changed-file manifest; absent when only a legacy v1 snapshot is available. */\n manifest?: ReviewManifest;\n}\n\nexport type FindingSink = (finding: Finding) => Promise<void> | void;\n\nexport interface ReviewerBackend {\n readonly kind: ReviewerBackendKind;\n run(job: ReviewerJob, sink: FindingSink, signal: AbortSignal): Promise<ReviewerReport>;\n /** Best-effort cancellation for backends that own an external process. */\n cancel?(): void;\n}\n\nexport type ReviewerErrorCode =\n 'invalid-output' | 'timeout' | 'nonzero-exit' | 'cancelled' | 'spawn-failed';\n\nexport class ReviewerError extends Error {\n readonly code: ReviewerErrorCode;\n\n constructor(code: ReviewerErrorCode, message: string) {\n super(message);\n this.name = 'ReviewerError';\n this.code = code;\n }\n}\n\nexport type GitStatusRunner = (\n cwd: string,\n args: readonly string[],\n options?: { signal?: AbortSignal },\n) => Promise<{ stdout: string; code: number; stderr: string }>;\n\nexport interface ReviewerActorContext {\n actor: Actor;\n requestId?: string;\n}\n", "import type {\n Finding,\n FindingCategory,\n FindingKind,\n FindingSeverity,\n RejectedReportItem,\n ReviewQuestion,\n ReviewerConfidence,\n RiskLevel,\n TestCommand,\n TestResult,\n TestSummary,\n ValidationResult,\n Verification,\n VerificationStatus,\n} from './types.js';\nimport type { FileDiff, Snapshot } from '../types.js';\n\nexport const MAX_TEXT_BYTES = 32 * 1024;\n\nconst CATEGORIES = new Set<FindingCategory>([\n 'security',\n 'correctness',\n 'tests',\n 'performance',\n 'maintainability',\n 'api',\n 'concurrency',\n 'docs',\n 'other',\n]);\nconst CONFIDENCES = new Set<ReviewerConfidence>(['high', 'medium', 'low']);\nconst KINDS = new Set<FindingKind>(['issue', 'question', 'praise']);\nconst RISKS = new Set<RiskLevel>(['low', 'medium', 'high', 'critical']);\nconst TEST_RESULTS = new Set<TestResult>(['pass', 'fail', 'unknown']);\nconst VERIFICATION_STATUSES = new Set<VerificationStatus>(['fixed', 'not-fixed', 'unclear']);\n\nconst REPORT_FIELDS = new Set([\n 'schemaVersion',\n 'summary',\n 'riskLevel',\n 'findings',\n 'questions',\n 'tests',\n 'verification',\n]);\nconst FINDING_FIELDS = new Set([\n 'id',\n 'severity',\n 'category',\n 'confidence',\n 'kind',\n 'file',\n 'lineStart',\n 'lineEnd',\n 'title',\n 'rationale',\n 'evidence',\n 'suggestion',\n]);\nconst QUESTION_FIELDS = new Set(['id', 'file', 'line', 'question', 'why']);\n\n/** LLM reviewers often use a low/medium/high scale; normalize it to our four levels. */\nconst SEVERITY_ALIASES: Record<string, FindingSeverity> = {\n blocker: 'blocker',\n critical: 'blocker',\n high: 'blocker',\n major: 'major',\n medium: 'major',\n minor: 'minor',\n low: 'minor',\n nit: 'nit',\n info: 'nit',\n};\n\n/**\n * Stable id for a finding that omitted one. The incremental `/findings` route\n * validates items one at a time with index 0, so an index-based id would make\n * every item collide; derive it from the content instead.\n */\nfunction autoFindingId(value: Record<string, unknown>): string {\n const basis = [value.file, value.lineStart, value.lineEnd, value.title, value.evidence].join(\n '\\u0000',\n );\n let hash = 2166136261;\n for (let index = 0; index < basis.length; index += 1) {\n hash ^= basis.charCodeAt(index);\n hash = Math.imul(hash, 16777619);\n }\n return `f_auto_${(hash >>> 0).toString(36)}`;\n}\n\nfunction autoQuestionId(value: Record<string, unknown>): string {\n const basis = [value.file, value.line, value.question].join('\\u0000');\n let hash = 2166136261;\n for (let index = 0; index < basis.length; index += 1) {\n hash ^= basis.charCodeAt(index);\n hash = Math.imul(hash, 16777619);\n }\n return `q_auto_${(hash >>> 0).toString(36)}`;\n}\n\nexport class ReportValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ReportValidationError';\n }\n}\n\ninterface ValidationOptions {\n snapshot?: Snapshot;\n maxTextBytes?: number;\n}\n\ninterface Context {\n snapshot?: Snapshot;\n rejected: RejectedReportItem[];\n warnings: string[];\n maxTextBytes: number;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isNonEmpty(value: unknown): value is string {\n return typeof value === 'string' && value.trim() !== '';\n}\n\nfunction isPositiveInt(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= 1;\n}\n\nfunction textWithin(ctx: Context, value: unknown): value is string {\n return typeof value === 'string' && Buffer.byteLength(value, 'utf8') <= ctx.maxTextBytes;\n}\n\nfunction reject(\n ctx: Context,\n kind: RejectedReportItem['kind'],\n reason: string,\n id?: string,\n index?: number,\n): void {\n ctx.rejected.push({\n kind,\n ...(id === undefined ? {} : { id }),\n ...(index === undefined ? {} : { index }),\n reason,\n });\n}\n\nfunction warnUnknown(\n ctx: Context,\n value: Record<string, unknown>,\n allowed: Set<string>,\n label: string,\n): void {\n for (const key of Object.keys(value)) {\n if (!allowed.has(key)) ctx.warnings.push(`unknown-${label}-field:${key}`);\n }\n}\n\nfunction fileLines(file: FileDiff | undefined): string[] | undefined {\n return file?.newLines ?? file?.oldLines;\n}\n\nfunction findFile(snapshot: Snapshot | undefined, path: string): FileDiff | undefined {\n return snapshot?.files.find((file) => file.path === path);\n}\n\n/** Removes indentation and collapses horizontal whitespace for comparison. */\nexport function normalizeCode(value: string): string {\n return value\n .split('\\n')\n .map((line) => line.trim().replace(/[ \\t]+/g, ' '))\n .join('\\n');\n}\n\nfunction validateSuggestion(\n ctx: Context,\n file: FileDiff,\n lineStart: number,\n lineEnd: number,\n value: unknown,\n): { suggestion?: { original: string; replacement: string }; unanchored?: boolean } {\n if (!isRecord(value)) return { unanchored: true };\n const { original, replacement } = value;\n if (!textWithin(ctx, original) || !textWithin(ctx, replacement)) return { unanchored: true };\n const lines = fileLines(file);\n if (lines === undefined) return { unanchored: true };\n const current = lines.slice(lineStart - 1, lineEnd).join('\\n');\n if (normalizeCode(current) !== normalizeCode(original)) return { unanchored: true };\n return { suggestion: { original, replacement } };\n}\n\nfunction validateFinding(\n ctx: Context,\n value: unknown,\n index: number,\n ids: Set<string>,\n): Finding | null {\n if (!isRecord(value)) {\n reject(ctx, 'finding', 'finding must be an object', undefined, index);\n return null;\n }\n warnUnknown(ctx, value, FINDING_FIELDS, 'finding');\n const id = isNonEmpty(value.id) ? value.id : autoFindingId(value);\n const rejected = (reason: string): null => {\n reject(ctx, 'finding', reason, id, index);\n return null;\n };\n if (ids.has(id)) return rejected(`duplicate finding id: ${id}`);\n const severityKey = typeof value.severity === 'string' ? value.severity.toLowerCase() : '';\n const severity = Object.prototype.hasOwnProperty.call(SEVERITY_ALIASES, severityKey)\n ? SEVERITY_ALIASES[severityKey]\n : undefined;\n if (severity === undefined) return rejected('severity must be blocker|major|minor|nit');\n // Keep reports from capable but imperfect models: missing metadata gets a\n // safe default, while present-but-invalid metadata and broken anchors reject.\n let category: FindingCategory = 'other';\n if (value.category !== undefined) {\n if (!CATEGORIES.has(value.category as FindingCategory)) {\n return rejected('category is not a known category');\n }\n category = value.category as FindingCategory;\n }\n let confidence: ReviewerConfidence = 'medium';\n if (value.confidence !== undefined) {\n if (!CONFIDENCES.has(value.confidence as ReviewerConfidence)) {\n return rejected('confidence must be high|medium|low');\n }\n confidence = value.confidence as ReviewerConfidence;\n }\n let kind: FindingKind = 'issue';\n if (value.kind !== undefined) {\n if (!KINDS.has(value.kind as FindingKind))\n return rejected('kind must be issue|question|praise');\n kind = value.kind as FindingKind;\n }\n if (!isNonEmpty(value.file)) return rejected('file must be a non-empty string');\n const lineStart = value.lineStart;\n const lineEnd = value.lineEnd === undefined ? lineStart : value.lineEnd;\n if (!isPositiveInt(lineStart) || !isPositiveInt(lineEnd)) {\n return rejected('lineStart and lineEnd must be positive integers');\n }\n if (lineEnd < lineStart) return rejected('lineEnd must not precede lineStart');\n const title = value.title;\n if (!textWithin(ctx, title)) {\n return rejected(`title must be a string no larger than ${ctx.maxTextBytes} bytes`);\n }\n let rationale: unknown = value.rationale;\n if (rationale === undefined) {\n rationale = textWithin(ctx, value.recommendation) ? value.recommendation : title;\n }\n if (!textWithin(ctx, rationale)) {\n return rejected(`rationale must be a string no larger than ${ctx.maxTextBytes} bytes`);\n }\n const evidence = value.evidence;\n if (!textWithin(ctx, evidence)) {\n return rejected(`evidence must be a string no larger than ${ctx.maxTextBytes} bytes`);\n }\n\n const file = findFile(ctx.snapshot, value.file);\n if (ctx.snapshot !== undefined && file === undefined) {\n return rejected(`file is not present in the snapshot: ${value.file}`);\n }\n const lines = fileLines(file);\n if (lines !== undefined && lineEnd > lines.length) {\n return rejected(`line range ${lineStart}..${lineEnd} exceeds ${lines.length} lines`);\n }\n\n const finding: Finding = {\n id,\n severity,\n category,\n confidence,\n kind,\n file: value.file,\n lineStart,\n lineEnd,\n title,\n rationale,\n evidence,\n };\n if (value.suggestion !== undefined && file !== undefined) {\n const suggestion = validateSuggestion(ctx, file, lineStart, lineEnd, value.suggestion);\n if (suggestion.suggestion !== undefined) finding.suggestion = suggestion.suggestion;\n if (suggestion.unanchored === true) finding.unanchored = true;\n } else if (value.suggestion !== undefined) {\n finding.unanchored = true;\n }\n ids.add(id);\n return finding;\n}\n\nexport interface FindingItemValidation {\n finding: Finding | null;\n rejected: RejectedReportItem[];\n warnings: string[];\n}\n\n/**\n * Validate one incremental finding against the same rules as a full report.\n * Used by the job route so an agent cannot append malformed findings to the\n * event-sourced review before its final report is validated.\n */\nexport function validateFindingItem(\n value: unknown,\n options: { snapshot?: Snapshot; maxTextBytes?: number } = {},\n): FindingItemValidation {\n const ctx: Context = {\n rejected: [],\n warnings: [],\n maxTextBytes: options.maxTextBytes ?? MAX_TEXT_BYTES,\n ...(options.snapshot === undefined ? {} : { snapshot: options.snapshot }),\n };\n const finding = validateFinding(ctx, value, 0, new Set<string>());\n return { finding, rejected: ctx.rejected, warnings: ctx.warnings };\n}\n\nfunction validateQuestion(\n ctx: Context,\n value: unknown,\n index: number,\n ids: Set<string>,\n): ReviewQuestion | null {\n if (!isRecord(value)) {\n reject(ctx, 'question', 'question must be an object', undefined, index);\n return null;\n }\n warnUnknown(ctx, value, QUESTION_FIELDS, 'question');\n const id = isNonEmpty(value.id) ? value.id : autoQuestionId(value);\n const rejected = (reason: string): null => {\n reject(ctx, 'question', reason, id, index);\n return null;\n };\n if (ids.has(id)) return rejected(`duplicate question id: ${id}`);\n if (!isNonEmpty(value.file)) return rejected('file must be a non-empty string');\n if (!isPositiveInt(value.line)) return rejected('line must be a positive integer');\n if (!textWithin(ctx, value.question) || !textWithin(ctx, value.why)) {\n return rejected(`question text must be no larger than ${ctx.maxTextBytes} bytes`);\n }\n const file = findFile(ctx.snapshot, value.file);\n if (ctx.snapshot !== undefined && file === undefined) {\n return rejected(`file is not present in the snapshot: ${value.file}`);\n }\n const lines = fileLines(file);\n if (lines !== undefined && value.line > lines.length) {\n return rejected(`line ${value.line} exceeds ${lines.length} lines`);\n }\n ids.add(id);\n return {\n id,\n file: value.file,\n line: value.line,\n question: value.question,\n why: value.why,\n };\n}\n\nfunction validateTests(ctx: Context, value: unknown): TestSummary {\n if (value === undefined) return { ran: false, commands: [] };\n if (!isRecord(value)) {\n reject(ctx, 'test', 'tests must be an object');\n return { ran: false, commands: [] };\n }\n const ran = value.ran === true;\n const commands: TestCommand[] = [];\n if (Array.isArray(value.commands)) {\n value.commands.forEach((entry, index) => {\n if (!isRecord(entry)) {\n reject(ctx, 'test', 'test command must be an object', undefined, index);\n return;\n }\n if (\n typeof entry.command !== 'string' ||\n typeof entry.summary !== 'string' ||\n typeof entry.result !== 'string' ||\n !TEST_RESULTS.has(entry.result as TestResult)\n ) {\n reject(ctx, 'test', 'invalid test command', undefined, index);\n return;\n }\n if (\n Buffer.byteLength(entry.command, 'utf8') > ctx.maxTextBytes ||\n Buffer.byteLength(entry.summary, 'utf8') > ctx.maxTextBytes\n ) {\n reject(ctx, 'test', 'test command text exceeds the text limit', undefined, index);\n return;\n }\n commands.push({\n command: entry.command,\n result: entry.result as TestResult,\n summary: entry.summary,\n });\n });\n }\n return { ran, commands };\n}\n\nfunction validateVerification(ctx: Context, value: unknown, index: number): Verification | null {\n if (!isRecord(value)) {\n reject(ctx, 'verification', 'verification must be an object', undefined, index);\n return null;\n }\n if (\n !isNonEmpty(value.commentId) ||\n typeof value.status !== 'string' ||\n !VERIFICATION_STATUSES.has(value.status as VerificationStatus) ||\n !textWithin(ctx, value.evidence)\n ) {\n reject(ctx, 'verification', 'invalid verification entry', undefined, index);\n return null;\n }\n return {\n commentId: value.commentId,\n status: value.status as VerificationStatus,\n evidence: value.evidence,\n };\n}\n\n/**\n * Dependency-free validation of reviewer output. Invalid items are rejected\n * individually; the rest of the report is kept.\n */\nexport function validateReport(raw: unknown, options: ValidationOptions = {}): ValidationResult {\n if (!isRecord(raw)) throw new ReportValidationError('reviewer report must be an object');\n if (raw.schemaVersion !== 1) {\n throw new ReportValidationError('reviewer report schemaVersion must be 1');\n }\n\n const ctx: Context = {\n rejected: [],\n warnings: [],\n maxTextBytes: options.maxTextBytes ?? MAX_TEXT_BYTES,\n ...(options.snapshot === undefined ? {} : { snapshot: options.snapshot }),\n };\n warnUnknown(ctx, raw, REPORT_FIELDS, 'report');\n\n const riskLevel: RiskLevel =\n typeof raw.riskLevel === 'string' && RISKS.has(raw.riskLevel as RiskLevel)\n ? (raw.riskLevel as RiskLevel)\n : 'medium';\n if (typeof raw.riskLevel !== 'string' || !RISKS.has(raw.riskLevel as RiskLevel)) {\n ctx.warnings.push('invalid-risk-level');\n }\n\n let summary = typeof raw.summary === 'string' ? raw.summary : '';\n if (typeof raw.summary !== 'string') ctx.warnings.push('invalid-summary');\n if (Buffer.byteLength(summary, 'utf8') > ctx.maxTextBytes) {\n summary = Buffer.from(summary, 'utf8').subarray(0, ctx.maxTextBytes).toString('utf8');\n ctx.warnings.push('summary-truncated');\n }\n\n const findings: Finding[] = [];\n const findingIds = new Set<string>();\n if (Array.isArray(raw.findings)) {\n raw.findings.forEach((entry, index) => {\n const finding = validateFinding(ctx, entry, index, findingIds);\n if (finding !== null) findings.push(finding);\n });\n } else if (raw.findings !== undefined) {\n reject(ctx, 'report', 'findings must be an array');\n }\n\n const questions: ReviewQuestion[] = [];\n const questionIds = new Set<string>();\n if (Array.isArray(raw.questions)) {\n raw.questions.forEach((entry, index) => {\n const question = validateQuestion(ctx, entry, index, questionIds);\n if (question !== null) questions.push(question);\n });\n } else if (raw.questions !== undefined) {\n reject(ctx, 'report', 'questions must be an array');\n }\n\n const verification: Verification[] = [];\n if (Array.isArray(raw.verification)) {\n raw.verification.forEach((entry, index) => {\n const item = validateVerification(ctx, entry, index);\n if (item !== null) verification.push(item);\n });\n } else if (raw.verification !== undefined) {\n reject(ctx, 'report', 'verification must be an array');\n }\n\n return {\n report: {\n schemaVersion: 1,\n summary,\n riskLevel,\n findings,\n questions,\n tests: validateTests(ctx, raw.tests),\n verification,\n },\n rejected: ctx.rejected,\n warnings: ctx.warnings,\n };\n}\n", "import type { DiffScope, Snapshot } from '../types.js';\nimport type { GcResult } from '../review/store.js';\nimport type { AgentReport } from '../reviewer/types.js';\nimport type { IdPrefix } from '../review/ids.js';\nimport type { ReviewEvent } from '../review/events.js';\nimport type { ReviewLifecycle } from '../review/lifecycle.js';\nimport type { ReviewStore } from '../review/store.js';\nimport type {\n Actor,\n AddCommentInput,\n Comment,\n FindingDecision,\n FindingDecisionState,\n FixClaimRecord,\n CommentState,\n ReviewId,\n ReviewState,\n ReviewSummary,\n Initiator,\n RoundNo,\n SubmissionRecord,\n} from '../review/types.js';\nimport type {\n GitStatusRunner,\n ReviewQuestion,\n ReviewerBackend,\n ReviewerConfig,\n Verification,\n} from '../reviewer/types.js';\n\nexport interface CallContext {\n actor: Actor;\n requestId?: string;\n}\n\nexport type ReviewErrorCode =\n 'not-found' | 'validation' | 'conflict' | 'agent-busy' | 'stale-review' | 'internal';\n\nexport class ReviewError extends Error {\n readonly code: ReviewErrorCode;\n readonly details?: Record<string, unknown>;\n\n constructor(code: ReviewErrorCode, message: string, details?: Record<string, unknown>) {\n super(message);\n this.name = 'ReviewError';\n this.code = code;\n if (details !== undefined) this.details = details;\n }\n}\n\nexport interface ServiceCreateInput {\n repoRoot: string;\n title: string;\n scope: DiffScope;\n reviewer?: ReviewerConfig;\n initiator?: Initiator;\n}\n\nexport interface ReviewUpdateInput {\n title?: string;\n reviewer?: ReviewerConfig;\n /** A changed scope creates a new round; repoRoot is never editable. */\n scope?: DiffScope;\n}\n\nexport interface CommentEditInput {\n body: string;\n}\n\nexport interface ReviewView {\n review: ReviewState;\n latestSnapshot: Snapshot | null;\n report: AgentReport | null;\n}\n\nexport interface CommentView {\n comment: Comment;\n}\n\nexport interface ReviewFilter {\n status?: 'open' | 'closed';\n limit?: number;\n offset?: number;\n}\n\nexport interface Page<T> {\n items: T[];\n total: number;\n limit: number;\n offset: number;\n}\n\nexport interface ReplyInput {\n body: string;\n}\n\nexport interface FindingDecisionInput {\n state: FindingDecisionState;\n note?: string;\n}\n\nexport interface FindingDecisionView {\n decision: FindingDecision;\n}\n\nexport interface BulkFindingDecisionInput {\n state: FindingDecisionState;\n /**\n * When present, decide only these findings. Omit it to decide every remaining\n * non-praise finding in the report.\n */\n findingIds?: string[];\n}\n\nexport interface BulkFindingDecisionView {\n /** Decisions appended by this request, in report order. */\n decisions: FindingDecision[];\n /** Findings left untouched because they were praise or already decided. */\n skipped: number;\n}\n\nexport interface TransferAcceptedFindingsView {\n /** Comments created by this idempotent backfill. */\n transferred: number;\n}\n\nexport interface SubmitInput {\n verdict: 'approve' | 'request-changes' | 'comment';\n summary?: string;\n includeResolved?: boolean;\n}\n\nexport interface FeedbackFinding {\n id: string;\n severity: string;\n file: string;\n lineStart: number;\n lineEnd: number;\n title: string;\n rationale: string;\n evidence: string;\n /** Present only when a human accepted or dismissed this finding. */\n decision?: FindingDecisionState;\n /** Human note attached to the decision. */\n note?: string;\n}\n\nexport interface FeedbackComment {\n commentId: string;\n path: string;\n lineStart: number;\n lineEnd: number;\n body: string;\n suggestion?: { original: string; replacement: string };\n}\n\nexport interface FeedbackSuggestion {\n commentId: string;\n path: string;\n lineStart: number;\n lineEnd: number;\n original: string;\n replacement: string;\n}\n\nexport interface FeedbackJson {\n schemaVersion: 1;\n reviewId: ReviewId;\n round: RoundNo;\n verdict: SubmitInput['verdict'];\n title: string;\n scope: {\n baseSha: string;\n headSha: string | null;\n label: string;\n };\n deliveryKey: string;\n summary?: string;\n findings: FeedbackFinding[];\n /** Findings a human dismissed; notes are omitted when the human left none. */\n dismissedFindings: FeedbackFinding[];\n humanComments: FeedbackComment[];\n appliedSuggestions: FeedbackSuggestion[];\n acceptedSuggestions: FeedbackSuggestion[];\n questions: ReviewQuestion[];\n verification: Verification[];\n resolved: {\n count: number;\n commentIds: string[];\n };\n /** Set when the JSON package was reduced to the 100 KiB budget. */\n truncated?: boolean;\n notice?: string;\n}\n\nexport interface FeedbackPackage {\n markdown: string;\n json: FeedbackJson;\n deliveryKey: string;\n}\n\nexport interface SubmissionView {\n reviewId: ReviewId;\n round: RoundNo;\n verdict: SubmitInput['verdict'];\n feedback: FeedbackPackage;\n deliveryKey: string;\n}\n\nexport interface SuggestionActionInput {\n action: 'accept' | 'decline' | 'apply';\n}\n\nexport interface FixStatusInput {\n items: Array<{ commentId: string; status: FixClaimRecord['status']; evidence?: string }>;\n}\n\nexport interface RefreshInput {\n /** Omit to rebuild the latest scope; pass a scope after new commits. */\n scope?: DiffScope;\n}\n\nexport interface LatestFeedbackView {\n submission: SubmissionRecord;\n feedback: FeedbackPackage;\n}\n\nexport interface ServiceSnapshotView {\n snapshot: Snapshot;\n round: RoundNo;\n file?: string;\n}\n\nexport interface ReviewService {\n create(input: ServiceCreateInput, ctx: CallContext): Promise<ReviewView>;\n updateReview(id: ReviewId, input: ReviewUpdateInput, ctx: CallContext): Promise<ReviewView>;\n deleteReview(id: ReviewId, ctx: CallContext, reason?: string): Promise<void>;\n list(filter?: ReviewFilter): Promise<Page<ReviewSummary>>;\n get(id: ReviewId): Promise<ReviewView>;\n snapshot(id: ReviewId, round: RoundNo, file?: string): Promise<ServiceSnapshotView>;\n addComment(id: ReviewId, input: AddCommentInput, ctx: CallContext): Promise<CommentView>;\n editComment(\n id: ReviewId,\n commentId: string,\n input: CommentEditInput,\n ctx: CallContext,\n ): Promise<CommentView>;\n deleteComment(id: ReviewId, commentId: string, ctx: CallContext): Promise<CommentView>;\n reply(id: ReviewId, commentId: string, input: ReplyInput, ctx: CallContext): Promise<CommentView>;\n setCommentState(\n id: ReviewId,\n commentId: string,\n state: CommentState,\n ctx: CallContext,\n ): Promise<CommentView>;\n decideFinding(\n id: ReviewId,\n findingId: string,\n input: FindingDecisionInput,\n ctx: CallContext,\n ): Promise<FindingDecisionView>;\n decideFindings(\n id: ReviewId,\n input: BulkFindingDecisionInput,\n ctx: CallContext,\n ): Promise<BulkFindingDecisionView>;\n transferAcceptedFindings(id: ReviewId, ctx: CallContext): Promise<TransferAcceptedFindingsView>;\n events(id: ReviewId, after?: number): Promise<ReviewEvent[]>;\n suggestionAction(\n id: ReviewId,\n commentId: string,\n action: SuggestionActionInput['action'],\n ctx: CallContext,\n ): Promise<CommentView>;\n refresh(id: ReviewId, input: RefreshInput, ctx: CallContext): Promise<ReviewView>;\n close(id: ReviewId, verdict: 'approved' | 'closed', ctx: CallContext): Promise<ReviewView>;\n claimFixStatus(id: ReviewId, input: FixStatusInput, ctx: CallContext): Promise<void>;\n latestFeedback(id: ReviewId): Promise<LatestFeedbackView | null>;\n gc(olderThanDays: number): Promise<GcResult>;\n submit(id: ReviewId, input: SubmitInput, ctx: CallContext): Promise<SubmissionView>;\n runReviewer(id: ReviewId, ctx: CallContext): Promise<AgentReport>;\n cancelAgent(id: ReviewId, ctx: CallContext): Promise<void>;\n}\n\nexport interface ReviewServiceImplDeps {\n lifecycle: ReviewLifecycle;\n store: ReviewStore;\n snapshots: {\n build(input: { repoRoot: string; scope: DiffScope }): Promise<Snapshot>;\n };\n now?: () => Date;\n newId?: (prefix: IdPrefix) => string;\n backendFactory?: (config: ReviewerConfig) => ReviewerBackend;\n runGit?: GitStatusRunner;\n /** Upper bound for the in-memory request-id cache. */\n idempotencyLimit?: number;\n}\n", "import type { Snapshot } from '../types.js';\nimport type { AgentReport, Finding } from '../reviewer/types.js';\nimport type { Comment, FindingDecision, ReviewState, RoundNo } from '../review/types.js';\nimport type {\n FeedbackComment,\n FeedbackFinding,\n FeedbackJson,\n FeedbackPackage,\n FeedbackSuggestion,\n SubmitInput,\n} from './types.js';\n\nexport const FEEDBACK_BYTE_LIMIT = 100 * 1024;\n\nexport interface BuildFeedbackInput {\n review: ReviewState;\n snapshot: Snapshot;\n report: AgentReport | null;\n round: RoundNo;\n verdict: SubmitInput['verdict'];\n deliveryKey: string;\n summary?: string;\n includeResolved?: boolean;\n}\n\nfunction latestAnchor(\n comment: Comment,\n): { path: string; lineStart: number; lineEnd: number } | null {\n const anchor = comment.anchors.at(-1);\n if (anchor === undefined) return null;\n return { path: anchor.path, lineStart: anchor.lineStart, lineEnd: anchor.lineEnd };\n}\n\nfunction isApplied(comment: Comment): boolean {\n return comment.outcomes.some((outcome) => outcome.status === 'applied');\n}\n\nfunction suggestionOf(comment: Comment): FeedbackSuggestion | null {\n const anchor = latestAnchor(comment);\n if (anchor === null || comment.suggestion === undefined) return null;\n return {\n commentId: comment.id,\n path: anchor.path,\n lineStart: anchor.lineStart,\n lineEnd: anchor.lineEnd,\n original: comment.suggestion.original,\n replacement: comment.suggestion.replacement,\n };\n}\n\nfunction humanComment(\n comment: Comment,\n anchor: { path: string; lineStart: number; lineEnd: number },\n): FeedbackComment {\n const item: FeedbackComment = {\n commentId: comment.id,\n path: anchor.path,\n lineStart: anchor.lineStart,\n lineEnd: anchor.lineEnd,\n body: comment.body,\n };\n if (comment.suggestion !== undefined) item.suggestion = comment.suggestion;\n return item;\n}\n\nfunction latestDecision(\n review: ReviewState,\n findingId: string,\n round: RoundNo,\n): FindingDecision | undefined {\n const decisions = review.findingDecisions ?? [];\n for (let index = decisions.length - 1; index >= 0; index -= 1) {\n const decision = decisions[index];\n if (decision?.findingId === findingId && decision.round === round) return decision;\n }\n return undefined;\n}\n\nfunction findingItem(finding: Finding, decision?: FindingDecision): FeedbackFinding {\n return {\n id: finding.id,\n severity: finding.severity,\n file: finding.file,\n lineStart: finding.lineStart,\n lineEnd: finding.lineEnd,\n title: finding.title,\n rationale: finding.rationale,\n evidence: finding.evidence,\n ...(decision === undefined ? {} : { decision: decision.state }),\n ...(decision?.note === undefined ? {} : { note: decision.note }),\n };\n}\n\nfunction findingLabel(finding: Finding, decision?: FindingDecision): string {\n if (decision?.state === 'accepted') {\n return `[accepted][${finding.severity}]`;\n }\n return `[${finding.severity}]`;\n}\n\nfunction findingLines(finding: Finding, decision?: FindingDecision): string[] {\n return [\n `- ${findingLabel(finding, decision)}[${finding.file}:${finding.lineStart}] ${finding.title}`,\n ` ${finding.rationale}`,\n ` > ${finding.evidence.replace(/\\n/g, '\\n > ')}`,\n ...(decision?.note === undefined ? [] : [` \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430: ${decision.note}`]),\n ];\n}\n\nfunction actionableFinding(finding: Finding, decision: FindingDecision | undefined): boolean {\n if (finding.kind === 'praise') return false;\n if (decision?.state === 'dismissed') return false;\n if (decision?.state === 'accepted') return true;\n return finding.severity === 'blocker' || finding.severity === 'major';\n}\n\nfunction verdictLabel(verdict: SubmitInput['verdict']): string {\n if (verdict === 'approve') return 'approved';\n if (verdict === 'request-changes') return 'changes requested';\n return 'comment';\n}\n\nfunction section(lines: string[], title: string, body: string[]): void {\n if (body.length === 0) return;\n lines.push(`### ${title}`, ...body, '');\n}\n\nexport function jsonBytes(value: FeedbackJson): number {\n return Buffer.byteLength(JSON.stringify(value), 'utf8');\n}\n\nfunction capFeedbackJson(input: FeedbackJson): FeedbackJson {\n if (jsonBytes(input) <= FEEDBACK_BYTE_LIMIT) return input;\n const json = structuredClone(input);\n json.truncated = true;\n json.notice = `feedback json truncated at ${FEEDBACK_BYTE_LIMIT} bytes`;\n\n for (const comment of json.humanComments) {\n if (jsonBytes(json) <= FEEDBACK_BYTE_LIMIT) break;\n if (comment.body.length > 16 * 1024) {\n const excess = jsonBytes(json) - FEEDBACK_BYTE_LIMIT;\n comment.body = truncateUtf8(\n comment.body,\n Math.max(0, Buffer.byteLength(comment.body, 'utf8') - excess - 1024),\n );\n }\n }\n const arrays: Array<\n keyof Pick<\n FeedbackJson,\n | 'findings'\n | 'dismissedFindings'\n | 'questions'\n | 'acceptedSuggestions'\n | 'appliedSuggestions'\n | 'verification'\n | 'humanComments'\n >\n > = [\n 'findings',\n 'dismissedFindings',\n 'questions',\n 'acceptedSuggestions',\n 'appliedSuggestions',\n 'verification',\n 'humanComments',\n ];\n for (const key of arrays) {\n while (jsonBytes(json) > FEEDBACK_BYTE_LIMIT && json[key].length > 0) json[key].pop();\n }\n if (jsonBytes(json) > FEEDBACK_BYTE_LIMIT) json.summary = truncateUtf8(json.summary ?? '', 1024);\n if (jsonBytes(json) > FEEDBACK_BYTE_LIMIT) json.notice = 'feedback json truncated';\n if (jsonBytes(json) > FEEDBACK_BYTE_LIMIT) {\n json.title = truncateUtf8(json.title, 1024);\n json.scope = { ...json.scope, label: truncateUtf8(json.scope.label, 1024) };\n }\n if (jsonBytes(json) > FEEDBACK_BYTE_LIMIT) {\n json.findings = [];\n json.dismissedFindings = [];\n json.questions = [];\n json.acceptedSuggestions = [];\n json.appliedSuggestions = [];\n json.verification = [];\n json.humanComments = [];\n }\n return json;\n}\n\nfunction truncateUtf8(value: string, maxBytes: number): string {\n const bytes = Buffer.from(value, 'utf8');\n if (bytes.length <= maxBytes) return value;\n let end = maxBytes;\n while (end > 0 && (bytes[end] ?? 0) >= 0x80 && (bytes[end] ?? 0) < 0xc0) end -= 1;\n return bytes.subarray(0, end).toString('utf8');\n}\n\n/** Deterministic feedback package for one submission. */\nexport function buildFeedback(input: BuildFeedbackInput): FeedbackPackage {\n const { review, snapshot, report, round, verdict, deliveryKey } = input;\n const activeComments = review.comments.filter((comment) => comment.deletedAt === undefined);\n const openComments = activeComments.filter(\n (comment) => comment.author.kind === 'human' && comment.state === 'open',\n );\n const resolved = activeComments.filter(\n (comment) => comment.author.kind === 'human' && comment.state === 'resolved',\n );\n\n const reportFindings = report?.findings ?? [];\n const decisions = new Map<string, FindingDecision>();\n for (const finding of reportFindings) {\n const decision = latestDecision(review, finding.id, round);\n if (decision !== undefined) decisions.set(finding.id, decision);\n }\n const addressedFindingIds = new Set(\n activeComments\n .filter((comment) => comment.state === 'resolved' && comment.sourceFindingId !== undefined)\n .map((comment) => comment.sourceFindingId),\n );\n const findings = reportFindings.filter(\n (finding) =>\n !addressedFindingIds.has(finding.id) && actionableFinding(finding, decisions.get(finding.id)),\n );\n const dismissed = reportFindings.filter(\n (finding) => decisions.get(finding.id)?.state === 'dismissed',\n );\n const humanComments: FeedbackComment[] = [];\n const accepted: FeedbackSuggestion[] = [];\n const applied: FeedbackSuggestion[] = [];\n for (const comment of openComments) {\n const anchor = latestAnchor(comment);\n if (anchor === null) continue;\n humanComments.push(humanComment(comment, anchor));\n const suggestion = suggestionOf(comment);\n if (suggestion !== null) {\n if (isApplied(comment)) applied.push(suggestion);\n else accepted.push(suggestion);\n }\n }\n for (const comment of activeComments) {\n if (comment.author.kind === 'human' && isApplied(comment)) {\n const suggestion = suggestionOf(comment);\n if (suggestion !== null && !applied.some((item) => item.commentId === suggestion.commentId)) {\n applied.push(suggestion);\n }\n }\n }\n\n const json: FeedbackJson = {\n schemaVersion: 1,\n reviewId: review.id,\n round,\n verdict,\n title: review.title,\n scope: {\n baseSha: snapshot.scope.baseSha,\n headSha: snapshot.scope.headSha,\n label: snapshot.scope.label,\n },\n deliveryKey,\n findings: findings.map((finding) => findingItem(finding, decisions.get(finding.id))),\n dismissedFindings: dismissed.map((finding) => findingItem(finding, decisions.get(finding.id))),\n humanComments,\n appliedSuggestions: applied,\n acceptedSuggestions: accepted,\n questions: report?.questions ?? [],\n verification: report?.verification ?? [],\n resolved: {\n count: resolved.length,\n commentIds: resolved.map((comment) => comment.id),\n },\n };\n if (input.summary !== undefined) json.summary = input.summary;\n\n const lines: string[] = [\n `## \u0420\u0435\u0432\u044C\u044E \u00AB${review.title}\u00BB \u2014 ${verdictLabel(verdict)} (round ${round})`,\n `Review: /review/${review.id}?round=${round}`,\n `Scope: ${snapshot.scope.label} (${snapshot.scope.baseSha}..${snapshot.scope.headSha ?? 'worktree'})`,\n '',\n ];\n if (json.summary !== undefined) lines.push(json.summary, '');\n\n section(\n lines,\n '\u0417\u0430\u043C\u0435\u0447\u0430\u043D\u0438\u044F \u0430\u0433\u0435\u043D\u0442\u0430 (\u043A \u0438\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u044E)',\n findings.flatMap((finding) => findingLines(finding, decisions.get(finding.id))),\n );\n\n section(\n lines,\n '\u041E\u0442\u043A\u043B\u043E\u043D\u0435\u043D\u043E \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u043E\u043C (\u043D\u0435 \u043F\u043E\u0432\u0442\u043E\u0440\u044F\u0442\u044C)',\n dismissed.flatMap((finding) => {\n const decision = decisions.get(finding.id);\n if (decision?.note === undefined) return [];\n return [`- [${finding.file}:${finding.lineStart}] ${finding.title} \u2014 ${decision.note}`];\n }),\n );\n\n section(\n lines,\n '\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 (open)',\n humanComments.map((comment) => `- [${comment.path}:${comment.lineStart}] ${comment.body}`),\n );\n\n section(lines, '\u041F\u0440\u0438\u043D\u044F\u0442\u044B\u0435 suggested \u043F\u0440\u0430\u0432\u043A\u0438', [\n ...applied.map(\n (suggestion) =>\n `- [${suggestion.path}:${suggestion.lineStart}] \u043F\u0440\u0438\u043C\u0435\u043D\u0435\u043D\u043E \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u043E\u043C (\u043D\u0435 \u043F\u0440\u0438\u043C\u0435\u043D\u044F\u0442\u044C \u043F\u043E\u0432\u0442\u043E\u0440\u043D\u043E)`,\n ),\n ...accepted.flatMap((suggestion) => [\n `- [${suggestion.path}:${suggestion.lineStart}] \u043F\u0440\u0438\u043D\u044F\u0442\u043E, \u043D\u043E \u043D\u0435 \u043F\u0440\u0438\u043C\u0435\u043D\u0435\u043D\u043E (\u043F\u0430\u0442\u0447 \u043D\u0438\u0436\u0435)`,\n '```diff',\n ...suggestion.original.split('\\n').map((line) => `- ${line}`),\n ...suggestion.replacement.split('\\n').map((line) => `+ ${line}`),\n '```',\n ]),\n ]);\n\n section(\n lines,\n '\u0412\u043E\u043F\u0440\u043E\u0441\u044B \u043A \u0442\u0435\u0431\u0435',\n (report?.questions ?? []).map(\n (question) => `- [${question.id}] ${question.question} \u2014 ${question.why}`,\n ),\n );\n\n if (resolved.length > 0 || input.includeResolved === true) {\n section(\n lines,\n '\u0423\u0436\u0435 \u0438\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043E \u0432 \u044D\u0442\u043E\u043C \u0440\u0430\u0443\u043D\u0434\u0435',\n resolved.map((comment) => `- [${comment.id}] resolved`),\n );\n }\n\n lines.push(\n '### \u0418\u043D\u0441\u0442\u0440\u0443\u043A\u0446\u0438\u044F',\n '\u041F\u0440\u0430\u0432\u044C \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0435\u0440\u0435\u0447\u0438\u0441\u043B\u0435\u043D\u043D\u043E\u0435, \u043D\u0435 \u043F\u0435\u0440\u0435\u043F\u0438\u0441\u044B\u0432\u0430\u0439 \u043D\u0435\u0441\u0432\u044F\u0437\u0430\u043D\u043D\u044B\u0439 \u043A\u043E\u0434, \u043F\u0440\u043E\u0433\u043E\u043D\u0438 \u0442\u0435\u0441\u0442\u044B,',\n '\u0437\u0430\u0442\u0435\u043C \u0432\u044B\u0437\u043E\u0432\u0438 review_refresh(reviewId), \u043F\u043E\u0441\u043C\u043E\u0442\u0440\u0438 \u043E\u0442\u043A\u0440\u044B\u0442\u044B\u0435 \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 \u0447\u0435\u0440\u0435\u0437',\n 'review_comments_list(reviewId) \u0438 \u0437\u0430\u043A\u0440\u043E\u0439 \u0438\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043D\u044B\u0435 review_resolve_comment(reviewId, commentId).',\n '\u0415\u0441\u043B\u0438 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u043F\u043E\u0432\u0442\u043E\u0440\u043D\u043E\u0435 \u2014 \u043D\u0435 \u043F\u0440\u0438\u043C\u0435\u043D\u044F\u0439 \u043F\u0440\u0430\u0432\u043A\u0438 \u0434\u0432\u0430\u0436\u0434\u044B.',\n );\n\n let markdown = lines.join('\\n');\n if (Buffer.byteLength(markdown, 'utf8') > FEEDBACK_BYTE_LIMIT) {\n const notice = `\\n\\n\u2026 (feedback truncated at ${FEEDBACK_BYTE_LIMIT} bytes; see [review](/review/${review.id}?round=${round}))`;\n const room = FEEDBACK_BYTE_LIMIT - Buffer.byteLength(notice, 'utf8');\n markdown = `${truncateUtf8(markdown, room)}${notice}`;\n }\n\n return { markdown, json: capFeedbackJson(json), deliveryKey };\n}\n", "import { createHash } from 'node:crypto';\nimport { createId } from '../review/ids.js';\nimport { ReviewNotFoundError } from '../review/store.js';\nimport type { GcResult } from '../review/store.js';\nimport { ReviewLifecycleError } from '../review/lifecycle.js';\nimport { createEvent } from '../review/events.js';\nimport type { ReviewEvent } from '../review/events.js';\nimport type {\n AddCommentInput,\n CommentState,\n FindingDecision,\n ReviewId,\n ReviewState,\n ReviewSummary,\n Round,\n RoundNo,\n SubmissionRecord,\n} from '../review/types.js';\nimport type { DiffScope, Snapshot } from '../types.js';\nimport { manifestFromSnapshot } from '../diff/manifest.js';\nimport { CommandReviewer } from '../reviewer/command.js';\nimport { FakeReviewer } from '../reviewer/fake.js';\nimport { ReviewerError } from '../reviewer/types.js';\nimport type { IdPrefix } from '../review/ids.js';\nimport type {\n AgentReport,\n ReviewerBackend,\n ReviewerConfig,\n ReviewerJob,\n ReviewerReport,\n} from '../reviewer/types.js';\nimport { validateReport, ReportValidationError } from '../reviewer/validate.js';\nimport { isFinalReviewReport } from '../review/final.js';\nimport { buildFeedback } from './feedback.js';\nimport { ReviewError } from './types.js';\nimport type {\n BulkFindingDecisionInput,\n BulkFindingDecisionView,\n CallContext,\n TransferAcceptedFindingsView,\n CommentEditInput,\n CommentView,\n FindingDecisionInput,\n FindingDecisionView,\n Page,\n ReviewFilter,\n ReviewServiceImplDeps,\n ReviewService,\n ReviewUpdateInput,\n ReviewView,\n ServiceCreateInput,\n ServiceSnapshotView,\n SubmissionView,\n SubmitInput,\n SuggestionActionInput,\n FixStatusInput,\n RefreshInput,\n LatestFeedbackView,\n} from './types.js';\n\nconst IDEMPOTENCY_LIMIT = 1000;\nconst MAX_BULK_FINDING_IDS = 1000;\nconst VERDICTS = new Set(['approve', 'request-changes', 'comment']);\n\nfunction normalizeBulkFindingIds(ids: unknown, reviewId: ReviewId): Set<string> {\n if (!Array.isArray(ids)) {\n throw new ReviewError('validation', 'findingIds must be an array', { id: reviewId });\n }\n if (ids.length === 0) {\n throw new ReviewError('validation', 'findingIds must not be empty', { id: reviewId });\n }\n if (ids.length > MAX_BULK_FINDING_IDS) {\n throw new ReviewError(\n 'validation',\n `findingIds must contain at most ${MAX_BULK_FINDING_IDS} entries`,\n { id: reviewId },\n );\n }\n const selected = new Set<string>();\n for (const findingId of ids) {\n if (typeof findingId !== 'string' || findingId.trim() === '') {\n throw new ReviewError('validation', 'findingIds must contain non-empty strings', {\n id: reviewId,\n });\n }\n selected.add(findingId);\n }\n return selected;\n}\n\nfunction bulkSelectionKey(selected: Set<string> | null): string {\n if (selected === null) return 'all';\n return createHash('sha256')\n .update([...selected].sort().join('\\u0000'))\n .digest('hex');\n}\nconst COMMENT_STATES = new Set<CommentState>(['open', 'resolved', 'dismissed']);\n\nfunction clone<T>(value: T): T {\n return structuredClone(value);\n}\n\nfunction agentIsActive(review: ReviewState): boolean {\n return review.agent?.status === 'queued' || review.agent?.status === 'running';\n}\n\nfunction scopeFromSnapshot(snapshot: Snapshot): DiffScope {\n const scope = snapshot.scope;\n if (scope.kind === 'worktree') return { kind: 'worktree', baseRef: scope.baseRef ?? 'HEAD' };\n if (scope.kind === 'commit') {\n return { kind: 'commit', sha: scope.headSha ?? scope.baseSha };\n }\n if (scope.kind === 'commits') {\n return { kind: 'commits', shas: scope.shas ?? [] };\n }\n return {\n kind: 'range',\n baseRef: scope.baseSha,\n headRef: scope.headRef ?? scope.headSha ?? 'HEAD',\n };\n}\n\nfunction scopeKey(scope: DiffScope): string {\n if (scope.kind === 'range') {\n return `range:${scope.baseRef}\\u0000${scope.headRef}\\u0000${scope.twoDot === true}`;\n }\n if (scope.kind === 'worktree') return `worktree:${scope.baseRef}`;\n if (scope.kind === 'commit') return `commit:${scope.sha}`;\n return `commits:${scope.shas.join('\\u0000')}`;\n}\n\nfunction assertContext(ctx: CallContext): void {\n if (ctx === undefined || ctx.actor === undefined) {\n throw new ReviewError('validation', 'CallContext with an actor is required');\n }\n}\n\nfunction validateInitiator(value: ServiceCreateInput['initiator']): void {\n if (value === undefined) return;\n if (typeof value !== 'object' || value === null) {\n throw new ReviewError('validation', 'initiator must be an object');\n }\n if (typeof value.harness !== 'string' || value.harness.trim() === '') {\n throw new ReviewError('validation', 'initiator.harness must be a non-empty string');\n }\n if (typeof value.sessionId !== 'string' || value.sessionId.trim() === '') {\n throw new ReviewError('validation', 'initiator.sessionId must be a non-empty string');\n }\n for (const field of ['cwd', 'agentPreset'] as const) {\n const fieldValue = value[field];\n if (fieldValue !== undefined && (typeof fieldValue !== 'string' || fieldValue.trim() === '')) {\n throw new ReviewError('validation', `initiator.${field} must be a non-empty string`);\n }\n }\n}\n\nfunction validateReviewer(config: ReviewerConfig): void {\n if (!['fake', 'command', 'none', 'worker'].includes(config.backend)) {\n throw new ReviewError('validation', `unknown reviewer backend: ${config.backend}`);\n }\n if (config.backend === 'command') {\n if (!Array.isArray(config.command) || config.command.length === 0) {\n throw new ReviewError('validation', 'command reviewer requires a non-empty argv array');\n }\n if (config.command.some((part) => typeof part !== 'string' || part === '')) {\n throw new ReviewError(\n 'validation',\n 'command reviewer argv entries must be non-empty strings',\n );\n }\n }\n}\n\nfunction mapLifecycleCode(code: ReviewLifecycleError['code']): ReviewError['code'] {\n switch (code) {\n case 'not-found':\n case 'comment-not-found':\n case 'finding-not-found':\n return 'not-found';\n case 'closed':\n case 'duplicate-round':\n case 'round-order':\n return 'conflict';\n case 'no-rounds':\n case 'snapshot-mismatch':\n case 'invalid-input':\n return 'validation';\n }\n}\n\n/**\n * Application service for reviews. Transports map requests to these methods;\n * every mutation is serialized by the store and idempotent by request id.\n */\nexport class ReviewServiceImpl implements ReviewService {\n private readonly lifecycle: ReviewServiceImplDeps['lifecycle'];\n private readonly store: ReviewServiceImplDeps['store'];\n private readonly snapshots: ReviewServiceImplDeps['snapshots'];\n private readonly now: () => Date;\n private readonly newId: (prefix: IdPrefix) => string;\n private readonly backendFactory?: ReviewServiceImplDeps['backendFactory'];\n private readonly runGit?: ReviewServiceImplDeps['runGit'];\n private readonly idempotencyLimit: number;\n private readonly results = new Map<string, unknown>();\n private readonly inflight = new Map<string, Promise<unknown>>();\n private readonly running = new Set<ReviewId>();\n private readonly active = new Map<\n ReviewId,\n { controller: AbortController; backend?: ReviewerBackend }\n >();\n\n constructor(deps: ReviewServiceImplDeps) {\n this.lifecycle = deps.lifecycle;\n this.store = deps.store;\n this.snapshots = deps.snapshots;\n this.now = deps.now ?? (() => new Date());\n this.newId = deps.newId ?? ((prefix) => createId(prefix, this.now));\n this.backendFactory = deps.backendFactory;\n this.runGit = deps.runGit;\n this.idempotencyLimit = deps.idempotencyLimit ?? IDEMPOTENCY_LIMIT;\n }\n\n async create(input: ServiceCreateInput, ctx: CallContext): Promise<ReviewView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (typeof input.title !== 'string' || input.title.trim() === '') {\n throw new ReviewError('validation', 'title must be non-empty');\n }\n if (typeof input.repoRoot !== 'string' || input.repoRoot.trim() === '') {\n throw new ReviewError('validation', 'repoRoot must be non-empty');\n }\n if (typeof input.scope !== 'object' || input.scope === null) {\n throw new ReviewError('validation', 'scope is required');\n }\n const reviewer = input.reviewer ?? { backend: 'none' as const };\n validateReviewer(reviewer);\n validateInitiator(input.initiator);\n\n let snapshot: Snapshot;\n try {\n snapshot = await this.snapshots.build({ repoRoot: input.repoRoot, scope: input.scope });\n } catch (error) {\n throw this.translate(error);\n }\n\n let state: ReviewState;\n try {\n state = await this.lifecycle.create({\n title: input.title,\n repoRoot: input.repoRoot,\n actor: ctx.actor,\n reviewer,\n ...(input.initiator === undefined ? {} : { initiator: input.initiator }),\n });\n await this.lifecycle.addRound(state.id, snapshot, ctx.actor);\n } catch (error) {\n throw this.translate(error);\n }\n return await this.get(state.id);\n },\n 'reviews.create',\n ctx.requestId,\n );\n }\n\n async updateReview(\n id: ReviewId,\n input: ReviewUpdateInput,\n ctx: CallContext,\n ): Promise<ReviewView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (\n input.title === undefined &&\n input.reviewer === undefined &&\n input.scope === undefined\n ) {\n throw new ReviewError('validation', 'review update is empty');\n }\n if (input.title !== undefined && typeof input.title !== 'string') {\n throw new ReviewError('validation', 'title must be a string');\n }\n if (input.title !== undefined && input.title.trim() === '') {\n throw new ReviewError('validation', 'title must be non-empty');\n }\n if (input.reviewer !== undefined) validateReviewer(input.reviewer);\n const review = await this.requireReview(id);\n if (review.status === 'closed') {\n throw new ReviewError('conflict', `review is closed: ${id}`, { id });\n }\n\n let snapshot: Snapshot | undefined;\n if (input.scope !== undefined) {\n if (this.running.has(id) || agentIsActive(review)) {\n throw new ReviewError('agent-busy', `a reviewer is active for ${id}`, { id });\n }\n const latest = await this.latestSnapshotOrThrow(review);\n if (scopeKey(input.scope) !== scopeKey(scopeFromSnapshot(latest))) {\n try {\n snapshot = await this.snapshots.build({\n repoRoot: review.repoRoot,\n scope: input.scope,\n });\n } catch (error) {\n throw this.translate(error);\n }\n }\n }\n\n if (input.title !== undefined || input.reviewer !== undefined) {\n try {\n await this.lifecycle.updateReview(\n id,\n {\n ...(input.title === undefined ? {} : { title: input.title }),\n ...(input.reviewer === undefined ? {} : { reviewer: input.reviewer }),\n },\n ctx.actor,\n );\n } catch (error) {\n throw this.translate(error);\n }\n }\n if (snapshot !== undefined) {\n try {\n await this.lifecycle.refresh(id, snapshot, ctx.actor);\n } catch (error) {\n throw this.translate(error);\n }\n }\n return await this.get(id);\n },\n `review.update:${id}`,\n ctx.requestId,\n );\n }\n\n async deleteReview(id: ReviewId, ctx: CallContext, reason?: string): Promise<void> {\n assertContext(ctx);\n await this.idempotent(\n async () => {\n let review: ReviewState;\n try {\n review = await this.lifecycle.get(id);\n } catch (error) {\n throw this.translate(error);\n }\n if (review.deletedAt !== undefined) return;\n const active = this.active.get(id);\n active?.controller.abort();\n active?.backend?.cancel?.();\n try {\n await this.lifecycle.deleteReview(id, ctx.actor, reason);\n } catch (error) {\n throw this.translate(error);\n }\n },\n `review.delete:${id}`,\n ctx.requestId,\n );\n }\n\n async get(id: ReviewId): Promise<ReviewView> {\n let review: ReviewState;\n try {\n review = await this.lifecycle.get(id);\n } catch (error) {\n throw this.translate(error);\n }\n if (review.deletedAt !== undefined) {\n throw new ReviewError('not-found', `review not found: ${id}`, { id });\n }\n const latestSnapshot = await this.readLatestSnapshot(review);\n return {\n review,\n latestSnapshot,\n report: review.report ?? null,\n };\n }\n\n async list(filter: ReviewFilter = {}): Promise<Page<ReviewSummary>> {\n const limit = Math.min(Math.max(Math.trunc(filter.limit ?? 50), 1), 100);\n const offset = Math.max(Math.trunc(filter.offset ?? 0), 0);\n let items: ReviewSummary[];\n try {\n items = await this.lifecycle.list();\n } catch (error) {\n throw this.translate(error);\n }\n if (filter.status !== undefined) {\n items = items.filter((item) => item.status === filter.status);\n }\n return {\n items: items.slice(offset, offset + limit),\n total: items.length,\n limit,\n offset,\n };\n }\n\n async snapshot(id: ReviewId, round: RoundNo, file?: string): Promise<ServiceSnapshotView> {\n const review = await this.requireReview(id);\n const target = review.rounds.find((item) => item.no === round);\n if (target === undefined) {\n throw new ReviewError('not-found', `round ${round} not found for ${id}`, { id, round });\n }\n let snapshot: Snapshot;\n try {\n snapshot = await this.store.readSnapshot(target.snapshotId);\n } catch (error) {\n throw this.translate(error);\n }\n if (file !== undefined) {\n const selected = snapshot.files.find((item) => item.path === file);\n if (selected === undefined) {\n throw new ReviewError('not-found', `file not found in round ${round}: ${file}`, {\n id,\n round,\n file,\n });\n }\n // The file query bounds the rendered view, not the manifest or its totals.\n snapshot = { ...snapshot, files: [clone(selected)] };\n }\n return { snapshot, round, ...(file === undefined ? {} : { file }) };\n }\n\n async addComment(id: ReviewId, input: AddCommentInput, ctx: CallContext): Promise<CommentView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (typeof input.body !== 'string' || input.body.trim() === '') {\n throw new ReviewError('validation', 'comment body must be non-empty');\n }\n try {\n const comment = await this.lifecycle.addComment(id, input, ctx.actor);\n return { comment };\n } catch (error) {\n throw this.translate(error);\n }\n },\n `comment.add:${id}`,\n ctx.requestId,\n );\n }\n\n async editComment(\n id: ReviewId,\n commentId: string,\n input: CommentEditInput,\n ctx: CallContext,\n ): Promise<CommentView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (typeof input.body !== 'string' || input.body.trim() === '') {\n throw new ReviewError('validation', 'comment body must be non-empty');\n }\n try {\n const comment = await this.lifecycle.editComment(id, commentId, input.body, ctx.actor);\n return { comment };\n } catch (error) {\n throw this.translate(error);\n }\n },\n `comment.edit:${id}:${commentId}`,\n ctx.requestId,\n );\n }\n\n async deleteComment(id: ReviewId, commentId: string, ctx: CallContext): Promise<CommentView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n try {\n const comment = await this.lifecycle.deleteComment(id, commentId, ctx.actor);\n return { comment };\n } catch (error) {\n throw this.translate(error);\n }\n },\n `comment.delete:${id}:${commentId}`,\n ctx.requestId,\n );\n }\n\n async reply(\n id: ReviewId,\n commentId: string,\n input: { body: string },\n ctx: CallContext,\n ): Promise<CommentView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (typeof input.body !== 'string' || input.body.trim() === '') {\n throw new ReviewError('validation', 'reply body must be non-empty');\n }\n try {\n const comment = await this.lifecycle.reply(id, commentId, input.body, ctx.actor);\n return { comment };\n } catch (error) {\n throw this.translate(error);\n }\n },\n `comment.reply:${id}:${commentId}`,\n ctx.requestId,\n );\n }\n\n async setCommentState(\n id: ReviewId,\n commentId: string,\n state: CommentState,\n ctx: CallContext,\n ): Promise<CommentView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (!COMMENT_STATES.has(state)) {\n throw new ReviewError('validation', `unknown comment state: ${String(state)}`);\n }\n try {\n const comment = await this.lifecycle.setCommentState(id, commentId, state, ctx.actor);\n return { comment };\n } catch (error) {\n throw this.translate(error);\n }\n },\n `comment.state:${id}:${commentId}`,\n ctx.requestId,\n );\n }\n\n async decideFinding(\n id: ReviewId,\n findingId: string,\n input: FindingDecisionInput,\n ctx: CallContext,\n ): Promise<FindingDecisionView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n try {\n const decision = await this.lifecycle.decideFinding(id, findingId, input, ctx.actor);\n return { decision };\n } catch (error) {\n throw this.translate(error);\n }\n },\n `finding.decision:${id}:${findingId}`,\n ctx.requestId,\n );\n }\n\n async decideFindings(\n id: ReviewId,\n input: BulkFindingDecisionInput,\n ctx: CallContext,\n ): Promise<BulkFindingDecisionView> {\n assertContext(ctx);\n const selected =\n input.findingIds === undefined ? null : normalizeBulkFindingIds(input.findingIds, id);\n return await this.idempotent(\n async () => {\n if (input.state !== 'accepted' && input.state !== 'dismissed') {\n throw new ReviewError('validation', `unknown finding decision: ${String(input.state)}`, {\n id,\n });\n }\n\n let review: ReviewState;\n try {\n review = await this.lifecycle.get(id);\n } catch (error) {\n throw this.translate(error);\n }\n if (review.deletedAt !== undefined) {\n throw new ReviewError('not-found', `review not found: ${id}`, { id });\n }\n if (review.status === 'closed') {\n throw new ReviewError('conflict', `review is closed: ${id}`, { id });\n }\n\n const latestRound = review.rounds.at(-1);\n const report = review.report;\n if (report === undefined || latestRound === undefined) {\n throw new ReviewError('validation', `review has no reviewer report: ${id}`, { id });\n }\n if (report.round !== latestRound.no) {\n throw new ReviewError(\n 'validation',\n `reviewer report is from round ${report.round}, latest is ${latestRound.no}`,\n { id },\n );\n }\n if (!isFinalReviewReport(review)) {\n throw new ReviewError('validation', `reviewer report is not final: ${id}`, { id });\n }\n\n const decided = new Set(\n (review.findingDecisions ?? [])\n .filter((decision) => decision.round === report.round)\n .map((decision) => decision.findingId),\n );\n const targets = report.findings.filter(\n (finding) =>\n finding.kind !== 'praise' &&\n !decided.has(finding.id) &&\n (selected === null || selected.has(finding.id)),\n );\n const decisions: FindingDecision[] = [];\n try {\n for (const finding of targets) {\n const decision = await this.lifecycle.decideFindingIfUndecided(\n id,\n finding.id,\n { state: input.state },\n ctx.actor,\n );\n if (decision !== null) decisions.push(decision);\n }\n } catch (error) {\n throw this.translate(error);\n }\n\n return {\n decisions,\n skipped:\n selected === null\n ? report.findings.length - decisions.length\n : selected.size - decisions.length,\n };\n },\n `finding.decisions:${id}:${input.state}:${bulkSelectionKey(selected)}`,\n ctx.requestId,\n );\n }\n\n async transferAcceptedFindings(\n id: ReviewId,\n ctx: CallContext,\n ): Promise<TransferAcceptedFindingsView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n try {\n const comments = await this.lifecycle.transferAcceptedFindings(id, ctx.actor);\n return { transferred: comments.length };\n } catch (error) {\n throw this.translate(error);\n }\n },\n `finding.transfer:${id}`,\n ctx.requestId,\n );\n }\n\n async events(id: ReviewId, after = 0): Promise<ReviewEvent[]> {\n if (!Number.isInteger(after) || after < 0) {\n throw new ReviewError('validation', 'after must be a non-negative integer');\n }\n // The event log outlives soft deletion: the SSE hub replays the delete event,\n // and GET /api/events guards visibility at the route level. latestFeedback()\n // still calls requireReview() to hide deleted reviews.\n try {\n return await this.store.events(id, after);\n } catch (error) {\n throw this.translate(error);\n }\n }\n\n async suggestionAction(\n id: ReviewId,\n commentId: string,\n action: SuggestionActionInput['action'],\n ctx: CallContext,\n ): Promise<CommentView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (!['accept', 'decline', 'apply'].includes(action)) {\n throw new ReviewError('validation', `unknown suggestion action: ${String(action)}`);\n }\n const review = await this.requireReview(id);\n if (review.status === 'closed') {\n throw new ReviewError('conflict', `review is closed: ${id}`, { id });\n }\n const comment = review.comments.find((candidate) => candidate.id === commentId);\n if (comment === undefined) {\n throw new ReviewError('not-found', `unknown comment: ${commentId}`, { id, commentId });\n }\n if (comment.suggestion === undefined) {\n throw new ReviewError('validation', `comment has no suggestion: ${commentId}`, {\n id,\n commentId,\n });\n }\n if (action === 'apply') {\n const round = review.rounds.at(-1);\n if (round === undefined)\n throw new ReviewError('validation', `review has no rounds: ${id}`);\n try {\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'suggestion/applied',\n actor: ctx.actor,\n data: { commentId, round: round.no },\n now: this.now,\n }),\n );\n } catch (error) {\n throw this.translate(error);\n }\n } else {\n const state = action === 'accept' ? 'accepted' : 'declined';\n try {\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'suggestion/state',\n actor: ctx.actor,\n data: { commentId, state },\n now: this.now,\n }),\n );\n } catch (error) {\n throw this.translate(error);\n }\n }\n return await this.getComment(id, commentId);\n },\n `comment.suggestion:${id}:${commentId}`,\n ctx.requestId,\n );\n }\n\n async refresh(id: ReviewId, input: RefreshInput, ctx: CallContext): Promise<ReviewView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n const review = await this.requireReview(id);\n if (review.status === 'closed') {\n throw new ReviewError('conflict', `review is closed: ${id}`, { id });\n }\n if (this.running.has(id) || agentIsActive(review)) {\n throw new ReviewError('agent-busy', `a reviewer is active for ${id}`, { id });\n }\n const latest = await this.latestSnapshotOrThrow(review);\n const scope = input.scope ?? scopeFromSnapshot(latest);\n let snapshot: Snapshot;\n try {\n snapshot = await this.snapshots.build({ repoRoot: review.repoRoot, scope });\n } catch (error) {\n throw this.translate(error);\n }\n try {\n await this.lifecycle.refresh(id, snapshot, ctx.actor);\n } catch (error) {\n throw this.translate(error);\n }\n return await this.get(id);\n },\n `review.refresh:${id}`,\n ctx.requestId,\n );\n }\n\n async close(id: ReviewId, verdict: 'approved' | 'closed', ctx: CallContext): Promise<ReviewView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (verdict !== 'approved' && verdict !== 'closed') {\n throw new ReviewError('validation', `unknown close verdict: ${String(verdict)}`);\n }\n try {\n await this.lifecycle.close(id, verdict, ctx.actor);\n } catch (error) {\n throw this.translate(error);\n }\n return await this.get(id);\n },\n `review.close:${id}`,\n ctx.requestId,\n );\n }\n\n async claimFixStatus(id: ReviewId, input: FixStatusInput, ctx: CallContext): Promise<void> {\n assertContext(ctx);\n await this.idempotent(\n async () => {\n if (!Array.isArray(input.items) || input.items.length === 0) {\n throw new ReviewError('validation', 'items must be a non-empty array');\n }\n const review = await this.requireReview(id);\n if (review.status === 'closed') {\n throw new ReviewError('conflict', `review is closed: ${id}`, { id });\n }\n const known = new Set(review.comments.map((comment) => comment.id));\n const claims = input.items.map((item) => {\n if (!['fixed', 'not-fixed', 'unclear'].includes(item.status)) {\n throw new ReviewError('validation', `unknown fix status: ${String(item.status)}`);\n }\n if (!known.has(item.commentId)) {\n throw new ReviewError('not-found', `unknown comment: ${item.commentId}`, {\n id,\n commentId: item.commentId,\n });\n }\n if (item.evidence !== undefined && typeof item.evidence !== 'string') {\n throw new ReviewError('validation', 'evidence must be a string');\n }\n return {\n commentId: item.commentId,\n status: item.status,\n ...(item.evidence === undefined ? {} : { evidence: item.evidence }),\n by: ctx.actor,\n at: this.now().toISOString(),\n };\n });\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'fix/claim',\n actor: ctx.actor,\n data: { claims },\n now: this.now,\n }),\n );\n },\n `review.fix-status:${id}`,\n ctx.requestId,\n );\n }\n\n async latestFeedback(id: ReviewId): Promise<LatestFeedbackView | null> {\n await this.requireReview(id);\n const events = await this.events(id, 0);\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index];\n if (event?.type !== 'review/submitted') continue;\n return {\n submission: event.data.submission,\n feedback: event.data.feedback as LatestFeedbackView['feedback'],\n };\n }\n return null;\n }\n\n async gc(olderThanDays: number): Promise<GcResult> {\n const result = await this.store.gc(olderThanDays, this.now());\n this.results.clear();\n return result;\n }\n\n async submit(id: ReviewId, input: SubmitInput, ctx: CallContext): Promise<SubmissionView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (!VERDICTS.has(input.verdict)) {\n throw new ReviewError('validation', `unknown verdict: ${String(input.verdict)}`);\n }\n if (input.summary !== undefined && typeof input.summary !== 'string') {\n throw new ReviewError('validation', 'summary must be a string');\n }\n const review = await this.requireReview(id);\n if (review.status === 'closed') {\n throw new ReviewError('conflict', `review is closed: ${id}`, { id });\n }\n const round = review.rounds.at(-1);\n if (round === undefined) {\n throw new ReviewError('validation', `review has no rounds: ${id}`, { id });\n }\n if ((review.submissions ?? []).some((submission) => submission.round === round.no)) {\n throw new ReviewError('conflict', `round ${round.no} was already submitted`, {\n id,\n round: round.no,\n });\n }\n let snapshot: Snapshot;\n try {\n snapshot = await this.store.readSnapshot(round.snapshotId);\n } catch (error) {\n throw this.translate(error);\n }\n const report =\n review.report !== undefined && review.report.round === round.no ? review.report : null;\n const submissionId = this.newId('sub');\n const deliveryKey = `${id}:${round.no}:${submissionId}`;\n const feedback = buildFeedback({\n review,\n snapshot,\n report,\n round: round.no,\n verdict: input.verdict,\n deliveryKey,\n ...(input.summary === undefined ? {} : { summary: input.summary }),\n ...(input.includeResolved === undefined\n ? {}\n : { includeResolved: input.includeResolved }),\n });\n const submission: SubmissionRecord = {\n submissionId,\n round: round.no,\n verdict: input.verdict,\n deliveryKey,\n createdAt: this.now().toISOString(),\n };\n try {\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'review/submitted',\n actor: ctx.actor,\n data: {\n submission,\n feedback: {\n markdown: feedback.markdown,\n json: feedback.json,\n deliveryKey,\n },\n },\n now: this.now,\n }),\n );\n } catch (error) {\n throw this.translate(error);\n }\n return {\n reviewId: id,\n round: round.no,\n verdict: input.verdict,\n feedback,\n deliveryKey,\n };\n },\n `review.submit:${id}`,\n ctx.requestId,\n );\n }\n\n async runReviewer(id: ReviewId, ctx: CallContext): Promise<AgentReport> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (this.running.has(id)) {\n throw new ReviewError('agent-busy', `a reviewer is already running for ${id}`, { id });\n }\n this.running.add(id);\n try {\n return await this.runReviewerOnce(id, ctx);\n } finally {\n this.running.delete(id);\n }\n },\n `review.run:${id}`,\n ctx.requestId,\n );\n }\n\n async cancelAgent(id: ReviewId, ctx: CallContext): Promise<void> {\n assertContext(ctx);\n const active = this.active.get(id);\n if (active === undefined) {\n const review = await this.requireReview(id);\n if (agentIsActive(review)) {\n throw new ReviewError('conflict', `reviewer is not owned by this service instance`, {\n id,\n });\n }\n return;\n }\n active.controller.abort();\n active.backend?.cancel?.();\n }\n\n private async runReviewerOnce(id: ReviewId, ctx: CallContext): Promise<AgentReport> {\n const review = await this.requireReview(id);\n if (review.status === 'closed') {\n throw new ReviewError('stale-review', `review is closed: ${id}`, { id });\n }\n if (agentIsActive(review)) {\n throw new ReviewError('agent-busy', `a reviewer is already running for ${id}`, { id });\n }\n const round = review.rounds.at(-1);\n if (round === undefined) {\n throw new ReviewError('validation', `review has no rounds: ${id}`, { id });\n }\n let snapshot: Snapshot;\n try {\n snapshot = await this.store.readSnapshot(round.snapshotId);\n } catch (error) {\n throw this.translate(error);\n }\n\n const config: ReviewerConfig = review.reviewer ?? { backend: 'none' };\n const job: ReviewerJob = {\n id: this.newId('job'),\n reviewId: id,\n round: round.no,\n kind: review.report === undefined ? 'initial' : 'verify',\n repoRoot: review.repoRoot,\n prompt: this.buildPrompt(review, round, snapshot),\n snapshot,\n manifest: manifestFromSnapshot(snapshot),\n };\n const controller = new AbortController();\n this.active.set(id, { controller });\n\n try {\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'agent/started',\n actor: ctx.actor,\n data: { jobId: job.id, round: round.no, backend: config.backend },\n now: this.now,\n }),\n );\n\n let raw: ReviewerReport;\n if (config.backend === 'none') {\n raw = {\n schemaVersion: 1,\n summary: 'Reviewer backend is none; review skipped.',\n riskLevel: 'low',\n findings: [],\n questions: [],\n tests: { ran: false, commands: [] },\n verification: [],\n };\n } else {\n let backend: ReviewerBackend;\n try {\n backend = this.backendFor(config);\n } catch (error) {\n throw this.translate(error);\n }\n this.active.set(id, { controller, backend });\n if (controller.signal.aborted) {\n throw new ReviewError('conflict', `reviewer was cancelled for ${id}`, { id });\n }\n raw = await backend.run(\n job,\n async (finding) => {\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'agent/finding',\n actor: ctx.actor,\n data: { finding, round: round.no },\n now: this.now,\n }),\n );\n },\n controller.signal,\n );\n }\n\n if (controller.signal.aborted) {\n throw new ReviewError('conflict', `reviewer was cancelled for ${id}`, { id });\n }\n const validation = validateReport(raw, { snapshot });\n const warnings = [...validation.warnings];\n if (raw.dirtyWorktree === true) warnings.push('dirty-worktree');\n const report: AgentReport = {\n ...validation.report,\n reviewId: id,\n round: round.no,\n backend: config.backend,\n rejected: validation.rejected,\n warnings,\n ...(raw.dirtyWorktree === true ? { dirtyWorktree: true } : {}),\n ...(config.backend === 'none' ? { skipped: true } : {}),\n };\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'agent/report',\n actor: ctx.actor,\n data: { report },\n now: this.now,\n }),\n );\n return report;\n } catch (error) {\n const reviewError =\n error instanceof ReviewError\n ? error\n : controller.signal.aborted\n ? new ReviewError('conflict', `reviewer was cancelled for ${id}`, { id })\n : new ReviewError('internal', (error as Error).message, { id });\n try {\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'agent/failed',\n actor: ctx.actor,\n data: { code: reviewError.code, message: reviewError.message },\n now: this.now,\n }),\n );\n } catch {\n // The original failure is more useful than a secondary log failure.\n }\n throw reviewError;\n } finally {\n this.active.delete(id);\n }\n }\n\n private backendFor(config: ReviewerConfig): ReviewerBackend {\n if (this.backendFactory !== undefined) return this.backendFactory(config);\n if (config.backend === 'fake') return new FakeReviewer();\n if (config.backend === 'command') {\n return new CommandReviewer({\n command: config.command ?? [],\n ...(this.runGit === undefined ? {} : { runGit: this.runGit }),\n ...(config.timeoutMs === undefined ? {} : { timeoutMs: config.timeoutMs }),\n });\n }\n throw new ReviewError('validation', `reviewer backend cannot run: ${config.backend}`);\n }\n\n private buildPrompt(review: ReviewState, round: Round, snapshot: Snapshot): string {\n const files = snapshot.files\n .map((file) => `- ${file.status} ${file.path} (+${file.added}/-${file.deleted})`)\n .join('\\n');\n return [\n `# Independent code review: ${review.title}`,\n '',\n `Review: ${review.id}`,\n `Round: ${round.no}`,\n `Repository: ${review.repoRoot}`,\n `Scope: ${snapshot.scope.label} (${snapshot.scope.baseSha}..${snapshot.scope.headSha ?? 'worktree'})`,\n '',\n 'You are a read-only reviewer. Do not modify files.',\n 'Review the changes and surrounding code, run tests if useful, and report only actionable',\n 'findings with file/line anchors and evidence. Return strict JSON (schemaVersion 1), or',\n 'write it to output.json / a fenced json block.',\n '',\n '## Files',\n files,\n '',\n '## Instructions',\n '- Blockers and major issues first; no style nitpicks without impact.',\n '- Every finding needs file, lineStart/lineEnd, title, rationale and evidence.',\n '- Put product/intent questions in questions[], not findings[].',\n '- Verification entries use the supplied comment ids when this is a verify round.',\n ].join('\\n');\n }\n\n private async readLatestSnapshot(review: ReviewState): Promise<Snapshot | null> {\n const round = review.rounds.at(-1);\n if (round === undefined) return null;\n try {\n return await this.store.readSnapshot(round.snapshotId);\n } catch (error) {\n throw this.translate(error);\n }\n }\n\n private async getComment(id: ReviewId, commentId: string): Promise<CommentView> {\n const review = await this.requireReview(id);\n const comment = review.comments.find((candidate) => candidate.id === commentId);\n if (comment === undefined) {\n throw new ReviewError('not-found', `unknown comment: ${commentId}`, { id, commentId });\n }\n return { comment };\n }\n\n private async latestSnapshotOrThrow(review: ReviewState): Promise<Snapshot> {\n const round = review.rounds.at(-1);\n if (round === undefined) {\n throw new ReviewError('validation', `review has no rounds: ${review.id}`, { id: review.id });\n }\n try {\n return await this.store.readSnapshot(round.snapshotId);\n } catch (error) {\n throw this.translate(error);\n }\n }\n\n private async requireReview(id: ReviewId): Promise<ReviewState> {\n try {\n const review = await this.lifecycle.get(id);\n if (review.deletedAt !== undefined) {\n throw new ReviewError('not-found', `review not found: ${id}`, { id });\n }\n return review;\n } catch (error) {\n throw this.translate(error);\n }\n }\n\n private async idempotent<T>(\n operation: () => Promise<T>,\n scope: string,\n requestId?: string,\n ): Promise<T> {\n if (requestId === undefined || requestId === '') return await operation();\n // The request id is only unique per operation (route and review), so a\n // client retry on a different route must not reuse another response.\n const key = `${scope}\\u0000${requestId}`;\n if (this.results.has(key)) return clone(this.results.get(key) as T);\n const pending = this.inflight.get(key);\n if (pending !== undefined) return clone((await pending) as T);\n const run = operation();\n this.inflight.set(key, run);\n try {\n const result = await run;\n if (this.results.size >= this.idempotencyLimit) {\n const oldest = this.results.keys().next().value as string | undefined;\n if (oldest !== undefined) this.results.delete(oldest);\n }\n this.results.set(key, clone(result));\n return result;\n } finally {\n if (this.inflight.get(key) === run) this.inflight.delete(key);\n }\n }\n\n private translate(error: unknown): ReviewError {\n if (error instanceof ReviewError) return error;\n if (error instanceof ReviewLifecycleError) {\n return new ReviewError(mapLifecycleCode(error.code), error.message, {\n ...(error.reviewId === undefined ? {} : { reviewId: error.reviewId }),\n ...(error.commentId === undefined ? {} : { commentId: error.commentId }),\n });\n }\n if (error instanceof ReviewNotFoundError) {\n return new ReviewError('not-found', error.message, { reviewId: error.reviewId });\n }\n if (error instanceof ReviewerError || error instanceof ReportValidationError) {\n return new ReviewError('internal', error.message);\n }\n return new ReviewError('internal', (error as Error).message);\n }\n}\n", "export const CORE_VERSION = '0.1.0';\nexport { safeJoin, PathEscapeError } from './paths.js';\nexport { buildSnapshot } from './diff/snapshot.js';\nexport {\n buildReviewManifest,\n manifestFileFromDiff,\n manifestFromSnapshot,\n patchBytesFromHunks,\n reviewManifest,\n} from './diff/manifest.js';\nexport { readBlob } from './git/content.js';\nexport type { BlobRead } from './git/content.js';\nexport { DiffParseError, parseUnifiedDiff } from './diff/parse.js';\nexport { EMPTY_TREE_SHA, resolveDefaultBase, resolveScope, worktreeDigest } from './git/scope.js';\nexport type { ResolveScopeInput } from './git/scope.js';\nexport { GitError, runGit } from './git/run.js';\nexport type { GitErrorCode, GitResult, GitRunOptions } from './git/run.js';\nexport { resolveRepoRoot } from './git/repo.js';\nexport type {\n DiffHunk,\n DiffLine,\n DiffLineKind,\n DiffScope,\n FileDiff,\n FileStatus,\n ManifestFile,\n ManifestFileReason,\n ManifestTotals,\n ParsedFile,\n ResolvedScope,\n ReviewManifest,\n Snapshot,\n SnapshotOptions,\n} from './types.js';\nexport { createId, ID_LENGTHS, ReviewIdError } from './review/ids.js';\nexport type { IdPrefix, RandomBytes } from './review/ids.js';\nexport {\n createEvent,\n isActor,\n isReviewEvent,\n isReviewEventType,\n REVIEW_EVENT_TYPES,\n ReviewEventError,\n} from './review/events.js';\nexport type {\n AgentCoverageData,\n AgentShardData,\n AgentFailedData,\n AgentFindingData,\n AgentReportData,\n AgentStartedData,\n CommentAddedData,\n CommentAnchorData,\n CommentRepliedData,\n CommentStateData,\n CreateEventInput,\n FindingDecisionData,\n FixClaimData,\n SuggestionStateData,\n ReviewClosedData,\n ReviewCreatedData,\n ReviewEvent,\n ReviewEventBase,\n ReviewEventDataMap,\n ReviewEventErrorCode,\n ReviewEventType,\n ReviewSubmittedData,\n RoundCreatedData,\n SuggestionAppliedData,\n} from './review/events.js';\nexport type {\n Actor,\n ActorKind,\n AgentShardState,\n AgentState,\n AgentStatus,\n AddCommentInput,\n Anchor,\n AnchorPosition,\n AnchorState,\n Comment,\n CommentId,\n CommentState,\n Confidence,\n CoverageStatus,\n CoverageTotals,\n CreateReviewInput,\n FileCoverage,\n FindingDecision,\n FindingDecisionState,\n Outcome,\n OutcomeStatus,\n Reply,\n ReviewCoverage,\n ReviewId,\n ReviewState,\n ReviewStatus,\n ReviewSummary,\n Round,\n RoundNo,\n Side,\n SuggestionState,\n FixStatus,\n FixClaimRecord,\n Initiator,\n SubmissionRecord,\n Suggestion,\n} from './review/types.js';\nexport { AnchorError, captureAnchor, normalizeQuote, reanchor } from './review/anchors.js';\nexport type { AnchorErrorCode, CaptureAnchorInput, ReanchorOptions } from './review/anchors.js';\nexport {\n COVERAGE_STATUSES,\n coverageFromPrompt,\n initialCoverage,\n isCoverageComplete,\n promotePendingToLight,\n summarizeCoverage,\n} from './review/coverage.js';\nexport {\n buildModuleMap,\n buildReviewPlan,\n classifyFile,\n coverageFromPlan,\n DEFAULT_SHARD_LIMITS,\n isUserFacingDoc,\n} from './review/plan.js';\nexport type {\n FileKind,\n ModuleInfo,\n ModuleMap,\n ModuleRoot,\n PlanFile,\n ReviewPlan,\n ReviewShard,\n ReviewTier,\n ShardLimits,\n} from './review/plan.js';\nexport { aggregateShardReports, mergeShardReports } from './review/aggregate.js';\nexport type {\n AggregateShardReportsInput,\n AggregateShardReportsResult,\n MergeShardReportsInput,\n ShardReportInput,\n} from './review/aggregate.js';\nexport { deriveOutcome } from './review/outcomes.js';\nexport { isFinalReviewReport } from './review/final.js';\nexport { fold, ReviewFoldError } from './review/fold.js';\nexport { ReviewLifecycle, ReviewLifecycleError } from './review/lifecycle.js';\nexport type { RefreshResult, ReviewLifecycleErrorCode } from './review/lifecycle.js';\nexport {\n ReviewNotFoundError,\n ReviewStore,\n ReviewStoreCorruptionError,\n ReviewStoreLockedError,\n} from './review/store.js';\nexport type { GcResult } from './review/store.js';\nexport type { ReviewStoreOptions } from './review/store.js';\n\nexport { FakeReviewer } from './reviewer/fake.js';\nexport type { FakeReviewerOptions } from './reviewer/fake.js';\nexport { CommandReviewer } from './reviewer/command.js';\nexport type { CommandReviewerOptions } from './reviewer/command.js';\nexport {\n MAX_TEXT_BYTES,\n normalizeCode,\n ReportValidationError,\n validateFindingItem,\n validateReport,\n} from './reviewer/validate.js';\nexport type { FindingItemValidation } from './reviewer/validate.js';\nexport type {\n AgentReport,\n Finding,\n FindingCategory,\n FindingKind,\n FindingSeverity,\n FindingSink,\n GitStatusRunner,\n RejectedReportItem,\n RejectedReportKind,\n ReviewQuestion,\n ReviewSuggestion,\n ReviewerBackend,\n ReviewerBackendKind,\n ReviewerConfidence,\n ReviewerConfig,\n ReviewerErrorCode,\n ReviewerJob,\n ReviewerReport,\n RiskLevel,\n TestCommand,\n TestResult,\n TestSummary,\n ValidationResult,\n Verification,\n VerificationStatus,\n} from './reviewer/types.js';\nexport { ReviewerError } from './reviewer/types.js';\nexport { ReviewError } from './service/types.js';\nexport type {\n CallContext,\n CommentView,\n FeedbackComment,\n FeedbackFinding,\n FeedbackJson,\n FeedbackPackage,\n FeedbackSuggestion,\n BulkFindingDecisionInput,\n BulkFindingDecisionView,\n FindingDecisionInput,\n FindingDecisionView,\n Page,\n ReplyInput,\n ReviewErrorCode,\n ReviewFilter,\n ReviewService,\n ReviewServiceImplDeps,\n ReviewView,\n ServiceCreateInput,\n ServiceSnapshotView,\n SubmissionView,\n SuggestionActionInput,\n FixStatusInput,\n RefreshInput,\n LatestFeedbackView,\n SubmitInput,\n} from './service/types.js';\nexport { buildFeedback, FEEDBACK_BYTE_LIMIT } from './service/feedback.js';\nexport type { BuildFeedbackInput } from './service/feedback.js';\nexport { ReviewServiceImpl } from './service/service.js';\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { lstat } from 'node:fs/promises';\nimport { relative, resolve, sep } from 'node:path';\n\nexport class PathEscapeError extends Error {\n constructor(readonly relative: string) {\n super(`path escapes repository root: ${relative}`);\n this.name = 'PathEscapeError';\n }\n}\n\nexport function safeJoin(root: string, relative: string): string {\n if (relative.includes('\\0')) throw new PathEscapeError(relative);\n const absolute = resolve(root, relative);\n if (absolute !== root && !absolute.startsWith(root + sep)) {\n throw new PathEscapeError(relative);\n }\n return absolute;\n}\n\n/**\n * Split a NUL-delimited Git path list. A truncated stream may end without a\n * trailing NUL, leaving an incomplete final token; drop it.\n */\nexport function splitNulPaths(output: string): string[] {\n const paths = output.split('\\0');\n if (!output.endsWith('\\0')) paths.pop();\n return paths.filter((path) => path.length > 0);\n}\n\n/**\n * Detect a symlink in any parent component of a repository-relative path.\n * The final component is excluded: callers inspect it themselves so they can\n * distinguish a symlinked file from a symlinked directory.\n */\nexport async function hasSymlinkParent(root: string, relativePath: string): Promise<boolean> {\n const absolute = safeJoin(root, relativePath);\n const rel = relative(root, absolute);\n if (rel === '') return false;\n\n let current = root;\n const parts = rel.split(sep);\n for (const part of parts.slice(0, -1)) {\n current = resolve(current, part);\n const info = await lstat(current).catch(() => null);\n if (info === null) return false;\n if (info.isSymbolicLink()) return true;\n if (!info.isDirectory()) return false;\n }\n return false;\n}\n", "import { lstat } from 'node:fs/promises';\nimport type {\n DiffHunk,\n FileDiff,\n FileStatus,\n ManifestFile,\n ManifestFileReason,\n ParsedFile,\n Snapshot,\n SnapshotOptions,\n} from '../types.js';\nimport { hasSymlinkParent, safeJoin, splitNulPaths } from '../paths.js';\nimport { readBlob } from '../git/content.js';\nimport { resolveScope } from '../git/scope.js';\nimport { runGit } from '../git/run.js';\nimport type { GitResult } from '../git/run.js';\nimport { manifestFileFromDiff, reviewManifest } from './manifest.js';\nimport { parseDiffHeader, parseUnifiedDiff, stripDiffPrefix } from './parse.js';\nimport { isIgnored } from './glob.js';\n\nconst DEFAULTS = {\n includeUntracked: true,\n includeContent: true,\n maxDiffBytes: 2 * 1024 * 1024,\n maxFileLines: 20_000,\n maxContentBytes: 1024 * 1024,\n maxTotalContentBytes: 64 * 1024 * 1024,\n maxFiles: 500,\n} as const;\n\n/**\n * The changed-path listing is metadata only; this byte cap is a safety valve\n * for pathological repositories. Hitting it is surfaced as a snapshot warning,\n * never as a silent omission.\n */\nconst MAX_MANIFEST_LISTING_BYTES = 64 * 1024 * 1024;\n\ninterface ContentBudget {\n includeContent: boolean;\n maxTotalBytes: number;\n usedBytes: number;\n exhausted: boolean;\n warned: boolean;\n warnings: string[];\n}\n\nfunction fitsContent(budget: ContentBudget, bytes: number): boolean {\n if (!budget.includeContent) return false;\n if (budget.exhausted || budget.usedBytes + bytes > budget.maxTotalBytes) {\n if (!budget.warned) {\n budget.warnings.push('content-budget-truncated');\n budget.warned = true;\n }\n budget.exhausted = true;\n return false;\n }\n budget.usedBytes += bytes;\n return true;\n}\n\nfunction comparePaths(left: string, right: string): number {\n return Buffer.compare(Buffer.from(left, 'utf8'), Buffer.from(right, 'utf8'));\n}\n\nfunction warnUnreadable(warnings: string[], path: string): void {\n const warning = `unreadable:${path}`;\n if (!warnings.includes(warning)) warnings.push(warning);\n}\n\ninterface DiffText {\n text: string;\n truncated: boolean;\n synthetic?: ParsedFile;\n}\n\ntype DiffFormat = 'patch' | 'raw' | 'numstat';\n\nfunction diffArgs(\n scope: Snapshot['scope'],\n format: DiffFormat = 'patch',\n paths?: readonly string[],\n): string[] {\n const common = ['diff', '--no-color', '--no-ext-diff', '--no-textconv'];\n if (format === 'raw') common.push('--raw', '-z');\n else if (format === 'numstat') common.push('--numstat', '-z');\n else common.push('--unified=3');\n common.push('--find-renames=50%', '--src-prefix=a/', '--dst-prefix=b/');\n if (scope.kind === 'worktree') common.push(scope.baseSha);\n else common.push(`${scope.baseSha}..${scope.headSha}`);\n common.push('--');\n if (paths !== undefined) common.push(...paths);\n return common;\n}\n\nfunction truncateAtFileBoundary(text: string, maxBytes: number): DiffText {\n if (Buffer.byteLength(text, 'utf8') <= maxBytes) {\n return { text, truncated: false };\n }\n const cut = Buffer.from(text, 'utf8').subarray(0, maxBytes).toString('utf8');\n const boundary = cut.lastIndexOf('\\ndiff --git ');\n if (boundary > 0) {\n const synthetic = syntheticFileFromCut(cut.slice(boundary + 1));\n return {\n text: cut.slice(0, boundary + 1),\n truncated: true,\n ...(synthetic === undefined ? {} : { synthetic }),\n };\n }\n if (cut.startsWith('diff --git ')) {\n const synthetic = syntheticFileFromCut(cut);\n return { text: '', truncated: true, ...(synthetic === undefined ? {} : { synthetic }) };\n }\n return { text: '', truncated: true };\n}\n\nfunction syntheticFileFromCut(cut: string): ParsedFile | undefined {\n const firstLineEnd = cut.indexOf('\\n');\n const headerLine = firstLineEnd < 0 ? cut : cut.slice(0, firstLineEnd);\n if (!headerLine.startsWith('diff --git ')) return undefined;\n\n const header = parseDiffHeader(headerLine, 1);\n let oldPath = header.oldPath;\n let newPath = header.newPath;\n let status: ParsedFile['status'] = 'modified';\n let oldIsNull = false;\n let newIsNull = false;\n\n for (const line of cut.split('\\n').slice(1)) {\n if (line.startsWith('@@ ') || line === 'GIT binary patch') break;\n if (line.startsWith('new file mode ')) status = 'added';\n else if (line.startsWith('deleted file mode ')) status = 'deleted';\n else if (line.startsWith('rename from ')) {\n oldPath = line.slice('rename from '.length);\n status = 'renamed';\n } else if (line.startsWith('rename to ')) {\n newPath = line.slice('rename to '.length);\n status = 'renamed';\n } else if (line.startsWith('--- ')) {\n const value = line.slice(4);\n if (value === '/dev/null') oldIsNull = true;\n else oldPath = stripDiffPrefix(value);\n } else if (line.startsWith('+++ ')) {\n const value = line.slice(4);\n if (value === '/dev/null') newIsNull = true;\n else newPath = stripDiffPrefix(value);\n }\n }\n\n if (oldIsNull) status = 'added';\n if (newIsNull) status = 'deleted';\n const path = newIsNull ? oldPath : newPath;\n const file: ParsedFile = {\n path,\n status,\n binary: false,\n hunks: [],\n added: 0,\n deleted: 0,\n synthetic: true,\n };\n if (oldPath !== path) file.oldPath = oldPath;\n return file;\n}\n\nfunction candidateKey(entry: ParsedFile): string {\n return `${entry.path}\\0${entry.oldPath ?? ''}`;\n}\n\nfunction rawStatus(letter: string, oldMode: string, newMode: string): ParsedFile['status'] {\n if (letter === 'R') return 'renamed';\n if (oldMode === '160000' || newMode === '160000') return 'submodule';\n if (letter === 'A') return 'added';\n if (letter === 'D') return 'deleted';\n return 'modified';\n}\n\nfunction parseRawDiff(raw: string): ParsedFile[] {\n const tokens = raw.split('\\0');\n const entries: ParsedFile[] = [];\n for (let index = 0; index < tokens.length;) {\n const header = tokens[index++];\n if (header === undefined || !header.startsWith(':')) continue;\n const fields = header.slice(1).split(' ');\n const oldMode = fields[0] ?? '';\n const newMode = fields[1] ?? '';\n const letter = (fields[4] ?? 'M').charAt(0);\n let oldPath: string | undefined;\n let path = tokens[index++] ?? '';\n if (letter === 'R' || letter === 'C') {\n oldPath = path;\n path = tokens[index++] ?? '';\n }\n if (path === '') continue;\n const entry: ParsedFile = {\n path,\n status: rawStatus(letter, oldMode, newMode),\n binary: false,\n hunks: [],\n added: 0,\n deleted: 0,\n };\n if (oldPath !== undefined) entry.oldPath = oldPath;\n entries.push(entry);\n }\n return entries;\n}\n\ninterface RawListing {\n entries: ParsedFile[];\n truncated: boolean;\n}\n\nasync function listRawChanges(\n scope: Snapshot['scope'],\n signal?: AbortSignal,\n paths?: readonly string[],\n): Promise<RawListing> {\n const result = await runGit(scope.repoRoot, diffArgs(scope, 'raw', paths), {\n signal,\n maxBytes: MAX_MANIFEST_LISTING_BYTES,\n truncateOnOverflow: true,\n });\n return { entries: parseRawDiff(result.stdout), truncated: result.truncated === true };\n}\n\ninterface NumstatEntry {\n added: number;\n deleted: number;\n binary: boolean;\n}\n\ninterface NumstatListing {\n entries: Map<string, NumstatEntry>;\n truncated: boolean;\n}\n\n/**\n * Parses `git diff --numstat -z`. A rename record is\n * `added\\tdeleted\\t\\0oldPath\\0newPath\\0`, so the empty path field is followed\n * by two NUL-delimited path tokens; the result is keyed by the new path.\n */\nfunction parseNumstat(raw: string): Map<string, NumstatEntry> {\n const entries = new Map<string, NumstatEntry>();\n const tokens = raw.split('\\0');\n if (!raw.endsWith('\\0')) tokens.pop();\n\n for (let index = 0; index < tokens.length;) {\n const record = tokens[index++];\n if (record === undefined || record === '') continue;\n const fields = record.split('\\t');\n if (fields.length < 3) continue;\n const addedField = fields[0] ?? '';\n const deletedField = fields[1] ?? '';\n let path = fields.slice(2).join('\\t');\n if (path === '') {\n index += 1; // old path; only the new path keys the manifest\n path = tokens[index++] ?? '';\n if (path === '') continue;\n }\n const binary = addedField === '-' || deletedField === '-';\n const added = binary ? 0 : Number.parseInt(addedField, 10);\n const deleted = binary ? 0 : Number.parseInt(deletedField, 10);\n if (!Number.isFinite(added) || !Number.isFinite(deleted)) continue;\n entries.set(path, { added, deleted, binary });\n }\n return entries;\n}\n\nasync function listNumstatChanges(\n scope: Snapshot['scope'],\n signal?: AbortSignal,\n paths?: readonly string[],\n): Promise<NumstatListing> {\n const result = await runGit(scope.repoRoot, diffArgs(scope, 'numstat', paths), {\n signal,\n maxBytes: MAX_MANIFEST_LISTING_BYTES,\n truncateOnOverflow: true,\n });\n return { entries: parseNumstat(result.stdout), truncated: result.truncated === true };\n}\n\ninterface ManifestSeed {\n path: string;\n oldPath?: string;\n status: FileStatus;\n binary: boolean;\n added: number;\n deleted: number;\n ignored: boolean;\n oversized: boolean;\n conflicted?: boolean;\n /** True when `added`/`deleted` came from the exact numstat listing. */\n fromNumstat: boolean;\n reason?: ManifestFileReason;\n}\n\nfunction rawSeeds(\n raw: readonly ParsedFile[],\n numstat: Map<string, NumstatEntry>,\n ignore: readonly string[],\n): Map<string, ManifestSeed> {\n const seeds = new Map<string, ManifestSeed>();\n for (const entry of raw) {\n const counts = numstat.get(entry.path);\n const seed: ManifestSeed = {\n path: entry.path,\n status: entry.status,\n binary: counts?.binary === true,\n added: counts?.added ?? entry.added,\n deleted: counts?.deleted ?? entry.deleted,\n ignored: isIgnored(entry.path, ignore),\n oversized: false,\n fromNumstat: counts !== undefined,\n };\n if (entry.oldPath !== undefined) seed.oldPath = entry.oldPath;\n seeds.set(entry.path, seed);\n }\n return seeds;\n}\n\n/**\n * Builds one complete-manifest entry from the full listing seed and, when the\n * path is inside the render subset, the bounded render data. Manifest-only\n * entries never trigger content reads; their patch fields stay at zero.\n *\n * Exported from the module (not the package index) so the reason precedence\n * for manifest-only paths can be pinned without a synthetic git fixture.\n */\nexport function manifestEntry(input: {\n seed: ManifestSeed;\n file?: FileDiff;\n renderExcluded: boolean;\n}): ManifestFile {\n const mapped = input.file === undefined ? undefined : manifestFileFromDiff(input.file);\n const ignored = input.seed.ignored || mapped?.ignored === true;\n const oversized = input.seed.oversized || mapped?.oversized === true;\n const binary = input.seed.binary || mapped?.binary === true;\n const conflicted = input.seed.conflicted === true || mapped?.conflicted === true;\n let reason = mapped?.reason ?? input.seed.reason;\n // A binary path has no textual patch regardless of the cap; report the more\n // specific reason. Ignored/unreadable/explicit policy reasons still win.\n if (reason === 'diff-truncated' && binary && !ignored) reason = 'binary';\n if (reason === undefined) {\n if (ignored) reason = 'ignored';\n else if (binary) reason = 'binary';\n else if (oversized) reason = 'per-file-cap';\n else if (input.renderExcluded) reason = 'render-budget';\n }\n const entry: ManifestFile = {\n path: input.seed.path,\n status: mapped?.status ?? input.seed.status,\n binary,\n ignored,\n oversized,\n ...(conflicted ? { conflicted: true } : {}),\n added: input.seed.fromNumstat ? input.seed.added : (mapped?.added ?? input.seed.added),\n deleted: input.seed.fromNumstat ? input.seed.deleted : (mapped?.deleted ?? input.seed.deleted),\n hunkCount: mapped?.hunkCount ?? 0,\n patchBytes: mapped?.patchBytes ?? 0,\n };\n const oldPath = mapped?.oldPath ?? input.seed.oldPath;\n if (oldPath !== undefined) entry.oldPath = oldPath;\n if (reason !== undefined) entry.reason = reason;\n return entry;\n}\n\ninterface UntrackedListing {\n paths: string[];\n truncated: boolean;\n}\n\nasync function listUntracked(repoRoot: string, signal?: AbortSignal): Promise<UntrackedListing> {\n const result = await runGit(repoRoot, ['ls-files', '--others', '--exclude-standard', '-z'], {\n signal,\n maxBytes: 8 * 1024 * 1024,\n truncateOnOverflow: true,\n });\n return {\n paths: splitNulPaths(result.stdout),\n truncated: result.truncated === true,\n };\n}\n\ninterface ModeListing {\n modes: Map<string, string>;\n available: boolean;\n}\n\nasync function headModes(\n repoRoot: string,\n headSha: string | null,\n signal?: AbortSignal,\n): Promise<ModeListing> {\n let result: GitResult;\n try {\n result = await runGit(\n repoRoot,\n headSha === null ? ['ls-files', '-s', '-z'] : ['ls-tree', '-r', '-z', headSha],\n { allowFailure: true, signal, maxBytes: 8 * 1024 * 1024 },\n );\n } catch (error) {\n if (signal?.aborted === true) throw error;\n return { modes: new Map(), available: false };\n }\n if (result.code !== 0) return { modes: new Map(), available: false };\n\n const modes = new Map<string, string>();\n for (const entry of result.stdout.split('\\0')) {\n const tab = entry.indexOf('\\t');\n if (tab < 0) continue;\n const mode = entry.slice(0, tab).split(' ')[0];\n const path = entry.slice(tab + 1);\n if (mode !== undefined && path !== '') modes.set(path, mode);\n }\n return { modes, available: true };\n}\n\nasync function untrackedFile(\n repoRoot: string,\n path: string,\n maxFileLines: number,\n maxContentBytes: number,\n includeContent: boolean,\n ignored: boolean,\n budget: ContentBudget,\n warnings: string[],\n): Promise<FileDiff | null> {\n const absolute = safeJoin(repoRoot, path);\n if (await hasSymlinkParent(repoRoot, path)) return null;\n const info = await lstat(absolute).catch(() => null);\n if (info === null) {\n warnUnreadable(warnings, path);\n return {\n path,\n status: 'untracked',\n binary: false,\n oversized: false,\n added: 0,\n deleted: 0,\n hunks: [],\n contentHash: null,\n reason: 'unreadable',\n };\n }\n if (info.isSymbolicLink() || !info.isFile()) return null;\n\n const read = await readBlob(repoRoot, null, path, maxFileLines, maxContentBytes);\n if (read.reason === 'unreadable') {\n warnUnreadable(warnings, path);\n return {\n path,\n status: 'untracked',\n binary: false,\n oversized: false,\n added: 0,\n deleted: 0,\n hunks: [],\n contentHash: null,\n reason: 'unreadable',\n };\n }\n\n if (ignored) {\n if (read.lines === null && !read.binary && !read.oversized) return null;\n return {\n path,\n status: 'untracked',\n binary: read.binary,\n oversized: read.oversized,\n ignored: true,\n added: read.lines?.length ?? 0,\n deleted: 0,\n hunks: [],\n contentHash: null,\n };\n }\n\n if (read.lines === null) {\n if (!read.binary && !read.oversized) return null;\n const binaryLike: FileDiff = {\n path,\n status: 'untracked',\n binary: read.binary,\n oversized: read.oversized,\n added: 0,\n deleted: 0,\n hunks: [],\n contentHash: includeContent && !read.oversized ? read.hash : null,\n };\n if (read.encoding !== undefined) binaryLike.encoding = read.encoding;\n return binaryLike;\n }\n\n const truncated = includeContent && !fitsContent(budget, read.bytes);\n const hunk: DiffHunk = {\n oldStart: 0,\n oldLines: 0,\n newStart: 1,\n newLines: read.lines.length,\n header: '',\n lines: read.lines.map((text, index) => ({\n kind: 'add' as const,\n oldNo: null,\n newNo: index + 1,\n text,\n })),\n };\n\n const file: FileDiff = {\n path,\n status: 'untracked',\n binary: false,\n oversized: false,\n added: read.lines.length,\n deleted: 0,\n hunks: truncated || read.lines.length === 0 ? [] : [hunk],\n contentHash: includeContent && !truncated ? read.hash : null,\n };\n if (truncated) file.truncated = true;\n if (includeContent && !truncated) file.newLines = read.lines;\n return file;\n}\n\ninterface UnmergedListing {\n paths: Set<string>;\n truncated: boolean;\n}\n\n/**\n * Worktree conflicts are not a normal diff status: `git diff` renders the\n * conflict markers and the raw listing reports a synthetic `U` entry. Ask the\n * index directly so a conflicted path is never silently treated as an ordinary\n * modification.\n */\nasync function listUnmerged(repoRoot: string, signal?: AbortSignal): Promise<UnmergedListing> {\n const result = await runGit(repoRoot, ['ls-files', '-u', '-z'], {\n signal,\n maxBytes: 8 * 1024 * 1024,\n truncateOnOverflow: true,\n });\n const paths = new Set<string>();\n for (const record of splitNulPaths(result.stdout)) {\n const tab = record.indexOf('\\t');\n if (tab >= 0) paths.add(record.slice(tab + 1));\n }\n return { paths, truncated: result.truncated === true };\n}\n\nexport async function buildSnapshot(options: SnapshotOptions): Promise<Snapshot> {\n const includeContent = options.includeContent ?? DEFAULTS.includeContent;\n const includeUntracked = options.includeUntracked ?? DEFAULTS.includeUntracked;\n const maxDiffBytes = options.maxDiffBytes ?? DEFAULTS.maxDiffBytes;\n const maxFileLines = options.maxFileLines ?? DEFAULTS.maxFileLines;\n const maxContentBytes = options.maxContentBytes ?? DEFAULTS.maxContentBytes;\n const maxTotalContentBytes = options.maxTotalContentBytes ?? DEFAULTS.maxTotalContentBytes;\n const maxFiles = options.maxFiles ?? DEFAULTS.maxFiles;\n const ignore = options.ignore ?? [];\n\n const scope = await resolveScope({\n repoRoot: options.repoRoot,\n scope: options.scope,\n signal: options.signal,\n });\n\n const warnings: string[] = [];\n if (scope.worktreeDigestTruncated === true) warnings.push('worktree-digest-truncated');\n\n // The complete changed-path listing is independent of the render budget.\n // It is metadata only, so it stays cheap even when patch bytes are capped.\n const paths = options.paths;\n const rawListing = await listRawChanges(scope, options.signal, paths);\n const numstatListing = await listNumstatChanges(scope, options.signal, paths);\n const listingTruncated = rawListing.truncated || numstatListing.truncated;\n if (listingTruncated) warnings.push('manifest-listing-truncated');\n const seeds = rawSeeds(rawListing.entries, numstatListing.entries, ignore);\n\n const unmerged = new Set<string>();\n if (scope.kind === 'worktree') {\n const listing = await listUnmerged(scope.repoRoot, options.signal);\n if (listing.truncated) warnings.push('merge-conflict-list-truncated');\n for (const path of listing.paths) {\n if (paths !== undefined && !paths.includes(path)) continue;\n unmerged.add(path);\n const seed = seeds.get(path);\n if (seed === undefined) {\n seeds.set(path, {\n path,\n status: 'modified',\n binary: false,\n added: 0,\n deleted: 0,\n ignored: isIgnored(path, ignore),\n oversized: false,\n conflicted: true,\n fromNumstat: false,\n });\n } else {\n seed.conflicted = true;\n }\n const warning = `merge-conflict:${path}`;\n if (!warnings.includes(warning)) warnings.push(warning);\n }\n }\n\n const diff = await runGit(scope.repoRoot, diffArgs(scope, 'patch', paths), {\n signal: options.signal,\n maxBytes: Math.max(maxDiffBytes * 8, 16 * 1024 * 1024),\n truncateOnOverflow: true,\n });\n const diffTruncated = diff.truncated === true;\n if (diffTruncated) warnings.push('diff-truncated');\n const limited = truncateAtFileBoundary(diff.stdout, maxDiffBytes);\n if (limited.truncated && !diffTruncated) warnings.push('diff-truncated');\n if (limited.synthetic !== undefined) {\n warnings.push(`diff-file-truncated:${limited.synthetic.path}`);\n }\n\n const candidates = [\n ...(limited.synthetic === undefined ? [] : [limited.synthetic]),\n ...parseUnifiedDiff(limited.text),\n ].sort((left, right) => comparePaths(left.path, right.path));\n\n let truncated = listingTruncated || diffTruncated || limited.truncated;\n if (truncated) {\n const seen = new Set(candidates.map((entry) => candidateKey(entry)));\n const byKey = new Map(candidates.map((entry) => [candidateKey(entry), entry]));\n for (const listed of rawListing.entries) {\n const key = candidateKey(listed);\n const warning = `diff-file-skipped:${listed.path}`;\n if (seen.has(key)) {\n const existing = byKey.get(key);\n // Every synthetic entry is a file cut by the global diff cap, whether\n // the cut lands in the first file or after a complete prefix.\n if (existing?.synthetic === true) {\n existing.skipped = true;\n if (!warnings.includes(warning)) warnings.push(warning);\n }\n continue;\n }\n // Only this backfill copy carries the marker; the seed above stays plain\n // listing metadata so it is not mistaken for a diff-cap omission.\n const entry: ParsedFile = { ...listed, backfill: true };\n seen.add(key);\n byKey.set(key, entry);\n candidates.push(entry);\n if (!warnings.includes(warning)) warnings.push(warning);\n }\n candidates.sort((left, right) => comparePaths(left.path, right.path));\n }\n\n let renderCapped = false;\n let selected = candidates;\n const reviewableCandidates = candidates.filter((entry) => !isIgnored(entry.path, ignore));\n if (reviewableCandidates.length > maxFiles) {\n const kept = new Set(reviewableCandidates.slice(0, maxFiles));\n selected = candidates.filter((entry) => isIgnored(entry.path, ignore) || kept.has(entry));\n truncated = true;\n renderCapped = true;\n warnings.push('files-truncated');\n }\n\n const modeListing = await headModes(scope.repoRoot, scope.headSha, options.signal);\n if (!modeListing.available) warnings.push('submodule-modes-unavailable');\n\n const budget: ContentBudget = {\n includeContent,\n maxTotalBytes: maxTotalContentBytes,\n usedBytes: 0,\n exhausted: false,\n warned: false,\n warnings,\n };\n const files: FileDiff[] = [];\n for (const entry of selected) {\n if (entry.backfill === true) {\n const seed = seeds.get(entry.path);\n const skipped: FileDiff = {\n path: entry.path,\n status: entry.status,\n binary: seed?.binary === true,\n oversized: false,\n added: 0,\n deleted: 0,\n hunks: [],\n contentHash: null,\n truncated: true,\n reason: 'diff-truncated',\n };\n if (entry.oldPath !== undefined) skipped.oldPath = entry.oldPath;\n if (isIgnored(entry.path, ignore)) skipped.ignored = true;\n files.push(skipped);\n continue;\n }\n if (entry.synthetic === true) {\n const seed = seeds.get(entry.path);\n const synthetic: FileDiff = {\n path: entry.path,\n status: entry.status,\n binary: entry.binary || seed?.binary === true,\n // Nothing measured this file's size; the global diff cap cut it.\n oversized: false,\n added: 0,\n deleted: 0,\n hunks: [],\n contentHash: null,\n truncated: true,\n reason: 'diff-truncated',\n };\n if (entry.oldPath !== undefined) synthetic.oldPath = entry.oldPath;\n if (isIgnored(entry.path, ignore)) synthetic.ignored = true;\n files.push(synthetic);\n continue;\n }\n if (isIgnored(entry.path, ignore)) {\n const ignored: FileDiff = {\n path: entry.path,\n status: entry.status,\n binary: entry.binary,\n oversized: false,\n ignored: true,\n added: entry.added,\n deleted: entry.deleted,\n hunks: [],\n contentHash: null,\n };\n if (entry.oldPath !== undefined) ignored.oldPath = entry.oldPath;\n files.push(ignored);\n continue;\n }\n const oldPath = entry.oldPath ?? entry.path;\n const hasMode =\n entry.oldMode !== undefined || entry.newMode !== undefined || entry.indexMode !== undefined;\n const isGitlink = hasMode\n ? entry.oldMode === '160000' || entry.newMode === '160000' || entry.indexMode === '160000'\n : modeListing.modes.get(entry.path) === '160000';\n if (isGitlink) {\n // A gitlink addresses a commit, not a worktree path: never read content for it.\n const submodule: FileDiff = {\n path: entry.path,\n status: 'submodule',\n binary: false,\n oversized: false,\n added: entry.added,\n deleted: entry.deleted,\n hunks: entry.hunks,\n contentHash: null,\n };\n if (entry.oldPath !== undefined) submodule.oldPath = entry.oldPath;\n files.push(submodule);\n continue;\n }\n const budgetSkipped = includeContent && budget.exhausted;\n const base =\n entry.status === 'added' || !includeContent || budgetSkipped\n ? null\n : await readBlob(scope.repoRoot, scope.baseSha, oldPath, maxFileLines, maxContentBytes);\n const head =\n entry.status === 'deleted' || !includeContent || budgetSkipped\n ? null\n : await readBlob(scope.repoRoot, scope.headSha, entry.path, maxFileLines, maxContentBytes);\n\n const binary = entry.binary || base?.binary === true || head?.binary === true;\n const oversized = base?.oversized === true || head?.oversized === true;\n const encoding =\n base?.encoding === 'unknown' || head?.encoding === 'unknown' ? 'unknown' : undefined;\n const reason =\n base?.reason === 'unreadable' || head?.reason === 'unreadable' ? 'unreadable' : undefined;\n\n let fileTruncated = false;\n let oldLines: string[] | undefined;\n let newLines: string[] | undefined;\n if (reason !== undefined) {\n warnUnreadable(warnings, entry.path);\n } else if (includeContent && !binary && !oversized) {\n if (budgetSkipped) {\n fileTruncated = true;\n } else {\n const bytes =\n (base?.lines === null || base === null ? 0 : base.bytes) +\n (head?.lines === null || head === null ? 0 : head.bytes);\n if (fitsContent(budget, bytes)) {\n oldLines = base?.lines ?? undefined;\n newLines = head?.lines ?? undefined;\n } else {\n fileTruncated = true;\n }\n }\n }\n\n let contentHash: string | null = null;\n if (includeContent && !oversized && reason === undefined && !fileTruncated) {\n if (head !== null && head.hash !== '') contentHash = head.hash;\n else if (base !== null && base.hash !== '') contentHash = base.hash;\n }\n\n const file: FileDiff = {\n path: entry.path,\n status: entry.status,\n binary,\n oversized,\n added: entry.added,\n deleted: entry.deleted,\n hunks: binary || oversized ? [] : entry.hunks,\n contentHash,\n };\n if (entry.oldPath !== undefined) file.oldPath = entry.oldPath;\n if (encoding !== undefined) file.encoding = encoding;\n if (reason !== undefined) file.reason = reason;\n if (fileTruncated) file.truncated = true;\n if (oldLines !== undefined) file.oldLines = oldLines;\n if (newLines !== undefined) file.newLines = newLines;\n files.push(file);\n }\n\n if (unmerged.size > 0) {\n for (const file of files) {\n if (unmerged.has(file.path)) file.conflicted = true;\n }\n }\n\n if (scope.kind === 'worktree' && includeUntracked) {\n const listing = await listUntracked(scope.repoRoot, options.signal);\n if (listing.truncated) {\n if (!warnings.includes('untracked-list-truncated')) {\n warnings.push('untracked-list-truncated');\n }\n truncated = true;\n }\n for (const path of listing.paths) {\n const ignored = isIgnored(path, ignore);\n const seed: ManifestSeed = {\n path,\n status: 'untracked',\n binary: false,\n added: 0,\n deleted: 0,\n ignored,\n oversized: false,\n fromNumstat: false,\n };\n seeds.set(path, seed);\n const absolute = safeJoin(scope.repoRoot, path);\n const info = await lstat(absolute).catch(() => null);\n if (info?.isSymbolicLink() === true || (await hasSymlinkParent(scope.repoRoot, path))) {\n // The link target is deliberately not followed. Mark it as a symlink\n // rather than unreadable so coverage can treat it as terminal\n // `no-hunks` instead of pinning every worktree review to `partial`.\n seed.reason = 'symlink';\n warnings.push(`symlink-not-followed:${path}`);\n continue;\n }\n const file = await untrackedFile(\n scope.repoRoot,\n path,\n maxFileLines,\n maxContentBytes,\n includeContent,\n ignored,\n budget,\n warnings,\n );\n if (file !== null) files.push(file);\n }\n }\n\n files.sort((left, right) => comparePaths(left.path, right.path));\n\n // Everything built before the render cap is retained for manifest metadata;\n // culling below only bounds what the snapshot renders.\n const retainedFiles = files.slice();\n const reviewableFiles = files.filter((file) => file.ignored !== true);\n if (reviewableFiles.length > maxFiles) {\n const kept = new Set(reviewableFiles.slice(0, maxFiles));\n files.splice(\n 0,\n files.length,\n ...files.filter((file) => file.ignored === true || kept.has(file)),\n );\n truncated = true;\n renderCapped = true;\n if (!warnings.includes('files-truncated')) warnings.push('files-truncated');\n }\n\n const retainedByPath = new Map(retainedFiles.map((file) => [file.path, file]));\n for (const file of retainedFiles) {\n if (seeds.has(file.path)) continue;\n const seed: ManifestSeed = {\n path: file.path,\n status: file.status,\n binary: file.binary,\n added: file.added,\n deleted: file.deleted,\n ignored: file.ignored === true,\n oversized: file.oversized,\n fromNumstat: false,\n };\n if (file.oldPath !== undefined) seed.oldPath = file.oldPath;\n if (file.reason !== undefined) seed.reason = file.reason;\n seeds.set(file.path, seed);\n }\n\n const renderPaths = new Set(files.map((file) => file.path));\n const manifest = reviewManifest(\n scope,\n [...seeds.values()]\n .map((seed) => {\n const file = retainedByPath.get(seed.path);\n return manifestEntry({\n seed,\n ...(file === undefined ? {} : { file }),\n renderExcluded: !renderPaths.has(seed.path),\n });\n })\n .sort((left, right) => comparePaths(left.path, right.path)),\n warnings,\n );\n\n const manifestTruncated =\n truncated ||\n budget.exhausted ||\n renderCapped ||\n manifest.files.some(\n (file) =>\n file.reason === 'render-budget' ||\n file.reason === 'diff-truncated' ||\n file.reason === 'per-file-cap',\n );\n\n const totals = {\n files: manifest.totals.files,\n added: manifest.totals.added,\n deleted: manifest.totals.deleted,\n truncated: manifestTruncated,\n };\n\n return {\n schemaVersion: 2,\n scope,\n files,\n manifest,\n totals,\n warnings,\n };\n}\n", "import { createHash } from 'node:crypto';\nimport { lstat, readFile, readlink } from 'node:fs/promises';\nimport { hasSymlinkParent, safeJoin } from '../paths.js';\nimport { GitError, runGit } from './run.js';\nimport type { GitResult } from './run.js';\n\nconst DEFAULT_MAX_BYTES = 8 * 1024 * 1024;\n\nexport interface BlobRead {\n lines: string[] | null;\n binary: boolean;\n oversized: boolean;\n symlink: boolean;\n hash: string;\n /** Raw bytes retained for content-budget accounting (0 when no content is kept). */\n bytes: number;\n encoding?: 'unknown';\n reason?: 'unreadable';\n}\n\nconst EMPTY: BlobRead = {\n lines: null,\n binary: false,\n oversized: false,\n symlink: false,\n hash: '',\n bytes: 0,\n};\n\nfunction hashOf(buffer: Buffer): string {\n return createHash('sha256').update(buffer).digest('hex');\n}\n\nfunction splitText(text: string): string[] {\n const lines = text.split('\\n');\n if (lines.length > 0 && lines[lines.length - 1] === '') lines.pop();\n return lines;\n}\n\nfunction decode(buffer: Buffer): string | null {\n try {\n return new TextDecoder('utf-8', { fatal: true }).decode(buffer);\n } catch {\n return null;\n }\n}\n\nfunction readBuffer(buffer: Buffer, maxLines: number, symlink: boolean): BlobRead {\n if (buffer.includes(0)) {\n return { ...EMPTY, binary: true, hash: hashOf(buffer), bytes: buffer.length };\n }\n const text = decode(buffer);\n if (text === null) {\n return {\n ...EMPTY,\n binary: true,\n encoding: 'unknown',\n hash: hashOf(buffer),\n bytes: buffer.length,\n };\n }\n const lines = splitText(text);\n if (lines.length > maxLines) return { ...EMPTY, oversized: true };\n return {\n lines,\n binary: false,\n oversized: false,\n symlink,\n hash: hashOf(buffer),\n bytes: buffer.length,\n };\n}\n\nexport async function readBlob(\n repoRoot: string,\n revision: string | null,\n path: string,\n maxLines: number,\n maxBytes: number = DEFAULT_MAX_BYTES,\n): Promise<BlobRead> {\n let buffer: Buffer;\n\n if (revision === null) {\n const absolute = safeJoin(repoRoot, path);\n if (await hasSymlinkParent(repoRoot, path)) {\n return { ...EMPTY, symlink: true };\n }\n\n let info: Awaited<ReturnType<typeof lstat>>;\n try {\n info = await lstat(absolute);\n } catch {\n return { ...EMPTY, reason: 'unreadable' };\n }\n if (info.isSymbolicLink()) {\n let target: Buffer;\n try {\n target = await readlink(absolute, { encoding: 'buffer' });\n } catch {\n return { ...EMPTY, symlink: true, reason: 'unreadable' };\n }\n if (target.length > maxBytes) return { ...EMPTY, symlink: true, oversized: true };\n return readBuffer(target, maxLines, true);\n }\n if (!info.isFile()) return EMPTY;\n if (info.size > maxBytes) {\n return { ...EMPTY, oversized: true };\n }\n\n try {\n buffer = await readFile(absolute);\n } catch {\n return { ...EMPTY, reason: 'unreadable' };\n }\n } else {\n let result: GitResult;\n try {\n result = await runGit(repoRoot, ['show', `${revision}:${path}`], {\n allowFailure: true,\n maxBytes,\n });\n } catch (error) {\n if (error instanceof GitError && error.message.includes('exceeded')) {\n return { ...EMPTY, oversized: true };\n }\n throw error;\n }\n if (result.code !== 0) return EMPTY;\n if (result.stdoutBytes.length > maxBytes) return { ...EMPTY, oversized: true };\n buffer = result.stdoutBytes;\n }\n\n return readBuffer(buffer, maxLines, false);\n}\n", "import { spawn } from 'node:child_process';\n\nexport type GitErrorCode = 'git-missing' | 'not-a-repo' | 'git-failed';\n\nexport class GitError extends Error {\n constructor(\n readonly code: GitErrorCode,\n message: string,\n readonly stderr = '',\n ) {\n super(message);\n this.name = 'GitError';\n }\n}\n\nexport interface GitRunOptions {\n allowFailure?: boolean;\n maxBytes?: number;\n maxStderrBytes?: number;\n truncateOnOverflow?: boolean;\n signal?: AbortSignal;\n env?: NodeJS.ProcessEnv;\n}\n\nexport interface GitResult {\n stdout: string;\n stdoutBytes: Buffer;\n stderr: string;\n code: number;\n truncated?: boolean;\n}\n\nconst DEFAULT_MAX_BYTES = 16 * 1024 * 1024;\nconst DEFAULT_MAX_STDERR_BYTES = 1024 * 1024;\n\nexport async function runGit(\n cwd: string,\n args: readonly string[],\n options: GitRunOptions = {},\n): Promise<GitResult> {\n const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;\n const maxStderrBytes = options.maxStderrBytes ?? DEFAULT_MAX_STDERR_BYTES;\n if (options.signal?.aborted === true) {\n throw new GitError('git-failed', 'git command aborted');\n }\n\n const env: NodeJS.ProcessEnv = { ...process.env };\n delete env.GIT_DIR;\n delete env.GIT_WORK_TREE;\n delete env.GIT_INDEX_FILE;\n Object.assign(env, {\n GIT_CONFIG_NOSYSTEM: '1',\n GIT_EXTERNAL_DIFF: '',\n GIT_TERMINAL_PROMPT: '0',\n GIT_OPTIONAL_LOCKS: '0',\n LC_ALL: 'C',\n ...options.env,\n });\n\n const gitArgs = [\n '--no-pager',\n '-c',\n 'core.quotePath=false',\n '-c',\n 'core.pager=cat',\n '-c',\n 'diff.external=',\n '-c',\n 'diff.noprefix=false',\n '-c',\n 'diff.mnemonicPrefix=false',\n '-c',\n 'diff.submodule=short',\n ...args,\n ];\n\n return await new Promise<GitResult>((resolve, reject) => {\n const child = spawn('git', gitArgs, {\n cwd,\n shell: false,\n stdio: ['ignore', 'pipe', 'pipe'],\n signal: options.signal,\n env,\n });\n\n const stdout: Buffer[] = [];\n const stderr: Buffer[] = [];\n let bytes = 0;\n let stderrBytes = 0;\n let settled = false;\n\n const fail = (error: GitError): void => {\n if (settled) return;\n settled = true;\n reject(error);\n };\n\n child.on('error', (error: NodeJS.ErrnoException) => {\n if (error.code === 'ENOENT') {\n fail(new GitError('git-missing', 'git executable not found'));\n } else {\n fail(new GitError('git-failed', error.message));\n }\n });\n\n child.stdout.on('data', (chunk: Buffer) => {\n if (settled) return;\n const remaining = maxBytes - bytes;\n if (chunk.length > remaining) {\n if (remaining > 0) {\n stdout.push(chunk.subarray(0, remaining));\n bytes += remaining;\n }\n if (options.truncateOnOverflow === true) {\n child.kill('SIGKILL');\n settled = true;\n const buffer = Buffer.concat(stdout);\n resolve({\n stdout: buffer.toString('utf8'),\n stdoutBytes: buffer,\n stderr: Buffer.concat(stderr).toString('utf8'),\n code: 1,\n truncated: true,\n });\n return;\n }\n child.kill('SIGKILL');\n fail(new GitError('git-failed', `git output exceeded ${maxBytes} bytes`));\n return;\n }\n stdout.push(chunk);\n bytes += chunk.length;\n });\n\n child.stderr.on('data', (chunk: Buffer) => {\n stderrBytes += chunk.length;\n if (stderrBytes > maxStderrBytes) {\n child.kill('SIGKILL');\n fail(new GitError('git-failed', `git stderr exceeded ${maxStderrBytes} bytes`));\n return;\n }\n stderr.push(chunk);\n });\n\n child.on('close', (code) => {\n if (settled) return;\n const buffer = Buffer.concat(stdout);\n const result: GitResult = {\n stdout: buffer.toString('utf8'),\n stdoutBytes: buffer,\n stderr: Buffer.concat(stderr).toString('utf8'),\n code: code ?? 1,\n truncated: false,\n };\n if (result.code !== 0 && options.allowFailure !== true) {\n settled = true;\n reject(\n new GitError(\n 'git-failed',\n `git ${args.join(' ')} failed (${result.code}): ${result.stderr.trim()}`,\n result.stderr,\n ),\n );\n return;\n }\n settled = true;\n resolve(result);\n });\n });\n}\n", "import { createHash, type Hash } from 'node:crypto';\nimport { constants } from 'node:fs';\nimport { lstat, open, readlink, realpath } from 'node:fs/promises';\nimport { isAbsolute, relative, sep } from 'node:path';\nimport type { DiffScope, ResolvedScope } from '../types.js';\nimport { hasSymlinkParent, safeJoin, splitNulPaths } from '../paths.js';\nimport { resolveRepoRoot } from './repo.js';\nimport { GitError, runGit } from './run.js';\n\nexport const EMPTY_TREE_SHA = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';\n\nexport async function resolveDefaultBase(repoRoot: string): Promise<string> {\n const origin = await runGit(repoRoot, ['symbolic-ref', '--short', 'refs/remotes/origin/HEAD'], {\n allowFailure: true,\n });\n if (origin.code === 0 && origin.stdout.trim() !== '') return origin.stdout.trim();\n\n for (const candidate of ['main', 'master']) {\n const result = await runGit(\n repoRoot,\n ['rev-parse', '--verify', '--quiet', `refs/heads/${candidate}`],\n { allowFailure: true },\n );\n if (result.code === 0) return candidate;\n }\n\n const head = await runGit(repoRoot, ['symbolic-ref', '--short', 'HEAD'], { allowFailure: true });\n if (head.code === 0 && head.stdout.trim() !== '') return head.stdout.trim();\n throw new GitError('git-failed', 'cannot determine the default base branch');\n}\n\nexport interface ResolveScopeInput {\n repoRoot: string;\n scope: DiffScope;\n signal?: AbortSignal;\n}\n\nexport async function resolveScope(input: ResolveScopeInput): Promise<ResolvedScope> {\n const root = await resolveRepoRoot(input.repoRoot);\n const signal = input.signal;\n\n if (input.scope.kind === 'range') {\n const headSha = await resolveCommitRef(root, input.scope.headRef, signal);\n const baseSha =\n input.scope.twoDot === true\n ? await resolveCommitRef(root, input.scope.baseRef, signal)\n : (\n await runGit(root, [\n 'merge-base',\n await resolveCommitRef(root, input.scope.baseRef, signal),\n headSha,\n ])\n ).stdout.trim();\n return {\n kind: 'range',\n repoRoot: root,\n baseRef: input.scope.baseRef,\n headRef: input.scope.headRef,\n baseSha,\n headSha,\n label: `${input.scope.baseRef}${input.scope.twoDot === true ? '..' : '...'}${input.scope.headRef}`,\n worktreeDigest: headSha,\n };\n }\n\n if (input.scope.kind === 'worktree') {\n const baseSha = await resolveCommitRef(root, input.scope.baseRef, signal);\n const digest = await worktreeDigestState(root, baseSha, signal);\n const resolved: ResolvedScope = {\n kind: 'worktree',\n repoRoot: root,\n baseRef: input.scope.baseRef,\n baseSha,\n headSha: null,\n label: `${input.scope.baseRef} (worktree)`,\n worktreeDigest: digest.hash,\n };\n if (digest.truncated) resolved.worktreeDigestTruncated = true;\n return resolved;\n }\n\n if (input.scope.kind === 'commits') {\n const shas: unknown = input.scope.shas;\n if (!Array.isArray(shas) || shas.length === 0) {\n throw new GitError('git-failed', 'a commit scope needs at least one commit');\n }\n if (shas.length > MAX_SELECTED_COMMITS) {\n throw new GitError(\n 'git-failed',\n `a commit scope accepts at most ${MAX_SELECTED_COMMITS} commits`,\n );\n }\n const resolved: string[] = [];\n const seen = new Set<string>();\n for (const sha of shas) {\n if (typeof sha !== 'string' || sha.trim() === '') {\n throw new GitError('git-failed', 'every selected commit must be a commit ref');\n }\n const resolvedSha = await resolveCommitRef(root, sha.trim(), signal);\n if (seen.has(resolvedSha)) continue;\n seen.add(resolvedSha);\n resolved.push(resolvedSha);\n }\n for (let index = 1; index < resolved.length; index += 1) {\n const previous = resolved[index - 1] ?? '';\n const current = resolved[index] ?? '';\n const ancestor = await runGit(root, ['merge-base', '--is-ancestor', previous, current], {\n allowFailure: true,\n signal,\n });\n if (ancestor.code !== 0) {\n throw new GitError(\n 'git-failed',\n 'selected commits must be ordered oldest to newest along one ancestry path',\n );\n }\n }\n const oldest = resolved[0] ?? '';\n const headSha = resolved[resolved.length - 1] ?? oldest;\n const baseSha = await resolveParentBase(root, oldest, signal);\n return {\n kind: 'commits',\n repoRoot: root,\n baseSha,\n headSha,\n label:\n resolved.length === 1\n ? `commit ${headSha.slice(0, 8)}`\n : `${resolved.length} commits: ${oldest.slice(0, 8)}..${headSha.slice(0, 8)}`,\n worktreeDigest: headSha,\n shas: resolved,\n };\n }\n\n const headSha = await resolveCommitRef(root, input.scope.sha, signal);\n return {\n kind: 'commit',\n repoRoot: root,\n baseSha: await resolveParentBase(root, headSha, signal),\n headSha,\n label: headSha.slice(0, 12),\n worktreeDigest: headSha,\n };\n}\n\nconst MAX_SELECTED_COMMITS = 200;\n\nasync function resolveCommitRef(\n repoRoot: string,\n ref: string,\n signal?: AbortSignal,\n): Promise<string> {\n const result = await runGit(\n repoRoot,\n ['rev-parse', '--verify', '--end-of-options', `${ref}^{commit}`],\n { signal },\n );\n return result.stdout.trim();\n}\n\nasync function resolveParentBase(\n repoRoot: string,\n headSha: string,\n signal?: AbortSignal,\n): Promise<string> {\n const parentSha = await firstParentSha(repoRoot, headSha, signal);\n if (parentSha === null) return EMPTY_TREE_SHA;\n const available = await runGit(repoRoot, ['cat-file', '-e', `${parentSha}^{commit}`], {\n allowFailure: true,\n signal,\n });\n if (available.code !== 0) {\n throw new GitError(\n 'git-failed',\n `commit ${headSha} has a parent that is not available; fetch/unshallow the repository`,\n );\n }\n return parentSha;\n}\n\nasync function firstParentSha(\n repoRoot: string,\n headSha: string,\n signal?: AbortSignal,\n): Promise<string | null> {\n const listed = await runGit(repoRoot, ['rev-list', '--parents', '-n', '1', headSha], { signal });\n const fields = listed.stdout\n .trim()\n .split(/\\s+/)\n .filter((field) => field !== '');\n if (fields.length > 1) return fields[1] ?? null;\n\n // `rev-list` hides the parent of a shallow boundary. The commit object still\n // records it, so use that to tell a real root commit from an unshallowed edge.\n const object = await runGit(repoRoot, ['cat-file', '-p', headSha], { signal });\n const match = /^parent ([0-9a-f]{40})$/m.exec(object.stdout);\n return match?.[1] ?? null;\n}\n\ninterface WorktreeDigestState {\n hash: string;\n truncated: boolean;\n}\n\nfunction compareBytePaths(left: string, right: string): number {\n return Buffer.compare(Buffer.from(left, 'utf8'), Buffer.from(right, 'utf8'));\n}\n\nfunction abortedError(): GitError {\n return new GitError('git-failed', 'git command aborted');\n}\n\nfunction isAborted(signal?: AbortSignal): boolean {\n return signal?.aborted === true;\n}\n\nconst DIGEST_DOMAIN = Buffer.from('dsh-worktree-digest-v2\\0', 'utf8');\nconst RECORD_DOMAIN = Buffer.from('dsh-untracked-record-v2\\0', 'utf8');\nconst TAG_STATUS = 1;\nconst TAG_DIFF = 2;\nconst TAG_UNTRACKED = 3;\nconst FIELD_TYPE = 1;\nconst FIELD_PATH = 2;\nconst FIELD_CONTENT = 3;\nconst TYPE_FILE = 1;\nconst TYPE_SYMLINK = 2;\nconst TYPE_UNREADABLE = 3;\nconst UNREADABLE = Buffer.from('unreadable', 'utf8');\n\nfunction updateFramedHeader(hash: Hash, tag: number, length: number): void {\n const header = Buffer.alloc(9);\n header.writeUInt8(tag, 0);\n header.writeBigUInt64BE(BigInt(length), 1);\n hash.update(header);\n}\n\nfunction updateFramed(hash: Hash, tag: number, data: Buffer): void {\n updateFramedHeader(hash, tag, data.length);\n hash.update(data);\n}\n\nfunction newRecord(): Hash {\n return createHash('sha256').update(RECORD_DOMAIN);\n}\n\nfunction recordPrefix(type: number, pathBytes: Buffer): Hash {\n const record = newRecord();\n updateFramed(record, FIELD_TYPE, Buffer.from([type]));\n updateFramed(record, FIELD_PATH, pathBytes);\n return record;\n}\n\nfunction unreadableRecord(pathBytes: Buffer): Buffer {\n const record = recordPrefix(TYPE_UNREADABLE, pathBytes);\n updateFramed(record, FIELD_CONTENT, UNREADABLE);\n return record.digest();\n}\n\nfunction symlinkRecord(pathBytes: Buffer, target: Buffer): Buffer {\n const record = recordPrefix(TYPE_SYMLINK, pathBytes);\n updateFramed(record, FIELD_CONTENT, target);\n return record.digest();\n}\n\nfunction fileRecord(pathBytes: Buffer, size: number): Hash {\n const record = recordPrefix(TYPE_FILE, pathBytes);\n updateFramedHeader(record, FIELD_CONTENT, size);\n return record;\n}\n\nasync function openedPath(handle: { readonly fd: number }, absolute: string): Promise<string> {\n try {\n // /proc/self/fd names the opened descriptor, not the current pathname.\n return await readlink(`/proc/self/fd/${handle.fd}`);\n } catch {\n // Non-procfs platforms keep the pathname-based fallback and its TOCTOU window.\n return await realpath(absolute);\n }\n}\n\nasync function untrackedRecord(\n repoRoot: string,\n realRoot: string,\n path: string,\n signal?: AbortSignal,\n): Promise<Buffer> {\n if (isAborted(signal)) throw abortedError();\n const absolute = safeJoin(repoRoot, path);\n const pathBytes = Buffer.from(path, 'utf8');\n if (await hasSymlinkParent(repoRoot, path)) return unreadableRecord(pathBytes);\n\n let info;\n try {\n info = await lstat(absolute);\n } catch {\n return unreadableRecord(pathBytes);\n }\n if (isAborted(signal)) throw abortedError();\n\n if (info.isSymbolicLink()) {\n try {\n const target = await readlink(absolute, { encoding: 'buffer' });\n if (isAborted(signal)) throw abortedError();\n return symlinkRecord(pathBytes, target);\n } catch {\n if (isAborted(signal)) throw abortedError();\n return unreadableRecord(pathBytes);\n }\n }\n\n let handle;\n try {\n handle = await open(absolute, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);\n const stat = await handle.stat();\n if (!stat.isFile()) return unreadableRecord(pathBytes);\n const opened = await openedPath(handle, absolute);\n if (!isAbsolute(opened)) return unreadableRecord(pathBytes);\n const rel = relative(realRoot, opened);\n if (rel === '' || rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {\n return unreadableRecord(pathBytes);\n }\n const record = fileRecord(pathBytes, stat.size);\n if (stat.size > 0) {\n let read = 0;\n const stream = handle.createReadStream({\n start: 0,\n end: stat.size - 1,\n autoClose: false,\n signal,\n });\n for await (const chunk of stream) {\n record.update(chunk);\n read += chunk.length;\n }\n if (read !== stat.size) return unreadableRecord(pathBytes);\n }\n return record.digest();\n } catch {\n if (isAborted(signal)) throw abortedError();\n return unreadableRecord(pathBytes);\n } finally {\n if (handle !== undefined) await handle.close().catch(() => undefined);\n }\n}\n\nasync function worktreeDigestState(\n repoRoot: string,\n baseSha: string,\n signal?: AbortSignal,\n): Promise<WorktreeDigestState> {\n const status = await runGit(\n repoRoot,\n ['status', '--porcelain=v2', '-z', '--untracked-files=all'],\n { signal, maxBytes: 8 * 1024 * 1024, truncateOnOverflow: true },\n );\n const diff = await runGit(\n repoRoot,\n [\n 'diff',\n '--no-color',\n '--no-ext-diff',\n '--no-textconv',\n '--binary',\n '--src-prefix=a/',\n '--dst-prefix=b/',\n baseSha,\n '--',\n ],\n { signal, maxBytes: 8 * 1024 * 1024, truncateOnOverflow: true },\n );\n const untracked = await runGit(repoRoot, ['ls-files', '--others', '--exclude-standard', '-z'], {\n signal,\n maxBytes: 8 * 1024 * 1024,\n truncateOnOverflow: true,\n });\n const hash = createHash('sha256').update(DIGEST_DOMAIN);\n updateFramed(hash, TAG_STATUS, status.stdoutBytes);\n updateFramed(hash, TAG_DIFF, diff.stdoutBytes);\n const realRoot = await realpath(repoRoot);\n const paths = splitNulPaths(untracked.stdout).sort(compareBytePaths);\n for (const path of paths) {\n updateFramed(hash, TAG_UNTRACKED, await untrackedRecord(repoRoot, realRoot, path, signal));\n }\n return {\n hash: hash.digest('hex'),\n truncated: status.truncated === true || diff.truncated === true || untracked.truncated === true,\n };\n}\n\nexport async function worktreeDigest(\n repoRoot: string,\n baseSha: string,\n signal?: AbortSignal,\n): Promise<string> {\n return (await worktreeDigestState(repoRoot, baseSha, signal)).hash;\n}\n", "import { realpath, stat } from 'node:fs/promises';\nimport { GitError, runGit } from './run.js';\n\nexport async function resolveRepoRoot(input: string): Promise<string> {\n const absolute = await realpath(input).catch(() => {\n throw new GitError('not-a-repo', `path does not exist: ${input}`);\n });\n const info = await stat(absolute).catch(() => {\n throw new GitError('not-a-repo', `path does not exist: ${input}`);\n });\n if (!info.isDirectory()) {\n throw new GitError('not-a-repo', `not a directory: ${input}`);\n }\n\n const result = await runGit(absolute, ['rev-parse', '--show-toplevel'], {\n allowFailure: true,\n });\n if (result.code !== 0) {\n throw new GitError('not-a-repo', `not a git repository: ${input}`, result.stderr);\n }\n return await realpath(result.stdout.trim());\n}\n", "import type {\n DiffHunk,\n FileDiff,\n ManifestFile,\n ManifestFileReason,\n ResolvedScope,\n ReviewManifest,\n Snapshot,\n} from '../types.js';\n\nconst LINE_PREFIX: Record<DiffHunk['lines'][number]['kind'], string> = {\n add: '+',\n del: '-',\n context: ' ',\n};\n\nfunction hunkHeaderLine(hunk: DiffHunk): string {\n const section = hunk.header === '' ? '' : ` ${hunk.header}`;\n return `@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@${section}`;\n}\n\n/**\n * UTF-8 byte size of the parsed hunks. This is a lower bound on the full\n * unified-diff bytes for a file (path/mode/index metadata is not retained);\n * use raw diff bytes where an exact budget matters.\n */\nexport function patchBytesFromHunks(hunks: readonly DiffHunk[]): number {\n let bytes = 0;\n for (const hunk of hunks) {\n bytes += Buffer.byteLength(`${hunkHeaderLine(hunk)}\\n`, 'utf8');\n for (const line of hunk.lines) {\n bytes += Buffer.byteLength(`${LINE_PREFIX[line.kind]}${line.text}\\n`, 'utf8');\n }\n }\n return bytes;\n}\n\nfunction reasonForFile(file: FileDiff): ManifestFileReason | undefined {\n if (file.reason !== undefined) return file.reason;\n if (file.ignored === true) return 'ignored';\n if (file.binary) return 'binary';\n if (file.oversized) return 'per-file-cap';\n return undefined;\n}\n\n/**\n * Maps one bounded render entry to its complete-manifest entry.\n *\n * `FileDiff.truncated` and `FileDiff.encoding` are intentionally not manifest\n * fields in R1. A missing `contentBytes` means \"unknown\", never \"no content\".\n */\nexport function manifestFileFromDiff(file: FileDiff): ManifestFile {\n const reason = reasonForFile(file);\n return {\n path: file.path,\n ...(file.oldPath === undefined ? {} : { oldPath: file.oldPath }),\n status: file.status,\n binary: file.binary,\n ignored: file.ignored === true,\n oversized: file.oversized,\n ...(file.conflicted === true ? { conflicted: true } : {}),\n added: file.added,\n deleted: file.deleted,\n hunkCount: file.hunks.length,\n patchBytes: patchBytesFromHunks(file.hunks),\n ...(reason === undefined ? {} : { reason }),\n };\n}\n\n/** Builds a manifest document from already-normalized entries. */\nexport function reviewManifest(\n scope: ResolvedScope,\n files: readonly ManifestFile[],\n warnings: readonly string[] = [],\n): ReviewManifest {\n const totals = files.reduce(\n (accumulator, file) => ({\n files: accumulator.files + 1,\n added: accumulator.added + file.added,\n deleted: accumulator.deleted + file.deleted,\n patchBytes: accumulator.patchBytes + file.patchBytes,\n }),\n { files: 0, added: 0, deleted: 0, patchBytes: 0 },\n );\n return {\n schemaVersion: 1,\n scope,\n files: [...files],\n totals,\n warnings: [...warnings],\n };\n}\n\n/**\n * Builds a complete manifest from the available render entries. Callers that\n * have the full changed-path listing must supply every path here; this helper\n * never applies a file-count cap.\n */\nexport function buildReviewManifest(input: {\n scope: ResolvedScope;\n files: readonly FileDiff[];\n warnings?: readonly string[];\n}): ReviewManifest {\n return reviewManifest(\n input.scope,\n input.files.map((file) => manifestFileFromDiff(file)),\n input.warnings,\n );\n}\n\n/**\n * Returns the snapshot's own manifest when present. Legacy v1 snapshots only\n * retain the bounded render subset, so a truncated one gets a\n * `legacy-truncated` warning; a complete v1 snapshot already lists every path.\n * A v2 snapshot without a manifest is corrupt, so its synthesized manifest is\n * marked `manifest-missing` and coverage cannot treat the render subset as the\n * complete changed-path listing.\n *\n * `totals.truncated` is the only aggregate truncation signal a legacy snapshot\n * retains, and it covers files, diff bytes, and content bytes alike. Keeping\n * the warning for all three is deliberate: we cannot tell from a legacy\n * snapshot whether a path was omitted, only that some budget was applied.\n */\nexport function manifestFromSnapshot(snapshot: Snapshot): ReviewManifest {\n if (snapshot.manifest !== undefined) return snapshot.manifest;\n const warnings = [...snapshot.warnings];\n if (snapshot.schemaVersion === 2) {\n if (!warnings.includes('manifest-missing')) warnings.push('manifest-missing');\n } else if (snapshot.totals.truncated && !warnings.includes('legacy-truncated')) {\n warnings.push('legacy-truncated');\n }\n return buildReviewManifest({ scope: snapshot.scope, files: snapshot.files, warnings });\n}\n", "import type { DiffHunk, DiffLine, ParsedFile } from '../types.js';\n\ninterface MutableFile {\n path: string;\n oldPath?: string;\n status: 'added' | 'modified' | 'deleted' | 'renamed';\n binary: boolean;\n hunks: DiffHunk[];\n added: number;\n deleted: number;\n oldMode?: string;\n newMode?: string;\n indexMode?: string;\n oldIsNull: boolean;\n newIsNull: boolean;\n}\n\nconst FILE_HEADER = /^diff --git a\\/(.+) b\\/(.+)$/;\nconst HUNK_HEADER = /^@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@(?: ?(.*))?$/;\nconst INDEX_LINE = /^index [0-9a-f]+\\.\\.[0-9a-f]+ (\\d{6})$/;\n\nexport interface DiffHeader {\n oldPath: string;\n newPath: string;\n}\n\n/** Parse a `diff --git` line and fail closed on ambiguous paths. */\nexport function parseDiffHeader(line: string, lineNumber = 1): DiffHeader {\n const match = FILE_HEADER.exec(line);\n const separatorCount = line.split(' b/').length - 1;\n if (match === null || separatorCount !== 1) {\n throw new DiffParseError(\n `Malformed or ambiguous diff file header at line ${lineNumber}: expected exactly one \" b/\" separator between a/<path> and b/<path>`,\n lineNumber,\n );\n }\n return { oldPath: match[1], newPath: match[2] };\n}\n\nexport class DiffParseError extends Error {\n readonly line: number;\n\n constructor(message: string, line: number) {\n super(message);\n this.name = 'DiffParseError';\n this.line = line;\n }\n}\n\nexport function parseUnifiedDiff(diff: string): ParsedFile[] {\n const files: ParsedFile[] = [];\n let current: MutableFile | null = null;\n let hunk: DiffHunk | null = null;\n let oldNo = 0;\n let newNo = 0;\n\n const finish = (): void => {\n if (current === null) return;\n if (hunk !== null) current.hunks.push(hunk);\n const hunks = current.hunks.filter((candidate) => candidate.lines.length > 0);\n\n let status = current.status;\n if (current.oldIsNull && !current.newIsNull) status = 'added';\n else if (!current.oldIsNull && current.newIsNull) status = 'deleted';\n else if (current.oldPath !== undefined && current.oldPath !== current.path) status = 'renamed';\n\n const parsed: ParsedFile = {\n path: current.path,\n status,\n binary: current.binary,\n hunks,\n added: current.added,\n deleted: current.deleted,\n };\n if (current.oldPath !== undefined && current.oldPath !== current.path) {\n parsed.oldPath = current.oldPath;\n }\n if (current.oldMode !== undefined) parsed.oldMode = current.oldMode;\n if (current.newMode !== undefined) parsed.newMode = current.newMode;\n if (current.indexMode !== undefined) parsed.indexMode = current.indexMode;\n files.push(parsed);\n\n current = null;\n hunk = null;\n };\n\n for (const [index, line] of diff.split('\\n').entries()) {\n if (line.startsWith('diff --git ')) {\n finish();\n const { oldPath, newPath } = parseDiffHeader(line, index + 1);\n current = {\n path: newPath,\n ...(oldPath !== newPath ? { oldPath } : {}),\n status: 'modified',\n binary: false,\n hunks: [],\n added: 0,\n deleted: 0,\n oldIsNull: false,\n newIsNull: false,\n };\n continue;\n }\n\n if (current === null) continue;\n\n if (line.startsWith('@@ ')) {\n if (hunk !== null) current.hunks.push(hunk);\n const match = HUNK_HEADER.exec(line);\n if (match === null) {\n hunk = null;\n continue;\n }\n const oldStart = Number(match[1]);\n const oldLines = match[2] === undefined ? 1 : Number(match[2]);\n const newStart = Number(match[3]);\n const newLines = match[4] === undefined ? 1 : Number(match[4]);\n hunk = {\n oldStart,\n oldLines,\n newStart,\n newLines,\n header: match[5] ?? '',\n lines: [],\n };\n oldNo = oldStart;\n newNo = newStart;\n continue;\n }\n\n if (hunk === null) {\n if (line.startsWith('new file mode ')) {\n current.status = 'added';\n current.newMode = line.slice('new file mode '.length);\n continue;\n }\n if (line.startsWith('deleted file mode ')) {\n current.status = 'deleted';\n current.oldMode = line.slice('deleted file mode '.length);\n continue;\n }\n if (line.startsWith('old mode ')) {\n current.oldMode = line.slice('old mode '.length);\n continue;\n }\n if (line.startsWith('new mode ')) {\n current.newMode = line.slice('new mode '.length);\n continue;\n }\n if (line.startsWith('index ')) {\n const match = INDEX_LINE.exec(line);\n if (match?.[1] !== undefined) current.indexMode = match[1];\n continue;\n }\n if (line.startsWith('rename from ')) {\n current.oldPath = line.slice('rename from '.length);\n current.status = 'renamed';\n continue;\n }\n if (line.startsWith('rename to ')) {\n current.path = line.slice('rename to '.length);\n current.status = 'renamed';\n continue;\n }\n if (line.startsWith('--- ')) {\n const value = line.slice(4);\n if (value === '/dev/null') {\n current.oldIsNull = true;\n current.status = 'added';\n } else {\n current.oldPath = stripPrefix(value);\n }\n continue;\n }\n if (line.startsWith('+++ ')) {\n const value = line.slice(4);\n if (value === '/dev/null') {\n current.newIsNull = true;\n current.status = 'deleted';\n } else {\n current.path = stripPrefix(value);\n }\n continue;\n }\n if (line.startsWith('Binary files ') || line === 'GIT binary patch') {\n current.binary = true;\n continue;\n }\n continue;\n }\n\n if (line.startsWith('\\\\ No newline')) continue;\n\n if (line.startsWith('+') || line.startsWith('-') || line.startsWith(' ')) {\n const kind: DiffLine['kind'] = line[0] === '+' ? 'add' : line[0] === '-' ? 'del' : 'context';\n const text = line.slice(1);\n hunk.lines.push({\n kind,\n oldNo: kind === 'add' ? null : oldNo,\n newNo: kind === 'del' ? null : newNo,\n text,\n });\n if (kind === 'add') {\n current.added += 1;\n newNo += 1;\n } else if (kind === 'del') {\n current.deleted += 1;\n oldNo += 1;\n } else {\n oldNo += 1;\n newNo += 1;\n }\n }\n }\n\n finish();\n return files;\n}\n\nexport function stripDiffPrefix(path: string): string {\n return path.startsWith('a/') || path.startsWith('b/') ? path.slice(2) : path;\n}\n\nconst stripPrefix = stripDiffPrefix;\n", "function globToRegExp(glob: string): RegExp {\n let pattern = glob.trim();\n if (pattern.endsWith('/')) pattern += '**';\n const anchored = pattern.includes('/');\n let source = '';\n\n for (let index = 0; index < pattern.length; index += 1) {\n const character = pattern[index] ?? '';\n if (character === '*') {\n if (pattern[index + 1] === '*') {\n index += 1;\n if (pattern[index + 1] === '/') {\n index += 1;\n source += '(?:.*/)?';\n } else {\n source += '.*';\n }\n } else {\n source += '[^/]*';\n }\n continue;\n }\n if (character === '?') {\n source += '[^/]';\n continue;\n }\n source += character.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }\n\n return new RegExp(anchored ? `^${source}$` : `(?:^|.*/)${source}$`);\n}\n\nexport function isIgnored(path: string, patterns: readonly string[]): boolean {\n return patterns.some((pattern) => globToRegExp(pattern).test(path));\n}\n", "import { randomBytes } from 'node:crypto';\n\nexport type IdPrefix = 'rev' | 'rnd' | 'cmt' | 'evt' | 'snap' | 'anc' | 'sub' | 'job';\n\nexport type RandomBytes = (length: number) => Uint8Array;\n\nexport class ReviewIdError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ReviewIdError';\n }\n}\n\nconst PREFIXES = new Set<IdPrefix>(['rev', 'rnd', 'cmt', 'evt', 'snap', 'anc', 'sub', 'job']);\nconst CROCKFORD = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst TIME_LENGTH = 10;\nconst RANDOM_LENGTH = 16;\nconst RANDOM_BYTES = 10;\nconst MAX_TIME = 0xffffffffffff;\n\nfunction encodeFixed(value: number, length: number): string {\n let remaining = value;\n let out = '';\n for (let index = 0; index < length; index++) {\n out = CROCKFORD[remaining % 32] + out;\n remaining = Math.floor(remaining / 32);\n }\n return out;\n}\n\nfunction encodeBytes(bytes: Uint8Array): string {\n let accumulator = 0;\n let bits = 0;\n let out = '';\n for (const byte of bytes) {\n accumulator = (accumulator << 8) | byte;\n bits += 8;\n while (bits >= 5) {\n out += CROCKFORD[(accumulator >>> (bits - 5)) & 31];\n bits -= 5;\n }\n }\n if (bits > 0) out += CROCKFORD[(accumulator << (5 - bits)) & 31];\n return out;\n}\n\nfunction defaultRandom(length: number): Uint8Array {\n return randomBytes(length);\n}\n\n/**\n * Creates a ULID-like id: 48-bit millisecond timestamp + 80 bits of randomness,\n * prefixed with a domain tag. Fixed-width Crockford base32 keeps ids sortable.\n */\nexport function createId(\n prefix: IdPrefix,\n now: () => Date = () => new Date(),\n random: RandomBytes = defaultRandom,\n): string {\n if (!PREFIXES.has(prefix)) {\n throw new ReviewIdError(`unknown id prefix: ${String(prefix)}`);\n }\n\n const date = now();\n if (!(date instanceof Date) || !Number.isFinite(date.getTime())) {\n throw new ReviewIdError('clock returned an invalid date');\n }\n const time = date.getTime();\n if (time < 0 || time > MAX_TIME) {\n throw new ReviewIdError(`clock is outside the 48-bit millisecond range: ${time}`);\n }\n\n const bytes = random(RANDOM_BYTES);\n if (!(bytes instanceof Uint8Array) || bytes.length !== RANDOM_BYTES) {\n throw new ReviewIdError(`random source must return ${RANDOM_BYTES} bytes`);\n }\n\n const timePart = encodeFixed(time, TIME_LENGTH);\n const randomPart = encodeBytes(bytes);\n return `${prefix}_${timePart}${randomPart}`;\n}\n\nexport const ID_LENGTHS = {\n time: TIME_LENGTH,\n random: RANDOM_LENGTH,\n total: TIME_LENGTH + RANDOM_LENGTH,\n} as const;\n", "import type {\n AgentReport,\n Finding,\n ReviewerBackendKind,\n ReviewerConfig,\n} from '../reviewer/types.js';\nimport type {\n Actor,\n ActorKind,\n Anchor,\n Comment,\n CommentState,\n FindingDecision,\n FixClaimRecord,\n Outcome,\n SuggestionState,\n Reply,\n ReviewState,\n Round,\n ReviewId,\n ReviewCoverage,\n SubmissionRecord,\n} from './types.js';\nimport { createId } from './ids.js';\nimport type { IdPrefix } from './ids.js';\n\nexport interface ReviewCreatedData {\n review: ReviewState;\n}\n\nexport interface RoundCreatedData {\n round: Round;\n}\n\nexport interface CommentAddedData {\n comment: Comment;\n}\n\nexport interface CommentRepliedData {\n commentId: string;\n reply: Reply;\n}\n\nexport interface CommentStateData {\n commentId: string;\n state: CommentState;\n}\n\nexport interface CommentEditedData {\n commentId: string;\n body: string;\n}\n\nexport interface CommentDeletedData {\n commentId: string;\n}\n\nexport interface ReviewUpdatedData {\n title?: string;\n reviewer?: ReviewerConfig;\n}\n\nexport interface ReviewDeletedData {\n /** Optional human-readable reason retained in the audit log. */\n reason?: string;\n}\n\nexport interface CommentAnchorData {\n commentId: string;\n anchor: Anchor;\n outcome?: Outcome;\n}\n\nexport interface SuggestionStateData {\n commentId: string;\n state: SuggestionState;\n}\n\nexport interface FixClaimData {\n claims: FixClaimRecord[];\n}\n\nexport interface FindingDecisionData {\n decision: FindingDecision;\n /** Present when accepting a finding also creates its comment. */\n comment?: Comment;\n /** Present when dismissing an accepted finding removes its transferred comment. */\n deletedCommentId?: string;\n}\n\nexport interface SuggestionAppliedData {\n commentId: string;\n round: number;\n sha?: string;\n result?: string;\n}\n\nexport interface ReviewClosedData {\n verdict: 'approved' | 'closed';\n}\n\nexport interface ReviewSubmittedData {\n submission: SubmissionRecord;\n feedback: {\n markdown: string;\n json: unknown;\n deliveryKey: string;\n };\n}\n\nexport interface AgentStartedData {\n jobId: string;\n round: number;\n backend: ReviewerBackendKind;\n}\n\nexport interface AgentCoverageData {\n coverage: ReviewCoverage;\n round: number;\n}\n\nexport interface AgentFindingData {\n finding: Finding;\n round: number;\n}\n\nexport interface AgentReportData {\n report: AgentReport;\n /** Explicit coverage for an aggregated multi-shard report. */\n coverage?: ReviewCoverage;\n}\n\nexport interface AgentShardData {\n shardId: string;\n shardIndex: number;\n shardCount: number;\n round: number;\n report: AgentReport;\n /** Paths covered by this shard, used for incremental coverage progress. */\n paths?: string[];\n tier?: 'deep' | 'light';\n}\n\nexport interface AgentFailedData {\n code: string;\n message: string;\n}\n\nexport interface AgentRetryData {\n round: number;\n /** Shards whose work is missing and must run again in the same round. */\n shardIds: string[];\n}\n\nexport interface ReviewEventDataMap {\n 'review/created': ReviewCreatedData;\n 'round/created': RoundCreatedData;\n 'comment/added': CommentAddedData;\n 'comment/replied': CommentRepliedData;\n 'comment/state': CommentStateData;\n 'comment/edited': CommentEditedData;\n 'comment/deleted': CommentDeletedData;\n 'comment/anchor': CommentAnchorData;\n 'suggestion/state': SuggestionStateData;\n 'suggestion/applied': SuggestionAppliedData;\n 'fix/claim': FixClaimData;\n 'finding/decision': FindingDecisionData;\n 'review/updated': ReviewUpdatedData;\n 'review/deleted': ReviewDeletedData;\n 'review/closed': ReviewClosedData;\n 'review/submitted': ReviewSubmittedData;\n 'agent/started': AgentStartedData;\n 'agent/coverage': AgentCoverageData;\n 'agent/shard': AgentShardData;\n 'agent/finding': AgentFindingData;\n 'agent/report': AgentReportData;\n 'agent/failed': AgentFailedData;\n 'agent/retry': AgentRetryData;\n}\n\nexport type ReviewEventType = keyof ReviewEventDataMap;\n\nexport const REVIEW_EVENT_TYPES: readonly ReviewEventType[] = [\n 'review/created',\n 'round/created',\n 'comment/added',\n 'comment/replied',\n 'comment/state',\n 'comment/edited',\n 'comment/deleted',\n 'comment/anchor',\n 'suggestion/state',\n 'suggestion/applied',\n 'fix/claim',\n 'finding/decision',\n 'review/updated',\n 'review/deleted',\n 'review/closed',\n 'review/submitted',\n 'agent/started',\n 'agent/coverage',\n 'agent/shard',\n 'agent/finding',\n 'agent/report',\n 'agent/failed',\n 'agent/retry',\n];\n\nexport interface ReviewEventBase<T extends ReviewEventType = ReviewEventType> {\n v: 1;\n id: string;\n /** 1-based append position in the review's JSONL log. Older logs are backfilled on read. */\n seq?: number;\n reviewId: ReviewId;\n type: T;\n at: string;\n actor: Actor;\n data: ReviewEventDataMap[T];\n}\n\nexport type ReviewEvent = {\n [T in ReviewEventType]: ReviewEventBase<T>;\n}[ReviewEventType];\n\nexport interface CreateEventInput<T extends ReviewEventType> {\n reviewId: ReviewId;\n type: T;\n actor: Actor;\n data: ReviewEventDataMap[T];\n now?: () => Date;\n newId?: (prefix: IdPrefix) => string;\n}\n\nexport type ReviewEventErrorCode =\n 'unknown-type' | 'invalid-actor' | 'invalid-review-id' | 'invalid-event' | 'invalid-id';\n\nexport class ReviewEventError extends Error {\n readonly code: ReviewEventErrorCode;\n\n constructor(code: ReviewEventErrorCode, message: string) {\n super(message);\n this.name = 'ReviewEventError';\n this.code = code;\n }\n}\n\nconst ACTOR_KINDS = new Set<ActorKind>(['human', 'agent', 'system']);\nconst EVENT_TYPE_SET = new Set<string>(REVIEW_EVENT_TYPES);\n\nexport function isReviewEventType(value: unknown): value is ReviewEventType {\n return typeof value === 'string' && EVENT_TYPE_SET.has(value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport function isActor(value: unknown): value is Actor {\n if (!isRecord(value)) return false;\n return (\n typeof value.name === 'string' &&\n value.name.trim().length > 0 &&\n typeof value.kind === 'string' &&\n ACTOR_KINDS.has(value.kind as ActorKind)\n );\n}\n\nfunction isIsoTimestamp(value: unknown): value is string {\n if (typeof value !== 'string') return false;\n const parsed = new Date(value);\n return Number.isFinite(parsed.getTime()) && parsed.toISOString() === value;\n}\n\nfunction isEventId(value: unknown): value is string {\n return typeof value === 'string' && value.startsWith('evt_') && value.length > 4;\n}\n\nexport function createEvent<T extends ReviewEventType>(\n input: CreateEventInput<T>,\n): ReviewEventBase<T> {\n if (!isReviewEventType(input.type)) {\n throw new ReviewEventError('unknown-type', `unknown event type: ${String(input.type)}`);\n }\n if (!isActor(input.actor)) {\n throw new ReviewEventError('invalid-actor', 'event actor must have a non-empty name');\n }\n if (typeof input.reviewId !== 'string' || input.reviewId.trim() === '') {\n throw new ReviewEventError('invalid-review-id', 'event reviewId must be non-empty');\n }\n if (!isRecord(input.data)) {\n throw new ReviewEventError('invalid-event', 'event data must be an object');\n }\n\n const now = input.now ?? (() => new Date());\n const date = now();\n if (!(date instanceof Date) || !Number.isFinite(date.getTime())) {\n throw new ReviewEventError('invalid-event', 'event clock returned an invalid date');\n }\n\n const id = (input.newId ?? ((prefix: IdPrefix) => createId(prefix, now)))('evt');\n if (!isEventId(id)) {\n throw new ReviewEventError('invalid-id', 'event id must start with evt_');\n }\n\n return {\n v: 1,\n id,\n reviewId: input.reviewId,\n type: input.type,\n at: date.toISOString(),\n actor: input.actor,\n data: input.data,\n };\n}\n\nexport function isReviewEvent(value: unknown): value is ReviewEvent {\n if (!isRecord(value)) return false;\n if (value.v !== 1) return false;\n if (!isReviewEventType(value.type)) return false;\n if (!isEventId(value.id)) return false;\n if (typeof value.reviewId !== 'string' || value.reviewId.trim() === '') return false;\n if (!isIsoTimestamp(value.at)) return false;\n if (!isActor(value.actor)) return false;\n if (!isRecord(value.data)) return false;\n if (\n value.seq !== undefined &&\n (typeof value.seq !== 'number' || !Number.isInteger(value.seq) || value.seq < 1)\n ) {\n return false;\n }\n return true;\n}\n", "import { createHash } from 'node:crypto';\nimport { createId } from './ids.js';\nimport type { Anchor, AnchorPosition, Side } from './types.js';\nimport type { DiffHunk, FileDiff, Snapshot } from '../types.js';\n\nexport type AnchorErrorCode = 'missing-path' | 'missing-lines' | 'invalid-range' | 'invalid-round';\n\nexport class AnchorError extends Error {\n readonly code: AnchorErrorCode;\n\n constructor(code: AnchorErrorCode, message: string) {\n super(message);\n this.name = 'AnchorError';\n this.code = code;\n }\n}\n\nexport interface CaptureAnchorInput {\n path: string;\n side: Side;\n lineStart: number;\n lineEnd?: number;\n round: number;\n id?: string;\n}\n\nexport interface ReanchorOptions {\n round: number;\n id?: string;\n window?: number;\n /** When the old quote is gone, look for an applied suggestion replacement. */\n fallbackQuote?: string;\n}\n\nconst DEFAULT_WINDOW = 40;\nconst CONTEXT_LINES = 2;\n\ninterface Candidate {\n start: number;\n score: number;\n distance: number;\n}\n\nfunction normalizeLine(line: string): string {\n return line.replace(/\\r$/, '').replace(/[ \\t]+$/, '');\n}\n\n/**\n * Normalizes a quoted block for comparisons: LF line endings and no trailing\n * horizontal whitespace per line. Internal spacing and indentation are kept.\n */\nexport function normalizeQuote(quote: string): string {\n return quote.split('\\n').map(normalizeLine).join('\\n');\n}\n\nfunction normalizeQuoteLines(quote: string): string[] {\n return normalizeQuote(quote).split('\\n');\n}\n\nfunction hashQuote(quote: string): string {\n return createHash('sha256').update(quote, 'utf8').digest('hex');\n}\n\nfunction position(anchor: Anchor): AnchorPosition {\n return {\n round: anchor.round,\n path: anchor.path,\n lineStart: anchor.lineStart,\n lineEnd: anchor.lineEnd,\n };\n}\n\nfunction linesFor(file: FileDiff, side: Side): string[] | undefined {\n return side === 'new' ? file.newLines : file.oldLines;\n}\n\nfunction hunkHeaderFor(hunks: DiffHunk[], line: number, side: Side): string {\n for (const hunk of hunks) {\n const start = side === 'new' ? hunk.newStart : hunk.oldStart;\n const count = side === 'new' ? hunk.newLines : hunk.oldLines;\n if (count > 0 && line >= start && line < start + count) return hunk.header;\n }\n return '';\n}\n\nfunction contextBefore(lines: string[], lineStart: number): string[] {\n return lines.slice(Math.max(0, lineStart - 1 - CONTEXT_LINES), lineStart - 1);\n}\n\nfunction contextAfter(lines: string[], lineEnd: number): string[] {\n return lines.slice(lineEnd, lineEnd + CONTEXT_LINES);\n}\n\n/**\n * Captures a comment anchor against one side of a snapshot. Invalid input is a\n * caller error; re-anchoring missing content is not (see `reanchor`).\n */\nexport function captureAnchor(snapshot: Snapshot, input: CaptureAnchorInput): Anchor {\n if (!Number.isInteger(input.round) || input.round < 1) {\n throw new AnchorError('invalid-round', `round must be a positive integer: ${input.round}`);\n }\n const file = snapshot.files.find((candidate) => candidate.path === input.path);\n if (file === undefined) {\n throw new AnchorError('missing-path', `file is not present in the snapshot: ${input.path}`);\n }\n\n const lines = linesFor(file, input.side);\n if (lines === undefined || lines.length === 0) {\n if (file.truncated === true) {\n throw new AnchorError('missing-lines', `file content was truncated: ${input.path}`);\n }\n throw new AnchorError(\n 'missing-lines',\n `snapshot has no ${input.side} lines for: ${input.path}`,\n );\n }\n\n const lineEnd = input.lineEnd ?? input.lineStart;\n if (\n !Number.isInteger(input.lineStart) ||\n !Number.isInteger(lineEnd) ||\n input.lineStart < 1 ||\n lineEnd < input.lineStart ||\n lineEnd > lines.length\n ) {\n throw new AnchorError(\n 'invalid-range',\n `range ${input.lineStart}..${lineEnd} is outside 1..${lines.length}`,\n );\n }\n\n const quote = lines.slice(input.lineStart - 1, lineEnd).join('\\n');\n return {\n id: input.id ?? createId('anc'),\n round: input.round,\n path: input.path,\n side: input.side,\n lineStart: input.lineStart,\n lineEnd,\n quote,\n contextBefore: contextBefore(lines, input.lineStart),\n contextAfter: contextAfter(lines, lineEnd),\n hunkHeader: hunkHeaderFor(file.hunks, input.lineStart, input.side),\n contentHash: hashQuote(quote),\n state: 'active',\n };\n}\n\nfunction resolveFile(previous: Anchor, next: Snapshot): FileDiff | undefined {\n return (\n next.files.find((file) => file.path === previous.path) ??\n next.files.find((file) => file.oldPath === previous.path)\n );\n}\n\nfunction expectedOldLine(line: number, hunks: DiffHunk[]): number {\n let delta = 0;\n for (const hunk of hunks) {\n const oldEnd = hunk.oldStart + hunk.oldLines - 1;\n if (hunk.oldLines > 0 && line >= hunk.oldStart && line <= oldEnd) {\n return hunk.newStart + (line - hunk.oldStart);\n }\n if (hunk.oldStart + hunk.oldLines <= line) {\n delta += hunk.newLines - hunk.oldLines;\n }\n }\n return line + delta;\n}\n\nfunction contextMatches(\n lines: string[],\n context: string[],\n start: number,\n quoteLength: number,\n direction: 'before' | 'after',\n): boolean {\n if (context.length === 0) return false;\n for (let index = 0; index < context.length; index += 1) {\n const lineIndex =\n direction === 'before'\n ? start - 2 - (context.length - 1 - index)\n : start + quoteLength - 1 + index;\n const line = lines[lineIndex];\n if (line === undefined || normalizeLine(line) !== normalizeLine(context[index] ?? '')) {\n return false;\n }\n }\n return true;\n}\n\ninterface FoundCandidate extends Candidate {\n tied: boolean;\n}\n\nfunction findCandidate(\n lines: string[],\n quoteLines: string[],\n expected: number,\n window: number,\n previous: Anchor,\n): FoundCandidate | undefined {\n const maxStart = lines.length - quoteLines.length + 1;\n const from = Math.max(1, expected - window);\n const to = Math.min(maxStart, expected + window);\n let best: Candidate | undefined;\n let tied = false;\n\n for (let start = from; start <= to; start += 1) {\n let matches = true;\n for (let offset = 0; offset < quoteLines.length; offset += 1) {\n const line = lines[start - 1 + offset];\n if (line === undefined || normalizeLine(line) !== quoteLines[offset]) {\n matches = false;\n break;\n }\n }\n if (!matches) continue;\n\n const distance = Math.abs(start - expected);\n const score =\n 3 +\n (contextMatches(lines, previous.contextBefore, start, quoteLines.length, 'before') ? 1 : 0) +\n (contextMatches(lines, previous.contextAfter, start, quoteLines.length, 'after') ? 1 : 0) +\n Math.max(0, 1 - distance / (window + 1));\n if (\n best === undefined ||\n score > best.score ||\n (score === best.score && distance < best.distance)\n ) {\n best = { start, score, distance };\n tied = false;\n } else if (score === best.score && distance === best.distance) {\n tied = true;\n }\n }\n\n return best === undefined ? undefined : { ...best, tied };\n}\n\nfunction outdated(previous: Anchor, file: FileDiff | undefined, options: ReanchorOptions): Anchor {\n return {\n id: options.id ?? createId('anc'),\n round: options.round,\n path: file?.path ?? previous.path,\n side: previous.side,\n lineStart: previous.lineStart,\n lineEnd: previous.lineEnd,\n quote: previous.quote,\n contextBefore: [...previous.contextBefore],\n contextAfter: [...previous.contextAfter],\n hunkHeader: previous.hunkHeader,\n contentHash: previous.contentHash,\n state: 'outdated',\n previous: position(previous),\n };\n}\n\n/**\n * Re-anchors a comment against the next round's snapshot. A missing file,\n * missing side or an absent quote degrades to `outdated`; this function never\n * throws for content-level problems.\n */\nexport function reanchor(previous: Anchor, next: Snapshot, options: ReanchorOptions): Anchor {\n const file = resolveFile(previous, next);\n if (file === undefined) return outdated(previous, undefined, options);\n\n // Re-anchoring always searches the post-change side: old-side anchors are\n // mapped through hunks into new line numbers before the search.\n const lines = file.newLines;\n if (lines === undefined || lines.length === 0) return outdated(previous, file, options);\n\n const quoteLines = normalizeQuoteLines(previous.quote);\n if (quoteLines.length === 0 || lines.length < quoteLines.length) {\n return outdated(previous, file, options);\n }\n\n const expectedRaw =\n previous.side === 'old' ? expectedOldLine(previous.lineStart, file.hunks) : previous.lineStart;\n const expected = Math.max(1, expectedRaw);\n const window = Number.isFinite(options.window)\n ? Math.max(0, Math.trunc(options.window as number))\n : DEFAULT_WINDOW;\n\n let quote = previous.quote;\n let best = findCandidate(lines, quoteLines, expected, window, previous);\n if (best === undefined && options.fallbackQuote !== undefined) {\n const fallbackLines = normalizeQuoteLines(options.fallbackQuote);\n if (fallbackLines.length > 0 && lines.length >= fallbackLines.length) {\n best = findCandidate(lines, fallbackLines, expected, window, previous);\n if (best !== undefined) quote = options.fallbackQuote;\n }\n }\n\n if (best === undefined) return outdated(previous, file, options);\n\n const quoteLinesForAnchor = normalizeQuoteLines(quote);\n const lineStart = best.start;\n const lineEnd = lineStart + quoteLinesForAnchor.length - 1;\n return {\n id: options.id ?? createId('anc'),\n round: options.round,\n path: file.path,\n side: previous.side,\n lineStart,\n lineEnd,\n quote,\n contextBefore: contextBefore(lines, lineStart),\n contextAfter: contextAfter(lines, lineEnd),\n hunkHeader: hunkHeaderFor(file.hunks, lineStart, 'new'),\n contentHash: hashQuote(quote),\n state: best.tied ? 'ambiguous' : 'active',\n previous: position(previous),\n };\n}\n", "import type { ManifestFile, ManifestFileReason, ReviewManifest } from '../types.js';\nimport type { CoverageStatus, CoverageTotals, FileCoverage, ReviewCoverage } from './types.js';\n\nexport const COVERAGE_STATUSES: readonly CoverageStatus[] = Object.freeze([\n 'pending',\n 'deep-reviewed',\n 'light-reviewed',\n 'manifest-only',\n 'skipped',\n 'no-hunks',\n 'deferred',\n 'failed',\n]);\n\n/** Statuses that mean work is still owed before a round can be `done`. */\nconst UNRESOLVED_STATUSES = new Set<CoverageStatus>(['pending', 'skipped', 'deferred', 'failed']);\n\n/** Manifest reasons where policy, not the render budget, excluded the content. */\nconst POLICY_REASONS = new Set<ManifestFileReason>(['binary', 'ignored', 'generated']);\n\n/** Manifest reasons that explain why a non-policy file was not reviewed. */\nconst SKIP_REASONS = new Set<ManifestFileReason>([\n 'render-budget',\n 'per-file-cap',\n 'diff-truncated',\n 'unreadable',\n 'legacy-truncated',\n 'symlink',\n]);\n\n/** Warnings that prove the manifest's changed-path listing itself was cut. */\nconst INCOMPLETE_MANIFEST_WARNINGS = new Set([\n 'manifest-listing-truncated',\n 'untracked-list-truncated',\n 'manifest-missing',\n]);\n\n/**\n * Counts file coverage by status without mutating the ledger. `files` counts\n * every ledger entry; unknown persisted statuses are excluded from `byStatus`\n * rather than creating a NaN bucket.\n */\nexport function summarizeCoverage(files: readonly FileCoverage[]): CoverageTotals {\n const byStatus = Object.fromEntries(COVERAGE_STATUSES.map((status) => [status, 0])) as Record<\n CoverageStatus,\n number\n >;\n const known = new Set<string>(COVERAGE_STATUSES);\n for (const file of files) {\n if (!known.has(file.status)) continue;\n byStatus[file.status] += 1;\n }\n return { files: files.length, byStatus };\n}\n\n/**\n * Seeds a coverage ledger from the manifest: every changed file starts as\n * pending so no manifest path can be silently absent from coverage.\n */\nexport function initialCoverage(manifest: ReviewManifest): ReviewCoverage {\n const files: FileCoverage[] = manifest.files.map((file) => ({\n path: file.path,\n status: 'pending',\n }));\n return { files, totals: summarizeCoverage(files) };\n}\n\nfunction policyReason(file: ManifestFile): ManifestFileReason | undefined {\n if (file.reason !== undefined && POLICY_REASONS.has(file.reason)) return file.reason;\n if (file.ignored) return 'ignored';\n if (file.binary) return 'binary';\n return undefined;\n}\n\nfunction skipReason(file: ManifestFile): ManifestFileReason {\n if (file.reason !== undefined && SKIP_REASONS.has(file.reason)) return file.reason;\n return 'render-budget';\n}\n\n/**\n * Builds the R1 coverage bridge from the complete manifest and the paths whose\n * file header made it into the prompt. Policy-excluded content is explicitly\n * `manifest-only`; an included file with a reviewable hunk is `pending` and may\n * at most become `light-reviewed` after the report. A file with no content\n * change (pure rename, mode-only, empty file, or an untracked symlink whose\n * target is deliberately not followed) is terminal `no-hunks`, because there\n * is nothing to inspect and it was not dropped by a budget. Everything else is\n * `skipped` with the manifest reason (or `render-budget` when the prompt\n * dropped it). This never mutates the manifest.\n */\nexport function coverageFromPrompt(\n manifest: ReviewManifest,\n includedPaths: readonly string[],\n): ReviewCoverage {\n const included = new Set(includedPaths);\n const files = manifest.files.map((file): FileCoverage => {\n const policy = policyReason(file);\n if (policy !== undefined) {\n return { path: file.path, status: 'manifest-only', reason: policy };\n }\n if (\n file.reason === 'symlink' &&\n file.hunkCount === 0 &&\n file.added === 0 &&\n file.deleted === 0\n ) {\n return { path: file.path, status: 'no-hunks' };\n }\n if (included.has(file.path)) {\n if (file.hunkCount > 0) return { path: file.path, status: 'pending' };\n if (file.reason === undefined && file.added === 0 && file.deleted === 0) {\n return { path: file.path, status: 'no-hunks' };\n }\n }\n return { path: file.path, status: 'skipped', reason: skipReason(file) };\n });\n const incomplete = manifest.warnings.some((warning) => INCOMPLETE_MANIFEST_WARNINGS.has(warning));\n return {\n files,\n totals: summarizeCoverage(files),\n ...(incomplete ? { incomplete: true } : {}),\n };\n}\n\n/**\n * A round is complete only when every ledger file has a final reviewed or\n * policy-excluded status. Unknown persisted statuses and inconsistent totals\n * are treated as incomplete: they prove the ledger cannot be trusted.\n */\nexport function isCoverageComplete(coverage: ReviewCoverage): boolean {\n if (coverage.incomplete === true) return false;\n const computed = summarizeCoverage(coverage.files);\n const knownCount = COVERAGE_STATUSES.reduce((sum, status) => sum + computed.byStatus[status], 0);\n if (knownCount !== coverage.files.length) return false;\n if (coverage.totals.files !== coverage.files.length) return false;\n for (const status of COVERAGE_STATUSES) {\n if ((coverage.totals.byStatus[status] ?? 0) !== computed.byStatus[status]) return false;\n }\n const persistedCount = COVERAGE_STATUSES.reduce(\n (sum, status) => sum + (coverage.totals.byStatus[status] ?? 0),\n 0,\n );\n if (persistedCount !== coverage.files.length) return false;\n return coverage.files.every((file) => {\n if (UNRESOLVED_STATUSES.has(file.status)) return false;\n if (file.status !== 'manifest-only') return true;\n return file.reason !== undefined && POLICY_REASONS.has(file.reason as ManifestFileReason);\n });\n}\n\n/**\n * Promotes pending files to light-reviewed after an accepted report. The\n * returned ledger and its file entries are new objects; the input is not\n * mutated. Totals are always recomputed from the resulting files.\n */\nexport function promotePendingToLight(coverage: ReviewCoverage): ReviewCoverage {\n const files = coverage.files.map((file): FileCoverage =>\n file.status === 'pending' ? { ...file, status: 'light-reviewed' } : { ...file },\n );\n return {\n files,\n totals: summarizeCoverage(files),\n ...(coverage.incomplete === true ? { incomplete: true } : {}),\n };\n}\n", "import type { ManifestFile, ReviewManifest } from '../types.js';\nimport type { FileCoverage, ReviewCoverage } from './types.js';\nimport { summarizeCoverage } from './coverage.js';\n\nexport type ReviewTier = 'deep' | 'light' | 'manifest-only';\nexport type FileKind =\n | 'source'\n | 'test'\n | 'docs'\n | 'config'\n | 'migration'\n | 'generated'\n | 'binary'\n | 'instructions'\n | 'other';\n\nexport interface ModuleRoot {\n id: string;\n root: string;\n name?: string;\n}\n\nexport interface ModuleInfo extends ModuleRoot {\n source: 'workspace' | 'convention' | 'root';\n}\n\nexport interface ModuleMap {\n modules: ModuleInfo[];\n moduleFor(path: string): string;\n}\n\nconst WORKSPACE_CONTAINERS = new Set([\n 'packages',\n 'apps',\n 'services',\n 'libs',\n 'modules',\n 'plugins',\n]);\n\nconst CONVENTION_ROOTS = new Set([\n 'src',\n 'app',\n 'backend',\n 'frontend',\n 'server',\n 'client',\n 'ui',\n 'web',\n 'api',\n 'docs',\n 'tests',\n 'test',\n 'e2e',\n 'ui-tests',\n 'migrations',\n 'config',\n 'scripts',\n 'tools',\n]);\n\nconst INSTRUCTION_FILES = new Set([\n 'AGENTS.md',\n 'CLAUDE.md',\n 'GEMINI.md',\n '.cursorrules',\n '.github/copilot-instructions.md',\n]);\n\nconst DOC_FILES = new Set([\n 'README.md',\n 'CHANGELOG.md',\n 'ARCHITECTURE.md',\n 'BACKEND_SPEC.md',\n 'CONTRIBUTING.md',\n 'SECURITY.md',\n 'LICENSE.md',\n]);\n\nconst CONFIG_FILES = new Set([\n 'package.json',\n 'pnpm-workspace.yaml',\n 'pnpm-lock.yaml',\n 'package-lock.json',\n 'yarn.lock',\n 'uv.lock',\n 'poetry.lock',\n 'Cargo.lock',\n 'go.sum',\n 'tsconfig.json',\n 'pyproject.toml',\n 'requirements.txt',\n 'go.mod',\n 'Cargo.toml',\n 'pom.xml',\n 'Makefile',\n 'Dockerfile',\n 'docker-compose.yml',\n 'docker-compose.yaml',\n]);\n\nconst SOURCE_EXTENSIONS = new Set([\n '.ts',\n '.tsx',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n '.py',\n '.go',\n '.rs',\n '.java',\n '.kt',\n '.kts',\n '.swift',\n '.c',\n '.cc',\n '.cpp',\n '.h',\n '.hpp',\n '.rb',\n '.php',\n '.cs',\n '.sh',\n '.bash',\n '.zsh',\n '.sql',\n]);\n\nconst DOC_EXTENSIONS = new Set(['.md', '.mdx', '.rst', '.adoc']);\nconst GENERATED_DIRS = new Set([\n 'dist',\n 'build',\n 'coverage',\n 'node_modules',\n '.next',\n 'out',\n 'target',\n '.turbo',\n '.cache',\n]);\n\nfunction basename(path: string): string {\n const parts = path.split('/');\n return parts.at(-1) ?? path;\n}\n\nfunction extension(path: string): string {\n const name = basename(path);\n const dot = name.lastIndexOf('.');\n return dot <= 0 ? '' : name.slice(dot).toLowerCase();\n}\n\nfunction normalizeRoot(root: string): string {\n const normalized = root.replace(/\\\\/g, '/').replace(/^\\/+|\\/+$/g, '');\n return normalized === '' ? '.' : normalized;\n}\n\nfunction isUnder(path: string, root: string): boolean {\n if (root === '.') return true;\n return path === root || path.startsWith(`${root}/`);\n}\n\nfunction conventionRoot(path: string): string {\n const parts = path.split('/');\n if (parts.length === 1) return '.';\n const first = parts[0];\n if (first === undefined) return '.';\n if (WORKSPACE_CONTAINERS.has(first) && parts.length > 2) {\n return `${first}/${parts[1] ?? ''}`;\n }\n if (CONVENTION_ROOTS.has(first)) return first;\n return first;\n}\n\n/**\n * Builds a deterministic path-to-module map. Explicit workspace roots win over\n * convention roots for the same directory; the longest matching root wins for\n * a path. Root-level files belong to the synthetic `.` module.\n */\nexport function buildModuleMap(\n files: readonly ManifestFile[],\n roots: readonly ModuleRoot[] = [],\n): ModuleMap {\n const byRoot = new Map<string, ModuleInfo>();\n const add = (root: string, source: ModuleInfo['source'], info?: ModuleRoot): void => {\n const normalized = normalizeRoot(root);\n if (normalized === '.' && source !== 'root') return;\n const existing = byRoot.get(normalized);\n if (existing !== undefined && !(source === 'workspace' && existing.source === 'convention')) {\n return;\n }\n if (existing !== undefined && source === 'workspace') {\n byRoot.set(normalized, {\n id: info?.id ?? existing.id,\n root: normalized,\n ...(info?.name === undefined && existing.name === undefined\n ? {}\n : { name: info?.name ?? existing.name }),\n source,\n });\n return;\n }\n byRoot.set(normalized, {\n id: info?.id ?? normalized,\n root: normalized,\n ...(info?.name === undefined ? {} : { name: info.name }),\n source,\n });\n };\n\n for (const root of roots) {\n add(root.root, 'workspace', root);\n }\n for (const path of files.map((file) => file.path)) {\n add(conventionRoot(path), 'convention');\n }\n add('.', 'root');\n\n const modules = [...byRoot.values()].sort((left, right) => {\n if (left.id < right.id) return -1;\n if (left.id > right.id) return 1;\n return 0;\n });\n const orderedByRoot = [...modules].sort((left, right) => right.root.length - left.root.length);\n\n return {\n modules,\n moduleFor(path: string): string {\n for (const module of orderedByRoot) {\n if (isUnder(path, module.root)) return module.id;\n }\n return '.';\n },\n };\n}\n\nfunction isGenerated(file: ManifestFile): boolean {\n if (file.reason === 'generated') return true;\n const name = basename(file.path);\n if (\n name === 'pnpm-lock.yaml' ||\n name === 'package-lock.json' ||\n name === 'yarn.lock' ||\n name === 'uv.lock' ||\n name === 'poetry.lock' ||\n name === 'Cargo.lock' ||\n name === 'go.sum'\n ) {\n return true;\n }\n if (/(\\.min\\.|\\.generated\\.)/.test(name)) return true;\n return file.path.split('/').some((part) => GENERATED_DIRS.has(part));\n}\n\nfunction isInstructions(path: string): boolean {\n return INSTRUCTION_FILES.has(path) || path.startsWith('.dsh/');\n}\n\nfunction isMigration(path: string): boolean {\n if (extension(path) === '.sql') return true;\n return /(^|\\/)(migrations?|alembic|migrate)\\//.test(path);\n}\n\nfunction isTest(path: string): boolean {\n if (/(^|\\/)(test|tests|__tests__|e2e|ui-tests|spec|specs)\\//.test(path)) return true;\n return /\\.(test|spec)\\.[^/]+$/.test(path);\n}\n\nfunction isDocs(path: string): boolean {\n if (path.startsWith('docs/')) return true;\n if (DOC_FILES.has(basename(path))) return true;\n return DOC_EXTENSIONS.has(extension(path));\n}\n\nfunction isConfig(path: string): boolean {\n const name = basename(path);\n if (CONFIG_FILES.has(name)) return true;\n if (path.startsWith('.github/')) return true;\n if (\n /^(tsconfig|vite|vitest|eslint|prettier|playwright|jest|rollup|webpack).*\\.(json|js|mjs|cjs|ts)$/.test(\n name,\n )\n ) {\n return true;\n }\n if (/^\\.env(\\..*)?$/.test(name)) return true;\n return extension(path) === '.yml' || extension(path) === '.yaml' || extension(path) === '.toml';\n}\n\nfunction isSource(path: string): boolean {\n return SOURCE_EXTENSIONS.has(extension(path));\n}\n\n/**\n * Classifies a changed path by kind. Manifest policy (`generated`) and binary\n * metadata take priority over the path shape; `ignored` alone does not change\n * the kind because ignore policy is applied by the tier planner.\n */\nexport function classifyFile(file: ManifestFile): FileKind {\n if (isInstructions(file.path)) return 'instructions';\n if (file.binary) return 'binary';\n if (isGenerated(file)) return 'generated';\n if (isMigration(file.path)) return 'migration';\n if (isTest(file.path)) return 'test';\n if (isDocs(file.path)) return 'docs';\n if (isConfig(file.path)) return 'config';\n if (isSource(file.path)) return 'source';\n return 'other';\n}\n\n/**\n * User-facing docs are deep-reviewed because they can change behavior or\n * contracts. Internal notes are still docs, but light.\n */\nexport function isUserFacingDoc(path: string): boolean {\n if (path.startsWith('docs/internal/')) return false;\n if (path.startsWith('docs/')) return true;\n const name = basename(path);\n return DOC_FILES.has(name) || /^README\\./i.test(name);\n}\n\nexport interface ShardLimits {\n maxFiles: number;\n maxPatchBytes: number;\n}\n\nexport const DEFAULT_SHARD_LIMITS: ShardLimits = Object.freeze({\n maxFiles: 12,\n maxPatchBytes: 120_000,\n});\n\nexport interface PlanFile {\n path: string;\n moduleId: string;\n kind: FileKind;\n tier: ReviewTier;\n shardId?: string;\n /** Policy reason for a manifest-only file; absent for reviewed files. */\n reason?: string;\n}\n\nexport interface ReviewShard {\n id: string;\n moduleId: string;\n tier: 'deep' | 'light';\n effort: 'deep' | 'light';\n paths: string[];\n fileCount: number;\n patchBytes: number;\n}\n\nexport interface ReviewPlan {\n schemaVersion: 1;\n files: PlanFile[];\n shards: ReviewShard[];\n coverage: ReviewCoverage;\n coveragePlan: {\n total: number;\n byTier: Record<ReviewTier, number>;\n };\n riskFlags: string[];\n limits: ShardLimits;\n}\n\nconst INCOMPLETE_MANIFEST_WARNINGS = new Set([\n 'manifest-listing-truncated',\n 'untracked-list-truncated',\n 'manifest-missing',\n]);\n\nfunction byteCompare(left: string, right: string): number {\n return Buffer.compare(Buffer.from(left, 'utf8'), Buffer.from(right, 'utf8'));\n}\n\nfunction isNoHunks(file: ManifestFile): boolean {\n return (\n file.reason === undefined &&\n !file.binary &&\n !file.ignored &&\n file.hunkCount === 0 &&\n file.added === 0 &&\n file.deleted === 0\n );\n}\n\nfunction policyReason(file: ManifestFile, kind: FileKind): string | undefined {\n if (file.reason !== undefined && ['generated', 'binary', 'ignored'].includes(file.reason)) {\n return file.reason;\n }\n if (file.ignored) return 'ignored';\n if (file.binary) return 'binary';\n if (kind === 'generated') return 'generated';\n return undefined;\n}\n\nfunction tierFor(file: ManifestFile, kind: FileKind, moduleHasSource: boolean): ReviewTier {\n if (kind === 'binary' || kind === 'generated' || file.ignored) return 'manifest-only';\n switch (kind) {\n case 'source':\n case 'config':\n case 'migration':\n case 'instructions':\n return 'deep';\n case 'test':\n return moduleHasSource ? 'deep' : 'light';\n case 'docs':\n return isUserFacingDoc(file.path) ? 'deep' : 'light';\n case 'other':\n return 'light';\n }\n}\n\nfunction riskFlags(input: {\n manifest: ReviewManifest;\n files: readonly PlanFile[];\n modules: number;\n}): string[] {\n const flags: string[] = [];\n const generated = input.files.filter((file) => file.tier === 'manifest-only').length;\n if (input.manifest.totals.files >= 100 || input.manifest.totals.patchBytes >= 1_000_000) {\n flags.push('large-diff');\n }\n if (input.files.length >= 10 && generated * 10 >= input.files.length) {\n flags.push('generated-heavy');\n }\n if (input.manifest.warnings.some((warning) => INCOMPLETE_MANIFEST_WARNINGS.has(warning))) {\n flags.push('manifest-incomplete');\n }\n if (\n input.files.some((file) => /(^|\\/)(auth|security|crypto|migrations?|config)\\//.test(file.path))\n ) {\n flags.push('security-sensitive');\n }\n if (!input.files.some((file) => file.tier === 'deep' && file.kind === 'source')) {\n flags.push('no-source');\n }\n if (input.modules > 8) flags.push('many-modules');\n return flags;\n}\n\n/**\n * Builds a pure, deterministic review plan. The planner never executes a\n * shard, calls a model, or marks work complete; every deep/light file starts\n * pending in the returned coverage ledger.\n */\nexport function buildReviewPlan(input: {\n manifest: ReviewManifest;\n moduleRoots?: readonly ModuleRoot[];\n limits?: Partial<ShardLimits>;\n}): ReviewPlan {\n const limits: ShardLimits = {\n maxFiles: Math.max(1, Math.trunc(input.limits?.maxFiles ?? DEFAULT_SHARD_LIMITS.maxFiles)),\n maxPatchBytes: Math.max(\n 1,\n Math.trunc(input.limits?.maxPatchBytes ?? DEFAULT_SHARD_LIMITS.maxPatchBytes),\n ),\n };\n const modules = buildModuleMap(input.manifest.files, input.moduleRoots);\n const kinds = new Map<string, FileKind>();\n for (const file of input.manifest.files) {\n kinds.set(file.path, classifyFile(file));\n }\n const sourceModules = new Set<string>();\n for (const file of input.manifest.files) {\n if (kinds.get(file.path) === 'source') sourceModules.add(modules.moduleFor(file.path));\n }\n\n const files: PlanFile[] = input.manifest.files.map((file) => {\n const kind = kinds.get(file.path) ?? 'other';\n const moduleId = modules.moduleFor(file.path);\n const tier = tierFor(file, kind, sourceModules.has(moduleId));\n const reason = tier === 'manifest-only' ? policyReason(file, kind) : undefined;\n return {\n path: file.path,\n moduleId,\n kind,\n tier,\n ...(reason === undefined ? {} : { reason }),\n };\n });\n const byPath = new Map(files.map((file) => [file.path, file]));\n\n const groups = new Map<string, PlanFile[]>();\n for (const file of files) {\n if (file.tier === 'manifest-only') continue;\n const manifestFile = input.manifest.files.find((item) => item.path === file.path);\n if (manifestFile === undefined || isNoHunks(manifestFile)) continue;\n const key = `${file.moduleId}\\0${file.tier}`;\n const group = groups.get(key) ?? [];\n group.push(file);\n groups.set(key, group);\n }\n\n const shards: ReviewShard[] = [];\n const keys = [...groups.keys()].sort(byteCompare);\n for (const key of keys) {\n const group = groups.get(key) ?? [];\n group.sort((left, right) => byteCompare(left.path, right.path));\n let current: PlanFile[] = [];\n let currentBytes = 0;\n const flush = (): void => {\n if (current.length === 0) return;\n const id = `shard_${String(shards.length + 1).padStart(3, '0')}`;\n const first = current[0];\n if (first === undefined) return;\n const shard: ReviewShard = {\n id,\n moduleId: first.moduleId,\n tier: first.tier === 'deep' ? 'deep' : 'light',\n effort: first.tier === 'deep' ? 'deep' : 'light',\n paths: current.map((file) => file.path),\n fileCount: current.length,\n patchBytes: currentBytes,\n };\n shards.push(shard);\n for (const file of current) file.shardId = id;\n current = [];\n currentBytes = 0;\n };\n for (const file of group) {\n const manifestFile = input.manifest.files.find((item) => item.path === file.path);\n const bytes = manifestFile?.patchBytes ?? 0;\n if (\n current.length > 0 &&\n (current.length >= limits.maxFiles || currentBytes + bytes > limits.maxPatchBytes)\n ) {\n flush();\n }\n current.push(file);\n currentBytes += bytes;\n }\n flush();\n }\n\n const coverageFiles: FileCoverage[] = input.manifest.files.map((manifestFile) => {\n const planFile = byPath.get(manifestFile.path);\n if (planFile === undefined) {\n return { path: manifestFile.path, status: 'skipped', reason: 'render-budget' };\n }\n if (planFile.tier === 'manifest-only') {\n return {\n path: planFile.path,\n status: 'manifest-only',\n ...(planFile.reason === undefined ? {} : { reason: planFile.reason }),\n };\n }\n if (isNoHunks(manifestFile)) {\n return { path: planFile.path, status: 'no-hunks' };\n }\n if (planFile.shardId !== undefined) {\n return { path: planFile.path, status: 'pending', shardId: planFile.shardId };\n }\n return { path: planFile.path, status: 'skipped', reason: 'render-budget' };\n });\n const coverage: ReviewCoverage = {\n files: coverageFiles,\n totals: summarizeCoverage(coverageFiles),\n ...(input.manifest.warnings.some((warning) => INCOMPLETE_MANIFEST_WARNINGS.has(warning))\n ? { incomplete: true }\n : {}),\n };\n\n const byTier: Record<ReviewTier, number> = {\n deep: files.filter((file) => file.tier === 'deep').length,\n light: files.filter((file) => file.tier === 'light').length,\n 'manifest-only': files.filter((file) => file.tier === 'manifest-only').length,\n };\n return {\n schemaVersion: 1,\n files,\n shards,\n coverage,\n coveragePlan: { total: files.length, byTier },\n riskFlags: riskFlags({\n manifest: input.manifest,\n files,\n modules: modules.modules.length,\n }),\n limits,\n };\n}\n\n/** Returns a detached copy of the plan's coverage ledger for event persistence. */\nexport function coverageFromPlan(plan: ReviewPlan): ReviewCoverage {\n return {\n files: plan.coverage.files.map((file) => ({ ...file })),\n totals: summarizeCoverage(plan.coverage.files),\n ...(plan.coverage.incomplete === true ? { incomplete: true } : {}),\n };\n}\n", "import type {\n AgentReport,\n Finding,\n ReviewQuestion,\n RiskLevel,\n TestCommand,\n Verification,\n} from '../reviewer/types.js';\nimport type { ReviewPlan } from './plan.js';\nimport { coverageFromPlan } from './plan.js';\nimport { summarizeCoverage } from './coverage.js';\nimport type { FileCoverage, ReviewCoverage, ReviewId, RoundNo } from './types.js';\nimport type { ReviewerBackendKind } from '../reviewer/types.js';\n\nconst RISK_ORDER: Record<RiskLevel, number> = {\n low: 0,\n medium: 1,\n high: 2,\n critical: 3,\n};\n\nexport interface ShardReportInput {\n shardId: string;\n report: AgentReport;\n}\n\nexport interface AggregateShardReportsInput {\n reviewId: ReviewId;\n round: RoundNo;\n backend: ReviewerBackendKind;\n plan: ReviewPlan;\n reports: readonly ShardReportInput[];\n /** Shards known to have failed; missing shards are failed automatically. */\n failedShards?: readonly string[];\n}\n\nexport interface AggregateShardReportsResult {\n report: AgentReport;\n coverage: ReviewCoverage;\n}\n\nfunction findingKey(finding: Finding): string {\n return `${finding.file}\\0${finding.lineStart}\\0${finding.lineEnd}\\0${finding.title}`;\n}\n\nfunction questionKey(question: ReviewQuestion): string {\n return `${question.file}\\0${question.line}\\0${question.question}`;\n}\n\nfunction mergeFindings(reports: readonly ShardReportInput[]): Finding[] {\n const findings: Finding[] = [];\n const seen = new Set<string>();\n for (const report of reports) {\n for (const finding of report.report.findings) {\n const key = findingKey(finding);\n if (seen.has(key)) continue;\n seen.add(key);\n findings.push({ ...finding });\n }\n }\n return findings;\n}\n\nfunction mergeQuestions(reports: readonly ShardReportInput[]): ReviewQuestion[] {\n const questions: ReviewQuestion[] = [];\n const seen = new Set<string>();\n for (const report of reports) {\n for (const question of report.report.questions) {\n const key = questionKey(question);\n if (seen.has(key)) continue;\n seen.add(key);\n questions.push({ ...question });\n }\n }\n return questions;\n}\n\nfunction mergeTests(reports: readonly ShardReportInput[]): AgentReport['tests'] {\n const commands: TestCommand[] = [];\n const seen = new Set<string>();\n for (const report of reports) {\n for (const command of report.report.tests.commands) {\n const key = `${command.command}\\0${command.result}\\0${command.summary}`;\n if (seen.has(key)) continue;\n seen.add(key);\n commands.push({ ...command });\n }\n }\n return { ran: reports.some((report) => report.report.tests.ran), commands };\n}\n\nfunction mergeVerification(reports: readonly ShardReportInput[]): Verification[] {\n const entries: Verification[] = [];\n const seen = new Set<string>();\n for (const report of reports) {\n for (const item of report.report.verification) {\n const key = `${item.commentId}\\0${item.status}\\0${item.evidence}`;\n if (seen.has(key)) continue;\n seen.add(key);\n entries.push({ ...item });\n }\n }\n return entries;\n}\n\nfunction highestRisk(reports: readonly ShardReportInput[]): RiskLevel {\n let result: RiskLevel = 'low';\n for (const report of reports) {\n if (RISK_ORDER[report.report.riskLevel] > RISK_ORDER[result]) {\n result = report.report.riskLevel;\n }\n }\n return result;\n}\n\nfunction updateCoverage(\n plan: ReviewPlan,\n reports: readonly ShardReportInput[],\n failed: ReadonlySet<string>,\n): ReviewCoverage {\n const base = coverageFromPlan(plan);\n const byShard = new Map(reports.map((report) => [report.shardId, report]));\n const files: FileCoverage[] = base.files.map((file) => {\n const planFile = plan.files.find((item) => item.path === file.path);\n const shardId = planFile?.shardId;\n if (shardId === undefined) return { ...file };\n if (failed.has(shardId)) {\n return { ...file, status: 'failed', reason: 'shard-failed' };\n }\n const shard = plan.shards.find((item) => item.id === shardId);\n if (shard === undefined || !byShard.has(shardId)) {\n return { ...file, status: 'failed', reason: 'shard-failed' };\n }\n const status = shard.tier === 'deep' ? 'deep-reviewed' : 'light-reviewed';\n const next: FileCoverage = { ...file, status };\n delete next.reason;\n return next;\n });\n return {\n files,\n totals: summarizeCoverage(files),\n ...(base.incomplete === true ? { incomplete: true } : {}),\n };\n}\n\nexport interface MergeShardReportsInput {\n reviewId: ReviewId;\n round: RoundNo;\n backend: ReviewerBackendKind;\n /**\n * Reports in display order. Callers that have a plan must sort by plan order;\n * live previews sort by shard index before calling this helper.\n */\n reports: readonly ShardReportInput[];\n}\n\n/**\n * Merges completed shard reports without another model call or coverage\n * assumptions. Missing shards are intentionally ignored: this is the live\n * preview path while a round is still running. Final aggregation, which also\n * computes coverage and fails missing shards, uses this helper after ordering\n * reports by the plan.\n */\nexport function mergeShardReports(input: MergeShardReportsInput): AgentReport {\n const findings = mergeFindings(input.reports);\n const summaryParts = input.reports\n .map((report) => report.report.summary.trim())\n .filter((summary) => summary !== '');\n const summary =\n summaryParts.length === 0\n ? 'The review did not produce a shard report.'\n : summaryParts.join('\\n\\n').slice(0, 20_000);\n return {\n schemaVersion: 1,\n summary,\n riskLevel: highestRisk(input.reports),\n findings,\n questions: mergeQuestions(input.reports),\n tests: mergeTests(input.reports),\n verification: mergeVerification(input.reports),\n reviewId: input.reviewId,\n round: input.round,\n backend: input.backend,\n rejected: input.reports.flatMap((item) => item.report.rejected),\n warnings: [...new Set(input.reports.flatMap((report) => report.report.warnings))],\n ...(input.reports.some((item) => item.report.dirtyWorktree === true)\n ? { dirtyWorktree: true }\n : {}),\n skipped: false,\n };\n}\n\n/**\n * Merges shard reports without another model call. Deterministic: reports are\n * ordered by the review plan (not shard completion order), findings dedupe by\n * file/range/title, coverage is derived from the plan and the completed shards.\n * Missing shards are failed, never silently reviewed.\n */\nexport function aggregateShardReports(\n input: AggregateShardReportsInput,\n): AggregateShardReportsResult {\n const failed = new Set(input.failedShards ?? []);\n for (const shard of input.plan.shards) {\n if (!input.reports.some((report) => report.shardId === shard.id)) failed.add(shard.id);\n }\n const shardOrder = new Map(input.plan.shards.map((shard, index) => [shard.id, index]));\n const rank = (shardId: string): number => shardOrder.get(shardId) ?? input.plan.shards.length;\n const reports = [...input.reports].sort(\n (left, right) => rank(left.shardId) - rank(right.shardId),\n );\n const report = mergeShardReports({\n reviewId: input.reviewId,\n round: input.round,\n backend: input.backend,\n reports,\n });\n for (const shardId of [...failed].sort()) {\n report.warnings.push(`shard-failed:${shardId}`);\n }\n return { report, coverage: updateCoverage(input.plan, reports, failed) };\n}\n", "import { normalizeQuote } from './anchors.js';\nimport type { Anchor, Outcome, Suggestion } from './types.js';\nimport type { FileDiff, Snapshot } from '../types.js';\n\nfunction findFile(anchor: Anchor, snapshot: Snapshot): FileDiff | undefined {\n return (\n snapshot.files.find((file) => file.path === anchor.path) ??\n snapshot.files.find((file) => file.oldPath === anchor.path)\n );\n}\n\nfunction contentAt(anchor: Anchor, file: FileDiff): string | null {\n const lines = file.newLines;\n if (lines === undefined || file.truncated === true) return null;\n if (\n !Number.isInteger(anchor.lineStart) ||\n !Number.isInteger(anchor.lineEnd) ||\n anchor.lineStart < 1 ||\n anchor.lineEnd < anchor.lineStart ||\n anchor.lineEnd > lines.length\n ) {\n return null;\n }\n return normalizeQuote(lines.slice(anchor.lineStart - 1, anchor.lineEnd).join('\\n'));\n}\n\nfunction containsBlock(lines: string[] | undefined, block: string): boolean {\n if (lines === undefined || block === '') return false;\n const wanted = normalizeQuote(block).split('\\n');\n if (wanted.length === 0) return false;\n for (let start = 0; start + wanted.length <= lines.length; start += 1) {\n let matches = true;\n for (let offset = 0; offset < wanted.length; offset += 1) {\n const line = lines[start + offset];\n if (line === undefined || normalizeQuote(line) !== wanted[offset]) {\n matches = false;\n break;\n }\n }\n if (matches) return true;\n }\n return false;\n}\n\n/**\n * Derives the deterministic \u201Cfixed / not fixed\u201D guess for one re-anchored\n * comment. This is intentionally a pure, no-LLM signal: the reviewer's\n * verification and the agent's fix/claim are separate inputs in later rounds.\n */\nexport function deriveOutcome(\n previous: Anchor,\n next: Anchor,\n nextSnapshot: Snapshot,\n suggestion?: Suggestion,\n): Outcome {\n const file = findFile(next, nextSnapshot);\n const content = file === undefined ? null : contentAt(next, file);\n if (next.state === 'outdated' || file === undefined || content === null) {\n return { round: next.round, status: 'outdated', confidence: 'high' };\n }\n\n const previousQuote = normalizeQuote(previous.quote);\n const nextQuote = normalizeQuote(next.quote);\n\n if (\n suggestion !== undefined &&\n normalizeQuote(suggestion.original) === previousQuote &&\n content === normalizeQuote(suggestion.replacement) &&\n content !== previousQuote\n ) {\n return { round: next.round, status: 'applied', confidence: 'high' };\n }\n\n if (nextQuote === previousQuote) {\n if (\n next.lineStart === previous.lineStart &&\n next.lineEnd === previous.lineEnd &&\n next.path === previous.path\n ) {\n return { round: next.round, status: 'unchanged', confidence: 'high' };\n }\n return { round: next.round, status: 'moved', confidence: 'high' };\n }\n\n if (next.state === 'active' || next.state === 'ambiguous') {\n const confidence =\n suggestion !== undefined && containsBlock(file.newLines, suggestion.replacement)\n ? 'high'\n : 'medium';\n return { round: next.round, status: 'addressed', confidence };\n }\n\n return { round: next.round, status: 'outdated', confidence: 'low' };\n}\n", "import { isCoverageComplete } from './coverage.js';\nimport type { ReviewState } from './types.js';\n\n/**\n * True when the stored report is the final report for the latest round.\n *\n * A queued, running, failed, skipped or coverage-partial run does not make its\n * report final, even when a previous run left a report in place. Legacy states\n * without an agent still qualify because their report is all we have.\n */\nexport function isFinalReviewReport(\n review: ReviewState,\n report: ReviewState['report'] = review.report,\n): boolean {\n const latestRound = review.rounds.at(-1);\n if (report === undefined || latestRound === undefined || report.round !== latestRound.no) {\n return false;\n }\n const agent = review.agent;\n if (agent === undefined) return true;\n if (agent.status !== 'done') return false;\n return agent.coverage === undefined || isCoverageComplete(agent.coverage);\n}\n", "import { isCoverageComplete, promotePendingToLight, summarizeCoverage } from './coverage.js';\nimport type { ReviewEvent } from './events.js';\nimport type { AgentStatus, Comment, ReviewState } from './types.js';\n\nexport class ReviewFoldError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ReviewFoldError';\n }\n}\n\nfunction findComment(state: ReviewState, commentId: string): Comment {\n const comment = state.comments.find((candidate) => candidate.id === commentId);\n if (comment === undefined) {\n throw new ReviewFoldError(`unknown comment: ${commentId}`);\n }\n return comment;\n}\n\n/**\n * Pure reduction of one event into review state. The input is never mutated;\n * callers replay events in append order. `review/created` seeds the aggregate\n * (and resets the version to 1); every other event advances it by one.\n */\nexport function fold(state: ReviewState, event: ReviewEvent): ReviewState {\n if (event.reviewId !== state.id) {\n throw new ReviewFoldError(`event ${event.id} belongs to ${event.reviewId}, not ${state.id}`);\n }\n\n if (event.type === 'review/created') {\n if (event.data.review.id !== event.reviewId) {\n throw new ReviewFoldError(\n `review payload ${event.data.review.id} belongs to a different review than ${event.reviewId}`,\n );\n }\n return {\n ...structuredClone(event.data.review),\n version: 1,\n warnings: [],\n };\n }\n\n const next = structuredClone(state);\n next.version += 1;\n next.warnings ??= [];\n\n switch (event.type) {\n case 'round/created': {\n if (next.rounds.some((round) => round.no === event.data.round.no)) {\n throw new ReviewFoldError(`duplicate round: ${event.data.round.no}`);\n }\n const expected = next.rounds.length + 1;\n if (event.data.round.no !== expected) {\n throw new ReviewFoldError(`round order: expected ${expected}, got ${event.data.round.no}`);\n }\n next.rounds.push(structuredClone(event.data.round));\n break;\n }\n case 'comment/added': {\n if (next.comments.some((comment) => comment.id === event.data.comment.id)) {\n throw new ReviewFoldError(`duplicate comment: ${event.data.comment.id}`);\n }\n next.comments.push(structuredClone(event.data.comment));\n break;\n }\n case 'comment/replied': {\n const comment = findComment(next, event.data.commentId);\n comment.replies.push(structuredClone(event.data.reply));\n break;\n }\n case 'comment/state': {\n findComment(next, event.data.commentId).state = event.data.state;\n break;\n }\n case 'comment/edited': {\n const comment = findComment(next, event.data.commentId);\n comment.body = event.data.body;\n comment.editedAt = event.at;\n comment.editedBy = structuredClone(event.actor);\n break;\n }\n case 'comment/deleted': {\n const comment = findComment(next, event.data.commentId);\n comment.deletedAt = event.at;\n comment.deletedBy = structuredClone(event.actor);\n break;\n }\n case 'comment/anchor': {\n const comment = findComment(next, event.data.commentId);\n const anchor = structuredClone(event.data.anchor);\n const index = comment.anchors.findIndex((candidate) => candidate.round === anchor.round);\n if (index < 0) comment.anchors.push(anchor);\n else comment.anchors[index] = anchor;\n if (event.data.outcome !== undefined) {\n comment.outcomes.push(structuredClone(event.data.outcome));\n }\n break;\n }\n case 'suggestion/state': {\n findComment(next, event.data.commentId).suggestionState = event.data.state;\n break;\n }\n case 'fix/claim': {\n next.fixClaims ??= [];\n next.fixClaims.push(...structuredClone(event.data.claims));\n break;\n }\n case 'finding/decision': {\n next.findingDecisions ??= [];\n next.findingDecisions.push(structuredClone(event.data.decision));\n if (event.data.comment !== undefined) {\n const comment = event.data.comment;\n if (next.comments.some((candidate) => candidate.id === comment.id)) {\n throw new ReviewFoldError(`duplicate comment: ${comment.id}`);\n }\n next.comments.push(structuredClone(comment));\n }\n if (event.data.deletedCommentId !== undefined) {\n const comment = findComment(next, event.data.deletedCommentId);\n if (comment.deletedAt === undefined) {\n comment.deletedAt = event.at;\n comment.deletedBy = structuredClone(event.actor);\n }\n }\n break;\n }\n case 'review/updated': {\n if (event.data.title !== undefined) next.title = event.data.title;\n if (event.data.reviewer !== undefined) {\n next.reviewer = structuredClone(event.data.reviewer);\n }\n next.updatedAt = event.at;\n next.updatedBy = structuredClone(event.actor);\n break;\n }\n case 'review/deleted': {\n next.deletedAt = event.at;\n next.deletedBy = structuredClone(event.actor);\n break;\n }\n case 'suggestion/applied': {\n const comment = findComment(next, event.data.commentId);\n const alreadyApplied = comment.outcomes.some(\n (outcome) => outcome.round === event.data.round && outcome.status === 'applied',\n );\n if (!alreadyApplied) {\n comment.outcomes.push({\n round: event.data.round,\n status: 'applied',\n confidence: 'high',\n });\n comment.suggestionState = 'applied';\n }\n break;\n }\n case 'review/closed': {\n next.status = 'closed';\n next.closedAt ??= event.at;\n next.closeVerdict = event.data.verdict;\n break;\n }\n case 'review/submitted': {\n const submission = structuredClone(event.data.submission);\n next.submissions ??= [];\n if (next.submissions.some((item) => item.submissionId === submission.submissionId)) {\n throw new ReviewFoldError(`duplicate submission: ${submission.submissionId}`);\n }\n next.submissions.push(submission);\n if (submission.verdict === 'approve') {\n next.status = 'closed';\n next.closedAt ??= event.at;\n next.closeVerdict ??= 'approved';\n }\n break;\n }\n case 'agent/coverage': {\n next.agent = {\n status: 'queued',\n round: event.data.round,\n coverage: structuredClone(event.data.coverage),\n findings: [],\n shards: [],\n };\n break;\n }\n case 'agent/started': {\n next.agent = {\n ...(next.agent?.coverage === undefined ? {} : { coverage: next.agent.coverage }),\n ...(next.agent?.shards === undefined ? {} : { shards: next.agent.shards }),\n status: 'running',\n jobId: event.data.jobId,\n round: event.data.round,\n startedAt: event.at,\n findings: [],\n };\n break;\n }\n case 'agent/shard': {\n next.agent ??= { status: 'running', findings: [] };\n next.agent.shards ??= [];\n const index = next.agent.shards.findIndex((shard) => shard.shardId === event.data.shardId);\n const shard = {\n shardId: event.data.shardId,\n shardIndex: event.data.shardIndex,\n shardCount: event.data.shardCount,\n round: event.data.round,\n report: structuredClone(event.data.report),\n };\n if (index < 0) next.agent.shards.push(shard);\n else next.agent.shards[index] = shard;\n if (next.agent.coverage !== undefined && event.data.paths !== undefined) {\n const covered = new Set(event.data.paths);\n const tier = event.data.tier ?? 'deep';\n const files = next.agent.coverage.files.map((file) => {\n if (!covered.has(file.path) || file.status !== 'pending') return file;\n const nextFile = {\n ...file,\n status: tier === 'deep' ? ('deep-reviewed' as const) : ('light-reviewed' as const),\n };\n delete nextFile.reason;\n return nextFile;\n });\n next.agent.coverage = {\n ...next.agent.coverage,\n files,\n totals: summarizeCoverage(files),\n };\n }\n break;\n }\n case 'agent/finding': {\n next.agent ??= { status: 'running', findings: [] };\n next.agent.findings ??= [];\n next.agent.findings.push(structuredClone(event.data.finding));\n break;\n }\n case 'agent/report': {\n const reportSkipped = event.data.report.skipped === true;\n const coverage =\n event.data.coverage !== undefined\n ? structuredClone(event.data.coverage)\n : reportSkipped || next.agent?.coverage === undefined\n ? next.agent?.coverage\n : promotePendingToLight(next.agent.coverage);\n let status: AgentStatus;\n if (reportSkipped) status = 'skipped';\n else if (coverage === undefined) status = 'done';\n else status = isCoverageComplete(coverage) ? 'done' : 'partial';\n next.report = structuredClone(event.data.report);\n next.agent = {\n ...(next.agent ?? {}),\n status,\n round: event.data.report.round,\n findings: structuredClone(event.data.report.findings),\n ...(coverage === undefined ? {} : { coverage }),\n };\n break;\n }\n case 'agent/failed': {\n next.agent = {\n ...(next.agent ?? {}),\n status: 'failed',\n error: event.data.message,\n };\n break;\n }\n case 'agent/retry': {\n const agent = next.agent ?? { status: 'queued' as const, findings: [] };\n const retryShards = new Set(event.data.shardIds);\n let coverage = agent.coverage;\n if (coverage !== undefined) {\n const files = coverage.files.map((file) => {\n if (\n file.shardId === undefined ||\n !retryShards.has(file.shardId) ||\n (file.status !== 'failed' && file.status !== 'pending')\n ) {\n return file;\n }\n const retried = { ...file, status: 'pending' as const };\n delete retried.reason;\n return retried;\n });\n coverage = { ...coverage, files, totals: summarizeCoverage(files) };\n }\n next.agent = {\n ...agent,\n status: 'queued',\n round: event.data.round,\n ...(coverage === undefined ? {} : { coverage }),\n };\n delete next.agent.jobId;\n delete next.agent.startedAt;\n delete next.agent.error;\n break;\n }\n }\n\n return next;\n}\n", "import { createHash } from 'node:crypto';\nimport { captureAnchor, AnchorError, reanchor } from './anchors.js';\nimport { createEvent } from './events.js';\nimport { isFinalReviewReport } from './final.js';\nimport { createId } from './ids.js';\nimport { deriveOutcome } from './outcomes.js';\nimport { ReviewNotFoundError } from './store.js';\nimport type { ReviewStore } from './store.js';\nimport type {\n Actor,\n AddCommentInput,\n Anchor,\n Comment,\n CommentState,\n CreateReviewInput,\n FindingDecision,\n FindingDecisionState,\n ReviewId,\n ReviewState,\n ReviewSummary,\n Round,\n} from './types.js';\nimport type { Snapshot } from '../types.js';\nimport type { Finding, ReviewerConfig } from '../reviewer/types.js';\n\nexport type ReviewLifecycleErrorCode =\n | 'not-found'\n | 'closed'\n | 'no-rounds'\n | 'duplicate-round'\n | 'round-order'\n | 'comment-not-found'\n | 'finding-not-found'\n | 'snapshot-mismatch'\n | 'invalid-input';\n\nexport class ReviewLifecycleError extends Error {\n readonly code: ReviewLifecycleErrorCode;\n readonly reviewId?: ReviewId;\n readonly commentId?: string;\n readonly findingId?: string;\n\n constructor(\n code: ReviewLifecycleErrorCode,\n message: string,\n details: { reviewId?: ReviewId; commentId?: string; findingId?: string } = {},\n ) {\n super(message);\n this.name = 'ReviewLifecycleError';\n this.code = code;\n if (details.reviewId !== undefined) this.reviewId = details.reviewId;\n if (details.commentId !== undefined) this.commentId = details.commentId;\n if (details.findingId !== undefined) this.findingId = details.findingId;\n }\n}\n\nfunction findComment(state: ReviewState, commentId: string): Comment {\n const comment = state.comments.find((candidate) => candidate.id === commentId);\n if (comment === undefined) {\n throw new ReviewLifecycleError('comment-not-found', `unknown comment: ${commentId}`, {\n reviewId: state.id,\n commentId,\n });\n }\n return comment;\n}\n\nfunction requireLatestReport(\n state: ReviewState,\n reviewId: ReviewId,\n): NonNullable<ReviewState['report']> {\n const latestRound = state.rounds.at(-1);\n if (state.report === undefined || latestRound === undefined) {\n throw new ReviewLifecycleError('invalid-input', `review has no reviewer report: ${reviewId}`, {\n reviewId,\n });\n }\n if (state.report.round !== latestRound.no) {\n throw new ReviewLifecycleError(\n 'invalid-input',\n `reviewer report is from round ${state.report.round}, latest is ${latestRound.no}`,\n { reviewId },\n );\n }\n return state.report;\n}\n\nfunction requireFinalReport(\n state: ReviewState,\n reviewId: ReviewId,\n): NonNullable<ReviewState['report']> {\n const report = requireLatestReport(state, reviewId);\n if (!isFinalReviewReport(state)) {\n throw new ReviewLifecycleError('invalid-input', `reviewer report is not final: ${reviewId}`, {\n reviewId,\n });\n }\n return report;\n}\n\nfunction normalizeDecisionInput(\n input: { state: FindingDecisionState; note?: string },\n reviewId: ReviewId,\n): { state: FindingDecisionState; note?: string } {\n if (input.state !== 'accepted' && input.state !== 'dismissed') {\n throw new ReviewLifecycleError('invalid-input', `unknown finding decision: ${input.state}`, {\n reviewId,\n });\n }\n if (input.note !== undefined && typeof input.note !== 'string') {\n throw new ReviewLifecycleError('invalid-input', 'finding decision note must be a string', {\n reviewId,\n });\n }\n const note = input.note?.trim();\n if (note !== undefined && note.length > 4000) {\n throw new ReviewLifecycleError('invalid-input', 'finding decision note is too long', {\n reviewId,\n });\n }\n return {\n state: input.state,\n ...(note === undefined || note === '' ? {} : { note }),\n };\n}\n\nfunction requireFinding(\n report: NonNullable<ReviewState['report']>,\n findingId: string,\n reviewId: ReviewId,\n): Finding {\n const finding = report.findings.find((candidate) => candidate.id === findingId);\n if (finding === undefined) {\n throw new ReviewLifecycleError('finding-not-found', `unknown finding: ${findingId}`, {\n reviewId,\n findingId,\n });\n }\n return finding;\n}\n\nfunction activeFindingComment(state: ReviewState, findingId: string): Comment | undefined {\n return state.comments.find(\n (comment) => comment.sourceFindingId === findingId && comment.deletedAt === undefined,\n );\n}\n\nfunction findingAnchor(finding: Finding, round: number, now: () => Date): Anchor {\n return {\n id: createId('anc', now),\n round,\n path: finding.file,\n side: 'new',\n lineStart: finding.lineStart,\n lineEnd: finding.lineEnd,\n quote: finding.evidence,\n contextBefore: [],\n contextAfter: [],\n hunkHeader: '',\n contentHash: createHash('sha256').update(finding.evidence, 'utf8').digest('hex'),\n state: 'active',\n };\n}\n\nfunction transferredCommentBody(finding: Finding, note: string | undefined): string {\n return [\n finding.title,\n finding.rationale,\n finding.evidence.trim() === '' ? '' : `Evidence:\\n${finding.evidence}`,\n note === undefined ? '' : `Note to the agent: ${note}`,\n ]\n .filter((part) => part !== '')\n .join('\\n\\n');\n}\n\nfunction transferredComment(\n reviewId: ReviewId,\n finding: Finding,\n round: number,\n note: string | undefined,\n now: () => Date,\n): Comment {\n return {\n id: createId('cmt', now),\n reviewId,\n createdAt: now().toISOString(),\n author: { name: 'AI', kind: 'agent' },\n body: transferredCommentBody(finding, note),\n ...(finding.suggestion === undefined\n ? {}\n : { suggestion: structuredClone(finding.suggestion) }),\n state: 'open',\n replies: [],\n anchors: [findingAnchor(finding, round, now)],\n outcomes: [],\n sourceFindingId: finding.id,\n };\n}\n\ninterface DecisionTransfer {\n comment?: Comment;\n deletedCommentId?: string;\n commentId?: string;\n}\n\nfunction decisionTransfer(\n state: ReviewState,\n reviewId: ReviewId,\n finding: Finding,\n round: number,\n decisionState: FindingDecisionState,\n note: string | undefined,\n now: () => Date,\n): DecisionTransfer {\n const existing = activeFindingComment(state, finding.id);\n if (decisionState === 'accepted') {\n if (existing !== undefined) return { commentId: existing.id };\n const comment = transferredComment(reviewId, finding, round, note, now);\n return { comment, commentId: comment.id };\n }\n if (existing === undefined) return {};\n return { deletedCommentId: existing.id, commentId: existing.id };\n}\n\nfunction hasDecision(state: ReviewState, findingId: string, round: number): boolean {\n return (state.findingDecisions ?? []).some(\n (decision) => decision.round === round && decision.findingId === findingId,\n );\n}\n\nexport interface RefreshResult {\n round: Round;\n comments: Comment[];\n}\n\n/**\n * Domain-level mutations for one review. Every method appends an event; the\n * aggregate is always reloaded through the store so callers never observe a\n * state that has not been folded from the log.\n */\nexport class ReviewLifecycle {\n private readonly store: ReviewStore;\n private readonly now: () => Date;\n\n constructor(store: ReviewStore, now: () => Date = () => new Date()) {\n this.store = store;\n this.now = now;\n }\n\n async create(input: CreateReviewInput): Promise<ReviewState> {\n const id = createId('rev', this.now);\n const state: ReviewState = {\n id,\n title: input.title,\n repoRoot: input.repoRoot,\n status: 'open',\n createdAt: this.now().toISOString(),\n createdBy: input.actor,\n ...(input.initiator === undefined ? {} : { initiator: input.initiator }),\n rounds: [],\n comments: [],\n version: 0,\n ...(input.reviewer === undefined ? {} : { reviewer: input.reviewer }),\n };\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'review/created',\n actor: input.actor,\n data: { review: state },\n now: this.now,\n }),\n );\n return this.get(id);\n }\n\n async get(reviewId: ReviewId): Promise<ReviewState> {\n try {\n return await this.store.load(reviewId);\n } catch (error) {\n if (error instanceof ReviewNotFoundError) {\n throw new ReviewLifecycleError('not-found', error.message, { reviewId });\n }\n throw error;\n }\n }\n\n async list(): Promise<ReviewSummary[]> {\n return this.store.list();\n }\n\n async addRound(reviewId: ReviewId, snapshot: Snapshot, actor: Actor): Promise<Round> {\n const state = await this.requireOpen(reviewId);\n const previous = state.rounds.at(-1);\n // A worktree snapshot has no head commit; its identity is the digest.\n const sameScope = (round: Round): boolean =>\n snapshot.scope.headSha !== null &&\n round.baseSha === snapshot.scope.baseSha &&\n round.headSha === snapshot.scope.headSha;\n const earlier = state.rounds.slice(0, -1).find(sameScope);\n if (earlier !== undefined) {\n throw new ReviewLifecycleError(\n 'duplicate-round',\n `snapshot already belongs to round ${earlier.no}`,\n { reviewId },\n );\n }\n if (previous !== undefined && sameScope(previous)) {\n throw new ReviewLifecycleError(\n 'duplicate-round',\n `snapshot already belongs to round ${previous.no}`,\n { reviewId },\n );\n }\n\n const snapshotId = createId('snap', this.now);\n await this.store.writeSnapshot(snapshotId, snapshot);\n const round: Round = {\n no: state.rounds.length + 1,\n snapshotId,\n createdAt: this.now().toISOString(),\n baseSha: snapshot.scope.baseSha,\n headSha: snapshot.scope.headSha,\n path: `snapshots/${snapshotId}.json`,\n };\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'round/created',\n actor,\n data: { round },\n now: this.now,\n }),\n );\n return round;\n }\n\n async latestSnapshot(reviewId: ReviewId): Promise<Snapshot> {\n const state = await this.get(reviewId);\n const round = state.rounds.at(-1);\n if (round === undefined) {\n throw new ReviewLifecycleError('no-rounds', `review has no rounds: ${reviewId}`, {\n reviewId,\n });\n }\n try {\n return await this.store.readSnapshot(round.snapshotId);\n } catch (error) {\n if (error instanceof ReviewNotFoundError) {\n throw new ReviewLifecycleError(\n 'snapshot-mismatch',\n `round ${round.no} snapshot is missing or invalid: ${round.snapshotId}`,\n { reviewId },\n );\n }\n throw error;\n }\n }\n\n async addComment(reviewId: ReviewId, input: AddCommentInput, actor: Actor): Promise<Comment> {\n const state = await this.requireOpen(reviewId);\n const round = state.rounds.at(-1);\n if (round === undefined) {\n throw new ReviewLifecycleError('no-rounds', `review has no rounds: ${reviewId}`, {\n reviewId,\n });\n }\n const snapshot = await this.latestSnapshot(reviewId);\n\n let anchor: Anchor;\n try {\n anchor = captureAnchor(snapshot, {\n path: input.path,\n side: input.side,\n lineStart: input.lineStart,\n ...(input.lineEnd === undefined ? {} : { lineEnd: input.lineEnd }),\n round: round.no,\n id: createId('anc', this.now),\n });\n } catch (error) {\n if (error instanceof AnchorError) {\n throw new ReviewLifecycleError('snapshot-mismatch', error.message, { reviewId });\n }\n throw error;\n }\n\n const comment: Comment = {\n id: createId('cmt', this.now),\n reviewId,\n createdAt: this.now().toISOString(),\n author: actor,\n body: input.body,\n state: 'open',\n replies: [],\n anchors: [anchor],\n outcomes: [],\n ...(input.suggestion === undefined ? {} : { suggestion: structuredClone(input.suggestion) }),\n };\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'comment/added',\n actor,\n data: { comment },\n now: this.now,\n }),\n );\n return this.findComment(await this.get(reviewId), comment.id);\n }\n\n async reply(reviewId: ReviewId, commentId: string, body: string, actor: Actor): Promise<Comment> {\n const state = await this.requireOpen(reviewId);\n const target = findComment(state, commentId);\n if (target.deletedAt !== undefined) {\n throw new ReviewLifecycleError('comment-not-found', `unknown comment: ${commentId}`, {\n reviewId,\n commentId,\n });\n }\n if (body.trim() === '') {\n throw new ReviewLifecycleError('invalid-input', 'reply body must be non-empty', { reviewId });\n }\n\n const reply = {\n id: createId('cmt', this.now),\n author: actor,\n body,\n createdAt: this.now().toISOString(),\n };\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'comment/replied',\n actor,\n data: { commentId, reply },\n now: this.now,\n }),\n );\n return this.findComment(await this.get(reviewId), commentId);\n }\n\n async editComment(\n reviewId: ReviewId,\n commentId: string,\n body: string,\n actor: Actor,\n ): Promise<Comment> {\n const state = await this.requireOpen(reviewId);\n const comment = findComment(state, commentId);\n if (comment.deletedAt !== undefined) {\n throw new ReviewLifecycleError('comment-not-found', `unknown comment: ${commentId}`, {\n reviewId,\n commentId,\n });\n }\n const text = body.trim();\n if (text === '') {\n throw new ReviewLifecycleError('invalid-input', 'comment body must be non-empty', {\n reviewId,\n commentId,\n });\n }\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'comment/edited',\n actor,\n data: { commentId, body: text },\n now: this.now,\n }),\n );\n return findComment(await this.get(reviewId), commentId);\n }\n\n async deleteComment(reviewId: ReviewId, commentId: string, actor: Actor): Promise<Comment> {\n const state = await this.get(reviewId);\n if (state.deletedAt !== undefined) {\n throw new ReviewLifecycleError('not-found', `review not found: ${reviewId}`, { reviewId });\n }\n const comment = findComment(state, commentId);\n if (comment.deletedAt !== undefined) return comment;\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'comment/deleted',\n actor,\n data: { commentId },\n now: this.now,\n }),\n );\n return findComment(await this.get(reviewId), commentId);\n }\n\n async setCommentState(\n reviewId: ReviewId,\n commentId: string,\n state: CommentState,\n actor: Actor,\n ): Promise<Comment> {\n const review = await this.requireOpen(reviewId);\n const comment = findComment(review, commentId);\n if (comment.deletedAt !== undefined) {\n throw new ReviewLifecycleError('comment-not-found', `unknown comment: ${commentId}`, {\n reviewId,\n commentId,\n });\n }\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'comment/state',\n actor,\n data: { commentId, state },\n now: this.now,\n }),\n );\n return this.findComment(await this.get(reviewId), commentId);\n }\n\n async decideFinding(\n reviewId: ReviewId,\n findingId: string,\n input: { state: FindingDecisionState; note?: string },\n actor: Actor,\n ): Promise<FindingDecision> {\n const normalized = normalizeDecisionInput(input, reviewId);\n const state = await this.requireOpen(reviewId);\n const report = requireFinalReport(state, reviewId);\n const finding = requireFinding(report, findingId, reviewId);\n const at = this.now().toISOString();\n const transfer = decisionTransfer(\n state,\n reviewId,\n finding,\n report.round,\n normalized.state,\n normalized.note,\n this.now,\n );\n\n const decision: FindingDecision = {\n findingId,\n round: report.round,\n state: normalized.state,\n ...(normalized.note === undefined ? {} : { note: normalized.note }),\n ...(transfer.commentId === undefined ? {} : { commentId: transfer.commentId }),\n by: actor,\n at,\n };\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'finding/decision',\n actor,\n data: {\n decision,\n ...(transfer.comment === undefined ? {} : { comment: transfer.comment }),\n ...(transfer.deletedCommentId === undefined\n ? {}\n : { deletedCommentId: transfer.deletedCommentId }),\n },\n now: this.now,\n }),\n );\n return decision;\n }\n\n /**\n * Records a decision only when the finding has no decision for the same\n * report round. The existence check and append share the store's per-review\n * critical section, so two concurrent bulk requests cannot both win.\n * Returns null when another writer decided the finding first.\n */\n async decideFindingIfUndecided(\n reviewId: ReviewId,\n findingId: string,\n input: { state: FindingDecisionState },\n actor: Actor,\n ): Promise<FindingDecision | null> {\n const normalized = normalizeDecisionInput(input, reviewId);\n const state = await this.requireOpen(reviewId);\n const report = requireFinalReport(state, reviewId);\n const finding = requireFinding(report, findingId, reviewId);\n const at = this.now().toISOString();\n const transfer = decisionTransfer(\n state,\n reviewId,\n finding,\n report.round,\n normalized.state,\n normalized.note,\n this.now,\n );\n\n const decision: FindingDecision = {\n findingId,\n round: report.round,\n state: normalized.state,\n ...(transfer.commentId === undefined ? {} : { commentId: transfer.commentId }),\n by: actor,\n at,\n };\n const appended = await this.store.appendIf(\n reviewId,\n createEvent({\n reviewId,\n type: 'finding/decision',\n actor,\n data: {\n decision,\n ...(transfer.comment === undefined ? {} : { comment: transfer.comment }),\n ...(transfer.deletedCommentId === undefined\n ? {}\n : { deletedCommentId: transfer.deletedCommentId }),\n },\n now: this.now,\n }),\n (current) => {\n if (current.deletedAt !== undefined) {\n throw new ReviewLifecycleError('not-found', `review not found: ${reviewId}`, {\n reviewId,\n });\n }\n if (current.status === 'closed') {\n throw new ReviewLifecycleError('closed', `review is closed: ${reviewId}`, { reviewId });\n }\n const currentReport = requireFinalReport(current, reviewId);\n if (currentReport.round !== decision.round) {\n throw new ReviewLifecycleError(\n 'invalid-input',\n `reviewer report is from round ${currentReport.round}, expected ${decision.round}`,\n { reviewId },\n );\n }\n requireFinding(currentReport, findingId, reviewId);\n return !hasDecision(current, findingId, decision.round);\n },\n );\n return appended === null ? null : decision;\n }\n\n /**\n * Materializes a comment for accepted findings that predate automatic\n * transfer. It is idempotent: an active source comment suppresses a second\n * append, and `appendIf` re-checks the current state inside the review lock.\n */\n async transferAcceptedFindings(reviewId: ReviewId, actor: Actor): Promise<Comment[]> {\n const state = await this.get(reviewId);\n if (state.deletedAt !== undefined || !isFinalReviewReport(state)) return [];\n const report = state.report;\n if (report === undefined) return [];\n const latest = new Map<string, FindingDecision>();\n for (const decision of state.findingDecisions ?? []) {\n if (decision.round === report.round) latest.set(decision.findingId, decision);\n }\n const accepted = new Set(\n [...latest.values()]\n .filter((decision) => decision.state === 'accepted')\n .map((decision) => decision.findingId),\n );\n const transferred: Comment[] = [];\n for (const finding of report.findings) {\n if (!accepted.has(finding.id) || activeFindingComment(state, finding.id) !== undefined) {\n continue;\n }\n const note = latest.get(finding.id)?.note;\n const comment = transferredComment(reviewId, finding, report.round, note, this.now);\n const appended = await this.store.appendIf(\n reviewId,\n createEvent({\n reviewId,\n type: 'comment/added',\n actor,\n data: { comment },\n now: this.now,\n }),\n (current) => {\n if (current.deletedAt !== undefined) return false;\n if (!isFinalReviewReport(current) || current.report?.round !== report.round) {\n return false;\n }\n const decision = [...(current.findingDecisions ?? [])]\n .reverse()\n .find(\n (candidate) => candidate.round === report.round && candidate.findingId === finding.id,\n );\n return (\n decision?.state === 'accepted' &&\n activeFindingComment(current, finding.id) === undefined\n );\n },\n );\n if (appended !== null) transferred.push(comment);\n }\n return transferred;\n }\n\n async updateReview(\n reviewId: ReviewId,\n input: { title?: string; reviewer?: ReviewerConfig },\n actor: Actor,\n ): Promise<ReviewState> {\n await this.requireOpen(reviewId);\n const title = input.title?.trim();\n if (title === undefined && input.reviewer === undefined) {\n throw new ReviewLifecycleError('invalid-input', 'review update is empty', { reviewId });\n }\n if (title !== undefined && title === '') {\n throw new ReviewLifecycleError('invalid-input', 'review title must be non-empty', {\n reviewId,\n });\n }\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'review/updated',\n actor,\n data: {\n ...(title === undefined ? {} : { title }),\n ...(input.reviewer === undefined ? {} : { reviewer: input.reviewer }),\n },\n now: this.now,\n }),\n );\n return this.get(reviewId);\n }\n\n async deleteReview(reviewId: ReviewId, actor: Actor, reason?: string): Promise<ReviewState> {\n const state = await this.get(reviewId);\n if (state.deletedAt !== undefined) return state;\n if (reason !== undefined && typeof reason !== 'string') {\n throw new ReviewLifecycleError('invalid-input', 'delete reason must be a string', {\n reviewId,\n });\n }\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'review/deleted',\n actor,\n data: reason === undefined || reason.trim() === '' ? {} : { reason: reason.trim() },\n now: this.now,\n }),\n );\n return this.get(reviewId);\n }\n\n async close(\n reviewId: ReviewId,\n verdict: 'approved' | 'closed',\n actor: Actor,\n ): Promise<ReviewState> {\n const state = await this.get(reviewId);\n if (state.deletedAt !== undefined) {\n throw new ReviewLifecycleError('not-found', `review not found: ${reviewId}`, { reviewId });\n }\n if (state.status === 'closed') {\n throw new ReviewLifecycleError('closed', `review is already closed: ${reviewId}`, {\n reviewId,\n });\n }\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'review/closed',\n actor,\n data: { verdict },\n now: this.now,\n }),\n );\n return this.get(reviewId);\n }\n\n async refresh(reviewId: ReviewId, snapshot: Snapshot, actor: Actor): Promise<RefreshResult> {\n const state = await this.requireOpen(reviewId);\n const round = await this.addRound(reviewId, snapshot, actor);\n const comments = structuredClone(state.comments);\n\n for (const comment of comments) {\n const previous = comment.anchors.at(-1);\n if (previous === undefined) continue;\n const anchor = reanchor(previous, snapshot, {\n round: round.no,\n id: createId('anc', this.now),\n ...(comment.suggestion === undefined\n ? {}\n : { fallbackQuote: comment.suggestion.replacement }),\n });\n const outcome = deriveOutcome(previous, anchor, snapshot, comment.suggestion);\n await this.store.append(\n reviewId,\n createEvent({\n reviewId,\n type: 'comment/anchor',\n actor,\n data: { commentId: comment.id, anchor, outcome },\n now: this.now,\n }),\n );\n const index = comment.anchors.findIndex((candidate) => candidate.round === anchor.round);\n if (index < 0) comment.anchors.push(anchor);\n else comment.anchors[index] = anchor;\n comment.outcomes.push(outcome);\n }\n\n return { round, comments };\n }\n\n private async requireOpen(reviewId: ReviewId): Promise<ReviewState> {\n const state = await this.get(reviewId);\n if (state.deletedAt !== undefined) {\n throw new ReviewLifecycleError('not-found', `review not found: ${reviewId}`, { reviewId });\n }\n if (state.status === 'closed') {\n throw new ReviewLifecycleError('closed', `review is closed: ${reviewId}`, { reviewId });\n }\n return state;\n }\n\n private findComment(state: ReviewState, commentId: string): Comment {\n return findComment(state, commentId);\n }\n}\n", "import { randomBytes } from 'node:crypto';\nimport type { Dirent } from 'node:fs';\nimport {\n link,\n open,\n readdir,\n readFile,\n stat,\n mkdir,\n rename,\n rm,\n truncate,\n unlink,\n} from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport { isReviewEvent, ReviewEventError } from './events.js';\nimport type { ReviewEvent } from './events.js';\nimport { fold } from './fold.js';\nimport { manifestFromSnapshot } from '../diff/manifest.js';\nimport type { FileStatus, ManifestFileReason, ReviewManifest, Snapshot } from '../types.js';\nimport type {\n Actor,\n Comment,\n FindingDecision,\n ReviewId,\n ReviewState,\n ReviewStatus,\n ReviewSummary,\n} from './types.js';\n\nexport interface ReviewStoreOptions {\n now?: () => Date;\n newId?: (prefix: string) => string;\n}\n\ninterface CacheEntry {\n state: ReviewState;\n eventCount: number;\n /** Exact byte length of the log prefix this state was folded from. */\n bytes?: number;\n events?: ReviewEvent[];\n}\n\ninterface SnapshotCache {\n reviewId: ReviewId;\n eventCount: number;\n /** Size of events.jsonl when this cache was written; detects a stale cache. */\n eventBytes?: number;\n state: ReviewState;\n}\n\ninterface LockFile {\n pid: number;\n createdAt: string;\n}\n\nexport class ReviewStoreLockedError extends Error {\n readonly pid?: number;\n readonly stale: boolean;\n readonly lockPath: string;\n\n constructor(message: string, options: { pid?: number; stale: boolean; lockPath: string }) {\n super(message);\n this.name = 'ReviewStoreLockedError';\n this.pid = options.pid;\n this.stale = options.stale;\n this.lockPath = options.lockPath;\n }\n}\n\nexport class ReviewStoreCorruptionError extends Error {\n readonly reviewId: ReviewId;\n readonly line: number;\n\n constructor(message: string, reviewId: ReviewId, line: number) {\n super(message);\n this.name = 'ReviewStoreCorruptionError';\n this.reviewId = reviewId;\n this.line = line;\n }\n}\n\nexport class ReviewNotFoundError extends Error {\n readonly reviewId: ReviewId;\n\n constructor(reviewId: ReviewId) {\n super(`review not found: ${reviewId}`);\n this.name = 'ReviewNotFoundError';\n this.reviewId = reviewId;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isTimestamp(value: unknown): value is string {\n if (typeof value !== 'string') return false;\n const parsed = new Date(value);\n return Number.isFinite(parsed.getTime()) && parsed.toISOString() === value;\n}\n\nconst REVIEW_STATUSES = new Set<ReviewStatus>(['open', 'closed']);\n\nfunction isActor(value: unknown): value is Actor {\n if (!isRecord(value)) return false;\n return (\n typeof value.name === 'string' &&\n (value.kind === 'human' || value.kind === 'agent' || value.kind === 'system')\n );\n}\n\nfunction isComment(value: unknown): value is Comment {\n if (!isRecord(value)) return false;\n return (\n typeof value.id === 'string' &&\n typeof value.reviewId === 'string' &&\n isTimestamp(value.createdAt) &&\n typeof value.body === 'string' &&\n (value.state === 'open' || value.state === 'resolved' || value.state === 'dismissed') &&\n Array.isArray(value.replies) &&\n Array.isArray(value.anchors) &&\n Array.isArray(value.outcomes) &&\n (value.editedAt === undefined || isTimestamp(value.editedAt)) &&\n (value.editedBy === undefined || isActor(value.editedBy)) &&\n (value.deletedAt === undefined || isTimestamp(value.deletedAt)) &&\n (value.deletedBy === undefined || isActor(value.deletedBy)) &&\n (value.sourceFindingId === undefined || typeof value.sourceFindingId === 'string')\n );\n}\n\nfunction isFindingDecision(value: unknown): value is FindingDecision {\n if (!isRecord(value)) return false;\n return (\n typeof value.findingId === 'string' &&\n typeof value.round === 'number' &&\n Number.isInteger(value.round) &&\n value.round > 0 &&\n (value.state === 'accepted' || value.state === 'dismissed') &&\n (value.note === undefined || typeof value.note === 'string') &&\n (value.commentId === undefined || typeof value.commentId === 'string') &&\n isRecord(value.by) &&\n typeof value.by.name === 'string' &&\n (value.by.kind === 'human' || value.by.kind === 'agent' || value.by.kind === 'system') &&\n isTimestamp(value.at)\n );\n}\n\nfunction isReviewState(value: unknown): value is ReviewState {\n if (!isRecord(value)) return false;\n return (\n typeof value.id === 'string' &&\n typeof value.title === 'string' &&\n typeof value.repoRoot === 'string' &&\n typeof value.status === 'string' &&\n REVIEW_STATUSES.has(value.status as ReviewStatus) &&\n isTimestamp(value.createdAt) &&\n (value.closedAt === undefined || isTimestamp(value.closedAt)) &&\n (value.updatedAt === undefined || isTimestamp(value.updatedAt)) &&\n (value.updatedBy === undefined || isActor(value.updatedBy)) &&\n (value.deletedAt === undefined || isTimestamp(value.deletedAt)) &&\n (value.deletedBy === undefined || isActor(value.deletedBy)) &&\n Array.isArray(value.rounds) &&\n Array.isArray(value.comments) &&\n value.comments.every(isComment) &&\n (value.findingDecisions === undefined ||\n (Array.isArray(value.findingDecisions) && value.findingDecisions.every(isFindingDecision))) &&\n typeof value.version === 'number' &&\n Number.isInteger(value.version) &&\n value.version >= 0 &&\n (value.warnings === undefined ||\n (Array.isArray(value.warnings) && value.warnings.every((item) => typeof item === 'string')))\n );\n}\n\nfunction safeReviewId(reviewId: ReviewId): string {\n if (\n typeof reviewId !== 'string' ||\n !/^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(reviewId) ||\n reviewId.length > 200\n ) {\n throw new ReviewNotFoundError(reviewId);\n }\n return reviewId;\n}\n\nfunction safeSnapshotId(snapshotId: string): string {\n if (typeof snapshotId !== 'string' || !/^snap_[A-Za-z0-9]+$/.test(snapshotId)) {\n throw new ReviewNotFoundError(snapshotId);\n }\n return snapshotId;\n}\n\nconst FILE_STATUSES = new Set<FileStatus>([\n 'added',\n 'modified',\n 'deleted',\n 'renamed',\n 'submodule',\n 'untracked',\n]);\n\nconst MANIFEST_REASONS = new Set<ManifestFileReason>([\n 'per-file-cap',\n 'binary',\n 'ignored',\n 'generated',\n 'legacy-truncated',\n 'diff-truncated',\n 'render-budget',\n 'unreadable',\n 'symlink',\n]);\n\nfunction isManifestFile(value: unknown): boolean {\n if (!isRecord(value)) return false;\n if (typeof value.path !== 'string') return false;\n if (value.oldPath !== undefined && typeof value.oldPath !== 'string') return false;\n if (typeof value.status !== 'string' || !FILE_STATUSES.has(value.status as FileStatus)) {\n return false;\n }\n if (\n typeof value.binary !== 'boolean' ||\n typeof value.ignored !== 'boolean' ||\n typeof value.oversized !== 'boolean'\n ) {\n return false;\n }\n for (const field of ['added', 'deleted', 'hunkCount', 'patchBytes'] as const) {\n if (typeof value[field] !== 'number' || !Number.isFinite(value[field])) return false;\n }\n if (\n value.contentBytes !== undefined &&\n (typeof value.contentBytes !== 'number' || !Number.isFinite(value.contentBytes))\n ) {\n return false;\n }\n if (\n value.reason !== undefined &&\n (typeof value.reason !== 'string' || !MANIFEST_REASONS.has(value.reason as ManifestFileReason))\n ) {\n return false;\n }\n return true;\n}\n\nfunction isManifest(value: unknown): value is ReviewManifest {\n if (!isRecord(value)) return false;\n if (value.schemaVersion !== 1) return false;\n if (!isRecord(value.scope) || typeof value.scope.baseSha !== 'string') return false;\n if (!Array.isArray(value.files) || !value.files.every(isManifestFile)) return false;\n if (!isRecord(value.totals)) return false;\n for (const field of ['files', 'added', 'deleted', 'patchBytes'] as const) {\n if (typeof value.totals[field] !== 'number' || !Number.isFinite(value.totals[field])) {\n return false;\n }\n }\n return Array.isArray(value.warnings) && value.warnings.every((item) => typeof item === 'string');\n}\n\nfunction isSnapshot(value: unknown): value is Snapshot {\n if (!isRecord(value)) return false;\n if (value.schemaVersion !== 1 && value.schemaVersion !== 2) return false;\n if (!isRecord(value.scope) || typeof value.scope.baseSha !== 'string') return false;\n if (!Array.isArray(value.files)) return false;\n if (!isRecord(value.totals)) return false;\n if (value.schemaVersion === 2 && typeof value.totals.truncated !== 'boolean') return false;\n if (\n value.schemaVersion === 1 &&\n value.totals.truncated !== undefined &&\n typeof value.totals.truncated !== 'boolean'\n ) {\n return false;\n }\n if (!Array.isArray(value.warnings)) return false;\n if (value.manifest !== undefined && !isManifest(value.manifest)) return false;\n return value.files.every(\n (file) => isRecord(file) && typeof file.path === 'string' && Array.isArray(file.hunks),\n );\n}\n\n/**\n * API and job consumers expect a manifest. Legacy v1 snapshots are normalized\n * on read (schemaVersion stays 1 so callers can still recognize them); a v2\n * snapshot that somehow lacks one gets a synthesized manifest marked\n * `manifest-missing`, so coverage can never treat the bounded render subset as\n * the complete changed-path listing. A missing v1 totals.truncated means false\n * before the manifest is synthesized.\n */\nfunction normalizeSnapshot(snapshot: Snapshot): Snapshot {\n // Older v1 snapshots predate totals.truncated; a missing value means false.\n const normalized: Snapshot = {\n ...snapshot,\n totals: { ...snapshot.totals, truncated: snapshot.totals.truncated === true },\n };\n if (normalized.manifest !== undefined) return normalized;\n return { ...normalized, manifest: manifestFromSnapshot(normalized) };\n}\n\nfunction isPidAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return (error as NodeJS.ErrnoException).code === 'EPERM';\n }\n}\n\nfunction parseLock(raw: string): Partial<LockFile> {\n try {\n const value: unknown = JSON.parse(raw);\n if (!isRecord(value)) return {};\n return {\n ...(typeof value.pid === 'number' ? { pid: value.pid } : {}),\n ...(typeof value.createdAt === 'string' ? { createdAt: value.createdAt } : {}),\n };\n } catch {\n return {};\n }\n}\n\nasync function readLock(lockPath: string): Promise<Partial<LockFile> | null> {\n try {\n const raw = await readFile(lockPath, 'utf8');\n return parseLock(raw);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return null;\n return {};\n }\n}\n\nfunction corrupt(reviewId: ReviewId, line: number, detail: string): ReviewStoreCorruptionError {\n return new ReviewStoreCorruptionError(\n `review ${reviewId} is corrupt at line ${line}: ${detail}`,\n reviewId,\n line,\n );\n}\n\nfunction splitEventLines(content: string): string[] {\n if (content === '') return [];\n const lines = content.split('\\n');\n if (content.endsWith('\\n')) lines.pop();\n return lines;\n}\n\nfunction parseEventLog(\n content: string,\n reviewId: ReviewId,\n): { events: ReviewEvent[]; eventCount: number; torn: boolean } {\n const hasTrailingNewline = content.endsWith('\\n');\n const lines = splitEventLines(content);\n if (lines.length === 0) throw new ReviewNotFoundError(reviewId);\n\n const events: ReviewEvent[] = [];\n let torn = false;\n\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? '';\n const lineNo = index + 1;\n const isLast = index === lines.length - 1;\n\n if (line.trim() === '') {\n if (isLast) {\n torn = true;\n continue;\n }\n throw corrupt(reviewId, lineNo, 'empty line');\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n if (isLast) {\n torn = true;\n continue;\n }\n throw corrupt(reviewId, lineNo, 'invalid JSON');\n }\n\n if (!isReviewEvent(parsed) || parsed.reviewId !== reviewId) {\n // A missing newline always means the write was torn. A newline means the\n // line is complete, so invalid event fields are real corruption.\n if (isLast && !hasTrailingNewline) {\n torn = true;\n continue;\n }\n throw corrupt(reviewId, lineNo, 'invalid review event');\n }\n\n parsed.seq ??= lineNo;\n events.push(parsed);\n }\n\n return { events, eventCount: events.length, torn };\n}\n\nfunction parseReview(\n content: string,\n reviewId: ReviewId,\n): { state: ReviewState; eventCount: number; events: ReviewEvent[] } {\n const { events, eventCount, torn } = parseEventLog(content, reviewId);\n\n let state: ReviewState | undefined;\n for (let index = 0; index < events.length; index++) {\n const parsed = events[index] as ReviewEvent;\n const lineNo = index + 1;\n try {\n if (state === undefined) {\n if (parsed.type !== 'review/created') {\n throw new Error('first event must be review/created');\n }\n state = fold(parsed.data.review, parsed);\n } else {\n state = fold(state, parsed);\n }\n } catch (error) {\n throw corrupt(reviewId, lineNo, (error as Error).message);\n }\n }\n\n if (state === undefined) throw new ReviewNotFoundError(reviewId);\n if (torn) state.warnings = [...(state.warnings ?? []), 'torn-tail'];\n return { state, eventCount, events };\n}\n\nfunction shortSha(sha: string | null): string {\n return sha === null ? 'worktree' : sha.slice(0, 8);\n}\n\nfunction summary(state: ReviewState): ReviewSummary {\n const latest = state.rounds.at(-1);\n const comments = state.comments.filter((comment) => comment.deletedAt === undefined);\n const latestClaims = new Map<string, string>();\n for (const claim of state.fixClaims ?? []) latestClaims.set(claim.commentId, claim.status);\n return {\n id: state.id,\n title: state.title,\n repoRoot: state.repoRoot,\n status: state.status,\n createdAt: state.createdAt,\n roundCount: state.rounds.length,\n commentCount: comments.length,\n openCommentCount: comments.filter((comment) => comment.state === 'open').length,\n ...(latest === undefined\n ? { scope: 'no rounds' }\n : { scope: `${shortSha(latest.baseSha)} \u2192 ${shortSha(latest.headSha)}` }),\n ...(state.createdBy === undefined ? {} : { author: state.createdBy.name }),\n notFixedCount: [...latestClaims.values()].filter((status) => status === 'not-fixed').length,\n };\n}\n\n/**\n * One process writes a review store. JSONL is the source of truth; the\n * atomically replaced snapshot.json is only a replay cache.\n */\n\nexport interface GcResult {\n removedReviews: ReviewId[];\n removedSnapshots: number;\n}\n\nexport class ReviewStore {\n readonly root: string;\n readonly lockPath: string;\n private readonly lockCreatedAt: string;\n private readonly entries = new Map<ReviewId, CacheEntry>();\n private readonly locks = new Map<ReviewId, Promise<unknown>>();\n private closed = false;\n\n private constructor(root: string, lockCreatedAt: string) {\n this.root = root;\n this.lockPath = join(root, 'lock');\n this.lockCreatedAt = lockCreatedAt;\n }\n\n static async open(root: string, options: ReviewStoreOptions = {}): Promise<ReviewStore> {\n const absolute = resolve(root);\n await mkdir(absolute, { recursive: true });\n const lockPath = join(absolute, 'lock');\n const createdAt = (options.now ?? (() => new Date()))().toISOString();\n\n let handle;\n try {\n handle = await open(lockPath, 'wx');\n await handle.writeFile(JSON.stringify({ pid: process.pid, createdAt }));\n await handle.sync();\n await handle.close();\n } catch (error) {\n if (handle !== undefined) await handle.close().catch(() => undefined);\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;\n\n const existing = await readLock(lockPath);\n const pid = existing?.pid;\n if (pid !== undefined && isPidAlive(pid)) {\n throw new ReviewStoreLockedError(`review store is locked by pid ${pid}`, {\n pid,\n stale: false,\n lockPath,\n });\n }\n const message =\n pid === undefined\n ? `stale lock: unreadable lock file ${lockPath}; remove it manually`\n : `stale lock: pid ${pid} is not running; remove ${lockPath} manually`;\n throw new ReviewStoreLockedError(message, {\n ...(pid === undefined ? {} : { pid }),\n stale: true,\n lockPath,\n });\n }\n\n return new ReviewStore(absolute, createdAt);\n }\n\n async append(reviewId: ReviewId, event: ReviewEvent): Promise<ReviewEvent> {\n const appended = await this.appendInternal(reviewId, event);\n if (appended === null) throw new Error('unconditional append was skipped');\n return appended;\n }\n\n /**\n * Appends an event only when `accept` returns true for the review state\n * observed inside the per-review critical section. Returning null means the\n * event was not written. This makes existence checks atomic with the append.\n */\n async appendIf(\n reviewId: ReviewId,\n event: ReviewEvent,\n accept: (state: ReviewState) => boolean,\n ): Promise<ReviewEvent | null> {\n return await this.appendInternal(reviewId, event, accept);\n }\n\n private async appendInternal(\n reviewId: ReviewId,\n event: ReviewEvent,\n accept?: (state: ReviewState) => boolean,\n ): Promise<ReviewEvent | null> {\n if (this.closed) throw new Error('review store is closed');\n const id = safeReviewId(reviewId);\n if (!isReviewEvent(event)) {\n throw new ReviewEventError('invalid-event', 'append requires a valid review event');\n }\n if (event.reviewId !== id) {\n throw new ReviewEventError(\n 'invalid-review-id',\n `event belongs to ${event.reviewId}, not ${id}`,\n );\n }\n\n // A review's read-fold-append-cache sequence is one critical section. Two\n // concurrent appends must not both read the same event count and write the\n // same sequence number.\n return await this.withReviewLock(id, async () => {\n const dir = this.reviewDir(id);\n await mkdir(dir, { recursive: true });\n const eventsPath = join(dir, 'events.jsonl');\n await this.repairTornTail(eventsPath);\n\n let fileBytes = 0;\n try {\n fileBytes = (await stat(eventsPath)).size;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n\n let entry: CacheEntry | undefined = this.entries.get(id);\n if (entry === undefined) {\n try {\n entry = await this.readEntry(id);\n } catch (error) {\n if (!(error instanceof ReviewNotFoundError)) throw error;\n }\n }\n if (entry === undefined) {\n if (event.type !== 'review/created') throw new ReviewNotFoundError(id);\n entry = { state: event.data.review, eventCount: 0 };\n }\n\n if (accept !== undefined && !accept(entry.state)) return null;\n\n // Validate against the aggregate before touching the log: a rejected event\n // must not leave a line that makes every later replay fail.\n const state = fold(entry.state, event);\n // The append starts after repairTornTail removed an incomplete final\n // line, so a warning that belonged to that line must not survive in the\n // cache we are about to persist.\n if (state.warnings !== undefined) {\n state.warnings = state.warnings.filter((warning) => warning !== 'torn-tail');\n }\n const sequenced = { ...event, seq: entry.eventCount + 1 } as ReviewEvent;\n const payload = `${JSON.stringify(sequenced)}\\n`;\n const handle = await open(eventsPath, 'a');\n try {\n const result = await handle.write(payload);\n if (result.bytesWritten !== Buffer.byteLength(payload)) {\n throw new Error('short event write');\n }\n await handle.sync();\n } finally {\n await handle.close();\n }\n\n const next = {\n state,\n eventCount: entry.eventCount + 1,\n // The stat is taken after repairing a torn tail, so it is the exact\n // byte offset where this append started. Do not trust a cached byte\n // count that may describe a larger pre-repair file.\n bytes: fileBytes + Buffer.byteLength(payload),\n };\n this.entries.set(id, next);\n // The event log is the source of truth. A cache failure must not turn a\n // committed mutation into an error; the next read rebuilds the cache.\n await this.writeCache(id, next).catch(() => undefined);\n return structuredClone(sequenced);\n });\n }\n\n async load(reviewId: ReviewId): Promise<ReviewState> {\n if (this.closed) throw new Error('review store is closed');\n const id = safeReviewId(reviewId);\n return await this.withReviewLock(id, async () => {\n const entry = await this.readState(id);\n return structuredClone(entry.state);\n });\n }\n\n async events(reviewId: ReviewId, after = 0): Promise<ReviewEvent[]> {\n if (this.closed) throw new Error('review store is closed');\n const id = safeReviewId(reviewId);\n if (!Number.isInteger(after) || after < 0) {\n throw new ReviewEventError('invalid-event', 'after must be a non-negative integer');\n }\n return await this.withReviewLock(id, async () => {\n let content: string;\n try {\n content = await readFile(join(this.reviewDir(id), 'events.jsonl'), 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new ReviewNotFoundError(id);\n }\n throw error;\n }\n const { events } = parseEventLog(content, id);\n return structuredClone(events.filter((event) => (event.seq ?? 0) > after));\n });\n }\n\n async list(): Promise<ReviewSummary[]> {\n if (this.closed) throw new Error('review store is closed');\n const reviewsRoot = join(this.root, 'reviews');\n let entries;\n try {\n entries = await readdir(reviewsRoot, { withFileTypes: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return [];\n throw error;\n }\n\n const summaries: ReviewSummary[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const id = entry.name as ReviewId;\n const cache = await this.readCache(id).catch(() => null);\n const cacheFresh =\n cache !== null &&\n cache.state.id === id &&\n cache.eventBytes !== undefined &&\n (await stat(join(this.reviewDir(id), 'events.jsonl')).catch(() => null))?.size ===\n cache.eventBytes;\n if (cache !== null && cacheFresh) {\n if (cache.state.deletedAt === undefined) summaries.push(summary(cache.state));\n continue;\n }\n // A missing or corrupt cache must not hide the review: replay its JSONL\n // log and write a replacement cache as a side effect.\n const rebuilt = await this.readEntry(id).catch(() => null);\n if (rebuilt === null || rebuilt.state.id !== id) continue;\n this.entries.set(id, rebuilt);\n if (rebuilt.state.deletedAt === undefined) summaries.push(summary(rebuilt.state));\n }\n summaries.sort((left, right) => {\n if (left.createdAt !== right.createdAt) return left.createdAt < right.createdAt ? -1 : 1;\n return left.id < right.id ? -1 : left.id > right.id ? 1 : 0;\n });\n return summaries;\n }\n\n async writeSnapshot(snapshotId: string, snapshot: Snapshot): Promise<void> {\n if (this.closed) throw new Error('review store is closed');\n const id = safeSnapshotId(snapshotId);\n if (!isSnapshot(snapshot)) {\n throw new ReviewNotFoundError(id);\n }\n\n const dir = join(this.root, 'snapshots');\n await mkdir(dir, { recursive: true });\n const target = join(dir, `${id}.json`);\n const temp = join(dir, `.${id}.${process.pid}.${randomBytes(6).toString('hex')}.tmp`);\n const handle = await open(temp, 'wx');\n try {\n await handle.writeFile(JSON.stringify(snapshot));\n await handle.sync();\n } finally {\n await handle.close();\n }\n try {\n // A hard link publishes the finished file atomically and fails with\n // EEXIST when the snapshot id is already taken, so snapshots are immutable.\n await link(temp, target);\n } catch (error) {\n await unlink(temp).catch(() => undefined);\n throw error;\n }\n await unlink(temp).catch(() => undefined);\n }\n\n async readSnapshot(snapshotId: string): Promise<Snapshot> {\n if (this.closed) throw new Error('review store is closed');\n const id = safeSnapshotId(snapshotId);\n let raw: string;\n try {\n raw = await readFile(join(this.root, 'snapshots', `${id}.json`), 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new ReviewNotFoundError(id);\n }\n throw error;\n }\n\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n throw new ReviewNotFoundError(id);\n }\n if (!isSnapshot(value)) throw new ReviewNotFoundError(id);\n return structuredClone(normalizeSnapshot(value));\n }\n\n /**\n * Removes closed reviews older than `olderThanDays` and snapshots that no\n * remaining review references. Open reviews are never touched.\n */\n async gc(olderThanDays: number, now: Date = new Date()): Promise<GcResult> {\n if (this.closed) throw new Error('review store is closed');\n if (!Number.isFinite(olderThanDays) || olderThanDays < 0) {\n throw new RangeError('olderThanDays must be a non-negative number');\n }\n const cutoff = now.getTime() - olderThanDays * 24 * 60 * 60 * 1000;\n const reviewsRoot = join(this.root, 'reviews');\n let reviewEntries: Dirent[] = [];\n try {\n reviewEntries = await readdir(reviewsRoot, { withFileTypes: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n\n // Scan directories directly instead of trusting list(): a missing or stale\n // cache must not make an old review invisible to garbage collection.\n const all = new Map<ReviewId, ReviewState>();\n for (const entry of reviewEntries) {\n if (!entry.isDirectory()) continue;\n const id = entry.name as ReviewId;\n const loaded = await this.readEntry(id).catch(() => null);\n if (loaded === null) continue;\n all.set(id, loaded.state);\n this.entries.set(id, loaded);\n }\n\n const removedReviews: ReviewId[] = [];\n for (const [id, state] of all) {\n if (state.status !== 'closed') continue;\n // Newer logs carry the close time; legacy logs fall back to createdAt so\n // their previous collection behavior is preserved.\n const closedTime = new Date(state.closedAt ?? state.createdAt).getTime();\n if (!Number.isFinite(closedTime) || closedTime >= cutoff) continue;\n removedReviews.push(id);\n await rm(this.reviewDir(id), { recursive: true, force: true });\n this.entries.delete(id);\n all.delete(id);\n }\n\n const referenced = new Set<string>();\n for (const state of all.values()) {\n for (const round of state.rounds) referenced.add(round.snapshotId);\n }\n let removedSnapshots = 0;\n let entries: string[] = [];\n try {\n entries = await readdir(join(this.root, 'snapshots'));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n for (const entry of entries) {\n if (!entry.endsWith('.json')) continue;\n const snapshotId = entry.slice(0, -'.json'.length);\n if (referenced.has(snapshotId)) continue;\n try {\n await unlink(join(this.root, 'snapshots', entry));\n removedSnapshots += 1;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n }\n return { removedReviews, removedSnapshots };\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n this.entries.clear();\n const existing = await readLock(this.lockPath);\n if (existing?.pid === process.pid && existing.createdAt === this.lockCreatedAt) {\n await unlink(this.lockPath).catch((error: unknown) => {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n });\n }\n }\n\n /**\n * Serializes work per review without blocking other reviews. A failed task\n * releases the gate so later appends can still make progress.\n */\n private async withReviewLock<T>(reviewId: ReviewId, task: () => Promise<T>): Promise<T> {\n const previous = this.locks.get(reviewId) ?? Promise.resolve();\n let release!: () => void;\n const gate = new Promise<void>((resolveGate) => {\n release = resolveGate;\n });\n const current: Promise<unknown> = previous.catch(() => undefined).then(() => gate);\n this.locks.set(reviewId, current);\n await previous.catch(() => undefined);\n try {\n return await task();\n } finally {\n release();\n if (this.locks.get(reviewId) === current) this.locks.delete(reviewId);\n }\n }\n\n private reviewDir(reviewId: ReviewId): string {\n return join(this.root, 'reviews', reviewId);\n }\n\n private async repairTornTail(eventsPath: string): Promise<void> {\n let content: string;\n try {\n content = await readFile(eventsPath, 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return;\n throw error;\n }\n if (content === '' || content.endsWith('\\n')) return;\n const lastNewline = content.lastIndexOf('\\n');\n await truncate(eventsPath, lastNewline < 0 ? 0 : lastNewline + 1);\n }\n\n /**\n * Reads state without replaying the log when the event file is unchanged.\n * `snapshot.json` is a replay cache, so a matching byte length and event\n * count prove it describes this log prefix. Mutations still go through\n * `readEntry` when the cache is missing or stale, preserving log validation.\n */\n private async readState(reviewId: ReviewId): Promise<CacheEntry> {\n const eventsPath = join(this.reviewDir(reviewId), 'events.jsonl');\n let eventBytes: number;\n try {\n eventBytes = (await stat(eventsPath)).size;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new ReviewNotFoundError(reviewId);\n }\n throw error;\n }\n\n const cache = await this.readCache(reviewId).catch(() => null);\n if (\n cache !== null &&\n cache.eventBytes === eventBytes &&\n cache.eventCount === cache.state.version &&\n cache.state.id === reviewId\n ) {\n const entry = { state: cache.state, eventCount: cache.eventCount, bytes: eventBytes };\n this.entries.set(reviewId, entry);\n return entry;\n }\n\n const entry = await this.readEntry(reviewId);\n this.entries.set(reviewId, entry);\n return entry;\n }\n\n private async readEntry(reviewId: ReviewId): Promise<CacheEntry> {\n const dir = this.reviewDir(reviewId);\n let content: string;\n try {\n content = await readFile(join(dir, 'events.jsonl'), 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new ReviewNotFoundError(reviewId);\n }\n throw error;\n }\n\n const { state, eventCount, events } = parseReview(content, reviewId);\n const cache = await this.readCache(reviewId);\n const eventBytes = Buffer.byteLength(content);\n if (\n cache !== null &&\n cache.eventCount === eventCount &&\n cache.eventBytes === eventBytes &&\n cache.state.version === state.version &&\n cache.state.id === reviewId\n ) {\n return {\n state: {\n ...structuredClone(cache.state),\n warnings: [...(state.warnings ?? [])],\n },\n eventCount,\n events,\n };\n }\n\n const entry = { state, eventCount, bytes: eventBytes, events };\n await this.writeCache(reviewId, entry).catch(() => undefined);\n return entry;\n }\n\n private async readCache(reviewId: ReviewId): Promise<SnapshotCache | null> {\n let raw: string;\n try {\n raw = await readFile(join(this.reviewDir(reviewId), 'snapshot.json'), 'utf8');\n } catch {\n return null;\n }\n try {\n const value: unknown = JSON.parse(raw);\n if (!isRecord(value)) return null;\n if (value.reviewId !== reviewId) return null;\n if (typeof value.eventCount !== 'number' || !Number.isInteger(value.eventCount)) return null;\n if (value.eventBytes !== undefined && typeof value.eventBytes !== 'number') return null;\n if (!isReviewState(value.state)) return null;\n return {\n reviewId,\n eventCount: value.eventCount,\n ...(typeof value.eventBytes === 'number' ? { eventBytes: value.eventBytes } : {}),\n state: value.state,\n };\n } catch {\n return null;\n }\n }\n\n private async writeCache(reviewId: ReviewId, entry: CacheEntry): Promise<void> {\n const dir = this.reviewDir(reviewId);\n const target = join(dir, 'snapshot.json');\n const temp = join(dir, `.snapshot.${process.pid}.${randomBytes(6).toString('hex')}.tmp`);\n const eventBytes =\n entry.bytes ??\n (await stat(join(dir, 'events.jsonl')).then(\n (info) => info.size,\n () => undefined,\n ));\n const payload: SnapshotCache = {\n reviewId,\n eventCount: entry.eventCount,\n ...(eventBytes === undefined ? {} : { eventBytes }),\n state: entry.state,\n };\n const handle = await open(temp, 'wx');\n try {\n await handle.writeFile(JSON.stringify(payload));\n await handle.sync();\n } finally {\n await handle.close();\n }\n try {\n await rename(temp, target);\n } catch (error) {\n await unlink(temp).catch(() => undefined);\n throw error;\n }\n }\n}\n", "import type {\n Finding,\n FindingSink,\n ReviewerBackend,\n ReviewerJob,\n ReviewerReport,\n} from './types.js';\n\nexport interface FakeReviewerOptions {\n report?: ReviewerReport | ((job: ReviewerJob) => ReviewerReport);\n findings?: Finding[];\n}\n\nfunction emptyReport(job: ReviewerJob): ReviewerReport {\n return {\n schemaVersion: 1,\n summary: `Fake review of ${job.reviewId} round ${job.round}`,\n riskLevel: 'low',\n findings: [],\n questions: [],\n tests: { ran: false, commands: [] },\n verification: [],\n };\n}\n\n/** Deterministic in-process reviewer used by tests and local smoke runs. */\nexport class FakeReviewer implements ReviewerBackend {\n readonly kind = 'fake' as const;\n private readonly options: FakeReviewerOptions;\n\n constructor(options: FakeReviewerOptions = {}) {\n this.options = options;\n }\n\n async run(job: ReviewerJob, sink: FindingSink, signal: AbortSignal): Promise<ReviewerReport> {\n if (signal.aborted) throw new Error('reviewer cancelled');\n const report =\n typeof this.options.report === 'function'\n ? this.options.report(job)\n : (this.options.report ?? emptyReport(job));\n const findings = this.options.findings ?? report.findings;\n for (const finding of findings) {\n if (signal.aborted) throw new Error('reviewer cancelled');\n await sink(finding);\n }\n return {\n ...structuredClone(report),\n findings: structuredClone(findings),\n };\n }\n}\n", "import { spawn } from 'node:child_process';\nimport { mkdtemp, open, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { runGit } from '../git/run.js';\nimport { ReviewerError } from './types.js';\nimport type {\n FindingSink,\n GitStatusRunner,\n ReviewerBackend,\n ReviewerJob,\n ReviewerReport,\n} from './types.js';\n\nexport interface CommandReviewerOptions {\n /** argv array only; never passed through a shell. */\n command: readonly string[];\n runGit?: GitStatusRunner;\n timeoutMs?: number;\n env?: NodeJS.ProcessEnv;\n maxOutputBytes?: number;\n}\n\nconst DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;\nconst DEFAULT_MAX_OUTPUT_BYTES = 4 * 1024 * 1024;\nconst BASE_ENV_KEYS = ['PATH', 'HOME', 'LANG', 'TMPDIR', 'TMP', 'TEMP'] as const;\nconst WINDOWS_ENV_KEYS = [\n 'SystemRoot',\n 'ComSpec',\n 'PATHEXT',\n 'USERPROFILE',\n 'APPDATA',\n 'LOCALAPPDATA',\n] as const;\n\nfunction reviewerEnv(job: ReviewerJob, overrides?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = {};\n const keys =\n process.platform === 'win32' ? [...BASE_ENV_KEYS, ...WINDOWS_ENV_KEYS] : BASE_ENV_KEYS;\n for (const key of keys) {\n const value = process.env[key];\n if (value !== undefined) env[key] = value;\n }\n for (const [key, value] of Object.entries(process.env)) {\n if (value === undefined) continue;\n if (key.startsWith('LC_') || key.startsWith('REVIEW_')) env[key] = value;\n }\n env.REVIEW_ID = job.reviewId;\n env.REVIEW_ROUND = String(job.round);\n env.REVIEW_JOB_ID = job.id;\n env.REVIEW_REPO = job.repoRoot;\n return Object.assign(env, overrides);\n}\n\nfunction killProcess(child: ReturnType<typeof spawn>): void {\n if (child.pid !== undefined && process.platform !== 'win32') {\n try {\n // The child is spawned detached, so a negative pid reaches its whole group.\n process.kill(-child.pid, 'SIGKILL');\n return;\n } catch {\n // Fall through to the direct child if the group is already gone.\n }\n }\n child.kill('SIGKILL');\n}\n\nfunction replacePlaceholders(value: string, values: Record<string, string>): string {\n return value.replace(/\\{(promptFile|repo|outputFile|reviewId)\\}/g, (_match, key: string) => {\n return values[key] ?? '';\n });\n}\n\nfunction lastFencedJson(stdout: string): unknown {\n const matches = [...stdout.matchAll(/```(?:json)?[ \\t]*\\r?\\n([\\s\\S]*?)```/g)];\n const last = matches.at(-1)?.[1];\n if (last === undefined) return undefined;\n try {\n return JSON.parse(last);\n } catch {\n throw new ReviewerError('invalid-output', 'last fenced block is not valid JSON');\n }\n}\n\nasync function readOutputFile(outputFile: string, maxBytes: number): Promise<string | undefined> {\n let handle;\n try {\n handle = await open(outputFile, 'r');\n } catch {\n return undefined;\n }\n try {\n const info = await handle.stat();\n if (!info.isFile()) {\n throw new ReviewerError('invalid-output', 'reviewer output file is not a regular file');\n }\n if (info.size > maxBytes) {\n throw new ReviewerError('invalid-output', `reviewer output file exceeded ${maxBytes} bytes`);\n }\n const raw = await handle.readFile({ encoding: 'utf8' });\n if (Buffer.byteLength(raw) > maxBytes) {\n throw new ReviewerError('invalid-output', `reviewer output file exceeded ${maxBytes} bytes`);\n }\n return raw;\n } finally {\n await handle.close();\n }\n}\n\nasync function parseOutput(outputFile: string, stdout: string, maxBytes: number): Promise<unknown> {\n const raw = await readOutputFile(outputFile, maxBytes);\n if (raw !== undefined && raw.trim() !== '') {\n try {\n return JSON.parse(raw);\n } catch {\n throw new ReviewerError('invalid-output', 'reviewer output file is not valid JSON');\n }\n }\n const fenced = lastFencedJson(stdout);\n if (fenced !== undefined) return fenced;\n const trimmed = stdout.trim();\n if (trimmed.startsWith('{')) {\n try {\n return JSON.parse(trimmed);\n } catch {\n throw new ReviewerError('invalid-output', 'reviewer stdout is not valid JSON');\n }\n }\n throw new ReviewerError('invalid-output', 'reviewer produced no JSON output');\n}\n\nasync function status(\n runner: GitStatusRunner,\n repoRoot: string,\n signal: AbortSignal,\n): Promise<string> {\n try {\n const result = await runner(repoRoot, ['status', '--porcelain'], { signal });\n return result.code === 0 ? result.stdout : '';\n } catch {\n return '';\n }\n}\n\n/** Opt-in backend that runs an external reviewer command in the repo root. */\nexport class CommandReviewer implements ReviewerBackend {\n readonly kind = 'command' as const;\n private readonly options: CommandReviewerOptions;\n private child: ReturnType<typeof spawn> | undefined;\n\n constructor(options: CommandReviewerOptions) {\n this.options = options;\n }\n\n async run(job: ReviewerJob, sink: FindingSink, signal: AbortSignal): Promise<ReviewerReport> {\n if (signal.aborted) throw new ReviewerError('cancelled', 'reviewer was cancelled');\n const temp = await mkdtemp(join(tmpdir(), 'cr-reviewer-'));\n const promptFile = join(temp, 'prompt.md');\n const outputFile = join(temp, 'output.json');\n await writeFile(promptFile, job.prompt, 'utf8');\n\n const runner = this.options.runGit ?? runGit;\n const before = await status(runner, job.repoRoot, signal);\n const values = {\n promptFile,\n repo: job.repoRoot,\n outputFile,\n reviewId: job.reviewId,\n };\n const argv = this.options.command.map((part) => replacePlaceholders(part, values));\n if (argv.length === 0 || argv[0] === '') {\n await rm(temp, { recursive: true, force: true });\n throw new ReviewerError('spawn-failed', 'reviewer command is empty');\n }\n\n try {\n const stdout = await this.execute(argv, job, signal);\n const after = await status(runner, job.repoRoot, signal);\n const parsed = await parseOutput(\n outputFile,\n stdout,\n this.options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES,\n );\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n throw new ReviewerError('invalid-output', 'reviewer JSON must be an object');\n }\n const report = parsed as ReviewerReport;\n for (const finding of Array.isArray(report.findings) ? report.findings : []) {\n await sink(finding);\n }\n if (before !== after) return { ...report, dirtyWorktree: true };\n return report;\n } finally {\n await rm(temp, { recursive: true, force: true });\n }\n }\n\n cancel(): void {\n if (this.child !== undefined) killProcess(this.child);\n }\n\n private async execute(\n argv: readonly string[],\n job: ReviewerJob,\n signal: AbortSignal,\n ): Promise<string> {\n const timeoutMs = this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const maxOutput = this.options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;\n return await new Promise<string>((resolve, reject) => {\n const child = spawn(argv[0] as string, argv.slice(1), {\n cwd: job.repoRoot,\n shell: false,\n stdio: ['pipe', 'pipe', 'pipe'],\n detached: process.platform !== 'win32',\n env: reviewerEnv(job, this.options.env),\n });\n this.child = child;\n const chunks: Buffer[] = [];\n const stderr: Buffer[] = [];\n let bytes = 0;\n let settled = false;\n let timedOut = false;\n\n const finish = (error?: Error, value?: string): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n signal.removeEventListener('abort', onAbort);\n this.child = undefined;\n if (error !== undefined) reject(error);\n else resolve(value ?? '');\n };\n const onAbort = (): void => {\n killProcess(child);\n finish(new ReviewerError('cancelled', 'reviewer was cancelled'));\n };\n const timer = setTimeout(() => {\n timedOut = true;\n killProcess(child);\n finish(new ReviewerError('timeout', `reviewer timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n signal.addEventListener('abort', onAbort, { once: true });\n\n child.on('error', (error: NodeJS.ErrnoException) => {\n finish(\n new ReviewerError(\n 'spawn-failed',\n error.code === 'ENOENT' ? `reviewer command not found: ${argv[0]}` : error.message,\n ),\n );\n });\n child.stdout.on('data', (chunk: Buffer) => {\n bytes += chunk.length;\n if (bytes > maxOutput) {\n killProcess(child);\n finish(\n new ReviewerError('invalid-output', `reviewer stdout exceeded ${maxOutput} bytes`),\n );\n return;\n }\n chunks.push(chunk);\n });\n child.stderr.on('data', (chunk: Buffer) => {\n if (stderr.reduce((sum, item) => sum + item.length, 0) < 1024 * 1024) stderr.push(chunk);\n });\n child.on('close', (code) => {\n if (settled) return;\n if (timedOut) {\n finish(new ReviewerError('timeout', `reviewer timed out after ${timeoutMs}ms`));\n return;\n }\n if (code !== 0) {\n finish(\n new ReviewerError(\n 'nonzero-exit',\n `reviewer exited with ${code}: ${Buffer.concat(stderr).toString('utf8').trim()}`,\n ),\n );\n return;\n }\n finish(undefined, Buffer.concat(chunks).toString('utf8'));\n });\n child.stdin.on('error', () => undefined);\n child.stdin.end(job.prompt);\n });\n }\n}\n", "import type { Actor, ReviewId, RoundNo } from '../review/types.js';\nimport type { ReviewManifest, Snapshot } from '../types.js';\n\nexport type FindingSeverity = 'blocker' | 'major' | 'minor' | 'nit';\nexport type FindingCategory =\n | 'security'\n | 'correctness'\n | 'tests'\n | 'performance'\n | 'maintainability'\n | 'api'\n | 'concurrency'\n | 'docs'\n | 'other';\nexport type FindingKind = 'issue' | 'question' | 'praise';\nexport type ReviewerConfidence = 'high' | 'medium' | 'low';\nexport type RiskLevel = 'low' | 'medium' | 'high' | 'critical';\nexport type TestResult = 'pass' | 'fail' | 'unknown';\nexport type VerificationStatus = 'fixed' | 'not-fixed' | 'unclear';\nexport type ReviewerBackendKind = 'fake' | 'command' | 'none' | 'worker';\n\nexport interface ReviewerConfig {\n backend: ReviewerBackendKind;\n command?: string[];\n timeoutMs?: number;\n}\n\nexport interface ReviewSuggestion {\n original: string;\n replacement: string;\n}\n\nexport interface Finding {\n id: string;\n severity: FindingSeverity;\n category: FindingCategory;\n confidence: ReviewerConfidence;\n kind: FindingKind;\n file: string;\n lineStart: number;\n lineEnd: number;\n title: string;\n rationale: string;\n evidence: string;\n suggestion?: ReviewSuggestion;\n /** Suggestion was supplied but could not be matched against the snapshot. */\n unanchored?: boolean;\n}\n\nexport interface ReviewQuestion {\n id: string;\n file: string;\n line: number;\n question: string;\n why: string;\n}\n\nexport interface TestCommand {\n command: string;\n result: TestResult;\n summary: string;\n}\n\nexport interface TestSummary {\n ran: boolean;\n commands: TestCommand[];\n}\n\nexport interface Verification {\n commentId: string;\n status: VerificationStatus;\n evidence: string;\n}\n\nexport interface ReviewerReport {\n schemaVersion: 1;\n summary: string;\n riskLevel: RiskLevel;\n findings: Finding[];\n questions: ReviewQuestion[];\n tests: TestSummary;\n verification: Verification[];\n /** Set by command backends when the repo changed during the run. */\n dirtyWorktree?: boolean;\n}\n\nexport type RejectedReportKind = 'report' | 'finding' | 'question' | 'test' | 'verification';\n\nexport interface RejectedReportItem {\n kind: RejectedReportKind;\n index?: number;\n id?: string;\n reason: string;\n}\n\nexport interface ValidationResult {\n report: ReviewerReport;\n rejected: RejectedReportItem[];\n warnings: string[];\n}\n\n/** Persisted report: validated content plus provenance and rejected items. */\nexport interface AgentReport extends ReviewerReport {\n reviewId: ReviewId;\n round: RoundNo;\n backend: ReviewerBackendKind;\n rejected: RejectedReportItem[];\n warnings: string[];\n dirtyWorktree?: boolean;\n /** True when the configured backend intentionally did not run. */\n skipped?: boolean;\n}\n\nexport interface ReviewerJob {\n id: string;\n reviewId: ReviewId;\n round: RoundNo;\n kind: 'initial' | 'verify';\n repoRoot: string;\n /** Complete markdown prompt handed to the reviewer. */\n prompt: string;\n snapshot: Snapshot;\n /** Full changed-file manifest; absent when only a legacy v1 snapshot is available. */\n manifest?: ReviewManifest;\n}\n\nexport type FindingSink = (finding: Finding) => Promise<void> | void;\n\nexport interface ReviewerBackend {\n readonly kind: ReviewerBackendKind;\n run(job: ReviewerJob, sink: FindingSink, signal: AbortSignal): Promise<ReviewerReport>;\n /** Best-effort cancellation for backends that own an external process. */\n cancel?(): void;\n}\n\nexport type ReviewerErrorCode =\n 'invalid-output' | 'timeout' | 'nonzero-exit' | 'cancelled' | 'spawn-failed';\n\nexport class ReviewerError extends Error {\n readonly code: ReviewerErrorCode;\n\n constructor(code: ReviewerErrorCode, message: string) {\n super(message);\n this.name = 'ReviewerError';\n this.code = code;\n }\n}\n\nexport type GitStatusRunner = (\n cwd: string,\n args: readonly string[],\n options?: { signal?: AbortSignal },\n) => Promise<{ stdout: string; code: number; stderr: string }>;\n\nexport interface ReviewerActorContext {\n actor: Actor;\n requestId?: string;\n}\n", "import type {\n Finding,\n FindingCategory,\n FindingKind,\n FindingSeverity,\n RejectedReportItem,\n ReviewQuestion,\n ReviewerConfidence,\n RiskLevel,\n TestCommand,\n TestResult,\n TestSummary,\n ValidationResult,\n Verification,\n VerificationStatus,\n} from './types.js';\nimport type { FileDiff, Snapshot } from '../types.js';\n\nexport const MAX_TEXT_BYTES = 32 * 1024;\n\nconst CATEGORIES = new Set<FindingCategory>([\n 'security',\n 'correctness',\n 'tests',\n 'performance',\n 'maintainability',\n 'api',\n 'concurrency',\n 'docs',\n 'other',\n]);\nconst CONFIDENCES = new Set<ReviewerConfidence>(['high', 'medium', 'low']);\nconst KINDS = new Set<FindingKind>(['issue', 'question', 'praise']);\nconst RISKS = new Set<RiskLevel>(['low', 'medium', 'high', 'critical']);\nconst TEST_RESULTS = new Set<TestResult>(['pass', 'fail', 'unknown']);\nconst VERIFICATION_STATUSES = new Set<VerificationStatus>(['fixed', 'not-fixed', 'unclear']);\n\nconst REPORT_FIELDS = new Set([\n 'schemaVersion',\n 'summary',\n 'riskLevel',\n 'findings',\n 'questions',\n 'tests',\n 'verification',\n]);\nconst FINDING_FIELDS = new Set([\n 'id',\n 'severity',\n 'category',\n 'confidence',\n 'kind',\n 'file',\n 'lineStart',\n 'lineEnd',\n 'title',\n 'rationale',\n 'evidence',\n 'suggestion',\n]);\nconst QUESTION_FIELDS = new Set(['id', 'file', 'line', 'question', 'why']);\n\n/** LLM reviewers often use a low/medium/high scale; normalize it to our four levels. */\nconst SEVERITY_ALIASES: Record<string, FindingSeverity> = {\n blocker: 'blocker',\n critical: 'blocker',\n high: 'blocker',\n major: 'major',\n medium: 'major',\n minor: 'minor',\n low: 'minor',\n nit: 'nit',\n info: 'nit',\n};\n\n/**\n * Stable id for a finding that omitted one. The incremental `/findings` route\n * validates items one at a time with index 0, so an index-based id would make\n * every item collide; derive it from the content instead.\n */\nfunction autoFindingId(value: Record<string, unknown>): string {\n const basis = [value.file, value.lineStart, value.lineEnd, value.title, value.evidence].join(\n '\\u0000',\n );\n let hash = 2166136261;\n for (let index = 0; index < basis.length; index += 1) {\n hash ^= basis.charCodeAt(index);\n hash = Math.imul(hash, 16777619);\n }\n return `f_auto_${(hash >>> 0).toString(36)}`;\n}\n\nfunction autoQuestionId(value: Record<string, unknown>): string {\n const basis = [value.file, value.line, value.question].join('\\u0000');\n let hash = 2166136261;\n for (let index = 0; index < basis.length; index += 1) {\n hash ^= basis.charCodeAt(index);\n hash = Math.imul(hash, 16777619);\n }\n return `q_auto_${(hash >>> 0).toString(36)}`;\n}\n\nexport class ReportValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ReportValidationError';\n }\n}\n\ninterface ValidationOptions {\n snapshot?: Snapshot;\n maxTextBytes?: number;\n}\n\ninterface Context {\n snapshot?: Snapshot;\n rejected: RejectedReportItem[];\n warnings: string[];\n maxTextBytes: number;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isNonEmpty(value: unknown): value is string {\n return typeof value === 'string' && value.trim() !== '';\n}\n\nfunction isPositiveInt(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= 1;\n}\n\nfunction textWithin(ctx: Context, value: unknown): value is string {\n return typeof value === 'string' && Buffer.byteLength(value, 'utf8') <= ctx.maxTextBytes;\n}\n\nfunction reject(\n ctx: Context,\n kind: RejectedReportItem['kind'],\n reason: string,\n id?: string,\n index?: number,\n): void {\n ctx.rejected.push({\n kind,\n ...(id === undefined ? {} : { id }),\n ...(index === undefined ? {} : { index }),\n reason,\n });\n}\n\nfunction warnUnknown(\n ctx: Context,\n value: Record<string, unknown>,\n allowed: Set<string>,\n label: string,\n): void {\n for (const key of Object.keys(value)) {\n if (!allowed.has(key)) ctx.warnings.push(`unknown-${label}-field:${key}`);\n }\n}\n\nfunction fileLines(file: FileDiff | undefined): string[] | undefined {\n return file?.newLines ?? file?.oldLines;\n}\n\nfunction findFile(snapshot: Snapshot | undefined, path: string): FileDiff | undefined {\n return snapshot?.files.find((file) => file.path === path);\n}\n\n/** Removes indentation and collapses horizontal whitespace for comparison. */\nexport function normalizeCode(value: string): string {\n return value\n .split('\\n')\n .map((line) => line.trim().replace(/[ \\t]+/g, ' '))\n .join('\\n');\n}\n\nfunction validateSuggestion(\n ctx: Context,\n file: FileDiff,\n lineStart: number,\n lineEnd: number,\n value: unknown,\n): { suggestion?: { original: string; replacement: string }; unanchored?: boolean } {\n if (!isRecord(value)) return { unanchored: true };\n const { original, replacement } = value;\n if (!textWithin(ctx, original) || !textWithin(ctx, replacement)) return { unanchored: true };\n const lines = fileLines(file);\n if (lines === undefined) return { unanchored: true };\n const current = lines.slice(lineStart - 1, lineEnd).join('\\n');\n if (normalizeCode(current) !== normalizeCode(original)) return { unanchored: true };\n return { suggestion: { original, replacement } };\n}\n\nfunction validateFinding(\n ctx: Context,\n value: unknown,\n index: number,\n ids: Set<string>,\n): Finding | null {\n if (!isRecord(value)) {\n reject(ctx, 'finding', 'finding must be an object', undefined, index);\n return null;\n }\n warnUnknown(ctx, value, FINDING_FIELDS, 'finding');\n const id = isNonEmpty(value.id) ? value.id : autoFindingId(value);\n const rejected = (reason: string): null => {\n reject(ctx, 'finding', reason, id, index);\n return null;\n };\n if (ids.has(id)) return rejected(`duplicate finding id: ${id}`);\n const severityKey = typeof value.severity === 'string' ? value.severity.toLowerCase() : '';\n const severity = Object.prototype.hasOwnProperty.call(SEVERITY_ALIASES, severityKey)\n ? SEVERITY_ALIASES[severityKey]\n : undefined;\n if (severity === undefined) return rejected('severity must be blocker|major|minor|nit');\n // Keep reports from capable but imperfect models: missing metadata gets a\n // safe default, while present-but-invalid metadata and broken anchors reject.\n let category: FindingCategory = 'other';\n if (value.category !== undefined) {\n if (!CATEGORIES.has(value.category as FindingCategory)) {\n return rejected('category is not a known category');\n }\n category = value.category as FindingCategory;\n }\n let confidence: ReviewerConfidence = 'medium';\n if (value.confidence !== undefined) {\n if (!CONFIDENCES.has(value.confidence as ReviewerConfidence)) {\n return rejected('confidence must be high|medium|low');\n }\n confidence = value.confidence as ReviewerConfidence;\n }\n let kind: FindingKind = 'issue';\n if (value.kind !== undefined) {\n if (!KINDS.has(value.kind as FindingKind))\n return rejected('kind must be issue|question|praise');\n kind = value.kind as FindingKind;\n }\n if (!isNonEmpty(value.file)) return rejected('file must be a non-empty string');\n const lineStart = value.lineStart;\n const lineEnd = value.lineEnd === undefined ? lineStart : value.lineEnd;\n if (!isPositiveInt(lineStart) || !isPositiveInt(lineEnd)) {\n return rejected('lineStart and lineEnd must be positive integers');\n }\n if (lineEnd < lineStart) return rejected('lineEnd must not precede lineStart');\n const title = value.title;\n if (!textWithin(ctx, title)) {\n return rejected(`title must be a string no larger than ${ctx.maxTextBytes} bytes`);\n }\n let rationale: unknown = value.rationale;\n if (rationale === undefined) {\n rationale = textWithin(ctx, value.recommendation) ? value.recommendation : title;\n }\n if (!textWithin(ctx, rationale)) {\n return rejected(`rationale must be a string no larger than ${ctx.maxTextBytes} bytes`);\n }\n const evidence = value.evidence;\n if (!textWithin(ctx, evidence)) {\n return rejected(`evidence must be a string no larger than ${ctx.maxTextBytes} bytes`);\n }\n\n const file = findFile(ctx.snapshot, value.file);\n if (ctx.snapshot !== undefined && file === undefined) {\n return rejected(`file is not present in the snapshot: ${value.file}`);\n }\n const lines = fileLines(file);\n if (lines !== undefined && lineEnd > lines.length) {\n return rejected(`line range ${lineStart}..${lineEnd} exceeds ${lines.length} lines`);\n }\n\n const finding: Finding = {\n id,\n severity,\n category,\n confidence,\n kind,\n file: value.file,\n lineStart,\n lineEnd,\n title,\n rationale,\n evidence,\n };\n if (value.suggestion !== undefined && file !== undefined) {\n const suggestion = validateSuggestion(ctx, file, lineStart, lineEnd, value.suggestion);\n if (suggestion.suggestion !== undefined) finding.suggestion = suggestion.suggestion;\n if (suggestion.unanchored === true) finding.unanchored = true;\n } else if (value.suggestion !== undefined) {\n finding.unanchored = true;\n }\n ids.add(id);\n return finding;\n}\n\nexport interface FindingItemValidation {\n finding: Finding | null;\n rejected: RejectedReportItem[];\n warnings: string[];\n}\n\n/**\n * Validate one incremental finding against the same rules as a full report.\n * Used by the job route so an agent cannot append malformed findings to the\n * event-sourced review before its final report is validated.\n */\nexport function validateFindingItem(\n value: unknown,\n options: { snapshot?: Snapshot; maxTextBytes?: number } = {},\n): FindingItemValidation {\n const ctx: Context = {\n rejected: [],\n warnings: [],\n maxTextBytes: options.maxTextBytes ?? MAX_TEXT_BYTES,\n ...(options.snapshot === undefined ? {} : { snapshot: options.snapshot }),\n };\n const finding = validateFinding(ctx, value, 0, new Set<string>());\n return { finding, rejected: ctx.rejected, warnings: ctx.warnings };\n}\n\nfunction validateQuestion(\n ctx: Context,\n value: unknown,\n index: number,\n ids: Set<string>,\n): ReviewQuestion | null {\n if (!isRecord(value)) {\n reject(ctx, 'question', 'question must be an object', undefined, index);\n return null;\n }\n warnUnknown(ctx, value, QUESTION_FIELDS, 'question');\n const id = isNonEmpty(value.id) ? value.id : autoQuestionId(value);\n const rejected = (reason: string): null => {\n reject(ctx, 'question', reason, id, index);\n return null;\n };\n if (ids.has(id)) return rejected(`duplicate question id: ${id}`);\n if (!isNonEmpty(value.file)) return rejected('file must be a non-empty string');\n if (!isPositiveInt(value.line)) return rejected('line must be a positive integer');\n if (!textWithin(ctx, value.question) || !textWithin(ctx, value.why)) {\n return rejected(`question text must be no larger than ${ctx.maxTextBytes} bytes`);\n }\n const file = findFile(ctx.snapshot, value.file);\n if (ctx.snapshot !== undefined && file === undefined) {\n return rejected(`file is not present in the snapshot: ${value.file}`);\n }\n const lines = fileLines(file);\n if (lines !== undefined && value.line > lines.length) {\n return rejected(`line ${value.line} exceeds ${lines.length} lines`);\n }\n ids.add(id);\n return {\n id,\n file: value.file,\n line: value.line,\n question: value.question,\n why: value.why,\n };\n}\n\nfunction validateTests(ctx: Context, value: unknown): TestSummary {\n if (value === undefined) return { ran: false, commands: [] };\n if (!isRecord(value)) {\n reject(ctx, 'test', 'tests must be an object');\n return { ran: false, commands: [] };\n }\n const ran = value.ran === true;\n const commands: TestCommand[] = [];\n if (Array.isArray(value.commands)) {\n value.commands.forEach((entry, index) => {\n if (!isRecord(entry)) {\n reject(ctx, 'test', 'test command must be an object', undefined, index);\n return;\n }\n if (\n typeof entry.command !== 'string' ||\n typeof entry.summary !== 'string' ||\n typeof entry.result !== 'string' ||\n !TEST_RESULTS.has(entry.result as TestResult)\n ) {\n reject(ctx, 'test', 'invalid test command', undefined, index);\n return;\n }\n if (\n Buffer.byteLength(entry.command, 'utf8') > ctx.maxTextBytes ||\n Buffer.byteLength(entry.summary, 'utf8') > ctx.maxTextBytes\n ) {\n reject(ctx, 'test', 'test command text exceeds the text limit', undefined, index);\n return;\n }\n commands.push({\n command: entry.command,\n result: entry.result as TestResult,\n summary: entry.summary,\n });\n });\n }\n return { ran, commands };\n}\n\nfunction validateVerification(ctx: Context, value: unknown, index: number): Verification | null {\n if (!isRecord(value)) {\n reject(ctx, 'verification', 'verification must be an object', undefined, index);\n return null;\n }\n if (\n !isNonEmpty(value.commentId) ||\n typeof value.status !== 'string' ||\n !VERIFICATION_STATUSES.has(value.status as VerificationStatus) ||\n !textWithin(ctx, value.evidence)\n ) {\n reject(ctx, 'verification', 'invalid verification entry', undefined, index);\n return null;\n }\n return {\n commentId: value.commentId,\n status: value.status as VerificationStatus,\n evidence: value.evidence,\n };\n}\n\n/**\n * Dependency-free validation of reviewer output. Invalid items are rejected\n * individually; the rest of the report is kept.\n */\nexport function validateReport(raw: unknown, options: ValidationOptions = {}): ValidationResult {\n if (!isRecord(raw)) throw new ReportValidationError('reviewer report must be an object');\n if (raw.schemaVersion !== 1) {\n throw new ReportValidationError('reviewer report schemaVersion must be 1');\n }\n\n const ctx: Context = {\n rejected: [],\n warnings: [],\n maxTextBytes: options.maxTextBytes ?? MAX_TEXT_BYTES,\n ...(options.snapshot === undefined ? {} : { snapshot: options.snapshot }),\n };\n warnUnknown(ctx, raw, REPORT_FIELDS, 'report');\n\n const riskLevel: RiskLevel =\n typeof raw.riskLevel === 'string' && RISKS.has(raw.riskLevel as RiskLevel)\n ? (raw.riskLevel as RiskLevel)\n : 'medium';\n if (typeof raw.riskLevel !== 'string' || !RISKS.has(raw.riskLevel as RiskLevel)) {\n ctx.warnings.push('invalid-risk-level');\n }\n\n let summary = typeof raw.summary === 'string' ? raw.summary : '';\n if (typeof raw.summary !== 'string') ctx.warnings.push('invalid-summary');\n if (Buffer.byteLength(summary, 'utf8') > ctx.maxTextBytes) {\n summary = Buffer.from(summary, 'utf8').subarray(0, ctx.maxTextBytes).toString('utf8');\n ctx.warnings.push('summary-truncated');\n }\n\n const findings: Finding[] = [];\n const findingIds = new Set<string>();\n if (Array.isArray(raw.findings)) {\n raw.findings.forEach((entry, index) => {\n const finding = validateFinding(ctx, entry, index, findingIds);\n if (finding !== null) findings.push(finding);\n });\n } else if (raw.findings !== undefined) {\n reject(ctx, 'report', 'findings must be an array');\n }\n\n const questions: ReviewQuestion[] = [];\n const questionIds = new Set<string>();\n if (Array.isArray(raw.questions)) {\n raw.questions.forEach((entry, index) => {\n const question = validateQuestion(ctx, entry, index, questionIds);\n if (question !== null) questions.push(question);\n });\n } else if (raw.questions !== undefined) {\n reject(ctx, 'report', 'questions must be an array');\n }\n\n const verification: Verification[] = [];\n if (Array.isArray(raw.verification)) {\n raw.verification.forEach((entry, index) => {\n const item = validateVerification(ctx, entry, index);\n if (item !== null) verification.push(item);\n });\n } else if (raw.verification !== undefined) {\n reject(ctx, 'report', 'verification must be an array');\n }\n\n return {\n report: {\n schemaVersion: 1,\n summary,\n riskLevel,\n findings,\n questions,\n tests: validateTests(ctx, raw.tests),\n verification,\n },\n rejected: ctx.rejected,\n warnings: ctx.warnings,\n };\n}\n", "import type { DiffScope, Snapshot } from '../types.js';\nimport type { GcResult } from '../review/store.js';\nimport type { AgentReport } from '../reviewer/types.js';\nimport type { IdPrefix } from '../review/ids.js';\nimport type { ReviewEvent } from '../review/events.js';\nimport type { ReviewLifecycle } from '../review/lifecycle.js';\nimport type { ReviewStore } from '../review/store.js';\nimport type {\n Actor,\n AddCommentInput,\n Comment,\n FindingDecision,\n FindingDecisionState,\n FixClaimRecord,\n CommentState,\n ReviewId,\n ReviewState,\n ReviewSummary,\n Initiator,\n RoundNo,\n SubmissionRecord,\n} from '../review/types.js';\nimport type {\n GitStatusRunner,\n ReviewQuestion,\n ReviewerBackend,\n ReviewerConfig,\n Verification,\n} from '../reviewer/types.js';\n\nexport interface CallContext {\n actor: Actor;\n requestId?: string;\n}\n\nexport type ReviewErrorCode =\n 'not-found' | 'validation' | 'conflict' | 'agent-busy' | 'stale-review' | 'internal';\n\nexport class ReviewError extends Error {\n readonly code: ReviewErrorCode;\n readonly details?: Record<string, unknown>;\n\n constructor(code: ReviewErrorCode, message: string, details?: Record<string, unknown>) {\n super(message);\n this.name = 'ReviewError';\n this.code = code;\n if (details !== undefined) this.details = details;\n }\n}\n\nexport interface ServiceCreateInput {\n repoRoot: string;\n title: string;\n scope: DiffScope;\n reviewer?: ReviewerConfig;\n initiator?: Initiator;\n}\n\nexport interface ReviewUpdateInput {\n title?: string;\n reviewer?: ReviewerConfig;\n /** A changed scope creates a new round; repoRoot is never editable. */\n scope?: DiffScope;\n}\n\nexport interface CommentEditInput {\n body: string;\n}\n\nexport interface ReviewView {\n review: ReviewState;\n latestSnapshot: Snapshot | null;\n report: AgentReport | null;\n}\n\nexport interface CommentView {\n comment: Comment;\n}\n\nexport interface ReviewFilter {\n status?: 'open' | 'closed';\n limit?: number;\n offset?: number;\n}\n\nexport interface Page<T> {\n items: T[];\n total: number;\n limit: number;\n offset: number;\n}\n\nexport interface ReplyInput {\n body: string;\n}\n\nexport interface FindingDecisionInput {\n state: FindingDecisionState;\n note?: string;\n}\n\nexport interface FindingDecisionView {\n decision: FindingDecision;\n}\n\nexport interface BulkFindingDecisionInput {\n state: FindingDecisionState;\n /**\n * When present, decide only these findings. Omit it to decide every remaining\n * non-praise finding in the report.\n */\n findingIds?: string[];\n}\n\nexport interface BulkFindingDecisionView {\n /** Decisions appended by this request, in report order. */\n decisions: FindingDecision[];\n /** Findings left untouched because they were praise or already decided. */\n skipped: number;\n}\n\nexport interface TransferAcceptedFindingsView {\n /** Comments created by this idempotent backfill. */\n transferred: number;\n}\n\nexport interface SubmitInput {\n verdict: 'approve' | 'request-changes' | 'comment';\n summary?: string;\n includeResolved?: boolean;\n}\n\nexport interface FeedbackFinding {\n id: string;\n severity: string;\n file: string;\n lineStart: number;\n lineEnd: number;\n title: string;\n rationale: string;\n evidence: string;\n /** Present only when a human accepted or dismissed this finding. */\n decision?: FindingDecisionState;\n /** Human note attached to the decision. */\n note?: string;\n}\n\nexport interface FeedbackComment {\n commentId: string;\n path: string;\n lineStart: number;\n lineEnd: number;\n body: string;\n suggestion?: { original: string; replacement: string };\n}\n\nexport interface FeedbackSuggestion {\n commentId: string;\n path: string;\n lineStart: number;\n lineEnd: number;\n original: string;\n replacement: string;\n}\n\nexport interface FeedbackJson {\n schemaVersion: 1;\n reviewId: ReviewId;\n round: RoundNo;\n verdict: SubmitInput['verdict'];\n title: string;\n scope: {\n baseSha: string;\n headSha: string | null;\n label: string;\n };\n deliveryKey: string;\n summary?: string;\n findings: FeedbackFinding[];\n /** Findings a human dismissed; notes are omitted when the human left none. */\n dismissedFindings: FeedbackFinding[];\n humanComments: FeedbackComment[];\n appliedSuggestions: FeedbackSuggestion[];\n acceptedSuggestions: FeedbackSuggestion[];\n questions: ReviewQuestion[];\n verification: Verification[];\n resolved: {\n count: number;\n commentIds: string[];\n };\n /** Set when the JSON package was reduced to the 100 KiB budget. */\n truncated?: boolean;\n notice?: string;\n}\n\nexport interface FeedbackPackage {\n markdown: string;\n json: FeedbackJson;\n deliveryKey: string;\n}\n\nexport interface SubmissionView {\n reviewId: ReviewId;\n round: RoundNo;\n verdict: SubmitInput['verdict'];\n feedback: FeedbackPackage;\n deliveryKey: string;\n}\n\nexport interface SuggestionActionInput {\n action: 'accept' | 'decline' | 'apply';\n}\n\nexport interface FixStatusInput {\n items: Array<{ commentId: string; status: FixClaimRecord['status']; evidence?: string }>;\n}\n\nexport interface RefreshInput {\n /** Omit to rebuild the latest scope; pass a scope after new commits. */\n scope?: DiffScope;\n}\n\nexport interface LatestFeedbackView {\n submission: SubmissionRecord;\n feedback: FeedbackPackage;\n}\n\nexport interface ServiceSnapshotView {\n snapshot: Snapshot;\n round: RoundNo;\n file?: string;\n}\n\nexport interface ReviewService {\n create(input: ServiceCreateInput, ctx: CallContext): Promise<ReviewView>;\n updateReview(id: ReviewId, input: ReviewUpdateInput, ctx: CallContext): Promise<ReviewView>;\n deleteReview(id: ReviewId, ctx: CallContext, reason?: string): Promise<void>;\n list(filter?: ReviewFilter): Promise<Page<ReviewSummary>>;\n get(id: ReviewId): Promise<ReviewView>;\n snapshot(id: ReviewId, round: RoundNo, file?: string): Promise<ServiceSnapshotView>;\n addComment(id: ReviewId, input: AddCommentInput, ctx: CallContext): Promise<CommentView>;\n editComment(\n id: ReviewId,\n commentId: string,\n input: CommentEditInput,\n ctx: CallContext,\n ): Promise<CommentView>;\n deleteComment(id: ReviewId, commentId: string, ctx: CallContext): Promise<CommentView>;\n reply(id: ReviewId, commentId: string, input: ReplyInput, ctx: CallContext): Promise<CommentView>;\n setCommentState(\n id: ReviewId,\n commentId: string,\n state: CommentState,\n ctx: CallContext,\n ): Promise<CommentView>;\n decideFinding(\n id: ReviewId,\n findingId: string,\n input: FindingDecisionInput,\n ctx: CallContext,\n ): Promise<FindingDecisionView>;\n decideFindings(\n id: ReviewId,\n input: BulkFindingDecisionInput,\n ctx: CallContext,\n ): Promise<BulkFindingDecisionView>;\n transferAcceptedFindings(id: ReviewId, ctx: CallContext): Promise<TransferAcceptedFindingsView>;\n events(id: ReviewId, after?: number): Promise<ReviewEvent[]>;\n suggestionAction(\n id: ReviewId,\n commentId: string,\n action: SuggestionActionInput['action'],\n ctx: CallContext,\n ): Promise<CommentView>;\n refresh(id: ReviewId, input: RefreshInput, ctx: CallContext): Promise<ReviewView>;\n close(id: ReviewId, verdict: 'approved' | 'closed', ctx: CallContext): Promise<ReviewView>;\n claimFixStatus(id: ReviewId, input: FixStatusInput, ctx: CallContext): Promise<void>;\n latestFeedback(id: ReviewId): Promise<LatestFeedbackView | null>;\n gc(olderThanDays: number): Promise<GcResult>;\n submit(id: ReviewId, input: SubmitInput, ctx: CallContext): Promise<SubmissionView>;\n runReviewer(id: ReviewId, ctx: CallContext): Promise<AgentReport>;\n cancelAgent(id: ReviewId, ctx: CallContext): Promise<void>;\n}\n\nexport interface ReviewServiceImplDeps {\n lifecycle: ReviewLifecycle;\n store: ReviewStore;\n snapshots: {\n build(input: { repoRoot: string; scope: DiffScope }): Promise<Snapshot>;\n };\n now?: () => Date;\n newId?: (prefix: IdPrefix) => string;\n backendFactory?: (config: ReviewerConfig) => ReviewerBackend;\n runGit?: GitStatusRunner;\n /** Upper bound for the in-memory request-id cache. */\n idempotencyLimit?: number;\n}\n", "import type { Snapshot } from '../types.js';\nimport type { AgentReport, Finding } from '../reviewer/types.js';\nimport type { Comment, FindingDecision, ReviewState, RoundNo } from '../review/types.js';\nimport type {\n FeedbackComment,\n FeedbackFinding,\n FeedbackJson,\n FeedbackPackage,\n FeedbackSuggestion,\n SubmitInput,\n} from './types.js';\n\nexport const FEEDBACK_BYTE_LIMIT = 100 * 1024;\n\nexport interface BuildFeedbackInput {\n review: ReviewState;\n snapshot: Snapshot;\n report: AgentReport | null;\n round: RoundNo;\n verdict: SubmitInput['verdict'];\n deliveryKey: string;\n summary?: string;\n includeResolved?: boolean;\n}\n\nfunction latestAnchor(\n comment: Comment,\n): { path: string; lineStart: number; lineEnd: number } | null {\n const anchor = comment.anchors.at(-1);\n if (anchor === undefined) return null;\n return { path: anchor.path, lineStart: anchor.lineStart, lineEnd: anchor.lineEnd };\n}\n\nfunction isApplied(comment: Comment): boolean {\n return comment.outcomes.some((outcome) => outcome.status === 'applied');\n}\n\nfunction suggestionOf(comment: Comment): FeedbackSuggestion | null {\n const anchor = latestAnchor(comment);\n if (anchor === null || comment.suggestion === undefined) return null;\n return {\n commentId: comment.id,\n path: anchor.path,\n lineStart: anchor.lineStart,\n lineEnd: anchor.lineEnd,\n original: comment.suggestion.original,\n replacement: comment.suggestion.replacement,\n };\n}\n\nfunction humanComment(\n comment: Comment,\n anchor: { path: string; lineStart: number; lineEnd: number },\n): FeedbackComment {\n const item: FeedbackComment = {\n commentId: comment.id,\n path: anchor.path,\n lineStart: anchor.lineStart,\n lineEnd: anchor.lineEnd,\n body: comment.body,\n };\n if (comment.suggestion !== undefined) item.suggestion = comment.suggestion;\n return item;\n}\n\nfunction latestDecision(\n review: ReviewState,\n findingId: string,\n round: RoundNo,\n): FindingDecision | undefined {\n const decisions = review.findingDecisions ?? [];\n for (let index = decisions.length - 1; index >= 0; index -= 1) {\n const decision = decisions[index];\n if (decision?.findingId === findingId && decision.round === round) return decision;\n }\n return undefined;\n}\n\nfunction findingItem(finding: Finding, decision?: FindingDecision): FeedbackFinding {\n return {\n id: finding.id,\n severity: finding.severity,\n file: finding.file,\n lineStart: finding.lineStart,\n lineEnd: finding.lineEnd,\n title: finding.title,\n rationale: finding.rationale,\n evidence: finding.evidence,\n ...(decision === undefined ? {} : { decision: decision.state }),\n ...(decision?.note === undefined ? {} : { note: decision.note }),\n };\n}\n\nfunction findingLabel(finding: Finding, decision?: FindingDecision): string {\n if (decision?.state === 'accepted') {\n return `[accepted][${finding.severity}]`;\n }\n return `[${finding.severity}]`;\n}\n\nfunction findingLines(finding: Finding, decision?: FindingDecision): string[] {\n return [\n `- ${findingLabel(finding, decision)}[${finding.file}:${finding.lineStart}] ${finding.title}`,\n ` ${finding.rationale}`,\n ` > ${finding.evidence.replace(/\\n/g, '\\n > ')}`,\n ...(decision?.note === undefined ? [] : [` \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430: ${decision.note}`]),\n ];\n}\n\nfunction actionableFinding(finding: Finding, decision: FindingDecision | undefined): boolean {\n if (finding.kind === 'praise') return false;\n if (decision?.state === 'dismissed') return false;\n if (decision?.state === 'accepted') return true;\n return finding.severity === 'blocker' || finding.severity === 'major';\n}\n\nfunction verdictLabel(verdict: SubmitInput['verdict']): string {\n if (verdict === 'approve') return 'approved';\n if (verdict === 'request-changes') return 'changes requested';\n return 'comment';\n}\n\nfunction section(lines: string[], title: string, body: string[]): void {\n if (body.length === 0) return;\n lines.push(`### ${title}`, ...body, '');\n}\n\nexport function jsonBytes(value: FeedbackJson): number {\n return Buffer.byteLength(JSON.stringify(value), 'utf8');\n}\n\nfunction capFeedbackJson(input: FeedbackJson): FeedbackJson {\n if (jsonBytes(input) <= FEEDBACK_BYTE_LIMIT) return input;\n const json = structuredClone(input);\n json.truncated = true;\n json.notice = `feedback json truncated at ${FEEDBACK_BYTE_LIMIT} bytes`;\n\n for (const comment of json.humanComments) {\n if (jsonBytes(json) <= FEEDBACK_BYTE_LIMIT) break;\n if (comment.body.length > 16 * 1024) {\n const excess = jsonBytes(json) - FEEDBACK_BYTE_LIMIT;\n comment.body = truncateUtf8(\n comment.body,\n Math.max(0, Buffer.byteLength(comment.body, 'utf8') - excess - 1024),\n );\n }\n }\n const arrays: Array<\n keyof Pick<\n FeedbackJson,\n | 'findings'\n | 'dismissedFindings'\n | 'questions'\n | 'acceptedSuggestions'\n | 'appliedSuggestions'\n | 'verification'\n | 'humanComments'\n >\n > = [\n 'findings',\n 'dismissedFindings',\n 'questions',\n 'acceptedSuggestions',\n 'appliedSuggestions',\n 'verification',\n 'humanComments',\n ];\n for (const key of arrays) {\n while (jsonBytes(json) > FEEDBACK_BYTE_LIMIT && json[key].length > 0) json[key].pop();\n }\n if (jsonBytes(json) > FEEDBACK_BYTE_LIMIT) json.summary = truncateUtf8(json.summary ?? '', 1024);\n if (jsonBytes(json) > FEEDBACK_BYTE_LIMIT) json.notice = 'feedback json truncated';\n if (jsonBytes(json) > FEEDBACK_BYTE_LIMIT) {\n json.title = truncateUtf8(json.title, 1024);\n json.scope = { ...json.scope, label: truncateUtf8(json.scope.label, 1024) };\n }\n if (jsonBytes(json) > FEEDBACK_BYTE_LIMIT) {\n json.findings = [];\n json.dismissedFindings = [];\n json.questions = [];\n json.acceptedSuggestions = [];\n json.appliedSuggestions = [];\n json.verification = [];\n json.humanComments = [];\n }\n return json;\n}\n\nfunction truncateUtf8(value: string, maxBytes: number): string {\n const bytes = Buffer.from(value, 'utf8');\n if (bytes.length <= maxBytes) return value;\n let end = maxBytes;\n while (end > 0 && (bytes[end] ?? 0) >= 0x80 && (bytes[end] ?? 0) < 0xc0) end -= 1;\n return bytes.subarray(0, end).toString('utf8');\n}\n\n/** Deterministic feedback package for one submission. */\nexport function buildFeedback(input: BuildFeedbackInput): FeedbackPackage {\n const { review, snapshot, report, round, verdict, deliveryKey } = input;\n const activeComments = review.comments.filter((comment) => comment.deletedAt === undefined);\n const openComments = activeComments.filter(\n (comment) => comment.author.kind === 'human' && comment.state === 'open',\n );\n const resolvedComments = activeComments.filter(\n (comment) => comment.author.kind === 'human' && comment.state === 'resolved',\n );\n const resolved = input.includeResolved === false ? [] : resolvedComments;\n\n const reportFindings = report?.findings ?? [];\n const decisions = new Map<string, FindingDecision>();\n for (const finding of reportFindings) {\n const decision = latestDecision(review, finding.id, round);\n if (decision !== undefined) decisions.set(finding.id, decision);\n }\n const addressedFindingIds = new Set(\n activeComments\n .filter((comment) => comment.state === 'resolved' && comment.sourceFindingId !== undefined)\n .map((comment) => comment.sourceFindingId),\n );\n const findings = reportFindings.filter(\n (finding) =>\n !addressedFindingIds.has(finding.id) && actionableFinding(finding, decisions.get(finding.id)),\n );\n const dismissed = reportFindings.filter(\n (finding) => decisions.get(finding.id)?.state === 'dismissed',\n );\n const humanComments: FeedbackComment[] = [];\n const accepted: FeedbackSuggestion[] = [];\n const applied: FeedbackSuggestion[] = [];\n for (const comment of openComments) {\n const anchor = latestAnchor(comment);\n if (anchor === null) continue;\n humanComments.push(humanComment(comment, anchor));\n const suggestion = suggestionOf(comment);\n if (suggestion !== null) {\n if (isApplied(comment)) applied.push(suggestion);\n else accepted.push(suggestion);\n }\n }\n for (const comment of activeComments) {\n if (comment.author.kind === 'human' && isApplied(comment)) {\n const suggestion = suggestionOf(comment);\n if (suggestion !== null && !applied.some((item) => item.commentId === suggestion.commentId)) {\n applied.push(suggestion);\n }\n }\n }\n\n const json: FeedbackJson = {\n schemaVersion: 1,\n reviewId: review.id,\n round,\n verdict,\n title: review.title,\n scope: {\n baseSha: snapshot.scope.baseSha,\n headSha: snapshot.scope.headSha,\n label: snapshot.scope.label,\n },\n deliveryKey,\n findings: findings.map((finding) => findingItem(finding, decisions.get(finding.id))),\n dismissedFindings: dismissed.map((finding) => findingItem(finding, decisions.get(finding.id))),\n humanComments,\n appliedSuggestions: applied,\n acceptedSuggestions: accepted,\n questions: report?.questions ?? [],\n verification: report?.verification ?? [],\n resolved: {\n count: resolved.length,\n commentIds: resolved.map((comment) => comment.id),\n },\n };\n if (input.summary !== undefined) json.summary = input.summary;\n\n const lines: string[] = [\n `## \u0420\u0435\u0432\u044C\u044E \u00AB${review.title}\u00BB \u2014 ${verdictLabel(verdict)} (round ${round})`,\n `Review: /review/${review.id}?round=${round}`,\n `Scope: ${snapshot.scope.label} (${snapshot.scope.baseSha}..${snapshot.scope.headSha ?? 'worktree'})`,\n '',\n ];\n if (json.summary !== undefined) lines.push(json.summary, '');\n\n section(\n lines,\n '\u0417\u0430\u043C\u0435\u0447\u0430\u043D\u0438\u044F \u0430\u0433\u0435\u043D\u0442\u0430 (\u043A \u0438\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u044E)',\n findings.flatMap((finding) => findingLines(finding, decisions.get(finding.id))),\n );\n\n section(\n lines,\n '\u041E\u0442\u043A\u043B\u043E\u043D\u0435\u043D\u043E \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u043E\u043C (\u043D\u0435 \u043F\u043E\u0432\u0442\u043E\u0440\u044F\u0442\u044C)',\n dismissed.flatMap((finding) => {\n const decision = decisions.get(finding.id);\n if (decision?.note === undefined) return [];\n return [`- [${finding.file}:${finding.lineStart}] ${finding.title} \u2014 ${decision.note}`];\n }),\n );\n\n section(\n lines,\n '\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 (open)',\n humanComments.map((comment) => `- [${comment.path}:${comment.lineStart}] ${comment.body}`),\n );\n\n section(lines, '\u041F\u0440\u0438\u043D\u044F\u0442\u044B\u0435 suggested \u043F\u0440\u0430\u0432\u043A\u0438', [\n ...applied.map(\n (suggestion) =>\n `- [${suggestion.path}:${suggestion.lineStart}] \u043F\u0440\u0438\u043C\u0435\u043D\u0435\u043D\u043E \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u043E\u043C (\u043D\u0435 \u043F\u0440\u0438\u043C\u0435\u043D\u044F\u0442\u044C \u043F\u043E\u0432\u0442\u043E\u0440\u043D\u043E)`,\n ),\n ...accepted.flatMap((suggestion) => [\n `- [${suggestion.path}:${suggestion.lineStart}] \u043F\u0440\u0438\u043D\u044F\u0442\u043E, \u043D\u043E \u043D\u0435 \u043F\u0440\u0438\u043C\u0435\u043D\u0435\u043D\u043E (\u043F\u0430\u0442\u0447 \u043D\u0438\u0436\u0435)`,\n '```diff',\n ...suggestion.original.split('\\n').map((line) => `- ${line}`),\n ...suggestion.replacement.split('\\n').map((line) => `+ ${line}`),\n '```',\n ]),\n ]);\n\n section(\n lines,\n '\u0412\u043E\u043F\u0440\u043E\u0441\u044B \u043A \u0442\u0435\u0431\u0435',\n (report?.questions ?? []).map(\n (question) => `- [${question.id}] ${question.question} \u2014 ${question.why}`,\n ),\n );\n\n if (resolved.length > 0) {\n section(\n lines,\n '\u0423\u0436\u0435 \u0438\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043E \u0432 \u044D\u0442\u043E\u043C \u0440\u0430\u0443\u043D\u0434\u0435',\n resolved.map((comment) => `- [${comment.id}] resolved`),\n );\n }\n\n lines.push(\n '### \u0418\u043D\u0441\u0442\u0440\u0443\u043A\u0446\u0438\u044F',\n '\u041F\u0440\u0430\u0432\u044C \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0435\u0440\u0435\u0447\u0438\u0441\u043B\u0435\u043D\u043D\u043E\u0435, \u043D\u0435 \u043F\u0435\u0440\u0435\u043F\u0438\u0441\u044B\u0432\u0430\u0439 \u043D\u0435\u0441\u0432\u044F\u0437\u0430\u043D\u043D\u044B\u0439 \u043A\u043E\u0434, \u043F\u0440\u043E\u0433\u043E\u043D\u0438 \u0442\u0435\u0441\u0442\u044B,',\n '\u0437\u0430\u0442\u0435\u043C \u0432\u044B\u0437\u043E\u0432\u0438 review_refresh(reviewId), \u043F\u043E\u0441\u043C\u043E\u0442\u0440\u0438 \u043E\u0442\u043A\u0440\u044B\u0442\u044B\u0435 \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 \u0447\u0435\u0440\u0435\u0437',\n 'review_comments_list(reviewId) \u0438 \u0437\u0430\u043A\u0440\u043E\u0439 \u0438\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043D\u044B\u0435 review_resolve_comment(reviewId, commentId).',\n '\u0415\u0441\u043B\u0438 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u043F\u043E\u0432\u0442\u043E\u0440\u043D\u043E\u0435 \u2014 \u043D\u0435 \u043F\u0440\u0438\u043C\u0435\u043D\u044F\u0439 \u043F\u0440\u0430\u0432\u043A\u0438 \u0434\u0432\u0430\u0436\u0434\u044B.',\n );\n\n let markdown = lines.join('\\n');\n if (Buffer.byteLength(markdown, 'utf8') > FEEDBACK_BYTE_LIMIT) {\n const notice = `\\n\\n\u2026 (feedback truncated at ${FEEDBACK_BYTE_LIMIT} bytes; see [review](/review/${review.id}?round=${round}))`;\n const room = FEEDBACK_BYTE_LIMIT - Buffer.byteLength(notice, 'utf8');\n markdown = `${truncateUtf8(markdown, room)}${notice}`;\n }\n\n return { markdown, json: capFeedbackJson(json), deliveryKey };\n}\n", "import { createHash } from 'node:crypto';\nimport { createId } from '../review/ids.js';\nimport { ReviewNotFoundError } from '../review/store.js';\nimport type { GcResult } from '../review/store.js';\nimport { ReviewLifecycleError } from '../review/lifecycle.js';\nimport { createEvent } from '../review/events.js';\nimport type { ReviewEvent } from '../review/events.js';\nimport type {\n AddCommentInput,\n CommentState,\n FindingDecision,\n ReviewId,\n ReviewState,\n ReviewSummary,\n Round,\n RoundNo,\n SubmissionRecord,\n} from '../review/types.js';\nimport type { DiffScope, Snapshot } from '../types.js';\nimport { manifestFromSnapshot } from '../diff/manifest.js';\nimport { CommandReviewer } from '../reviewer/command.js';\nimport { FakeReviewer } from '../reviewer/fake.js';\nimport { ReviewerError } from '../reviewer/types.js';\nimport type { IdPrefix } from '../review/ids.js';\nimport type {\n AgentReport,\n ReviewerBackend,\n ReviewerConfig,\n ReviewerJob,\n ReviewerReport,\n} from '../reviewer/types.js';\nimport { validateReport, ReportValidationError } from '../reviewer/validate.js';\nimport { isFinalReviewReport } from '../review/final.js';\nimport { buildFeedback } from './feedback.js';\nimport { ReviewError } from './types.js';\nimport type {\n BulkFindingDecisionInput,\n BulkFindingDecisionView,\n CallContext,\n TransferAcceptedFindingsView,\n CommentEditInput,\n CommentView,\n FindingDecisionInput,\n FindingDecisionView,\n Page,\n ReviewFilter,\n ReviewServiceImplDeps,\n ReviewService,\n ReviewUpdateInput,\n ReviewView,\n ServiceCreateInput,\n ServiceSnapshotView,\n SubmissionView,\n SubmitInput,\n SuggestionActionInput,\n FixStatusInput,\n RefreshInput,\n LatestFeedbackView,\n} from './types.js';\n\nconst IDEMPOTENCY_LIMIT = 1000;\nconst MAX_BULK_FINDING_IDS = 1000;\nconst VERDICTS = new Set(['approve', 'request-changes', 'comment']);\n\nfunction normalizeBulkFindingIds(ids: unknown, reviewId: ReviewId): Set<string> {\n if (!Array.isArray(ids)) {\n throw new ReviewError('validation', 'findingIds must be an array', { id: reviewId });\n }\n if (ids.length === 0) {\n throw new ReviewError('validation', 'findingIds must not be empty', { id: reviewId });\n }\n if (ids.length > MAX_BULK_FINDING_IDS) {\n throw new ReviewError(\n 'validation',\n `findingIds must contain at most ${MAX_BULK_FINDING_IDS} entries`,\n { id: reviewId },\n );\n }\n const selected = new Set<string>();\n for (const findingId of ids) {\n if (typeof findingId !== 'string' || findingId.trim() === '') {\n throw new ReviewError('validation', 'findingIds must contain non-empty strings', {\n id: reviewId,\n });\n }\n selected.add(findingId);\n }\n return selected;\n}\n\nfunction bulkSelectionKey(selected: Set<string> | null): string {\n if (selected === null) return 'all';\n return createHash('sha256')\n .update([...selected].sort().join('\\u0000'))\n .digest('hex');\n}\nconst COMMENT_STATES = new Set<CommentState>(['open', 'resolved', 'dismissed']);\n\nfunction clone<T>(value: T): T {\n return structuredClone(value);\n}\n\nfunction agentIsActive(review: ReviewState): boolean {\n return review.agent?.status === 'queued' || review.agent?.status === 'running';\n}\n\nfunction scopeFromSnapshot(snapshot: Snapshot): DiffScope {\n const scope = snapshot.scope;\n if (scope.kind === 'worktree') return { kind: 'worktree', baseRef: scope.baseRef ?? 'HEAD' };\n if (scope.kind === 'commit') {\n return { kind: 'commit', sha: scope.headSha ?? scope.baseSha };\n }\n if (scope.kind === 'commits') {\n return { kind: 'commits', shas: scope.shas ?? [] };\n }\n return {\n kind: 'range',\n baseRef: scope.baseSha,\n headRef: scope.headRef ?? scope.headSha ?? 'HEAD',\n };\n}\n\nfunction scopeKey(scope: DiffScope): string {\n if (scope.kind === 'range') {\n return `range:${scope.baseRef}\\u0000${scope.headRef}\\u0000${scope.twoDot === true}`;\n }\n if (scope.kind === 'worktree') return `worktree:${scope.baseRef}`;\n if (scope.kind === 'commit') return `commit:${scope.sha}`;\n return `commits:${scope.shas.join('\\u0000')}`;\n}\n\nfunction assertContext(ctx: CallContext): void {\n if (ctx === undefined || ctx.actor === undefined) {\n throw new ReviewError('validation', 'CallContext with an actor is required');\n }\n}\n\nfunction validateInitiator(value: ServiceCreateInput['initiator']): void {\n if (value === undefined) return;\n if (typeof value !== 'object' || value === null) {\n throw new ReviewError('validation', 'initiator must be an object');\n }\n if (typeof value.harness !== 'string' || value.harness.trim() === '') {\n throw new ReviewError('validation', 'initiator.harness must be a non-empty string');\n }\n if (typeof value.sessionId !== 'string' || value.sessionId.trim() === '') {\n throw new ReviewError('validation', 'initiator.sessionId must be a non-empty string');\n }\n for (const field of ['cwd', 'agentPreset'] as const) {\n const fieldValue = value[field];\n if (fieldValue !== undefined && (typeof fieldValue !== 'string' || fieldValue.trim() === '')) {\n throw new ReviewError('validation', `initiator.${field} must be a non-empty string`);\n }\n }\n}\n\nfunction validateReviewer(config: ReviewerConfig): void {\n if (!['fake', 'command', 'none', 'worker'].includes(config.backend)) {\n throw new ReviewError('validation', `unknown reviewer backend: ${config.backend}`);\n }\n if (config.backend === 'command') {\n if (!Array.isArray(config.command) || config.command.length === 0) {\n throw new ReviewError('validation', 'command reviewer requires a non-empty argv array');\n }\n if (config.command.some((part) => typeof part !== 'string' || part === '')) {\n throw new ReviewError(\n 'validation',\n 'command reviewer argv entries must be non-empty strings',\n );\n }\n }\n}\n\nfunction mapLifecycleCode(code: ReviewLifecycleError['code']): ReviewError['code'] {\n switch (code) {\n case 'not-found':\n case 'comment-not-found':\n case 'finding-not-found':\n return 'not-found';\n case 'closed':\n case 'duplicate-round':\n case 'round-order':\n return 'conflict';\n case 'no-rounds':\n case 'snapshot-mismatch':\n case 'invalid-input':\n return 'validation';\n }\n}\n\n/**\n * Application service for reviews. Transports map requests to these methods;\n * every mutation is serialized by the store and idempotent by request id.\n */\nexport class ReviewServiceImpl implements ReviewService {\n private readonly lifecycle: ReviewServiceImplDeps['lifecycle'];\n private readonly store: ReviewServiceImplDeps['store'];\n private readonly snapshots: ReviewServiceImplDeps['snapshots'];\n private readonly now: () => Date;\n private readonly newId: (prefix: IdPrefix) => string;\n private readonly backendFactory?: ReviewServiceImplDeps['backendFactory'];\n private readonly runGit?: ReviewServiceImplDeps['runGit'];\n private readonly idempotencyLimit: number;\n private readonly results = new Map<string, unknown>();\n private readonly inflight = new Map<string, Promise<unknown>>();\n private readonly running = new Set<ReviewId>();\n private readonly active = new Map<\n ReviewId,\n { controller: AbortController; backend?: ReviewerBackend }\n >();\n\n constructor(deps: ReviewServiceImplDeps) {\n this.lifecycle = deps.lifecycle;\n this.store = deps.store;\n this.snapshots = deps.snapshots;\n this.now = deps.now ?? (() => new Date());\n this.newId = deps.newId ?? ((prefix) => createId(prefix, this.now));\n this.backendFactory = deps.backendFactory;\n this.runGit = deps.runGit;\n this.idempotencyLimit = deps.idempotencyLimit ?? IDEMPOTENCY_LIMIT;\n }\n\n async create(input: ServiceCreateInput, ctx: CallContext): Promise<ReviewView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (typeof input.title !== 'string' || input.title.trim() === '') {\n throw new ReviewError('validation', 'title must be non-empty');\n }\n if (typeof input.repoRoot !== 'string' || input.repoRoot.trim() === '') {\n throw new ReviewError('validation', 'repoRoot must be non-empty');\n }\n if (typeof input.scope !== 'object' || input.scope === null) {\n throw new ReviewError('validation', 'scope is required');\n }\n const reviewer = input.reviewer ?? { backend: 'none' as const };\n validateReviewer(reviewer);\n validateInitiator(input.initiator);\n\n let snapshot: Snapshot;\n try {\n snapshot = await this.snapshots.build({ repoRoot: input.repoRoot, scope: input.scope });\n } catch (error) {\n throw this.translate(error);\n }\n\n let state: ReviewState;\n try {\n state = await this.lifecycle.create({\n title: input.title,\n repoRoot: input.repoRoot,\n actor: ctx.actor,\n reviewer,\n ...(input.initiator === undefined ? {} : { initiator: input.initiator }),\n });\n await this.lifecycle.addRound(state.id, snapshot, ctx.actor);\n } catch (error) {\n throw this.translate(error);\n }\n return await this.get(state.id);\n },\n 'reviews.create',\n ctx.requestId,\n );\n }\n\n async updateReview(\n id: ReviewId,\n input: ReviewUpdateInput,\n ctx: CallContext,\n ): Promise<ReviewView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (\n input.title === undefined &&\n input.reviewer === undefined &&\n input.scope === undefined\n ) {\n throw new ReviewError('validation', 'review update is empty');\n }\n if (input.title !== undefined && typeof input.title !== 'string') {\n throw new ReviewError('validation', 'title must be a string');\n }\n if (input.title !== undefined && input.title.trim() === '') {\n throw new ReviewError('validation', 'title must be non-empty');\n }\n if (input.reviewer !== undefined) validateReviewer(input.reviewer);\n const review = await this.requireReview(id);\n if (review.status === 'closed') {\n throw new ReviewError('conflict', `review is closed: ${id}`, { id });\n }\n\n let snapshot: Snapshot | undefined;\n if (input.scope !== undefined) {\n if (this.running.has(id) || agentIsActive(review)) {\n throw new ReviewError('agent-busy', `a reviewer is active for ${id}`, { id });\n }\n const latest = await this.latestSnapshotOrThrow(review);\n if (scopeKey(input.scope) !== scopeKey(scopeFromSnapshot(latest))) {\n try {\n snapshot = await this.snapshots.build({\n repoRoot: review.repoRoot,\n scope: input.scope,\n });\n } catch (error) {\n throw this.translate(error);\n }\n }\n }\n\n if (input.title !== undefined || input.reviewer !== undefined) {\n try {\n await this.lifecycle.updateReview(\n id,\n {\n ...(input.title === undefined ? {} : { title: input.title }),\n ...(input.reviewer === undefined ? {} : { reviewer: input.reviewer }),\n },\n ctx.actor,\n );\n } catch (error) {\n throw this.translate(error);\n }\n }\n if (snapshot !== undefined) {\n try {\n await this.lifecycle.refresh(id, snapshot, ctx.actor);\n } catch (error) {\n throw this.translate(error);\n }\n }\n return await this.get(id);\n },\n `review.update:${id}`,\n ctx.requestId,\n );\n }\n\n async deleteReview(id: ReviewId, ctx: CallContext, reason?: string): Promise<void> {\n assertContext(ctx);\n await this.idempotent(\n async () => {\n let review: ReviewState;\n try {\n review = await this.lifecycle.get(id);\n } catch (error) {\n throw this.translate(error);\n }\n if (review.deletedAt !== undefined) return;\n const active = this.active.get(id);\n active?.controller.abort();\n active?.backend?.cancel?.();\n try {\n await this.lifecycle.deleteReview(id, ctx.actor, reason);\n } catch (error) {\n throw this.translate(error);\n }\n },\n `review.delete:${id}`,\n ctx.requestId,\n );\n }\n\n async get(id: ReviewId): Promise<ReviewView> {\n let review: ReviewState;\n try {\n review = await this.lifecycle.get(id);\n } catch (error) {\n throw this.translate(error);\n }\n if (review.deletedAt !== undefined) {\n throw new ReviewError('not-found', `review not found: ${id}`, { id });\n }\n const latestSnapshot = await this.readLatestSnapshot(review);\n return {\n review,\n latestSnapshot,\n report: review.report ?? null,\n };\n }\n\n async list(filter: ReviewFilter = {}): Promise<Page<ReviewSummary>> {\n const limit = Math.min(Math.max(Math.trunc(filter.limit ?? 50), 1), 100);\n const offset = Math.max(Math.trunc(filter.offset ?? 0), 0);\n let items: ReviewSummary[];\n try {\n items = await this.lifecycle.list();\n } catch (error) {\n throw this.translate(error);\n }\n if (filter.status !== undefined) {\n items = items.filter((item) => item.status === filter.status);\n }\n return {\n items: items.slice(offset, offset + limit),\n total: items.length,\n limit,\n offset,\n };\n }\n\n async snapshot(id: ReviewId, round: RoundNo, file?: string): Promise<ServiceSnapshotView> {\n const review = await this.requireReview(id);\n const target = review.rounds.find((item) => item.no === round);\n if (target === undefined) {\n throw new ReviewError('not-found', `round ${round} not found for ${id}`, { id, round });\n }\n let snapshot: Snapshot;\n try {\n snapshot = await this.store.readSnapshot(target.snapshotId);\n } catch (error) {\n throw this.translate(error);\n }\n if (file !== undefined) {\n const selected = snapshot.files.find((item) => item.path === file);\n if (selected === undefined) {\n throw new ReviewError('not-found', `file not found in round ${round}: ${file}`, {\n id,\n round,\n file,\n });\n }\n // The file query bounds the rendered view, not the manifest or its totals.\n snapshot = { ...snapshot, files: [clone(selected)] };\n }\n return { snapshot, round, ...(file === undefined ? {} : { file }) };\n }\n\n async addComment(id: ReviewId, input: AddCommentInput, ctx: CallContext): Promise<CommentView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (typeof input.body !== 'string' || input.body.trim() === '') {\n throw new ReviewError('validation', 'comment body must be non-empty');\n }\n try {\n const comment = await this.lifecycle.addComment(id, input, ctx.actor);\n return { comment };\n } catch (error) {\n throw this.translate(error);\n }\n },\n `comment.add:${id}`,\n ctx.requestId,\n );\n }\n\n async editComment(\n id: ReviewId,\n commentId: string,\n input: CommentEditInput,\n ctx: CallContext,\n ): Promise<CommentView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (typeof input.body !== 'string' || input.body.trim() === '') {\n throw new ReviewError('validation', 'comment body must be non-empty');\n }\n try {\n const comment = await this.lifecycle.editComment(id, commentId, input.body, ctx.actor);\n return { comment };\n } catch (error) {\n throw this.translate(error);\n }\n },\n `comment.edit:${id}:${commentId}`,\n ctx.requestId,\n );\n }\n\n async deleteComment(id: ReviewId, commentId: string, ctx: CallContext): Promise<CommentView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n try {\n const comment = await this.lifecycle.deleteComment(id, commentId, ctx.actor);\n return { comment };\n } catch (error) {\n throw this.translate(error);\n }\n },\n `comment.delete:${id}:${commentId}`,\n ctx.requestId,\n );\n }\n\n async reply(\n id: ReviewId,\n commentId: string,\n input: { body: string },\n ctx: CallContext,\n ): Promise<CommentView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (typeof input.body !== 'string' || input.body.trim() === '') {\n throw new ReviewError('validation', 'reply body must be non-empty');\n }\n try {\n const comment = await this.lifecycle.reply(id, commentId, input.body, ctx.actor);\n return { comment };\n } catch (error) {\n throw this.translate(error);\n }\n },\n `comment.reply:${id}:${commentId}`,\n ctx.requestId,\n );\n }\n\n async setCommentState(\n id: ReviewId,\n commentId: string,\n state: CommentState,\n ctx: CallContext,\n ): Promise<CommentView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (!COMMENT_STATES.has(state)) {\n throw new ReviewError('validation', `unknown comment state: ${String(state)}`);\n }\n try {\n const comment = await this.lifecycle.setCommentState(id, commentId, state, ctx.actor);\n return { comment };\n } catch (error) {\n throw this.translate(error);\n }\n },\n `comment.state:${id}:${commentId}`,\n ctx.requestId,\n );\n }\n\n async decideFinding(\n id: ReviewId,\n findingId: string,\n input: FindingDecisionInput,\n ctx: CallContext,\n ): Promise<FindingDecisionView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n try {\n const decision = await this.lifecycle.decideFinding(id, findingId, input, ctx.actor);\n return { decision };\n } catch (error) {\n throw this.translate(error);\n }\n },\n `finding.decision:${id}:${findingId}`,\n ctx.requestId,\n );\n }\n\n async decideFindings(\n id: ReviewId,\n input: BulkFindingDecisionInput,\n ctx: CallContext,\n ): Promise<BulkFindingDecisionView> {\n assertContext(ctx);\n const selected =\n input.findingIds === undefined ? null : normalizeBulkFindingIds(input.findingIds, id);\n return await this.idempotent(\n async () => {\n if (input.state !== 'accepted' && input.state !== 'dismissed') {\n throw new ReviewError('validation', `unknown finding decision: ${String(input.state)}`, {\n id,\n });\n }\n\n let review: ReviewState;\n try {\n review = await this.lifecycle.get(id);\n } catch (error) {\n throw this.translate(error);\n }\n if (review.deletedAt !== undefined) {\n throw new ReviewError('not-found', `review not found: ${id}`, { id });\n }\n if (review.status === 'closed') {\n throw new ReviewError('conflict', `review is closed: ${id}`, { id });\n }\n\n const latestRound = review.rounds.at(-1);\n const report = review.report;\n if (report === undefined || latestRound === undefined) {\n throw new ReviewError('validation', `review has no reviewer report: ${id}`, { id });\n }\n if (report.round !== latestRound.no) {\n throw new ReviewError(\n 'validation',\n `reviewer report is from round ${report.round}, latest is ${latestRound.no}`,\n { id },\n );\n }\n if (!isFinalReviewReport(review)) {\n throw new ReviewError('validation', `reviewer report is not final: ${id}`, { id });\n }\n\n const decided = new Set(\n (review.findingDecisions ?? [])\n .filter((decision) => decision.round === report.round)\n .map((decision) => decision.findingId),\n );\n const targets = report.findings.filter(\n (finding) =>\n finding.kind !== 'praise' &&\n !decided.has(finding.id) &&\n (selected === null || selected.has(finding.id)),\n );\n const decisions: FindingDecision[] = [];\n try {\n for (const finding of targets) {\n const decision = await this.lifecycle.decideFindingIfUndecided(\n id,\n finding.id,\n { state: input.state },\n ctx.actor,\n );\n if (decision !== null) decisions.push(decision);\n }\n } catch (error) {\n throw this.translate(error);\n }\n\n return {\n decisions,\n skipped:\n selected === null\n ? report.findings.length - decisions.length\n : selected.size - decisions.length,\n };\n },\n `finding.decisions:${id}:${input.state}:${bulkSelectionKey(selected)}`,\n ctx.requestId,\n );\n }\n\n async transferAcceptedFindings(\n id: ReviewId,\n ctx: CallContext,\n ): Promise<TransferAcceptedFindingsView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n try {\n const comments = await this.lifecycle.transferAcceptedFindings(id, ctx.actor);\n return { transferred: comments.length };\n } catch (error) {\n throw this.translate(error);\n }\n },\n `finding.transfer:${id}`,\n ctx.requestId,\n );\n }\n\n async events(id: ReviewId, after = 0): Promise<ReviewEvent[]> {\n if (!Number.isInteger(after) || after < 0) {\n throw new ReviewError('validation', 'after must be a non-negative integer');\n }\n // The event log outlives soft deletion: the SSE hub replays the delete event,\n // and GET /api/events guards visibility at the route level. latestFeedback()\n // still calls requireReview() to hide deleted reviews.\n try {\n return await this.store.events(id, after);\n } catch (error) {\n throw this.translate(error);\n }\n }\n\n async suggestionAction(\n id: ReviewId,\n commentId: string,\n action: SuggestionActionInput['action'],\n ctx: CallContext,\n ): Promise<CommentView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (!['accept', 'decline', 'apply'].includes(action)) {\n throw new ReviewError('validation', `unknown suggestion action: ${String(action)}`);\n }\n const review = await this.requireReview(id);\n if (review.status === 'closed') {\n throw new ReviewError('conflict', `review is closed: ${id}`, { id });\n }\n const comment = review.comments.find((candidate) => candidate.id === commentId);\n if (comment === undefined) {\n throw new ReviewError('not-found', `unknown comment: ${commentId}`, { id, commentId });\n }\n if (comment.suggestion === undefined) {\n throw new ReviewError('validation', `comment has no suggestion: ${commentId}`, {\n id,\n commentId,\n });\n }\n if (action === 'apply') {\n const round = review.rounds.at(-1);\n if (round === undefined)\n throw new ReviewError('validation', `review has no rounds: ${id}`);\n try {\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'suggestion/applied',\n actor: ctx.actor,\n data: { commentId, round: round.no },\n now: this.now,\n }),\n );\n } catch (error) {\n throw this.translate(error);\n }\n } else {\n const state = action === 'accept' ? 'accepted' : 'declined';\n try {\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'suggestion/state',\n actor: ctx.actor,\n data: { commentId, state },\n now: this.now,\n }),\n );\n } catch (error) {\n throw this.translate(error);\n }\n }\n return await this.getComment(id, commentId);\n },\n `comment.suggestion:${id}:${commentId}`,\n ctx.requestId,\n );\n }\n\n async refresh(id: ReviewId, input: RefreshInput, ctx: CallContext): Promise<ReviewView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n const review = await this.requireReview(id);\n if (review.status === 'closed') {\n throw new ReviewError('conflict', `review is closed: ${id}`, { id });\n }\n if (this.running.has(id) || agentIsActive(review)) {\n throw new ReviewError('agent-busy', `a reviewer is active for ${id}`, { id });\n }\n const latest = await this.latestSnapshotOrThrow(review);\n const scope = input.scope ?? scopeFromSnapshot(latest);\n let snapshot: Snapshot;\n try {\n snapshot = await this.snapshots.build({ repoRoot: review.repoRoot, scope });\n } catch (error) {\n throw this.translate(error);\n }\n try {\n await this.lifecycle.refresh(id, snapshot, ctx.actor);\n } catch (error) {\n throw this.translate(error);\n }\n return await this.get(id);\n },\n `review.refresh:${id}`,\n ctx.requestId,\n );\n }\n\n async close(id: ReviewId, verdict: 'approved' | 'closed', ctx: CallContext): Promise<ReviewView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (verdict !== 'approved' && verdict !== 'closed') {\n throw new ReviewError('validation', `unknown close verdict: ${String(verdict)}`);\n }\n try {\n await this.lifecycle.close(id, verdict, ctx.actor);\n } catch (error) {\n throw this.translate(error);\n }\n return await this.get(id);\n },\n `review.close:${id}`,\n ctx.requestId,\n );\n }\n\n async claimFixStatus(id: ReviewId, input: FixStatusInput, ctx: CallContext): Promise<void> {\n assertContext(ctx);\n await this.idempotent(\n async () => {\n if (!Array.isArray(input.items) || input.items.length === 0) {\n throw new ReviewError('validation', 'items must be a non-empty array');\n }\n const review = await this.requireReview(id);\n if (review.status === 'closed') {\n throw new ReviewError('conflict', `review is closed: ${id}`, { id });\n }\n const known = new Set(review.comments.map((comment) => comment.id));\n const claims = input.items.map((item) => {\n if (!['fixed', 'not-fixed', 'unclear'].includes(item.status)) {\n throw new ReviewError('validation', `unknown fix status: ${String(item.status)}`);\n }\n if (!known.has(item.commentId)) {\n throw new ReviewError('not-found', `unknown comment: ${item.commentId}`, {\n id,\n commentId: item.commentId,\n });\n }\n if (item.evidence !== undefined && typeof item.evidence !== 'string') {\n throw new ReviewError('validation', 'evidence must be a string');\n }\n return {\n commentId: item.commentId,\n status: item.status,\n ...(item.evidence === undefined ? {} : { evidence: item.evidence }),\n by: ctx.actor,\n at: this.now().toISOString(),\n };\n });\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'fix/claim',\n actor: ctx.actor,\n data: { claims },\n now: this.now,\n }),\n );\n },\n `review.fix-status:${id}`,\n ctx.requestId,\n );\n }\n\n async latestFeedback(id: ReviewId): Promise<LatestFeedbackView | null> {\n await this.requireReview(id);\n const events = await this.events(id, 0);\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index];\n if (event?.type !== 'review/submitted') continue;\n return {\n submission: event.data.submission,\n feedback: event.data.feedback as LatestFeedbackView['feedback'],\n };\n }\n return null;\n }\n\n async gc(olderThanDays: number): Promise<GcResult> {\n const result = await this.store.gc(olderThanDays, this.now());\n this.results.clear();\n return result;\n }\n\n async submit(id: ReviewId, input: SubmitInput, ctx: CallContext): Promise<SubmissionView> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (!VERDICTS.has(input.verdict)) {\n throw new ReviewError('validation', `unknown verdict: ${String(input.verdict)}`);\n }\n if (input.summary !== undefined && typeof input.summary !== 'string') {\n throw new ReviewError('validation', 'summary must be a string');\n }\n const review = await this.requireReview(id);\n if (review.status === 'closed') {\n throw new ReviewError('conflict', `review is closed: ${id}`, { id });\n }\n const round = review.rounds.at(-1);\n if (round === undefined) {\n throw new ReviewError('validation', `review has no rounds: ${id}`, { id });\n }\n if ((review.submissions ?? []).some((submission) => submission.round === round.no)) {\n throw new ReviewError('conflict', `round ${round.no} was already submitted`, {\n id,\n round: round.no,\n });\n }\n let snapshot: Snapshot;\n try {\n snapshot = await this.store.readSnapshot(round.snapshotId);\n } catch (error) {\n throw this.translate(error);\n }\n const report =\n review.report !== undefined && review.report.round === round.no ? review.report : null;\n const submissionId = this.newId('sub');\n const deliveryKey = `${id}:${round.no}:${submissionId}`;\n const feedback = buildFeedback({\n review,\n snapshot,\n report,\n round: round.no,\n verdict: input.verdict,\n deliveryKey,\n ...(input.summary === undefined ? {} : { summary: input.summary }),\n ...(input.includeResolved === undefined\n ? {}\n : { includeResolved: input.includeResolved }),\n });\n const submission: SubmissionRecord = {\n submissionId,\n round: round.no,\n verdict: input.verdict,\n deliveryKey,\n createdAt: this.now().toISOString(),\n };\n try {\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'review/submitted',\n actor: ctx.actor,\n data: {\n submission,\n feedback: {\n markdown: feedback.markdown,\n json: feedback.json,\n deliveryKey,\n },\n },\n now: this.now,\n }),\n );\n } catch (error) {\n throw this.translate(error);\n }\n return {\n reviewId: id,\n round: round.no,\n verdict: input.verdict,\n feedback,\n deliveryKey,\n };\n },\n `review.submit:${id}`,\n ctx.requestId,\n );\n }\n\n async runReviewer(id: ReviewId, ctx: CallContext): Promise<AgentReport> {\n assertContext(ctx);\n return await this.idempotent(\n async () => {\n if (this.running.has(id)) {\n throw new ReviewError('agent-busy', `a reviewer is already running for ${id}`, { id });\n }\n this.running.add(id);\n try {\n return await this.runReviewerOnce(id, ctx);\n } finally {\n this.running.delete(id);\n }\n },\n `review.run:${id}`,\n ctx.requestId,\n );\n }\n\n async cancelAgent(id: ReviewId, ctx: CallContext): Promise<void> {\n assertContext(ctx);\n const active = this.active.get(id);\n if (active === undefined) {\n const review = await this.requireReview(id);\n if (agentIsActive(review)) {\n throw new ReviewError('conflict', `reviewer is not owned by this service instance`, {\n id,\n });\n }\n return;\n }\n active.controller.abort();\n active.backend?.cancel?.();\n }\n\n private async runReviewerOnce(id: ReviewId, ctx: CallContext): Promise<AgentReport> {\n const review = await this.requireReview(id);\n if (review.status === 'closed') {\n throw new ReviewError('stale-review', `review is closed: ${id}`, { id });\n }\n if (agentIsActive(review)) {\n throw new ReviewError('agent-busy', `a reviewer is already running for ${id}`, { id });\n }\n const round = review.rounds.at(-1);\n if (round === undefined) {\n throw new ReviewError('validation', `review has no rounds: ${id}`, { id });\n }\n let snapshot: Snapshot;\n try {\n snapshot = await this.store.readSnapshot(round.snapshotId);\n } catch (error) {\n throw this.translate(error);\n }\n\n const config: ReviewerConfig = review.reviewer ?? { backend: 'none' };\n const job: ReviewerJob = {\n id: this.newId('job'),\n reviewId: id,\n round: round.no,\n kind: review.report === undefined ? 'initial' : 'verify',\n repoRoot: review.repoRoot,\n prompt: this.buildPrompt(review, round, snapshot),\n snapshot,\n manifest: manifestFromSnapshot(snapshot),\n };\n const controller = new AbortController();\n this.active.set(id, { controller });\n\n try {\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'agent/started',\n actor: ctx.actor,\n data: { jobId: job.id, round: round.no, backend: config.backend },\n now: this.now,\n }),\n );\n\n let raw: ReviewerReport;\n if (config.backend === 'none') {\n raw = {\n schemaVersion: 1,\n summary: 'Reviewer backend is none; review skipped.',\n riskLevel: 'low',\n findings: [],\n questions: [],\n tests: { ran: false, commands: [] },\n verification: [],\n };\n } else {\n let backend: ReviewerBackend;\n try {\n backend = this.backendFor(config);\n } catch (error) {\n throw this.translate(error);\n }\n this.active.set(id, { controller, backend });\n if (controller.signal.aborted) {\n throw new ReviewError('conflict', `reviewer was cancelled for ${id}`, { id });\n }\n raw = await backend.run(\n job,\n async (finding) => {\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'agent/finding',\n actor: ctx.actor,\n data: { finding, round: round.no },\n now: this.now,\n }),\n );\n },\n controller.signal,\n );\n }\n\n if (controller.signal.aborted) {\n throw new ReviewError('conflict', `reviewer was cancelled for ${id}`, { id });\n }\n const validation = validateReport(raw, { snapshot });\n const warnings = [...validation.warnings];\n if (raw.dirtyWorktree === true) warnings.push('dirty-worktree');\n const report: AgentReport = {\n ...validation.report,\n reviewId: id,\n round: round.no,\n backend: config.backend,\n rejected: validation.rejected,\n warnings,\n ...(raw.dirtyWorktree === true ? { dirtyWorktree: true } : {}),\n ...(config.backend === 'none' ? { skipped: true } : {}),\n };\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'agent/report',\n actor: ctx.actor,\n data: { report },\n now: this.now,\n }),\n );\n return report;\n } catch (error) {\n const reviewError =\n error instanceof ReviewError\n ? error\n : controller.signal.aborted\n ? new ReviewError('conflict', `reviewer was cancelled for ${id}`, { id })\n : new ReviewError('internal', (error as Error).message, { id });\n try {\n await this.store.append(\n id,\n createEvent({\n reviewId: id,\n type: 'agent/failed',\n actor: ctx.actor,\n data: { code: reviewError.code, message: reviewError.message },\n now: this.now,\n }),\n );\n } catch {\n // The original failure is more useful than a secondary log failure.\n }\n throw reviewError;\n } finally {\n this.active.delete(id);\n }\n }\n\n private backendFor(config: ReviewerConfig): ReviewerBackend {\n if (this.backendFactory !== undefined) return this.backendFactory(config);\n if (config.backend === 'fake') return new FakeReviewer();\n if (config.backend === 'command') {\n return new CommandReviewer({\n command: config.command ?? [],\n ...(this.runGit === undefined ? {} : { runGit: this.runGit }),\n ...(config.timeoutMs === undefined ? {} : { timeoutMs: config.timeoutMs }),\n });\n }\n throw new ReviewError('validation', `reviewer backend cannot run: ${config.backend}`);\n }\n\n private buildPrompt(review: ReviewState, round: Round, snapshot: Snapshot): string {\n const files = snapshot.files\n .map((file) => `- ${file.status} ${file.path} (+${file.added}/-${file.deleted})`)\n .join('\\n');\n return [\n `# Independent code review: ${review.title}`,\n '',\n `Review: ${review.id}`,\n `Round: ${round.no}`,\n `Repository: ${review.repoRoot}`,\n `Scope: ${snapshot.scope.label} (${snapshot.scope.baseSha}..${snapshot.scope.headSha ?? 'worktree'})`,\n '',\n 'You are a read-only reviewer. Do not modify files.',\n 'Review the changes and surrounding code, run tests if useful, and report only actionable',\n 'findings with file/line anchors and evidence. Return strict JSON (schemaVersion 1), or',\n 'write it to output.json / a fenced json block.',\n '',\n '## Files',\n files,\n '',\n '## Instructions',\n '- Blockers and major issues first; no style nitpicks without impact.',\n '- Every finding needs file, lineStart/lineEnd, title, rationale and evidence.',\n '- Put product/intent questions in questions[], not findings[].',\n '- Verification entries use the supplied comment ids when this is a verify round.',\n ].join('\\n');\n }\n\n private async readLatestSnapshot(review: ReviewState): Promise<Snapshot | null> {\n const round = review.rounds.at(-1);\n if (round === undefined) return null;\n try {\n return await this.store.readSnapshot(round.snapshotId);\n } catch (error) {\n throw this.translate(error);\n }\n }\n\n private async getComment(id: ReviewId, commentId: string): Promise<CommentView> {\n const review = await this.requireReview(id);\n const comment = review.comments.find((candidate) => candidate.id === commentId);\n if (comment === undefined) {\n throw new ReviewError('not-found', `unknown comment: ${commentId}`, { id, commentId });\n }\n return { comment };\n }\n\n private async latestSnapshotOrThrow(review: ReviewState): Promise<Snapshot> {\n const round = review.rounds.at(-1);\n if (round === undefined) {\n throw new ReviewError('validation', `review has no rounds: ${review.id}`, { id: review.id });\n }\n try {\n return await this.store.readSnapshot(round.snapshotId);\n } catch (error) {\n throw this.translate(error);\n }\n }\n\n private async requireReview(id: ReviewId): Promise<ReviewState> {\n try {\n const review = await this.lifecycle.get(id);\n if (review.deletedAt !== undefined) {\n throw new ReviewError('not-found', `review not found: ${id}`, { id });\n }\n return review;\n } catch (error) {\n throw this.translate(error);\n }\n }\n\n private async idempotent<T>(\n operation: () => Promise<T>,\n scope: string,\n requestId?: string,\n ): Promise<T> {\n if (requestId === undefined || requestId === '') return await operation();\n // The request id is only unique per operation (route and review), so a\n // client retry on a different route must not reuse another response.\n const key = `${scope}\\u0000${requestId}`;\n if (this.results.has(key)) return clone(this.results.get(key) as T);\n const pending = this.inflight.get(key);\n if (pending !== undefined) return clone((await pending) as T);\n const run = operation();\n this.inflight.set(key, run);\n try {\n const result = await run;\n if (this.results.size >= this.idempotencyLimit) {\n const oldest = this.results.keys().next().value as string | undefined;\n if (oldest !== undefined) this.results.delete(oldest);\n }\n this.results.set(key, clone(result));\n return result;\n } finally {\n if (this.inflight.get(key) === run) this.inflight.delete(key);\n }\n }\n\n private translate(error: unknown): ReviewError {\n if (error instanceof ReviewError) return error;\n if (error instanceof ReviewLifecycleError) {\n return new ReviewError(mapLifecycleCode(error.code), error.message, {\n ...(error.reviewId === undefined ? {} : { reviewId: error.reviewId }),\n ...(error.commentId === undefined ? {} : { commentId: error.commentId }),\n });\n }\n if (error instanceof ReviewNotFoundError) {\n return new ReviewError('not-found', error.message, { reviewId: error.reviewId });\n }\n if (error instanceof ReviewerError || error instanceof ReportValidationError) {\n return new ReviewError('internal', error.message);\n }\n return new ReviewError('internal', (error as Error).message);\n }\n}\n", "export const CORE_VERSION = '0.3.0';\nexport { safeJoin, PathEscapeError } from './paths.js';\nexport { buildSnapshot } from './diff/snapshot.js';\nexport {\n buildReviewManifest,\n manifestFileFromDiff,\n manifestFromSnapshot,\n patchBytesFromHunks,\n reviewManifest,\n} from './diff/manifest.js';\nexport { readBlob } from './git/content.js';\nexport type { BlobRead } from './git/content.js';\nexport { DiffParseError, parseUnifiedDiff } from './diff/parse.js';\nexport { EMPTY_TREE_SHA, resolveDefaultBase, resolveScope, worktreeDigest } from './git/scope.js';\nexport type { ResolveScopeInput } from './git/scope.js';\nexport { GitError, runGit } from './git/run.js';\nexport type { GitErrorCode, GitResult, GitRunOptions } from './git/run.js';\nexport { resolveRepoRoot } from './git/repo.js';\nexport type {\n DiffHunk,\n DiffLine,\n DiffLineKind,\n DiffScope,\n FileDiff,\n FileStatus,\n ManifestFile,\n ManifestFileReason,\n ManifestTotals,\n ParsedFile,\n ResolvedScope,\n ReviewManifest,\n Snapshot,\n SnapshotOptions,\n} from './types.js';\nexport { createId, ID_LENGTHS, ReviewIdError } from './review/ids.js';\nexport type { IdPrefix, RandomBytes } from './review/ids.js';\nexport {\n createEvent,\n isActor,\n isReviewEvent,\n isReviewEventType,\n REVIEW_EVENT_TYPES,\n ReviewEventError,\n} from './review/events.js';\nexport type {\n AgentCoverageData,\n AgentShardData,\n AgentFailedData,\n AgentFindingData,\n AgentReportData,\n AgentStartedData,\n CommentAddedData,\n CommentAnchorData,\n CommentRepliedData,\n CommentStateData,\n CreateEventInput,\n FindingDecisionData,\n FixClaimData,\n SuggestionStateData,\n ReviewClosedData,\n ReviewCreatedData,\n ReviewEvent,\n ReviewEventBase,\n ReviewEventDataMap,\n ReviewEventErrorCode,\n ReviewEventType,\n ReviewSubmittedData,\n RoundCreatedData,\n SuggestionAppliedData,\n} from './review/events.js';\nexport type {\n Actor,\n ActorKind,\n AgentShardState,\n AgentState,\n AgentStatus,\n AddCommentInput,\n Anchor,\n AnchorPosition,\n AnchorState,\n Comment,\n CommentId,\n CommentState,\n Confidence,\n CoverageStatus,\n CoverageTotals,\n CreateReviewInput,\n FileCoverage,\n FindingDecision,\n FindingDecisionState,\n Outcome,\n OutcomeStatus,\n Reply,\n ReviewCoverage,\n ReviewId,\n ReviewState,\n ReviewStatus,\n ReviewSummary,\n Round,\n RoundNo,\n Side,\n SuggestionState,\n FixStatus,\n FixClaimRecord,\n Initiator,\n SubmissionRecord,\n Suggestion,\n} from './review/types.js';\nexport { AnchorError, captureAnchor, normalizeQuote, reanchor } from './review/anchors.js';\nexport type { AnchorErrorCode, CaptureAnchorInput, ReanchorOptions } from './review/anchors.js';\nexport {\n COVERAGE_STATUSES,\n coverageFromPrompt,\n initialCoverage,\n isCoverageComplete,\n promotePendingToLight,\n summarizeCoverage,\n} from './review/coverage.js';\nexport {\n buildModuleMap,\n buildReviewPlan,\n classifyFile,\n coverageFromPlan,\n DEFAULT_SHARD_LIMITS,\n isUserFacingDoc,\n} from './review/plan.js';\nexport type {\n FileKind,\n ModuleInfo,\n ModuleMap,\n ModuleRoot,\n PlanFile,\n ReviewPlan,\n ReviewShard,\n ReviewTier,\n ShardLimits,\n} from './review/plan.js';\nexport { aggregateShardReports, mergeShardReports } from './review/aggregate.js';\nexport type {\n AggregateShardReportsInput,\n AggregateShardReportsResult,\n MergeShardReportsInput,\n ShardReportInput,\n} from './review/aggregate.js';\nexport { deriveOutcome } from './review/outcomes.js';\nexport { isFinalReviewReport } from './review/final.js';\nexport { fold, ReviewFoldError } from './review/fold.js';\nexport { ReviewLifecycle, ReviewLifecycleError } from './review/lifecycle.js';\nexport type { RefreshResult, ReviewLifecycleErrorCode } from './review/lifecycle.js';\nexport {\n ReviewNotFoundError,\n ReviewStore,\n ReviewStoreCorruptionError,\n ReviewStoreLockedError,\n} from './review/store.js';\nexport type { GcResult } from './review/store.js';\nexport type { ReviewStoreOptions } from './review/store.js';\n\nexport { FakeReviewer } from './reviewer/fake.js';\nexport type { FakeReviewerOptions } from './reviewer/fake.js';\nexport { CommandReviewer } from './reviewer/command.js';\nexport type { CommandReviewerOptions } from './reviewer/command.js';\nexport {\n MAX_TEXT_BYTES,\n normalizeCode,\n ReportValidationError,\n validateFindingItem,\n validateReport,\n} from './reviewer/validate.js';\nexport type { FindingItemValidation } from './reviewer/validate.js';\nexport type {\n AgentReport,\n Finding,\n FindingCategory,\n FindingKind,\n FindingSeverity,\n FindingSink,\n GitStatusRunner,\n RejectedReportItem,\n RejectedReportKind,\n ReviewQuestion,\n ReviewSuggestion,\n ReviewerBackend,\n ReviewerBackendKind,\n ReviewerConfidence,\n ReviewerConfig,\n ReviewerErrorCode,\n ReviewerJob,\n ReviewerReport,\n RiskLevel,\n TestCommand,\n TestResult,\n TestSummary,\n ValidationResult,\n Verification,\n VerificationStatus,\n} from './reviewer/types.js';\nexport { ReviewerError } from './reviewer/types.js';\nexport { ReviewError } from './service/types.js';\nexport type {\n CallContext,\n CommentView,\n FeedbackComment,\n FeedbackFinding,\n FeedbackJson,\n FeedbackPackage,\n FeedbackSuggestion,\n BulkFindingDecisionInput,\n BulkFindingDecisionView,\n FindingDecisionInput,\n FindingDecisionView,\n Page,\n ReplyInput,\n ReviewErrorCode,\n ReviewFilter,\n ReviewService,\n ReviewServiceImplDeps,\n ReviewView,\n ServiceCreateInput,\n ServiceSnapshotView,\n SubmissionView,\n SuggestionActionInput,\n FixStatusInput,\n RefreshInput,\n LatestFeedbackView,\n SubmitInput,\n} from './service/types.js';\nexport { buildFeedback, FEEDBACK_BYTE_LIMIT } from './service/feedback.js';\nexport type { BuildFeedbackInput } from './service/feedback.js';\nexport { ReviewServiceImpl } from './service/service.js';\n"],
5
+ "mappings": "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",
6
6
  "names": ["relative", "lstat", "lstat", "resolve", "reject", "DEFAULT_MAX_BYTES", "lstat", "createHash", "lstat", "readlink", "realpath", "relative", "sep", "headSha", "createHash", "readlink", "realpath", "lstat", "stat", "relative", "sep", "status", "section", "status", "status", "lstat", "createHash", "createHash", "status", "INCOMPLETE_MANIFEST_WARNINGS", "policyReason", "status", "summary", "report", "shard", "status", "createHash", "randomBytes", "open", "readFile", "stat", "resolve", "isRecord", "isActor", "readFile", "status", "resolve", "open", "stat", "randomBytes", "entry", "findComment", "createHash", "round", "spawn", "open", "rm", "join", "open", "join", "rm", "resolve", "reject", "spawn", "isRecord", "findFile", "summary", "createHash", "createHash", "submission"]
7
7
  }