Created: 2026-01-22
Status: ✅ Approved
Dependency: P3.1 Provenance Tracking System (complete)
Implement an intelligent drift remediation system that detects, analyzes, and proposes fixes for spec→code misalignments. The system enables:
[!IMPORTANT] This builds on the P3.1 Provenance System. All drift detection leverages the existing lineage graph to trace generated code back to source specs.
Conservative Auto-Fix Scope: Auto-generated PRs are limited to regeneration from specs (no direct code patching). Complex semantic drift requires human review.
Dual-Mode Architecture: The system operates in both CI (blocking/advisory) and Workbench UI (interactive) modes.
GitHub Integration First: PR automation targets GitHub API. GitLab/Bitbucket adapters are out of scope but interface is extensible.
flowchart TD
subgraph Detection["Drift Detection Layer"]
DD[DriftDetector] --> |hash compare| PC[ProvenanceComparator]
DD --> |semantic diff| SD[SemanticDiffer]
end
subgraph Analysis["Analysis & Suggestion Layer"]
AN[DriftAnalyzer] --> |classify| CL{DriftType}
CL --> |benign| BEN[FormatDrift]
CL --> |spec_stale| STALE[SpecSuggestion]
CL --> |code_stale| CODE[RegenSuggestion]
CL --> |semantic| SEM[ManualReviewRequired]
end
subgraph Remediation["Remediation Layer"]
REM[RemediationEngine] --> |generate| REGEN[RegenerationRunner]
REM --> |create| PR[PRCreator]
REM --> |notify| UI[WorkbenchNotifier]
end
Detection --> Analysis --> Remediation
New service module under services/workbench-bff/ for drift detection and remediation orchestration.
Core drift detection engine leveraging the provenance graph.
Key Classes:
DriftType(Enum): Classification of drift (NONE, BENIGN, SPEC_STALE, CODE_STALE, SEMANTIC)DriftReport(dataclass): Structured drift analysis resultDriftDetector: Main detection class comparing spec hashes to generated artifact hashesFeatures:
Intelligent drift classification and suggestion generation.
Key Classes:
DriftSuggestion(dataclass): Actionable fix suggestion with confidence scoreDriftAnalyzer: Classifies drift and generates remediation suggestionsFeatures:
Orchestrates remediation actions including PR creation.
Key Classes:
RemediationConfig(dataclass): Configuration for auto-fix thresholdsRemediationAction(dataclass): Concrete action (regenerate, update_spec, manual_review)RemediationEngine: Executes remediation strategiesFeatures:
just pipeline <context>Auto-Fix Safety Policy:
**/src/gen/** for patching (regen is allowed via pipeline).ts, .tsx, .py, .md (for reporting only)manual_reviewGitHub PR automation following the port/adapter pattern.
Port Interface:
1
2
3
4
5
6
7
8
class PRCreatorPort(Protocol):
def create_remediation_pr(
self,
title: str,
body: str,
branch: str,
changes: list[FileChange],
) -> PRResult: ...
Adapter Implementation:
GitHubPRCreator: Full GitHub API integrationdrift-remediation, auto-generatedcreate_remediation_pr (avoid admin scopes)REST endpoints for drift detection and remediation.
Cross-cutting concerns:
/drift/analyze and /drift/remediateEndpoints:
| Method | Path | Description |
|——–|——|————-|
| GET | /drift/scan | Scan all contexts for drift |
| GET | /drift/context/{context} | Get drift status for specific context |
| GET | /drift/report/{node_id} | Detailed drift report for a node |
| POST | /drift/analyze | Analyze drift and get suggestions |
| POST | /drift/remediate | Execute remediation action |
| GET | /drift/history | Get remediation audit history |
API constraints:
/drift/scan supports contexts[] filter to limit scope/drift/report/{node_id} supports summary=true for light payloads/drift/history supports pagination (limit, cursor)Add drift-related API models:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class DriftType(str, Enum):
NONE = "none"
BENIGN = "benign"
SPEC_STALE = "spec_stale"
CODE_STALE = "code_stale"
SEMANTIC = "semantic"
class DriftReportModel(BaseModel):
nodeId: str
nodeType: str
context: str
driftType: DriftType
confidence: float # 0.0-1.0
specHash: str | None
codeHash: str | None
lastSyncedAt: str | None
suggestions: list[DriftSuggestionModel]
class DriftSuggestionModel(BaseModel):
suggestionId: str
action: Literal["regenerate", "update_spec", "manual_review"]
description: str
confidence: float
autoFixable: bool
estimatedImpact: str # "low" | "medium" | "high"
command: str | None # e.g., "just pipeline semantic-core"
class RemediationRequestModel(BaseModel):
nodeId: str
suggestionId: str
createPR: bool = True
draftPR: bool = True
class RemediationResultModel(BaseModel):
success: bool
action: str
prUrl: str | None
errorMessage: str | None
auditId: str
Frontend API client for drift endpoints.
1
2
3
4
5
6
export function scanForDrift(): Promise<DriftScanResult>;
export function getContextDrift(context: string): Promise<DriftReport[]>;
export function getDriftReport(nodeId: string): Promise<DriftReport>;
export function analyzeDrift(nodeId: string): Promise<DriftAnalysis>;
export function executeRemediation(request: RemediationRequest): Promise<RemediationResult>;
export function getDriftHistory(): Promise<DriftAuditEntry[]>;
Main UI for drift visualization and remediation.
Features:
Component displaying individual drift reports.
Shows:
TypeScript type definitions mirroring backend models.
Add route for Drift Dashboard:
1
<Route path="/drift" element={<DriftDashboard />} />
Add navigation link to Drift Dashboard in sidebar/header.
CI guard script for drift-aware merges.
Modes:
--warn: Advisory mode (log drift, don’t fail)--fail: Blocking mode (fail if semantic drift detected)--auto-remediate: Create remediation PR automatically--dry-run: Simulate remediation actions without creating PRs--confirm: Explicit confirmation required for actual PR creation--require-approval: Gate PR creation on human approval signalSafety gates:
MAX_REMEDIATION_PRS) to prevent PR spamcreate_remediation_prremediation_audit.log (context, node, action, timestamp)Integration:
1
2
3
# .github/workflows/ci.yml addition
- name: Drift Check
run: ./scripts/ci/drift_check.sh --fail
GitHub Actions workflow for automated remediation PRs.
Token configuration:
GITHUB_TOKEN or custom DRIFT_REMEDIATION_TOKENcontents: write, pull-requests: writeGITHUB_TOKEN for same-repo PRs; use PAT for cross-repo or elevated limitsenv for scripts (used by scripts/ci/drift_check.sh)1
2
3
4
5
6
7
8
9
permissions:
contents: write
pull-requests: write
steps:
- name: Drift Check (auto-remediate)
run: ./scripts/ci/drift_check.sh --auto-remediate --confirm
env:
GITHUB_TOKEN: $
Triggers:
dev if drift detectedcron: '0 6 * * *' — 6 AM UTC)Actions:
Command-line interface for drift operations.
Commands:
1
2
3
4
5
6
7
8
9
10
11
# Scan all contexts
python tools/drift_heal.py scan
# Check specific context
python tools/drift_heal.py check semantic-core
# Apply remediation
python tools/drift_heal.py remediate <node-id> --type=regenerate [--dry-run] [--force]
# Generate report
python tools/drift_heal.py report --format=json > drift-report.json
Remediate behavior:
--dry-run: print human-readable preview and exit without changes--force: skip confirmation prompt and proceed--auto unless --force is set (except --dry-run)--auto only performs regeneration suggestions (no direct patching)Add drift-related recipes:
# Scan all contexts for drift
drift-scan:
python tools/drift_heal.py scan
# Check drift for specific context
drift-check context:
python tools/drift_heal.py check
# Auto-remediation preview (regenerate/update-spec only)
drift-heal:
python tools/drift_heal.py remediate --auto --dry-run
# Generate drift report
drift-report:
python tools/drift_heal.py report --format=markdown
Suggestions are ranked by:
One-click “Fix All Safe Issues” that:
Dashboard shows:
From ProvenanceExplorer:
1
2
3
4
5
6
7
# .pre-commit-config.yaml
- repo: local
hooks:
- id: drift-check
name: Drift Check
entry: python tools/drift_heal.py check --fail-on-semantic
language: system
| Category | New Files | Modified Files |
|---|---|---|
| Backend Adapters | 4 | 0 |
| API Routes | 1 | 0 |
| Models | 0 | 1 |
| Frontend Pages | 1 | 1 |
| Frontend Components | 1 | 0 |
| Frontend Types/API | 2 | 0 |
| CI Scripts | 1 | 0 |
| GitHub Actions | 1 | 0 |
| CLI Tools | 1 | 0 |
| Build Config | 0 | 1 |
| Total | 12 | 3 |
File: services/workbench-bff/tests/test_drift_detector.py
1
2
# Run drift detector tests
cd services/workbench-bff && python -m pytest tests/test_drift_detector.py -v
Test Cases:
test_detect_no_drift: Clean state returns NONEtest_detect_benign_drift: Format-only changes classified correctlytest_detect_spec_stale: Outdated spec detectedtest_detect_code_stale: Outdated code detectedtest_detect_semantic_drift: Structural changes flaggedtest_batch_scan: All contexts scanned efficientlyFile: services/workbench-bff/tests/test_drift_api.py
1
2
# Run drift API integration tests
cd services/workbench-bff && python -m pytest tests/test_drift_api.py -v
Test Cases:
test_scan_endpoint: /drift/scan returns valid responsetest_context_drift: /drift/context/{context} filters correctlytest_analyze_and_remediate: Full remediation workflowtest_audit_history: Remediation actions loggedFile: apps/workbench/src/pages/__tests__/DriftDashboard.test.tsx
1
2
# Run Workbench tests
pnpm nx test workbench --testFile=DriftDashboard
Test Cases:
1
2
3
4
5
6
7
# Test drift_check.sh in warn mode (should always pass)
./scripts/ci/drift_check.sh --warn
# Test with intentional drift (create temp file in gen/)
touch libs/semantic-core/domain/src/gen/temp_test_file.ts
./scripts/ci/drift_check.sh --warn # Should report drift
rm libs/semantic-core/domain/src/gen/temp_test_file.ts
just dev-up && just workbench-devhttp://localhost:3000/drift1
2
3
4
# Verify CLI commands work
python tools/drift_heal.py scan
python tools/drift_heal.py check semantic-core
python tools/drift_heal.py report --format=markdown
1
2
3
4
5
6
# Verify just recipes are registered
just --list | grep drift
# Run recipes
just drift-scan
just drift-report
| Dependency | Version | Purpose |
|---|---|---|
pygithub |
^2.1.0 | GitHub API for PR creation |
difflib |
stdlib | Semantic diff generation |
humanize |
^4.9.0 | Human-readable time formatting |
| Risk | Mitigation |
|---|---|
| False positives in drift detection | Conservative thresholds + human review gate |
| Accidental code overwrites | Draft PRs only, no direct commits |
| GitHub API rate limits | Caching + exponential backoff |
| Large diffs causing timeouts | Pagination + summary-first approach |
| Phase | Duration | Deliverables |
|---|---|---|
| Backend Core | 3 days | Detector, Analyzer, Engine |
| API + Models | 1 day | Routes, Pydantic models |
| CI Integration | 1 day | Guard script, GH Action |
| Workbench UI | 2 days | Dashboard, Components |
| CLI + Just | 0.5 days | Tool, Recipes |
| Testing | 2 days | Unit, Integration, Manual |
| Polish | 0.5 days | Docs, Edge cases |
| Total | 10 days | Production-ready P3.2 |