getgloss 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/daemon.ts","../../src/shared/paths.ts","../../package.json","../../src/shared/server-info.ts","../../src/shared/json.ts","../../src/shared/validation.ts","../../src/server/index.ts","../../src/shared/comments.ts","../../src/shared/reviews.ts","../../src/server/store.ts","../../src/shared/language.ts","../../src/shared/markdown.ts"],"sourcesContent":["import { serve } from '@hono/node-server';\nimport { globalStateDir, packageVersion } from '../shared/paths';\nimport { writeServerInfo } from '../shared/server-info';\nimport { createApp } from './index';\n\nconst port = Number(process.env.GLOSS_PORT ?? '0');\n\nif (!port) {\n throw new Error('GLOSS_PORT is required');\n}\n\nconst origin = `http://localhost:${port}`;\nconst server = serve({\n fetch: createApp(origin).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\nprocess.on('SIGTERM', () => {\n server.close(() => {\n process.exit(0);\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 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.6.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 \"@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 \"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 { 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\nfunction isFileNotFound(error: unknown): boolean {\n return error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n\nfunction formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { writeFile } from 'node:fs/promises';\n\nfunction serializeJson(value: object): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nexport async function writeJsonFile(filePath: string, value: object): Promise<void> {\n await writeFile(filePath, serializeJson(value));\n}\n","import type {\n Comment,\n CreateReviewResponse,\n DiffFile,\n DiffHunk,\n DiffLine,\n DiffPayload,\n DiffStats,\n FeedbackBundle,\n HealthResponse,\n ListReviewsResponse,\n OpenResult,\n ResolutionBundle,\n ResolutionRequest,\n ResolvedComment,\n ResolveResult,\n ReviewEvent,\n ReviewMeta,\n ReviewRecord,\n ServerInfo,\n SubmitReviewRequest\n} from './types';\n\nexport type JsonGuard<T> = (value: unknown) => value is T;\n\nexport type StoredReviewMeta = Omit<ReviewMeta, 'artifactDir'> &\n Partial<Pick<ReviewMeta, 'artifactDir' | 'feedbackPath' | 'markdownPath'>>;\n\nconst reviewStatuses = ['pending', 'submitted', 'cancelled', 'resolved'] as const;\nconst resolutionStatuses = ['partial', 'resolved'] as const;\nconst reviewUpdateReasons = ['review-resolved', 'comment-resolved', 'comment-reopened'] as const;\nconst sides = ['L', 'R'] as const;\nconst diffLineTypes = ['context', 'add', 'delete'] as const;\nconst diffScopeModes = ['working', 'branch', 'explicit'] as const;\nconst diffFallbackReasons = ['working-tree-clean', 'missing-branch-base'] as const;\n\nexport function parseJson<T>(raw: string, guard: JsonGuard<T>, label: string): T {\n const parsed: unknown = JSON.parse(raw);\n return parseJsonValue(parsed, guard, label);\n}\n\nexport function parseJsonValue<T>(value: unknown, 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 isRecord(value) && isReviewMeta(value.meta) && isString(value.url);\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 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 isResolveResult(value: unknown): value is ResolveResult {\n return (\n isRecord(value) &&\n value.ok === true &&\n isString(value.reviewId) &&\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 isRecord(value) && isArrayOf(value.comments, isComment);\n}\n\nexport function isResolutionRequest(value: unknown): value is ResolutionRequest {\n return isRecord(value) && isOptionalString(value.summary);\n}\n\nexport function isReviewRecord(value: unknown): value is ReviewRecord {\n return (\n isRecord(value) &&\n isReviewMeta(value.meta) &&\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.feedbackPath) &&\n isOptionalString(value.markdownPath)\n );\n}\n\nfunction isReviewMeta(value: unknown): value is ReviewMeta {\n return isStoredReviewMeta(value) && isString(value.artifactDir);\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 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 isString(value.timestamp) &&\n isBaseRef(value.base) &&\n isNullableString(value.branch) &&\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 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.submitted':\n return (\n isRecord(value.counts) && isNumber(value.counts.files) && isNumber(value.counts.comments)\n );\n case 'review.updated':\n return (\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\nfunction isDiffScope(value: unknown): value is DiffPayload['scope'] {\n return (\n isRecord(value) &&\n isOneOf(value.mode, diffScopeModes) &&\n isNullableString(value.requestedBase) &&\n isBaseRef(value.base) &&\n isDiffRef(value.comparison) &&\n (value.fallbackReason === null || isOneOf(value.fallbackReason, diffFallbackReasons))\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 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, diffLineTypes) &&\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, reviewStatuses);\n}\n\nfunction isResolutionStatus(value: unknown): value is ResolutionBundle['status'] {\n return isOneOf(value, resolutionStatuses);\n}\n\nfunction isReviewUpdateReason(\n value: unknown\n): value is Extract<ReviewEvent, { type: 'review.updated' }>['reason'] {\n return isOneOf(value, reviewUpdateReasons);\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 } 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 { packageVersion } from '../shared/paths';\nimport { isResolvableReviewStatus } from '../shared/reviews';\nimport type {\n CreateReviewResponse,\n HealthResponse,\n ListReviewsResponse,\n OpenResult,\n ResolutionRequest,\n ReviewEvent,\n SubmitReviewRequest\n} from '../shared/types';\nimport {\n isDiffPayload,\n isResolutionRequest,\n isSubmitReviewRequest,\n type JsonGuard,\n parseJsonValue\n} from '../shared/validation';\nimport { reviewStore } from './store';\n\nconst webRoot = fileURLToPath(new URL('../web', import.meta.url));\nconst eventStreamHeartbeatMs = 15_000;\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): 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 url: `${origin}/review/${record.meta.id}`\n };\n return c.json(response, 201);\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/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 const closedPromise = new Promise<void>((resolve) => {\n close = () => {\n if (closed) {\n return;\n }\n closed = true;\n cleanup?.();\n resolve();\n };\n });\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 };\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 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 if (existing.meta.status !== 'pending') {\n return c.json({ error: `review is ${existing.meta.status} and cannot be submitted` }, 409);\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 const { record, feedbackPath, markdownPath } = await reviewStore.submit(id, body.comments);\n const response: OpenResult = {\n reviewId: id,\n url: `${origin}/review/${id}`,\n files: record.diff.files.length,\n comments: body.comments.length,\n artifactDir: record.meta.artifactDir,\n feedbackPath,\n markdownPath\n };\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 if (!isResolvableReviewStatus(existing.meta.status)) {\n return c.json({ error: `review is ${existing.meta.status} and cannot be resolved` }, 409);\n }\n if (!existing.feedback) {\n return c.json({ error: 'submitted feedback not found' }, 409);\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 return c.json(await reviewStore.markResolved(id, body.summary));\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 if (!isResolvableReviewStatus(existing.meta.status)) {\n return c.json({ error: `review is ${existing.meta.status} and cannot be resolved` }, 409);\n }\n if (!existing.feedback?.comments.some((comment) => comment.id === commentId)) {\n return c.json({ error: 'comment 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 return c.json(await reviewStore.resolveComment(id, commentId, body.summary));\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 if (!isResolvableReviewStatus(existing.meta.status)) {\n return c.json({ error: `review is ${existing.meta.status} and cannot be resolved` }, 409);\n }\n if (!existing.feedback?.comments.some((comment) => comment.id === commentId)) {\n return c.json({ error: 'comment not found' }, 404);\n }\n return c.json(await reviewStore.reopenComment(id, commentId));\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 {\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 {\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 {\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: unknown;\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 formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\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 type { ReviewStatus } from './types';\n\nexport function isResolvableReviewStatus(status: ReviewStatus): boolean {\n return status === 'submitted' || status === 'resolved';\n}\n","import type { Dirent } from 'node:fs';\nimport { readdir, readFile, writeFile } from 'node:fs/promises';\nimport { ulid } from 'ulid';\nimport { compareCommentsByLocation, countCommentFiles, resolutionCounts } from '../shared/comments';\nimport { writeJsonFile } 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} from '../shared/paths';\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 ReviewUpdateReason\n} from '../shared/types';\nimport {\n isDiffPayload,\n isFeedbackBundle,\n isResolutionBundle,\n isStoredReviewMeta,\n type JsonGuard,\n parseJson\n} from '../shared/validation';\n\ntype Listener = (event: ReviewEvent) => void;\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 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 };\n const record: ReviewRecord = { meta, diff };\n this.reviews.set(id, record);\n await this.persistInitial(record);\n this.emit({ type: 'review.opened', reviewId: id });\n return record;\n }\n\n async list(): Promise<ReviewMeta[]> {\n await this.loadAllReviews();\n return [...this.reviews.values()]\n .map((record) => record.meta)\n .sort((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 submit(\n id: string,\n comments: Comment[]\n ): Promise<{ record: ReviewRecord; feedbackPath: string; markdownPath: string }> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n if (record.meta.status !== 'pending') {\n throw new Error(`Review ${id} is ${record.meta.status} and cannot be submitted`);\n }\n const timestamp = new Date().toISOString();\n const feedback: FeedbackBundle = {\n version: 1,\n reviewId: id,\n timestamp,\n base: record.diff.base,\n branch: record.diff.branch,\n comments: [...comments].sort(compareCommentsByLocation)\n };\n record.feedback = feedback;\n record.meta = { ...record.meta, status: 'submitted', submittedAt: timestamp };\n this.reviews.set(id, record);\n\n const artifactDir = globalReviewDir(id);\n const feedbackPath = globalReviewFeedbackFile(id);\n const markdownPath = globalReviewMarkdownFile(id);\n record.meta = {\n ...record.meta,\n artifactDir,\n feedbackPath,\n markdownPath\n };\n await ensureDir(artifactDir);\n await Promise.all([\n writeJsonFile(globalReviewMetaFile(id), record.meta),\n writeJsonFile(feedbackPath, feedback),\n writeFile(markdownPath, serializeFeedbackMarkdown(feedback))\n ]);\n\n this.emit({\n type: 'review.submitted',\n reviewId: id,\n counts: {\n files: countCommentFiles(feedback.comments),\n comments: feedback.comments.length\n }\n });\n return { record, feedbackPath, markdownPath };\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): Promise<ResolveResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n this.assertResolvable(record, id);\n const resolvedAt = new Date().toISOString();\n const existingById = new Map(\n (record.resolution?.comments ?? []).map((comment) => [comment.commentId, comment])\n );\n const comments = this.sortResolvedComments(\n (record.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 record\n );\n const resolution: ResolutionBundle = {\n reviewId: id,\n status: 'resolved',\n summary: summary ?? record.resolution?.summary ?? null,\n resolvedAt,\n comments\n };\n record.meta = { ...record.meta, status: 'resolved', resolvedAt };\n return this.persistResolution(record, 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 this.assertResolvable(record, id);\n this.assertCommentExists(record, commentId);\n\n const resolvedAt = new Date().toISOString();\n const previous = record.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 ...(record.resolution?.comments ?? []).filter((comment) => comment.commentId !== commentId),\n nextComment\n ],\n record\n );\n const counts = resolutionCounts(record.feedback, comments);\n const fullyResolved = counts.total === counts.resolved;\n const resolution: ResolutionBundle = {\n reviewId: id,\n status: fullyResolved ? 'resolved' : 'partial',\n summary: fullyResolved ? (record.resolution?.summary ?? null) : null,\n resolvedAt: fullyResolved ? resolvedAt : null,\n comments\n };\n record.meta = fullyResolved\n ? { ...record.meta, status: 'resolved', resolvedAt }\n : { ...record.meta, status: 'submitted', resolvedAt: undefined };\n return this.persistResolution(record, 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 this.assertResolvable(record, id);\n this.assertCommentExists(record, commentId);\n\n const comments = this.sortResolvedComments(\n (record.resolution?.comments ?? []).filter((comment) => comment.commentId !== commentId),\n record\n );\n const counts = resolutionCounts(record.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 status: fullyResolved ? 'resolved' : 'partial',\n summary: fullyResolved ? (record.resolution?.summary ?? null) : null,\n resolvedAt,\n comments\n };\n record.meta = fullyResolved\n ? { ...record.meta, status: 'resolved', resolvedAt: resolvedAt ?? undefined }\n : { ...record.meta, status: 'submitted', resolvedAt: undefined };\n return this.persistResolution(record, 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): Promise<void> {\n const dir = globalReviewDir(record.meta.id);\n await ensureDir(dir);\n await Promise.all([\n writeJsonFile(globalReviewMetaFile(record.meta.id), record.meta),\n writeJsonFile(globalReviewDiffFile(record.meta.id), record.diff)\n ]);\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 await Promise.all(\n entries.filter((entry) => entry.isDirectory()).map((entry) => this.loadReview(entry.name))\n );\n }\n\n private async loadReview(id: string): Promise<ReviewRecord | null> {\n const metaPath = globalReviewMetaFile(id);\n const diffPath = globalReviewDiffFile(id);\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}: ${formatError(error)}`, { cause: error });\n }\n\n const meta = parseJsonFile(metaRaw, isStoredReviewMeta, 'review metadata', metaPath);\n const diff = parseJsonFile(diffRaw, isDiffPayload, 'review diff', diffPath);\n const feedback = await readOptionalJsonFile(\n globalReviewFeedbackFile(id),\n isFeedbackBundle,\n 'review feedback'\n );\n const resolution = await readOptionalJsonFile(\n globalReviewResolvedFile(id),\n isResolutionBundle,\n 'review resolution'\n );\n\n const record: ReviewRecord = {\n meta: {\n ...meta,\n artifactDir: meta.artifactDir ?? globalReviewDir(id),\n feedbackPath: meta.feedbackPath ?? (feedback ? globalReviewFeedbackFile(id) : undefined),\n markdownPath: meta.markdownPath ?? (feedback ? globalReviewMarkdownFile(id) : undefined)\n },\n diff,\n feedback,\n resolution\n };\n this.reviews.set(id, record);\n return record;\n }\n\n private assertResolvable(\n record: ReviewRecord,\n id: string\n ): asserts record is ReviewRecord & {\n feedback: FeedbackBundle;\n } {\n if (!isResolvableReviewStatus(record.meta.status)) {\n throw new Error(`Review ${id} is ${record.meta.status} and cannot be resolved`);\n }\n if (!record.feedback) {\n throw new Error(`Review ${id} has no submitted feedback`);\n }\n }\n\n private assertCommentExists(\n record: ReviewRecord & { feedback: FeedbackBundle },\n commentId: string\n ): void {\n if (!record.feedback.comments.some((comment) => comment.id === commentId)) {\n throw new Error(`Comment ${commentId} not found`);\n }\n }\n\n private async persistResolution(\n record: ReviewRecord & { feedback: FeedbackBundle },\n resolution: ResolutionBundle,\n reason: ReviewUpdateReason\n ): Promise<ResolveResult> {\n record.resolution = resolution;\n this.reviews.set(record.meta.id, record);\n const resolvedPath = globalReviewResolvedFile(record.meta.id);\n await ensureDir(globalReviewDir(record.meta.id));\n await Promise.all([\n writeJsonFile(resolvedPath, resolution),\n writeJsonFile(globalReviewMetaFile(record.meta.id), record.meta)\n ]);\n const result: ResolveResult = {\n ok: true,\n reviewId: record.meta.id,\n status: record.meta.status,\n resolutionStatus: resolution.status,\n comments: resolutionCounts(record.feedback, resolution.comments),\n path: resolvedPath,\n resolution\n };\n this.emit({\n type: 'review.updated',\n reviewId: record.meta.id,\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 record: ReviewRecord & { feedback: FeedbackBundle }\n ): ResolvedComment[] {\n const feedbackIndex = new Map(\n record.feedback.comments.map((comment, index) => [comment.id, index] as const)\n );\n return comments\n .filter((comment) => feedbackIndex.has(comment.commentId))\n .sort(\n (a, b) =>\n (feedbackIndex.get(a.commentId) ?? Number.MAX_SAFE_INTEGER) -\n (feedbackIndex.get(b.commentId) ?? Number.MAX_SAFE_INTEGER)\n );\n }\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\nfunction isFileNotFound(error: unknown): boolean {\n return error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n\nfunction formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport const reviewStore = new ReviewStore();\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 { compareCommentsByLocation, formatLineRange } from './comments';\nimport { languageForPath } from './language';\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].sort(compareCommentsByLocation);\n const files = [...new Set(comments.map((comment) => comment.filePath))];\n const lines: string[] = [\n `# Gloss feedback - ${bundle.timestamp}`,\n `Review: ${bundle.reviewId}`,\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 comments.filter((item) => item.filePath === filePath)) {\n const snippet = comment.originalSnippet.trimEnd();\n const firstSnippetLine = snippet.split('\\n').find((line) => line.trim().length > 0);\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"],"mappings":"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","names":["readFile","path","readFile","writeFile","path","writeFile","readFile","origin","path","readFile","formatError"]}
1
+ {"version":3,"sources":["../../src/server/daemon.ts","../../src/shared/paths.ts","../../package.json","../../src/shared/server-info.ts","../../src/shared/json.ts","../../src/shared/validation.ts","../../src/server/index.ts","../../src/shared/comments.ts","../../src/shared/reviews.ts","../../src/server/store.ts","../../src/shared/language.ts","../../src/shared/markdown.ts"],"sourcesContent":["import { serve } from '@hono/node-server';\nimport { globalStateDir, packageVersion } from '../shared/paths';\nimport { writeServerInfo } from '../shared/server-info';\nimport { createApp } from './index';\n\nconst port = Number(process.env.GLOSS_PORT ?? '0');\n\nif (!port) {\n throw new Error('GLOSS_PORT is required');\n}\n\nconst origin = `http://localhost:${port}`;\nconst server = serve({\n fetch: createApp(origin).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\nprocess.on('SIGTERM', () => {\n server.close(() => {\n process.exit(0);\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 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.7.1\",\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 \"@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 \"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 { 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\nfunction isFileNotFound(error: unknown): boolean {\n return error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n\nfunction formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { writeFile } from 'node:fs/promises';\n\nfunction serializeJson(value: object): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nexport async function writeJsonFile(filePath: string, value: object): Promise<void> {\n await writeFile(filePath, serializeJson(value));\n}\n","import type {\n Comment,\n CreateReviewResponse,\n DiffFile,\n DiffHunk,\n DiffLine,\n DiffPayload,\n DiffStats,\n FeedbackBundle,\n HealthResponse,\n ListReviewsResponse,\n OpenResult,\n ResolutionBundle,\n ResolutionRequest,\n ResolvedComment,\n ResolveResult,\n ReviewEvent,\n ReviewMeta,\n ReviewRecord,\n ServerInfo,\n SubmitReviewRequest\n} from './types';\n\nexport type JsonGuard<T> = (value: unknown) => value is T;\n\nexport type StoredReviewMeta = Omit<ReviewMeta, 'artifactDir'> &\n Partial<Pick<ReviewMeta, 'artifactDir' | 'feedbackPath' | 'markdownPath'>>;\n\nconst reviewStatuses = ['pending', 'submitted', 'cancelled', 'resolved'] as const;\nconst resolutionStatuses = ['partial', 'resolved'] as const;\nconst reviewUpdateReasons = ['review-resolved', 'comment-resolved', 'comment-reopened'] as const;\nconst sides = ['L', 'R'] as const;\nconst diffLineTypes = ['context', 'add', 'delete'] as const;\nconst diffScopeModes = ['working', 'branch', 'explicit'] as const;\nconst diffFallbackReasons = ['working-tree-clean', 'missing-branch-base'] as const;\n\nexport function parseJson<T>(raw: string, guard: JsonGuard<T>, label: string): T {\n const parsed: unknown = JSON.parse(raw);\n return parseJsonValue(parsed, guard, label);\n}\n\nexport function parseJsonValue<T>(value: unknown, 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 isRecord(value) && isReviewMeta(value.meta) && isString(value.url);\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 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 isResolveResult(value: unknown): value is ResolveResult {\n return (\n isRecord(value) &&\n value.ok === true &&\n isString(value.reviewId) &&\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 isRecord(value) && isArrayOf(value.comments, isComment);\n}\n\nexport function isResolutionRequest(value: unknown): value is ResolutionRequest {\n return isRecord(value) && isOptionalString(value.summary);\n}\n\nexport function isReviewRecord(value: unknown): value is ReviewRecord {\n return (\n isRecord(value) &&\n isReviewMeta(value.meta) &&\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.feedbackPath) &&\n isOptionalString(value.markdownPath)\n );\n}\n\nfunction isReviewMeta(value: unknown): value is ReviewMeta {\n return isStoredReviewMeta(value) && isString(value.artifactDir);\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 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 isString(value.timestamp) &&\n isBaseRef(value.base) &&\n isNullableString(value.branch) &&\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 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.submitted':\n return (\n isRecord(value.counts) && isNumber(value.counts.files) && isNumber(value.counts.comments)\n );\n case 'review.updated':\n return (\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\nfunction isDiffScope(value: unknown): value is DiffPayload['scope'] {\n return (\n isRecord(value) &&\n isOneOf(value.mode, diffScopeModes) &&\n isNullableString(value.requestedBase) &&\n isBaseRef(value.base) &&\n isDiffRef(value.comparison) &&\n (value.fallbackReason === null || isOneOf(value.fallbackReason, diffFallbackReasons))\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 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, diffLineTypes) &&\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, reviewStatuses);\n}\n\nfunction isResolutionStatus(value: unknown): value is ResolutionBundle['status'] {\n return isOneOf(value, resolutionStatuses);\n}\n\nfunction isReviewUpdateReason(\n value: unknown\n): value is Extract<ReviewEvent, { type: 'review.updated' }>['reason'] {\n return isOneOf(value, reviewUpdateReasons);\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 } 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 { packageVersion } from '../shared/paths';\nimport { isResolvableReviewStatus } from '../shared/reviews';\nimport type {\n CreateReviewResponse,\n HealthResponse,\n ListReviewsResponse,\n OpenResult,\n ResolutionRequest,\n ReviewEvent,\n SubmitReviewRequest\n} from '../shared/types';\nimport {\n isDiffPayload,\n isResolutionRequest,\n isSubmitReviewRequest,\n type JsonGuard,\n parseJsonValue\n} from '../shared/validation';\nimport { reviewStore } from './store';\n\nconst webRoot = fileURLToPath(new URL('../web', import.meta.url));\nconst eventStreamHeartbeatMs = 15_000;\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): 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 url: `${origin}/review/${record.meta.id}`\n };\n return c.json(response, 201);\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/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 const closedPromise = new Promise<void>((resolve) => {\n close = () => {\n if (closed) {\n return;\n }\n closed = true;\n cleanup?.();\n resolve();\n };\n });\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 };\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 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 if (existing.meta.status !== 'pending') {\n return c.json({ error: `review is ${existing.meta.status} and cannot be submitted` }, 409);\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 const { record, feedbackPath, markdownPath } = await reviewStore.submit(id, body.comments);\n const response: OpenResult = {\n reviewId: id,\n url: `${origin}/review/${id}`,\n files: record.diff.files.length,\n comments: body.comments.length,\n artifactDir: record.meta.artifactDir,\n feedbackPath,\n markdownPath\n };\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 if (!isResolvableReviewStatus(existing.meta.status)) {\n return c.json({ error: `review is ${existing.meta.status} and cannot be resolved` }, 409);\n }\n if (!existing.feedback) {\n return c.json({ error: 'submitted feedback not found' }, 409);\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 return c.json(await reviewStore.markResolved(id, body.summary));\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 if (!isResolvableReviewStatus(existing.meta.status)) {\n return c.json({ error: `review is ${existing.meta.status} and cannot be resolved` }, 409);\n }\n if (!existing.feedback?.comments.some((comment) => comment.id === commentId)) {\n return c.json({ error: 'comment 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 return c.json(await reviewStore.resolveComment(id, commentId, body.summary));\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 if (!isResolvableReviewStatus(existing.meta.status)) {\n return c.json({ error: `review is ${existing.meta.status} and cannot be resolved` }, 409);\n }\n if (!existing.feedback?.comments.some((comment) => comment.id === commentId)) {\n return c.json({ error: 'comment not found' }, 404);\n }\n return c.json(await reviewStore.reopenComment(id, commentId));\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 {\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 {\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 {\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: unknown;\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 formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\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 type { ReviewStatus } from './types';\n\nexport function isResolvableReviewStatus(status: ReviewStatus): boolean {\n return status === 'submitted' || status === 'resolved';\n}\n","import type { Dirent } from 'node:fs';\nimport { readdir, readFile, writeFile } from 'node:fs/promises';\nimport { ulid } from 'ulid';\nimport { compareCommentsByLocation, countCommentFiles, resolutionCounts } from '../shared/comments';\nimport { writeJsonFile } 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} from '../shared/paths';\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 ReviewUpdateReason\n} from '../shared/types';\nimport {\n isDiffPayload,\n isFeedbackBundle,\n isResolutionBundle,\n isStoredReviewMeta,\n type JsonGuard,\n parseJson\n} from '../shared/validation';\n\ntype Listener = (event: ReviewEvent) => void;\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 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 };\n const record: ReviewRecord = { meta, diff };\n this.reviews.set(id, record);\n await this.persistInitial(record);\n this.emit({ type: 'review.opened', reviewId: id });\n return record;\n }\n\n async list(): Promise<ReviewMeta[]> {\n await this.loadAllReviews();\n return [...this.reviews.values()]\n .map((record) => record.meta)\n .sort((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 submit(\n id: string,\n comments: Comment[]\n ): Promise<{ record: ReviewRecord; feedbackPath: string; markdownPath: string }> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n if (record.meta.status !== 'pending') {\n throw new Error(`Review ${id} is ${record.meta.status} and cannot be submitted`);\n }\n const timestamp = new Date().toISOString();\n const feedback: FeedbackBundle = {\n version: 1,\n reviewId: id,\n timestamp,\n base: record.diff.base,\n branch: record.diff.branch,\n comments: [...comments].sort(compareCommentsByLocation)\n };\n record.feedback = feedback;\n record.meta = { ...record.meta, status: 'submitted', submittedAt: timestamp };\n this.reviews.set(id, record);\n\n const artifactDir = globalReviewDir(id);\n const feedbackPath = globalReviewFeedbackFile(id);\n const markdownPath = globalReviewMarkdownFile(id);\n record.meta = {\n ...record.meta,\n artifactDir,\n feedbackPath,\n markdownPath\n };\n await ensureDir(artifactDir);\n await Promise.all([\n writeJsonFile(globalReviewMetaFile(id), record.meta),\n writeJsonFile(feedbackPath, feedback),\n writeFile(markdownPath, serializeFeedbackMarkdown(feedback))\n ]);\n\n this.emit({\n type: 'review.submitted',\n reviewId: id,\n counts: {\n files: countCommentFiles(feedback.comments),\n comments: feedback.comments.length\n }\n });\n return { record, feedbackPath, markdownPath };\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): Promise<ResolveResult> {\n const record = await this.get(id);\n if (!record) {\n throw new Error(`Review ${id} not found`);\n }\n this.assertResolvable(record, id);\n const resolvedAt = new Date().toISOString();\n const existingById = new Map(\n (record.resolution?.comments ?? []).map((comment) => [comment.commentId, comment])\n );\n const comments = this.sortResolvedComments(\n (record.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 record\n );\n const resolution: ResolutionBundle = {\n reviewId: id,\n status: 'resolved',\n summary: summary ?? record.resolution?.summary ?? null,\n resolvedAt,\n comments\n };\n record.meta = { ...record.meta, status: 'resolved', resolvedAt };\n return this.persistResolution(record, 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 this.assertResolvable(record, id);\n this.assertCommentExists(record, commentId);\n\n const resolvedAt = new Date().toISOString();\n const previous = record.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 ...(record.resolution?.comments ?? []).filter((comment) => comment.commentId !== commentId),\n nextComment\n ],\n record\n );\n const counts = resolutionCounts(record.feedback, comments);\n const fullyResolved = counts.total === counts.resolved;\n const resolution: ResolutionBundle = {\n reviewId: id,\n status: fullyResolved ? 'resolved' : 'partial',\n summary: fullyResolved ? (record.resolution?.summary ?? null) : null,\n resolvedAt: fullyResolved ? resolvedAt : null,\n comments\n };\n record.meta = fullyResolved\n ? { ...record.meta, status: 'resolved', resolvedAt }\n : { ...record.meta, status: 'submitted', resolvedAt: undefined };\n return this.persistResolution(record, 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 this.assertResolvable(record, id);\n this.assertCommentExists(record, commentId);\n\n const comments = this.sortResolvedComments(\n (record.resolution?.comments ?? []).filter((comment) => comment.commentId !== commentId),\n record\n );\n const counts = resolutionCounts(record.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 status: fullyResolved ? 'resolved' : 'partial',\n summary: fullyResolved ? (record.resolution?.summary ?? null) : null,\n resolvedAt,\n comments\n };\n record.meta = fullyResolved\n ? { ...record.meta, status: 'resolved', resolvedAt: resolvedAt ?? undefined }\n : { ...record.meta, status: 'submitted', resolvedAt: undefined };\n return this.persistResolution(record, 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): Promise<void> {\n const dir = globalReviewDir(record.meta.id);\n await ensureDir(dir);\n await Promise.all([\n writeJsonFile(globalReviewMetaFile(record.meta.id), record.meta),\n writeJsonFile(globalReviewDiffFile(record.meta.id), record.diff)\n ]);\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 await Promise.all(\n entries.filter((entry) => entry.isDirectory()).map((entry) => this.loadReview(entry.name))\n );\n }\n\n private async loadReview(id: string): Promise<ReviewRecord | null> {\n const metaPath = globalReviewMetaFile(id);\n const diffPath = globalReviewDiffFile(id);\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}: ${formatError(error)}`, { cause: error });\n }\n\n const meta = parseJsonFile(metaRaw, isStoredReviewMeta, 'review metadata', metaPath);\n const diff = parseJsonFile(diffRaw, isDiffPayload, 'review diff', diffPath);\n const feedback = await readOptionalJsonFile(\n globalReviewFeedbackFile(id),\n isFeedbackBundle,\n 'review feedback'\n );\n const resolution = await readOptionalJsonFile(\n globalReviewResolvedFile(id),\n isResolutionBundle,\n 'review resolution'\n );\n\n const record: ReviewRecord = {\n meta: {\n ...meta,\n artifactDir: meta.artifactDir ?? globalReviewDir(id),\n feedbackPath: meta.feedbackPath ?? (feedback ? globalReviewFeedbackFile(id) : undefined),\n markdownPath: meta.markdownPath ?? (feedback ? globalReviewMarkdownFile(id) : undefined)\n },\n diff,\n feedback,\n resolution\n };\n this.reviews.set(id, record);\n return record;\n }\n\n private assertResolvable(\n record: ReviewRecord,\n id: string\n ): asserts record is ReviewRecord & {\n feedback: FeedbackBundle;\n } {\n if (!isResolvableReviewStatus(record.meta.status)) {\n throw new Error(`Review ${id} is ${record.meta.status} and cannot be resolved`);\n }\n if (!record.feedback) {\n throw new Error(`Review ${id} has no submitted feedback`);\n }\n }\n\n private assertCommentExists(\n record: ReviewRecord & { feedback: FeedbackBundle },\n commentId: string\n ): void {\n if (!record.feedback.comments.some((comment) => comment.id === commentId)) {\n throw new Error(`Comment ${commentId} not found`);\n }\n }\n\n private async persistResolution(\n record: ReviewRecord & { feedback: FeedbackBundle },\n resolution: ResolutionBundle,\n reason: ReviewUpdateReason\n ): Promise<ResolveResult> {\n record.resolution = resolution;\n this.reviews.set(record.meta.id, record);\n const resolvedPath = globalReviewResolvedFile(record.meta.id);\n await ensureDir(globalReviewDir(record.meta.id));\n await Promise.all([\n writeJsonFile(resolvedPath, resolution),\n writeJsonFile(globalReviewMetaFile(record.meta.id), record.meta)\n ]);\n const result: ResolveResult = {\n ok: true,\n reviewId: record.meta.id,\n status: record.meta.status,\n resolutionStatus: resolution.status,\n comments: resolutionCounts(record.feedback, resolution.comments),\n path: resolvedPath,\n resolution\n };\n this.emit({\n type: 'review.updated',\n reviewId: record.meta.id,\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 record: ReviewRecord & { feedback: FeedbackBundle }\n ): ResolvedComment[] {\n const feedbackIndex = new Map(\n record.feedback.comments.map((comment, index) => [comment.id, index] as const)\n );\n return comments\n .filter((comment) => feedbackIndex.has(comment.commentId))\n .sort(\n (a, b) =>\n (feedbackIndex.get(a.commentId) ?? Number.MAX_SAFE_INTEGER) -\n (feedbackIndex.get(b.commentId) ?? Number.MAX_SAFE_INTEGER)\n );\n }\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\nfunction isFileNotFound(error: unknown): boolean {\n return error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n\nfunction formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport const reviewStore = new ReviewStore();\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 { compareCommentsByLocation, formatLineRange } from './comments';\nimport { languageForPath } from './language';\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].sort(compareCommentsByLocation);\n const files = [...new Set(comments.map((comment) => comment.filePath))];\n const lines: string[] = [\n `# Gloss feedback - ${bundle.timestamp}`,\n `Review: ${bundle.reviewId}`,\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 comments.filter((item) => item.filePath === filePath)) {\n const snippet = comment.originalSnippet.trimEnd();\n const firstSnippetLine = snippet.split('\\n').find((line) => line.trim().length > 0);\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"],"mappings":"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","names":["readFile","path","readFile","writeFile","path","writeFile","readFile","origin","path","readFile","formatError"]}