# Email-Reactor fail-closed fix — classifier failure / partner mail no longer auto-archived (MC #103815)

## Incident / Root Cause

`~/system/daemons/email-agent.js` was **FAIL-OPEN**. When Ollama classification failed (request timeout, JSON parse error, or no-JSON-match), `ollamaClassify` resolved to `{category:'INFO', priority:'low'}`. The auto-archive block then archived any info/spam/own row. The strategic-partner elevation block only ran when `dbCategory === 'ACTION'`, so a misclassified partner email was never elevated.

**Net effect:** A revenue email from strategic partner **Asmir Merdžanović** ("QODY" project, email #9661, 2026-06-13) was silently auto-archived and never answered until he re-sent it 2026-06-17.

## Fix (FAIL-CLOSED) — 3 Changes

1. **All three `ollamaClassify` failure branches** now resolve `{category:'ACTION', priority:'medium', _classifyFailed:true}` with distinct reason (timeout/parse\_error/no\_json) — an unclassifiable email defaults to actionable, never FYI/archive.
2. **`matchStrategicPartner()` now runs independent of category** (guard `if (!ARGS.dryRun)`); on a partner match it elevates to ACTION via `emailInbox.updateClassification(...,'ACTION','high')`, sets partner\_tier, fires CEO push.
3. **Auto-archive is guarded** by `_skipArchiveDueToClassifyFail` and partner-elevated rows (cat patched to 'action') never reach the archive branch.

**New helper:** `updateClassification(id, classification, priority)` added + exported in `~/system/tools/email-inbox.js`.

## Verification

- `node --check` clean on both files
- Simulation harness `/tmp/evidence-103815/sim.test.js` = **39 PASS / 0 FAIL** incl. the exact Asmir/QODY regression
- Independent verification: **native verifier (7/7 atomic claims)** + **Proveo P2P PASS** (mesh-thr-95c7fb0b / mesh-msg-008f947c)

## Deployment

Daemon `com.john.email-agent` is `StartInterval` (spawns fresh node each cycle) → fix is **live on the next cycle**, no restart needed.

## Residual Known Gap (Follow-on MC #103819)

Two heuristic INFO fallbacks **OUTSIDE `ollamaClassify`** (circuit-breaker path ~L2161 and promise-rejection catch ~L2177) do not yet carry `_classifyFailed`; narrow exposure (non-partner email during Ollama TCP error / breaker-open with no heuristic keyword match).

## Lesson

**Email triage must FAIL-CLOSED** — an email the classifier could not process must never be silently archived; strategic-partner safety net must be category-independent.

---

*Evidence bundle:* `/tmp/evidence-103815/`  
*MC task:* #103815  
*Date:* 2026-06-17