Quality Gates
Documents the automatic checks that protect code quality. Updated: 23/Jun/2026
Quality Chain
Each commit goes through 3 layers of verification before reaching production:
[Commit] → pre-commit (5 gates, <120s) → [Push] → pre-push (E2E + doc audit + deploy check) → CI (full suite) → [Deploy]Pre-commit (local — .husky/pre-commit)
Runs on every git commit. Blocks the commit if it fails. Must complete in < 120s (Reasonix sandbox limit).
| # | Gate | Command | What it checks | Since |
|---|---|---|---|---|
| 1 | Lint-staged | npx lint-staged | Biome only on staged files | Project |
| 2 | as any regression | bash scripts/count-as-any.sh | No new as any in the codebase (baseline: 41) | issue #196 |
| 3 | Biome check | pnpm lint | Whole codebase (formatting + lint) | Project |
| 4 | Type check | pnpm typecheck | tsc --build — full TS compilation | issue #193 |
| 5 | Unit tests | pnpm -r test | 1050 unit tests (Workers + App + Packages) | Project |
Pre-push (local — .husky/pre-push)
Runs on every git push. Slower than pre-commit — E2E smoke, changelog validation, drift audit.
| # | Gate | Command | What it checks | Since |
|---|---|---|---|---|
| 1 | Changelog | bash scripts/validate-changelog.sh | Tag v* has entry in CHANGELOG | Project |
| 2 | Lint | pnpm lint | Biome check full | Project |
| 3 | Type check | pnpm typecheck | tsc --build | Project |
| 4 | Unit tests | pnpm -r test | 1050 tests | Project |
| 5 | Smoke E2E | playwright test --config=playwright.smoke.config.ts | 23 critical specs | Project |
| 6 | Pre-deploy | bash scripts/pre-deploy-check.sh | Validates config before deploy | Project |
| 7 | Doc drift | bash scripts/doc-audit.sh | Semantic doc audit | issue #230 |
E2E smoke was moved to pre-push in Jun/2026 because it exceeded the 120s timeout of the Reasonix sandbox during
git commit. CI always runs the full suite (integration + 23 E2E + coverage).
CI (GitHub Actions — .github/workflows/ci.yml)
Runs on every push to main and every pull_request.
| # | Gate | Command | What it checks |
|---|---|---|---|
| 1 | Lint + Format | pnpm lint | Biome — formatting + quality rules |
| 2 | Type check | pnpm typecheck | tsc --build — type compatibility |
| 3 | as any regression | bash scripts/count-as-any.sh | Baseline 0 — no as any in code |
| 4 | Unit tests | pnpm -r test | Workers (67 unit + 17 events + 22 integration) + App (313) + Packages (42) |
| 5 | Documentation | pnpm docs:check + pnpm docs:links + pnpm docs:staleness | docs job — markdownlint (incl. docs/en), check:i18n (mirror no-partial + freshness), VitePress build, lychee (dead links on the built site, drifted pages exempt), and staleness (lastReviewed, incl. docs/en) |
| 6 | Build frontend | pnpm build:app | Vite production build (verifies compilation) |
The docs CI job is the single documentation seam: pnpm docs:lint → pnpm docs:i18n → pnpm docs:build → lychee (binary pinned, v0.24.2) → pnpm docs:staleness. Any failure blocks merge/push.
⚠️ CI does not pass
--coveragetopnpm -r testbecause@vitest/coverage-v8is incompatible with theworkerdruntime used in Workers integration tests. The app already hascoverage.enabled: truein its ownvitest.config.ts.
Submodules in CI
CI clones submodules via actions/checkout@v7 with submodules: true. After neemias-modules became public (21/Jun/2026), a PAT is not needed — the clone works without authentication.
Total tests in CI
⚠️ Counting via
scripts/verify-test-counts.sh. Baseline kept in.test-count-baseline.
| Suite | Tests | Note |
|---|---|---|
| Workers (unit) | 232 | workers/src/__tests__/ |
| Workers (events) | 47 | Event sourcing |
| Workers (integration) | 56 | D1 with cloudflare:test |
| Workers (services) | 112 | workers/src/services/__tests__/ |
| App (vitest) | 696 | React + MemoryVFS SQLite |
| Packages (vitest) | 158 | schemas + permissions + plugin-registry |
| E2E (Playwright) | 29 | full suite, 1 worker |
| Total | 1344 | count of it()/test() blocks |
Code Coverage
ℹ️ Informational — does not block merge. Per-directory thresholds in
app/vitest.config.ts. Baseline versioned in.coverage-baseline.json— local check viabash scripts/check-coverage.sh.
| Package | Lines | Branches | 30d Target | 90d Target |
|---|---|---|---|---|
| app/ | 32.8% | 27.3% | 35% | 40% |
| workers/ | 78.4% | 73.1% | 80% | 80% |
| packages/ | 100% | 100% | 100% | 100% |
Per-directory thresholds (app): src/db/ ≥ 80% · src/modules/auth/ ≥ 25% · src/modules/sync/ ≥ 40% · src/storage/ ≥ 45%
Pre-push (local — .husky/pre-push)
Currently empty — pre-commit already validates everything. Message displayed:
✅ Pre-push: pre-commit already validated. Skipping.neemias-modules
The barateza/neemias-modules repository does not have standalone CI. Module validation is done by the core monorepo CI, which runs pnpm lint + pnpm typecheck + pnpm -r test with the submodule code included.
This avoids configuration duplication and ensures modules are always tested in the real monorepo context (with correct dependencies on @neemias/plugin-registry, @neemias/schemas, etc.).
Deploy (GitHub Actions — .github/workflows/deploy.yml)
Runs on every tag push (v*). Executes the same 6 CI gates + wrangler deploy for production.
Detailed documentation: Deployment
History
| Date | Change | Issue |
|---|---|---|
| 2026-06-21 | Submodule modules added to CI (submodules: true) | #200 |
| 2026-06-21 | Standalone neemias-modules CI removed (validated via core) | #200 |
| 2026-06-21 | Typecheck added to pre-commit | #193 |
| 2026-06-21 | count-as-any added to pre-commit + CI | #196 |
| 2026-06-21 | as any baseline adjusted to 0 | #196 |
| 2026-06-19 | Initial CI workflow | — |