dsh-plugin-wsl-env 0.11.0 → 0.13.0
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/CHANGELOG.md +181 -0
- package/CONTRIBUTING.md +29 -7
- package/README.md +124 -138
- package/SECURITY.md +11 -1
- package/SUPPORT.md +29 -2
- package/cordis.patch.yml +17 -19
- package/docs/ARCHITECTURE.md +30 -29
- package/docs/CONFIGURATION.md +81 -21
- package/docs/LIMITATIONS.md +71 -6
- package/docs/MIGRATION.md +98 -0
- package/docs/PARITY.md +1 -1
- package/docs/PERFORMANCE.md +60 -0
- package/docs/QUICKSTART.md +125 -0
- package/docs/README.zh.md +117 -137
- package/docs/ROADMAP-1.0.md +780 -0
- package/docs/ROADMAP.md +4 -0
- package/docs/UPSTREAM-FILE-REFERENCE-SEAM.md +80 -0
- package/docs/UPSTREAM-LSP-SEAM.md +90 -0
- package/docs/UPSTREAM-SESSION-NOTICE.md +95 -0
- package/lib/agent-errors.d.ts +19 -0
- package/lib/agent-errors.js +22 -0
- package/lib/agent-exec.js +2 -2
- package/lib/agent.d.ts +68 -5
- package/lib/agent.js +129 -22
- package/lib/distro-route.d.ts +75 -0
- package/lib/distro-route.js +86 -0
- package/lib/fs-routing.d.ts +4 -1
- package/lib/index.d.ts +166 -37
- package/lib/index.js +353 -75
- package/lib/paths.d.ts +15 -0
- package/lib/paths.js +28 -0
- package/lib/preflight.d.ts +46 -3
- package/lib/preflight.js +83 -14
- package/lib/shell-env.d.ts +9 -3
- package/lib/shell-env.js +121 -43
- package/lib/subprocess.d.ts +12 -3
- package/lib/subprocess.js +21 -3
- package/package.json +23 -15
- package/scripts/diagnose.sh +9 -88
- package/scripts/doctor.mjs +548 -0
- package/scripts/profile-preset.mjs +254 -0
- package/lib/workspace-files-route.d.ts +0 -136
- package/lib/workspace-files-route.js +0 -225
- package/lib/workspace-files-wsl.d.ts +0 -257
- package/lib/workspace-files-wsl.js +0 -418
|
@@ -0,0 +1,780 @@
|
|
|
1
|
+
# Roadmap 1.0: the WSL plugin the DSH ecosystem should have
|
|
2
|
+
|
|
3
|
+
Status: working plan, 2026-10-19. Baseline: `0.12.0`.
|
|
4
|
+
Audience: maintainers and contributors. This is a plan, not a release promise.
|
|
5
|
+
The short version: **from "the only WSL plugin" to "the default WSL plugin"** —
|
|
6
|
+
first run works, every distro and workspace is served by its own environment,
|
|
7
|
+
every DSH surface has a story, and every claim has a test or a probe.
|
|
8
|
+
|
|
9
|
+
## 1. What "must-have" means
|
|
10
|
+
|
|
11
|
+
"Best" is not "most features". It is five acceptance lines:
|
|
12
|
+
|
|
13
|
+
1. **Five-minute first run.** On a clean Windows 11 + WSL 2 + Ubuntu machine,
|
|
14
|
+
the first command runs in the right directory, in the right distro, under
|
|
15
|
+
the sandbox, within five minutes (p50; p90 within fifteen).
|
|
16
|
+
2. **Any distro, any workspace.** Opening a folder in distro A runs in distro A
|
|
17
|
+
even when distro B is the WSL default; two distros can run concurrently
|
|
18
|
+
without crossing streams.
|
|
19
|
+
3. **Full surface coverage.** Shell, files, search, git, terminal, picker, GUI
|
|
20
|
+
previews, ports and `@` references do not fall back to 9p for a WSL
|
|
21
|
+
workspace. Where an upstream seam is missing, the gap is named and measured.
|
|
22
|
+
4. **Explainable failure.** Every refusal has a code and a remedy; no silent
|
|
23
|
+
wrong-tree execution and no fail-open.
|
|
24
|
+
5. **Sustainable.** Every public promise is covered by a unit test or a
|
|
25
|
+
real-machine probe; aarch64 is executed, not only built; documentation has
|
|
26
|
+
no known stale claim.
|
|
27
|
+
|
|
28
|
+
North-star metrics:
|
|
29
|
+
|
|
30
|
+
| Metric | Target |
|
|
31
|
+
|---|---|
|
|
32
|
+
| Tier 1 first-run success | >= 95% |
|
|
33
|
+
| Time to first successful WSL command | p50 <= 5 min, p90 <= 15 min |
|
|
34
|
+
| Real-machine probe suite | 100% on Tier 1, nightly |
|
|
35
|
+
| Known documentation drift | 0 |
|
|
36
|
+
|
|
37
|
+
## 2. Where 0.12.0 stands
|
|
38
|
+
|
|
39
|
+
> WSL-101 is implemented in the working tree (2026-10-19): the distro follows the
|
|
40
|
+
> workspace and the per-distro caches are in place. The table below records the
|
|
41
|
+
> 0.12.0 baseline that motivated the plan.
|
|
42
|
+
|
|
43
|
+
| Area | Strong today | Gap to "must-have" |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| Execution | Native agent is the default; systemd session scope; background processes survive | The distro is pinned by configuration. The picker lists every distro, but a workspace in a non-default distro hits the cross-distro guard ([`src/index.ts:838`](../src/index.ts), [`src/paths.ts:227`](../src/paths.ts)) |
|
|
46
|
+
| Files | ext4 substrate, root-plane `fs-routing`, kernel-enforced confined writes | GUI previews take roughly four to six agent round trips ([`LIMITATIONS.md:122`](LIMITATIONS.md)); `@` completion still reads through 9p |
|
|
47
|
+
| Sandbox | `bubblewrap`, fail-closed, honest `enforcement: partial`, `maskWindowsDrive` | systemd and Linger are default prerequisites, but neither `diagnose` nor `bootstrap` checks them |
|
|
48
|
+
| Onboarding | `bootstrap`, `diagnose`, session-start preflight, package-family install commands | No single "check and fix" command; the preflight only probes bwrap; the preset override is a trap |
|
|
49
|
+
| Configuration | Every shipped key is documented | `wsl-shell` and `wsl-fs` are nested in `preset-wsl`; an id patch only logs a warning and changes nothing ([`CONFIGURATION.md:64`](CONFIGURATION.md)) |
|
|
50
|
+
| Quality | 33 unit-test files, 12 real-machine probes, build/type/coverage gates | Probes are manual; aarch64 is build-only ([`ROADMAP.md:45`](ROADMAP.md)); `fs-routing` is outside `test:unit`/`test:coverage` ([`REQUIREMENTS.zh.md:72`](REQUIREMENTS.zh.md)) |
|
|
51
|
+
| Ecosystem | npm package, bundle patch, bilingual locale, substantial docs | The upstream seams are fragile: the `ensureSession` monkey patch, argv-shape search interception, and the missing `FileReferenceTraversal` seam ([`upstream/promotion-map.md`](upstream/promotion-map.md)) |
|
|
52
|
+
|
|
53
|
+
The engineering base is already in the top tier of comparable projects. The
|
|
54
|
+
remaining gap is productization: **multi-distro correctness, first-run
|
|
55
|
+
friction, configuration ergonomics, and ecosystem presence**.
|
|
56
|
+
|
|
57
|
+
## 3. Design principles
|
|
58
|
+
|
|
59
|
+
1. **Coordinate routing over per-profile pinning.** A path already names its
|
|
60
|
+
distro. The environment should follow that coordinate; an explicit pin
|
|
61
|
+
remains an override, not the default mental model.
|
|
62
|
+
2. **Explicit over implicit, but not silent.** A fallback must be reported in
|
|
63
|
+
the result. A failure must name the remedy. Never turn an unsupported case
|
|
64
|
+
into a wrong-tree success.
|
|
65
|
+
3. **No new service, no listening port.** The resident agent remains a
|
|
66
|
+
transport, not a daemon. Uninstall must stay "remove the cache".
|
|
67
|
+
4. **Measure before optimizing.** v6 FS concurrency and speculative caches wait
|
|
68
|
+
for a measured consumer. The A6/A7 numbers are the model: fix the measured
|
|
69
|
+
bottleneck, not the imagined one.
|
|
70
|
+
5. **Upstream-ready, not upstream-dependent.** The plugin must remain fully
|
|
71
|
+
usable if upstream never accepts a seam. Promotion work is packaging and
|
|
72
|
+
proof, not a blocking dependency.
|
|
73
|
+
6. **Every promise has a test or a probe.** A behavior that cannot be verified
|
|
74
|
+
is either documented as an explicit boundary or not shipped.
|
|
75
|
+
|
|
76
|
+
## 4. Workstreams
|
|
77
|
+
|
|
78
|
+
| Workstream | Question it answers |
|
|
79
|
+
|---|---|
|
|
80
|
+
| **A. Zero-friction onboarding** | Can a new user get from install to a working command without reading the whole manual? |
|
|
81
|
+
| **B. Coordinate-correct multi-distro** | Does the environment follow the workspace, including multiple distros at once? |
|
|
82
|
+
| **C. Full-surface coverage** | Do all DSH consumers of a WSL workspace stay inside the distro? |
|
|
83
|
+
| **D. Trust, performance, reliability** | When something breaks, is it visible, recoverable and fast enough? |
|
|
84
|
+
| **E. Ecosystem presence** | Is this the obvious, documented, supportable choice in the DSH ecosystem? |
|
|
85
|
+
|
|
86
|
+
## 5. Phases
|
|
87
|
+
|
|
88
|
+
### P0 — make "it works" true (0-4 weeks)
|
|
89
|
+
|
|
90
|
+
| ID | Outcome | Acceptance gate | Size |
|
|
91
|
+
|---|---|---|---|
|
|
92
|
+
| P0.1 | `distro: auto` coordinate routing across shell, fs, terminal, shell-env and the session runtime | Default Ubuntu + Debian workspace runs in Debian; two distro sessions concurrent; explicit pin still wins; cross-distro paths still refuse | L |
|
|
93
|
+
| P0.2 | One `doctor`/`setup` path covering bwrap, systemd, Linger, optional tools, peers and config | Clean Win11 + Ubuntu passes in five minutes; missing bwrap, non-systemd, stopped distro and wrong peer each produce a copy-paste remedy | M |
|
|
94
|
+
| P0.3 | Safe `preset-wsl` override helper and validation | Changing `sessionSandbox` or `distro` works in one step; an invalid nested patch fails loudly instead of warning | M |
|
|
95
|
+
| P0.4 | Documentation and gate hygiene | The three known drifts are fixed; `fs-routing` enters the test lists; `probe:fs-routing` exists; links resolve | S |
|
|
96
|
+
| P0.5 | Preflight visible before the first command | A missing bwrap or systemd/Linger is visible in the session UI, not only in `logger.warn` | M |
|
|
97
|
+
|
|
98
|
+
P0 is not a performance phase. It is the difference between "the plugin is
|
|
99
|
+
correct once configured" and "the plugin is correct on first contact".
|
|
100
|
+
|
|
101
|
+
### P1 — make "every day" complete (1-3 months)
|
|
102
|
+
|
|
103
|
+
| ID | Outcome | Acceptance gate | Size |
|
|
104
|
+
|---|---|---|---|
|
|
105
|
+
| P1.1 | `sessionSandbox: auto` for distros without systemd | Non-systemd distro runs the first command under per-command bwrap and reports the narrower scope; explicit `true` still refuses | M |
|
|
106
|
+
| P1.2 | Compatibility matrix and real validation | Tier 1 (Ubuntu/Debian, systemd, x86_64) green; aarch64 spike runs under qemu; Tier 2 status documented | L |
|
|
107
|
+
| P1.3 | Install/upgrade/uninstall E2E | Temporary `DSH_HOME`, packed tarball, `dsh plugin add`, `--dump-config`, remove; upgrade from the previous minor | M |
|
|
108
|
+
| P1.4 | `@` references seam | Measure the 9p cost; land the upstream `FileReferenceTraversal` seam or a declared, tested fallback | L |
|
|
109
|
+
| P1.5 | LSP provider spike | A documented plan and prototype for `ctx.lsp` over fs + subprocess, conditional on the desktop composition mounting LSP | M |
|
|
110
|
+
| P1.6 | GUI preview performance | Baseline measured; p95 <= 1s/MiB for a representative page; v6 only if the measurement justifies it | M |
|
|
111
|
+
| P1.7 | Agent recovery and status | In-flight death recovers within 2s or fails with a named state; `doctor`/status shows agent and scope health | M |
|
|
112
|
+
| P1.8 | Security posture | Strict preset documented and probed; interop visibility/mask matrix; no claim beyond `partial` | S |
|
|
113
|
+
| P1.9 | Peer upgrade canary | A scheduled check against the latest DSH line reports breakage before users do | S |
|
|
114
|
+
|
|
115
|
+
### P2 — make it the ecosystem default (3-6 months)
|
|
116
|
+
|
|
117
|
+
| ID | Outcome | Acceptance gate | Size |
|
|
118
|
+
|---|---|---|---|
|
|
119
|
+
| P2.1 | Upstream promotion pack | Package layout, real-composition boot test, RFCs and PR-ready seams; the plugin still works if none land | L |
|
|
120
|
+
| P2.2 | Discoverability | A docs site or one-page entry, compatibility page, demo, recipes; marketplace directory if DSH has one | M |
|
|
121
|
+
| P2.3 | Community and support | Feature-request and setup-report templates, public roadmap, predictable release cadence, triage target | S |
|
|
122
|
+
| P2.4 | 1.0 readiness | Config schema frozen, migration/deprecation policy, Tier 1 green, aarch64 executed, no P0 bugs for 30 days | M |
|
|
123
|
+
|
|
124
|
+
## 6. Ninety-day sequence
|
|
125
|
+
|
|
126
|
+
| Week | Focus | Output |
|
|
127
|
+
|---|---|---|
|
|
128
|
+
| 1-2 | Baseline and hygiene | Ten clean-machine timings; P0.4; doctor specification |
|
|
129
|
+
| 3-6 | Multi-distro | P0.1 implementation, unit tests, two-distro probe, migration note |
|
|
130
|
+
| 7-8 | First-run loop | P0.2, P0.3, P0.5 |
|
|
131
|
+
| 9-10 | Compatibility and proof | P1.2, P1.3, nightly probe runner |
|
|
132
|
+
| 11-12 | Surface and performance | P1.4/P1.5 spike, P1.6 baseline, P1.7 fault injection |
|
|
133
|
+
| 13+ | Ecosystem and 1.0 | P2.1-P2.4, release gates |
|
|
134
|
+
|
|
135
|
+
The sequence assumes one maintainer-equivalent. P0 is not cuttable; P1 items
|
|
136
|
+
may move if the compatibility matrix exposes a higher-severity failure.
|
|
137
|
+
|
|
138
|
+
## 7. Metrics
|
|
139
|
+
|
|
140
|
+
| Metric | Current | Target | How measured |
|
|
141
|
+
|---|---|---|---|
|
|
142
|
+
| Time to first command | Not systematically measured | p50 <= 5 min, p90 <= 15 min | Ten clean-machine runs |
|
|
143
|
+
| Tier 1 first-run success | Not measured | >= 95% | Compatibility matrix |
|
|
144
|
+
| Real-machine probes | 14, manual | 100%, nightly | Self-hosted Windows runner |
|
|
145
|
+
| FS single-op p95 | ~22ms host round trip | <= 30ms | `fs-queue.mjs` |
|
|
146
|
+
| 16 concurrent reads p95 | 2.4-8.2ms | <= 20ms | `fs-queue.mjs` |
|
|
147
|
+
| GUI preview p95 | Backend 63.5 ms/MiB (service round trips on top) | <= 1s/MiB | `probe:gui-preview` |
|
|
148
|
+
| Agent recovery | One rebuild | < 2s | Fault injection |
|
|
149
|
+
| Documentation drift | Three known | 0 | Release checklist |
|
|
150
|
+
| Release cadence | Ad hoc | Every 2-4 weeks | Calendar |
|
|
151
|
+
| Adoption (lagging) | Not established | +50% per quarter | npm download stats |
|
|
152
|
+
|
|
153
|
+
No default telemetry. Facts come from `doctor --json`, issue templates and
|
|
154
|
+
probe reports.
|
|
155
|
+
|
|
156
|
+
## 8. Risks, non-goals and decision rules
|
|
157
|
+
|
|
158
|
+
| Risk | Mitigation |
|
|
159
|
+
|---|---|
|
|
160
|
+
| Upstream never lands a seam | Keep the plugin independent; promotion work is packaging and proof, not a dependency |
|
|
161
|
+
| Multi-distro refactor destabilizes routing | Introduce `distro: auto` behind tests; keep explicit pins; run two-distro probes before release |
|
|
162
|
+
| `sessionSandbox: auto` hides a semantic change | Still use bwrap; report the scope mode in the result; explicit `true` keeps the strict behavior |
|
|
163
|
+
| Real-machine CI is unavailable | Self-hosted Windows nightly; qemu for the aarch64 binary; manual suite before release |
|
|
164
|
+
| Solo maintenance and bus factor | Freeze scope for 1.0; document every seam; keep the issue templates and probes current |
|
|
165
|
+
| Security overclaim | Keep `enforcement: partial`; the strict preset narrows, never closes, the interop hole |
|
|
166
|
+
| GUI regression repeats | Never replace the shipped `workspace-files` row again; only route and optimize |
|
|
167
|
+
|
|
168
|
+
**Non-goals:** WSL 1, macOS/Linux hosts, a bundled daemon or listening port,
|
|
169
|
+
full isolation from Windows interop, uniform support for every distro, an
|
|
170
|
+
editor/LSP rewrite without an upstream seam, and default telemetry.
|
|
171
|
+
|
|
172
|
+
**Decision rules:**
|
|
173
|
+
|
|
174
|
+
- A P1 item moves only with a measured need or a concrete consumer.
|
|
175
|
+
- A compatibility claim enters the matrix only with a test or a probe.
|
|
176
|
+
- A security statement never exceeds what the sandbox actually enforces.
|
|
177
|
+
- A release does not ship without the P0 gates; a native change also needs the
|
|
178
|
+
aarch64 spike.
|
|
179
|
+
|
|
180
|
+
## 9. Issue-ready breakdown
|
|
181
|
+
|
|
182
|
+
The blocks below were filed as GitHub issues #5-#22 on 2026-10-19. The
|
|
183
|
+
acceptance list in each issue is the contract; filter by priority:
|
|
184
|
+
[P0](https://github.com/Big-Dao/dsh-plugin-wsl-env/issues?q=is%3Aissue+label%3Apriority%3AP0),
|
|
185
|
+
[P1](https://github.com/Big-Dao/dsh-plugin-wsl-env/issues?q=is%3Aissue+label%3Apriority%3AP1),
|
|
186
|
+
[P2](https://github.com/Big-Dao/dsh-plugin-wsl-env/issues?q=is%3Aissue+label%3Apriority%3AP2).
|
|
187
|
+
|
|
188
|
+
### WSL-101 — Multi-distro coordinate routing
|
|
189
|
+
|
|
190
|
+
**Status:** implemented in the working tree (2026-10-19); unit-covered, with the
|
|
191
|
+
real-machine two-distro probe still to run.
|
|
192
|
+
|
|
193
|
+
**Priority:** P0 · **Size:** L · **Labels:** `area:multi-distro`,
|
|
194
|
+
`type:feature`, `priority:P0`
|
|
195
|
+
|
|
196
|
+
**Why:** The picker lists every distro, but the preset pins one. A workspace in
|
|
197
|
+
another distro is refused instead of served.
|
|
198
|
+
|
|
199
|
+
**Acceptance:**
|
|
200
|
+
|
|
201
|
+
- [ ] `distro: "auto"` resolves the distro from the workspace UNC; an explicit
|
|
202
|
+
name still pins; `"default"` forces the WSL default.
|
|
203
|
+
- [ ] `wsl-shell`, `wsl-fs`, `fs-routing`, `subprocess-wsl` and `shell-env`
|
|
204
|
+
all follow the same coordinate rule.
|
|
205
|
+
- [ ] The shared agent and session runtime are keyed by distro; two distros run
|
|
206
|
+
concurrently.
|
|
207
|
+
- [ ] A workspace in its own distro never raises `FS_OUTSIDE_DISTRO`; another
|
|
208
|
+
distro's path still does.
|
|
209
|
+
- [ ] Migration note documents the `""`/`auto`/`default` semantics.
|
|
210
|
+
|
|
211
|
+
**Tests/probes:** unit tests for the resolver; two-distro real-machine probe;
|
|
212
|
+
cross-distro refusal leg; composition test through the service proxy.
|
|
213
|
+
|
|
214
|
+
**Depends on:** none.
|
|
215
|
+
|
|
216
|
+
### WSL-102 — Doctor and one-command setup
|
|
217
|
+
|
|
218
|
+
**Status:** implemented (2026-10-19): [`scripts/doctor.mjs`](../scripts/doctor.mjs)
|
|
219
|
+
is the one-command check, exposed as `pnpm run doctor`; `diagnose` is its
|
|
220
|
+
read-only alias (`--read-only` refuses `--fix`/`--install`). The unit suite runs
|
|
221
|
+
the doctor as a subprocess against a fake `wsl.exe`/`cmd.exe` on PATH: a healthy
|
|
222
|
+
machine, missing bubblewrap, no systemd, a stopped distro and stale scopes are
|
|
223
|
+
each asserted end to end. The clean-machine five-minute stopwatch has not been
|
|
224
|
+
run (this machine has one, already-configured distro); it stays on the release
|
|
225
|
+
checklist.
|
|
226
|
+
|
|
227
|
+
**Priority:** P0 · **Size:** M · **Labels:** `area:onboarding`,
|
|
228
|
+
`type:feature`, `priority:P0`
|
|
229
|
+
|
|
230
|
+
**Why:** The default path has two prerequisites (bwrap, systemd/Linger) and the
|
|
231
|
+
current diagnostics do not cover the second.
|
|
232
|
+
|
|
233
|
+
**Acceptance:**
|
|
234
|
+
|
|
235
|
+
- [x] One command reports Windows/WSL versions, distro, shell, bwrap
|
|
236
|
+
usability, systemd PID 1, `systemd-run`, Linger, rg/git/inotifywait,
|
|
237
|
+
peer version, agent cache and stale scopes.
|
|
238
|
+
- [x] Human-readable output and `--json`; each failure includes one
|
|
239
|
+
copy-paste remedy.
|
|
240
|
+
- [x] `--fix` performs only safe actions; package installation requires
|
|
241
|
+
explicit confirmation and never runs silently.
|
|
242
|
+
- [x] Missing bwrap, non-systemd, stopped distro and wrong peer are each
|
|
243
|
+
classified (fake-`wsl.exe` tests).
|
|
244
|
+
- [ ] Clean Win11 + Ubuntu first run is <= 5 minutes (release checklist; not
|
|
245
|
+
run on this single configured machine).
|
|
246
|
+
|
|
247
|
+
**Tests/probes:** process-level tests against fake `wsl.exe` outputs
|
|
248
|
+
([`test/doctor.test.mjs`](../test/doctor.test.mjs)); real-machine run on the
|
|
249
|
+
Tier 1 image; `diagnose` remains a read-only alias.
|
|
250
|
+
|
|
251
|
+
**Depends on:** none.
|
|
252
|
+
|
|
253
|
+
### WSL-103 — Preset override guardrail
|
|
254
|
+
|
|
255
|
+
**Priority:** P0 · **Size:** M · **Labels:** `area:configuration`,
|
|
256
|
+
`type:feature`, `priority:P0`
|
|
257
|
+
|
|
258
|
+
**Status:** implemented (2026-10-19): [`scripts/profile-preset.mjs`](../scripts/profile-preset.mjs)
|
|
259
|
+
(`pnpm run preset`) prints the complete `preset-wsl` row, applies `--distro`,
|
|
260
|
+
`--session-sandbox`, `--sandbox`, `--mask-windows-drive` and `--agent-backend`,
|
|
261
|
+
and writes a profile layer with `--out`. `--check` fails on a top-level
|
|
262
|
+
`- id: wsl-shell`/`wsl-fs` entry and prints the exact block to paste. The unit
|
|
263
|
+
suite compares the printed block byte-for-byte with the shipped row the app
|
|
264
|
+
loads and exercises every CLI path.
|
|
265
|
+
|
|
266
|
+
**Why:** `wsl-shell` and `wsl-fs` are nested inside `preset-wsl`; an id patch
|
|
267
|
+
logs a warning and does nothing, which is the worst kind of configuration
|
|
268
|
+
failure.
|
|
269
|
+
|
|
270
|
+
**Acceptance:**
|
|
271
|
+
|
|
272
|
+
- [x] A helper prints the complete, copy-paste `preset-wsl` block for the
|
|
273
|
+
installed version.
|
|
274
|
+
- [x] The helper can apply a small set of common edits (`distro`,
|
|
275
|
+
`sessionSandbox`, `sandbox`, `maskWindowsDrive`, `agentBackend`).
|
|
276
|
+
- [x] An invalid nested patch fails with a message that includes the exact
|
|
277
|
+
block to paste; no silent no-op.
|
|
278
|
+
- [x] The helper is covered by a unit test and documented in CONFIGURATION.
|
|
279
|
+
|
|
280
|
+
**Tests/probes:** generated YAML compared byte-for-byte against the shipped
|
|
281
|
+
block (the row the real composition loads); the CLI's print/write/check paths
|
|
282
|
+
run in [`test/profile-preset.test.mjs`](../test/profile-preset.test.mjs).
|
|
283
|
+
|
|
284
|
+
**Depends on:** none.
|
|
285
|
+
|
|
286
|
+
### WSL-104 — Documentation and gate hygiene
|
|
287
|
+
|
|
288
|
+
**Status:** implemented (2026-10-19): the three drifts are fixed, `fs-routing`
|
|
289
|
+
and `distro-route` are in both test lists, `scripts/check-links.mjs` gates
|
|
290
|
+
relative links from `pnpm test`, and `probe:fs-routing` is written and wired
|
|
291
|
+
into the real-machine suite. The routing probe has not been executed yet (it
|
|
292
|
+
needs the app closed); its first run stays on the release checklist.
|
|
293
|
+
|
|
294
|
+
**Priority:** P0 · **Size:** S · **Labels:** `area:docs`, `area:quality`,
|
|
295
|
+
`priority:P0`
|
|
296
|
+
|
|
297
|
+
**Why:** Three user-visible claims are stale, and `fs-routing` is outside the
|
|
298
|
+
test lists despite the repository's own rule.
|
|
299
|
+
|
|
300
|
+
**Acceptance:**
|
|
301
|
+
|
|
302
|
+
- [x] `VALUE.zh` no longer says watch is polling-only; `PARITY` no longer says
|
|
303
|
+
"a poll, not inotify"; the `cordis.patch.yml` substrate comment no
|
|
304
|
+
longer calls `share` an opt-out.
|
|
305
|
+
- [x] `test/fs-routing.test.mjs` is in `test:unit` and `test:coverage`.
|
|
306
|
+
- [x] A `probe:fs-routing` exists and is wired into the real-machine suite
|
|
307
|
+
(first execution pending: the suite needs the app closed).
|
|
308
|
+
- [x] Markdown links resolve (`scripts/check-links.mjs`, in `pnpm test`);
|
|
309
|
+
version references in the roadmap/docs are checked at release time.
|
|
310
|
+
|
|
311
|
+
**Tests/probes:** `pnpm test`, `pnpm run test:coverage`, `probe:fs-routing`.
|
|
312
|
+
|
|
313
|
+
**Depends on:** none.
|
|
314
|
+
|
|
315
|
+
### WSL-105 — Visible preflight and systemd/Linger coverage
|
|
316
|
+
|
|
317
|
+
**Priority:** P0 · **Size:** M · **Labels:** `area:onboarding`,
|
|
318
|
+
`area:sandbox`, `priority:P0`
|
|
319
|
+
|
|
320
|
+
**Status:** implemented (2026-10-19): `wsl-preflight` runs the shared
|
|
321
|
+
session-runtime probe after the bwrap probe and warns with the existing
|
|
322
|
+
remedy for `no-systemd`, `no-user-manager`, `no-systemd-run` and `no-linger`
|
|
323
|
+
(`sessionSandbox: false` on the row skips the session half). The advisory is
|
|
324
|
+
logged **and** published as a session-scoped `wsl-preflight` runtime-context
|
|
325
|
+
entry, so it is visible in the session transcript rather than only in the app
|
|
326
|
+
log. DSH 0.2.1 has no toast/banner seam; the exact ask is written up (not yet
|
|
327
|
+
filed — no issue channel here) in
|
|
328
|
+
[UPSTREAM-SESSION-NOTICE.md](UPSTREAM-SESSION-NOTICE.md), and
|
|
329
|
+
[LIMITATIONS.md](LIMITATIONS.md#session-start-advisories) records the boundary.
|
|
330
|
+
Unit coverage drives every probe verdict through a fake `wsl.exe`; the
|
|
331
|
+
real-machine missing-bwrap and non-systemd legs are still manual.
|
|
332
|
+
|
|
333
|
+
**Why:** The session-start preflight currently only probes bwrap and writes to
|
|
334
|
+
`logger.warn`; the other default prerequisite is discovered at the first
|
|
335
|
+
command.
|
|
336
|
+
|
|
337
|
+
**Acceptance:**
|
|
338
|
+
|
|
339
|
+
- [x] The preflight checks bwrap, systemd PID 1, `systemd-run` and Linger.
|
|
340
|
+
- [x] The warning is visibly attached to the session through the
|
|
341
|
+
runtime-context entry (not only logs).
|
|
342
|
+
- [ ] A GUI notice/banner renders it: upstream seam missing; the filing payload
|
|
343
|
+
is ready at [proposal-session-notice.md](upstream/proposal-session-notice.md)
|
|
344
|
+
and has not been submitted (a maintainer action).
|
|
345
|
+
- [x] The warning never installs anything and never changes fail-closed
|
|
346
|
+
behavior.
|
|
347
|
+
- [x] A session with a usable environment produces no warning.
|
|
348
|
+
|
|
349
|
+
**Tests/probes:** preflight unit tests with fake probe output (every verdict);
|
|
350
|
+
real-machine missing-bwrap and non-systemd sessions.
|
|
351
|
+
|
|
352
|
+
**Depends on:** WSL-102 for the shared probe logic; UI seam may be upstream.
|
|
353
|
+
|
|
354
|
+
### WSL-201 — `sessionSandbox: auto`
|
|
355
|
+
|
|
356
|
+
**Priority:** P1 · **Size:** M · **Labels:** `area:sandbox`,
|
|
357
|
+
`type:feature`, `priority:P1`
|
|
358
|
+
|
|
359
|
+
**Status:** implemented (2026-10-19): `sessionSandbox` accepts `true`, `false`
|
|
360
|
+
or `"auto"` on both `wsl-shell` and `wsl-fs`. `auto` probes the session runtime
|
|
361
|
+
and, when the platform cannot host it, falls back to the per-command `bwrap`
|
|
362
|
+
profile — still confined — and the command result reports
|
|
363
|
+
`sessionScope: "session" | "per-command"`. A failed `auto` verdict is re-probed
|
|
364
|
+
at most once a minute, so following the remedy upgrades without a restart.
|
|
365
|
+
`true` still refuses with the preflight remedy; `false` is unchanged. Unit
|
|
366
|
+
tests cover auto-usable, auto-fallback (shell and fs) and the `true` refusal;
|
|
367
|
+
the non-systemd real-machine leg has not been run (this machine has systemd and
|
|
368
|
+
only one distro).
|
|
369
|
+
|
|
370
|
+
**Why:** systemd is a hard default prerequisite. A distro without it should
|
|
371
|
+
still get a safe, sandboxed first command instead of a refusal.
|
|
372
|
+
|
|
373
|
+
**Acceptance:**
|
|
374
|
+
|
|
375
|
+
- [x] `sessionSandbox: auto` uses the scope when systemd and Linger are
|
|
376
|
+
available, otherwise falls back to per-command bwrap and reports the
|
|
377
|
+
narrower scope.
|
|
378
|
+
- [x] `true` still refuses with the existing remedy; `false` is unchanged.
|
|
379
|
+
- [x] The result exposes whether the scope was active (`sessionScope`);
|
|
380
|
+
CONFIGURATION explains the `/tmp` and background-process difference.
|
|
381
|
+
- [x] The fallback never runs unconfined.
|
|
382
|
+
|
|
383
|
+
**Tests/probes:** `test/provider.test.mjs` (auto-usable, auto-fallback for the
|
|
384
|
+
shell and the filesystem, the `true` refusal); a non-systemd distro real-machine
|
|
385
|
+
probe remains unrun (no non-systemd distro here).
|
|
386
|
+
|
|
387
|
+
**Depends on:** WSL-102, WSL-105.
|
|
388
|
+
|
|
389
|
+
### WSL-202 — Compatibility matrix and aarch64
|
|
390
|
+
|
|
391
|
+
**Priority:** P1 · **Size:** L · **Labels:** `area:compatibility`,
|
|
392
|
+
`area:quality`, `priority:P1`
|
|
393
|
+
|
|
394
|
+
**Why:** The support matrix is prose, and the aarch64 binary is built but never
|
|
395
|
+
executed.
|
|
396
|
+
|
|
397
|
+
**Acceptance:**
|
|
398
|
+
|
|
399
|
+
- [ ] Tier 1 and Tier 2 are defined and tested: Ubuntu LTS, Debian stable,
|
|
400
|
+
Fedora, Arch, Alpine (musl), openSUSE; systemd and non-systemd;
|
|
401
|
+
x86_64 and aarch64; Windows 10/11; current WSL.
|
|
402
|
+
- [ ] The native 18-check suite runs for aarch64 under qemu in CI.
|
|
403
|
+
- [ ] The shell agent runs in Linux containers for the non-Ubuntu families.
|
|
404
|
+
- [ ] The support table states "supported", "partial" and "unsupported" with
|
|
405
|
+
evidence.
|
|
406
|
+
|
|
407
|
+
**Tests/probes:** container matrix, qemu spike, self-hosted nightly.
|
|
408
|
+
|
|
409
|
+
**Depends on:** WSL-201 for non-systemd; WSL-203 for packaging.
|
|
410
|
+
|
|
411
|
+
### WSL-203 — Install/upgrade/uninstall E2E
|
|
412
|
+
|
|
413
|
+
**Priority:** P1 · **Size:** M · **Labels:** `area:release`,
|
|
414
|
+
`area:quality`, `priority:P1`
|
|
415
|
+
|
|
416
|
+
**Status:** implemented (2026-10-19): [`test/e2e/install.sh`](../test/e2e/install.sh)
|
|
417
|
+
(`pnpm run e2e:install`) packs the tree, creates a fresh `DSH_HOME` under
|
|
418
|
+
`%TEMP%`, initializes a profile from the shipped `web` template, installs the
|
|
419
|
+
tarball, asserts `--dump-config` composes the plugin rows with no skipped-patch
|
|
420
|
+
warnings, removes it and asserts every row is gone. With network it also
|
|
421
|
+
installs the previous minor (0.11.0), plants a marker in the profile layer,
|
|
422
|
+
upgrades to the packed version, and asserts the marker survives, the installed
|
|
423
|
+
version is current, and the installed CHANGELOG carries the migration note.
|
|
424
|
+
The run passed 10/10 on this machine (the app may stay running: plugin
|
|
425
|
+
management is local). [`test/packaging.test.mjs`](../test/packaging.test.mjs)
|
|
426
|
+
guards the packed file list in `pnpm test`. A self-hosted Windows runner job is
|
|
427
|
+
still unconfigured; the local command is the documented path.
|
|
428
|
+
|
|
429
|
+
**Why:** The install path is manual and has no automated guard; an upgrade can
|
|
430
|
+
silently leave an obsolete workaround behind.
|
|
431
|
+
|
|
432
|
+
**Acceptance:**
|
|
433
|
+
|
|
434
|
+
- [x] A script creates a temporary `DSH_HOME`, installs a packed tarball,
|
|
435
|
+
checks `--dump-config`, removes the plugin and asserts cleanup.
|
|
436
|
+
- [x] Upgrading from the previous minor preserves the profile and prints the
|
|
437
|
+
migration note (asserted against the installed CHANGELOG).
|
|
438
|
+
- [x] The E2E runs via a documented local command (`pnpm run e2e:install`);
|
|
439
|
+
the self-hosted runner job remains to be wired.
|
|
440
|
+
|
|
441
|
+
**Tests/probes:** bash E2E (`test/e2e/install.sh`), packaging test
|
|
442
|
+
(`test/packaging.test.mjs`), release checklist.
|
|
443
|
+
|
|
444
|
+
**Depends on:** none.
|
|
445
|
+
|
|
446
|
+
### WSL-204 — `@` references seam
|
|
447
|
+
|
|
448
|
+
**Priority:** P1 · **Size:** L · **Labels:** `area:file-reference`,
|
|
449
|
+
`type:feature`, `priority:P1`
|
|
450
|
+
|
|
451
|
+
**Status:** measured and deferred (2026-10-19):
|
|
452
|
+
[UPSTREAM-FILE-REFERENCE-SEAM.md](UPSTREAM-FILE-REFERENCE-SEAM.md) records the
|
|
453
|
+
cost (20 dirs / 520 files: 9p walk median 84.7 ms vs ext4 1.5 ms, ~56×; 9p
|
|
454
|
+
samples 63–192 ms) measured by `pnpm run probe:file-reference`. The seam
|
|
455
|
+
contract (three functions, Dirent/error/coordinate semantics) is already
|
|
456
|
+
written in [rfc-wsl-workspaces.md](upstream/rfc-wsl-workspaces.md); the
|
|
457
|
+
consumer [`src/file-reference-wsl.ts`](../src/file-reference-wsl.ts) is built
|
|
458
|
+
and unit-tested but deliberately unwired. The fallback is to keep the 9p walk
|
|
459
|
+
until upstream exposes the funnel; the trigger and the follow-up probe are
|
|
460
|
+
recorded.
|
|
461
|
+
|
|
462
|
+
**Why:** `@` completion still walks the 9p share; the WSL traversal module is
|
|
463
|
+
built but unwired.
|
|
464
|
+
|
|
465
|
+
**Acceptance:**
|
|
466
|
+
|
|
467
|
+
- [x] The 9p cost is measured on a representative tree (84.7 ms vs 1.5 ms).
|
|
468
|
+
- [x] The upstream `FileReferenceTraversal` seam is proposed with the three
|
|
469
|
+
function contract and the coordinate/error semantics.
|
|
470
|
+
- [x] The seam did not land, so the limitation is stated with the measured cost
|
|
471
|
+
and a fallback decision (keep the 9p walk; wire on the trigger).
|
|
472
|
+
|
|
473
|
+
**Tests/probes:** `probe:file-reference` (9p-vs-ext4 walk);
|
|
474
|
+
`test/file-reference-wsl.test.mjs` (the consumer); no live completion probe
|
|
475
|
+
until the seam exists.
|
|
476
|
+
|
|
477
|
+
**Depends on:** upstream seam; no hard block for 1.0 if documented.
|
|
478
|
+
|
|
479
|
+
### WSL-205 — LSP provider spike
|
|
480
|
+
|
|
481
|
+
**Priority:** P1 · **Size:** M · **Labels:** `area:lsp`, `type:research`,
|
|
482
|
+
`priority:P1`
|
|
483
|
+
|
|
484
|
+
**Status:** researched and deferred (2026-10-19):
|
|
485
|
+
[UPSTREAM-LSP-SEAM.md](UPSTREAM-LSP-SEAM.md) records that `dsh-lsp`,
|
|
486
|
+
`dsh-lsp-stdio` and `dsh-tool-lsp` exist in the harness but are **not** mounted
|
|
487
|
+
in the `0.2.1-rc.2` base composition (verified against the app's bundled
|
|
488
|
+
`dsh-base/cordis.patch.yml`). The stdio provider injects `fs` + `subprocess` and
|
|
489
|
+
assumes one execution world; a WSL session's `ctx.fs` is the distro's while
|
|
490
|
+
`ctx.subprocess` is the host's, so the gap is a preset-scoped subprocess
|
|
491
|
+
provider plus URI/path translation. The prototype is deferred with an explicit
|
|
492
|
+
trigger (the composition mounts the seam, or upstream adds the provider seam).
|
|
493
|
+
|
|
494
|
+
**Why:** The desktop composition does not mount LSP today, but the WSL family
|
|
495
|
+
would be the natural place to provide it.
|
|
496
|
+
|
|
497
|
+
**Acceptance:**
|
|
498
|
+
|
|
499
|
+
- [x] Document whether the current DSH line mounts `ctx.lsp` and what a
|
|
500
|
+
WSL-backed provider would need (paired fs + subprocess).
|
|
501
|
+
- [x] A prototype proves the shape or is explicitly deferred with a trigger.
|
|
502
|
+
- [x] No user-facing claim until the composition actually mounts it.
|
|
503
|
+
|
|
504
|
+
**Tests/probes:** composition inspection (documented in UPSTREAM-LSP-SEAM.md);
|
|
505
|
+
no prototype while the trigger is unmet.
|
|
506
|
+
|
|
507
|
+
**Depends on:** upstream composition; not a 1.0 blocker.
|
|
508
|
+
|
|
509
|
+
### WSL-206 — GUI preview performance
|
|
510
|
+
|
|
511
|
+
**Priority:** P1 · **Size:** M · **Labels:** `area:performance`,
|
|
512
|
+
`area:gui`, `priority:P1`
|
|
513
|
+
|
|
514
|
+
**Status:** implemented (2026-10-19): [`test/probe/gui-preview.sh`](../test/probe/gui-preview.sh)
|
|
515
|
+
(`pnpm run probe:gui-preview`) measures the three routed backend operations a
|
|
516
|
+
preview pays — `stat`, `listDir`, and a 1 MiB `readByteRange` — with p50/p95 and
|
|
517
|
+
budgets (stat 100 ms, listing 500 ms, page 1 s/MiB). Measured on this machine
|
|
518
|
+
(20 iterations): stat p95 2.7 ms, listDir p95 5.1 ms, 1 MiB page read p95
|
|
519
|
+
63.5 ms/MiB. The service's own round trips are not part of this number; they
|
|
520
|
+
stack on top, and the earlier "four to six" remains the qualitative shape. No
|
|
521
|
+
optimization is justified; the shipped `workspace-files` row is untouched, so
|
|
522
|
+
there is no speculative v6.
|
|
523
|
+
|
|
524
|
+
**Why:** The 0.12.0 correction restored previews at the cost of four to six
|
|
525
|
+
agent round trips. Correctness first, but the latency needs a measured budget.
|
|
526
|
+
|
|
527
|
+
**Acceptance:**
|
|
528
|
+
|
|
529
|
+
- [x] A probe measures listing, stat and page-read latency for a representative
|
|
530
|
+
tree and a 1 MiB file.
|
|
531
|
+
- [x] p95 <= 1s/MiB for the page read (63.5 ms/MiB); listings within the agreed
|
|
532
|
+
budget (5.1 ms).
|
|
533
|
+
- [x] Any optimization is justified by the probe; no speculative v6.
|
|
534
|
+
- [x] The shipped `workspace-files` row is not replaced again.
|
|
535
|
+
|
|
536
|
+
**Tests/probes:** `test/probe/gui-preview.sh` (new); `fs-queue.mjs` for the
|
|
537
|
+
agent queue; the service-level round-trip count remains qualitative.
|
|
538
|
+
|
|
539
|
+
**Depends on:** WSL-101 for per-distro routing.
|
|
540
|
+
|
|
541
|
+
### WSL-207 — Agent recovery and status
|
|
542
|
+
|
|
543
|
+
**Priority:** P1 · **Size:** M · **Labels:** `area:reliability`,
|
|
544
|
+
`type:feature`, `priority:P1`
|
|
545
|
+
|
|
546
|
+
**Status:** implemented (2026-10-19): a resident that spends its one rebuild
|
|
547
|
+
enters a bounded revival (2/4/8 s backoff, one fresh transport and one rebuild
|
|
548
|
+
per attempt); after three deaths the refusal is permanent and names the restart
|
|
549
|
+
remedy. `WslAgent.status()` exposes state, pid, lastError, deaths and pending.
|
|
550
|
+
`pnpm run doctor` now probes a fresh shell resident (`agent.handshake`: pid,
|
|
551
|
+
protocol, script digest) and still reports the agent cache and live/stale
|
|
552
|
+
`dsh-wsl-*.scope` counts. The live app resident's last error has no IPC channel
|
|
553
|
+
to the doctor, so the doctor reports its own probe failure and the app log
|
|
554
|
+
keeps the live last error — documented in LIMITATIONS.
|
|
555
|
+
|
|
556
|
+
**Why:** An in-flight agent death can take the filesystem substrate out until
|
|
557
|
+
the app restarts; users experience "everything suddenly fails".
|
|
558
|
+
|
|
559
|
+
**Acceptance:**
|
|
560
|
+
|
|
561
|
+
- [x] A failed agent is re-established on the next call with bounded backoff,
|
|
562
|
+
or fails with a named state and a restart remedy.
|
|
563
|
+
- [x] A status/doctor view reports the agent, scope and last error (doctor:
|
|
564
|
+
fresh-agent handshake + scopes + probe error; `status()`: live snapshot;
|
|
565
|
+
the live resident's last error stays in the app log).
|
|
566
|
+
- [x] Fault injection covers in-flight EXEC, FS read and FS write.
|
|
567
|
+
- [x] Recovery does not replay mutation frames.
|
|
568
|
+
|
|
569
|
+
**Tests/probes:** `test/agent.test.mjs` (revival, budget exhaustion, status,
|
|
570
|
+
EXEC/read/write fault injection); `test/doctor.test.mjs` (handshake, digest
|
|
571
|
+
mismatch); a real-machine kill/restart probe is still unrun.
|
|
572
|
+
|
|
573
|
+
**Depends on:** WSL-102 for status output.
|
|
574
|
+
|
|
575
|
+
### WSL-208 — Security strict profile and interop matrix
|
|
576
|
+
|
|
577
|
+
**Priority:** P1 · **Size:** S · **Labels:** `area:security`,
|
|
578
|
+
`area:docs`, `priority:P1`
|
|
579
|
+
|
|
580
|
+
**Status:** implemented except the distro-disabled leg (2026-10-19):
|
|
581
|
+
[CONFIGURATION](../docs/CONFIGURATION.md#the-strict-profile) documents the strict
|
|
582
|
+
profile, its trade-offs and the visible/masked/disabled matrix;
|
|
583
|
+
`pnpm run probe:sandbox` now also runs the masked profile (14 expectations:
|
|
584
|
+
`/mnt` hidden, the Windows binary unreachable, the workspace still writable). The
|
|
585
|
+
visible leg's INFO still records the interop escape, and the `partial`
|
|
586
|
+
enforcement fact is untouched. The disabled leg (`[interop] enabled=false` +
|
|
587
|
+
`wsl --shutdown`) needs a distro-level change and is documented but not probed
|
|
588
|
+
automatically.
|
|
589
|
+
|
|
590
|
+
**Why:** The sandbox is honest about `partial`, but users need a clear "strict"
|
|
591
|
+
configuration and evidence for each interop state.
|
|
592
|
+
|
|
593
|
+
**Acceptance:**
|
|
594
|
+
|
|
595
|
+
- [x] A documented strict preset (`maskWindowsDrive: true`, `sandbox: true`)
|
|
596
|
+
with its trade-offs.
|
|
597
|
+
- [x] A probe matrix covers interop visible and masked on a real machine; the
|
|
598
|
+
disabled leg is documented and marked manual (needs a distro-level change).
|
|
599
|
+
- [x] No document claims full isolation; the `partial` fact is unchanged.
|
|
600
|
+
- [x] The strict preset is covered by a sandbox probe (`probe:sandbox`).
|
|
601
|
+
|
|
602
|
+
**Tests/probes:** `probe:sandbox` (visible + masked); the disabled leg is a
|
|
603
|
+
manual distro-level check recorded in CONFIGURATION.
|
|
604
|
+
|
|
605
|
+
**Depends on:** none.
|
|
606
|
+
|
|
607
|
+
### WSL-209 — Peer upgrade canary
|
|
608
|
+
|
|
609
|
+
**Priority:** P1 · **Size:** S · **Labels:** `area:release`,
|
|
610
|
+
`area:compatibility`, `priority:P1`
|
|
611
|
+
|
|
612
|
+
**Status:** implemented (2026-10-19): `.github/workflows/peer-canary.yml` runs
|
|
613
|
+
weekly and on demand; `scripts/peer-canary.mjs` resolves the `next` dist-tag for
|
|
614
|
+
every pinned peer, compares it with the pins, and (on a moved line) installs the
|
|
615
|
+
tagged peers into a scratch copy and runs `pnpm test` plus the composition boot
|
|
616
|
+
test. The summary table goes to `$GITHUB_STEP_SUMMARY` and a failed upgrade fails
|
|
617
|
+
the run with the delta. `SUPPORT.md` points the supported-version row at that
|
|
618
|
+
summary. Local `--check` on this machine resolved the line with no delta; the
|
|
619
|
+
workflow itself has not run in this environment (no Actions runner here), and
|
|
620
|
+
opening an issue on a red run was left out because the workflow has no issue
|
|
621
|
+
permission — the failing run plus its delta is the signal.
|
|
622
|
+
|
|
623
|
+
**Why:** The peer pins are exact; a DSH release can break the plugin before a
|
|
624
|
+
user reports it.
|
|
625
|
+
|
|
626
|
+
**Acceptance:**
|
|
627
|
+
|
|
628
|
+
- [x] A scheduled workflow checks the latest `@deepseek-ai/dsh-*` line,
|
|
629
|
+
installs it in a scratch tree and runs `pnpm test` plus the composition
|
|
630
|
+
boot test.
|
|
631
|
+
- [x] A failure fails the scheduled run with the exact version delta (step
|
|
632
|
+
summary + failing step; no auto-filed issue).
|
|
633
|
+
- [x] The supported-version table is updated from the result (`SUPPORT.md`
|
|
634
|
+
points at the canary summary).
|
|
635
|
+
|
|
636
|
+
**Tests/probes:** `.github/workflows/peer-canary.yml`;
|
|
637
|
+
`test/peer-canary.test.mjs`; composition test.
|
|
638
|
+
|
|
639
|
+
**Depends on:** none.
|
|
640
|
+
|
|
641
|
+
### WSL-301 — Upstream promotion pack
|
|
642
|
+
|
|
643
|
+
**Priority:** P2 · **Size:** L · **Labels:** `area:upstream`,
|
|
644
|
+
`type:research`, `priority:P2`
|
|
645
|
+
|
|
646
|
+
**Why:** The plugin is standalone, but upstream seams would remove the most
|
|
647
|
+
fragile parts.
|
|
648
|
+
|
|
649
|
+
**Status:** packaging plan written (2026-10-19):
|
|
650
|
+
[docs/upstream/promotion-pack.md](upstream/promotion-pack.md) records the
|
|
651
|
+
`packages/wsl/*` layout (ten capability packages plus a thin integration
|
|
652
|
+
package, each with its existing tests), the seam/RFC index with the current
|
|
653
|
+
state of each seam, what `test/composition.test.mjs` boots today and the gaps a
|
|
654
|
+
real-composition boot test would close, and the install proof
|
|
655
|
+
(`e2e:install`, CI on both platforms). The LSP pair is explicitly deferred
|
|
656
|
+
(`UPSTREAM-LSP-SEAM.md`), so the "RFCs/prototypes for all four seams" item is
|
|
657
|
+
satisfied for three and documented as deferred for LSP.
|
|
658
|
+
|
|
659
|
+
**Acceptance:**
|
|
660
|
+
|
|
661
|
+
- [x] A `packages/wsl`-shaped layout is documented, with the package-level
|
|
662
|
+
test split and real-composition boot test (the current one; gaps listed).
|
|
663
|
+
- [x] RFCs/prototypes exist for the session environment resolver
|
|
664
|
+
(promotion-map), the `FileReferenceTraversal` seam (RFC addendum ① plus the
|
|
665
|
+
built consumer), the search provider (promotion-map), and the LSP pair
|
|
666
|
+
(deferred note with trigger).
|
|
667
|
+
- [x] The plugin remains installable and green with none of them accepted
|
|
668
|
+
(`e2e:install` 10/10; CI green on both platforms).
|
|
669
|
+
|
|
670
|
+
**Tests/probes:** `test/composition.test.mjs`; `test/e2e/install.sh`;
|
|
671
|
+
`docs/upstream/promotion-pack.md`.
|
|
672
|
+
|
|
673
|
+
**Depends on:** WSL-101, WSL-204, WSL-205.
|
|
674
|
+
|
|
675
|
+
### WSL-302 — Discoverability and docs entry
|
|
676
|
+
|
|
677
|
+
**Priority:** P2 · **Size:** M · **Labels:** `area:docs`,
|
|
678
|
+
`area:community`, `priority:P2`
|
|
679
|
+
|
|
680
|
+
**Status:** implemented except the visual demo (2026-10-19):
|
|
681
|
+
[docs/QUICKSTART.md](QUICKSTART.md) is the one-page entry (prerequisites,
|
|
682
|
+
install, first session, recipes for Node/Python/Rust/Go and a monorepo, an
|
|
683
|
+
honest Tier 1/Tier 2 table); [docs/PERFORMANCE.md](PERFORMANCE.md) is the
|
|
684
|
+
9p-vs-agent page with the A6/A7 numbers and the GUI-preview baseline, and
|
|
685
|
+
`pnpm run probe:gui-preview` / `fs-queue.mjs` reproduce the latter. No GIF or
|
|
686
|
+
screenshot exists yet (capturing the GUI is not something this repository has
|
|
687
|
+
recorded), so that acceptance item is explicitly open. No DSH plugin
|
|
688
|
+
marketplace was identified, so nothing was submitted.
|
|
689
|
+
|
|
690
|
+
**Why:** "Best" also means easy to find and evaluate.
|
|
691
|
+
|
|
692
|
+
**Acceptance:**
|
|
693
|
+
|
|
694
|
+
- [x] A one-page entry with a five-minute quickstart, compatibility table and
|
|
695
|
+
screenshots (text only; screenshots are the open item).
|
|
696
|
+
- [ ] A demo or GIF showing the picker, terminal, preview and sandbox fact
|
|
697
|
+
(not produced; recorded here and in QUICKSTART).
|
|
698
|
+
- [x] Recipes for Node, Python, Rust/Go and a monorepo; a 9p-vs-plugin
|
|
699
|
+
benchmark page.
|
|
700
|
+
- [ ] The DSH plugin directory/marketplace is updated if one exists (none
|
|
701
|
+
identified).
|
|
702
|
+
|
|
703
|
+
**Tests/probes:** `pnpm run lint:links`; the quickstart's commands are the
|
|
704
|
+
documented Tier 1 path, not executed by CI.
|
|
705
|
+
|
|
706
|
+
**Depends on:** WSL-102, WSL-202.
|
|
707
|
+
|
|
708
|
+
### WSL-303 — Community and support loop
|
|
709
|
+
|
|
710
|
+
**Priority:** P2 · **Size:** S · **Labels:** `area:community`,
|
|
711
|
+
`priority:P2`
|
|
712
|
+
|
|
713
|
+
**Status:** implemented (2026-10-19): `.github/ISSUE_TEMPLATE/` now carries a
|
|
714
|
+
feature-request form, a setup-report form that **requires** the `doctor --json`
|
|
715
|
+
output, and a chooser config (blank issues disabled; private security and
|
|
716
|
+
quickstart links). `SUPPORT.md` documents the public roadmap, the
|
|
717
|
+
three-business-day P1 triage target and the two-to-four-week release cadence;
|
|
718
|
+
the `good first issue` label already exists, and `CONTRIBUTING.md` lists the
|
|
719
|
+
usual shapes and how to claim one.
|
|
720
|
+
|
|
721
|
+
**Acceptance:**
|
|
722
|
+
|
|
723
|
+
- [x] Feature-request and setup-report issue templates; setup reports ask for
|
|
724
|
+
`doctor --json`.
|
|
725
|
+
- [x] Public roadmap and a predictable release cadence (ROADMAP-1.0 + SUPPORT).
|
|
726
|
+
- [x] Triage target for P1 issues (three days, best effort).
|
|
727
|
+
- [x] A "good first issue" label and a contributor path for probes/docs.
|
|
728
|
+
|
|
729
|
+
**Tests/probes:** `pnpm run lint:links`; a process check in the release review.
|
|
730
|
+
|
|
731
|
+
**Depends on:** WSL-102.
|
|
732
|
+
|
|
733
|
+
### WSL-304 — 1.0 readiness
|
|
734
|
+
|
|
735
|
+
**Priority:** P2 · **Size:** M · **Labels:** `area:release`,
|
|
736
|
+
`priority:P2`
|
|
737
|
+
|
|
738
|
+
**Status:** policy subset implemented (2026-10-19): [MIGRATION.md](MIGRATION.md)
|
|
739
|
+
records the configuration freeze (new keys are minors with preserving defaults,
|
|
740
|
+
removals need a boot-time refusal, meaning changes need a migration note; exact
|
|
741
|
+
peer pins are tested by the canary), the deprecation path with the
|
|
742
|
+
`substrate: "share"` and `distro: ''` cases, and the release-gate table with the
|
|
743
|
+
manual legs marked unrun. RELEASING and SUPPORT link it. The empirical legs
|
|
744
|
+
(Tier 1 matrix, aarch64 execution, 30 days without a P0) and the final `1.0.0`
|
|
745
|
+
release notes remain open.
|
|
746
|
+
|
|
747
|
+
**Acceptance:**
|
|
748
|
+
|
|
749
|
+
- [x] Configuration schema frozen; new keys require a minor.
|
|
750
|
+
- [x] Migration and deprecation policy documented.
|
|
751
|
+
- [ ] Tier 1 green, aarch64 executed, install E2E green, no P0 bugs for 30
|
|
752
|
+
days (install E2E is 10/10; the other three are open/unrun).
|
|
753
|
+
- [ ] `1.0.0` release notes list the supported matrix and the known
|
|
754
|
+
limitations (draft waits for the matrix).
|
|
755
|
+
|
|
756
|
+
**Tests/probes:** [MIGRATION.md](MIGRATION.md#gates-a-release-must-clear);
|
|
757
|
+
release gate; full probe suite.
|
|
758
|
+
|
|
759
|
+
**Depends on:** WSL-101, WSL-102, WSL-202, WSL-203.
|
|
760
|
+
|
|
761
|
+
## 10. Release gates
|
|
762
|
+
|
|
763
|
+
A release is ready when:
|
|
764
|
+
|
|
765
|
+
1. `pnpm test` and `pnpm run test:coverage` pass.
|
|
766
|
+
2. The real-machine suite passes on the Tier 1 image.
|
|
767
|
+
3. A native-agent change also passes the aarch64 spike.
|
|
768
|
+
4. The supported-version table and the changelog are updated.
|
|
769
|
+
5. No known documentation drift and no open P0 issue.
|
|
770
|
+
|
|
771
|
+
A 1.0 release additionally requires the WSL-304 checklist.
|
|
772
|
+
|
|
773
|
+
## Evidence and related documents
|
|
774
|
+
|
|
775
|
+
- Current architecture: [ARCHITECTURE.md](ARCHITECTURE.md)
|
|
776
|
+
- Known boundaries: [LIMITATIONS.md](LIMITATIONS.md)
|
|
777
|
+
- Current technical roadmap: [ROADMAP.md](ROADMAP.md)
|
|
778
|
+
- Requirements traceability: [REQUIREMENTS.zh.md](REQUIREMENTS.zh.md)
|
|
779
|
+
- Upstream mapping: [upstream/promotion-map.md](upstream/promotion-map.md)
|
|
780
|
+
- Real-machine suite: [`test/probe/run-all-when-closed.sh`](../test/probe/run-all-when-closed.sh)
|