diff --git a/CHANGELOG.md b/CHANGELOG.md
index 58f41c2..820e51a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,41 @@
All notable changes to Chat Switchboard.
+## [0.10.3] — 2026-02-24
+
+### Changed
+- **Frontend refactor: 2 monolith files → 13 domain-scoped files.** Split
+ `ui.js` (2,582 lines) and `app.js` (2,940 lines) into 13 focused files
+ averaging ~544 lines each. No features added, no functions renamed, no
+ architectural changes. Vanilla JS, no modules, no build step.
+
+ **New file structure:**
+
+ | File | Lines | Domain |
+ |------|------:|--------|
+ | ui-format.js | 353 | Markdown rendering, `esc()`, code blocks, side panel |
+ | ui-core.js | 974 | UI object: sidebar, chat list, messages, streaming, model selector |
+ | ui-settings.js | 640 | Settings tabs, teams, providers, user preferences |
+ | ui-admin.js | 645 | Admin tabs, users, roles, usage, teams |
+ | tokens.js | 123 | Context tracking, token estimation |
+ | notes.js | 364 | Notes panel, editor, multi-select |
+ | chat.js | 584 | Chat ops, send, regen, edit, branch, summarize |
+ | settings-handlers.js | 692 | Settings save, provider CRUD, command palette |
+ | admin-handlers.js | 652 | Admin actions, presets, team management |
+ | app.js | 567 | State, init, boot, auth, listener dispatch |
+
+ Unchanged: `api.js` (575), `debug.js` (580), `events.js` (327).
+
+- **`initListeners()` decomposed** into domain-specific init functions:
+ `_initChatListeners()`, `_initSettingsListeners()`, `_initAdminListeners()`,
+ `_initNotesListeners()`, `_initGlobalKeyboard()`. The orchestrator in `app.js`
+ dispatches to each.
+- **Side panel resize** changed from self-invoking IIFE to `_initSidePanelResize()`
+ called during listener init, avoiding DOM timing issues.
+- **Service worker** updated with new file list for pre-caching.
+- **Policy-gating tests** updated to read from the correct source files after
+ the split. All 159 tests pass.
+
## [0.10.2] — 2026-02-24
### Added
diff --git a/REFACTOR-0.10.3.md b/REFACTOR-0.10.3.md
new file mode 100644
index 0000000..48c7a8f
--- /dev/null
+++ b/REFACTOR-0.10.3.md
@@ -0,0 +1,530 @@
+# v0.10.3 — Frontend Refactor Plan
+
+## Problem
+
+Two monolith files accumulate every feature:
+
+| File | Lines | Role |
+|----------|------:|-----------------------------------|
+| app.js | 2,940 | All application logic + listeners |
+| ui.js | 2,582 | All rendering + admin + settings |
+| api.js | 575 | HTTP client (fine) |
+| debug.js | 580 | Debug logger (fine) |
+| events.js| 327 | EventBus WebSocket (fine) |
+| **Total**| **7,004** | |
+
+The v0.10.2 syntax bug (orphan brace nesting everything from notes
+through banners) is a direct consequence: in a 2,940-line file, a
+misplaced insertion is invisible.
+
+## Constraints
+
+- **Vanilla JS** — no build step, no bundler, no ES modules.
+- **Global functions** — HTML `onclick` handlers call ~25 named globals.
+ These must stay on `window`. No renaming.
+- **Load order via `
-
+
+
+
+
+
+
+
+
+