Cortivex Drift Detection
You have access to a drift detection system that identifies when a codebase has diverged from its intended or documented state. Drift occurs silently -- architecture erodes, configs reference dead modules, test coverage slides, dependencies fall behind, and documentation describes features that no longer exist. This skill detects all of it, scores the severity, and tells you exactly what changed and when.
Overview
Drift detection works by establishing a baseline snapshot of the codebase's intended state, then comparing the current state against that baseline on every scan. The system tracks five drift categories independently, each with its own detection strategy and severity scoring.
The drift score is a composite 0-100 value where 0 means the codebase perfectly matches its baseline and 100 means catastrophic divergence across all categories. Scores above 60 indicate structural problems that will compound if left unaddressed.
When to Use
- After a sprint or release cycle to measure how far the codebase has drifted from its documented architecture
- As a nightly scheduled scan integrated into the
nightly-reviewpipeline - Before onboarding new team members to verify that documentation matches reality
- After large refactors to confirm that configs, tests, and docs were updated to match
- When dependency update PRs have been deferred and you need to quantify the technical debt
- Before major releases to catch coverage regressions and stale documentation
When NOT to Use
- During active development on a feature branch where drift is expected and temporary
- On brand-new projects with no established baseline (run
baselinefirst) - For real-time file watching during coding sessions (use linting and IDE tools instead)
- As a replacement for CI test suites -- drift detection complements CI, it does not replace it
How It Works
Drift Categories
Architecture Drift measures how far the actual code structure has diverged from architecture documentation. It parses architecture docs (README sections, ADRs, design docs) and cross-references them against the file tree, module boundaries, and import graphs. When docs describe a services/ layer but all business logic has migrated into controllers/, architecture drift catches it.
Config Drift detects pipeline configurations, build configs, and CI/CD definitions that reference files, modules, environment variables, or scripts that no longer exist. A webpack config importing a deleted alias, a pipeline YAML referencing a removed node type, or a Makefile target calling a script that was renamed -- all are config drift.
Coverage Drift tracks test coverage against established baselines. Unlike a simple threshold check, coverage drift measures the delta from the baseline per-module. If src/auth/ was at 92% coverage when the baseline was set and has dropped to 71%, that is a 21-point coverage drift even if the overall project coverage is still above the global threshold.
Dependency Drift compares installed package versions against lockfile specifications and declared version ranges. It also detects packages declared in the manifest but missing from the lockfile, packages in the lockfile but removed from the manifest, and major version gaps between declared ranges and latest available versions.
Documentation Drift identifies README files, API docs, and guides that describe features, endpoints, or configurations that no longer exist in the codebase, as well as new features, modules, or public APIs that have no documentation at all.
Drift Scoring
Each category produces a score from 0 to 100:
category_score = (drift_items / total_items) * severity_weight * 100
where:
drift_items = number of items that have drifted from baseline
total_items = total items tracked in this category
severity_weight = multiplier based on item severity (0.5 for low, 1.0 for medium, 2.0 for high)
The composite drift score is a weighted average:
composite = (arch * 0.25) + (config * 0.20) + (coverage * 0.20) + (deps * 0.15) + (docs * 0.20)
Architecture drift is weighted highest because it signals systemic structural decay. Dependency drift is weighted lowest because it is often intentional (pinning versions).
Pipeline Configuration
Standalone Drift Scan
name: drift-scan
version: "1.0"
description: Full drift analysis against established baseline
nodes:
- id: drift_scan
type: DriftDetector
config:
action: scan
repo: .
baseline_id: latest
categories:
- architecture
- config
- coverage
- dependencies
- documentation
severity_threshold: low
output_format: structured
- id: drift_report
type: DriftDetector
depends_on: [drift_scan]
config:
action: report
format: markdown
include_recommendations: true
include_history: true
Nightly Review Integration
name: nightly-review
version: "1.0"
description: Nightly pipeline with drift detection
nodes:
- id: drift_check
type: DriftDetector
config:
action: scan
baseline_id: latest
categories: [architecture, config, coverage, dependencies, documentation]
severity_threshold: medium
- id: security_scan
type: SecurityScanner
config:
scan_depth: standard
- id: code_review
type: CodeReviewer
config:
review_scope: changed_files
- id: nightly_report
type: CustomAgent
depends_on: [drift_check, security_scan, code_review]
config:
system_prompt: |
Combine drift analysis, security findings, and code review into a
single nightly health report. Flag any drift score above 40 as
requiring attention.
output_format: markdown
Scheduled Drift Watch
name: drift-watch
version: "1.0"
description: Continuous drift monitoring with alerting
nodes:
- id: watch
type: DriftDetector
config:
action: watch
interval_hours: 24
baseline_id: latest
alert_threshold: 40
categories: [architecture, config, coverage]
on_alert:
action: notify
channel: pipeline-alerts
MCP Tool Reference
Scan for Drift
cortivex_drift({
action: "scan",
repo: "/path/to/repo",
baseline_id: "latest",
categories: ["architecture", "config", "coverage", "dependencies", "documentation"],
severity_threshold: "low"
})
Response:
{
"scan_id": "drift-8f2a",
"timestamp": "2025-01-15T09:30:00Z",
"composite_score": 37,
"categories": {
"architecture": {
"score": 45,
"items": [
{
"severity": "high",
"description": "Architecture doc describes services/ layer but 6 service classes have been moved into controllers/",
"baseline_state": "12 files in src/services/",
"current_state": "6 files in src/services/, 6 moved to src/controllers/",
"first_detected": "2025-01-10T14:00:00Z"
}
]
},
"config": {
"score": 25,
"items": [
{
"severity": "medium",
"description": "Pipeline config references LegacyParser node type which was removed in v2.3",
"file": ".cortivex/pipelines/legacy-scan.yaml",
"line": 14
}
]
},
"coverage": {
"score": 52,
"items": [
{ "severity": "high", "description": "src/auth/ coverage dropped from 92% to 71%", "delta": -21 },
{ "severity": "medium", "description": "src/api/orders.ts has 0% coverage (new file)", "current_value": 0 }
]
},
"dependencies": {
"score": 18,
"items": [
{ "severity": "low", "package": "express", "declared": "^4.18.0", "locked": "4.19.0", "installed": "4.18.2" }
]
},
"documentation": {
"score": 38,
"items": [
{ "severity": "medium", "description": "README documents /api/v