The frame carried `agentPreset` for surfaces that label the session, but
nothing consumed it: `noteAgentPreset` ran only in the switching tab's RPC
callback, so a second connected client refetched its catalogs while its
session row — the header label's source, and the hero chip's no-op input —
kept the composition the session had replaced.
`SessionManager.handleHostEnvelope` now folds the frame like the other
session frames. Re-applying the switching tab's own frame is a no-op: the
merge lowers `blank` only and keeps the row's `updatedAt`.
Presets own the rows that decide what a session's `/` menu contains, but
both browser catalogs cache per session and had no invalidation edge for a
recompose: `commands/changed` is registry-wide and recomposing registers
nothing, so the menu kept serving the composition the session no longer ran.
The host stream now frames the logged `agent-preset/selected` commit as
`host/session-preset-changed`; the runtime bridges it to the typed
`session/preset-changed` event, `ui-command` soft-refreshes that session's
directory key and `ui-skill` invalidates its catalog entry.
Reaching the host on a second switch was a separate defect: the list-row
identity guard compared every summary field except `agentPreset`, and the
merge keeps the row's `updatedAt`, so a switched row looked unchanged and
served its cached instance forever. The hero chip compares the pick against
that row, so switching back to the creation-time preset sent no RPC at all.
The SVG media query alone fixes the dark-mode icon for every SVG-capable
browser (Chrome, Edge, Firefox, Safari 26+); the PNG only served Safari
versions before 26, which is a shrinking legacy audience not worth a second
asset, its manifest/link declarations, and the extra test surface. index.html
and the manifest are back to the single SVG icon.
The pwa-manifest e2e now asserts the shipped 32x32 PNG is a valid non-empty
PNG of the declared dimensions, that the PNG link precedes the SVG link in
the built index.html (the spec selects the last equally appropriate icon),
and that the light fill lives inside the dark-scheme media query while the
light-mode default stays black.
favicon.svg embeds @media (prefers-color-scheme: dark) so the DeepSeek
mark turns white under a dark browser scheme; index.html and the install
manifest gain a 32x32 PNG fallback (brand blue) for Safari, which cannot
render SVG favicons. pwa-manifest.e2e.ts pins the PNG link, both manifest
icons, and the dark media query.
The mid golden was racing the reasoning block's stream: captureStableAria
could freeze on the pre-render gap between steering acceptance and the
assistant step, pinning a snapshot without the Think row. Wait for the
[data-variant=think] row so the golden captures the complete assistant step.
Steering bubbles render as plain user bubbles; a mid-turn steer is
recognizable by its position in the flow. The runtime SteeringMessageNode
projection and pending-steering lifecycle are unchanged.
Partially supersedes the 2026-08-04 context-source and steer marks note;
the new simplification note owns the removal rationale.
The persistence catalog recognizes SessionEventMap augmentations of
'@deepseek-ai/dsh-session/types' alone, so the selected event's old
root-specifier declaration compiled but silently vanished from the
generated catalog. The hermetic scaffold e2e still addressed the skill
registry as a preset-realm service; under the layered host registry the
composed agent's view is a scope read, and the ambient-root isolation it
proves is unchanged.
The suite composes over the ambient DSH home, so a fixed session id
collides with the log a previous run persisted once the tool-execution
path checks persisted identity.
The shipped-Web e2e enables the bundled badge skill as a stand-in for a
repository plugin's deployment-level provider and asserts the layering both
ways: a standard-preset agent's view merges the global layer with its
preset's local discovery and its loader tool resolves the global skill,
while the host view stays global-only and a core-web agent can read the
layer but composes no loader tool.
This reverts commit f12c131ee9fdbc01b9294c8dc2c73cd36ab717cf.
The layered host skill registry closes the gap the bypass recorded: a
repository plugin's skill root registers into the global layer and reaches
every preset-composed session's catalog, so the fixture declares its skill
root again and the e2e proves the full skill, MCP, and TypeScript
contribution set. The accidental .claude/launch.json from that commit goes
with it.