Three pre-existing issues in ui/dashboard were flagged during the review of #981 (Playwright smoke harness). None are introduced by that PR — logging here so they're tracked rather than lost. Independent fixes; can be split into separate PRs if preferred.
1. Duplicate best_height key in ancestors renderCells
src/routes/ancestors/+page.svelte defines best_height twice in the same renderCells object literal (:417 and :550). The second silently overwrites the first — and they differ: the dead one falls back to '-', the live one to '0'. Decide the intended empty-value rendering and keep a single definition.
2. Peers catchup button uses fragile DOM-index traversal
src/routes/peers/+page.svelte:625 (handleCatchupButtonClick) resolves the clicked peer by walking target.closest('tr') → row.parentElement → indexOf(row) into data[rowIndex]. This couples the handler to the table's exact DOM shape and breaks if the table wraps rows, virtualizes, reorders, or paginates differently than data. A global document click listener + index math is brittle; prefer a per-row handler passing the peer directly, or a data-* attribute carrying the peer id.
3. Admin page duplicates backend FSM transition logic
src/routes/admin/+page.svelte:66 (isEventAllowedForState) hardcodes the state→allowed-events transition table (IDLE/RUNNING/LEGACYSYNCING/CATCHINGBLOCKS). This mirrors the backend FSM and will drift when transitions change server-side. Prefer deriving allowed events from the backend (the FSM already exposes states/events) rather than a hand-maintained client copy.
Surfaced by: #981 consolidated review. Not blocking that PR.
Three pre-existing issues in
ui/dashboardwere flagged during the review of #981 (Playwright smoke harness). None are introduced by that PR — logging here so they're tracked rather than lost. Independent fixes; can be split into separate PRs if preferred.1. Duplicate
best_heightkey inancestorsrenderCellssrc/routes/ancestors/+page.sveltedefinesbest_heighttwice in the samerenderCellsobject literal (:417and:550). The second silently overwrites the first — and they differ: the dead one falls back to'-', the live one to'0'. Decide the intended empty-value rendering and keep a single definition.2. Peers catchup button uses fragile DOM-index traversal
src/routes/peers/+page.svelte:625(handleCatchupButtonClick) resolves the clicked peer by walkingtarget.closest('tr')→row.parentElement→indexOf(row)intodata[rowIndex]. This couples the handler to the table's exact DOM shape and breaks if the table wraps rows, virtualizes, reorders, or paginates differently thandata. A globaldocumentclick listener + index math is brittle; prefer a per-row handler passing the peer directly, or adata-*attribute carrying the peer id.3. Admin page duplicates backend FSM transition logic
src/routes/admin/+page.svelte:66(isEventAllowedForState) hardcodes the state→allowed-events transition table (IDLE/RUNNING/LEGACYSYNCING/CATCHINGBLOCKS). This mirrors the backend FSM and will drift when transitions change server-side. Prefer deriving allowed events from the backend (the FSM already exposes states/events) rather than a hand-maintained client copy.Surfaced by: #981 consolidated review. Not blocking that PR.