Spec
Intent
Drift is the silent killer in AI-led codebases. This gauge gives a single, glanceable measure of how far implementation has wandered from spec.
Acceptance Criteria
- [ ] Needle position maps to drift percentage
- [ ] Coloured bands: success (low) → attention (mid) → danger (high)
- [ ] Numeric readout below the needle
- [ ] Negative: does NOT smooth the needle — neubrutalist hard angle
Constraints
- Pure SVG, no JS
- Theme-aware colours
// drift-gauge.astro
---
import type { CompendiumMeta } from '../../../data/types';
export const meta: CompendiumMeta = {
id: 58,
slug: 'drift-gauge',
name: 'Drift Gauge',
category: 'metrics-telemetry',
subcategory: 'gauges',
pillar: 'de',
description: 'A radial gauge with a hard needle measuring distance between intent and implementation.',
spec: `## Intent
Drift is the silent killer in AI-led codebases. This gauge gives a single, glanceable measure of how far implementation has wandered from spec.
## Acceptance Criteria
- [ ] Needle position maps to drift percentage
- [ ] Coloured bands: success (low) → attention (mid) → danger (high)
- [ ] Numeric readout below the needle
- [ ] Negative: does NOT smooth the needle — neubrutalist hard angle
## Constraints
- Pure SVG, no JS
- Theme-aware colours`,
tags: ['svg', 'gauge', 'real-content'],
status: 'stable',
health: { ics: 88, a11y: 'aa', themed: true, animated: false },
};
const drift = 34; // percent
const angle = -90 + (drift / 100) * 180;
const rad = (angle * Math.PI) / 180;
const needleX = 100 + Math.cos(rad) * 70;
const needleY = 100 + Math.sin(rad) * 70;
const band = drift < 25 ? 'NOMINAL' : drift < 60 ? 'WATCH' : 'CRITICAL';
---
<div class="w-full bg-paper text-black border-4 border-black p-4 flex flex-col items-center">
<svg viewBox="0 0 200 130" class="w-full max-w-[280px] block" aria-label={`Drift ${drift}%, ${band}`}>
<path d="M 30 100 A 70 70 0 0 1 79.3 33.3" stroke="var(--color-success)" stroke-width="16" fill="none" />
<path d="M 79.3 33.3 A 70 70 0 0 1 166.6 78.4" stroke="var(--color-attention)" stroke-width="16" fill="none" />
<path d="M 166.6 78.4 A 70 70 0 0 1 170 100" stroke="var(--color-danger)" stroke-width="16" fill="none" />
<g stroke="var(--color-ink)" stroke-width="2">
<line x1="30" y1="100" x2="22" y2="100" />
<line x1="100" y1="30" x2="100" y2="22" />
<line x1="170" y1="100" x2="178" y2="100" />
</g>
<line x1="100" y1="100" x2={needleX} y2={needleY} stroke="var(--color-ink)" stroke-width="4" stroke-linecap="butt" />
<circle cx="100" cy="100" r="6" fill="var(--color-ink)" />
<circle cx="100" cy="100" r="2" fill="var(--color-paper)" />
</svg>
<div class="mt-1 flex items-baseline gap-3">
<span class="font-black text-2xl tabular-nums">{drift}<span class="text-sm opacity-60">%</span></span>
<span class="font-mono text-[10px] uppercase tracking-widest opacity-60">drift</span>
<span class="font-black text-[11px] uppercase tracking-widest">{band}</span>
</div>
</div>