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

运行时护栏 goatliamia/dsh-runtime

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

拦截重复无效动作,核对工具执行真实结果

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

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

自动兼容检查未通过:仓库根目录无 package.json,浅层子目录有 12 份 dsh 插件清单(plugins/dsh-notify/package.json、plugins/runtime-progress/package.json、experiments/harness/fixture/package.json 等),无法唯一定位安装名。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add goatliamia/dsh-runtime
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · other
装得上吗
作者未把包发布到 npm,只能用源码安装
插件本身没问题,是分发方式不同
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 46 天前
档位由哪些信号合成

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

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

仓库根目录无 package.json,浅层子目录有 12 份 dsh 插件清单(plugins/dsh-notify/package.json、plugins/runtime-progress/package.json、experiments/harness/fixture/package.json 等),无法唯一定位安装名

展开查看检查明细 ↓

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

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

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

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/3 15:20:13

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

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 58 处,展示前 57 条)
  • 写入本地文件
    core/runtime-circuit/lib/index.js:130
    writeFileSync(
  • 写入本地文件
    core/runtime-investigate/lib/index.js:138
    writeFileSync(
  • 写入本地文件
    core/runtime-progress/lib/index.js:272
    writeFileSync(join(resultsDir, `${runId}.projection.json`), `${JSON.stringify(payload, null, 2)}\n`);
  • 写入本地文件
    core/runtime-reconcile/lib/index.js:142
    writeFileSync(
  • 发起网络请求
    core/runtime-seam/lib/client.js:97
    fetch("/api/runtime-seam/activity")
  • 发起网络请求
    core/runtime-seam/lib/client.js:113
    return fetch(path, {
  • 读取本地文件
    core/runtime-seam/lib/index.js:127
    if (readConfig().capabilities.persistence && existsSync(STATE_FILE)) {
  • 读取本地文件
    core/runtime-seam/lib/index.js:129
    const saved = JSON.parse(readFileSync(STATE_FILE, "utf8"));
  • 写入本地文件
    core/runtime-seam/lib/index.js:145
    mkdirSync(STATE_DIR, { recursive: true });
  • 写入本地文件
    core/runtime-seam/lib/index.js:146
    writeFileSync(
  • 写入本地文件
    core/runtime-seam/lib/pre-continuation.mjs:215
    mkdirSync(join(diagPath, ".."), { recursive: true });
  • 写入本地文件
    core/runtime-seam/lib/pre-continuation.mjs:216
    writeFileSync(diagPath, JSON.stringify({ ...diag, metrics: state.metrics }, null, 2));
  • 读取本地文件
    experiments/harness/aggregate.mjs:18
    if (!existsSync(path)) return null;
  • 读取本地文件
    experiments/harness/aggregate.mjs:20
    return JSON.parse(readFileSync(path, "utf8"));
  • 读取本地文件
    experiments/harness/aggregate.mjs:28
    if (!existsSync(path)) return { found: false };
  • 读取本地文件
    experiments/harness/aggregate.mjs:30
    return { found: true, text: readFileSync(path, "utf8").trim() };
  • 读取本地文件
    experiments/harness/aggregate.mjs:38
    if (!existsSync(path)) return "";
  • 读取本地文件
    experiments/harness/aggregate.mjs:40
    const text = readFileSync(path, "utf8");
  • 写入本地文件
    experiments/harness/aggregate.mjs:190
    writeFileSync(join(RESULTS, "summary.json"), JSON.stringify(summary, null, 2));
  • 写入本地文件
    experiments/harness/aggregate.mjs:191
    writeFileSync(join(RESULTS, "summary.md"), md.join("\n"));
  • 读取本地文件
    experiments/harness/aggregate2.mjs:26
    if (!existsSync(path)) return null;
  • 读取本地文件
    experiments/harness/aggregate2.mjs:28
    return JSON.parse(readFileSync(path, "utf8"));
  • 读取本地文件
    experiments/harness/aggregate2.mjs:36
    if (!existsSync(path)) return "(missing)";
  • 读取本地文件
    experiments/harness/aggregate2.mjs:38
    return readFileSync(path, "utf8").trim().replace(/ +/g, " ").slice(0, 80);
  • 读取本地文件
    experiments/harness/aggregate2.mjs:58
    for (const file of readdirSync(RESULTS)) {
  • 写入本地文件
    experiments/harness/aggregate2.mjs:172
    writeFileSync(join(RESULTS, "summary2.json"), JSON.stringify(summary, null, 2));
  • 写入本地文件
    experiments/harness/aggregate2.mjs:173
    writeFileSync(join(RESULTS, "summary2.md"), md.join("\n"));
  • 读取本地文件
    experiments/harness/aggregate4.mjs:18
    if (!existsSync(path)) return null;
  • 读取本地文件
    experiments/harness/aggregate4.mjs:20
    return JSON.parse(readFileSync(path, "utf8"));
  • 读取本地文件
    experiments/harness/aggregate4.mjs:28
    if (!existsSync(path)) return "(missing)";
  • 读取本地文件
    experiments/harness/aggregate4.mjs:30
    return readFileSync(path, "utf8").trim().replace(/ +/g, " ").slice(0, 60);
  • 读取本地文件
    experiments/harness/aggregate4.mjs:44
    for (const file of readdirSync(RESULTS)) {
  • 写入本地文件
    experiments/harness/aggregate4.mjs:109
    writeFileSync(join(RESULTS, "summary4.json"), JSON.stringify({ generatedAt: new Date().toISOString(), byArm, rows }, null, 2));
  • 写入本地文件
    experiments/harness/aggregate4.mjs:110
    writeFileSync(join(RESULTS, "summary4.md"), md.join("\n"));
  • 读取本地文件
    experiments/harness/aggregate4b.mjs:17
    if (!existsSync(path)) return null;
  • 读取本地文件
    experiments/harness/aggregate4b.mjs:19
    return JSON.parse(readFileSync(path, "utf8"));
  • 读取本地文件
    experiments/harness/aggregate4b.mjs:27
    if (!existsSync(path)) return "(missing)";
  • 读取本地文件
    experiments/harness/aggregate4b.mjs:29
    return readFileSync(path, "utf8").trim().replace(/ +/g, " ").slice(0, 60);
  • 读取本地文件
    experiments/harness/aggregate4b.mjs:43
    for (const file of readdirSync(RESULTS)) {
  • 写入本地文件
    experiments/harness/aggregate4b.mjs:107
    writeFileSync(join(RESULTS, "summary4b.json"), JSON.stringify({ generatedAt: new Date().toISOString(), byArm, rows }, null, 2));
  • 写入本地文件
    experiments/harness/aggregate4b.mjs:108
    writeFileSync(join(RESULTS, "summary4b.md"), md.join("\n"));
  • 读取本地文件
    experiments/harness/aggregate56.mjs:11
    if (!existsSync(path)) return null;
  • 读取本地文件
    experiments/harness/aggregate56.mjs:13
    return JSON.parse(readFileSync(path, "utf8"));
  • 读取本地文件
    experiments/harness/aggregate56.mjs:21
    if (!existsSync(path)) return "(missing)";
  • 读取本地文件
    experiments/harness/aggregate56.mjs:23
    return readFileSync(path, "utf8").trim().replace(/ +/g, " ").slice(0, 140);
  • 读取本地文件
    experiments/harness/aggregate56.mjs:37
    for (const file of readdirSync(RESULTS)) {
  • 写入本地文件
    experiments/harness/aggregate56.mjs:116
    writeFileSync(join(RESULTS, "summary56.json"), JSON.stringify({ generatedAt: new Date().toISOString(), e5, e6 }, null, 2));
  • 写入本地文件
    experiments/harness/aggregate56.mjs:117
    writeFileSync(join(RESULTS, "summary56.md"), md.join("\n"));
  • 读取本地文件
    experiments/harness/aggregate7.mjs:12
    if (!existsSync(path)) return null;
  • 读取本地文件
    experiments/harness/aggregate7.mjs:14
    return JSON.parse(readFileSync(path, "utf8"));
  • 读取本地文件
    experiments/harness/aggregate7.mjs:28
    if (!existsSync(path)) return "(missing)";
  • 读取本地文件
    experiments/harness/aggregate7.mjs:30
    return readFileSync(path, "utf8").trim().replace(/ +/g, " ").slice(0, 100);
  • 读取本地文件
    experiments/harness/aggregate7.mjs:38
    for (const file of readdirSync(RESULTS)) {
  • 写入本地文件
    experiments/harness/aggregate7.mjs:166
    writeFileSync(join(RESULTS, "summary7.md"), md.join("\n"));
  • 执行外部命令固定命令
    plugins/dsh-notify/lib/notify.js:120
    return spawn("osascript", ["-e", expr], { stdio: "ignore" });
  • 执行外部命令固定命令
    plugins/dsh-notify/lib/notify.js:149
    child = spawn(
  • 执行外部命令固定命令
    plugins/dsh-notify/lib/notify.js:165
    child = spawn("notify-send", [opts.title, opts.body], { stdio: "ignore" });
扫描于 2026/11/4(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库

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

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 拦截重复无效动作
  • 核对工具执行结果

不要让 Model 为确定性问题反复思考,也不要让 Harness 为不确定的问题假装知道答案

README

由 DeepSeek 最新模型翻译生成
DSH Runtime 让模型负责思考,让 Harness 处理那些可以确定的事情。 dsh-runtime 是一组面向 DeepSeek Harness 的小型 Runtime 能力。 它不试图做一个新的 Agent,也不试图用更多 Prompt、Skill 或规则去“教会”模型所有事情。 它只接住一类问题: 那些模型不应该反复猜,Harness 本来就可以确定的问题。 例如: * 这件事现在能不能做? * 刚才这一步到底有没有产生变化? * 工具虽然报错了,实际操作有没有已经发生? * 工具说成功了,目标状态有没有真的生效? * 一个动作已经重复很多次,但事情有没有继续往前走? 安装 一条命令装完(所有能力都在一个包里;装完去设置页选模式 / 场景 / 自定义即可): 从 GitHub 页面直接下载 release/dsh-runtime-0.1.0.tgz,或先 clone 仓库 dsh plugin --profile add dsh-runtime-0.1.0.tgz 装完 dsh --profile --dump-config 能看到 runtime-progress / circuit / reconcile / investigate / seam 五行,即成功。
展开完整文档(README 剩余 1 节)
DSH Runtime

让模型负责思考,让 Harness 处理那些可以确定的事情。

dsh-runtime 是一组面向 DeepSeek Harness 的小型 Runtime 能力。

它不试图做一个新的 Agent,也不试图用更多 Prompt、Skill 或规则去“教会”模型所有事情。

它只接住一类问题:

那些模型不应该反复猜,Harness 本来就可以确定的问题。

例如:

* 这件事现在能不能做?
* 刚才这一步到底有没有产生变化?
* 工具虽然报错了,实际操作有没有已经发生?
* 工具说成功了,目标状态有没有真的生效?
* 一个动作已经重复很多次,但事情有没有继续往前走?

安装

一条命令装完(所有能力都在一个包里;装完去设置页选模式 / 场景 / 自定义即可):

从 GitHub 页面直接下载 release/dsh-runtime-0.1.0.tgz,或先 clone 仓库
dsh plugin --profile add dsh-runtime-0.1.0.tgz

装完 dsh --profile --dump-config 能看到 runtime-progress / circuit / reconcile / investigate / seam 五行,即成功。

- 用户不需要选包:模式(Off / Minimal / Balanced / Strict)、场景预设(Creative / Coding / External / Safe)和自定义勾选都在 Runtime 设置页里完成;
- 开发者按需:release/ 里另有五个单独包(progress + circuit + reconcile + investigate + seam),只想装某几个能力时才用;
- 开发者重建:改完代码跑 node scripts/pack-release.mjs 重新生成 release/。

它是怎么工作的?

一次工具调用会发生四件事,Runtime 只做后面两件:

模型调用工具 value !== "locked", predicateText: "pwsh requires runtime-progress.shell-lock != locked", })

事实是 locked 时,模型调用 pwsh 会拿到一条 [action-rejected] 加那句 predicateText,调用不会进入执行。

Progress

执行之后看有没有真的往前走。

const p = foldProjection(events)
p.verdict.execution // "success" | "failed" | "none"
p.verdict.effect // { 工具名: "success" | "failed" | "unknown" }

"命令跑成了"和"事情往前走了"是两条轴,分开报。它不停止、不重试、不修,只提供判断。

Circuit

同一件事反复失败,而且一直没有进展时,说一次。

registerCircuitContract({ id: "exp_flaky", match: { tool: "exp_flaky" }, threshold: 2 })

判定的单位是工具加失败形态加目标,不是"工具"。到阈值时模型收到一条观测:

[runtime-observation circuit-open]
observed: "read" failed 2 times with the same failure on c:\repo\gone.mjs (threshold 2).
failure: Error: cannot read "": not found
fact: capabilities.read.state = "stalled" (authority: runtime, revision: 1, fingerprint: ...)

它只报观测,不下命令。也不做拒绝:文件工具里读、写、改互为解法,拒绝会把会话锁死。

Reconcile

非原子动作已经跑过一次时,不许重放。

registerNonAtomicContract({ id: "deploy", match: { tool: "pwsh", pattern: /deploy\.ps1/ } })

第二次调用被拦下,理由是:"was already invoked once and its confirmation was lost; the effect may already be applied, so a retry can duplicate the side effect."

Delta

只有值得关注的变化才告诉模型。

{ role: "user",
source: { kind: "plugin", plugin: "dsh-runtime-seam" },
content: [{ type: "text", text: "[runtime-observation ...]" }] }

变化以一条 user-role 消息进入下一步。Runtime 不播报"现在还是这样"。

子代编排(Child orchestration)

父 agent 把活派给后台子代,编排层等的是终局事实,不是状态。

const fact = await ctx.childOrchestration.wait(childId, 30000)
// { outcome: "settled", stopReason: "completed", lastAssistantMessage: "..." }

idle 不等于结束:子代静默但还持有活孙代时是 waiting,不是完成。实测里这个等待在"看起来已经不跑了"的 30.5 秒内一次都没有提前返回。语义冻结在 docs/20-child-orchestration-semantic-contract.md,实测见 experiments/async-lifecycle/。

Continuation(事前)

当事实与契约把下一步压缩到唯一确定的动作时,Runtime 直接执行,模型只消化结果。

首发合同是 post-write-syntax-check:模型写完或改完工作区 JS 模块后,Runtime 自己跑 node --check,然后交给模型一条 digest:

[runtime-continuation] deterministic step already executed by the runtime: post-write-syntax-check.
Do not re-run it; digest the outcome and continue from the current world state.

它走正常的工具管线(权限、守卫、取消照旧),所以模型看到的是一个已经发生的结果,不是一句要求。没有把握时一律不接管。由 settings 里的 continuation 位驱动,详见 docs/status/pre-productized-2026-09-03.md。

一个简单的例子

Agent 执行:

“把插件切到 fast 模式。”

它修改了配置,构建也成功了。

但运行中的插件实际上还在旧模式。

普通流程很容易得到:

修改成功 → build 成功 → 完成

Runtime-aware 的流程可以继续观察实际状态:

执行成功 → 没有看到预期变化 → investigate → 发现仍是旧状态 → reload → 再确认 → ready

这里 Runtime 没有替模型做创造。

它只是避免把:

“工具完成了”

误认为:

“事情完成了”。

Runtime 应该尽量安静

Runtime 不是一个新的“大管家”。

一个重要原则是:

模型自己看得清的地方,不需要 Runtime 出手。

正常 Coding 任务中,Runtime 应该可以完全不介入。

只有当 Harness 能明确看到一些模型不容易可靠判断的事情时,才值得介入。

因此 Runtime 更像是一层很薄的保护,而不是一套新的 Agent。

模式

设置页分为两根独立的轴:

| 轴 | 是什么 | 选择 |
| 事前 Pre | 一个开关——Continuation:事实 + 契约把下一步压缩到唯一时,替模型走这一步 | 开 / 关 |
| 事后 Post | 执行后纠偏与止损:guard、circuit、reconcile、verify & repair | Off / Minimal / Balanced / Strict / Custom |

两根轴不必落在同一个模式里:Post 模式选择事后职责组合,Pre 开关独立翻转。

也可以直接从场景开始(一个同时设定两轴的快捷键):

Creative · Coding · External Actions · Safe

模式只是选择不同的 Runtime 能力组合,不会改变模型本身。

为什么不是更多 Skill?

有些东西确实适合写进 Skill。

比如:

一种工作习惯、一种偏好、一种场景下更好的做法。

但有些东西不属于这个层面:

文件到底有没有写进去?
插件到底有没有加载?
一个操作到底有没有发生?
用户到底有没有真正批准?

这些事情,如果 Harness 能够确定,就不应该只靠模型记住一段文字。

一个简单的原则:

需要理解的事情交给模型。

可以确定的事情交给 Harness。

无法确认的事情,就承认不知道。

Evidence

这个项目不是只停留在设计上,目前已经完成了一组 DSH 实际实验。

在确定性的场景中:

* 重复无进展:真实执行次数下降 67%
* 非原子失败:重复副作用下降 75%
* 成功但未生效:世界正确率从 0/2 提升到 2/2
* 正常 Coding:0 次误介入
* 异步 polling:在当前场景和模型下没有明显优势
* 确定性 continuation(第 1-4 轮):Runtime 接管唯一确定的下一步(B 模型调用 15 vs A 19,−21%),stale/cancel/guard/多选一律零误执行,事实缺失或误导时克制,instruction continuity 保持——模型消化已发生的事实并把动作诚实归给 runtime

这些结果说明 Runtime 的价值不是“任何地方都更强”。

更接近:

模型自己看得清的地方,它不打扰;模型看不清现实的地方,它补上一点确定性。

完整实验过程、原始数据和限制条件见 docs/——尤其是 Runtime Continuation 线:docs/status/runtime-continuation-2026-09-02.md(命题)、runtime-continuation-boundaries-2026-09-02.md(边界)、runtime-continuation-instruction-2026-09-02.md(instruction continuity)、runtime-continuation-ownership-2026-09-03.md(所有权边界),以及四轮汇总 runtime-continuation-summary-2026-09-03.md。

后面三条线各有独立报告:

* 子代编排 —— docs/20-child-orchestration-semantic-contract.md(冻结的语义,含那个把 idle 从终局判定里排除掉的 30.5 秒负例)
* turn-stopping —— docs/status/turn-stopping-continuation-and-cost-2026-09-11.md(收尾点算不算合法的续跑点,在那里注入的代价是多少),机制写在 docs/21-turn-continuation-and-injection.md
* 熔断在文件工具上的误报 —— docs/status/circuit-fingerprint-vs-fs-errors-2026-09-11.md(两个不同文件塌成一条指纹,以及修法)

Project Status

当前项目仍然是一个实验驱动的小型 Runtime capability 集合。

它不会试图成为新的 Agent Framework,也不会自己重新实现 DSH 的底层 Runtime。

能力应该从真实问题中长出来:

真实问题 ↓ 找到可以确定的事实 ↓ 最小 Runtime 能力 ↓ 实际验证 ↓ 重复出现 ↓ 再考虑抽象

先解决一个具体的问题,而不是先设计一个完整系统。

Repository

这个仓库目前主要面向:

* DSH Runtime capability 实验
* Runtime / Event / Progress 研究
* 真实 Agent trajectory 验证
* DSH 插件组合与场景实验

安装和启用方式以各 capability 的文档为准;这个仓库本身不是一个需要单独启动的 Agent 应用。

License

见 LICENSE。

最后:为什么是 Plugin?

因为我们并不认为已经知道 Agent 的最终结构应该是什么。

这个项目只是观察到了一个很具体的事实:

真实 Agent 运行中,有些工作已经足够确定,不值得继续占用模型的推理空间。

如果这些工作可以被独立出来,那么最自然的方式不是把它们全部塞回 Core。

而是:

Real friction
↓
Deterministic part
↓
Capability
↓
Plugin
↓
Harness

今天可能是 Runtime。

明天可能是别的东西。

不需要预先知道。

一个暂时足够简单的原则

如果模型仍然需要判断,让模型判断。

如果程序已经知道答案,不要让模型重复发现。

如果现实已经确定不允许,不要让模型决定能不能执行。

如果现实没有变化,不要告诉模型。

如果一条路径已经没有进展,不要让它无限继续。

如果状态已经存在,不意味着必须重新注入。

如果用户的意图可能错,保护现实,但不要替用户重新定义意图。

Agent = Model + Harness

这个仓库只是在探索:

Harness 究竟应该接住哪一部分。
预览分享卡片长什么样 ↓goatliamia/dsh-runtime
分享 · DeepSeek Harness Hub
goatliamia/dsh-runtime

拦截重复无效动作,核对工具执行真实结果

这是你的仓库?认领条目

回到顶部