@kira905/dsh-ecosystem-panel 0.0.0-stage → 0.4.4
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 +71 -0
- package/LICENSE +661 -0
- package/README.en.md +220 -0
- package/README.md +215 -2
- package/cordis.patch.yml +7 -0
- package/docs/RELEASING.md +68 -0
- package/examples/breaking-symbols.example.json +9 -0
- package/examples/ecosystem-panel.config.example.json +28 -0
- package/examples/labels.example.json +6 -0
- package/examples/patch-manifest.example.json +53 -0
- package/examples/upgrade-rules.example.json +28 -0
- package/lib/client.js +414 -0
- package/lib/config.js +362 -0
- package/lib/host-protocol.js +33 -0
- package/lib/index.js +59 -0
- package/lib/state.js +775 -0
- package/lib/upgrade.js +487 -0
- package/package.json +71 -4
- package/scripts/test-fixture.mjs +251 -0
- package/scripts/verify-source.mjs +278 -0
- package/scripts/verify-state.mjs +103 -0
package/README.en.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# dsh-ecosystem-panel
|
|
2
|
+
|
|
3
|
+
> **Status**: published on npm as `@kira905/dsh-ecosystem-panel` (repository Releases remain available)
|
|
4
|
+
> **Repository**: <https://github.com/kira905/dsh-ecosystem-panel> | <https://gitee.com/kira905/dsh-ecosystem-panel>
|
|
5
|
+
> **License**: AGPL-3.0-only — see [`LICENSE`](./LICENSE)
|
|
6
|
+
> **中文**: [README.md](./README.md)
|
|
7
|
+
|
|
8
|
+
> A **read-only** ecosystem overview panel for a DSH instance: did the plugins load, are the patches
|
|
9
|
+
> still in place, is any skill frontmatter broken, do the dependencies carry an upgrade risk — all on
|
|
10
|
+
> one screen, in three colours (green / yellow / red).
|
|
11
|
+
>
|
|
12
|
+
> It **only diagnoses, it never acts**: it installs nothing, removes nothing, upgrades nothing,
|
|
13
|
+
> changes no configuration, and writes to none of the objects it inspects.
|
|
14
|
+
|
|
15
|
+
A new icon button appears in the sidebar above the settings gear; clicking it opens the panel.
|
|
16
|
+
The server side exposes exactly one read-only endpoint:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
GET /api/dsh-ecosystem-panel/state
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Design basis
|
|
23
|
+
|
|
24
|
+
This component is one implementation of the operational system described in
|
|
25
|
+
[ops-handoff-design](https://github.com/kira905/ops-handoff-design), with the design basis
|
|
26
|
+
(the fixed four questions that documentation repository defines):
|
|
27
|
+
|
|
28
|
+
- **Why it exists and where its boundary is** → see *Design Discipline for a Read-Only Monitoring Panel* **§1 the questions the panel must answer**, **§2 display discipline (not probeable + reason)**; this component's six checks are one landing of that discipline
|
|
29
|
+
- **Its compatibility window with the host** → see *Multi-machine Handoff and Cloud Relay* **§4.5 "compatibility requirements"** (see also §6 "Compatibility" in this README)
|
|
30
|
+
- **This component's own pitfalls and measurements** → the "Known limitations" section of this README; see also *Design Discipline for a Read-Only Monitoring Panel* **§7 summary of design lessons** (where the three cases of "silently not reporting" came from)
|
|
31
|
+
- **Documentation repository** → Gitee (mirror) <https://gitee.com/kira905/ops-handoff-design>
|
|
32
|
+
| GitHub (primary) <https://github.com/kira905/ops-handoff-design>
|
|
33
|
+
(the documentation repository's component index points back to this repository; the two repositories link to each other and version independently)
|
|
34
|
+
|
|
35
|
+
> Design documents carry no concrete repository addresses (a hard-coded address becomes a dead link);
|
|
36
|
+
> the implementation list is kept in the documentation repository's component index — this repository
|
|
37
|
+
> only links back to the sections.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 1. What it looks at (six classes plus one optional one)
|
|
42
|
+
|
|
43
|
+
| Class | Data source | Judgement | When data is missing |
|
|
44
|
+
|---|---|---|---|
|
|
45
|
+
| ① **bundle plugins** | the profile's `package.json` (`dsh.profile.bundles` + `dependencies`) + each package entity's `package.json` + the boot manifest of the host home page | whether the entity exists / whether the declared version drifts from the entity version / client capability declared but not loaded in boot = red | boot cannot be fetched ⇒ shows "load state unknown" (yellow), **not treated as loaded** |
|
|
46
|
+
| ② **patch insert plugins** | the `insert` entries in the profile's `cordis.patch.yml` | whether the entity directory can be resolved (profile layer → shared fallback layer); entries under `disabled` are marked yellow | the YAML parser is unavailable ⇒ says "not parseable" explicitly instead of treating it as an empty list |
|
|
47
|
+
| ③ **patch health** | **the patch manifest you supply** (an external JSON) | a marker-string scan, entry by entry: a missing `contains` = a customisation was overwritten (yellow); the target file is gone = red; a `notContains` hit = leftovers | the manifest is not configured ⇒ shows "not configured ⇒ cannot be judged" (yellow), **never "0 patches"** |
|
|
48
|
+
| ④ **skills** | the frontmatter of `skills/*/SKILL.md` under the data root | missing `name` / `description`, frontmatter parse failure | the directory does not exist ⇒ reports `skillsDirOk=false` |
|
|
49
|
+
| ⑤ **upgrade check** | local entity versions + the latest npm registry version (24 h file cache) + the wording of your rule table | the colour is decided by an **external read-only CLI**; this panel only renders it (when that is unavailable it shows "tier unavailable" + the reason, and **never guesses a colour**) | no CLI configured ⇒ `unknown` on every row + the reason |
|
|
50
|
+
| ⑥ **decoupling health** | **the external check script you supply** (reused by dynamic `import` of its exported function — the judgement is not copied) | R1 static import of a host symbol = red; dynamic import / dependencies not driven to zero = yellow | no script configured ⇒ one yellow row + configuration guidance |
|
|
51
|
+
| ⑦ **cross-table admission consistency** (optional) | **the external validator you supply** | three states, explicitly enumerated: `ok / fail / unavailable`; a missing `asOf` is judged `unavailable` | not configured ⇒ `unavailable` (**not** a green 0/0/0) |
|
|
52
|
+
|
|
53
|
+
**Design red line (throughout the repository)**: anything that cannot be read is shown as "not probeable + reason" — **never 0, never a pretend all-green**.
|
|
54
|
+
The panel meta also carries a **self-attestation of configuration provenance** (which layer each configuration key was actually read from: CLI / environment variable / config file / auto-detection / built-in default). Look at it first when troubleshooting on a different machine.
|
|
55
|
+
|
|
56
|
+
## 2. Prerequisites
|
|
57
|
+
|
|
58
|
+
- A DSH instance (web profile); for the host package line see the compatibility table in §6
|
|
59
|
+
- Node ≥ 18.17 (it uses the built-in `fetch` / `AbortSignal.timeout`)
|
|
60
|
+
- **A YAML parser (`js-yaml`)**: provided by the host profile's dependency chain (normally shipped with the host package). When it cannot be resolved, classes ② and ④ say "not parseable" explicitly; the other four are unaffected
|
|
61
|
+
- The optional three or four external scripts (decoupling check, tier CLI, cross-table validator, adapter-layer consistency checker) — **it runs without them**; the corresponding classes degrade. This repository does not ship these scripts (they belong to your own check system)
|
|
62
|
+
|
|
63
|
+
## 3. Installing in three steps
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# 1. Install it into the profile (npm package name: @kira905/dsh-ecosystem-panel)
|
|
67
|
+
npm install @kira905/dsh-ecosystem-panel --prefix "<data root>/profiles/web"
|
|
68
|
+
# offline / editing the source: clone this repository to
|
|
69
|
+
# "<data root>/profiles/web/node_modules/@kira905/dsh-ecosystem-panel"
|
|
70
|
+
|
|
71
|
+
# 2. Register it in the profile's package.json:
|
|
72
|
+
# "dependencies": add "@kira905/dsh-ecosystem-panel": "0.4.4"
|
|
73
|
+
# "dsh.profile.bundles": add "@kira905/dsh-ecosystem-panel" to the array
|
|
74
|
+
|
|
75
|
+
# 3. Restart DSH (this plugin has no hot reload), then open the GUI: the panel button should appear
|
|
76
|
+
# above the settings gear in the sidebar
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Verification (no GUI needed):
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
node "<data root>/profiles/web/node_modules/@kira905/dsh-ecosystem-panel/scripts/verify-state.mjs"
|
|
83
|
+
# the terminal should print the six classes plus the configuration-provenance self-attestation
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
> The package is published on npm (`@kira905/dsh-ecosystem-panel`): `npm install` only fetches the
|
|
87
|
+
> package itself (`dependencies` is empty; `js-yaml` comes from the host profile). Earlier releases
|
|
88
|
+
> shipped Releases only; this version (`0.4.4`) is the first to ship under the scoped npm name.
|
|
89
|
+
|
|
90
|
+
## 4. Configuration
|
|
91
|
+
|
|
92
|
+
Precedence (**per key, independently**): `explicit input (plugin config / call argument)` > `environment variable` > `config file` > `auto-detection` > `built-in default`.
|
|
93
|
+
|
|
94
|
+
### 4.1 Environment variables
|
|
95
|
+
|
|
96
|
+
| Variable | Purpose | Default |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| `DSH_ECOSYSTEM_PANEL_HOME` | DSH data root | `os.homedir()/.dsh` (`DSH_HOME` has the same effect, at lower precedence) |
|
|
99
|
+
| `DSH_ECOSYSTEM_PANEL_PROFILE` | profile name | `web` |
|
|
100
|
+
| `DSH_ECOSYSTEM_PANEL_WEB_URL` | base URL of this instance (used to fetch the boot manifest) | `DSH_WEB_URL`, otherwise `http://127.0.0.1:3080` |
|
|
101
|
+
| `DSH_ECOSYSTEM_PANEL_TOOLS_DIR` | external tools directory (**never auto-detected**) | empty ⇒ the classes that depend on it degrade |
|
|
102
|
+
| `DSH_ECOSYSTEM_PANEL_MAIN_NM` | host package `node_modules` | detected from the global npm layout; unusable when detection fails |
|
|
103
|
+
| `DSH_ECOSYSTEM_PANEL_CONFIG` | path to the JSON configuration file | empty |
|
|
104
|
+
| `DSH_ECOSYSTEM_PANEL_CACHE_FILE` | upgrade-check cache file | `<data root>/ecosystem-panel-upgrade-cache.json` |
|
|
105
|
+
| `DSH_ECOSYSTEM_PANEL_DECOUPLING_SCRIPT` | decoupling check script | `<toolsDir>/check-decoupling.mjs` |
|
|
106
|
+
| `DSH_ECOSYSTEM_PANEL_TRIAGE_CLI` | read-only upgrade tier CLI | `<toolsDir>/upgrade-triage-cli.mjs` |
|
|
107
|
+
| `DSH_ECOSYSTEM_PANEL_REGISTRY_AUDIT_LIB` | cross-table admission validator | `<toolsDir>/registry-audit.mjs` |
|
|
108
|
+
| `DSH_ECOSYSTEM_PANEL_HOST_ADAPTER_SYNC` | adapter-layer consistency checker (optional) | `<toolsDir>/sync-host-adapter.mjs` |
|
|
109
|
+
| `DSH_ECOSYSTEM_PANEL_PATCH_MANIFEST_FILE` | patch manifest JSON | empty ⇒ ③ shows "not configured" |
|
|
110
|
+
| `DSH_ECOSYSTEM_PANEL_UPGRADE_RULES_FILE` | upgrade rule table JSON | empty |
|
|
111
|
+
| `DSH_ECOSYSTEM_PANEL_BREAKING_SYMBOLS_FILE` | breaking-symbol table JSON | empty |
|
|
112
|
+
| `DSH_ECOSYSTEM_PANEL_LABELS_FILE` | package name → one-line description, JSON | empty (an unregistered package simply has no description) |
|
|
113
|
+
| `DSH_ECOSYSTEM_PANEL_DISABLED_GROUPS` | classes disabled as a whole (comma-separated) | all enabled |
|
|
114
|
+
| `DSH_ECOSYSTEM_PANEL_WEBSERVER_SERVICE` | host web server service name | `webServer` |
|
|
115
|
+
|
|
116
|
+
### 4.2 Configuration file and examples
|
|
117
|
+
|
|
118
|
+
`examples/` holds five samples you can copy directly:
|
|
119
|
+
|
|
120
|
+
| File | Configuration it covers |
|
|
121
|
+
|---|---|
|
|
122
|
+
| `ecosystem-panel.config.example.json` | overview (where each key lives and what shape it takes) |
|
|
123
|
+
| `patch-manifest.example.json` | ③ patch manifest (all three shapes — `checks` / `special` / `retired` — have examples; `${HOME}` can be used as a placeholder inside strings) |
|
|
124
|
+
| `upgrade-rules.example.json` | ⑤ rule-table wording (`verdict` is only a wording category, it does not decide the colour) |
|
|
125
|
+
| `breaking-symbols.example.json` | reference table of breaking symbols in the host package |
|
|
126
|
+
| `labels.example.json` | package name → one-line description |
|
|
127
|
+
|
|
128
|
+
Usage:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
DSH_ECOSYSTEM_PANEL_CONFIG=/path/to/my.config.json # points at the copy you edited
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 4.3 Degradation semantics (important)
|
|
135
|
+
|
|
136
|
+
- **Not configured ≠ absent**: with no manifest configured, ③ shows "not configured ⇒ cannot be judged" and never "0 patches, all green"; ⑥⑦ and ⑤ work the same way (each carries configuration guidance).
|
|
137
|
+
- **Cannot be fetched**: when the boot manifest cannot be fetched from the host home page, ① marks only the "unknown" as yellow and puts the raw fetch error into `meta.bootError`.
|
|
138
|
+
- **Disabled**: if a class is genuinely not needed, put it into `disabledGroups` — the panel then shows a "disabled by configuration" notice (clearer than silently disappearing, and not counted in the summary).
|
|
139
|
+
- A configuration parse failure (a broken manifest JSON, say) does not crash the panel: `meta.configErrors` carries the reason and that key falls back to its default.
|
|
140
|
+
|
|
141
|
+
## 5. Interface
|
|
142
|
+
|
|
143
|
+
- Each of the six classes has its own tab; the small dot on a tab = the worst state of that class (red > yellow > green)
|
|
144
|
+
- Clicking "refresh" fetches the data again; `GET /state?refresh=1` forces a fresh lookup of the npm latest version (otherwise the 24 h cache is used)
|
|
145
|
+
- Colours: green = healthy / yellow = at risk or not judgeable / red = abnormal (a missing patch insert entity, for instance)
|
|
146
|
+
- The panel's title and footer note can be overridden by configuration (`text.title` / `text.note` / `text.tabs`, delivered by the server through `meta.ui`)
|
|
147
|
+
|
|
148
|
+
## 6. Compatibility
|
|
149
|
+
|
|
150
|
+
| Host package line | Status | Basis |
|
|
151
|
+
|---|---|---|
|
|
152
|
+
| **`0.2.0-rc.2`** | ✅ **Measured end-to-end (2026-10-16)** | **The baseline of the range this version declares in `peerDependencies`**: installed and exercised for real on an isolated instance (separate data root + port 3090) — `scripts/verify-state.mjs` (read-only, six check classes) **completed with rc=0**, reading that instance's data root and configuration provenance; the client half `client.js` appears in the plugin resource list of the instance's startup HTML |
|
|
153
|
+
| later `0.2.x` | ⚠️ **Not measured; no promise** (declared upper bound `<0.3.0`) | — |
|
|
154
|
+
| the `0.1.1-rc.2` / `0.1.5` lines | ⚠️ Historical static check (**this version no longer declares a 0.1.x range**) | see this section in `v0.4.3` and earlier |
|
|
155
|
+
| the **readings** of the upgrade-check / decoupling-health cards | ⚠️ **Not calibrated on a 0.2.0 instance** | Since 0.1.5, client resources use a "roster + merged URL" scheme; whether these two cards read it completely is unverified — **the most likely symptom is conservative readings, not a crash** |
|
|
156
|
+
| other | Unknown | self-test required |
|
|
157
|
+
|
|
158
|
+
## 7. Known limitations
|
|
159
|
+
|
|
160
|
+
1. **`js-yaml` is provided by the host** — when it cannot be resolved, classes ② and ④ show "not parseable" (no false green), but that also means they cannot be checked.
|
|
161
|
+
2. **The boot manifest is fetched from the host home page**, from the inline `__DSH_BOOT__` block — if the host changes that projection, ①'s "load state" becomes unknown (yellow).
|
|
162
|
+
3. **③'s verdict depends entirely on the manifest you supply**: this repository **embeds no patch manifest** for any environment, so a wrong manifest produces wrong reports.
|
|
163
|
+
4. **⑤'s colour does not come from this panel**: it comes from the tier CLI you configure (the single source of judgement). The panel only renders it and never guesses a colour.
|
|
164
|
+
5. **⑥⑦ depend on external scripts**, which this repository does not ship; when they are not configured the corresponding classes only show a degradation notice.
|
|
165
|
+
6. **The upgrade check reaches the npm registry** (`registry.npmjs.org`) and caches its result for 24 h; when offline it shows "remote lookup failed" and keeps using the cache.
|
|
166
|
+
7. **Read-only**: the panel has no write entry point at all (the only file it writes is the upgrade check's own cache).
|
|
167
|
+
8. **The front end supports the web platform only** (`dsh.client.inject` is empty; it depends on no client package).
|
|
168
|
+
9. **The interface copy is Chinese**, overridable through the `text` configuration; there is no built-in language switch.
|
|
169
|
+
10. **No dedicated mobile optimisation** (the panel width adapts, but buttons and touch interaction have not been tested specifically).
|
|
170
|
+
|
|
171
|
+
## 8. Repository layout
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
lib/index.js server side: registers the read-only route
|
|
175
|
+
lib/state.js the six-class aggregation logic (every data source goes through the config layer and degrades explicitly)
|
|
176
|
+
lib/upgrade.js ⑤ the upgrade check (local facts + npm cache → external read-only CLI → rendering)
|
|
177
|
+
lib/config.js the config layer (precedence resolution + placeholder expansion + provenance self-attestation)
|
|
178
|
+
lib/host-protocol.js host protocol constants (this plugin uses only the single service name webServer)
|
|
179
|
+
lib/client.js browser side: sidebar button + panel (zero imports)
|
|
180
|
+
cordis.patch.yml bundle patch (mounts the plugin into the host)
|
|
181
|
+
scripts/verify-source.mjs pre-release static verification (syntax + config-layer behaviour + sanitization scan)
|
|
182
|
+
scripts/test-fixture.mjs end-to-end fixture on a clean temporary path (with assertions for degradation on missing data)
|
|
183
|
+
scripts/verify-state.mjs read-only state verifier (no GUI needed)
|
|
184
|
+
examples/ five configuration examples
|
|
185
|
+
docs/RELEASING.md release conventions and checklist
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## 9. Self-checks
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
node scripts/verify-source.mjs . # syntax + config-layer behaviour + sanitization scan (must be run before a release)
|
|
192
|
+
node scripts/test-fixture.mjs # end-to-end fixture: needs no real installation, everything is built in a temporary directory
|
|
193
|
+
node scripts/verify-state.mjs # read-only health check of the current instance (prints the six classes + configuration provenance)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
`test-fixture.mjs` builds a minimal data root on the spot (a fake profile / fake plugin entities / fake skills / four external tool stubs), asserts that all six classes produce a result, and specifically verifies that "missing data always degrades explicitly".
|
|
197
|
+
|
|
198
|
+
## 10. Related components
|
|
199
|
+
|
|
200
|
+
Sibling components in the same DSH ecosystem — separate repositories, separate versions and separate licenses. They all link back to the same documentation repository,
|
|
201
|
+
[`ops-handoff-design`](https://github.com/kira905/ops-handoff-design)
|
|
202
|
+
(Gitee mirror: <https://gitee.com/kira905/ops-handoff-design>):
|
|
203
|
+
|
|
204
|
+
| Repository | What it does | How it relates to this one |
|
|
205
|
+
|---|---|---|
|
|
206
|
+
| `dsh-ecosystem-panel` | Read-only ecosystem overview panel | **this repo** |
|
|
207
|
+
| [`dsh-butler-archive`](https://github.com/kira905/dsh-butler-archive) | Session archiving (list / preview / restore / delete, plus optional auto-archive) | It is **one of the objects class ③ observes**: it registers through an `insert` in `cordis.patch.yml`, and this panel reports red when its entity is missing |
|
|
208
|
+
| [`dsh-session-title-live`](https://github.com/kira905/dsh-session-title-live) | Session titles that track the conversation live | It also registers through an `insert` in `cordis.patch.yml` (no client half); "did the plugin actually load" is answered by class ① of this panel |
|
|
209
|
+
| [`dsh-diagnostic-tools`](https://github.com/kira905/dsh-diagnostic-tools) | Diagnostic forensics toolkit: dependency-closure check + session image attachment reconciliation | Complementary division of labour: this panel answers **"how is it today"** (continuous, read-only, three colours) while that one answers **"what exactly is broken, and how do I fix it"** (offline, re-runnable, with fixes and a rollback list) — both only diagnose |
|
|
210
|
+
| [`dsh-task-board-local`](https://github.com/kira905/dsh-task-board-local) | Self-maintained task board (a card = a real session + a human acceptance gate) | It is a **typical subject of classes ① / ③**: built in-house and registered through an `insert` in `cordis.patch.yml` — the two silent failure modes, plugin load state and patch health, are visible at a glance on this panel |
|
|
211
|
+
| [`dsh-firstaid`](https://github.com/kira905/dsh-firstaid) | Zero-dependency incident toolkit: will not start / hangs / a change to undo / deleted data — four on-site scenarios behind one entry point | The contingency plan: **this panel may itself be the broken one** (if the panel will not start, or cannot fetch its data, you cannot use it to diagnose itself), and that is when the other one takes over |
|
|
212
|
+
|
|
213
|
+
> There are **no code dependencies** between the components and they share no runtime — they point at each other because they answer the same class of question for the same kind of person (running an agent on your own machine over the long term: install it, find it, see it, diagnose it). Installing one does not affect the others.
|
|
214
|
+
|
|
215
|
+
## 11. License
|
|
216
|
+
|
|
217
|
+
**AGPL-3.0-only plus a commercial license** (dual licensing; see the full text in `LICENSE`; the `license` field in `package.json` carries `AGPL-3.0-only`).
|
|
218
|
+
|
|
219
|
+
- ⚠️ **The AGPL does not forbid commercial use by itself**: you may use, modify and redistribute it freely (commercial use included), but **if you make a modified version available to others over a network, you must offer the corresponding source under the AGPL as well**;
|
|
220
|
+
- "+ a commercial license" = **dual licensing**: obtain a **commercial license** if you need it in a **closed-source** or **commercial** setting (where AGPL's copyleft obligations do not apply) — there is no public contact address yet, so **please reach out by opening an issue**.
|
package/README.md
CHANGED
|
@@ -1,3 +1,216 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-ecosystem-panel
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **English**: [README.en.md](./README.en.md)
|
|
4
|
+
|
|
5
|
+
> 给 DSH 实例装一块**只读**的生态总览面板:插件有没有加载、补丁还在不在、技能 frontmatter 有没有写坏、
|
|
6
|
+
> 依赖有没有升级风险 —— 一屏看完,🟢🟡🔴 三色。
|
|
7
|
+
>
|
|
8
|
+
> 它**只诊断,不动手**:不装包、不卸包、不升级、不改配置、不写任何被体检对象。
|
|
9
|
+
|
|
10
|
+
侧边栏底部「设置」齿轮上方会多一个图标按钮,点开就是面板;服务端只暴露一个只读接口:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
GET /api/dsh-ecosystem-panel/state
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## 设计依据
|
|
17
|
+
|
|
18
|
+
本组件是「[ops-handoff-design](https://github.com/kira905/ops-handoff-design)」所述运维体系的一个实现,
|
|
19
|
+
设计依据(对应文档仓约定的固定四问):
|
|
20
|
+
|
|
21
|
+
- **它为什么存在、边界在哪** → 见《只读监控面板的设计纪律》**§1 面板要回答的问题**、**§2 显示纪律(不可探测 + 原因)**;本组件的六类体检正是那份纪律的一次落地
|
|
22
|
+
- **它与宿主版本的兼容区间** → 见《多机交接与云中继》**§4.5「兼容性要求」**(另见本 README 第 6 节「兼容性」)
|
|
23
|
+
- **本组件特有的坑与实测** → 见本 README「已知限制」一节;另见《只读监控面板的设计纪律》**§7 设计教训汇总**(三次"静默不报"的来历)
|
|
24
|
+
- **文档仓地址** → Gitee(镜像)<https://gitee.com/kira905/ops-handoff-design>
|
|
25
|
+
| GitHub(主)<https://github.com/kira905/ops-handoff-design>
|
|
26
|
+
(文档仓的组件索引表回指本仓;两仓互链、版本各自独立)
|
|
27
|
+
|
|
28
|
+
> 设计稿里不写具体仓库地址(写死即死链),实现清单统一收在文档仓的组件索引表里——本仓只负责回链章节。
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 1. 它看什么(六类 + 一个可选类)
|
|
33
|
+
|
|
34
|
+
| 类目 | 数据来源 | 判定 | 数据缺失时 |
|
|
35
|
+
|---|---|---|---|
|
|
36
|
+
| ① **bundle 插件** | profile 的 `package.json`(`dsh.profile.bundles` + `dependencies`)+ 各包实体 `package.json` + 宿主首页的 boot 清单 | 实体在不在 / 声明版本与实体版本是否漂移 / 声明了 client 能力但 boot 里没加载 = 🔴 | boot 抓不到 ⇒ 显示「加载状态未知」(黄),**不当作已加载** |
|
|
37
|
+
| ② **patch insert 插件** | profile 的 `cordis.patch.yml` 里的 `insert` 条目 | 实体目录能否解析到(profile 层 → 共享 fallback 层);被 `disabled` 的标黄 | YAML 解析器不可用 ⇒ 明说「不可解析」,不当成空清单 |
|
|
38
|
+
| ③ **补丁健康** | **你提供的补丁清单**(外置 JSON) | 逐条做特征串扫描:`contains` 缺一个 = 定制被冲掉(黄);目标文件没了 = 🔴;`notContains` 命中 = 残留 | 清单没配 ⇒ 显示「未配置 ⇒ 不可判定」(黄),**不显示"0 个补丁"** |
|
|
39
|
+
| ④ **技能** | 数据根下 `skills/*/SKILL.md` 的 frontmatter | 缺 `name` / `description`、frontmatter 解析失败 | 目录不存在 ⇒ 报 `skillsDirOk=false` |
|
|
40
|
+
| ⑤ **升级体检** | 本地实体版本 + npm registry 最新版(24h 文件缓存)+ 你的规则表文案 | 颜色由**外部只读 CLI** 判定;本面板只渲染(拿不到就显示「档位不可用」+ 原因,**绝不猜颜色**) | 没配 CLI ⇒ 每行 `unknown` + 原因 |
|
|
41
|
+
| ⑥ **解耦健康** | **你提供的外部检查脚本**(动态 import 复用其导出函数,不复制判定) | R1 静态 import 宿主符号 = 🔴;动态导入/依赖未归零 = 🟡 | 没配脚本 ⇒ 一条 🟡 + 配置指引 |
|
|
42
|
+
| ⑦ **跨表准入一致性**(可选) | **你提供的外部校验器** | 三态显式枚举 `ok / fail / unavailable`;`asOf` 缺失即判 `unavailable` | 没配 ⇒ `unavailable`(**不是** 0/0/0 绿) |
|
|
43
|
+
|
|
44
|
+
**设计红线(贯穿全仓)**:读不到的东西一律显示「不可探测 + 原因」,**绝不显示 0、绝不假装全绿**。
|
|
45
|
+
面板 meta 里还带一份**配置来源自证**(每个配置键到底是从 CLI / 环境变量 / 配置文件 / 自动探测 / 默认值
|
|
46
|
+
哪一层读到的),换机器排障时先看它。
|
|
47
|
+
|
|
48
|
+
## 2. 前置条件
|
|
49
|
+
|
|
50
|
+
- 一个 DSH 实例(web profile),主包线见 §6 兼容性表
|
|
51
|
+
- Node ≥ 18.17(用到了内置 `fetch` / `AbortSignal.timeout`)
|
|
52
|
+
- **YAML 解析器(`js-yaml`)**:由宿主 profile 的依赖链提供(通常随主包自带)。解析不到时 ②④
|
|
53
|
+
两类会显式显示「不可解析」,其它四类不受影响
|
|
54
|
+
- 可选的三个/四个外部脚本(解耦检查、档位 CLI、跨表校验器、适配层一致性校验器)——**没有也能跑**,
|
|
55
|
+
对应类目会降级;本仓不附带这些脚本(它们属于你自己的体检体系)
|
|
56
|
+
|
|
57
|
+
## 3. 安装三步
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# ① 装进 profile(npm 包名:@kira905/dsh-ecosystem-panel)
|
|
61
|
+
npm install @kira905/dsh-ecosystem-panel --prefix "<数据根>/profiles/web"
|
|
62
|
+
# 离线 / 要改源码时:把本仓 clone 到
|
|
63
|
+
# "<数据根>/profiles/web/node_modules/@kira905/dsh-ecosystem-panel"
|
|
64
|
+
|
|
65
|
+
# ② 注册:profile 的 package.json 里
|
|
66
|
+
# "dependencies": 加一条 "@kira905/dsh-ecosystem-panel": "0.4.4"
|
|
67
|
+
# "dsh.profile.bundles": 数组里加 "@kira905/dsh-ecosystem-panel"
|
|
68
|
+
|
|
69
|
+
# ③ 重启 DSH(本插件没有热加载),然后打开 GUI:侧边栏齿轮上方应出现面板按钮
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
验证(不依赖 GUI):
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
node "<数据根>/profiles/web/node_modules/@kira905/dsh-ecosystem-panel/scripts/verify-state.mjs"
|
|
76
|
+
# 终端里应打印六类结果 + 配置来源自证
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
> 包已发布到 npm(`@kira905/dsh-ecosystem-panel`):`npm install` 只装它自己(`dependencies` 为空,
|
|
80
|
+
> `js-yaml` 由宿主 profile 提供)。早期版本只发 Release、不进 npm;本版(`0.4.4`)起以 scope 包名发布。
|
|
81
|
+
|
|
82
|
+
## 4. 配置
|
|
83
|
+
|
|
84
|
+
优先级(**每个键独立**):`显式传入(插件 config / 调用参数)` > `环境变量` > `配置文件` > `自动探测` > `内置默认`。
|
|
85
|
+
|
|
86
|
+
### 4.1 环境变量
|
|
87
|
+
|
|
88
|
+
| 变量 | 作用 | 默认 |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| `DSH_ECOSYSTEM_PANEL_HOME` | DSH 数据根 | `os.homedir()/.dsh`(`DSH_HOME` 同效、优先级更低) |
|
|
91
|
+
| `DSH_ECOSYSTEM_PANEL_PROFILE` | profile 名 | `web` |
|
|
92
|
+
| `DSH_ECOSYSTEM_PANEL_WEB_URL` | 本实例基址(抓 boot 清单用) | `DSH_WEB_URL`,否则 `http://127.0.0.1:3080` |
|
|
93
|
+
| `DSH_ECOSYSTEM_PANEL_TOOLS_DIR` | 外部工具目录(**不自动探测**) | 空 ⇒ 依赖它的类目降级 |
|
|
94
|
+
| `DSH_ECOSYSTEM_PANEL_MAIN_NM` | 宿主主包 node_modules | 按全局 npm 布局探测;探测不到即判不可用 |
|
|
95
|
+
| `DSH_ECOSYSTEM_PANEL_CONFIG` | 配置文件 JSON 路径 | 空 |
|
|
96
|
+
| `DSH_ECOSYSTEM_PANEL_CACHE_FILE` | 升级体检缓存文件 | `<数据根>/ecosystem-panel-upgrade-cache.json` |
|
|
97
|
+
| `DSH_ECOSYSTEM_PANEL_DECOUPLING_SCRIPT` | 解耦检查脚本 | `<toolsDir>/check-decoupling.mjs` |
|
|
98
|
+
| `DSH_ECOSYSTEM_PANEL_TRIAGE_CLI` | 升级档位只读 CLI | `<toolsDir>/upgrade-triage-cli.mjs` |
|
|
99
|
+
| `DSH_ECOSYSTEM_PANEL_REGISTRY_AUDIT_LIB` | 跨表准入校验器 | `<toolsDir>/registry-audit.mjs` |
|
|
100
|
+
| `DSH_ECOSYSTEM_PANEL_HOST_ADAPTER_SYNC` | 适配层一致性校验器(可选) | `<toolsDir>/sync-host-adapter.mjs` |
|
|
101
|
+
| `DSH_ECOSYSTEM_PANEL_PATCH_MANIFEST_FILE` | 补丁清单 JSON | 空 ⇒ ③ 显示「未配置」 |
|
|
102
|
+
| `DSH_ECOSYSTEM_PANEL_UPGRADE_RULES_FILE` | 升级规则表 JSON | 空 |
|
|
103
|
+
| `DSH_ECOSYSTEM_PANEL_BREAKING_SYMBOLS_FILE` | 断裂符号表 JSON | 空 |
|
|
104
|
+
| `DSH_ECOSYSTEM_PANEL_LABELS_FILE` | 包名 → 一句话简介 JSON | 空(没登记的包只是没有简介) |
|
|
105
|
+
| `DSH_ECOSYSTEM_PANEL_DISABLED_GROUPS` | 整组停用的类目(逗号分隔) | 全开 |
|
|
106
|
+
| `DSH_ECOSYSTEM_PANEL_WEBSERVER_SERVICE` | 宿主 web server 服务名 | `webServer` |
|
|
107
|
+
|
|
108
|
+
### 4.2 配置文件与示例
|
|
109
|
+
|
|
110
|
+
`examples/` 下有五份可直接抄的示例:
|
|
111
|
+
|
|
112
|
+
| 文件 | 对应配置 |
|
|
113
|
+
|---|---|
|
|
114
|
+
| `ecosystem-panel.config.example.json` | 总览(各键的位置与形态) |
|
|
115
|
+
| `patch-manifest.example.json` | ③ 补丁清单(`checks` / `special` / `retired` 三种形态都有例子,字符串里可用 `${HOME}` 占位符) |
|
|
116
|
+
| `upgrade-rules.example.json` | ⑤ 规则表文案(`verdict` 只是文案分类,不决定颜色) |
|
|
117
|
+
| `breaking-symbols.example.json` | 宿主主包断裂符号参考底表 |
|
|
118
|
+
| `labels.example.json` | 包名 → 一句话简介 |
|
|
119
|
+
|
|
120
|
+
用法:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
DSH_ECOSYSTEM_PANEL_CONFIG=/path/to/my.config.json # 指向你抄过去改的那份
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 4.3 降级语义(重要)
|
|
127
|
+
|
|
128
|
+
- **没配 ≠ 没有**:③ 未配清单时显示「未配置 ⇒ 不可判定」,不会显示"0 个补丁全绿";
|
|
129
|
+
⑥⑦ 与 ⑤ 同理(都带配置指引)。
|
|
130
|
+
- **抓不到**:宿主首页抓不到 boot 清单时,① 只把"未知"标黄,并把抓取错误原文放进 `meta.bootError`。
|
|
131
|
+
- **停用**:确实不需要某一类,就把它写进 `disabledGroups` —— 面板会显示一条「已按配置停用」的提示项
|
|
132
|
+
(比静默消失更清楚,且不计入汇总)。
|
|
133
|
+
- 配置解析失败(比如清单 JSON 坏了)不会让面板崩:`meta.configErrors` 里能看到原因,该键回落默认。
|
|
134
|
+
|
|
135
|
+
## 5. 界面
|
|
136
|
+
|
|
137
|
+
- 六类各占一张标签卡(Tab),Tab 上的小圆点 = 该类最差状态(红 > 黄 > 绿)
|
|
138
|
+
- 点「刷新」会重新取数;`GET /state?refresh=1` 强制重查 npm 最新版(否则 24h 缓存)
|
|
139
|
+
- 颜色:🟢 正常 / 🟡 风险或不可判定 / 🔴 异常(比如 patch insert 的实体缺失)
|
|
140
|
+
- 面板底部说明与标题可由配置覆盖(`text.title` / `text.note` / `text.tabs`,服务端经 `meta.ui` 下发)
|
|
141
|
+
|
|
142
|
+
## 6. 兼容性
|
|
143
|
+
|
|
144
|
+
| 宿主主包线 | 状态 | 依据 |
|
|
145
|
+
|---|---|---|
|
|
146
|
+
| **`0.2.0-rc.2`** | ✅ **已端到端实测(2026-10-16)** | **本版 `peerDependencies` 声明的区间基线**:在隔离实例(独立数据根 + 端口 3090)上真装真跑 —— 本仓 `scripts/verify-state.mjs`(只读六类体检)**rc=0 跑通**,读到了该实例的数据根与配置来源;客户端半 `client.js` 出现在实例启动 HTML 的插件资源清单里 |
|
|
147
|
+
| `0.2.x` 后续版本 | ⚠️ **未实测,不作承诺**(区间上界 `<0.3.0`) | — |
|
|
148
|
+
| `0.1.1-rc.2` / `0.1.5` 线 | ⚠️ 历史静态核对(**本版起 `peerDependencies` 不再声明 0.1.x**) | 见 `v0.4.3` 及之前的本节 |
|
|
149
|
+
| ⚠️ 升级体检 / 解耦健康 两卡的**读数** | ⚠️ **未在 0.2.0 实例上校准** | 0.1.5 起客户端资源改成"名册制 + 合并 URL",两卡是否读全未验证 —— **最可能的表现是读数偏保守,不是崩溃** |
|
|
150
|
+
| 其它 | ❓ 未知 | 需自测 |
|
|
151
|
+
|
|
152
|
+
## 7. 已知限制
|
|
153
|
+
|
|
154
|
+
1. **js-yaml 依赖宿主提供** —— 解析不到时 ②④ 两类显示「不可解析」(不假绿),但也就查不了了。
|
|
155
|
+
2. **boot 清单靠抓宿主首页**的内联 `__DSH_BOOT__` 段 —— 宿主若改了这个投影,① 的"加载状态"就变成未知(黄)。
|
|
156
|
+
3. **③ 的判定完全取决于你给的清单**:本仓**不内嵌**任何环境的补丁清单,清单写错就会报错。
|
|
157
|
+
4. **⑤ 的颜色不来自本面板**:它来自你配置的档位 CLI(唯一判定源)。本面板只渲染,绝不猜颜色。
|
|
158
|
+
5. **⑥⑦ 依赖外部脚本**,本仓不带这些脚本;未配置时对应类目只会显示降级提示。
|
|
159
|
+
6. **升级体检会访问 npm registry**(`registry.npmjs.org`),结果缓存 24h;离线时显示"远端查询失败"并继续用缓存。
|
|
160
|
+
7. **只读**:面板没有任何写操作入口(唯一写文件的是升级体检自己的缓存)。
|
|
161
|
+
8. **前端只支持 web platform**(`dsh.client.inject` 为空,不依赖任何 client 包)。
|
|
162
|
+
9. **界面文案为中文**,可通过 `text` 配置覆盖;没有内置多语言切换。
|
|
163
|
+
10. **未做移动端专门优化**(面板宽度自适应,但按钮/触摸交互没专门测过)。
|
|
164
|
+
|
|
165
|
+
## 8. 仓结构
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
lib/index.js 服务端:注册只读 route
|
|
169
|
+
lib/state.js 六类聚合逻辑(每个数据源都走配置层 + 显式降级)
|
|
170
|
+
lib/upgrade.js ⑤ 升级体检(本地事实 + npm 缓存 → 外部只读 CLI → 渲染)
|
|
171
|
+
lib/config.js 配置层(优先级解析 + 占位符展开 + 来源自证)
|
|
172
|
+
lib/host-protocol.js 宿主协议常量(本插件只用 webServer 一个服务名)
|
|
173
|
+
lib/client.js 浏览器端:侧边栏按钮 + 面板(零 import)
|
|
174
|
+
cordis.patch.yml bundle patch(把插件挂到宿主)
|
|
175
|
+
scripts/verify-source.mjs 发布前静态验证(语法 + 配置层行为 + 脱敏扫描)
|
|
176
|
+
scripts/test-fixture.mjs 干净临时路径上的端到端夹具(含缺数据降级断言)
|
|
177
|
+
scripts/verify-state.mjs 只读状态验证器(不依赖 GUI)
|
|
178
|
+
examples/ 五份配置示例
|
|
179
|
+
docs/RELEASING.md 发版规范与检查单
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## 9. 自测
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
node scripts/verify-source.mjs . # 语法 + 配置层行为 + 脱敏扫描(发布前必跑)
|
|
186
|
+
node scripts/test-fixture.mjs # 端到端夹具:不需要任何真实安装,全在临时目录里造
|
|
187
|
+
node scripts/verify-state.mjs # 对当前实例只读体检(打印六类 + 配置来源)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
`test-fixture.mjs` 会现场造一个最小数据根(假 profile / 假插件实体 / 假技能 / 四个外部工具 stub),
|
|
191
|
+
断言六类都能跑出结果,并专门验证「缺数据必显式降级」。
|
|
192
|
+
|
|
193
|
+
## 10. 相关组件
|
|
194
|
+
|
|
195
|
+
同属 DSH 生态的伴生组件,各自独立仓、独立版本、许可各自独立;它们都回链到同一份文档仓
|
|
196
|
+
[`ops-handoff-design`](https://github.com/kira905/ops-handoff-design)
|
|
197
|
+
(Gitee 镜像 <https://gitee.com/kira905/ops-handoff-design>):
|
|
198
|
+
|
|
199
|
+
| 组件仓 | 做什么 | 与本组件的关系 |
|
|
200
|
+
|---|---|---|
|
|
201
|
+
| `dsh-ecosystem-panel` | 只读生态总览面板 | **本仓** |
|
|
202
|
+
| [`dsh-butler-archive`](https://github.com/kira905/dsh-butler-archive) | 会话归档管理(列表 / 预览 / 恢复 / 删除 + 可选自动归档) | 它是**本面板第 ③ 类的观察对象之一**:靠 `cordis.patch.yml` 的 insert 注册,实体缺失时本面板报 🔴 |
|
|
203
|
+
| [`dsh-session-title-live`](https://github.com/kira905/dsh-session-title-live) | 会话标题跟着对话实时更新 | 同样靠 `cordis.patch.yml` 的 insert 注册(无 client 半);「插件到底加载上了没有」由本面板第 ① 类回答 |
|
|
204
|
+
| [`dsh-diagnostic-tools`](https://github.com/kira905/dsh-diagnostic-tools) | 诊断取证工具组:依赖闭包体检 + 会话图片附件对账 | 分工互补:本面板回答**「今天怎么样」**(持续、只读、三色),它回答**「具体坏在哪、怎么修」**(离线、可复跑、带修法与回滚清单)——两者都只诊断 |
|
|
205
|
+
| [`dsh-task-board-local`](https://github.com/kira905/dsh-task-board-local) | 自维护任务看板(卡片 = 一次真实会话 + 人工验收闸) | 它是本面板**第 ① / ③ 类体检对象的典型**:自研 + 靠 `cordis.patch.yml` 的 insert 注册——插件装载状态与补丁健康这两类静默故障,在本面板上一眼看得到 |
|
|
206
|
+
| [`dsh-firstaid`](https://github.com/kira905/dsh-firstaid) | 零依赖急救台:起不来 / 假死 / 要撤销改动 / 数据被删四类现场压成一个入口 | 应急预案:**本面板自己也可能是坏掉的那个**(面板要起不来或者数据取不到,你没法用它诊断它),那时换它出场 |
|
|
207
|
+
|
|
208
|
+
> 组件之间**没有代码依赖**,也不共享运行时 —— 之所以互指,是因为它们回答的是同一类人的同一批问题
|
|
209
|
+
> (长期在自有机器上跑 agent:装得下、找得到、看得见、查得清)。谁装谁不装,互不影响。
|
|
210
|
+
|
|
211
|
+
## 11. 许可
|
|
212
|
+
|
|
213
|
+
**AGPL-3.0-only + 商业授权**(双许可;见 `LICENSE` 全文;`package.json` 的 `license` 字段为 `AGPL-3.0-only`)。
|
|
214
|
+
|
|
215
|
+
- ⚠️ **AGPL 本身不禁商用**:你可以自由使用、修改、再分发(含商用),但**通过网络向他人提供本软件的修改版时,必须按 AGPL 一并提供对应源码**;
|
|
216
|
+
- 「+ 商业授权」= **双许可**:若需在**闭源**或**商业场景**中使用(AGPL 的传染条款不适用),可另行取得**商业授权** —— 本仓暂无公开联系邮箱,**请通过本仓 Issue 联系**。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# dsh-ecosystem-panel bundle patch: mounts the read-only ecosystem overview
|
|
2
|
+
# (plugin / patch / skill health). The node half (exports ".") serves
|
|
3
|
+
# GET /api/dsh-ecosystem-panel/state; the `dsh.client` declaration makes the
|
|
4
|
+
# browser half (exports "./client") load in the web GUI sidebar.
|
|
5
|
+
- insert:
|
|
6
|
+
- id: ecosystem-panel
|
|
7
|
+
name: '@kira905/dsh-ecosystem-panel'
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# 发版与发布规范(RELEASING)
|
|
2
|
+
|
|
3
|
+
本仓只发 **Release**(clone 手工装),**不发 npm**。
|
|
4
|
+
|
|
5
|
+
## 1. 版本号怎么定(SemVer)
|
|
6
|
+
|
|
7
|
+
判据是**使用者可见的行为**,不是代码改动量。
|
|
8
|
+
|
|
9
|
+
| 改动类型 | 版本位 | 例子 |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| 六类体检的判定口径变化、接口字段增删、必需的新配置项、环境变量改名 | **major** | 把「未配置」从 🟡 改成 🟢(判定语义变了) |
|
|
12
|
+
| 新增类目 / 新增可选配置项 / 新增脚本 / 新增面板元素 | **minor** | 加一类体检、加 `disabledGroups` |
|
|
13
|
+
| 修 bug、文案、注释、内部重构、性能 | **patch** | boot 抓不到时的颜色修正 |
|
|
14
|
+
|
|
15
|
+
配置层**新增键**永远是向后兼容的(不设就走默认),可以走 minor。
|
|
16
|
+
|
|
17
|
+
## 2. 变更记录规范
|
|
18
|
+
|
|
19
|
+
- 一律写进 `CHANGELOG.md`,按 `Added / Changed / Fixed / Breaking / Security` 分组(没内容的分组不写)。
|
|
20
|
+
- 涉及使用者动作的(要改配置、要重命名、要重装)必须在 `Breaking` 里写清**迁移动作**。
|
|
21
|
+
- 每条尽量写"为什么",而不是"改了哪个函数"。
|
|
22
|
+
|
|
23
|
+
## 3. 发布前检查单(逐条打勾)
|
|
24
|
+
|
|
25
|
+
1. `node scripts/verify-source.mjs .` → `ALL CHECKS PASSED`(含语法 + 配置层断言 + 脱敏扫描)
|
|
26
|
+
2. 脱敏扫描**必须带全注入变量**再跑一遍(未注入时是空判):
|
|
27
|
+
```
|
|
28
|
+
DSH 侧示例(发布环境自己给值,别把真实值写进仓):
|
|
29
|
+
BUILD_MACHINE_NAMES=<主机名列表>
|
|
30
|
+
BUILD_USER_NAMES=<用户名列表>
|
|
31
|
+
BUILD_LAYOUT_ROOTS=<本机关键目录名列表>
|
|
32
|
+
BUILD_SYNC_PRODUCTS=<同步/备份产品目录名列表>
|
|
33
|
+
BUILD_INTERNAL_TERMS=<内部项目代号 / 体系名列表> ← 形态上枚举不出,只能注入
|
|
34
|
+
BUILD_PERSONAL_TERMS=<私人称呼列表> ← 扫描器源码里一个字都不许有
|
|
35
|
+
```
|
|
36
|
+
注入值为 0 时脚本会明确提示"仅通用形态规则生效"——**不要**把这种运行当成通过。
|
|
37
|
+
⚠️ 脚本自身的规则表里**不许**出现私人称呼或内部专有名(它会进公开仓);本脚本末尾有
|
|
38
|
+
自检段:把**注入规则**再跑一遍脚本自身,命中数必须为 0。
|
|
39
|
+
3. `node scripts/test-fixture.mjs` → `FIXTURE PASSED`(含「缺数据必显式降级」断言)
|
|
40
|
+
4. 在一个**隔离实例**上跑一次 `node scripts/verify-state.mjs --home <隔离数据根> --tools <工具目录>`,
|
|
41
|
+
确认六类都能出结果、降级项都带原因
|
|
42
|
+
5. 与上一个版本的判定做等价性比对(同一数据根、同一清单):**逐条 status 必须零差异**;
|
|
43
|
+
有差异就说明判定逻辑被动过,要么补进 CHANGELOG 的 `Breaking`,要么退回去查
|
|
44
|
+
6. `package.json` 的 `version` 与 `CHANGELOG.md` 顶部条目一致;`license` 三处一致
|
|
45
|
+
(`LICENSE` 文件 / `package.json` / `README` §10)
|
|
46
|
+
7. `README.md` 的配置表与 `lib/config.js` 里的 `ENV_PREFIX` 键**逐个对照**(加了键必须补表)
|
|
47
|
+
8. `examples/` 下所有 JSON 能被 `JSON.parse`(`npm test` 里不含这条,发布前手工过一遍)
|
|
48
|
+
9. 公开仓里没有 `node_modules/`、没有生成物、没有日志;`.gitignore` 覆盖这些
|
|
49
|
+
10. 提交信息用中性身份(不要带本机用户名与邮箱)
|
|
50
|
+
|
|
51
|
+
## 4. 发布步骤
|
|
52
|
+
|
|
53
|
+
1. 打出干净的发布目录(`package.json` 的 `files` 白名单已在位:`lib/` + `cordis.patch.yml` +
|
|
54
|
+
`scripts/` + `examples/` + `docs/` + 三个文档)
|
|
55
|
+
2. 建 tag(`vX.Y.Z`)并从该 tag 生成 Release,正文 = `CHANGELOG.md` 对应条目
|
|
56
|
+
3. Release 附件里附上本仓目录的归档(若发布渠道支持),或明确写"clone 后按 README §3 装入"
|
|
57
|
+
4. 发布后在本机/隔离实例各装一次,跑 `scripts/verify-state.mjs` 复核一次
|
|
58
|
+
|
|
59
|
+
## 5. 兼容性回归纪律
|
|
60
|
+
|
|
61
|
+
本插件与宿主只有**一个**耦合点:宿主 web server 的服务名(`lib/host-protocol.js`)。
|
|
62
|
+
|
|
63
|
+
- 升级宿主主包后,若面板按钮不出现(插件未激活),第一件事看这个服务名是否被改名;
|
|
64
|
+
改名**不用改代码**:设 `DSH_ECOSYSTEM_PANEL_WEBSERVER_SERVICE=<新名>` 即可。
|
|
65
|
+
- 其余所有外部依赖(解耦脚本 / 档位 CLI / 跨表校验器 / 适配层一致性校验器)都在**进程边界之外**,
|
|
66
|
+
宿主升级不会连带改变它们的判定;它们各自不可用时本插件只降级、不崩。
|
|
67
|
+
- **纪律**:任何一次"升级宿主后判定变化"的排查结论,都要写进 `CHANGELOG.md` 的 `Changed`(口径面)
|
|
68
|
+
或本文件 §3 第 5 条(回归面),别只留在会话里。
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "已知断裂符号表示例:宿主主包某条线移除了哪些导出(插件若仍静态 import 就会在升级后启动崩)。本面板只把它作为**参考底表**展示,不做任何自动判定。默认表为空。",
|
|
3
|
+
"@scope/some-host-package": {
|
|
4
|
+
"removed": ["oldExportName", "anotherOldExport"],
|
|
5
|
+
"since": "x.y.z",
|
|
6
|
+
"replacement": "hostApi.doTheThing(...)",
|
|
7
|
+
"affected": ["example-plugin"]
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "dsh-ecosystem-panel 配置示例。用法:拷成自己的路径,然后设 DSH_ECOSYSTEM_PANEL_CONFIG=<该路径>;同样的键也可以直接用环境变量给(见 README 配置表)。所有键都是可选的 —— 不设就走自动探测 / 内置默认。",
|
|
3
|
+
"home": "<DSH 数据根。默认 os.homedir()/.dsh;环境变量 DSH_ECOSYSTEM_PANEL_HOME 或 DSH_HOME 同效>",
|
|
4
|
+
"profile": "web",
|
|
5
|
+
"webUrl": "http://127.0.0.1:3080",
|
|
6
|
+
"toolsDir": "<外部工具目录(本面板要复用的体检脚本所在目录)。不设时,依赖它的三类体检会显式降级为「不可判定」,不会假绿>",
|
|
7
|
+
"mainNm": "<宿主主包 node_modules 路径。默认按全局 npm 布局自动探测;探测不到即判「不可用」>",
|
|
8
|
+
"cacheFile": "<升级体检的本地缓存文件。默认 <home>/ecosystem-panel-upgrade-cache.json>",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"decoupling": "<解耦检查脚本。默认 <toolsDir>/check-decoupling.mjs>",
|
|
11
|
+
"triageCli": "<升级档位判定只读 CLI。默认 <toolsDir>/upgrade-triage-cli.mjs>;不设时所有插件行的档位显示「不可用」,不猜颜色>",
|
|
12
|
+
"registryAudit": "<跨表准入校验器(可选类目)。默认 <toolsDir>/registry-audit.mjs>",
|
|
13
|
+
"hostAdapterSync": "<适配层一致性校验器(可选项)。默认 <toolsDir>/sync-host-adapter.mjs>"
|
|
14
|
+
},
|
|
15
|
+
"patchManifest": "<也可以直接内联补丁清单(数组),形状见 patch-manifest.example.json;默认空 = 该组显示「未配置」而不是 0 个补丁>",
|
|
16
|
+
"patchManifestFile": "<或者给一个 JSON 文件路径,效果相同>",
|
|
17
|
+
"upgradeRulesFile": "<升级规则表 JSON 路径,形状见 upgrade-rules.example.json>",
|
|
18
|
+
"breakingSymbolsFile": "<已知断裂符号表 JSON 路径,形状见 breaking-symbols.example.json>",
|
|
19
|
+
"labelsFile": "<包名 → 一句话简介 的 JSON 路径,形状见 labels.example.json>",
|
|
20
|
+
"disabledGroups": [],
|
|
21
|
+
"text": {
|
|
22
|
+
"title": "插件 · 技能生态状态",
|
|
23
|
+
"note": "<面板底部说明文案;不设则用内置中性文案>",
|
|
24
|
+
"tabs": {
|
|
25
|
+
"patches": "补丁健康"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "example-client-patch",
|
|
4
|
+
"title": "示例插件:某个客户端补丁",
|
|
5
|
+
"script": "patch-example-client.mjs",
|
|
6
|
+
"checks": [
|
|
7
|
+
{ "pkg": "example-plugin", "rel": "lib/client.js", "contains": ["__PATCH_MARKER__"], "notContains": ["legacy-poll"] }
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": "example-global-target",
|
|
12
|
+
"title": "宿主主包内的补丁(target=global 时在宿主主包 node_modules 里找)",
|
|
13
|
+
"script": "patch-host-package.mjs",
|
|
14
|
+
"checks": [
|
|
15
|
+
{ "target": "global", "pkg": "@deepseek-ai/dsh-subprocess-local", "rel": "lib/index.js", "contains": ["windowsHide: true"] }
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "example-dir-file",
|
|
20
|
+
"title": "随包二进制存在性(special: 目录内必须有某后缀文件)",
|
|
21
|
+
"script": "patch-put-binary.mjs",
|
|
22
|
+
"special": {
|
|
23
|
+
"kind": "dir-has-file",
|
|
24
|
+
"pkg": "example-plugin",
|
|
25
|
+
"dir": "desktop",
|
|
26
|
+
"suffix": ".dll",
|
|
27
|
+
"label": "例:随包二进制文件"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "example-no-sidecar",
|
|
32
|
+
"title": "数据目录不许有 -wal/-shm 残留(special: no-sidecar-files)",
|
|
33
|
+
"script": "patch-journal-mode.mjs",
|
|
34
|
+
"checks": [
|
|
35
|
+
{ "pkg": "example-plugin", "rel": "lib/index.js", "contains": ["journal_mode = DELETE"] }
|
|
36
|
+
],
|
|
37
|
+
"special": {
|
|
38
|
+
"kind": "no-sidecar-files",
|
|
39
|
+
"dir": "${HOME}/data",
|
|
40
|
+
"suffix": [".db-wal", ".db-shm"],
|
|
41
|
+
"label": "数据目录无 -wal/-shm 残留(字符串里可用 ${HOME} / ${PROFILE_NM} / ${MAIN_NM} 占位符)"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"id": "example-retired",
|
|
46
|
+
"title": "已退役条目:带 retired 的条目不参与体检(避免长期假红)",
|
|
47
|
+
"script": "patch-old-thing.mjs",
|
|
48
|
+
"retired": "示例:目标包已 fork 为自建,原补丁不再适用",
|
|
49
|
+
"checks": [
|
|
50
|
+
{ "pkg": "example-plugin", "rel": "lib/index.js", "contains": ["something"] }
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
]
|