dsh-code-server-app 0.3.69 → 0.3.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -19,15 +19,18 @@ A static profile plugin (npm package with host + client bundle) that ships the *
19
19
  > uses), so typography, highlighting and math match the UI and a renderer version mismatch is impossible.
20
20
  > There is **no build step anywhere on that chain**. See "Working with DSH: the editor bridge".
21
21
 
22
- ## UI carrier and required DSH version (0.2.3: right-sidebar DSH only)
22
+ ## UI carrier and required DSH version (0.2.3: right-sidebar DSH only; converged 2026-10-01 to one generation, ≥ 0.2.0-rc.2)
23
23
 
24
- Every verdict is a **capability probe**, never a version comparison. The two lines differ in two independent
25
- places: the **right-sidebar session scope** (`sessionId` standard prop ↔ the snapshot's `current`, see
26
- "Workspace") and the **settings surface** (seat × data channel, see the "Settings" section):
24
+ Every verdict is a **capability probe**, never a version comparison. Exactly **one generation** is supported:
25
+ **DSH ≥ 0.2.0-rc.2** (web and desktop are the same generation — both UIs have moved to 0.2.0-rc.2). The
26
+ compatibility branches written for the rc line `0.1.5-rc.x` and the alpha line
27
+ `0.1.6-alpha.2…0.1.7-rc.x` have been **deleted**: the old seat `settings.plugin.item`, the old data channel
28
+ `settingsScope`, the session-list snapshot's `current` fallback and the `recentWorkspaceId` fallback are all
29
+ gone (see "Settings" and "Legacy DSH"):
27
30
 
28
31
  | DSH version | Carrier | Entry points |
29
32
  |---|---|---|
30
- | **rc line** `0.1.5-rc.x` (latest `0.1.5-rc.3` = npm `latest`/`next`)**and alpha line** `>= 0.1.6-alpha.2` (latest `0.1.7-alpha.1`) — detected by the presence of `sidebarRight` / `sidebarRightTabs`, never by version comparison | **Right-sidebar tab** (kind `code-server`, chip `Code Server`), which also **claims file addresses** (see below) | ① DSH's own **produced-file chips / presented-file card previews / inline file names in prose** (since 0.2.5, via the official `openFile` → file address → this tab); ② the **Code Server box** on the sidebar's guide ("开始") page; ③ the settings block (location per "Settings") → **"Open in right sidebar"** |
33
+ | **≥ 0.2.0-rc.2** (web and desktop are the same generation) — detected by the presence of `sidebarRight` / `sidebarRightTabs`, never by version comparison | **Right-sidebar tab** (kind `code-server`, chip `Code Server`), which also **claims file addresses** (see below) | ① DSH's own **produced-file chips / presented-file card previews / inline file names in prose** (since 0.2.5, via the official `openFile` → file address → this tab); ② the **Code Server box** on the sidebar's guide ("开始") page; ③ the settings block (location per "Settings") → **"Open in right sidebar"** |
31
34
  | older (no sidebar service) | **Unsupported**: nothing but one notice in the settings block | none (the settings block shows an upgrade notice) |
32
35
 
