dsh-advisor 0.1.3 → 0.2.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/README.i18n.yaml +2 -2
- package/README.md +61 -244
- package/README.zh.md +60 -109
- package/lib/advisor-runtime.d.ts +34 -26
- package/lib/advisor-runtime.js +56 -32
- package/lib/advisor-runtime.js.map +1 -1
- package/lib/client/advisor-store.d.ts +1 -1
- package/lib/client.js +6 -1
- package/lib/commands.d.ts +48 -0
- package/lib/commands.js +51 -2
- package/lib/commands.js.map +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.js +58 -8
- package/lib/index.js.map +1 -1
- package/lib/tui.d.ts +60 -0
- package/lib/tui.js +113 -0
- package/lib/tui.js.map +1 -0
- package/package.json +1 -1
package/README.i18n.yaml
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
# editing either side, bring the other along and re-record with:
|
|
4
4
|
# git hash-object README.md
|
|
5
5
|
# git hash-object README.zh.md
|
|
6
|
-
README.md:
|
|
7
|
-
README.zh.md:
|
|
6
|
+
README.md: 6da971fed9908121287601132c6e39ff66dba750
|
|
7
|
+
README.zh.md: 4c770571e72e38e64c9cf48a789cc41aa544192b
|
package/README.md
CHANGED
|
@@ -1,135 +1,62 @@
|
|
|
1
1
|
# dsh-advisor
|
|
2
2
|
|
|
3
|
-
English | [中文](README.zh.md)
|
|
3
|
+
[English](README.md) | [中文](README.zh.md)
|
|
4
4
|
|
|
5
5
|
[](LICENSE)
|
|
6
6
|

|
|
7
7
|

