🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

过程监督 qlheric/dsh-cvm

DeepSeek Harness
qlheric23 天前有提交已提供中文文档扫描:含敏感能力

dsh-cvm —— 给 DSH agent 加一层「防卡住 / 防假完成 / 防超支」的运行时监督

30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/9 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查未通过:缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add qlheric/dsh-cvm
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:待复验
是什么
dsh 原生插件 · security
装得上吗
曾在 dsh 0.2.0-rc.2 下真实安装成功,但当前 dsh 已更新至 0.2.1-rc.5,本站尚未在新版下复验
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 23 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装

缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-cvm-workspace(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/14 04:18:49

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件
查看扫描证据(共 50 处,展示前 48 条)
  • 写入本地文件
    eval/batch-eval.mjs:21
    mkdirSync(OUTDIR, { recursive: true });
  • 读取本地文件
    eval/batch-eval.mjs:24
    if (reset && existsSync(outFile)) rmSync(outFile);
  • 删除本地文件
    eval/batch-eval.mjs:24
    if (reset && existsSync(outFile)) rmSync(outFile);
  • 写入本地文件
    eval/batch-eval.mjs:30
    mkdirSync(fix, { recursive: true });
  • 读取本地文件
    eval/batch-eval.mjs:31
    for (const name of readdirSync(fix)) {
  • 删除本地文件递归
    eval/batch-eval.mjs:33
    rmSync(join(fix, name), { recursive: true, force: true });
  • 读取本地文件
    eval/batch-eval.mjs:35
    for (const name of readdirSync(scen)) {
  • 写入本地文件
    eval/batch-eval.mjs:36
    copyFileSync(join(scen, name), join(fix, name));
  • 读取本地文件
    eval/batch-eval.mjs:40
    const done = existsSync(outFile)
  • 读取本地文件
    eval/batch-eval.mjs:41
    ? readFileSync(outFile, 'utf8').split('\n').filter((l) => l.trim() !== '').length
  • 执行外部命令来自配置/变量
    eval/batch-eval.mjs:50
    const r = spawnSync(NODE, [join(__dirname, 'drive.mjs'), '--case', caseId], {
  • 写入本地文件
    eval/batch-eval.mjs:64
    appendFileSync(outFile, `${JSON.stringify({ i: i + 1, pass, detail, metrics })}\n`);
  • 读取本地文件
    eval/batch-eval.mjs:68
    const lines = readFileSync(outFile, 'utf8').split('\n').filter(Boolean).map((l) => JSON.parse(l));
  • 读取本地文件
    eval/cost-run.mjs:14
    const CASES = JSON.parse(readFileSync(join(ROOT, 'eval', 'cases.json'), 'utf8')).cases;
  • 写入本地文件
    eval/cost-run.mjs:28
    mkdirSync(OUTDIR, { recursive: true });
  • 写入本地文件
    eval/cost-run.mjs:38
    mkdirSync(FIXTURES, { recursive: true });
  • 读取本地文件
    eval/cost-run.mjs:39
    for (const name of readdirSync(FIXTURES)) {
  • 删除本地文件递归
    eval/cost-run.mjs:41
    rmSync(join(FIXTURES, name), { recursive: true, force: true });
  • 读取本地文件
    eval/cost-run.mjs:43
    for (const name of readdirSync(SCEN)) copyFileSync(join(SCEN, name), join(FIXTURES, name));
  • 写入本地文件
    eval/cost-run.mjs:43
    for (const name of readdirSync(SCEN)) copyFileSync(join(SCEN, name), join(FIXTURES, name));
  • 执行外部命令来自配置/变量
    eval/cost-run.mjs:60
    const r = spawnSync(NODE, args, {
  • 读取本地文件
    eval/cost-run.mjs:81
    const done = existsSync(outFile)
  • 读取本地文件
    eval/cost-run.mjs:82
    ? readFileSync(outFile, 'utf8').split('\n').filter((l) => l.trim()).length
  • 写入本地文件
    eval/cost-run.mjs:88
    appendFileSync(outFile, `${JSON.stringify({ i: i + 1, ...rec })}\n`);
  • 读取本地文件
    eval/cost-run.mjs:90
    const lines = readFileSync(outFile, 'utf8').split('\n').filter(Boolean).map((l) => JSON.parse(l));
  • 读取本地文件
    eval/cost-summary.mjs:17
    if (!existsSync(f)) return null;
  • 读取本地文件
    eval/cost-summary.mjs:18
    return readFileSync(f, 'utf8').split('\n').filter(Boolean).map((l) => JSON.parse(l));
  • 读取本地文件
    eval/drive.mjs:13
    const CASES = JSON.parse(readFileSync(join(ROOT, 'eval', 'cases.json'), 'utf8')).cases;
  • 执行外部命令固定命令
    eval/drive.mjs:134
    const r = spawnSync('python', [script, ...(j.args ?? [])], {
  • 读取本地文件
    eval/drive.mjs:147
    const same = existsSync(cur) && existsSync(tpl) && readFileSync(cur, 'utf8') === readFileSync(tpl, 'utf8');
  • 读取本地文件
    eval/drive.mjs:147
    const same = existsSync(cur) && existsSync(tpl) && readFileSync(cur, 'utf8') === readFileSync(tpl, 'utf8');
  • 执行外部命令来自配置/变量
    eval/drive.mjs:170
    const r = spawnSync(NODE, args, {
  • 读取本地文件
    eval/parallel-eval.mjs:11
    const CASES = JSON.parse(readFileSync(join(ROOT, 'eval', 'cases.json'), 'utf8')).cases;
  • 执行外部命令来自配置/变量
    eval/parallel-eval.mjs:22
    const child = spawn(NODE, args, { cwd: FIXTURES, env: { ...process.env, DSH_HOME } });
  • 读取本地文件
    install.mjs:51
    if (!existsSync(dir)) return [];
  • 读取本地文件
    install.mjs:53
    return readdirSync(dir, { withFileTypes: true })
  • 执行外部命令来自配置/变量
    install.mjs:60
    return spawnSync(cmd, args, {
  • 读取本地文件
    src/domain/ledger-validator.mjs:208
    stat = statSync(filePath);
  • 读取本地文件
    src/domain/ledger-validator.mjs:219
    raw = readFileSync(filePath, 'utf8');
  • 写入本地文件
    src/domain/test-ledger-validator.mjs:155
    writeFileSync(p, JSON.stringify(ledger(), null, 2), 'utf8');
  • 删除本地文件递归
    src/domain/test-ledger-validator.mjs:159
    } finally { rmSync(dir, { recursive: true, force: true }); }
  • 写入本地文件
    src/domain/test-ledger-validator.mjs:165
    writeFileSync(p, '{ not json', 'utf8');
  • 删除本地文件递归
    src/domain/test-ledger-validator.mjs:169
    } finally { rmSync(dir, { recursive: true, force: true }); }
  • 执行外部命令来自配置/变量
    src/domain/test-ledger-validator.mjs:183
    const runCli = (args) => spawnSync(process.execPath, [CLI_PATH, ...args], { encoding: 'utf8' });
  • 写入本地文件
    src/domain/test-ledger-validator.mjs:194
    writeFileSync(p, JSON.stringify(ledger(), null, 2), 'utf8');
  • 删除本地文件递归
    src/domain/test-ledger-validator.mjs:198
    } finally { rmSync(dir, { recursive: true, force: true }); }
  • 写入本地文件
    src/domain/test-ledger-validator.mjs:204
    writeFileSync(p, JSON.stringify(ledger([unit({ reviewed_paths: [] })]), null, 2), 'utf8');
  • 删除本地文件递归
    src/domain/test-ledger-validator.mjs:208
    } finally { rmSync(dir, { recursive: true, force: true }); }
扫描于 2026/11/1(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-llm@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 防卡住与假完成
  • 四道认知护栏
  • 预算超支提醒

防止 DSH 智能体卡壳、假装完工或超支:4 道认知护栏(任务契约/循环检测/完工前举证/单一注入点)+ 1 道成本护栏(预算提醒)。不改核心,只用官方扩展点。

README

由 DeepSeek 最新模型翻译生成
dsh-cvm —— 给 DSH agent 加一层「防卡住 / 防假完成 / 防超支」的运行时监督 五个正交的 Cordis 插件(4 认知监督 + 1 成本监督),不改 DSH 内核,只用官方接缝。 不提升模型能力——模型已经够强了;它管的是偶尔会出现的几种「跑偏」。 实测结论:几乎零成本地把「打转」削掉一半(−48%),单任务成本仅 +2%。 一、它解决什么问题(先看症状,对号入座) 强模型在长任务里偶尔会停在一个低于自己水平的状态。三种症状,中了哪条装哪个插件: | 你会看到的症状 | 它为什么坏 | 插件 | 做什么 | | 第 1 轮说了硬约束,第 6 轮忘了——把「不许动」的文件也改了 | 全局目标被最近的局部信号挤掉 | dsh-contract | 把首条消息落成任务契约(含约束原话)钉进 system prompt | | 反复读文件、就是不推进——烧掉几十步,最后啥也没改 | 轨迹塌进「打转」,没有信息增益 | dsh-convergence | 数连续只读,到阈值提示「停止读,直接改/验证」 | | 说「已完成」,其实一次没跑过——改了文件就宣布成功 | 模型被自己的结论锚住 | dsh-evidence | 检测「声称完成 + 改了文件 + 没有一次成功验证」 | 上面三个只检测,真正「开口」的是第四个: | 插件 | 职责 |
展开完整文档(README 剩余 1 节)
dsh-cvm —— 给 DSH agent 加一层「防卡住 / 防假完成 / 防超支」的运行时监督

五个正交的 Cordis 插件(4 认知监督 + 1 成本监督),不改 DSH 内核,只用官方接缝。
不提升模型能力——模型已经够强了;它管的是偶尔会出现的几种「跑偏」。
实测结论:几乎零成本地把「打转」削掉一半(−48%),单任务成本仅 +2%。

一、它解决什么问题(先看症状,对号入座)

强模型在长任务里偶尔会停在一个低于自己水平的状态。三种症状,中了哪条装哪个插件:

| 你会看到的症状 | 它为什么坏 | 插件 | 做什么 |
| 第 1 轮说了硬约束,第 6 轮忘了——把「不许动」的文件也改了 | 全局目标被最近的局部信号挤掉 | dsh-contract | 把首条消息落成任务契约(含约束原话)钉进 system prompt |
| 反复读文件、就是不推进——烧掉几十步,最后啥也没改 | 轨迹塌进「打转」,没有信息增益 | dsh-convergence | 数连续只读,到阈值提示「停止读,直接改/验证」 |
| 说「已完成」,其实一次没跑过——改了文件就宣布成功 | 模型被自己的结论锚住 | dsh-evidence | 检测「声称完成 + 改了文件 + 没有一次成功验证」 |

上面三个只检测,真正「开口」的是第四个:

| 插件 | 职责 |
| dsh-intervention | 唯一注入点:读前三个状态 → 注入提示,或在轮次收尾 agent.steer 强制再走一步 |

检测(写状态)与行动(读状态)分开 → 每个都能单独开关、单独调参,互不耦合。

B 组|成本监督(一个):dsh-budget —— token 不知不觉烧掉一大截时,到阈值软提醒一次(不中断、不做硬熔断)。与 A 组完全正交,可只装 A 不装 B。

一句话定位:给强模型加的过程保险。风险不是「模型做错」,而是「模型偶尔停住或自我说服」。适用于长任务、要它真跑起来、无人看管防打转、控成本;不适用于一句话问答。

二、装(一条命令)

node install.mjs # dry-run:只打印命令
node install.mjs --apply --profile <你的profile> # 真装(5 个包 + 自动自检)
node install.mjs --check --profile <你的profile> # 只自检

⚠️ 不要用 add github:qlheric/dsh-cvm(不带 #path:)——本仓库根是 workspace 包,那样只装到根包、一个插件都不生效。

三、配置(都能单独关)

所有阈值/关键词/提示文本都在各插件 Config(schemastery),可在 cordis.patch.yml 覆盖(跨升级存活):

- id: convergence
config:
threshold: 5 # 连续只读 5 次判定打转
- id: intervention
config:
steerAtTurnStop: false # 关掉「收尾强制再走一步」
- id: evidence
config:
enabled: false # 整个终局门禁关掉
- id: budget
config:
maxTokens: 1000000
softRatio: 0.8

四、实测效果(诚实版)

一句话结论:削打转 −48%,单任务成本 +2%(基本打平)。 价值在「过程」(少打转、少假完成),不在「结果」——强模型本来就不怎么掉,任务成功率测不出差异。

完整数据台账在 C1-AB数据汇总.md,下面的数字都来自各 20 次的 A/B(eval/batch-eval.mjs)。

4.1 关键归因:成本一度 +28.7%,真凶不是缓存,是「轨迹变长」

早期实测打转确实被削了(−33%),但 token 成本反而 +28.7%。最初怀疑是「动态注入 system prompt 破坏前缀缓存」,于是加了两项观测来验证:

- 缓存命中率:cacheReadRatio 基线 96.4% → 装插件 95.2%,几乎没动——缓存根本没坏。
- 成本加权 token(cache_read ×0.1、cache_write ×1.25,区分「命中 vs 未命中」):这才是真实成本。

结论:成本上升不是缓存失效,而是「轨迹变长」——干预把「一次长打转」拆成了「多次短探索/验证」,模型被提醒后反而更谨慎、多读多验,总工作量增加。

4.2 关键改进:把干预从「发散」改成「收敛」

对症下药:不是改注入机制,而是改文案方向。原来提示「换一种方法」是发散指令(诱发更多探索);改成收敛指令后成本一路压下来:

| 版本(各 20 次) | 打转 maxReadStreak | 真实成本 costTokens |
| 旧文案「换一种方法」 | −33% | +28.7% |
| 收敛文案「停止读 + 直接改」 | −48% | +12.7% |
| +「验证一次就够」✅ | −48% | +2.2% |
| 滞回冷却(边沿只注入一次)❌ | −34% | +8.6%(已回退) |

最终定案的干预文案(收敛版,也是默认):

⚠️ 运行时检测:已连续 N 次只读、无推进。停止读文件,直接改最可疑处并运行验证——验证一次就够,不要反复验证;不确定就运行最小复现命令;信息不足就用一句话说明卡点。

4.3 边界(别把数字当承诺)

- 样本 20 次/组,方向性证据,未到生产级(隔离 DSH_HOME + headless)。
- 结果指标测不出:强模型在 C5 场景基线就 20/20,价值只在过程指标(打转长度/步数),且要看 sd / 极值,不能只看均值。
- 阈值有倒 U 型最优窗口:T=5 最优,T=3(过早打断探索)和 T=8(已陷深打转)都比不装还差。
- 留着一个被撤回的假阳性当标本:差异 10pp 时 p≈0.34,样本不够就下结论会翻车(详见台账 §11)。

五、已知代价(风险是「误伤」,不是「没效果」)

- dsh-evidence 早期把 tool/result.error 当成「工具失败」,在调试场景误判正常报错,退化率反涨到 37.5%。修正为「验证工具成功执行才算验证过」后消除。
- dsh-convergence 的 threshold 过低(T=3)会过早干预、恶化过程。
- dsh-budget 的团队聚合是「下界」:只计当前活跃子 agent(已结束的无法归属)。

⇒ 每个插件都可配、可单独关;调参按场景标定,不照搬默认值。

六、评测方法学(写给要复现的人)

1. 场景文件每轮复位,复位源不能是 git HEAD(模型产物会被 git add -A 一起提交)——用独立模板目录 eval/scenarios/。
2. A/B 数据并存:batch-eval.mjs --label A|B,否则互相覆盖。
3. 别只看均值:强模型的过程指标均值可能不动,差异在 sd / 极值 / p90。
4. 单测 mock 必须对齐真实事件结构(user/message 的 payload 是 UserMessage,assistant/message 才是嵌套 {turn,step,message})。
5. 归因要分项 token:totalTokens 简单相加看不出缓存问题,要用 cacheReadRatio + costTokens(成本加权)拆「缓存失效 vs 轨迹变长」。

七、目录

packages/dsh-{contract,convergence,evidence,intervention,budget}/ # 五个插件
install.mjs # 一键安装器 eval/ # 评测集 + 驱动 + cost-summary src/domain/ # 单测 *.md # 知识底座、调研、数据台账

License

MIT
预览分享卡片长什么样 ↓qlheric/dsh-cvm
分享 · DeepSeek Harness Hub
qlheric/dsh-cvm

dsh-cvm —— 给 DSH agent 加一层「防卡住 / 防假完成 / 防超支」的运行时监督

回到顶部