Repository navigation
fix(ui-web): draw the rail after a re-read replaces its rows - #597
Conversation
Replacing the rows is not showing them. Every other writer in the rail knows this -- leave.ts and the session registry both draw after their replace -- but the plain re-read did not, and the archive page's restore reaches the rail only through it. So a restored conversation came back in the config, on disk and in what the server lists, and stayed off the screen until the page was reloaded: the same shape as the archive report this fixes the other half of. At boot the rail is still held, where a draw sets the skeleton and releaseRail paints the rows, so the other caller is unaffected. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The draw added in the commit before this one made a older defect visible. `loadSessions` replaced the rows with the raw answer, while its sibling `refreshList` puts the same answer through `reconcileRows` first -- which is what carries across the two things `session.list` cannot know: which conversation has a turn running, and the current conversation while it is too new to be listed. Dropping those was invisible as long as nothing repainted. With the repaint it is a running badge wiped, and the row for the conversation the reader is in removed, every time they restore something from the archive page. Through the reconcile now. `currentMissing` stays `refreshList`'s business: that answer means the open conversation was deleted under the reader, and leaving it is the transition that owns moving them out. Found by an adversarial review of the previous commit, reproduced against the real store before and after. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
30a5c0a to
f4a09c1
Compare
gloryfromca
left a comment
There was a problem hiding this comment.
No blockers; this can merge as far as I am concerned.
Reviewed the full target diff and the new revision delta. I checked the repository rules and ui-web vocabulary/architecture, both loadSessions callers (boot and archive restore), the parallel registry refresh path, row/store behavior, relevant history, backward compatibility, and that the tests strengthen rather than weaken coverage. The reconciliation preserves client-only running/current state before the newly visible redraw, while boot remains safe because the rail is held until release.
Verification: npm test -- src/features/rail/source.test.ts (14 passed), npm test (2,474 passed across 189 files; Happy DOM emitted aborted localhost fetch diagnostics), npm run type-check (passed), and npx eslint src/features/rail/source.ts src/features/rail/source.test.ts (passed).
## Summary Restoring a conversation from the archive page put it back everywhere except the screen. `loadSessions` replaced the rail's rows and never drew them, and the restore reaches the rail only through that function, so the row came back in the server's listing and on disk while the rail kept showing the list from before. Reloading the page was what appeared to restore it. Every other writer in this feature already draws after a replace -- `leave.ts` does it on both of its transitions, the session registry does it after its reconcile -- so the fix is the missing call in the one path that did not, rather than a draw at the restore call site. At boot the rail is still held, where a draw sets the skeleton and `releaseRail` paints the rows, so the other caller is unaffected. Found while driving the merged archive flow end to end on a real host, after #585, #589 and #596. It is the same shape as #596: server state correct, screen stale until a reload. ## Type - [x] Fix - [ ] Feature - [ ] Docs - [ ] CI / tooling - [ ] Refactor - [ ] Other ## Verification On a real host (`raven web` on an isolated `RAVEN_HOME` built from a real config, driven through the browser), reading the archived flag from the last metadata record of the session transcript rather than from the page: | Step | Before | After | | --- | --- | --- | | Archive a conversation from the rail | leaves the rail, `archived: true` on disk | same | | Settings, Archive page | it is listed | same | | Restart the gateway | still archived, does not come back | same | | Restore it from the Archive page | `archived: false` on disk, **rail still does not show it** | rail shows it at once | | Reload the page | rail shows it | rail shows it | Commands: - `npm test --prefix ui-web` -- 189 files, 2470 tests, all pass - `npm run lint --prefix ui-web` -- 0 errors (4 pre-existing warnings in CronPage/SubagentsPage, untouched here) - `npm run type-check --prefix ui-web` -- clean - `npm run --prefix ui-web build && python3 ui-web/build.py` -- boot-snapshot OK (235 nodes match golden) - `npx commitlint --from github/refactor/ui_web_architecture --to HEAD` -- clean The new case, `a plain re-read draws the rows it just replaced`, was run against the unfixed module first and fails there on the assertion it is named for. - [x] Relevant tests pass locally - [x] Relevant lint / type checks pass locally - [ ] User-facing docs or screenshots are updated when needed ## Risk One added call in a function with two callers; the other one runs while the rail is held, where the draw is a no-op beyond the skeleton it already sets. No server change, no stored state change. Rollback is reverting one commit. - [x] Security impact considered - [x] Backward compatibility considered - [x] Rollback path is clear for risky changes ## Related Issues N/A --------- Co-authored-by: gloryfromca <23442919+gloryfromca@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Summary
Restoring a conversation from the archive page put it back everywhere except the
screen.
loadSessionsreplaced the rail's rows and never drew them, and therestore reaches the rail only through that function, so the row came back in the
server's listing and on disk while the rail kept showing the list from before.
Reloading the page was what appeared to restore it.
Every other writer in this feature already draws after a replace --
leave.tsdoes it on both of its transitions, the session registry does it after its
reconcile -- so the fix is the missing call in the one path that did not, rather
than a draw at the restore call site. At boot the rail is still held, where a
draw sets the skeleton and
releaseRailpaints the rows, so the other caller isunaffected.
Found while driving the merged archive flow end to end on a real host, after
#585, #589 and #596. It is the same shape as #596: server state correct, screen
stale until a reload.
Type
Verification
On a real host (
raven webon an isolatedRAVEN_HOMEbuilt from a realconfig, driven through the browser), reading the archived flag from the last
metadata record of the session transcript rather than from the page:
archived: trueon diskarchived: falseon disk, rail still does not show itCommands:
npm test --prefix ui-web-- 189 files, 2470 tests, all passnpm run lint --prefix ui-web-- 0 errors (4 pre-existing warnings inCronPage/SubagentsPage, untouched here)
npm run type-check --prefix ui-web-- cleannpm run --prefix ui-web build && python3 ui-web/build.py-- boot-snapshot OK(235 nodes match golden)
npx commitlint --from github/refactor/ui_web_architecture --to HEAD-- cleanThe new case,
a plain re-read draws the rows it just replaced, was run againstthe unfixed module first and fails there on the assertion it is named for.
Risk
One added call in a function with two callers; the other one runs while the rail
is held, where the draw is a no-op beyond the skeleton it already sets. No server
change, no stored state change. Rollback is reverting one commit.
Related Issues
N/A