ATOM SaaS Coverage Monitoring Guide
**Version:** 1.0
**Last Updated:** 2026-02-22
**Purpose:** Strategy for ongoing coverage maintenance and monitoring
---
Table of Contents
- Coverage Metrics Dashboard
- Monitoring Tools
- Reporting Cadence
- Coverage Decay Prevention
- New Feature Coverage Requirements
- Legacy Code Strategy
- Coverage Alerts
---
1. Coverage Metrics Dashboard
ATOM SaaS tracks coverage across multiple dimensions to maintain quality standards.
Overall Coverage Percentage
**Combined frontend + backend coverage:**
# Frontend coverage
npm run test:coverage
# Backend coverage
cd backend-saas
pytest --cov=core --cov=api --cov-report=term-missing
# Current baseline (Phase 65B-01, 2026-02-21):
# Frontend: 19.01% (3,606 tests, 100% pass rate)
# Backend: 22.20% (2,786 tests, 90.6% pass rate)
# Combined: 20.6% coverage
# Target: 80% overall coveragePer-Module Coverage Breakdown
**Track individual module coverage to identify gaps:**
# Frontend per-module coverage
npm run test:coverage -- --reporter=json
# Parse coverage/coverage-final.json for breakdown
# Backend per-module coverage
pytest --cov=core/agent_governance_service --cov-report=term-missing
pytest --cov=core/episode_service --cov-report=term-missing**Example breakdown:**
| Module | Coverage | Target | Gap | Priority |
|---|---|---|---|---|
| cognitive-architecture.ts | 50.2% | 90% | 39.8% | P0 |
| agent-governance.ts | 67.9% | 90% | 22.1% | P0 |
| integrations/slack.ts | 45.3% | 85% | 39.7% | P1 |
| services/hosting.ts | 68.2% | 80% | 11.8% | P2 |
Coverage Trend Over Time
**Track weekly and monthly trends to identify decay:**
# Store coverage snapshots weekly
node scripts/store-coverage-snapshot.js
# Generate trend report
node scripts/generate-coverage-trend.js**Example trend visualization:**
Coverage Trend (Last 8 Weeks)
Week 1: ████████████████████░░░░░░░░ 20.6% (baseline)
Week 2: ████████████████████░░░░░░░░ 20.8% (+0.2%)
Week 3: ████████████████████░░░░░░░░ 20.6% (-0.2%)
Week 4: ████████████████████░░░░░░░░ 20.9% (+0.3%)
Week 5: ████████████████████░░░░░░░░ 21.1% (+0.2%)
Week 6: ████████████████████░░░░░░░░ 20.8% (-0.3%) ⚠️ Decay
Week 7: ████████████████████░░░░░░░░ 21.2% (+0.4%)
Week 8: ████████████████████░░░░░░░░ 21.5% (+0.3%) ✅ ImprovingUncovered Lines Count
**Prioritize high-impact uncovered lines:**
# Frontend: Generate HTML report
npm run test:coverage
open coverage/index.html
# Backend: Generate HTML report
pytest --cov=core --cov-report=html
open backend-saas/htmlcov/index.html**HTML report features:**
- Red = uncovered lines
- Yellow = partial coverage (branches not fully covered)
- Green = covered lines
- Click file names to drill down
Test Pass Rate
**Track test reliability (target: 98%+ pass rate):**
# Frontend test pass rate
npm test 2>&1 | grep "Test Files"
# Backend test pass rate
pytest 2>&1 | grep -E "(passed|failed)"
# Current baseline (Phase 65B-01):
# Frontend: 100% pass rate (3,606 tests, 43 skipped)
# Backend: 90.6% pass rate (2,524 passed, 227 failed, 35 skipped)---
2. Monitoring Tools
Vitest (Frontend Coverage)
**Configuration:** vitest.config.ts
export default defineConfig({
test: {
coverage: {
provider: 'v8', // 10-100x faster than Istanbul
reporter: ['text', 'json', 'html', 'lcov'],
reportsDirectory: './coverage',
thresholds: {
lines: 80,
functions: 80,
branches: 80,
statements: 80,
perFile: true,
thresholdAutoUpdate: true, // Prevents regression
},
},
},
});**Running coverage:**
# Generate full coverage report
npm run test:coverage
# View HTML report
open coverage/index.html
# Generate specific module coverage
npm run test:coverage -- src/lib/ai/
# Check coverage for changed files only
npm run test:coverage -- --changed**Output files:**
coverage/index.html- Interactive HTML reportcoverage/coverage-final.json- Machine-readable JSONcoverage/lcov.info- LCOV format for CI/CD
pytest-cov (Backend Coverage)
**Configuration:** pytest.ini or pyproject.toml
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = "test_*.py"
addopts = """
--cov=core
--cov=api
--cov-report=term-missing
--cov-report=html:htmlcov
--cov-report=json:coverage.json
--cov-fail-under=80
"""**Running coverage:**
# Generate full coverage report
cd backend-saas
pytest --cov=core --cov=api --cov-report=html
# View HTML report
open htmlcov/index.html
# Run with missing lines highlighted
pytest --cov=core --cov-report=term-missing
# Generate specific module coverage
pytest tests/unit/test_agent_governance.py --cov=core.agent_governance_service**Output files:**
backend-saas/htmlcov/index.html- Interactive HTML reportbackend-saas/coverage.json- Machine-readable JSON- Terminal output with missing line numbers
Coverage Trends (EpisodeService Integration)
**Store coverage snapshots in database for trend analysis:**
# backend-saas/core/coverage_service.py
from datetime import datetime
from typing import Dict, Any
class CoverageService:
"""Store and retrieve coverage snapshots for trend analysis."""
def store_snapshot(self, coverage_data: Dict[str, Any]) -> None:
"""Store coverage snapshot in database."""
snapshot = {
'timestamp': datetime.utcnow(),
'frontend_coverage': coverage_data.get('frontend', {}),
'backend_coverage': coverage_data.get('backend', {}),
'overall_coverage': coverage_data.get('overall', 0),
'test_pass_rate': coverage_data.get('pass_rate', 0),
'test_count': coverage_data.get('test_count', 0),
}
# Store in coverage_snapshots table
self.db.query(
"INSERT INTO coverage_snapshots (timestamp, data) VALUES ($1, $2)",
[snapshot['timestamp'], json.dumps(snapshot)]
)
def get_trends(self, days: int = 30) -> list:
"""Retrieve coverage trends for last N days."""
return self.db.query(
"""
SELECT timestamp, data
FROM coverage_snapshots
WHERE timestamp > NOW() - INTERVAL '%s days'
ORDER BY timestamp DESC
""" % days
).fetchall()
def detect_regression(self, threshold: float = 0.02) -> bool:
"""Detect if coverage has regressed more than threshold."""
trends = self.get_trends(days=7)
if len(trends) < 2:
return False
latest = trends[0]['data']['overall_coverage']
previous = trends[-1]['data']['overall_coverage']
return (previous - latest) > threshold # Regression > 2%**API endpoint for trends:**
# backend-saas/api/routes/coverage_routes.py
from fastapi import APIRouter
from core.coverage_service import CoverageService
router = APIRouter()
coverage_service = CoverageService(db)
@router.get("/api/coverage/trends")
async def get_coverage_trends(days: int = 30):
"""Get coverage trends for dashboard."""
trends = coverage_service.get_trends(days=days)
return {
'trends': trends,
'current_coverage': trends[0]['data'] if trends else None,
'regression_detected': coverage_service.detect_regression(),
}---
3. Reporting Cadence
Daily: Automated Coverage Runs (When CI/CD Activated)
**Frequency:** Every commit to main branch
**Purpose:** Detect coverage regression immediately
**Implementation:** GitHub Actions workflow
# .github/workflows/coverage.yml
name: Coverage Report
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run frontend coverage
run: |
npm run test:coverage
COVERAGE=$(node -e "console.log(require('./coverage/coverage-summary.json').total.lines.pct)")
echo "Frontend: $COVERAGE%"
- name: Run backend coverage
run: |
cd backend-saas
pytest --cov=core --cov-report=json
COVERAGE=$(python -c "import json; print(json.load(open('coverage.json'))['totals']['percent_covered'])")
echo "Backend: $COVERAGE%"
- name: Comment on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
let comment = '## 📊 Coverage Report\n\n';
// Add coverage details...
github.rest.issues.createComment({
issue_number: context.issue.number,
body: comment
});Weekly: Coverage Trend Reports
**Frequency:** Every Monday 9:00 AM UTC
**Purpose:** Weekly summary for team retrospective
**Report format:**
# Weekly Coverage Report - Week of 2026-02-15
## Summary
- **Overall Coverage:** 21.5% (+0.3% from last week) ✅
- **Frontend Coverage:** 19.3% (+0.2%)
- **Backend Coverage:** 23.7% (+0.4%)
- **Test Pass Rate:** 98.2% (2,524/2,570 tests)
## Top Improvements
1. **cognitive-architecture.ts**: 50% → 55% (+5%) - Added tests for reasoning paths
2. **integrations/slack.ts**: 45% → 52% (+7%) - Added webhook tests
3. **services/hosting.ts**: 68% → 75% (+7%) - Added ATOM Cloud error handling tests
## Declining Modules (⚠️ Action Required)
1. **agent-governance.ts**: 72% → 68% (-4%) - New code untested
2. **episode_service.py**: 8% → 5% (-3%) - Bug fixes without tests
## Quick Wins Identified
- **workflow_metrics.py**: 49.25% → Target 75% (+25.75% gap, 2 hours estimated)
- **analytics_engine.py**: 48.23% → Target 75% (+26.77% gap, 2 hours estimated)
## Action Items
- [ ] Add tests for agent-governance new code paths (1 hour)
- [ ] Cover episode_service bug fixes with tests (30 minutes)
- [ ] Execute quick wins: workflow_metrics + analytics_engine (4 hours)Monthly: Coverage Audit
**Frequency:** First Monday of every month
**Purpose:** Identify declining modules and create improvement plan
**Audit process:**
- **Generate coverage reports:**
- **Compare with previous month:**
- **Identify declining modules:**
- Sort by coverage delta (descending)
- Flag modules with >5% decline
- Prioritize by business criticality (P0 → P1 → P2)
- **Create improvement plan:**
- Assign owner to each declining module
- Estimate effort to recover coverage
- Add to next sprint backlog
Quarterly: Mutation Testing
**Frequency:** Every 3 months (quarter)
**Purpose:** Validate test effectiveness, find weak assertions
**Tools:** Stryker (TypeScript), Mutmut (Python)
**Execution:**
# Frontend mutation testing (Stryker)
npm install --save-dev @stryker-mutator/core
npx stryker run --mutate "src/lib/ai/**/*.ts"
# Target: 80%+ mutation score for critical modules
# Backend mutation testing (Mutmut)
pip install mutmut
cd backend-saas
mutmut run --paths-to-mutate core/episode_service.py core/graduation_exam.py
# Target: 80%+ mutation score**Report format:**
# Q1 2026 Mutation Testing Report
## Summary
- **Modules Tested:** 4 critical modules
- **Mutation Score:** 82.3% (above 80% target)
- **Weak Assertions Found:** 15
- **Test Quality:** Good
## Modules Tested
| Module | Mutation Score | Status | Action Required |
|--------|---------------|--------|----------------|
| cognitive-architecture.ts | 85.2% | ✅ Pass | None |
| agent-governance.ts | 78.5% | ⚠️ Below target | Add assertions for error paths |
| episode_service.py | 83.7% | ✅ Pass | None |
| graduation_exam.py | 81.9% | ✅ Pass | None |
## Weak Assertions Identified
1. **agent-governance.ts:123** - Assertion missing for null case
2. **agent-governance.ts:156** - Generic assertion, should be more specific
3. ... (13 more)
## Action Items
- [ ] Fix weak assertions in agent-governance.ts (30 minutes)
- [ ] Re-run mutation testing to verify fixes (10 minutes)---
4. Coverage Decay Prevention
Pre-Commit Hook
**Block commits if tests fail:**
# .git/hooks/pre-commit
#!/bin/bash
echo "Running pre-commit checks..."
# 1. TypeScript type check
echo "Type checking..."
npm run type-check || { echo "❌ Type check failed"; exit 1; }
# 2. Lint
echo "Linting..."
npm run lint || { echo "❌ Lint failed"; exit 1; }
# 3. Run tests for changed files only
echo "Running affected tests..."
CHANGED_FILES=$(git diff --name-only HEAD | grep '\.\(ts\|tsx\)$')
if [ -n "$CHANGED_FILES" ]; then
npm run test:affected -- $CHANGED_FILES || { echo "❌ Tests failed"; exit 1; }
fi
echo "✅ Pre-commit checks passed"**Make executable:**
chmod +x .git/hooks/pre-commitCoverage Delta Enforcement
**New code must be tested. No regression allowed.**
**CI/CD check (when activated):**
# .github/workflows/coverage.yml
- name: Check coverage delta
run: |
# Get coverage from base branch
git fetch origin main
BASE_COVERAGE=$(git show origin/main:coverage/coverage-summary.json | node -e "console.log(require('/dev/stdin').total.lines.pct)")
# Get coverage from current branch
CURRENT_COVERAGE=$(node -e "console.log(require('./coverage/coverage-summary.json').total.lines.pct)")
# Calculate delta
DELTA=$(echo "$CURRENT_COVERAGE - $BASE_COVERAGE" | bc)
echo "Base: $BASE_COVERAGE%"
echo "Current: $CURRENT_COVERAGE%"
echo "Delta: $DELTA%"
# Block if delta < 0 (regression)
if (( $(echo "$DELTA < 0" | bc -l) )); then
echo "❌ Coverage regression detected: $DELTA%"
exit 1
fi
echo "✅ No coverage regression"thresholdAutoUpdate
**Automatically update baseline to prevent regression:**
// vitest.config.ts
export default defineConfig({
test: {
coverage: {
thresholds: {
lines: 80,
perFile: true,
thresholdAutoUpdate: true, // ✅ Auto-update baseline
},
},
},
});**How it works:**
- Run
npm run test:coverage - If coverage is **higher** than baseline → Update baseline automatically
- If coverage is **lower** than baseline → Fail with error
**Example:**
# First run: Establish baseline
npm run test:coverage
# Coverage: 21.5% → Baseline set to 21.5%
# Second run: Coverage improved
npm run test:coverage
# Coverage: 22.1% → Baseline updated to 22.1% ✅
# Third run: Coverage regressed
npm run test:coverage
# Coverage: 21.8% → ERROR: Below baseline (22.1%) ❌---
5. New Feature Coverage Requirements
All New Code Must Have 80%+ Coverage
**PR review checklist:**
## Testing
- [ ] Unit tests added for new code (80%+ coverage)
- [ ] Integration tests added for API changes (85%+ coverage)
- [ ] E2E tests added for user-facing features
- [ ] All tests pass locally: `npm test && cd backend-saas && pytest`
- [ ] Coverage report generated: `npm run test:coverage`
- [ ] No coverage regression (coverage delta ≥ 0)Coverage Impact Section in PR
**Required in every PR description:**
## Coverage Impact
- **Before:** 21.5% overall (frontend 19.3%, backend 23.7%)
- **After:** 22.3% overall (frontend 20.1%, backend 24.5%)
- **Delta:** +0.8% overall (+0.8% frontend, +0.8% backend)
## Tests Added
- `src/lib/ai/__tests__/new-feature.test.ts` (52 lines, 12 tests)
- `backend-saas/tests/unit/test_new_feature.py` (38 lines, 8 tests)
All tests passing (100% pass rate).Code Reviewer Verification
**Reviewers must verify:**
- [ ] Tests verify **behavior**, not implementation
- [ ] Tests are **independent** (no shared state)
- [ ] Test naming follows **given_when_then** pattern
- [ ] Assertions include **descriptive error messages**
- [ ] Mocks used **appropriately** (external APIs, not simple functions)
**Example review comments:**
### Test Quality Review
**✅ Passing**
- Tests verify behavior (not internals)
- Descriptive test names: "should allow autonomous agent to delete code when action is high-risk"
- Good assertion messages: `expect(decision.allowed, \`Agent ${agentId} should be allowed to ${action}\`).toBe(true)`
**⚠️ Suggestions**
- Consider adding property-based test for edge cases (fast-check/Hypothesis)
- Test for null input handling missing
- Add integration test for database interaction
**Overall:** Approved (test quality is good)---
6. Legacy Code Strategy
When Touching Legacy Code: Add Tests
**Guidelines:**
- **Target:** 60% coverage for legacy modules (lower than 80% for new code)
- **Add tests** when modifying functions (bug fixes, feature additions)
- **Document** legacy modules with testing strategy comments
- **No big bang rewrites** - Incremental improvement over time
**Example:**
/**
* LEGACY MODULE: Migrated from v1.0 (2024)
* Testing Strategy: Gradual improvement
* Current Coverage: 45% (target: 60% by Q2 2026)
*
* @todo Add tests for error handling paths
* @todo Add tests for edge cases (null inputs, empty arrays)
* @todo Refactor to reduce complexity (currently 15/10 cyclomatic complexity)
*/
export class LegacyService {
// ... implementation
}Allocate 20% Time Per Sprint
**Coverage paydown backlog:**
## Sprint 24 - Coverage Paydown (20% Time)
**Goal:** Improve legacy module coverage from 45% → 60%
**Tasks:**
1. **legacy-service.ts** - Add tests for error handling (2 hours)
2. **old-integration.ts** - Add tests for edge cases (1.5 hours)
3. **deprecated-utils.ts** - Refactor and test (2.5 hours)
**Total:** 6 hours (20% of 30-hour sprint)Document Legacy Module Strategy
**Create LEGACY_TESTING.md for each legacy module:**
# Legacy Module: Old Integration Service
## Current Coverage
**Coverage:** 42% (125/295 statements)
**Target:** 60% by Q2 2026
**Gap:** 18% (30 statements)
## Testing Strategy
### High Priority (Uncovered Paths)
1. **Error handling in `syncData()`** - 12 uncovered statements
2. **Edge cases in `transformResponse()`** - 8 uncovered statements
3. **Null checks in `validateInput()`** - 6 uncovered statements
### Medium Priority (Partial Coverage)
1. **`processWebhook()`** - 50% coverage, missing error branch
2. **`retryFailed()`** - 60% coverage, missing timeout handling
### Low Priority (Non-Critical)
1. **`logMetrics()`** - 30% coverage, logging utility (low risk)
## Improvement Plan
**Sprint 24:** Add tests for error handling in `syncData()` (2 hours)
**Sprint 25:** Add tests for edge cases in `transformResponse()` (1.5 hours)
**Sprint 26:** Refactor `processWebhook()` to reduce complexity, add tests (2 hours)
## Notes
- **Complexity:** High (cyclomatic complexity 15/10)
- **Dependencies:** Tight coupling to deprecated API
- **Recommendation:** Consider rewriting when API v2 is available---
7. Coverage Alerts
Daily: Coverage Drops Below 75%
**Alert in Slack when daily coverage drops below 75%:**
# backend-saas/core/coverage_alerts.py
from datetime import datetime, timedelta
from slack_sdk import WebClient
slack = WebClient(token=os.environ['SLACK_ALERT_TOKEN'])
def check_daily_coverage():
"""Check if coverage dropped below 75% today."""
today = datetime.utcnow().date()
# Get today's coverage snapshot
snapshot = db.query(
"SELECT data FROM coverage_snapshots WHERE DATE(timestamp) = $1",
[today]
).fetchone()
if not snapshot:
return # No snapshot today
coverage = snapshot['data']['overall_coverage']
if coverage < 75:
# Send Slack alert
slack.chat_postMessage(
channel='#platform-alerts',
text=f"""
⚠️ COVERAGE ALERT: Coverage dropped below 75%
- Current coverage: {coverage}%
- Date: {today}
- Action required: Investigate and fix
<!channel>
""".strip()
)Weekly: Module Coverage Drops > 5%
**Email to module owner when module coverage drops > 5%:**
def check_module_regression():
"""Check if any module dropped > 5% coverage this week."""
week_ago = datetime.utcnow() - timedelta(days=7)
# Get coverage snapshots
snapshots = db.query(
"""
SELECT timestamp, data
FROM coverage_snapshots
WHERE timestamp > $1
ORDER BY timestamp ASC
""",
[week_ago]
).fetchall()
if len(snapshots) < 2:
return
latest = json.loads(snapshots[-1]['data'])
previous = json.loads(snapshots[0]['data'])
# Check each module for regression
for module in latest['modules']:
current_cov = latest['modules'][module]['coverage']
previous_cov = previous['modules'].get(module, {}).get('coverage', current_cov)
delta = previous_cov - current_cov
if delta > 5: # > 5% drop
# Send email to module owner
send_email(
to=get_module_owner(module),
subject=f"Coverage regression in {module}",
body=f"""
Module {module} coverage dropped by {delta:.1f}% this week:
- Previous: {previous_cov:.1f}%
- Current: {current_cov:.1f}%
- Delta: -{delta:.1f}%
Please add tests to recover coverage.
""".strip()
)Monthly: Overall Coverage Trend Negative
**Team retro action item when monthly trend is negative:**
def check_monthly_trend():
"""Check if monthly coverage trend is negative."""
month_ago = datetime.utcnow() - timedelta(days=30)
# Get monthly snapshots
snapshots = db.query(
"""
SELECT timestamp, data
FROM coverage_snapshots
WHERE timestamp > $1
ORDER BY timestamp ASC
""",
[month_ago]
).fetchall()
if len(snapshots) < 2:
return
# Calculate trend
first = json.loads(snapshots[0]['data'])
last = json.loads(snapshots[-1]['data'])
first_cov = first['overall_coverage']
last_cov = last['overall_coverage']
trend = last_cov - first_cov
if trend < 0: # Negative trend
# Create GitHub issue for team retro
github.create_issue(
title=f"Negative coverage trend this month: {trend:.1f}%",
body=f"""
## Coverage Regression Detected
Monthly coverage trend is negative ({trend:.1f}%).
**Start of month:** {first_cov:.1f}%
**End of month:** {last_cov:.1f}%
**Delta:** {trend:.1f}%
## Action Required
Please discuss in team retro and assign time to recover coverage.
## Declining Modules
{list_declining_modules(snapshots)}
""".strip()
)---
Summary
ATOM SaaS coverage monitoring strategy provides comprehensive tracking and maintenance of test coverage:
**Key components:**
- **Metrics dashboard** - Overall coverage, per-module breakdown, trends, pass rate
- **Monitoring tools** - Vitest, pytest-cov, EpisodeService integration
- **Reporting cadence** - Daily automated, weekly summary, monthly audit, quarterly mutation testing
- **Decay prevention** - Pre-commit hooks, coverage delta enforcement, thresholdAutoUpdate
- **New feature requirements** - 80%+ coverage for new code, PR checklist, reviewer verification
- **Legacy code strategy** - 60% target, add tests when touching, 20% time per sprint
- **Coverage alerts** - Daily <75%, weekly >5% module drop, monthly negative trend
**Current baseline (Phase 65B-01):**
- Combined: 20.6% coverage (target: 80%)
- Frontend: 19.01% (3,606 tests, 100% pass rate)
- Backend: 22.20% (2,786 tests, 90.6% pass rate)
- Gap: 59.4% improvement needed
**Next steps:**
- Execute Phase 62C-01 through 62C-06 (systematic coverage improvement)
- Activate CI/CD coverage enforcement when ready
- Implement coverage alerts (daily/weekly/monthly)
- Schedule quarterly mutation testing
**References:**
- Testing standards:
TESTING_STANDARDS.md - Research:
.planning/phases/65A-01/65A-01-RESEARCH.md - Test execution:
.planning/phases/65B-01/65B-01-SUMMARY.md
---
*Document version: 1.0*
*Last updated: 2026-02-22*
*Maintained by: Platform Engineering Team*