# Coverage Sprint Backlog — #76 Follow-up Work **Generated:** 2026-05-25 **Baseline source:** [`coverage-baseline-2026-05-25.md`](./coverage-baseline-2026-05-25.md) **Current overall coverage:** 77.68% statements / 79.34% branches / 75.46% functions / 77.68% lines **2026-05-29 closeout check:** `pnpm run verify:test-coverage` passes with the current per-module gates. The historical baseline remains useful for trend context, but the active closeout state is now "no positive sprint gaps". **Rule:** Every entry in the "Critical-path positive-gap" table below must reach its `sprintTarget` before a future coverage ratchet can be treated as done. There are no positive-gap rows in the latest baseline, so #76 is closed; remaining work is gate maintenance and opportunistic threshold ratcheting rather than broad test writing. ## Pick-the-next-module workflow For a follow-up session that wants to pick mechanically: 1. Read this file. 2. Grab the top row of the "Critical-path positive-gap" table. 3. Open the HTML coverage report (`coverage/lcov-report/index.html`) and drill into that module. 4. Identify uncovered lines/branches; write tests against real code paths (no mocks-only padding). 5. Re-run `pnpm exec vitest run --coverage --exclude ...` (see baseline doc for the exclude flags). Confirm achievement. 6. Bump the entry in `scripts/coverage-targets.json` for that module to the new achieved level (round DOWN by 0.5-1pp for headroom). Never weaken existing thresholds. 7. Commit with `test(): close coverage gap for `. Move the row to the "Graduated" table below. ## Critical-path positive-gap modules — priority order Sorted by sprint-priority (per detail-MD section d): Auth > Tenant-Isolation > Billing > Permissions > Entitlements > DB. No critical-path modules currently have a positive sprint gap. ## Standard-tier modules with positive gap No standard-tier runtime modules currently have a positive sprint gap. ## Graduated modules (already at or past sprintTarget) Where the gap is negative the module has met or exceeded the sprintTarget. Rows marked `(raised)` had their active gate raised on 2026-05-25 to lock the achievement in. | Module | stmt now | br now | sprint | Active gate now | | ------------------------------------- | -------: | -----: | -----: | --------------: | | `apps/api/src/auth/**` (raised) | 99.2 | 92.2 | 90/85 | **99/92** | | `apps/web/app/services/auth/**` (raised) | 97.4 | 88.5 | 90/85 | **97/88** | | `apps/web/app/utils/session.server.ts` (raised) | 100.0 | 99.1 | 95/90 | **99/98** | | `apps/web/app/utils/auth/**` (raised) | 97.7 | 92.7 | 90/85 | **97/92** | | `apps/web/app/utils/stripe.server.ts` (raised) | 95.4 | 91.1 | 85/75 | **95/90** | | `apps/web/app/utils/db/tenants.db.server.ts` (raised) | 98.5 | 96.1 | 95/90 | **98/95** | | `apps/web/app/utils/db/permissions/**` (raised) | 99.8 | 99.0 | 90/80 | **99/98** | | `apps/api/src/billing/**` (raised) | 99.3 | 98.0 | 99/95 | **99/97** | | `packages/entitlements/**` (raised) | 97.0 | 89.9 | 90/80 | **96/89** | | `apps/api/src/isolation/**` (raised) | 100.0 | 100.0 | 95/90 | **99/99** | | `packages/db/src/outbox*` (raised) | 93.0 | 88.6 | 90/80 | **92/88** | | `packages/shared-store/**` (raised) | 91.3 | 90.7 | 90/80 | **91/90** | | `packages/error-reporter/**` (raised) | 81.5 | 86.9 | 80/70 | **81/86** | | `apps/mobile/src/**` (raised) | 79.2 | 80.2 | 70/60 | **79/79** | | `apps/hocuspocus/src/**` (raised) | 89.2 | 92.9 | 70/60 | **88/90** | | `packages/cli/src/**` (raised) | 80.4 | 83.6 | 80/70 | **80/83** | | `packages/ui-app/src/**` (raised) | 95.1 | 73.7 | 70/60 | **94/73** | | `packages/api-client-ts/src/**` (raised) | 70.9 | 80.9 | 70/60 | **70/80** | | `packages/plugins/src/**` (raised) | 100.0 | 86.8 | 98/80 | **99/86** | | `packages/ai/src/**` (raised) | 81.6 | 81.0 | 80/70 | **81/81** | | `packages/config/src/**` (raised) | 99.0 | 95.4 | 80/70 | **98/95** | | `packages/feature-flags/src/**` (raised) | 94.3 | 86.4 | 80/70 | **94/86** | | `packages/i18n/src/**` (raised) | 95.2 | 75.7 | 80/70 | **95/75** | | `packages/plugin-runtime/src/**` (raised) | 92.7 | 88.5 | 80/70 | **92/88** | | `packages/queue/src/**` (raised) | 93.5 | 96.0 | 80/70 | **93/95** | | `packages/exports/src/**` (raised) | 90.7 | 83.6 | 80/70 | **90/83** | | `packages/imports/src/**` (raised) | 91.8 | 87.5 | 80/70 | **91/87** | | `packages/realtime/src/**` (raised) | 91.6 | 85.3 | 80/70 | **91/85** | | `packages/search/src/**` (raised) | 88.6 | 71.7 | 80/70 | **88/71** | | `packages/storage/src/**` (raised) | 82.8 | 84.2 | 80/70 | **82/84** | | `packages/vector-store/src/**` (raised) | 94.6 | 90.4 | 80/70 | **94/90** | | `packages/metrics/src/**` (raised) | 98.9 | 90.2 | 80/70 | **98/90** | | `packages/form-widget/src/**` (raised) | 96.7 | 86.5 | 80/70 | **96/86** | | `packages/email-sequences/src/**` (raised) | 84.5 | 78.0 | 80/70 | **84/77** | | `packages/email-templates/src/**` (raised) | 96.9 | 86.5 | 70/60 | **96/86** | | `packages/observability/src/**` (raised) | 100.0 | 100.0 | 80/70 | **99/99** | | `packages/marketing-outbound/src/**` (raised) | 85.8 | 65.9 | 70/60 | **85/65** | | `packages/plugin-sdk/src/**` (raised) | 100.0 | 100.0 | 75/65 | **99/99** | | `packages/ui-mock/src/**` (raised) | 97.9 | 68.6 | 70/60 | **97/68** | | `packages/view-models/src/**` (raised) | 86.7 | 71.4 | 75/65 | **86/71** | | `packages/url/src/**` (raised) | 98.3 | 95.9 | 80/70 | **98/95** | | `packages/logger/src/**` (raised) | 100.0 | 100.0 | 80/70 | **99/99** | | `packages/brand/src/**` (raised) | 100.0 | 93.8 | 80/70 | **99/93** | | `packages/api-types/src/**` (type-only) | 0.0 | 100.0 | 0/0 | **0/0** | ## Out-of-scope notes - `packages/ui-subframe/**` keeps an active 30/20 gate while its sprint target remains 50/40 by design; visual confidence lives in Storybook lost-pixel (#62). Do NOT force the active gate to 50/40 with shallow unit tests; close that gap with the visual regression contract. - **The latest full coverage run puts `apps/web/app/utils/stripe.server.ts` past both sprint targets**. The active gate is raised to 95/90 so future changes cannot drop back to the old mock-only baseline. - **The latest full coverage run graduates `packages/cli/src/**` at 80.4% statements / 83.6% branches**. The active gate is raised to 80/83 so the new AI-cost, feature-flag, chatbot, backup-create, DSGVO, sequence, leads, and KB article coverage does not regress. - **The latest full coverage run graduates `packages/ui-app/src/**` at 95.1% statements / 73.7% branches**. The active gate is raised to 94/73 after covering the public a11y-template test factory. - **The latest full coverage run graduates `packages/api-client-ts/src/**` at 70.9% statements / 80.9% branches**. The active gate is raised to 70/80 after covering generated body/path/query/auth/client/SSE helpers and catching a cookie header separator regression. - **The latest full coverage run graduates `packages/plugins/src/**` at 100.0% statements / 86.8% branches**. The active gate is raised to 99/86 after adding branch-edge coverage for manifest schema and loader behavior. - `packages/api-types/src/**` reports 0% statements because the source contains only `export type ... = ...` aliases (no runtime code). Its sprint target is intentionally 0/0 and guarded by `expectTypeOf` tests plus package typecheck instead of fake runtime assertions. - **The latest `pnpm run verify:test-coverage` execution had 399 passing files, 2 skipped files, 3597 passing tests, and 50/50 passing coverage targets**. - **2026-05-27 focused recon:** the four historical coverage-scope failures called out in `coverage-baseline-2026-05-25.md` now pass when run together: `apps/web/app/application/ui/uiInventory.test.ts`, `apps/api/src/app.test.ts`, `packages/config/src/env-examples.test.ts`, and `packages/cli/src/commands/tenant/json-codec.test.ts` (193 tests passing). - **2026-05-29 closeout verification:** `pnpm run verify:test-coverage` passes with the current gate set; #76 is closed in `docs/improvement-plan/PROGRESS.md`. ## References - Spec: `docs/improvement-plan/10-compliance-polish/test-coverage.md` - Policy: `docs/architecture/test-coverage.md` - Baseline: `docs/testing/coverage-baseline-2026-05-25.md` - Gate runner: `scripts/verify-test-coverage.mjs` - Targets data: `scripts/coverage-targets.json`