Suppression System
Manage false positives and track analyzer improvements with the suppression system.
Overview
The suppression system allows you to mark violations as false positives while tracking metadata to detect when the analyzer improves and suppressions become obsolete.
Key Features:
- ✅ Inline comment suppression for visibility
- ✅ Config file suppression for global rules
- ✅ Auto-generated manifest tracking metadata
- ✅ Dead suppression detection
- ✅ AI-friendly programmatic API
Quick Start
Suppress a Single Violation
Add a comment before the line:
// @behavioral-contract-ignore axios/network-failure: Global error handler
await axios.get('/api/users');
Suppress All Test Files
Create .behavioralcontractsrc.json:
{
"ignore": [
{
"file": "src/test/**",
"reason": "Test files intentionally trigger errors"
}
]
}
Check for Dead Suppressions
verify-cli --tsconfig ./tsconfig.json --check-dead-suppressions
Inline Comment Syntax
Format
// @behavioral-contract-ignore <package>/<postcondition-id>: <reason>
Examples
Specific suppression:
// @behavioral-contract-ignore axios/network-failure: Global error handler
await axios.get('/api/users');
Package wildcard:
// @behavioral-contract-ignore */timeout-not-set: Timeout set globally in config
await axios.post('/api/users', data);
Postcondition wildcard:
// @behavioral-contract-ignore prisma/*: NestJS exception filter handles all errors
await prisma.user.create({ data });
Suppress everything (not recommended):
// @behavioral-contract-ignore */*: Legacy code with global error handler
legacyCode();
Config File Suppression
Location
Create .behavioralcontractsrc.json in your project root.
Schema
{
"ignore": [
{
"file": "<glob-pattern>",
"package": "<package-name>",
"postconditionId": "<postcondition-id>",
"reason": "<explanation>"
}
]
}
Examples
Suppress all test files:
{
"ignore": [
{
"file": "src/test/**",
"reason": "Test files intentionally trigger errors"
},
{
"file": "**/*.test.ts",
"reason": "Test files"
},
{
"file": "**/*.spec.ts",
"reason": "Test files"
}
]
}
Suppress specific package in specific file:
{
"ignore": [
{
"file": "src/api/legacy.ts",
"package": "axios",
"postconditionId": "network-failure",
"reason": "Legacy code with global error handler"
}
]
}
Suppress all Prisma errors in API directory:
{
"ignore": [
{
"file": "src/api/**",
"package": "@prisma/client",
"reason": "NestJS exception filter handles all database errors"
}
]
}
Suppression Manifest
Location
Auto-generated at .verify-cli/suppressions.json
What It Tracks
- When suppression was created
- Who/what created it (inline-comment, config-file, ai-agent, cli)
- Last checked timestamp
- Whether it still violates
- Analyzer version when suppressed
Example
{
"version": "1.0.0",
"projectRoot": "/path/to/project",
"lastUpdated": "2026-02-27T10:30:00Z",
"suppressions": [
{
"id": "suppress-src-api-ts-42-a1b2c3d4",
"file": "src/api.ts",
"line": 42,
"package": "axios",
"postconditionId": "network-failure",
"reason": "Global error handler",
"suppressedAt": "2026-02-27T10:30:00Z",
"suppressedBy": "inline-comment",
"lastChecked": "2026-02-27T10:30:00Z",
"stillViolates": true,
"analyzerVersion": "1.1.0"
}
]
}
Should I Commit It?
Recommended: Yes
- Team-wide tracking
- Shared suppressions
- Audit trail
Optional: Gitignore
- Local suppressions only
- Per-developer exceptions
Add to .gitignore if needed:
.verify-cli/suppressions.json
Dead Suppression Detection
What Are Dead Suppressions?
Suppressions that are no longer needed because the analyzer has improved and no longer flags the pattern.
How It Works
On every run, the analyzer:
- Checks if each suppression location still violates
- If not, marks
stillViolates: false - Reports dead suppressions to user
Check for Dead Suppressions
verify-cli --tsconfig ./tsconfig.json --check-dead-suppressions
Output:
🎉 Found 2 dead suppressions (analyzer improved!):
├─ src/auth.ts:123
│ Package: axios
│ Postcondition: timeout-not-set
│ Suppressed: 2026-01-15 (42 days ago)
│ Analyzer: v1.0.0 → v1.1.0
│
│ Why improved: Analyzer now detects timeout in axios config
│ Action: Remove @behavioral-contract-ignore comment at line 123
Clean Up Dead Suppressions
# List dead suppressions
verify-cli suppressions list --dead
# Remove from manifest (automatic)
verify-cli suppressions clean --auto
# Note: Inline comments must be removed manually
CLI Commands
Main Command Flags
# Show suppressed violations in output
verify-cli --tsconfig ./tsconfig.json --show-suppressions
# Check for dead suppressions
verify-cli --tsconfig ./tsconfig.json --check-dead-suppressions
# Fail if dead suppressions found (CI)
verify-cli --tsconfig ./tsconfig.json --fail-on-dead-suppressions
Suppressions Subcommand
# List all suppressions
verify-cli suppressions list
# List only active suppressions
verify-cli suppressions list --active
# List only dead suppressions
verify-cli suppressions list --dead
# Show specific suppression
verify-cli suppressions show src/api.ts:42
# Show suppression statistics
verify-cli suppressions stats
# Clean up dead suppressions
verify-cli suppressions clean --auto
AI Integration
Workflow
When AI reviews violations and identifies false positives:
// 1. AI reads violations
const violations = JSON.parse(await readFile('violations.json'));
// 2. AI identifies false positives
const falsePositives = aiAgent.identifyFalsePositives(violations);
// 3. AI adds inline comments
for (const fp of falsePositives) {
const fileContent = await readFile(fp.file);
const lines = fileContent.split('\n');
lines.splice(fp.line - 1, 0,
`// @behavioral-contract-ignore ${fp.package}/${fp.postconditionId}: ${fp.reason}`
);
await writeFile(fp.file, lines.join('\n'));
}
// 4. Re-run analyzer (manifest auto-updates)
await exec('verify-cli --tsconfig ./tsconfig.json');
Benefits
- ✅ AI can add suppressions programmatically
- ✅ Manifest auto-updates on next run
- ✅ No manual manifest editing needed
- ✅ Full audit trail maintained
Best Practices
1. Always Provide Meaningful Reasons
Bad:
// @behavioral-contract-ignore axios/network-failure: false positive
Good:
// @behavioral-contract-ignore axios/network-failure: Global error handler in src/middleware/errors.ts handles all network failures
2. Prefer Inline Comments for Specific Cases
Use inline comments when:
- Specific line needs suppression
- Reason is context-dependent
- Developers should see it when reading code
3. Prefer Config File for Global Rules
Use config file when:
- Suppressing entire directories (tests, legacy)
- Suppressing all instances of a pattern
- Centralized management needed
4. Regularly Clean Dead Suppressions
Set up a monthly task:
verify-cli --check-dead-suppressions
verify-cli suppressions clean --auto
5. Use in CI to Prevent Regressions
# .github/workflows/verify.yml
- name: Check behavioral contracts
run: |
verify-cli --tsconfig ./tsconfig.json --fail-on-dead-suppressions
Common Use Cases
Use Case 1: Framework Handles Errors
Scenario: NestJS exception filter handles all database errors
// @behavioral-contract-ignore @prisma/client/p2002: NestJS filter handles unique constraint
@Post()
async create(@Body() data: CreateUserDto) {
return this.prisma.user.create({ data });
}
Use Case 2: Global Error Handler
Scenario: Express error middleware catches all errors
// @behavioral-contract-ignore axios/*: Global error middleware in app.ts handles all API errors
async function fetchData() {
const response = await axios.get('/api/data');
return response.data;
}
Use Case 3: Test Files
Scenario: Tests intentionally trigger errors
.behavioralcontractsrc.json:
{
"ignore": [
{
"file": "**/*.test.ts",
"reason": "Test files intentionally trigger errors"
}
]
}
Use Case 4: Legacy Code
Scenario: Legacy code with technical debt
// @behavioral-contract-ignore */*: Legacy code - refactor in Q3 2026 (JIRA-1234)
// TODO: Add proper error handling
function legacyOperation() {
// ... old code
}
Troubleshooting
Suppression Not Working
Check:
- Is the format correct?
@behavioral-contract-ignore package/postcondition: reason - Is the comment on the line BEFORE the violation?
- Is the reason at least 10 characters?
- Run
verify-cli --show-suppressionsto see if it's detected
Manifest Not Updating
Check:
- Does
.verify-cli/directory have write permissions? - Is the project root correctly detected?
- Check for errors in terminal output
Dead Suppressions Not Detected
This is expected:
- Dead suppressions are only detected if
stillViolatesis set tofalse - Run the analyzer after upgrading to update
stillViolatesstatus - The first run after upgrade will mark suppressions as active/dead
FAQ
Can I suppress all violations in a file?
Use a config rule:
{
"ignore": [{ "file": "src/problematic.ts", "reason": "Explanation" }]
}
Can I use wildcards in package names?
Yes: */postcondition-id suppresses for all packages.
What happens if I remove an inline comment?
The suppression is automatically removed from the manifest on the next run.
Can I manually edit the manifest?
Not recommended. The manifest is auto-generated. Use inline comments or config file instead.
See Also
- Understanding Output - How to read violations
- Fixing Violations - Best practices for resolving issues
- AI Integration - Automate with AI agents