33
36
  - Detection: first a synchronous `ctx.get('sidebarRightTabs') / ctx.get('sidebarRight')` probe; because the services may come up after this plugin, `ctx.inject(['sidebarRightTabs','sidebarRight'], …)` is awaited and a **2.5 s timeout marks the DSH as legacy** (no version comparison, and the plugin's own activation is never blocked).
@@ -38,7 +41,7 @@ places: the **right-sidebar session scope** (`sessionId` standard prop ↔ the s
38
41
  - services arriving late automatically revoke the legacy verdict, register the sidebar, and report `{sidebar:true}` so the host re-enables;
39
42
  - a failed registration is no longer silent: it logs an error and the card's entry row says "right-sidebar services were found but the tab could not be registered".
40
43
  - **0.2.3 dropped legacy-DSH compatibility**: the floating ball and the internal floating window are **deleted**. When the DSH is detected as legacy the plugin
41
- - registers only the settings notice (seat per "Settings") — no ball, no floating window, **no file-address claim**, no IDE preload;
44
+ - registers only the settings notice (location per "Settings") — no ball, no floating window, **no file-address claim**, no IDE preload;
42
45
  - reports `/api/code-server/ui-mode { sidebar:false }` to the host (after the 10 s grace above); the host then **recycles an instance it auto-prestarted** and stops prestarting (a user-started/adopted instance is never touched), and `{sidebar:true}` reverses that if the services show up later;
43
46
  - upgrading DSH needs **no reinstall** — refresh the page and the notice turns back into the full settings form.
44
47
  - The sidebar tab hosts the code-server page (iframe) and follows the current session workspace; the panel can be collapsed/split/floated/fullscreened by DSH's right sidebar.
@@ -463,31 +466,39 @@ data call changes; the caller stays as it is).
463
466
 
464
467
  ## Legacy DSH (unsupported since 0.2.3)
465
468
 
466
- **Behaviour**: when `sidebarRightTabs` / `sidebarRight` cannot be found, the plugin registers a single settings card:
469
+ **Behaviour**: when `sidebarRightTabs` / `sidebarRight` cannot be found, the plugin registers a single settings notice (location per "Settings"):
467
470
 
468
471
  > **Code Server** — this DSH version is unsupported (no right-sidebar service)
469
472
  > Since 0.2.3 this plugin no longer supports older DSH versions.
470
473
  > The right-sidebar plugin services `sidebarRightTabs` / `sidebarRight` were not detected, so the plugin exposes no
471
474
  > entry point at all (the old floating ball and floating window have been removed) and will not start the IDE in the
472
- > background. Upgrade DSH to the rc line (0.1.5-rc.x) or the alpha line from 0.1.6-alpha.2 on: Code Server then appears as a
475
+ > background. Upgrade DSH to 0.2.0-rc.2 or newer: Code Server then appears as a
473
476
  > right-sidebar tab, this page shows the full settings again, and no reinstall is needed — a page refresh is enough.
474
477
 
478
+ - **Where the notice lives**: it is a read-only block on the only settings seat (`plugins.bundle.config`,
479
+ driven by the `configForms` channel); an old-generation DSH has neither, so on those deployments all that is
480
+ left is the console warning `[code-server] 未探测到右侧栏服务…`. Behaviour is unchanged: **no IDE start,
481
+ no entry point at all**.
475
482
  - **No other UI**: no `shell.overlay` registration (floating ball), no file-address claim, no resident preload.
476
483
  - **Host side**: the client posts `/api/code-server/ui-mode { sidebar:false }`; the host then ① stops auto-prestarting
477
484
  the IDE (`maybePrestart` returns immediately) and ② **recycles** an instance it had just auto-prestarted (unless it
478
485
  was adopted), so no unusable IDE process or port is left behind. A user-started/adopted instance is never stopped.
479
486
  - **Why delete instead of keeping**: the internal floating window was a stopgap from the era of early-2026 DSH builds
480
487
  without right-sidebar services. The resident surface, clipboard handling, shortcuts and panel collapsing all build on
481
- DSH's right sidebar, so maintaining two carriers costs more than it is worth. Older-DSH users should stay on `0.2.2`
482
- (`dsh plugin --profile web add dsh-code-server-app@0.2.2`).
488
+ DSH's right sidebar, so maintaining two carriers costs more than it is worth. The old-generation compatibility
489
+ branches (the rc / alpha lines' seats, channels and the `current` fallback) were deleted on 2026-10-01 as well —
490
+ **users who still need an old-generation DSH (≤ 0.1.7-rc.x) should pin `dsh-code-server-app@0.3.69`**
491
+ (`dsh plugin --profile web add dsh-code-server-app@0.3.69`), the last version that still carries those branches.
492
+ - **Rollback**: for an old-generation DSH, drop to `0.3.69`
493
+ (`dsh plugin --profile web add dsh-code-server-app@0.3.69`); on a 0.2-generation DSH no rollback is needed.
483
494
 
484
495
  ## code-server workspace and process lifecycle
485
496
 
486
497
  - code-server's workspace **follows the active DSH session/workspace**: switching sessions/workspaces while the IDE is open moves code-server to the new directory
487
498
  (resolution order: current session cwd → session's `workspace.path` → workspace of the most recently active session → first workspace.path;
488
- **where "the current session" comes from depends on the DSH version**: the alpha line (≥ 0.1.6-alpha.2) reads the session-scoped standard prop `sessionId`,
489
- the rc line (≤ 0.1.5-rc.3) falls back to `current` on the session-list snapshot — see the 0.3.48 bullet below; the logic is inlined in `lib/client.js`
490
- (the "workspace resolution" section) and the contract for both shapes is pinned by `scripts/test-client-bundle-cwd.mjs` directly against the entry file);
499
+ **there is only one source for "the current session"**: the session-scoped standard prop `sessionId` (this 0.2 generation;
500
+ the session-list snapshot's `current` fallback used by the old rc line has been deleted with the old-generation branches) — see the 0.3.48 bullet below; the logic is inlined in `lib/client.js`
501
+ (the "workspace resolution" section) and the contract is pinned by `scripts/test-client-bundle-cwd.mjs` directly against the entry file);
491
502
  the opened directory is shown inside code-server (`?folder=<cwd>`, the page reloads when following a switch);
492
503
  implementation note: the iframe `src` must carry `?folder=<cwd>` — code-server's front-end remembers the "last workspace" and restores it by itself;
493
504
  a bare root URL only shows the previously opened directory and does not follow switches (verified locally).
@@ -500,8 +511,9 @@ data call changes; the caller stays as it is).
500
511
  to the host, and the IDE started with an **empty workspace** (measured locally: `cwd`/`launchCwd` both empty in
501
512
  `$DSH_HOME/code-server/pid.json`, with nothing visible in the UI). Since 0.3.48 it reads the session-scoped standard prop
502
513
  `sessionId` (the same source DSH's own right-sidebar tab uses — `ui-deliverables`' ReviewTab does
503
- `useSessions(s => s.byId[sessionId]?.cwd)`), keeping the old `current` as a backward-compatible fallback; when neither
504
- source resolves, it **does not guess a directory** (no cwd is sent, the workbench keeps its current one) and logs a
514
+ `useSessions(s => s.byId[sessionId]?.cwd)`); **the old-generation `current` fallback was deleted with the
515
+ old-generation branches** (2026-10-01), and when the source does not resolve it **does not guess a directory**
516
+ (no cwd is sent, the workbench keeps its current one) and logs a
505
517
  `[code-server] 未能解析当前工作区目录…` warning — the silence is exactly what made this bug hard to find.
