Until today, the only way to learn that an /enhance upload couldn't be fixed in-place was to wait the full pipeline run, get a compliance-gate-failed at the end, and then re-submit with mode: "regenerate". That round-trip is gone.
Every POST /api/v1/enhance now runs a pre-flight veraPDF pass first, cached by sha256(bytes). If the failing rules require a font or content rebuild that the in-place pipeline structurally can't do (CIDSet, embedded font program, ActualText for PUA codepoints), the producer returns 400 error="in-place-impossible" with the full blocker list and a ready-to-resubmit regenerateRequest.options payload — no queue work, no credit hold. Already-compliant uploads short-circuit to 200 status="already-compliant". Unsupportable uploads (encrypted, DRM-protected) get 400 error="unsupportable" with a one-line reason.
The companion POST /api/v1/pdf/validate endpoint surfaces the same routing decision under enhanceRecommendation, so callers (and the /validate page in your browser) can preview which mode is needed before submitting.
In the web UI, the /validate page now renders a per-mode eligibility panel below the rule list — naming the rules that block in-place — and /enhance auto-validates on file select so the recommendation lands before you click submit. If you submit on in-place anyway and the producer rejects it, the error panel surfaces the one-line reason without re-rendering the rule list you already saw.
Regenerate mode itself is still on the Phase 3.5 list — until that lands, the "Switch to regenerate" hand-off is informational. The pre-flight is the immediate win: the same call you make today now tells the truth in sub-second time when the answer is "you'll need a different mode."