|
|
8
|
+
[](https://dshfind.com/plugins/omdsh-dev/dsh-advisor?ref=badge)
|
|
8
9
|
|
|
9
|
-
A standalone dsh plugin bundle porting the omp "advisor"
|
|
10
|
-
subsystem: a per-session reviewer model that observes the primary transcript,
|
|
11
|
-
reviews each stepped turn with an explicitly configured model (provider +
|
|
12
|
-
model are required), and injects severity-ranked advice (nit / concern /
|
|
13
|
-
blocker) back into the session — without polluting or recursively reviewing
|
|
14
|
-
itself.
|
|
10
|
+
A standalone dsh (DeepSeek Harness) plugin bundle porting the omp "advisor" subsystem: a per-session independent reviewer model that observes the primary transcript, reviews each stepped turn with an explicitly configured model (provider + model are required), and injects severity-ranked advice (nit / concern / blocker) back into the session — without polluting or recursively reviewing itself.
|
|
15
11
|
|
|
16
|
-
|
|
12
|
+
**Advisory only.** The advisor never approves or rejects the primary agent's actions, and never issues commands as if it were the primary agent. Every delivered message is self-described advisory content, and a misbehaving reviewer is bounded end to end (emission guard, immuneTurns cooldown, failure policy) so it can never stall or pollute the primary loop.
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
dsh plugin --profile web add dsh-advisor # <name> = your profile name
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
**Advisory only.** The advisor never approves or rejects the primary agent's
|
|
23
|
-
actions; it never issues commands as if it were the primary agent. Every
|
|
24
|
-
delivered message is self-described advisory content, and a misbehaving
|
|
25
|
-
reviewer is bounded end to end (emission guard, immuneTurns cooldown, failure
|
|
26
|
-
policy) so it can never stall or pollute the primary loop.
|
|
14
|
+
Works in both dsh front ends: the **web** profile (Settings → 插件配置 → Advisor card) and the **dsh-tui** terminal profile (`/advisor` + `/advisor config`).
|
|
27
15
|
|
|
28
|
-
##
|
|
16
|
+
## Quick start
|
|
29
17
|
|
|
30
|
-
###
|
|
18
|
+
### Install
|
|
31
19
|
|
|
32
20
|
```sh
|
|
33
|
-
dsh plugin --profile web add dsh-advisor
|
|
21
|
+
dsh plugin --profile web add dsh-advisor # web profile (Settings → Advisor card)
|
|
22
|
+
dsh plugin --profile dsh-tui add dsh-advisor # dsh-tui terminal profile
|
|
34
23
|
```
|
|
35
24
|
|
|
36
|
-
A registry install fetches the published tarball, which ships the built
|
|
37
|
-
artifacts (`lib/` + `cordis.patch.yml`), so no `prepare` build or build
|
|
38
|
-
permission is needed. Runtime dependencies (`@deepseek-ai/cordis`, `@deepseek-ai/schemastery`,
|
|
39
|
-
and the `@deepseek-ai/dsh-*` peers) are declared as peerDependencies and resolve
|
|
40
|
-
through the dsh installation's flat profile module fallback — no extra install
|
|
41
|
-
step. Pin an exact version (`dsh-advisor@0.1.0`) for reproducible installs.
|
|
25
|
+
Same plugin, either front end — the only difference is the `--profile` flag. Pin a version with `@<version>` (e.g. `dsh-advisor@0.1.0`). A registry install fetches the published tarball, which ships the built artifacts (`lib/` + `cordis.patch.yml`) — nothing builds on the target machine, and runtime dependencies (`@deepseek-ai/cordis`, `@deepseek-ai/schemastery`, `@deepseek-ai/dsh-*` peers) resolve through the dsh installation's flat profile module fallback — no extra install step. Registry / git / tarball / local-directory variants (local-dir from a built checkout: `dsh plugin --profile web add .` or `dsh plugin --profile dsh-tui add .`), web Settings exposure, uninstall, and `--dump-config` verification → [docs/install.md](docs/install.md).
|
|
42
26
|
|
|
43
|
-
###
|
|
27
|
+
### Configuration
|
|
44
28
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
29
|
+
Add an `advisor:` section to the global dsh settings document (default `$DSH_HOME/settings.yaml` — shared across profiles; the web Settings card writes to this same file):
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
advisor:
|
|
33
|
+
enabled: true # master switch (default false) — set explicitly to enable
|
|
34
|
+
provider: deepseek-official # REQUIRED when enabled
|
|
35
|
+
model: deepseek-v4-flash # REQUIRED when enabled
|
|
36
|
+
systemPrompt: "" # optional; "" = built-in reviewer prompt
|
|
37
|
+
immuneTurns: 3 # int ≥ 0, default 3 — cooldown after a delivered steer
|
|
38
|
+
maxDeltaMessages: 60 # int ≥ 0, default 60 — delta window; 0 = unbounded
|
|
48
39
|
```
|
|
49
40
|
|
|
50
|
-
|
|
41
|
+
The advisor is off by default. When enabled, `provider` and `model` are **mandatory**: `enabled: true` without both is a hard gate — the advisor never starts a model call and reports a disabled-with-reason status; unknown config keys are rejected.
|
|
51
42
|
|
|
52
|
-
|
|
53
|
-
dsh --profile web --dump-config # shows a "# == dsh-advisor" layer with the advisor row
|
|
54
|
-
dsh --profile web
|
|
55
|
-
```
|
|
43
|
+
The same keys compose across **three surfaces** (later layers override earlier ones; every surface shares the same key set and the same hard gate, with the host-side gate as the final line of defense on every path):
|
|
56
44
|
|
|
57
|
-
|
|
45
|
+
1. **Plugin-row config** — the profile patch layer (`$DSH_HOME/profiles/<profile>/cordis.patch.yml`). This is the composition base.
|
|
46
|
+
2. **dsh web Settings page — the "插件配置" (Plugin Configuration) page** — the Advisor **card** (id `advisor`) with the enabled toggle, provider / model selects restricted to system-configured providers and their models, and the optional fields. Saving writes into the `advisor` settings namespace and applies to new sessions immediately — no restart. The card requires a current dsh web build whose shell declares the `settings.plugin.item` card slot and loads packages that declare `dsh.client`; it reads and writes the namespace through the official `GatewayService` RPC channel (`/api/advisor/get` + `/api/advisor/set`), which is not gated by the settings exposure allowlist. It additionally blocks saving while enabled with a required field empty.
|
|
47
|
+
3. **`/advisor` command** — per-session and ephemeral: it flips a session override, never the persisted config (see [Verify](#verify)).
|
|
58
48
|
|
|
59
|
-
|
|
49
|
+
In a **dsh-tui** profile there is no settings page: the same two persisted surfaces (profile patch layer + global `$DSH_HOME/settings.yaml`) compose the config, and `/advisor config` prints the composed config as a read-only readback with edit hints. Full reference → [docs/configuration.md](docs/configuration.md).
|
|
60
50
|
|
|
61
51
|

|
|
62
52
|
|
|
63
|
-
|
|
64
|
-
**mandatory**: `enabled: true` without both is a hard gate — the advisor never
|
|
65
|
-
starts a model call and reports a disabled-with-reason status. Unknown config
|
|
66
|
-
keys are rejected.
|
|
67
|
-
|
|
68
|
-
Configuration composes across **three surfaces** (later layers override earlier
|
|
69
|
-
ones; every surface uses the same key set):
|
|
70
|
-
|
|
71
|
-
1. **Plugin-row config** — `$DSH_HOME/profiles/web/cordis.patch.yml`
|
|
72
|
-
(below). This is the composition base.
|
|
73
|
-
2. **dsh web Settings page — the "插件配置" (Plugin Configuration) page** —
|
|
74
|
-
the Advisor **card** (id `advisor`, rendered after the upstream bash /
|
|
75
|
-
agent-loop / web-search cards) with the enabled toggle, provider / model
|
|
76
|
-
selects restricted to system-configured providers and their models, and the
|
|
77
|
-
optional fields. Saving writes into the `advisor` settings namespace and
|
|
78
|
-
overrides the plugin-row config without editing it. Saving applies to new
|
|
79
|
-
sessions immediately — no restart (the runtime reads the composed value
|
|
80
|
-
live). Requires a current dsh web build whose shell declares the
|
|
81
|
-
`settings.plugin.item` card slot and loads packages that declare
|
|
82
|
-
`dsh.client`. The card reads and writes the namespace through the
|
|
83
|
-
**official `GatewayService` RPC channel** (`/api/advisor/get` +
|
|
84
|
-
`/api/advisor/set`, claimed by the host's typertGateway — the same
|
|
85
|
-
mechanism the dsh `goals` service uses), which is **not gated by the
|
|
86
|
-
settings exposure allowlist**: the in-process write
|
|
87
|
-
(`ctx.settings.update`) carries no exposed-namespace check. No host
|
|
88
|
-
patching is applied or required.
|
|
89
|
-
3. **`/advisor` command** — per-session and ephemeral: it flips a session
|
|
90
|
-
override, never the persisted config (see [Usage](#usage)).
|
|
91
|
-
|
|
92
|
-
Both persisted surfaces share the same hard gate: `enabled: true` with empty
|
|
93
|
-
`provider`/`model` never starts a model call (disabled-with-reason). The
|
|
94
|
-
Settings page additionally blocks saving while enabled with a required field
|
|
95
|
-
empty; the host-side gate stays the final line of defense on every path.
|
|
96
|
-
|
|
97
|
-
Plugin-row config:
|
|
53
|
+
### Verify
|
|
98
54
|
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
- id: advisor
|
|
102
|
-
config:
|
|
103
|
-
enabled: true # master switch (default false)
|
|
104
|
-
provider: deepseek-official # REQUIRED when enabled
|
|
105
|
-
model: deepseek-v4-flash # REQUIRED when enabled
|
|
106
|
-
systemPrompt: "" # optional; "" = built-in reviewer prompt
|
|
107
|
-
immuneTurns: 3 # int ≥ 0, default 3 — cooldown after a delivered interrupt
|
|
108
|
-
maxDeltaMessages: 60 # int ≥ 0, default 60 — delta window; 0 = unbounded
|
|
55
|
+
```sh
|
|
56
|
+
dsh --profile web --dump-config # shows a "# == dsh-advisor" layer with the advisor row
|
|
109
57
|
```
|
|
110
58
|
|
|
111
|
-
|
|
112
|
-
|---|---|---|
|
|
113
|
-
| `enabled` | bool, `false` | Master switch. |
|
|
114
|
-
| `provider` | string, optional | Provider route. Required (non-empty) when `enabled: true`. |
|
|
115
|
-
| `model` | string, optional | Model id. Required (non-empty) when `enabled: true`. |
|
|
116
|
-
| `systemPrompt` | string, `""` | Overrides the built-in reviewer prompt (severity definitions + JSON-frame output contract). |
|
|
117
|
-
| `immuneTurns` | int ≥ 0, `3` | After a concern/blocker is actually steered, the next N stepped primary turns must complete before another interrupting note may steer; notes inside the window downgrade to inject. |
|
|
118
|
-
| `maxDeltaMessages` | int ≥ 0, `60` | Bounded advisor input window. Deltas beyond N are truncated with a `… <earlier messages omitted>` marker; `0` = unbounded. |
|
|
119
|
-
|
|
120
|
-
**Model capability & budget**: the advisor call runs with `reasoningEffort:
|
|
121
|
-
'off'` — sent only when the configured model's adapter declares that effort
|
|
122
|
-
(deepseek models do; any other model gets the option omitted automatically, so
|
|
123
|
-
non-reasoning providers keep working) — and a **5120-token** output cap (a
|
|
124
|
-
user-directed 20× supersession of the original 256). Extracted notes are
|
|
125
|
-
bounded (1000 chars) and the notice summary to 120 chars, so the raised budget
|
|
126
|
-
cannot translate into an unbounded injection into the primary session.
|
|
127
|
-
|
|
128
|
-
## Usage
|
|
129
|
-
|
|
130
|
-
Once installed and enabled, the advisor observes every session. Control it per
|
|
131
|
-
session with the `/advisor` command (available when a command registry is
|
|
132
|
-
composed):
|
|
59
|
+
With the advisor installed and enabled, control it in-session with the `/advisor` command (available when a command registry is composed):
|
|
133
60
|
|
|
134
61
|
```
|
|
135
62
|
/advisor toggle the advisor for this session
|
|
@@ -138,163 +65,53 @@ composed):
|
|
|
138
65
|
/advisor status show state, model, runtime status, pending count, last activity
|
|
139
66
|
```
|
|
140
67
|
|
|
141
|
-
`/advisor on|off|toggle` are session-scoped and ephemeral: they flip a
|
|
142
|
-
per-session override, never the persisted config. Enabling a session whose
|
|
143
|
-
config lacks `provider`/`model` starts no model call — `/advisor status` (and
|
|
144
|
-
the `/advisor on` reply) shows the gate reason.
|
|
145
|
-
|
|
146
|
-
`/advisor on` is also the manual recovery path: a session advisor paused by a
|
|
147
|
-
quota/rate-limit (`quota_exhausted` — KD-5 has no auto-resume timer) resumes in
|
|
148
|
-
place, and a halted advisor (permanent model error, e.g. invalid credentials)
|
|
149
|
-
is rebuilt fresh for the session.
|
|
68
|
+
`/advisor on|off|toggle` are session-scoped and ephemeral: they flip a per-session override, never the persisted config. Enabling a session whose config lacks `provider`/`model` starts no model call — `/advisor status` (and the `/advisor on` reply) shows the gate reason: the advisor runs only when enabled **with** both configured. `/advisor on` is also the manual recovery path: a session advisor paused by a quota/rate-limit (`quota_exhausted` — no auto-resume timer) resumes in place, and a halted advisor (permanent model error, e.g. invalid credentials) is rebuilt fresh for the session.
|
|
150
69
|
|
|
151
|
-
|
|
70
|
+
In a **dsh-tui** profile, `/advisor config` additionally reads back the composed configuration — read-only, with edit hints: the web Settings card is web-only, and the TUI has no settings page and no write command, so edit through the profile patch layer or `$DSH_HOME/settings.yaml`. The `/advisor` / `on|off|status|config` commands are listed in the TUI `/` menu with subcommand completion (command discovery requires the `dsh-tui-command-trees` row — the shipped dsh-tui bundle has it).
|
|
152
71
|
|
|
153
|
-
|
|
154
|
-
normally (`completed`, `max-tokens`, or `error`), the advisor reviews the
|
|
155
|
-
incremental transcript delta.
|
|
156
|
-
- **Agentic / harness sessions** (never emit `turn/end`) — after each completed
|
|
157
|
-
agent reply round: when a new human input arrives (inbox-spliced input
|
|
158
|
-
included) after an unreviewed assistant increment, the advisor reviews that
|
|
159
|
-
increment.
|
|
72
|
+
## Features
|
|
160
73
|
|
|
161
|
-
|
|
74
|
+
- **Independent reviewer per session**: a separate model call observes the primary transcript and reviews each stepped primary turn; advisor messages are excluded from later deltas, so the advisor never reads its own advice back.
|
|
75
|
+
- **Severity-ranked advice with inject/steer semantics**: at most one note per review — **nit** (a minor style, clarity, or quality suggestion; delivered via non-waking `agent.inject`, consumed at the next pre-step boundary), **concern** (a material risk or clearly better direction to weigh before continuing; delivered via waking `agent.steer`, subject to the `immuneTurns` cooldown), **blocker** (continuing clearly wastes work — contradicts an explicit user instruction, going in circles, fundamentally unsound; delivered via `agent.steer`). Delivered messages carry the `[advisor:{severity}]` prefix and are self-described advisory content:
|
|
162
76
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
continuing; delivered via `agent.steer` (waking), subject to the
|
|
167
|
-
`immuneTurns` cooldown.
|
|
168
|
-
- **blocker** — continuing clearly wastes work (contradicts an explicit user
|
|
169
|
-
instruction, going in circles, fundamentally unsound); delivered via
|
|
170
|
-
`agent.steer`.
|
|
77
|
+
```
|
|
78
|
+
[advisor:concern] extract the helper into a module and unit-test it
|
|
79
|
+
```
|
|
171
80
|
|
|
172
|
-
|
|
173
|
-
the
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
[advisor:concern] extract the helper into a module and unit-test it
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
The `[advisor:{severity}]` prefix is the only cue the primary model gets about
|
|
180
|
-
how to treat it — the primary system prompt never mentions advisories. Advisor
|
|
181
|
-
messages are excluded from later advisor deltas, so the advisor never reads
|
|
182
|
-
its own advice back.
|
|
81
|
+
- **Explicit model gate**: `enabled` defaults to off; `enabled: true` without `provider` + `model` never starts a model call — status reports disabled-with-reason. Unknown config keys are rejected.
|
|
82
|
+
- **Zero-tool minimal start**: the reviewer is an independent model call only — no advisor tools, nothing it can do to the session besides advisory messages.
|
|
83
|
+
- **No-stall failure policy**: a failing or quota-limited advisor only drops its own bounded backlog — it can never park or pollute the primary loop.
|
|
84
|
+
- **Session-scoped controls**: `/advisor on|off|status|config` work per session; the toggles are ephemeral overrides, never persisted config.
|
|
183
85
|
|
|
184
86
|

|
|
185
87
|
|
|
186
|
-
##
|
|
187
|
-
|
|
188
|
-
The plugin subscribes to `session/event`. Two triggers render an incremental
|
|
189
|
-
markdown delta of the primary transcript (own advisor messages excluded) and
|
|
190
|
-
queue it on a per-session runtime: after each stepped `turn/end` in standard
|
|
191
|
-
stepped sessions, and — in agentic/harness sessions that never emit `turn/end`
|
|
192
|
-
— when a new human input arrives (inbox-spliced input included) after an
|
|
193
|
-
unreviewed assistant increment, i.e. at each completed agent reply round. The
|
|
194
|
-
runtime calls a separately configured model via `ctx.llm.stream`, extracts one
|
|
195
|
-
`{note, severity}` from the JSON-framed reply, gates it through an emission
|
|
196
|
-
guard (normalize / dedupe / content-free suppression / one-note-per-update),
|
|
197
|
-
and routes it: nit → inject, concern/blocker → steer. The advisor call runs
|
|
198
|
-
with reasoning off and a 20x token budget so the JSON note is never starved by
|
|
199
|
-
reasoning output. Compaction and surface rewrites reset the observer, the
|
|
200
|
-
emission guard, and the immuneTurns latch
|
|
201
|
-
(KD-5); the drain is fully async with a bounded backlog, so a failing or
|
|
202
|
-
quota'd advisor can only drop its own backlog — never park the primary loop.
|
|
88
|
+
## Mount-only (no dsh modification)
|
|
203
89
|
|
|
204
|
-
|
|
90
|
+
The plugin installs as a **pure mount**: bundle insert + client card (web Settings 插件配置) + its own gateway channel (`/api/advisor/get|set`, claimed by the host's typertGateway — the same mechanism the dsh `goals` service uses, not gated by the settings exposure allowlist) + the `/advisor` commands — no dsh patches, no postinstall step, and dsh upgrades never require re-patching.
|
|
205
91
|
|
|
206
|
-
|
|
207
|
-
harness iteration roadmap):
|
|
208
|
-
|
|
209
|
-
- **Single advisor per session** — no parallel advisor roster or WATCHDOG-style
|
|
210
|
-
file discovery (next iteration).
|
|
211
|
-
- **No advisor tools** — the reviewer is an independent model call only; it
|
|
212
|
-
cannot verify claims itself (next-next iteration).
|
|
213
|
-
- **No in-session advisor panel** — advice surfaces only as tagged injected
|
|
214
|
-
messages (the Advisor card on the "插件配置" settings page is a config
|
|
215
|
-
surface, not a session view; an in-session card is next-next iteration).
|
|
216
|
-
- **No transcript persistence or cost stats** — no resumable advisor history or
|
|
217
|
-
cost observability (next-next iteration).
|
|
218
|
-
- **No secret obfuscation of delta content** — secrets present in the transcript
|
|
219
|
-
can reach the advisor model; mitigate by configuring a trusted reviewer model.
|
|
220
|
-
- **No quarantine of unsafe advisor output** — a misbehaving note can carry
|
|
221
|
-
directive text; the JSON frame + validation + advisory-only framing
|
|
222
|
-
(`[advisor:…]`, "weigh, don't blindly obey") are the only mitigation, and the
|
|
223
|
-
note is delivered as-is into the primary transcript (roadmap).
|
|
224
|
-
- **No `syncBacklog` catch-up wait** — a far-behind advisor does not wait for
|
|
225
|
-
the primary loop; its backlog is bounded and dropped (never parks the
|
|
226
|
-
primary), so advisor notes may arrive after the next primary turn started
|
|
227
|
-
(roadmap: context-maintenance batch).
|
|
228
|
-
- **Bounded advisor context** — long-session full replays are truncated
|
|
229
|
-
(`maxDeltaMessages`), so the advisor may lose early context after compaction;
|
|
230
|
-
advisor context maintenance is roadmap (next-next iteration).
|
|
231
|
-
|
|
232
|
-
## Development
|
|
233
|
-
|
|
234
|
-
The bundle builds itself on install: `package.json` declares `"prepare": "node
|
|
235
|
-
scripts/setup-dsh-links.mjs && pnpm build"` (the dev-time link farm plus the
|
|
236
|
-
same build `prepack` runs), so any clone is
|
|
237
|
-
immediately buildable **once `DSH_HOME` points at a dsh home whose
|
|
238
|
-
`source/current` is a dsh source tree** (or `DSH_SOURCE_DIR` points at such a
|
|
239
|
-
tree directly). The private
|
|
240
|
-
`@deepseek-ai/dsh-*` runtime dependencies are **peerDependencies only**; at dev
|
|
241
|
-
time `scripts/setup-dsh-links.mjs` (wired into `prepare`, standalone as
|
|
242
|
-
`pnpm dsh:link`, verified with `pnpm dsh:link:check`) links the REAL packages
|
|
243
|
-
from that tree into `node_modules/@deepseek-ai/` — every `@deepseek-ai/*`
|
|
244
|
-
package the tree declares (tool CLIs with a `bin` are skipped: linking them
|
|
245
|
-
would make pnpm write their bins into the shared tree), a bin-less shim for
|
|
246
|
-
the in-box `cordis` framework, and the tree's own `react`/`react-dom` copies
|
|
247
|
-
(node resolution — including externalized CJS deps — must see ONE react
|
|
248
|
-
identity, the identity the real client packages use; the dsh profile
|
|
249
|
-
convention `nodeLinker=hoisted` lives in `pnpm-workspace.yaml` (pnpm 11+
|
|
250
|
-
ignores non-auth settings in `.npmrc`), so no `.pnpm` per-package dirs shadow
|
|
251
|
-
those links). The farm is idempotent, prunes stale entries, and fails with
|
|
252
|
-
guidance when the tree is missing or a peer cannot be linked.
|
|
253
|
-
`pnpm-workspace.yaml` also sets `autoInstallPeers: false` (dsh profile
|
|
254
|
-
convention): the private peers must never be fetched from the npm registry.
|
|
92
|
+
## Limitations & roadmap
|
|
255
93
|
|
|
256
|
-
|
|
257
|
-
export DSH_HOME=~/.dsh # a dsh home with source/current (or set DSH_SOURCE_DIR)
|
|
258
|
-
pnpm install # registry deps + link farm (via prepare), no private-registry access
|
|
259
|
-
pnpm test # vitest (unit + the composed integration loop)
|
|
260
|
-
pnpm typecheck # tsc --noEmit (node) + tsc -p tsconfig.client.json --noEmit + tsc -p tsconfig.spec.json --noEmit
|
|
261
|
-
pnpm build # tsc -p tsconfig.build.json emit to lib/ + node scripts/build-client.mjs (client bundle)
|
|
262
|
-
pnpm pack # build + produce dsh-advisor-0.0.1.tgz
|
|
263
|
-
```
|
|
94
|
+
The MVP deliberately drops full omp parity. Accepted gaps (tracked in the harness iteration roadmap):
|
|
264
95
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
`@deepseek-ai/cordis: ^4.0.1-rc.1` (the range carries the exact publish tag —
|
|
274
|
-
a comparator prerelease such as `^4.0.0-rc.7` never matches the vendored
|
|
275
|
-
`4.0.1-rc.1` per the node-semver tuple rule); after install the link farm's
|
|
276
|
-
bin-less cordis shim at `node_modules/@deepseek-ai/cordis` answers the scoped
|
|
277
|
-
name and resolves to the vendored files, because the real packages type and
|
|
278
|
-
run against the vendored build and module identity requires dev-time
|
|
279
|
-
`import '@deepseek-ai/cordis'` to resolve to the same files. The public
|
|
280
|
-
devDependencies (`@deepseek-ai/schemastery`, `react`, …) resolve from the npm registry as
|
|
281
|
-
usual.
|
|
282
|
-
|
|
283
|
-
`prepack` runs `pnpm build`; `prepare` runs the link farm and the build, so
|
|
284
|
-
`pnpm pack` runs the build twice (once per lifecycle) — the documented
|
|
285
|
-
tradeoff that keeps git-install builds working. There is no `postinstall`
|
|
286
|
-
step: already-built tarball installs skip the build entirely.
|
|
287
|
-
|
|
288
|
-
The integration test (`tests/integration.test.ts`) composes the plugin into a
|
|
289
|
-
real cordis context with a stub LLM adapter and drives the full
|
|
290
|
-
turn → delta → advisor call → inject/steer cycle.
|
|
96
|
+
- **Single advisor per session** — no parallel advisor roster or WATCHDOG-style file discovery (next iteration).
|
|
97
|
+
- **No advisor tools** — the reviewer is an independent model call only; it cannot verify claims itself (next-next iteration).
|
|
98
|
+
- **No in-session advisor panel** — advice surfaces only as tagged injected messages; the web Advisor card is a config surface, not a session view (next-next iteration).
|
|
99
|
+
- **No transcript persistence or cost stats** — no resumable advisor history or cost observability (next-next iteration).
|
|
100
|
+
- **No secret obfuscation of delta content** — secrets present in the transcript can reach the advisor model; mitigate by configuring a trusted reviewer model.
|
|
101
|
+
- **No quarantine of unsafe advisor output** — a misbehaving note can carry directive text; the JSON frame + validation + advisory-only framing are the only mitigation, and the note is delivered as-is (roadmap).
|
|
102
|
+
- **No `syncBacklog` catch-up wait** — a far-behind advisor does not wait for the primary loop; its backlog is bounded and dropped, so notes may arrive after the next primary turn started (roadmap: context-maintenance batch).
|
|
103
|
+
- **Bounded advisor context** — long-session full replays are truncated (`maxDeltaMessages`), so the advisor may lose early context after compaction (roadmap: next-next iteration).
|
|
291
104
|
|
|
292
105
|
## Documentation
|
|
293
106
|
|
|
294
107
|
| Doc | Content |
|
|
295
108
|
|---|---|
|
|
296
|
-
| [docs/install.md](docs/install.md) |
|
|
109
|
+
| [docs/install.md](docs/install.md) | profile install (web + dsh-tui) / registry / git / tarball / local-directory variants / web Settings exposure / uninstall / `--dump-config` verification |
|
|
110
|
+
| [docs/configuration.md](docs/configuration.md) | full `advisor` namespace reference: keys & defaults, explicit model gate (S4), settings surfaces (web card / patch layer / global settings.yaml), example YAML, live re-apply behavior |
|
|
111
|
+
| [docs/consumer-api.md](docs/consumer-api.md) | developer consumption contract: package-root library API, `dsh-advisor/client` entry, `/advisor` command surface, export inventory, lifecycle |
|
|
112
|
+
| [docs/verification.md](docs/verification.md) | verification records: test matrix (16 files / 319 cases), typecheck/build, CI contract, real-environment steps |
|
|
113
|
+
| [docs/release.md](docs/release.md) | release process: PR-driven Release prep + Release workflows, OIDC trusted publishing, version strategy, rollback |
|
|
297
114
|
|
|
298
115
|
## License
|
|
299
116
|
|
|
300
|
-
MIT
|
|
117
|
+
Released under the **MIT** License — see [LICENSE](LICENSE). The LICENSE file is authoritative for copyright and license terms.
|