ATOM Documentation

← Back to App

ATOM SaaS Coverage Monitoring Guide

**Version:** 1.0

**Last Updated:** 2026-02-22

**Purpose:** Strategy for ongoing coverage maintenance and monitoring

---

Table of Contents

  1. Coverage Metrics Dashboard
  2. Monitoring Tools
  3. Reporting Cadence
  4. Coverage Decay Prevention
  5. New Feature Coverage Requirements
  6. Legacy Code Strategy
  7. 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 coverage

Per-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:**

ModuleCoverageTargetGapPriority
cognitive-architecture.ts50.2%90%39.8%P0
agent-governance.ts67.9%90%22.1%P0
integrations/slack.ts45.3%85%39.7%P1
services/hosting.ts68.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%) ✅ Improving

Uncovered 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 report
  • coverage/coverage-final.json - Machine-readable JSON
  • coverage/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 report
  • backend-saas/coverage.json - Machine-readable JSON
  • Terminal output with missing line numbers

**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:**

  1. **Generate coverage reports:**
  1. **Compare with previous month:**
  1. **Identify declining modules:**
  • Sort by coverage delta (descending)
  • Flag modules with >5% decline
  • Prioritize by business criticality (P0 → P1 → P2)
  1. **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-commit

Coverage 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:**

  1. Run npm run test:coverage
  2. If coverage is **higher** than baseline → Update baseline automatically
  3. 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:**

  1. **Metrics dashboard** - Overall coverage, per-module breakdown, trends, pass rate
  2. **Monitoring tools** - Vitest, pytest-cov, EpisodeService integration
  3. **Reporting cadence** - Daily automated, weekly summary, monthly audit, quarterly mutation testing
  4. **Decay prevention** - Pre-commit hooks, coverage delta enforcement, thresholdAutoUpdate
  5. **New feature requirements** - 80%+ coverage for new code, PR checklist, reviewer verification
  6. **Legacy code strategy** - 60% target, add tests when touching, 20% time per sprint
  7. **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:**

  1. Execute Phase 62C-01 through 62C-06 (systematic coverage improvement)
  2. Activate CI/CD coverage enforcement when ready
  3. Implement coverage alerts (daily/weekly/monthly)
  4. 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*