Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 2
- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v6
with:
node-version: '24'
cache: pnpm
- uses: actions/setup-python@v6
with:
python-version: '3.12'
- run: pnpm install --frozen-lockfile --ignore-scripts
- run: pnpm run validate:env:build
- run: pnpm run --if-present lint
- run: pnpm run --if-present type-check
- run: pnpm run --if-present test
- run: python -m pip install lizard==1.23.0
- run: pnpm quality
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pnpm cf:build # build + landing-astro + overlay into dist/
pnpm deploy # validate env + cf:build + wrangler deploy (manual; CI does not auto-deploy)
pnpm typecheck # tsc --noEmit (app + worker tsconfigs)
pnpm test # vitest run
pnpm quality # complete local/CI code-health gate
pnpm test:e2e # playwright
pnpm lint # biome check .
pnpm format # biome format --write .
Expand Down
12 changes: 8 additions & 4 deletions PROJECT_STATUS.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# PROJECT_STATUS — Reader

> **Pointer.** The canonical current-state view is now
> [`STATUS.md`](STATUS.md). This file is kept for fleet tooling that reads
> `PROJECT_STATUS.md` by name (e.g. the `name-domains` skill). For the full
> product/feature/architecture record, see [`docs/`](docs/index.md).
This is Reader's durable current and shipped product truth. For the full
product, feature, and architecture record, see [`docs/`](docs/index.md).

## Why / What

Expand All @@ -22,6 +20,11 @@ maintenance-first support.

## Timeline

- **2026-08-12:** Adopted the Fleet code-health contract across the app,
Worker, landing, and Chrome extension with truthful whole-library coverage,
unused-code, cycle, complexity, duplication, dependency, suppression, build,
docs, and repository-hygiene ratchets in CI. Removed the retired Firebase
migration and unused extension/UI surfaces; remaining debt is in GitHub.
- **2026-08-09:** Adopted the verified Ultracite-backed Biome baseline through
the existing non-writing check, with explicit compatibility exceptions and
no source rewrite, production dependency, storage/auth/AI, migration, or
Expand Down Expand Up @@ -51,6 +54,7 @@ maintenance-first support.
- HTML-only public sitemap with cataloged Markdown mirrors for agent discovery.
- Exact Ultracite-backed Biome presets with explicit local compatibility
exceptions; `pnpm check` remains non-writing.
- One `pnpm quality` command reproduces the complete hosted code-health gate.

## Work queue

Expand Down
2 changes: 1 addition & 1 deletion docs/development/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ ordering; run `pnpm run` to see the live list.
| `pnpm test` | `vitest run` |
| `pnpm test:watch` | `vitest` |
| `pnpm test:coverage` | `vitest run --coverage` |
| `pnpm quality` | Complete CI code-health gate across the app, Worker, landing, and extension |
| `pnpm test:e2e` | `playwright test` |
| `pnpm memory:demo` | `tsx scripts/memory-capture-demo.ts` |
| `pnpm db:generate` | Generate a tracked D1 migration from `src/lib/db/schema.ts` |
| `pnpm db:migrate:local` | Apply tracked migrations to isolated local D1 |
| `pnpm db:migrate:remote` | Explicitly apply tracked migrations to the configured remote D1 |
| `pnpm migrate:firestore` | Legacy Firestore → D1 migration (`tsx scripts/migrate-firestore-to-d1.ts`; dry-run by default) |
| `pnpm prepare` | `husky` (installs pre-commit hook) |
| `pnpm format` | `biome format --write .` |
| `pnpm format:check` | `biome format .` |
Expand Down
21 changes: 16 additions & 5 deletions docs/development/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
`src/lib/__tests__/memory-capture.test.ts`,
`src/worker/routes/__tests__/` (route-level tests).

Coverage includes the complete `src/lib/**/*.{ts,tsx}` denominator. The
ratchet starts at the result the suite proves: 37% lines, 35% functions, 28%
branches, and 34% statements. Thresholds may move up, never silently down.

## Playwright (e2e)

- Config: `playwright.config.ts`.
Expand All @@ -30,14 +34,21 @@ type-check; CI runs it on every push/PR.
## Chrome extension tests

