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.
- A media-named FIFO or device node is refused before the open would
block on it (pre-open isFile check); POSIX FIFO regression test added.
- The full-body stream is bounded to the stat'ed size so concurrent
appends cannot exceed the declared Content-Length.
- Error responses carry no body for HEAD requests.
- Docs no longer overclaim the replacement race: the stat-identity
comparison narrows (does not fully close) the replacement window, and
the earlier realpath-to-stat window is acknowledged. Pairs re-recorded.
range-parser never validates the range unit, so /api/file now parses only
headers that start with the bytes unit: unsatisfiable ranges answer 416,
while malformed, unknown-unit, and multi-range headers are ignored for a
full 200 body per RFC 9110. The filesystem-root workspace case stays
POSIX-only in tests (a Windows drive-root spelling cannot be constructed
portably); containment already treats any separator-terminated root the
same. Docs (README pair, Agent Note pair) re-recorded.
- HEAD never opens a file stream; GET streams are destroyed on client
abort and are never opened for already-aborted requests.
- Validation and reading bind to the same opened file: pre-open and
opened stat identities are compared, so replacement/re-linking races
are refused (dev/ino check, read through the FileHandle).
- Workspace containment compares path components, so a filesystem-root
workspace serves files instead of doubling the separator.
- Multi-range headers are ignored for a full 200 body instead of a
mislabeled single-segment 206; single-range behavior unchanged.
- Tests now cover the reviewed edges (empty path, multi-range, root
workspace, HEAD+range, mid/early abort, unreadable file, explicit
unregister-on-dispose, private outside-target directories); module
coverage is back at 100/100/100/100.
- Agent Note bilingual facts and the ui-primitives/session-controller
README pairs are synced to the shipped behavior (pairs re-recorded).
- /api/file module now exports only the SessionMediaReferences plugin
contribution; MIME and range policy helpers are module-private and
exercised entirely through the registered route.
- Replace the hand-rolled media extension table with mime-types (served
categories image/video/audio, excluding image/svg+xml) and the
hand-rolled Range parser with range-parser; keep the fail-closed
workspace containment policy.
- Spec rewritten as route-level behavior tests (12 cases) covering the
same branches; Agent Note facts updated in the same change.
Drop the byte-signature sniff duplicated from fs/tool-fs's read_image tool:
the cross-file duplication gate forbids the clone, and no shared owner
exists without widening the attachment package's public API. The
extension allowlist keeps non-media content out; corrupt image payloads
fail in the browser, not on the route. Agent Note facts updated in the
same change.
Preserve the V3 PTC scenario while enabling the current subagent human-steering fixture environment. All product changes are inherited from master; no V3 migration semantics are altered.
* feat(subagent): align continuable human inbox controls
* fix: repair rebase documentation and close test persistence
* docs: refresh rebased module dependency graph
Assistant prose that references a workspace-contained local media path
(e.g. ``) now renders through a same-origin
`GET|HEAD /api/file?path=` route instead of inert alt text.
- ui-primitives: MarkdownText gains a settled-only MarkdownPathImages
vocabulary gate (same posture as file mentions); no vocabulary means
byte-identical output.
- ui-chat: AssistantMarkdown supplies a page-stable rewrite vocabulary
for absolute POSIX paths (local-path-media.ts).
- session-controller: SessionMediaReferences plugin contribution mounts
the route on the authenticated connection.fetch channel; per-request
policy = workspace-root containment after realpath, regular file,
allowlisted media extension (images additionally signature-checked),
range/HEAD streaming, private no-store + nosniff, fail-closed statuses.
- Agent Note added (feature/2026-09-07-session-prose-local-media-display).
Closes#3662.