@leonhardthust/dsh-decision-engine 1.11.1 → 1.11.2

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/docs/releasing.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # npm 发布
2
2
 
3
- 发布目标:`@leonhardthust/dsh-decision-engine`,当前版本 `1.11.1`,公开包。
3
+ 发布目标:`@leonhardthust/dsh-decision-engine`,当前版本 `1.11.2`,公开包。
4
4
 
5
5
  本分支基于 `zuosus/dsh-decision-engine` 的 MIT 代码,保留原作者与许可证;npm scope、源码仓库、bundle 引用和浏览器主模块 / charts chunk 标识已同步为本分支身份。内部 API、样式标识和用户数据目录保留旧名称以兼容已有配置。不要同时启用原包与本 scoped fork,它们提供相同的服务与页面。
6
6
 
@@ -9,7 +9,7 @@
9
9
  - `.github/workflows/ci.yml`:main push、PR、手动运行或发布工作流复用;Ubuntu 24.04 + Node.js 24 + Vite+ 1.6.0。执行 frozen install、完整测试与接线、隔离情景、实际打包和 tarball 检查。失败不会被忽略。
10
10
  - `.github/workflows/publish.yml`:每次 `main` push 自动检测版本。先比较整个 push 的 `before` 与当前 manifest,拒绝错误包名、非法或倒退版本;再只读查询 npmjs。当前版本已上传则跳过;当前版本高于 npmjs latest 且未上传则进入完整验证及发布。多提交 push 比较整个 push 前后,不仅比较 HEAD 的父提交。
11
11
  - 后续发版只需修改 `package.json` 版本并提交到 main;无需创建 tag 或手动点运行。发布依赖检测和本次提交的完整 CI 均成功,不跳过测试。稳定版本发布到 `latest`,预发布版本自动进入 `next`。
12
- - 当前 `1.11.1` 包含 DEC-070:空闲但仍可接续的同一棵树的子代理不再被误判为「接收方权限未核验」,普通队友消息不再升级成人审/拒绝。`1.11.0` 的第二轮审计修复见 DEC-067 ~ DEC-069,`1.10.0` 的五项改动见 DEC-062 ~ DEC-066。
12
+ - 当前 `1.11.2` 包含 DEC-071:审批策略为 `never` 时,模型给出的软性询问(medium / 档位升级)交给 `guardFallback` 复核,而不是静默 deny;高危、注入、未知副作用与强制权限约束仍保持失败关闭。`1.11.1` 的 DEC-070、`1.11.0` 的审计修复、`1.10.0` 的五项改动依次见 DEC-067 ~ DEC-069 与 DEC-062 ~ DEC-066。
13
13
  - checkout 与 setup-vp Action 固定到已核对的 commit SHA;不通过 `pull_request_target` 运行不可信 PR。
14
14
  - 验证任务只有 `contents: read`;只有发布 job 有 `id-token: write`。发布 step 只使用 OIDC(trusted publishing),不再读取任何 npm token secret。代码 checkout 不保留 Git 凭据。此工作流不会自动修改版本、提交源码或推送 Git。
15
15
 
@@ -58,7 +58,7 @@ Windows 全量测试最近仍有 3 个既有 POSIX 文件权限断言失败;
58
58
  授权及完整验证均满足后:
59
59
 
60
60
  ```powershell
61
- npm publish ./release-artifacts/leonhardthust-dsh-decision-engine-1.11.1.tgz --registry "https://registry.npmjs.org/" --access public --tag latest
61
+ npm publish ./release-artifacts/leonhardthust-dsh-decision-engine-1.11.2.tgz --registry "https://registry.npmjs.org/" --access public --tag latest
62
62
  npm view @leonhardthust/dsh-decision-engine version --registry "https://registry.npmjs.org/" --json
63
63
  ```
64
64
 
@@ -66,4 +66,4 @@ npm view @leonhardthust/dsh-decision-engine version --registry "https://registry
66
66
 
67
67
  ## 安装
68
68
 
