First implementation milestone of the agent-first coverage architecture (ADR-020, PRD 2026-05-13). Lands the keystone — coverage bands as a typed declaration in feature.manifest.ts plus a helper that derives vitest threshold shapes from them. New file packages/core-shared/src/conformance/coverage.ts (self- contained, no relative imports — loadable at vitest config time): - CoverageBand / CoverageBands / CoverageManifest / VitestThresholds types - DEFAULT_COVERAGE_BANDS (baseline 80/75/80/80; entities 100/100/100/ 100; use-cases + controllers 100/95/100/100) — matches ADR-011 - DEFAULT_MUTATION_SCORE (80) + DEFAULT_MUTATION_TARGETS (entities + use-cases) - getCoverageBands / getMutationConfig — manifest -> resolved bands, with default fallback for missing layers - vitestThresholdsFromBands / vitestThresholdsFromManifest — convert to vitest's coverage.thresholds shape with the layer-to-glob mapping define-feature.ts gains the optional coverage field on FeatureManifest (imports its type from coverage.ts to avoid a relative-import cycle at config-load time). Exposed via two subpaths: @repo/core-shared/conformance (re-exports for source/test code) and @repo/core-shared/conformance/coverage (direct subpath safe to load from vitest configs, bypasses the index re-export chain that Node ESM doesn't auto-extension-resolve). Auth wired as proof-of-concept: - packages/auth/src/feature.manifest.ts declares its coverage section - packages/auth/vitest.config.ts imports the helper + DEFAULT_COVERAGE_BANDS and emits thresholds via vitestThresholdsFromBands(DEFAULT_COVERAGE_BANDS) — no more hand-maintained per-glob thresholds block. Verified: 175/175 tests pass; 14/14 typechecks clean; auth coverage green (21 tests, 93.77% overall, all per-layer 100% bands hold). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
39 lines
1.5 KiB
TypeScript
39 lines
1.5 KiB
TypeScript
import path from "node:path";
|
|
import { mergeConfig } from "vitest/config";
|
|
import { nodeVitestConfig } from "@repo/core-typescript/vitest.base.node";
|
|
import {
|
|
DEFAULT_COVERAGE_BANDS,
|
|
vitestThresholdsFromBands,
|
|
} from "@repo/core-shared/conformance/coverage";
|
|
|
|
// Coverage thresholds derived from DEFAULT_COVERAGE_BANDS via the shared
|
|
// helper — one source of truth for the conventional band shape across all
|
|
// features (ADR-020). The feature.manifest.ts `coverage.bands` section also
|
|
// declares these for boot-time `assertFeatureConformance` (which reads the
|
|
// manifest directly, not the vitest config). For features that need
|
|
// non-default bands, override here AND in the manifest, then add a drift
|
|
// test in core-shared/conformance/.
|
|
export default mergeConfig(nodeVitestConfig, {
|
|
test: {
|
|
coverage: {
|
|
exclude: [
|
|
// DI bootstrap — wires InversifyJS at app startup; not unit-testable
|
|
"src/di/bind-production.ts",
|
|
// Pure TypeScript interface files — not executable
|
|
"src/application/repositories/**",
|
|
"src/application/services/**",
|
|
// Payload CMS collection config — declarative data, tested via Payload integration
|
|
"src/integrations/cms/**",
|
|
// Pure type-alias file — no executable code
|
|
"src/entities/cookie.ts",
|
|
// React Query option builders — integration-tested in apps
|
|
"src/ui/**",
|
|
],
|
|
thresholds: vitestThresholdsFromBands(DEFAULT_COVERAGE_BANDS),
|
|
},
|
|
},
|
|
resolve: {
|
|
alias: { "@": path.resolve(__dirname, "./src") },
|
|
},
|
|
});
|