getgloss 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/cli/index.js +504 -229
- package/dist/cli/index.js.map +1 -1
- package/dist/server/daemon.js +281 -15
- package/dist/server/daemon.js.map +1 -1
- package/dist/web/setup.md +3 -0
- package/package.json +1 -1
- package/skill/SKILL.md +52 -54
|
@@ -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/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/reviews.ts","../../src/server/local-open.ts","../../src/server/store.ts","../../src/shared/review-scope.ts","../../src/shared/markdown.ts"],"sourcesContent":["import { rm } from 'node:fs/promises';\nimport { serve } from '@hono/node-server';\nimport { globalServerFile, globalStateDir, packageVersion } from '../shared/paths';\nimport { readServerInfo, writeServerInfo } from '../shared/server-info';\nimport { createApp } from './index';\nimport { reviewStore } from './store';\n\nconst port = Number(process.env.GLOSS_PORT ?? '0');\nconst idleTimeoutMs = Number(process.env.GLOSS_IDLE_TIMEOUT_MS ?? '120000');\n\nif (!port) {\n throw new Error('GLOSS_PORT is required');\n}\n\nconst origin = `http://localhost:${port}`;\nconst eventStreams = new Set<() => void>();\nlet idleTimer: NodeJS.Timeout | null = null;\nlet shuttingDown = false;\n\nconst server = serve({\n fetch: createApp(origin, {\n onReviewActivity: () => {\n void scheduleIdleShutdown();\n },\n registerEventStream: (close) => {\n eventStreams.add(close);\n return () => {\n eventStreams.delete(close);\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});\n\nawait scheduleIdleShutdown();\n\nfor (const signal of ['SIGTERM', 'SIGINT', 'SIGHUP'] as const) {\n process.on(signal, () => {\n void shutdown(0);\n });\n}\n\nasync function scheduleIdleShutdown(): Promise<void> {\n if (shuttingDown || idleTimeoutMs <= 0) {\n return;\n }\n\n const activeReviews = await countActiveReviews();\n if (activeReviews > 0) {\n if (idleTimer) {\n clearTimeout(idleTimer);\n idleTimer = null;\n }\n return;\n }\n\n if (!idleTimer) {\n idleTimer = setTimeout(() => {\n idleTimer = null;\n void shutdownIfIdle();\n }, idleTimeoutMs);\n }\n}\n\nasync function shutdownIfIdle(): Promise<void> {\n if ((await countActiveReviews()) > 0) {\n await scheduleIdleShutdown();\n return;\n }\n await shutdown(0);\n}\n\nasync function countActiveReviews(): Promise<number> {\n const reviews = await reviewStore.list();\n return reviews.filter((review) => review.status === 'pending').length;\n}\n\nasync function shutdown(exitCode: number): Promise<void> {\n if (shuttingDown) {\n return;\n }\n shuttingDown = true;\n if (idleTimer) {\n clearTimeout(idleTimer);\n idleTimer = null;\n }\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 await rm(globalServerFile(), { force: true });\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 globalLogDir(): string {\n return path.join(globalStateDir(), 'logs');\n}\n\nexport function globalServerLogFile(): string {\n return path.join(globalLogDir(), 'server.log');\n}\n\nexport function globalReviewsDir(): string {\n return path.join(globalStateDir(), 'reviews');\n}\n\nexport function globalReviewDir(reviewId: string): string {\n return path.join(globalReviewsDir(), reviewId);\n}\n\nexport function globalReviewTurnsDir(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'turns');\n}\n\nexport function globalReviewTurnDir(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnsDir(reviewId), turnId);\n}\n\nexport function globalReviewTurnMetaFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'turn.json');\n}\n\nexport function globalReviewTurnDiffFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'diff.json');\n}\n\nexport function globalReviewTurnFeedbackFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'feedback.json');\n}\n\nexport function globalReviewTurnMarkdownFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'feedback.md');\n}\n\nexport function globalReviewTurnResolvedFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'resolved.json');\n}\n\nexport function globalReviewMetaFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'meta.json');\n}\n\nexport function globalReviewDiffFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'diff.json');\n}\n\nexport function globalReviewFeedbackFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'feedback.json');\n}\n\nexport function globalReviewMarkdownFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'feedback.md');\n}\n\nexport function globalReviewResolvedFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'resolved.json');\n}\n\nexport async function ensureDir(dir: string): Promise<void> {\n await mkdir(dir, { recursive: true });\n}\n","{\n \"name\": \"getgloss\",\n \"version\": \"0.8.0\",\n \"description\": \"Local browser-based diff review for coding-agent loops.\",\n \"type\": \"module\",\n \"packageManager\": \"pnpm@10.33.2\",\n \"bin\": {\n \"getgloss\": \"./dist/cli/index.js\",\n \"gloss\": \"./dist/cli/index.js\"\n },\n \"files\": [\n \"dist\",\n \"skill\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"pnpm build:web && pnpm build:node\",\n \"build:web\": \"vite build\",\n \"build:node\": \"tsup\",\n \"check\": \"biome check .\",\n \"format\": \"biome format --write .\",\n \"prepack\": \"pnpm build\",\n \"dev:web\": \"vite --host 127.0.0.1\",\n \"setup\": \"tsx scripts/dev-cli.ts\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"dependencies\": {\n \"@hono/node-server\": \"1.19.14\",\n \"@shikijs/langs\": \"4.1.0\",\n \"@shikijs/themes\": \"4.1.0\",\n \"@tailwindcss/vite\": \"4.3.0\",\n \"commander\": \"14.0.3\",\n \"execa\": \"9.6.1\",\n \"get-port\": \"7.2.0\",\n \"hono\": \"4.12.21\",\n \"lucide-react\": \"1.16.0\",\n \"open\": \"10.2.0\",\n \"react\": \"19.2.6\",\n \"react-dom\": \"19.2.6\",\n \"shiki\": \"4.1.0\",\n \"ulid\": \"3.0.2\",\n \"zustand\": \"5.0.13\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"2.4.15\",\n \"@types/node\": \"24.12.4\",\n \"@types/react\": \"19.2.15\",\n \"@types/react-dom\": \"19.2.3\",\n \"@vitejs/plugin-react\": \"4.7.0\",\n \"tailwindcss\": \"4.3.0\",\n \"tsup\": \"8.5.1\",\n \"tsx\": \"4.22.3\",\n \"typescript\": \"5.9.3\",\n \"vite\": \"6.4.2\",\n \"vitest\": \"3.2.4\"\n },\n \"keywords\": [\n \"diff\",\n \"review\",\n \"coding-agents\"\n ],\n \"author\": \"Raj Joshi\",\n \"license\": \"MIT\",\n \"homepage\": \"https://getgloss.dev\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/iamrajjoshi/gloss.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/iamrajjoshi/gloss/issues\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { formatError, isFileNotFound } from './errors';\nimport { writeJsonFile } from './json';\nimport { ensureDir, globalServerFile, globalStateDir } from './paths';\nimport type { ServerInfo } from './types';\nimport { isServerInfo, parseJson } from './validation';\n\nexport async function readServerInfo(): Promise<ServerInfo | null> {\n let raw: string;\n try {\n raw = await readFile(globalServerFile(), 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return null;\n }\n throw new Error(`Could not read server info at ${globalServerFile()}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n try {\n return parseJson(raw, isServerInfo, 'server info');\n } catch (error) {\n throw new Error(`Invalid server info at ${globalServerFile()}: ${formatError(error)}`, {\n cause: error\n });\n }\n}\n\nexport async function writeServerInfo(info: ServerInfo): Promise<void> {\n await ensureDir(globalStateDir());\n await writeJsonFile(globalServerFile(), info);\n}\n","export function formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport function isFileNotFound(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n","import { randomUUID } from 'node:crypto';\nimport { rename, rm, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type {\n DiffPayload,\n FeedbackBundle,\n ResolutionBundle,\n ReviewMeta,\n ReviewTurnMeta,\n ServerInfo\n} from './types';\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | { [key: string]: JsonValue }\n | JsonValue[];\n\ntype PersistedJson =\n | ServerInfo\n | ReviewMeta\n | ReviewTurnMeta\n | DiffPayload\n | FeedbackBundle\n | ResolutionBundle;\n\nfunction serializeJson(value: PersistedJson): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nexport async function writeJsonFile(filePath: string, value: PersistedJson): Promise<void> {\n await writeTextFile(filePath, serializeJson(value));\n}\n\nexport async function writeTextFile(filePath: string, value: string): Promise<void> {\n const tempPath = path.join(\n path.dirname(filePath),\n `.${path.basename(filePath)}.${process.pid}.${randomUUID()}.tmp`\n );\n try {\n await writeFile(tempPath, value);\n await rename(tempPath, filePath);\n } catch (error) {\n await rm(tempPath, { force: true }).catch(() => undefined);\n throw error;\n }\n}\n","export const SIDES = ['L', 'R'] as const;\n\nexport type Side = (typeof SIDES)[number];\n\nexport const REVIEW_STATUSES = ['pending', 'submitted', 'cancelled', 'resolved'] as const;\n\nexport type ReviewStatus = (typeof REVIEW_STATUSES)[number];\n\nexport interface Comment {\n id: string;\n filePath: string;\n startLine: number;\n endLine: number;\n side: Side;\n body: string;\n originalSnippet: string;\n createdAt: string;\n}\n\nexport const DIFF_LINE_TYPES = ['context', 'add', 'delete'] as const;\n\nexport type DiffLineType = (typeof DIFF_LINE_TYPES)[number];\n\nexport interface DiffLine {\n type: DiffLineType;\n oldLine: number | null;\n newLine: number | null;\n content: string;\n}\n\nexport interface DiffHunk {\n oldStart: number;\n oldLines: number;\n newStart: number;\n newLines: number;\n header: string;\n lines: DiffLine[];\n}\n\nexport interface DiffFile {\n path: string;\n oldPath: string | null;\n additions: number;\n deletions: number;\n isBinary: boolean;\n isDeleted: boolean;\n isNew: boolean;\n isRenamed: boolean;\n language: string | null;\n hunks: DiffHunk[];\n}\n\nexport const DIFF_SCOPE_MODES = ['working', 'branch', 'explicit'] as const;\n\nexport type DiffScopeMode = (typeof DIFF_SCOPE_MODES)[number];\n\nexport const DIFF_FALLBACK_REASONS = ['working-tree-clean', 'missing-branch-base'] as const;\n\nexport type DiffFallbackReason = (typeof DIFF_FALLBACK_REASONS)[number] | null;\n\nexport interface BaseRef {\n ref: string;\n sha: string;\n}\n\nexport interface DiffRef {\n ref: string;\n sha: string | null;\n}\n\nexport interface DiffStats {\n files: number;\n additions: number;\n deletions: number;\n}\n\nexport interface DiffCommit {\n sha: string;\n shortSha: string;\n subject: string;\n authorName: string;\n authorEmail: string;\n authoredAt: string;\n committedAt: string;\n}\n\nexport interface CommitDiff {\n commit: DiffCommit;\n stats: DiffStats;\n rawDiff: string;\n files: DiffFile[];\n}\n\nexport interface CommitRangeDiffRequest {\n fromSha: string;\n toSha: string;\n turnId?: string;\n}\n\nexport interface CommitRangeDiffResponse {\n fromSha: string;\n toSha: string;\n stats: DiffStats;\n rawDiff: string;\n files: DiffFile[];\n}\n\nexport const REVIEW_SCOPE_MODES = ['all', 'single', 'range'] as const;\n\nexport type ReviewScope =\n | { mode: 'all' }\n | { mode: 'single'; sha: string }\n | { mode: 'range'; fromSha: string; toSha: string };\n\ninterface DiffScope {\n mode: DiffScopeMode;\n requestedBase: string | null;\n base: BaseRef;\n comparison: DiffRef;\n fallbackReason: DiffFallbackReason;\n}\n\nexport interface DiffPayload {\n base: BaseRef;\n branch: string | null;\n cwd: string;\n scope: DiffScope;\n stats: DiffStats;\n rawDiff: string;\n files: DiffFile[];\n commitDiffs?: CommitDiff[];\n capturedAt: string;\n}\n\nexport interface ReviewMeta {\n id: string;\n cwd: string;\n base: DiffPayload['base'];\n branch: string | null;\n status: ReviewStatus;\n createdAt: string;\n submittedAt?: string;\n resolvedAt?: string;\n artifactDir: string;\n activeTurnId?: string;\n turns?: ReviewTurnSummary[];\n feedbackPath?: string;\n markdownPath?: string;\n}\n\nexport interface FeedbackBundle {\n version: 1;\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n timestamp: string;\n base: DiffPayload['base'];\n branch: string | null;\n reviewScope?: ReviewScope;\n comments: Comment[];\n}\n\nexport const RESOLUTION_STATUSES = ['partial', 'resolved'] as const;\n\ntype ResolutionStatus = (typeof RESOLUTION_STATUSES)[number];\n\nexport interface ResolvedComment {\n commentId: string;\n status: 'resolved';\n summary?: string;\n resolvedAt: string;\n}\n\nexport interface ResolutionBundle {\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n status: ResolutionStatus;\n summary: string | null;\n resolvedAt: string | null;\n comments: ResolvedComment[];\n}\n\nexport interface ResolutionCounts {\n total: number;\n resolved: number;\n open: number;\n}\n\nexport interface ResolveResult {\n ok: true;\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n status: ReviewStatus;\n resolutionStatus: ResolutionStatus;\n comments: ResolutionCounts;\n path: string;\n resolution: ResolutionBundle;\n}\n\nexport const REVIEW_UPDATE_REASONS = [\n 'review-resolved',\n 'comment-resolved',\n 'comment-reopened',\n 'turn-created'\n] as const;\n\nexport type ReviewUpdateReason = (typeof REVIEW_UPDATE_REASONS)[number];\n\nexport type ReviewEvent =\n | { type: 'review.opened'; reviewId: string }\n | {\n type: 'review.turn.created';\n reviewId: string;\n turnId: string;\n turnIndex: number;\n reused: boolean;\n }\n | {\n type: 'review.submitted';\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n counts: { files: number; comments: number };\n }\n | {\n type: 'review.updated';\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n reason: ReviewUpdateReason;\n status: ReviewStatus;\n resolutionStatus: ResolutionStatus;\n counts: ResolutionCounts;\n }\n | { type: 'review.cancelled'; reviewId: string };\n\nexport interface ReviewTurnMeta {\n id: string;\n index: number;\n status: ReviewStatus;\n createdAt: string;\n submittedAt?: string;\n resolvedAt?: string;\n artifactDir: string;\n diffPath: string;\n feedbackPath?: string;\n markdownPath?: string;\n resolvedPath?: string;\n}\n\nexport interface ReviewTurnSummary extends ReviewTurnMeta {\n capturedAt: string;\n stats: DiffStats;\n comments: ResolutionCounts;\n}\n\nexport interface ReviewTurn extends ReviewTurnMeta {\n diff: DiffPayload;\n feedback?: FeedbackBundle;\n resolution?: ResolutionBundle;\n}\n\nexport interface ReviewRecord {\n meta: ReviewMeta;\n turns: ReviewTurn[];\n diff: DiffPayload;\n feedback?: FeedbackBundle;\n resolution?: ResolutionBundle;\n}\n\nexport interface ServerInfo {\n pid: number;\n port: number;\n version: string;\n startedAt: string;\n stateDir: string;\n}\n\nexport interface OpenResult {\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n url: string;\n files: number;\n comments?: number;\n feedbackPath?: string;\n markdownPath?: string;\n artifactDir?: string;\n}\n\nexport interface HealthResponse {\n ok: boolean;\n version: string;\n activeReviews: number;\n}\n\ninterface ReviewRegistrationResponse {\n meta: ReviewMeta;\n url: string;\n turn?: ReviewTurnSummary;\n}\n\nexport interface CreateReviewResponse extends ReviewRegistrationResponse {}\n\nexport interface CreateReviewTurnResponse extends ReviewRegistrationResponse {\n turn: ReviewTurnSummary;\n reused: boolean;\n}\n\nexport interface ListReviewsResponse {\n reviews: ReviewMeta[];\n}\n\nexport interface SubmitReviewRequest {\n comments: Comment[];\n reviewScope?: ReviewScope;\n}\n\nexport interface ResolutionRequest {\n summary?: string;\n turn?: string;\n}\n\nexport interface OpenFileRequest {\n filePath: string;\n turnId?: string;\n}\n\nexport interface OpenFileResponse {\n ok: true;\n path: string;\n}\n","import type { JsonValue } from './json';\nimport type {\n Comment,\n CommitDiff,\n CommitRangeDiffRequest,\n CommitRangeDiffResponse,\n CreateReviewResponse,\n CreateReviewTurnResponse,\n DiffCommit,\n DiffFile,\n DiffHunk,\n DiffLine,\n DiffPayload,\n DiffStats,\n FeedbackBundle,\n HealthResponse,\n ListReviewsResponse,\n OpenFileRequest,\n OpenFileResponse,\n OpenResult,\n ResolutionBundle,\n ResolutionRequest,\n ResolvedComment,\n ResolveResult,\n ReviewEvent,\n ReviewMeta,\n ReviewRecord,\n ReviewScope,\n ReviewTurn,\n ReviewTurnMeta,\n ReviewTurnSummary,\n ServerInfo,\n SubmitReviewRequest\n} from './types';\nimport {\n DIFF_FALLBACK_REASONS,\n DIFF_LINE_TYPES,\n DIFF_SCOPE_MODES,\n RESOLUTION_STATUSES,\n REVIEW_SCOPE_MODES,\n REVIEW_STATUSES,\n REVIEW_UPDATE_REASONS,\n SIDES\n} from './types';\n\nexport type JsonGuard<T> = (value: unknown) => value is T;\n\nexport type StoredReviewMeta = Omit<ReviewMeta, 'artifactDir'> &\n Partial<\n Pick<ReviewMeta, 'artifactDir' | 'activeTurnId' | 'turns' | 'feedbackPath' | 'markdownPath'>\n >;\n\ntype ReviewRegistrationResponseShape = {\n meta: ReviewMeta;\n url: string;\n turn?: ReviewTurnSummary;\n};\n\nexport function parseJson<T>(raw: string, guard: JsonGuard<T>, label: string): T {\n const parsed: JsonValue = JSON.parse(raw);\n return parseJsonValue(parsed, guard, label);\n}\n\nexport function parseJsonValue<T>(value: JsonValue, guard: JsonGuard<T>, label: string): T {\n if (!guard(value)) {\n throw new Error(`Invalid ${label}`);\n }\n return value;\n}\n\nexport function isServerInfo(value: unknown): value is ServerInfo {\n return (\n isRecord(value) &&\n isNumber(value.pid) &&\n isNumber(value.port) &&\n isString(value.version) &&\n isString(value.startedAt) &&\n isString(value.stateDir)\n );\n}\n\nexport function isHealthResponse(value: unknown): value is HealthResponse {\n return (\n isRecord(value) &&\n isBoolean(value.ok) &&\n isString(value.version) &&\n isNumber(value.activeReviews)\n );\n}\n\nexport function isCreateReviewResponse(value: unknown): value is CreateReviewResponse {\n return (\n isRecord(value) &&\n hasReviewRegistrationFields(value) &&\n isOptional(value.turn, isReviewTurnSummary)\n );\n}\n\nexport function isCreateReviewTurnResponse(value: unknown): value is CreateReviewTurnResponse {\n return (\n isRecord(value) &&\n hasReviewRegistrationFields(value) &&\n isReviewTurnSummary(value.turn) &&\n isBoolean(value.reused)\n );\n}\n\nexport function isListReviewsResponse(value: unknown): value is ListReviewsResponse {\n return isRecord(value) && isArrayOf(value.reviews, isReviewMeta);\n}\n\nexport function isOpenResult(value: unknown): value is OpenResult {\n return (\n isRecord(value) &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isString(value.url) &&\n isNumber(value.files) &&\n isOptionalNumber(value.comments) &&\n isOptionalString(value.feedbackPath) &&\n isOptionalString(value.markdownPath) &&\n isOptionalString(value.artifactDir)\n );\n}\n\nexport function isOpenFileRequest(value: unknown): value is OpenFileRequest {\n return isRecord(value) && isString(value.filePath) && isOptionalString(value.turnId);\n}\n\nexport function isOpenFileResponse(value: unknown): value is OpenFileResponse {\n return isRecord(value) && value.ok === true && isString(value.path);\n}\n\nexport function isCommitRangeDiffRequest(value: unknown): value is CommitRangeDiffRequest {\n return (\n isRecord(value) &&\n isString(value.fromSha) &&\n isString(value.toSha) &&\n isOptionalString(value.turnId)\n );\n}\n\nexport function isCommitRangeDiffResponse(value: unknown): value is CommitRangeDiffResponse {\n return (\n isRecord(value) &&\n isString(value.fromSha) &&\n isString(value.toSha) &&\n isDiffStats(value.stats) &&\n isString(value.rawDiff) &&\n isArrayOf(value.files, isDiffFile)\n );\n}\n\nexport function isResolveResult(value: unknown): value is ResolveResult {\n return (\n isRecord(value) &&\n value.ok === true &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isReviewStatus(value.status) &&\n isResolutionStatus(value.resolutionStatus) &&\n isResolutionCounts(value.comments) &&\n isString(value.path) &&\n isResolutionBundle(value.resolution)\n );\n}\n\nexport function isSubmitReviewRequest(value: unknown): value is SubmitReviewRequest {\n return (\n isRecord(value) &&\n isArrayOf(value.comments, isComment) &&\n isOptional(value.reviewScope, isReviewScope)\n );\n}\n\nexport function isResolutionRequest(value: unknown): value is ResolutionRequest {\n return isRecord(value) && isOptionalString(value.summary) && isOptionalString(value.turn);\n}\n\nexport function isReviewRecord(value: unknown): value is ReviewRecord {\n return (\n isRecord(value) &&\n isReviewMeta(value.meta) &&\n isArrayOf(value.turns, isReviewTurn) &&\n isDiffPayload(value.diff) &&\n isOptional(value.feedback, isFeedbackBundle) &&\n isOptional(value.resolution, isResolutionBundle)\n );\n}\n\nexport function isStoredReviewMeta(value: unknown): value is StoredReviewMeta {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.cwd) &&\n isBaseRef(value.base) &&\n isNullableString(value.branch) &&\n isReviewStatus(value.status) &&\n isString(value.createdAt) &&\n isOptionalString(value.submittedAt) &&\n isOptionalString(value.resolvedAt) &&\n isOptionalString(value.artifactDir) &&\n isOptionalString(value.activeTurnId) &&\n isOptional(value.turns, (turns): turns is ReviewTurnSummary[] =>\n isArrayOf(turns, isReviewTurnSummary)\n ) &&\n isOptionalString(value.feedbackPath) &&\n isOptionalString(value.markdownPath)\n );\n}\n\nfunction isReviewMeta(value: unknown): value is ReviewMeta {\n return isStoredReviewMeta(value) && isString(value.artifactDir);\n}\n\nfunction hasReviewRegistrationFields(\n value: Record<string, unknown>\n): value is Record<string, unknown> & ReviewRegistrationResponseShape {\n return isReviewMeta(value.meta) && isString(value.url);\n}\n\nexport function isDiffPayload(value: unknown): value is DiffPayload {\n return (\n isRecord(value) &&\n isBaseRef(value.base) &&\n isNullableString(value.branch) &&\n isString(value.cwd) &&\n isDiffScope(value.scope) &&\n isDiffStats(value.stats) &&\n isString(value.rawDiff) &&\n isArrayOf(value.files, isDiffFile) &&\n isOptional(value.commitDiffs, (commitDiffs): commitDiffs is CommitDiff[] =>\n isArrayOf(commitDiffs, isCommitDiff)\n ) &&\n isString(value.capturedAt)\n );\n}\n\nexport function isFeedbackBundle(value: unknown): value is FeedbackBundle {\n return (\n isRecord(value) &&\n value.version === 1 &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isString(value.timestamp) &&\n isBaseRef(value.base) &&\n isNullableString(value.branch) &&\n isOptional(value.reviewScope, isReviewScope) &&\n isArrayOf(value.comments, isComment)\n );\n}\n\nexport function isResolutionBundle(value: unknown): value is ResolutionBundle {\n return (\n isRecord(value) &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isResolutionStatus(value.status) &&\n isNullableString(value.summary) &&\n isNullableString(value.resolvedAt) &&\n isArrayOf(value.comments, isResolvedComment)\n );\n}\n\nexport function isReviewEvent(value: unknown): value is ReviewEvent {\n if (!isRecord(value) || !isString(value.reviewId) || !isString(value.type)) {\n return false;\n }\n switch (value.type) {\n case 'review.opened':\n case 'review.cancelled':\n return true;\n case 'review.turn.created':\n return isString(value.turnId) && isNumber(value.turnIndex) && isBoolean(value.reused);\n case 'review.submitted':\n return (\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isRecord(value.counts) &&\n isNumber(value.counts.files) &&\n isNumber(value.counts.comments)\n );\n case 'review.updated':\n return (\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isReviewUpdateReason(value.reason) &&\n isReviewStatus(value.status) &&\n isResolutionStatus(value.resolutionStatus) &&\n isResolutionCounts(value.counts)\n );\n default:\n return false;\n }\n}\n\nexport function isReviewTurnMeta(value: unknown): value is ReviewTurnMeta {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isNumber(value.index) &&\n isReviewStatus(value.status) &&\n isString(value.createdAt) &&\n isOptionalString(value.submittedAt) &&\n isOptionalString(value.resolvedAt) &&\n isString(value.artifactDir) &&\n isString(value.diffPath) &&\n isOptionalString(value.feedbackPath) &&\n isOptionalString(value.markdownPath) &&\n isOptionalString(value.resolvedPath)\n );\n}\n\nfunction isReviewTurnSummary(value: unknown): value is ReviewTurnSummary {\n if (!isRecord(value) || !isReviewTurnMeta(value)) {\n return false;\n }\n return (\n isString(value.capturedAt) && isDiffStats(value.stats) && isResolutionCounts(value.comments)\n );\n}\n\nfunction isReviewTurn(value: unknown): value is ReviewTurn {\n if (!isRecord(value) || !isReviewTurnMeta(value)) {\n return false;\n }\n return (\n isDiffPayload(value.diff) &&\n isOptional(value.feedback, isFeedbackBundle) &&\n isOptional(value.resolution, isResolutionBundle)\n );\n}\n\nfunction isDiffScope(value: unknown): value is DiffPayload['scope'] {\n return (\n isRecord(value) &&\n isOneOf(value.mode, DIFF_SCOPE_MODES) &&\n isNullableString(value.requestedBase) &&\n isBaseRef(value.base) &&\n isDiffRef(value.comparison) &&\n (value.fallbackReason === null || isOneOf(value.fallbackReason, DIFF_FALLBACK_REASONS))\n );\n}\n\nfunction isDiffRef(value: unknown): value is DiffPayload['scope']['comparison'] {\n return isRecord(value) && isString(value.ref) && isNullableString(value.sha);\n}\n\nfunction isBaseRef(value: unknown): value is { ref: string; sha: string } {\n return isRecord(value) && isString(value.ref) && isString(value.sha);\n}\n\nfunction isDiffStats(value: unknown): value is DiffStats {\n return (\n isRecord(value) &&\n isNumber(value.files) &&\n isNumber(value.additions) &&\n isNumber(value.deletions)\n );\n}\n\nfunction isDiffCommit(value: unknown): value is DiffCommit {\n return (\n isRecord(value) &&\n isString(value.sha) &&\n isString(value.shortSha) &&\n isString(value.subject) &&\n isString(value.authorName) &&\n isString(value.authorEmail) &&\n isString(value.authoredAt) &&\n isString(value.committedAt)\n );\n}\n\nfunction isCommitDiff(value: unknown): value is CommitDiff {\n return (\n isRecord(value) &&\n isDiffCommit(value.commit) &&\n isDiffStats(value.stats) &&\n isString(value.rawDiff) &&\n isArrayOf(value.files, isDiffFile)\n );\n}\n\nfunction isReviewScope(value: unknown): value is ReviewScope {\n if (!isRecord(value) || !isOneOf(value.mode, REVIEW_SCOPE_MODES)) {\n return false;\n }\n switch (value.mode) {\n case 'all':\n return true;\n case 'single':\n return isString(value.sha);\n case 'range':\n return isString(value.fromSha) && isString(value.toSha);\n }\n}\n\nfunction isDiffFile(value: unknown): value is DiffFile {\n return (\n isRecord(value) &&\n isString(value.path) &&\n isNullableString(value.oldPath) &&\n isNumber(value.additions) &&\n isNumber(value.deletions) &&\n isBoolean(value.isBinary) &&\n isBoolean(value.isDeleted) &&\n isBoolean(value.isNew) &&\n isBoolean(value.isRenamed) &&\n isNullableString(value.language) &&\n isArrayOf(value.hunks, isDiffHunk)\n );\n}\n\nfunction isDiffHunk(value: unknown): value is DiffHunk {\n return (\n isRecord(value) &&\n isNumber(value.oldStart) &&\n isNumber(value.oldLines) &&\n isNumber(value.newStart) &&\n isNumber(value.newLines) &&\n isString(value.header) &&\n isArrayOf(value.lines, isDiffLine)\n );\n}\n\nfunction isDiffLine(value: unknown): value is DiffLine {\n return (\n isRecord(value) &&\n isOneOf(value.type, DIFF_LINE_TYPES) &&\n isNullableNumber(value.oldLine) &&\n isNullableNumber(value.newLine) &&\n isString(value.content)\n );\n}\n\nfunction isComment(value: unknown): value is Comment {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.filePath) &&\n isNumber(value.startLine) &&\n isNumber(value.endLine) &&\n isOneOf(value.side, SIDES) &&\n isString(value.body) &&\n isString(value.originalSnippet) &&\n isString(value.createdAt)\n );\n}\n\nfunction isResolvedComment(value: unknown): value is ResolvedComment {\n return (\n isRecord(value) &&\n isString(value.commentId) &&\n value.status === 'resolved' &&\n isOptionalString(value.summary) &&\n isString(value.resolvedAt)\n );\n}\n\nfunction isResolutionCounts(value: unknown): value is ResolveResult['comments'] {\n return (\n isRecord(value) && isNumber(value.total) && isNumber(value.resolved) && isNumber(value.open)\n );\n}\n\nfunction isReviewStatus(value: unknown): value is ReviewMeta['status'] {\n return isOneOf(value, REVIEW_STATUSES);\n}\n\nfunction isResolutionStatus(value: unknown): value is ResolutionBundle['status'] {\n return isOneOf(value, RESOLUTION_STATUSES);\n}\n\nfunction isReviewUpdateReason(\n value: unknown\n): value is Extract<ReviewEvent, { type: 'review.updated' }>['reason'] {\n return isOneOf(value, REVIEW_UPDATE_REASONS);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isArrayOf<T>(value: unknown, guard: JsonGuard<T>): value is T[] {\n return Array.isArray(value) && value.every(guard);\n}\n\nfunction isOptional<T>(value: unknown, guard: JsonGuard<T>): value is T | undefined {\n return value === undefined || guard(value);\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\nfunction isOptionalString(value: unknown): value is string | undefined {\n return value === undefined || isString(value);\n}\n\nfunction isNullableString(value: unknown): value is string | null {\n return value === null || isString(value);\n}\n\nfunction isNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nfunction isOptionalNumber(value: unknown): value is number | undefined {\n return value === undefined || isNumber(value);\n}\n\nfunction isNullableNumber(value: unknown): value is number | null {\n return value === null || isNumber(value);\n}\n\nfunction isBoolean(value: unknown): value is boolean {\n return typeof value === 'boolean';\n}\n\nfunction isOneOf<const T extends readonly string[]>(\n value: unknown,\n options: T\n): value is T[number] {\n return typeof value === 'string' && options.includes(value);\n}\n","import { 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 } from '../shared/git-diff';\nimport type { JsonValue } from '../shared/json';\nimport { packageVersion } from '../shared/paths';\nimport { isResolvableReviewStatus } from '../shared/reviews';\nimport type {\n CommitRangeDiffResponse,\n CreateReviewResponse,\n CreateReviewTurnResponse,\n HealthResponse,\n ListReviewsResponse,\n OpenFileResponse,\n OpenResult,\n ResolutionRequest,\n ReviewEvent,\n ReviewMeta,\n ReviewTurnSummary,\n SubmitReviewRequest\n} from '../shared/types';\nimport {\n isCommitRangeDiffRequest,\n isDiffPayload,\n isOpenFileRequest,\n isResolutionRequest,\n isSubmitReviewRequest,\n type JsonGuard,\n parseJsonValue\n} from '../shared/validation';\nimport { openLocalPath } from './local-open';\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}\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 };\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/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/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, 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 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 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 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\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 ResolutionBundle,\n ResolutionCounts,\n ResolvedComment,\n Side\n} from './types';\n\nexport interface LineRange {\n side: Side;\n startLine: number;\n endLine: number;\n}\n\nexport function compareCommentsByLocation(a: Comment, b: Comment): number {\n return (\n a.filePath.localeCompare(b.filePath) ||\n a.startLine - b.startLine ||\n a.endLine - b.endLine ||\n a.side.localeCompare(b.side)\n );\n}\n\nexport function countCommentFiles(comments: Pick<Comment, 'filePath'>[]): number {\n return new Set(comments.map((comment) => comment.filePath)).size;\n}\n\nexport function formatLineRange(\n range: LineRange,\n options: { repeatSideOnEnd?: boolean } = {}\n): string {\n const startLine = Math.min(range.startLine, range.endLine);\n const endLine = Math.max(range.startLine, range.endLine);\n if (startLine === endLine) {\n return `${range.side}${startLine}`;\n }\n const endPrefix = options.repeatSideOnEnd === false ? '' : range.side;\n return `${range.side}${startLine}-${endPrefix}${endLine}`;\n}\n\nexport function resolutionCounts(\n feedback: FeedbackBundle | undefined,\n resolvedComments: ResolvedComment[] = []\n): ResolutionCounts {\n const comments = feedback?.comments ?? [];\n const resolvedIds = new Set(resolvedComments.map((comment) => comment.commentId));\n const resolved = comments.filter((comment) => resolvedIds.has(comment.id)).length;\n return {\n total: comments.length,\n resolved,\n open: comments.length - resolved\n };\n}\n\nexport function reviewResolutionCounts(record: {\n feedback?: FeedbackBundle;\n resolution?: ResolutionBundle;\n}): ResolutionCounts {\n return resolutionCounts(record.feedback, record.resolution?.comments ?? []);\n}\n","import { execa } from 'execa';\nimport { parseUnifiedDiff } from './diff-parser';\nimport { summarizeDiffFiles } from './diff-stats';\nimport type { CommitDiff } 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 = parseUnifiedDiff(rawDiff);\n return {\n stats: summarizeDiffFiles(files),\n rawDiff,\n files\n };\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 { ReviewStatus } from './types';\n\nexport function isResolvableReviewStatus(status: ReviewStatus): boolean {\n return status === 'submitted' || status === 'resolved';\n}\n","import open from 'open';\n\nexport async function openLocalPath(filePath: string): Promise<void> {\n await open(filePath, { wait: false });\n}\n","import { createHash } from 'node:crypto';\nimport type { Dirent } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { ulid } from 'ulid';\nimport { compareCommentsByLocation, countCommentFiles, resolutionCounts } from '../shared/comments';\nimport { formatError, isFileNotFound } from '../shared/errors';\nimport { writeJsonFile, writeTextFile } from '../shared/json';\nimport { serializeFeedbackMarkdown } from '../shared/markdown';\nimport {\n ensureDir,\n globalReviewDiffFile,\n globalReviewDir,\n globalReviewFeedbackFile,\n globalReviewMarkdownFile,\n globalReviewMetaFile,\n globalReviewResolvedFile,\n globalReviewsDir,\n globalReviewTurnDiffFile,\n globalReviewTurnDir,\n globalReviewTurnFeedbackFile,\n globalReviewTurnMarkdownFile,\n globalReviewTurnMetaFile,\n globalReviewTurnResolvedFile,\n globalReviewTurnsDir\n} from '../shared/paths';\nimport { normalizeReviewScope, sameReviewScope } from '../shared/review-scope';\nimport { isResolvableReviewStatus } from '../shared/reviews';\nimport type {\n Comment,\n DiffPayload,\n FeedbackBundle,\n ResolutionBundle,\n ResolvedComment,\n ResolveResult,\n ReviewEvent,\n ReviewMeta,\n ReviewRecord,\n ReviewScope,\n ReviewTurn,\n ReviewTurnMeta,\n ReviewTurnSummary,\n ReviewUpdateReason\n} from '../shared/types';\nimport {\n isDiffPayload,\n isFeedbackBundle,\n isResolutionBundle,\n isReviewTurnMeta,\n isStoredReviewMeta,\n type JsonGuard,\n parseJson,\n type StoredReviewMeta\n} from '../shared/validation';\n\ntype Listener = (event: ReviewEvent) => void;\n\ninterface SubmitResult {\n record: ReviewRecord;\n feedbackPath: string;\n markdownPath: string;\n turn: ReviewTurn;\n}\n\ninterface AppendTurnResult {\n record: ReviewRecord;\n turn: ReviewTurn;\n reused: boolean;\n}\n\nexport class ReviewStore {\n private readonly reviews = new Map<string, ReviewRecord>();\n private readonly listeners = new Map<string, Set<Listener>>();\n\n async create(diff: DiffPayload): Promise<ReviewRecord> {\n const id = ulid();\n const createdAt = new Date().toISOString();\n const turn = createTurn(id, 1, diff, createdAt);\n const meta: ReviewMeta = {\n id,\n cwd: diff.cwd,\n base: diff.base,\n branch: diff.branch,\n status: 'pending',\n createdAt,\n artifactDir: globalReviewDir(id),\n activeTurnId: turn.id\n };\n const record = normalizeRecord({ meta, turns: [turn], diff: turn.diff });\n this.reviews.set(id, record);\n await this.persistInitial(record, turn);\n this.emit({ type: 'review.opened', reviewId: id });\n return record;\n }\n\n async appendTurn(id: string, diff: DiffPayload): Promise<AppendTurnResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n if (record.meta.cwd !== diff.cwd) {\n throw new Error(`Review ${id} belongs to ${record.meta.cwd}, not ${diff.cwd}`);\n }\n\n const latest = latestTurn(record);\n if (latest.status === 'pending') {\n if (diffFingerprint(latest.diff) === diffFingerprint(diff)) {\n this.emit({\n type: 'review.turn.created',\n reviewId: id,\n turnId: latest.id,\n turnIndex: latest.index,\n reused: true\n });\n return { record, turn: latest, reused: true };\n }\n throw new Error(`Review ${id} already has a pending turn`);\n }\n if (latest.status === 'cancelled') {\n throw new Error(`Review ${id} is cancelled and cannot be continued`);\n }\n\n const turn = createTurn(id, latest.index + 1, diff, new Date().toISOString());\n const nextRecord = normalizeRecord({\n ...record,\n meta: { ...record.meta, activeTurnId: turn.id },\n turns: [...record.turns, turn]\n });\n this.reviews.set(id, nextRecord);\n await this.persistInitial(nextRecord, turn);\n this.emit({\n type: 'review.turn.created',\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n reused: false\n });\n return { record: nextRecord, turn, reused: false };\n }\n\n async list(): Promise<ReviewMeta[]> {\n await this.loadAllReviews();\n return Array.from(this.reviews.values())\n .map((record) => record.meta)\n .toSorted((a, b) => a.createdAt.localeCompare(b.createdAt));\n }\n\n async get(id: string): Promise<ReviewRecord | null> {\n return this.reviews.get(id) ?? (await this.loadKnownReview(id));\n }\n\n async getTurn(id: string, turnId: string): Promise<ReviewTurn | null> {\n const record = await this.get(id);\n return record?.turns.find((turn) => turn.id === turnId) ?? null;\n }\n\n async submit(id: string, comments: Comment[], reviewScope?: ReviewScope): Promise<SubmitResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = activeTurn(record);\n const sortedComments = comments.toSorted(compareCommentsByLocation);\n const normalizedReviewScope = normalizeReviewScope(turn.diff, reviewScope);\n if (turn.status !== 'pending') {\n if (\n turn.feedback &&\n sameComments(turn.feedback.comments, sortedComments) &&\n sameReviewScope(turn.feedback.reviewScope, normalizedReviewScope)\n ) {\n return {\n record,\n feedbackPath: requiredPath(turn.feedbackPath, 'feedback path'),\n markdownPath: requiredPath(turn.markdownPath, 'markdown path'),\n turn\n };\n }\n throw new Error(`Review ${id} turn ${turn.index} is ${turn.status} and cannot be submitted`);\n }\n\n const timestamp = new Date().toISOString();\n const feedbackPath = globalReviewTurnFeedbackFile(id, turn.id);\n const markdownPath = globalReviewTurnMarkdownFile(id, turn.id);\n const feedback: FeedbackBundle = {\n version: 1,\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n timestamp,\n base: turn.diff.base,\n branch: turn.diff.branch,\n reviewScope: normalizedReviewScope,\n comments: sortedComments\n };\n const nextTurn: ReviewTurn = {\n ...turn,\n status: 'submitted',\n submittedAt: timestamp,\n feedbackPath,\n markdownPath,\n feedback\n };\n const nextRecord = normalizeRecord(replaceTurn(record, nextTurn));\n this.reviews.set(id, nextRecord);\n\n await ensureDir(globalReviewTurnDir(id, nextTurn.id));\n await Promise.all([\n writeJsonFile(globalReviewTurnMetaFile(id, nextTurn.id), turnMeta(nextTurn)),\n writeJsonFile(feedbackPath, feedback),\n writeTextFile(markdownPath, serializeFeedbackMarkdown(feedback))\n ]);\n await this.persistMeta(nextRecord);\n\n this.emit({\n type: 'review.submitted',\n reviewId: id,\n turnId: nextTurn.id,\n turnIndex: nextTurn.index,\n counts: {\n files: countCommentFiles(feedback.comments),\n comments: feedback.comments.length\n }\n });\n return { record: nextRecord, feedbackPath, markdownPath, turn: nextTurn };\n }\n\n async feedback(id: string): Promise<FeedbackBundle | null> {\n const record = await this.get(id);\n return record?.feedback ?? null;\n }\n\n async markResolved(id: string, summary?: string, turnSelector?: string): Promise<ResolveResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = this.resolveTurnSelector(record, turnSelector);\n this.assertResolvable(turn, id);\n\n const resolvedAt = new Date().toISOString();\n const existingById = new Map(\n (turn.resolution?.comments ?? []).map((comment) => [comment.commentId, comment])\n );\n const comments = this.sortResolvedComments(\n (turn.feedback?.comments ?? []).map((comment) => ({\n ...existingById.get(comment.id),\n commentId: comment.id,\n status: 'resolved' as const,\n resolvedAt: existingById.get(comment.id)?.resolvedAt ?? resolvedAt\n })),\n turn\n );\n const resolution: ResolutionBundle = {\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n status: 'resolved',\n summary: summary ?? turn.resolution?.summary ?? null,\n resolvedAt,\n comments\n };\n const nextTurn: ReviewTurn & { feedback: FeedbackBundle } = {\n ...turn,\n status: 'resolved',\n resolvedAt\n };\n return this.persistResolution(record, nextTurn, resolution, 'review-resolved');\n }\n\n async resolveComment(id: string, commentId: string, summary?: string): Promise<ResolveResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = this.findTurnForComment(record, commentId);\n if (!turn) {\n const currentTurn = activeTurn(record);\n if (!isResolvableReviewStatus(currentTurn.status)) {\n throw new Error(\n `Review ${id} turn ${currentTurn.index} is ${currentTurn.status} and cannot be resolved`\n );\n }\n throw new Error(`Comment ${commentId} not found`);\n }\n this.assertResolvable(turn, id);\n\n const resolvedAt = new Date().toISOString();\n const previous = turn.resolution?.comments.find((comment) => comment.commentId === commentId);\n const nextSummary = summary ?? previous?.summary;\n const nextComment: ResolvedComment = {\n commentId,\n status: 'resolved',\n ...(nextSummary ? { summary: nextSummary } : {}),\n resolvedAt\n };\n const comments = this.sortResolvedComments(\n [\n ...(turn.resolution?.comments ?? []).filter((comment) => comment.commentId !== commentId),\n nextComment\n ],\n turn\n );\n const counts = resolutionCounts(turn.feedback, comments);\n const fullyResolved = counts.total === counts.resolved;\n const resolution: ResolutionBundle = {\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n status: fullyResolved ? 'resolved' : 'partial',\n summary: fullyResolved ? (turn.resolution?.summary ?? null) : null,\n resolvedAt: fullyResolved ? resolvedAt : null,\n comments\n };\n const nextTurn: ReviewTurn & { feedback: FeedbackBundle } = fullyResolved\n ? { ...turn, status: 'resolved', resolvedAt }\n : { ...turn, status: 'submitted', resolvedAt: undefined };\n return this.persistResolution(record, nextTurn, resolution, 'comment-resolved');\n }\n\n async reopenComment(id: string, commentId: string): Promise<ResolveResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = this.findTurnForComment(record, commentId);\n if (!turn) {\n const currentTurn = activeTurn(record);\n if (!isResolvableReviewStatus(currentTurn.status)) {\n throw new Error(\n `Review ${id} turn ${currentTurn.index} is ${currentTurn.status} and cannot be resolved`\n );\n }\n throw new Error(`Comment ${commentId} not found`);\n }\n this.assertResolvable(turn, id);\n\n const comments = this.sortResolvedComments(\n (turn.resolution?.comments ?? []).filter((comment) => comment.commentId !== commentId),\n turn\n );\n const counts = resolutionCounts(turn.feedback, comments);\n const fullyResolved = counts.total > 0 && counts.total === counts.resolved;\n const resolvedAt = fullyResolved ? new Date().toISOString() : null;\n const resolution: ResolutionBundle = {\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n status: fullyResolved ? 'resolved' : 'partial',\n summary: fullyResolved ? (turn.resolution?.summary ?? null) : null,\n resolvedAt,\n comments\n };\n const nextTurn: ReviewTurn & { feedback: FeedbackBundle } = fullyResolved\n ? { ...turn, status: 'resolved', resolvedAt: resolvedAt ?? undefined }\n : { ...turn, status: 'submitted', resolvedAt: undefined };\n return this.persistResolution(record, nextTurn, resolution, 'comment-reopened');\n }\n\n subscribe(reviewId: string, listener: Listener): () => void {\n const listeners = this.listeners.get(reviewId) ?? new Set<Listener>();\n listeners.add(listener);\n this.listeners.set(reviewId, listeners);\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0) {\n this.listeners.delete(reviewId);\n }\n };\n }\n\n private emit(event: ReviewEvent): void {\n for (const listener of this.listeners.get(event.reviewId) ?? []) {\n listener(event);\n }\n }\n\n private async persistInitial(record: ReviewRecord, turn: ReviewTurn): Promise<void> {\n await ensureDir(turn.artifactDir);\n await Promise.all([\n writeJsonFile(globalReviewTurnMetaFile(record.meta.id, turn.id), turnMeta(turn)),\n writeJsonFile(turn.diffPath, turn.diff)\n ]);\n await this.persistMeta(record);\n }\n\n private async persistMeta(record: ReviewRecord): Promise<void> {\n await ensureDir(globalReviewDir(record.meta.id));\n await writeJsonFile(globalReviewMetaFile(record.meta.id), record.meta);\n }\n\n private async loadKnownReview(id: string): Promise<ReviewRecord | null> {\n const existing = this.reviews.get(id);\n if (existing) {\n return existing;\n }\n\n return this.loadReview(id);\n }\n\n private async loadAllReviews(): Promise<void> {\n let entries: Dirent[];\n try {\n entries = await readdir(globalReviewsDir(), { withFileTypes: true });\n } catch (error) {\n if (isFileNotFound(error)) {\n return;\n }\n throw new Error(\n `Could not read reviews directory at ${globalReviewsDir()}: ${formatError(error)}`,\n {\n cause: error\n }\n );\n }\n\n const reviewLoads: Array<Promise<ReviewRecord | null>> = [];\n for (const entry of entries) {\n if (entry.isDirectory()) {\n reviewLoads.push(this.loadReview(entry.name));\n }\n }\n await Promise.all(reviewLoads);\n }\n\n private async loadReview(id: string): Promise<ReviewRecord | null> {\n const metaPath = globalReviewMetaFile(id);\n let metaRaw: string;\n\n try {\n metaRaw = await readFile(metaPath, 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return this.loadReviewFromTurnsOnly(id);\n }\n throw new Error(`Could not load review ${id}: ${formatError(error)}`, { cause: error });\n }\n\n const storedMeta = parseJsonFile(metaRaw, isStoredReviewMeta, 'review metadata', metaPath);\n const persistedTurns = await this.loadPersistedTurns(id);\n const legacyTurn = await this.loadLegacyTurn(id, storedMeta);\n const turns = mergeRecoveredTurns(legacyTurn, persistedTurns);\n if (turns.length === 0) {\n throw new Error(`Review ${id} has no recoverable turns`);\n }\n\n const latest = latestTurn({ turns } as ReviewRecord);\n const record = normalizeRecord({\n meta: {\n ...storedMeta,\n artifactDir: storedMeta.artifactDir ?? globalReviewDir(id),\n activeTurnId: latest.id\n },\n turns,\n diff: latest.diff\n });\n this.reviews.set(id, record);\n return record;\n }\n\n private async loadReviewFromTurnsOnly(id: string): Promise<ReviewRecord | null> {\n const turns = await this.loadPersistedTurns(id);\n if (turns.length === 0) {\n return null;\n }\n\n const latest = latestTurn({ turns });\n const record = normalizeRecord({\n meta: {\n id,\n cwd: latest.diff.cwd,\n base: latest.diff.base,\n branch: latest.diff.branch,\n status: latest.status,\n createdAt: turns[0]?.createdAt ?? latest.createdAt,\n artifactDir: globalReviewDir(id),\n activeTurnId: latest.id\n },\n turns,\n diff: latest.diff\n });\n this.reviews.set(id, record);\n await this.persistMeta(record);\n return record;\n }\n\n private async loadPersistedTurns(id: string): Promise<ReviewTurn[]> {\n let entries: Dirent[];\n try {\n entries = await readdir(globalReviewTurnsDir(id), { withFileTypes: true });\n } catch (error) {\n if (isFileNotFound(error)) {\n return [];\n }\n throw new Error(`Could not read review turns for ${id}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n const turns: ReviewTurn[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) {\n continue;\n }\n const turn = await this.loadPersistedTurn(id, entry.name);\n if (turn) {\n turns.push(turn);\n }\n }\n\n return turns.toSorted((a, b) => a.index - b.index);\n }\n\n private async loadPersistedTurn(id: string, turnId: string): Promise<ReviewTurn | null> {\n const metaPath = globalReviewTurnMetaFile(id, turnId);\n const diffPath = globalReviewTurnDiffFile(id, turnId);\n let metaRaw: string;\n let diffRaw: string;\n\n try {\n [metaRaw, diffRaw] = await Promise.all([\n readFile(metaPath, 'utf8'),\n readFile(diffPath, 'utf8')\n ]);\n } catch (error) {\n if (isFileNotFound(error)) {\n return null;\n }\n throw new Error(`Could not load review ${id} turn ${turnId}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n const meta = parseJsonFile(metaRaw, isReviewTurnMeta, 'review turn metadata', metaPath);\n const diff = parseJsonFile(diffRaw, isDiffPayload, 'review turn diff', diffPath);\n const [feedback, resolution] = await Promise.all([\n readOptionalJsonFile(\n globalReviewTurnFeedbackFile(id, turnId),\n isFeedbackBundle,\n 'review feedback'\n ),\n readOptionalJsonFile(\n globalReviewTurnResolvedFile(id, turnId),\n isResolutionBundle,\n 'review resolution'\n )\n ]);\n\n return reconcileTurn(meta, diff, feedback, resolution);\n }\n\n private async loadLegacyTurn(\n id: string,\n storedMeta: StoredReviewMeta\n ): Promise<ReviewTurn | null> {\n const diffPath = globalReviewDiffFile(id);\n let diffRaw: string;\n try {\n diffRaw = await readFile(diffPath, 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return null;\n }\n throw new Error(`Could not load legacy review ${id}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n const diff = parseJsonFile(diffRaw, isDiffPayload, 'review diff', diffPath);\n const [feedback, resolution] = await Promise.all([\n readOptionalJsonFile(globalReviewFeedbackFile(id), isFeedbackBundle, 'review feedback'),\n readOptionalJsonFile(globalReviewResolvedFile(id), isResolutionBundle, 'review resolution')\n ]);\n const artifactDir = storedMeta.artifactDir ?? globalReviewDir(id);\n const legacySummary =\n storedMeta.turns?.find(\n (turn) => turn.artifactDir === artifactDir || turn.diffPath === diffPath\n ) ??\n storedMeta.turns?.find((turn) => turn.index === 1) ??\n storedMeta.turns?.[0];\n const meta: ReviewTurnMeta = {\n id: legacySummary?.id ?? storedMeta.activeTurnId ?? 'turn-1',\n index: legacySummary?.index ?? 1,\n status: legacySummary?.status ?? storedMeta.status,\n createdAt: legacySummary?.createdAt ?? storedMeta.createdAt,\n submittedAt: legacySummary?.submittedAt ?? storedMeta.submittedAt,\n resolvedAt: legacySummary?.resolvedAt ?? storedMeta.resolvedAt,\n artifactDir: legacySummary?.artifactDir ?? artifactDir,\n diffPath,\n ...(feedback\n ? { feedbackPath: globalReviewFeedbackFile(id), markdownPath: globalReviewMarkdownFile(id) }\n : {}),\n ...(resolution ? { resolvedPath: globalReviewResolvedFile(id) } : {})\n };\n return reconcileTurn(meta, diff, feedback, resolution);\n }\n\n private assertResolvable(\n turn: ReviewTurn,\n id: string\n ): asserts turn is ReviewTurn & {\n feedback: FeedbackBundle;\n } {\n if (!isResolvableReviewStatus(turn.status)) {\n throw new Error(`Review ${id} turn ${turn.index} is ${turn.status} and cannot be resolved`);\n }\n if (!turn.feedback) {\n throw new Error(`Review ${id} turn ${turn.index} has no submitted feedback`);\n }\n }\n\n private resolveTurnSelector(record: ReviewRecord, selector?: string): ReviewTurn {\n if (!selector) {\n return activeTurn(record);\n }\n const turn =\n record.turns.find((candidate) => candidate.id === selector) ??\n record.turns.find((candidate) => String(candidate.index) === selector);\n if (!turn) {\n throw new Error(`Turn ${selector} not found in review ${record.meta.id}`);\n }\n return turn;\n }\n\n private findTurnForComment(record: ReviewRecord, commentId: string): ReviewTurn | null {\n return (\n [...record.turns]\n .reverse()\n .find((candidate) =>\n candidate.feedback?.comments.some((comment) => comment.id === commentId)\n ) ?? null\n );\n }\n\n private async persistResolution(\n record: ReviewRecord,\n turn: ReviewTurn & { feedback: FeedbackBundle },\n resolution: ResolutionBundle,\n reason: ReviewUpdateReason\n ): Promise<ResolveResult> {\n const resolvedPath = globalReviewTurnResolvedFile(record.meta.id, turn.id);\n const nextTurn: ReviewTurn = {\n ...turn,\n resolvedPath,\n resolution\n };\n const nextRecord = normalizeRecord(replaceTurn(record, nextTurn));\n this.reviews.set(record.meta.id, nextRecord);\n await ensureDir(globalReviewTurnDir(record.meta.id, nextTurn.id));\n await Promise.all([\n writeJsonFile(resolvedPath, resolution),\n writeJsonFile(globalReviewTurnMetaFile(record.meta.id, nextTurn.id), turnMeta(nextTurn))\n ]);\n await this.persistMeta(nextRecord);\n const result: ResolveResult = {\n ok: true,\n reviewId: record.meta.id,\n turnId: nextTurn.id,\n turnIndex: nextTurn.index,\n status: nextTurn.status,\n resolutionStatus: resolution.status,\n comments: resolutionCounts(nextTurn.feedback, resolution.comments),\n path: resolvedPath,\n resolution\n };\n this.emit({\n type: 'review.updated',\n reviewId: record.meta.id,\n turnId: nextTurn.id,\n turnIndex: nextTurn.index,\n reason,\n status: result.status,\n resolutionStatus: result.resolutionStatus,\n counts: result.comments\n });\n return result;\n }\n\n private sortResolvedComments(\n comments: ResolvedComment[],\n turn: ReviewTurn & { feedback: FeedbackBundle }\n ): ResolvedComment[] {\n const feedbackIndex = new Map(\n turn.feedback.comments.map((comment, index) => [comment.id, index] as const)\n );\n return comments\n .map((comment) => ({ comment, index: feedbackIndex.get(comment.commentId) }))\n .filter(\n (entry): entry is { comment: ResolvedComment; index: number } => entry.index !== undefined\n )\n .sort((a, b) => a.index - b.index)\n .map(({ comment }) => comment);\n }\n}\n\nfunction createTurn(\n reviewId: string,\n index: number,\n diff: DiffPayload,\n createdAt: string\n): ReviewTurn {\n const id = ulid();\n return {\n id,\n index,\n status: 'pending',\n createdAt,\n artifactDir: globalReviewTurnDir(reviewId, id),\n diffPath: globalReviewTurnDiffFile(reviewId, id),\n diff\n };\n}\n\nfunction normalizeRecord(record: Pick<ReviewRecord, 'meta' | 'turns' | 'diff'>): ReviewRecord {\n const turns = record.turns.toSorted((a, b) => a.index - b.index);\n const active =\n turns.find((turn) => turn.id === record.meta.activeTurnId) ?? turns[turns.length - 1];\n const meta: ReviewMeta = {\n ...record.meta,\n base: active.diff.base,\n branch: active.diff.branch,\n status: active.status,\n submittedAt: active.submittedAt,\n resolvedAt: active.resolvedAt,\n artifactDir: record.meta.artifactDir ?? globalReviewDir(record.meta.id),\n activeTurnId: active.id,\n turns: turns.map(turnSummary),\n feedbackPath: active.feedbackPath,\n markdownPath: active.markdownPath\n };\n return {\n meta,\n turns,\n diff: active.diff,\n ...(active.feedback ? { feedback: active.feedback } : {}),\n ...(active.resolution ? { resolution: active.resolution } : {})\n };\n}\n\nfunction replaceTurn(record: ReviewRecord, nextTurn: ReviewTurn): ReviewRecord {\n return {\n ...record,\n turns: record.turns.map((turn) => (turn.id === nextTurn.id ? nextTurn : turn))\n };\n}\n\nfunction activeTurn(record: ReviewRecord): ReviewTurn {\n return (\n record.turns.find((turn) => turn.id === record.meta.activeTurnId) ??\n record.turns[record.turns.length - 1]\n );\n}\n\nfunction latestTurn(record: Pick<ReviewRecord, 'turns'>): ReviewTurn {\n return record.turns.toSorted((a, b) => a.index - b.index)[record.turns.length - 1];\n}\n\nfunction turnMeta(turn: ReviewTurn): ReviewTurnMeta {\n return {\n id: turn.id,\n index: turn.index,\n status: turn.status,\n createdAt: turn.createdAt,\n submittedAt: turn.submittedAt,\n resolvedAt: turn.resolvedAt,\n artifactDir: turn.artifactDir,\n diffPath: turn.diffPath,\n feedbackPath: turn.feedbackPath,\n markdownPath: turn.markdownPath,\n resolvedPath: turn.resolvedPath\n };\n}\n\nfunction turnSummary(turn: ReviewTurn): ReviewTurnSummary {\n return {\n ...turnMeta(turn),\n capturedAt: turn.diff.capturedAt,\n stats: turn.diff.stats,\n comments: resolutionCounts(turn.feedback, turn.resolution?.comments ?? [])\n };\n}\n\nfunction reconcileTurn(\n meta: ReviewTurnMeta,\n diff: DiffPayload,\n feedback?: FeedbackBundle,\n resolution?: ResolutionBundle\n): ReviewTurn {\n const status =\n resolution?.status === 'resolved' ? 'resolved' : feedback ? 'submitted' : 'pending';\n return {\n ...meta,\n status,\n submittedAt: feedback?.timestamp ?? meta.submittedAt,\n resolvedAt: status === 'resolved' ? (resolution?.resolvedAt ?? meta.resolvedAt) : undefined,\n feedbackPath: feedback\n ? (meta.feedbackPath ?? path.join(meta.artifactDir, 'feedback.json'))\n : undefined,\n markdownPath: feedback\n ? (meta.markdownPath ?? path.join(meta.artifactDir, 'feedback.md'))\n : undefined,\n resolvedPath: resolution\n ? (meta.resolvedPath ?? path.join(meta.artifactDir, 'resolved.json'))\n : undefined,\n diff,\n ...(feedback ? { feedback } : {}),\n ...(resolution ? { resolution } : {})\n };\n}\n\nfunction mergeRecoveredTurns(\n legacyTurn: ReviewTurn | null,\n persistedTurns: ReviewTurn[]\n): ReviewTurn[] {\n const turns =\n legacyTurn &&\n !persistedTurns.some((turn) => turn.id === legacyTurn.id || turn.index === legacyTurn.index)\n ? [legacyTurn, ...persistedTurns]\n : persistedTurns;\n return turns.toSorted((a, b) => a.index - b.index);\n}\n\nfunction diffFingerprint(diff: DiffPayload): string {\n return createHash('sha256')\n .update(\n JSON.stringify({\n base: diff.base,\n branch: diff.branch,\n cwd: diff.cwd,\n scope: diff.scope,\n rawDiff: diff.rawDiff\n })\n )\n .digest('hex');\n}\n\nfunction sameComments(left: Comment[], right: Comment[]): boolean {\n return (\n JSON.stringify(left.toSorted(compareCommentsByLocation)) ===\n JSON.stringify(right.toSorted(compareCommentsByLocation))\n );\n}\n\nfunction requiredPath(value: string | undefined, label: string): string {\n if (!value) {\n throw new Error(`Submitted review is missing ${label}`);\n }\n return value;\n}\n\nasync function readOptionalJsonFile<T>(\n filePath: string,\n guard: JsonGuard<T>,\n label: string\n): Promise<T | undefined> {\n let raw: string;\n try {\n raw = await readFile(filePath, 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return undefined;\n }\n throw new Error(`Could not read ${label} at ${filePath}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n return parseJsonFile(raw, guard, label, filePath);\n}\n\nfunction parseJsonFile<T>(raw: string, guard: JsonGuard<T>, label: string, filePath: string): T {\n try {\n return parseJson(raw, guard, label);\n } catch (error) {\n throw new Error(`Invalid ${label} at ${filePath}: ${formatError(error)}`, { cause: error });\n }\n}\n\nexport const reviewStore = new ReviewStore();\n","import type { CommitDiff, DiffPayload, ReviewScope } from './types';\n\nconst ALL_REVIEW_SCOPE: ReviewScope = { mode: 'all' };\n\nexport function normalizeReviewScope(\n diff: Pick<DiffPayload, 'commitDiffs'>,\n scope: ReviewScope = ALL_REVIEW_SCOPE\n): ReviewScope {\n if (scope.mode === 'all') {\n return ALL_REVIEW_SCOPE;\n }\n\n const commitDiffs = diff.commitDiffs ?? [];\n if (commitDiffs.length === 0) {\n throw new Error('Review scope requires a review with per-commit diffs');\n }\n\n if (scope.mode === 'single') {\n const commit = commitDiffs.find((commitDiff) => commitDiff.commit.sha === scope.sha);\n if (!commit) {\n throw new Error('Review scope must use commits from this review');\n }\n return { mode: 'single', sha: commit.commit.sha };\n }\n\n const fromIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === scope.fromSha);\n const toIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === scope.toSha);\n if (fromIndex < 0 || toIndex < 0) {\n throw new Error('Review scope must use commits from this review');\n }\n if (fromIndex > toIndex) {\n throw new Error('Review scope range must be in review order');\n }\n return {\n mode: 'range',\n fromSha: commitDiffs[fromIndex].commit.sha,\n toSha: commitDiffs[toIndex].commit.sha\n };\n}\n\nexport function sameReviewScope(left?: ReviewScope, right?: ReviewScope): boolean {\n return JSON.stringify(left ?? ALL_REVIEW_SCOPE) === JSON.stringify(right ?? ALL_REVIEW_SCOPE);\n}\n\nexport function reviewScopeLabel(\n scope: ReviewScope = ALL_REVIEW_SCOPE,\n commitDiffs: CommitDiff[] = []\n): string {\n if (scope.mode === 'all') {\n return 'All commits';\n }\n if (scope.mode === 'single') {\n const commit = commitDiffs.find((commitDiff) => commitDiff.commit.sha === scope.sha);\n return commit\n ? `${commit.commit.shortSha} ${commit.commit.subject}`\n : `Commit ${shortSha(scope.sha)}`;\n }\n\n const fromIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === scope.fromSha);\n const toIndex = commitDiffs.findIndex((commitDiff) => commitDiff.commit.sha === scope.toSha);\n if (fromIndex >= 0 && toIndex >= fromIndex) {\n const count = toIndex - fromIndex + 1;\n return `${count} commits · ${commitDiffs[fromIndex].commit.shortSha} to ${\n commitDiffs[toIndex].commit.shortSha\n }`;\n }\n return `Commit range ${shortSha(scope.fromSha)} to ${shortSha(scope.toSha)}`;\n}\n\nfunction shortSha(sha: string): string {\n return sha.slice(0, 7);\n}\n","import { compareCommentsByLocation, formatLineRange } from './comments';\nimport { languageForPath } from './language';\nimport { reviewScopeLabel } from './review-scope';\nimport type { FeedbackBundle } from './types';\n\nfunction fenceFor(snippet: string): string {\n let fence = '```';\n while (snippet.includes(fence)) {\n fence += '`';\n }\n return fence;\n}\n\nfunction languageForSnippet(filePath: string, snippet: string): string {\n const lines = snippet.split('\\n').filter((line) => line.length > 0);\n const looksLikeUnifiedDiff =\n lines.length > 0 &&\n lines.some((line) => line.startsWith('+') || line.startsWith('-')) &&\n lines.every((line) => line.startsWith('+') || line.startsWith('-') || line.startsWith(' '));\n return looksLikeUnifiedDiff ? 'diff' : (languageForPath(filePath) ?? '');\n}\n\nexport function serializeFeedbackMarkdown(bundle: FeedbackBundle): string {\n const comments = bundle.comments.toSorted(compareCommentsByLocation);\n const commentsByFile = new Map<string, typeof comments>();\n const files: string[] = [];\n for (const comment of comments) {\n const fileComments = commentsByFile.get(comment.filePath);\n if (fileComments) {\n fileComments.push(comment);\n } else {\n commentsByFile.set(comment.filePath, [comment]);\n files.push(comment.filePath);\n }\n }\n const lines: string[] = [\n `# Gloss feedback - ${bundle.timestamp}`,\n `Review: ${bundle.reviewId}`,\n ...(bundle.turnIndex ? [`Turn: ${bundle.turnIndex} (${bundle.turnId ?? 'unknown'})`] : []),\n ...(bundle.reviewScope ? [`Review scope: ${reviewScopeLabel(bundle.reviewScope)}`] : []),\n `Base: ${bundle.base.ref} (${bundle.base.sha.slice(0, 7)}) Branch: ${bundle.branch ?? '(detached)'}`,\n `Files: ${files.length} Comments: ${comments.length}`,\n ''\n ];\n\n for (const filePath of files) {\n lines.push(`## ${filePath}`, '');\n for (const comment of commentsByFile.get(filePath) ?? []) {\n const snippet = comment.originalSnippet.trimEnd();\n const firstSnippetLine = firstNonEmptyLine(snippet);\n const heading =\n comment.startLine === comment.endLine && firstSnippetLine\n ? `### ${formatLineRange(comment)} - \\`${firstSnippetLine.trim().slice(0, 80)}\\``\n : `### ${formatLineRange(comment)}`;\n lines.push(heading, comment.body.trim(), '');\n if (snippet) {\n const fence = fenceFor(snippet);\n lines.push(`${fence}${languageForSnippet(comment.filePath, snippet)}`, snippet, fence, '');\n }\n }\n }\n\n return `${lines.join('\\n').trimEnd()}\\n`;\n}\n\nfunction firstNonEmptyLine(text: string): string | undefined {\n for (const line of text.split('\\n')) {\n if (line.trim().length > 0) {\n return line;\n }\n }\n return undefined;\n}\n"],"mappings":"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","names":["rm","path","readFile","path","path","readFile","path","readFile","path","origin","turnSummary","path","readFile","rm"]}
|
|
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/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/reviews.ts","../../src/server/local-open.ts","../../src/server/store.ts","../../src/shared/cleanup.ts","../../src/shared/review-scope.ts","../../src/shared/markdown.ts","../../src/server/maintenance.ts"],"sourcesContent":["import { rm } from 'node:fs/promises';\nimport { serve } from '@hono/node-server';\nimport { globalServerFile, globalStateDir, packageVersion } from '../shared/paths';\nimport { readServerInfo, writeServerInfo } from '../shared/server-info';\nimport { createApp } from './index';\nimport { runStartupCleanup } from './maintenance';\nimport { reviewStore } from './store';\n\nconst port = Number(process.env.GLOSS_PORT ?? '0');\nconst idleTimeoutMs = Number(process.env.GLOSS_IDLE_TIMEOUT_MS ?? '120000');\n\nif (!port) {\n throw new Error('GLOSS_PORT is required');\n}\n\nconst origin = `http://localhost:${port}`;\nconst eventStreams = new Set<() => void>();\nlet idleTimer: NodeJS.Timeout | null = null;\nlet shuttingDown = false;\n\nconst server = serve({\n fetch: createApp(origin, {\n onReviewActivity: () => {\n void scheduleIdleShutdown();\n },\n registerEventStream: (close) => {\n eventStreams.add(close);\n return () => {\n eventStreams.delete(close);\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});\n\nawait runStartupCleanup();\nawait scheduleIdleShutdown();\n\nfor (const signal of ['SIGTERM', 'SIGINT', 'SIGHUP'] as const) {\n process.on(signal, () => {\n void shutdown(0);\n });\n}\n\nasync function scheduleIdleShutdown(): Promise<void> {\n if (shuttingDown || idleTimeoutMs <= 0) {\n return;\n }\n\n const activeReviews = await countActiveReviews();\n if (activeReviews > 0) {\n if (idleTimer) {\n clearTimeout(idleTimer);\n idleTimer = null;\n }\n return;\n }\n\n if (!idleTimer) {\n idleTimer = setTimeout(() => {\n idleTimer = null;\n void shutdownIfIdle();\n }, idleTimeoutMs);\n }\n}\n\nasync function shutdownIfIdle(): Promise<void> {\n if ((await countActiveReviews()) > 0) {\n await scheduleIdleShutdown();\n return;\n }\n await shutdown(0);\n}\n\nasync function countActiveReviews(): Promise<number> {\n const reviews = await reviewStore.list();\n return reviews.filter((review) => review.status === 'pending').length;\n}\n\nasync function shutdown(exitCode: number): Promise<void> {\n if (shuttingDown) {\n return;\n }\n shuttingDown = true;\n if (idleTimer) {\n clearTimeout(idleTimer);\n idleTimer = null;\n }\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 await rm(globalServerFile(), { force: true });\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 globalLogDir(): string {\n return path.join(globalStateDir(), 'logs');\n}\n\nexport function globalServerLogFile(): string {\n return path.join(globalLogDir(), 'server.log');\n}\n\nexport function globalReviewsDir(): string {\n return path.join(globalStateDir(), 'reviews');\n}\n\nexport function globalReviewDir(reviewId: string): string {\n return path.join(globalReviewsDir(), reviewId);\n}\n\nexport function globalReviewTurnsDir(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'turns');\n}\n\nexport function globalReviewTurnDir(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnsDir(reviewId), turnId);\n}\n\nexport function globalReviewTurnMetaFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'turn.json');\n}\n\nexport function globalReviewTurnDiffFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'diff.json');\n}\n\nexport function globalReviewTurnFeedbackFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'feedback.json');\n}\n\nexport function globalReviewTurnMarkdownFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'feedback.md');\n}\n\nexport function globalReviewTurnResolvedFile(reviewId: string, turnId: string): string {\n return path.join(globalReviewTurnDir(reviewId, turnId), 'resolved.json');\n}\n\nexport function globalReviewMetaFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'meta.json');\n}\n\nexport function globalReviewDiffFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'diff.json');\n}\n\nexport function globalReviewFeedbackFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'feedback.json');\n}\n\nexport function globalReviewMarkdownFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'feedback.md');\n}\n\nexport function globalReviewResolvedFile(reviewId: string): string {\n return path.join(globalReviewDir(reviewId), 'resolved.json');\n}\n\nexport async function ensureDir(dir: string): Promise<void> {\n await mkdir(dir, { recursive: true });\n}\n","{\n \"name\": \"getgloss\",\n \"version\": \"0.8.2\",\n \"description\": \"Local browser-based diff review for coding-agent loops.\",\n \"type\": \"module\",\n \"packageManager\": \"pnpm@10.33.2\",\n \"bin\": {\n \"getgloss\": \"./dist/cli/index.js\",\n \"gloss\": \"./dist/cli/index.js\"\n },\n \"files\": [\n \"dist\",\n \"skill\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"pnpm build:web && pnpm build:node\",\n \"build:web\": \"vite build\",\n \"build:node\": \"tsup\",\n \"check\": \"biome check .\",\n \"format\": \"biome format --write .\",\n \"prepack\": \"pnpm build\",\n \"dev:web\": \"vite --host 127.0.0.1\",\n \"setup\": \"tsx scripts/dev-cli.ts\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"dependencies\": {\n \"@hono/node-server\": \"1.19.14\",\n \"@shikijs/langs\": \"4.1.0\",\n \"@shikijs/themes\": \"4.1.0\",\n \"@tailwindcss/vite\": \"4.3.0\",\n \"commander\": \"14.0.3\",\n \"execa\": \"9.6.1\",\n \"get-port\": \"7.2.0\",\n \"hono\": \"4.12.21\",\n \"lucide-react\": \"1.16.0\",\n \"open\": \"10.2.0\",\n \"react\": \"19.2.6\",\n \"react-dom\": \"19.2.6\",\n \"shiki\": \"4.1.0\",\n \"ulid\": \"3.0.2\",\n \"zustand\": \"5.0.13\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"2.4.15\",\n \"@types/node\": \"24.12.4\",\n \"@types/react\": \"19.2.15\",\n \"@types/react-dom\": \"19.2.3\",\n \"@vitejs/plugin-react\": \"4.7.0\",\n \"tailwindcss\": \"4.3.0\",\n \"tsup\": \"8.5.1\",\n \"tsx\": \"4.22.3\",\n \"typescript\": \"5.9.3\",\n \"vite\": \"6.4.2\",\n \"vitest\": \"3.2.4\"\n },\n \"keywords\": [\n \"diff\",\n \"review\",\n \"coding-agents\"\n ],\n \"author\": \"Raj Joshi\",\n \"license\": \"MIT\",\n \"homepage\": \"https://getgloss.dev\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/iamrajjoshi/gloss.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/iamrajjoshi/gloss/issues\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { formatError, isFileNotFound } from './errors';\nimport { writeJsonFile } from './json';\nimport { ensureDir, globalServerFile, globalStateDir } from './paths';\nimport type { ServerInfo } from './types';\nimport { isServerInfo, parseJson } from './validation';\n\nexport async function readServerInfo(): Promise<ServerInfo | null> {\n let raw: string;\n try {\n raw = await readFile(globalServerFile(), 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return null;\n }\n throw new Error(`Could not read server info at ${globalServerFile()}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n try {\n return parseJson(raw, isServerInfo, 'server info');\n } catch (error) {\n throw new Error(`Invalid server info at ${globalServerFile()}: ${formatError(error)}`, {\n cause: error\n });\n }\n}\n\nexport async function writeServerInfo(info: ServerInfo): Promise<void> {\n await ensureDir(globalStateDir());\n await writeJsonFile(globalServerFile(), info);\n}\n","export function formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport function isFileNotFound(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n","import { randomUUID } from 'node:crypto';\nimport { rename, rm, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type {\n DiffPayload,\n FeedbackBundle,\n ResolutionBundle,\n ReviewMeta,\n ReviewTurnMeta,\n ServerInfo\n} from './types';\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | { [key: string]: JsonValue }\n | JsonValue[];\n\ntype PersistedJson =\n | ServerInfo\n | ReviewMeta\n | ReviewTurnMeta\n | DiffPayload\n | FeedbackBundle\n | ResolutionBundle;\n\nfunction serializeJson(value: PersistedJson): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nexport async function writeJsonFile(filePath: string, value: PersistedJson): Promise<void> {\n await writeTextFile(filePath, serializeJson(value));\n}\n\nexport async function writeTextFile(filePath: string, value: string): Promise<void> {\n const tempPath = path.join(\n path.dirname(filePath),\n `.${path.basename(filePath)}.${process.pid}.${randomUUID()}.tmp`\n );\n try {\n await writeFile(tempPath, value);\n await rename(tempPath, filePath);\n } catch (error) {\n await rm(tempPath, { force: true }).catch(() => undefined);\n throw error;\n }\n}\n","export const SIDES = ['L', 'R'] as const;\n\nexport type Side = (typeof SIDES)[number];\n\nexport const REVIEW_STATUSES = ['pending', 'submitted', 'cancelled', 'resolved'] as const;\n\nexport type ReviewStatus = (typeof REVIEW_STATUSES)[number];\n\nexport interface ClearReviewEntry {\n reviewId: string;\n status: ReviewStatus;\n artifactDir: string;\n lastActivityAt: string;\n}\n\nexport interface ClearReviewSkipped {\n reviewId: string;\n artifactDir: string;\n reason: string;\n}\n\nexport interface ClearReviewsRequest {\n olderThanDays?: number;\n dryRun?: boolean;\n}\n\nexport interface ClearReviewsResult {\n reviewsDir: string;\n cutoff: string;\n olderThanDays: number;\n dryRun: boolean;\n candidates: ClearReviewEntry[];\n deleted: ClearReviewEntry[];\n skipped: ClearReviewSkipped[];\n counts: {\n candidates: number;\n deleted: number;\n skipped: number;\n };\n}\n\nexport interface Comment {\n id: string;\n filePath: string;\n startLine: number;\n endLine: number;\n side: Side;\n body: string;\n originalSnippet: string;\n createdAt: string;\n}\n\nexport const DIFF_LINE_TYPES = ['context', 'add', 'delete'] as const;\n\nexport type DiffLineType = (typeof DIFF_LINE_TYPES)[number];\n\nexport interface DiffLine {\n type: DiffLineType;\n oldLine: number | null;\n newLine: number | null;\n content: string;\n}\n\nexport interface DiffHunk {\n oldStart: number;\n oldLines: number;\n newStart: number;\n newLines: number;\n header: string;\n lines: DiffLine[];\n}\n\nexport interface DiffFile {\n path: string;\n oldPath: string | null;\n additions: number;\n deletions: number;\n isBinary: boolean;\n isDeleted: boolean;\n isNew: boolean;\n isRenamed: boolean;\n language: string | null;\n hunks: DiffHunk[];\n}\n\nexport const DIFF_SCOPE_MODES = ['working', 'branch', 'explicit'] as const;\n\nexport type DiffScopeMode = (typeof DIFF_SCOPE_MODES)[number];\n\nexport const DIFF_FALLBACK_REASONS = ['working-tree-clean', 'missing-branch-base'] as const;\n\nexport type DiffFallbackReason = (typeof DIFF_FALLBACK_REASONS)[number] | null;\n\nexport interface BaseRef {\n ref: string;\n sha: string;\n}\n\nexport interface DiffRef {\n ref: string;\n sha: string | null;\n}\n\nexport interface DiffStats {\n files: number;\n additions: number;\n deletions: number;\n}\n\nexport interface DiffCommit {\n sha: string;\n shortSha: string;\n subject: string;\n authorName: string;\n authorEmail: string;\n authoredAt: string;\n committedAt: string;\n}\n\nexport interface CommitDiff {\n commit: DiffCommit;\n stats: DiffStats;\n rawDiff: string;\n files: DiffFile[];\n}\n\nexport interface CommitRangeDiffRequest {\n fromSha: string;\n toSha: string;\n turnId?: string;\n}\n\nexport interface CommitRangeDiffResponse {\n fromSha: string;\n toSha: string;\n stats: DiffStats;\n rawDiff: string;\n files: DiffFile[];\n}\n\nexport const REVIEW_SCOPE_MODES = ['all', 'single', 'range'] as const;\n\nexport type ReviewScope =\n | { mode: 'all' }\n | { mode: 'single'; sha: string }\n | { mode: 'range'; fromSha: string; toSha: string };\n\ninterface DiffScope {\n mode: DiffScopeMode;\n requestedBase: string | null;\n base: BaseRef;\n comparison: DiffRef;\n fallbackReason: DiffFallbackReason;\n}\n\nexport interface DiffPayload {\n base: BaseRef;\n branch: string | null;\n cwd: string;\n scope: DiffScope;\n stats: DiffStats;\n rawDiff: string;\n files: DiffFile[];\n commitDiffs?: CommitDiff[];\n capturedAt: string;\n}\n\nexport interface ReviewMeta {\n id: string;\n cwd: string;\n base: DiffPayload['base'];\n branch: string | null;\n status: ReviewStatus;\n createdAt: string;\n submittedAt?: string;\n resolvedAt?: string;\n artifactDir: string;\n activeTurnId?: string;\n turns?: ReviewTurnSummary[];\n feedbackPath?: string;\n markdownPath?: string;\n}\n\nexport interface FeedbackBundle {\n version: 1;\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n timestamp: string;\n base: DiffPayload['base'];\n branch: string | null;\n reviewScope?: ReviewScope;\n comments: Comment[];\n}\n\nexport const RESOLUTION_STATUSES = ['partial', 'resolved'] as const;\n\ntype ResolutionStatus = (typeof RESOLUTION_STATUSES)[number];\n\nexport interface ResolvedComment {\n commentId: string;\n status: 'resolved';\n summary?: string;\n resolvedAt: string;\n}\n\nexport interface ResolutionBundle {\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n status: ResolutionStatus;\n summary: string | null;\n resolvedAt: string | null;\n comments: ResolvedComment[];\n}\n\nexport interface ResolutionCounts {\n total: number;\n resolved: number;\n open: number;\n}\n\nexport interface ResolveResult {\n ok: true;\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n status: ReviewStatus;\n resolutionStatus: ResolutionStatus;\n comments: ResolutionCounts;\n path: string;\n resolution: ResolutionBundle;\n}\n\nexport const REVIEW_UPDATE_REASONS = [\n 'review-resolved',\n 'comment-resolved',\n 'comment-reopened',\n 'turn-created'\n] as const;\n\nexport type ReviewUpdateReason = (typeof REVIEW_UPDATE_REASONS)[number];\n\nexport type ReviewEvent =\n | { type: 'review.opened'; reviewId: string }\n | {\n type: 'review.turn.created';\n reviewId: string;\n turnId: string;\n turnIndex: number;\n reused: boolean;\n }\n | {\n type: 'review.submitted';\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n counts: { files: number; comments: number };\n }\n | {\n type: 'review.updated';\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n reason: ReviewUpdateReason;\n status: ReviewStatus;\n resolutionStatus: ResolutionStatus;\n counts: ResolutionCounts;\n }\n | { type: 'review.cancelled'; reviewId: string };\n\nexport interface ReviewTurnMeta {\n id: string;\n index: number;\n status: ReviewStatus;\n createdAt: string;\n submittedAt?: string;\n resolvedAt?: string;\n artifactDir: string;\n diffPath: string;\n feedbackPath?: string;\n markdownPath?: string;\n resolvedPath?: string;\n}\n\nexport interface ReviewTurnSummary extends ReviewTurnMeta {\n capturedAt: string;\n stats: DiffStats;\n comments: ResolutionCounts;\n}\n\nexport interface ReviewTurn extends ReviewTurnMeta {\n diff: DiffPayload;\n feedback?: FeedbackBundle;\n resolution?: ResolutionBundle;\n}\n\nexport interface ReviewRecord {\n meta: ReviewMeta;\n turns: ReviewTurn[];\n diff: DiffPayload;\n feedback?: FeedbackBundle;\n resolution?: ResolutionBundle;\n}\n\nexport interface ServerInfo {\n pid: number;\n port: number;\n version: string;\n startedAt: string;\n stateDir: string;\n}\n\nexport interface OpenResult {\n reviewId: string;\n turnId?: string;\n turnIndex?: number;\n url: string;\n files: number;\n comments?: number;\n feedbackPath?: string;\n markdownPath?: string;\n artifactDir?: string;\n}\n\nexport interface HealthResponse {\n ok: boolean;\n version: string;\n activeReviews: number;\n}\n\ninterface ReviewRegistrationResponse {\n meta: ReviewMeta;\n url: string;\n turn?: ReviewTurnSummary;\n}\n\nexport interface CreateReviewResponse extends ReviewRegistrationResponse {}\n\nexport interface CreateReviewTurnResponse extends ReviewRegistrationResponse {\n turn: ReviewTurnSummary;\n reused: boolean;\n}\n\nexport interface ListReviewsResponse {\n reviews: ReviewMeta[];\n}\n\nexport interface SubmitReviewRequest {\n comments: Comment[];\n reviewScope?: ReviewScope;\n}\n\nexport interface ResolutionRequest {\n summary?: string;\n turn?: string;\n}\n\nexport interface OpenFileRequest {\n filePath: string;\n turnId?: string;\n}\n\nexport interface OpenFileResponse {\n ok: true;\n path: string;\n}\n","import type { JsonValue } from './json';\nimport type {\n ClearReviewEntry,\n ClearReviewsRequest,\n ClearReviewsResult,\n Comment,\n CommitDiff,\n CommitRangeDiffRequest,\n CommitRangeDiffResponse,\n CreateReviewResponse,\n CreateReviewTurnResponse,\n DiffCommit,\n DiffFile,\n DiffHunk,\n DiffLine,\n DiffPayload,\n DiffStats,\n FeedbackBundle,\n HealthResponse,\n ListReviewsResponse,\n OpenFileRequest,\n OpenFileResponse,\n OpenResult,\n ResolutionBundle,\n ResolutionRequest,\n ResolvedComment,\n ResolveResult,\n ReviewEvent,\n ReviewMeta,\n ReviewRecord,\n ReviewScope,\n ReviewTurn,\n ReviewTurnMeta,\n ReviewTurnSummary,\n ServerInfo,\n SubmitReviewRequest\n} from './types';\nimport {\n DIFF_FALLBACK_REASONS,\n DIFF_LINE_TYPES,\n DIFF_SCOPE_MODES,\n RESOLUTION_STATUSES,\n REVIEW_SCOPE_MODES,\n REVIEW_STATUSES,\n REVIEW_UPDATE_REASONS,\n SIDES\n} from './types';\n\nexport type JsonGuard<T> = (value: unknown) => value is T;\n\nexport type StoredReviewMeta = Omit<ReviewMeta, 'artifactDir'> &\n Partial<\n Pick<ReviewMeta, 'artifactDir' | 'activeTurnId' | 'turns' | 'feedbackPath' | 'markdownPath'>\n >;\n\ntype ReviewRegistrationResponseShape = {\n meta: ReviewMeta;\n url: string;\n turn?: ReviewTurnSummary;\n};\n\nexport function parseJson<T>(raw: string, guard: JsonGuard<T>, label: string): T {\n const parsed: JsonValue = JSON.parse(raw);\n return parseJsonValue(parsed, guard, label);\n}\n\nexport function parseJsonValue<T>(value: JsonValue, guard: JsonGuard<T>, label: string): T {\n if (!guard(value)) {\n throw new Error(`Invalid ${label}`);\n }\n return value;\n}\n\nexport function isServerInfo(value: unknown): value is ServerInfo {\n return (\n isRecord(value) &&\n isNumber(value.pid) &&\n isNumber(value.port) &&\n isString(value.version) &&\n isString(value.startedAt) &&\n isString(value.stateDir)\n );\n}\n\nexport function isHealthResponse(value: unknown): value is HealthResponse {\n return (\n isRecord(value) &&\n isBoolean(value.ok) &&\n isString(value.version) &&\n isNumber(value.activeReviews)\n );\n}\n\nexport function isClearReviewsRequest(value: unknown): value is ClearReviewsRequest {\n return (\n isRecord(value) &&\n isOptionalNonNegativeInteger(value.olderThanDays) &&\n isOptionalBoolean(value.dryRun)\n );\n}\n\nexport function isClearReviewsResult(value: unknown): value is ClearReviewsResult {\n return (\n isRecord(value) &&\n isString(value.reviewsDir) &&\n isString(value.cutoff) &&\n isNumber(value.olderThanDays) &&\n isBoolean(value.dryRun) &&\n isArrayOf(value.candidates, isClearReviewEntry) &&\n isArrayOf(value.deleted, isClearReviewEntry) &&\n isArrayOf(value.skipped, isClearReviewSkipped) &&\n isRecord(value.counts) &&\n isNumber(value.counts.candidates) &&\n isNumber(value.counts.deleted) &&\n isNumber(value.counts.skipped)\n );\n}\n\nexport function isCreateReviewResponse(value: unknown): value is CreateReviewResponse {\n return (\n isRecord(value) &&\n hasReviewRegistrationFields(value) &&\n isOptional(value.turn, isReviewTurnSummary)\n );\n}\n\nexport function isCreateReviewTurnResponse(value: unknown): value is CreateReviewTurnResponse {\n return (\n isRecord(value) &&\n hasReviewRegistrationFields(value) &&\n isReviewTurnSummary(value.turn) &&\n isBoolean(value.reused)\n );\n}\n\nexport function isListReviewsResponse(value: unknown): value is ListReviewsResponse {\n return isRecord(value) && isArrayOf(value.reviews, isReviewMeta);\n}\n\nexport function isOpenResult(value: unknown): value is OpenResult {\n return (\n isRecord(value) &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isString(value.url) &&\n isNumber(value.files) &&\n isOptionalNumber(value.comments) &&\n isOptionalString(value.feedbackPath) &&\n isOptionalString(value.markdownPath) &&\n isOptionalString(value.artifactDir)\n );\n}\n\nexport function isOpenFileRequest(value: unknown): value is OpenFileRequest {\n return isRecord(value) && isString(value.filePath) && isOptionalString(value.turnId);\n}\n\nexport function isOpenFileResponse(value: unknown): value is OpenFileResponse {\n return isRecord(value) && value.ok === true && isString(value.path);\n}\n\nexport function isCommitRangeDiffRequest(value: unknown): value is CommitRangeDiffRequest {\n return (\n isRecord(value) &&\n isString(value.fromSha) &&\n isString(value.toSha) &&\n isOptionalString(value.turnId)\n );\n}\n\nexport function isCommitRangeDiffResponse(value: unknown): value is CommitRangeDiffResponse {\n return (\n isRecord(value) &&\n isString(value.fromSha) &&\n isString(value.toSha) &&\n isDiffStats(value.stats) &&\n isString(value.rawDiff) &&\n isArrayOf(value.files, isDiffFile)\n );\n}\n\nexport function isResolveResult(value: unknown): value is ResolveResult {\n return (\n isRecord(value) &&\n value.ok === true &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isReviewStatus(value.status) &&\n isResolutionStatus(value.resolutionStatus) &&\n isResolutionCounts(value.comments) &&\n isString(value.path) &&\n isResolutionBundle(value.resolution)\n );\n}\n\nexport function isSubmitReviewRequest(value: unknown): value is SubmitReviewRequest {\n return (\n isRecord(value) &&\n isArrayOf(value.comments, isComment) &&\n isOptional(value.reviewScope, isReviewScope)\n );\n}\n\nexport function isResolutionRequest(value: unknown): value is ResolutionRequest {\n return isRecord(value) && isOptionalString(value.summary) && isOptionalString(value.turn);\n}\n\nexport function isReviewRecord(value: unknown): value is ReviewRecord {\n return (\n isRecord(value) &&\n isReviewMeta(value.meta) &&\n isArrayOf(value.turns, isReviewTurn) &&\n isDiffPayload(value.diff) &&\n isOptional(value.feedback, isFeedbackBundle) &&\n isOptional(value.resolution, isResolutionBundle)\n );\n}\n\nexport function isStoredReviewMeta(value: unknown): value is StoredReviewMeta {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.cwd) &&\n isBaseRef(value.base) &&\n isNullableString(value.branch) &&\n isReviewStatus(value.status) &&\n isString(value.createdAt) &&\n isOptionalString(value.submittedAt) &&\n isOptionalString(value.resolvedAt) &&\n isOptionalString(value.artifactDir) &&\n isOptionalString(value.activeTurnId) &&\n isOptional(value.turns, (turns): turns is ReviewTurnSummary[] =>\n isArrayOf(turns, isReviewTurnSummary)\n ) &&\n isOptionalString(value.feedbackPath) &&\n isOptionalString(value.markdownPath)\n );\n}\n\nfunction isReviewMeta(value: unknown): value is ReviewMeta {\n return isStoredReviewMeta(value) && isString(value.artifactDir);\n}\n\nfunction hasReviewRegistrationFields(\n value: Record<string, unknown>\n): value is Record<string, unknown> & ReviewRegistrationResponseShape {\n return isReviewMeta(value.meta) && isString(value.url);\n}\n\nexport function isDiffPayload(value: unknown): value is DiffPayload {\n return (\n isRecord(value) &&\n isBaseRef(value.base) &&\n isNullableString(value.branch) &&\n isString(value.cwd) &&\n isDiffScope(value.scope) &&\n isDiffStats(value.stats) &&\n isString(value.rawDiff) &&\n isArrayOf(value.files, isDiffFile) &&\n isOptional(value.commitDiffs, (commitDiffs): commitDiffs is CommitDiff[] =>\n isArrayOf(commitDiffs, isCommitDiff)\n ) &&\n isString(value.capturedAt)\n );\n}\n\nexport function isFeedbackBundle(value: unknown): value is FeedbackBundle {\n return (\n isRecord(value) &&\n value.version === 1 &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isString(value.timestamp) &&\n isBaseRef(value.base) &&\n isNullableString(value.branch) &&\n isOptional(value.reviewScope, isReviewScope) &&\n isArrayOf(value.comments, isComment)\n );\n}\n\nexport function isResolutionBundle(value: unknown): value is ResolutionBundle {\n return (\n isRecord(value) &&\n isString(value.reviewId) &&\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isResolutionStatus(value.status) &&\n isNullableString(value.summary) &&\n isNullableString(value.resolvedAt) &&\n isArrayOf(value.comments, isResolvedComment)\n );\n}\n\nexport function isReviewEvent(value: unknown): value is ReviewEvent {\n if (!isRecord(value) || !isString(value.reviewId) || !isString(value.type)) {\n return false;\n }\n switch (value.type) {\n case 'review.opened':\n case 'review.cancelled':\n return true;\n case 'review.turn.created':\n return isString(value.turnId) && isNumber(value.turnIndex) && isBoolean(value.reused);\n case 'review.submitted':\n return (\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isRecord(value.counts) &&\n isNumber(value.counts.files) &&\n isNumber(value.counts.comments)\n );\n case 'review.updated':\n return (\n isOptionalString(value.turnId) &&\n isOptionalNumber(value.turnIndex) &&\n isReviewUpdateReason(value.reason) &&\n isReviewStatus(value.status) &&\n isResolutionStatus(value.resolutionStatus) &&\n isResolutionCounts(value.counts)\n );\n default:\n return false;\n }\n}\n\nexport function isReviewTurnMeta(value: unknown): value is ReviewTurnMeta {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isNumber(value.index) &&\n isReviewStatus(value.status) &&\n isString(value.createdAt) &&\n isOptionalString(value.submittedAt) &&\n isOptionalString(value.resolvedAt) &&\n isString(value.artifactDir) &&\n isString(value.diffPath) &&\n isOptionalString(value.feedbackPath) &&\n isOptionalString(value.markdownPath) &&\n isOptionalString(value.resolvedPath)\n );\n}\n\nfunction isReviewTurnSummary(value: unknown): value is ReviewTurnSummary {\n if (!isRecord(value) || !isReviewTurnMeta(value)) {\n return false;\n }\n return (\n isString(value.capturedAt) && isDiffStats(value.stats) && isResolutionCounts(value.comments)\n );\n}\n\nfunction isReviewTurn(value: unknown): value is ReviewTurn {\n if (!isRecord(value) || !isReviewTurnMeta(value)) {\n return false;\n }\n return (\n isDiffPayload(value.diff) &&\n isOptional(value.feedback, isFeedbackBundle) &&\n isOptional(value.resolution, isResolutionBundle)\n );\n}\n\nfunction isClearReviewEntry(value: unknown): value is ClearReviewEntry {\n return (\n isRecord(value) &&\n isString(value.reviewId) &&\n isReviewStatus(value.status) &&\n isString(value.artifactDir) &&\n isString(value.lastActivityAt)\n );\n}\n\nfunction isClearReviewSkipped(value: unknown): value is ClearReviewsResult['skipped'][number] {\n return (\n isRecord(value) &&\n isString(value.reviewId) &&\n isString(value.artifactDir) &&\n isString(value.reason)\n );\n}\n\nfunction isDiffScope(value: unknown): value is DiffPayload['scope'] {\n return (\n isRecord(value) &&\n isOneOf(value.mode, DIFF_SCOPE_MODES) &&\n isNullableString(value.requestedBase) &&\n isBaseRef(value.base) &&\n isDiffRef(value.comparison) &&\n (value.fallbackReason === null || isOneOf(value.fallbackReason, DIFF_FALLBACK_REASONS))\n );\n}\n\nfunction isDiffRef(value: unknown): value is DiffPayload['scope']['comparison'] {\n return isRecord(value) && isString(value.ref) && isNullableString(value.sha);\n}\n\nfunction isBaseRef(value: unknown): value is { ref: string; sha: string } {\n return isRecord(value) && isString(value.ref) && isString(value.sha);\n}\n\nfunction isDiffStats(value: unknown): value is DiffStats {\n return (\n isRecord(value) &&\n isNumber(value.files) &&\n isNumber(value.additions) &&\n isNumber(value.deletions)\n );\n}\n\nfunction isDiffCommit(value: unknown): value is DiffCommit {\n return (\n isRecord(value) &&\n isString(value.sha) &&\n isString(value.shortSha) &&\n isString(value.subject) &&\n isString(value.authorName) &&\n isString(value.authorEmail) &&\n isString(value.authoredAt) &&\n isString(value.committedAt)\n );\n}\n\nfunction isCommitDiff(value: unknown): value is CommitDiff {\n return (\n isRecord(value) &&\n isDiffCommit(value.commit) &&\n isDiffStats(value.stats) &&\n isString(value.rawDiff) &&\n isArrayOf(value.files, isDiffFile)\n );\n}\n\nfunction isReviewScope(value: unknown): value is ReviewScope {\n if (!isRecord(value) || !isOneOf(value.mode, REVIEW_SCOPE_MODES)) {\n return false;\n }\n switch (value.mode) {\n case 'all':\n return true;\n case 'single':\n return isString(value.sha);\n case 'range':\n return isString(value.fromSha) && isString(value.toSha);\n }\n}\n\nfunction isDiffFile(value: unknown): value is DiffFile {\n return (\n isRecord(value) &&\n isString(value.path) &&\n isNullableString(value.oldPath) &&\n isNumber(value.additions) &&\n isNumber(value.deletions) &&\n isBoolean(value.isBinary) &&\n isBoolean(value.isDeleted) &&\n isBoolean(value.isNew) &&\n isBoolean(value.isRenamed) &&\n isNullableString(value.language) &&\n isArrayOf(value.hunks, isDiffHunk)\n );\n}\n\nfunction isDiffHunk(value: unknown): value is DiffHunk {\n return (\n isRecord(value) &&\n isNumber(value.oldStart) &&\n isNumber(value.oldLines) &&\n isNumber(value.newStart) &&\n isNumber(value.newLines) &&\n isString(value.header) &&\n isArrayOf(value.lines, isDiffLine)\n );\n}\n\nfunction isDiffLine(value: unknown): value is DiffLine {\n return (\n isRecord(value) &&\n isOneOf(value.type, DIFF_LINE_TYPES) &&\n isNullableNumber(value.oldLine) &&\n isNullableNumber(value.newLine) &&\n isString(value.content)\n );\n}\n\nfunction isComment(value: unknown): value is Comment {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.filePath) &&\n isNumber(value.startLine) &&\n isNumber(value.endLine) &&\n isOneOf(value.side, SIDES) &&\n isString(value.body) &&\n isString(value.originalSnippet) &&\n isString(value.createdAt)\n );\n}\n\nfunction isResolvedComment(value: unknown): value is ResolvedComment {\n return (\n isRecord(value) &&\n isString(value.commentId) &&\n value.status === 'resolved' &&\n isOptionalString(value.summary) &&\n isString(value.resolvedAt)\n );\n}\n\nfunction isResolutionCounts(value: unknown): value is ResolveResult['comments'] {\n return (\n isRecord(value) && isNumber(value.total) && isNumber(value.resolved) && isNumber(value.open)\n );\n}\n\nfunction isReviewStatus(value: unknown): value is ReviewMeta['status'] {\n return isOneOf(value, REVIEW_STATUSES);\n}\n\nfunction isResolutionStatus(value: unknown): value is ResolutionBundle['status'] {\n return isOneOf(value, RESOLUTION_STATUSES);\n}\n\nfunction isReviewUpdateReason(\n value: unknown\n): value is Extract<ReviewEvent, { type: 'review.updated' }>['reason'] {\n return isOneOf(value, REVIEW_UPDATE_REASONS);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isArrayOf<T>(value: unknown, guard: JsonGuard<T>): value is T[] {\n return Array.isArray(value) && value.every(guard);\n}\n\nfunction isOptional<T>(value: unknown, guard: JsonGuard<T>): value is T | undefined {\n return value === undefined || guard(value);\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\nfunction isOptionalString(value: unknown): value is string | undefined {\n return value === undefined || isString(value);\n}\n\nfunction isNullableString(value: unknown): value is string | null {\n return value === null || isString(value);\n}\n\nfunction isNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nfunction isOptionalNumber(value: unknown): value is number | undefined {\n return value === undefined || isNumber(value);\n}\n\nfunction isOptionalNonNegativeInteger(value: unknown): value is number | undefined {\n return value === undefined || (isNumber(value) && Number.isInteger(value) && value >= 0);\n}\n\nfunction isOptionalBoolean(value: unknown): value is boolean | undefined {\n return value === undefined || isBoolean(value);\n}\n\nfunction isNullableNumber(value: unknown): value is number | null {\n return value === null || isNumber(value);\n}\n\nfunction isBoolean(value: unknown): value is boolean {\n return typeof value === 'boolean';\n}\n\nfunction isOneOf<const T extends readonly string[]>(\n value: unknown,\n options: T\n): value is T[number] {\n return typeof value === 'string' && options.includes(value);\n}\n","import { 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 } 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 HealthResponse,\n ListReviewsResponse,\n OpenFileResponse,\n OpenResult,\n ResolutionRequest,\n ReviewEvent,\n ReviewMeta,\n ReviewTurnSummary,\n SubmitReviewRequest\n} from '../shared/types';\nimport {\n isClearReviewsRequest,\n isCommitRangeDiffRequest,\n isDiffPayload,\n isOpenFileRequest,\n isResolutionRequest,\n isSubmitReviewRequest,\n type JsonGuard,\n parseJsonValue\n} from '../shared/validation';\nimport { openLocalPath } from './local-open';\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}\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 };\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/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, 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 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 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 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\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 ResolutionBundle,\n ResolutionCounts,\n ResolvedComment,\n Side\n} from './types';\n\nexport interface LineRange {\n side: Side;\n startLine: number;\n endLine: number;\n}\n\nexport function compareCommentsByLocation(a: Comment, b: Comment): number {\n return (\n a.filePath.localeCompare(b.filePath) ||\n a.startLine - b.startLine ||\n a.endLine - b.endLine ||\n a.side.localeCompare(b.side)\n );\n}\n\nexport function countCommentFiles(comments: Pick<Comment, 'filePath'>[]): number {\n return new Set(comments.map((comment) => comment.filePath)).size;\n}\n\nexport function formatLineRange(\n range: LineRange,\n options: { repeatSideOnEnd?: boolean } = {}\n): string {\n const startLine = Math.min(range.startLine, range.endLine);\n const endLine = Math.max(range.startLine, range.endLine);\n if (startLine === endLine) {\n return `${range.side}${startLine}`;\n }\n const endPrefix = options.repeatSideOnEnd === false ? '' : range.side;\n return `${range.side}${startLine}-${endPrefix}${endLine}`;\n}\n\nexport function resolutionCounts(\n feedback: FeedbackBundle | undefined,\n resolvedComments: ResolvedComment[] = []\n): ResolutionCounts {\n const comments = feedback?.comments ?? [];\n const resolvedIds = new Set(resolvedComments.map((comment) => comment.commentId));\n const resolved = comments.filter((comment) => resolvedIds.has(comment.id)).length;\n return {\n total: comments.length,\n resolved,\n open: comments.length - resolved\n };\n}\n\nexport function reviewResolutionCounts(record: {\n feedback?: FeedbackBundle;\n resolution?: ResolutionBundle;\n}): ResolutionCounts {\n return resolutionCounts(record.feedback, record.resolution?.comments ?? []);\n}\n","import { execa } from 'execa';\nimport { parseUnifiedDiff } from './diff-parser';\nimport { summarizeDiffFiles } from './diff-stats';\nimport type { CommitDiff } 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 = parseUnifiedDiff(rawDiff);\n return {\n stats: summarizeDiffFiles(files),\n rawDiff,\n files\n };\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 { ReviewStatus } from './types';\n\nexport function isResolvableReviewStatus(status: ReviewStatus): boolean {\n return status === 'submitted' || status === 'resolved';\n}\n","import open from 'open';\n\nexport async function openLocalPath(filePath: string): Promise<void> {\n await open(filePath, { wait: false });\n}\n","import { createHash } from 'node:crypto';\nimport type { Dirent } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { ulid } from 'ulid';\nimport { type ClearReviewArtifactsOptions, clearReviewArtifacts } from '../shared/cleanup';\nimport { compareCommentsByLocation, countCommentFiles, resolutionCounts } from '../shared/comments';\nimport { formatError, isFileNotFound } from '../shared/errors';\nimport { writeJsonFile, writeTextFile } from '../shared/json';\nimport { serializeFeedbackMarkdown } from '../shared/markdown';\nimport {\n ensureDir,\n globalReviewDiffFile,\n globalReviewDir,\n globalReviewFeedbackFile,\n globalReviewMarkdownFile,\n globalReviewMetaFile,\n globalReviewResolvedFile,\n globalReviewsDir,\n globalReviewTurnDiffFile,\n globalReviewTurnDir,\n globalReviewTurnFeedbackFile,\n globalReviewTurnMarkdownFile,\n globalReviewTurnMetaFile,\n globalReviewTurnResolvedFile,\n globalReviewTurnsDir\n} from '../shared/paths';\nimport { normalizeReviewScope, sameReviewScope } from '../shared/review-scope';\nimport { isResolvableReviewStatus } from '../shared/reviews';\nimport type {\n ClearReviewsResult,\n Comment,\n DiffPayload,\n FeedbackBundle,\n ResolutionBundle,\n ResolvedComment,\n ResolveResult,\n ReviewEvent,\n ReviewMeta,\n ReviewRecord,\n ReviewScope,\n ReviewTurn,\n ReviewTurnMeta,\n ReviewTurnSummary,\n ReviewUpdateReason\n} from '../shared/types';\nimport {\n isDiffPayload,\n isFeedbackBundle,\n isResolutionBundle,\n isReviewTurnMeta,\n isStoredReviewMeta,\n type JsonGuard,\n parseJson,\n type StoredReviewMeta\n} from '../shared/validation';\n\ntype Listener = (event: ReviewEvent) => void;\n\ninterface SubmitResult {\n record: ReviewRecord;\n feedbackPath: string;\n markdownPath: string;\n turn: ReviewTurn;\n}\n\ninterface AppendTurnResult {\n record: ReviewRecord;\n turn: ReviewTurn;\n reused: boolean;\n}\n\nexport class ReviewStore {\n private readonly reviews = new Map<string, ReviewRecord>();\n private readonly listeners = new Map<string, Set<Listener>>();\n\n async create(diff: DiffPayload): Promise<ReviewRecord> {\n const id = ulid();\n const createdAt = new Date().toISOString();\n const turn = createTurn(id, 1, diff, createdAt);\n const meta: ReviewMeta = {\n id,\n cwd: diff.cwd,\n base: diff.base,\n branch: diff.branch,\n status: 'pending',\n createdAt,\n artifactDir: globalReviewDir(id),\n activeTurnId: turn.id\n };\n const record = normalizeRecord({ meta, turns: [turn], diff: turn.diff });\n this.reviews.set(id, record);\n await this.persistInitial(record, turn);\n this.emit({ type: 'review.opened', reviewId: id });\n return record;\n }\n\n async appendTurn(id: string, diff: DiffPayload): Promise<AppendTurnResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n if (record.meta.cwd !== diff.cwd) {\n throw new Error(`Review ${id} belongs to ${record.meta.cwd}, not ${diff.cwd}`);\n }\n\n const latest = latestTurn(record);\n if (latest.status === 'pending') {\n if (diffFingerprint(latest.diff) === diffFingerprint(diff)) {\n this.emit({\n type: 'review.turn.created',\n reviewId: id,\n turnId: latest.id,\n turnIndex: latest.index,\n reused: true\n });\n return { record, turn: latest, reused: true };\n }\n throw new Error(`Review ${id} already has a pending turn`);\n }\n if (latest.status === 'cancelled') {\n throw new Error(`Review ${id} is cancelled and cannot be continued`);\n }\n\n const turn = createTurn(id, latest.index + 1, diff, new Date().toISOString());\n const nextRecord = normalizeRecord({\n ...record,\n meta: { ...record.meta, activeTurnId: turn.id },\n turns: [...record.turns, turn]\n });\n this.reviews.set(id, nextRecord);\n await this.persistInitial(nextRecord, turn);\n this.emit({\n type: 'review.turn.created',\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n reused: false\n });\n return { record: nextRecord, turn, reused: false };\n }\n\n async list(): Promise<ReviewMeta[]> {\n await this.loadAllReviews();\n return Array.from(this.reviews.values())\n .map((record) => record.meta)\n .toSorted((a, b) => a.createdAt.localeCompare(b.createdAt));\n }\n\n async clearReviewArtifacts(\n options: ClearReviewArtifactsOptions = {}\n ): Promise<ClearReviewsResult> {\n const result = await clearReviewArtifacts(options);\n if (!result.dryRun) {\n for (const review of result.deleted) {\n this.reviews.delete(review.reviewId);\n }\n }\n return result;\n }\n\n async get(id: string): Promise<ReviewRecord | null> {\n return this.reviews.get(id) ?? (await this.loadKnownReview(id));\n }\n\n async getTurn(id: string, turnId: string): Promise<ReviewTurn | null> {\n const record = await this.get(id);\n return record?.turns.find((turn) => turn.id === turnId) ?? null;\n }\n\n async submit(id: string, comments: Comment[], reviewScope?: ReviewScope): Promise<SubmitResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = activeTurn(record);\n const sortedComments = comments.toSorted(compareCommentsByLocation);\n const normalizedReviewScope = normalizeReviewScope(turn.diff, reviewScope);\n if (turn.status !== 'pending') {\n if (\n turn.feedback &&\n sameComments(turn.feedback.comments, sortedComments) &&\n sameReviewScope(turn.feedback.reviewScope, normalizedReviewScope)\n ) {\n return {\n record,\n feedbackPath: requiredPath(turn.feedbackPath, 'feedback path'),\n markdownPath: requiredPath(turn.markdownPath, 'markdown path'),\n turn\n };\n }\n throw new Error(`Review ${id} turn ${turn.index} is ${turn.status} and cannot be submitted`);\n }\n\n const timestamp = new Date().toISOString();\n const feedbackPath = globalReviewTurnFeedbackFile(id, turn.id);\n const markdownPath = globalReviewTurnMarkdownFile(id, turn.id);\n const feedback: FeedbackBundle = {\n version: 1,\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n timestamp,\n base: turn.diff.base,\n branch: turn.diff.branch,\n reviewScope: normalizedReviewScope,\n comments: sortedComments\n };\n const nextTurn: ReviewTurn = {\n ...turn,\n status: 'submitted',\n submittedAt: timestamp,\n feedbackPath,\n markdownPath,\n feedback\n };\n const nextRecord = normalizeRecord(replaceTurn(record, nextTurn));\n this.reviews.set(id, nextRecord);\n\n await ensureDir(globalReviewTurnDir(id, nextTurn.id));\n await Promise.all([\n writeJsonFile(globalReviewTurnMetaFile(id, nextTurn.id), turnMeta(nextTurn)),\n writeJsonFile(feedbackPath, feedback),\n writeTextFile(markdownPath, serializeFeedbackMarkdown(feedback))\n ]);\n await this.persistMeta(nextRecord);\n\n this.emit({\n type: 'review.submitted',\n reviewId: id,\n turnId: nextTurn.id,\n turnIndex: nextTurn.index,\n counts: {\n files: countCommentFiles(feedback.comments),\n comments: feedback.comments.length\n }\n });\n return { record: nextRecord, feedbackPath, markdownPath, turn: nextTurn };\n }\n\n async feedback(id: string): Promise<FeedbackBundle | null> {\n const record = await this.get(id);\n return record?.feedback ?? null;\n }\n\n async markResolved(id: string, summary?: string, turnSelector?: string): Promise<ResolveResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = this.resolveTurnSelector(record, turnSelector);\n this.assertResolvable(turn, id);\n\n const resolvedAt = new Date().toISOString();\n const existingById = new Map(\n (turn.resolution?.comments ?? []).map((comment) => [comment.commentId, comment])\n );\n const comments = this.sortResolvedComments(\n (turn.feedback?.comments ?? []).map((comment) => ({\n ...existingById.get(comment.id),\n commentId: comment.id,\n status: 'resolved' as const,\n resolvedAt: existingById.get(comment.id)?.resolvedAt ?? resolvedAt\n })),\n turn\n );\n const resolution: ResolutionBundle = {\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n status: 'resolved',\n summary: summary ?? turn.resolution?.summary ?? null,\n resolvedAt,\n comments\n };\n const nextTurn: ReviewTurn & { feedback: FeedbackBundle } = {\n ...turn,\n status: 'resolved',\n resolvedAt\n };\n return this.persistResolution(record, nextTurn, resolution, 'review-resolved');\n }\n\n async resolveComment(id: string, commentId: string, summary?: string): Promise<ResolveResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = this.findTurnForComment(record, commentId);\n if (!turn) {\n const currentTurn = activeTurn(record);\n if (!isResolvableReviewStatus(currentTurn.status)) {\n throw new Error(\n `Review ${id} turn ${currentTurn.index} is ${currentTurn.status} and cannot be resolved`\n );\n }\n throw new Error(`Comment ${commentId} not found`);\n }\n this.assertResolvable(turn, id);\n\n const resolvedAt = new Date().toISOString();\n const previous = turn.resolution?.comments.find((comment) => comment.commentId === commentId);\n const nextSummary = summary ?? previous?.summary;\n const nextComment: ResolvedComment = {\n commentId,\n status: 'resolved',\n ...(nextSummary ? { summary: nextSummary } : {}),\n resolvedAt\n };\n const comments = this.sortResolvedComments(\n [\n ...(turn.resolution?.comments ?? []).filter((comment) => comment.commentId !== commentId),\n nextComment\n ],\n turn\n );\n const counts = resolutionCounts(turn.feedback, comments);\n const fullyResolved = counts.total === counts.resolved;\n const resolution: ResolutionBundle = {\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n status: fullyResolved ? 'resolved' : 'partial',\n summary: fullyResolved ? (turn.resolution?.summary ?? null) : null,\n resolvedAt: fullyResolved ? resolvedAt : null,\n comments\n };\n const nextTurn: ReviewTurn & { feedback: FeedbackBundle } = fullyResolved\n ? { ...turn, status: 'resolved', resolvedAt }\n : { ...turn, status: 'submitted', resolvedAt: undefined };\n return this.persistResolution(record, nextTurn, resolution, 'comment-resolved');\n }\n\n async reopenComment(id: string, commentId: string): Promise<ResolveResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n const turn = this.findTurnForComment(record, commentId);\n if (!turn) {\n const currentTurn = activeTurn(record);\n if (!isResolvableReviewStatus(currentTurn.status)) {\n throw new Error(\n `Review ${id} turn ${currentTurn.index} is ${currentTurn.status} and cannot be resolved`\n );\n }\n throw new Error(`Comment ${commentId} not found`);\n }\n this.assertResolvable(turn, id);\n\n const comments = this.sortResolvedComments(\n (turn.resolution?.comments ?? []).filter((comment) => comment.commentId !== commentId),\n turn\n );\n const counts = resolutionCounts(turn.feedback, comments);\n const fullyResolved = counts.total > 0 && counts.total === counts.resolved;\n const resolvedAt = fullyResolved ? new Date().toISOString() : null;\n const resolution: ResolutionBundle = {\n reviewId: id,\n turnId: turn.id,\n turnIndex: turn.index,\n status: fullyResolved ? 'resolved' : 'partial',\n summary: fullyResolved ? (turn.resolution?.summary ?? null) : null,\n resolvedAt,\n comments\n };\n const nextTurn: ReviewTurn & { feedback: FeedbackBundle } = fullyResolved\n ? { ...turn, status: 'resolved', resolvedAt: resolvedAt ?? undefined }\n : { ...turn, status: 'submitted', resolvedAt: undefined };\n return this.persistResolution(record, nextTurn, resolution, 'comment-reopened');\n }\n\n subscribe(reviewId: string, listener: Listener): () => void {\n const listeners = this.listeners.get(reviewId) ?? new Set<Listener>();\n listeners.add(listener);\n this.listeners.set(reviewId, listeners);\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0) {\n this.listeners.delete(reviewId);\n }\n };\n }\n\n private emit(event: ReviewEvent): void {\n for (const listener of this.listeners.get(event.reviewId) ?? []) {\n listener(event);\n }\n }\n\n private async persistInitial(record: ReviewRecord, turn: ReviewTurn): Promise<void> {\n await ensureDir(turn.artifactDir);\n await Promise.all([\n writeJsonFile(globalReviewTurnMetaFile(record.meta.id, turn.id), turnMeta(turn)),\n writeJsonFile(turn.diffPath, turn.diff)\n ]);\n await this.persistMeta(record);\n }\n\n private async persistMeta(record: ReviewRecord): Promise<void> {\n await ensureDir(globalReviewDir(record.meta.id));\n await writeJsonFile(globalReviewMetaFile(record.meta.id), record.meta);\n }\n\n private async loadKnownReview(id: string): Promise<ReviewRecord | null> {\n const existing = this.reviews.get(id);\n if (existing) {\n return existing;\n }\n\n return this.loadReview(id);\n }\n\n private async loadAllReviews(): Promise<void> {\n let entries: Dirent[];\n try {\n entries = await readdir(globalReviewsDir(), { withFileTypes: true });\n } catch (error) {\n if (isFileNotFound(error)) {\n return;\n }\n throw new Error(\n `Could not read reviews directory at ${globalReviewsDir()}: ${formatError(error)}`,\n {\n cause: error\n }\n );\n }\n\n const reviewLoads: Array<Promise<ReviewRecord | null>> = [];\n for (const entry of entries) {\n if (entry.isDirectory()) {\n reviewLoads.push(this.loadReview(entry.name));\n }\n }\n await Promise.all(reviewLoads);\n }\n\n private async loadReview(id: string): Promise<ReviewRecord | null> {\n const metaPath = globalReviewMetaFile(id);\n let metaRaw: string;\n\n try {\n metaRaw = await readFile(metaPath, 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return this.loadReviewFromTurnsOnly(id);\n }\n throw new Error(`Could not load review ${id}: ${formatError(error)}`, { cause: error });\n }\n\n const storedMeta = parseJsonFile(metaRaw, isStoredReviewMeta, 'review metadata', metaPath);\n const persistedTurns = await this.loadPersistedTurns(id);\n const legacyTurn = await this.loadLegacyTurn(id, storedMeta);\n const turns = mergeRecoveredTurns(legacyTurn, persistedTurns);\n if (turns.length === 0) {\n throw new Error(`Review ${id} has no recoverable turns`);\n }\n\n const latest = latestTurn({ turns } as ReviewRecord);\n const record = normalizeRecord({\n meta: {\n ...storedMeta,\n artifactDir: storedMeta.artifactDir ?? globalReviewDir(id),\n activeTurnId: latest.id\n },\n turns,\n diff: latest.diff\n });\n this.reviews.set(id, record);\n return record;\n }\n\n private async loadReviewFromTurnsOnly(id: string): Promise<ReviewRecord | null> {\n const turns = await this.loadPersistedTurns(id);\n if (turns.length === 0) {\n return null;\n }\n\n const latest = latestTurn({ turns });\n const record = normalizeRecord({\n meta: {\n id,\n cwd: latest.diff.cwd,\n base: latest.diff.base,\n branch: latest.diff.branch,\n status: latest.status,\n createdAt: turns[0]?.createdAt ?? latest.createdAt,\n artifactDir: globalReviewDir(id),\n activeTurnId: latest.id\n },\n turns,\n diff: latest.diff\n });\n this.reviews.set(id, record);\n await this.persistMeta(record);\n return record;\n }\n\n private async loadPersistedTurns(id: string): Promise<ReviewTurn[]> {\n let entries: Dirent[];\n try {\n entries = await readdir(globalReviewTurnsDir(id), { withFileTypes: true });\n } catch (error) {\n if (isFileNotFound(error)) {\n return [];\n }\n throw new Error(`Could not read review turns for ${id}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n const turns: ReviewTurn[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) {\n continue;\n }\n const turn = await this.loadPersistedTurn(id, entry.name);\n if (turn) {\n turns.push(turn);\n }\n }\n\n return turns.toSorted((a, b) => a.index - b.index);\n }\n\n private async loadPersistedTurn(id: string, turnId: string): Promise<ReviewTurn | null> {\n const metaPath = globalReviewTurnMetaFile(id, turnId);\n const diffPath = globalReviewTurnDiffFile(id, turnId);\n let metaRaw: string;\n let diffRaw: string;\n\n try {\n [metaRaw, diffRaw] = await Promise.all([\n readFile(metaPath, 'utf8'),\n readFile(diffPath, 'utf8')\n ]);\n } catch (error) {\n if (isFileNotFound(error)) {\n return null;\n }\n throw new Error(`Could not load review ${id} turn ${turnId}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n const meta = parseJsonFile(metaRaw, isReviewTurnMeta, 'review turn metadata', metaPath);\n const diff = parseJsonFile(diffRaw, isDiffPayload, 'review turn diff', diffPath);\n const [feedback, resolution] = await Promise.all([\n readOptionalJsonFile(\n globalReviewTurnFeedbackFile(id, turnId),\n isFeedbackBundle,\n 'review feedback'\n ),\n readOptionalJsonFile(\n globalReviewTurnResolvedFile(id, turnId),\n isResolutionBundle,\n 'review resolution'\n )\n ]);\n\n return reconcileTurn(meta, diff, feedback, resolution);\n }\n\n private async loadLegacyTurn(\n id: string,\n storedMeta: StoredReviewMeta\n ): Promise<ReviewTurn | null> {\n const diffPath = globalReviewDiffFile(id);\n let diffRaw: string;\n try {\n diffRaw = await readFile(diffPath, 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return null;\n }\n throw new Error(`Could not load legacy review ${id}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n const diff = parseJsonFile(diffRaw, isDiffPayload, 'review diff', diffPath);\n const [feedback, resolution] = await Promise.all([\n readOptionalJsonFile(globalReviewFeedbackFile(id), isFeedbackBundle, 'review feedback'),\n readOptionalJsonFile(globalReviewResolvedFile(id), isResolutionBundle, 'review resolution')\n ]);\n const artifactDir = storedMeta.artifactDir ?? globalReviewDir(id);\n const legacySummary =\n storedMeta.turns?.find(\n (turn) => turn.artifactDir === artifactDir || turn.diffPath === diffPath\n ) ??\n storedMeta.turns?.find((turn) => turn.index === 1) ??\n storedMeta.turns?.[0];\n const meta: ReviewTurnMeta = {\n id: legacySummary?.id ?? storedMeta.activeTurnId ?? 'turn-1',\n index: legacySummary?.index ?? 1,\n status: legacySummary?.status ?? storedMeta.status,\n createdAt: legacySummary?.createdAt ?? storedMeta.createdAt,\n submittedAt: legacySummary?.submittedAt ?? storedMeta.submittedAt,\n resolvedAt: legacySummary?.resolvedAt ?? storedMeta.resolvedAt,\n artifactDir: legacySummary?.artifactDir ?? artifactDir,\n diffPath,\n ...(feedback\n ? { feedbackPath: globalReviewFeedbackFile(id), markdownPath: globalReviewMarkdownFile(id) }\n : {}),\n ...(resolution ? { resolvedPath: globalReviewResolvedFile(id) } : {})\n };\n return reconcileTurn(meta, diff, feedback, resolution);\n }\n\n private assertResolvable(\n turn: ReviewTurn,\n id: string\n ): asserts turn is ReviewTurn & {\n feedback: FeedbackBundle;\n } {\n if (!isResolvableReviewStatus(turn.status)) {\n throw new Error(`Review ${id} turn ${turn.index} is ${turn.status} and cannot be resolved`);\n }\n if (!turn.feedback) {\n throw new Error(`Review ${id} turn ${turn.index} has no submitted feedback`);\n }\n }\n\n private resolveTurnSelector(record: ReviewRecord, selector?: string): ReviewTurn {\n if (!selector) {\n return activeTurn(record);\n }\n const turn =\n record.turns.find((candidate) => candidate.id === selector) ??\n record.turns.find((candidate) => String(candidate.index) === selector);\n if (!turn) {\n throw new Error(`Turn ${selector} not found in review ${record.meta.id}`);\n }\n return turn;\n }\n\n private findTurnForComment(record: ReviewRecord, commentId: string): ReviewTurn | null {\n return (\n [...record.turns]\n .reverse()\n .find((candidate) =>\n candidate.feedback?.comments.some((comment) => comment.id === commentId)\n ) ?? null\n );\n }\n\n private async persistResolution(\n record: ReviewRecord,\n turn: ReviewTurn & { feedback: FeedbackBundle },\n resolution: ResolutionBundle,\n reason: ReviewUpdateReason\n ): Promise<ResolveResult> {\n const resolvedPath = globalReviewTurnResolvedFile(record.meta.id, turn.id);\n const nextTurn: ReviewTurn = {\n ...turn,\n resolvedPath,\n resolution\n };\n const nextRecord = normalizeRecord(replaceTurn(record, nextTurn));\n this.reviews.set(record.meta.id, nextRecord);\n await ensureDir(globalReviewTurnDir(record.meta.id, nextTurn.id));\n await Promise.all([\n writeJsonFile(resolvedPath, resolution),\n writeJsonFile(globalReviewTurnMetaFile(record.meta.id, nextTurn.id), turnMeta(nextTurn))\n ]);\n await this.persistMeta(nextRecord);\n const result: ResolveResult = {\n ok: true,\n reviewId: record.meta.id,\n turnId: nextTurn.id,\n turnIndex: nextTurn.index,\n status: nextTurn.status,\n resolutionStatus: resolution.status,\n comments: resolutionCounts(nextTurn.feedback, resolution.comments),\n path: resolvedPath,\n resolution\n };\n this.emit({\n type: 'review.updated',\n reviewId: record.meta.id,\n turnId: nextTurn.id,\n turnIndex: nextTurn.index,\n reason,\n status: result.status,\n resolutionStatus: result.resolutionStatus,\n counts: result.comments\n });\n return result;\n }\n\n private sortResolvedComments(\n comments: ResolvedComment[],\n turn: ReviewTurn & { feedback: FeedbackBundle }\n ): ResolvedComment[] {\n const feedbackIndex = new Map(\n turn.feedback.comments.map((comment, index) => [comment.id, index] as const)\n );\n return comments\n .map((comment) => ({ comment, index: feedbackIndex.get(comment.commentId) }))\n .filter(\n (entry): entry is { comment: ResolvedComment; index: number } => entry.index !== undefined\n )\n .sort((a, b) => a.index - b.index)\n .map(({ comment }) => comment);\n }\n}\n\nfunction createTurn(\n reviewId: string,\n index: number,\n diff: DiffPayload,\n createdAt: string\n): ReviewTurn {\n const id = ulid();\n return {\n id,\n index,\n status: 'pending',\n createdAt,\n artifactDir: globalReviewTurnDir(reviewId, id),\n diffPath: globalReviewTurnDiffFile(reviewId, id),\n diff\n };\n}\n\nfunction normalizeRecord(record: Pick<ReviewRecord, 'meta' | 'turns' | 'diff'>): ReviewRecord {\n const turns = record.turns.toSorted((a, b) => a.index - b.index);\n const active =\n turns.find((turn) => turn.id === record.meta.activeTurnId) ?? turns[turns.length - 1];\n const meta: ReviewMeta = {\n ...record.meta,\n base: active.diff.base,\n branch: active.diff.branch,\n status: active.status,\n submittedAt: active.submittedAt,\n resolvedAt: active.resolvedAt,\n artifactDir: record.meta.artifactDir ?? globalReviewDir(record.meta.id),\n activeTurnId: active.id,\n turns: turns.map(turnSummary),\n feedbackPath: active.feedbackPath,\n markdownPath: active.markdownPath\n };\n return {\n meta,\n turns,\n diff: active.diff,\n ...(active.feedback ? { feedback: active.feedback } : {}),\n ...(active.resolution ? { resolution: active.resolution } : {})\n };\n}\n\nfunction replaceTurn(record: ReviewRecord, nextTurn: ReviewTurn): ReviewRecord {\n return {\n ...record,\n turns: record.turns.map((turn) => (turn.id === nextTurn.id ? nextTurn : turn))\n };\n}\n\nfunction activeTurn(record: ReviewRecord): ReviewTurn {\n return (\n record.turns.find((turn) => turn.id === record.meta.activeTurnId) ??\n record.turns[record.turns.length - 1]\n );\n}\n\nfunction latestTurn(record: Pick<ReviewRecord, 'turns'>): ReviewTurn {\n return record.turns.toSorted((a, b) => a.index - b.index)[record.turns.length - 1];\n}\n\nfunction turnMeta(turn: ReviewTurn): ReviewTurnMeta {\n return {\n id: turn.id,\n index: turn.index,\n status: turn.status,\n createdAt: turn.createdAt,\n submittedAt: turn.submittedAt,\n resolvedAt: turn.resolvedAt,\n artifactDir: turn.artifactDir,\n diffPath: turn.diffPath,\n feedbackPath: turn.feedbackPath,\n markdownPath: turn.markdownPath,\n resolvedPath: turn.resolvedPath\n };\n}\n\nfunction turnSummary(turn: ReviewTurn): ReviewTurnSummary {\n return {\n ...turnMeta(turn),\n capturedAt: turn.diff.capturedAt,\n stats: turn.diff.stats,\n comments: resolutionCounts(turn.feedback, turn.resolution?.comments ?? [])\n };\n}\n\nfunction reconcileTurn(\n meta: ReviewTurnMeta,\n diff: DiffPayload,\n feedback?: FeedbackBundle,\n resolution?: ResolutionBundle\n): ReviewTurn {\n const status =\n resolution?.status === 'resolved' ? 'resolved' : feedback ? 'submitted' : 'pending';\n return {\n ...meta,\n status,\n submittedAt: feedback?.timestamp ?? meta.submittedAt,\n resolvedAt: status === 'resolved' ? (resolution?.resolvedAt ?? meta.resolvedAt) : undefined,\n feedbackPath: feedback\n ? (meta.feedbackPath ?? path.join(meta.artifactDir, 'feedback.json'))\n : undefined,\n markdownPath: feedback\n ? (meta.markdownPath ?? path.join(meta.artifactDir, 'feedback.md'))\n : undefined,\n resolvedPath: resolution\n ? (meta.resolvedPath ?? path.join(meta.artifactDir, 'resolved.json'))\n : undefined,\n diff,\n ...(feedback ? { feedback } : {}),\n ...(resolution ? { resolution } : {})\n };\n}\n\nfunction mergeRecoveredTurns(\n legacyTurn: ReviewTurn | null,\n persistedTurns: ReviewTurn[]\n): ReviewTurn[] {\n const turns =\n legacyTurn &&\n !persistedTurns.some((turn) => turn.id === legacyTurn.id || turn.index === legacyTurn.index)\n ? [legacyTurn, ...persistedTurns]\n : persistedTurns;\n return turns.toSorted((a, b) => a.index - b.index);\n}\n\nfunction diffFingerprint(diff: DiffPayload): string {\n return createHash('sha256')\n .update(\n JSON.stringify({\n base: diff.base,\n branch: diff.branch,\n cwd: diff.cwd,\n scope: diff.scope,\n rawDiff: diff.rawDiff\n })\n )\n .digest('hex');\n}\n\nfunction sameComments(left: Comment[], right: Comment[]): boolean {\n return (\n JSON.stringify(left.toSorted(compareCommentsByLocation)) ===\n JSON.stringify(right.toSorted(compareCommentsByLocation))\n );\n}\n\nfunction requiredPath(value: string | undefined, label: string): string {\n if (!value) {\n throw new Error(`Submitted review is missing ${label}`);\n }\n return value;\n}\n\nasync function readOptionalJsonFile<T>(\n filePath: string,\n guard: JsonGuard<T>,\n label: string\n): Promise<T | undefined> {\n let raw: string;\n try {\n raw = await readFile(filePath, 'utf8');\n } catch (error) {\n if (isFileNotFound(error)) {\n return undefined;\n }\n throw new Error(`Could not read ${label} at ${filePath}: ${formatError(error)}`, {\n cause: error\n });\n }\n\n return parseJsonFile(raw, guard, label, filePath);\n}\n\nfunction parseJsonFile<T>(raw: string, guard: JsonGuard<T>, label: string, filePath: string): T {\n try {\n return parseJson(raw, guard, label);\n } catch (error) {\n throw new Error(`Invalid ${label} at ${filePath}: ${formatError(error)}`, { cause: error });\n }\n}\n\nexport const reviewStore = new ReviewStore();\n","import type { 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 } from './comments';\nimport { languageForPath } from './language';\nimport { reviewScopeLabel } from './review-scope';\nimport type { FeedbackBundle } from './types';\n\nfunction fenceFor(snippet: string): string {\n let fence = '```';\n while (snippet.includes(fence)) {\n fence += '`';\n }\n return fence;\n}\n\nfunction languageForSnippet(filePath: string, snippet: string): string {\n const lines = snippet.split('\\n').filter((line) => line.length > 0);\n const looksLikeUnifiedDiff =\n lines.length > 0 &&\n lines.some((line) => line.startsWith('+') || line.startsWith('-')) &&\n lines.every((line) => line.startsWith('+') || line.startsWith('-') || line.startsWith(' '));\n return looksLikeUnifiedDiff ? 'diff' : (languageForPath(filePath) ?? '');\n}\n\nexport function serializeFeedbackMarkdown(bundle: FeedbackBundle): string {\n const comments = bundle.comments.toSorted(compareCommentsByLocation);\n const commentsByFile = new Map<string, typeof comments>();\n const files: string[] = [];\n for (const comment of comments) {\n const fileComments = commentsByFile.get(comment.filePath);\n if (fileComments) {\n fileComments.push(comment);\n } else {\n commentsByFile.set(comment.filePath, [comment]);\n files.push(comment.filePath);\n }\n }\n const lines: string[] = [\n `# Gloss feedback - ${bundle.timestamp}`,\n `Review: ${bundle.reviewId}`,\n ...(bundle.turnIndex ? [`Turn: ${bundle.turnIndex} (${bundle.turnId ?? 'unknown'})`] : []),\n ...(bundle.reviewScope ? [`Review scope: ${reviewScopeLabel(bundle.reviewScope)}`] : []),\n `Base: ${bundle.base.ref} (${bundle.base.sha.slice(0, 7)}) Branch: ${bundle.branch ?? '(detached)'}`,\n `Files: ${files.length} Comments: ${comments.length}`,\n ''\n ];\n\n for (const filePath of files) {\n lines.push(`## ${filePath}`, '');\n for (const comment of commentsByFile.get(filePath) ?? []) {\n const snippet = comment.originalSnippet.trimEnd();\n const firstSnippetLine = firstNonEmptyLine(snippet);\n const heading =\n comment.startLine === comment.endLine && firstSnippetLine\n ? `### ${formatLineRange(comment)} - \\`${firstSnippetLine.trim().slice(0, 80)}\\``\n : `### ${formatLineRange(comment)}`;\n lines.push(heading, comment.body.trim(), '');\n if (snippet) {\n const fence = fenceFor(snippet);\n lines.push(`${fence}${languageForSnippet(comment.filePath, snippet)}`, snippet, fence, '');\n }\n }\n }\n\n return `${lines.join('\\n').trimEnd()}\\n`;\n}\n\nfunction firstNonEmptyLine(text: string): string | undefined {\n for (const line of text.split('\\n')) {\n if (line.trim().length > 0) {\n return line;\n }\n }\n return undefined;\n}\n","import { 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":["rm","path","readFile","path","path","readdir","readFile","path","readFile","rm","rm","readFile","readdir","readFile","path","origin","turnSummary","path","readFile","rm"]}
|