`packages/chrome-extension/` has its own Vitest config
(`packages/chrome-extension/vitest.config.ts`); run `pnpm test` from that
directory. Excluded from root tooling.
(`packages/chrome-extension/vitest.config.ts`). The complete root `pnpm quality`
gate runs its type check, 20 tests, and production build in addition to the app
and Worker checks.

## CI

CI (`.github/workflows/ci.yml`) runs on push/PR to `main`/`master`:
`pnpm install --frozen-lockfile --ignore-scripts` → `validate:env:build` →
`lint` → `type-check` → `test`. See [../operations/ci-cd.md](../operations/ci-cd.md).
CI (`.github/workflows/ci.yml`) runs `pnpm quality` on pushes and PRs to
`main`/`master`. In addition to formatting, lint, types, tests, docs, and builds,
the command blocks regressions in coverage, unused code, complexity, exact
duplication, dependency advisories, import cycles, suppressions, and repository
hygiene. Existing debt is recorded in GitHub issue #42 as checked ceilings, not
described as clean. See [../operations/ci-cd.md](../operations/ci-cd.md).

Biome currently reports 39 established warnings. `pnpm lint` rejects errors or
any increase in that count; each cleanup should lower the baseline.

## Documentation checks

Expand Down
8 changes: 5 additions & 3 deletions docs/operations/ci-cd.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ for triggers and steps; this page documents intent.

**Triggers:** push to `main`/`master`, PR to `main`/`master`.

**Steps:** checkout → pnpm setup → Node 24 →
`pnpm install --frozen-lockfile --ignore-scripts` → `validate:env:build` →
`lint` (if present) → `type-check` (if present) → `test` (if present).
**Steps:** checkout → pnpm setup → Node 24 + Python 3.12 →
`pnpm install --frozen-lockfile --ignore-scripts` → install pinned Lizard →
`pnpm quality` (format, lint, types, app/Worker coverage, extension checks,
unused code, complexity, duplication, cycles, dependency risk, suppressions,
docs, production builds, and repository hygiene).

No deploy. No secrets beyond what `validate:env:build` needs (none for
`build` mode).
Expand Down
90 changes: 0 additions & 90 deletions knip.json

This file was deleted.

