Negative Context for Agents¶
Drift generates deterministic anti-pattern constraints from analysis findings — telling AI coding agents what patterns must not be reproduced when generating code.
Why negative context matters¶
Findings explain what went wrong. Negative context prevents re-introducing the same problem:
| Component | Purpose |
|---|---|
| Finding | "Module X has 4 variants of error handling" |
| Negative context | "DO NOT add another bare except Exception: pass. INSTEAD use the canonical raise ServiceError(...) pattern." |
Without negative context, AI agents frequently fix one finding while re-introducing an already-known anti-pattern elsewhere.
Quick start¶
Generate anti-pattern instructions for your repo¶
# Preview to terminal
drift export-context
# Write to file (default: .drift-negative-context.md)
drift export-context --write
# Compact prompt format for system prompts
drift export-context --format prompt -w -o .cursorrules
# Include positive guidance too
drift export-context --include-positive -w
Use in agent workflows¶
# Add to Copilot instructions (auto-merged)
drift copilot-context --write
# Export as raw JSON for custom pipelines
drift export-context --format raw -o patterns.json
How it works¶
drift analyze → Findings → Negative Context Generators → Anti-Pattern Items
│
┌─────────────────────────────────────────┘
│
┌─────▼──────┐
│ Deduplicate │
│ + Sort by │
│ severity │
└─────┬──────┘
│
┌──────────┼──────────┐
│ │ │
instructions prompt raw
(Markdown) (compact) (JSON)
Each signal has a registered generator that transforms its findings into structured anti-pattern items. Currently 20+ generators cover all scoring-active and report-only signals.
Data model¶
Each anti-pattern item has this stable shape:
{
"anti_pattern_id": "neg-avs-1234567890",
"category": "architecture",
"source_signal": "architecture_violation",
"severity": "high",
"scope": "module",
"description": "Layer boundary violation detected",
"forbidden_pattern": "Importing from API layer into data layer",
"canonical_alternative": "Move shared contract into neutral domain module",
"affected_files": ["src/service/orders.py"],
"confidence": 0.9,
"rationale": "Repeated cross-layer imports increase coupling and drift risk",
"metadata": {}
}
Categories¶
| Category | Signals | Description |
|---|---|---|
security |
HSC, MAZ, ISD | Hardcoded secrets, missing auth, insecure defaults |
error_handling |
BEM, ECM | Broad exceptions, exception contract drift |
architecture |
PFS, AVS, MDS, CCC, CIR, FOE, COD | Structural and boundary violations |
testing |
TPD | Missing test coverage or polarity |
naming |
NBV | Naming convention violations |
complexity |
EDS, GCD, CXS | Unnecessary complexity, missing guards |
completeness |
DIA, BAT, DCA | Missing docs, accumulated bypasses, dead code |
Scopes¶
| Scope | Meaning |
|---|---|
file |
Pattern specific to a single file |
module |
Pattern spans a module/directory |
repo |
Repository-wide pattern |
Output formats¶
instructions (default)¶
Markdown with category headings — suitable for .github/copilot-instructions.md or .cursorrules:
## Security Anti-Patterns
- [!] **Hardcoded API token found** (hardcoded_secret, high)
- **DO NOT:** `API_KEY = "sk-A1B2C3..."`
- **INSTEAD:** Import from os.environ
- Affected: src/config.py, src/auth.py
prompt¶
Compact format for system prompts (minimal tokens):
AVOID: Bare except Exception: pass (broad_exception_monoculture, high)
USE INSTEAD: Specific exception types with proper handling
---
AVOID: Cross-layer import api→db (architecture_violation, high)
USE INSTEAD: Neutral domain module for shared contracts
raw¶
Full JSON array of anti-pattern items — for custom pipelines and automation.
Seed pattern library¶
Drift ships with 12 curated seed patterns under data/negative-patterns/patterns/ — ground-truth anti-patterns validated against real codebases:
| Pattern | Signal | Severity | Description |
|---|---|---|---|
broad_exception_001 |
BEM | high | Three connector modules catch bare Exception and log-only |
broad_exception_002 |
BEM | medium | Four adapters with mixed broad except clauses |
explainability_deficit_001 |
EDS | high | Complex function: nested conditionals, no docstring |
explainability_deficit_002 |
EDS | high | Four levels of nested loops with conditional filtering |
guard_clause_deficit_001 |
GCD | medium | Three public functions with zero guard clauses |
guard_clause_deficit_002 |
GCD | medium | Deep nesting without guards in pipeline functions |
mutant_duplicate_001 |
MDS | high | Two functions with identical logic, different names |
mutant_duplicate_002 |
MDS | high | Near-duplicate functions with renamed variables |
mutant_duplicate_003 |
MDS | high | Additional mutation-resilient duplicate variant |
naming_violation_001 |
NBV | medium | validate_email() that performs transformation, never raises |
pattern_fragmentation_001 |
PFS | high | Three handlers with incompatible error-handling strategies |
pattern_fragmentation_002 |
PFS | medium | Four validators each use different validation approach |
Each pattern file includes metadata conforming to data/negative-patterns/schema.json:
{
"id": "broad_exception_001",
"signal": "broad_exception_monoculture",
"origin": "ai_assisted",
"confirmed_problematic": true,
"tp_confirmed": true,
"severity": "high",
"description": "Three connector modules catch bare Exception and log-only"
}
Adding custom patterns¶
Create a Python file under data/negative-patterns/patterns/ with a companion JSON metadata file matching the schema:
- Pattern file (
.py): Contains the actual anti-pattern code - Metadata file (
.json): Describes the pattern perschema.json
Patterns must have confirmed_problematic: true and tp_confirmed: true to count as validated.
Integration points¶
| Surface | How negative context appears |
|---|---|
drift analyze --format json |
Top-level negative_context array |
drift analyze --format agent-tasks |
Per-task negative_context items |
drift export-context |
Standalone file generation |
drift copilot-context |
Merged into Copilot instructions |
MCP drift_scan |
Included in scan response |
MCP drift_fix_plan |
Included per repair task |
Configuration¶
Control negative context scope and volume via CLI options:
drift export-context \
--scope module \ # file, module, or repo scope filter
--max-items 25 \ # maximum anti-pattern items
--format instructions # instructions, prompt, or raw
No drift.yaml configuration needed — negative context uses the same analysis configuration as drift analyze.