# Simplification Loop — Mission Charter & Progress Started 2026-07-02 on branch `fable/clean-up`. Recurring loop (every 30 min), ~10-hour horizon. Each iteration reads this doc, executes the next items, keeps gates green, commits, and updates this doc. ## Charter (user directives) 1. **Keep every feature** — the contract is docs/ux-stories.md; nothing there regresses. 2. **Drastically cut** code size, surfaces, complexity, settings, config files, dependencies. Every file scrutinized (docs, workflows, CLI, controller, frontend). 3. **UI pixel-identical.** Consolidate everything onto the base UI kit (`src/ui`). 4. **Catch and fix bugs** along the way. 5. Autonomous; no questions. Never delete untracked/user data without explicit OK. ## Gates - Full: `npm run check`. NOTE coverage gap: root gate runs controller typecheck only; CI also runs controller lint + check (knip/jscpd/depcheck/standards) + unit + integration tests. Run `cd controller && bun run lint && bun run check && bun run test:unit` for controller changes. (Hitlist C0 fixes this.) - Commit per coherent unit, `--no-verify` (hooks: frontend bans useEffect etc.). ## HITLIST — Controller (from audit) - [x] **C1 BUG unbounded telemetry growth** (ffc1baa9): observability middleware writes a row per request (`http/observability-middleware.ts:32`, `core/function-observability.ts`, `stores/controller-request-store.ts`) with no retention and no skip-list; polling floods DB forever. Fix: reuse app.ts:63 skip-set + add retention prune. SAFE. - [x] C2 (c5dd16b9) dead route `/events/stats` (`system/logs-routes.ts:266`) — no caller. SAFE. - [x] C3 (c5dd16b9) dead route `/runtime/sglang/config` (`engines/routes.ts:356`) — frontend only fetches vllm/llamacpp configs. SAFE. - [x] C4 (c5dd16b9) collapse single-impl `EngineService` interface (`engines/engine-service.ts`, 26 lines) into EngineCoordinator. SAFE. - [x] C5 (c5dd16b9) dedupe 10× `findInferenceProcess` observability wrapper (system/routes, metrics-routes, logs-routes, models/routes, tokenization-routes) → one helper. SAFE. - [x] C6 (c5dd16b9) remove (createEngineCoordinator/createEventManager; other create* are real closure factories, kept) `create*` one-line factory wrappers (createEngineCoordinator etc.). SAFE. - [x] C7 (c5dd16b9) `main.ts` metricsDisabled() duplicates `parseBooleanFlag` (validation.ts:41). SAFE. - [x] C8 (f1cf3313) inline tiny per-module `configs.ts` constant files (audio 7, proxy 6, system 5, models 15, engines 20 lines); keep studio/configs.ts. SAFE. - [x] C9 (f1cf3313) delete `modules/shared/{system,recipe}-types.ts` re-export shims → import shared/contracts directly. SAFE. - [x] C10 (f1cf3313) provider serializer dup ×4 in `studio/provider-routes.ts` → serializeProvider + parseProviderBody. SAFE. - [x] C11 (f1cf3313) standardize `parseJsonObjectBody` (core/validation.ts:10) in routes that hand-roll `req.json().catch`. SAFE. - [x] C12 (a771fcba) dead route `/api/title` (proxy/chat-title-routes.ts, ~70 lines) — only the integration test calls it; verify no external client (grep pi runtime) then cut. - [x] C13 (a5b65200) dead cross-controller passthrough `/controllers/route/*` (http/app.ts:22-37,85-137 + LOCAL_STUDIO_CONTROLLER_ROUTE_ALLOWLIST). NOTE memory says frontend "Add controller" feature exists — verify /controllers/route vs /controllers before cutting. - [x] C14 (a771fcba) dead `/lifetime-metrics` route (store kept — live via inference accounting) (+ maybe LifetimeMetricsStore). - [x] C15 (a771fcba) dead `/v1/tokenize` + `/v1/detokenize` — CAUTION: reachable by external OpenAI clients via proxy; grep pi/droid runtimes first. - [x] C16 (a771fcba) dead `GET /runtime/targets/:id` + `/health` probe. - [KEEP] C17 flag audit done: strict_openai_models read at openai-routes.ts:135 (live branch); MOCK_INFERENCE load-bearing for test fixtures; vLLM extra-args escape hatches deliberate. All stay. flag audit: STRICT_OPENAI_MODELS readers; vLLM extra-args escape hatches; MOCK_INFERENCE (used by E2E? verify). - [x] C18 (a171aca0) inlined all Promise-ceremony Effect wrappers (fetchLocal, resolveBinary, delay, AsyncLock, AsyncQueue). Dep itself STAYS: Schema in recipe-serializer/env/errors + Effect.gen process pipelines are substantive. inline single-use `*Effect` variants (function-observability, local-fetch, command.ts resolveBinary, async.ts) then consider dropping `effect` dep entirely (only trivial usage remains + env.ts Schema + errors.ts TaggedError). - [SKIP] C19 `/api/docs` is user-facing: Server pane links to /api/proxy/api/docs (server-view.tsx:388). KEEP. `/api/docs` swagger UI + `@hono/swagger-ui` dep + openapi-spec.ts (255 lines) — /api/spec is proxied by frontend; verify what reads it. - [SKIP] C20 lateral shuffle: capability rules are env-sensitive (upgrade-cmd checks) and cohesive in the factory; moving to EngineSpec spreads env logic across spec files for ~0 line win. Same reasoning as the earlier runtime-targets split skip. - Previously skipped (do NOT re-propose): store merges, metrics throughputSamples unification, runtime-targets.ts split. ## HITLIST — Frontend (from audit; knip/depcheck/jscpd all clean already) - [x] **F1 BUG copy-toast timer leak ×5** (a9e60da7, hooks/use-copied-flag.ts): setTimeout(setCopied) with no cleanup in copyable-path-chip.tsx:26, assistant-markdown.tsx:61, user-message-block.tsx:92, assistant-message-actions.tsx:41, use-discover.ts:106 → one useCopiedFlag() hook (NB: eslint bans raw useEffect; follow useMountSubscription pattern). SAFE. - [x] F2 (a9e60da7) move `ui/model-page.tsx` (7 exports) → features/recipes/recipes-content/ (all 6 consumers there); drop ui/index.ts:112-121. SAFE. - [x] F3 (a9e60da7) move (as features/settings/settings-ui.tsx; setup + recipes cross-feature consumers exist and are boundary-legal) `ui/settings.tsx` (8 exports) → features/settings/ (all 4 consumers there); drop ui/index.ts:95-110. SAFE. - [SKIP] F4 messages barrel has 24 importers — real aggregation point (also re-exports contracts); folding = churn. fold 7-line `features/agent/messages/index.ts` barrel — CHECK scripts/validate-barrel-dir-siblings.mjs convention first. - [SKIP] F5 all candidates fail criteria: filesystem-panel (612 post-merge), use-workspace (571), git-diff-panel (642) exceed 500 lines; agent-browser-effects + quick-panel-bridge have 2 importers each. merge single-consumer twins (grep importers first, keep parent <500 lines): filesystem-panel-effects, use-workspace-effects, git-diff-panel-model, agent-browser-effects, quick-panel-bridge (13 lines). Do NOT merge chat-pane* cluster (all files substantial). - [SKIP] F6 types has 6 importers; equality merge makes store 600+ lines, net-negative. collapse hooks/realtime-status-{equality,types}.ts into store if single-importer. - [ ] F7 PRODUCT settings/local-agent-* cluster (~750 lines) — real feature landed 07c8db90 (attach-local-agents); KEEP unless user retires it. Not a cut. - [ ] F8 voice routes (app/api/voice/*) — UI caller thin/unclear; memory says recipe db has voice fields and local test uses voiceModel. Verify before touching. ## HITLIST — UI-kit consolidation (pixel-identical; ranked by call sites) Base kit: `src/ui` (catalogue in audit). Missing primitives: Spinner, Tooltip, Dropdown/Popover. Two token systems: `--ui-*` (12 files) vs legacy `--fg/--dim/ --surface/--hl1` (41 files, most of features/agent). - [BLOCKED-ON-USER] U1 Button variants have own padding/hover ≠ bespoke classes; wholesale swap changes pixels. Only exact-class matches safe (none found worth it). ~140 raw `