@bruc3van/dsh-doctor 0.1.6 → 0.5.1
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 +192 -84
- package/README.md +190 -82
- package/migrations/dsh-v0.1.1-rc.2__dsh-v0.1.2-alpha.2/behavior.md +12 -0
- package/migrations/dsh-v0.1.1-rc.2__dsh-v0.1.2-alpha.2/config-rules.json +36 -0
- package/migrations/dsh-v0.1.1-rc.2__dsh-v0.1.2-alpha.2/manifest.json +19 -0
- package/migrations/dsh-v0.1.1-rc.2__dsh-v0.1.2-alpha.2/packages.json +62 -0
- package/migrations/dsh-v0.1.1-rc.2__dsh-v0.1.2-alpha.2/services.json +28 -0
- package/migrations/dsh-v0.1.1-rc.2__dsh-v0.1.2-alpha.2/symbols.json +126 -0
- package/package.json +6 -3
- package/skills/dsh-plugin-upgrade/SKILL.md +98 -0
- package/skills/dsh-plugin-upgrade/evals/evals.json +36 -0
- package/skills/dsh-plugin-upgrade/references/migration-map.md +32 -0
- package/skills/dsh-plugin-upgrade/references/verification.md +27 -0
- package/src/baseline.mjs +69 -0
- package/src/cli.mjs +262 -88
- package/src/config-model.mjs +167 -0
- package/src/doctor.mjs +201 -23
- package/src/i18n.mjs +18 -0
- package/src/migrate-verify.mjs +195 -0
- package/src/migrate.mjs +418 -0
- package/src/migration-catalog.mjs +60 -0
- package/src/recovery.mjs +358 -0
- package/src/redact.mjs +46 -0
- package/src/registry.mjs +61 -0
- package/src/safe-write.mjs +50 -0
package/README.en.md
CHANGED
|
@@ -2,142 +2,250 @@
|
|
|
2
2
|
|
|
3
3
|
[中文](README.md) | English
|
|
4
4
|
|
|
5
|
-
DSH Doctor
|
|
5
|
+
DSH Doctor is a diagnostic and recovery-decision tool for DSH upgrade incidents. For each plugin, it explains the incompatibility, the configuration layer that caused or amplified it, the preferred repair, and whether temporary isolation or removal can be proven safe enough to offer.
|
|
6
6
|
|
|
7
|
-
This is a community-maintained third-party tool
|
|
7
|
+
This is a community-maintained third-party tool, not an official DeepSeek project. Normal diagnosis is read-only and never loads or executes inspected plugin code.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Install
|
|
10
10
|
|
|
11
11
|
Node.js `22.19+` or `24+` is required:
|
|
12
12
|
|
|
13
13
|
```sh
|
|
14
14
|
npm install --global @bruc3van/dsh-doctor
|
|
15
|
-
dsh-doctor
|
|
15
|
+
dsh-doctor diagnose
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Or run without installing:
|
|
19
19
|
|
|
20
20
|
```sh
|
|
21
|
-
npx @bruc3van/dsh-doctor
|
|
21
|
+
npx @bruc3van/dsh-doctor diagnose
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
The default target is `$DSH_HOME/profiles/web`, falling back to `~/.dsh`. Use `--dsh-command /path/to/dsh` for a special installation or `--harness-root /path/to/deepseek-harness` for a source checkout.
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
---
|
|
27
27
|
|
|
28
|
-
##
|
|
28
|
+
## Plugin migration: 0.1.1 → 0.1.2
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
### migrate commands
|
|
31
31
|
|
|
32
|
-
1.
|
|
33
|
-
2. Doctor reports evidence and recommendations by severity and plugin compatibility state.
|
|
34
|
-
3. `dsh-doctor --fix` shows the exact file edits or DSH command plan and waits for confirmation.
|
|
35
|
-
4. After applying confirmed repairs, Doctor runs the full diagnosis again and determines the exit code from the final state.
|
|
32
|
+
Doctor ships a versioned `dsh-v0.1.1-rc.2 → dsh-v0.1.2-alpha.2` migration catalog and exposes three auditable stages:
|
|
36
33
|
|
|
37
|
-
|
|
34
|
+
```sh
|
|
35
|
+
# Stage 1: read-only analysis of source, type imports, manifest, client graph, and build artifacts
|
|
36
|
+
dsh-doctor migrate analyze /path/to/plugin \
|
|
37
|
+
--from dsh-v0.1.1-rc.2 \
|
|
38
|
+
--to dsh-v0.1.2-alpha.2 \
|
|
39
|
+
--harness-root /path/to/deepseek-harness
|
|
40
|
+
|
|
41
|
+
# Stage 2: preview exact rewrites; add --yes to write and create timestamped backups
|
|
42
|
+
dsh-doctor migrate apply /path/to/plugin --safe \
|
|
43
|
+
--harness-root /path/to/deepseek-harness
|
|
44
|
+
dsh-doctor migrate apply /path/to/plugin --safe --yes \
|
|
45
|
+
--harness-root /path/to/deepseek-harness
|
|
46
|
+
|
|
47
|
+
# Stage 3: static, build, and isolated runtime verification in order
|
|
48
|
+
dsh-doctor migrate verify /path/to/plugin --level static \
|
|
49
|
+
--harness-root /path/to/deepseek-harness
|
|
50
|
+
dsh-doctor migrate verify /path/to/plugin --level build --yes \
|
|
51
|
+
--harness-root /path/to/deepseek-harness
|
|
52
|
+
dsh-doctor migrate verify /path/to/plugin --level runtime --yes \
|
|
53
|
+
--harness-root /path/to/deepseek-harness
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Run `dsh-doctor migrations list` to confirm the CLI contains this exact version pair before starting. Without a local install, `npx --package=@bruc3van/dsh-doctor dsh-doctor migrations list` works the same.
|
|
57
|
+
|
|
58
|
+
### Stage details
|
|
59
|
+
|
|
60
|
+
**analyze**: Uses the TypeScript AST so it sees type-only imports that disappear from JavaScript bundles. Also checks package metadata, client graph declarations, and build artifacts. A clean bundle alone does not imply compatibility.
|
|
61
|
+
|
|
62
|
+
**apply --safe**: Rewrites only catalog-confirmed exact-equivalent symbols, pins non-removed DSH development dependencies to the target version, and creates timestamped backups. It may add dependencies required by exact symbol moves but does not automatically change existing peer ranges. Session, Workspace, Conversation, and pending-interaction ownership changes are left as `MIG_SEMANTIC_API_CHANGE` and are never mechanically replaced.
|
|
63
|
+
|
|
64
|
+
**verify**:
|
|
65
|
+
|
|
66
|
+
| Level | What it does |
|
|
67
|
+
|---|---|
|
|
68
|
+
| `static` | Uses the TypeScript AST to inspect source/imports, manifest, client graph, and build artifacts without running project scripts |
|
|
69
|
+
| `build` | Executes plugin build scripts and verifies the artifact (`build` or `pack:check` must succeed; `test`/`typecheck` alone is insufficient proof of a publishable artifact) |
|
|
70
|
+
| `runtime` | Packs the real plugin tarball, installs it under a temporary `DSH_HOME` via the target CLI into a fresh web profile, verifies CLI version, profile manifest, installed package, activated bundle, effective config, and performs an activation smoke; never touches the normal `~/.dsh` |
|
|
38
71
|
|
|
39
|
-
|
|
72
|
+
The highest achievable gate is `analyzed` → `source-migrated` → `artifact-verified` → `runtime-verified`. `runtime-verified` still does not prove real UI, lifecycle, or business behavior. Failed workspaces are retained and reported; successful ones are cleaned up by default.
|
|
40
73
|
|
|
41
|
-
|
|
74
|
+
### Key API changes
|
|
42
75
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
76
|
+
`@deepseek-ai/dsh-client-runtime` was removed with **no aggregate replacement**. Capabilities migrate to:
|
|
77
|
+
|
|
78
|
+
| Concern | 0.1.2 owner | Migration |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| store engine and equality helpers | `dsh-client-store` | exact (catalog-listed symbols) |
|
|
81
|
+
| Cordis client context type | `@deepseek-ai/cordis` `Context` | exact; preserve local aliases |
|
|
82
|
+
| session control / list / commands | `dsh-api-session-controller/client` | semantic (developer judgment required) |
|
|
83
|
+
| workspace state / commands | `dsh-api-workspace-controller/client` | semantic |
|
|
84
|
+
| conversation assembly | `dsh-client-ui-conversation/client` | semantic |
|
|
85
|
+
| pending-interaction state | domain UI packages aggregated by `ui-session` | semantic |
|
|
86
|
+
|
|
87
|
+
`@deepseek-ai/dsh-host-apiproxy` was also removed with no compatible substitute. Browser operations use their natural generated Remote owners through API Remotes/API Gateway contributions.
|
|
88
|
+
|
|
89
|
+
### dsh-plugin-upgrade skill
|
|
90
|
+
|
|
91
|
+
The package ships the [`dsh-plugin-upgrade` skill](skills/dsh-plugin-upgrade/SKILL.md) so coding agents (such as Claude Code) can drive the full migration workflow without collapsing any safety gate. The skill triggers when a plugin developer asks for migration, compatibility assessment, API replacement, peer dependency updates, artifact rebuilds, or DSH 0.1.2 runtime verification.
|
|
92
|
+
|
|
93
|
+
Install it directly from the GitHub repository into a supported coding agent:
|
|
47
94
|
|
|
48
95
|
```sh
|
|
49
|
-
dsh-doctor
|
|
50
|
-
dsh-doctor --lang en
|
|
51
|
-
DSH_DOCTOR_LANG=zh dsh-doctor
|
|
96
|
+
npx skills add bruc3van/dsh-doctor
|
|
52
97
|
```
|
|
53
98
|
|
|
54
|
-
`--
|
|
99
|
+
The repository currently exposes one skill, so the `skills` CLI discovers and installs `dsh-plugin-upgrade`; add `--skill dsh-plugin-upgrade` to select it explicitly. This installs the agent skill, not a global DSH Doctor CLI. The skill uses an existing `dsh-doctor` command when available and falls back to the matching `npx @bruc3van/dsh-doctor` workflow when it is not installed.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Diagnosis
|
|
104
|
+
|
|
105
|
+
### Diagnosis model
|
|
55
106
|
|
|
56
|
-
|
|
107
|
+
`diagnose` composes the configuration from an empty tree in the same order as current DSH:
|
|
108
|
+
|
|
109
|
+
```text
|
|
110
|
+
bundle layers → profile cordis.patch.yml → home cordis.patch.yml → CLI overlays
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The JSON report retains `currentDefaultTree`, `currentEffectiveTree`, field-level provenance, replaced sources, and paths removed by whole-`config` replacement. It diagnoses:
|
|
114
|
+
|
|
115
|
+
- stale patches, missing targets, wrong name assertions;
|
|
116
|
+
- duplicate entry ids and duplicate plugin mounts;
|
|
117
|
+
- higher-layer disabling, structural replacement, whole group/config overrides;
|
|
118
|
+
- bundle declaration conflicts with profile activation state;
|
|
119
|
+
- plugin versions, artifacts, client contracts, dependencies, and runtime issues.
|
|
120
|
+
|
|
121
|
+
Every `pluginDiagnoses[]` object keeps current `status` separate from `recovery`. Being removable does not make an incompatible plugin compatible.
|
|
57
122
|
|
|
58
123
|
```sh
|
|
59
|
-
|
|
60
|
-
dsh-doctor
|
|
61
|
-
dsh-doctor --
|
|
62
|
-
|
|
63
|
-
dsh-doctor --dsh-command /path/to/@deepseek-ai/dsh/lib/bin.js
|
|
124
|
+
dsh-doctor diagnose
|
|
125
|
+
dsh-doctor diagnose --json
|
|
126
|
+
dsh-doctor diagnose --check-updates
|
|
127
|
+
```
|
|
64
128
|
|
|
65
|
-
|
|
66
|
-
dsh-doctor --json
|
|
129
|
+
Only `--check-updates` and `recover` contact the npm registry. Offline diagnosis reports `update.status: "not-checked"` and never turns "not checked" into "no compatible version."
|
|
67
130
|
|
|
68
|
-
|
|
69
|
-
dsh-doctor --fix
|
|
131
|
+
---
|
|
70
132
|
|
|
71
|
-
|
|
72
|
-
|
|
133
|
+
## Recovery decisions
|
|
134
|
+
|
|
135
|
+
### Compatible-version search
|
|
136
|
+
|
|
137
|
+
Doctor checks all published manifests instead of trusting `latest`, then selects the highest version whose declared peer ranges accept the resolvable active DSH packages. This is a manifest-declared candidate only, not proof from a real startup or UI test.
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
dsh-doctor recover @scope/plugin --action check-update
|
|
141
|
+
dsh-doctor recover @scope/plugin --action update # preview
|
|
142
|
+
dsh-doctor recover @scope/plugin --action update --yes # exact version
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Quarantine
|
|
146
|
+
|
|
147
|
+
When no compatible release is available, generate and test a temporary overlay first:
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
dsh-doctor recover @scope/plugin --action quarantine
|
|
151
|
+
dsh-doctor recover @scope/plugin --action quarantine --output ./plugin-quarantine.yml
|
|
152
|
+
dsh --profile web --patch ./plugin-quarantine.yml
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Doctor only generates an overlay when every active entry is precisely mapped, has a unique non-empty id and an exact name assertion, and the bundle does not rewrite entries owned by another layer. Core bundles, declared client dependents, and plugins statically detected as runtime Service providers with unproven dependents require manual review. The overlay disables all known active entries, causing both host and client sources to exit composition.
|
|
156
|
+
|
|
157
|
+
After testing the overlay, persistence is separately gated:
|
|
158
|
+
|
|
159
|
+
```sh
|
|
160
|
+
# Preview the exact diff first
|
|
161
|
+
dsh-doctor recover @scope/plugin --action persist-quarantine --verified
|
|
162
|
+
|
|
163
|
+
# Write to profile/cordis.patch.yml after explicit confirmation
|
|
164
|
+
dsh-doctor recover @scope/plugin --action persist-quarantine --verified --yes
|
|
73
165
|
```
|
|
74
166
|
|
|
75
|
-
|
|
167
|
+
Persistence appends the final winning profile-layer disable override and refuses the write when a home or CLI overlay would still outrank it. It then recomposes the configuration and verifies every exact target is disabled; failed verification returns a nonzero exit code. The write rechecks SHA-256 and atomically replaces the profile patch. An existing patch gets a `.dsh-doctor-<timestamp>.bak`; a first-time file gets a `.rollback.json` containing its target and created-content hash, enabling deletion rollback only while the file is unchanged.
|
|
76
168
|
|
|
77
|
-
|
|
169
|
+
Preview and explicitly restore that backup or rollback record:
|
|
78
170
|
|
|
79
|
-
|
|
171
|
+
```sh
|
|
172
|
+
dsh-doctor recover @scope/plugin --action rollback-quarantine \
|
|
173
|
+
--backup /path/to/cordis.patch.yml.dsh-doctor-...bak
|
|
174
|
+
dsh-doctor recover @scope/plugin --action rollback-quarantine \
|
|
175
|
+
--backup /path/to/cordis.patch.yml.dsh-doctor-...bak --yes
|
|
176
|
+
```
|
|
80
177
|
|
|
81
|
-
|
|
82
|
-
- `risk`: Doctor found a current-version risk, such as a Harness peer range that rejects the new version, a dependency on a removed DSH package, an unsupported Node.js version, or installation drift.
|
|
83
|
-
- `unknown`: The plugin does not declare a Harness compatibility range through `peerDependencies`, or the active package version for a declared peer cannot be resolved. Doctor cannot prove it supports the upgraded DSH, but does not report uncertainty as a failure.
|
|
84
|
-
- `compatible`: The declared compatibility ranges accept the active Harness and no plugin-related errors or warnings were found.
|
|
178
|
+
Doctor only accepts timestamped recovery files belonging to the selected profile patch.
|
|
85
179
|
|
|
86
|
-
|
|
180
|
+
### Safe removal
|
|
87
181
|
|
|
88
|
-
|
|
182
|
+
Removal is always explicit and can never be inferred by legacy `--fix --yes`:
|
|
89
183
|
|
|
90
|
-
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
|
|
94
|
-
- Consistency among the profile `package.json`, the `pnpm-lock.yaml` importer, and installed versions
|
|
95
|
-
- Node.js `engines`, Harness peer ranges, and obsolete DSH dependencies for all direct plugins, including bundle-only and server-side plugins
|
|
96
|
-
- Version drift and stale top-level `@deepseek-ai/dsh-*` packages across the active DSH CLI, Harness workspace, and profile
|
|
97
|
-
- The `platform`, `immediately`, `inject`, `external`, and `./client` export contract for `dsh.client`
|
|
98
|
-
- Consistency between literal `require()` calls in client bundles and external or module suppliers
|
|
99
|
-
- References to removed Harness client packages
|
|
100
|
-
- Third-party plugin peer ranges against actual active Harness versions
|
|
101
|
-
- Real resolution precedence where the Harness installation wins over a profile-local bundle with the same name
|
|
102
|
-
- Static composition of bundle, profile, and home patches in official Harness order, including missing targets, invalid group inserts, and name assertions, without loading plugins
|
|
184
|
+
```sh
|
|
185
|
+
dsh-doctor recover @scope/plugin --action remove # impact preview
|
|
186
|
+
dsh-doctor recover @scope/plugin --action remove --yes
|
|
187
|
+
```
|
|
103
188
|
|
|
104
|
-
|
|
189
|
+
Automatic removal requires a direct profile dependency, a readable lockfile, a non-core bundle, no manual mount or dangling patch that would remain, and a working current DSH CLI. Before the official command runs, Doctor saves a redacted diagnostic snapshot and quarantine overlay:
|
|
105
190
|
|
|
106
|
-
|
|
191
|
+
```sh
|
|
192
|
+
dsh plugin --profile web remove @scope/plugin
|
|
193
|
+
```
|
|
107
194
|
|
|
108
|
-
|
|
109
|
-
- Doctor creates a `.dsh-doctor-<timestamp>.bak` backup before replacing a file atomically through a temporary file in the same directory.
|
|
110
|
-
- External commands use fixed argument arrays and never construct shell commands.
|
|
111
|
-
- `--json --fix --yes` captures subprocess output in the repair result so stdout remains exactly one valid JSON document.
|
|
112
|
-
- Command repairs bind the diagnosed `DSH_HOME` and show the resolved CLI path instead of assuming `dsh` exists on PATH.
|
|
113
|
-
- Each command repair has a 10-minute limit; a timeout terminates that action and marks subsequent actions as skipped.
|
|
114
|
-
- A failed repair stops later actions and preserves backups already created.
|
|
115
|
-
- Doctor runs every diagnostic again after repairs and uses the final state for its exit code.
|
|
195
|
+
It then re-diagnoses dependency, bundle-layer, and active-entry absence and reports the exact rollback install command. Static analysis cannot prove the absence of dynamic Service dependencies, external data, or regressions in every real workflow. Restart the profile and validate its main functions after any bundle update or removal.
|
|
116
196
|
|
|
117
|
-
|
|
197
|
+
---
|
|
118
198
|
|
|
119
|
-
##
|
|
199
|
+
## Baselines
|
|
120
200
|
|
|
121
|
-
|
|
122
|
-
- `1`: Doctor found a problem that may prevent Harness from starting
|
|
123
|
-
- `2`: Invalid arguments, an operational failure, or a failed repair
|
|
201
|
+
Save a baseline before upgrading, then compare plugin versions, compatibility state, Harness state, and finding changes afterwards:
|
|
124
202
|
|
|
125
|
-
|
|
203
|
+
```sh
|
|
204
|
+
dsh-doctor baseline create
|
|
205
|
+
dsh-doctor baseline compare
|
|
126
206
|
|
|
127
|
-
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
|
|
131
|
-
|
|
207
|
+
# Custom path
|
|
208
|
+
dsh-doctor baseline create --output ./before-upgrade.json
|
|
209
|
+
dsh-doctor baseline compare --output ./before-upgrade.json
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The default baseline is `.dsh-doctor/baseline.json` inside the profile. It supplements current evidence and is never required for diagnosis.
|
|
213
|
+
|
|
214
|
+
## Legacy confirmed repairs
|
|
215
|
+
|
|
216
|
+
`--fix` and `--repair` remain compatible with deterministic 0.1.x install, update, and bundle-manifest repairs. They never quarantine or remove a plugin. File actions are hash-checked, backed up, and atomically replaced; commands use fixed argv and the selected `DSH_HOME`.
|
|
217
|
+
|
|
218
|
+
```sh
|
|
219
|
+
dsh-doctor --fix
|
|
220
|
+
dsh-doctor --fix --yes --json
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Output and exit codes
|
|
226
|
+
|
|
227
|
+
Text output supports Chinese and English. `--json` keeps stable English codes and complete non-secret evidence; plugin `config` values and other common secret fields are replaced with `[REDACTED]`.
|
|
228
|
+
|
|
229
|
+
| Exit code | Meaning |
|
|
230
|
+
|---|---|
|
|
231
|
+
| `0` | No blocking error, or an explicit action passed static verification |
|
|
232
|
+
| `1` | A possible startup blocker remains, or recovery verification is incomplete |
|
|
233
|
+
| `2` | Argument, environment, or action execution failure |
|
|
234
|
+
|
|
235
|
+
## Security boundaries
|
|
236
|
+
|
|
237
|
+
- Does not execute third-party plugins or evaluate `!!js`; diagnosis parses configuration structure but redacts every plugin `config` value plus other common secret fields from JSON, baselines, and recovery snapshots; text reports do not print configuration values.
|
|
238
|
+
- Registry compatibility is declarative only; it does not prove a real startup or UI test.
|
|
239
|
+
- Dynamic Service dependencies, external side effects, real UI behavior, and business workflows require user validation.
|
|
240
|
+
- Precise patch edits only operate on structures Doctor can safely parse and locate; ambiguous cases are refused automatically.
|
|
241
|
+
- After adding, updating, or removing a bundle, a running profile does not automatically change its bundle set — a restart is required.
|
|
132
242
|
|
|
133
243
|
## Development
|
|
134
244
|
|
|
135
245
|
```sh
|
|
136
246
|
npm install
|
|
137
247
|
npm run check
|
|
138
|
-
|
|
248
|
+
npm pack --dry-run
|
|
139
249
|
```
|
|
140
250
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
Before each later release, add a Chinese `## vX.Y.Z` entry matching the version tag to `CHANGELOG.md`. Pushing a tag that matches `package.json` makes the workflow publish through OIDC with npm provenance and automatically create or update the GitHub Release from that Chinese entry. The release fails if the entry is missing or contains no Chinese text. No long-lived npm token is required.
|
|
251
|
+
Publishing uses GitHub Actions OIDC and npm provenance. Local implementation and verification do not commit, tag, or publish automatically.
|