# Bug + Dead Code Audit — 2026-04-03 ## Scope Static audit focused on the changed `tauri-app` surface plus verification via: - `cd tauri-app && npm test` - `cd tauri-app && npm run build` - `cd tauri-app/src-tauri && cargo check` - targeted reference searches with `rg` ## Files reviewed - `tauri-app/src/App.tsx` - `tauri-app/src/App.test.tsx` - `tauri-app/src/components/ChatView.tsx` - `tauri-app/src/components/Sidebar.tsx` - `tauri-app/src/components/Sidebar.test.tsx` - `tauri-app/src/components/MessageBubble.tsx` - `tauri-app/src/components/StreamingBubble.tsx` - `tauri-app/src/lib/devLogger.ts` - `tauri-app/src/types/forgeagent.ts` - `tauri-app/src/components/chat/index.ts` - `tauri-app/src/components/chat/MessageBubble.tsx` - `tauri-app/src/components/chat/ThinkingCard.tsx` - `tauri-app/src/components/chat/TaskList.tsx` - `tauri-app/src/components/chat/ArtifactViewer.tsx` ## Findings ### 1. `tauri-app/src/components/ChatView.tsx:21-33` **Severity:** High **Problem:** Stream decoders are module-level singletons with `stream: true` and are never flushed/reset. **Evidence:** `WINDOWS_1252_DECODER` and `UTF8_DECODER` live across requests. If a request aborts or ends mid-multibyte sequence, decoder internal state can bleed into the next response and create phantom mojibake. **Fix:** Create fresh decoders per request inside `handleSend`, and flush on stream completion with `decoder.decode()`. ### 2. `tauri-app/src/App.tsx:22-25` **Severity:** Medium **Problem:** `window.localStorage.getItem(...)` is called without checking that `localStorage` is a functional Storage object. **Evidence:** Full suite fails with `TypeError: window.localStorage.getItem is not a function` from this exact line. **Fix:** Guard with `typeof window.localStorage?.getItem === 'function'` and wrap storage access in a safe helper. ### 3. `tauri-app/src/components/Sidebar.tsx:196-198` **Severity:** Medium **Problem:** Settings control has only `title="Settings"` and no explicit accessible name. **Evidence:** Sidebar tests cannot reliably locate the footer settings action after the UI rewrite; button markup lacks `aria-label`. **Fix:** Add `aria-label="Open settings"`. ### 4. `tauri-app/src/components/ChatView.tsx:467-491` **Severity:** Medium **Problem:** Assistant message persistence depends on a DB refresh path after generation; one regression test shows the final reply is not visible after completion. **Evidence:** `npm test` fails at `src/components/ChatView.test.tsx:514` even though DB insert succeeds (`The answer is 42` logged and inserted). **Fix:** Add a direct optimistic append to local `messages` state after successful insert, then re-sync from DB. ### 5. `tauri-app/src/components/chat/index.ts:1-4` + `tauri-app/src/components/chat/*` **Severity:** Medium **Problem:** Obsolete component subtree appears dead. **Evidence:** Reference search shows no runtime imports of `components/chat/index.ts`, `ThinkingCard`, `TaskList`, `ArtifactViewer`, or `components/chat/MessageBubble.tsx`. **Fix:** Remove the unused subtree or wire it back intentionally. Keeping both old and new message-bubble systems increases maintenance risk. ### 6. `tauri-app/src/types/forgeagent.ts:109-112` **Severity:** Low **Problem:** `ArtifactViewerProps` is duplicated/unused. **Evidence:** The real component defines its own local props in `src/components/chat/ArtifactViewer.tsx`; no imports reference the exported type. **Fix:** Delete the unused interface or centralize the prop type. ## Test / verification summary - `build`: PASS - `cargo check`: PASS - `npm test`: FAIL - `src/App.test.tsx` (4 failures) - `src/Sidebar.test.tsx` (4 failures) - `src/components/ChatView.test.tsx` (1 failure) ## Checklist summary - Injection/XSS/auth/CSRF/crypto: no concrete new exploit found in reviewed files - Bugs/regressions: confirmed - Dead code/obsolete paths: confirmed - Not fully verified: Rust inference crates outside `tauri-app` changed set were not fully line-audited in this pass