69
- DSH 插件管理中使用 `@leonhardthust/dsh-decision-engine` 或指定 `@leonhardthust/dsh-decision-engine@1.11.1`。安装和启用是另外的用户动作,发布工作流不会修改本机 DSH profile。
69
+ DSH 插件管理中使用 `@leonhardthust/dsh-decision-engine` 或指定 `@leonhardthust/dsh-decision-engine@1.11.2`。安装和启用是另外的用户动作,发布工作流不会修改本机 DSH profile。
@@ -22,7 +22,18 @@ export function approvalOutcomeForCall(session, callId, toolName, afterSeq) {
22
22
  const numberOrNull = (value) => Number.isFinite(value) ? value : null;
23
23
  const identityOrNull = (value) => typeof value === "string" && value ? redactGuardData(value).replace(/[\r\n\0]/g, " ").slice(0, 256) : null;
24
24
  const idleEvaluation = () => ({ status: "not_requested", provider: null, model: null, latencyMs: null, reason: null });
25
- const automaticReview = (context, config) => context?.permissionPreset === "auto" || config?.tolerance === "autonomous";
25
+ /**
26
+ * 是否走「自动审查」:把软性询问交给回退审查者,而不是直接拒绝。
27
+ *
28
+ * 这里刻意**不**把 `approvalPolicy === "never"` 也算进来:这个开关同时
29
+ * 决定「模型失效 / 答案畸形 / 审查异常」是否走回退,而那条链路必须保持
30
+ * fail-closed(失败不能变成一次放行)。never 下真正需要改的只是「模型给出
31
+ * 了**有效**意见、结论是 ask」这一种情况——它在下面用 `automaticReview`
32
+ * 之外的分支单独交给 `guardFallback` 处理。
33
+ */
34
+ const automaticReview = (context, config) =>
35
+ context?.permissionPreset === "auto"
36
+ || config?.tolerance === "autonomous";
26
37
 
27
38
  export function mountGuard(ctx, deps) {
28
39
  const { getConfig, reloadOwnConfig, effectivePointModes, client, toleranceCalibrator, digestRecent, previewArguments, logDecision, recordGuardDetail } = deps;
@@ -224,7 +235,31 @@ export function mountGuard(ctx, deps) {
224
235
  } else if (primary.status === "failed") {
225
236
  action = { kind: context.approvalAvailable === true ? "ask" : "deny", reason: "advisory-failed-unknown-effect" };
226
237
  } else if (action.kind === "ask" && context.approvalPolicy === "never") {
227
- action = { ...action, kind: "deny" };
238
+ /**
239
+ * 审批通道不存在(DSH 的 `never` = 每个 ask 确定性 rejected)。
240
+ *
241
+ * 只有「模型给出了有效意见,且这次询问属于**软性**升级」才交给
242
+ * `guardFallback`——那是用户配置好的「没人可问时谁来裁决」。
243
+ *
244
+ * 刻意排除三类,它们必须保持 fail-closed,不能被回退模型洗成放行:
245
+ * - `mandatory.status === "unknown"`:工具副作用没判定,这不是
246
+ * 「软性询问」,而是一条未知边界(现有情景测试专门钉住
247
+ * `manual unknown + never` 不得伪造批准);
248
+ * - `risk.choice === "high"` / 注入达线:高危与注入嫌疑不接受
249
+ * 「再问一个模型」的软化;
250
+ * - 模型失效 / 答案畸形:没有可复核的有效意见(走上面的失败分支)。
251
+ */
252
+ const injectionThreshold = Number.isFinite(config.guardInjectionAskThreshold)
253
+ ? config.guardInjectionAskThreshold
254
+ : 0.8;
255
+ const softAsk = advisory?.status === "valid"
256
+ && mandatory.status !== "unknown"
257
+ && advisory.risk.choice !== "high"
258
+ && !(Number.isFinite(advisory.injectionP) && advisory.injectionP >= injectionThreshold)
259
+ && (advisory.risk.choice === "medium" || tolerated?.changed === true);
260
+ action = softAsk
261
+ ? await runFallback()
262
+ : { ...action, kind: "deny" };
228
263
  }
229
264
  // 档位把「默认放行」升级成「询问」时,`action.reason` 是档位 note(含
230
265
  // `severity=` 与阈值小数)——那是审计口径,不能当审批卡标题。这里换成
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leonhardthust/dsh-decision-engine",
3
- "version": "1.11.1",
3
+ "version": "1.11.2",
4
4
  "description": "dsh-decision-engine: a cheap judgement layer for DeepSeek Harness — a small decision model answers structured questions before the main model acts, so calls can be allowed, escalated, rerouted to a cheaper model, or skipped. All eight decision points (tool authorization, model routing, delegation, compaction, turn continuation, retrieval, skill pick, COT translation) are implemented and individually switchable. Works against any service exposing a decision endpoint: built-in presets (system one, bamboonode, SiliconFlow, Silicon Flow) or a custom base URL.",
5
5
  "icon": "./icon.svg",
6
6
  "type": "module",