- files tree records its scroll offset in a ref and commits it once on
unmount, only while the owner's signal is live, so a scroll neither
re-renders the tree nor writes to a forgotten bucket
- LoadingIndicator drops iconOnly and always renders icon-only
- registry and the unviewable list share one suffix-matching module, and
register() rejects binaryExtensions entries outside extensions
- drop the ambiguous key suffix from the unviewable office group
- extract the text preview's header path block shared by the unsupported
and content branches; clsx for static class joins; CSS trailing newline
- sync the preview-operations and polish Agent Notes with shipped facts
Both archive verbs answer with the complete set, so a reply that lands
after a newer request or after a pushed increment overwrote it. The
Client model now installs an answer only while it is still the latest
archive-set request, and the follow increment and baseline supersede it.
Also narrow the page's public surface and its states: the locale
namespace stays internal, row derivation is a memo over the framework
hooks, the search input carries one accessible name, the empty-archive
message no longer covers a set whose entries cannot be restored, and the
new package declares no client dependency edge it does not import.
Sessions could be archived from the sidebar row menu but never restored:
the registry-global archive set was a one-way display filter with no
inverse RPC and no surface listing its members.
WorkspaceRegistry.unarchiveSession drops one id from archivedSessionIds in
one durable write on the same operation chain as archive, with no
session-existence probe because a removal cannot introduce an unknown
referent. The Workspace controller exposes it as workspace.unarchiveSession
returning the complete archive set, which the existing archived follow
increment already propagates, so no frame type and no persisted field
changes.
The new client package dsh-client-ui-settings-unarchive-sessions owns the
restore surface: one localized settings.section page listing the archive
set joined with loaded session summaries, newest archive first, searchable
by title or workspace, with one Unarchive action per row.
The late-listener case now carries a pending generation change, so its
assertions depend on the disposed guard, and the silent-generation cases assert
their tick counts.