506
518
  - **The switch is lightweight (since 0.2.12)**: a running instance is **not restarted** when the workspace changes — the host
507
519
  only updates `state.cwd` and the workbench re-navigates with the new `?folder=` (the workspace directory was always the
@@ -580,12 +592,72 @@ pnpm run promote -- <version>
580
592
  | **Publish the plugin itself** | `pnpm run publish:plugin` (publishes the exact tarball that was verified; no re-packing; default dist-tag `next`) |
581
593
  | **Promote `latest`** | `pnpm run promote -- <version>` (only after the user restarted and confirmed; `--dry-run` shows the current tags first) |
582
594
  | **Just report versions** | `pnpm run vendor:check` |
595
+ | **Watch for upstream releases** | `pnpm run watch:upstream` (local watchdog: watches only `code-server`'s `latest` on npm and raises a Windows notification plus the upgrade chain when it moves; see the next section) |
583
596
 
584
- > `pnpm pack`'s `prepack` runs the vendor-code-server script once; when `vendor/code-server` already exists it is
597
+ > `pnpm pack`'s `prepack` runs the vendor-vscode-server script once; when `vendor/vscode` already exists it is
585
598
  > a **no-op that takes seconds**, so after ordinary code changes you can just run `pnpm pack` (it will never
586
599
  > silently upgrade code-server). Upgrading code-server requires an explicit `pnpm run vendor:latest`
587
600
  > (or `--force` / `--version`) **plus** republishing the sub-packages.
588
601
 
602
+ ### Upstream update monitoring (a local automation task)
603
+
604
+ The **start** of the upgrade chain is an upstream release — and nothing currently looks for one: all three
605
+ workflows are push/PR/manual (**there is no `schedule` anywhere**), and the `vendor:check` step inside CI is
606
+ `continue-on-error`. So "upstream shipped a release weeks ago while the bundled tree still sits on the previous
607
+ one" is completely invisible inside an all-green run. `scripts/watch-upstream.mjs` closes exactly that gap.
608
+
609
+ ```powershell
610
+ node scripts/watch-upstream.mjs # one check; on a new version → report + Windows notification; otherwise one line
611
+ pnpm run watch:upstream # same, but first goes through pnpm's dependency pre-flight (see the note below)
612
+ node scripts/watch-upstream.mjs --json # machine readable (what a DSH in-session reminder parses); human output goes to stderr
613
+ node scripts/watch-upstream.mjs --no-notify # report only, no notification (regressions / unattended)
614
+ node scripts/watch-upstream.mjs --fixture f.json # use a local JSON file as the registry response (offline)
615
+ node scripts/watch-upstream.mjs --local 4.140.0 # override the local baseline for a dry run (does not read vendor/)
616
+ node scripts/test-upstream-watch.mjs # regression suite (offline, never notifies)
617
+ ```
618
+
619
+ > **Why the docs lead with `node scripts/…` rather than `pnpm run …`**: `pnpm run` performs a dependency
620
+ > status pre-flight first and runs `pnpm install` whenever things are out of sync. **Mid-upgrade that is
621
+ > guaranteed to bite**: `package.json` pins the new `@jinsiyu/dshcs-vscode-server@<new version>` first, but
622
+ > that version does not exist until `pnpm run publish:repacks` has run — and in the meantime `pnpm run` /
623
+ > `pnpm test` fail right there with `ERR_PNPM_NO_MATCHING_VERSION`, never reaching the script (hit for real
624
+ > while upgrading to 4.139.1 on 2026-09-30: the registry only had 4.136.2 / 4.137.0 / 4.138.0 then).
625
+ > The watchdog must not be blocked by the state of the release flow, so the scheduled reminder invokes node
626
+ > directly; the two forms are equivalent once dependencies are in sync.
627
+
628
+ | Exit code | Meaning |
629
+ |---|---|
630
+ | `0` | Check succeeded — **a new upstream version is still success** (this reports, it does not gate) |
631
+ | `1` | Check failed (network down / bad registry response / no local baseline). **Strictly distinct from "no update"** |
632
+ | `2` | A new version exists *and* `--fail-on-update` was given (only if you want it as a gate) |
633
+
634
+ Signal scope (**upstream version only**, deliberately narrow): `registry.npmjs.org/code-server/latest` against the
635
+ local baseline, which falls back in three steps — `vendor/VENDOR.json` → `vendor/vscode/package.json` → the
636
+ `@jinsiyu/dshcs-vscode-server` pin in `package.json` (a fresh CI clone has no `vendor/`, so it takes the third).
637
+ It does **not** look at `@jinsiyu/*` sub-package drift, and does **not** decide whether *our* repack of the new
638
+ version has been published — that belongs to the upgrade flow itself.
639
+
640
+ Notifications go to the **Windows Action Center** (a system notification, not a popup window):
641
+
642
+ - Signed as **`dsh-code-server-app 上游监控`**. On first use it writes a `DisplayName` under
643
+ `HKCU\SOFTWARE\Classes\AppUserModelId\dsh-code-server-app.UpstreamWatch` — the script's **only system side
644
+ effect**; disable it with `--no-register-notify-id`, and deleting that key undoes it completely.
645
+ - **Delivery is verified**: right after showing the toast it reads the notification history back with
646
+ `History.GetHistory($AppId)`, so the report states *delivered* as evidence rather than "the command did not
647
+ error, so it probably went out". If the lookup misses, it says so plainly.
648
+ (Gotcha we hit: the **parameterless** `GetHistory()` overload resolves the *calling process's own* AUMID, so
649
+ inside `powershell.exe` it always fails with `0x80070490 ELEMENT_NOT_FOUND` — do not be misled by it.)
650
+ - **Throttling**: each upstream version notifies once; after 7 days without an upgrade it reminds again (so
651
+ "we notified once" never decays into "never again"). State lives in `.upstream-watch.json` (gitignored).
652
+ State is recorded **only after a notification actually goes out** — a routine `--no-notify` run must not consume
653
+ the slot, or that version would never be announced at all, which is the "silent miss" failure mode.
654
+ - **Transient network errors are retried** (3 attempts with backoff) so an occasional `ECONNRESET` is not reported
655
+ as a check failure; false alarms are what make people stop reading reminders.
656
+
657
+ It also works as a DSH in-session reminder: when the reminder fires, run `pnpm run watch:upstream`, paste the
658
+ report if there is an update, and answer with a single line if there is not.
659
+
660
+
589
661
  ## GitHub Actions (CI + tag-triggered release)
590
662
 
591
663
  Both workflows live in `.github/workflows/`, and the regression list exists exactly once
@@ -695,13 +767,13 @@ pnpm test:bridge-extension # extension-side pure logic (dirty buffers, diagnos
695
767
  pnpm test:ask-dialog # ask-dialog wiring: no artifacts/build chain left, the host's four ask routes, the extension only reporting editor state, the four approval constraints, the bridge's safety invariants
696
768
  pnpm test:launcher-routes # launcher HTTP surface (spawns a real process; slow)
697
769
  pnpm test:workspace-switch # switching workspaces does not restart the process
698
- pnpm test:workspace-cwd # "current workspace directory" resolution (alpha line: sessionId vs. rc line: the snapshot's current)
770
+ pnpm test:workspace-cwd # "current workspace directory" resolution: the session-scoped standard prop `sessionId` is the only shape (the old rc line's snapshot `current` fallback is gone)
699
771
  pnpm test:client-cwd # the same contract, but asserted against the **client entry** lib/client.js
700
772
  pnpm test:client-tabs # "one code-server tab on the DSH side": a new tab closes the old one in the same pane
701
773
  pnpm test:client-entry # client-entry guard: classic script + factory wrapper, require whitelist, src/ gone, parity with lib/claim-types.js
702
- pnpm test:apply # apply() under a stub ctx (ReferenceError regressions) + both settings data lines: the new one reads volatile leaves and follows settings/document-updated, the legacy one registers a **non-volatile** schema and subscribes scope.watch
703
- pnpm test:client-seat # settings **seat × data channel**: seat (plugin page plugins.bundle.config ≥ 0.1.6-alpha.2 / settings page settings.plugin.item ≤ 0.1.5-rc.3) × channel (configForms ≥ 0.1.7-alpha.1 / settingsScope earlier)
704
- # all eight combinations must apply (injection guard) + behaviour for the three real ones: the new line has **mutate** as its only write path, registration is gated by whileServed, the rc line still uses the old seat
774
+ pnpm test:apply # apply() under a stub ctx (ReferenceError regressions) + the settings data plane: volatile leaves are read and settings/document-updated is followed (the legacy line that registered a schema and subscribed scope.watch is gone)
775
+ pnpm test:client-seat # settings surface (**one seat** `plugins.bundle.config` + **one channel** `configForms`): seat declared × channel present/absent — all 4 combinations must apply (injection guard)
776
+ # the only write path is mutate and registration is gated by whileServed, plus **anti-assertions**: the old seat `settings.plugin.item` / old channel `settingsScope` must not come back, and a missing channel must leave the sidebar tab and the resident preload untouched
705
777
  pnpm test:fullscreen # opening the tab goes fullscreen
706
778
  pnpm test:vendored # repack table ↔ plugin dependency table (no npm: aliases, no aggregator)
707
779
  pnpm test:installed # install smoke: assert on what was **installed into a profile**
@@ -859,8 +931,8 @@ The main package is only **~110KB** (the plugin's own code plus the launcher); e
859
931
 
860
932
  - **the VS Code tree** (`lib/vscode` 196.9MB + `out/browser` + `src/browser`) is a **platform-independent package**
861
933
  `@jinsiyu/dshcs-vscode-server@<code-server version>` declared in the plugin's `dependencies`; it runs from
862
- `<profile>\node_modules\@jinsiyu\dshcs-vscode-server\vscode` (the legacy full tree at
863
- `@jinsiyu/dshcs-code-server/code-server` is still recognised as a fallback);
934
+ `<profile>\node_modules\@jinsiyu\dshcs-vscode-server\vscode` (the old full tree at
935
+ `@jinsiyu/dshcs-code-server/code-server` and the 0.1.37 platform sub-packages are **no longer recognised**);
864
936
  - the **pure-JS part** of VS Code's inner dependencies (35 packages: xterm / katex / typescript / ws / tar …) is
865
937
  declared in the plugin's `dependencies` and installed by pnpm into the profile's `node_modules` (hoisted);
866
938
  - the **binary part** comes entirely from `@jinsiyu/dshcs-*` sub-packages, declared **directly on the plugin's own
@@ -904,7 +976,8 @@ The main package is only **~110KB** (the plugin's own code plus the launcher); e
904
976
  - **resolution path**: the host finds the tree with `require.resolve('@jinsiyu/dshcs-vscode-server/package.json')`
905
977
  (then the inner `vscode/` directory) and the entry is `vscode/lib/vscode/out/server-main.js`; VS Code's inner deps are
906
978
  resolved upwards from that root (`vscode/lib/vscode/node_modules` → package `node_modules` → `<profile>/node_modules`).
907
- The legacy full tree (`@jinsiyu/dshcs-code-server/code-server`) is still recognised as a fallback;
979
+ The old full tree (`@jinsiyu/dshcs-code-server`) and the in-package `vendor/code-server` are **no longer
980
+ recognised as fallbacks** — they were deleted with the old-generation branches;
908
981
  - **runtime layout self-healing** (`ensureRuntimeLayout()` in `lib/native.js`, idempotent, run **at activation before
909
982
  `envCheck` and again before every start**): the host adds two kinds of **junctions** (Windows junctions / POSIX dir
910
983
  symlinks) into the tree:
@@ -919,11 +992,27 @@ The main package is only **~110KB** (the plugin's own code plus the launcher); e
919
992
  > **Size note**: the plugin tarball is **~110KB**; `@jinsiyu/dshcs-vscode-server` is **~60MB** (~197MB unpacked);
920
993
  > the 16 native packages add ~250MB. A full install downloads roughly 310MB. Neither `vendor/` nor `repack/` is committed to git (see `.gitignore`).
921
994
 
922
- > **Upgrading from ≤ 0.1.43**: the tree package changed from `@jinsiyu/dshcs-code-server` (the full code-server tree with
923
- > `out/node` and 136 runtime deps) to `@jinsiyu/dshcs-vscode-server` (the trimmed tree). **The new code defaults to
924
- > `serve: loopback`, which behaves exactly like 0.1.43**; switch to `serve: dsh` for same-origin mounting. The install
925
- > command is unchanged (`dsh plugin --profile web add dsh-code-server-app@<version>`), and pnpm drops the old
926
- > `dshcs-code-server` sub-package.
995
+ > **Upgrading from ≤ 0.1.43**: the tree package used to be `@jinsiyu/dshcs-code-server` (the full code-server tree with
996
+ > `out/node` and 136 runtime deps) and is now `@jinsiyu/dshcs-vscode-server` (the trimmed tree); **the old package name
997
+ > and the old platform sub-packages are no longer recognised as fallbacks** — only the current layout remains (see
998
+ > "Tree and install-location resolution"). The install command is unchanged
999
+ > (`dsh plugin --profile web add dsh-code-server-app@<version>`), and pnpm drops the old
1000
+ > `dshcs-code-server` sub-package. The current version still defaults to `serve: loopback` (equivalent to 0.1.43);
1001
+ > switch to `serve: dsh` for same-origin mounting.
1002
+
1003
+ > **Upgrading from ≤ 0.1.35**: the old install root `<profile>\.code-server-app` (~1.4GB of inner dependencies) and the
1004
+ > "Install environment" step are both unnecessary — and that probing was **deleted with the old-generation branches**:
1005
+ > the plugin no longer detects the directory and no longer logs a "safe to delete" hint, so leaving it in place is
1006
+ > harmless. To clean it up, run
1007
+ > `Remove-Item -Recurse -Force <profile>\.code-server-app`. Old entries such as `dsh-code-server-app: false` left in
1008
+ > the profile's `pnpm-workspace.yaml` can go too (the current version needs no build approvals at all).
1009
+
1010
+ > **Uninstall**: `dsh plugin --profile web remove dsh-code-server-app` is enough; the tree package and the native
1011
+ > packages are separate dependencies, so for a full cleanup also remove `@jinsiyu/dshcs-vscode-server`
1012
+ > (or `pnpm remove` it inside the profile). Only a profile that was upgraded from ≤ 0.1.43 can still carry the old
1013
+ > tree package `@jinsiyu/dshcs-code-server` and the old install root `<profile>\.code-server-app` — delete those by
1014
+ > hand (the plugin no longer recognises them).
1015
+
927
1016
  ### Why the client half has no build step (since 0.3.58)
928
1017
 
929
1018
  **`lib/client.js` *is* the source** — hand-written, committed, not minified. What was removed: `src/**`
@@ -984,8 +1073,9 @@ and `pnpm test:ask-dialog` (the wiring, plus "not one trace of the build chain m
984
1073
  dsh plugin --profile web add C:\Users\User\Desktop\dsh-code-server-app
985
1074
  ```
986
1075
 
987
- > A source path installs via `link:`. On a dev machine without `vendor/code-server`, run
988
- > `pnpm run vendor:vscode -- --dev-links` first. Dependencies (inner JS deps + the platform aggregator) are installed by pnpm
1076
+ > A source path installs via `link:`. On a dev machine without `vendor/vscode`, run
1077
+ > `pnpm run vendor:vscode -- --dev-links` first (the old-generation fallback to an in-package
1078
+ > `vendor/code-server` is **gone**, so `vendor/vscode` must exist). Dependencies (inner JS deps + the platform aggregator) are installed by pnpm
989
1079
  > too — but the not-yet-published local `@jinsiyu/*` packages must either be published first, or the
990
1080
  > `repack/tgz/*.tgz` files must be installed into the profile as `file:` dependencies.
991
1081
  >
@@ -1059,37 +1149,38 @@ dsh plugin --profile web add C:\Users\User\Desktop\dsh-code-server-app
1059
1149
  - **No runtime auto-upgrade anymore**: nothing fetches latest at startup; the version is fully determined by the bundled artifact.
1060
1150
  - Bundled locally right now: the tree of `code-server@4.139.1` (VS Code 1.139.1, `productPath=stable-53c2f325…`).
1061
1151
 
1062
- ### Compatibility with the old install locations
1152
+ ### Tree and install-location resolution
1063
1153
 
1064
- Host probe order: `@jinsiyu/dshcs-vscode-server/vscode` (**the real layout since 0.2.0**) >
1065
- `@jinsiyu/dshcs-code-server/code-server` (the full tree, 0.1.40–0.1.43) >
1066
- `@jinsiyu/dshcs-code-server-<platform>-<arch>/code-server` (the 0.1.37 platform sub-packages) >
1067
- the in-package `vendor/vscode` > the in-package `vendor/code-server` (development). The old install root
1068
- `<profile>\.code-server-app` is only mentioned in a startup log line; nothing writes to it any more.
1069
- ## Settings (since 0.3.50: the plugin page; earlier: Settings → Plugins → Code Server)
1154
+ **Only two candidates remain** (since 2026-10-01): `@jinsiyu/dshcs-vscode-server/vscode` (**the real layout since
1155
+ 0.2.0**) > the in-package `vendor/vscode` (development). The old-generation fallbacks —
1156
+ `@jinsiyu/dshcs-code-server/code-server` (the full tree, 0.1.40–0.1.43),
1157
+ `@jinsiyu/dshcs-code-server-<platform>-<arch>/code-server` (the 0.1.37 platform sub-packages) and the in-package
1158
+ `vendor/code-server` — plus the old install root `<profile>\.code-server-app` (probing and the "safe to delete" log
1159
+ line alike) are **all deleted**: if the current layout is missing, startup fails instead of silently landing on an
1160
+ old directory.
1070
1161
 
1071
- The settings surface is decided by **two independent axes** — the **seat** (where the UI is drawn) and the
1072
- **data channel** (where values are read from and written to). Their break points are **not the same release**,
1073
- so three real combinations must all work:
1162
+ ## Settings (since 0.3.50: the plugin page)
1074
1163
 
1075
- | DSH | Seat (declaration-driven: `slots.inject` only fires for a declared slot, so both legs are registered) | Data channel (capability probe) |
1076
- |---|---|---|
1077
- | **rc line ≤ 0.1.5-rc.3** (latest rc is still this one) | `settings.plugin.item` (key `code-server`) — the self-drawn collapsible card in Settings → Plugins → Code Server | `ctx.settingsScope` (namespace `code-server`), per-field `set/unset` |
1078
- | **0.1.6-alpha.2** | `plugins.bundle.config`, **key = package name** `dsh-code-server-app` — plugin page → `dsh-code-server-app` → the settings block sits **between the description and the rows** | same as above (`settingsScope` still exists in this release) |
1079
- | **alpha line ≥ 0.1.7-alpha.1** (latest 0.1.7-alpha.1) | as above (the page draws title/icon/crumb itself; we only render the form + save control) | `ctx.configForms.get('code-server')` — the configuration **is the plugin entry's own `Config`**, and the only write path is one atomic `mutate(ops, revision)` |
1080
-
1081
- > Why both legs stay: `settings.plugin.item` retired in ≥ 0.1.6-alpha.2 (the plugin page only renders that
1082
- > block when `ledger.bundles.has(packageName)` — a wrong key or the old seat makes the settings block
1083
- > **silently disappear**), while `settingsScope` was **deleted in 0.1.7-alpha.1** (renamed/re-modelled to
1084
- > `configForms`). Declaring such a service in the client `inject` costs even more: the entry stays **pending
1085
- > forever**, and the right-sidebar tab, the settings block and the resident preload **all vanish together**,
1086
- > leaving only `web boot: 1 entry did not activate` / `pending (waiting for service: settingsScope)` in the log.
1087
- > So the client `inject` keeps only the universally present `['slots']`, and both channels are **probed at
1088
- > runtime** (`ctx.get`); the host half does the same (`typeof settings.register === 'function'` → legacy path,
1089
- > otherwise read the volatile leaves). Regressions: `pnpm test:client-seat` (injection guard over the eight
1090
- > seat × channel combinations plus behaviour for the three real ones) and `pnpm test:apply` (both host lines).
1091
-
1092
- **Configurable fields** (one shared list for both channels; these fields carry `.volatile()` in the host
1164
+ The settings surface is **one seat + one data channel** (since 2026-10-01):
1165
+
1166
+ | Seat (declaration-driven: `slots.inject` only fires for a declared slot) | Data channel (capability probe) |
1167
+ |---|---|
1168
+ | `plugins.bundle.config`, **key = package name** `dsh-code-server-app` — plugin page → `dsh-code-server-app` → the settings block sits **between the description and the rows** (the page draws title/icon/crumb itself; we only render the form + save control) | `ctx.configForms.get('code-server')` — the configuration **is the plugin entry's own `Config`**, and the only write path is one atomic `mutate(ops, revision)` |
1169
+
1170
+ > The old-generation lines (the rc line's old seat `settings.plugin.item` + old channel `ctx.settingsScope`, and
1171
+ > 0.1.6-alpha.2's {new seat, old channel} combination) were **deleted wholesale** with the old-generation branches —
1172
+ > both UIs (web and desktop) are on this 0.2 generation now, so the seat × channel matrix is no longer needed.
1173
+ > One rule still holds: **the channel is always probed at runtime, never declared in `inject`** — putting
1174
+ > `configForms` into `inject` leaves the entry **pending forever** on a host without that service, and the
1175
+ > right-sidebar tab, the settings block and the resident preload **all vanish together**, leaving only
1176
+ > `web boot: 1 entry did not activate` / `pending (waiting for service: …)` in the log. So the client `inject`
1177
+ > keeps only the universally present `['slots']`, and `configForms` is only reached through
1178
+ > `ctx.get('configForms')` (property access to an undeclared service throws in DSH).
1179
+ > Regression: `pnpm test:client-seat` (one seat × one channel: injection guard over the 4 seat-declared ×
1180
+ > channel-present combinations + anti-assertions that the old seat/channel must not come back + a missing channel
1181
+ > must leave the sidebar tab and the resident preload untouched).
1182
+
1183
+ **Configurable fields** (these fields carry `.volatile()` in the host
1093
1184
  `Config`, so saving re-resolves that leaf **in place** without remounting the plugin):
1094
1185
 
1095
1186
  | Key | Default | Description |
@@ -1109,12 +1200,12 @@ editable in the `cordis.patch.yml` `config` and in settings; changes apply immed
1109
1200
  (Since 0.2.9 the card keeps only those settings (0.3.61 added FIM completion, 0.3.62 its three sub-rows); `windowedOpen` and `reserveComposer` are gone — leftover keys in an old
1110
1201
  settings document neither fail nor apply.)
1111
1202
 
1112
- > Changes apply immediately, no dsh restart needed: the legacy channel goes through `scope.watch`, the new one
1113
- > through the `settings/document-updated` event (both host lines land in the same commit function). The host
1203
+ > Changes apply immediately, no dsh restart needed: changes arrive through the `settings/document-updated` event
1204
+ > and land in the same commit function (the old channel's `scope.watch` was deleted with the old-generation
1205
+ > branches). The host
1114
1206
  > status API returns `keepResident`, `claimExtensions` and `fullscreenOnOpen`, and the client applies them at
1115
- > once. **After adding new setting keys, restart dsh web before first use**: the new line only offers the
1116
- > **volatile** fields of an active, uniquely locatable entry, and the legacy line must re-register the
1117
- > settings namespace.
1207
+ > once. **After adding new setting keys, restart dsh web before first use**: the form only offers the
1208
+ > **volatile** fields of an active, uniquely locatable entry.
1118
1209
 
1119
1210
  Since 0.2.7 the card has **no** "Entry", "dependency install" or "environment check" rows: the entry lives in the sidebar's
1120
1211
  guide page (and in DSH's own file clicks), and diagnostics stay out of the UI — the `/api/code-server/status` `env` field still
@@ -1141,7 +1232,7 @@ dictionaries). Regression: `pnpm test:metadata` (`scripts/test-plugin-metadata.m
1141
1232
 
1142
1233
  | Key | Default | Description |
1143
1234
  |---|---|---|
1144
- | `bin` | `code-server` (placeholder) | Launch priority: explicit `bin` in config > the tree package `@jinsiyu/dshcs-code-server/code-server/out/node/entry.js` > the old platform sub-packages `@jinsiyu/dshcs-code-server-<platform>-<arch>` > the in-package `vendor/code-server` > the old install root `.code-server-app` > plugin-internal `node_modules` > `code-server` on PATH. None present → startup error with troubleshooting hints |
1235
+ | `bin` | `''` (empty = use the bundled launcher) | Escape hatch: point at an external code-server executable / `out/node/entry.js` to fall back to the old model (bypassing `lib/launcher.mjs`) |
1145
1236
  | `host` | `127.0.0.1` | Bind address; `auth: none` only allows loopback (localhost/127.0.0.1/::1) |
1146
1237
  | `port` | `0` | Port for loopback mode; **`0` = a random free port assigned per start** (the actual one is written to `endpoint.json` and read back by the host). Give an explicit port to pin it; when that port is taken and no valid `pid.json` exists, startup fails with diagnostics instead of killing a stranger |
1147
1238
  | `auth` | `none` | `none` \| `password`; non-loopback host automatically requires password |
@@ -1171,16 +1262,20 @@ Host/Origin fence and browser auth); in the desktop profile `apps/desktop-host`
1171
1262
 
1172
1263
  | Method | Path | Description |
1173
1264
  |---|---|---|
1174
- | GET | `/api/code-server/status` | `{ ok, running, status, host, port, pid, cwd, url, version, error, logTail, adopted }` (also `env` environment check and the `setup` compatibility field) |
1265
+ | GET | `/api/code-server/status` | `{ ok, running, status, host, port, pid, cwd, url, version, error, logTail, adopted }` (also the `env` environment check) |
1175
1266
  | POST | `/api/code-server/start` | body `{ cwd? }` (omit cwd to keep the current workspace); idempotent; changing cwd while running only **switches the directory, without restarting the process** (0.2.12) |
1176
1267
  | POST | `/api/code-server/stop` | Stop and recycle the process tree |
1177
- | POST | `/api/code-server/setup` | **Compatibility no-op**: since 0.1.36 dependencies are installed by the package manager, so this only re-runs the env self-check and returns |
1178
1268
  | POST | `/api/code-server/open-file` | body `{ file }` — writes the signal consumed by the built-in `dshcs-open-file` extension to open the file in code-server |
1179
1269
  | GET | `/code-server-bridge/health` | editor-bridge liveness (**unauthenticated**; no editor data). Runs over **local IPC** (named pipe / unix socket), not under `/api`, and needs no `webServer` |
1180
1270
  | POST | `/code-server-bridge/sync` | editor bridge: the extension pushes state (`{context, diagnostics, workspace, at}`) and takes back events; `?since=<seq>` is the event cursor. Requires `x-dshcs-bridge-token`, and **any Origin header is 403** |
1181
1271
  | POST | `/code-server-bridge/ask` | editor bridge: push an editor question into the current session (`{text, file?, lineStart?, lineEnd?, selection?, languageId?}`); **409** when no session can receive it |
1182
1272
  | POST | `/code-server-bridge/event` | editor bridge: extension reports open/close and similar (host log tail). Requires the token |
1183
1273
 
1274
+ > `/api/code-server/setup` (the 0.1.36 "Install environment" compatibility no-op) and the `status` `setup` field
1275
+ > are **deleted** (2026-10-01): now that dependencies are installed by the package manager they had no effect
1276
+ > left, and keeping them only suggested an "Install environment" step still existed. For the environment
1277
+ > self-check use `status.env` or the `[code-server]` lines in the host log.
1278
+
1184
1279
  > All four bridge routes carry their own token check — they **cannot** rely on DSH's cookie fence, because the
1185
1280
  > extension host has no browser cookie — and they are read-only by construction. See "Working with DSH" above.
1186
1281
 
@@ -1318,9 +1413,14 @@ in. Apache-2.0 grants no trademark rights; this project does not use "Continue"
1318
1413
  - **`serve: dsh` shares DSH's origin**, so the iframe is not sandboxed there (same-origin plus `allow-same-origin` is
1319
1414
  escapable by the frame itself); in `loopback` mode the iframe is cross-origin and `sandbox` stays as real protection.
1320
1415
  - **Single instance across sessions**: one shared IDE per host; switching cwd only re-navigates the workbench (since 0.2.12 no process restart, so the old directory's background terminals are not collected).
1321
- - **Older DSH versions are unsupported (since 0.2.3).** Exactly two lines are supported (converged 2026-09-22): the **rc line** `0.1.5-rc.x` (old seat + `current` on the snapshot) and the **alpha line** `>= 0.1.6-alpha.2` (new seat + the `sessionId` standard prop). Earlier alphas (`0.1.5-alpha.x`, `0.1.6-alpha.1`) are **not separate targets** — they share the rc line's shapes, so the code happens to work, but they are not verified. Detail: on a DSH without `sidebarRightTabs` / `sidebarRight` the plugin
1322
- offers nothing but an upgrade notice on the settings page; older-DSH users should stay on `0.2.2`
1323
- (`dsh plugin --profile web add dsh-code-server-app@0.2.2`).
1416
+ - **Older DSH versions are unsupported (since 0.2.3; converged to one generation on 2026-10-01).** On a DSH without
1417
+ `sidebarRightTabs` / `sidebarRight` the plugin
1418
+ offers nothing but an upgrade notice on the settings page. Exactly **one generation** is supported:
1419
+ **DSH ≥ 0.2.0-rc.2** (web and desktop are the same generation), and the verdict is still a capability probe
1420
+ (`sidebarRight`/`sidebarRightTabs` present or not), never a version comparison. The old-generation compatibility
1421
+ branches (the rc / alpha lines' seats, channels and the snapshot's `current`) are deleted;
1422
+ **users who still need an old-generation DSH (≤ 0.1.7-rc.x) should pin `dsh-code-server-app@0.3.69`**
1423
+ (`dsh plugin --profile web add dsh-code-server-app@0.3.69`) — the last version that still carries them.
1324
1424
  - **Sidebar tab switching** (no longer reloads since 0.2.2): DSH's right sidebar renders only the active tab's body, and
1325
1425
  a React unmount moves the iframe away; the plugin keeps it as a singleton resident surface and shuttles it between the
1326
1426
  dock slot and a document-level park container with `Element.moveBefore()` (a state-preserving atomic move), so