Promote warnings. Enforce zero-tolerance. Your severity, your rules.

Not all drift is equal. Checkout hardcoded colors matter more than test utility spacing. Severity rules let you set the weight.

Get started free

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.

buoy-cli
$
Running drift check...
Severity Rules Applied:
warningcritical hardcoded-color in src/checkout/**
✗ CRITICAL Hardcoded color #3b82f6 in checkout/PaymentForm.tsx:24
Promoted from warning — matches rule: hardcoded-color in src/checkout/**
.buoy.yaml
<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.

hardcoded-color
hardcoded-spacing
close-match

severity

Match drift by current severity before promotion. Only available in promote rules.

warning
info
📁

file

Match drift by file path using glob patterns. Target specific directories or file types.

src/checkout/**
**/*.legacy.tsx
📦

component

Match drift by component name using regex. Target specific components or patterns.

PaymentForm
Legacy.*
🎨

token

Match drift by token name using regex. Target specific token references.

color-primary
spacing-.*
🎯

value

Match drift by the hardcoded value using regex. Target specific values across the codebase.

#3b82f6
\d+px

drift.enforce

Zero-tolerance rules. No severity filter, no to field. Matching drift is always set to critical. No negotiation.

buoy-cli
$
Running drift check...
Enforcement Rules Applied:
enforced close-match → critical (no negotiation)
✗ CRITICAL Close match #3b83f6#3b82f6 in Button.tsx:28
Enforced — close-match drift is always critical
✗ 2 critical issues found. Exiting with code 1.
.buoy.yaml
<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.

1

Promote

Conditional upgrades. Elevate severity based on filters like file path, type, or component.

2

Enforce

Unconditional critical. Overrides any promote result. If enforce matches, it's critical.

3

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.

.buoy.yaml
<div class=""># .buoy.yaml</div><div class="">health:</div><div class="">  failBelow: 70    # Exit code 1 if health score < 70</div>
--json output
<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.

Ready to catch design drift?

Free. Open source. No signup required.

Related Features

Drift Detection

Find every inconsistency across your codebase

CI Integration

Add drift checks to your CI pipeline

Ignore Rules

Intentional exceptions for known drift