getgloss 0.13.2 → 0.13.3

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/server/daemon.ts","../../src/shared/paths.ts","../../package.json","../../src/shared/server-info.ts","../../src/shared/errors.ts","../../src/shared/json.ts","../../src/shared/types.ts","../../src/shared/validation.ts","../../src/server/idle.ts","../../src/server/index.ts","../../src/shared/comments.ts","../../src/shared/git-diff.ts","../../src/shared/language.ts","../../src/shared/diff-parser.ts","../../src/shared/diff-stats.ts","../../src/shared/file-order.ts","../../src/shared/reviews.ts","../../src/server/local-open.ts","../../src/server/source-peek.ts","../../src/server/store.ts","../../src/shared/cleanup.ts","../../src/shared/review-scope.ts","../../src/shared/markdown.ts","../../src/server/maintenance.ts"],"sourcesContent":["import { fileURLToPath } from 'node:url';\nimport { serve } from '@hono/node-server';\nimport { globalStateDir, packageVersion } from '../shared/paths';\nimport { readServerInfo, removeServerInfoFile, writeServerInfo } from '../shared/server-info';\nimport { createIdleScheduler, normalizeIdleTimeoutMs } from './idle';\nimport { createApp } from './index';\nimport { runStartupCleanup } from './maintenance';\n\nconst port = Number(process.env.GLOSS_PORT ?? '0');\nconst idleTimeoutMs = normalizeIdleTimeoutMs();\nconst daemonPath = fileURLToPath(import.meta.url);\n\nif (!port) {\n throw new Error('GLOSS_PORT is required');\n}\n\nconst origin = `http://localhost:${port}`;\nconst eventStreams = new Set<() => void>();\nlet shuttingDown = false;\nconst idleScheduler = createIdleScheduler({\n timeoutMs: idleTimeoutMs,\n hasLiveClients: () => eventStreams.size > 0,\n isShuttingDown: () => shuttingDown,\n shutdown: () => shutdown(0)\n});\n\nconst server = serve({\n fetch: createApp(origin, {\n onReviewActivity: () => {\n idleScheduler.schedule();\n },\n registerEventStream: (close) => {\n eventStreams.add(close);\n idleScheduler.schedule();\n return () => {\n eventStreams.delete(close);\n idleScheduler.schedule();\n };\n },\n health: () => {\n return {\n connections: eventStreams.size,\n cwd: process.cwd(),\n daemonPath,\n stateDir: globalStateDir()\n };\n }\n }).fetch,\n port\n});\n\nawait writeServerInfo({\n pid: process.pid,\n port,\n version: packageVersion,\n startedAt: new Date().toISOString(),\n stateDir: globalStateDir(),\n cwd: process.cwd(),\n daemonPath\n});\n\nawait runStartupCleanup();\nidleScheduler.schedule();\n\nfor (const signal of ['SIGTERM', 'SIGINT', 'SIGHUP'] as const) {\n process.on(signal, () => {\n void shutdown(0);\n });\n}\n\nasync function shutdown(exitCode: number): Promise<void> {\n if (shuttingDown) {\n return;\n }\n shuttingDown = true;\n idleScheduler.cancel();\n for (const close of [...eventStreams]) {\n close();\n }\n await new Promise<void>((resolve) => {\n server.close(() => resolve());\n });\n await removeCurrentServerInfo();\n process.exit(exitCode);\n}\n\nasync function removeCurrentServerInfo(): Promise<void> {\n const info = await readServerInfo().catch(() => null);\n if (!info || info.pid === process.pid) {\n const warning = await removeServerInfoFile();\n if (warning) {\n process.stderr.write(`Warning: ${warning}\\n`);\n }\n }\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 globalServerLockDir(): string {\n return path.join(globalStateDir(), 'server.lock');\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.13.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 \"simple-icons\": \"16.23.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.3\",\n \"vitest\": \"3.2.6\"\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 { randomUUID } from 'node:crypto';\nimport { readFile, rm, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { formatError, isFileNotFound, isPermissionError } 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 if (isPermissionError(error)) {\n throw new Error(serverInfoPermissionMessage('read', error), { cause: error });\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 try {\n await ensureDir(globalStateDir());\n } catch (error) {\n if (isPermissionError(error)) {\n throw new Error(serverInfoPermissionMessage('create', error), { cause: error });\n }\n throw error;\n }\n\n try {\n await writeJsonFile(globalServerFile(), info);\n } catch (error) {\n if (!isPermissionError(error)) {\n throw error;\n }\n await assertStateDirWritable();\n try {\n await writeFile(globalServerFile(), serializeServerInfo(info));\n } catch (directWriteError) {\n throw new Error(serverInfoPermissionMessage('write', directWriteError), {\n cause: directWriteError\n });\n }\n }\n}\n\nexport async function removeServerInfoFile(): Promise<string | null> {\n try {\n await rm(globalServerFile(), { force: true });\n return null;\n } catch (error) {\n return serverInfoPermissionMessage('remove', error);\n }\n}\n\nexport function serverInfoPermissionMessage(action: string, error: unknown): string {\n const stateDir = globalStateDir();\n const source = process.env.GLOSS_STATE_DIR\n ? `GLOSS_STATE_DIR=${stateDir}`\n : 'GLOSS_STATE_DIR is not set; defaulting to ~/.gloss';\n return [\n `Could not ${action} Gloss server state at ${globalServerFile()}: ${formatError(error)}.`,\n '`server.json` is not a review lock, so there is nothing to unlock after a review.',\n `Check that ${stateDir} and ${globalServerFile()} are owned and writable by your user.`,\n `On macOS, if the file is immutable, run \\`chflags nouchg \"${globalServerFile()}\"\\`.`,\n `For sandboxed agents, set GLOSS_STATE_DIR to a writable directory. ${source}.`\n ].join(' ');\n}\n\nfunction serializeServerInfo(info: ServerInfo): string {\n return `${JSON.stringify(info, null, 2)}\\n`;\n}\n\nasync function assertStateDirWritable(): Promise<void> {\n const probePath = path.join(\n globalStateDir(),\n `.server.json.${process.pid}.${randomUUID()}.probe`\n );\n try {\n await writeFile(probePath, '');\n await rm(probePath, { force: true });\n } catch (error) {\n await rm(probePath, { force: true }).catch(() => undefined);\n throw new Error(serverInfoPermissionMessage('write', error), { cause: error });\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\nexport function isPermissionError(error: unknown): error is NodeJS.ErrnoException {\n return (\n error instanceof Error && 'code' in error && (error.code === 'EACCES' || error.code === 'EPERM')\n );\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 ClearReviewEntry {\n reviewId: string;\n status: ReviewStatus;\n artifactDir: string;\n lastActivityAt: string;\n}\n\ninterface 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 LineComment {\n kind?: 'line';\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 interface GeneralComment {\n kind: 'general';\n id: string;\n body: string;\n createdAt: string;\n}\n\nexport type Comment = LineComment | GeneralComment;\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 DIFF_CONTEXT_MAX_LINES = 500;\n\nexport type DiffContextSource =\n | { mode: 'turn' }\n | { mode: 'commit'; sha: string }\n | { mode: 'range'; fromSha: string; toSha: string };\n\nexport interface DiffContextRequest {\n filePath: string;\n oldPath: string | null;\n turnId?: string;\n source: DiffContextSource;\n oldStart: number;\n newStart: number;\n lineCount: number;\n}\n\nexport interface DiffContextResponse {\n filePath: string;\n oldStart: number;\n newStart: number;\n lines: DiffLine[];\n}\n\nexport const SOURCE_PEEK_MAX_BYTES = 350_000;\nexport const SOURCE_PEEK_RANGE_MAX_LINES = 240;\n\nexport const SOURCE_PEEK_MATCH_REASONS = ['import', 'same-file', 'repo-search', 'module'] as const;\n\nexport type SourcePeekMatchReason = (typeof SOURCE_PEEK_MATCH_REASONS)[number];\n\nexport interface SourcePeekRequest {\n filePath: string;\n oldPath: string | null;\n turnId?: string;\n source: DiffContextSource;\n side: Side;\n line: number;\n column: number;\n symbol: string;\n}\n\nexport interface SourcePeekResponse {\n symbol: string;\n targetSymbol: string;\n filePath: string;\n startLine: number;\n line: number;\n column: number;\n language: string | null;\n content: string;\n truncated: boolean;\n totalLines: number;\n hasMoreAbove: boolean;\n hasMoreBelow: boolean;\n matchReason: SourcePeekMatchReason;\n}\n\nexport interface SourcePeekRangeRequest {\n filePath: string;\n turnId?: string;\n source: DiffContextSource;\n side: Side;\n startLine: number;\n lineCount: number;\n}\n\nexport interface SourcePeekRangeResponse {\n filePath: string;\n startLine: number;\n totalLines: number;\n content: string;\n truncated: boolean;\n hasMoreAbove: boolean;\n hasMoreBelow: boolean;\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 cwd?: string;\n daemonPath?: 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 connections?: number;\n stateDir?: string;\n cwd?: string;\n daemonPath?: string;\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 const OPEN_FILE_SCOPES = ['review', 'repo'] as const;\n\nexport type OpenFileScope = (typeof OPEN_FILE_SCOPES)[number];\n\nexport const OPEN_FILE_TARGETS = [\n 'default',\n 'vscode',\n 'vscode-insiders',\n 'vscodium',\n 'cursor',\n 'sublime',\n 'zed',\n 'windsurf',\n 'webstorm',\n 'intellij',\n 'pycharm',\n 'goland',\n 'phpstorm',\n 'rubymine',\n 'clion',\n 'datagrip',\n 'android-studio',\n 'fleet',\n 'neovide',\n 'macvim',\n 'emacs',\n 'lapce',\n 'textmate',\n 'bbedit',\n 'coteditor',\n 'nova',\n 'textedit',\n 'xcode',\n 'terminal',\n 'iterm2',\n 'ghostty',\n 'folder'\n] as const;\n\nexport type OpenFileTarget = (typeof OPEN_FILE_TARGETS)[number];\n\nexport interface OpenFileRequest {\n filePath: string;\n turnId?: string;\n scope?: OpenFileScope;\n target?: OpenFileTarget;\n}\n\nexport interface OpenFileResponse {\n ok: true;\n path: string;\n}\n\nexport interface OpenFileTargetInfo {\n target: OpenFileTarget;\n label: string;\n}\n\nexport interface OpenFileTargetsResponse {\n targets: OpenFileTargetInfo[];\n}\n\nexport interface FileContentRequest {\n filePath: string;\n turnId?: string;\n scope?: OpenFileScope;\n}\n\nexport interface FileContentResponse {\n filePath: string;\n content: 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 DiffContextRequest,\n DiffContextResponse,\n DiffContextSource,\n DiffFile,\n DiffHunk,\n DiffLine,\n DiffPayload,\n DiffStats,\n FeedbackBundle,\n FileContentRequest,\n FileContentResponse,\n HealthResponse,\n ListReviewsResponse,\n OpenFileRequest,\n OpenFileResponse,\n OpenFileScope,\n OpenFileTarget,\n OpenFileTargetInfo,\n OpenFileTargetsResponse,\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 SourcePeekMatchReason,\n SourcePeekRangeRequest,\n SourcePeekRangeResponse,\n SourcePeekRequest,\n SourcePeekResponse,\n SubmitReviewRequest\n} from './types';\nimport {\n DIFF_FALLBACK_REASONS,\n DIFF_LINE_TYPES,\n DIFF_SCOPE_MODES,\n OPEN_FILE_SCOPES,\n OPEN_FILE_TARGETS,\n RESOLUTION_STATUSES,\n REVIEW_SCOPE_MODES,\n REVIEW_STATUSES,\n REVIEW_UPDATE_REASONS,\n SIDES,\n SOURCE_PEEK_MATCH_REASONS,\n SOURCE_PEEK_RANGE_MAX_LINES\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 isOptionalString(value.cwd) &&\n isOptionalString(value.daemonPath)\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 isOptionalNumber(value.connections) &&\n isOptionalString(value.stateDir) &&\n isOptionalString(value.cwd) &&\n isOptionalString(value.daemonPath)\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 (\n isRecord(value) &&\n isString(value.filePath) &&\n isOptionalString(value.turnId) &&\n isOptional(value.scope, isOpenFileScope) &&\n isOptional(value.target, isOpenFileTarget)\n );\n}\n\nexport function isOpenFileResponse(value: unknown): value is OpenFileResponse {\n return isRecord(value) && value.ok === true && isString(value.path);\n}\n\nexport function isOpenFileTargetsResponse(value: unknown): value is OpenFileTargetsResponse {\n return isRecord(value) && isArrayOf(value.targets, isOpenFileTargetInfo);\n}\n\nexport function isFileContentRequest(value: unknown): value is FileContentRequest {\n return (\n isRecord(value) &&\n isString(value.filePath) &&\n isOptionalString(value.turnId) &&\n isOptional(value.scope, isOpenFileScope)\n );\n}\n\nexport function isFileContentResponse(value: unknown): value is FileContentResponse {\n return isRecord(value) && isString(value.filePath) && isString(value.content);\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 isDiffContextRequest(value: unknown): value is DiffContextRequest {\n return (\n isRecord(value) &&\n isString(value.filePath) &&\n isNullableString(value.oldPath) &&\n isOptionalString(value.turnId) &&\n isDiffContextSource(value.source) &&\n isPositiveInteger(value.oldStart) &&\n isPositiveInteger(value.newStart) &&\n isPositiveInteger(value.lineCount)\n );\n}\n\nexport function isDiffContextResponse(value: unknown): value is DiffContextResponse {\n return (\n isRecord(value) &&\n isString(value.filePath) &&\n isPositiveInteger(value.oldStart) &&\n isPositiveInteger(value.newStart) &&\n isArrayOf(value.lines, isDiffLine)\n );\n}\n\nexport function isSourcePeekRequest(value: unknown): value is SourcePeekRequest {\n return (\n isRecord(value) &&\n isString(value.filePath) &&\n isNullableString(value.oldPath) &&\n isOptionalString(value.turnId) &&\n isDiffContextSource(value.source) &&\n isOneOf(value.side, SIDES) &&\n isPositiveInteger(value.line) &&\n isNonNegativeInteger(value.column) &&\n isIdentifier(value.symbol)\n );\n}\n\nexport function isSourcePeekResponse(value: unknown): value is SourcePeekResponse {\n return (\n isRecord(value) &&\n isString(value.symbol) &&\n isString(value.targetSymbol) &&\n isString(value.filePath) &&\n isPositiveInteger(value.startLine) &&\n isPositiveInteger(value.line) &&\n isNonNegativeInteger(value.column) &&\n isNullableString(value.language) &&\n isString(value.content) &&\n isBoolean(value.truncated) &&\n isPositiveInteger(value.totalLines) &&\n isBoolean(value.hasMoreAbove) &&\n isBoolean(value.hasMoreBelow) &&\n isSourcePeekMatchReason(value.matchReason)\n );\n}\n\nexport function isSourcePeekRangeRequest(value: unknown): value is SourcePeekRangeRequest {\n return (\n isRecord(value) &&\n isString(value.filePath) &&\n isOptionalString(value.turnId) &&\n isDiffContextSource(value.source) &&\n isOneOf(value.side, SIDES) &&\n isPositiveInteger(value.startLine) &&\n isPositiveInteger(value.lineCount) &&\n value.lineCount <= SOURCE_PEEK_RANGE_MAX_LINES\n );\n}\n\nexport function isSourcePeekRangeResponse(value: unknown): value is SourcePeekRangeResponse {\n return (\n isRecord(value) &&\n isString(value.filePath) &&\n isPositiveInteger(value.startLine) &&\n isPositiveInteger(value.totalLines) &&\n isString(value.content) &&\n isBoolean(value.truncated) &&\n isBoolean(value.hasMoreAbove) &&\n isBoolean(value.hasMoreBelow)\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 isDiffContextSource(value: unknown): value is DiffContextSource {\n if (!isRecord(value) || !isString(value.mode)) {\n return false;\n }\n switch (value.mode) {\n case 'turn':\n return true;\n case 'commit':\n return isString(value.sha);\n case 'range':\n return isString(value.fromSha) && isString(value.toSha);\n default:\n return false;\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 if (!isRecord(value)) {\n return false;\n }\n if (value.kind === 'general') {\n return isString(value.id) && isString(value.body) && isString(value.createdAt);\n }\n return (\n isString(value.id) &&\n (value.kind === undefined || value.kind === 'line') &&\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 isSourcePeekMatchReason(value: unknown): value is SourcePeekMatchReason {\n return isOneOf(value, SOURCE_PEEK_MATCH_REASONS);\n}\n\nfunction isOpenFileScope(value: unknown): value is OpenFileScope {\n return isOneOf(value, OPEN_FILE_SCOPES);\n}\n\nfunction isOpenFileTarget(value: unknown): value is OpenFileTarget {\n return isOneOf(value, OPEN_FILE_TARGETS);\n}\n\nfunction isOpenFileTargetInfo(value: unknown): value is OpenFileTargetInfo {\n return isRecord(value) && isOpenFileTarget(value.target) && isString(value.label);\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 isPositiveInteger(value: unknown): value is number {\n return isNumber(value) && Number.isInteger(value) && value > 0;\n}\n\nfunction isNonNegativeInteger(value: unknown): value is number {\n return isNumber(value) && Number.isInteger(value) && value >= 0;\n}\n\nfunction isIdentifier(value: unknown): value is string {\n return isString(value) && /^[A-Za-z_$][\\w$]*$/.test(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","export const DEFAULT_DAEMON_IDLE_TIMEOUT_MS = 120000;\n\nexport interface IdleScheduler {\n cancel: () => void;\n schedule: () => void;\n}\n\ninterface IdleSchedulerOptions {\n timeoutMs: number;\n hasLiveClients: () => boolean;\n isShuttingDown: () => boolean;\n shutdown: () => void | Promise<void>;\n}\n\nexport function normalizeIdleTimeoutMs(\n rawValue = process.env.GLOSS_IDLE_TIMEOUT_MS,\n warn: (message: string) => void = (message) => process.stderr.write(message)\n): number {\n if (rawValue === undefined) {\n return DEFAULT_DAEMON_IDLE_TIMEOUT_MS;\n }\n\n const parsed = Number(rawValue);\n if (Number.isFinite(parsed) && parsed > 0) {\n return parsed;\n }\n\n warn(\n `Warning: GLOSS_IDLE_TIMEOUT_MS=${JSON.stringify(rawValue)} is not positive; using ${DEFAULT_DAEMON_IDLE_TIMEOUT_MS}.\\n`\n );\n return DEFAULT_DAEMON_IDLE_TIMEOUT_MS;\n}\n\nexport function createIdleScheduler(options: IdleSchedulerOptions): IdleScheduler {\n let idleTimer: NodeJS.Timeout | null = null;\n\n const cancel = () => {\n if (idleTimer) {\n clearTimeout(idleTimer);\n idleTimer = null;\n }\n };\n\n const schedule = () => {\n if (options.isShuttingDown()) {\n return;\n }\n\n if (options.hasLiveClients()) {\n cancel();\n return;\n }\n\n if (!idleTimer) {\n idleTimer = setTimeout(() => {\n idleTimer = null;\n void shutdownIfIdle();\n }, options.timeoutMs);\n }\n };\n\n const shutdownIfIdle = async () => {\n if (options.isShuttingDown()) {\n return;\n }\n if (options.hasLiveClients()) {\n schedule();\n return;\n }\n await options.shutdown();\n };\n\n return { cancel, schedule };\n}\n","import { readFile, realpath, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Context } from 'hono';\nimport { Hono } from 'hono';\nimport { streamSSE } from 'hono/streaming';\nimport { countCommentFiles } from '../shared/comments';\nimport { formatError, isFileNotFound } from '../shared/errors';\nimport { captureCommitRangeDiff, captureDiffContext } from '../shared/git-diff';\nimport type { JsonValue } from '../shared/json';\nimport { packageVersion } from '../shared/paths';\nimport { isResolvableReviewStatus } from '../shared/reviews';\nimport type {\n ClearReviewsRequest,\n CommitRangeDiffResponse,\n CreateReviewResponse,\n CreateReviewTurnResponse,\n DiffContextRequest,\n DiffContextSource,\n DiffFile,\n DiffPayload,\n FileContentResponse,\n HealthResponse,\n ListReviewsResponse,\n OpenFileResponse,\n OpenFileTargetsResponse,\n OpenResult,\n ResolutionRequest,\n ReviewEvent,\n ReviewMeta,\n ReviewTurnSummary,\n SourcePeekRangeRequest,\n SourcePeekRequest,\n SubmitReviewRequest\n} from '../shared/types';\nimport { DIFF_CONTEXT_MAX_LINES } from '../shared/types';\nimport {\n isClearReviewsRequest,\n isCommitRangeDiffRequest,\n isDiffContextRequest,\n isDiffPayload,\n isFileContentRequest,\n isOpenFileRequest,\n isResolutionRequest,\n isSourcePeekRangeRequest,\n isSourcePeekRequest,\n isSubmitReviewRequest,\n type JsonGuard,\n parseJsonValue\n} from '../shared/validation';\nimport { availableOpenFileTargets, openLocalPath } from './local-open';\nimport { readSourcePeekRange, resolveSourcePeek } from './source-peek';\nimport { reviewStore } from './store';\n\nconst webRoot = fileURLToPath(new URL('../web', import.meta.url));\nconst eventStreamHeartbeatMs = 15_000;\n\ninterface AppOptions {\n onReviewActivity?: () => void;\n registerEventStream?: (close: () => void) => () => void;\n health?: () => Partial<Pick<HealthResponse, 'connections' | 'cwd' | 'daemonPath' | 'stateDir'>>;\n}\n\nconst mimeTypes: Record<string, string> = {\n '.css': 'text/css; charset=utf-8',\n '.html': 'text/html; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.map': 'application/json; charset=utf-8',\n '.png': 'image/png',\n '.sh': 'text/x-shellscript; charset=utf-8',\n '.svg': 'image/svg+xml'\n};\n\nexport function createApp(origin: string, options: AppOptions = {}): Hono {\n const app = new Hono();\n\n app.get('/api/health', async (c) => {\n const reviews = await reviewStore.list();\n const response: HealthResponse = {\n ok: true,\n version: packageVersion,\n activeReviews: reviews.filter((review) => review.status === 'pending').length,\n ...options.health?.()\n };\n return c.json(response);\n });\n\n app.get('/api/open-targets', async (c) => {\n const response: OpenFileTargetsResponse = { targets: await availableOpenFileTargets() };\n return c.json(response);\n });\n\n app.get('/api/reviews', async (c) => {\n const response: ListReviewsResponse = { reviews: await reviewStore.list() };\n return c.json(response);\n });\n\n app.post('/api/maintenance/clear-reviews', async (c) => {\n const parsed = await readJsonBody(c, isClearReviewsRequest, 'clear reviews request');\n if (!parsed.ok) {\n return parsed.response;\n }\n const body: ClearReviewsRequest = parsed.body;\n const result = await reviewStore.clearReviewArtifacts(body);\n return c.json(result);\n });\n\n app.post('/api/reviews', async (c) => {\n const parsed = await readJsonBody(c, isDiffPayload, 'review diff');\n if (!parsed.ok) {\n return parsed.response;\n }\n const diff = parsed.body;\n const record = await reviewStore.create(diff);\n const response: CreateReviewResponse = {\n meta: record.meta,\n turn: activeTurnSummary(record.meta),\n url: `${origin}/review/${record.meta.id}`\n };\n options.onReviewActivity?.();\n return c.json(response, 201);\n });\n\n app.post('/api/reviews/:id/turns', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isDiffPayload, 'review diff');\n if (!parsed.ok) {\n return parsed.response;\n }\n try {\n const { record, turn, reused } = await reviewStore.appendTurn(id, parsed.body);\n const response: CreateReviewTurnResponse = {\n meta: record.meta,\n turn: turnSummary(record.meta, turn.id),\n url: `${origin}/review/${id}`,\n reused\n };\n options.onReviewActivity?.();\n return c.json(response);\n } catch (error) {\n return c.json({ error: formatError(error) }, 409);\n }\n });\n\n app.get('/api/reviews/:id', async (c) => {\n const record = await reviewStore.get(c.req.param('id'));\n if (!record) {\n return c.json({ error: 'review not found' }, 404);\n }\n return c.json(record);\n });\n\n app.get('/api/reviews/:id/turns/:turnId', async (c) => {\n const turn = await reviewStore.getTurn(c.req.param('id'), c.req.param('turnId'));\n if (!turn) {\n return c.json({ error: 'turn not found' }, 404);\n }\n return c.json(turn);\n });\n\n app.get('/api/reviews/:id/feedback', async (c) => {\n const feedback = await reviewStore.feedback(c.req.param('id'));\n if (!feedback) {\n return c.json({ error: 'feedback not found' }, 404);\n }\n return c.json(feedback);\n });\n\n app.get('/api/reviews/:id/events', async (c) => {\n const id = c.req.param('id');\n const record = await reviewStore.get(id);\n if (!record) {\n return c.json({ error: 'review not found' }, 404);\n }\n\n return streamSSE(c, async (stream) => {\n let closed = false;\n let pending: Promise<void> = Promise.resolve();\n let cleanup: (() => void) | null = null;\n let close: (() => void) | null = null;\n let unregisterEventStream: (() => void) | null = null;\n const closedPromise = new Promise<void>((resolve) => {\n close = () => {\n if (closed) {\n return;\n }\n closed = true;\n cleanup?.();\n resolve();\n };\n });\n unregisterEventStream = options.registerEventStream?.(() => close?.()) ?? null;\n const send = (event: ReviewEvent) => {\n pending = pending\n .then(() => stream.writeSSE({ data: JSON.stringify(event) }))\n .then(() => {\n if (event.type === 'review.cancelled') {\n close?.();\n }\n });\n void pending.catch(() => close?.());\n };\n const unsubscribe = reviewStore.subscribe(id, send);\n const heartbeat = setInterval(() => {\n pending = pending.then(async () => {\n await stream.write(`: keep-alive ${Date.now()}\\n\\n`);\n });\n void pending.catch(() => close?.());\n }, eventStreamHeartbeatMs);\n cleanup = () => {\n clearInterval(heartbeat);\n unsubscribe();\n unregisterEventStream?.();\n unregisterEventStream = null;\n };\n stream.onAbort(() => close?.());\n\n send({ type: 'review.opened', reviewId: id });\n if (isResolvableReviewStatus(record.meta.status) && record.feedback) {\n send({\n type: 'review.submitted',\n reviewId: id,\n turnId: record.meta.activeTurnId,\n turnIndex: record.meta.turns?.find((turn) => turn.id === record.meta.activeTurnId)?.index,\n counts: {\n files: countCommentFiles(record.feedback.comments),\n comments: record.feedback.comments.length\n }\n });\n }\n await closedPromise;\n });\n });\n\n app.post('/api/reviews/:id/submit', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isSubmitReviewRequest, 'submit review request');\n if (!parsed.ok) {\n return parsed.response;\n }\n const body: SubmitReviewRequest = parsed.body;\n let submitted: Awaited<ReturnType<typeof reviewStore.submit>>;\n try {\n submitted = await reviewStore.submit(id, body.comments, body.reviewScope);\n } catch (error) {\n return c.json({ error: formatError(error) }, 409);\n }\n const { feedbackPath, markdownPath, turn } = submitted;\n const response: OpenResult = {\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n url: `${origin}/review/${id}`,\n files: turn.diff.files.length,\n comments: body.comments.length,\n artifactDir: turn.artifactDir,\n feedbackPath,\n markdownPath\n };\n options.onReviewActivity?.();\n return c.json(response);\n });\n\n app.post('/api/reviews/:id/commits/range', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isCommitRangeDiffRequest, 'commit range diff request');\n if (!parsed.ok) {\n return parsed.response;\n }\n\n const requestedTurnId = parsed.body.turnId;\n const turn = requestedTurnId ? await reviewStore.getTurn(id, requestedTurnId) : null;\n if (requestedTurnId && !turn) {\n return c.json({ error: 'turn not found' }, 404);\n }\n const diffPayload = turn?.diff ?? existing.diff;\n const commitDiffs = diffPayload.commitDiffs ?? [];\n if (commitDiffs.length === 0) {\n return c.json({ error: 'commit ranges are only available for branch reviews' }, 409);\n }\n\n const { fromSha, toSha } = parsed.body;\n const fromIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === fromSha);\n const toIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === toSha);\n if (fromIndex < 0 || toIndex < 0) {\n return c.json({ error: 'commit range must use commits from this review' }, 404);\n }\n if (fromIndex > toIndex) {\n return c.json({ error: 'fromSha must come before or match toSha' }, 400);\n }\n\n const diff =\n fromSha === toSha\n ? commitDiffs[fromIndex]\n : await captureCommitRangeDiff(fromSha, toSha, diffPayload.cwd);\n const response: CommitRangeDiffResponse = {\n fromSha,\n toSha,\n stats: diff.stats,\n rawDiff: diff.rawDiff,\n files: diff.files\n };\n return c.json(response);\n });\n\n app.post('/api/reviews/:id/files/context', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isDiffContextRequest, 'diff context request');\n if (!parsed.ok) {\n return parsed.response;\n }\n\n const body: DiffContextRequest = parsed.body;\n if (body.lineCount > DIFF_CONTEXT_MAX_LINES) {\n return c.json({ error: `lineCount must be ${DIFF_CONTEXT_MAX_LINES} or less` }, 400);\n }\n\n const turn = body.turnId ? await reviewStore.getTurn(id, body.turnId) : null;\n if (body.turnId && !turn) {\n return c.json({ error: 'turn not found' }, 404);\n }\n const diffPayload = turn?.diff ?? existing.diff;\n const repoRoot = path.resolve(diffPayload.cwd);\n const pathError =\n validateContextPath(repoRoot, body.filePath, 'filePath') ??\n (body.oldPath ? validateContextPath(repoRoot, body.oldPath, 'oldPath') : null);\n if (pathError) {\n return c.json({ error: pathError }, 400);\n }\n\n const source = await resolveContextSource(diffPayload, body.source);\n if (!source.ok) {\n return c.json({ error: source.error }, source.status);\n }\n\n const reviewFile = source.files.find((file) => file.path === body.filePath);\n if (!reviewFile) {\n return c.json({ error: 'file is not part of this review context' }, 404);\n }\n if ((reviewFile.oldPath ?? null) !== body.oldPath) {\n return c.json({ error: 'oldPath does not match the reviewed file' }, 400);\n }\n if (reviewFile.isBinary) {\n return c.json({ error: 'binary file context is not available' }, 409);\n }\n\n try {\n const response = await captureDiffContext({\n filePath: body.filePath,\n oldPath: body.oldPath,\n oldRef: source.oldRef,\n newRef: source.newRef,\n oldStart: body.oldStart,\n newStart: body.newStart,\n lineCount: body.lineCount,\n repoRoot\n });\n return c.json(response);\n } catch (error) {\n return c.json({ error: `context is unavailable: ${formatError(error)}` }, 409);\n }\n });\n\n app.post('/api/reviews/:id/source-peek', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isSourcePeekRequest, 'source peek request');\n if (!parsed.ok) {\n return parsed.response;\n }\n\n const body: SourcePeekRequest = parsed.body;\n const turn = body.turnId ? await reviewStore.getTurn(id, body.turnId) : null;\n if (body.turnId && !turn) {\n return c.json({ error: 'turn not found' }, 404);\n }\n const diffPayload = turn?.diff ?? existing.diff;\n const repoRoot = path.resolve(diffPayload.cwd);\n const pathError =\n validateContextPath(repoRoot, body.filePath, 'filePath') ??\n (body.oldPath ? validateContextPath(repoRoot, body.oldPath, 'oldPath') : null);\n if (pathError) {\n return c.json({ error: pathError }, 400);\n }\n\n const source = await resolveContextSource(diffPayload, body.source);\n if (!source.ok) {\n return c.json({ error: source.error }, source.status);\n }\n\n const reviewFile = source.files.find((file) => file.path === body.filePath);\n if (!reviewFile) {\n return c.json({ error: 'file is not part of this review context' }, 404);\n }\n if ((reviewFile.oldPath ?? null) !== body.oldPath) {\n return c.json({ error: 'oldPath does not match the reviewed file' }, 400);\n }\n if (reviewFile.isBinary) {\n return c.json({ error: 'binary file source peek is not available' }, 409);\n }\n if (body.side === 'L' && reviewFile.isNew) {\n return c.json({ error: 'new files do not have an old-side source' }, 409);\n }\n if (body.side === 'R' && reviewFile.isDeleted) {\n return c.json({ error: 'deleted files do not have a new-side source' }, 409);\n }\n\n const sourceFilePath = body.side === 'L' ? (body.oldPath ?? body.filePath) : body.filePath;\n const sourceRef = body.side === 'L' ? source.oldRef : source.newRef;\n try {\n return c.json(\n await resolveSourcePeek({\n repoRoot,\n sourceFilePath,\n sourceRef,\n symbol: body.symbol,\n line: body.line,\n column: body.column\n })\n );\n } catch (error) {\n return c.json({ error: `source peek unavailable: ${formatError(error)}` }, 404);\n }\n });\n\n app.post('/api/reviews/:id/source-peek/range', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isSourcePeekRangeRequest, 'source peek range request');\n if (!parsed.ok) {\n return parsed.response;\n }\n\n const body: SourcePeekRangeRequest = parsed.body;\n const turn = body.turnId ? await reviewStore.getTurn(id, body.turnId) : null;\n if (body.turnId && !turn) {\n return c.json({ error: 'turn not found' }, 404);\n }\n const diffPayload = turn?.diff ?? existing.diff;\n const repoRoot = path.resolve(diffPayload.cwd);\n const pathError = validateContextPath(repoRoot, body.filePath, 'filePath');\n if (pathError) {\n return c.json({ error: pathError }, 400);\n }\n\n const source = await resolveContextSource(diffPayload, body.source);\n if (!source.ok) {\n return c.json({ error: source.error }, source.status);\n }\n\n const sourceRef = body.side === 'L' ? source.oldRef : source.newRef;\n try {\n return c.json(\n await readSourcePeekRange({\n repoRoot,\n sourceFilePath: body.filePath,\n sourceRef,\n startLine: body.startLine,\n lineCount: body.lineCount\n })\n );\n } catch (error) {\n return c.json({ error: `source range unavailable: ${formatError(error)}` }, 404);\n }\n });\n\n app.post('/api/reviews/:id/files/content', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isFileContentRequest, 'file content request');\n if (!parsed.ok) {\n return parsed.response;\n }\n\n const { filePath, scope = 'review', turnId } = parsed.body;\n if (!filePath || filePath.includes('\\0') || path.isAbsolute(filePath)) {\n return c.json({ error: 'filePath must be a repo-relative path' }, 400);\n }\n\n const repoRoot = path.resolve(existing.diff.cwd);\n const requestedAbsolutePath = path.resolve(repoRoot, filePath);\n if (!isPathWithin(repoRoot, requestedAbsolutePath)) {\n return c.json({ error: 'filePath must stay within the review cwd' }, 400);\n }\n\n const turn = turnId ? await reviewStore.getTurn(id, turnId) : null;\n if (turnId && !turn) {\n return c.json({ error: 'turn not found' }, 404);\n }\n\n if (scope === 'review') {\n const diffPayload = turn?.diff ?? existing.diff;\n const reviewFiles = [\n ...diffPayload.files,\n ...(diffPayload.commitDiffs ?? []).flatMap((commitDiff) => commitDiff.files)\n ].filter((file) => file.path === filePath);\n if (reviewFiles.length === 0) {\n return c.json({ error: 'file is not part of this review' }, 404);\n }\n if (reviewFiles.every((file) => file.isDeleted)) {\n return c.json({ error: 'deleted files cannot be copied' }, 409);\n }\n if (reviewFiles.some((file) => file.isBinary)) {\n return c.json({ error: 'binary file contents cannot be copied' }, 409);\n }\n }\n\n let realRepoRoot: string;\n let realFilePath: string;\n try {\n [realRepoRoot, realFilePath] = await Promise.all([\n realpath(repoRoot),\n realpath(requestedAbsolutePath)\n ]);\n } catch (error) {\n if (isFileNotFound(error)) {\n return c.json({ error: 'file no longer exists on disk' }, 404);\n }\n throw error;\n }\n\n if (!isPathWithin(realRepoRoot, realFilePath)) {\n return c.json({ error: 'filePath must stay within the review cwd' }, 400);\n }\n\n const fileStats = await stat(realFilePath);\n if (!fileStats.isFile()) {\n return c.json({ error: 'path is not a file' }, 409);\n }\n\n const response: FileContentResponse = {\n content: await readFile(realFilePath, 'utf8'),\n filePath\n };\n return c.json(response);\n });\n\n app.post('/api/reviews/:id/files/open', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isOpenFileRequest, 'open file request');\n if (!parsed.ok) {\n return parsed.response;\n }\n\n const { filePath, scope = 'review', target, turnId } = parsed.body;\n if (!filePath || filePath.includes('\\0') || path.isAbsolute(filePath)) {\n return c.json({ error: 'filePath must be a repo-relative path' }, 400);\n }\n\n const repoRoot = path.resolve(existing.diff.cwd);\n const requestedAbsolutePath = path.resolve(repoRoot, filePath);\n if (!isPathWithin(repoRoot, requestedAbsolutePath)) {\n return c.json({ error: 'filePath must stay within the review cwd' }, 400);\n }\n\n const turn = turnId ? await reviewStore.getTurn(id, turnId) : null;\n if (turnId && !turn) {\n return c.json({ error: 'turn not found' }, 404);\n }\n\n if (scope === 'review') {\n const diffPayload = turn?.diff ?? existing.diff;\n const reviewFiles = [\n ...diffPayload.files,\n ...(diffPayload.commitDiffs ?? []).flatMap((commitDiff) => commitDiff.files)\n ].filter((file) => file.path === filePath);\n if (reviewFiles.length === 0) {\n return c.json({ error: 'file is not part of this review' }, 404);\n }\n if (reviewFiles.every((file) => file.isDeleted)) {\n return c.json({ error: 'deleted files cannot be opened locally' }, 409);\n }\n }\n\n let realRepoRoot: string;\n let realFilePath: string;\n try {\n [realRepoRoot, realFilePath] = await Promise.all([\n realpath(repoRoot),\n realpath(requestedAbsolutePath)\n ]);\n } catch (error) {\n if (isFileNotFound(error)) {\n return c.json({ error: 'file no longer exists on disk' }, 404);\n }\n throw error;\n }\n\n if (!isPathWithin(realRepoRoot, realFilePath)) {\n return c.json({ error: 'filePath must stay within the review cwd' }, 400);\n }\n\n const fileStats = await stat(realFilePath);\n if (!fileStats.isFile()) {\n return c.json({ error: 'path is not a file' }, 409);\n }\n\n try {\n target ? await openLocalPath(realFilePath, target) : await openLocalPath(realFilePath);\n } catch (error) {\n return c.json({ error: `could not open file: ${formatError(error)}` }, 500);\n }\n\n const response: OpenFileResponse = { ok: true, path: realFilePath };\n return c.json(response);\n });\n\n app.post('/api/reviews/:id/resolved', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isResolutionRequest, 'resolution request');\n if (!parsed.ok) {\n return parsed.response;\n }\n const body: ResolutionRequest = parsed.body;\n try {\n const result = await reviewStore.markResolved(id, body.summary, body.turn);\n options.onReviewActivity?.();\n return c.json(result);\n } catch (error) {\n return c.json({ error: formatError(error) }, statusForStoreError(error));\n }\n });\n\n app.post('/api/reviews/:id/comments/:commentId/resolved', async (c) => {\n const id = c.req.param('id');\n const commentId = c.req.param('commentId');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isResolutionRequest, 'resolution request');\n if (!parsed.ok) {\n return parsed.response;\n }\n const body: ResolutionRequest = parsed.body;\n try {\n const result = await reviewStore.resolveComment(id, commentId, body.summary);\n options.onReviewActivity?.();\n return c.json(result);\n } catch (error) {\n return c.json({ error: formatError(error) }, statusForStoreError(error));\n }\n });\n\n app.delete('/api/reviews/:id/comments/:commentId/resolved', async (c) => {\n const id = c.req.param('id');\n const commentId = c.req.param('commentId');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n try {\n const result = await reviewStore.reopenComment(id, commentId);\n options.onReviewActivity?.();\n return c.json(result);\n } catch (error) {\n return c.json({ error: formatError(error) }, statusForStoreError(error));\n }\n });\n\n app.get('/logo.svg', serveRootFile('logo.svg', mimeTypes['.svg']));\n app.get('/logo-mark.svg', serveRootFile('logo-mark.svg', mimeTypes['.svg']));\n app.get('/og.png', serveRootFile('og.png', mimeTypes['.png']));\n app.get('/install.sh', serveRootFile('install.sh', mimeTypes['.sh']));\n app.get('/setup.md', serveRootFile('setup.md', 'text/markdown; charset=utf-8'));\n app.get('/prompt.md', serveRootFile('prompt.md', 'text/markdown; charset=utf-8'));\n app.get('/assets/*', serveAsset);\n app.get('/setup', serveIndex);\n app.get('/setup/', serveIndex);\n app.get('/review/:id', serveIndex);\n app.get('/', serveIndex);\n\n return app;\n}\n\nasync function serveAsset(c: Context) {\n const requestPath = new URL(c.req.url).pathname.replace(/^\\/assets\\//, '');\n const normalized = path.normalize(requestPath).replace(/^(\\.\\.(\\/|\\\\|$))+/, '');\n const assetPath = path.join(webRoot, 'assets', normalized);\n try {\n const body = await readFile(assetPath);\n return new Response(body, {\n headers: {\n 'content-type': mimeTypes[path.extname(assetPath)] ?? 'application/octet-stream'\n }\n });\n } catch (error) {\n if (!isFileNotFound(error)) {\n throw error;\n }\n return new Response('Not found', { status: 404 });\n }\n}\n\nasync function serveIndex() {\n try {\n const body = await readFile(path.join(webRoot, 'index.html'));\n return new Response(body, {\n headers: { 'content-type': 'text/html; charset=utf-8' }\n });\n } catch (error) {\n if (!isFileNotFound(error)) {\n throw error;\n }\n return new Response('Gloss web assets are missing. Run pnpm build.', { status: 500 });\n }\n}\n\nfunction serveRootFile(fileName: string, contentType: string) {\n return async () => {\n try {\n const body = await readFile(path.join(webRoot, fileName));\n return new Response(body, {\n headers: { 'content-type': contentType }\n });\n } catch (error) {\n if (!isFileNotFound(error)) {\n throw error;\n }\n return new Response(`${fileName} is missing. Run pnpm build.`, { status: 404 });\n }\n };\n}\n\nasync function readJsonBody<T>(\n c: Context,\n guard: JsonGuard<T>,\n label: string\n): Promise<{ ok: true; body: T } | { ok: false; response: Response }> {\n let body: JsonValue;\n try {\n body = await c.req.json();\n } catch (error) {\n return {\n ok: false,\n response: c.json({ error: `invalid JSON body: ${formatError(error)}` }, 400)\n };\n }\n\n try {\n return { ok: true, body: parseJsonValue(body, guard, label) };\n } catch (error) {\n return {\n ok: false,\n response: c.json({ error: formatError(error) }, 400)\n };\n }\n}\n\nfunction isPathWithin(parentPath: string, childPath: string): boolean {\n const relative = path.relative(parentPath, childPath);\n return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));\n}\n\ntype ContextSourceResolution =\n | {\n ok: true;\n files: DiffFile[];\n oldRef: string | null;\n newRef: string | null;\n }\n | { ok: false; status: 400 | 404 | 409; error: string };\n\nasync function resolveContextSource(\n diffPayload: DiffPayload,\n source: DiffContextSource\n): Promise<ContextSourceResolution> {\n if (source.mode === 'turn') {\n return {\n ok: true,\n files: diffPayload.files,\n oldRef: diffPayload.base.sha,\n newRef: diffPayload.scope.comparison.sha\n };\n }\n\n const commitDiffs = diffPayload.commitDiffs ?? [];\n if (commitDiffs.length === 0) {\n return {\n ok: false,\n status: 409,\n error: 'commit context is only available for branch reviews'\n };\n }\n\n if (source.mode === 'commit') {\n const commitDiff = commitDiffs.find((diff) => diff.commit.sha === source.sha);\n if (!commitDiff) {\n return { ok: false, status: 404, error: 'commit must be part of this review' };\n }\n return {\n ok: true,\n files: commitDiff.files,\n oldRef: `${source.sha}^`,\n newRef: source.sha\n };\n }\n\n const fromIndex = commitDiffs.findIndex((diff) => diff.commit.sha === source.fromSha);\n const toIndex = commitDiffs.findIndex((diff) => diff.commit.sha === source.toSha);\n if (fromIndex < 0 || toIndex < 0) {\n return { ok: false, status: 404, error: 'commit range must use commits from this review' };\n }\n if (fromIndex > toIndex) {\n return { ok: false, status: 400, error: 'fromSha must come before or match toSha' };\n }\n\n const rangeDiff =\n source.fromSha === source.toSha\n ? commitDiffs[fromIndex]\n : await captureCommitRangeDiff(source.fromSha, source.toSha, diffPayload.cwd);\n return {\n ok: true,\n files: rangeDiff.files,\n oldRef: `${source.fromSha}^`,\n newRef: source.toSha\n };\n}\n\nfunction validateContextPath(repoRoot: string, filePath: string, label: string): string | null {\n if (!filePath || filePath.includes('\\0') || path.isAbsolute(filePath)) {\n return `${label} must be a repo-relative path`;\n }\n\n const requestedAbsolutePath = path.resolve(repoRoot, filePath);\n if (!isPathWithin(repoRoot, requestedAbsolutePath)) {\n return `${label} must stay within the review cwd`;\n }\n\n return null;\n}\n\nfunction activeTurnSummary(meta: ReviewMeta): ReviewTurnSummary {\n if (!meta.activeTurnId) {\n throw new Error(`Review ${meta.id} has no active turn`);\n }\n return turnSummary(meta, meta.activeTurnId);\n}\n\nfunction turnSummary(meta: ReviewMeta, turnId: string): ReviewTurnSummary {\n const summary = meta.turns?.find((turn) => turn.id === turnId);\n if (!summary) {\n throw new Error(`Review ${meta.id} is missing turn ${turnId}`);\n }\n return summary;\n}\n\nfunction statusForStoreError(error: unknown): 404 | 409 {\n return /not found/i.test(formatError(error)) ? 404 : 409;\n}\n","import type {\n Comment,\n FeedbackBundle,\n LineComment,\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 isLineComment(comment: Comment): comment is LineComment {\n return comment.kind === undefined || comment.kind === 'line';\n}\n\nexport function compareCommentsByLocation(a: Comment, b: Comment): number {\n const aIsLine = isLineComment(a);\n const bIsLine = isLineComment(b);\n if (!aIsLine || !bIsLine) {\n if (aIsLine !== bIsLine) {\n return aIsLine ? 1 : -1;\n }\n return a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id);\n }\n\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: Comment[]): number {\n const filePaths = new Set<string>();\n for (const comment of comments) {\n if (isLineComment(comment)) {\n filePaths.add(comment.filePath);\n }\n }\n return filePaths.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 { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { execa } from 'execa';\nimport { parseUnifiedDiff } from './diff-parser';\nimport { summarizeDiffFiles } from './diff-stats';\nimport { sortDiffFiles } from './file-order';\nimport type { CommitDiff, DiffContextResponse, DiffLine } from './types';\n\nconst DIFF_ARGS = ['diff', '--no-color', '--find-renames', '--find-copies'];\n\nasync function git(args: string[], cwd: string): Promise<string> {\n const result = await execa('git', args, { cwd });\n return result.stdout.trimEnd();\n}\n\nexport async function captureCommitRangeDiff(\n fromSha: string,\n toSha: string,\n repoRoot: string\n): Promise<Pick<CommitDiff, 'stats' | 'rawDiff' | 'files'>> {\n const rawDiff = await git([...DIFF_ARGS, `${fromSha}^`, toSha, '--'], repoRoot);\n const files = sortDiffFiles(parseUnifiedDiff(rawDiff));\n return {\n stats: summarizeDiffFiles(files),\n rawDiff,\n files\n };\n}\n\nexport async function captureDiffContext({\n filePath,\n lineCount,\n newRef,\n oldPath,\n oldRef,\n newStart,\n oldStart,\n repoRoot\n}: {\n filePath: string;\n oldPath: string | null;\n oldRef: string | null;\n newRef: string | null;\n oldStart: number;\n newStart: number;\n lineCount: number;\n repoRoot: string;\n}): Promise<DiffContextResponse> {\n const [oldLines, newLines] = await Promise.all([\n oldRef && oldPath ? readRevisionLines(repoRoot, oldRef, oldPath).catch(() => null) : null,\n newRef === null\n ? readWorkingTreeLines(repoRoot, filePath).catch(() => null)\n : readRevisionLines(repoRoot, newRef, filePath).catch(() => null)\n ]);\n\n if (!oldLines && !newLines) {\n throw new Error(`Could not read ${filePath} from either side of the diff`);\n }\n\n const lines: DiffLine[] = [];\n for (let index = 0; index < lineCount; index += 1) {\n const oldLine = oldStart + index;\n const newLine = newStart + index;\n const content = newLines?.[newLine - 1] ?? oldLines?.[oldLine - 1];\n if (content === undefined) {\n continue;\n }\n lines.push({\n type: 'context',\n oldLine,\n newLine,\n content\n });\n }\n\n return {\n filePath,\n oldStart,\n newStart,\n lines\n };\n}\n\nasync function readRevisionLines(\n repoRoot: string,\n ref: string,\n filePath: string\n): Promise<string[]> {\n const result = await execa('git', ['show', `${ref}:${filePath}`], { cwd: repoRoot });\n return splitFileLines(result.stdout);\n}\n\nasync function readWorkingTreeLines(repoRoot: string, filePath: string): Promise<string[]> {\n return splitFileLines(await readFile(path.resolve(repoRoot, filePath), 'utf8'));\n}\n\nfunction splitFileLines(contents: string): string[] {\n const lines = contents.replace(/\\r\\n/g, '\\n').split('\\n');\n if (lines.at(-1) === '') {\n lines.pop();\n }\n return lines;\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 type { DiffFile } from './types';\n\nexport function compareFilePaths(\n leftPath: string,\n rightPath: string,\n leftTieBreaker = '',\n rightTieBreaker = ''\n): number {\n return (\n leftPath.localeCompare(rightPath, undefined, { sensitivity: 'base' }) ||\n leftPath.localeCompare(rightPath) ||\n leftTieBreaker.localeCompare(rightTieBreaker, undefined, { sensitivity: 'base' }) ||\n leftTieBreaker.localeCompare(rightTieBreaker)\n );\n}\n\nfunction compareDiffFiles(left: DiffFile, right: DiffFile): number {\n return compareFilePaths(left.path, right.path, left.oldPath ?? '', right.oldPath ?? '');\n}\n\nexport function sortDiffFiles<T extends DiffFile>(files: T[]): T[] {\n return files.toSorted(compareDiffFiles);\n}\n","import type { ReviewStatus } from './types';\n\nexport function isResolvableReviewStatus(status: ReviewStatus): boolean {\n return status === 'submitted' || status === 'resolved';\n}\n","import { execFile } from 'node:child_process';\nimport { access } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport path from 'node:path';\nimport { promisify } from 'node:util';\nimport open from 'open';\nimport type { OpenFileTarget, OpenFileTargetInfo } from '../shared/types';\n\nconst execFileAsync = promisify(execFile);\n\nconst applicationRoots = [\n '/Applications',\n path.join(homedir(), 'Applications'),\n '/System/Applications',\n '/System/Applications/Utilities'\n];\n\ninterface OpenFileTargetDescriptor extends OpenFileTargetInfo {\n appName?: string | readonly string[];\n opensFolder?: boolean;\n}\n\nconst openFileTargetDescriptors: OpenFileTargetDescriptor[] = [\n { appName: 'Visual Studio Code', label: 'VS Code', target: 'vscode' },\n {\n appName: ['Visual Studio Code - Insiders', 'Code - Insiders'],\n label: 'VS Code Insiders',\n target: 'vscode-insiders'\n },\n { appName: 'VSCodium', label: 'VSCodium', target: 'vscodium' },\n { appName: 'Cursor', label: 'Cursor', target: 'cursor' },\n { appName: 'Sublime Text', label: 'Sublime Text', target: 'sublime' },\n { appName: 'Zed', label: 'Zed', target: 'zed' },\n { appName: 'Windsurf', label: 'Windsurf', target: 'windsurf' },\n { appName: 'WebStorm', label: 'WebStorm', target: 'webstorm' },\n {\n appName: ['IntelliJ IDEA', 'IntelliJ IDEA Ultimate', 'IntelliJ IDEA CE'],\n label: 'IntelliJ IDEA',\n target: 'intellij'\n },\n { appName: ['PyCharm', 'PyCharm CE'], label: 'PyCharm', target: 'pycharm' },\n { appName: 'GoLand', label: 'GoLand', target: 'goland' },\n { appName: 'PhpStorm', label: 'PhpStorm', target: 'phpstorm' },\n { appName: 'RubyMine', label: 'RubyMine', target: 'rubymine' },\n { appName: 'CLion', label: 'CLion', target: 'clion' },\n { appName: 'DataGrip', label: 'DataGrip', target: 'datagrip' },\n { appName: 'Android Studio', label: 'Android Studio', target: 'android-studio' },\n { appName: 'Fleet', label: 'Fleet', target: 'fleet' },\n { appName: 'Neovide', label: 'Neovide', target: 'neovide' },\n { appName: 'MacVim', label: 'MacVim', target: 'macvim' },\n { appName: 'Emacs', label: 'Emacs', target: 'emacs' },\n { appName: 'Lapce', label: 'Lapce', target: 'lapce' },\n { appName: 'TextMate', label: 'TextMate', target: 'textmate' },\n { appName: 'BBEdit', label: 'BBEdit', target: 'bbedit' },\n { appName: 'CotEditor', label: 'CotEditor', target: 'coteditor' },\n { appName: 'Nova', label: 'Nova', target: 'nova' },\n { appName: 'TextEdit', label: 'TextEdit', target: 'textedit' },\n { appName: 'Terminal', label: 'Terminal', opensFolder: true, target: 'terminal' },\n { appName: ['iTerm', 'iTerm2'], label: 'iTerm2', opensFolder: true, target: 'iterm2' },\n { appName: 'Ghostty', label: 'Ghostty', opensFolder: true, target: 'ghostty' },\n { appName: 'Xcode', label: 'Xcode', target: 'xcode' },\n { label: 'Default app', target: 'default' },\n { label: 'Open in folder', opensFolder: true, target: 'folder' }\n];\n\nconst openFileTargetDescriptorByTarget = new Map(\n openFileTargetDescriptors.map((descriptor) => [descriptor.target, descriptor])\n);\n\nexport async function availableOpenFileTargets(): Promise<OpenFileTargetInfo[]> {\n const availability = await Promise.all(\n openFileTargetDescriptors.map(async (descriptor) =>\n descriptor.appName && !(await resolveAppPath(descriptor.appName)) ? null : descriptor\n )\n );\n return availability\n .filter((descriptor): descriptor is OpenFileTargetDescriptor => descriptor !== null)\n .map(({ label, target }) => ({ label, target }));\n}\n\nexport async function openLocalPath(\n filePath: string,\n target: OpenFileTarget = 'default'\n): Promise<void> {\n const descriptor = openFileTargetDescriptorByTarget.get(target);\n const openPath = descriptor?.opensFolder ? path.dirname(filePath) : filePath;\n const appName = descriptor?.appName;\n if (!appName) {\n await open(openPath, { wait: false });\n return;\n }\n\n const appPath = await resolveAppPath(appName);\n if (appPath) {\n await execFileAsync('open', ['-a', appPath, openPath]);\n return;\n }\n\n await open(openPath, { app: { name: appName }, wait: false });\n}\n\nasync function resolveAppPath(appName: string | readonly string[]): Promise<string | null> {\n if (process.platform !== 'darwin') {\n return null;\n }\n\n const appNames = Array.isArray(appName) ? appName : [appName];\n for (const name of appNames) {\n for (const root of applicationRoots) {\n const appPath = path.join(root, `${name}.app`);\n try {\n await access(appPath);\n return appPath;\n } catch {\n // Try the next likely application location.\n }\n }\n }\n return null;\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { execa } from 'execa';\nimport { languageForPath } from '../shared/language';\nimport type { SourcePeekRangeResponse, SourcePeekResponse } from '../shared/types';\nimport {\n SOURCE_PEEK_MAX_BYTES,\n SOURCE_PEEK_RANGE_MAX_LINES,\n type SourcePeekMatchReason\n} from '../shared/types';\n\nconst MODULE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json'];\nconst PATH_CONFIG_FILES = ['tsconfig.json', 'jsconfig.json'];\nconst IGNORED_SEARCH_PATHS = ['node_modules', 'dist', 'build', 'coverage', '.git'];\nconst IDENTIFIER_PATTERN = '[A-Za-z_$][\\\\w$]*';\nconst SOURCE_PEEK_CONTEXT_LINES = 520;\nconst SOURCE_PEEK_TARGET_CONTEXT_LINES = 240;\n\ninterface SourcePeekOptions {\n repoRoot: string;\n sourceFilePath: string;\n sourceRef: string | null;\n symbol: string;\n line: number;\n column: number;\n}\n\ninterface SourcePeekRangeOptions {\n repoRoot: string;\n sourceFilePath: string;\n sourceRef: string | null;\n startLine: number;\n lineCount: number;\n}\n\ninterface ImportBinding {\n importedName: string;\n kind: 'default' | 'named' | 'namespace';\n localName: string;\n moduleSpecifier: string;\n}\n\ninterface ReExportBinding {\n exportedName: string;\n importedName: string;\n moduleSpecifier: string;\n}\n\ninterface PathAlias {\n pattern: string;\n replacements: string[];\n}\n\ninterface PathAliasConfig {\n baseUrl: string | null;\n aliases: PathAlias[];\n}\n\ninterface DefinitionMatch {\n column: number;\n line: number;\n}\n\ninterface ModuleFile {\n content: string;\n filePath: string;\n}\n\ninterface ReferenceToken {\n namespace: string | null;\n symbol: string;\n}\n\nexport async function resolveSourcePeek({\n column,\n line,\n repoRoot,\n sourceFilePath,\n sourceRef,\n symbol\n}: SourcePeekOptions): Promise<SourcePeekResponse> {\n const sourceContent = await readRepoText(repoRoot, sourceRef, sourceFilePath);\n const sourceLines = splitFileLines(sourceContent);\n const reference = referenceTokenAt(sourceLines[line - 1] ?? '', column, symbol);\n const imports = parseImportBindings(sourceContent);\n const aliasConfig = await loadPathAliasConfig(repoRoot);\n const importedCandidates = candidateImportsForReference(imports, reference);\n\n for (const candidate of importedCandidates) {\n const resolved = await resolveImportedTarget({\n aliasConfig,\n importedName: candidate.targetSymbol,\n matchReason: 'import',\n moduleSpecifier: candidate.moduleSpecifier,\n repoRoot,\n sourceFilePath,\n sourceRef,\n symbol\n });\n if (resolved) {\n return resolved;\n }\n }\n\n const sameFileMatch = findDefinition(sourceContent, symbol);\n if (sameFileMatch) {\n return responseForMatch({\n column: sameFileMatch.column,\n content: sourceContent,\n filePath: sourceFilePath,\n line: sameFileMatch.line,\n matchReason: 'same-file',\n symbol,\n targetSymbol: symbol\n });\n }\n\n const searched = await searchRepoDefinition(repoRoot, sourceRef, symbol);\n if (searched) {\n return responseForMatch({\n ...searched,\n matchReason: 'repo-search',\n symbol,\n targetSymbol: symbol\n });\n }\n\n throw new Error(`No definition found for ${symbol}`);\n}\n\nexport async function readSourcePeekRange({\n lineCount,\n repoRoot,\n sourceFilePath,\n sourceRef,\n startLine\n}: SourcePeekRangeOptions): Promise<SourcePeekRangeResponse> {\n const content = await readRepoText(repoRoot, sourceRef, sourceFilePath);\n const limited = limitContentRange(content, startLine, lineCount);\n return {\n filePath: sourceFilePath,\n startLine: limited.startLine,\n totalLines: limited.totalLines,\n content: limited.content,\n truncated: limited.truncated,\n hasMoreAbove: limited.hasMoreAbove,\n hasMoreBelow: limited.hasMoreBelow\n };\n}\n\nasync function resolveImportedTarget({\n aliasConfig,\n importedName,\n matchReason,\n moduleSpecifier,\n repoRoot,\n sourceFilePath,\n sourceRef,\n symbol\n}: {\n aliasConfig: PathAliasConfig;\n importedName: string;\n matchReason: SourcePeekMatchReason;\n moduleSpecifier: string;\n repoRoot: string;\n sourceFilePath: string;\n sourceRef: string | null;\n symbol: string;\n}): Promise<SourcePeekResponse | null> {\n const moduleFile = await firstExistingModuleFile(\n repoRoot,\n sourceRef,\n moduleCandidates(repoRoot, aliasConfig, sourceFilePath, moduleSpecifier)\n );\n if (!moduleFile) {\n return null;\n }\n\n const targetMatch = findDefinition(moduleFile.content, importedName);\n if (targetMatch) {\n return responseForMatch({\n column: targetMatch.column,\n content: moduleFile.content,\n filePath: moduleFile.filePath,\n line: targetMatch.line,\n matchReason,\n symbol,\n targetSymbol: importedName\n });\n }\n\n const reExported = await resolveReExport({\n aliasConfig,\n content: moduleFile.content,\n depth: 0,\n repoRoot,\n sourceFilePath: moduleFile.filePath,\n sourceRef,\n symbol,\n targetSymbol: importedName\n });\n if (reExported) {\n return reExported;\n }\n\n if (importedName === 'default') {\n const fallbackLine = firstMeaningfulLine(moduleFile.content);\n return responseForMatch({\n column: 0,\n content: moduleFile.content,\n filePath: moduleFile.filePath,\n line: fallbackLine,\n matchReason: 'module',\n symbol,\n targetSymbol: importedName\n });\n }\n\n return null;\n}\n\nasync function resolveReExport({\n aliasConfig,\n content,\n depth,\n repoRoot,\n sourceFilePath,\n sourceRef,\n symbol,\n targetSymbol\n}: {\n aliasConfig: PathAliasConfig;\n content: string;\n depth: number;\n repoRoot: string;\n sourceFilePath: string;\n sourceRef: string | null;\n symbol: string;\n targetSymbol: string;\n}): Promise<SourcePeekResponse | null> {\n if (depth > 3) {\n return null;\n }\n\n for (const binding of parseReExportBindings(content)) {\n if (binding.exportedName !== '*' && binding.exportedName !== targetSymbol) {\n continue;\n }\n const nextTarget = binding.importedName === '*' ? targetSymbol : binding.importedName;\n const moduleFile = await firstExistingModuleFile(\n repoRoot,\n sourceRef,\n moduleCandidates(repoRoot, aliasConfig, sourceFilePath, binding.moduleSpecifier)\n );\n if (!moduleFile) {\n continue;\n }\n const match = findDefinition(moduleFile.content, nextTarget);\n if (match) {\n return responseForMatch({\n column: match.column,\n content: moduleFile.content,\n filePath: moduleFile.filePath,\n line: match.line,\n matchReason: 'import',\n symbol,\n targetSymbol: nextTarget\n });\n }\n const nested = await resolveReExport({\n aliasConfig,\n content: moduleFile.content,\n depth: depth + 1,\n repoRoot,\n sourceFilePath: moduleFile.filePath,\n sourceRef,\n symbol,\n targetSymbol: nextTarget\n });\n if (nested) {\n return nested;\n }\n }\n\n return null;\n}\n\nasync function searchRepoDefinition(\n repoRoot: string,\n sourceRef: string | null,\n symbol: string\n): Promise<({ content: string; filePath: string } & DefinitionMatch) | null> {\n const grepPattern = definitionGrepPattern(symbol);\n const args = ['grep', '-n', '-I', '-E', grepPattern];\n if (sourceRef) {\n args.push(sourceRef);\n }\n args.push('--', '.');\n for (const ignoredPath of IGNORED_SEARCH_PATHS) {\n args.push(`:!${ignoredPath}`);\n }\n\n let output = '';\n try {\n output = (await execa('git', args, { cwd: repoRoot })).stdout;\n } catch (error) {\n if (isExitCode(error, 1)) {\n return null;\n }\n throw error;\n }\n\n for (const rawLine of output.split('\\n')) {\n const parsed = parseGrepLine(rawLine, sourceRef);\n if (!parsed) {\n continue;\n }\n const content = await readRepoText(repoRoot, sourceRef, parsed.filePath).catch(() => null);\n if (!content) {\n continue;\n }\n const match = findDefinition(content, symbol);\n if (!match) {\n continue;\n }\n return {\n column: match.column,\n content,\n filePath: parsed.filePath,\n line: match.line\n };\n }\n\n return null;\n}\n\nasync function readRepoText(\n repoRoot: string,\n ref: string | null,\n filePath: string\n): Promise<string> {\n if (ref === null) {\n return readFile(path.resolve(repoRoot, filePath), 'utf8');\n }\n return (await execa('git', ['show', `${ref}:${filePath}`], { cwd: repoRoot })).stdout;\n}\n\nfunction responseForMatch({\n column,\n content,\n filePath,\n line,\n matchReason,\n symbol,\n targetSymbol\n}: {\n column: number;\n content: string;\n filePath: string;\n line: number;\n matchReason: SourcePeekMatchReason;\n symbol: string;\n targetSymbol: string;\n}): SourcePeekResponse {\n const limited = limitContentAroundLine(content, line);\n return {\n symbol,\n targetSymbol,\n filePath,\n startLine: limited.startLine,\n line,\n column,\n language: languageForPath(filePath),\n content: limited.content,\n truncated: limited.truncated,\n totalLines: limited.totalLines,\n hasMoreAbove: limited.hasMoreAbove,\n hasMoreBelow: limited.hasMoreBelow,\n matchReason\n };\n}\n\ninterface SourcePeekWindow {\n content: string;\n startLine: number;\n totalLines: number;\n truncated: boolean;\n hasMoreAbove: boolean;\n hasMoreBelow: boolean;\n}\n\nfunction limitContentAroundLine(content: string, line: number): SourcePeekWindow {\n const lines = splitFileLines(content);\n const totalLines = sourceTotalLines(lines);\n if (Buffer.byteLength(content, 'utf8') <= SOURCE_PEEK_MAX_BYTES) {\n return {\n content,\n startLine: 1,\n totalLines,\n truncated: false,\n hasMoreAbove: false,\n hasMoreBelow: false\n };\n }\n\n if (lines.length === 0) {\n return emptySourceWindow();\n }\n\n const targetIndex = Math.max(0, line - 1);\n const preferredStartIndex = Math.max(0, targetIndex - SOURCE_PEEK_TARGET_CONTEXT_LINES);\n const preferredEndIndex = Math.min(lines.length, preferredStartIndex + SOURCE_PEEK_CONTEXT_LINES);\n return limitLinesByIndexes(lines, preferredStartIndex, preferredEndIndex, targetIndex);\n}\n\nfunction limitContentRange(\n content: string,\n startLine: number,\n lineCount: number\n): SourcePeekWindow {\n const lines = splitFileLines(content);\n if (lines.length === 0) {\n return emptySourceWindow();\n }\n\n const cappedLineCount = Math.min(lineCount, SOURCE_PEEK_RANGE_MAX_LINES);\n const startIndex = clampNumber(startLine - 1, 0, lines.length - 1);\n const endIndex = Math.min(lines.length, startIndex + cappedLineCount);\n return limitLinesByIndexes(lines, startIndex, endIndex, null);\n}\n\nfunction limitLinesByIndexes(\n lines: string[],\n startIndex: number,\n endIndex: number,\n targetIndex: number | null\n): SourcePeekWindow {\n let limitedStartIndex = startIndex;\n let limitedEndIndex = endIndex;\n let limitedContent = lines.slice(limitedStartIndex, limitedEndIndex).join('\\n');\n let truncatedByBytes = false;\n\n while (\n Buffer.byteLength(limitedContent, 'utf8') > SOURCE_PEEK_MAX_BYTES &&\n limitedEndIndex - limitedStartIndex > 1\n ) {\n if (\n targetIndex !== null &&\n targetIndex - limitedStartIndex > limitedEndIndex - targetIndex - 1\n ) {\n limitedStartIndex += 1;\n } else {\n limitedEndIndex -= 1;\n }\n limitedContent = lines.slice(limitedStartIndex, limitedEndIndex).join('\\n');\n truncatedByBytes = true;\n }\n\n if (Buffer.byteLength(limitedContent, 'utf8') > SOURCE_PEEK_MAX_BYTES) {\n limitedContent = truncateUtf8(limitedContent, SOURCE_PEEK_MAX_BYTES);\n truncatedByBytes = true;\n }\n\n return {\n content: limitedContent,\n startLine: limitedStartIndex + 1,\n totalLines: sourceTotalLines(lines),\n truncated: truncatedByBytes || limitedStartIndex > 0 || limitedEndIndex < lines.length,\n hasMoreAbove: limitedStartIndex > 0,\n hasMoreBelow: limitedEndIndex < lines.length\n };\n}\n\nfunction emptySourceWindow(): SourcePeekWindow {\n return {\n content: '',\n startLine: 1,\n totalLines: 1,\n truncated: false,\n hasMoreAbove: false,\n hasMoreBelow: false\n };\n}\n\nfunction sourceTotalLines(lines: string[]): number {\n return Math.max(1, lines.length);\n}\n\nfunction clampNumber(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nfunction truncateUtf8(value: string, maxBytes: number): string {\n const buffer = Buffer.from(value, 'utf8');\n if (buffer.byteLength <= maxBytes) {\n return value;\n }\n return buffer\n .subarray(0, maxBytes)\n .toString('utf8')\n .replace(/\\uFFFD$/, '');\n}\n\nfunction candidateImportsForReference(\n imports: ImportBinding[],\n reference: ReferenceToken\n): Array<{ moduleSpecifier: string; targetSymbol: string }> {\n if (reference.namespace) {\n return imports\n .filter(\n (binding) => binding.kind === 'namespace' && binding.localName === reference.namespace\n )\n .map((binding) => ({\n moduleSpecifier: binding.moduleSpecifier,\n targetSymbol: reference.symbol\n }));\n }\n\n return imports\n .filter((binding) => binding.localName === reference.symbol)\n .map((binding) => ({\n moduleSpecifier: binding.moduleSpecifier,\n targetSymbol: binding.importedName\n }));\n}\n\nfunction referenceTokenAt(line: string, column: number, symbol: string): ReferenceToken {\n let start = Math.min(Math.max(column, 0), line.length);\n if (line.slice(start, start + symbol.length) !== symbol) {\n const beforeOrAt = line.lastIndexOf(symbol, start);\n start = beforeOrAt >= 0 ? beforeOrAt : line.indexOf(symbol);\n }\n if (start < 0) {\n return { namespace: null, symbol };\n }\n\n const namespaceMatch = line.slice(0, start).match(/([A-Za-z_$][\\w$]*)\\s*\\.\\s*$/);\n return {\n namespace: namespaceMatch?.[1] ?? null,\n symbol\n };\n}\n\nfunction parseImportBindings(content: string): ImportBinding[] {\n const bindings: ImportBinding[] = [];\n const importRegex = /^\\s*import\\s+(?:type\\s+)?([^;]*?)\\s+from\\s+['\"]([^'\"]+)['\"];?/gm;\n let match = importRegex.exec(content);\n while (match !== null) {\n const body = match[1]?.trim() ?? '';\n const moduleSpecifier = match[2] ?? '';\n for (const part of splitImportParts(body)) {\n if (part.startsWith('{') && part.endsWith('}')) {\n bindings.push(\n ...parseNamedBindings(part).map((binding) => ({\n ...binding,\n kind: 'named' as const,\n moduleSpecifier\n }))\n );\n continue;\n }\n\n const namespaceMatch = part.match(/^\\*\\s+as\\s+([A-Za-z_$][\\w$]*)$/);\n if (namespaceMatch?.[1]) {\n bindings.push({\n importedName: '*',\n kind: 'namespace',\n localName: namespaceMatch[1],\n moduleSpecifier\n });\n continue;\n }\n\n if (new RegExp(`^${IDENTIFIER_PATTERN}$`).test(part)) {\n bindings.push({\n importedName: 'default',\n kind: 'default',\n localName: part,\n moduleSpecifier\n });\n }\n }\n match = importRegex.exec(content);\n }\n return bindings;\n}\n\nfunction parseReExportBindings(content: string): ReExportBinding[] {\n const bindings: ReExportBinding[] = [];\n const exportRegex = /^\\s*export\\s+(?:type\\s+)?(\\*|\\{[\\s\\S]*?\\})\\s+from\\s+['\"]([^'\"]+)['\"];?/gm;\n let match = exportRegex.exec(content);\n while (match !== null) {\n const body = match[1] ?? '';\n const moduleSpecifier = match[2] ?? '';\n if (body === '*') {\n bindings.push({ exportedName: '*', importedName: '*', moduleSpecifier });\n match = exportRegex.exec(content);\n continue;\n }\n bindings.push(\n ...parseNamedBindings(body).map((binding) => ({\n exportedName: binding.localName,\n importedName: binding.importedName,\n moduleSpecifier\n }))\n );\n match = exportRegex.exec(content);\n }\n return bindings;\n}\n\nfunction parseNamedBindings(body: string): Array<{ importedName: string; localName: string }> {\n return body\n .slice(1, -1)\n .split(',')\n .map((part) => part.trim().replace(/^type\\s+/, ''))\n .filter(Boolean)\n .map((part) => {\n const aliasMatch = part.match(/^([A-Za-z_$][\\w$]*)\\s+as\\s+([A-Za-z_$][\\w$]*)$/);\n if (aliasMatch?.[1] && aliasMatch[2]) {\n return { importedName: aliasMatch[1], localName: aliasMatch[2] };\n }\n return new RegExp(`^${IDENTIFIER_PATTERN}$`).test(part)\n ? { importedName: part, localName: part }\n : null;\n })\n .filter((binding): binding is { importedName: string; localName: string } => Boolean(binding));\n}\n\nfunction splitImportParts(body: string): string[] {\n const parts: string[] = [];\n let depth = 0;\n let start = 0;\n for (let index = 0; index < body.length; index += 1) {\n const char = body[index];\n if (char === '{') {\n depth += 1;\n } else if (char === '}') {\n depth = Math.max(0, depth - 1);\n } else if (char === ',' && depth === 0) {\n parts.push(body.slice(start, index).trim());\n start = index + 1;\n }\n }\n parts.push(body.slice(start).trim());\n return parts.filter(Boolean);\n}\n\nasync function loadPathAliasConfig(repoRoot: string): Promise<PathAliasConfig> {\n for (const configFile of PATH_CONFIG_FILES) {\n const rawConfig = await readFile(path.join(repoRoot, configFile), 'utf8').catch(() => null);\n if (!rawConfig) {\n continue;\n }\n const parsed = parseJsonConfig(rawConfig);\n if (!parsed) {\n continue;\n }\n const compilerOptions = asRecord(parsed.compilerOptions);\n const baseUrlValue = compilerOptions ? compilerOptions.baseUrl : null;\n const baseUrl =\n typeof baseUrlValue === 'string' ? path.resolve(repoRoot, baseUrlValue) : repoRoot;\n const paths = asRecord(compilerOptions?.paths);\n const aliases = paths\n ? Object.entries(paths).flatMap(([pattern, replacements]) =>\n Array.isArray(replacements)\n ? [\n {\n pattern,\n replacements: replacements.filter(\n (replacement): replacement is string => typeof replacement === 'string'\n )\n }\n ]\n : []\n )\n : [];\n return { aliases, baseUrl };\n }\n\n return { aliases: [], baseUrl: null };\n}\n\nfunction parseJsonConfig(rawConfig: string): Record<string, unknown> | null {\n try {\n return JSON.parse(stripJsonComments(rawConfig).replace(/,\\s*([}\\]])/g, '$1'));\n } catch {\n return null;\n }\n}\n\nfunction stripJsonComments(input: string): string {\n return input.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '').replace(/^\\s*\\/\\/.*$/gm, '');\n}\n\nfunction moduleCandidates(\n repoRoot: string,\n aliasConfig: PathAliasConfig,\n sourceFilePath: string,\n moduleSpecifier: string\n): string[] {\n const roots: string[] = [];\n if (moduleSpecifier.startsWith('.')) {\n roots.push(path.resolve(repoRoot, path.dirname(sourceFilePath), moduleSpecifier));\n } else {\n roots.push(...aliasCandidateRoots(repoRoot, aliasConfig, moduleSpecifier));\n if (aliasConfig.baseUrl) {\n roots.push(path.resolve(aliasConfig.baseUrl, moduleSpecifier));\n }\n }\n\n const candidates = new Set<string>();\n for (const root of roots) {\n for (const candidate of expandModuleRoot(root)) {\n const relativePath = repoRelativePath(repoRoot, candidate);\n if (relativePath) {\n candidates.add(relativePath);\n }\n }\n }\n return [...candidates];\n}\n\nfunction aliasCandidateRoots(\n repoRoot: string,\n aliasConfig: PathAliasConfig,\n moduleSpecifier: string\n): string[] {\n const roots: string[] = [];\n for (const alias of aliasConfig.aliases) {\n const wildcardIndex = alias.pattern.indexOf('*');\n const matched =\n wildcardIndex >= 0\n ? matchWildcardPattern(alias.pattern, wildcardIndex, moduleSpecifier)\n : alias.pattern === moduleSpecifier\n ? ''\n : null;\n if (matched === null) {\n continue;\n }\n for (const replacement of alias.replacements) {\n roots.push(\n path.resolve(\n aliasConfig.baseUrl ?? repoRoot,\n wildcardIndex >= 0 ? replacement.replace('*', matched) : replacement\n )\n );\n }\n }\n return roots;\n}\n\nfunction matchWildcardPattern(\n pattern: string,\n wildcardIndex: number,\n value: string\n): string | null {\n const prefix = pattern.slice(0, wildcardIndex);\n const suffix = pattern.slice(wildcardIndex + 1);\n if (!value.startsWith(prefix) || !value.endsWith(suffix)) {\n return null;\n }\n return value.slice(prefix.length, value.length - suffix.length);\n}\n\nfunction expandModuleRoot(root: string): string[] {\n const candidates: string[] = [];\n if (path.extname(root)) {\n candidates.push(root);\n } else {\n for (const extension of MODULE_EXTENSIONS) {\n candidates.push(`${root}${extension}`);\n }\n for (const extension of MODULE_EXTENSIONS) {\n candidates.push(path.join(root, `index${extension}`));\n }\n }\n return candidates;\n}\n\nasync function firstExistingModuleFile(\n repoRoot: string,\n sourceRef: string | null,\n candidates: string[]\n): Promise<ModuleFile | null> {\n for (const filePath of candidates) {\n const content = await readRepoText(repoRoot, sourceRef, filePath).catch(() => null);\n if (content !== null) {\n return { content, filePath };\n }\n }\n return null;\n}\n\nfunction findDefinition(content: string, symbol: string): DefinitionMatch | null {\n const lines = splitFileLines(content);\n const patterns = definitionPatterns(symbol);\n for (let index = 0; index < lines.length; index += 1) {\n const line = lines[index] ?? '';\n if (!patterns.some((pattern) => pattern.test(line))) {\n continue;\n }\n return {\n column: Math.max(0, line.indexOf(symbol === 'default' ? 'default' : symbol)),\n line: index + 1\n };\n }\n return null;\n}\n\nfunction definitionPatterns(symbol: string): RegExp[] {\n if (symbol === 'default') {\n return [/^\\s*export\\s+default\\b/];\n }\n\n const escaped = escapeRegex(symbol);\n return [\n new RegExp(`^\\\\s*(?:export\\\\s+)?(?:declare\\\\s+)?(?:async\\\\s+)?function\\\\s+${escaped}\\\\b`),\n new RegExp(`^\\\\s*(?:export\\\\s+)?(?:declare\\\\s+)?(?:const|let|var)\\\\s+${escaped}\\\\b`),\n new RegExp(\n `^\\\\s*(?:export\\\\s+)?(?:declare\\\\s+)?(?:class|interface|type|enum)\\\\s+${escaped}\\\\b`\n ),\n new RegExp(`^\\\\s*export\\\\s+default\\\\s+(?:async\\\\s+)?function\\\\s+${escaped}\\\\b`),\n new RegExp(`^\\\\s*export\\\\s+default\\\\s+class\\\\s+${escaped}\\\\b`)\n ];\n}\n\nfunction definitionGrepPattern(symbol: string): string {\n const escaped = escapeExtendedGrep(symbol);\n return [\n `^[[:space:]]*(export[[:space:]]+)?(declare[[:space:]]+)?(async[[:space:]]+)?function[[:space:]]+${escaped}([^[:alnum:]_$]|$)`,\n `^[[:space:]]*(export[[:space:]]+)?(declare[[:space:]]+)?(const|let|var)[[:space:]]+${escaped}([^[:alnum:]_$]|$)`,\n `^[[:space:]]*(export[[:space:]]+)?(declare[[:space:]]+)?(class|interface|type|enum)[[:space:]]+${escaped}([^[:alnum:]_$]|$)`\n ].join('|');\n}\n\nfunction firstMeaningfulLine(content: string): number {\n const lines = splitFileLines(content);\n const index = lines.findIndex((line) => line.trim() !== '');\n return index >= 0 ? index + 1 : 1;\n}\n\nfunction parseGrepLine(\n rawLine: string,\n sourceRef: string | null\n): { filePath: string; line: number } | null {\n const line = sourceRef ? rawLine.slice(sourceRef.length + 1) : rawLine;\n const firstColon = line.indexOf(':');\n const secondColon = line.indexOf(':', firstColon + 1);\n if (firstColon < 0 || secondColon < 0) {\n return null;\n }\n const lineNumber = Number(line.slice(firstColon + 1, secondColon));\n if (!Number.isFinite(lineNumber)) {\n return null;\n }\n return {\n filePath: line.slice(0, firstColon),\n line: lineNumber\n };\n}\n\nfunction repoRelativePath(repoRoot: string, absolutePath: string): string | null {\n const relativePath = path.relative(repoRoot, absolutePath);\n if (!relativePath || relativePath.startsWith('..') || path.isAbsolute(relativePath)) {\n return null;\n }\n return relativePath.split(path.sep).join('/');\n}\n\nfunction splitFileLines(contents: string): string[] {\n const lines = contents.replace(/\\r\\n/g, '\\n').split('\\n');\n if (lines.at(-1) === '') {\n lines.pop();\n }\n return lines;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction isExitCode(error: unknown, exitCode: number): boolean {\n return typeof error === 'object' && error !== null && 'exitCode' in error\n ? error.exitCode === exitCode\n : false;\n}\n\nfunction escapeRegex(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction escapeExtendedGrep(value: string): string {\n return value.replace(/[.[*^$()+?{}|\\\\]/g, '\\\\$&');\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.loadReviewForList(entry.name));\n }\n }\n await Promise.all(reviewLoads);\n }\n\n private async loadReviewForList(id: string): Promise<ReviewRecord | null> {\n try {\n return await this.loadReview(id);\n } catch (error) {\n process.stderr.write(`Warning: Skipping corrupt review ${id}: ${formatError(error)}\\n`);\n return null;\n }\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 { 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","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, isLineComment } from './comments';\nimport { languageForPath } from './language';\nimport { reviewScopeLabel } from './review-scope';\nimport type { FeedbackBundle, LineComment } 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 generalComments = comments.filter((comment) => !isLineComment(comment));\n const lineComments = comments.filter(isLineComment);\n const commentsByFile = new Map<string, LineComment[]>();\n const files: string[] = [];\n for (const comment of lineComments) {\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 if (generalComments.length > 0) {\n lines.push('## General comments', '');\n for (const comment of generalComments) {\n lines.push(`### ${comment.id}`, comment.body.trim(), '');\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 { DEFAULT_REVIEW_RETENTION_DAYS } from '../shared/cleanup';\nimport { formatError } from '../shared/errors';\nimport { reviewStore } from './store';\n\ninterface StartupCleanupLogger {\n info(message: string): void;\n error(message: string): void;\n}\n\nconst defaultLogger: StartupCleanupLogger = {\n info: (message) => {\n process.stdout.write(`${message}\\n`);\n },\n error: (message) => {\n process.stderr.write(`${message}\\n`);\n }\n};\n\nexport async function runStartupCleanup(\n logger: StartupCleanupLogger = defaultLogger\n): Promise<void> {\n try {\n const result = await reviewStore.clearReviewArtifacts({\n olderThanDays: DEFAULT_REVIEW_RETENTION_DAYS\n });\n logger.info(\n `Gloss cleanup deleted ${result.counts.deleted} review artifact(s); skipped ${result.counts.skipped}`\n );\n } catch (error) {\n logger.error(`Gloss cleanup failed: ${formatError(error)}`);\n }\n}\n"],"mappings":"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","names":["fileURLToPath","randomUUID","rm","writeFile","path","path","writeFile","rm","path","randomUUID","readFile","path","readFile","path","path","readFile","path","homedir","path","readFile","path","execa","splitFileLines","execa","readFile","path","readdir","readFile","path","readFile","rm","rm","readFile","readdir","readFile","path","origin","turnSummary","path","readFile","fileURLToPath"]}
1
+ {"version":3,"sources":["../../src/server/daemon.ts","../../src/shared/paths.ts","../../package.json","../../src/shared/server-info.ts","../../src/shared/errors.ts","../../src/shared/json.ts","../../src/shared/types.ts","../../src/shared/validation.ts","../../src/server/idle.ts","../../src/server/index.ts","../../src/shared/comments.ts","../../src/shared/git-diff.ts","../../src/shared/language.ts","../../src/shared/diff-parser.ts","../../src/shared/diff-stats.ts","../../src/shared/file-order.ts","../../src/shared/reviews.ts","../../src/server/local-open.ts","../../src/server/source-peek.ts","../../src/server/store.ts","../../src/shared/cleanup.ts","../../src/shared/review-scope.ts","../../src/shared/markdown.ts","../../src/server/maintenance.ts"],"sourcesContent":["import { fileURLToPath } from 'node:url';\nimport { serve } from '@hono/node-server';\nimport { globalStateDir, packageVersion } from '../shared/paths';\nimport { readServerInfo, removeServerInfoFile, writeServerInfo } from '../shared/server-info';\nimport { createIdleScheduler, normalizeIdleTimeoutMs } from './idle';\nimport { createApp } from './index';\nimport { runStartupCleanup } from './maintenance';\n\nconst port = Number(process.env.GLOSS_PORT ?? '0');\nconst idleTimeoutMs = normalizeIdleTimeoutMs();\nconst daemonPath = fileURLToPath(import.meta.url);\n\nif (!port) {\n throw new Error('GLOSS_PORT is required');\n}\n\nconst origin = `http://localhost:${port}`;\nconst eventStreams = new Set<() => void>();\nlet shuttingDown = false;\nconst idleScheduler = createIdleScheduler({\n timeoutMs: idleTimeoutMs,\n hasLiveClients: () => eventStreams.size > 0,\n isShuttingDown: () => shuttingDown,\n shutdown: () => shutdown(0)\n});\n\nconst server = serve({\n fetch: createApp(origin, {\n onReviewActivity: () => {\n idleScheduler.schedule();\n },\n registerEventStream: (close) => {\n eventStreams.add(close);\n idleScheduler.schedule();\n return () => {\n eventStreams.delete(close);\n idleScheduler.schedule();\n };\n },\n health: () => {\n return {\n connections: eventStreams.size,\n cwd: process.cwd(),\n daemonPath,\n stateDir: globalStateDir()\n };\n }\n }).fetch,\n port\n});\n\nawait writeServerInfo({\n pid: process.pid,\n port,\n version: packageVersion,\n startedAt: new Date().toISOString(),\n stateDir: globalStateDir(),\n cwd: process.cwd(),\n daemonPath\n});\n\nawait runStartupCleanup();\nidleScheduler.schedule();\n\nfor (const signal of ['SIGTERM', 'SIGINT', 'SIGHUP'] as const) {\n process.on(signal, () => {\n void shutdown(0);\n });\n}\n\nasync function shutdown(exitCode: number): Promise<void> {\n if (shuttingDown) {\n return;\n }\n shuttingDown = true;\n idleScheduler.cancel();\n for (const close of [...eventStreams]) {\n close();\n }\n await new Promise<void>((resolve) => {\n server.close(() => resolve());\n });\n await removeCurrentServerInfo();\n process.exit(exitCode);\n}\n\nasync function removeCurrentServerInfo(): Promise<void> {\n const info = await readServerInfo().catch(() => null);\n if (!info || info.pid === process.pid) {\n const warning = await removeServerInfoFile();\n if (warning) {\n process.stderr.write(`Warning: ${warning}\\n`);\n }\n }\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 globalServerLockDir(): string {\n return path.join(globalStateDir(), 'server.lock');\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.13.3\",\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 \"simple-icons\": \"16.23.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.3\",\n \"vitest\": \"3.2.6\"\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 { randomUUID } from 'node:crypto';\nimport { readFile, rm, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { formatError, isFileNotFound, isPermissionError } 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 if (isPermissionError(error)) {\n throw new Error(serverInfoPermissionMessage('read', error), { cause: error });\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 try {\n await ensureDir(globalStateDir());\n } catch (error) {\n if (isPermissionError(error)) {\n throw new Error(serverInfoPermissionMessage('create', error), { cause: error });\n }\n throw error;\n }\n\n try {\n await writeJsonFile(globalServerFile(), info);\n } catch (error) {\n if (!isPermissionError(error)) {\n throw error;\n }\n await assertStateDirWritable();\n try {\n await writeFile(globalServerFile(), serializeServerInfo(info));\n } catch (directWriteError) {\n throw new Error(serverInfoPermissionMessage('write', directWriteError), {\n cause: directWriteError\n });\n }\n }\n}\n\nexport async function removeServerInfoFile(): Promise<string | null> {\n try {\n await rm(globalServerFile(), { force: true });\n return null;\n } catch (error) {\n return serverInfoPermissionMessage('remove', error);\n }\n}\n\nexport function serverInfoPermissionMessage(action: string, error: unknown): string {\n const stateDir = globalStateDir();\n const source = process.env.GLOSS_STATE_DIR\n ? `GLOSS_STATE_DIR=${stateDir}`\n : 'GLOSS_STATE_DIR is not set; defaulting to ~/.gloss';\n return [\n `Could not ${action} Gloss server state at ${globalServerFile()}: ${formatError(error)}.`,\n '`server.json` is not a review lock, so there is nothing to unlock after a review.',\n `Check that ${stateDir} and ${globalServerFile()} are owned and writable by your user.`,\n `On macOS, if the file is immutable, run \\`chflags nouchg \"${globalServerFile()}\"\\`.`,\n `For sandboxed agents, set GLOSS_STATE_DIR to a writable directory. ${source}.`\n ].join(' ');\n}\n\nfunction serializeServerInfo(info: ServerInfo): string {\n return `${JSON.stringify(info, null, 2)}\\n`;\n}\n\nasync function assertStateDirWritable(): Promise<void> {\n const probePath = path.join(\n globalStateDir(),\n `.server.json.${process.pid}.${randomUUID()}.probe`\n );\n try {\n await writeFile(probePath, '');\n await rm(probePath, { force: true });\n } catch (error) {\n await rm(probePath, { force: true }).catch(() => undefined);\n throw new Error(serverInfoPermissionMessage('write', error), { cause: error });\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\nexport function isPermissionError(error: unknown): error is NodeJS.ErrnoException {\n return (\n error instanceof Error && 'code' in error && (error.code === 'EACCES' || error.code === 'EPERM')\n );\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 ClearReviewEntry {\n reviewId: string;\n status: ReviewStatus;\n artifactDir: string;\n lastActivityAt: string;\n}\n\ninterface 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 LineComment {\n kind?: 'line';\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 interface GeneralComment {\n kind: 'general';\n id: string;\n body: string;\n createdAt: string;\n}\n\nexport type Comment = LineComment | GeneralComment;\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 DIFF_CONTEXT_MAX_LINES = 500;\n\nexport type DiffContextSource =\n | { mode: 'turn' }\n | { mode: 'commit'; sha: string }\n | { mode: 'range'; fromSha: string; toSha: string };\n\nexport interface DiffContextRequest {\n filePath: string;\n oldPath: string | null;\n turnId?: string;\n source: DiffContextSource;\n oldStart: number;\n newStart: number;\n lineCount: number;\n}\n\nexport interface DiffContextResponse {\n filePath: string;\n oldStart: number;\n newStart: number;\n lines: DiffLine[];\n}\n\nexport const SOURCE_PEEK_MAX_BYTES = 350_000;\nexport const SOURCE_PEEK_RANGE_MAX_LINES = 240;\n\nexport const SOURCE_PEEK_MATCH_REASONS = ['import', 'same-file', 'repo-search', 'module'] as const;\n\nexport type SourcePeekMatchReason = (typeof SOURCE_PEEK_MATCH_REASONS)[number];\n\nexport interface SourcePeekRequest {\n filePath: string;\n oldPath: string | null;\n turnId?: string;\n source: DiffContextSource;\n side: Side;\n line: number;\n column: number;\n symbol: string;\n}\n\nexport interface SourcePeekResponse {\n symbol: string;\n targetSymbol: string;\n filePath: string;\n startLine: number;\n line: number;\n column: number;\n language: string | null;\n content: string;\n truncated: boolean;\n totalLines: number;\n hasMoreAbove: boolean;\n hasMoreBelow: boolean;\n matchReason: SourcePeekMatchReason;\n}\n\nexport interface SourcePeekRangeRequest {\n filePath: string;\n turnId?: string;\n source: DiffContextSource;\n side: Side;\n startLine: number;\n lineCount: number;\n}\n\nexport interface SourcePeekRangeResponse {\n filePath: string;\n startLine: number;\n totalLines: number;\n content: string;\n truncated: boolean;\n hasMoreAbove: boolean;\n hasMoreBelow: boolean;\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 cwd?: string;\n daemonPath?: 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 connections?: number;\n stateDir?: string;\n cwd?: string;\n daemonPath?: string;\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 const OPEN_FILE_SCOPES = ['review', 'repo'] as const;\n\nexport type OpenFileScope = (typeof OPEN_FILE_SCOPES)[number];\n\nexport const OPEN_FILE_TARGETS = [\n 'default',\n 'vscode',\n 'vscode-insiders',\n 'vscodium',\n 'cursor',\n 'sublime',\n 'zed',\n 'windsurf',\n 'webstorm',\n 'intellij',\n 'pycharm',\n 'goland',\n 'phpstorm',\n 'rubymine',\n 'clion',\n 'datagrip',\n 'android-studio',\n 'fleet',\n 'neovide',\n 'macvim',\n 'emacs',\n 'lapce',\n 'textmate',\n 'bbedit',\n 'coteditor',\n 'nova',\n 'textedit',\n 'xcode',\n 'terminal',\n 'iterm2',\n 'ghostty',\n 'folder'\n] as const;\n\nexport type OpenFileTarget = (typeof OPEN_FILE_TARGETS)[number];\n\nexport interface OpenFileRequest {\n filePath: string;\n turnId?: string;\n scope?: OpenFileScope;\n target?: OpenFileTarget;\n}\n\nexport interface OpenFileResponse {\n ok: true;\n path: string;\n}\n\nexport interface OpenFileTargetInfo {\n target: OpenFileTarget;\n label: string;\n}\n\nexport interface OpenFileTargetsResponse {\n targets: OpenFileTargetInfo[];\n}\n\nexport interface FileContentRequest {\n filePath: string;\n turnId?: string;\n scope?: OpenFileScope;\n}\n\nexport interface FileContentResponse {\n filePath: string;\n content: 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 DiffContextRequest,\n DiffContextResponse,\n DiffContextSource,\n DiffFile,\n DiffHunk,\n DiffLine,\n DiffPayload,\n DiffStats,\n FeedbackBundle,\n FileContentRequest,\n FileContentResponse,\n HealthResponse,\n ListReviewsResponse,\n OpenFileRequest,\n OpenFileResponse,\n OpenFileScope,\n OpenFileTarget,\n OpenFileTargetInfo,\n OpenFileTargetsResponse,\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 SourcePeekMatchReason,\n SourcePeekRangeRequest,\n SourcePeekRangeResponse,\n SourcePeekRequest,\n SourcePeekResponse,\n SubmitReviewRequest\n} from './types';\nimport {\n DIFF_FALLBACK_REASONS,\n DIFF_LINE_TYPES,\n DIFF_SCOPE_MODES,\n OPEN_FILE_SCOPES,\n OPEN_FILE_TARGETS,\n RESOLUTION_STATUSES,\n REVIEW_SCOPE_MODES,\n REVIEW_STATUSES,\n REVIEW_UPDATE_REASONS,\n SIDES,\n SOURCE_PEEK_MATCH_REASONS,\n SOURCE_PEEK_RANGE_MAX_LINES\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 isOptionalString(value.cwd) &&\n isOptionalString(value.daemonPath)\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 isOptionalNumber(value.connections) &&\n isOptionalString(value.stateDir) &&\n isOptionalString(value.cwd) &&\n isOptionalString(value.daemonPath)\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 (\n isRecord(value) &&\n isString(value.filePath) &&\n isOptionalString(value.turnId) &&\n isOptional(value.scope, isOpenFileScope) &&\n isOptional(value.target, isOpenFileTarget)\n );\n}\n\nexport function isOpenFileResponse(value: unknown): value is OpenFileResponse {\n return isRecord(value) && value.ok === true && isString(value.path);\n}\n\nexport function isOpenFileTargetsResponse(value: unknown): value is OpenFileTargetsResponse {\n return isRecord(value) && isArrayOf(value.targets, isOpenFileTargetInfo);\n}\n\nexport function isFileContentRequest(value: unknown): value is FileContentRequest {\n return (\n isRecord(value) &&\n isString(value.filePath) &&\n isOptionalString(value.turnId) &&\n isOptional(value.scope, isOpenFileScope)\n );\n}\n\nexport function isFileContentResponse(value: unknown): value is FileContentResponse {\n return isRecord(value) && isString(value.filePath) && isString(value.content);\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 isDiffContextRequest(value: unknown): value is DiffContextRequest {\n return (\n isRecord(value) &&\n isString(value.filePath) &&\n isNullableString(value.oldPath) &&\n isOptionalString(value.turnId) &&\n isDiffContextSource(value.source) &&\n isPositiveInteger(value.oldStart) &&\n isPositiveInteger(value.newStart) &&\n isPositiveInteger(value.lineCount)\n );\n}\n\nexport function isDiffContextResponse(value: unknown): value is DiffContextResponse {\n return (\n isRecord(value) &&\n isString(value.filePath) &&\n isPositiveInteger(value.oldStart) &&\n isPositiveInteger(value.newStart) &&\n isArrayOf(value.lines, isDiffLine)\n );\n}\n\nexport function isSourcePeekRequest(value: unknown): value is SourcePeekRequest {\n return (\n isRecord(value) &&\n isString(value.filePath) &&\n isNullableString(value.oldPath) &&\n isOptionalString(value.turnId) &&\n isDiffContextSource(value.source) &&\n isOneOf(value.side, SIDES) &&\n isPositiveInteger(value.line) &&\n isNonNegativeInteger(value.column) &&\n isIdentifier(value.symbol)\n );\n}\n\nexport function isSourcePeekResponse(value: unknown): value is SourcePeekResponse {\n return (\n isRecord(value) &&\n isString(value.symbol) &&\n isString(value.targetSymbol) &&\n isString(value.filePath) &&\n isPositiveInteger(value.startLine) &&\n isPositiveInteger(value.line) &&\n isNonNegativeInteger(value.column) &&\n isNullableString(value.language) &&\n isString(value.content) &&\n isBoolean(value.truncated) &&\n isPositiveInteger(value.totalLines) &&\n isBoolean(value.hasMoreAbove) &&\n isBoolean(value.hasMoreBelow) &&\n isSourcePeekMatchReason(value.matchReason)\n );\n}\n\nexport function isSourcePeekRangeRequest(value: unknown): value is SourcePeekRangeRequest {\n return (\n isRecord(value) &&\n isString(value.filePath) &&\n isOptionalString(value.turnId) &&\n isDiffContextSource(value.source) &&\n isOneOf(value.side, SIDES) &&\n isPositiveInteger(value.startLine) &&\n isPositiveInteger(value.lineCount) &&\n value.lineCount <= SOURCE_PEEK_RANGE_MAX_LINES\n );\n}\n\nexport function isSourcePeekRangeResponse(value: unknown): value is SourcePeekRangeResponse {\n return (\n isRecord(value) &&\n isString(value.filePath) &&\n isPositiveInteger(value.startLine) &&\n isPositiveInteger(value.totalLines) &&\n isString(value.content) &&\n isBoolean(value.truncated) &&\n isBoolean(value.hasMoreAbove) &&\n isBoolean(value.hasMoreBelow)\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 isDiffContextSource(value: unknown): value is DiffContextSource {\n if (!isRecord(value) || !isString(value.mode)) {\n return false;\n }\n switch (value.mode) {\n case 'turn':\n return true;\n case 'commit':\n return isString(value.sha);\n case 'range':\n return isString(value.fromSha) && isString(value.toSha);\n default:\n return false;\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 if (!isRecord(value)) {\n return false;\n }\n if (value.kind === 'general') {\n return isString(value.id) && isString(value.body) && isString(value.createdAt);\n }\n return (\n isString(value.id) &&\n (value.kind === undefined || value.kind === 'line') &&\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 isSourcePeekMatchReason(value: unknown): value is SourcePeekMatchReason {\n return isOneOf(value, SOURCE_PEEK_MATCH_REASONS);\n}\n\nfunction isOpenFileScope(value: unknown): value is OpenFileScope {\n return isOneOf(value, OPEN_FILE_SCOPES);\n}\n\nfunction isOpenFileTarget(value: unknown): value is OpenFileTarget {\n return isOneOf(value, OPEN_FILE_TARGETS);\n}\n\nfunction isOpenFileTargetInfo(value: unknown): value is OpenFileTargetInfo {\n return isRecord(value) && isOpenFileTarget(value.target) && isString(value.label);\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 isPositiveInteger(value: unknown): value is number {\n return isNumber(value) && Number.isInteger(value) && value > 0;\n}\n\nfunction isNonNegativeInteger(value: unknown): value is number {\n return isNumber(value) && Number.isInteger(value) && value >= 0;\n}\n\nfunction isIdentifier(value: unknown): value is string {\n return isString(value) && /^[A-Za-z_$][\\w$]*$/.test(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","export const DEFAULT_DAEMON_IDLE_TIMEOUT_MS = 120000;\n\nexport interface IdleScheduler {\n cancel: () => void;\n schedule: () => void;\n}\n\ninterface IdleSchedulerOptions {\n timeoutMs: number;\n hasLiveClients: () => boolean;\n isShuttingDown: () => boolean;\n shutdown: () => void | Promise<void>;\n}\n\nexport function normalizeIdleTimeoutMs(\n rawValue = process.env.GLOSS_IDLE_TIMEOUT_MS,\n warn: (message: string) => void = (message) => process.stderr.write(message)\n): number {\n if (rawValue === undefined) {\n return DEFAULT_DAEMON_IDLE_TIMEOUT_MS;\n }\n\n const parsed = Number(rawValue);\n if (Number.isFinite(parsed) && parsed > 0) {\n return parsed;\n }\n\n warn(\n `Warning: GLOSS_IDLE_TIMEOUT_MS=${JSON.stringify(rawValue)} is not positive; using ${DEFAULT_DAEMON_IDLE_TIMEOUT_MS}.\\n`\n );\n return DEFAULT_DAEMON_IDLE_TIMEOUT_MS;\n}\n\nexport function createIdleScheduler(options: IdleSchedulerOptions): IdleScheduler {\n let idleTimer: NodeJS.Timeout | null = null;\n\n const cancel = () => {\n if (idleTimer) {\n clearTimeout(idleTimer);\n idleTimer = null;\n }\n };\n\n const schedule = () => {\n if (options.isShuttingDown()) {\n return;\n }\n\n if (options.hasLiveClients()) {\n cancel();\n return;\n }\n\n if (!idleTimer) {\n idleTimer = setTimeout(() => {\n idleTimer = null;\n void shutdownIfIdle();\n }, options.timeoutMs);\n }\n };\n\n const shutdownIfIdle = async () => {\n if (options.isShuttingDown()) {\n return;\n }\n if (options.hasLiveClients()) {\n schedule();\n return;\n }\n await options.shutdown();\n };\n\n return { cancel, schedule };\n}\n","import { readFile, realpath, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Context } from 'hono';\nimport { Hono } from 'hono';\nimport { streamSSE } from 'hono/streaming';\nimport { countCommentFiles } from '../shared/comments';\nimport { formatError, isFileNotFound } from '../shared/errors';\nimport { captureCommitRangeDiff, captureDiffContext } from '../shared/git-diff';\nimport type { JsonValue } from '../shared/json';\nimport { packageVersion } from '../shared/paths';\nimport { isResolvableReviewStatus } from '../shared/reviews';\nimport type {\n ClearReviewsRequest,\n CommitRangeDiffResponse,\n CreateReviewResponse,\n CreateReviewTurnResponse,\n DiffContextRequest,\n DiffContextSource,\n DiffFile,\n DiffPayload,\n FileContentResponse,\n HealthResponse,\n ListReviewsResponse,\n OpenFileResponse,\n OpenFileTargetsResponse,\n OpenResult,\n ResolutionRequest,\n ReviewEvent,\n ReviewMeta,\n ReviewTurnSummary,\n SourcePeekRangeRequest,\n SourcePeekRequest,\n SubmitReviewRequest\n} from '../shared/types';\nimport { DIFF_CONTEXT_MAX_LINES } from '../shared/types';\nimport {\n isClearReviewsRequest,\n isCommitRangeDiffRequest,\n isDiffContextRequest,\n isDiffPayload,\n isFileContentRequest,\n isOpenFileRequest,\n isResolutionRequest,\n isSourcePeekRangeRequest,\n isSourcePeekRequest,\n isSubmitReviewRequest,\n type JsonGuard,\n parseJsonValue\n} from '../shared/validation';\nimport { availableOpenFileTargets, openLocalPath } from './local-open';\nimport { readSourcePeekRange, resolveSourcePeek } from './source-peek';\nimport { reviewStore } from './store';\n\nconst webRoot = fileURLToPath(new URL('../web', import.meta.url));\nconst eventStreamHeartbeatMs = 15_000;\n\ninterface AppOptions {\n onReviewActivity?: () => void;\n registerEventStream?: (close: () => void) => () => void;\n health?: () => Partial<Pick<HealthResponse, 'connections' | 'cwd' | 'daemonPath' | 'stateDir'>>;\n}\n\nconst mimeTypes: Record<string, string> = {\n '.css': 'text/css; charset=utf-8',\n '.html': 'text/html; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.map': 'application/json; charset=utf-8',\n '.png': 'image/png',\n '.sh': 'text/x-shellscript; charset=utf-8',\n '.svg': 'image/svg+xml'\n};\n\nexport function createApp(origin: string, options: AppOptions = {}): Hono {\n const app = new Hono();\n\n app.get('/api/health', async (c) => {\n const reviews = await reviewStore.list();\n const response: HealthResponse = {\n ok: true,\n version: packageVersion,\n activeReviews: reviews.filter((review) => review.status === 'pending').length,\n ...options.health?.()\n };\n return c.json(response);\n });\n\n app.get('/api/open-targets', async (c) => {\n const response: OpenFileTargetsResponse = { targets: await availableOpenFileTargets() };\n return c.json(response);\n });\n\n app.get('/api/reviews', async (c) => {\n const response: ListReviewsResponse = { reviews: await reviewStore.list() };\n return c.json(response);\n });\n\n app.post('/api/maintenance/clear-reviews', async (c) => {\n const parsed = await readJsonBody(c, isClearReviewsRequest, 'clear reviews request');\n if (!parsed.ok) {\n return parsed.response;\n }\n const body: ClearReviewsRequest = parsed.body;\n const result = await reviewStore.clearReviewArtifacts(body);\n return c.json(result);\n });\n\n app.post('/api/reviews', async (c) => {\n const parsed = await readJsonBody(c, isDiffPayload, 'review diff');\n if (!parsed.ok) {\n return parsed.response;\n }\n const diff = parsed.body;\n const record = await reviewStore.create(diff);\n const response: CreateReviewResponse = {\n meta: record.meta,\n turn: activeTurnSummary(record.meta),\n url: `${origin}/review/${record.meta.id}`\n };\n options.onReviewActivity?.();\n return c.json(response, 201);\n });\n\n app.post('/api/reviews/:id/turns', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isDiffPayload, 'review diff');\n if (!parsed.ok) {\n return parsed.response;\n }\n try {\n const { record, turn, reused } = await reviewStore.appendTurn(id, parsed.body);\n const response: CreateReviewTurnResponse = {\n meta: record.meta,\n turn: turnSummary(record.meta, turn.id),\n url: `${origin}/review/${id}`,\n reused\n };\n options.onReviewActivity?.();\n return c.json(response);\n } catch (error) {\n return c.json({ error: formatError(error) }, 409);\n }\n });\n\n app.get('/api/reviews/:id', async (c) => {\n const record = await reviewStore.get(c.req.param('id'));\n if (!record) {\n return c.json({ error: 'review not found' }, 404);\n }\n return c.json(record);\n });\n\n app.get('/api/reviews/:id/turns/:turnId', async (c) => {\n const turn = await reviewStore.getTurn(c.req.param('id'), c.req.param('turnId'));\n if (!turn) {\n return c.json({ error: 'turn not found' }, 404);\n }\n return c.json(turn);\n });\n\n app.get('/api/reviews/:id/feedback', async (c) => {\n const feedback = await reviewStore.feedback(c.req.param('id'));\n if (!feedback) {\n return c.json({ error: 'feedback not found' }, 404);\n }\n return c.json(feedback);\n });\n\n app.get('/api/reviews/:id/events', async (c) => {\n const id = c.req.param('id');\n const record = await reviewStore.get(id);\n if (!record) {\n return c.json({ error: 'review not found' }, 404);\n }\n\n return streamSSE(c, async (stream) => {\n let closed = false;\n let pending: Promise<void> = Promise.resolve();\n let cleanup: (() => void) | null = null;\n let close: (() => void) | null = null;\n let unregisterEventStream: (() => void) | null = null;\n const closedPromise = new Promise<void>((resolve) => {\n close = () => {\n if (closed) {\n return;\n }\n closed = true;\n cleanup?.();\n resolve();\n };\n });\n unregisterEventStream = options.registerEventStream?.(() => close?.()) ?? null;\n const send = (event: ReviewEvent) => {\n pending = pending\n .then(() => stream.writeSSE({ data: JSON.stringify(event) }))\n .then(() => {\n if (event.type === 'review.cancelled') {\n close?.();\n }\n });\n void pending.catch(() => close?.());\n };\n const unsubscribe = reviewStore.subscribe(id, send);\n const heartbeat = setInterval(() => {\n pending = pending.then(async () => {\n await stream.write(`: keep-alive ${Date.now()}\\n\\n`);\n });\n void pending.catch(() => close?.());\n }, eventStreamHeartbeatMs);\n cleanup = () => {\n clearInterval(heartbeat);\n unsubscribe();\n unregisterEventStream?.();\n unregisterEventStream = null;\n };\n stream.onAbort(() => close?.());\n\n send({ type: 'review.opened', reviewId: id });\n if (isResolvableReviewStatus(record.meta.status) && record.feedback) {\n send({\n type: 'review.submitted',\n reviewId: id,\n turnId: record.meta.activeTurnId,\n turnIndex: record.meta.turns?.find((turn) => turn.id === record.meta.activeTurnId)?.index,\n counts: {\n files: countCommentFiles(record.feedback.comments),\n comments: record.feedback.comments.length\n }\n });\n }\n await closedPromise;\n });\n });\n\n app.post('/api/reviews/:id/submit', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isSubmitReviewRequest, 'submit review request');\n if (!parsed.ok) {\n return parsed.response;\n }\n const body: SubmitReviewRequest = parsed.body;\n let submitted: Awaited<ReturnType<typeof reviewStore.submit>>;\n try {\n submitted = await reviewStore.submit(id, body.comments, body.reviewScope);\n } catch (error) {\n return c.json({ error: formatError(error) }, 409);\n }\n const { feedbackPath, markdownPath, turn } = submitted;\n const response: OpenResult = {\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n url: `${origin}/review/${id}`,\n files: turn.diff.files.length,\n comments: body.comments.length,\n artifactDir: turn.artifactDir,\n feedbackPath,\n markdownPath\n };\n options.onReviewActivity?.();\n return c.json(response);\n });\n\n app.post('/api/reviews/:id/commits/range', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isCommitRangeDiffRequest, 'commit range diff request');\n if (!parsed.ok) {\n return parsed.response;\n }\n\n const requestedTurnId = parsed.body.turnId;\n const turn = requestedTurnId ? await reviewStore.getTurn(id, requestedTurnId) : null;\n if (requestedTurnId && !turn) {\n return c.json({ error: 'turn not found' }, 404);\n }\n const diffPayload = turn?.diff ?? existing.diff;\n const commitDiffs = diffPayload.commitDiffs ?? [];\n if (commitDiffs.length === 0) {\n return c.json({ error: 'commit ranges are only available for branch reviews' }, 409);\n }\n\n const { fromSha, toSha } = parsed.body;\n const fromIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === fromSha);\n const toIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === toSha);\n if (fromIndex < 0 || toIndex < 0) {\n return c.json({ error: 'commit range must use commits from this review' }, 404);\n }\n if (fromIndex > toIndex) {\n return c.json({ error: 'fromSha must come before or match toSha' }, 400);\n }\n\n const diff =\n fromSha === toSha\n ? commitDiffs[fromIndex]\n : await captureCommitRangeDiff(fromSha, toSha, diffPayload.cwd);\n const response: CommitRangeDiffResponse = {\n fromSha,\n toSha,\n stats: diff.stats,\n rawDiff: diff.rawDiff,\n files: diff.files\n };\n return c.json(response);\n });\n\n app.post('/api/reviews/:id/files/context', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isDiffContextRequest, 'diff context request');\n if (!parsed.ok) {\n return parsed.response;\n }\n\n const body: DiffContextRequest = parsed.body;\n if (body.lineCount > DIFF_CONTEXT_MAX_LINES) {\n return c.json({ error: `lineCount must be ${DIFF_CONTEXT_MAX_LINES} or less` }, 400);\n }\n\n const turn = body.turnId ? await reviewStore.getTurn(id, body.turnId) : null;\n if (body.turnId && !turn) {\n return c.json({ error: 'turn not found' }, 404);\n }\n const diffPayload = turn?.diff ?? existing.diff;\n const repoRoot = path.resolve(diffPayload.cwd);\n const pathError =\n validateContextPath(repoRoot, body.filePath, 'filePath') ??\n (body.oldPath ? validateContextPath(repoRoot, body.oldPath, 'oldPath') : null);\n if (pathError) {\n return c.json({ error: pathError }, 400);\n }\n\n const source = await resolveContextSource(diffPayload, body.source);\n if (!source.ok) {\n return c.json({ error: source.error }, source.status);\n }\n\n const reviewFile = source.files.find((file) => file.path === body.filePath);\n if (!reviewFile) {\n return c.json({ error: 'file is not part of this review context' }, 404);\n }\n if ((reviewFile.oldPath ?? null) !== body.oldPath) {\n return c.json({ error: 'oldPath does not match the reviewed file' }, 400);\n }\n if (reviewFile.isBinary) {\n return c.json({ error: 'binary file context is not available' }, 409);\n }\n\n try {\n const response = await captureDiffContext({\n filePath: body.filePath,\n oldPath: body.oldPath,\n oldRef: source.oldRef,\n newRef: source.newRef,\n oldStart: body.oldStart,\n newStart: body.newStart,\n lineCount: body.lineCount,\n repoRoot\n });\n return c.json(response);\n } catch (error) {\n return c.json({ error: `context is unavailable: ${formatError(error)}` }, 409);\n }\n });\n\n app.post('/api/reviews/:id/source-peek', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isSourcePeekRequest, 'source peek request');\n if (!parsed.ok) {\n return parsed.response;\n }\n\n const body: SourcePeekRequest = parsed.body;\n const turn = body.turnId ? await reviewStore.getTurn(id, body.turnId) : null;\n if (body.turnId && !turn) {\n return c.json({ error: 'turn not found' }, 404);\n }\n const diffPayload = turn?.diff ?? existing.diff;\n const repoRoot = path.resolve(diffPayload.cwd);\n const pathError =\n validateContextPath(repoRoot, body.filePath, 'filePath') ??\n (body.oldPath ? validateContextPath(repoRoot, body.oldPath, 'oldPath') : null);\n if (pathError) {\n return c.json({ error: pathError }, 400);\n }\n\n const source = await resolveContextSource(diffPayload, body.source);\n if (!source.ok) {\n return c.json({ error: source.error }, source.status);\n }\n\n const reviewFile = source.files.find((file) => file.path === body.filePath);\n if (!reviewFile) {\n return c.json({ error: 'file is not part of this review context' }, 404);\n }\n if ((reviewFile.oldPath ?? null) !== body.oldPath) {\n return c.json({ error: 'oldPath does not match the reviewed file' }, 400);\n }\n if (reviewFile.isBinary) {\n return c.json({ error: 'binary file source peek is not available' }, 409);\n }\n if (body.side === 'L' && reviewFile.isNew) {\n return c.json({ error: 'new files do not have an old-side source' }, 409);\n }\n if (body.side === 'R' && reviewFile.isDeleted) {\n return c.json({ error: 'deleted files do not have a new-side source' }, 409);\n }\n\n const sourceFilePath = body.side === 'L' ? (body.oldPath ?? body.filePath) : body.filePath;\n const sourceRef = body.side === 'L' ? source.oldRef : source.newRef;\n try {\n return c.json(\n await resolveSourcePeek({\n repoRoot,\n sourceFilePath,\n sourceRef,\n symbol: body.symbol,\n line: body.line,\n column: body.column\n })\n );\n } catch (error) {\n return c.json({ error: `source peek unavailable: ${formatError(error)}` }, 404);\n }\n });\n\n app.post('/api/reviews/:id/source-peek/range', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isSourcePeekRangeRequest, 'source peek range request');\n if (!parsed.ok) {\n return parsed.response;\n }\n\n const body: SourcePeekRangeRequest = parsed.body;\n const turn = body.turnId ? await reviewStore.getTurn(id, body.turnId) : null;\n if (body.turnId && !turn) {\n return c.json({ error: 'turn not found' }, 404);\n }\n const diffPayload = turn?.diff ?? existing.diff;\n const repoRoot = path.resolve(diffPayload.cwd);\n const pathError = validateContextPath(repoRoot, body.filePath, 'filePath');\n if (pathError) {\n return c.json({ error: pathError }, 400);\n }\n\n const source = await resolveContextSource(diffPayload, body.source);\n if (!source.ok) {\n return c.json({ error: source.error }, source.status);\n }\n\n const sourceRef = body.side === 'L' ? source.oldRef : source.newRef;\n try {\n return c.json(\n await readSourcePeekRange({\n repoRoot,\n sourceFilePath: body.filePath,\n sourceRef,\n startLine: body.startLine,\n lineCount: body.lineCount\n })\n );\n } catch (error) {\n return c.json({ error: `source range unavailable: ${formatError(error)}` }, 404);\n }\n });\n\n app.post('/api/reviews/:id/files/content', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isFileContentRequest, 'file content request');\n if (!parsed.ok) {\n return parsed.response;\n }\n\n const { filePath, scope = 'review', turnId } = parsed.body;\n if (!filePath || filePath.includes('\\0') || path.isAbsolute(filePath)) {\n return c.json({ error: 'filePath must be a repo-relative path' }, 400);\n }\n\n const repoRoot = path.resolve(existing.diff.cwd);\n const requestedAbsolutePath = path.resolve(repoRoot, filePath);\n if (!isPathWithin(repoRoot, requestedAbsolutePath)) {\n return c.json({ error: 'filePath must stay within the review cwd' }, 400);\n }\n\n const turn = turnId ? await reviewStore.getTurn(id, turnId) : null;\n if (turnId && !turn) {\n return c.json({ error: 'turn not found' }, 404);\n }\n\n if (scope === 'review') {\n const diffPayload = turn?.diff ?? existing.diff;\n const reviewFiles = [\n ...diffPayload.files,\n ...(diffPayload.commitDiffs ?? []).flatMap((commitDiff) => commitDiff.files)\n ].filter((file) => file.path === filePath);\n if (reviewFiles.length === 0) {\n return c.json({ error: 'file is not part of this review' }, 404);\n }\n if (reviewFiles.every((file) => file.isDeleted)) {\n return c.json({ error: 'deleted files cannot be copied' }, 409);\n }\n if (reviewFiles.some((file) => file.isBinary)) {\n return c.json({ error: 'binary file contents cannot be copied' }, 409);\n }\n }\n\n let realRepoRoot: string;\n let realFilePath: string;\n try {\n [realRepoRoot, realFilePath] = await Promise.all([\n realpath(repoRoot),\n realpath(requestedAbsolutePath)\n ]);\n } catch (error) {\n if (isFileNotFound(error)) {\n return c.json({ error: 'file no longer exists on disk' }, 404);\n }\n throw error;\n }\n\n if (!isPathWithin(realRepoRoot, realFilePath)) {\n return c.json({ error: 'filePath must stay within the review cwd' }, 400);\n }\n\n const fileStats = await stat(realFilePath);\n if (!fileStats.isFile()) {\n return c.json({ error: 'path is not a file' }, 409);\n }\n\n const response: FileContentResponse = {\n content: await readFile(realFilePath, 'utf8'),\n filePath\n };\n return c.json(response);\n });\n\n app.post('/api/reviews/:id/files/open', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isOpenFileRequest, 'open file request');\n if (!parsed.ok) {\n return parsed.response;\n }\n\n const { filePath, scope = 'review', target, turnId } = parsed.body;\n if (!filePath || filePath.includes('\\0') || path.isAbsolute(filePath)) {\n return c.json({ error: 'filePath must be a repo-relative path' }, 400);\n }\n\n const repoRoot = path.resolve(existing.diff.cwd);\n const requestedAbsolutePath = path.resolve(repoRoot, filePath);\n if (!isPathWithin(repoRoot, requestedAbsolutePath)) {\n return c.json({ error: 'filePath must stay within the review cwd' }, 400);\n }\n\n const turn = turnId ? await reviewStore.getTurn(id, turnId) : null;\n if (turnId && !turn) {\n return c.json({ error: 'turn not found' }, 404);\n }\n\n if (scope === 'review') {\n const diffPayload = turn?.diff ?? existing.diff;\n const reviewFiles = [\n ...diffPayload.files,\n ...(diffPayload.commitDiffs ?? []).flatMap((commitDiff) => commitDiff.files)\n ].filter((file) => file.path === filePath);\n if (reviewFiles.length === 0) {\n return c.json({ error: 'file is not part of this review' }, 404);\n }\n if (reviewFiles.every((file) => file.isDeleted)) {\n return c.json({ error: 'deleted files cannot be opened locally' }, 409);\n }\n }\n\n let realRepoRoot: string;\n let realFilePath: string;\n try {\n [realRepoRoot, realFilePath] = await Promise.all([\n realpath(repoRoot),\n realpath(requestedAbsolutePath)\n ]);\n } catch (error) {\n if (isFileNotFound(error)) {\n return c.json({ error: 'file no longer exists on disk' }, 404);\n }\n throw error;\n }\n\n if (!isPathWithin(realRepoRoot, realFilePath)) {\n return c.json({ error: 'filePath must stay within the review cwd' }, 400);\n }\n\n const fileStats = await stat(realFilePath);\n if (!fileStats.isFile()) {\n return c.json({ error: 'path is not a file' }, 409);\n }\n\n try {\n target ? await openLocalPath(realFilePath, target) : await openLocalPath(realFilePath);\n } catch (error) {\n return c.json({ error: `could not open file: ${formatError(error)}` }, 500);\n }\n\n const response: OpenFileResponse = { ok: true, path: realFilePath };\n return c.json(response);\n });\n\n app.post('/api/reviews/:id/resolved', async (c) => {\n const id = c.req.param('id');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isResolutionRequest, 'resolution request');\n if (!parsed.ok) {\n return parsed.response;\n }\n const body: ResolutionRequest = parsed.body;\n try {\n const result = await reviewStore.markResolved(id, body.summary, body.turn);\n options.onReviewActivity?.();\n return c.json(result);\n } catch (error) {\n return c.json({ error: formatError(error) }, statusForStoreError(error));\n }\n });\n\n app.post('/api/reviews/:id/comments/:commentId/resolved', async (c) => {\n const id = c.req.param('id');\n const commentId = c.req.param('commentId');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n const parsed = await readJsonBody(c, isResolutionRequest, 'resolution request');\n if (!parsed.ok) {\n return parsed.response;\n }\n const body: ResolutionRequest = parsed.body;\n try {\n const result = await reviewStore.resolveComment(id, commentId, body.summary);\n options.onReviewActivity?.();\n return c.json(result);\n } catch (error) {\n return c.json({ error: formatError(error) }, statusForStoreError(error));\n }\n });\n\n app.delete('/api/reviews/:id/comments/:commentId/resolved', async (c) => {\n const id = c.req.param('id');\n const commentId = c.req.param('commentId');\n const existing = await reviewStore.get(id);\n if (!existing) {\n return c.json({ error: 'review not found' }, 404);\n }\n try {\n const result = await reviewStore.reopenComment(id, commentId);\n options.onReviewActivity?.();\n return c.json(result);\n } catch (error) {\n return c.json({ error: formatError(error) }, statusForStoreError(error));\n }\n });\n\n app.get('/logo.svg', serveRootFile('logo.svg', mimeTypes['.svg']));\n app.get('/logo-mark.svg', serveRootFile('logo-mark.svg', mimeTypes['.svg']));\n app.get('/og.png', serveRootFile('og.png', mimeTypes['.png']));\n app.get('/install.sh', serveRootFile('install.sh', mimeTypes['.sh']));\n app.get('/setup.md', serveRootFile('setup.md', 'text/markdown; charset=utf-8'));\n app.get('/prompt.md', serveRootFile('prompt.md', 'text/markdown; charset=utf-8'));\n app.get('/assets/*', serveAsset);\n app.get('/setup', serveIndex);\n app.get('/setup/', serveIndex);\n app.get('/review/:id', serveIndex);\n app.get('/', serveIndex);\n\n return app;\n}\n\nasync function serveAsset(c: Context) {\n const requestPath = new URL(c.req.url).pathname.replace(/^\\/assets\\//, '');\n const normalized = path.normalize(requestPath).replace(/^(\\.\\.(\\/|\\\\|$))+/, '');\n const assetPath = path.join(webRoot, 'assets', normalized);\n try {\n const body = await readFile(assetPath);\n return new Response(body, {\n headers: {\n 'content-type': mimeTypes[path.extname(assetPath)] ?? 'application/octet-stream'\n }\n });\n } catch (error) {\n if (!isFileNotFound(error)) {\n throw error;\n }\n return new Response('Not found', { status: 404 });\n }\n}\n\nasync function serveIndex() {\n try {\n const body = await readFile(path.join(webRoot, 'index.html'));\n return new Response(body, {\n headers: { 'content-type': 'text/html; charset=utf-8' }\n });\n } catch (error) {\n if (!isFileNotFound(error)) {\n throw error;\n }\n return new Response('Gloss web assets are missing. Run pnpm build.', { status: 500 });\n }\n}\n\nfunction serveRootFile(fileName: string, contentType: string) {\n return async () => {\n try {\n const body = await readFile(path.join(webRoot, fileName));\n return new Response(body, {\n headers: { 'content-type': contentType }\n });\n } catch (error) {\n if (!isFileNotFound(error)) {\n throw error;\n }\n return new Response(`${fileName} is missing. Run pnpm build.`, { status: 404 });\n }\n };\n}\n\nasync function readJsonBody<T>(\n c: Context,\n guard: JsonGuard<T>,\n label: string\n): Promise<{ ok: true; body: T } | { ok: false; response: Response }> {\n let body: JsonValue;\n try {\n body = await c.req.json();\n } catch (error) {\n return {\n ok: false,\n response: c.json({ error: `invalid JSON body: ${formatError(error)}` }, 400)\n };\n }\n\n try {\n return { ok: true, body: parseJsonValue(body, guard, label) };\n } catch (error) {\n return {\n ok: false,\n response: c.json({ error: formatError(error) }, 400)\n };\n }\n}\n\nfunction isPathWithin(parentPath: string, childPath: string): boolean {\n const relative = path.relative(parentPath, childPath);\n return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));\n}\n\ntype ContextSourceResolution =\n | {\n ok: true;\n files: DiffFile[];\n oldRef: string | null;\n newRef: string | null;\n }\n | { ok: false; status: 400 | 404 | 409; error: string };\n\nasync function resolveContextSource(\n diffPayload: DiffPayload,\n source: DiffContextSource\n): Promise<ContextSourceResolution> {\n if (source.mode === 'turn') {\n return {\n ok: true,\n files: diffPayload.files,\n oldRef: diffPayload.base.sha,\n newRef: diffPayload.scope.comparison.sha\n };\n }\n\n const commitDiffs = diffPayload.commitDiffs ?? [];\n if (commitDiffs.length === 0) {\n return {\n ok: false,\n status: 409,\n error: 'commit context is only available for branch reviews'\n };\n }\n\n if (source.mode === 'commit') {\n const commitDiff = commitDiffs.find((diff) => diff.commit.sha === source.sha);\n if (!commitDiff) {\n return { ok: false, status: 404, error: 'commit must be part of this review' };\n }\n return {\n ok: true,\n files: commitDiff.files,\n oldRef: `${source.sha}^`,\n newRef: source.sha\n };\n }\n\n const fromIndex = commitDiffs.findIndex((diff) => diff.commit.sha === source.fromSha);\n const toIndex = commitDiffs.findIndex((diff) => diff.commit.sha === source.toSha);\n if (fromIndex < 0 || toIndex < 0) {\n return { ok: false, status: 404, error: 'commit range must use commits from this review' };\n }\n if (fromIndex > toIndex) {\n return { ok: false, status: 400, error: 'fromSha must come before or match toSha' };\n }\n\n const rangeDiff =\n source.fromSha === source.toSha\n ? commitDiffs[fromIndex]\n : await captureCommitRangeDiff(source.fromSha, source.toSha, diffPayload.cwd);\n return {\n ok: true,\n files: rangeDiff.files,\n oldRef: `${source.fromSha}^`,\n newRef: source.toSha\n };\n}\n\nfunction validateContextPath(repoRoot: string, filePath: string, label: string): string | null {\n if (!filePath || filePath.includes('\\0') || path.isAbsolute(filePath)) {\n return `${label} must be a repo-relative path`;\n }\n\n const requestedAbsolutePath = path.resolve(repoRoot, filePath);\n if (!isPathWithin(repoRoot, requestedAbsolutePath)) {\n return `${label} must stay within the review cwd`;\n }\n\n return null;\n}\n\nfunction activeTurnSummary(meta: ReviewMeta): ReviewTurnSummary {\n if (!meta.activeTurnId) {\n throw new Error(`Review ${meta.id} has no active turn`);\n }\n return turnSummary(meta, meta.activeTurnId);\n}\n\nfunction turnSummary(meta: ReviewMeta, turnId: string): ReviewTurnSummary {\n const summary = meta.turns?.find((turn) => turn.id === turnId);\n if (!summary) {\n throw new Error(`Review ${meta.id} is missing turn ${turnId}`);\n }\n return summary;\n}\n\nfunction statusForStoreError(error: unknown): 404 | 409 {\n return /not found/i.test(formatError(error)) ? 404 : 409;\n}\n","import type {\n Comment,\n FeedbackBundle,\n LineComment,\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 isLineComment(comment: Comment): comment is LineComment {\n return comment.kind === undefined || comment.kind === 'line';\n}\n\nexport function compareCommentsByLocation(a: Comment, b: Comment): number {\n const aIsLine = isLineComment(a);\n const bIsLine = isLineComment(b);\n if (!aIsLine || !bIsLine) {\n if (aIsLine !== bIsLine) {\n return aIsLine ? 1 : -1;\n }\n return a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id);\n }\n\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: Comment[]): number {\n const filePaths = new Set<string>();\n for (const comment of comments) {\n if (isLineComment(comment)) {\n filePaths.add(comment.filePath);\n }\n }\n return filePaths.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 { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { execa } from 'execa';\nimport { parseUnifiedDiff } from './diff-parser';\nimport { summarizeDiffFiles } from './diff-stats';\nimport { sortDiffFiles } from './file-order';\nimport type { CommitDiff, DiffContextResponse, DiffLine } from './types';\n\nconst DIFF_ARGS = ['diff', '--no-color', '--find-renames', '--find-copies'];\n\nasync function git(args: string[], cwd: string): Promise<string> {\n const result = await execa('git', args, { cwd });\n return result.stdout.trimEnd();\n}\n\nexport async function captureCommitRangeDiff(\n fromSha: string,\n toSha: string,\n repoRoot: string\n): Promise<Pick<CommitDiff, 'stats' | 'rawDiff' | 'files'>> {\n const rawDiff = await git([...DIFF_ARGS, `${fromSha}^`, toSha, '--'], repoRoot);\n const files = sortDiffFiles(parseUnifiedDiff(rawDiff));\n return {\n stats: summarizeDiffFiles(files),\n rawDiff,\n files\n };\n}\n\nexport async function captureDiffContext({\n filePath,\n lineCount,\n newRef,\n oldPath,\n oldRef,\n newStart,\n oldStart,\n repoRoot\n}: {\n filePath: string;\n oldPath: string | null;\n oldRef: string | null;\n newRef: string | null;\n oldStart: number;\n newStart: number;\n lineCount: number;\n repoRoot: string;\n}): Promise<DiffContextResponse> {\n const [oldLines, newLines] = await Promise.all([\n oldRef && oldPath ? readRevisionLines(repoRoot, oldRef, oldPath).catch(() => null) : null,\n newRef === null\n ? readWorkingTreeLines(repoRoot, filePath).catch(() => null)\n : readRevisionLines(repoRoot, newRef, filePath).catch(() => null)\n ]);\n\n if (!oldLines && !newLines) {\n throw new Error(`Could not read ${filePath} from either side of the diff`);\n }\n\n const lines: DiffLine[] = [];\n for (let index = 0; index < lineCount; index += 1) {\n const oldLine = oldStart + index;\n const newLine = newStart + index;\n const content = newLines?.[newLine - 1] ?? oldLines?.[oldLine - 1];\n if (content === undefined) {\n continue;\n }\n lines.push({\n type: 'context',\n oldLine,\n newLine,\n content\n });\n }\n\n return {\n filePath,\n oldStart,\n newStart,\n lines\n };\n}\n\nasync function readRevisionLines(\n repoRoot: string,\n ref: string,\n filePath: string\n): Promise<string[]> {\n const result = await execa('git', ['show', `${ref}:${filePath}`], { cwd: repoRoot });\n return splitFileLines(result.stdout);\n}\n\nasync function readWorkingTreeLines(repoRoot: string, filePath: string): Promise<string[]> {\n return splitFileLines(await readFile(path.resolve(repoRoot, filePath), 'utf8'));\n}\n\nfunction splitFileLines(contents: string): string[] {\n const lines = contents.replace(/\\r\\n/g, '\\n').split('\\n');\n if (lines.at(-1) === '') {\n lines.pop();\n }\n return lines;\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 type { DiffFile } from './types';\n\nexport function compareFilePaths(\n leftPath: string,\n rightPath: string,\n leftTieBreaker = '',\n rightTieBreaker = ''\n): number {\n return (\n leftPath.localeCompare(rightPath, undefined, { sensitivity: 'base' }) ||\n leftPath.localeCompare(rightPath) ||\n leftTieBreaker.localeCompare(rightTieBreaker, undefined, { sensitivity: 'base' }) ||\n leftTieBreaker.localeCompare(rightTieBreaker)\n );\n}\n\nfunction compareDiffFiles(left: DiffFile, right: DiffFile): number {\n return compareFilePaths(left.path, right.path, left.oldPath ?? '', right.oldPath ?? '');\n}\n\nexport function sortDiffFiles<T extends DiffFile>(files: T[]): T[] {\n return files.toSorted(compareDiffFiles);\n}\n","import type { ReviewStatus } from './types';\n\nexport function isResolvableReviewStatus(status: ReviewStatus): boolean {\n return status === 'submitted' || status === 'resolved';\n}\n","import { execFile } from 'node:child_process';\nimport { access } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport path from 'node:path';\nimport { promisify } from 'node:util';\nimport open from 'open';\nimport type { OpenFileTarget, OpenFileTargetInfo } from '../shared/types';\n\nconst execFileAsync = promisify(execFile);\n\nconst applicationRoots = [\n '/Applications',\n path.join(homedir(), 'Applications'),\n '/System/Applications',\n '/System/Applications/Utilities'\n];\n\ninterface OpenFileTargetDescriptor extends OpenFileTargetInfo {\n appName?: string | readonly string[];\n opensFolder?: boolean;\n}\n\nconst openFileTargetDescriptors: OpenFileTargetDescriptor[] = [\n { appName: 'Visual Studio Code', label: 'VS Code', target: 'vscode' },\n {\n appName: ['Visual Studio Code - Insiders', 'Code - Insiders'],\n label: 'VS Code Insiders',\n target: 'vscode-insiders'\n },\n { appName: 'VSCodium', label: 'VSCodium', target: 'vscodium' },\n { appName: 'Cursor', label: 'Cursor', target: 'cursor' },\n { appName: 'Sublime Text', label: 'Sublime Text', target: 'sublime' },\n { appName: 'Zed', label: 'Zed', target: 'zed' },\n { appName: 'Windsurf', label: 'Windsurf', target: 'windsurf' },\n { appName: 'WebStorm', label: 'WebStorm', target: 'webstorm' },\n {\n appName: ['IntelliJ IDEA', 'IntelliJ IDEA Ultimate', 'IntelliJ IDEA CE'],\n label: 'IntelliJ IDEA',\n target: 'intellij'\n },\n { appName: ['PyCharm', 'PyCharm CE'], label: 'PyCharm', target: 'pycharm' },\n { appName: 'GoLand', label: 'GoLand', target: 'goland' },\n { appName: 'PhpStorm', label: 'PhpStorm', target: 'phpstorm' },\n { appName: 'RubyMine', label: 'RubyMine', target: 'rubymine' },\n { appName: 'CLion', label: 'CLion', target: 'clion' },\n { appName: 'DataGrip', label: 'DataGrip', target: 'datagrip' },\n { appName: 'Android Studio', label: 'Android Studio', target: 'android-studio' },\n { appName: 'Fleet', label: 'Fleet', target: 'fleet' },\n { appName: 'Neovide', label: 'Neovide', target: 'neovide' },\n { appName: 'MacVim', label: 'MacVim', target: 'macvim' },\n { appName: 'Emacs', label: 'Emacs', target: 'emacs' },\n { appName: 'Lapce', label: 'Lapce', target: 'lapce' },\n { appName: 'TextMate', label: 'TextMate', target: 'textmate' },\n { appName: 'BBEdit', label: 'BBEdit', target: 'bbedit' },\n { appName: 'CotEditor', label: 'CotEditor', target: 'coteditor' },\n { appName: 'Nova', label: 'Nova', target: 'nova' },\n { appName: 'TextEdit', label: 'TextEdit', target: 'textedit' },\n { appName: 'Terminal', label: 'Terminal', opensFolder: true, target: 'terminal' },\n { appName: ['iTerm', 'iTerm2'], label: 'iTerm2', opensFolder: true, target: 'iterm2' },\n { appName: 'Ghostty', label: 'Ghostty', opensFolder: true, target: 'ghostty' },\n { appName: 'Xcode', label: 'Xcode', target: 'xcode' },\n { label: 'Default app', target: 'default' },\n { label: 'Open in folder', opensFolder: true, target: 'folder' }\n];\n\nconst openFileTargetDescriptorByTarget = new Map(\n openFileTargetDescriptors.map((descriptor) => [descriptor.target, descriptor])\n);\n\nexport async function availableOpenFileTargets(): Promise<OpenFileTargetInfo[]> {\n const availability = await Promise.all(\n openFileTargetDescriptors.map(async (descriptor) =>\n descriptor.appName && !(await resolveAppPath(descriptor.appName)) ? null : descriptor\n )\n );\n return availability\n .filter((descriptor): descriptor is OpenFileTargetDescriptor => descriptor !== null)\n .map(({ label, target }) => ({ label, target }));\n}\n\nexport async function openLocalPath(\n filePath: string,\n target: OpenFileTarget = 'default'\n): Promise<void> {\n const descriptor = openFileTargetDescriptorByTarget.get(target);\n const openPath = descriptor?.opensFolder ? path.dirname(filePath) : filePath;\n const appName = descriptor?.appName;\n if (!appName) {\n await open(openPath, { wait: false });\n return;\n }\n\n const appPath = await resolveAppPath(appName);\n if (appPath) {\n await execFileAsync('open', ['-a', appPath, openPath]);\n return;\n }\n\n await open(openPath, { app: { name: appName }, wait: false });\n}\n\nasync function resolveAppPath(appName: string | readonly string[]): Promise<string | null> {\n if (process.platform !== 'darwin') {\n return null;\n }\n\n const appNames = Array.isArray(appName) ? appName : [appName];\n for (const name of appNames) {\n for (const root of applicationRoots) {\n const appPath = path.join(root, `${name}.app`);\n try {\n await access(appPath);\n return appPath;\n } catch {\n // Try the next likely application location.\n }\n }\n }\n return null;\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { execa } from 'execa';\nimport { languageForPath } from '../shared/language';\nimport type { SourcePeekRangeResponse, SourcePeekResponse } from '../shared/types';\nimport {\n SOURCE_PEEK_MAX_BYTES,\n SOURCE_PEEK_RANGE_MAX_LINES,\n type SourcePeekMatchReason\n} from '../shared/types';\n\nconst MODULE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json'];\nconst PATH_CONFIG_FILES = ['tsconfig.json', 'jsconfig.json'];\nconst IGNORED_SEARCH_PATHS = ['node_modules', 'dist', 'build', 'coverage', '.git'];\nconst IDENTIFIER_PATTERN = '[A-Za-z_$][\\\\w$]*';\nconst SOURCE_PEEK_CONTEXT_LINES = 520;\nconst SOURCE_PEEK_TARGET_CONTEXT_LINES = 240;\n\ninterface SourcePeekOptions {\n repoRoot: string;\n sourceFilePath: string;\n sourceRef: string | null;\n symbol: string;\n line: number;\n column: number;\n}\n\ninterface SourcePeekRangeOptions {\n repoRoot: string;\n sourceFilePath: string;\n sourceRef: string | null;\n startLine: number;\n lineCount: number;\n}\n\ninterface ImportBinding {\n importedName: string;\n kind: 'default' | 'named' | 'namespace';\n localName: string;\n moduleSpecifier: string;\n}\n\ninterface ReExportBinding {\n exportedName: string;\n importedName: string;\n moduleSpecifier: string;\n}\n\ninterface PathAlias {\n pattern: string;\n replacements: string[];\n}\n\ninterface PathAliasConfig {\n baseUrl: string | null;\n aliases: PathAlias[];\n}\n\ninterface DefinitionMatch {\n column: number;\n line: number;\n}\n\ninterface ModuleFile {\n content: string;\n filePath: string;\n}\n\ninterface ReferenceToken {\n namespace: string | null;\n symbol: string;\n}\n\nexport async function resolveSourcePeek({\n column,\n line,\n repoRoot,\n sourceFilePath,\n sourceRef,\n symbol\n}: SourcePeekOptions): Promise<SourcePeekResponse> {\n const sourceContent = await readRepoText(repoRoot, sourceRef, sourceFilePath);\n const sourceLines = splitFileLines(sourceContent);\n const reference = referenceTokenAt(sourceLines[line - 1] ?? '', column, symbol);\n const imports = parseImportBindings(sourceContent);\n const aliasConfig = await loadPathAliasConfig(repoRoot);\n const importedCandidates = candidateImportsForReference(imports, reference);\n\n for (const candidate of importedCandidates) {\n const resolved = await resolveImportedTarget({\n aliasConfig,\n importedName: candidate.targetSymbol,\n matchReason: 'import',\n moduleSpecifier: candidate.moduleSpecifier,\n repoRoot,\n sourceFilePath,\n sourceRef,\n symbol\n });\n if (resolved) {\n return resolved;\n }\n }\n\n const sameFileMatch = findDefinition(sourceContent, symbol);\n if (sameFileMatch) {\n return responseForMatch({\n column: sameFileMatch.column,\n content: sourceContent,\n filePath: sourceFilePath,\n line: sameFileMatch.line,\n matchReason: 'same-file',\n symbol,\n targetSymbol: symbol\n });\n }\n\n const searched = await searchRepoDefinition(repoRoot, sourceRef, symbol);\n if (searched) {\n return responseForMatch({\n ...searched,\n matchReason: 'repo-search',\n symbol,\n targetSymbol: symbol\n });\n }\n\n throw new Error(`No definition found for ${symbol}`);\n}\n\nexport async function readSourcePeekRange({\n lineCount,\n repoRoot,\n sourceFilePath,\n sourceRef,\n startLine\n}: SourcePeekRangeOptions): Promise<SourcePeekRangeResponse> {\n const content = await readRepoText(repoRoot, sourceRef, sourceFilePath);\n const limited = limitContentRange(content, startLine, lineCount);\n return {\n filePath: sourceFilePath,\n startLine: limited.startLine,\n totalLines: limited.totalLines,\n content: limited.content,\n truncated: limited.truncated,\n hasMoreAbove: limited.hasMoreAbove,\n hasMoreBelow: limited.hasMoreBelow\n };\n}\n\nasync function resolveImportedTarget({\n aliasConfig,\n importedName,\n matchReason,\n moduleSpecifier,\n repoRoot,\n sourceFilePath,\n sourceRef,\n symbol\n}: {\n aliasConfig: PathAliasConfig;\n importedName: string;\n matchReason: SourcePeekMatchReason;\n moduleSpecifier: string;\n repoRoot: string;\n sourceFilePath: string;\n sourceRef: string | null;\n symbol: string;\n}): Promise<SourcePeekResponse | null> {\n const moduleFile = await firstExistingModuleFile(\n repoRoot,\n sourceRef,\n moduleCandidates(repoRoot, aliasConfig, sourceFilePath, moduleSpecifier)\n );\n if (!moduleFile) {\n return null;\n }\n\n const targetMatch = findDefinition(moduleFile.content, importedName);\n if (targetMatch) {\n return responseForMatch({\n column: targetMatch.column,\n content: moduleFile.content,\n filePath: moduleFile.filePath,\n line: targetMatch.line,\n matchReason,\n symbol,\n targetSymbol: importedName\n });\n }\n\n const reExported = await resolveReExport({\n aliasConfig,\n content: moduleFile.content,\n depth: 0,\n repoRoot,\n sourceFilePath: moduleFile.filePath,\n sourceRef,\n symbol,\n targetSymbol: importedName\n });\n if (reExported) {\n return reExported;\n }\n\n if (importedName === 'default') {\n const fallbackLine = firstMeaningfulLine(moduleFile.content);\n return responseForMatch({\n column: 0,\n content: moduleFile.content,\n filePath: moduleFile.filePath,\n line: fallbackLine,\n matchReason: 'module',\n symbol,\n targetSymbol: importedName\n });\n }\n\n return null;\n}\n\nasync function resolveReExport({\n aliasConfig,\n content,\n depth,\n repoRoot,\n sourceFilePath,\n sourceRef,\n symbol,\n targetSymbol\n}: {\n aliasConfig: PathAliasConfig;\n content: string;\n depth: number;\n repoRoot: string;\n sourceFilePath: string;\n sourceRef: string | null;\n symbol: string;\n targetSymbol: string;\n}): Promise<SourcePeekResponse | null> {\n if (depth > 3) {\n return null;\n }\n\n for (const binding of parseReExportBindings(content)) {\n if (binding.exportedName !== '*' && binding.exportedName !== targetSymbol) {\n continue;\n }\n const nextTarget = binding.importedName === '*' ? targetSymbol : binding.importedName;\n const moduleFile = await firstExistingModuleFile(\n repoRoot,\n sourceRef,\n moduleCandidates(repoRoot, aliasConfig, sourceFilePath, binding.moduleSpecifier)\n );\n if (!moduleFile) {\n continue;\n }\n const match = findDefinition(moduleFile.content, nextTarget);\n if (match) {\n return responseForMatch({\n column: match.column,\n content: moduleFile.content,\n filePath: moduleFile.filePath,\n line: match.line,\n matchReason: 'import',\n symbol,\n targetSymbol: nextTarget\n });\n }\n const nested = await resolveReExport({\n aliasConfig,\n content: moduleFile.content,\n depth: depth + 1,\n repoRoot,\n sourceFilePath: moduleFile.filePath,\n sourceRef,\n symbol,\n targetSymbol: nextTarget\n });\n if (nested) {\n return nested;\n }\n }\n\n return null;\n}\n\nasync function searchRepoDefinition(\n repoRoot: string,\n sourceRef: string | null,\n symbol: string\n): Promise<({ content: string; filePath: string } & DefinitionMatch) | null> {\n const grepPattern = definitionGrepPattern(symbol);\n const args = ['grep', '-n', '-I', '-E', grepPattern];\n if (sourceRef) {\n args.push(sourceRef);\n }\n args.push('--', '.');\n for (const ignoredPath of IGNORED_SEARCH_PATHS) {\n args.push(`:!${ignoredPath}`);\n }\n\n let output = '';\n try {\n output = (await execa('git', args, { cwd: repoRoot })).stdout;\n } catch (error) {\n if (isExitCode(error, 1)) {\n return null;\n }\n throw error;\n }\n\n for (const rawLine of output.split('\\n')) {\n const parsed = parseGrepLine(rawLine, sourceRef);\n if (!parsed) {\n continue;\n }\n const content = await readRepoText(repoRoot, sourceRef, parsed.filePath).catch(() => null);\n if (!content) {\n continue;\n }\n const match = findDefinition(content, symbol);\n if (!match) {\n continue;\n }\n return {\n column: match.column,\n content,\n filePath: parsed.filePath,\n line: match.line\n };\n }\n\n return null;\n}\n\nasync function readRepoText(\n repoRoot: string,\n ref: string | null,\n filePath: string\n): Promise<string> {\n if (ref === null) {\n return readFile(path.resolve(repoRoot, filePath), 'utf8');\n }\n return (await execa('git', ['show', `${ref}:${filePath}`], { cwd: repoRoot })).stdout;\n}\n\nfunction responseForMatch({\n column,\n content,\n filePath,\n line,\n matchReason,\n symbol,\n targetSymbol\n}: {\n column: number;\n content: string;\n filePath: string;\n line: number;\n matchReason: SourcePeekMatchReason;\n symbol: string;\n targetSymbol: string;\n}): SourcePeekResponse {\n const limited = limitContentAroundLine(content, line);\n return {\n symbol,\n targetSymbol,\n filePath,\n startLine: limited.startLine,\n line,\n column,\n language: languageForPath(filePath),\n content: limited.content,\n truncated: limited.truncated,\n totalLines: limited.totalLines,\n hasMoreAbove: limited.hasMoreAbove,\n hasMoreBelow: limited.hasMoreBelow,\n matchReason\n };\n}\n\ninterface SourcePeekWindow {\n content: string;\n startLine: number;\n totalLines: number;\n truncated: boolean;\n hasMoreAbove: boolean;\n hasMoreBelow: boolean;\n}\n\nfunction limitContentAroundLine(content: string, line: number): SourcePeekWindow {\n const lines = splitFileLines(content);\n const totalLines = sourceTotalLines(lines);\n if (Buffer.byteLength(content, 'utf8') <= SOURCE_PEEK_MAX_BYTES) {\n return {\n content,\n startLine: 1,\n totalLines,\n truncated: false,\n hasMoreAbove: false,\n hasMoreBelow: false\n };\n }\n\n if (lines.length === 0) {\n return emptySourceWindow();\n }\n\n const targetIndex = Math.max(0, line - 1);\n const preferredStartIndex = Math.max(0, targetIndex - SOURCE_PEEK_TARGET_CONTEXT_LINES);\n const preferredEndIndex = Math.min(lines.length, preferredStartIndex + SOURCE_PEEK_CONTEXT_LINES);\n return limitLinesByIndexes(lines, preferredStartIndex, preferredEndIndex, targetIndex);\n}\n\nfunction limitContentRange(\n content: string,\n startLine: number,\n lineCount: number\n): SourcePeekWindow {\n const lines = splitFileLines(content);\n if (lines.length === 0) {\n return emptySourceWindow();\n }\n\n const cappedLineCount = Math.min(lineCount, SOURCE_PEEK_RANGE_MAX_LINES);\n const startIndex = clampNumber(startLine - 1, 0, lines.length - 1);\n const endIndex = Math.min(lines.length, startIndex + cappedLineCount);\n return limitLinesByIndexes(lines, startIndex, endIndex, null);\n}\n\nfunction limitLinesByIndexes(\n lines: string[],\n startIndex: number,\n endIndex: number,\n targetIndex: number | null\n): SourcePeekWindow {\n let limitedStartIndex = startIndex;\n let limitedEndIndex = endIndex;\n let limitedContent = lines.slice(limitedStartIndex, limitedEndIndex).join('\\n');\n let truncatedByBytes = false;\n\n while (\n Buffer.byteLength(limitedContent, 'utf8') > SOURCE_PEEK_MAX_BYTES &&\n limitedEndIndex - limitedStartIndex > 1\n ) {\n if (\n targetIndex !== null &&\n targetIndex - limitedStartIndex > limitedEndIndex - targetIndex - 1\n ) {\n limitedStartIndex += 1;\n } else {\n limitedEndIndex -= 1;\n }\n limitedContent = lines.slice(limitedStartIndex, limitedEndIndex).join('\\n');\n truncatedByBytes = true;\n }\n\n if (Buffer.byteLength(limitedContent, 'utf8') > SOURCE_PEEK_MAX_BYTES) {\n limitedContent = truncateUtf8(limitedContent, SOURCE_PEEK_MAX_BYTES);\n truncatedByBytes = true;\n }\n\n return {\n content: limitedContent,\n startLine: limitedStartIndex + 1,\n totalLines: sourceTotalLines(lines),\n truncated: truncatedByBytes || limitedStartIndex > 0 || limitedEndIndex < lines.length,\n hasMoreAbove: limitedStartIndex > 0,\n hasMoreBelow: limitedEndIndex < lines.length\n };\n}\n\nfunction emptySourceWindow(): SourcePeekWindow {\n return {\n content: '',\n startLine: 1,\n totalLines: 1,\n truncated: false,\n hasMoreAbove: false,\n hasMoreBelow: false\n };\n}\n\nfunction sourceTotalLines(lines: string[]): number {\n return Math.max(1, lines.length);\n}\n\nfunction clampNumber(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nfunction truncateUtf8(value: string, maxBytes: number): string {\n const buffer = Buffer.from(value, 'utf8');\n if (buffer.byteLength <= maxBytes) {\n return value;\n }\n return buffer\n .subarray(0, maxBytes)\n .toString('utf8')\n .replace(/\\uFFFD$/, '');\n}\n\nfunction candidateImportsForReference(\n imports: ImportBinding[],\n reference: ReferenceToken\n): Array<{ moduleSpecifier: string; targetSymbol: string }> {\n if (reference.namespace) {\n return imports\n .filter(\n (binding) => binding.kind === 'namespace' && binding.localName === reference.namespace\n )\n .map((binding) => ({\n moduleSpecifier: binding.moduleSpecifier,\n targetSymbol: reference.symbol\n }));\n }\n\n return imports\n .filter((binding) => binding.localName === reference.symbol)\n .map((binding) => ({\n moduleSpecifier: binding.moduleSpecifier,\n targetSymbol: binding.importedName\n }));\n}\n\nfunction referenceTokenAt(line: string, column: number, symbol: string): ReferenceToken {\n let start = Math.min(Math.max(column, 0), line.length);\n if (line.slice(start, start + symbol.length) !== symbol) {\n const beforeOrAt = line.lastIndexOf(symbol, start);\n start = beforeOrAt >= 0 ? beforeOrAt : line.indexOf(symbol);\n }\n if (start < 0) {\n return { namespace: null, symbol };\n }\n\n const namespaceMatch = line.slice(0, start).match(/([A-Za-z_$][\\w$]*)\\s*\\.\\s*$/);\n return {\n namespace: namespaceMatch?.[1] ?? null,\n symbol\n };\n}\n\nfunction parseImportBindings(content: string): ImportBinding[] {\n const bindings: ImportBinding[] = [];\n const importRegex = /^\\s*import\\s+(?:type\\s+)?([^;]*?)\\s+from\\s+['\"]([^'\"]+)['\"];?/gm;\n let match = importRegex.exec(content);\n while (match !== null) {\n const body = match[1]?.trim() ?? '';\n const moduleSpecifier = match[2] ?? '';\n for (const part of splitImportParts(body)) {\n if (part.startsWith('{') && part.endsWith('}')) {\n bindings.push(\n ...parseNamedBindings(part).map((binding) => ({\n ...binding,\n kind: 'named' as const,\n moduleSpecifier\n }))\n );\n continue;\n }\n\n const namespaceMatch = part.match(/^\\*\\s+as\\s+([A-Za-z_$][\\w$]*)$/);\n if (namespaceMatch?.[1]) {\n bindings.push({\n importedName: '*',\n kind: 'namespace',\n localName: namespaceMatch[1],\n moduleSpecifier\n });\n continue;\n }\n\n if (new RegExp(`^${IDENTIFIER_PATTERN}$`).test(part)) {\n bindings.push({\n importedName: 'default',\n kind: 'default',\n localName: part,\n moduleSpecifier\n });\n }\n }\n match = importRegex.exec(content);\n }\n return bindings;\n}\n\nfunction parseReExportBindings(content: string): ReExportBinding[] {\n const bindings: ReExportBinding[] = [];\n const exportRegex = /^\\s*export\\s+(?:type\\s+)?(\\*|\\{[\\s\\S]*?\\})\\s+from\\s+['\"]([^'\"]+)['\"];?/gm;\n let match = exportRegex.exec(content);\n while (match !== null) {\n const body = match[1] ?? '';\n const moduleSpecifier = match[2] ?? '';\n if (body === '*') {\n bindings.push({ exportedName: '*', importedName: '*', moduleSpecifier });\n match = exportRegex.exec(content);\n continue;\n }\n bindings.push(\n ...parseNamedBindings(body).map((binding) => ({\n exportedName: binding.localName,\n importedName: binding.importedName,\n moduleSpecifier\n }))\n );\n match = exportRegex.exec(content);\n }\n return bindings;\n}\n\nfunction parseNamedBindings(body: string): Array<{ importedName: string; localName: string }> {\n return body\n .slice(1, -1)\n .split(',')\n .map((part) => part.trim().replace(/^type\\s+/, ''))\n .filter(Boolean)\n .map((part) => {\n const aliasMatch = part.match(/^([A-Za-z_$][\\w$]*)\\s+as\\s+([A-Za-z_$][\\w$]*)$/);\n if (aliasMatch?.[1] && aliasMatch[2]) {\n return { importedName: aliasMatch[1], localName: aliasMatch[2] };\n }\n return new RegExp(`^${IDENTIFIER_PATTERN}$`).test(part)\n ? { importedName: part, localName: part }\n : null;\n })\n .filter((binding): binding is { importedName: string; localName: string } => Boolean(binding));\n}\n\nfunction splitImportParts(body: string): string[] {\n const parts: string[] = [];\n let depth = 0;\n let start = 0;\n for (let index = 0; index < body.length; index += 1) {\n const char = body[index];\n if (char === '{') {\n depth += 1;\n } else if (char === '}') {\n depth = Math.max(0, depth - 1);\n } else if (char === ',' && depth === 0) {\n parts.push(body.slice(start, index).trim());\n start = index + 1;\n }\n }\n parts.push(body.slice(start).trim());\n return parts.filter(Boolean);\n}\n\nasync function loadPathAliasConfig(repoRoot: string): Promise<PathAliasConfig> {\n for (const configFile of PATH_CONFIG_FILES) {\n const rawConfig = await readFile(path.join(repoRoot, configFile), 'utf8').catch(() => null);\n if (!rawConfig) {\n continue;\n }\n const parsed = parseJsonConfig(rawConfig);\n if (!parsed) {\n continue;\n }\n const compilerOptions = asRecord(parsed.compilerOptions);\n const baseUrlValue = compilerOptions ? compilerOptions.baseUrl : null;\n const baseUrl =\n typeof baseUrlValue === 'string' ? path.resolve(repoRoot, baseUrlValue) : repoRoot;\n const paths = asRecord(compilerOptions?.paths);\n const aliases = paths\n ? Object.entries(paths).flatMap(([pattern, replacements]) =>\n Array.isArray(replacements)\n ? [\n {\n pattern,\n replacements: replacements.filter(\n (replacement): replacement is string => typeof replacement === 'string'\n )\n }\n ]\n : []\n )\n : [];\n return { aliases, baseUrl };\n }\n\n return { aliases: [], baseUrl: null };\n}\n\nfunction parseJsonConfig(rawConfig: string): Record<string, unknown> | null {\n try {\n return JSON.parse(stripJsonComments(rawConfig).replace(/,\\s*([}\\]])/g, '$1'));\n } catch {\n return null;\n }\n}\n\nfunction stripJsonComments(input: string): string {\n return input.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '').replace(/^\\s*\\/\\/.*$/gm, '');\n}\n\nfunction moduleCandidates(\n repoRoot: string,\n aliasConfig: PathAliasConfig,\n sourceFilePath: string,\n moduleSpecifier: string\n): string[] {\n const roots: string[] = [];\n if (moduleSpecifier.startsWith('.')) {\n roots.push(path.resolve(repoRoot, path.dirname(sourceFilePath), moduleSpecifier));\n } else {\n roots.push(...aliasCandidateRoots(repoRoot, aliasConfig, moduleSpecifier));\n if (aliasConfig.baseUrl) {\n roots.push(path.resolve(aliasConfig.baseUrl, moduleSpecifier));\n }\n }\n\n const candidates = new Set<string>();\n for (const root of roots) {\n for (const candidate of expandModuleRoot(root)) {\n const relativePath = repoRelativePath(repoRoot, candidate);\n if (relativePath) {\n candidates.add(relativePath);\n }\n }\n }\n return [...candidates];\n}\n\nfunction aliasCandidateRoots(\n repoRoot: string,\n aliasConfig: PathAliasConfig,\n moduleSpecifier: string\n): string[] {\n const roots: string[] = [];\n for (const alias of aliasConfig.aliases) {\n const wildcardIndex = alias.pattern.indexOf('*');\n const matched =\n wildcardIndex >= 0\n ? matchWildcardPattern(alias.pattern, wildcardIndex, moduleSpecifier)\n : alias.pattern === moduleSpecifier\n ? ''\n : null;\n if (matched === null) {\n continue;\n }\n for (const replacement of alias.replacements) {\n roots.push(\n path.resolve(\n aliasConfig.baseUrl ?? repoRoot,\n wildcardIndex >= 0 ? replacement.replace('*', matched) : replacement\n )\n );\n }\n }\n return roots;\n}\n\nfunction matchWildcardPattern(\n pattern: string,\n wildcardIndex: number,\n value: string\n): string | null {\n const prefix = pattern.slice(0, wildcardIndex);\n const suffix = pattern.slice(wildcardIndex + 1);\n if (!value.startsWith(prefix) || !value.endsWith(suffix)) {\n return null;\n }\n return value.slice(prefix.length, value.length - suffix.length);\n}\n\nfunction expandModuleRoot(root: string): string[] {\n const candidates: string[] = [];\n if (path.extname(root)) {\n candidates.push(root);\n } else {\n for (const extension of MODULE_EXTENSIONS) {\n candidates.push(`${root}${extension}`);\n }\n for (const extension of MODULE_EXTENSIONS) {\n candidates.push(path.join(root, `index${extension}`));\n }\n }\n return candidates;\n}\n\nasync function firstExistingModuleFile(\n repoRoot: string,\n sourceRef: string | null,\n candidates: string[]\n): Promise<ModuleFile | null> {\n for (const filePath of candidates) {\n const content = await readRepoText(repoRoot, sourceRef, filePath).catch(() => null);\n if (content !== null) {\n return { content, filePath };\n }\n }\n return null;\n}\n\nfunction findDefinition(content: string, symbol: string): DefinitionMatch | null {\n const lines = splitFileLines(content);\n const patterns = definitionPatterns(symbol);\n for (let index = 0; index < lines.length; index += 1) {\n const line = lines[index] ?? '';\n if (!patterns.some((pattern) => pattern.test(line))) {\n continue;\n }\n return {\n column: Math.max(0, line.indexOf(symbol === 'default' ? 'default' : symbol)),\n line: index + 1\n };\n }\n return null;\n}\n\nfunction definitionPatterns(symbol: string): RegExp[] {\n if (symbol === 'default') {\n return [/^\\s*export\\s+default\\b/];\n }\n\n const escaped = escapeRegex(symbol);\n return [\n new RegExp(`^\\\\s*(?:export\\\\s+)?(?:declare\\\\s+)?(?:async\\\\s+)?function\\\\s+${escaped}\\\\b`),\n new RegExp(`^\\\\s*(?:export\\\\s+)?(?:declare\\\\s+)?(?:const|let|var)\\\\s+${escaped}\\\\b`),\n new RegExp(\n `^\\\\s*(?:export\\\\s+)?(?:declare\\\\s+)?(?:class|interface|type|enum)\\\\s+${escaped}\\\\b`\n ),\n new RegExp(`^\\\\s*export\\\\s+default\\\\s+(?:async\\\\s+)?function\\\\s+${escaped}\\\\b`),\n new RegExp(`^\\\\s*export\\\\s+default\\\\s+class\\\\s+${escaped}\\\\b`)\n ];\n}\n\nfunction definitionGrepPattern(symbol: string): string {\n const escaped = escapeExtendedGrep(symbol);\n return [\n `^[[:space:]]*(export[[:space:]]+)?(declare[[:space:]]+)?(async[[:space:]]+)?function[[:space:]]+${escaped}([^[:alnum:]_$]|$)`,\n `^[[:space:]]*(export[[:space:]]+)?(declare[[:space:]]+)?(const|let|var)[[:space:]]+${escaped}([^[:alnum:]_$]|$)`,\n `^[[:space:]]*(export[[:space:]]+)?(declare[[:space:]]+)?(class|interface|type|enum)[[:space:]]+${escaped}([^[:alnum:]_$]|$)`\n ].join('|');\n}\n\nfunction firstMeaningfulLine(content: string): number {\n const lines = splitFileLines(content);\n const index = lines.findIndex((line) => line.trim() !== '');\n return index >= 0 ? index + 1 : 1;\n}\n\nfunction parseGrepLine(\n rawLine: string,\n sourceRef: string | null\n): { filePath: string; line: number } | null {\n const line = sourceRef ? rawLine.slice(sourceRef.length + 1) : rawLine;\n const firstColon = line.indexOf(':');\n const secondColon = line.indexOf(':', firstColon + 1);\n if (firstColon < 0 || secondColon < 0) {\n return null;\n }\n const lineNumber = Number(line.slice(firstColon + 1, secondColon));\n if (!Number.isFinite(lineNumber)) {\n return null;\n }\n return {\n filePath: line.slice(0, firstColon),\n line: lineNumber\n };\n}\n\nfunction repoRelativePath(repoRoot: string, absolutePath: string): string | null {\n const relativePath = path.relative(repoRoot, absolutePath);\n if (!relativePath || relativePath.startsWith('..') || path.isAbsolute(relativePath)) {\n return null;\n }\n return relativePath.split(path.sep).join('/');\n}\n\nfunction splitFileLines(contents: string): string[] {\n const lines = contents.replace(/\\r\\n/g, '\\n').split('\\n');\n if (lines.at(-1) === '') {\n lines.pop();\n }\n return lines;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction isExitCode(error: unknown, exitCode: number): boolean {\n return typeof error === 'object' && error !== null && 'exitCode' in error\n ? error.exitCode === exitCode\n : false;\n}\n\nfunction escapeRegex(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction escapeExtendedGrep(value: string): string {\n return value.replace(/[.[*^$()+?{}|\\\\]/g, '\\\\$&');\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.loadReviewForList(entry.name));\n }\n }\n await Promise.all(reviewLoads);\n }\n\n private async loadReviewForList(id: string): Promise<ReviewRecord | null> {\n try {\n return await this.loadReview(id);\n } catch (error) {\n process.stderr.write(`Warning: Skipping corrupt review ${id}: ${formatError(error)}\\n`);\n return null;\n }\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 { 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","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, isLineComment } from './comments';\nimport { languageForPath } from './language';\nimport { reviewScopeLabel } from './review-scope';\nimport type { FeedbackBundle, LineComment } 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 generalComments = comments.filter((comment) => !isLineComment(comment));\n const lineComments = comments.filter(isLineComment);\n const commentsByFile = new Map<string, LineComment[]>();\n const files: string[] = [];\n for (const comment of lineComments) {\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 if (generalComments.length > 0) {\n lines.push('## General comments', '');\n for (const comment of generalComments) {\n lines.push(`### ${comment.id}`, comment.body.trim(), '');\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 { DEFAULT_REVIEW_RETENTION_DAYS } from '../shared/cleanup';\nimport { formatError } from '../shared/errors';\nimport { reviewStore } from './store';\n\ninterface StartupCleanupLogger {\n info(message: string): void;\n error(message: string): void;\n}\n\nconst defaultLogger: StartupCleanupLogger = {\n info: (message) => {\n process.stdout.write(`${message}\\n`);\n },\n error: (message) => {\n process.stderr.write(`${message}\\n`);\n }\n};\n\nexport async function runStartupCleanup(\n logger: StartupCleanupLogger = defaultLogger\n): Promise<void> {\n try {\n const result = await reviewStore.clearReviewArtifacts({\n olderThanDays: DEFAULT_REVIEW_RETENTION_DAYS\n });\n logger.info(\n `Gloss cleanup deleted ${result.counts.deleted} review artifact(s); skipped ${result.counts.skipped}`\n );\n } catch (error) {\n logger.error(`Gloss cleanup failed: ${formatError(error)}`);\n }\n}\n"],"mappings":"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","names":["fileURLToPath","randomUUID","rm","writeFile","path","path","writeFile","rm","path","randomUUID","readFile","path","readFile","path","path","readFile","path","homedir","path","readFile","path","execa","splitFileLines","execa","readFile","path","readdir","readFile","path","readFile","rm","rm","readFile","readdir","readFile","path","origin","turnSummary","path","readFile","fileURLToPath"]}