Coverage harness & gate
tdmcp tracks executable-TypeScript test coverage with a small harness on top of Vitest's v8 coverage provider, and enforces a no-regression floor in CI.
Scope
Coverage is measured over src/**/*.ts only. Generated knowledge data (src/knowledge/data/**) is excluded — it is imported reference JSON, not executable code, so it must never drive the numbers up or down. See vitest.config.ts (coverage.include / coverage.exclude).
Commands
| Command | What it does |
|---|---|
npm run test:coverage | Raw Vitest coverage run; fails if any threshold in vitest.config.ts is not met. This is the gate. |
npm run coverage:harness | Runs the coverage gate, then writes a ranked gap report to _workspace/coverage/latest.md and a machine-readable coverage/coverage-summary.json. |
npm run coverage:harness -- --summary-only | Re-render the report from the existing coverage/coverage-summary.json without re-running the suite. |
npm run coverage:harness -- --limit=40 --min-lines=91 | Print more ranked gaps and fail if line coverage drops below the requested floor (use the +5pp target while a coverage wave is in flight). |
The report ranks files by a gap score (missing_lines*3 + missing_functions*2 + missing_branches) and buckets the top files into suggested test waves by surface (entrypoints/CLI/LLM, resources/knowledge, prompts, tools, server/transport).
The gate (G2)
The thresholds in vitest.config.ts are a no-regression floor: they are locked at the measured baseline, floored to the integer at or below current coverage. They must always PASS at current coverage and must never be lowered.
Baseline (2026-06-21)
| Metric | Measured | Locked threshold |
|---|---|---|
| Statements | 84.71% | 84 |
| Branches | 70.73% | 70 |
| Functions | 83.02% | 83 |
| Lines | 86.6% | 86 |
CI runs npm run test:coverage, so any regression below these floors red-lights the build. When a coverage wave raises the real numbers, raise the thresholds to the new floor in the same change — that is how the gate ratchets up.
Tracked +5pp target
The roadmap goal (docs/ROADMAP.md → "G2 — Test coverage") is lines and branches ≥ baseline + 5 pp:
| Metric | Baseline | +5pp target |
|---|---|---|
| Lines | 86.6% | ≥ 91 |
| Branches | 70.73% | ≥ 75 |
This is the next coverage wave's objective. Drive a wave toward it with npm run coverage:harness -- --min-lines=91 (and the ranked gap list), then ratchet the vitest.config.ts floors up as the numbers land. Branches is the widest gap (70.73% → 75 is ~4.3 pp, roughly 800 uncovered branches), so it needs the most new tests; lines (86.6% → 91 is ~4.4 pp, ~1,200 uncovered lines) follows the same wave.