From 6d720430ef8d45aa3ff59272e94b6fb3b6f91bf3 Mon Sep 17 00:00:00 2001 From: Sarthak Agrawal Date: Wed, 12 Aug 2026 11:33:43 +0530 Subject: [PATCH 1/2] chore: adopt fleet code health gate --- .github/workflows/ci.yml | 5 +- agent-edge.mjs | 2 +- extension/src/types.ts | 14 +- knip.json | 122 +++----- package.json | 11 +- pnpm-lock.yaml | 68 +++++ scripts/check-code-health.mjs | 358 +++++++++++++++++++++++ src/lib/actions/job-discovery-actions.ts | 12 - src/lib/actions/resume-actions.ts | 10 - src/lib/actions/token-actions.ts | 25 -- src/lib/api-timing.ts | 9 - src/lib/foundry-monitoring.ts | 2 +- vitest.config.ts | 6 +- 13 files changed, 485 insertions(+), 159 deletions(-) create mode 100644 scripts/check-code-health.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a96c2d2..f895f33 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,7 @@ on: [push, pull_request] jobs: ci: runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v6 - uses: pnpm/action-setup@v6 @@ -10,7 +11,7 @@ jobs: with: node-version: '22.19' cache: pnpm + - uses: astral-sh/setup-uv@v7 - run: pnpm install --frozen-lockfile --ignore-scripts - - run: pnpm run --if-present lint - - run: pnpm run --if-present test + - run: pnpm quality - run: pnpm cf:build diff --git a/agent-edge.mjs b/agent-edge.mjs index 74d00d5..cc4e0f3 100644 --- a/agent-edge.mjs +++ b/agent-edge.mjs @@ -10,7 +10,7 @@ /** @type {{ name: string, url: string, llmsTxt: string, llmsFullTxt?: string, indexMd: string, catalog: object }} */ // biome-ignore format: generated payload from apply-agent-surfaces (JSON keys/quotes) -export const AGENT_SURFACE = { +const AGENT_SURFACE = { "name": "RolePatch", "url": "https://rolepatch.com", "llmsFullTxt": "# RolePatch — full agent brief\n\nAI-powered resume tailoring. Score fit against a job description, rewrite bullets for the role, and prep interviews.\n\n## Index\n\n# RolePatch\n\nAI-powered resume tailoring and job-application assistant.\n\n## What it is\n\n- Score resume fit against a job description\n- Rewrite bullets for the role\n- Cover letters, company research, STAR prep\n\n## Who it's for\n\nJob seekers who want reviewed, role-specific application materials — not generic AI fluff.\n\n## Agent entrypoints\n\n- https://rolepatch.com/llms.txt\n- https://rolepatch.com/api/ai\n- https://rolepatch.com/index.md\n\nDashboard routes require auth and are not agent-indexed.\n\n## Product links\n\n- Home: https://rolepatch.com/ — Product landing\n- Pricing: https://rolepatch.com/pricing — Plans and limits\n- Tools: https://rolepatch.com/tools — Public tools\n\n## Machine surfaces\n\n- https://rolepatch.com/llms.txt\n- https://rolepatch.com/llms-full.txt\n- https://rolepatch.com/api/ai\n- https://rolepatch.com/index.md\n- https://rolepatch.com/sitemap.xml\n- https://rolepatch.com/robots.txt\n\n## Contact\n\n- Owner: https://sarthakagrawal.dev\n- Agent email for directory verification: sarthakagrawal@agentmail.to\n", diff --git a/extension/src/types.ts b/extension/src/types.ts index 1c849e4..88ecf88 100644 --- a/extension/src/types.ts +++ b/extension/src/types.ts @@ -16,7 +16,7 @@ export interface ScrapedJob { | 'generic'; } -interface ApplyPacketProfileAnswer { +export interface ApplyPacketProfileAnswer { id: string; category: string; label: string; @@ -39,7 +39,7 @@ interface ApplyPacketProofItem { source_url?: string; } -interface ApplyPacket { +export interface ApplyPacket { job_id: string; company?: string; role?: string; @@ -54,20 +54,20 @@ interface ApplyPacket { receipt?: ApplyPacketReceipt | null; } -interface ReceiptField { +export interface ReceiptField { label: string; value: string; source: 'profile' | 'resume' | 'cover_letter' | 'user' | 'system' | 'ats'; } -interface FileAttachment { +export interface FileAttachment { kind: 'resume' | 'cover_letter' | 'other'; name: string; type: string; base64: string; } -interface FillResult { +export interface FillResult { ok: boolean; job_id: string; url: string; @@ -82,7 +82,7 @@ interface FillResult { error?: string; } -interface SubmitResult { +export interface SubmitResult { ok: boolean; job_id: string; url: string; @@ -96,7 +96,7 @@ interface SubmitResult { error?: string; } -interface FieldSnapshotResult { +export interface FieldSnapshotResult { ok: boolean; fields: ReceiptField[]; error?: string; diff --git a/knip.json b/knip.json index 690c89f..df3a19e 100644 --- a/knip.json +++ b/knip.json @@ -1,100 +1,44 @@ { - "$schema": "https://unpkg.com/knip@latest/schema.json", - "entry": ["open-next.config.ts", "agent-edge.mjs"], - "project": ["**/*.{ts,tsx,js,jsx,mjs,cjs,mts}"], - "ignore": [ - "**/dist/**", - "**/build/**", - "**/.next/**", - "**/.astro/**", - "**/.output/**", - "**/node_modules/**", - "**/coverage/**", - "**/public/**", - "**/*.config.{js,ts,mjs,cjs}", - "**/eslint.config.*", - "**/blume.config.*", - "**/docs-blume/**", - "scripts/**", - "tests/e2e/**", - "test/**", - "**/*.test.{ts,tsx,js,mjs}", - "**/*.spec.{ts,tsx,js,mjs}", - "**/*.d.mts", - "**/*.d.ts", - "**/__tests__/**", - "**/playground/**", - "**/examples/**", - "extension/**" + "$schema": "https://unpkg.com/knip@6/schema.json", + "entry": [ + "src/app/**/*.{ts,tsx}", + "src/**/*.test.{ts,tsx}", + "src/**/__tests__/**/*.{ts,tsx}", + "__tests__/**/*.{ts,tsx}", + "agent-edge.mjs", + "worker.mjs", + "scripts/*.mjs", + "blume.config.ts", + "next.config.ts", + "open-next.config.ts", + "postcss.config.mjs", + "vitest.config.ts" ], + "project": [ + "src/**/*.{ts,tsx}", + "scripts/*.mjs", + "*.config.{ts,mjs}", + "agent-edge.mjs", + "worker.mjs" + ], + "ignore": ["blume.config.ts", "open-next.config.ts"], "ignoreDependencies": [ - "typescript", - "@types/*", - "biome", - "@biomejs/biome", - "prettier", - "prettier-plugin-tailwindcss", - "husky", - "lint-staged", - "vitest", - "@vitest/*", - "@cloudflare/vitest-pool-workers", - "playwright", - "@playwright/test", - "drizzle-kit", - "wrangler", - "opennextjs-cloudflare", - "tailwindcss", - "@tailwindcss/*", - "lightningcss", - "tsx", - "size-limit", - "knip", - "blume", - "@blume/*", - "stockfish", - "astro", - "@astrojs/*", - "@shikijs/*", - "shiki", - "@vercel/node", - "three-stdlib", "@mozilla/readability", "@sparticuz/chromium", + "jscpd", "mammoth", "pdf-parse", "puppeteer-core" ], - "ignoreBinaries": [ - "next", - "astro", - "vite", - "wrangler", - "drizzle-kit", - "tsx", - "biome", - "playwright", - "vitest", - "knip", - "eslint", - "prettier", - "blume", - "yt-dlp", - "tailscale", - "gemini", - "fallow", - "security" - ], - "ignoreIssues": { - "src/app/api/**/route.ts": ["exports", "types"], - "src/lib/actions/**": ["exports", "types"], - "lib/actions/**": ["exports", "types"], - "**/schema.ts": ["exports", "types"], - "**/db/schema*.ts": ["exports", "types"], - "**/commands/**": ["exports", "types"], - "**/agent-edge.*": ["exports", "types"], - "**/foundry-monitoring.ts": ["exports", "types"], - "**/analytics.ts": ["exports", "types"], - "**/api-timing.ts": ["exports", "types"] + "workspaces": { + "extension": { + "entry": ["src/background.ts", "src/content.ts", "src/popup.ts", "scripts/*.mjs"], + "project": ["src/**/*.ts", "scripts/*.mjs"] + }, + "landing-astro": { + "entry": ["src/pages/**/*.astro", "astro.config.mjs"], + "project": ["src/**/*.{astro,ts}", "astro.config.mjs"], + "ignoreDependencies": ["lightningcss", "tailwindcss"] + } } } diff --git a/package.json b/package.json index f5139c8..029e36b 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,15 @@ "docs:build": "blume build", "docs:dev": "blume dev", "knip": "knip --no-exit-code --reporter symbols", - "knip:strict": "knip --reporter symbols" + "knip:strict": "knip --reporter symbols", + "quality:unused": "node scripts/check-code-health.mjs unused", + "quality:complexity": "node scripts/check-code-health.mjs complexity", + "quality:duplication": "node scripts/check-code-health.mjs duplication", + "quality:cycles": "node scripts/check-code-health.mjs cycles", + "quality:dependencies": "node scripts/check-code-health.mjs dependencies", + "quality:suppressions": "node scripts/check-code-health.mjs suppressions", + "quality:hygiene": "node scripts/check-code-health.mjs hygiene", + "quality": "pnpm check && pnpm typecheck && pnpm test:coverage && pnpm docs:check && pnpm --filter @rolepatch/extension typecheck && pnpm quality:unused && pnpm quality:complexity && pnpm quality:duplication && pnpm quality:cycles && pnpm quality:dependencies && pnpm quality:suppressions && pnpm quality:hygiene" }, "dependencies": { "@ai-sdk/openai-compatible": "^2.0.41", @@ -80,6 +88,7 @@ "beasties": "^0.3.5", "blume": "1.2.0", "husky": "^9.1.7", + "jscpd": "5.0.14", "jsdom": "^29.1.1", "knip": "^6.29.0", "tailwindcss": "^4.3.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4ff8e69..9badbe6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -144,6 +144,9 @@ importers: husky: specifier: ^9.1.7 version: 9.1.7 + jscpd: + specifier: 5.0.14 + version: 5.0.14 jsdom: specifier: ^29.1.1 version: 29.1.1(@noble/hashes@2.2.0) @@ -6116,6 +6119,44 @@ packages: resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} hasBin: true + jscpd-darwin-arm64@5.0.14: + resolution: {integrity: sha512-Ojjl79SBuj9tEW6WbjZ1a/1ZOR89dneH9yLQYQu8WyWaQownttnx7RYFEHU6aGhS4jIvwUEbr+1wxzFTb37cwg==} + cpu: [arm64] + os: [darwin] + + jscpd-darwin-x64@5.0.14: + resolution: {integrity: sha512-DxFg5XvjMZ81iVeqillnM5apqcGCfNTbroNF+mPLr7RkHLGH6mudLgtO+ILL/hfpZXy1bF9oIY5BSudPmN/k9A==} + cpu: [x64] + os: [darwin] + + jscpd-linux-arm64-gnu@5.0.14: + resolution: {integrity: sha512-1uw+XBHEt9pONXNICSp5HpaVWPjG6mQ6deDXaq9Yb0xCNJkX4/8gmn0vhzekIyZD2DspRYKPUolbDsqm/HEdYg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + jscpd-linux-x64-gnu@5.0.14: + resolution: {integrity: sha512-dFTbyyrm+Z9pcXIVzJQCw8QAgiNqIiO69sm4AfA7/wFdPoizoVzjhaXsYXcSV4bs0aoPiWbNazg0J0HgslT/5A==} + cpu: [x64] + os: [linux] + libc: [glibc] + + jscpd-linux-x64-musl@5.0.14: + resolution: {integrity: sha512-SayS7qQJvixyy9eR0+UjepkTsUUwqvlsiuSxfIdHgG2qzqoh/thnkgiu4By8fsiiDpQONsQrRrZDwHRQ3GDrBQ==} + cpu: [x64] + os: [linux] + libc: [musl] + + jscpd-windows-x64-msvc@5.0.14: + resolution: {integrity: sha512-DqjxlVkUanlahGgY2lY7Zkrau4BUTI+AwWky+bPGK4kSK2AIOaUziY9Q19u8b58idXmJA9FKK98Fuu4ajNXVjQ==} + cpu: [x64] + os: [win32] + + jscpd@5.0.14: + resolution: {integrity: sha512-zge+FPZZAymt2Do5Z0+QHyIn4/XcUhrO/W7of9HcHZfx2AK8++dYhLA1uWtwXj47ml3Of8PbcUW4wUWvYMCc3w==} + engines: {node: '>=18'} + hasBin: true + jsdom@29.1.1: resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==} engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} @@ -14637,6 +14678,33 @@ snapshots: dependencies: argparse: 2.0.1 + jscpd-darwin-arm64@5.0.14: + optional: true + + jscpd-darwin-x64@5.0.14: + optional: true + + jscpd-linux-arm64-gnu@5.0.14: + optional: true + + jscpd-linux-x64-gnu@5.0.14: + optional: true + + jscpd-linux-x64-musl@5.0.14: + optional: true + + jscpd-windows-x64-msvc@5.0.14: + optional: true + + jscpd@5.0.14: + optionalDependencies: + jscpd-darwin-arm64: 5.0.14 + jscpd-darwin-x64: 5.0.14 + jscpd-linux-arm64-gnu: 5.0.14 + jscpd-linux-x64-gnu: 5.0.14 + jscpd-linux-x64-musl: 5.0.14 + jscpd-windows-x64-msvc: 5.0.14 + jsdom@29.1.1(@noble/hashes@2.2.0): dependencies: '@asamuzakjp/css-color': 5.1.11 diff --git a/scripts/check-code-health.mjs b/scripts/check-code-health.mjs new file mode 100644 index 0000000..58b909e --- /dev/null +++ b/scripts/check-code-health.mjs @@ -0,0 +1,358 @@ +#!/usr/bin/env node + +import { spawnSync } from 'node:child_process'; +import { mkdtempSync, readFileSync, readdirSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { dirname, extname, join, resolve } from 'node:path'; +import process from 'node:process'; +import { fileURLToPath } from 'node:url'; + +const currentFile = fileURLToPath(import.meta.url); +const projectRoot = resolve(dirname(currentFile), '..'); +const productionPaths = [ + 'src', + 'scripts', + 'extension/src', + 'landing-astro/src', + 'worker.mjs', + 'next.config.ts', + 'open-next.config.ts', + 'vitest.config.ts', +]; +const hygienePaths = [ + ...productionPaths, + '.github', + 'docs', + 'PROJECT_STATUS.md', + 'biome.json', + 'extension/package.json', + 'extension/tsconfig.json', + 'landing-astro/package.json', + 'landing-astro/tsconfig.json', + 'knip.json', + 'package.json', + 'pnpm-lock.yaml', + 'pnpm-workspace.yaml', + 'tsconfig.json', +]; +const sourceExtensions = new Set(['.astro', '.js', '.jsx', '.mjs', '.mts', '.ts', '.tsx']); +const baselines = { + complexity: { violations: 81, maxCcn: 49, maxLength: 615, maxParams: 9 }, + duplication: { + clones: 47, + duplicatedLines: 750, + percentage: 2.1453702909122114, + }, + unused: { + files: 0, + exports: 1, + types: 0, + dependencies: 1, + devDependencies: 0, + unlisted: 0, + unresolved: 0, + }, + suppressions: 13, + dependencies: { critical: 0, highIds: 21, highFindings: 29 }, +}; +const acceptedUnusedDependencies = new Set([ + 'landing-astro/package.json:@fontsource-variable/geist', +]); +const acceptedHighAdvisories = new Set([ + 'GHSA-28wg-ghj8-5hjv', + 'GHSA-2p49-hgcm-8545', + 'GHSA-2pvr-wf23-7pc7', + 'GHSA-2v37-7h3g-55p8', + 'GHSA-4cwx-7wf7-3272', + 'GHSA-52cp-r559-cp3m', + 'GHSA-5p4m-2wfm-xmqj', + 'GHSA-6g55-p6wh-862q', + 'GHSA-7p8r-x3mc-p8w7', + 'GHSA-8hv8-536x-4wqp', + 'GHSA-96hv-2xvq-fx4p', + 'GHSA-9wv6-86v2-598j', + 'GHSA-f88m-g3jw-g9cj', + 'GHSA-hm92-r4w5-c3mj', + 'GHSA-mh99-v99m-4gvg', + 'GHSA-mwp4-54f8-5fhr', + 'GHSA-r28c-9q8g-f849', + 'GHSA-rgw5-rvv9-x895', + 'GHSA-rpmf-866q-6p89', + 'GHSA-vmh5-mc38-953g', + 'GHSA-vxpw-j846-p89q', +]); + +function run(command, args, options = {}) { + const result = spawnSync(command, args, { + cwd: projectRoot, + encoding: 'utf8', + env: { ...process.env, ...(options.env ?? {}) }, + maxBuffer: 64 * 1024 * 1024, + }); + if (result.error) throw result.error; + if (result.status !== 0 && !options.allowFailure) { + process.stdout.write(result.stdout ?? ''); + process.stderr.write(result.stderr ?? ''); + throw new Error(`${command} exited with status ${result.status}`); + } + return { + status: result.status ?? 1, + stdout: result.stdout ?? '', + stderr: result.stderr ?? '', + }; +} + +function parseJson(result, label) { + try { + return JSON.parse(result.stdout); + } catch (error) { + process.stderr.write(result.stderr); + throw new Error(`${label} did not return valid JSON`, { cause: error }); + } +} + +function commandWithUvx(command, uvxArgs) { + const probe = spawnSync(command, ['--version'], { encoding: 'utf8' }); + return probe.status === 0 ? { command, prefix: [] } : { command: 'uvx', prefix: uvxArgs }; +} + +function issueCount(issues, key) { + return issues.reduce((sum, issue) => sum + (issue[key]?.length ?? 0), 0); +} + +function failRegressions(label, observed, baseline) { + const regressions = Object.entries(baseline).filter(([key, maximum]) => observed[key] > maximum); + if (regressions.length > 0) { + throw new Error( + regressions + .map(([key, maximum]) => `${label} ${key} regressed: ${observed[key]} > ${maximum}`) + .join('\n') + ); + } + if (Object.entries(baseline).some(([key, maximum]) => observed[key] < maximum)) { + console.log(`${label} improved; lower the checked-in baseline intentionally.`); + } +} + +function checkUnused() { + const report = parseJson( + run('pnpm', ['exec', 'knip', '--reporter', 'json', '--no-exit-code', '--no-progress'], { + allowFailure: true, + }), + 'Knip' + ); + const issues = report.issues ?? []; + const observed = Object.fromEntries( + Object.keys(baselines.unused).map((key) => [key, issueCount(issues, key)]) + ); + const unusedDependencies = issues.flatMap((issue) => + (issue.dependencies ?? []).map((dependency) => `${issue.file}:${dependency.name}`) + ); + const unexpectedDependencies = unusedDependencies.filter( + (dependency) => !acceptedUnusedDependencies.has(dependency) + ); + console.log( + `Unused: files=${observed.files}, exports=${observed.exports}, types=${observed.types}, ` + + `dependencies=${observed.dependencies}, devDependencies=${observed.devDependencies}, ` + + `unlisted=${observed.unlisted}, unresolved=${observed.unresolved}.` + ); + if (unexpectedDependencies.length > 0) { + throw new Error(`Unexpected unused dependencies: ${unexpectedDependencies.join(', ')}`); + } + failRegressions('Unused', observed, baselines.unused); +} + +function checkComplexity() { + const lizard = commandWithUvx('lizard', ['--from', 'lizard==1.23.0', 'lizard']); + const result = run(lizard.command, [ + ...lizard.prefix, + ...productionPaths, + '-x', + '**/*.test.*', + '-x', + '**/__tests__/**', + '-x', + 'scripts/check-code-health.mjs', + '-x', + '**/*.d.ts', + '--csv', + ]); + const rows = result.stdout + .trim() + .split('\n') + .map((line) => line.match(/^(\d+),(\d+),(\d+),(\d+),(\d+),/u)) + .filter(Boolean) + .map((match) => match.slice(1).map(Number)); + const observed = { + functions: rows.length, + nloc: rows.reduce((sum, row) => sum + row[0], 0), + violations: rows.filter((row) => row[1] > 15 || row[4] > 100 || row[3] > 7).length, + maxCcn: Math.max(0, ...rows.map((row) => row[1])), + maxLength: Math.max(0, ...rows.map((row) => row[4])), + maxParams: Math.max(0, ...rows.map((row) => row[3])), + }; + console.log( + `Complexity: ${observed.functions} functions, ${observed.nloc} NLOC, ` + + `${observed.violations} violations; max CCN ${observed.maxCcn}, ` + + `max length ${observed.maxLength}, max params ${observed.maxParams}.` + ); + failRegressions('Complexity', observed, baselines.complexity); +} + +function checkDuplication() { + const outputDirectory = mkdtempSync(join(tmpdir(), 'rolepatch-jscpd-')); + run('pnpm', [ + 'exec', + 'jscpd', + ...productionPaths, + '--min-lines', + '8', + '--min-tokens', + '60', + '--mode', + 'strict', + '--ignore', + '**/*.test.*,**/__tests__/**,**/*.d.ts,**/node_modules/**,**/dist/**,**/coverage/**,scripts/check-code-health.mjs', + '--reporters', + 'json', + '--output', + outputDirectory, + '--silent', + '--no-tips', + ]); + const observed = JSON.parse(readFileSync(join(outputDirectory, 'jscpd-report.json'), 'utf8')) + .statistics.total; + console.log( + `Duplication: ${observed.clones} groups, ${observed.duplicatedLines}/${observed.lines} lines ` + + `(${observed.percentage.toFixed(4)}%) across ${observed.sources} files.` + ); + failRegressions('Duplication', observed, baselines.duplication); +} + +function checkCycles() { + const report = parseJson( + run( + 'pnpm', + ['exec', 'knip', '--cycles', '--reporter', 'json', '--no-exit-code', '--no-progress'], + { allowFailure: true } + ), + 'Knip cycle analysis' + ); + const cycles = (report.issues ?? []).flatMap((issue) => issue.cycles ?? []); + if (cycles.length > 0) throw new Error(`Dependency cycles detected: ${cycles.length}`); + console.log('Cycles: zero JavaScript or TypeScript import cycles.'); +} + +function checkDependencies() { + const report = parseJson(run('pnpm', ['audit', '--json'], { allowFailure: true }), 'pnpm audit'); + const advisories = Object.values(report.advisories ?? {}); + const critical = advisories.filter((advisory) => advisory.severity === 'critical'); + const high = advisories.filter((advisory) => advisory.severity === 'high'); + const unexpected = [ + ...critical, + ...high.filter((advisory) => !acceptedHighAdvisories.has(advisory.github_advisory_id)), + ]; + const observed = { + critical: critical.length, + highIds: new Set(high.map((advisory) => advisory.github_advisory_id)).size, + highFindings: high.reduce( + (sum, advisory) => + sum + advisory.findings.reduce((count, finding) => count + finding.paths.length, 0), + 0 + ), + }; + console.log( + `Dependencies: ${observed.critical} critical, ${observed.highIds} accepted high IDs ` + + `across ${observed.highFindings} path findings; ${unexpected.length} unexpected.` + ); + if (unexpected.length > 0) { + throw new Error( + `Unexpected critical/high advisories: ${unexpected + .map((advisory) => advisory.github_advisory_id) + .join(', ')}` + ); + } + failRegressions('Dependencies', observed, baselines.dependencies); +} + +const suppressionPattern = + /biome-ignore|eslint-disable|@ts-ignore|@ts-expect-error|istanbul ignore|c8 ignore|(?:test|base)\.skip\(|\bTODO\b|\bFIXME\b/u; + +function sourceFiles(root) { + const files = []; + for (const entry of readdirSync(root, { withFileTypes: true })) { + const path = join(root, entry.name); + if (entry.isDirectory()) files.push(...sourceFiles(path)); + else if (entry.isFile() && sourceExtensions.has(extname(entry.name))) files.push(path); + } + return files; +} + +function checkSuppressions() { + const files = ['src', 'scripts', 'extension/src', 'landing-astro/src'].flatMap((root) => + sourceFiles(resolve(projectRoot, root)) + ); + files.push(resolve(projectRoot, 'worker.mjs')); + const matches = files + .filter((file) => file !== currentFile) + .flatMap((file) => + readFileSync(file, 'utf8') + .split('\n') + .filter((line) => suppressionPattern.test(line)) + ); + console.log(`Suppressions: ${matches.length} source/test markers.`); + if (matches.length > baselines.suppressions) { + throw new Error(`Suppressions regressed: ${matches.length} > ${baselines.suppressions}.`); + } + if (matches.length < baselines.suppressions) { + console.log('Suppressions improved; lower the checked-in baseline intentionally.'); + } +} + +function checkHygiene() { + const parent = run('git', ['rev-parse', '--verify', 'HEAD^'], { allowFailure: true }); + if (parent.status === 0) run('git', ['diff', '--check', 'HEAD^', 'HEAD', '--', ...hygienePaths]); + else run('git', ['diff-tree', '--check', '--root', '-r', 'HEAD', '--', ...hygienePaths]); + run('git', ['diff', '--check', 'HEAD', '--', ...hygienePaths]); + const conflicts = run('git', ['grep', '-nE', '^(<<<<<<< |=======|>>>>>>> )', '--', '.'], { + allowFailure: true, + }); + if (conflicts.status === 0) throw new Error(`Conflict markers found:\n${conflicts.stdout}`); + if (conflicts.status > 1) throw new Error(`git grep failed with status ${conflicts.status}`); + const generated = run('git', ['ls-files', '--others', '--exclude-standard']) + .stdout.trim() + .split('\n') + .filter(Boolean) + .filter((file) => + /(^|\/)(?:coverage|dist|build|\.next|\.open-next|\.wrangler)(?:\/|$)|(?:^|\/)\.DS_Store$|\.tsbuildinfo$/u.test( + file + ) + ); + if (generated.length > 0) { + throw new Error(`Untracked generated artifacts found: ${generated.join(', ')}`); + } + console.log('Repository hygiene: whitespace, conflicts, and generated outputs pass.'); +} + +const checks = { + unused: checkUnused, + complexity: checkComplexity, + duplication: checkDuplication, + cycles: checkCycles, + dependencies: checkDependencies, + suppressions: checkSuppressions, + hygiene: checkHygiene, +}; +const selected = process.argv[2]; + +if (!Object.hasOwn(checks, selected)) { + console.error(`Usage: check-code-health.mjs <${Object.keys(checks).join('|')}>`); + process.exit(2); +} + +try { + checks[selected](); +} catch (error) { + console.error(error instanceof Error ? error.message : String(error)); + process.exit(1); +} diff --git a/src/lib/actions/job-discovery-actions.ts b/src/lib/actions/job-discovery-actions.ts index 9592fa0..071b2ce 100644 --- a/src/lib/actions/job-discovery-actions.ts +++ b/src/lib/actions/job-discovery-actions.ts @@ -217,18 +217,6 @@ export async function listJobDiscoveryAlerts(): Promise return JSON.parse(JSON.stringify(result.rows)) as JobDiscoveryAlertRow[]; } -export async function listObservedJobFeed(limit = 100): Promise { - const safeLimit = Math.max(1, Math.min(200, Math.floor(limit))); - const result = await db.execute({ - sql: `SELECT * FROM job_discovery_alerts - WHERE user_id = ? - ORDER BY created_at DESC - LIMIT ?`, - args: [OBSERVED_JOB_FEED_USER_ID, safeLimit], - }); - return JSON.parse(JSON.stringify(result.rows)) as JobDiscoveryAlertRow[]; -} - export async function listObservedJobFeedPage( page = 1, pageSize = 50 diff --git a/src/lib/actions/resume-actions.ts b/src/lib/actions/resume-actions.ts index ef1f474..b83c3c6 100644 --- a/src/lib/actions/resume-actions.ts +++ b/src/lib/actions/resume-actions.ts @@ -90,13 +90,3 @@ export async function renameResume(id: string, name: string): Promise { }); revalidatePath('/'); } - -export async function deleteResume(id: string): Promise { - const userId = await getCurrentUserId(); - if (!userId) throw new Error('Sign in to delete resumes'); - await db.execute({ - sql: 'DELETE FROM resumes WHERE id = ? AND user_id = ?', - args: [id, userId], - }); - revalidatePath('/'); -} diff --git a/src/lib/actions/token-actions.ts b/src/lib/actions/token-actions.ts index 1120256..0257a75 100644 --- a/src/lib/actions/token-actions.ts +++ b/src/lib/actions/token-actions.ts @@ -73,31 +73,6 @@ export async function getTokenBalance(): Promise { return (result.rows[0]?.balance as number) ?? 0; } -/** - * Idempotent balance initialization for new users. - * Uses a D1 batch so the signup_bonus log is only written when the - * balance row is actually created. - */ -export async function initializeBalance(userId: string): Promise { - if (!userId || typeof userId !== 'string') { - throw new Error('Invalid user ID'); - } - - await db.batch([ - { - sql: `INSERT OR IGNORE INTO token_balances (user_id, balance, total_purchased, total_used) - VALUES (?, 3, 0, 0)`, - args: [userId], - }, - { - sql: `INSERT INTO token_transactions (id, user_id, amount, type, balance_after) - SELECT ?, ?, 3, 'signup_bonus', 3 - WHERE changes() > 0`, - args: [uuid(), userId], - }, - ]); -} - /** * Atomically debit one token and log the transaction in a D1 batch. * diff --git a/src/lib/api-timing.ts b/src/lib/api-timing.ts index 5d4d8e1..703231d 100644 --- a/src/lib/api-timing.ts +++ b/src/lib/api-timing.ts @@ -158,12 +158,3 @@ export function initApiTiming(options?: ApiTimingOptions): void { if (document.visibilityState === 'hidden') collectAndFlush(); }); } - -/** Stop sampling and flush remaining entries. */ -export function stopApiTiming(): void { - if (_flushTimer) { - clearInterval(_flushTimer); - _flushTimer = null; - } - collectAndFlush(); -} diff --git a/src/lib/foundry-monitoring.ts b/src/lib/foundry-monitoring.ts index f97efdc..fea6e7a 100644 --- a/src/lib/foundry-monitoring.ts +++ b/src/lib/foundry-monitoring.ts @@ -70,7 +70,7 @@ export function captureError( } } -export function capturePageCrash(error: unknown, source: 'window_error' | 'unhandled_rejection') { +function capturePageCrash(error: unknown, source: 'window_error' | 'unhandled_rejection') { posthog.capture('foundry_page_crash', { project_id: PROJECT_SLUG, route: route(), diff --git a/vitest.config.ts b/vitest.config.ts index b83306a..5415ece 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -29,8 +29,10 @@ export default defineConfig({ 'src/lib/**/*.sql', ], thresholds: { - lines: 20, - functions: 25, + branches: 47, + functions: 63, + lines: 55, + statements: 53, }, }, }, From cb516671b7a6223354a8f31d7c3cef1de8f338f0 Mon Sep 17 00:00:00 2001 From: Sarthak Agrawal Date: Wed, 12 Aug 2026 11:36:26 +0530 Subject: [PATCH 2/2] fix: scope hygiene to maintained code --- scripts/check-code-health.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/check-code-health.mjs b/scripts/check-code-health.mjs index 58b909e..098cb71 100644 --- a/scripts/check-code-health.mjs +++ b/scripts/check-code-health.mjs @@ -22,7 +22,6 @@ const productionPaths = [ const hygienePaths = [ ...productionPaths, '.github', - 'docs', 'PROJECT_STATUS.md', 'biome.json', 'extension/package.json',