f4ed7401da3ed7e48a77728c8a794914d77ace39
Four defects, one shape: a write that returns 200 and lands nowhere.
- Unknown keys were dropped by a chain of `if (match) continue` with no `else`. The three prefixes
CommandTerminalWrapper actually writes — tmux, nvim, claude-code — were among them, so those panel
maps lived in the React Query cache only: every reload minted a fresh uuid and abandoned a running
pty. They now live in a `panel_state` bag on the dashboard row, and an unmatched key 400s.
- `ws-terminals-{id}: null` fell through to an upsert, writing NULL into a NOT NULL column on a live
dashboard and re-INSERTing a deleted one. Renaming a dashboard sends exactly that, paired with
`ws-layout-{id}: null`, so the old slug came back as a zombie row in the dashboards list.
- HostTerminalWrapper and CommandTerminalWrapper built their state key straight from `dashboardId`,
which is a workspace *key* (`ws-layout-<id>`), while TerminalWrapper stripped the prefix. The server
read the un-stripped form back as a dashboard id and created it. One rule now, in state-key.ts.
Verified against the live server: unknown key 400s, the three prefixes round-trip, a null on a live
dashboard is a no-op, and the rename sequence leaves no zombie.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Description
No description provided
42 MiB
Languages
TypeScript
90.9%
Shell
4.7%
JavaScript
4.1%
CSS
0.2%
HTML
0.1%