diff --git a/.planning/quick/260716-pgr-fix-confidence-display-bug-in-classifica/260716-pgr-PLAN.md b/.planning/quick/260716-pgr-fix-confidence-display-bug-in-classifica/260716-pgr-PLAN.md
new file mode 100644
index 0000000..b204d45
--- /dev/null
+++ b/.planning/quick/260716-pgr-fix-confidence-display-bug-in-classifica/260716-pgr-PLAN.md
@@ -0,0 +1,109 @@
+---
+phase: quick
+plan: 260716-pgr
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - components/phishing/classification-card.tsx
+autonomous: true
+requirements: [QUICK-CONFIDENCE-DISPLAY]
+
+must_haves:
+ truths:
+ - "A maximum-confidence classification (confidence='1') displays as '100% confidence', not '1% confidence'"
+ - "A 0.85-confidence classification displays as '85% confidence'"
+ - "If confidence is null or does not parse to a finite number, no confidence text renders"
+ artifacts:
+ - path: components/phishing/classification-card.tsx
+ provides: "Corrected confidence display (0-1 scale rendered as 0-100 percent)"
+ contains: "Math.round(Number(classification.confidence) * 100)"
+ key_links:
+ - from: components/phishing/classification-card.tsx
+ to: classifications.confidence (0.0-1.0 NUMERIC, serialized as string)
+ via: "Number() coercion + *100 + Math.round in the render guard"
+ pattern: "Number\\(classification.confidence\\) \\* 100"
+---
+
+
+Fix a confidence display bug in the phishing ClassificationCard. The `classifications.confidence`
+column stores a 0.0-1.0 scale (computed by `campaign-classifier.ts` `computeConfidence()`, where
+`confidence=1` means maximum/100% confidence). The card currently appends "%" directly to the raw
+0-1 value, so a maximum-confidence classification renders as "1% confidence" — the exact opposite
+of its true meaning to an operator.
+
+Purpose: Operators reading a phishing classification must see the correct confidence percentage.
+Output: One corrected render expression in `components/phishing/classification-card.tsx`.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/quick/260716-pgr-fix-confidence-display-bug-in-classifica/260716-pgr-PLAN.md
+
+
+From components/phishing/classification-card.tsx:
+```typescript
+export interface ClassificationCardData {
+ id: string;
+ verdict: 'SPAM' | 'UNWANTED' | 'THREAT';
+ confidence: string | null; // API serializes the 0.0-1.0 NUMERIC column as a string
+ // ...
+}
+```
+
+Current render block (lines 118-122) — the exact block to replace:
+```tsx
+{classification.confidence != null && (
+
+ {classification.confidence}% confidence
+
+)}
+```
+
+
+
+
+
+
+ Task 1: Convert confidence to percent before rendering
+ components/phishing/classification-card.tsx
+ Replace the confidence render block at lines 118-122. Parse the value once
+with `Number(classification.confidence)` and multiply by 100 with `Math.round(... * 100)`
+so the 0.0-1.0 scale renders as a 0-100 integer percent. Extend the existing
+`classification.confidence != null` guard so the block ONLY renders when the parsed number
+is finite (use `Number.isFinite(...)`), matching the existing null-guard style already
+wrapping this block — if the string does not parse, render nothing rather than "NaN%".
+Keep the same `...% confidence`
+markup; only the numeric expression and the guard condition change. Do NOT change the
+`confidence: string | null` type or any other part of the file.
+
+ npx tsc --noEmit --pretty 2>&1 | grep -i "classification-card" || echo "no type errors in classification-card"
+ grep -q "Math.round(Number(classification.confidence) \* 100)" components/phishing/classification-card.tsx && echo "conversion present"
+ grep -q "Number.isFinite" components/phishing/classification-card.tsx && echo "finite guard present"
+
+ The card renders confidence='1' as "100% confidence" and confidence='0.85' as
+"85% confidence"; null or non-parsing values render no confidence text; `npx tsc --noEmit`
+reports no new errors.
+
+
+
+
+
+- `npx tsc --noEmit --pretty` passes (tsc is the only safety net; components/** has no vitest coverage).
+- Manual read-through: the render expression multiplies by 100 and rounds, and the guard checks `Number.isFinite`.
+
+
+
+- confidence='1' → "100% confidence"
+- confidence='0.85' → "85% confidence"
+- confidence=null or unparseable → no confidence text rendered
+- No other behavior in the component changes; type check clean.
+
+
+
diff --git a/.planning/quick/260716-pgr-fix-confidence-display-bug-in-classifica/260716-pgr-SUMMARY.md b/.planning/quick/260716-pgr-fix-confidence-display-bug-in-classifica/260716-pgr-SUMMARY.md
new file mode 100644
index 0000000..568de64
--- /dev/null
+++ b/.planning/quick/260716-pgr-fix-confidence-display-bug-in-classifica/260716-pgr-SUMMARY.md
@@ -0,0 +1,35 @@
+---
+status: complete
+---
+
+# Quick Task 260716-pgr: Fix confidence display bug — Summary
+
+**`ClassificationCard` rendered the 0.0-1.0 `classifications.confidence` value by appending "%" directly, so a maximum-confidence classification (`confidence='1'`) displayed as "1% confidence" — read by an operator as near-zero, the opposite of its true meaning. Fixed by multiplying by 100 and rounding, guarded by `Number.isFinite`.**
+
+## Change
+
+`components/phishing/classification-card.tsx` — confidence render block:
+```tsx
+{classification.confidence != null && Number.isFinite(Number(classification.confidence)) && (
+
+ {Math.round(Number(classification.confidence) * 100)}% confidence
+
+)}
+```
+
+## Verification
+
+- `npx tsc --noEmit --pretty` clean.
+- `Math.round(Number(classification.confidence) * 100)` present.
+- `Number.isFinite` guard present.
+- Manual trace: `confidence='1'` → "100% confidence"; `confidence='0.85'` → "85% confidence"; `confidence=null` or unparseable → no confidence text renders.
+
+## Deviations from Plan
+
+None — plan executed exactly as written.
+
+## Discovered while investigating this bug
+
+This was found live while reviewing ticket 699415's classification in the Phase 22 review page (a Breach Secure Now/KnowBe4 simulated-phishing report, correctly classified `UNWANTED` with `confidence=1`, displaying as "1% confidence" before this fix). The same investigation surfaced two follow-on items tracked separately:
+- A dead Autotask webhook (no delivery since 2026-04-29) — fixed same session by re-registering the Tickets/TicketNotes subscriptions.
+- A request to add a dedicated "User Awareness"/simulation verdict (today forced into the generic `UNWANTED` bucket) plus a per-company automation gate — scoped as a new phase, not part of this quick task.
diff --git a/components/phishing/classification-card.tsx b/components/phishing/classification-card.tsx
index 017468b..a6fc5a5 100644
--- a/components/phishing/classification-card.tsx
+++ b/components/phishing/classification-card.tsx
@@ -115,9 +115,9 @@ export function ClassificationCard({
{classification.verdict}
- {classification.confidence != null && (
+ {classification.confidence != null && Number.isFinite(Number(classification.confidence)) && (
- {classification.confidence}% confidence
+ {Math.round(Number(classification.confidence) * 100)}% confidence
)}