dsh-scout 0.9.2 → 0.9.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 +76 -1
- package/README.en.md +140 -47
- package/README.md +140 -47
- package/dist/i18n.d.ts +157 -1
- package/dist/i18n.js +354 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +360 -88
- package/dist/model.d.ts +62 -9
- package/dist/model.js +655 -134
- package/docs/dsh-scout-product-contract.md +22 -1
- package/package.json +4 -1
- package/scripts/acceptance-report.mjs +622 -0
- package/scripts/check-release.mjs +228 -0
- package/scripts/profile-smoke.mjs +12 -15
- package/scripts/smoke-tool-call.mjs +43 -0
- package/tests/acceptance.test.mjs +118 -42
- package/tests/model.test.mjs +301 -69
- package/tests/package.test.mjs +572 -3
- package/tests/tools.test.mjs +382 -16
package/README.md
CHANGED
|
@@ -103,81 +103,118 @@ scout_export / scout_import 落盘持久化(五文件 + 完成标记),换
|
|
|
103
103
|
- **Sources**:带 URL 的来源清单(可点击回溯)
|
|
104
104
|
- **Interview questions**:建议的面试反问(未调查维度的问题优先)
|
|
105
105
|
|
|
106
|
-
##
|
|
106
|
+
## 安装
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
|---|---|
|
|
110
|
-
| `scout_start` | 创建尽调案例 |
|
|
111
|
-
| `scout_add_source` | 登记信息来源(含证据等级) |
|
|
112
|
-
| `scout_ingest` | 批量登记采集结果(自动推断来源类型/证据等级,可随来源一键登记主张草稿) |
|
|
113
|
-
| `scout_search` | 调用 DSH Web Provider 搜索并自动登记结果来源(type/evidence 按 URL 推断) |
|
|
114
|
-
| `scout_add_claim` | 添加证据受限的主张 |
|
|
115
|
-
| `scout_verify_identity` | 用 E3 官方源核验法定主体 |
|
|
116
|
-
| `scout_verify_claim` | 用更强证据提升主张为 verified |
|
|
117
|
-
| `scout_report` | 渲染当前 Markdown 报告 |
|
|
118
|
-
| `scout_questions` | 从案例派生去重、按优先级排序的面试问题清单(上限 12 条;案例自带的精选问题保留名额) |
|
|
119
|
-
| `scout_compare` | 2–5 个案例的并排对比报告(决策/主体/关键结论/风险/面试问题) |
|
|
120
|
-
| `scout_export` | 持久化五文件导出(case/sources/claims/events/report)+ 完成标记 |
|
|
121
|
-
| `scout_import` | 从导出目录恢复案例并重算决策(容忍旧导出,报 `complete`) |
|
|
108
|
+
先确认你在哪运行——两条入口的安装方式完全不同,**不要混用**:
|
|
122
109
|
|
|
123
|
-
|
|
110
|
+
| 你在哪运行 | 目标 profile | 安装方式 |
|
|
111
|
+
|---|---|---|
|
|
112
|
+
| **桌面 App(DeepSeek Harness)** | `desktop` | **App 内安装**(唯一路径,见下) |
|
|
113
|
+
| CLI / headless / 自建 profile | 你自己的 profile 名 | `dsh plugin --profile <your-profile> add …` |
|
|
124
114
|
|
|
125
|
-
|
|
115
|
+
### 路径 0:桌面 App(推荐)
|
|
126
116
|
|
|
127
|
-
|
|
128
|
-
- `render` 是**整串不超过 1 KB 的紧凑摘要**:决策 + 本次增量 + 未核验阻断项 + 下一步。上限就是渲染预算本身(`MAX_RENDER_BYTES = 1024` B):省略号自身的 UTF-8 长度先从预算里扣掉、再按码元裁切,因此**含省略号的整串也不会超过 1024 B**;
|
|
129
|
-
- `persist: { persisted, targetDir, error? }` **只出现在变更类工具的 `autoPersist` 路径**(未尝试落盘时该键省略)。**落盘失败不再静默**:`persist.persisted === false` + `persist.error`,且不会产生 `case_exported` 事件。`scout_export` **不带 `persist` 键**,它用**顶层** `persisted` / `complete` / `error` 表达同一件事;
|
|
130
|
-
- **全量数据仍由 `scout_report`(Markdown 报告)与 `scout_export`(文件)提供**——模型看到的是摘要,不是台账全文。
|
|
117
|
+
桌面版的 `desktop` profile 由 Electron 应用独占,CLI 无法管理它——`dsh plugin --profile desktop list` 与 `add` 都会被直接拒绝:
|
|
131
118
|
|
|
132
|
-
|
|
119
|
+
```text
|
|
120
|
+
error: profile "desktop" is managed exclusively by the Electron application
|
|
121
|
+
```
|
|
133
122
|
|
|
134
|
-
|
|
123
|
+
这是 CLI 里**按 profile 名**的硬拒绝,该 profile 的**所有** `dsh plugin` 子命令都会命中——包括下面兼容性小节里的 `allow-version`。请在**侧边栏 → 插件页**(安装、启用、移除都在这一页)里安装:
|
|
135
124
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
| `scout` Skill | 插件直接注册的尽调工作流(`ctx.skills.register`,不需要落文件、不需要 client bundle):start → search/ingest → claim → verify_identity → report → questions + 四条证据纪律;卸载即消失 |
|
|
125
|
+
```sh
|
|
126
|
+
dsh-scout@0.9.4
|
|
127
|
+
```
|
|
140
128
|
|
|
141
|
-
|
|
129
|
+
> 版本务必显式写死。pnpm ≥ 11 默认启用最小发布年龄(minimum release age)供应链保护,裸包名会让刚发布的版本被静默跳过、回退到旧版(0.9.2 发布后立即安装曾解析到 0.9.0);写上精确版本后 pnpm 会把它记入 profile 的 `minimumReleaseAgeExclude`(输出里打印 `Added 1 entry to …`)。
|
|
142
130
|
|
|
143
|
-
|
|
144
|
-
|
|
131
|
+
装完不需要重启:实测 12 个 `scout_*` 工具即时注入当前会话。桌面会话的 cwd 与 CLI 不同,建议在 profile 的 `cordis.patch.yml` 里给 `scoutDir` 配绝对路径(见下文「配置」)。
|
|
132
|
+
|
|
133
|
+
### 路径 1:CLI(npm,推荐)
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
# 把 <your-profile> 换成你自己的 profile 名,不要照抄示例
|
|
137
|
+
dsh plugin --profile <your-profile> add dsh-scout@0.9.4
|
|
145
138
|
```
|
|
146
139
|
|
|
147
|
-
|
|
140
|
+
<details>
|
|
141
|
+
<summary>怎么知道我的 profile 名?</summary>
|
|
148
142
|
|
|
149
|
-
|
|
143
|
+
`dsh` 没有 `profile list` 子命令(`profile` 会被当成 profile 名解析并报错),直接看目录:
|
|
144
|
+
|
|
145
|
+
```sh
|
|
146
|
+
ls ~/.dsh/profiles # 或用 $DSH_HOME/profiles
|
|
147
|
+
```
|
|
150
148
|
|
|
151
|
-
|
|
149
|
+
列出的每个名字都是可用 profile 名(如 `web`,或你自建的 profile)。`desktop` 由 App 独占,CLI 对它执行任何 `dsh plugin` 子命令都会被拒绝。
|
|
150
|
+
</details>
|
|
151
|
+
|
|
152
|
+
**不要照抄示例名**(例如 `scout-demo`):CLI 会照常创建并使用它、不报任何错——结果是插件装进了另一个 profile,你以为装好了却完全没生效。
|
|
153
|
+
|
|
154
|
+
### 路径 2:本地 tarball(离线 / 可复现)
|
|
152
155
|
|
|
153
156
|
```sh
|
|
154
|
-
#
|
|
155
|
-
dsh plugin --profile
|
|
157
|
+
pnpm pack # 生成 dsh-scout-0.9.4.tgz
|
|
158
|
+
dsh plugin --profile <your-profile> add "file:$PWD/dsh-scout-0.9.4.tgz"
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### 其他安装方式与取舍
|
|
162
|
+
|
|
163
|
+
| 来源 | 自带构建产物 | 执行安装脚本 | 建议 |
|
|
164
|
+
|---|---|---|---|
|
|
165
|
+
| npm(路径 1) | ✅ 自带 `dist/` | ❌(实测 `pendingBuilds: []`) | **推荐** |
|
|
166
|
+
| 本地 tarball(路径 2) | ✅(`pnpm pack` 产物) | ❌ | 离线 / 自测 |
|
|
167
|
+
| git:`github:MaxHou-infinity/dsh-scout#v0.9.4` | ❌(仓库不含 `dist/`) | ✅ `prepare` 会跑 `tsc`,并安装 devDependencies | **不推荐**;只在需要未发布提交时使用 |
|
|
168
|
+
|
|
169
|
+
git 路径的 ref 必须是**真实存在的 tag 或 commit**:仓库自 `v0.3.0` 起共 11 个 tag(`v0.3.0` … `v0.9.3`;`v0.9.1` 是本地迭代版、未打 tag),本次发布创建 `v0.9.4`。它也是三条路径里唯一会执行代码的:仓库不含 `dist/`,装完必然在本地构建,pnpm 可能要求为 `dsh-scout` 显式添加 `allowBuilds`(只放行你审查过的固定版本)。
|
|
156
170
|
|
|
157
|
-
|
|
158
|
-
pnpm pack # 生成 dsh-scout-0.9.2.tgz
|
|
159
|
-
dsh plugin --profile scout-demo add "file:$PWD/dsh-scout-0.9.2.tgz"
|
|
171
|
+
> 桌面 App 自带 node / pnpm 运行时(实测 node 24.21.0 + pnpm 11.7.0),**无需**安装 Node;「Node ≥ 22.19」只对 CLI / 门禁路径成立。
|
|
160
172
|
|
|
161
|
-
|
|
162
|
-
|
|
173
|
+
### 装上了吗(成功判据)
|
|
174
|
+
|
|
175
|
+
**桌面 App**
|
|
176
|
+
|
|
177
|
+
1. **侧边栏 → 插件页**:`dsh-scout` 出现在「已安装」里;**打开它的详情页**,标题旁带 `v0.9.4`——版本号只在这一页(列表卡片上只有「实验性 / 异常」状态标签);
|
|
178
|
+
2. **设置 → 内置插件 → 插件列表**:`dsh-scout` 行是 **已启用**、运行状态 **运行中**,不是 **已停用** / **启动失败** / **条件启用**(这一页**不显示版本号**);
|
|
179
|
+
3. 新开一轮对话,工具列表里出现 12 个 `scout_*` 工具;
|
|
180
|
+
4. 输入 `/scout status <caseId>` 能命中命令,且输出末尾带插件版本(`· dsh-scout 0.9.4`)——桌面看不到 stderr 与日志,这是确认运行时真正加载了哪个版本的自证面。
|
|
181
|
+
|
|
182
|
+
**CLI**
|
|
183
|
+
|
|
184
|
+
```sh
|
|
185
|
+
# 组合树里应出现 dsh-scout 那一层
|
|
186
|
+
dsh --profile <your-profile> --dump-config | grep -A2 'dsh-scout'
|
|
163
187
|
```
|
|
164
188
|
|
|
165
|
-
|
|
189
|
+
但**组合进去 ≠ 运行时挂上了**:最可靠的判据始终是「12 个 `scout_*` 工具是否出现」「`/scout` 是否命中」。
|
|
190
|
+
|
|
191
|
+
CLI 在运行时不兼容时会把插件行置为 disabled,进程只在 stderr 打一行 `dsh: disabling profile plugin <row>: <reason>`——现象是"插件没生效",不是显眼的红色报错。**桌面 App 看不到 stderr**(实测 Electron 主进程的 fd0/fd1/fd2 都指向 `/dev/null`,`~/Library/Logs/DeepSeek Harness/` 为空目录、全盘没有 DSH 运行日志),桌面排障只能走 GUI:**设置 → 内置插件 → 插件列表**按「会话插件 / 全局插件」分组,用 **已启用 / 已停用 / 启动失败 / 条件启用** 标签与 **运行中 / 启动失败 / 等待依赖 / 未运行** 运行状态回答"装没装、为什么没生效"(这一页**没有版本号**)——启动时被禁用的插件行(peer 不匹配是其中一种)会以「已停用」出现在这里,宿主侧的投影就是 `enabled: !entry.disabled`;那行被丢进 `/dev/null` 的 stderr,答案其实已经在 GUI 里。装的是哪一版,去**侧边栏 → 插件页**打开该插件的详情页看 `v{version}`。
|
|
192
|
+
|
|
193
|
+
### 卸载与升级
|
|
194
|
+
|
|
195
|
+
```sh
|
|
196
|
+
dsh plugin --profile <your-profile> add dsh-scout@<new-version> # 升级:换成目标版本,同样写死
|
|
197
|
+
dsh plugin --profile <your-profile> remove dsh-scout # 卸载
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
桌面 App 请在**侧边栏 → 插件页**里升级 / 移除。安装失败会回滚 profile 清单与 lockfile。
|
|
166
201
|
|
|
167
202
|
### DSH 兼容性
|
|
168
203
|
|
|
169
|
-
DSH
|
|
204
|
+
以下表格记录 **DSH 0.2.0-rc.2 的历史行为**。截至 2026-10-29,[官方当前规则](https://deepseek-harness.github.io/deepseek-harness/develop/basic/publish)已优先检查 `engines.dsh`,缺失时才回退检查 DSH peer 范围。本插件两处范围相同。
|
|
205
|
+
|
|
206
|
+
在上述旧运行时中,兼容性分为三个层次:
|
|
170
207
|
|
|
171
208
|
| 层次 | 位置 | 谁在执行 | 不匹配会怎样 |
|
|
172
209
|
|---|---|---|---|
|
|
173
|
-
| **声明** | `package.json` 的 `engines.dsh`(`>=0.1.0-rc.6 <0.3.0-0`) |
|
|
210
|
+
| **声明** | `package.json` 的 `engines.dsh`(`>=0.1.0-rc.6 <0.3.0-0`) | 该版本**没有代码**读取(DSH 0.2.0-rc.2 运行时不读 `engines.dsh`;官方 manifest 的注释写明 *"DSH compatibility is declarative until a reader enforces it"*) | 只表达作者意图,不拦截任何东西 |
|
|
174
211
|
| **生效** | `peerDependencies` 中名字为 `@deepseek-ai/dsh` / `@deepseek-ai/dsh-*` 的范围(本仓库只有 `@deepseek-ai/dsh-tools: ">=0.1.0-rc.6 <0.3.0-0"` 一条) | DSH 安装检查 + profile 启动预检 `evaluatePluginCompatibility()` | 安装阶段拒绝,或启动时禁用该插件行 |
|
|
175
212
|
| **不被校验** | `@deepseek-ai/cordis: ">=4.0.2 <5"`(以及 `@deepseek-ai/schemastery`) | DSH 的 peer 名字过滤只认 `@deepseek-ai/dsh` / `@deepseek-ai/dsh-*` | 由 pnpm 解析,DSH 不做兼容判定 |
|
|
176
213
|
|
|
177
214
|
三个必须知道的细节:
|
|
178
215
|
|
|
179
216
|
1. **预发布版本参与匹配。** 判定用 `semver.satisfies(runtime, range, { includePrerelease: true })`。上界写成 `<0.3.0-0` 正是为了在开启 prerelease 的前提下排除 `0.3.0-alpha` 及以后;反过来说,这条 range 的写法**依赖这个标志位**——去掉它,`0.2.0-rc.2` 会被判成不匹配。**用其它工具核对这条范围时请带上 `includePrerelease`**:按默认 semver 语义(node-semver 的预发布规则——预发布版本只被「同 major.minor.patch 元组且带预发布」的比较器接受),`0.1.2-rc.1` / `0.2.0-rc.2` / `0.2.1-alpha.2` 都会被判为**不满足**(semver 7.8.5 实测:`0.1.0-rc.6` 两种语义均为 true;后三者 plain=false / incl=true;`0.3.0-alpha.1` 两者均为 false)。**以 DSH 的判定为准。**
|
|
180
|
-
2. **失败的形态是「静默不加载」,不是报错。** 安装时能预判的 spec(`add` 一个 registry 包)会在 pnpm 执行前直接拒绝并打印豁免命令;git / tarball spec 在安装后判定,失败会回滚 profile 清单与 lockfile。而**已经在 profile 里、启动时才发现不匹配**的插件行会被置为 disabled,本进程只在 stderr 打一行 `dsh: disabling profile plugin <row>: <reason>`——用户看到的现象是"插件没生效"(工具不在、`/scout`
|
|
217
|
+
2. **失败的形态是「静默不加载」,不是报错。** 安装时能预判的 spec(`add` 一个 registry 包)会在 pnpm 执行前直接拒绝并打印豁免命令;git / tarball spec 在安装后判定,失败会回滚 profile 清单与 lockfile。而**已经在 profile 里、启动时才发现不匹配**的插件行会被置为 disabled,本进程只在 stderr 打一行 `dsh: disabling profile plugin <row>: <reason>`——用户看到的现象是"插件没生效"(工具不在、`/scout` 不在),不是一条显眼的红色报错。**这一行只对 CLI 用户可见**;桌面 App 的 stderr 指向 `/dev/null`、没有运行日志(见上文「装上了吗」),桌面上的状态只能在**设置 → 内置插件 → 插件列表**里看(装在哪个版本则看**侧边栏 → 插件页**)。
|
|
181
218
|
3. **这一条 `@deepseek-ai/dsh-tools` peer 就是全部门禁。** 改 peer 范围等于改兼容承诺。
|
|
182
219
|
|
|
183
220
|
#### 逃生门:profile 级精确版本豁免
|
|
@@ -199,27 +236,82 @@ dsh plugin --profile <name> revoke-version <package>@<version> --dsh-version <ex
|
|
|
199
236
|
|
|
200
237
|
授予豁免需要显式风险确认(CLI 的 `--accept-risk`,插件管理器里是 `acceptRisk: true`),DSH 会在写入前打印风险警告——不兼容的插件可能崩溃或损坏数据。
|
|
201
238
|
|
|
239
|
+
**桌面 App 用户**:`allow-version` 与其它 `dsh plugin` 子命令一样被按 profile 名拒绝,需要手动写这个文件。它是一个平铺的 JSON 对象——精确 `package@version` → 允许的精确 DSH 版本数组,例如桌面 App 的运行时为 `0.2.0-rc.2` 时:
|
|
240
|
+
|
|
241
|
+
```json
|
|
242
|
+
{
|
|
243
|
+
"dsh-scout@0.9.4": ["0.2.1-rc.5"]
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
手写同样受上面四条边界约束(只接受精确版本、只授权「这一个包版本 + 这一个 DSH 版本」这一对、不授权安装脚本、下一次组合生效),并且**绕过了 CLI 的 `--accept-risk` 风险确认**——不兼容的插件可能崩溃或损坏数据。运行时的精确版本可从 `~/.dsh/dsh-runtimes/*/runtime.json` 的 `desktopVersion` 读取;写法不合规的记录会被忽略并给出告警,不会让 profile 不可用。
|
|
248
|
+
|
|
202
249
|
#### 已实测版本矩阵
|
|
203
250
|
|
|
204
|
-
|
|
251
|
+
**`dsh-scout@0.9.4` 已在四个精确 DSH 版本上实测通过**(2026-11-07 发布前,隔离 profile,四个 binary 均从 npm 真实取用、非本机 DSH):覆盖安装、冷启动、工具挂载、**六步真实宿主门禁**(`scout_start` → 导出 → 冷重启 → 惰性回填 → 跨语言导入 → 卸载,外加「标记缺失 / `complete:false`」两个负向对照)和卸载。完整门禁由 `npm run check:release` 执行,实测输出:
|
|
205
252
|
|
|
206
253
|
```text
|
|
207
254
|
dsh-scout release gate: PASS (4 DSH versions, >=0.1.0-rc.6 <0.3.0-0)
|
|
208
255
|
```
|
|
209
256
|
|
|
210
|
-
| DSH 版本 | npm 渠道(2026-10-12 核对) | 0.9.
|
|
257
|
+
| DSH 版本 | npm 渠道(2026-10-12 核对) | 0.9.4(候选 tarball)结果 |
|
|
211
258
|
| --- | --- | --- |
|
|
212
259
|
| `0.1.0-rc.6` | 兼容范围下界 | 通过 |
|
|
213
260
|
| `0.1.2-rc.1` | 旧版回归 | 通过 |
|
|
214
261
|
| `0.2.0-rc.2` | `latest` / `next` | 通过 |
|
|
215
262
|
| `0.2.1-alpha.2` | `alpha` | 通过 |
|
|
216
263
|
|
|
217
|
-
本表此前记录过 **0.9.0** 与 **0.9.
|
|
264
|
+
本表此前记录过 **0.9.0**、**0.9.1** 与 **0.9.3** 的候选/已发布结果;0.9.4 沿用同一 `peerDependencies` 与 `engines.dsh` 范围(**没有变化**):本版改的是运行时 fs 沙箱接缝、阶段式报告与证据分档,并用同一道门禁在同样四个精确版本上复跑通过(4/4),故更新为本版本。上一版 **0.9.3 已发布到 npm**(`dist-tags.latest` = `0.9.3`):发布 workflow(run `38428072425`)在 `pnpm pack` 之前跑了同一道四版本门禁,所以当时这张表记录的 0.9.3 四版本通过,就是最终发布的那份。**0.9.2 已发布到 npm**(`dist-tags.latest` = `0.9.2`):发布 workflow(run `38406696598`)在 `pnpm pack` 之前跑了同一道四版本门禁,所以更早一次记录同样对应最终发布的产物。npm 渠道那一列仍是 2026-10-12 的核对结果,本次复跑未重新核对。0.9.1 新增的 `/scout` 命令与 Skill 走可选绑定,宿主没有对应服务时静默跳过,不影响加载。
|
|
265
|
+
|
|
266
|
+
2026-10-29 验证脚本修复:夜间检查改用 Node 24,以满足 DSH `0.2.2-alpha.2` 的 Node ≥24.9 要求;验证器通过公开的 `setExecutor` 能力区分单次与批量执行接口,并校验结果数量及调用 ID。失败不重试。该修复尚未发布到 npm,验证结果与边界见 [本次记录](docs/verification-dsh-2026-10-29.md)。
|
|
218
267
|
|
|
219
268
|
未来的 `0.2.x` 版本虽落在声明范围内,仍需实际验证。[夜间兼容检查](https://github.com/MaxHou-infinity/dsh-scout/actions/workflows/compatibility-nightly.yml)每天解析 npm 的 `latest`、`next`、`alpha` 到精确版本,再运行测试和隔离 profile 检查。徽章显示该工作流最近一次运行结果;以上表格记录已完成的精确版本验证。
|
|
220
269
|
|
|
221
270
|
> **夜间变红不等于插件坏了**:它可能只是声明范围过期(例如 DSH 发布 `0.3.0-alpha.1`)。`check:release` 会把「超出声明范围(预期)」与「范围内但失败(回归)」分开报告——前者应当更新声明范围,或按上面的精确版本豁免处理,而不是当成回归去修。
|
|
222
271
|
|
|
272
|
+
## 工具清单(12 个)
|
|
273
|
+
|
|
274
|
+
| 工具 | 作用 |
|
|
275
|
+
|---|---|
|
|
276
|
+
| `scout_start` | 创建尽调案例 |
|
|
277
|
+
| `scout_add_source` | 登记信息来源(含证据等级) |
|
|
278
|
+
| `scout_ingest` | 批量登记采集结果(自动推断来源类型/证据等级,可随来源一键登记主张草稿) |
|
|
279
|
+
| `scout_search` | 调用 DSH Web Provider 搜索并自动登记结果来源(type/evidence 按 URL 推断) |
|
|
280
|
+
| `scout_add_claim` | 添加证据受限的主张 |
|
|
281
|
+
| `scout_verify_identity` | 用 E3 官方源核验法定主体 |
|
|
282
|
+
| `scout_verify_claim` | 用更强证据提升主张为 verified |
|
|
283
|
+
| `scout_report` | 渲染当前 Markdown 报告 |
|
|
284
|
+
| `scout_questions` | 从案例派生去重、按优先级排序的面试问题清单(上限 12 条;案例自带的精选问题保留名额) |
|
|
285
|
+
| `scout_compare` | 2–5 个案例的并排对比报告(决策/主体/关键结论/风险/面试问题) |
|
|
286
|
+
| `scout_export` | 持久化五文件导出(case/sources/claims/events/report)+ 完成标记 |
|
|
287
|
+
| `scout_import` | 从导出目录恢复案例并重算决策(容忍旧导出,报 `complete`) |
|
|
288
|
+
|
|
289
|
+
### 输出契约(0.9.1 起)
|
|
290
|
+
|
|
291
|
+
变更类工具(`scout_start` / `scout_add_source` / `scout_ingest` / `scout_search` / `scout_add_claim` / `scout_verify_identity` / `scout_verify_claim` / `scout_import`,共 8 个)**不再把整份 case JSON 回吐给模型**:
|
|
292
|
+
|
|
293
|
+
- `value` 是**结构化对象**:`{ ok, caseId, decision, identity, counts: { sources, claims, verified, open }, changed: { kind, ids }, nextActions, persist? }`;
|
|
294
|
+
- `render` 是**整串不超过 1 KB 的紧凑摘要**:决策 + 本次增量 + 未核验阻断项 + 下一步。上限就是渲染预算本身(`MAX_RENDER_BYTES = 1024` B):省略号自身的 UTF-8 长度先从预算里扣掉、再按码元裁切,因此**含省略号的整串也不会超过 1024 B**;
|
|
295
|
+
- `persist: { persisted, targetDir, error? }` **只出现在变更类工具的 `autoPersist` 路径**(未尝试落盘时该键省略)。**落盘失败不再静默**:`persist.persisted === false` + `persist.error`,且不会产生 `case_exported` 事件。`scout_export` **不带 `persist` 键**,它用**顶层** `persisted` / `complete` / `error` 表达同一件事;
|
|
296
|
+
- **全量数据仍由 `scout_report`(Markdown 报告)与 `scout_export`(文件)提供**——模型看到的是摘要,不是台账全文。
|
|
297
|
+
|
|
298
|
+
读类工具各有自己的形状:`scout_report` → `{ caseId, decision, report, coverage }`;`scout_questions` → `{ caseId, questions }`;`scout_compare` → `{ caseIds, report }`;`scout_export` → `{ caseId, targetDir, files, persisted, complete, error? }`,其中 `targetDir` 是**解析后的绝对路径**。`scout_import` 复用变更类信封,并额外带 `sourceDir`(恢复来源目录)与 `complete`(导出是否完整)。
|
|
299
|
+
|
|
300
|
+
### 命令与 Skill(0.9.1 新增)
|
|
301
|
+
|
|
302
|
+
| 入口 | 作用 |
|
|
303
|
+
|---|---|
|
|
304
|
+
| `/scout` 命令 | `status` / `questions` / `report` / `export` 四个子动作(复用工具逻辑)。宿主会在处理前后自动落 `command/run` + `command/done` 事件——两者都在宿主已知事件词表内,所以会话日志天然可重建 |
|
|
305
|
+
| `scout` Skill | 插件直接注册的尽调工作流(`ctx.skills.register`,不需要落文件、不需要 client bundle):start → search/ingest → claim → verify_identity → report → questions + 四条证据纪律;卸载即消失 |
|
|
306
|
+
|
|
307
|
+
命令用法(与实现一致):
|
|
308
|
+
|
|
309
|
+
```text
|
|
310
|
+
/scout status <caseId> | /scout questions <caseId> | /scout report <caseId> | /scout export <caseId> [targetDir]
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
两者都是**可选绑定**:宿主没有 `commands` / `skills` 服务时静默跳过,不影响插件加载与工具使用。
|
|
314
|
+
|
|
223
315
|
## 配置(可选)
|
|
224
316
|
|
|
225
317
|
在 DSH profile 的 `cordis.patch.yml` 中为 `dsh-scout` 配置:
|
|
@@ -235,6 +327,7 @@ dsh-scout release gate: PASS (4 DSH versions, >=0.1.0-rc.6 <0.3.0-0)
|
|
|
235
327
|
```
|
|
236
328
|
|
|
237
329
|
- 相对 `scoutDir` 以**会话的 cwd** 为基准解析,不再落到 DSH 进程的当前目录;
|
|
330
|
+
- **桌面 App**:`scoutDir` 的默认值 `./dsh-scout` 依赖 cwd,而桌面会话的 cwd 语义与 CLI 不同,建议在 `~/.dsh/profiles/desktop/cordis.patch.yml` 里给 `id: dsh-scout` 直接写绝对路径;该文件由 App 维护,手改前先退出 App,避免写入被覆盖;
|
|
238
331
|
- `autoPersist: true` 时,每次变更后自动落盘;**失败可见**:返回值带 `persist.persisted=false` + `persist.error`,且不会写 `case_exported` 事件;
|
|
239
332
|
- `language` 影响报告、面试问题、对比报告,以及 `scout_ingest` 采集草稿自动写入的说明文字(`confidenceNote` / `nextAction`);它还会对齐案例自带、**仍是出厂默认**的文案,判定粒度不同:`decisionObjective` / `role.fitQuestion` 是**逐字段**(该字段仍是出厂默认即对齐);精选面试问题是**按下标逐条**——长度与出厂数组相同时,该下标仍是出厂默认的条目替换为本部署语言的同下标默认值,**用户改过的那条保持原样**;长度与出厂数组不同时,整组视为用户自撰、原样保留。判定依据是「是否等于该下标的出厂默认」,不是编辑历史(把某条改回出厂原文,那条会被对齐)。与案例自带语言相同时是 no-op,默认 `zh-CN` 对既有用户零变化。另外,`case.json` 里的 `language` 是**本部署的渲染语言**,不是文件内容的语言:对齐只按这个标签判定,**不校验标签与内容是否自洽**,所以手工把 `language` 改成与内容不符的值再导入时,插件会按「语言相同」提前返回、不做校正(正常的导出 / 导入 / 升级路径不受影响:0.9.0 旧导出的 `language` 恒为 `zh-CN`,与其内容一致)。
|
|
240
333
|
|
package/dist/i18n.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* pre-0.9.1 output; `en` is additive. This module only imports types so that
|
|
6
6
|
* `model.ts` can import it at runtime without creating an import cycle.
|
|
7
7
|
*/
|
|
8
|
-
import type { ClaimDimension, ClaimImpact, ClaimStatus, Decision, EvidenceLevel } from './model.js';
|
|
8
|
+
import type { ClaimDimension, ClaimImpact, ClaimStatus, Decision, EvidenceLevel, IdentityField, SourceType } from './model.js';
|
|
9
9
|
export declare const SCOUT_LANGUAGES: readonly ["zh-CN", "en"];
|
|
10
10
|
export type ScoutLanguage = typeof SCOUT_LANGUAGES[number];
|
|
11
11
|
export declare function isScoutLanguage(value: unknown): value is ScoutLanguage;
|
|
@@ -31,8 +31,153 @@ export interface ScoutStrings {
|
|
|
31
31
|
claimLedger: string;
|
|
32
32
|
sources: string;
|
|
33
33
|
coverage: string;
|
|
34
|
+
identity: string;
|
|
34
35
|
interviewQuestions: string;
|
|
35
36
|
};
|
|
37
|
+
/** Verified-subject block (legal entity, registration number, tier, provenance). */
|
|
38
|
+
identity: {
|
|
39
|
+
legalEntity: string;
|
|
40
|
+
registrationNumber: string;
|
|
41
|
+
region: string;
|
|
42
|
+
representative: string;
|
|
43
|
+
brandRelationship: string;
|
|
44
|
+
tier: string;
|
|
45
|
+
tiers: Record<'verified' | 'corroborated' | 'needs_verification', string>;
|
|
46
|
+
fieldLabels: Record<IdentityField, string>;
|
|
47
|
+
evidence: string;
|
|
48
|
+
fieldEvidence: string;
|
|
49
|
+
unknown: string;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Stage-based report (0.9.4 readability rework). The report body speaks the
|
|
53
|
+
* reader's language: no E-codes, no source ids, no internal status enums.
|
|
54
|
+
*/
|
|
55
|
+
report: {
|
|
56
|
+
meta: {
|
|
57
|
+
role: string;
|
|
58
|
+
location: string;
|
|
59
|
+
evidenceAsOf: string;
|
|
60
|
+
decision: string;
|
|
61
|
+
objective: string;
|
|
62
|
+
unknownLocation: string;
|
|
63
|
+
};
|
|
64
|
+
readingGuide: string;
|
|
65
|
+
confidenceLegend: string;
|
|
66
|
+
quick: {
|
|
67
|
+
heading: string;
|
|
68
|
+
entity: string;
|
|
69
|
+
entityUnverified: string;
|
|
70
|
+
business: string;
|
|
71
|
+
businessUnknown: string;
|
|
72
|
+
capital: string;
|
|
73
|
+
capitalSuffix: string;
|
|
74
|
+
capitalUnknown: string;
|
|
75
|
+
confirmHeading: string;
|
|
76
|
+
confirmIdentity: string;
|
|
77
|
+
confirmRole: string;
|
|
78
|
+
confirmRisk: string;
|
|
79
|
+
};
|
|
80
|
+
sections: {
|
|
81
|
+
identity: string;
|
|
82
|
+
confirmed: string;
|
|
83
|
+
open: string;
|
|
84
|
+
risk: string;
|
|
85
|
+
interview: string;
|
|
86
|
+
gap: string;
|
|
87
|
+
appendixSources: string;
|
|
88
|
+
appendixLedger: string;
|
|
89
|
+
appendixCoverage: string;
|
|
90
|
+
appendixGlossary: string;
|
|
91
|
+
};
|
|
92
|
+
themes: {
|
|
93
|
+
business: string;
|
|
94
|
+
capital: string;
|
|
95
|
+
organization: string;
|
|
96
|
+
};
|
|
97
|
+
openSubheads: {
|
|
98
|
+
interview: string;
|
|
99
|
+
external: string;
|
|
100
|
+
conflict: string;
|
|
101
|
+
};
|
|
102
|
+
labels: {
|
|
103
|
+
ask: string;
|
|
104
|
+
nextStep: string;
|
|
105
|
+
advice: string;
|
|
106
|
+
tier: string;
|
|
107
|
+
means: string;
|
|
108
|
+
identityEvidence: string;
|
|
109
|
+
};
|
|
110
|
+
tier: {
|
|
111
|
+
verified: string;
|
|
112
|
+
corroborated: string;
|
|
113
|
+
unverified: string;
|
|
114
|
+
meansVerified: string;
|
|
115
|
+
meansOther: string;
|
|
116
|
+
};
|
|
117
|
+
confirmedItem: string;
|
|
118
|
+
captured: string;
|
|
119
|
+
openInterviewLine: string;
|
|
120
|
+
openExternalLine: string;
|
|
121
|
+
riskLine: string;
|
|
122
|
+
gapLine: {
|
|
123
|
+
why: string;
|
|
124
|
+
toProceed: string;
|
|
125
|
+
minActions: string;
|
|
126
|
+
identityItem: string;
|
|
127
|
+
};
|
|
128
|
+
decisionSentences: {
|
|
129
|
+
proceed: string;
|
|
130
|
+
identity: string;
|
|
131
|
+
corroborated: string;
|
|
132
|
+
unresolved: string;
|
|
133
|
+
stop: string;
|
|
134
|
+
};
|
|
135
|
+
questionThemes: {
|
|
136
|
+
role: string;
|
|
137
|
+
capital: string;
|
|
138
|
+
product: string;
|
|
139
|
+
process: string;
|
|
140
|
+
general: string;
|
|
141
|
+
};
|
|
142
|
+
questionKeywords: {
|
|
143
|
+
role: string[];
|
|
144
|
+
capital: string[];
|
|
145
|
+
product: string[];
|
|
146
|
+
process: string[];
|
|
147
|
+
};
|
|
148
|
+
tableHeaders: {
|
|
149
|
+
item: string;
|
|
150
|
+
value: string;
|
|
151
|
+
id: string;
|
|
152
|
+
source: string;
|
|
153
|
+
type: string;
|
|
154
|
+
level: string;
|
|
155
|
+
capturedAt: string;
|
|
156
|
+
summary: string;
|
|
157
|
+
stage: string;
|
|
158
|
+
impact: string;
|
|
159
|
+
next: string;
|
|
160
|
+
code: string;
|
|
161
|
+
label: string;
|
|
162
|
+
meaning: string;
|
|
163
|
+
};
|
|
164
|
+
coverage: {
|
|
165
|
+
untouched: string;
|
|
166
|
+
openOnly: string;
|
|
167
|
+
verified: string;
|
|
168
|
+
withOpen: string;
|
|
169
|
+
};
|
|
170
|
+
sourceTypes: Record<SourceType, string>;
|
|
171
|
+
levelLabels: Record<EvidenceLevel, string>;
|
|
172
|
+
levelMeanings: Record<EvidenceLevel, string>;
|
|
173
|
+
statusMeanings: Partial<Record<ClaimStatus, string>>;
|
|
174
|
+
empty: {
|
|
175
|
+
noVerified: string;
|
|
176
|
+
noOpen: string;
|
|
177
|
+
noRisks: string;
|
|
178
|
+
noQuestions: string;
|
|
179
|
+
};
|
|
180
|
+
};
|
|
36
181
|
/** Claim rendering templates. */
|
|
37
182
|
claim: {
|
|
38
183
|
line: string;
|
|
@@ -52,6 +197,7 @@ export interface ScoutStrings {
|
|
|
52
197
|
/** Investigation coverage block. */
|
|
53
198
|
coverage: {
|
|
54
199
|
entry: string;
|
|
200
|
+
identityEntry: string;
|
|
55
201
|
untouchedLine: string;
|
|
56
202
|
yes: string;
|
|
57
203
|
no: string;
|
|
@@ -63,6 +209,8 @@ export interface ScoutStrings {
|
|
|
63
209
|
/** One line per decision reason code; the missing-dimension one is a template. */
|
|
64
210
|
decisionReasons: {
|
|
65
211
|
identity: string;
|
|
212
|
+
identityCorroborated: string;
|
|
213
|
+
identityCorroboratedClear: string;
|
|
66
214
|
unresolved: string;
|
|
67
215
|
missingDimension: string;
|
|
68
216
|
proceed: string;
|
|
@@ -86,12 +234,20 @@ export interface ScoutStrings {
|
|
|
86
234
|
autoConfidenceNote: string;
|
|
87
235
|
autoNextAction: string;
|
|
88
236
|
};
|
|
237
|
+
/** Fallback next actions for a case that has no open claim yet. */
|
|
238
|
+
nextActions: {
|
|
239
|
+
verifyIdentity: string;
|
|
240
|
+
collectSources: string;
|
|
241
|
+
missingDimension: string;
|
|
242
|
+
conclude: string;
|
|
243
|
+
};
|
|
89
244
|
comparison: {
|
|
90
245
|
title: string;
|
|
91
246
|
overviewHeading: string;
|
|
92
247
|
summary: string;
|
|
93
248
|
countsSuffix: string;
|
|
94
249
|
identityVerified: string;
|
|
250
|
+
identityCorroborated: string;
|
|
95
251
|
identityUnverified: string;
|
|
96
252
|
decisionTableHeading: string;
|
|
97
253
|
tableHeader: string;
|