Baseline moves to DSH 0.1.5-alpha.2 only (peer floor ^0.1.5-alpha.2,
CI pin, manifest engines); alpha.1 users stay on v0.19.0-alpha.0.
Host-contract changes handled:
- the native guide entry lost its `description` field (entries are
icon+title capsules now): `TabDescriptor.description` and the six
`guideDesc*` keys plus the `nativeGuideDesc` fallback are removed.
- the file address grammar changed: `fileAddressFor` always returns a
session-scoped address (absolute paths keep their leading `/`),
`parseFileAddress` is prefix-based and strips `?`/`#`. The plugin's
purity-gated mirror follows.
- global main panels replaced the `conversation` root slot with the
keyed `main` slot (`main.conversation`): the bottom workbench's
center-column locator now accepts both keys and skips
`display: contents` slot hosts.
Fixes a pre-existing fill bug the alpha.2 probe made obvious: the native
tab body host is a block scroller with a definite height, so tab roots
that only declared `flex: 1` collapsed to content height and the side
chat composer drifted off the pane bottom. The native adapter now wraps
every tab body in a `height: 100%` column flex host.
Also promotes the dependencies `dsh-client-ui-primitives@0.1.5-alpha.2`
dropped from its manifest (anser / shiki / mdast-util-* / micromark-* /
katex / @shikijs/langs) and the newly unmet `dsh-session-persistence`
peer into devDependencies.
Phase 2 of the 0.1.5 adaptation: the plugin stops drawing its own right
panel and contributes tab TYPES to DSH's native right Sidebar, which owns
the right column. The bottom workbench (terminal dock) stays plugin-owned.
Registrations (src/client/native/):
- every TabDescriptor becomes a native tab type (kind = descriptor.id, the
default `extension` band) plus a keyed body in `sidebar.right.pane.tab`
and a live chip title in `sidebar.right.pane.tab.title`
- the `editor` type also claims `dsh-resource://file/**`, so it outranks
the built-in `text` preview (fallback) and every file the product opens
lands in the plugin's editor
- the built-in `files` page kind is TAKEN OVER by an extension
registration of the same kind: `openTab('files')` draws the plugin's
explorer, and the built-in resumes when the plugin unregisters
- registrations follow the plugin registry + the side-card settings: a
type registered later (external plugin) gets its native type too, a
disabled type is unregistered (absent from the guide, refuses opens)
Adapter (src/client/native/tab-adapter.tsx):
- one synthetic plugin `SidebarTab` per native tab id, minted from the
native record + navigation params (or the descriptor's own createTab,
which a native guide open bypasses), kept live across navigations and
updateTab writes
- the explorer's per-tab expansion/reveal sets and the per-kind instance
counter, which the plugin's own layout used to hold
Service routing (src/client/service.ts):
- `setSurface` installs the native write face; openTab/openFile land
natively (a path becomes a resource address, a path-less editor open
becomes the `files` page, the rest carry the seed as navigation params),
closeTab/updateTab/activateTab recognise native tab ids
- new optional `OpenTabSeed.target` ('right' default, 'bottom' keeps the
bottom workbench); the bottom panel's own + menu and auto-terminal pass
'bottom'
- src/client/native/surface.ts probes the controller's per-session writes
(`openTabIn`/`openResourceIn`/`closeIn`, not in `ISidebarRight`) and
queues opens for a session whose surface is not mounted yet
Right panel retired behaviourally (Phase 3 deletes the code): Sidebar
renders its bottom workbench only, keeps the panel collapsed, and hides
the right-panel toggle. The panel-specific e2e specs are removed; the
mount lane now drives the native guide (tab sweep), the plugin explorer
inside the native pane (editor/mermaid/README chunks) and the sidechat
host routes.
Verified: pnpm typecheck / lint / build / test (126 files, 1349 tests) /
check:consumer-types, plus pnpm test:mount against a real
@deepseek-ai/dsh@0.1.5-alpha.1 host (7/7).