49 changes: 49 additions & 0 deletions knip.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"$schema": "https://unpkg.com/knip@6/schema.json",
"workspaces": {
".": {
"entry": [
"src/main.tsx",
"src/worker.ts",
"src/agent-edge.mjs",
"scripts/*.{mjs,ts}",
"*.config.{js,ts,mjs,cjs}"
],
"project": ["src/**/*.{ts,tsx,mjs}", "scripts/*.{mjs,ts}", "*.config.{js,ts,mjs,cjs}"],
"ignoreDependencies": [
// Loaded through Tailwind CSS directives rather than JavaScript imports.
"@tailwindcss/typography",
// Optional documentation presentation layer; Markdown remains authoritative.
"blume",
// Spawned by the code-health checker rather than imported.
"jscpd",
"tailwindcss"
],
"ignoreBinaries": ["blume"]
},
"landing-astro": {
"entry": ["src/pages/**/*.astro", "astro.config.mjs"],
"project": ["src/**/*.{astro,ts,tsx}", "astro.config.mjs"],
"ignoreDependencies": [
// Astro consumes Lightning CSS from its build configuration.
"lightningcss"
]
},
"packages/chrome-extension": {
"entry": [
"src/background.ts",
"src/content-script.ts",
"src/popup/main.tsx",
"src/side-panel/main.tsx",
"*.config.{js,ts,mjs,cjs}"
],
"project": ["src/**/*.{ts,tsx}", "*.config.{js,ts,mjs,cjs}"],
"ignoreDependencies": [
// CSS/PostCSS integrations are not visible in the TypeScript graph.
"@tailwindcss/typography",
"autoprefixer",
"tailwindcss"
]
}
}
}
33 changes: 25 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"cf:build": "pnpm build && pnpm --filter ./landing-astro build && node scripts/overlay-astro-landing.mjs",
"preview": "vite preview",
"deploy": "pnpm validate:env:deploy && pnpm cf:build && pnpm exec wrangler deploy --tag \"$(git rev-parse HEAD)\"",
"lint": "biome check .",
"lint": "node scripts/check-code-health.mjs lint",
"type-check": "pnpm typecheck",
"typecheck": "tsc --noEmit -p tsconfig.app.json && tsc --noEmit -p tsconfig.worker.json",
"validate:env:build": "node scripts/validate-env.mjs build",
Expand All @@ -27,7 +27,6 @@
"db:generate": "drizzle-kit generate",
"db:migrate:local": "wrangler d1 migrations apply DB --local --config wrangler.local.toml",
"db:migrate:remote": "wrangler d1 migrations apply DB --remote",
"migrate:firestore": "tsx scripts/migrate-firestore-to-d1.ts",
"prepare": "husky",
"format": "biome format --write .",
"format:check": "biome format .",
Expand All @@ -36,7 +35,15 @@
"docs:dev": "blume dev",
"docs:build": "blume build",
"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 format:check && pnpm lint && pnpm typecheck && pnpm test:coverage && pnpm --filter web-annotator-extension type-check && pnpm --filter web-annotator-extension test && pnpm quality:unused && pnpm quality:complexity && pnpm quality:duplication && pnpm quality:cycles && pnpm quality:dependencies && pnpm quality:suppressions && pnpm docs:check && pnpm cf:build && pnpm --filter web-annotator-extension build && pnpm quality:hygiene"
},
"packageManager": "[email protected]",
"engines": {
Expand All @@ -60,11 +67,11 @@
"@tanstack/react-query": "5.101.4",
"@xyflow/react": "12.11.2",
"ai": "6.0.168",
"better-auth": "1.6.11",
"better-auth": "1.6.27",
"class-variance-authority": "0.7.1",
"drizzle-orm": "0.45.2",
"eventsource-parser": "3.1.0",
"hono": "4.12.32",
"hono": "4.13.1",
"linkedom": "0.18.13",
"lucide-react": "1.27.0",
"pdfjs-dist": "5.4.624",
Expand All @@ -73,7 +80,7 @@
"react-dom": "19.2.8",
"react-markdown": "10.1.0",
"react-pdf": "10.4.1",
"react-router-dom": "7.18.1",
"react-router-dom": "7.18.2",
"remark-gfm": "4.0.1",
"sanitize-html": "2.17.6"
},
Expand All @@ -88,11 +95,12 @@
"@types/react-dom": "19",
"@types/sanitize-html": "2.16.1",
"@vitejs/plugin-react": "6.0.4",
"@vitest/coverage-v8": "4.1.10",
"concurrently": "9.2.1",
"dotenv": "17.4.2",
"drizzle-kit": "0.31.10",
"happy-dom": "20.11.1",
"husky": "9.1.7",
"jscpd": "5.0.14",
"knip": "^6.29.0",
"lint-staged": "16.4.0",
"tailwindcss": "^4.3.3",
Expand All @@ -105,7 +113,16 @@
},
"pnpm": {
"overrides": {
"shell-quote": "1.9.0"
"dompurify@<=3.4.12": "3.4.13",
"js-yaml@>=4.0.0 <4.3.1": "4.3.1",
"nanoid@<3.3.18": "3.3.18",
"next@>=16.0.0 <16.2.11": "16.2.11",
"postcss@<=8.5.22": "8.5.23",
"sharp@<0.35.0": "0.35.3",
"shell-quote": "1.9.0",
"svgo@>=4.0.0 <4.0.2": "4.0.2",
"undici@>=7.0.0 <7.29.0": "7.29.0",
"ws@>=8.0.0 <8.21.0": "8.21.0"
}
}
}
10 changes: 4 additions & 6 deletions packages/chrome-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,16 @@
"devDependencies": {
"@tailwindcss/postcss": "4",
"@tailwindcss/typography": "0.5.19",
"@testing-library/jest-dom": "6.9.1",
"@testing-library/react": "16.3.2",
"@types/chrome": "0.0.304",
"@types/react": "19",
"@types/react-dom": "19",
"@vitejs/plugin-react": "6.0.1",
"@vitejs/plugin-react": "6.0.5",
"autoprefixer": "10.5.0",
"happy-dom": "20.9.0",
"postcss": "8.5.10",
"happy-dom": "20.11.2",
"postcss": "8.5.23",
"tailwindcss": "4",
"typescript": "6.0.3",
"vite": "8.0.10",
"vite": "8.2.1",
"vitest": "4.1.5"
}
}
Loading