getgloss 0.8.0 → 0.8.2

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/index.ts","../../src/shared/paths.ts","../../package.json","../../src/cli/git.ts","../../src/shared/language.ts","../../src/shared/diff-parser.ts","../../src/shared/diff-stats.ts","../../src/cli/lifecycle.ts","../../src/shared/server-info.ts","../../src/shared/errors.ts","../../src/shared/json.ts","../../src/shared/types.ts","../../src/shared/validation.ts","../../src/cli/server-client.ts","../../src/server/store.ts","../../src/shared/comments.ts","../../src/shared/review-scope.ts","../../src/shared/markdown.ts","../../src/shared/reviews.ts","../../src/cli/status.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport openBrowser from 'open';\nimport { packageVersion } from '../shared/paths';\nimport type {\n DiffPayload,\n FeedbackBundle,\n ResolveResult,\n ReviewEvent,\n ReviewMeta,\n ServerInfo\n} from '../shared/types';\nimport { assertGitAvailable, captureDiff, getRepoRoot } from './git';\nimport {\n ensureServer,\n isServerResponsive,\n listGlossDaemonPids,\n readServerInfo,\n serverUrl,\n startServer,\n stopServer\n} from './lifecycle';\nimport { ServerClient } from './server-client';\nimport { listReviewsForStatus } from './status';\n\ninterface GlobalOptions {\n json?: boolean;\n noColor?: boolean;\n}\n\ntype DoctorCheck = { name: string; ok: boolean; detail?: string };\n\ntype CliJsonOutput =\n | ServerInfo\n | ReviewEvent\n | ResolveResult\n | { stopped: boolean; info: ServerInfo | null; stoppedPids?: number[] }\n | {\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n url: string;\n files: number;\n scope: DiffPayload['scope']['mode'];\n artifactDir: string;\n reused?: boolean;\n }\n | {\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n url: string;\n files: number;\n comments: number;\n feedbackPath: string;\n markdownPath: string;\n artifactDir: string;\n feedback: FeedbackBundle;\n reused?: boolean;\n }\n | { running: boolean; server: ServerInfo | null; reviews: ReviewMeta[] }\n | (ResolveResult & { commentId: string | null; summary: string | null })\n | (ResolveResult & { commentId: string | null; summary: string | null; turn: string | null })\n | { checks: DoctorCheck[] };\n\nfunction printJson(value: CliJsonOutput): void {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\nfunction printPlain(value: string): void {\n process.stdout.write(`${value}\\n`);\n}\n\nconst program = new Command();\n\nprogram\n .name('gloss')\n .description('Local browser-based diff review for coding-agent loops.')\n .version(packageVersion)\n .option('--json', 'print JSON for supported commands')\n .option('--no-color', 'disable color output');\n\nprogram\n .command('open')\n .description('Capture local changes and open them for review')\n .option('--base <ref>', 'explicit base git ref')\n .option('--review <reviewId>', 'append or resume a turn in an existing review')\n .option('--print-url', 'print review URL')\n .option('--no-open', 'do not open a browser')\n .option('--no-watch', 'return immediately after registering the review')\n .option('--timeout <seconds>', 'watch timeout in seconds', Number)\n .action(\n async (options: {\n base?: string;\n printUrl?: boolean;\n open?: boolean;\n review?: string;\n watch?: boolean;\n timeout?: number;\n }) => {\n const globals = program.opts<GlobalOptions>();\n let info = await ensureServer();\n let client = new ServerClient(serverUrl(info));\n const inheritedBase =\n options.review && !options.base\n ? await baseForExistingReview(client, options.review)\n : null;\n const diff = await captureDiff(options.base ?? inheritedBase ?? undefined);\n const created = options.review\n ? await client.appendReviewTurn(options.review, diff)\n : await client.createReview(diff);\n const meta = created.meta;\n const turn = created.turn ?? meta.turns?.find((summary) => summary.id === meta.activeTurnId);\n if (!turn) {\n throw new Error(`Review ${meta.id} has no active turn`);\n }\n const reused = 'reused' in created ? created.reused === true : false;\n let url = created.url;\n const shouldWatch = options.watch !== false;\n\n if (options.printUrl) {\n printPlain(url);\n }\n if (options.open !== false) {\n await openBrowser(url);\n }\n\n if (!shouldWatch) {\n const result = {\n reviewId: meta.id,\n turnId: turn.id,\n turnIndex: turn.index,\n url,\n files: diff.files.length,\n scope: diff.scope.mode,\n artifactDir: turn.artifactDir,\n reused\n };\n globals.json ? printJson(result) : printPlain(`Review ${meta.id}: ${url}`);\n return;\n }\n\n const watched = await watchReviewWithReconnect(\n meta.id,\n info,\n options.timeout,\n async (nextInfo) => {\n info = nextInfo;\n client = new ServerClient(serverUrl(info));\n url = `${serverUrl(info)}/review/${meta.id}`;\n if (options.printUrl) {\n printPlain(url);\n }\n if (options.open !== false) {\n await openBrowser(url);\n }\n }\n );\n info = watched.info;\n client = new ServerClient(serverUrl(info));\n const event = watched.event;\n if (event.type === 'review.cancelled') {\n process.exitCode = 2;\n globals.json ? printJson(event) : printPlain(`Review ${meta.id} cancelled`);\n return;\n }\n if (event.type !== 'review.submitted') {\n throw new Error(`Unexpected review event ${event.type}`);\n }\n\n const [feedback, submittedRecord] = await Promise.all([\n client.getFeedback(meta.id),\n client.getReview(meta.id)\n ]);\n const submittedTurn =\n submittedRecord.meta.turns?.find((summary) => summary.id === (event.turnId ?? turn.id)) ??\n turn;\n if (!submittedTurn.feedbackPath || !submittedTurn.markdownPath) {\n throw new Error(`Review ${meta.id} turn ${submittedTurn.index} is missing feedback paths`);\n }\n const result = {\n reviewId: meta.id,\n turnId: submittedTurn.id,\n turnIndex: submittedTurn.index,\n url,\n files: event.counts.files,\n comments: event.counts.comments,\n feedbackPath: submittedTurn.feedbackPath,\n markdownPath: submittedTurn.markdownPath,\n artifactDir: submittedTurn.artifactDir,\n feedback,\n reused\n };\n globals.json\n ? printJson(result)\n : printPlain(`Review ${meta.id} submitted with ${event.counts.comments} comments`);\n }\n );\n\nprogram\n .command('watch')\n .argument('<reviewId>', 'review id')\n .description('Wait for review.submitted for an existing review')\n .option('--timeout <seconds>', 'watch timeout in seconds', Number)\n .action(async (reviewId: string, options: { timeout?: number }) => {\n const globals = program.opts<GlobalOptions>();\n const info = await ensureServer();\n const { event } = await watchReviewWithReconnect(\n reviewId,\n info,\n options.timeout,\n async () => undefined\n );\n globals.json ? printJson(event) : printPlain(`${event.type} ${event.reviewId}`);\n });\n\nprogram\n .command('start')\n .description('Start or reuse the background server')\n .option('--port <port>', 'port to bind', Number)\n .action(async (options: { port?: number }) => {\n const globals = program.opts<GlobalOptions>();\n const info = await startServer({ port: options.port });\n globals.json\n ? printJson(info)\n : printPlain(`Gloss server running at ${serverUrl(info)} (pid ${info.pid})`);\n });\n\nprogram\n .command('status')\n .description('Show server and active reviews')\n .action(async () => {\n const globals = program.opts<GlobalOptions>();\n const info = await readServerInfo();\n const responsive = info ? await isServerResponsive(info) : false;\n const reviews = await listReviewsForStatus({ responsive, server: info });\n const status = { running: responsive, server: info, reviews };\n globals.json\n ? printJson(status)\n : printPlain(\n responsive && info\n ? `Gloss server running at ${serverUrl(info)} with ${reviews.length} active review(s)`\n : 'Gloss server is not running'\n );\n });\n\nprogram\n .command('stop')\n .description('Stop the managed background server')\n .option('--all', 'stop all Gloss daemon processes for the current user')\n .action(async (options: { all?: boolean }) => {\n const globals = program.opts<GlobalOptions>();\n const result = await stopServer({ all: options.all });\n globals.json\n ? printJson(result)\n : printPlain(\n options.all && result.stoppedPids\n ? `Stopped ${result.stoppedPids.length} Gloss daemon(s)`\n : result.stopped\n ? 'Gloss server stopped'\n : 'Gloss server was not running'\n );\n });\n\nprogram\n .command('resolve')\n .argument('<reviewId>', 'review id')\n .description('Mark a submitted review or one feedback comment as resolved')\n .option('--comment <commentId>', 'resolve one submitted feedback comment')\n .option('--summary <text>', 'brief summary of the fixes applied')\n .option('--turn <idOrIndex>', 'resolve a specific turn for whole-review resolution')\n .action(\n async (reviewId: string, options: { comment?: string; summary?: string; turn?: string }) => {\n const globals = program.opts<GlobalOptions>();\n const info = await ensureServer();\n const client = new ServerClient(serverUrl(info));\n const result = options.comment\n ? await client.resolveComment(reviewId, options.comment, options.summary)\n : await client.markResolved(reviewId, options.summary, options.turn);\n if (globals.json) {\n printJson({\n commentId: options.comment ?? null,\n summary: options.summary ?? null,\n turn: options.turn ?? null,\n ...result\n });\n return;\n }\n printPlain(\n options.comment\n ? `Comment ${options.comment} resolved in review ${reviewId}`\n : `Review ${reviewId} resolved`\n );\n }\n );\n\nprogram\n .command('doctor')\n .description('Diagnose setup and validate git/state')\n .action(async () => {\n const globals = program.opts<GlobalOptions>();\n const checks: DoctorCheck[] = [];\n try {\n await assertGitAvailable();\n checks.push({ name: 'git', ok: true });\n } catch (error) {\n checks.push({\n name: 'git',\n ok: false,\n detail: error instanceof Error ? error.message : String(error)\n });\n }\n try {\n const root = await getRepoRoot();\n checks.push({ name: 'repo', ok: true, detail: root });\n } catch (error) {\n checks.push({\n name: 'repo',\n ok: false,\n detail: error instanceof Error ? error.message : String(error)\n });\n }\n const info = await readServerInfo();\n checks.push({\n name: 'server',\n ok: info ? await isServerResponsive(info) : false,\n detail: info ? serverUrl(info) : 'not started'\n });\n try {\n const daemonPids = await listGlossDaemonPids();\n const unmanagedDaemonPids = daemonPids.filter((pid) => pid !== info?.pid);\n checks.push({\n name: 'daemon-processes',\n ok: unmanagedDaemonPids.length === 0,\n detail:\n daemonPids.length === 0\n ? 'none'\n : `${daemonPids.length} found${unmanagedDaemonPids.length > 0 ? `; unmanaged pids ${unmanagedDaemonPids.join(', ')}` : ''}`\n });\n } catch (error) {\n checks.push({\n name: 'daemon-processes',\n ok: false,\n detail: error instanceof Error ? error.message : String(error)\n });\n }\n if (globals.json) {\n printJson({ checks });\n } else {\n for (const check of checks) {\n printPlain(\n `${check.ok ? 'ok' : 'fail'} ${check.name}${check.detail ? ` - ${check.detail}` : ''}`\n );\n }\n }\n });\n\nasync function watchReviewWithReconnect(\n reviewId: string,\n initialInfo: ServerInfo,\n timeoutSeconds: number | undefined,\n onServerChanged: (info: ServerInfo) => Promise<void>\n): Promise<{ event: ReviewEvent; info: ServerInfo }> {\n const startedAt = Date.now();\n let info = initialInfo;\n\n while (true) {\n const remainingSeconds =\n timeoutSeconds && timeoutSeconds > 0\n ? timeoutSeconds - (Date.now() - startedAt) / 1000\n : undefined;\n if (remainingSeconds !== undefined && remainingSeconds <= 0) {\n throw new Error(`watch timed out after ${timeoutSeconds} seconds`);\n }\n\n try {\n const event = await new ServerClient(serverUrl(info)).watchReview(reviewId, remainingSeconds);\n return { event, info };\n } catch (error) {\n if (isWatchTimeout(error)) {\n throw error;\n }\n if (!isReconnectableWatchError(error)) {\n throw error;\n }\n await sleep(500);\n const nextInfo = await ensureServer();\n if (nextInfo.port !== info.port) {\n await onServerChanged(nextInfo);\n }\n info = nextInfo;\n }\n }\n}\n\nasync function baseForExistingReview(\n client: ServerClient,\n reviewId: string\n): Promise<string | null> {\n const record = await client.getReview(reviewId);\n return record.diff.scope.mode === 'explicit'\n ? (record.diff.scope.requestedBase ?? record.diff.base.ref)\n : null;\n}\n\nfunction isWatchTimeout(error: unknown): error is Error {\n return error instanceof Error && /^watch timed out after/.test(error.message);\n}\n\nfunction isReconnectableWatchError(error: unknown): error is Error {\n return error instanceof Error && !/^watch failed: [45]\\d\\d /.test(error.message);\n}\n\nasync function sleep(milliseconds: number): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\n\nprogram.parseAsync(process.argv).catch((error: unknown) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 1;\n});\n","import { mkdir } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport path from 'node:path';\nimport packageJson from '../../package.json';\n\nexport const packageVersion = packageJson.version;\n\nexport function expandHome(input: string): string {\n if (input === '~') {\n return homedir();\n }\n if (input.startsWith('~/')) {\n return path.join(homedir(), input.slice(2));\n }\n return input;\n}\n\nexport function globalStateDir(): string {\n return expandHome(process.env.GLOSS_STATE_DIR ?? '~/.gloss');\n}\n\nexport function globalServerFile(): string {\n return path.join(globalStateDir(), 'server.json');\n}\n\nexport function globalLogDir(): string {\n return path.join(globalStateDir(), 'logs');\n}\n\nexport function globalServerLogFile(): string {\n return path.join(globalLogDir(), 'server.log');\n}\n\nexport function globalReviewsDir(): string {\n return path.join(globalStateDir(), 'reviews');\n}\n\nexport function globalReviewDir(reviewId: string): string {\n return path.join(globalReviewsDir(), reviewId);\n}\n\nexport function globalReviewTurnsDir(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'turns');\n}\n\nexport function globalReviewTurnDir(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnsDir(reviewId), turnId);\n}\n\nexport function globalReviewTurnMetaFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'turn.json');\n}\n\nexport function globalReviewTurnDiffFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'diff.json');\n}\n\nexport function globalReviewTurnFeedbackFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'feedback.json');\n}\n\nexport function globalReviewTurnMarkdownFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'feedback.md');\n}\n\nexport function globalReviewTurnResolvedFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'resolved.json');\n}\n\nexport function globalReviewMetaFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'meta.json');\n}\n\nexport function globalReviewDiffFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'diff.json');\n}\n\nexport function globalReviewFeedbackFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'feedback.json');\n}\n\nexport function globalReviewMarkdownFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'feedback.md');\n}\n\nexport function globalReviewResolvedFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'resolved.json');\n}\n\nexport async function ensureDir(dir: string): Promise<void> {\n await mkdir(dir, { recursive: true });\n}\n","{\n \"name\": \"getgloss\",\n \"version\": \"0.8.0\",\n \"description\": \"Local browser-based diff review for coding-agent loops.\",\n \"type\": \"module\",\n \"packageManager\": \"pnpm@10.33.2\",\n \"bin\": {\n \"getgloss\": \"./dist/cli/index.js\",\n \"gloss\": \"./dist/cli/index.js\"\n },\n \"files\": [\n \"dist\",\n \"skill\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"pnpm build:web && pnpm build:node\",\n \"build:web\": \"vite build\",\n \"build:node\": \"tsup\",\n \"check\": \"biome check .\",\n \"format\": \"biome format --write .\",\n \"prepack\": \"pnpm build\",\n \"dev:web\": \"vite --host 127.0.0.1\",\n \"setup\": \"tsx scripts/dev-cli.ts\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"dependencies\": {\n \"@hono/node-server\": \"1.19.14\",\n \"@shikijs/langs\": \"4.1.0\",\n \"@shikijs/themes\": \"4.1.0\",\n \"@tailwindcss/vite\": \"4.3.0\",\n \"commander\": \"14.0.3\",\n \"execa\": \"9.6.1\",\n \"get-port\": \"7.2.0\",\n \"hono\": \"4.12.21\",\n \"lucide-react\": \"1.16.0\",\n \"open\": \"10.2.0\",\n \"react\": \"19.2.6\",\n \"react-dom\": \"19.2.6\",\n \"shiki\": \"4.1.0\",\n \"ulid\": \"3.0.2\",\n \"zustand\": \"5.0.13\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"2.4.15\",\n \"@types/node\": \"24.12.4\",\n \"@types/react\": \"19.2.15\",\n \"@types/react-dom\": \"19.2.3\",\n \"@vitejs/plugin-react\": \"4.7.0\",\n \"tailwindcss\": \"4.3.0\",\n \"tsup\": \"8.5.1\",\n \"tsx\": \"4.22.3\",\n \"typescript\": \"5.9.3\",\n \"vite\": \"6.4.2\",\n \"vitest\": \"3.2.4\"\n },\n \"keywords\": [\n \"diff\",\n \"review\",\n \"coding-agents\"\n ],\n \"author\": \"Raj Joshi\",\n \"license\": \"MIT\",\n \"homepage\": \"https://getgloss.dev\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/iamrajjoshi/gloss.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/iamrajjoshi/gloss/issues\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n","import { execa } from 'execa';\nimport { parseUnifiedDiff } from '../shared/diff-parser';\nimport { summarizeDiffFiles } from '../shared/diff-stats';\nimport type {\n BaseRef,\n CommitDiff,\n DiffFallbackReason,\n DiffPayload,\n DiffRef,\n DiffScopeMode\n} from '../shared/types';\n\nconst DIFF_ARGS = ['diff', '--no-color', '--find-renames', '--find-copies'];\n\nasync function git(args: string[], cwd = process.cwd()): Promise<string> {\n const result = await execa('git', args, { cwd });\n return result.stdout.trimEnd();\n}\n\nasync function gitMaybe(args: string[], cwd: string): Promise<string | null> {\n const result = await execa('git', args, { cwd, reject: false });\n return result.exitCode === 0 ? result.stdout.trimEnd() : null;\n}\n\nasync function gitLenient(args: string[], cwd: string): Promise<string> {\n const result = await execa('git', args, { cwd, reject: false });\n if (result.exitCode !== 0 && result.stdout.length === 0) {\n throw new Error(result.stderr || `git ${args.join(' ')} failed`);\n }\n return result.stdout.trimEnd();\n}\n\nexport async function getRepoRoot(cwd = process.cwd()): Promise<string> {\n return git(['rev-parse', '--show-toplevel'], cwd);\n}\n\ninterface ResolvedBranchBase {\n sourceRef: string;\n mergeBaseSha: string;\n}\n\ninterface PayloadOptions {\n repoRoot: string;\n branch: string | null;\n rawDiff: string;\n base: BaseRef;\n mode: DiffScopeMode;\n requestedBase: string | null;\n comparison: DiffRef;\n fallbackReason: DiffFallbackReason;\n commitDiffs?: CommitDiff[];\n}\n\nfunction buildPayload({\n repoRoot,\n branch,\n rawDiff,\n base,\n mode,\n requestedBase,\n comparison,\n fallbackReason,\n commitDiffs\n}: PayloadOptions): DiffPayload {\n const files = parseUnifiedDiff(rawDiff);\n return {\n base,\n branch,\n cwd: repoRoot,\n scope: {\n mode,\n requestedBase,\n base,\n comparison,\n fallbackReason\n },\n stats: summarizeDiffFiles(files),\n rawDiff,\n files,\n ...(commitDiffs ? { commitDiffs } : {}),\n capturedAt: new Date().toISOString()\n };\n}\n\nasync function currentBranch(repoRoot: string): Promise<string | null> {\n const branch = await gitMaybe(['rev-parse', '--abbrev-ref', 'HEAD'], repoRoot);\n return branch && branch !== 'HEAD' ? branch : null;\n}\n\nasync function captureUntrackedDiff(repoRoot: string): Promise<string[]> {\n const untrackedFilesRaw = await git(\n ['ls-files', '--others', '--exclude-standard', '-z'],\n repoRoot\n );\n const untrackedFiles = untrackedFilesRaw.split('\\0').filter(Boolean);\n return Promise.all(\n untrackedFiles.map((filePath) =>\n gitLenient(['diff', '--no-color', '--no-index', '--', '/dev/null', filePath], repoRoot)\n )\n );\n}\n\nasync function captureWorkingDiff(baseRef: string, repoRoot: string): Promise<string> {\n const [trackedDiff, untrackedDiffs] = await Promise.all([\n git([...DIFF_ARGS, baseRef, '--'], repoRoot),\n captureUntrackedDiff(repoRoot)\n ]);\n return [trackedDiff, ...untrackedDiffs].filter(Boolean).join('\\n');\n}\n\nasync function resolveCommit(ref: string, repoRoot: string): Promise<string | null> {\n return gitMaybe(['rev-parse', '--verify', `${ref}^{commit}`], repoRoot);\n}\n\nasync function resolveBranchBase(repoRoot: string): Promise<ResolvedBranchBase | null> {\n const candidates: string[] = [];\n const upstream = await gitMaybe(\n ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{upstream}'],\n repoRoot\n );\n const originHead = await gitMaybe(\n ['symbolic-ref', '--quiet', '--short', 'refs/remotes/origin/HEAD'],\n repoRoot\n );\n\n for (const ref of [upstream, originHead, 'origin/main', 'origin/master']) {\n if (ref && !candidates.includes(ref)) {\n candidates.push(ref);\n }\n }\n\n for (const sourceRef of candidates) {\n const [sourceSha, mergeBaseSha] = await Promise.all([\n resolveCommit(sourceRef, repoRoot),\n gitMaybe(['merge-base', 'HEAD', sourceRef], repoRoot)\n ]);\n if (sourceSha && mergeBaseSha) {\n return { sourceRef, mergeBaseSha };\n }\n }\n\n return null;\n}\n\nasync function captureCommitDiffs(\n baseSha: string,\n comparisonRef: string,\n repoRoot: string\n): Promise<CommitDiff[]> {\n const rawLog = await gitMaybe(\n [\n 'log',\n '--reverse',\n '--format=%H%x00%h%x00%an%x00%ae%x00%aI%x00%cI%x00%s%x1e',\n `${baseSha}..${comparisonRef}`\n ],\n repoRoot\n );\n if (!rawLog) {\n return [];\n }\n\n const commits = rawLog\n .split('\\x1e')\n .map((entry) => entry.trim())\n .filter(Boolean)\n .map((entry) => {\n const [\n sha = '',\n shortSha = '',\n authorName = '',\n authorEmail = '',\n authoredAt = '',\n committedAt = '',\n ...subjectParts\n ] = entry.split('\\x00');\n return {\n sha,\n shortSha,\n subject: subjectParts.join('\\x00'),\n authorName,\n authorEmail,\n authoredAt,\n committedAt\n };\n })\n .filter((commit) => commit.sha && commit.shortSha);\n\n const commitDiffs: CommitDiff[] = [];\n for (const commit of commits) {\n const rawDiff = await git([...DIFF_ARGS, `${commit.sha}^`, commit.sha, '--'], repoRoot);\n const files = parseUnifiedDiff(rawDiff);\n commitDiffs.push({\n commit,\n stats: summarizeDiffFiles(files),\n rawDiff,\n files\n });\n }\n return commitDiffs;\n}\n\nexport async function captureDiff(baseRef?: string, cwd = process.cwd()): Promise<DiffPayload> {\n const repoRoot = await getRepoRoot(cwd);\n const [headSha, branch] = await Promise.all([\n git(['rev-parse', 'HEAD'], repoRoot),\n currentBranch(repoRoot)\n ]);\n\n if (baseRef) {\n const [baseSha, rawDiff] = await Promise.all([\n git(['rev-parse', baseRef], repoRoot),\n captureWorkingDiff(baseRef, repoRoot)\n ]);\n return buildPayload({\n repoRoot,\n branch,\n rawDiff,\n base: { ref: baseRef, sha: baseSha },\n mode: 'explicit',\n requestedBase: baseRef,\n comparison: { ref: 'working tree', sha: null },\n fallbackReason: null\n });\n }\n\n const workingDiff = await captureWorkingDiff('HEAD', repoRoot);\n if (workingDiff.trim().length > 0) {\n return buildPayload({\n repoRoot,\n branch,\n rawDiff: workingDiff,\n base: { ref: 'HEAD', sha: headSha },\n mode: 'working',\n requestedBase: null,\n comparison: { ref: 'working tree', sha: null },\n fallbackReason: null\n });\n }\n\n const branchBase = await resolveBranchBase(repoRoot);\n if (!branchBase) {\n return buildPayload({\n repoRoot,\n branch,\n rawDiff: '',\n base: { ref: 'HEAD', sha: headSha },\n mode: 'working',\n requestedBase: null,\n comparison: { ref: 'working tree', sha: null },\n fallbackReason: 'missing-branch-base'\n });\n }\n\n const [rawDiff, commitDiffs] = await Promise.all([\n git([...DIFF_ARGS, branchBase.mergeBaseSha, 'HEAD', '--'], repoRoot),\n captureCommitDiffs(branchBase.mergeBaseSha, 'HEAD', repoRoot)\n ]);\n return buildPayload({\n repoRoot,\n branch,\n rawDiff,\n base: { ref: `merge-base(${branchBase.sourceRef})`, sha: branchBase.mergeBaseSha },\n mode: 'branch',\n requestedBase: null,\n comparison: { ref: 'HEAD', sha: headSha },\n fallbackReason: 'working-tree-clean',\n commitDiffs\n });\n}\n\nexport async function assertGitAvailable(): Promise<void> {\n await execa('git', ['--version']);\n}\n","import path from 'node:path';\n\nconst languageByExtension: Record<string, string> = {\n cjs: 'js',\n css: 'css',\n go: 'go',\n html: 'html',\n js: 'js',\n json: 'json',\n jsx: 'jsx',\n md: 'markdown',\n mjs: 'js',\n py: 'python',\n rb: 'ruby',\n rs: 'rust',\n sh: 'bash',\n swift: 'swift',\n ts: 'ts',\n tsx: 'tsx',\n yaml: 'yaml',\n yml: 'yaml'\n};\n\nexport function languageForPath(filePath: string): string | null {\n const ext = path.extname(filePath).slice(1).toLowerCase();\n if (!ext) {\n return null;\n }\n return languageByExtension[ext] ?? ext;\n}\n","import { languageForPath } from './language';\nimport type { DiffFile, DiffHunk, DiffLine } from './types';\n\nconst hunkHeaderPattern = /^@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@(.*)$/;\n\nfunction stripGitPath(input: string): string {\n return input.replace(/^[ab]\\//, '');\n}\n\nfunction emptyFile(): DiffFile {\n return {\n path: '',\n oldPath: null,\n additions: 0,\n deletions: 0,\n isBinary: false,\n isDeleted: false,\n isNew: false,\n isRenamed: false,\n language: null,\n hunks: []\n };\n}\n\nexport function parseUnifiedDiff(diffText: string): DiffFile[] {\n const files: DiffFile[] = [];\n let current: DiffFile | null = null;\n let currentHunk: DiffHunk | null = null;\n let oldCursor = 0;\n let newCursor = 0;\n\n const finalizeFile = () => {\n if (current?.path) {\n current.language = languageForPath(current.path);\n files.push(current);\n }\n };\n\n for (const line of diffText.split('\\n')) {\n if (line.startsWith('diff --git ')) {\n finalizeFile();\n current = emptyFile();\n currentHunk = null;\n oldCursor = 0;\n newCursor = 0;\n const match = /^diff --git a\\/(.+) b\\/(.+)$/.exec(line);\n if (match) {\n current.oldPath = match[1];\n current.path = match[2];\n }\n continue;\n }\n\n if (!current) {\n continue;\n }\n\n if (line.startsWith('new file mode')) {\n current.isNew = true;\n continue;\n }\n\n if (line.startsWith('deleted file mode')) {\n current.isDeleted = true;\n continue;\n }\n\n if (line.startsWith('rename from ')) {\n current.oldPath = line.slice('rename from '.length);\n current.isRenamed = true;\n continue;\n }\n\n if (line.startsWith('rename to ')) {\n current.path = line.slice('rename to '.length);\n current.isRenamed = true;\n continue;\n }\n\n if (line.startsWith('Binary files ') || line.startsWith('GIT binary patch')) {\n current.isBinary = true;\n continue;\n }\n\n if (line.startsWith('--- ')) {\n const oldPath = line.slice(4).trim();\n current.oldPath = oldPath === '/dev/null' ? null : stripGitPath(oldPath);\n continue;\n }\n\n if (line.startsWith('+++ ')) {\n const newPath = line.slice(4).trim();\n current.path =\n newPath === '/dev/null' ? (current.oldPath ?? current.path) : stripGitPath(newPath);\n continue;\n }\n\n const hunkMatch = hunkHeaderPattern.exec(line);\n if (hunkMatch) {\n const oldStart = Number(hunkMatch[1]);\n const oldLines = Number(hunkMatch[2] ?? '1');\n const newStart = Number(hunkMatch[3]);\n const newLines = Number(hunkMatch[4] ?? '1');\n currentHunk = {\n oldStart,\n oldLines,\n newStart,\n newLines,\n header: hunkMatch[5]?.trim() ?? '',\n lines: []\n };\n current.hunks.push(currentHunk);\n oldCursor = oldStart;\n newCursor = newStart;\n continue;\n }\n\n if (!currentHunk) {\n continue;\n }\n\n const marker = line[0];\n const content = line.slice(1);\n let diffLine: DiffLine | null = null;\n\n if (marker === '+') {\n diffLine = { type: 'add', oldLine: null, newLine: newCursor, content };\n current.additions += 1;\n newCursor += 1;\n } else if (marker === '-') {\n diffLine = { type: 'delete', oldLine: oldCursor, newLine: null, content };\n current.deletions += 1;\n oldCursor += 1;\n } else if (marker === ' ') {\n diffLine = { type: 'context', oldLine: oldCursor, newLine: newCursor, content };\n oldCursor += 1;\n newCursor += 1;\n } else if (line.startsWith('\\\')) {\n continue;\n }\n\n if (diffLine) {\n currentHunk.lines.push(diffLine);\n }\n }\n\n finalizeFile();\n return files;\n}\n","import type { DiffFile, DiffStats } from './types';\n\nexport function summarizeDiffFiles(files: DiffFile[]): DiffStats {\n return files.reduce(\n (stats, file) => ({\n files: stats.files + 1,\n additions: stats.additions + file.additions,\n deletions: stats.deletions + file.deletions\n }),\n { files: 0, additions: 0, deletions: 0 }\n );\n}\n","import { execFile, spawn } from 'node:child_process';\nimport { closeSync, existsSync, openSync } from 'node:fs';\nimport { rm } from 'node:fs/promises';\nimport { userInfo } from 'node:os';\nimport { fileURLToPath } from 'node:url';\nimport { promisify } from 'node:util';\nimport getPort from 'get-port';\nimport {\n ensureDir,\n globalLogDir,\n globalServerFile,\n globalServerLogFile,\n globalStateDir,\n packageVersion\n} from '../shared/paths';\nimport { readServerInfo, writeServerInfo } from '../shared/server-info';\nimport type { ServerInfo } from '../shared/types';\nimport { ServerClient } from './server-client';\n\nexport { readServerInfo } from '../shared/server-info';\n\nconst execFileAsync = promisify(execFile);\nconst gracefulShutdownTimeoutMs = 2000;\nconst forceShutdownTimeoutMs = 1000;\n\nexport function serverUrl(info: Pick<ServerInfo, 'port'>): string {\n return `http://localhost:${info.port}`;\n}\n\nexport async function isServerResponsive(info: ServerInfo): Promise<boolean> {\n if (!isPidAlive(info.pid)) {\n return false;\n }\n try {\n const health = await new ServerClient(serverUrl(info)).health();\n return health.ok === true && health.version === packageVersion;\n } catch {\n return false;\n }\n}\n\nexport async function ensureServer(options: { port?: number } = {}): Promise<ServerInfo> {\n const existing = await readServerInfo();\n if (existing && (await isServerResponsive(existing))) {\n return existing;\n }\n return startServer(options);\n}\n\nexport async function startServer(options: { port?: number } = {}): Promise<ServerInfo> {\n const existing = await readServerInfo();\n if (existing && (await isServerResponsive(existing))) {\n return existing;\n }\n if (existing) {\n await retireServer(existing);\n }\n\n const preferredPort = options.port ?? existing?.port ?? (await getPort());\n try {\n return await launchServer(preferredPort);\n } catch (error) {\n if (options.port || !existing?.port) {\n throw error;\n }\n await removeServerInfoForPid(existing.pid);\n return launchServer(await getPort());\n }\n}\n\nasync function launchServer(port: number): Promise<ServerInfo> {\n await ensureDir(globalStateDir());\n await ensureDir(globalLogDir());\n const daemonPath = fileURLToPath(new URL('../server/daemon.js', import.meta.url));\n if (!existsSync(daemonPath)) {\n throw new Error(`Cannot find server daemon at ${daemonPath}. Run pnpm build first.`);\n }\n\n const logFd = openSync(globalServerLogFile(), 'a');\n const child = spawn(process.execPath, [daemonPath], {\n detached: true,\n env: {\n ...process.env,\n GLOSS_PORT: String(port),\n GLOSS_STATE_DIR: globalStateDir()\n },\n stdio: ['ignore', logFd, logFd]\n });\n closeSync(logFd);\n child.unref();\n\n const info: ServerInfo = {\n pid: child.pid ?? -1,\n port,\n version: packageVersion,\n startedAt: new Date().toISOString(),\n stateDir: globalStateDir()\n };\n await writeServerInfo(info);\n\n const deadline = Date.now() + 8000;\n while (Date.now() < deadline) {\n if (await isServerResponsive(info)) {\n return info;\n }\n await new Promise((resolve) => setTimeout(resolve, 150));\n }\n\n await terminatePid(info.pid);\n await removeServerInfoForPid(info.pid);\n throw new Error(`Server did not become responsive. See ${globalServerLogFile()}`);\n}\n\nexport async function stopServer(\n options: { all?: boolean } = {}\n): Promise<{ stopped: boolean; info: ServerInfo | null; stoppedPids?: number[] }> {\n if (options.all) {\n const info = await readServerInfo();\n const daemonPids = await listGlossDaemonPids();\n const stoppedPids: number[] = [];\n for (const pid of daemonPids) {\n if (await terminatePid(pid)) {\n stoppedPids.push(pid);\n }\n }\n await rm(globalServerFile(), { force: true });\n return { stopped: stoppedPids.length > 0, info, stoppedPids };\n }\n\n const info = await readServerInfo();\n if (!info) {\n return { stopped: false, info: null };\n }\n\n if (!isPidAlive(info.pid)) {\n await removeServerInfoForPid(info.pid);\n return { stopped: false, info };\n }\n\n if (!(await isGlossDaemonPid(info.pid))) {\n await removeServerInfoForPid(info.pid);\n return { stopped: false, info };\n }\n\n const stopped = await terminatePid(info.pid);\n if (stopped) {\n await removeServerInfoForPid(info.pid);\n }\n return { stopped, info };\n}\n\nfunction isPidAlive(pid: number): boolean {\n if (pid <= 0) {\n return false;\n }\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function retireServer(info: ServerInfo): Promise<void> {\n if (isPidAlive(info.pid) && (await isGlossDaemonPid(info.pid))) {\n await terminatePid(info.pid);\n }\n await removeServerInfoForPid(info.pid);\n}\n\nasync function terminatePid(pid: number): Promise<boolean> {\n if (!isPidAlive(pid)) {\n return true;\n }\n try {\n process.kill(pid, 'SIGTERM');\n } catch {\n return !isPidAlive(pid);\n }\n if (await waitForPidExit(pid, gracefulShutdownTimeoutMs)) {\n return true;\n }\n try {\n process.kill(pid, 'SIGKILL');\n } catch {\n return !isPidAlive(pid);\n }\n return waitForPidExit(pid, forceShutdownTimeoutMs);\n}\n\nasync function waitForPidExit(pid: number, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n if (!isPidAlive(pid)) {\n return true;\n }\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n return !isPidAlive(pid);\n}\n\nasync function removeServerInfoForPid(pid: number): Promise<void> {\n const current = await readServerInfo().catch(() => null);\n if (!current || current.pid === pid) {\n await rm(globalServerFile(), { force: true });\n }\n}\n\nasync function isGlossDaemonPid(pid: number): Promise<boolean> {\n const command = await readProcessCommand(pid);\n return command ? isGlossDaemonCommand(command) : false;\n}\n\nasync function readProcessCommand(pid: number): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync('ps', ['-o', 'command=', '-p', String(pid), '-ww']);\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\nexport async function listGlossDaemonPids(): Promise<number[]> {\n let stdout: string;\n try {\n ({ stdout } = await execFileAsync('ps', ['-axo', 'pid=,user=,command=', '-ww']));\n } catch {\n return [];\n }\n const currentUser = userInfo().username;\n return parseGlossDaemonPids(stdout, currentUser, process.pid);\n}\n\nexport function parseGlossDaemonPids(\n stdout: string,\n currentUser: string,\n currentPid = process.pid\n): number[] {\n return stdout\n .split('\\n')\n .map((line) => /^\\s*(\\d+)\\s+(\\S+)\\s+(.+)$/.exec(line))\n .filter((match): match is RegExpExecArray => Boolean(match))\n .map((match) => ({\n pid: Number(match[1]),\n user: match[2],\n command: match[3]\n }))\n .filter(\n ({ pid, user, command }) =>\n pid !== currentPid && user === currentUser && isGlossDaemonCommand(command)\n )\n .map(({ pid }) => pid);\n}\n\nfunction isGlossDaemonCommand(command: string): boolean {\n return /(?:^|\\s)(?:\\S*\\/)?node\\s+\\S*dist\\/server\\/daemon\\.js(?:\\s|$)/.test(command);\n}\n","import { readFile } from 'node:fs/promises';\nimport { formatError, isFileNotFound } from './errors';\nimport { writeJsonFile } from './json';\nimport { ensureDir, globalServerFile, globalStateDir } from './paths';\nimport type { ServerInfo } from './types';\nimport { isServerInfo, parseJson } from './validation';\n\nexport async function readServerInfo(): Promise<ServerInfo | null> {\n let raw: string;\n try {\n raw = await readFile(globalServerFile(), 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return null;\n }\n throw new Error(`Could not read server info at ${globalServerFile()}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n try {\n return parseJson(raw, isServerInfo, 'server info');\n } catch (error) {\n throw new Error(`Invalid server info at ${globalServerFile()}: ${formatError(error)}`, {\n cause: error\n });\n }\n}\n\nexport async function writeServerInfo(info: ServerInfo): Promise<void> {\n await ensureDir(globalStateDir());\n await writeJsonFile(globalServerFile(), info);\n}\n","export function formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport function isFileNotFound(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n","import { randomUUID } from 'node:crypto';\nimport { rename, rm, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type {\n DiffPayload,\n FeedbackBundle,\n ResolutionBundle,\n ReviewMeta,\n ReviewTurnMeta,\n ServerInfo\n} from './types';\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | { [key: string]: JsonValue }\n | JsonValue[];\n\ntype PersistedJson =\n | ServerInfo\n | ReviewMeta\n | ReviewTurnMeta\n | DiffPayload\n | FeedbackBundle\n | ResolutionBundle;\n\nfunction serializeJson(value: PersistedJson): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nexport async function writeJsonFile(filePath: string, value: PersistedJson): Promise<void> {\n await writeTextFile(filePath, serializeJson(value));\n}\n\nexport async function writeTextFile(filePath: string, value: string): Promise<void> {\n const tempPath = path.join(\n path.dirname(filePath),\n `.${path.basename(filePath)}.${process.pid}.${randomUUID()}.tmp`\n );\n try {\n await writeFile(tempPath, value);\n await rename(tempPath, filePath);\n } catch (error) {\n await rm(tempPath, { force: true }).catch(() => undefined);\n throw error;\n }\n}\n","export const SIDES = ['L', 'R'] as const;\n\nexport type Side = (typeof SIDES)[number];\n\nexport const REVIEW_STATUSES = ['pending', 'submitted', 'cancelled', 'resolved'] as const;\n\nexport type ReviewStatus = (typeof REVIEW_STATUSES)[number];\n\nexport interface Comment {\n id: string;\n filePath: string;\n startLine: number;\n endLine: number;\n side: Side;\n body: string;\n originalSnippet: string;\n createdAt: string;\n}\n\nexport const DIFF_LINE_TYPES = ['context', 'add', 'delete'] as const;\n\nexport type DiffLineType = (typeof DIFF_LINE_TYPES)[number];\n\nexport interface DiffLine {\n type: DiffLineType;\n oldLine: number | null;\n newLine: number | null;\n content: string;\n}\n\nexport interface DiffHunk {\n oldStart: number;\n oldLines: number;\n newStart: number;\n newLines: number;\n header: string;\n lines: DiffLine[];\n}\n\nexport interface DiffFile {\n path: string;\n oldPath: string | null;\n additions: number;\n deletions: number;\n isBinary: boolean;\n isDeleted: boolean;\n isNew: boolean;\n isRenamed: boolean;\n language: string | null;\n hunks: DiffHunk[];\n}\n\nexport const DIFF_SCOPE_MODES = ['working', 'branch', 'explicit'] as const;\n\nexport type DiffScopeMode = (typeof DIFF_SCOPE_MODES)[number];\n\nexport const DIFF_FALLBACK_REASONS = ['working-tree-clean', 'missing-branch-base'] as const;\n\nexport type DiffFallbackReason = (typeof DIFF_FALLBACK_REASONS)[number] | null;\n\nexport interface BaseRef {\n ref: string;\n sha: string;\n}\n\nexport interface DiffRef {\n ref: string;\n sha: string | null;\n}\n\nexport interface DiffStats {\n files: number;\n additions: number;\n deletions: number;\n}\n\nexport interface DiffCommit {\n sha: string;\n shortSha: string;\n subject: string;\n authorName: string;\n authorEmail: string;\n authoredAt: string;\n committedAt: string;\n}\n\nexport interface CommitDiff {\n commit: DiffCommit;\n stats: DiffStats;\n rawDiff: string;\n files: DiffFile[];\n}\n\nexport interface CommitRangeDiffRequest {\n fromSha: string;\n toSha: string;\n turnId?: string;\n}\n\nexport interface CommitRangeDiffResponse {\n fromSha: string;\n toSha: string;\n stats: DiffStats;\n rawDiff: string;\n files: DiffFile[];\n}\n\nexport const REVIEW_SCOPE_MODES = ['all', 'single', 'range'] as const;\n\nexport type ReviewScope =\n | { mode: 'all' }\n | { mode: 'single'; sha: string }\n | { mode: 'range'; fromSha: string; toSha: string };\n\ninterface DiffScope {\n mode: DiffScopeMode;\n requestedBase: string | null;\n base: BaseRef;\n comparison: DiffRef;\n fallbackReason: DiffFallbackReason;\n}\n\nexport interface DiffPayload {\n base: BaseRef;\n branch: string | null;\n cwd: string;\n scope: DiffScope;\n stats: DiffStats;\n rawDiff: string;\n files: DiffFile[];\n commitDiffs?: CommitDiff[];\n capturedAt: string;\n}\n\nexport interface ReviewMeta {\n id: string;\n cwd: string;\n base: DiffPayload['base'];\n branch: string | null;\n status: ReviewStatus;\n createdAt: string;\n submittedAt?: string;\n resolvedAt?: string;\n artifactDir: string;\n activeTurnId?: string;\n turns?: ReviewTurnSummary[];\n feedbackPath?: string;\n markdownPath?: string;\n}\n\nexport interface FeedbackBundle {\n version: 1;\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n timestamp: string;\n base: DiffPayload['base'];\n branch: string | null;\n reviewScope?: ReviewScope;\n comments: Comment[];\n}\n\nexport const RESOLUTION_STATUSES = ['partial', 'resolved'] as const;\n\ntype ResolutionStatus = (typeof RESOLUTION_STATUSES)[number];\n\nexport interface ResolvedComment {\n commentId: string;\n status: 'resolved';\n summary?: string;\n resolvedAt: string;\n}\n\nexport interface ResolutionBundle {\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n status: ResolutionStatus;\n summary: string | null;\n resolvedAt: string | null;\n comments: ResolvedComment[];\n}\n\nexport interface ResolutionCounts {\n total: number;\n resolved: number;\n open: number;\n}\n\nexport interface ResolveResult {\n ok: true;\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n status: ReviewStatus;\n resolutionStatus: ResolutionStatus;\n comments: ResolutionCounts;\n path: string;\n resolution: ResolutionBundle;\n}\n\nexport const REVIEW_UPDATE_REASONS = [\n 'review-resolved',\n 'comment-resolved',\n 'comment-reopened',\n 'turn-created'\n] as const;\n\nexport type ReviewUpdateReason = (typeof REVIEW_UPDATE_REASONS)[number];\n\nexport type ReviewEvent =\n | { type: 'review.opened'; reviewId: string }\n | {\n type: 'review.turn.created';\n reviewId: string;\n turnId: string;\n turnIndex: number;\n reused: boolean;\n }\n | {\n type: 'review.submitted';\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n counts: { files: number; comments: number };\n }\n | {\n type: 'review.updated';\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n reason: ReviewUpdateReason;\n status: ReviewStatus;\n resolutionStatus: ResolutionStatus;\n counts: ResolutionCounts;\n }\n | { type: 'review.cancelled'; reviewId: string };\n\nexport interface ReviewTurnMeta {\n id: string;\n index: number;\n status: ReviewStatus;\n createdAt: string;\n submittedAt?: string;\n resolvedAt?: string;\n artifactDir: string;\n diffPath: string;\n feedbackPath?: string;\n markdownPath?: string;\n resolvedPath?: string;\n}\n\nexport interface ReviewTurnSummary extends ReviewTurnMeta {\n capturedAt: string;\n stats: DiffStats;\n comments: ResolutionCounts;\n}\n\nexport interface ReviewTurn extends ReviewTurnMeta {\n diff: DiffPayload;\n feedback?: FeedbackBundle;\n resolution?: ResolutionBundle;\n}\n\nexport interface ReviewRecord {\n meta: ReviewMeta;\n turns: ReviewTurn[];\n diff: DiffPayload;\n feedback?: FeedbackBundle;\n resolution?: ResolutionBundle;\n}\n\nexport interface ServerInfo {\n pid: number;\n port: number;\n version: string;\n startedAt: string;\n stateDir: string;\n}\n\nexport interface OpenResult {\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n url: string;\n files: number;\n comments?: number;\n feedbackPath?: string;\n markdownPath?: string;\n artifactDir?: string;\n}\n\nexport interface HealthResponse {\n ok: boolean;\n version: string;\n activeReviews: number;\n}\n\ninterface ReviewRegistrationResponse {\n meta: ReviewMeta;\n url: string;\n turn?: ReviewTurnSummary;\n}\n\nexport interface CreateReviewResponse extends ReviewRegistrationResponse {}\n\nexport interface CreateReviewTurnResponse extends ReviewRegistrationResponse {\n turn: ReviewTurnSummary;\n reused: boolean;\n}\n\nexport interface ListReviewsResponse {\n reviews: ReviewMeta[];\n}\n\nexport interface SubmitReviewRequest {\n comments: Comment[];\n reviewScope?: ReviewScope;\n}\n\nexport interface ResolutionRequest {\n summary?: string;\n turn?: string;\n}\n\nexport interface OpenFileRequest {\n filePath: string;\n turnId?: string;\n}\n\nexport interface OpenFileResponse {\n ok: true;\n path: string;\n}\n","import type { JsonValue } from './json';\nimport type {\n Comment,\n CommitDiff,\n CommitRangeDiffRequest,\n CommitRangeDiffResponse,\n CreateReviewResponse,\n CreateReviewTurnResponse,\n DiffCommit,\n DiffFile,\n DiffHunk,\n DiffLine,\n DiffPayload,\n DiffStats,\n FeedbackBundle,\n HealthResponse,\n ListReviewsResponse,\n OpenFileRequest,\n OpenFileResponse,\n OpenResult,\n ResolutionBundle,\n ResolutionRequest,\n ResolvedComment,\n ResolveResult,\n ReviewEvent,\n ReviewMeta,\n ReviewRecord,\n ReviewScope,\n ReviewTurn,\n ReviewTurnMeta,\n ReviewTurnSummary,\n ServerInfo,\n SubmitReviewRequest\n} from './types';\nimport {\n DIFF_FALLBACK_REASONS,\n DIFF_LINE_TYPES,\n DIFF_SCOPE_MODES,\n RESOLUTION_STATUSES,\n REVIEW_SCOPE_MODES,\n REVIEW_STATUSES,\n REVIEW_UPDATE_REASONS,\n SIDES\n} from './types';\n\nexport type JsonGuard<T> = (value: unknown) => value is T;\n\nexport type StoredReviewMeta = Omit<ReviewMeta, 'artifactDir'> &\n Partial<\n Pick<ReviewMeta, 'artifactDir' | 'activeTurnId' | 'turns' | 'feedbackPath' | 'markdownPath'>\n >;\n\ntype ReviewRegistrationResponseShape = {\n meta: ReviewMeta;\n url: string;\n turn?: ReviewTurnSummary;\n};\n\nexport function parseJson<T>(raw: string, guard: JsonGuard<T>, label: string): T {\n const parsed: JsonValue = JSON.parse(raw);\n return parseJsonValue(parsed, guard, label);\n}\n\nexport function parseJsonValue<T>(value: JsonValue, guard: JsonGuard<T>, label: string): T {\n if (!guard(value)) {\n throw new Error(`Invalid ${label}`);\n }\n return value;\n}\n\nexport function isServerInfo(value: unknown): value is ServerInfo {\n return (\n isRecord(value) &&\n isNumber(value.pid) &&\n isNumber(value.port) &&\n isString(value.version) &&\n isString(value.startedAt) &&\n isString(value.stateDir)\n );\n}\n\nexport function isHealthResponse(value: unknown): value is HealthResponse {\n return (\n isRecord(value) &&\n isBoolean(value.ok) &&\n isString(value.version) &&\n isNumber(value.activeReviews)\n );\n}\n\nexport function isCreateReviewResponse(value: unknown): value is CreateReviewResponse {\n return (\n isRecord(value) &&\n hasReviewRegistrationFields(value) &&\n isOptional(value.turn, isReviewTurnSummary)\n );\n}\n\nexport function isCreateReviewTurnResponse(value: unknown): value is CreateReviewTurnResponse {\n return (\n isRecord(value) &&\n hasReviewRegistrationFields(value) &&\n isReviewTurnSummary(value.turn) &&\n isBoolean(value.reused)\n );\n}\n\nexport function isListReviewsResponse(value: unknown): value is ListReviewsResponse {\n return isRecord(value) && isArrayOf(value.reviews, isReviewMeta);\n}\n\nexport function isOpenResult(value: unknown): value is OpenResult {\n return (\n isRecord(value) &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isString(value.url) &&\n isNumber(value.files) &&\n isOptionalNumber(value.comments) &&\n isOptionalString(value.feedbackPath) &&\n isOptionalString(value.markdownPath) &&\n isOptionalString(value.artifactDir)\n );\n}\n\nexport function isOpenFileRequest(value: unknown): value is OpenFileRequest {\n return isRecord(value) && isString(value.filePath) && isOptionalString(value.turnId);\n}\n\nexport function isOpenFileResponse(value: unknown): value is OpenFileResponse {\n return isRecord(value) && value.ok === true && isString(value.path);\n}\n\nexport function isCommitRangeDiffRequest(value: unknown): value is CommitRangeDiffRequest {\n return (\n isRecord(value) &&\n isString(value.fromSha) &&\n isString(value.toSha) &&\n isOptionalString(value.turnId)\n );\n}\n\nexport function isCommitRangeDiffResponse(value: unknown): value is CommitRangeDiffResponse {\n return (\n isRecord(value) &&\n isString(value.fromSha) &&\n isString(value.toSha) &&\n isDiffStats(value.stats) &&\n isString(value.rawDiff) &&\n isArrayOf(value.files, isDiffFile)\n );\n}\n\nexport function isResolveResult(value: unknown): value is ResolveResult {\n return (\n isRecord(value) &&\n value.ok === true &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isReviewStatus(value.status) &&\n isResolutionStatus(value.resolutionStatus) &&\n isResolutionCounts(value.comments) &&\n isString(value.path) &&\n isResolutionBundle(value.resolution)\n );\n}\n\nexport function isSubmitReviewRequest(value: unknown): value is SubmitReviewRequest {\n return (\n isRecord(value) &&\n isArrayOf(value.comments, isComment) &&\n isOptional(value.reviewScope, isReviewScope)\n );\n}\n\nexport function isResolutionRequest(value: unknown): value is ResolutionRequest {\n return isRecord(value) && isOptionalString(value.summary) && isOptionalString(value.turn);\n}\n\nexport function isReviewRecord(value: unknown): value is ReviewRecord {\n return (\n isRecord(value) &&\n isReviewMeta(value.meta) &&\n isArrayOf(value.turns, isReviewTurn) &&\n isDiffPayload(value.diff) &&\n isOptional(value.feedback, isFeedbackBundle) &&\n isOptional(value.resolution, isResolutionBundle)\n );\n}\n\nexport function isStoredReviewMeta(value: unknown): value is StoredReviewMeta {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.cwd) &&\n isBaseRef(value.base) &&\n isNullableString(value.branch) &&\n isReviewStatus(value.status) &&\n isString(value.createdAt) &&\n isOptionalString(value.submittedAt) &&\n isOptionalString(value.resolvedAt) &&\n isOptionalString(value.artifactDir) &&\n isOptionalString(value.activeTurnId) &&\n isOptional(value.turns, (turns): turns is ReviewTurnSummary[] =>\n isArrayOf(turns, isReviewTurnSummary)\n ) &&\n isOptionalString(value.feedbackPath) &&\n isOptionalString(value.markdownPath)\n );\n}\n\nfunction isReviewMeta(value: unknown): value is ReviewMeta {\n return isStoredReviewMeta(value) && isString(value.artifactDir);\n}\n\nfunction hasReviewRegistrationFields(\n value: Record<string, unknown>\n): value is Record<string, unknown> & ReviewRegistrationResponseShape {\n return isReviewMeta(value.meta) && isString(value.url);\n}\n\nexport function isDiffPayload(value: unknown): value is DiffPayload {\n return (\n isRecord(value) &&\n isBaseRef(value.base) &&\n isNullableString(value.branch) &&\n isString(value.cwd) &&\n isDiffScope(value.scope) &&\n isDiffStats(value.stats) &&\n isString(value.rawDiff) &&\n isArrayOf(value.files, isDiffFile) &&\n isOptional(value.commitDiffs, (commitDiffs): commitDiffs is CommitDiff[] =>\n isArrayOf(commitDiffs, isCommitDiff)\n ) &&\n isString(value.capturedAt)\n );\n}\n\nexport function isFeedbackBundle(value: unknown): value is FeedbackBundle {\n return (\n isRecord(value) &&\n value.version === 1 &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isString(value.timestamp) &&\n isBaseRef(value.base) &&\n isNullableString(value.branch) &&\n isOptional(value.reviewScope, isReviewScope) &&\n isArrayOf(value.comments, isComment)\n );\n}\n\nexport function isResolutionBundle(value: unknown): value is ResolutionBundle {\n return (\n isRecord(value) &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isResolutionStatus(value.status) &&\n isNullableString(value.summary) &&\n isNullableString(value.resolvedAt) &&\n isArrayOf(value.comments, isResolvedComment)\n );\n}\n\nexport function isReviewEvent(value: unknown): value is ReviewEvent {\n if (!isRecord(value) || !isString(value.reviewId) || !isString(value.type)) {\n return false;\n }\n switch (value.type) {\n case 'review.opened':\n case 'review.cancelled':\n return true;\n case 'review.turn.created':\n return isString(value.turnId) && isNumber(value.turnIndex) && isBoolean(value.reused);\n case 'review.submitted':\n return (\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isRecord(value.counts) &&\n isNumber(value.counts.files) &&\n isNumber(value.counts.comments)\n );\n case 'review.updated':\n return (\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isReviewUpdateReason(value.reason) &&\n isReviewStatus(value.status) &&\n isResolutionStatus(value.resolutionStatus) &&\n isResolutionCounts(value.counts)\n );\n default:\n return false;\n }\n}\n\nexport function isReviewTurnMeta(value: unknown): value is ReviewTurnMeta {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isNumber(value.index) &&\n isReviewStatus(value.status) &&\n isString(value.createdAt) &&\n isOptionalString(value.submittedAt) &&\n isOptionalString(value.resolvedAt) &&\n isString(value.artifactDir) &&\n isString(value.diffPath) &&\n isOptionalString(value.feedbackPath) &&\n isOptionalString(value.markdownPath) &&\n isOptionalString(value.resolvedPath)\n );\n}\n\nfunction isReviewTurnSummary(value: unknown): value is ReviewTurnSummary {\n if (!isRecord(value) || !isReviewTurnMeta(value)) {\n return false;\n }\n return (\n isString(value.capturedAt) && isDiffStats(value.stats) && isResolutionCounts(value.comments)\n );\n}\n\nfunction isReviewTurn(value: unknown): value is ReviewTurn {\n if (!isRecord(value) || !isReviewTurnMeta(value)) {\n return false;\n }\n return (\n isDiffPayload(value.diff) &&\n isOptional(value.feedback, isFeedbackBundle) &&\n isOptional(value.resolution, isResolutionBundle)\n );\n}\n\nfunction isDiffScope(value: unknown): value is DiffPayload['scope'] {\n return (\n isRecord(value) &&\n isOneOf(value.mode, DIFF_SCOPE_MODES) &&\n isNullableString(value.requestedBase) &&\n isBaseRef(value.base) &&\n isDiffRef(value.comparison) &&\n (value.fallbackReason === null || isOneOf(value.fallbackReason, DIFF_FALLBACK_REASONS))\n );\n}\n\nfunction isDiffRef(value: unknown): value is DiffPayload['scope']['comparison'] {\n return isRecord(value) && isString(value.ref) && isNullableString(value.sha);\n}\n\nfunction isBaseRef(value: unknown): value is { ref: string; sha: string } {\n return isRecord(value) && isString(value.ref) && isString(value.sha);\n}\n\nfunction isDiffStats(value: unknown): value is DiffStats {\n return (\n isRecord(value) &&\n isNumber(value.files) &&\n isNumber(value.additions) &&\n isNumber(value.deletions)\n );\n}\n\nfunction isDiffCommit(value: unknown): value is DiffCommit {\n return (\n isRecord(value) &&\n isString(value.sha) &&\n isString(value.shortSha) &&\n isString(value.subject) &&\n isString(value.authorName) &&\n isString(value.authorEmail) &&\n isString(value.authoredAt) &&\n isString(value.committedAt)\n );\n}\n\nfunction isCommitDiff(value: unknown): value is CommitDiff {\n return (\n isRecord(value) &&\n isDiffCommit(value.commit) &&\n isDiffStats(value.stats) &&\n isString(value.rawDiff) &&\n isArrayOf(value.files, isDiffFile)\n );\n}\n\nfunction isReviewScope(value: unknown): value is ReviewScope {\n if (!isRecord(value) || !isOneOf(value.mode, REVIEW_SCOPE_MODES)) {\n return false;\n }\n switch (value.mode) {\n case 'all':\n return true;\n case 'single':\n return isString(value.sha);\n case 'range':\n return isString(value.fromSha) && isString(value.toSha);\n }\n}\n\nfunction isDiffFile(value: unknown): value is DiffFile {\n return (\n isRecord(value) &&\n isString(value.path) &&\n isNullableString(value.oldPath) &&\n isNumber(value.additions) &&\n isNumber(value.deletions) &&\n isBoolean(value.isBinary) &&\n isBoolean(value.isDeleted) &&\n isBoolean(value.isNew) &&\n isBoolean(value.isRenamed) &&\n isNullableString(value.language) &&\n isArrayOf(value.hunks, isDiffHunk)\n );\n}\n\nfunction isDiffHunk(value: unknown): value is DiffHunk {\n return (\n isRecord(value) &&\n isNumber(value.oldStart) &&\n isNumber(value.oldLines) &&\n isNumber(value.newStart) &&\n isNumber(value.newLines) &&\n isString(value.header) &&\n isArrayOf(value.lines, isDiffLine)\n );\n}\n\nfunction isDiffLine(value: unknown): value is DiffLine {\n return (\n isRecord(value) &&\n isOneOf(value.type, DIFF_LINE_TYPES) &&\n isNullableNumber(value.oldLine) &&\n isNullableNumber(value.newLine) &&\n isString(value.content)\n );\n}\n\nfunction isComment(value: unknown): value is Comment {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.filePath) &&\n isNumber(value.startLine) &&\n isNumber(value.endLine) &&\n isOneOf(value.side, SIDES) &&\n isString(value.body) &&\n isString(value.originalSnippet) &&\n isString(value.createdAt)\n );\n}\n\nfunction isResolvedComment(value: unknown): value is ResolvedComment {\n return (\n isRecord(value) &&\n isString(value.commentId) &&\n value.status === 'resolved' &&\n isOptionalString(value.summary) &&\n isString(value.resolvedAt)\n );\n}\n\nfunction isResolutionCounts(value: unknown): value is ResolveResult['comments'] {\n return (\n isRecord(value) && isNumber(value.total) && isNumber(value.resolved) && isNumber(value.open)\n );\n}\n\nfunction isReviewStatus(value: unknown): value is ReviewMeta['status'] {\n return isOneOf(value, REVIEW_STATUSES);\n}\n\nfunction isResolutionStatus(value: unknown): value is ResolutionBundle['status'] {\n return isOneOf(value, RESOLUTION_STATUSES);\n}\n\nfunction isReviewUpdateReason(\n value: unknown\n): value is Extract<ReviewEvent, { type: 'review.updated' }>['reason'] {\n return isOneOf(value, REVIEW_UPDATE_REASONS);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isArrayOf<T>(value: unknown, guard: JsonGuard<T>): value is T[] {\n return Array.isArray(value) && value.every(guard);\n}\n\nfunction isOptional<T>(value: unknown, guard: JsonGuard<T>): value is T | undefined {\n return value === undefined || guard(value);\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\nfunction isOptionalString(value: unknown): value is string | undefined {\n return value === undefined || isString(value);\n}\n\nfunction isNullableString(value: unknown): value is string | null {\n return value === null || isString(value);\n}\n\nfunction isNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nfunction isOptionalNumber(value: unknown): value is number | undefined {\n return value === undefined || isNumber(value);\n}\n\nfunction isNullableNumber(value: unknown): value is number | null {\n return value === null || isNumber(value);\n}\n\nfunction isBoolean(value: unknown): value is boolean {\n return typeof value === 'boolean';\n}\n\nfunction isOneOf<const T extends readonly string[]>(\n value: unknown,\n options: T\n): value is T[number] {\n return typeof value === 'string' && options.includes(value);\n}\n","import type { JsonValue } from '../shared/json';\nimport type {\n Comment,\n CreateReviewResponse,\n CreateReviewTurnResponse,\n DiffPayload,\n FeedbackBundle,\n HealthResponse,\n ListReviewsResponse,\n OpenResult,\n ResolutionRequest,\n ResolveResult,\n ReviewEvent,\n ReviewRecord,\n SubmitReviewRequest\n} from '../shared/types';\nimport {\n isCreateReviewResponse,\n isCreateReviewTurnResponse,\n isFeedbackBundle,\n isHealthResponse,\n isListReviewsResponse,\n isOpenResult,\n isResolveResult,\n isReviewEvent,\n isReviewRecord,\n type JsonGuard,\n parseJson,\n parseJsonValue\n} from '../shared/validation';\n\nexport class ServerClient {\n constructor(private readonly baseUrl: string) {}\n\n async health(): Promise<HealthResponse> {\n return this.get('/api/health', isHealthResponse, 'health response');\n }\n\n async createReview(diff: DiffPayload): Promise<CreateReviewResponse> {\n return this.post('/api/reviews', diff, isCreateReviewResponse, 'create review response');\n }\n\n async appendReviewTurn(reviewId: string, diff: DiffPayload): Promise<CreateReviewTurnResponse> {\n return this.post(\n `/api/reviews/${reviewId}/turns`,\n diff,\n isCreateReviewTurnResponse,\n 'create review turn response'\n );\n }\n\n async getReview(reviewId: string): Promise<ReviewRecord> {\n return this.get(`/api/reviews/${reviewId}`, isReviewRecord, 'review response');\n }\n\n async listReviews(): Promise<ListReviewsResponse> {\n return this.get('/api/reviews', isListReviewsResponse, 'review list response');\n }\n\n async getFeedback(reviewId: string): Promise<FeedbackBundle> {\n return this.get(`/api/reviews/${reviewId}/feedback`, isFeedbackBundle, 'feedback response');\n }\n\n async markResolved(reviewId: string, summary?: string, turn?: string): Promise<ResolveResult> {\n const request: ResolutionRequest = { summary, turn };\n return this.post(\n `/api/reviews/${reviewId}/resolved`,\n request,\n isResolveResult,\n 'resolve response'\n );\n }\n\n async resolveComment(\n reviewId: string,\n commentId: string,\n summary?: string\n ): Promise<ResolveResult> {\n const request: ResolutionRequest = { summary };\n return this.post(\n `/api/reviews/${reviewId}/comments/${commentId}/resolved`,\n request,\n isResolveResult,\n 'resolve comment response'\n );\n }\n\n async reopenComment(reviewId: string, commentId: string): Promise<ResolveResult> {\n return this.delete(\n `/api/reviews/${reviewId}/comments/${commentId}/resolved`,\n isResolveResult,\n 'reopen comment response'\n );\n }\n\n async submitReview(reviewId: string, comments: Comment[]): Promise<OpenResult> {\n const request: SubmitReviewRequest = { comments };\n return this.post(\n `/api/reviews/${reviewId}/submit`,\n request,\n isOpenResult,\n 'submit review response'\n );\n }\n\n async watchReview(reviewId: string, timeoutSeconds?: number): Promise<ReviewEvent> {\n const deadline =\n timeoutSeconds && timeoutSeconds > 0 ? Date.now() + timeoutSeconds * 1000 : null;\n\n while (true) {\n const remainingMs = deadline ? deadline - Date.now() : null;\n if (remainingMs !== null && remainingMs <= 0) {\n throw new Error(`watch timed out after ${timeoutSeconds} seconds`);\n }\n\n const controller = new AbortController();\n const timeout = remainingMs ? setTimeout(() => controller.abort(), remainingMs) : null;\n try {\n return await this.readReviewEvents(reviewId, controller.signal);\n } catch (error) {\n if (isAbortError(error)) {\n throw new Error(`watch timed out after ${timeoutSeconds} seconds`);\n }\n if (!isPrematureWatchEnd(error)) {\n throw error;\n }\n await sleep(500);\n } finally {\n if (timeout) {\n clearTimeout(timeout);\n }\n }\n }\n }\n\n private async readReviewEvents(reviewId: string, signal: AbortSignal): Promise<ReviewEvent> {\n const response = await fetch(`${this.baseUrl}/api/reviews/${reviewId}/events`, {\n signal\n });\n if (!response.ok || !response.body) {\n throw new Error(`watch failed: ${response.status} ${await response.text()}`);\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n throw new Error('watch stream ended before completion');\n }\n buffer += decoder.decode(value, { stream: true });\n const events = buffer.split('\\n\\n');\n buffer = events.pop() ?? '';\n for (const eventChunk of events) {\n const dataLine = eventChunk.split('\\n').find((line) => line.startsWith('data:'));\n if (!dataLine) {\n continue;\n }\n const event = parseJson(dataLine.slice(5).trim(), isReviewEvent, 'review event');\n if (event.type === 'review.submitted' || event.type === 'review.cancelled') {\n await reader.cancel().catch(() => undefined);\n return event;\n }\n }\n }\n }\n\n private async get<T>(path: string, guard: JsonGuard<T>, label: string): Promise<T> {\n const response = await fetch(`${this.baseUrl}${path}`);\n return parseResponse(response, guard, label);\n }\n\n private async post<T>(\n path: string,\n body: DiffPayload | ResolutionRequest | SubmitReviewRequest,\n guard: JsonGuard<T>,\n label: string\n ): Promise<T> {\n const response = await fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body)\n });\n return parseResponse(response, guard, label);\n }\n\n private async delete<T>(path: string, guard: JsonGuard<T>, label: string): Promise<T> {\n const response = await fetch(`${this.baseUrl}${path}`, { method: 'DELETE' });\n return parseResponse(response, guard, label);\n }\n}\n\nasync function parseResponse<T>(\n response: Response,\n guard: JsonGuard<T>,\n label: string\n): Promise<T> {\n if (!response.ok) {\n throw new Error(`${response.status} ${response.statusText}: ${await response.text()}`);\n }\n const value: JsonValue = await response.json();\n return parseJsonValue(value, guard, label);\n}\n\nfunction isPrematureWatchEnd(error: unknown): error is Error {\n return error instanceof Error && error.message === 'watch stream ended before completion';\n}\n\nfunction isAbortError(error: unknown): error is Error {\n return error instanceof Error && error.name === 'AbortError';\n}\n\nasync function sleep(milliseconds: number): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\n","import { createHash } from 'node:crypto';\nimport type { Dirent } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { ulid } from 'ulid';\nimport { compareCommentsByLocation, countCommentFiles, resolutionCounts } from '../shared/comments';\nimport { formatError, isFileNotFound } from '../shared/errors';\nimport { writeJsonFile, writeTextFile } from '../shared/json';\nimport { serializeFeedbackMarkdown } from '../shared/markdown';\nimport {\n ensureDir,\n globalReviewDiffFile,\n globalReviewDir,\n globalReviewFeedbackFile,\n globalReviewMarkdownFile,\n globalReviewMetaFile,\n globalReviewResolvedFile,\n globalReviewsDir,\n globalReviewTurnDiffFile,\n globalReviewTurnDir,\n globalReviewTurnFeedbackFile,\n globalReviewTurnMarkdownFile,\n globalReviewTurnMetaFile,\n globalReviewTurnResolvedFile,\n globalReviewTurnsDir\n} from '../shared/paths';\nimport { normalizeReviewScope, sameReviewScope } from '../shared/review-scope';\nimport { isResolvableReviewStatus } from '../shared/reviews';\nimport type {\n Comment,\n DiffPayload,\n FeedbackBundle,\n ResolutionBundle,\n ResolvedComment,\n ResolveResult,\n ReviewEvent,\n ReviewMeta,\n ReviewRecord,\n ReviewScope,\n ReviewTurn,\n ReviewTurnMeta,\n ReviewTurnSummary,\n ReviewUpdateReason\n} from '../shared/types';\nimport {\n isDiffPayload,\n isFeedbackBundle,\n isResolutionBundle,\n isReviewTurnMeta,\n isStoredReviewMeta,\n type JsonGuard,\n parseJson,\n type StoredReviewMeta\n} from '../shared/validation';\n\ntype Listener = (event: ReviewEvent) => void;\n\ninterface SubmitResult {\n record: ReviewRecord;\n feedbackPath: string;\n markdownPath: string;\n turn: ReviewTurn;\n}\n\ninterface AppendTurnResult {\n record: ReviewRecord;\n turn: ReviewTurn;\n reused: boolean;\n}\n\nexport class ReviewStore {\n private readonly reviews = new Map<string, ReviewRecord>();\n private readonly listeners = new Map<string, Set<Listener>>();\n\n async create(diff: DiffPayload): Promise<ReviewRecord> {\n const id = ulid();\n const createdAt = new Date().toISOString();\n const turn = createTurn(id, 1, diff, createdAt);\n const meta: ReviewMeta = {\n id,\n cwd: diff.cwd,\n base: diff.base,\n branch: diff.branch,\n status: 'pending',\n createdAt,\n artifactDir: globalReviewDir(id),\n activeTurnId: turn.id\n };\n const record = normalizeRecord({ meta, turns: [turn], diff: turn.diff });\n this.reviews.set(id, record);\n await this.persistInitial(record, turn);\n this.emit({ type: 'review.opened', reviewId: id });\n return record;\n }\n\n async appendTurn(id: string, diff: DiffPayload): Promise<AppendTurnResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n if (record.meta.cwd !== diff.cwd) {\n throw new Error(`Review ${id} belongs to ${record.meta.cwd}, not ${diff.cwd}`);\n }\n\n const latest = latestTurn(record);\n if (latest.status === 'pending') {\n if (diffFingerprint(latest.diff) === diffFingerprint(diff)) {\n this.emit({\n type: 'review.turn.created',\n reviewId: id,\n turnId: latest.id,\n turnIndex: latest.index,\n reused: true\n });\n return { record, turn: latest, reused: true };\n }\n throw new Error(`Review ${id} already has a pending turn`);\n }\n if (latest.status === 'cancelled') {\n throw new Error(`Review ${id} is cancelled and cannot be continued`);\n }\n\n const turn = createTurn(id, latest.index + 1, diff, new Date().toISOString());\n const nextRecord = normalizeRecord({\n ...record,\n meta: { ...record.meta, activeTurnId: turn.id },\n turns: [...record.turns, turn]\n });\n this.reviews.set(id, nextRecord);\n await this.persistInitial(nextRecord, turn);\n this.emit({\n type: 'review.turn.created',\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n reused: false\n });\n return { record: nextRecord, turn, reused: false };\n }\n\n async list(): Promise<ReviewMeta[]> {\n await this.loadAllReviews();\n return Array.from(this.reviews.values())\n .map((record) => record.meta)\n .toSorted((a, b) => a.createdAt.localeCompare(b.createdAt));\n }\n\n async get(id: string): Promise<ReviewRecord | null> {\n return this.reviews.get(id) ?? (await this.loadKnownReview(id));\n }\n\n async getTurn(id: string, turnId: string): Promise<ReviewTurn | null> {\n const record = await this.get(id);\n return record?.turns.find((turn) => turn.id === turnId) ?? null;\n }\n\n async submit(id: string, comments: Comment[], reviewScope?: ReviewScope): Promise<SubmitResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = activeTurn(record);\n const sortedComments = comments.toSorted(compareCommentsByLocation);\n const normalizedReviewScope = normalizeReviewScope(turn.diff, reviewScope);\n if (turn.status !== 'pending') {\n if (\n turn.feedback &&\n sameComments(turn.feedback.comments, sortedComments) &&\n sameReviewScope(turn.feedback.reviewScope, normalizedReviewScope)\n ) {\n return {\n record,\n feedbackPath: requiredPath(turn.feedbackPath, 'feedback path'),\n markdownPath: requiredPath(turn.markdownPath, 'markdown path'),\n turn\n };\n }\n throw new Error(`Review ${id} turn ${turn.index} is ${turn.status} and cannot be submitted`);\n }\n\n const timestamp = new Date().toISOString();\n const feedbackPath = globalReviewTurnFeedbackFile(id, turn.id);\n const markdownPath = globalReviewTurnMarkdownFile(id, turn.id);\n const feedback: FeedbackBundle = {\n version: 1,\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n timestamp,\n base: turn.diff.base,\n branch: turn.diff.branch,\n reviewScope: normalizedReviewScope,\n comments: sortedComments\n };\n const nextTurn: ReviewTurn = {\n ...turn,\n status: 'submitted',\n submittedAt: timestamp,\n feedbackPath,\n markdownPath,\n feedback\n };\n const nextRecord = normalizeRecord(replaceTurn(record, nextTurn));\n this.reviews.set(id, nextRecord);\n\n await ensureDir(globalReviewTurnDir(id, nextTurn.id));\n await Promise.all([\n writeJsonFile(globalReviewTurnMetaFile(id, nextTurn.id), turnMeta(nextTurn)),\n writeJsonFile(feedbackPath, feedback),\n writeTextFile(markdownPath, serializeFeedbackMarkdown(feedback))\n ]);\n await this.persistMeta(nextRecord);\n\n this.emit({\n type: 'review.submitted',\n reviewId: id,\n turnId: nextTurn.id,\n turnIndex: nextTurn.index,\n counts: {\n files: countCommentFiles(feedback.comments),\n comments: feedback.comments.length\n }\n });\n return { record: nextRecord, feedbackPath, markdownPath, turn: nextTurn };\n }\n\n async feedback(id: string): Promise<FeedbackBundle | null> {\n const record = await this.get(id);\n return record?.feedback ?? null;\n }\n\n async markResolved(id: string, summary?: string, turnSelector?: string): Promise<ResolveResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = this.resolveTurnSelector(record, turnSelector);\n this.assertResolvable(turn, id);\n\n const resolvedAt = new Date().toISOString();\n const existingById = new Map(\n (turn.resolution?.comments ?? []).map((comment) => [comment.commentId, comment])\n );\n const comments = this.sortResolvedComments(\n (turn.feedback?.comments ?? []).map((comment) => ({\n ...existingById.get(comment.id),\n commentId: comment.id,\n status: 'resolved' as const,\n resolvedAt: existingById.get(comment.id)?.resolvedAt ?? resolvedAt\n })),\n turn\n );\n const resolution: ResolutionBundle = {\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n status: 'resolved',\n summary: summary ?? turn.resolution?.summary ?? null,\n resolvedAt,\n comments\n };\n const nextTurn: ReviewTurn & { feedback: FeedbackBundle } = {\n ...turn,\n status: 'resolved',\n resolvedAt\n };\n return this.persistResolution(record, nextTurn, resolution, 'review-resolved');\n }\n\n async resolveComment(id: string, commentId: string, summary?: string): Promise<ResolveResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = this.findTurnForComment(record, commentId);\n if (!turn) {\n const currentTurn = activeTurn(record);\n if (!isResolvableReviewStatus(currentTurn.status)) {\n throw new Error(\n `Review ${id} turn ${currentTurn.index} is ${currentTurn.status} and cannot be resolved`\n );\n }\n throw new Error(`Comment ${commentId} not found`);\n }\n this.assertResolvable(turn, id);\n\n const resolvedAt = new Date().toISOString();\n const previous = turn.resolution?.comments.find((comment) => comment.commentId === commentId);\n const nextSummary = summary ?? previous?.summary;\n const nextComment: ResolvedComment = {\n commentId,\n status: 'resolved',\n ...(nextSummary ? { summary: nextSummary } : {}),\n resolvedAt\n };\n const comments = this.sortResolvedComments(\n [\n ...(turn.resolution?.comments ?? []).filter((comment) => comment.commentId !== commentId),\n nextComment\n ],\n turn\n );\n const counts = resolutionCounts(turn.feedback, comments);\n const fullyResolved = counts.total === counts.resolved;\n const resolution: ResolutionBundle = {\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n status: fullyResolved ? 'resolved' : 'partial',\n summary: fullyResolved ? (turn.resolution?.summary ?? null) : null,\n resolvedAt: fullyResolved ? resolvedAt : null,\n comments\n };\n const nextTurn: ReviewTurn & { feedback: FeedbackBundle } = fullyResolved\n ? { ...turn, status: 'resolved', resolvedAt }\n : { ...turn, status: 'submitted', resolvedAt: undefined };\n return this.persistResolution(record, nextTurn, resolution, 'comment-resolved');\n }\n\n async reopenComment(id: string, commentId: string): Promise<ResolveResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = this.findTurnForComment(record, commentId);\n if (!turn) {\n const currentTurn = activeTurn(record);\n if (!isResolvableReviewStatus(currentTurn.status)) {\n throw new Error(\n `Review ${id} turn ${currentTurn.index} is ${currentTurn.status} and cannot be resolved`\n );\n }\n throw new Error(`Comment ${commentId} not found`);\n }\n this.assertResolvable(turn, id);\n\n const comments = this.sortResolvedComments(\n (turn.resolution?.comments ?? []).filter((comment) => comment.commentId !== commentId),\n turn\n );\n const counts = resolutionCounts(turn.feedback, comments);\n const fullyResolved = counts.total > 0 && counts.total === counts.resolved;\n const resolvedAt = fullyResolved ? new Date().toISOString() : null;\n const resolution: ResolutionBundle = {\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n status: fullyResolved ? 'resolved' : 'partial',\n summary: fullyResolved ? (turn.resolution?.summary ?? null) : null,\n resolvedAt,\n comments\n };\n const nextTurn: ReviewTurn & { feedback: FeedbackBundle } = fullyResolved\n ? { ...turn, status: 'resolved', resolvedAt: resolvedAt ?? undefined }\n : { ...turn, status: 'submitted', resolvedAt: undefined };\n return this.persistResolution(record, nextTurn, resolution, 'comment-reopened');\n }\n\n subscribe(reviewId: string, listener: Listener): () => void {\n const listeners = this.listeners.get(reviewId) ?? new Set<Listener>();\n listeners.add(listener);\n this.listeners.set(reviewId, listeners);\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0) {\n this.listeners.delete(reviewId);\n }\n };\n }\n\n private emit(event: ReviewEvent): void {\n for (const listener of this.listeners.get(event.reviewId) ?? []) {\n listener(event);\n }\n }\n\n private async persistInitial(record: ReviewRecord, turn: ReviewTurn): Promise<void> {\n await ensureDir(turn.artifactDir);\n await Promise.all([\n writeJsonFile(globalReviewTurnMetaFile(record.meta.id, turn.id), turnMeta(turn)),\n writeJsonFile(turn.diffPath, turn.diff)\n ]);\n await this.persistMeta(record);\n }\n\n private async persistMeta(record: ReviewRecord): Promise<void> {\n await ensureDir(globalReviewDir(record.meta.id));\n await writeJsonFile(globalReviewMetaFile(record.meta.id), record.meta);\n }\n\n private async loadKnownReview(id: string): Promise<ReviewRecord | null> {\n const existing = this.reviews.get(id);\n if (existing) {\n return existing;\n }\n\n return this.loadReview(id);\n }\n\n private async loadAllReviews(): Promise<void> {\n let entries: Dirent[];\n try {\n entries = await readdir(globalReviewsDir(), { withFileTypes: true });\n } catch (error) {\n if (isFileNotFound(error)) {\n return;\n }\n throw new Error(\n `Could not read reviews directory at ${globalReviewsDir()}: ${formatError(error)}`,\n {\n cause: error\n }\n );\n }\n\n const reviewLoads: Array<Promise<ReviewRecord | null>> = [];\n for (const entry of entries) {\n if (entry.isDirectory()) {\n reviewLoads.push(this.loadReview(entry.name));\n }\n }\n await Promise.all(reviewLoads);\n }\n\n private async loadReview(id: string): Promise<ReviewRecord | null> {\n const metaPath = globalReviewMetaFile(id);\n let metaRaw: string;\n\n try {\n metaRaw = await readFile(metaPath, 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return this.loadReviewFromTurnsOnly(id);\n }\n throw new Error(`Could not load review ${id}: ${formatError(error)}`, { cause: error });\n }\n\n const storedMeta = parseJsonFile(metaRaw, isStoredReviewMeta, 'review metadata', metaPath);\n const persistedTurns = await this.loadPersistedTurns(id);\n const legacyTurn = await this.loadLegacyTurn(id, storedMeta);\n const turns = mergeRecoveredTurns(legacyTurn, persistedTurns);\n if (turns.length === 0) {\n throw new Error(`Review ${id} has no recoverable turns`);\n }\n\n const latest = latestTurn({ turns } as ReviewRecord);\n const record = normalizeRecord({\n meta: {\n ...storedMeta,\n artifactDir: storedMeta.artifactDir ?? globalReviewDir(id),\n activeTurnId: latest.id\n },\n turns,\n diff: latest.diff\n });\n this.reviews.set(id, record);\n return record;\n }\n\n private async loadReviewFromTurnsOnly(id: string): Promise<ReviewRecord | null> {\n const turns = await this.loadPersistedTurns(id);\n if (turns.length === 0) {\n return null;\n }\n\n const latest = latestTurn({ turns });\n const record = normalizeRecord({\n meta: {\n id,\n cwd: latest.diff.cwd,\n base: latest.diff.base,\n branch: latest.diff.branch,\n status: latest.status,\n createdAt: turns[0]?.createdAt ?? latest.createdAt,\n artifactDir: globalReviewDir(id),\n activeTurnId: latest.id\n },\n turns,\n diff: latest.diff\n });\n this.reviews.set(id, record);\n await this.persistMeta(record);\n return record;\n }\n\n private async loadPersistedTurns(id: string): Promise<ReviewTurn[]> {\n let entries: Dirent[];\n try {\n entries = await readdir(globalReviewTurnsDir(id), { withFileTypes: true });\n } catch (error) {\n if (isFileNotFound(error)) {\n return [];\n }\n throw new Error(`Could not read review turns for ${id}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n const turns: ReviewTurn[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) {\n continue;\n }\n const turn = await this.loadPersistedTurn(id, entry.name);\n if (turn) {\n turns.push(turn);\n }\n }\n\n return turns.toSorted((a, b) => a.index - b.index);\n }\n\n private async loadPersistedTurn(id: string, turnId: string): Promise<ReviewTurn | null> {\n const metaPath = globalReviewTurnMetaFile(id, turnId);\n const diffPath = globalReviewTurnDiffFile(id, turnId);\n let metaRaw: string;\n let diffRaw: string;\n\n try {\n [metaRaw, diffRaw] = await Promise.all([\n readFile(metaPath, 'utf8'),\n readFile(diffPath, 'utf8')\n ]);\n } catch (error) {\n if (isFileNotFound(error)) {\n return null;\n }\n throw new Error(`Could not load review ${id} turn ${turnId}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n const meta = parseJsonFile(metaRaw, isReviewTurnMeta, 'review turn metadata', metaPath);\n const diff = parseJsonFile(diffRaw, isDiffPayload, 'review turn diff', diffPath);\n const [feedback, resolution] = await Promise.all([\n readOptionalJsonFile(\n globalReviewTurnFeedbackFile(id, turnId),\n isFeedbackBundle,\n 'review feedback'\n ),\n readOptionalJsonFile(\n globalReviewTurnResolvedFile(id, turnId),\n isResolutionBundle,\n 'review resolution'\n )\n ]);\n\n return reconcileTurn(meta, diff, feedback, resolution);\n }\n\n private async loadLegacyTurn(\n id: string,\n storedMeta: StoredReviewMeta\n ): Promise<ReviewTurn | null> {\n const diffPath = globalReviewDiffFile(id);\n let diffRaw: string;\n try {\n diffRaw = await readFile(diffPath, 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return null;\n }\n throw new Error(`Could not load legacy review ${id}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n const diff = parseJsonFile(diffRaw, isDiffPayload, 'review diff', diffPath);\n const [feedback, resolution] = await Promise.all([\n readOptionalJsonFile(globalReviewFeedbackFile(id), isFeedbackBundle, 'review feedback'),\n readOptionalJsonFile(globalReviewResolvedFile(id), isResolutionBundle, 'review resolution')\n ]);\n const artifactDir = storedMeta.artifactDir ?? globalReviewDir(id);\n const legacySummary =\n storedMeta.turns?.find(\n (turn) => turn.artifactDir === artifactDir || turn.diffPath === diffPath\n ) ??\n storedMeta.turns?.find((turn) => turn.index === 1) ??\n storedMeta.turns?.[0];\n const meta: ReviewTurnMeta = {\n id: legacySummary?.id ?? storedMeta.activeTurnId ?? 'turn-1',\n index: legacySummary?.index ?? 1,\n status: legacySummary?.status ?? storedMeta.status,\n createdAt: legacySummary?.createdAt ?? storedMeta.createdAt,\n submittedAt: legacySummary?.submittedAt ?? storedMeta.submittedAt,\n resolvedAt: legacySummary?.resolvedAt ?? storedMeta.resolvedAt,\n artifactDir: legacySummary?.artifactDir ?? artifactDir,\n diffPath,\n ...(feedback\n ? { feedbackPath: globalReviewFeedbackFile(id), markdownPath: globalReviewMarkdownFile(id) }\n : {}),\n ...(resolution ? { resolvedPath: globalReviewResolvedFile(id) } : {})\n };\n return reconcileTurn(meta, diff, feedback, resolution);\n }\n\n private assertResolvable(\n turn: ReviewTurn,\n id: string\n ): asserts turn is ReviewTurn & {\n feedback: FeedbackBundle;\n } {\n if (!isResolvableReviewStatus(turn.status)) {\n throw new Error(`Review ${id} turn ${turn.index} is ${turn.status} and cannot be resolved`);\n }\n if (!turn.feedback) {\n throw new Error(`Review ${id} turn ${turn.index} has no submitted feedback`);\n }\n }\n\n private resolveTurnSelector(record: ReviewRecord, selector?: string): ReviewTurn {\n if (!selector) {\n return activeTurn(record);\n }\n const turn =\n record.turns.find((candidate) => candidate.id === selector) ??\n record.turns.find((candidate) => String(candidate.index) === selector);\n if (!turn) {\n throw new Error(`Turn ${selector} not found in review ${record.meta.id}`);\n }\n return turn;\n }\n\n private findTurnForComment(record: ReviewRecord, commentId: string): ReviewTurn | null {\n return (\n [...record.turns]\n .reverse()\n .find((candidate) =>\n candidate.feedback?.comments.some((comment) => comment.id === commentId)\n ) ?? null\n );\n }\n\n private async persistResolution(\n record: ReviewRecord,\n turn: ReviewTurn & { feedback: FeedbackBundle },\n resolution: ResolutionBundle,\n reason: ReviewUpdateReason\n ): Promise<ResolveResult> {\n const resolvedPath = globalReviewTurnResolvedFile(record.meta.id, turn.id);\n const nextTurn: ReviewTurn = {\n ...turn,\n resolvedPath,\n resolution\n };\n const nextRecord = normalizeRecord(replaceTurn(record, nextTurn));\n this.reviews.set(record.meta.id, nextRecord);\n await ensureDir(globalReviewTurnDir(record.meta.id, nextTurn.id));\n await Promise.all([\n writeJsonFile(resolvedPath, resolution),\n writeJsonFile(globalReviewTurnMetaFile(record.meta.id, nextTurn.id), turnMeta(nextTurn))\n ]);\n await this.persistMeta(nextRecord);\n const result: ResolveResult = {\n ok: true,\n reviewId: record.meta.id,\n turnId: nextTurn.id,\n turnIndex: nextTurn.index,\n status: nextTurn.status,\n resolutionStatus: resolution.status,\n comments: resolutionCounts(nextTurn.feedback, resolution.comments),\n path: resolvedPath,\n resolution\n };\n this.emit({\n type: 'review.updated',\n reviewId: record.meta.id,\n turnId: nextTurn.id,\n turnIndex: nextTurn.index,\n reason,\n status: result.status,\n resolutionStatus: result.resolutionStatus,\n counts: result.comments\n });\n return result;\n }\n\n private sortResolvedComments(\n comments: ResolvedComment[],\n turn: ReviewTurn & { feedback: FeedbackBundle }\n ): ResolvedComment[] {\n const feedbackIndex = new Map(\n turn.feedback.comments.map((comment, index) => [comment.id, index] as const)\n );\n return comments\n .map((comment) => ({ comment, index: feedbackIndex.get(comment.commentId) }))\n .filter(\n (entry): entry is { comment: ResolvedComment; index: number } => entry.index !== undefined\n )\n .sort((a, b) => a.index - b.index)\n .map(({ comment }) => comment);\n }\n}\n\nfunction createTurn(\n reviewId: string,\n index: number,\n diff: DiffPayload,\n createdAt: string\n): ReviewTurn {\n const id = ulid();\n return {\n id,\n index,\n status: 'pending',\n createdAt,\n artifactDir: globalReviewTurnDir(reviewId, id),\n diffPath: globalReviewTurnDiffFile(reviewId, id),\n diff\n };\n}\n\nfunction normalizeRecord(record: Pick<ReviewRecord, 'meta' | 'turns' | 'diff'>): ReviewRecord {\n const turns = record.turns.toSorted((a, b) => a.index - b.index);\n const active =\n turns.find((turn) => turn.id === record.meta.activeTurnId) ?? turns[turns.length - 1];\n const meta: ReviewMeta = {\n ...record.meta,\n base: active.diff.base,\n branch: active.diff.branch,\n status: active.status,\n submittedAt: active.submittedAt,\n resolvedAt: active.resolvedAt,\n artifactDir: record.meta.artifactDir ?? globalReviewDir(record.meta.id),\n activeTurnId: active.id,\n turns: turns.map(turnSummary),\n feedbackPath: active.feedbackPath,\n markdownPath: active.markdownPath\n };\n return {\n meta,\n turns,\n diff: active.diff,\n ...(active.feedback ? { feedback: active.feedback } : {}),\n ...(active.resolution ? { resolution: active.resolution } : {})\n };\n}\n\nfunction replaceTurn(record: ReviewRecord, nextTurn: ReviewTurn): ReviewRecord {\n return {\n ...record,\n turns: record.turns.map((turn) => (turn.id === nextTurn.id ? nextTurn : turn))\n };\n}\n\nfunction activeTurn(record: ReviewRecord): ReviewTurn {\n return (\n record.turns.find((turn) => turn.id === record.meta.activeTurnId) ??\n record.turns[record.turns.length - 1]\n );\n}\n\nfunction latestTurn(record: Pick<ReviewRecord, 'turns'>): ReviewTurn {\n return record.turns.toSorted((a, b) => a.index - b.index)[record.turns.length - 1];\n}\n\nfunction turnMeta(turn: ReviewTurn): ReviewTurnMeta {\n return {\n id: turn.id,\n index: turn.index,\n status: turn.status,\n createdAt: turn.createdAt,\n submittedAt: turn.submittedAt,\n resolvedAt: turn.resolvedAt,\n artifactDir: turn.artifactDir,\n diffPath: turn.diffPath,\n feedbackPath: turn.feedbackPath,\n markdownPath: turn.markdownPath,\n resolvedPath: turn.resolvedPath\n };\n}\n\nfunction turnSummary(turn: ReviewTurn): ReviewTurnSummary {\n return {\n ...turnMeta(turn),\n capturedAt: turn.diff.capturedAt,\n stats: turn.diff.stats,\n comments: resolutionCounts(turn.feedback, turn.resolution?.comments ?? [])\n };\n}\n\nfunction reconcileTurn(\n meta: ReviewTurnMeta,\n diff: DiffPayload,\n feedback?: FeedbackBundle,\n resolution?: ResolutionBundle\n): ReviewTurn {\n const status =\n resolution?.status === 'resolved' ? 'resolved' : feedback ? 'submitted' : 'pending';\n return {\n ...meta,\n status,\n submittedAt: feedback?.timestamp ?? meta.submittedAt,\n resolvedAt: status === 'resolved' ? (resolution?.resolvedAt ?? meta.resolvedAt) : undefined,\n feedbackPath: feedback\n ? (meta.feedbackPath ?? path.join(meta.artifactDir, 'feedback.json'))\n : undefined,\n markdownPath: feedback\n ? (meta.markdownPath ?? path.join(meta.artifactDir, 'feedback.md'))\n : undefined,\n resolvedPath: resolution\n ? (meta.resolvedPath ?? path.join(meta.artifactDir, 'resolved.json'))\n : undefined,\n diff,\n ...(feedback ? { feedback } : {}),\n ...(resolution ? { resolution } : {})\n };\n}\n\nfunction mergeRecoveredTurns(\n legacyTurn: ReviewTurn | null,\n persistedTurns: ReviewTurn[]\n): ReviewTurn[] {\n const turns =\n legacyTurn &&\n !persistedTurns.some((turn) => turn.id === legacyTurn.id || turn.index === legacyTurn.index)\n ? [legacyTurn, ...persistedTurns]\n : persistedTurns;\n return turns.toSorted((a, b) => a.index - b.index);\n}\n\nfunction diffFingerprint(diff: DiffPayload): string {\n return createHash('sha256')\n .update(\n JSON.stringify({\n base: diff.base,\n branch: diff.branch,\n cwd: diff.cwd,\n scope: diff.scope,\n rawDiff: diff.rawDiff\n })\n )\n .digest('hex');\n}\n\nfunction sameComments(left: Comment[], right: Comment[]): boolean {\n return (\n JSON.stringify(left.toSorted(compareCommentsByLocation)) ===\n JSON.stringify(right.toSorted(compareCommentsByLocation))\n );\n}\n\nfunction requiredPath(value: string | undefined, label: string): string {\n if (!value) {\n throw new Error(`Submitted review is missing ${label}`);\n }\n return value;\n}\n\nasync function readOptionalJsonFile<T>(\n filePath: string,\n guard: JsonGuard<T>,\n label: string\n): Promise<T | undefined> {\n let raw: string;\n try {\n raw = await readFile(filePath, 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return undefined;\n }\n throw new Error(`Could not read ${label} at ${filePath}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n return parseJsonFile(raw, guard, label, filePath);\n}\n\nfunction parseJsonFile<T>(raw: string, guard: JsonGuard<T>, label: string, filePath: string): T {\n try {\n return parseJson(raw, guard, label);\n } catch (error) {\n throw new Error(`Invalid ${label} at ${filePath}: ${formatError(error)}`, { cause: error });\n }\n}\n\nexport const reviewStore = new ReviewStore();\n","import type {\n Comment,\n FeedbackBundle,\n ResolutionBundle,\n ResolutionCounts,\n ResolvedComment,\n Side\n} from './types';\n\nexport interface LineRange {\n side: Side;\n startLine: number;\n endLine: number;\n}\n\nexport function compareCommentsByLocation(a: Comment, b: Comment): number {\n return (\n a.filePath.localeCompare(b.filePath) ||\n a.startLine - b.startLine ||\n a.endLine - b.endLine ||\n a.side.localeCompare(b.side)\n );\n}\n\nexport function countCommentFiles(comments: Pick<Comment, 'filePath'>[]): number {\n return new Set(comments.map((comment) => comment.filePath)).size;\n}\n\nexport function formatLineRange(\n range: LineRange,\n options: { repeatSideOnEnd?: boolean } = {}\n): string {\n const startLine = Math.min(range.startLine, range.endLine);\n const endLine = Math.max(range.startLine, range.endLine);\n if (startLine === endLine) {\n return `${range.side}${startLine}`;\n }\n const endPrefix = options.repeatSideOnEnd === false ? '' : range.side;\n return `${range.side}${startLine}-${endPrefix}${endLine}`;\n}\n\nexport function resolutionCounts(\n feedback: FeedbackBundle | undefined,\n resolvedComments: ResolvedComment[] = []\n): ResolutionCounts {\n const comments = feedback?.comments ?? [];\n const resolvedIds = new Set(resolvedComments.map((comment) => comment.commentId));\n const resolved = comments.filter((comment) => resolvedIds.has(comment.id)).length;\n return {\n total: comments.length,\n resolved,\n open: comments.length - resolved\n };\n}\n\nexport function reviewResolutionCounts(record: {\n feedback?: FeedbackBundle;\n resolution?: ResolutionBundle;\n}): ResolutionCounts {\n return resolutionCounts(record.feedback, record.resolution?.comments ?? []);\n}\n","import type { CommitDiff, DiffPayload, ReviewScope } from './types';\n\nconst ALL_REVIEW_SCOPE: ReviewScope = { mode: 'all' };\n\nexport function normalizeReviewScope(\n diff: Pick<DiffPayload, 'commitDiffs'>,\n scope: ReviewScope = ALL_REVIEW_SCOPE\n): ReviewScope {\n if (scope.mode === 'all') {\n return ALL_REVIEW_SCOPE;\n }\n\n const commitDiffs = diff.commitDiffs ?? [];\n if (commitDiffs.length === 0) {\n throw new Error('Review scope requires a review with per-commit diffs');\n }\n\n if (scope.mode === 'single') {\n const commit = commitDiffs.find((commitDiff) => commitDiff.commit.sha === scope.sha);\n if (!commit) {\n throw new Error('Review scope must use commits from this review');\n }\n return { mode: 'single', sha: commit.commit.sha };\n }\n\n const fromIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === scope.fromSha);\n const toIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === scope.toSha);\n if (fromIndex < 0 || toIndex < 0) {\n throw new Error('Review scope must use commits from this review');\n }\n if (fromIndex > toIndex) {\n throw new Error('Review scope range must be in review order');\n }\n return {\n mode: 'range',\n fromSha: commitDiffs[fromIndex].commit.sha,\n toSha: commitDiffs[toIndex].commit.sha\n };\n}\n\nexport function sameReviewScope(left?: ReviewScope, right?: ReviewScope): boolean {\n return JSON.stringify(left ?? ALL_REVIEW_SCOPE) === JSON.stringify(right ?? ALL_REVIEW_SCOPE);\n}\n\nexport function reviewScopeLabel(\n scope: ReviewScope = ALL_REVIEW_SCOPE,\n commitDiffs: CommitDiff[] = []\n): string {\n if (scope.mode === 'all') {\n return 'All commits';\n }\n if (scope.mode === 'single') {\n const commit = commitDiffs.find((commitDiff) => commitDiff.commit.sha === scope.sha);\n return commit\n ? `${commit.commit.shortSha} ${commit.commit.subject}`\n : `Commit ${shortSha(scope.sha)}`;\n }\n\n const fromIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === scope.fromSha);\n const toIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === scope.toSha);\n if (fromIndex >= 0 && toIndex >= fromIndex) {\n const count = toIndex - fromIndex + 1;\n return `${count} commits · ${commitDiffs[fromIndex].commit.shortSha} to ${\n commitDiffs[toIndex].commit.shortSha\n }`;\n }\n return `Commit range ${shortSha(scope.fromSha)} to ${shortSha(scope.toSha)}`;\n}\n\nfunction shortSha(sha: string): string {\n return sha.slice(0, 7);\n}\n","import { compareCommentsByLocation, formatLineRange } from './comments';\nimport { languageForPath } from './language';\nimport { reviewScopeLabel } from './review-scope';\nimport type { FeedbackBundle } from './types';\n\nfunction fenceFor(snippet: string): string {\n let fence = '```';\n while (snippet.includes(fence)) {\n fence += '`';\n }\n return fence;\n}\n\nfunction languageForSnippet(filePath: string, snippet: string): string {\n const lines = snippet.split('\\n').filter((line) => line.length > 0);\n const looksLikeUnifiedDiff =\n lines.length > 0 &&\n lines.some((line) => line.startsWith('+') || line.startsWith('-')) &&\n lines.every((line) => line.startsWith('+') || line.startsWith('-') || line.startsWith(' '));\n return looksLikeUnifiedDiff ? 'diff' : (languageForPath(filePath) ?? '');\n}\n\nexport function serializeFeedbackMarkdown(bundle: FeedbackBundle): string {\n const comments = bundle.comments.toSorted(compareCommentsByLocation);\n const commentsByFile = new Map<string, typeof comments>();\n const files: string[] = [];\n for (const comment of comments) {\n const fileComments = commentsByFile.get(comment.filePath);\n if (fileComments) {\n fileComments.push(comment);\n } else {\n commentsByFile.set(comment.filePath, [comment]);\n files.push(comment.filePath);\n }\n }\n const lines: string[] = [\n `# Gloss feedback - ${bundle.timestamp}`,\n `Review: ${bundle.reviewId}`,\n ...(bundle.turnIndex ? [`Turn: ${bundle.turnIndex} (${bundle.turnId ?? 'unknown'})`] : []),\n ...(bundle.reviewScope ? [`Review scope: ${reviewScopeLabel(bundle.reviewScope)}`] : []),\n `Base: ${bundle.base.ref} (${bundle.base.sha.slice(0, 7)}) Branch: ${bundle.branch ?? '(detached)'}`,\n `Files: ${files.length} Comments: ${comments.length}`,\n ''\n ];\n\n for (const filePath of files) {\n lines.push(`## ${filePath}`, '');\n for (const comment of commentsByFile.get(filePath) ?? []) {\n const snippet = comment.originalSnippet.trimEnd();\n const firstSnippetLine = firstNonEmptyLine(snippet);\n const heading =\n comment.startLine === comment.endLine && firstSnippetLine\n ? `### ${formatLineRange(comment)} - \\`${firstSnippetLine.trim().slice(0, 80)}\\``\n : `### ${formatLineRange(comment)}`;\n lines.push(heading, comment.body.trim(), '');\n if (snippet) {\n const fence = fenceFor(snippet);\n lines.push(`${fence}${languageForSnippet(comment.filePath, snippet)}`, snippet, fence, '');\n }\n }\n }\n\n return `${lines.join('\\n').trimEnd()}\\n`;\n}\n\nfunction firstNonEmptyLine(text: string): string | undefined {\n for (const line of text.split('\\n')) {\n if (line.trim().length > 0) {\n return line;\n }\n }\n return undefined;\n}\n","import type { ReviewStatus } from './types';\n\nexport function isResolvableReviewStatus(status: ReviewStatus): boolean {\n return status === 'submitted' || status === 'resolved';\n}\n","import { ReviewStore } from '../server/store';\nimport type { ReviewMeta, ServerInfo } from '../shared/types';\nimport { serverUrl } from './lifecycle';\nimport { ServerClient } from './server-client';\n\nexport async function listReviewsForStatus({\n responsive,\n server\n}: {\n responsive: boolean;\n server: ServerInfo | null;\n}): Promise<ReviewMeta[]> {\n if (server && responsive) {\n try {\n return (await new ServerClient(serverUrl(server)).listReviews()).reviews;\n } catch {\n // Fall through to durable state if the daemon disappears between health and list.\n }\n }\n\n return new ReviewStore().list();\n}\n"],"mappings":"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","names":["path","shortSha","rawDiff","rm","path","path","info","rm","readFile","path","readFile","path","result","sleep"]}
1
+ {"version":3,"sources":["../../src/cli/index.ts","../../src/shared/cleanup.ts","../../src/shared/errors.ts","../../src/shared/paths.ts","../../package.json","../../src/shared/types.ts","../../src/shared/validation.ts","../../src/cli/git.ts","../../src/shared/language.ts","../../src/shared/diff-parser.ts","../../src/shared/diff-stats.ts","../../src/cli/lifecycle.ts","../../src/shared/server-info.ts","../../src/shared/json.ts","../../src/cli/server-client.ts","../../src/server/store.ts","../../src/shared/comments.ts","../../src/shared/review-scope.ts","../../src/shared/markdown.ts","../../src/shared/reviews.ts","../../src/cli/status.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport openBrowser from 'open';\nimport { clearReviewArtifacts, DEFAULT_REVIEW_RETENTION_DAYS } from '../shared/cleanup';\nimport { packageVersion } from '../shared/paths';\nimport type {\n ClearReviewsResult,\n DiffPayload,\n FeedbackBundle,\n ResolveResult,\n ReviewEvent,\n ReviewMeta,\n ServerInfo\n} from '../shared/types';\nimport { assertGitAvailable, captureDiff, getRepoRoot } from './git';\nimport {\n ensureServer,\n isServerResponsive,\n listGlossDaemonPids,\n readServerInfo,\n serverUrl,\n startServer,\n stopServer\n} from './lifecycle';\nimport { ServerClient } from './server-client';\nimport { listReviewsForStatus } from './status';\n\ninterface GlobalOptions {\n json?: boolean;\n noColor?: boolean;\n}\n\ntype DoctorCheck = { name: string; ok: boolean; detail?: string };\n\ntype CliJsonOutput =\n | ServerInfo\n | ReviewEvent\n | ResolveResult\n | { stopped: boolean; info: ServerInfo | null; stoppedPids?: number[] }\n | ClearReviewsResult\n | {\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n url: string;\n files: number;\n scope: DiffPayload['scope']['mode'];\n artifactDir: string;\n reused?: boolean;\n }\n | {\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n url: string;\n files: number;\n comments: number;\n feedbackPath: string;\n markdownPath: string;\n artifactDir: string;\n feedback: FeedbackBundle;\n reused?: boolean;\n }\n | { running: boolean; server: ServerInfo | null; reviews: ReviewMeta[] }\n | (ResolveResult & { commentId: string | null; summary: string | null })\n | (ResolveResult & { commentId: string | null; summary: string | null; turn: string | null })\n | { checks: DoctorCheck[] };\n\nfunction printJson(value: CliJsonOutput): void {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\nfunction printPlain(value: string): void {\n process.stdout.write(`${value}\\n`);\n}\n\nconst program = new Command();\n\nprogram\n .name('gloss')\n .description('Local browser-based diff review for coding-agent loops.')\n .version(packageVersion)\n .option('--json', 'print JSON for supported commands')\n .option('--no-color', 'disable color output');\n\nprogram\n .command('open')\n .description('Capture local changes and open them for review')\n .option('--base <ref>', 'explicit base git ref')\n .option('--review <reviewId>', 'append or resume a turn in an existing review')\n .option('--print-url', 'print review URL')\n .option('--no-open', 'do not open a browser')\n .option('--no-watch', 'return immediately after registering the review')\n .option('--timeout <seconds>', 'watch timeout in seconds', Number)\n .action(\n async (options: {\n base?: string;\n printUrl?: boolean;\n open?: boolean;\n review?: string;\n watch?: boolean;\n timeout?: number;\n }) => {\n const globals = program.opts<GlobalOptions>();\n let info = await ensureServer();\n let client = new ServerClient(serverUrl(info));\n const inheritedBase =\n options.review && !options.base\n ? await baseForExistingReview(client, options.review)\n : null;\n const diff = await captureDiff(options.base ?? inheritedBase ?? undefined);\n const created = options.review\n ? await client.appendReviewTurn(options.review, diff)\n : await client.createReview(diff);\n const meta = created.meta;\n const turn = created.turn ?? meta.turns?.find((summary) => summary.id === meta.activeTurnId);\n if (!turn) {\n throw new Error(`Review ${meta.id} has no active turn`);\n }\n const reused = 'reused' in created ? created.reused === true : false;\n let url = created.url;\n const shouldWatch = options.watch !== false;\n\n if (options.printUrl) {\n printPlain(url);\n }\n if (options.open !== false) {\n await openBrowser(url);\n }\n\n if (!shouldWatch) {\n const result = {\n reviewId: meta.id,\n turnId: turn.id,\n turnIndex: turn.index,\n url,\n files: diff.files.length,\n scope: diff.scope.mode,\n artifactDir: turn.artifactDir,\n reused\n };\n globals.json ? printJson(result) : printPlain(`Review ${meta.id}: ${url}`);\n return;\n }\n\n const watched = await watchReviewWithReconnect(\n meta.id,\n info,\n options.timeout,\n async (nextInfo) => {\n info = nextInfo;\n client = new ServerClient(serverUrl(info));\n url = `${serverUrl(info)}/review/${meta.id}`;\n if (options.printUrl) {\n printPlain(url);\n }\n if (options.open !== false) {\n await openBrowser(url);\n }\n }\n );\n info = watched.info;\n client = new ServerClient(serverUrl(info));\n const event = watched.event;\n if (event.type === 'review.cancelled') {\n process.exitCode = 2;\n globals.json ? printJson(event) : printPlain(`Review ${meta.id} cancelled`);\n return;\n }\n if (event.type !== 'review.submitted') {\n throw new Error(`Unexpected review event ${event.type}`);\n }\n\n const [feedback, submittedRecord] = await Promise.all([\n client.getFeedback(meta.id),\n client.getReview(meta.id)\n ]);\n const submittedTurn =\n submittedRecord.meta.turns?.find((summary) => summary.id === (event.turnId ?? turn.id)) ??\n turn;\n if (!submittedTurn.feedbackPath || !submittedTurn.markdownPath) {\n throw new Error(`Review ${meta.id} turn ${submittedTurn.index} is missing feedback paths`);\n }\n const result = {\n reviewId: meta.id,\n turnId: submittedTurn.id,\n turnIndex: submittedTurn.index,\n url,\n files: event.counts.files,\n comments: event.counts.comments,\n feedbackPath: submittedTurn.feedbackPath,\n markdownPath: submittedTurn.markdownPath,\n artifactDir: submittedTurn.artifactDir,\n feedback,\n reused\n };\n globals.json\n ? printJson(result)\n : printPlain(`Review ${meta.id} submitted with ${event.counts.comments} comments`);\n }\n );\n\nprogram\n .command('watch')\n .argument('<reviewId>', 'review id')\n .description('Wait for review.submitted for an existing review')\n .option('--timeout <seconds>', 'watch timeout in seconds', Number)\n .action(async (reviewId: string, options: { timeout?: number }) => {\n const globals = program.opts<GlobalOptions>();\n const info = await ensureServer();\n const { event } = await watchReviewWithReconnect(\n reviewId,\n info,\n options.timeout,\n async () => undefined\n );\n globals.json ? printJson(event) : printPlain(`${event.type} ${event.reviewId}`);\n });\n\nprogram\n .command('start')\n .description('Start or reuse the background server')\n .option('--port <port>', 'port to bind', Number)\n .action(async (options: { port?: number }) => {\n const globals = program.opts<GlobalOptions>();\n const info = await startServer({ port: options.port });\n globals.json\n ? printJson(info)\n : printPlain(`Gloss server running at ${serverUrl(info)} (pid ${info.pid})`);\n });\n\nprogram\n .command('status')\n .description('Show server and active reviews')\n .action(async () => {\n const globals = program.opts<GlobalOptions>();\n const info = await readServerInfo();\n const responsive = info ? await isServerResponsive(info) : false;\n const reviews = await listReviewsForStatus({ responsive, server: info });\n const status = { running: responsive, server: info, reviews };\n globals.json\n ? printJson(status)\n : printPlain(\n responsive && info\n ? `Gloss server running at ${serverUrl(info)} with ${reviews.length} active review(s)`\n : 'Gloss server is not running'\n );\n });\n\nprogram\n .command('stop')\n .description('Stop the managed background server')\n .option('--all', 'stop all Gloss daemon processes for the current user')\n .action(async (options: { all?: boolean }) => {\n const globals = program.opts<GlobalOptions>();\n const result = await stopServer({ all: options.all });\n globals.json\n ? printJson(result)\n : printPlain(\n options.all && result.stoppedPids\n ? `Stopped ${result.stoppedPids.length} Gloss daemon(s)`\n : result.stopped\n ? 'Gloss server stopped'\n : 'Gloss server was not running'\n );\n });\n\nprogram\n .command('clear')\n .description('Delete old completed review artifacts')\n .option(\n '--older-than <days>',\n 'delete completed reviews older than this many days',\n parseOlderThanDays,\n DEFAULT_REVIEW_RETENTION_DAYS\n )\n .option('--dry-run', 'print cleanup candidates without deleting them')\n .action(async (options: { olderThan: number; dryRun?: boolean }) => {\n const globals = program.opts<GlobalOptions>();\n const result = await clearReviews({\n olderThanDays: options.olderThan,\n dryRun: options.dryRun === true\n });\n globals.json ? printJson(result) : printPlain(formatClearResult(result));\n });\n\nprogram\n .command('resolve')\n .argument('<reviewId>', 'review id')\n .description('Mark a submitted review or one feedback comment as resolved')\n .option('--comment <commentId>', 'resolve one submitted feedback comment')\n .option('--summary <text>', 'brief summary of the fixes applied')\n .option('--turn <idOrIndex>', 'resolve a specific turn for whole-review resolution')\n .action(\n async (reviewId: string, options: { comment?: string; summary?: string; turn?: string }) => {\n const globals = program.opts<GlobalOptions>();\n const info = await ensureServer();\n const client = new ServerClient(serverUrl(info));\n const result = options.comment\n ? await client.resolveComment(reviewId, options.comment, options.summary)\n : await client.markResolved(reviewId, options.summary, options.turn);\n if (globals.json) {\n printJson({\n commentId: options.comment ?? null,\n summary: options.summary ?? null,\n turn: options.turn ?? null,\n ...result\n });\n return;\n }\n printPlain(\n options.comment\n ? `Comment ${options.comment} resolved in review ${reviewId}`\n : `Review ${reviewId} resolved`\n );\n }\n );\n\nprogram\n .command('doctor')\n .description('Diagnose setup and validate git/state')\n .action(async () => {\n const globals = program.opts<GlobalOptions>();\n const checks: DoctorCheck[] = [];\n try {\n await assertGitAvailable();\n checks.push({ name: 'git', ok: true });\n } catch (error) {\n checks.push({\n name: 'git',\n ok: false,\n detail: error instanceof Error ? error.message : String(error)\n });\n }\n try {\n const root = await getRepoRoot();\n checks.push({ name: 'repo', ok: true, detail: root });\n } catch (error) {\n checks.push({\n name: 'repo',\n ok: false,\n detail: error instanceof Error ? error.message : String(error)\n });\n }\n const info = await readServerInfo();\n checks.push({\n name: 'server',\n ok: info ? await isServerResponsive(info) : false,\n detail: info ? serverUrl(info) : 'not started'\n });\n try {\n const daemonPids = await listGlossDaemonPids();\n const unmanagedDaemonPids = daemonPids.filter((pid) => pid !== info?.pid);\n checks.push({\n name: 'daemon-processes',\n ok: unmanagedDaemonPids.length === 0,\n detail:\n daemonPids.length === 0\n ? 'none'\n : `${daemonPids.length} found${unmanagedDaemonPids.length > 0 ? `; unmanaged pids ${unmanagedDaemonPids.join(', ')}` : ''}`\n });\n } catch (error) {\n checks.push({\n name: 'daemon-processes',\n ok: false,\n detail: error instanceof Error ? error.message : String(error)\n });\n }\n if (globals.json) {\n printJson({ checks });\n } else {\n for (const check of checks) {\n printPlain(\n `${check.ok ? 'ok' : 'fail'} ${check.name}${check.detail ? ` - ${check.detail}` : ''}`\n );\n }\n }\n });\n\nasync function watchReviewWithReconnect(\n reviewId: string,\n initialInfo: ServerInfo,\n timeoutSeconds: number | undefined,\n onServerChanged: (info: ServerInfo) => Promise<void>\n): Promise<{ event: ReviewEvent; info: ServerInfo }> {\n const startedAt = Date.now();\n let info = initialInfo;\n\n while (true) {\n const remainingSeconds =\n timeoutSeconds && timeoutSeconds > 0\n ? timeoutSeconds - (Date.now() - startedAt) / 1000\n : undefined;\n if (remainingSeconds !== undefined && remainingSeconds <= 0) {\n throw new Error(`watch timed out after ${timeoutSeconds} seconds`);\n }\n\n try {\n const event = await new ServerClient(serverUrl(info)).watchReview(reviewId, remainingSeconds);\n return { event, info };\n } catch (error) {\n if (isWatchTimeout(error)) {\n throw error;\n }\n if (!isReconnectableWatchError(error)) {\n throw error;\n }\n await sleep(500);\n const nextInfo = await ensureServer();\n if (nextInfo.port !== info.port) {\n await onServerChanged(nextInfo);\n }\n info = nextInfo;\n }\n }\n}\n\nasync function baseForExistingReview(\n client: ServerClient,\n reviewId: string\n): Promise<string | null> {\n const record = await client.getReview(reviewId);\n return record.diff.scope.mode === 'explicit'\n ? (record.diff.scope.requestedBase ?? record.diff.base.ref)\n : null;\n}\n\nasync function clearReviews(options: {\n olderThanDays: number;\n dryRun: boolean;\n}): Promise<ClearReviewsResult> {\n const info = await readServerInfo();\n if (info && (await isServerResponsive(info))) {\n return new ServerClient(serverUrl(info)).clearReviews(options);\n }\n return clearReviewArtifacts(options);\n}\n\nfunction parseOlderThanDays(value: string): number {\n const days = Number(value);\n if (!Number.isInteger(days) || days < 0) {\n throw new Error('--older-than must be a non-negative integer');\n }\n return days;\n}\n\nfunction formatClearResult(result: ClearReviewsResult): string {\n const action = result.dryRun ? 'Would delete' : 'Deleted';\n const count = result.dryRun ? result.counts.candidates : result.counts.deleted;\n const skipped =\n result.counts.skipped > 0\n ? `; skipped ${result.counts.skipped} invalid review artifact(s)`\n : '';\n return `${action} ${count} review artifact(s) older than ${result.olderThanDays} day(s) from ${result.reviewsDir}${skipped}`;\n}\n\nfunction isWatchTimeout(error: unknown): error is Error {\n return error instanceof Error && /^watch timed out after/.test(error.message);\n}\n\nfunction isReconnectableWatchError(error: unknown): error is Error {\n return error instanceof Error && !/^watch failed: [45]\\d\\d /.test(error.message);\n}\n\nasync function sleep(milliseconds: number): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\n\nprogram.parseAsync(process.argv).catch((error: unknown) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 1;\n});\n","import type { Dirent } from 'node:fs';\nimport { readdir, readFile, rm } from 'node:fs/promises';\nimport { formatError, isFileNotFound } from './errors';\nimport {\n globalReviewDir,\n globalReviewMetaFile,\n globalReviewsDir,\n globalReviewTurnMetaFile,\n globalReviewTurnsDir\n} from './paths';\nimport type {\n ClearReviewEntry,\n ClearReviewsRequest,\n ClearReviewsResult,\n ReviewStatus,\n ReviewTurnMeta\n} from './types';\nimport {\n isReviewTurnMeta,\n isStoredReviewMeta,\n parseJson,\n type StoredReviewMeta\n} from './validation';\n\nexport const DEFAULT_REVIEW_RETENTION_DAYS = 30;\n\nconst clearableStatuses = new Set<ReviewStatus>(['submitted', 'resolved', 'cancelled']);\nconst millisecondsPerDay = 24 * 60 * 60 * 1000;\n\nexport interface ClearReviewArtifactsOptions extends ClearReviewsRequest {\n now?: Date;\n}\n\nexport async function clearReviewArtifacts(\n options: ClearReviewArtifactsOptions = {}\n): Promise<ClearReviewsResult> {\n const olderThanDays = normalizeRetentionDays(options.olderThanDays);\n const dryRun = options.dryRun === true;\n const now = options.now ?? new Date();\n const cutoff = new Date(now.getTime() - olderThanDays * millisecondsPerDay);\n const reviewsDir = globalReviewsDir();\n const candidates: ClearReviewEntry[] = [];\n const deleted: ClearReviewEntry[] = [];\n const skipped: ClearReviewsResult['skipped'] = [];\n\n let entries: Dirent[];\n try {\n entries = await readdir(reviewsDir, { withFileTypes: true });\n } catch (error) {\n if (isFileNotFound(error)) {\n return cleanupResult({\n reviewsDir,\n cutoff,\n olderThanDays,\n dryRun,\n candidates,\n deleted,\n skipped\n });\n }\n throw new Error(`Could not read reviews directory at ${reviewsDir}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) {\n continue;\n }\n const reviewId = entry.name;\n const artifactDir = globalReviewDir(reviewId);\n const candidate = await cleanupCandidate(reviewId, artifactDir, cutoff, skipped);\n if (!candidate) {\n continue;\n }\n candidates.push(candidate);\n if (!dryRun) {\n await rm(artifactDir, { recursive: true, force: true });\n deleted.push(candidate);\n }\n }\n\n return cleanupResult({ reviewsDir, cutoff, olderThanDays, dryRun, candidates, deleted, skipped });\n}\n\nfunction normalizeRetentionDays(value: number | undefined): number {\n const days = value ?? DEFAULT_REVIEW_RETENTION_DAYS;\n if (!Number.isInteger(days) || days < 0) {\n throw new Error('olderThanDays must be a non-negative integer');\n }\n return days;\n}\n\nasync function cleanupCandidate(\n reviewId: string,\n artifactDir: string,\n cutoff: Date,\n skipped: ClearReviewsResult['skipped']\n): Promise<ClearReviewEntry | null> {\n let raw: string;\n try {\n raw = await readFile(globalReviewMetaFile(reviewId), 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n skipped.push({ reviewId, artifactDir, reason: 'missing metadata' });\n return null;\n }\n skipped.push({ reviewId, artifactDir, reason: `unreadable metadata: ${formatError(error)}` });\n return null;\n }\n\n let meta: StoredReviewMeta;\n try {\n meta = parseJson(raw, isStoredReviewMeta, 'review metadata');\n } catch (error) {\n skipped.push({ reviewId, artifactDir, reason: `invalid metadata: ${formatError(error)}` });\n return null;\n }\n\n if (meta.id !== reviewId) {\n skipped.push({ reviewId, artifactDir, reason: `metadata id mismatch: ${meta.id}` });\n return null;\n }\n if (!clearableStatuses.has(meta.status)) {\n return null;\n }\n\n const turnState = await persistedTurnCleanupState(reviewId, artifactDir, skipped);\n if (turnState === 'preserve') {\n return null;\n }\n\n const lastActivityAt = latestTimestamp([\n ...metadataTimestamps(meta),\n ...(turnState === 'none' ? [] : turnState.timestamps)\n ]);\n if (!lastActivityAt) {\n skipped.push({ reviewId, artifactDir, reason: 'missing valid activity timestamp' });\n return null;\n }\n if (Date.parse(lastActivityAt) >= cutoff.getTime()) {\n return null;\n }\n\n return {\n reviewId,\n status: meta.status,\n artifactDir,\n lastActivityAt\n };\n}\n\nasync function persistedTurnCleanupState(\n reviewId: string,\n artifactDir: string,\n skipped: ClearReviewsResult['skipped']\n): Promise<'none' | 'preserve' | { timestamps: Array<string | undefined> }> {\n let entries: Dirent[];\n try {\n entries = await readdir(globalReviewTurnsDir(reviewId), { withFileTypes: true });\n } catch (error) {\n if (isFileNotFound(error)) {\n return 'none';\n }\n skipped.push({\n reviewId,\n artifactDir,\n reason: `unreadable turns directory: ${formatError(error)}`\n });\n return 'preserve';\n }\n\n const turnDirs = entries.filter((entry) => entry.isDirectory());\n if (turnDirs.length === 0) {\n return 'none';\n }\n\n const timestamps: Array<string | undefined> = [];\n for (const entry of turnDirs) {\n const turn = await readPersistedTurnMeta(reviewId, entry.name, artifactDir, skipped);\n if (!turn) {\n return 'preserve';\n }\n if (turn.status === 'pending' || !clearableStatuses.has(turn.status)) {\n return 'preserve';\n }\n timestamps.push(turn.createdAt, turn.submittedAt, turn.resolvedAt);\n }\n\n return { timestamps };\n}\n\nasync function readPersistedTurnMeta(\n reviewId: string,\n turnDirName: string,\n artifactDir: string,\n skipped: ClearReviewsResult['skipped']\n): Promise<ReviewTurnMeta | null> {\n let raw: string;\n try {\n raw = await readFile(globalReviewTurnMetaFile(reviewId, turnDirName), 'utf8');\n } catch (error) {\n skipped.push({\n reviewId,\n artifactDir,\n reason: `${isFileNotFound(error) ? 'missing' : 'unreadable'} turn metadata for ${turnDirName}${\n isFileNotFound(error) ? '' : `: ${formatError(error)}`\n }`\n });\n return null;\n }\n\n try {\n const turn = parseJson(raw, isReviewTurnMeta, 'review turn metadata');\n if (turn.id !== turnDirName) {\n skipped.push({\n reviewId,\n artifactDir,\n reason: `turn metadata id mismatch for ${turnDirName}: ${turn.id}`\n });\n return null;\n }\n return turn;\n } catch (error) {\n skipped.push({\n reviewId,\n artifactDir,\n reason: `invalid turn metadata for ${turnDirName}: ${formatError(error)}`\n });\n return null;\n }\n}\n\nfunction metadataTimestamps(meta: StoredReviewMeta): Array<string | undefined> {\n return [\n meta.createdAt,\n meta.submittedAt,\n meta.resolvedAt,\n ...(meta.turns ?? []).flatMap((turn) => [\n turn.createdAt,\n turn.capturedAt,\n turn.submittedAt,\n turn.resolvedAt\n ])\n ];\n}\n\nfunction latestTimestamp(timestamps: Array<string | undefined | null>): string | null {\n const latest = Math.max(\n ...timestamps\n .map((timestamp) => (timestamp ? Date.parse(timestamp) : Number.NaN))\n .filter((timestamp) => Number.isFinite(timestamp))\n );\n return Number.isFinite(latest) ? new Date(latest).toISOString() : null;\n}\n\nfunction cleanupResult({\n reviewsDir,\n cutoff,\n olderThanDays,\n dryRun,\n candidates,\n deleted,\n skipped\n}: Omit<ClearReviewsResult, 'cutoff' | 'counts'> & { cutoff: Date }): ClearReviewsResult {\n return {\n reviewsDir,\n cutoff: cutoff.toISOString(),\n olderThanDays,\n dryRun,\n candidates,\n deleted,\n skipped,\n counts: {\n candidates: candidates.length,\n deleted: deleted.length,\n skipped: skipped.length\n }\n };\n}\n","export function formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport function isFileNotFound(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n","import { mkdir } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport path from 'node:path';\nimport packageJson from '../../package.json';\n\nexport const packageVersion = packageJson.version;\n\nexport function expandHome(input: string): string {\n if (input === '~') {\n return homedir();\n }\n if (input.startsWith('~/')) {\n return path.join(homedir(), input.slice(2));\n }\n return input;\n}\n\nexport function globalStateDir(): string {\n return expandHome(process.env.GLOSS_STATE_DIR ?? '~/.gloss');\n}\n\nexport function globalServerFile(): string {\n return path.join(globalStateDir(), 'server.json');\n}\n\nexport function globalLogDir(): string {\n return path.join(globalStateDir(), 'logs');\n}\n\nexport function globalServerLogFile(): string {\n return path.join(globalLogDir(), 'server.log');\n}\n\nexport function globalReviewsDir(): string {\n return path.join(globalStateDir(), 'reviews');\n}\n\nexport function globalReviewDir(reviewId: string): string {\n return path.join(globalReviewsDir(), reviewId);\n}\n\nexport function globalReviewTurnsDir(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'turns');\n}\n\nexport function globalReviewTurnDir(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnsDir(reviewId), turnId);\n}\n\nexport function globalReviewTurnMetaFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'turn.json');\n}\n\nexport function globalReviewTurnDiffFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'diff.json');\n}\n\nexport function globalReviewTurnFeedbackFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'feedback.json');\n}\n\nexport function globalReviewTurnMarkdownFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'feedback.md');\n}\n\nexport function globalReviewTurnResolvedFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'resolved.json');\n}\n\nexport function globalReviewMetaFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'meta.json');\n}\n\nexport function globalReviewDiffFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'diff.json');\n}\n\nexport function globalReviewFeedbackFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'feedback.json');\n}\n\nexport function globalReviewMarkdownFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'feedback.md');\n}\n\nexport function globalReviewResolvedFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'resolved.json');\n}\n\nexport async function ensureDir(dir: string): Promise<void> {\n await mkdir(dir, { recursive: true });\n}\n","{\n \"name\": \"getgloss\",\n \"version\": \"0.8.2\",\n \"description\": \"Local browser-based diff review for coding-agent loops.\",\n \"type\": \"module\",\n \"packageManager\": \"pnpm@10.33.2\",\n \"bin\": {\n \"getgloss\": \"./dist/cli/index.js\",\n \"gloss\": \"./dist/cli/index.js\"\n },\n \"files\": [\n \"dist\",\n \"skill\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"pnpm build:web && pnpm build:node\",\n \"build:web\": \"vite build\",\n \"build:node\": \"tsup\",\n \"check\": \"biome check .\",\n \"format\": \"biome format --write .\",\n \"prepack\": \"pnpm build\",\n \"dev:web\": \"vite --host 127.0.0.1\",\n \"setup\": \"tsx scripts/dev-cli.ts\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"dependencies\": {\n \"@hono/node-server\": \"1.19.14\",\n \"@shikijs/langs\": \"4.1.0\",\n \"@shikijs/themes\": \"4.1.0\",\n \"@tailwindcss/vite\": \"4.3.0\",\n \"commander\": \"14.0.3\",\n \"execa\": \"9.6.1\",\n \"get-port\": \"7.2.0\",\n \"hono\": \"4.12.21\",\n \"lucide-react\": \"1.16.0\",\n \"open\": \"10.2.0\",\n \"react\": \"19.2.6\",\n \"react-dom\": \"19.2.6\",\n \"shiki\": \"4.1.0\",\n \"ulid\": \"3.0.2\",\n \"zustand\": \"5.0.13\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"2.4.15\",\n \"@types/node\": \"24.12.4\",\n \"@types/react\": \"19.2.15\",\n \"@types/react-dom\": \"19.2.3\",\n \"@vitejs/plugin-react\": \"4.7.0\",\n \"tailwindcss\": \"4.3.0\",\n \"tsup\": \"8.5.1\",\n \"tsx\": \"4.22.3\",\n \"typescript\": \"5.9.3\",\n \"vite\": \"6.4.2\",\n \"vitest\": \"3.2.4\"\n },\n \"keywords\": [\n \"diff\",\n \"review\",\n \"coding-agents\"\n ],\n \"author\": \"Raj Joshi\",\n \"license\": \"MIT\",\n \"homepage\": \"https://getgloss.dev\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/iamrajjoshi/gloss.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/iamrajjoshi/gloss/issues\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n","export const SIDES = ['L', 'R'] as const;\n\nexport type Side = (typeof SIDES)[number];\n\nexport const REVIEW_STATUSES = ['pending', 'submitted', 'cancelled', 'resolved'] as const;\n\nexport type ReviewStatus = (typeof REVIEW_STATUSES)[number];\n\nexport interface ClearReviewEntry {\n reviewId: string;\n status: ReviewStatus;\n artifactDir: string;\n lastActivityAt: string;\n}\n\nexport interface ClearReviewSkipped {\n reviewId: string;\n artifactDir: string;\n reason: string;\n}\n\nexport interface ClearReviewsRequest {\n olderThanDays?: number;\n dryRun?: boolean;\n}\n\nexport interface ClearReviewsResult {\n reviewsDir: string;\n cutoff: string;\n olderThanDays: number;\n dryRun: boolean;\n candidates: ClearReviewEntry[];\n deleted: ClearReviewEntry[];\n skipped: ClearReviewSkipped[];\n counts: {\n candidates: number;\n deleted: number;\n skipped: number;\n };\n}\n\nexport interface Comment {\n id: string;\n filePath: string;\n startLine: number;\n endLine: number;\n side: Side;\n body: string;\n originalSnippet: string;\n createdAt: string;\n}\n\nexport const DIFF_LINE_TYPES = ['context', 'add', 'delete'] as const;\n\nexport type DiffLineType = (typeof DIFF_LINE_TYPES)[number];\n\nexport interface DiffLine {\n type: DiffLineType;\n oldLine: number | null;\n newLine: number | null;\n content: string;\n}\n\nexport interface DiffHunk {\n oldStart: number;\n oldLines: number;\n newStart: number;\n newLines: number;\n header: string;\n lines: DiffLine[];\n}\n\nexport interface DiffFile {\n path: string;\n oldPath: string | null;\n additions: number;\n deletions: number;\n isBinary: boolean;\n isDeleted: boolean;\n isNew: boolean;\n isRenamed: boolean;\n language: string | null;\n hunks: DiffHunk[];\n}\n\nexport const DIFF_SCOPE_MODES = ['working', 'branch', 'explicit'] as const;\n\nexport type DiffScopeMode = (typeof DIFF_SCOPE_MODES)[number];\n\nexport const DIFF_FALLBACK_REASONS = ['working-tree-clean', 'missing-branch-base'] as const;\n\nexport type DiffFallbackReason = (typeof DIFF_FALLBACK_REASONS)[number] | null;\n\nexport interface BaseRef {\n ref: string;\n sha: string;\n}\n\nexport interface DiffRef {\n ref: string;\n sha: string | null;\n}\n\nexport interface DiffStats {\n files: number;\n additions: number;\n deletions: number;\n}\n\nexport interface DiffCommit {\n sha: string;\n shortSha: string;\n subject: string;\n authorName: string;\n authorEmail: string;\n authoredAt: string;\n committedAt: string;\n}\n\nexport interface CommitDiff {\n commit: DiffCommit;\n stats: DiffStats;\n rawDiff: string;\n files: DiffFile[];\n}\n\nexport interface CommitRangeDiffRequest {\n fromSha: string;\n toSha: string;\n turnId?: string;\n}\n\nexport interface CommitRangeDiffResponse {\n fromSha: string;\n toSha: string;\n stats: DiffStats;\n rawDiff: string;\n files: DiffFile[];\n}\n\nexport const REVIEW_SCOPE_MODES = ['all', 'single', 'range'] as const;\n\nexport type ReviewScope =\n | { mode: 'all' }\n | { mode: 'single'; sha: string }\n | { mode: 'range'; fromSha: string; toSha: string };\n\ninterface DiffScope {\n mode: DiffScopeMode;\n requestedBase: string | null;\n base: BaseRef;\n comparison: DiffRef;\n fallbackReason: DiffFallbackReason;\n}\n\nexport interface DiffPayload {\n base: BaseRef;\n branch: string | null;\n cwd: string;\n scope: DiffScope;\n stats: DiffStats;\n rawDiff: string;\n files: DiffFile[];\n commitDiffs?: CommitDiff[];\n capturedAt: string;\n}\n\nexport interface ReviewMeta {\n id: string;\n cwd: string;\n base: DiffPayload['base'];\n branch: string | null;\n status: ReviewStatus;\n createdAt: string;\n submittedAt?: string;\n resolvedAt?: string;\n artifactDir: string;\n activeTurnId?: string;\n turns?: ReviewTurnSummary[];\n feedbackPath?: string;\n markdownPath?: string;\n}\n\nexport interface FeedbackBundle {\n version: 1;\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n timestamp: string;\n base: DiffPayload['base'];\n branch: string | null;\n reviewScope?: ReviewScope;\n comments: Comment[];\n}\n\nexport const RESOLUTION_STATUSES = ['partial', 'resolved'] as const;\n\ntype ResolutionStatus = (typeof RESOLUTION_STATUSES)[number];\n\nexport interface ResolvedComment {\n commentId: string;\n status: 'resolved';\n summary?: string;\n resolvedAt: string;\n}\n\nexport interface ResolutionBundle {\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n status: ResolutionStatus;\n summary: string | null;\n resolvedAt: string | null;\n comments: ResolvedComment[];\n}\n\nexport interface ResolutionCounts {\n total: number;\n resolved: number;\n open: number;\n}\n\nexport interface ResolveResult {\n ok: true;\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n status: ReviewStatus;\n resolutionStatus: ResolutionStatus;\n comments: ResolutionCounts;\n path: string;\n resolution: ResolutionBundle;\n}\n\nexport const REVIEW_UPDATE_REASONS = [\n 'review-resolved',\n 'comment-resolved',\n 'comment-reopened',\n 'turn-created'\n] as const;\n\nexport type ReviewUpdateReason = (typeof REVIEW_UPDATE_REASONS)[number];\n\nexport type ReviewEvent =\n | { type: 'review.opened'; reviewId: string }\n | {\n type: 'review.turn.created';\n reviewId: string;\n turnId: string;\n turnIndex: number;\n reused: boolean;\n }\n | {\n type: 'review.submitted';\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n counts: { files: number; comments: number };\n }\n | {\n type: 'review.updated';\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n reason: ReviewUpdateReason;\n status: ReviewStatus;\n resolutionStatus: ResolutionStatus;\n counts: ResolutionCounts;\n }\n | { type: 'review.cancelled'; reviewId: string };\n\nexport interface ReviewTurnMeta {\n id: string;\n index: number;\n status: ReviewStatus;\n createdAt: string;\n submittedAt?: string;\n resolvedAt?: string;\n artifactDir: string;\n diffPath: string;\n feedbackPath?: string;\n markdownPath?: string;\n resolvedPath?: string;\n}\n\nexport interface ReviewTurnSummary extends ReviewTurnMeta {\n capturedAt: string;\n stats: DiffStats;\n comments: ResolutionCounts;\n}\n\nexport interface ReviewTurn extends ReviewTurnMeta {\n diff: DiffPayload;\n feedback?: FeedbackBundle;\n resolution?: ResolutionBundle;\n}\n\nexport interface ReviewRecord {\n meta: ReviewMeta;\n turns: ReviewTurn[];\n diff: DiffPayload;\n feedback?: FeedbackBundle;\n resolution?: ResolutionBundle;\n}\n\nexport interface ServerInfo {\n pid: number;\n port: number;\n version: string;\n startedAt: string;\n stateDir: string;\n}\n\nexport interface OpenResult {\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n url: string;\n files: number;\n comments?: number;\n feedbackPath?: string;\n markdownPath?: string;\n artifactDir?: string;\n}\n\nexport interface HealthResponse {\n ok: boolean;\n version: string;\n activeReviews: number;\n}\n\ninterface ReviewRegistrationResponse {\n meta: ReviewMeta;\n url: string;\n turn?: ReviewTurnSummary;\n}\n\nexport interface CreateReviewResponse extends ReviewRegistrationResponse {}\n\nexport interface CreateReviewTurnResponse extends ReviewRegistrationResponse {\n turn: ReviewTurnSummary;\n reused: boolean;\n}\n\nexport interface ListReviewsResponse {\n reviews: ReviewMeta[];\n}\n\nexport interface SubmitReviewRequest {\n comments: Comment[];\n reviewScope?: ReviewScope;\n}\n\nexport interface ResolutionRequest {\n summary?: string;\n turn?: string;\n}\n\nexport interface OpenFileRequest {\n filePath: string;\n turnId?: string;\n}\n\nexport interface OpenFileResponse {\n ok: true;\n path: string;\n}\n","import type { JsonValue } from './json';\nimport type {\n ClearReviewEntry,\n ClearReviewsRequest,\n ClearReviewsResult,\n Comment,\n CommitDiff,\n CommitRangeDiffRequest,\n CommitRangeDiffResponse,\n CreateReviewResponse,\n CreateReviewTurnResponse,\n DiffCommit,\n DiffFile,\n DiffHunk,\n DiffLine,\n DiffPayload,\n DiffStats,\n FeedbackBundle,\n HealthResponse,\n ListReviewsResponse,\n OpenFileRequest,\n OpenFileResponse,\n OpenResult,\n ResolutionBundle,\n ResolutionRequest,\n ResolvedComment,\n ResolveResult,\n ReviewEvent,\n ReviewMeta,\n ReviewRecord,\n ReviewScope,\n ReviewTurn,\n ReviewTurnMeta,\n ReviewTurnSummary,\n ServerInfo,\n SubmitReviewRequest\n} from './types';\nimport {\n DIFF_FALLBACK_REASONS,\n DIFF_LINE_TYPES,\n DIFF_SCOPE_MODES,\n RESOLUTION_STATUSES,\n REVIEW_SCOPE_MODES,\n REVIEW_STATUSES,\n REVIEW_UPDATE_REASONS,\n SIDES\n} from './types';\n\nexport type JsonGuard<T> = (value: unknown) => value is T;\n\nexport type StoredReviewMeta = Omit<ReviewMeta, 'artifactDir'> &\n Partial<\n Pick<ReviewMeta, 'artifactDir' | 'activeTurnId' | 'turns' | 'feedbackPath' | 'markdownPath'>\n >;\n\ntype ReviewRegistrationResponseShape = {\n meta: ReviewMeta;\n url: string;\n turn?: ReviewTurnSummary;\n};\n\nexport function parseJson<T>(raw: string, guard: JsonGuard<T>, label: string): T {\n const parsed: JsonValue = JSON.parse(raw);\n return parseJsonValue(parsed, guard, label);\n}\n\nexport function parseJsonValue<T>(value: JsonValue, guard: JsonGuard<T>, label: string): T {\n if (!guard(value)) {\n throw new Error(`Invalid ${label}`);\n }\n return value;\n}\n\nexport function isServerInfo(value: unknown): value is ServerInfo {\n return (\n isRecord(value) &&\n isNumber(value.pid) &&\n isNumber(value.port) &&\n isString(value.version) &&\n isString(value.startedAt) &&\n isString(value.stateDir)\n );\n}\n\nexport function isHealthResponse(value: unknown): value is HealthResponse {\n return (\n isRecord(value) &&\n isBoolean(value.ok) &&\n isString(value.version) &&\n isNumber(value.activeReviews)\n );\n}\n\nexport function isClearReviewsRequest(value: unknown): value is ClearReviewsRequest {\n return (\n isRecord(value) &&\n isOptionalNonNegativeInteger(value.olderThanDays) &&\n isOptionalBoolean(value.dryRun)\n );\n}\n\nexport function isClearReviewsResult(value: unknown): value is ClearReviewsResult {\n return (\n isRecord(value) &&\n isString(value.reviewsDir) &&\n isString(value.cutoff) &&\n isNumber(value.olderThanDays) &&\n isBoolean(value.dryRun) &&\n isArrayOf(value.candidates, isClearReviewEntry) &&\n isArrayOf(value.deleted, isClearReviewEntry) &&\n isArrayOf(value.skipped, isClearReviewSkipped) &&\n isRecord(value.counts) &&\n isNumber(value.counts.candidates) &&\n isNumber(value.counts.deleted) &&\n isNumber(value.counts.skipped)\n );\n}\n\nexport function isCreateReviewResponse(value: unknown): value is CreateReviewResponse {\n return (\n isRecord(value) &&\n hasReviewRegistrationFields(value) &&\n isOptional(value.turn, isReviewTurnSummary)\n );\n}\n\nexport function isCreateReviewTurnResponse(value: unknown): value is CreateReviewTurnResponse {\n return (\n isRecord(value) &&\n hasReviewRegistrationFields(value) &&\n isReviewTurnSummary(value.turn) &&\n isBoolean(value.reused)\n );\n}\n\nexport function isListReviewsResponse(value: unknown): value is ListReviewsResponse {\n return isRecord(value) && isArrayOf(value.reviews, isReviewMeta);\n}\n\nexport function isOpenResult(value: unknown): value is OpenResult {\n return (\n isRecord(value) &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isString(value.url) &&\n isNumber(value.files) &&\n isOptionalNumber(value.comments) &&\n isOptionalString(value.feedbackPath) &&\n isOptionalString(value.markdownPath) &&\n isOptionalString(value.artifactDir)\n );\n}\n\nexport function isOpenFileRequest(value: unknown): value is OpenFileRequest {\n return isRecord(value) && isString(value.filePath) && isOptionalString(value.turnId);\n}\n\nexport function isOpenFileResponse(value: unknown): value is OpenFileResponse {\n return isRecord(value) && value.ok === true && isString(value.path);\n}\n\nexport function isCommitRangeDiffRequest(value: unknown): value is CommitRangeDiffRequest {\n return (\n isRecord(value) &&\n isString(value.fromSha) &&\n isString(value.toSha) &&\n isOptionalString(value.turnId)\n );\n}\n\nexport function isCommitRangeDiffResponse(value: unknown): value is CommitRangeDiffResponse {\n return (\n isRecord(value) &&\n isString(value.fromSha) &&\n isString(value.toSha) &&\n isDiffStats(value.stats) &&\n isString(value.rawDiff) &&\n isArrayOf(value.files, isDiffFile)\n );\n}\n\nexport function isResolveResult(value: unknown): value is ResolveResult {\n return (\n isRecord(value) &&\n value.ok === true &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isReviewStatus(value.status) &&\n isResolutionStatus(value.resolutionStatus) &&\n isResolutionCounts(value.comments) &&\n isString(value.path) &&\n isResolutionBundle(value.resolution)\n );\n}\n\nexport function isSubmitReviewRequest(value: unknown): value is SubmitReviewRequest {\n return (\n isRecord(value) &&\n isArrayOf(value.comments, isComment) &&\n isOptional(value.reviewScope, isReviewScope)\n );\n}\n\nexport function isResolutionRequest(value: unknown): value is ResolutionRequest {\n return isRecord(value) && isOptionalString(value.summary) && isOptionalString(value.turn);\n}\n\nexport function isReviewRecord(value: unknown): value is ReviewRecord {\n return (\n isRecord(value) &&\n isReviewMeta(value.meta) &&\n isArrayOf(value.turns, isReviewTurn) &&\n isDiffPayload(value.diff) &&\n isOptional(value.feedback, isFeedbackBundle) &&\n isOptional(value.resolution, isResolutionBundle)\n );\n}\n\nexport function isStoredReviewMeta(value: unknown): value is StoredReviewMeta {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.cwd) &&\n isBaseRef(value.base) &&\n isNullableString(value.branch) &&\n isReviewStatus(value.status) &&\n isString(value.createdAt) &&\n isOptionalString(value.submittedAt) &&\n isOptionalString(value.resolvedAt) &&\n isOptionalString(value.artifactDir) &&\n isOptionalString(value.activeTurnId) &&\n isOptional(value.turns, (turns): turns is ReviewTurnSummary[] =>\n isArrayOf(turns, isReviewTurnSummary)\n ) &&\n isOptionalString(value.feedbackPath) &&\n isOptionalString(value.markdownPath)\n );\n}\n\nfunction isReviewMeta(value: unknown): value is ReviewMeta {\n return isStoredReviewMeta(value) && isString(value.artifactDir);\n}\n\nfunction hasReviewRegistrationFields(\n value: Record<string, unknown>\n): value is Record<string, unknown> & ReviewRegistrationResponseShape {\n return isReviewMeta(value.meta) && isString(value.url);\n}\n\nexport function isDiffPayload(value: unknown): value is DiffPayload {\n return (\n isRecord(value) &&\n isBaseRef(value.base) &&\n isNullableString(value.branch) &&\n isString(value.cwd) &&\n isDiffScope(value.scope) &&\n isDiffStats(value.stats) &&\n isString(value.rawDiff) &&\n isArrayOf(value.files, isDiffFile) &&\n isOptional(value.commitDiffs, (commitDiffs): commitDiffs is CommitDiff[] =>\n isArrayOf(commitDiffs, isCommitDiff)\n ) &&\n isString(value.capturedAt)\n );\n}\n\nexport function isFeedbackBundle(value: unknown): value is FeedbackBundle {\n return (\n isRecord(value) &&\n value.version === 1 &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isString(value.timestamp) &&\n isBaseRef(value.base) &&\n isNullableString(value.branch) &&\n isOptional(value.reviewScope, isReviewScope) &&\n isArrayOf(value.comments, isComment)\n );\n}\n\nexport function isResolutionBundle(value: unknown): value is ResolutionBundle {\n return (\n isRecord(value) &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isResolutionStatus(value.status) &&\n isNullableString(value.summary) &&\n isNullableString(value.resolvedAt) &&\n isArrayOf(value.comments, isResolvedComment)\n );\n}\n\nexport function isReviewEvent(value: unknown): value is ReviewEvent {\n if (!isRecord(value) || !isString(value.reviewId) || !isString(value.type)) {\n return false;\n }\n switch (value.type) {\n case 'review.opened':\n case 'review.cancelled':\n return true;\n case 'review.turn.created':\n return isString(value.turnId) && isNumber(value.turnIndex) && isBoolean(value.reused);\n case 'review.submitted':\n return (\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isRecord(value.counts) &&\n isNumber(value.counts.files) &&\n isNumber(value.counts.comments)\n );\n case 'review.updated':\n return (\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isReviewUpdateReason(value.reason) &&\n isReviewStatus(value.status) &&\n isResolutionStatus(value.resolutionStatus) &&\n isResolutionCounts(value.counts)\n );\n default:\n return false;\n }\n}\n\nexport function isReviewTurnMeta(value: unknown): value is ReviewTurnMeta {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isNumber(value.index) &&\n isReviewStatus(value.status) &&\n isString(value.createdAt) &&\n isOptionalString(value.submittedAt) &&\n isOptionalString(value.resolvedAt) &&\n isString(value.artifactDir) &&\n isString(value.diffPath) &&\n isOptionalString(value.feedbackPath) &&\n isOptionalString(value.markdownPath) &&\n isOptionalString(value.resolvedPath)\n );\n}\n\nfunction isReviewTurnSummary(value: unknown): value is ReviewTurnSummary {\n if (!isRecord(value) || !isReviewTurnMeta(value)) {\n return false;\n }\n return (\n isString(value.capturedAt) && isDiffStats(value.stats) && isResolutionCounts(value.comments)\n );\n}\n\nfunction isReviewTurn(value: unknown): value is ReviewTurn {\n if (!isRecord(value) || !isReviewTurnMeta(value)) {\n return false;\n }\n return (\n isDiffPayload(value.diff) &&\n isOptional(value.feedback, isFeedbackBundle) &&\n isOptional(value.resolution, isResolutionBundle)\n );\n}\n\nfunction isClearReviewEntry(value: unknown): value is ClearReviewEntry {\n return (\n isRecord(value) &&\n isString(value.reviewId) &&\n isReviewStatus(value.status) &&\n isString(value.artifactDir) &&\n isString(value.lastActivityAt)\n );\n}\n\nfunction isClearReviewSkipped(value: unknown): value is ClearReviewsResult['skipped'][number] {\n return (\n isRecord(value) &&\n isString(value.reviewId) &&\n isString(value.artifactDir) &&\n isString(value.reason)\n );\n}\n\nfunction isDiffScope(value: unknown): value is DiffPayload['scope'] {\n return (\n isRecord(value) &&\n isOneOf(value.mode, DIFF_SCOPE_MODES) &&\n isNullableString(value.requestedBase) &&\n isBaseRef(value.base) &&\n isDiffRef(value.comparison) &&\n (value.fallbackReason === null || isOneOf(value.fallbackReason, DIFF_FALLBACK_REASONS))\n );\n}\n\nfunction isDiffRef(value: unknown): value is DiffPayload['scope']['comparison'] {\n return isRecord(value) && isString(value.ref) && isNullableString(value.sha);\n}\n\nfunction isBaseRef(value: unknown): value is { ref: string; sha: string } {\n return isRecord(value) && isString(value.ref) && isString(value.sha);\n}\n\nfunction isDiffStats(value: unknown): value is DiffStats {\n return (\n isRecord(value) &&\n isNumber(value.files) &&\n isNumber(value.additions) &&\n isNumber(value.deletions)\n );\n}\n\nfunction isDiffCommit(value: unknown): value is DiffCommit {\n return (\n isRecord(value) &&\n isString(value.sha) &&\n isString(value.shortSha) &&\n isString(value.subject) &&\n isString(value.authorName) &&\n isString(value.authorEmail) &&\n isString(value.authoredAt) &&\n isString(value.committedAt)\n );\n}\n\nfunction isCommitDiff(value: unknown): value is CommitDiff {\n return (\n isRecord(value) &&\n isDiffCommit(value.commit) &&\n isDiffStats(value.stats) &&\n isString(value.rawDiff) &&\n isArrayOf(value.files, isDiffFile)\n );\n}\n\nfunction isReviewScope(value: unknown): value is ReviewScope {\n if (!isRecord(value) || !isOneOf(value.mode, REVIEW_SCOPE_MODES)) {\n return false;\n }\n switch (value.mode) {\n case 'all':\n return true;\n case 'single':\n return isString(value.sha);\n case 'range':\n return isString(value.fromSha) && isString(value.toSha);\n }\n}\n\nfunction isDiffFile(value: unknown): value is DiffFile {\n return (\n isRecord(value) &&\n isString(value.path) &&\n isNullableString(value.oldPath) &&\n isNumber(value.additions) &&\n isNumber(value.deletions) &&\n isBoolean(value.isBinary) &&\n isBoolean(value.isDeleted) &&\n isBoolean(value.isNew) &&\n isBoolean(value.isRenamed) &&\n isNullableString(value.language) &&\n isArrayOf(value.hunks, isDiffHunk)\n );\n}\n\nfunction isDiffHunk(value: unknown): value is DiffHunk {\n return (\n isRecord(value) &&\n isNumber(value.oldStart) &&\n isNumber(value.oldLines) &&\n isNumber(value.newStart) &&\n isNumber(value.newLines) &&\n isString(value.header) &&\n isArrayOf(value.lines, isDiffLine)\n );\n}\n\nfunction isDiffLine(value: unknown): value is DiffLine {\n return (\n isRecord(value) &&\n isOneOf(value.type, DIFF_LINE_TYPES) &&\n isNullableNumber(value.oldLine) &&\n isNullableNumber(value.newLine) &&\n isString(value.content)\n );\n}\n\nfunction isComment(value: unknown): value is Comment {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.filePath) &&\n isNumber(value.startLine) &&\n isNumber(value.endLine) &&\n isOneOf(value.side, SIDES) &&\n isString(value.body) &&\n isString(value.originalSnippet) &&\n isString(value.createdAt)\n );\n}\n\nfunction isResolvedComment(value: unknown): value is ResolvedComment {\n return (\n isRecord(value) &&\n isString(value.commentId) &&\n value.status === 'resolved' &&\n isOptionalString(value.summary) &&\n isString(value.resolvedAt)\n );\n}\n\nfunction isResolutionCounts(value: unknown): value is ResolveResult['comments'] {\n return (\n isRecord(value) && isNumber(value.total) && isNumber(value.resolved) && isNumber(value.open)\n );\n}\n\nfunction isReviewStatus(value: unknown): value is ReviewMeta['status'] {\n return isOneOf(value, REVIEW_STATUSES);\n}\n\nfunction isResolutionStatus(value: unknown): value is ResolutionBundle['status'] {\n return isOneOf(value, RESOLUTION_STATUSES);\n}\n\nfunction isReviewUpdateReason(\n value: unknown\n): value is Extract<ReviewEvent, { type: 'review.updated' }>['reason'] {\n return isOneOf(value, REVIEW_UPDATE_REASONS);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isArrayOf<T>(value: unknown, guard: JsonGuard<T>): value is T[] {\n return Array.isArray(value) && value.every(guard);\n}\n\nfunction isOptional<T>(value: unknown, guard: JsonGuard<T>): value is T | undefined {\n return value === undefined || guard(value);\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\nfunction isOptionalString(value: unknown): value is string | undefined {\n return value === undefined || isString(value);\n}\n\nfunction isNullableString(value: unknown): value is string | null {\n return value === null || isString(value);\n}\n\nfunction isNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nfunction isOptionalNumber(value: unknown): value is number | undefined {\n return value === undefined || isNumber(value);\n}\n\nfunction isOptionalNonNegativeInteger(value: unknown): value is number | undefined {\n return value === undefined || (isNumber(value) && Number.isInteger(value) && value >= 0);\n}\n\nfunction isOptionalBoolean(value: unknown): value is boolean | undefined {\n return value === undefined || isBoolean(value);\n}\n\nfunction isNullableNumber(value: unknown): value is number | null {\n return value === null || isNumber(value);\n}\n\nfunction isBoolean(value: unknown): value is boolean {\n return typeof value === 'boolean';\n}\n\nfunction isOneOf<const T extends readonly string[]>(\n value: unknown,\n options: T\n): value is T[number] {\n return typeof value === 'string' && options.includes(value);\n}\n","import { execa } from 'execa';\nimport { parseUnifiedDiff } from '../shared/diff-parser';\nimport { summarizeDiffFiles } from '../shared/diff-stats';\nimport type {\n BaseRef,\n CommitDiff,\n DiffFallbackReason,\n DiffPayload,\n DiffRef,\n DiffScopeMode\n} from '../shared/types';\n\nconst DIFF_ARGS = ['diff', '--no-color', '--find-renames', '--find-copies'];\n\nasync function git(args: string[], cwd = process.cwd()): Promise<string> {\n const result = await execa('git', args, { cwd });\n return result.stdout.trimEnd();\n}\n\nasync function gitMaybe(args: string[], cwd: string): Promise<string | null> {\n const result = await execa('git', args, { cwd, reject: false });\n return result.exitCode === 0 ? result.stdout.trimEnd() : null;\n}\n\nasync function gitLenient(args: string[], cwd: string): Promise<string> {\n const result = await execa('git', args, { cwd, reject: false });\n if (result.exitCode !== 0 && result.stdout.length === 0) {\n throw new Error(result.stderr || `git ${args.join(' ')} failed`);\n }\n return result.stdout.trimEnd();\n}\n\nexport async function getRepoRoot(cwd = process.cwd()): Promise<string> {\n return git(['rev-parse', '--show-toplevel'], cwd);\n}\n\ninterface ResolvedBranchBase {\n sourceRef: string;\n mergeBaseSha: string;\n}\n\ninterface PayloadOptions {\n repoRoot: string;\n branch: string | null;\n rawDiff: string;\n base: BaseRef;\n mode: DiffScopeMode;\n requestedBase: string | null;\n comparison: DiffRef;\n fallbackReason: DiffFallbackReason;\n commitDiffs?: CommitDiff[];\n}\n\nfunction buildPayload({\n repoRoot,\n branch,\n rawDiff,\n base,\n mode,\n requestedBase,\n comparison,\n fallbackReason,\n commitDiffs\n}: PayloadOptions): DiffPayload {\n const files = parseUnifiedDiff(rawDiff);\n return {\n base,\n branch,\n cwd: repoRoot,\n scope: {\n mode,\n requestedBase,\n base,\n comparison,\n fallbackReason\n },\n stats: summarizeDiffFiles(files),\n rawDiff,\n files,\n ...(commitDiffs ? { commitDiffs } : {}),\n capturedAt: new Date().toISOString()\n };\n}\n\nasync function currentBranch(repoRoot: string): Promise<string | null> {\n const branch = await gitMaybe(['rev-parse', '--abbrev-ref', 'HEAD'], repoRoot);\n return branch && branch !== 'HEAD' ? branch : null;\n}\n\nasync function captureUntrackedDiff(repoRoot: string): Promise<string[]> {\n const untrackedFilesRaw = await git(\n ['ls-files', '--others', '--exclude-standard', '-z'],\n repoRoot\n );\n const untrackedFiles = untrackedFilesRaw.split('\\0').filter(Boolean);\n return Promise.all(\n untrackedFiles.map((filePath) =>\n gitLenient(['diff', '--no-color', '--no-index', '--', '/dev/null', filePath], repoRoot)\n )\n );\n}\n\nasync function captureWorkingDiff(baseRef: string, repoRoot: string): Promise<string> {\n const [trackedDiff, untrackedDiffs] = await Promise.all([\n git([...DIFF_ARGS, baseRef, '--'], repoRoot),\n captureUntrackedDiff(repoRoot)\n ]);\n return [trackedDiff, ...untrackedDiffs].filter(Boolean).join('\\n');\n}\n\nasync function resolveCommit(ref: string, repoRoot: string): Promise<string | null> {\n return gitMaybe(['rev-parse', '--verify', `${ref}^{commit}`], repoRoot);\n}\n\nasync function resolveBranchBase(repoRoot: string): Promise<ResolvedBranchBase | null> {\n const candidates: string[] = [];\n const upstream = await gitMaybe(\n ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{upstream}'],\n repoRoot\n );\n const originHead = await gitMaybe(\n ['symbolic-ref', '--quiet', '--short', 'refs/remotes/origin/HEAD'],\n repoRoot\n );\n\n for (const ref of [upstream, originHead, 'origin/main', 'origin/master']) {\n if (ref && !candidates.includes(ref)) {\n candidates.push(ref);\n }\n }\n\n for (const sourceRef of candidates) {\n const [sourceSha, mergeBaseSha] = await Promise.all([\n resolveCommit(sourceRef, repoRoot),\n gitMaybe(['merge-base', 'HEAD', sourceRef], repoRoot)\n ]);\n if (sourceSha && mergeBaseSha) {\n return { sourceRef, mergeBaseSha };\n }\n }\n\n return null;\n}\n\nasync function captureCommitDiffs(\n baseSha: string,\n comparisonRef: string,\n repoRoot: string\n): Promise<CommitDiff[]> {\n const rawLog = await gitMaybe(\n [\n 'log',\n '--reverse',\n '--format=%H%x00%h%x00%an%x00%ae%x00%aI%x00%cI%x00%s%x1e',\n `${baseSha}..${comparisonRef}`\n ],\n repoRoot\n );\n if (!rawLog) {\n return [];\n }\n\n const commits = rawLog\n .split('\\x1e')\n .map((entry) => entry.trim())\n .filter(Boolean)\n .map((entry) => {\n const [\n sha = '',\n shortSha = '',\n authorName = '',\n authorEmail = '',\n authoredAt = '',\n committedAt = '',\n ...subjectParts\n ] = entry.split('\\x00');\n return {\n sha,\n shortSha,\n subject: subjectParts.join('\\x00'),\n authorName,\n authorEmail,\n authoredAt,\n committedAt\n };\n })\n .filter((commit) => commit.sha && commit.shortSha);\n\n const commitDiffs: CommitDiff[] = [];\n for (const commit of commits) {\n const rawDiff = await git([...DIFF_ARGS, `${commit.sha}^`, commit.sha, '--'], repoRoot);\n const files = parseUnifiedDiff(rawDiff);\n commitDiffs.push({\n commit,\n stats: summarizeDiffFiles(files),\n rawDiff,\n files\n });\n }\n return commitDiffs;\n}\n\nexport async function captureDiff(baseRef?: string, cwd = process.cwd()): Promise<DiffPayload> {\n const repoRoot = await getRepoRoot(cwd);\n const [headSha, branch] = await Promise.all([\n git(['rev-parse', 'HEAD'], repoRoot),\n currentBranch(repoRoot)\n ]);\n\n if (baseRef) {\n const [baseSha, rawDiff] = await Promise.all([\n git(['rev-parse', baseRef], repoRoot),\n captureWorkingDiff(baseRef, repoRoot)\n ]);\n return buildPayload({\n repoRoot,\n branch,\n rawDiff,\n base: { ref: baseRef, sha: baseSha },\n mode: 'explicit',\n requestedBase: baseRef,\n comparison: { ref: 'working tree', sha: null },\n fallbackReason: null\n });\n }\n\n const workingDiff = await captureWorkingDiff('HEAD', repoRoot);\n if (workingDiff.trim().length > 0) {\n return buildPayload({\n repoRoot,\n branch,\n rawDiff: workingDiff,\n base: { ref: 'HEAD', sha: headSha },\n mode: 'working',\n requestedBase: null,\n comparison: { ref: 'working tree', sha: null },\n fallbackReason: null\n });\n }\n\n const branchBase = await resolveBranchBase(repoRoot);\n if (!branchBase) {\n return buildPayload({\n repoRoot,\n branch,\n rawDiff: '',\n base: { ref: 'HEAD', sha: headSha },\n mode: 'working',\n requestedBase: null,\n comparison: { ref: 'working tree', sha: null },\n fallbackReason: 'missing-branch-base'\n });\n }\n\n const [rawDiff, commitDiffs] = await Promise.all([\n git([...DIFF_ARGS, branchBase.mergeBaseSha, 'HEAD', '--'], repoRoot),\n captureCommitDiffs(branchBase.mergeBaseSha, 'HEAD', repoRoot)\n ]);\n return buildPayload({\n repoRoot,\n branch,\n rawDiff,\n base: { ref: `merge-base(${branchBase.sourceRef})`, sha: branchBase.mergeBaseSha },\n mode: 'branch',\n requestedBase: null,\n comparison: { ref: 'HEAD', sha: headSha },\n fallbackReason: 'working-tree-clean',\n commitDiffs\n });\n}\n\nexport async function assertGitAvailable(): Promise<void> {\n await execa('git', ['--version']);\n}\n","import path from 'node:path';\n\nconst languageByExtension: Record<string, string> = {\n cjs: 'js',\n css: 'css',\n go: 'go',\n html: 'html',\n js: 'js',\n json: 'json',\n jsx: 'jsx',\n md: 'markdown',\n mjs: 'js',\n py: 'python',\n rb: 'ruby',\n rs: 'rust',\n sh: 'bash',\n swift: 'swift',\n ts: 'ts',\n tsx: 'tsx',\n yaml: 'yaml',\n yml: 'yaml'\n};\n\nexport function languageForPath(filePath: string): string | null {\n const ext = path.extname(filePath).slice(1).toLowerCase();\n if (!ext) {\n return null;\n }\n return languageByExtension[ext] ?? ext;\n}\n","import { languageForPath } from './language';\nimport type { DiffFile, DiffHunk, DiffLine } from './types';\n\nconst hunkHeaderPattern = /^@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@(.*)$/;\n\nfunction stripGitPath(input: string): string {\n return input.replace(/^[ab]\\//, '');\n}\n\nfunction emptyFile(): DiffFile {\n return {\n path: '',\n oldPath: null,\n additions: 0,\n deletions: 0,\n isBinary: false,\n isDeleted: false,\n isNew: false,\n isRenamed: false,\n language: null,\n hunks: []\n };\n}\n\nexport function parseUnifiedDiff(diffText: string): DiffFile[] {\n const files: DiffFile[] = [];\n let current: DiffFile | null = null;\n let currentHunk: DiffHunk | null = null;\n let oldCursor = 0;\n let newCursor = 0;\n\n const finalizeFile = () => {\n if (current?.path) {\n current.language = languageForPath(current.path);\n files.push(current);\n }\n };\n\n for (const line of diffText.split('\\n')) {\n if (line.startsWith('diff --git ')) {\n finalizeFile();\n current = emptyFile();\n currentHunk = null;\n oldCursor = 0;\n newCursor = 0;\n const match = /^diff --git a\\/(.+) b\\/(.+)$/.exec(line);\n if (match) {\n current.oldPath = match[1];\n current.path = match[2];\n }\n continue;\n }\n\n if (!current) {\n continue;\n }\n\n if (line.startsWith('new file mode')) {\n current.isNew = true;\n continue;\n }\n\n if (line.startsWith('deleted file mode')) {\n current.isDeleted = true;\n continue;\n }\n\n if (line.startsWith('rename from ')) {\n current.oldPath = line.slice('rename from '.length);\n current.isRenamed = true;\n continue;\n }\n\n if (line.startsWith('rename to ')) {\n current.path = line.slice('rename to '.length);\n current.isRenamed = true;\n continue;\n }\n\n if (line.startsWith('Binary files ') || line.startsWith('GIT binary patch')) {\n current.isBinary = true;\n continue;\n }\n\n if (line.startsWith('--- ')) {\n const oldPath = line.slice(4).trim();\n current.oldPath = oldPath === '/dev/null' ? null : stripGitPath(oldPath);\n continue;\n }\n\n if (line.startsWith('+++ ')) {\n const newPath = line.slice(4).trim();\n current.path =\n newPath === '/dev/null' ? (current.oldPath ?? current.path) : stripGitPath(newPath);\n continue;\n }\n\n const hunkMatch = hunkHeaderPattern.exec(line);\n if (hunkMatch) {\n const oldStart = Number(hunkMatch[1]);\n const oldLines = Number(hunkMatch[2] ?? '1');\n const newStart = Number(hunkMatch[3]);\n const newLines = Number(hunkMatch[4] ?? '1');\n currentHunk = {\n oldStart,\n oldLines,\n newStart,\n newLines,\n header: hunkMatch[5]?.trim() ?? '',\n lines: []\n };\n current.hunks.push(currentHunk);\n oldCursor = oldStart;\n newCursor = newStart;\n continue;\n }\n\n if (!currentHunk) {\n continue;\n }\n\n const marker = line[0];\n const content = line.slice(1);\n let diffLine: DiffLine | null = null;\n\n if (marker === '+') {\n diffLine = { type: 'add', oldLine: null, newLine: newCursor, content };\n current.additions += 1;\n newCursor += 1;\n } else if (marker === '-') {\n diffLine = { type: 'delete', oldLine: oldCursor, newLine: null, content };\n current.deletions += 1;\n oldCursor += 1;\n } else if (marker === ' ') {\n diffLine = { type: 'context', oldLine: oldCursor, newLine: newCursor, content };\n oldCursor += 1;\n newCursor += 1;\n } else if (line.startsWith('\\\')) {\n continue;\n }\n\n if (diffLine) {\n currentHunk.lines.push(diffLine);\n }\n }\n\n finalizeFile();\n return files;\n}\n","import type { DiffFile, DiffStats } from './types';\n\nexport function summarizeDiffFiles(files: DiffFile[]): DiffStats {\n return files.reduce(\n (stats, file) => ({\n files: stats.files + 1,\n additions: stats.additions + file.additions,\n deletions: stats.deletions + file.deletions\n }),\n { files: 0, additions: 0, deletions: 0 }\n );\n}\n","import { execFile, spawn } from 'node:child_process';\nimport { closeSync, existsSync, openSync } from 'node:fs';\nimport { rm } from 'node:fs/promises';\nimport { userInfo } from 'node:os';\nimport { fileURLToPath } from 'node:url';\nimport { promisify } from 'node:util';\nimport getPort from 'get-port';\nimport {\n ensureDir,\n globalLogDir,\n globalServerFile,\n globalServerLogFile,\n globalStateDir,\n packageVersion\n} from '../shared/paths';\nimport { readServerInfo, writeServerInfo } from '../shared/server-info';\nimport type { ServerInfo } from '../shared/types';\nimport { ServerClient } from './server-client';\n\nexport { readServerInfo } from '../shared/server-info';\n\nconst execFileAsync = promisify(execFile);\nconst gracefulShutdownTimeoutMs = 2000;\nconst forceShutdownTimeoutMs = 1000;\n\nexport function serverUrl(info: Pick<ServerInfo, 'port'>): string {\n return `http://localhost:${info.port}`;\n}\n\nexport async function isServerResponsive(info: ServerInfo): Promise<boolean> {\n if (!isPidAlive(info.pid)) {\n return false;\n }\n try {\n const health = await new ServerClient(serverUrl(info)).health();\n return health.ok === true && health.version === packageVersion;\n } catch {\n return false;\n }\n}\n\nexport async function ensureServer(options: { port?: number } = {}): Promise<ServerInfo> {\n const existing = await readServerInfo();\n if (existing && (await isServerResponsive(existing))) {\n return existing;\n }\n return startServer(options);\n}\n\nexport async function startServer(options: { port?: number } = {}): Promise<ServerInfo> {\n const existing = await readServerInfo();\n if (existing && (await isServerResponsive(existing))) {\n return existing;\n }\n if (existing) {\n await retireServer(existing);\n }\n\n const preferredPort = options.port ?? existing?.port ?? (await getPort());\n try {\n return await launchServer(preferredPort);\n } catch (error) {\n if (options.port || !existing?.port) {\n throw error;\n }\n await removeServerInfoForPid(existing.pid);\n return launchServer(await getPort());\n }\n}\n\nasync function launchServer(port: number): Promise<ServerInfo> {\n await ensureDir(globalStateDir());\n await ensureDir(globalLogDir());\n const daemonPath = fileURLToPath(new URL('../server/daemon.js', import.meta.url));\n if (!existsSync(daemonPath)) {\n throw new Error(`Cannot find server daemon at ${daemonPath}. Run pnpm build first.`);\n }\n\n const logFd = openSync(globalServerLogFile(), 'a');\n const child = spawn(process.execPath, [daemonPath], {\n detached: true,\n env: {\n ...process.env,\n GLOSS_PORT: String(port),\n GLOSS_STATE_DIR: globalStateDir()\n },\n stdio: ['ignore', logFd, logFd]\n });\n closeSync(logFd);\n child.unref();\n\n const info: ServerInfo = {\n pid: child.pid ?? -1,\n port,\n version: packageVersion,\n startedAt: new Date().toISOString(),\n stateDir: globalStateDir()\n };\n await writeServerInfo(info);\n\n const deadline = Date.now() + 8000;\n while (Date.now() < deadline) {\n if (await isServerResponsive(info)) {\n return info;\n }\n await new Promise((resolve) => setTimeout(resolve, 150));\n }\n\n await terminatePid(info.pid);\n await removeServerInfoForPid(info.pid);\n throw new Error(`Server did not become responsive. See ${globalServerLogFile()}`);\n}\n\nexport async function stopServer(\n options: { all?: boolean } = {}\n): Promise<{ stopped: boolean; info: ServerInfo | null; stoppedPids?: number[] }> {\n if (options.all) {\n const info = await readServerInfo();\n const daemonPids = await listGlossDaemonPids();\n const stoppedPids: number[] = [];\n for (const pid of daemonPids) {\n if (await terminatePid(pid)) {\n stoppedPids.push(pid);\n }\n }\n await rm(globalServerFile(), { force: true });\n return { stopped: stoppedPids.length > 0, info, stoppedPids };\n }\n\n const info = await readServerInfo();\n if (!info) {\n return { stopped: false, info: null };\n }\n\n if (!isPidAlive(info.pid)) {\n await removeServerInfoForPid(info.pid);\n return { stopped: false, info };\n }\n\n if (!(await isGlossDaemonPid(info.pid))) {\n await removeServerInfoForPid(info.pid);\n return { stopped: false, info };\n }\n\n const stopped = await terminatePid(info.pid);\n if (stopped) {\n await removeServerInfoForPid(info.pid);\n }\n return { stopped, info };\n}\n\nfunction isPidAlive(pid: number): boolean {\n if (pid <= 0) {\n return false;\n }\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function retireServer(info: ServerInfo): Promise<void> {\n if (isPidAlive(info.pid) && (await isGlossDaemonPid(info.pid))) {\n await terminatePid(info.pid);\n }\n await removeServerInfoForPid(info.pid);\n}\n\nasync function terminatePid(pid: number): Promise<boolean> {\n if (!isPidAlive(pid)) {\n return true;\n }\n try {\n process.kill(pid, 'SIGTERM');\n } catch {\n return !isPidAlive(pid);\n }\n if (await waitForPidExit(pid, gracefulShutdownTimeoutMs)) {\n return true;\n }\n try {\n process.kill(pid, 'SIGKILL');\n } catch {\n return !isPidAlive(pid);\n }\n return waitForPidExit(pid, forceShutdownTimeoutMs);\n}\n\nasync function waitForPidExit(pid: number, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n if (!isPidAlive(pid)) {\n return true;\n }\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n return !isPidAlive(pid);\n}\n\nasync function removeServerInfoForPid(pid: number): Promise<void> {\n const current = await readServerInfo().catch(() => null);\n if (!current || current.pid === pid) {\n await rm(globalServerFile(), { force: true });\n }\n}\n\nasync function isGlossDaemonPid(pid: number): Promise<boolean> {\n const command = await readProcessCommand(pid);\n return command ? isGlossDaemonCommand(command) : false;\n}\n\nasync function readProcessCommand(pid: number): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync('ps', ['-o', 'command=', '-p', String(pid), '-ww']);\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\nexport async function listGlossDaemonPids(): Promise<number[]> {\n let stdout: string;\n try {\n ({ stdout } = await execFileAsync('ps', ['-axo', 'pid=,user=,command=', '-ww']));\n } catch {\n return [];\n }\n const currentUser = userInfo().username;\n return parseGlossDaemonPids(stdout, currentUser, process.pid);\n}\n\nexport function parseGlossDaemonPids(\n stdout: string,\n currentUser: string,\n currentPid = process.pid\n): number[] {\n return stdout\n .split('\\n')\n .map((line) => /^\\s*(\\d+)\\s+(\\S+)\\s+(.+)$/.exec(line))\n .filter((match): match is RegExpExecArray => Boolean(match))\n .map((match) => ({\n pid: Number(match[1]),\n user: match[2],\n command: match[3]\n }))\n .filter(\n ({ pid, user, command }) =>\n pid !== currentPid && user === currentUser && isGlossDaemonCommand(command)\n )\n .map(({ pid }) => pid);\n}\n\nfunction isGlossDaemonCommand(command: string): boolean {\n return /(?:^|\\s)(?:\\S*\\/)?node\\s+\\S*dist\\/server\\/daemon\\.js(?:\\s|$)/.test(command);\n}\n","import { readFile } from 'node:fs/promises';\nimport { formatError, isFileNotFound } from './errors';\nimport { writeJsonFile } from './json';\nimport { ensureDir, globalServerFile, globalStateDir } from './paths';\nimport type { ServerInfo } from './types';\nimport { isServerInfo, parseJson } from './validation';\n\nexport async function readServerInfo(): Promise<ServerInfo | null> {\n let raw: string;\n try {\n raw = await readFile(globalServerFile(), 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return null;\n }\n throw new Error(`Could not read server info at ${globalServerFile()}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n try {\n return parseJson(raw, isServerInfo, 'server info');\n } catch (error) {\n throw new Error(`Invalid server info at ${globalServerFile()}: ${formatError(error)}`, {\n cause: error\n });\n }\n}\n\nexport async function writeServerInfo(info: ServerInfo): Promise<void> {\n await ensureDir(globalStateDir());\n await writeJsonFile(globalServerFile(), info);\n}\n","import { randomUUID } from 'node:crypto';\nimport { rename, rm, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type {\n DiffPayload,\n FeedbackBundle,\n ResolutionBundle,\n ReviewMeta,\n ReviewTurnMeta,\n ServerInfo\n} from './types';\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | { [key: string]: JsonValue }\n | JsonValue[];\n\ntype PersistedJson =\n | ServerInfo\n | ReviewMeta\n | ReviewTurnMeta\n | DiffPayload\n | FeedbackBundle\n | ResolutionBundle;\n\nfunction serializeJson(value: PersistedJson): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nexport async function writeJsonFile(filePath: string, value: PersistedJson): Promise<void> {\n await writeTextFile(filePath, serializeJson(value));\n}\n\nexport async function writeTextFile(filePath: string, value: string): Promise<void> {\n const tempPath = path.join(\n path.dirname(filePath),\n `.${path.basename(filePath)}.${process.pid}.${randomUUID()}.tmp`\n );\n try {\n await writeFile(tempPath, value);\n await rename(tempPath, filePath);\n } catch (error) {\n await rm(tempPath, { force: true }).catch(() => undefined);\n throw error;\n }\n}\n","import type { JsonValue } from '../shared/json';\nimport type {\n ClearReviewsRequest,\n ClearReviewsResult,\n Comment,\n CreateReviewResponse,\n CreateReviewTurnResponse,\n DiffPayload,\n FeedbackBundle,\n HealthResponse,\n ListReviewsResponse,\n OpenResult,\n ResolutionRequest,\n ResolveResult,\n ReviewEvent,\n ReviewRecord,\n SubmitReviewRequest\n} from '../shared/types';\nimport {\n isClearReviewsResult,\n isCreateReviewResponse,\n isCreateReviewTurnResponse,\n isFeedbackBundle,\n isHealthResponse,\n isListReviewsResponse,\n isOpenResult,\n isResolveResult,\n isReviewEvent,\n isReviewRecord,\n type JsonGuard,\n parseJson,\n parseJsonValue\n} from '../shared/validation';\n\nexport class ServerClient {\n constructor(private readonly baseUrl: string) {}\n\n async health(): Promise<HealthResponse> {\n return this.get('/api/health', isHealthResponse, 'health response');\n }\n\n async createReview(diff: DiffPayload): Promise<CreateReviewResponse> {\n return this.post('/api/reviews', diff, isCreateReviewResponse, 'create review response');\n }\n\n async appendReviewTurn(reviewId: string, diff: DiffPayload): Promise<CreateReviewTurnResponse> {\n return this.post(\n `/api/reviews/${reviewId}/turns`,\n diff,\n isCreateReviewTurnResponse,\n 'create review turn response'\n );\n }\n\n async getReview(reviewId: string): Promise<ReviewRecord> {\n return this.get(`/api/reviews/${reviewId}`, isReviewRecord, 'review response');\n }\n\n async listReviews(): Promise<ListReviewsResponse> {\n return this.get('/api/reviews', isListReviewsResponse, 'review list response');\n }\n\n async clearReviews(request: ClearReviewsRequest): Promise<ClearReviewsResult> {\n return this.post(\n '/api/maintenance/clear-reviews',\n request,\n isClearReviewsResult,\n 'clear reviews response'\n );\n }\n\n async getFeedback(reviewId: string): Promise<FeedbackBundle> {\n return this.get(`/api/reviews/${reviewId}/feedback`, isFeedbackBundle, 'feedback response');\n }\n\n async markResolved(reviewId: string, summary?: string, turn?: string): Promise<ResolveResult> {\n const request: ResolutionRequest = { summary, turn };\n return this.post(\n `/api/reviews/${reviewId}/resolved`,\n request,\n isResolveResult,\n 'resolve response'\n );\n }\n\n async resolveComment(\n reviewId: string,\n commentId: string,\n summary?: string\n ): Promise<ResolveResult> {\n const request: ResolutionRequest = { summary };\n return this.post(\n `/api/reviews/${reviewId}/comments/${commentId}/resolved`,\n request,\n isResolveResult,\n 'resolve comment response'\n );\n }\n\n async reopenComment(reviewId: string, commentId: string): Promise<ResolveResult> {\n return this.delete(\n `/api/reviews/${reviewId}/comments/${commentId}/resolved`,\n isResolveResult,\n 'reopen comment response'\n );\n }\n\n async submitReview(reviewId: string, comments: Comment[]): Promise<OpenResult> {\n const request: SubmitReviewRequest = { comments };\n return this.post(\n `/api/reviews/${reviewId}/submit`,\n request,\n isOpenResult,\n 'submit review response'\n );\n }\n\n async watchReview(reviewId: string, timeoutSeconds?: number): Promise<ReviewEvent> {\n const deadline =\n timeoutSeconds && timeoutSeconds > 0 ? Date.now() + timeoutSeconds * 1000 : null;\n\n while (true) {\n const remainingMs = deadline ? deadline - Date.now() : null;\n if (remainingMs !== null && remainingMs <= 0) {\n throw new Error(`watch timed out after ${timeoutSeconds} seconds`);\n }\n\n const controller = new AbortController();\n const timeout = remainingMs ? setTimeout(() => controller.abort(), remainingMs) : null;\n try {\n return await this.readReviewEvents(reviewId, controller.signal);\n } catch (error) {\n if (isAbortError(error)) {\n throw new Error(`watch timed out after ${timeoutSeconds} seconds`);\n }\n if (!isPrematureWatchEnd(error)) {\n throw error;\n }\n await sleep(500);\n } finally {\n if (timeout) {\n clearTimeout(timeout);\n }\n }\n }\n }\n\n private async readReviewEvents(reviewId: string, signal: AbortSignal): Promise<ReviewEvent> {\n const response = await fetch(`${this.baseUrl}/api/reviews/${reviewId}/events`, {\n signal\n });\n if (!response.ok || !response.body) {\n throw new Error(`watch failed: ${response.status} ${await response.text()}`);\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n throw new Error('watch stream ended before completion');\n }\n buffer += decoder.decode(value, { stream: true });\n const events = buffer.split('\\n\\n');\n buffer = events.pop() ?? '';\n for (const eventChunk of events) {\n const dataLine = eventChunk.split('\\n').find((line) => line.startsWith('data:'));\n if (!dataLine) {\n continue;\n }\n const event = parseJson(dataLine.slice(5).trim(), isReviewEvent, 'review event');\n if (event.type === 'review.submitted' || event.type === 'review.cancelled') {\n await reader.cancel().catch(() => undefined);\n return event;\n }\n }\n }\n }\n\n private async get<T>(path: string, guard: JsonGuard<T>, label: string): Promise<T> {\n const response = await fetch(`${this.baseUrl}${path}`);\n return parseResponse(response, guard, label);\n }\n\n private async post<T>(\n path: string,\n body: ClearReviewsRequest | DiffPayload | ResolutionRequest | SubmitReviewRequest,\n guard: JsonGuard<T>,\n label: string\n ): Promise<T> {\n const response = await fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body)\n });\n return parseResponse(response, guard, label);\n }\n\n private async delete<T>(path: string, guard: JsonGuard<T>, label: string): Promise<T> {\n const response = await fetch(`${this.baseUrl}${path}`, { method: 'DELETE' });\n return parseResponse(response, guard, label);\n }\n}\n\nasync function parseResponse<T>(\n response: Response,\n guard: JsonGuard<T>,\n label: string\n): Promise<T> {\n if (!response.ok) {\n throw new Error(`${response.status} ${response.statusText}: ${await response.text()}`);\n }\n const value: JsonValue = await response.json();\n return parseJsonValue(value, guard, label);\n}\n\nfunction isPrematureWatchEnd(error: unknown): error is Error {\n return error instanceof Error && error.message === 'watch stream ended before completion';\n}\n\nfunction isAbortError(error: unknown): error is Error {\n return error instanceof Error && error.name === 'AbortError';\n}\n\nasync function sleep(milliseconds: number): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\n","import { createHash } from 'node:crypto';\nimport type { Dirent } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { ulid } from 'ulid';\nimport { type ClearReviewArtifactsOptions, clearReviewArtifacts } from '../shared/cleanup';\nimport { compareCommentsByLocation, countCommentFiles, resolutionCounts } from '../shared/comments';\nimport { formatError, isFileNotFound } from '../shared/errors';\nimport { writeJsonFile, writeTextFile } from '../shared/json';\nimport { serializeFeedbackMarkdown } from '../shared/markdown';\nimport {\n ensureDir,\n globalReviewDiffFile,\n globalReviewDir,\n globalReviewFeedbackFile,\n globalReviewMarkdownFile,\n globalReviewMetaFile,\n globalReviewResolvedFile,\n globalReviewsDir,\n globalReviewTurnDiffFile,\n globalReviewTurnDir,\n globalReviewTurnFeedbackFile,\n globalReviewTurnMarkdownFile,\n globalReviewTurnMetaFile,\n globalReviewTurnResolvedFile,\n globalReviewTurnsDir\n} from '../shared/paths';\nimport { normalizeReviewScope, sameReviewScope } from '../shared/review-scope';\nimport { isResolvableReviewStatus } from '../shared/reviews';\nimport type {\n ClearReviewsResult,\n Comment,\n DiffPayload,\n FeedbackBundle,\n ResolutionBundle,\n ResolvedComment,\n ResolveResult,\n ReviewEvent,\n ReviewMeta,\n ReviewRecord,\n ReviewScope,\n ReviewTurn,\n ReviewTurnMeta,\n ReviewTurnSummary,\n ReviewUpdateReason\n} from '../shared/types';\nimport {\n isDiffPayload,\n isFeedbackBundle,\n isResolutionBundle,\n isReviewTurnMeta,\n isStoredReviewMeta,\n type JsonGuard,\n parseJson,\n type StoredReviewMeta\n} from '../shared/validation';\n\ntype Listener = (event: ReviewEvent) => void;\n\ninterface SubmitResult {\n record: ReviewRecord;\n feedbackPath: string;\n markdownPath: string;\n turn: ReviewTurn;\n}\n\ninterface AppendTurnResult {\n record: ReviewRecord;\n turn: ReviewTurn;\n reused: boolean;\n}\n\nexport class ReviewStore {\n private readonly reviews = new Map<string, ReviewRecord>();\n private readonly listeners = new Map<string, Set<Listener>>();\n\n async create(diff: DiffPayload): Promise<ReviewRecord> {\n const id = ulid();\n const createdAt = new Date().toISOString();\n const turn = createTurn(id, 1, diff, createdAt);\n const meta: ReviewMeta = {\n id,\n cwd: diff.cwd,\n base: diff.base,\n branch: diff.branch,\n status: 'pending',\n createdAt,\n artifactDir: globalReviewDir(id),\n activeTurnId: turn.id\n };\n const record = normalizeRecord({ meta, turns: [turn], diff: turn.diff });\n this.reviews.set(id, record);\n await this.persistInitial(record, turn);\n this.emit({ type: 'review.opened', reviewId: id });\n return record;\n }\n\n async appendTurn(id: string, diff: DiffPayload): Promise<AppendTurnResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n if (record.meta.cwd !== diff.cwd) {\n throw new Error(`Review ${id} belongs to ${record.meta.cwd}, not ${diff.cwd}`);\n }\n\n const latest = latestTurn(record);\n if (latest.status === 'pending') {\n if (diffFingerprint(latest.diff) === diffFingerprint(diff)) {\n this.emit({\n type: 'review.turn.created',\n reviewId: id,\n turnId: latest.id,\n turnIndex: latest.index,\n reused: true\n });\n return { record, turn: latest, reused: true };\n }\n throw new Error(`Review ${id} already has a pending turn`);\n }\n if (latest.status === 'cancelled') {\n throw new Error(`Review ${id} is cancelled and cannot be continued`);\n }\n\n const turn = createTurn(id, latest.index + 1, diff, new Date().toISOString());\n const nextRecord = normalizeRecord({\n ...record,\n meta: { ...record.meta, activeTurnId: turn.id },\n turns: [...record.turns, turn]\n });\n this.reviews.set(id, nextRecord);\n await this.persistInitial(nextRecord, turn);\n this.emit({\n type: 'review.turn.created',\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n reused: false\n });\n return { record: nextRecord, turn, reused: false };\n }\n\n async list(): Promise<ReviewMeta[]> {\n await this.loadAllReviews();\n return Array.from(this.reviews.values())\n .map((record) => record.meta)\n .toSorted((a, b) => a.createdAt.localeCompare(b.createdAt));\n }\n\n async clearReviewArtifacts(\n options: ClearReviewArtifactsOptions = {}\n ): Promise<ClearReviewsResult> {\n const result = await clearReviewArtifacts(options);\n if (!result.dryRun) {\n for (const review of result.deleted) {\n this.reviews.delete(review.reviewId);\n }\n }\n return result;\n }\n\n async get(id: string): Promise<ReviewRecord | null> {\n return this.reviews.get(id) ?? (await this.loadKnownReview(id));\n }\n\n async getTurn(id: string, turnId: string): Promise<ReviewTurn | null> {\n const record = await this.get(id);\n return record?.turns.find((turn) => turn.id === turnId) ?? null;\n }\n\n async submit(id: string, comments: Comment[], reviewScope?: ReviewScope): Promise<SubmitResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = activeTurn(record);\n const sortedComments = comments.toSorted(compareCommentsByLocation);\n const normalizedReviewScope = normalizeReviewScope(turn.diff, reviewScope);\n if (turn.status !== 'pending') {\n if (\n turn.feedback &&\n sameComments(turn.feedback.comments, sortedComments) &&\n sameReviewScope(turn.feedback.reviewScope, normalizedReviewScope)\n ) {\n return {\n record,\n feedbackPath: requiredPath(turn.feedbackPath, 'feedback path'),\n markdownPath: requiredPath(turn.markdownPath, 'markdown path'),\n turn\n };\n }\n throw new Error(`Review ${id} turn ${turn.index} is ${turn.status} and cannot be submitted`);\n }\n\n const timestamp = new Date().toISOString();\n const feedbackPath = globalReviewTurnFeedbackFile(id, turn.id);\n const markdownPath = globalReviewTurnMarkdownFile(id, turn.id);\n const feedback: FeedbackBundle = {\n version: 1,\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n timestamp,\n base: turn.diff.base,\n branch: turn.diff.branch,\n reviewScope: normalizedReviewScope,\n comments: sortedComments\n };\n const nextTurn: ReviewTurn = {\n ...turn,\n status: 'submitted',\n submittedAt: timestamp,\n feedbackPath,\n markdownPath,\n feedback\n };\n const nextRecord = normalizeRecord(replaceTurn(record, nextTurn));\n this.reviews.set(id, nextRecord);\n\n await ensureDir(globalReviewTurnDir(id, nextTurn.id));\n await Promise.all([\n writeJsonFile(globalReviewTurnMetaFile(id, nextTurn.id), turnMeta(nextTurn)),\n writeJsonFile(feedbackPath, feedback),\n writeTextFile(markdownPath, serializeFeedbackMarkdown(feedback))\n ]);\n await this.persistMeta(nextRecord);\n\n this.emit({\n type: 'review.submitted',\n reviewId: id,\n turnId: nextTurn.id,\n turnIndex: nextTurn.index,\n counts: {\n files: countCommentFiles(feedback.comments),\n comments: feedback.comments.length\n }\n });\n return { record: nextRecord, feedbackPath, markdownPath, turn: nextTurn };\n }\n\n async feedback(id: string): Promise<FeedbackBundle | null> {\n const record = await this.get(id);\n return record?.feedback ?? null;\n }\n\n async markResolved(id: string, summary?: string, turnSelector?: string): Promise<ResolveResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = this.resolveTurnSelector(record, turnSelector);\n this.assertResolvable(turn, id);\n\n const resolvedAt = new Date().toISOString();\n const existingById = new Map(\n (turn.resolution?.comments ?? []).map((comment) => [comment.commentId, comment])\n );\n const comments = this.sortResolvedComments(\n (turn.feedback?.comments ?? []).map((comment) => ({\n ...existingById.get(comment.id),\n commentId: comment.id,\n status: 'resolved' as const,\n resolvedAt: existingById.get(comment.id)?.resolvedAt ?? resolvedAt\n })),\n turn\n );\n const resolution: ResolutionBundle = {\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n status: 'resolved',\n summary: summary ?? turn.resolution?.summary ?? null,\n resolvedAt,\n comments\n };\n const nextTurn: ReviewTurn & { feedback: FeedbackBundle } = {\n ...turn,\n status: 'resolved',\n resolvedAt\n };\n return this.persistResolution(record, nextTurn, resolution, 'review-resolved');\n }\n\n async resolveComment(id: string, commentId: string, summary?: string): Promise<ResolveResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = this.findTurnForComment(record, commentId);\n if (!turn) {\n const currentTurn = activeTurn(record);\n if (!isResolvableReviewStatus(currentTurn.status)) {\n throw new Error(\n `Review ${id} turn ${currentTurn.index} is ${currentTurn.status} and cannot be resolved`\n );\n }\n throw new Error(`Comment ${commentId} not found`);\n }\n this.assertResolvable(turn, id);\n\n const resolvedAt = new Date().toISOString();\n const previous = turn.resolution?.comments.find((comment) => comment.commentId === commentId);\n const nextSummary = summary ?? previous?.summary;\n const nextComment: ResolvedComment = {\n commentId,\n status: 'resolved',\n ...(nextSummary ? { summary: nextSummary } : {}),\n resolvedAt\n };\n const comments = this.sortResolvedComments(\n [\n ...(turn.resolution?.comments ?? []).filter((comment) => comment.commentId !== commentId),\n nextComment\n ],\n turn\n );\n const counts = resolutionCounts(turn.feedback, comments);\n const fullyResolved = counts.total === counts.resolved;\n const resolution: ResolutionBundle = {\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n status: fullyResolved ? 'resolved' : 'partial',\n summary: fullyResolved ? (turn.resolution?.summary ?? null) : null,\n resolvedAt: fullyResolved ? resolvedAt : null,\n comments\n };\n const nextTurn: ReviewTurn & { feedback: FeedbackBundle } = fullyResolved\n ? { ...turn, status: 'resolved', resolvedAt }\n : { ...turn, status: 'submitted', resolvedAt: undefined };\n return this.persistResolution(record, nextTurn, resolution, 'comment-resolved');\n }\n\n async reopenComment(id: string, commentId: string): Promise<ResolveResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = this.findTurnForComment(record, commentId);\n if (!turn) {\n const currentTurn = activeTurn(record);\n if (!isResolvableReviewStatus(currentTurn.status)) {\n throw new Error(\n `Review ${id} turn ${currentTurn.index} is ${currentTurn.status} and cannot be resolved`\n );\n }\n throw new Error(`Comment ${commentId} not found`);\n }\n this.assertResolvable(turn, id);\n\n const comments = this.sortResolvedComments(\n (turn.resolution?.comments ?? []).filter((comment) => comment.commentId !== commentId),\n turn\n );\n const counts = resolutionCounts(turn.feedback, comments);\n const fullyResolved = counts.total > 0 && counts.total === counts.resolved;\n const resolvedAt = fullyResolved ? new Date().toISOString() : null;\n const resolution: ResolutionBundle = {\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n status: fullyResolved ? 'resolved' : 'partial',\n summary: fullyResolved ? (turn.resolution?.summary ?? null) : null,\n resolvedAt,\n comments\n };\n const nextTurn: ReviewTurn & { feedback: FeedbackBundle } = fullyResolved\n ? { ...turn, status: 'resolved', resolvedAt: resolvedAt ?? undefined }\n : { ...turn, status: 'submitted', resolvedAt: undefined };\n return this.persistResolution(record, nextTurn, resolution, 'comment-reopened');\n }\n\n subscribe(reviewId: string, listener: Listener): () => void {\n const listeners = this.listeners.get(reviewId) ?? new Set<Listener>();\n listeners.add(listener);\n this.listeners.set(reviewId, listeners);\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0) {\n this.listeners.delete(reviewId);\n }\n };\n }\n\n private emit(event: ReviewEvent): void {\n for (const listener of this.listeners.get(event.reviewId) ?? []) {\n listener(event);\n }\n }\n\n private async persistInitial(record: ReviewRecord, turn: ReviewTurn): Promise<void> {\n await ensureDir(turn.artifactDir);\n await Promise.all([\n writeJsonFile(globalReviewTurnMetaFile(record.meta.id, turn.id), turnMeta(turn)),\n writeJsonFile(turn.diffPath, turn.diff)\n ]);\n await this.persistMeta(record);\n }\n\n private async persistMeta(record: ReviewRecord): Promise<void> {\n await ensureDir(globalReviewDir(record.meta.id));\n await writeJsonFile(globalReviewMetaFile(record.meta.id), record.meta);\n }\n\n private async loadKnownReview(id: string): Promise<ReviewRecord | null> {\n const existing = this.reviews.get(id);\n if (existing) {\n return existing;\n }\n\n return this.loadReview(id);\n }\n\n private async loadAllReviews(): Promise<void> {\n let entries: Dirent[];\n try {\n entries = await readdir(globalReviewsDir(), { withFileTypes: true });\n } catch (error) {\n if (isFileNotFound(error)) {\n return;\n }\n throw new Error(\n `Could not read reviews directory at ${globalReviewsDir()}: ${formatError(error)}`,\n {\n cause: error\n }\n );\n }\n\n const reviewLoads: Array<Promise<ReviewRecord | null>> = [];\n for (const entry of entries) {\n if (entry.isDirectory()) {\n reviewLoads.push(this.loadReview(entry.name));\n }\n }\n await Promise.all(reviewLoads);\n }\n\n private async loadReview(id: string): Promise<ReviewRecord | null> {\n const metaPath = globalReviewMetaFile(id);\n let metaRaw: string;\n\n try {\n metaRaw = await readFile(metaPath, 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return this.loadReviewFromTurnsOnly(id);\n }\n throw new Error(`Could not load review ${id}: ${formatError(error)}`, { cause: error });\n }\n\n const storedMeta = parseJsonFile(metaRaw, isStoredReviewMeta, 'review metadata', metaPath);\n const persistedTurns = await this.loadPersistedTurns(id);\n const legacyTurn = await this.loadLegacyTurn(id, storedMeta);\n const turns = mergeRecoveredTurns(legacyTurn, persistedTurns);\n if (turns.length === 0) {\n throw new Error(`Review ${id} has no recoverable turns`);\n }\n\n const latest = latestTurn({ turns } as ReviewRecord);\n const record = normalizeRecord({\n meta: {\n ...storedMeta,\n artifactDir: storedMeta.artifactDir ?? globalReviewDir(id),\n activeTurnId: latest.id\n },\n turns,\n diff: latest.diff\n });\n this.reviews.set(id, record);\n return record;\n }\n\n private async loadReviewFromTurnsOnly(id: string): Promise<ReviewRecord | null> {\n const turns = await this.loadPersistedTurns(id);\n if (turns.length === 0) {\n return null;\n }\n\n const latest = latestTurn({ turns });\n const record = normalizeRecord({\n meta: {\n id,\n cwd: latest.diff.cwd,\n base: latest.diff.base,\n branch: latest.diff.branch,\n status: latest.status,\n createdAt: turns[0]?.createdAt ?? latest.createdAt,\n artifactDir: globalReviewDir(id),\n activeTurnId: latest.id\n },\n turns,\n diff: latest.diff\n });\n this.reviews.set(id, record);\n await this.persistMeta(record);\n return record;\n }\n\n private async loadPersistedTurns(id: string): Promise<ReviewTurn[]> {\n let entries: Dirent[];\n try {\n entries = await readdir(globalReviewTurnsDir(id), { withFileTypes: true });\n } catch (error) {\n if (isFileNotFound(error)) {\n return [];\n }\n throw new Error(`Could not read review turns for ${id}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n const turns: ReviewTurn[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) {\n continue;\n }\n const turn = await this.loadPersistedTurn(id, entry.name);\n if (turn) {\n turns.push(turn);\n }\n }\n\n return turns.toSorted((a, b) => a.index - b.index);\n }\n\n private async loadPersistedTurn(id: string, turnId: string): Promise<ReviewTurn | null> {\n const metaPath = globalReviewTurnMetaFile(id, turnId);\n const diffPath = globalReviewTurnDiffFile(id, turnId);\n let metaRaw: string;\n let diffRaw: string;\n\n try {\n [metaRaw, diffRaw] = await Promise.all([\n readFile(metaPath, 'utf8'),\n readFile(diffPath, 'utf8')\n ]);\n } catch (error) {\n if (isFileNotFound(error)) {\n return null;\n }\n throw new Error(`Could not load review ${id} turn ${turnId}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n const meta = parseJsonFile(metaRaw, isReviewTurnMeta, 'review turn metadata', metaPath);\n const diff = parseJsonFile(diffRaw, isDiffPayload, 'review turn diff', diffPath);\n const [feedback, resolution] = await Promise.all([\n readOptionalJsonFile(\n globalReviewTurnFeedbackFile(id, turnId),\n isFeedbackBundle,\n 'review feedback'\n ),\n readOptionalJsonFile(\n globalReviewTurnResolvedFile(id, turnId),\n isResolutionBundle,\n 'review resolution'\n )\n ]);\n\n return reconcileTurn(meta, diff, feedback, resolution);\n }\n\n private async loadLegacyTurn(\n id: string,\n storedMeta: StoredReviewMeta\n ): Promise<ReviewTurn | null> {\n const diffPath = globalReviewDiffFile(id);\n let diffRaw: string;\n try {\n diffRaw = await readFile(diffPath, 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return null;\n }\n throw new Error(`Could not load legacy review ${id}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n const diff = parseJsonFile(diffRaw, isDiffPayload, 'review diff', diffPath);\n const [feedback, resolution] = await Promise.all([\n readOptionalJsonFile(globalReviewFeedbackFile(id), isFeedbackBundle, 'review feedback'),\n readOptionalJsonFile(globalReviewResolvedFile(id), isResolutionBundle, 'review resolution')\n ]);\n const artifactDir = storedMeta.artifactDir ?? globalReviewDir(id);\n const legacySummary =\n storedMeta.turns?.find(\n (turn) => turn.artifactDir === artifactDir || turn.diffPath === diffPath\n ) ??\n storedMeta.turns?.find((turn) => turn.index === 1) ??\n storedMeta.turns?.[0];\n const meta: ReviewTurnMeta = {\n id: legacySummary?.id ?? storedMeta.activeTurnId ?? 'turn-1',\n index: legacySummary?.index ?? 1,\n status: legacySummary?.status ?? storedMeta.status,\n createdAt: legacySummary?.createdAt ?? storedMeta.createdAt,\n submittedAt: legacySummary?.submittedAt ?? storedMeta.submittedAt,\n resolvedAt: legacySummary?.resolvedAt ?? storedMeta.resolvedAt,\n artifactDir: legacySummary?.artifactDir ?? artifactDir,\n diffPath,\n ...(feedback\n ? { feedbackPath: globalReviewFeedbackFile(id), markdownPath: globalReviewMarkdownFile(id) }\n : {}),\n ...(resolution ? { resolvedPath: globalReviewResolvedFile(id) } : {})\n };\n return reconcileTurn(meta, diff, feedback, resolution);\n }\n\n private assertResolvable(\n turn: ReviewTurn,\n id: string\n ): asserts turn is ReviewTurn & {\n feedback: FeedbackBundle;\n } {\n if (!isResolvableReviewStatus(turn.status)) {\n throw new Error(`Review ${id} turn ${turn.index} is ${turn.status} and cannot be resolved`);\n }\n if (!turn.feedback) {\n throw new Error(`Review ${id} turn ${turn.index} has no submitted feedback`);\n }\n }\n\n private resolveTurnSelector(record: ReviewRecord, selector?: string): ReviewTurn {\n if (!selector) {\n return activeTurn(record);\n }\n const turn =\n record.turns.find((candidate) => candidate.id === selector) ??\n record.turns.find((candidate) => String(candidate.index) === selector);\n if (!turn) {\n throw new Error(`Turn ${selector} not found in review ${record.meta.id}`);\n }\n return turn;\n }\n\n private findTurnForComment(record: ReviewRecord, commentId: string): ReviewTurn | null {\n return (\n [...record.turns]\n .reverse()\n .find((candidate) =>\n candidate.feedback?.comments.some((comment) => comment.id === commentId)\n ) ?? null\n );\n }\n\n private async persistResolution(\n record: ReviewRecord,\n turn: ReviewTurn & { feedback: FeedbackBundle },\n resolution: ResolutionBundle,\n reason: ReviewUpdateReason\n ): Promise<ResolveResult> {\n const resolvedPath = globalReviewTurnResolvedFile(record.meta.id, turn.id);\n const nextTurn: ReviewTurn = {\n ...turn,\n resolvedPath,\n resolution\n };\n const nextRecord = normalizeRecord(replaceTurn(record, nextTurn));\n this.reviews.set(record.meta.id, nextRecord);\n await ensureDir(globalReviewTurnDir(record.meta.id, nextTurn.id));\n await Promise.all([\n writeJsonFile(resolvedPath, resolution),\n writeJsonFile(globalReviewTurnMetaFile(record.meta.id, nextTurn.id), turnMeta(nextTurn))\n ]);\n await this.persistMeta(nextRecord);\n const result: ResolveResult = {\n ok: true,\n reviewId: record.meta.id,\n turnId: nextTurn.id,\n turnIndex: nextTurn.index,\n status: nextTurn.status,\n resolutionStatus: resolution.status,\n comments: resolutionCounts(nextTurn.feedback, resolution.comments),\n path: resolvedPath,\n resolution\n };\n this.emit({\n type: 'review.updated',\n reviewId: record.meta.id,\n turnId: nextTurn.id,\n turnIndex: nextTurn.index,\n reason,\n status: result.status,\n resolutionStatus: result.resolutionStatus,\n counts: result.comments\n });\n return result;\n }\n\n private sortResolvedComments(\n comments: ResolvedComment[],\n turn: ReviewTurn & { feedback: FeedbackBundle }\n ): ResolvedComment[] {\n const feedbackIndex = new Map(\n turn.feedback.comments.map((comment, index) => [comment.id, index] as const)\n );\n return comments\n .map((comment) => ({ comment, index: feedbackIndex.get(comment.commentId) }))\n .filter(\n (entry): entry is { comment: ResolvedComment; index: number } => entry.index !== undefined\n )\n .sort((a, b) => a.index - b.index)\n .map(({ comment }) => comment);\n }\n}\n\nfunction createTurn(\n reviewId: string,\n index: number,\n diff: DiffPayload,\n createdAt: string\n): ReviewTurn {\n const id = ulid();\n return {\n id,\n index,\n status: 'pending',\n createdAt,\n artifactDir: globalReviewTurnDir(reviewId, id),\n diffPath: globalReviewTurnDiffFile(reviewId, id),\n diff\n };\n}\n\nfunction normalizeRecord(record: Pick<ReviewRecord, 'meta' | 'turns' | 'diff'>): ReviewRecord {\n const turns = record.turns.toSorted((a, b) => a.index - b.index);\n const active =\n turns.find((turn) => turn.id === record.meta.activeTurnId) ?? turns[turns.length - 1];\n const meta: ReviewMeta = {\n ...record.meta,\n base: active.diff.base,\n branch: active.diff.branch,\n status: active.status,\n submittedAt: active.submittedAt,\n resolvedAt: active.resolvedAt,\n artifactDir: record.meta.artifactDir ?? globalReviewDir(record.meta.id),\n activeTurnId: active.id,\n turns: turns.map(turnSummary),\n feedbackPath: active.feedbackPath,\n markdownPath: active.markdownPath\n };\n return {\n meta,\n turns,\n diff: active.diff,\n ...(active.feedback ? { feedback: active.feedback } : {}),\n ...(active.resolution ? { resolution: active.resolution } : {})\n };\n}\n\nfunction replaceTurn(record: ReviewRecord, nextTurn: ReviewTurn): ReviewRecord {\n return {\n ...record,\n turns: record.turns.map((turn) => (turn.id === nextTurn.id ? nextTurn : turn))\n };\n}\n\nfunction activeTurn(record: ReviewRecord): ReviewTurn {\n return (\n record.turns.find((turn) => turn.id === record.meta.activeTurnId) ??\n record.turns[record.turns.length - 1]\n );\n}\n\nfunction latestTurn(record: Pick<ReviewRecord, 'turns'>): ReviewTurn {\n return record.turns.toSorted((a, b) => a.index - b.index)[record.turns.length - 1];\n}\n\nfunction turnMeta(turn: ReviewTurn): ReviewTurnMeta {\n return {\n id: turn.id,\n index: turn.index,\n status: turn.status,\n createdAt: turn.createdAt,\n submittedAt: turn.submittedAt,\n resolvedAt: turn.resolvedAt,\n artifactDir: turn.artifactDir,\n diffPath: turn.diffPath,\n feedbackPath: turn.feedbackPath,\n markdownPath: turn.markdownPath,\n resolvedPath: turn.resolvedPath\n };\n}\n\nfunction turnSummary(turn: ReviewTurn): ReviewTurnSummary {\n return {\n ...turnMeta(turn),\n capturedAt: turn.diff.capturedAt,\n stats: turn.diff.stats,\n comments: resolutionCounts(turn.feedback, turn.resolution?.comments ?? [])\n };\n}\n\nfunction reconcileTurn(\n meta: ReviewTurnMeta,\n diff: DiffPayload,\n feedback?: FeedbackBundle,\n resolution?: ResolutionBundle\n): ReviewTurn {\n const status =\n resolution?.status === 'resolved' ? 'resolved' : feedback ? 'submitted' : 'pending';\n return {\n ...meta,\n status,\n submittedAt: feedback?.timestamp ?? meta.submittedAt,\n resolvedAt: status === 'resolved' ? (resolution?.resolvedAt ?? meta.resolvedAt) : undefined,\n feedbackPath: feedback\n ? (meta.feedbackPath ?? path.join(meta.artifactDir, 'feedback.json'))\n : undefined,\n markdownPath: feedback\n ? (meta.markdownPath ?? path.join(meta.artifactDir, 'feedback.md'))\n : undefined,\n resolvedPath: resolution\n ? (meta.resolvedPath ?? path.join(meta.artifactDir, 'resolved.json'))\n : undefined,\n diff,\n ...(feedback ? { feedback } : {}),\n ...(resolution ? { resolution } : {})\n };\n}\n\nfunction mergeRecoveredTurns(\n legacyTurn: ReviewTurn | null,\n persistedTurns: ReviewTurn[]\n): ReviewTurn[] {\n const turns =\n legacyTurn &&\n !persistedTurns.some((turn) => turn.id === legacyTurn.id || turn.index === legacyTurn.index)\n ? [legacyTurn, ...persistedTurns]\n : persistedTurns;\n return turns.toSorted((a, b) => a.index - b.index);\n}\n\nfunction diffFingerprint(diff: DiffPayload): string {\n return createHash('sha256')\n .update(\n JSON.stringify({\n base: diff.base,\n branch: diff.branch,\n cwd: diff.cwd,\n scope: diff.scope,\n rawDiff: diff.rawDiff\n })\n )\n .digest('hex');\n}\n\nfunction sameComments(left: Comment[], right: Comment[]): boolean {\n return (\n JSON.stringify(left.toSorted(compareCommentsByLocation)) ===\n JSON.stringify(right.toSorted(compareCommentsByLocation))\n );\n}\n\nfunction requiredPath(value: string | undefined, label: string): string {\n if (!value) {\n throw new Error(`Submitted review is missing ${label}`);\n }\n return value;\n}\n\nasync function readOptionalJsonFile<T>(\n filePath: string,\n guard: JsonGuard<T>,\n label: string\n): Promise<T | undefined> {\n let raw: string;\n try {\n raw = await readFile(filePath, 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return undefined;\n }\n throw new Error(`Could not read ${label} at ${filePath}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n return parseJsonFile(raw, guard, label, filePath);\n}\n\nfunction parseJsonFile<T>(raw: string, guard: JsonGuard<T>, label: string, filePath: string): T {\n try {\n return parseJson(raw, guard, label);\n } catch (error) {\n throw new Error(`Invalid ${label} at ${filePath}: ${formatError(error)}`, { cause: error });\n }\n}\n\nexport const reviewStore = new ReviewStore();\n","import type {\n Comment,\n FeedbackBundle,\n ResolutionBundle,\n ResolutionCounts,\n ResolvedComment,\n Side\n} from './types';\n\nexport interface LineRange {\n side: Side;\n startLine: number;\n endLine: number;\n}\n\nexport function compareCommentsByLocation(a: Comment, b: Comment): number {\n return (\n a.filePath.localeCompare(b.filePath) ||\n a.startLine - b.startLine ||\n a.endLine - b.endLine ||\n a.side.localeCompare(b.side)\n );\n}\n\nexport function countCommentFiles(comments: Pick<Comment, 'filePath'>[]): number {\n return new Set(comments.map((comment) => comment.filePath)).size;\n}\n\nexport function formatLineRange(\n range: LineRange,\n options: { repeatSideOnEnd?: boolean } = {}\n): string {\n const startLine = Math.min(range.startLine, range.endLine);\n const endLine = Math.max(range.startLine, range.endLine);\n if (startLine === endLine) {\n return `${range.side}${startLine}`;\n }\n const endPrefix = options.repeatSideOnEnd === false ? '' : range.side;\n return `${range.side}${startLine}-${endPrefix}${endLine}`;\n}\n\nexport function resolutionCounts(\n feedback: FeedbackBundle | undefined,\n resolvedComments: ResolvedComment[] = []\n): ResolutionCounts {\n const comments = feedback?.comments ?? [];\n const resolvedIds = new Set(resolvedComments.map((comment) => comment.commentId));\n const resolved = comments.filter((comment) => resolvedIds.has(comment.id)).length;\n return {\n total: comments.length,\n resolved,\n open: comments.length - resolved\n };\n}\n\nexport function reviewResolutionCounts(record: {\n feedback?: FeedbackBundle;\n resolution?: ResolutionBundle;\n}): ResolutionCounts {\n return resolutionCounts(record.feedback, record.resolution?.comments ?? []);\n}\n","import type { CommitDiff, DiffPayload, ReviewScope } from './types';\n\nconst ALL_REVIEW_SCOPE: ReviewScope = { mode: 'all' };\n\nexport function normalizeReviewScope(\n diff: Pick<DiffPayload, 'commitDiffs'>,\n scope: ReviewScope = ALL_REVIEW_SCOPE\n): ReviewScope {\n if (scope.mode === 'all') {\n return ALL_REVIEW_SCOPE;\n }\n\n const commitDiffs = diff.commitDiffs ?? [];\n if (commitDiffs.length === 0) {\n throw new Error('Review scope requires a review with per-commit diffs');\n }\n\n if (scope.mode === 'single') {\n const commit = commitDiffs.find((commitDiff) => commitDiff.commit.sha === scope.sha);\n if (!commit) {\n throw new Error('Review scope must use commits from this review');\n }\n return { mode: 'single', sha: commit.commit.sha };\n }\n\n const fromIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === scope.fromSha);\n const toIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === scope.toSha);\n if (fromIndex < 0 || toIndex < 0) {\n throw new Error('Review scope must use commits from this review');\n }\n if (fromIndex > toIndex) {\n throw new Error('Review scope range must be in review order');\n }\n return {\n mode: 'range',\n fromSha: commitDiffs[fromIndex].commit.sha,\n toSha: commitDiffs[toIndex].commit.sha\n };\n}\n\nexport function sameReviewScope(left?: ReviewScope, right?: ReviewScope): boolean {\n return JSON.stringify(left ?? ALL_REVIEW_SCOPE) === JSON.stringify(right ?? ALL_REVIEW_SCOPE);\n}\n\nexport function reviewScopeLabel(\n scope: ReviewScope = ALL_REVIEW_SCOPE,\n commitDiffs: CommitDiff[] = []\n): string {\n if (scope.mode === 'all') {\n return 'All commits';\n }\n if (scope.mode === 'single') {\n const commit = commitDiffs.find((commitDiff) => commitDiff.commit.sha === scope.sha);\n return commit\n ? `${commit.commit.shortSha} ${commit.commit.subject}`\n : `Commit ${shortSha(scope.sha)}`;\n }\n\n const fromIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === scope.fromSha);\n const toIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === scope.toSha);\n if (fromIndex >= 0 && toIndex >= fromIndex) {\n const count = toIndex - fromIndex + 1;\n return `${count} commits · ${commitDiffs[fromIndex].commit.shortSha} to ${\n commitDiffs[toIndex].commit.shortSha\n }`;\n }\n return `Commit range ${shortSha(scope.fromSha)} to ${shortSha(scope.toSha)}`;\n}\n\nfunction shortSha(sha: string): string {\n return sha.slice(0, 7);\n}\n","import { compareCommentsByLocation, formatLineRange } from './comments';\nimport { languageForPath } from './language';\nimport { reviewScopeLabel } from './review-scope';\nimport type { FeedbackBundle } from './types';\n\nfunction fenceFor(snippet: string): string {\n let fence = '```';\n while (snippet.includes(fence)) {\n fence += '`';\n }\n return fence;\n}\n\nfunction languageForSnippet(filePath: string, snippet: string): string {\n const lines = snippet.split('\\n').filter((line) => line.length > 0);\n const looksLikeUnifiedDiff =\n lines.length > 0 &&\n lines.some((line) => line.startsWith('+') || line.startsWith('-')) &&\n lines.every((line) => line.startsWith('+') || line.startsWith('-') || line.startsWith(' '));\n return looksLikeUnifiedDiff ? 'diff' : (languageForPath(filePath) ?? '');\n}\n\nexport function serializeFeedbackMarkdown(bundle: FeedbackBundle): string {\n const comments = bundle.comments.toSorted(compareCommentsByLocation);\n const commentsByFile = new Map<string, typeof comments>();\n const files: string[] = [];\n for (const comment of comments) {\n const fileComments = commentsByFile.get(comment.filePath);\n if (fileComments) {\n fileComments.push(comment);\n } else {\n commentsByFile.set(comment.filePath, [comment]);\n files.push(comment.filePath);\n }\n }\n const lines: string[] = [\n `# Gloss feedback - ${bundle.timestamp}`,\n `Review: ${bundle.reviewId}`,\n ...(bundle.turnIndex ? [`Turn: ${bundle.turnIndex} (${bundle.turnId ?? 'unknown'})`] : []),\n ...(bundle.reviewScope ? [`Review scope: ${reviewScopeLabel(bundle.reviewScope)}`] : []),\n `Base: ${bundle.base.ref} (${bundle.base.sha.slice(0, 7)}) Branch: ${bundle.branch ?? '(detached)'}`,\n `Files: ${files.length} Comments: ${comments.length}`,\n ''\n ];\n\n for (const filePath of files) {\n lines.push(`## ${filePath}`, '');\n for (const comment of commentsByFile.get(filePath) ?? []) {\n const snippet = comment.originalSnippet.trimEnd();\n const firstSnippetLine = firstNonEmptyLine(snippet);\n const heading =\n comment.startLine === comment.endLine && firstSnippetLine\n ? `### ${formatLineRange(comment)} - \\`${firstSnippetLine.trim().slice(0, 80)}\\``\n : `### ${formatLineRange(comment)}`;\n lines.push(heading, comment.body.trim(), '');\n if (snippet) {\n const fence = fenceFor(snippet);\n lines.push(`${fence}${languageForSnippet(comment.filePath, snippet)}`, snippet, fence, '');\n }\n }\n }\n\n return `${lines.join('\\n').trimEnd()}\\n`;\n}\n\nfunction firstNonEmptyLine(text: string): string | undefined {\n for (const line of text.split('\\n')) {\n if (line.trim().length > 0) {\n return line;\n }\n }\n return undefined;\n}\n","import type { ReviewStatus } from './types';\n\nexport function isResolvableReviewStatus(status: ReviewStatus): boolean {\n return status === 'submitted' || status === 'resolved';\n}\n","import { ReviewStore } from '../server/store';\nimport type { ReviewMeta, ServerInfo } from '../shared/types';\nimport { serverUrl } from './lifecycle';\nimport { ServerClient } from './server-client';\n\nexport async function listReviewsForStatus({\n responsive,\n server\n}: {\n responsive: boolean;\n server: ServerInfo | null;\n}): Promise<ReviewMeta[]> {\n if (server && responsive) {\n try {\n return (await new ServerClient(serverUrl(server)).listReviews()).reviews;\n } catch {\n // Fall through to durable state if the daemon disappears between health and list.\n }\n }\n\n return new ReviewStore().list();\n}\n"],"mappings":"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","names":["path","shortSha","rawDiff","rm","readFile","rm","path","readFile","path","info","rm","readdir","readFile","path","readdir","readFile","path","result","sleep"]}