id: CORE-001D3A title: Alerts and Settings Entrypoint Normalization status: done priority: P2 effort: S depends_on: - CORE-001B - CORE-001D2B tags: - core - decimal - alerts - settings summary: Alert evaluation and settings save-status formatting now normalize float-heavy inputs through explicit named adapters. completed_notes: - Added explicit normalization adapters in `app/services/alerts.py` and `app/services/settings_status.py`. - Alert evaluation now compares thresholds through normalized Decimal-backed boundary values instead of ad-hoc `float(...)` extraction. - Settings save-status formatting now snapshots numeric boundary values through a named adapter before rendering. - Added focused regression tests for numeric-string coercion and bool fail-closed behavior in `tests/test_alerts.py` and `tests/test_settings.py`. - Hardened `/{workspace_id}/settings` so blank loan input no longer silently saves as a zero-loan portfolio; the loan field now preserves blank state until validation, keeps whole-dollar formatting stable, and marks the save card as `Last saved` / `Unsaved invalid changes` instead of presenting stale saved state as current. - Validated with focused pytest coverage, browser-driven Playwright coverage on local Docker, and `make build`.