---
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"
---

<objective>
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`.
</objective>

<execution_context>
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/quick/260716-pgr-fix-confidence-display-bug-in-classifica/260716-pgr-PLAN.md

<interfaces>
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 && (
  <span className="text-sm text-muted-foreground">
    {classification.confidence}% confidence
  </span>
)}
```
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Convert confidence to percent before rendering</name>
  <files>components/phishing/classification-card.tsx</files>
  <action>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 `<span className="text-sm text-muted-foreground">...% confidence</span>`
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.</action>
  <verify>
    <automated>npx tsc --noEmit --pretty 2>&1 | grep -i "classification-card" || echo "no type errors in classification-card"</automated>
    <automated>grep -q "Math.round(Number(classification.confidence) \* 100)" components/phishing/classification-card.tsx && echo "conversion present"</automated>
    <automated>grep -q "Number.isFinite" components/phishing/classification-card.tsx && echo "finite guard present"</automated>
  </verify>
  <done>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.</done>
</task>

</tasks>

<verification>
- `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`.
</verification>

<success_criteria>
- 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.
</success_criteria>

<output>
Create `.planning/quick/260716-pgr-fix-confidence-display-bug-in-classifica/260716-pgr-SUMMARY.md` when done.
</output>
