The Problem with Flat Severity
Without severity rules, all drift is treated equally. A hardcoded color in your checkout flow gets the same weight as a spacing value in a test utility. That's not how your team thinks about risk.
Without Severity Rules
- ✗ All drift is "warning" — nothing stands out
- ✗ Checkout drift and test utility drift look the same
- ✗ Close-match typos don't block the build
- ✗ CI thresholds are all-or-nothing
With Severity Rules
- ✓ Checkout drift promoted to critical
- ✓ Close-match typos enforced as critical — always
- ✓ Test utilities stay at warning
- ✓ CI fails only on what matters to your team
drift.promote
Elevate drift severity based on where it appears and what it is. A warning in the wrong place becomes a critical.
<div class=""># .buoy.yaml</div><div class="">drift:</div><div class=""> promote:</div><div class=""> # Hardcoded colors in checkout are critical</div><div class=""> - type: hardcoded-color</div><div class=""> file: "src/checkout/**"</div><div class=""> severity: warning</div><div class=""> to: critical</div><div class=""> reason: "Checkout UI must use design tokens"</div><div class=""></div><div class=""> # Any drift in shared components is critical</div><div class=""> - file: "src/components/shared/**"</div><div class=""> severity: warning</div><div class=""> to: critical</div><div class=""> reason: "Shared components set the standard"</div> Filter Fields
Six fields to target exactly the drift you care about. Multiple fields in a single rule combine with AND logic. Multiple rules use first-match-wins.
type
Match drift by type. Targets specific categories like hardcoded-color or close-match.
severity
Match drift by current severity before promotion. Only available in promote rules.
file
Match drift by file path using glob patterns. Target specific directories or file types.
component
Match drift by component name using regex. Target specific components or patterns.
token
Match drift by token name using regex. Target specific token references.
value
Match drift by the hardcoded value using regex. Target specific values across the codebase.
drift.enforce
Zero-tolerance rules. No severity filter, no to field. Matching drift is always set to critical. No negotiation.
<div class=""># .buoy.yaml</div><div class="">drift:</div><div class=""> enforce:</div><div class=""> # Close-match typos are always critical</div><div class=""> - type: close-match</div><div class=""> reason: "Typos must be fixed before merge"</div><div class=""></div><div class=""> # Any drift in the design system package is critical</div><div class=""> - file: "packages/design-system/**"</div><div class=""> reason: "The design system itself must be clean"</div> Severity Pipeline
Rules are applied in a fixed order. Enforce trumps promote. Ignore is the escape hatch.
Promote
Conditional upgrades. Elevate severity based on filters like file path, type, or component.
Enforce
Unconditional critical. Overrides any promote result. If enforce matches, it's critical.
Ignore
The escape hatch. Ignored drift is excluded entirely — even if enforced. Use sparingly.
health.failBelow
Set a minimum health score in your config. When buoy drift check runs,
it exits with code 1 if the score drops below your threshold.
<div class=""># .buoy.yaml</div><div class="">health:</div><div class=""> failBelow: 70 # Exit code 1 if health score < 70</div> <div class=""># buoy drift check --json output includes health data</div><div class="">{</div><div class=""> "drifts": [...],</div><div class=""> "health": {</div><div class=""> "score": 68,</div><div class=""> "threshold": 70,</div><div class=""> "passed": false</div><div class=""> }</div><div class="">}</div>
Pairs with --fail-on CLI flags. The health gate is config-based — no need to pass flags in CI.