A Host reload composes the new loader entries before the old ones are torn down, so the reloaded aggregate row asked for a package name the previous entry still held, its mount was dropped, and the previous entry then released the name with nobody left to take it: the row stayed listed as active with no degraded record and served no Host routes until a restart. The guard now queues the refused mount with its own context and replays it one microtask after the release, and a waiter whose fiber dies first is dropped instead of replayed. The Symbol.for registry keeps its Set shape because the satellite repositories compile their own copy of this guard.
The alpha.2 host import of npm undici costs Node built-in fetch its
content-encoding decompression. shared/host/http.ts now owns the rule as
withIdentityEncoding(init), and every host fetch that parses a remote body
adopts it: the market installer (manifest and assets), the plugin-manager
npm-registry probe, the remote-web-ui registry/GitHub probes and inner
app-shell fetch, and the usage provider probes.
- task-board: pick the newest SETTLED execution for session reuse; the
launch path appends this run's open record before the rule reads it
(#1587)
- plugin-manager: resolve the packaged desktop runtime's own lib/bin.js
and run it through the host interpreter when no PATH entry or .bin shim
exists (#1588)
- plugin cards: contribute to whichever plugin-card seat the host
declares (family list seat, else the official keyed settings.plugin.item
seat) and log a refused registration instead of swallowing it (#1589)
- usage: sidebar entry + collapsible panel over the same overview
document, with the family pairing fence on the host routes (#1592)
- usage: serve the zai route, key plan windows by the provider unit,
use the exact credit ratio, and skip TIME_LIMIT/unknown units (#1597)
- plugin-manager + remote-web-ui: accumulate child output as bytes and
decode once, so a Windows CP936 console renders readable text (#1600)
The DSH loader mounts every patch row as one transactional group: a single
plugin that fails to import or start rolls back the whole family and aborts
'dsh web'. Redefine the fault unit to one plugin.
- scripts/aggregate.mjs emits each family insert row with the aggregate's own
never-failing shell module as the row name and the real plugin package in
the row config (config.plugin, original config under config.config);
dsh-i18n and all external npm rows keep mounting directly
- @linxin666/dsh-web-all main entry is the shell: it imports the real module
at start time, contains import/shape/activation failures to that entry
(logged + recorded), and mounts the real plugin as a nested plugin so
cordis service scoping, lifecycle, and retraction semantics stay intact
- loopback-only GET /api/dsh-web-all/degraded reports the degradation ledger
for doctor/monitoring consumption
- shared/host/run-guarded.ts (+ synced copies in the four packages with
in-process HTTP/poll faces) converts fire-and-forget rejections into logged
errors against the host's installFailLoud whole-process exit
- tests: shell-isolation.spec.ts runs the real installed host boot through
start-failure / import-failure / no-webServer scenarios plus the control
case proving today's direct-mount shape still kills the boot
Evidence: pnpm typecheck, pnpm test (22 packages), pnpm docs:check,
pnpm i18n:check, pnpm aggregate:check, pnpm test:scripts (234), and full
pnpm build all pass. Bundle-layer change: needs a dsh web restart.
- dsh-web-all READMEs no longer claim the removed aionui-panel ships in
the aggregate; dsh-perf READMEs and renderDegrade copy stop advertising
the assistant-step shadow whose slot is gone upstream, and the orphaned
perf-assistant-shadow.tsx is deleted.
- pet and remote-web-ui notExposed copy adopts the corrected wording (the
dsh-host-apiproxy WEB_SETTINGS_NAMESPACES allowlist no longer exists).
- Dead libExternal entries for the deleted dsh-client-runtime are removed
(pet, git-graph, community-plugins), dead client-runtime mocks are
dropped (describe-image, remote-web-ui), skin-center's unused
api-workspace-controller inject is trimmed, and the mount e2e comment
matches the removal.
- shared/host/dsh-home.ts gains its final newline and the ten consumer
copies are resynced; leftover review debug output and stale aionui
comments are cleaned.
- Record the review evidence archive and the bug-fix Agent Note
(.agents/notes/implemented/bug-fix/2026-08-28-descriptor-faithful-wire-contracts).
Root pnpm typecheck failed: shared sources must not import
@deepseek-ai/cordis (no such dependency in the shared package). The
fence now reads a structural two-member context shape that cordis
Context satisfies; wrapper signatures and behavior are unchanged.
Git-graph, pet, and skill-explorer carried byte-identical fence logic.
The decision now lives in one shared source distributed as generated
sync-shared copies; each package keeps a self-describing thin wrapper.
Canonical tests added under shared/tests; wrapper specs stay as wiring
tests.
Dual-publish the final @linxin666/dsh-web-ui-all for the two-release transition window, then stop automatically. Plugin-manager recognizes the legacy aggregate and performs a transactional CLI migration. Doctor introduces autoMigrate (default true) and migrates before DSH launch, preserving bundle order and verifying --dump-config before boot. Add compatibility audit gates, Agent Notes, and isolation evidence.
Display and source layers rename to dsh-web: GitHub slug, docs and prose,
aggregate package dir packages/dsh-web-all with npm name
@linxin666/dsh-web-all, settings package dir packages/dsh-web-settings,
private shared package dsh-web-shared, repo-local skill dirs, and the
docs banner asset.
Runtime, wire, and storage identifiers are frozen byte-identical so
installed profiles keep resolving with zero migration: web-ui-* bundle
ids, the dsh-web-ui-market settings section id, /api/dsh-web-ui-settings
and its proxy-token header, and the dsh-web-ui-telemetry-* storage keys.
Frozen history (docs/archive, docs/release-notes, archived notes), the
JAVA-LW fork reference, and local filesystem paths keep the old name.
npm migration: the next tag release dual-publishes @linxin666/dsh-web-all
alongside the final @linxin666/dsh-web-ui-all version, then the old name
is deprecated with a pointer; dual-publish lasts two releases.
Decision record: .agents/notes/implemented/architecture/2026-08-24-product-rename-dsh-web.md
Aggregate generator now rewrites child row ids to web-ui-* (stripping the
ui- prefix) and validates uniqueness, so installing the family bundle next
to a standalone plugin no longer trips the loader's duplicate-entry check.
A shared shared/host/mount-once.ts module (sync-shared synced into 12 family
packages) makes the host apply a no-op when the same plugin loads twice;
browser half is deduped by package name. Docs synced: root README FAQ,
web-ui-all README trio, plugins.md, packages/AGENTS.md; regenerated
dsh-skins and dsh-web-ui-all patches and skin-center lib; archived the
verification snapshot in docs/archive.
shared/host/poll-guard.ts is a bounded, non-overlapping, backoff-capped
poll loop; shared/host/dsh-home.ts centralizes DSH_HOME resolution. Both
carry unit tests in the shared package. The sync-shared manifest now
mirrors poll-guard into git-graph and aionui-panel and dsh-home into pet
and liangshen; adoption wiring lands with each package's lane.