用规则先给工单分类,拿不准的转人工复核
30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/21 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/Phocinae/dsh-batch-triage.git状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
生态应用
桌面端 / Web 外壳,不以 dsh plugin add 安装
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 11 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🟢 扫描:未发现敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
DeepSeek Harness 的分诊以确定性优先:规则预过滤器给每张工单分类,规则无法归类的都标为 needs_review,绝不猜测。
README
由 DeepSeek 最新模型翻译生成dsh-batch-triage
规则决定简单的工单。规则放不下的,交给人工——绝不悄悄归为常规。
一个 DeepSeek Harness 插件。不用模型,不用服务,不联网,不需要 API key。
$ node -e "
import('dsh-batch-triage').then(m => {
const r = m.triageBatch([
{ id: 'a', text: 'The service is down for all users' },
{ id: 'b', text: 'How do I install this on Windows?' },
{ id: 'c', text: 'The frobnitz is blorp.' },
], m.resolveConfig({}));
console.log(r.items.map(i => i.id + ' ' + i.class + ' ' + i.reasonCodes[0]).join('\n'));
console.log('exit', r.exitCode, r.exitBasis);
})"
a urgent OUTAGE_REPORTED
b routine INSTALL_QUESTION
c needs_review NO_RULE_MATCHED
展开完整文档(README 剩余 1 节)
dsh-batch-triage
规则决定简单的工单。规则放不下的,交给人工——绝不悄悄归为常规。
一个 DeepSeek Harness 插件。不用模型,不用服务,不联网,不需要 API key。
$ node -e "
import('dsh-batch-triage').then(m => {
const r = m.triageBatch([
{ id: 'a', text: 'The service is down for all users' },
{ id: 'b', text: 'How do I install this on Windows?' },
{ id: 'c', text: 'The frobnitz is blorp.' },
], m.resolveConfig({}));
console.log(r.items.map(i => i.id + ' ' + i.class + ' ' + i.reasonCodes[0]).join('\n'));
console.log('exit', r.exitCode, r.exitBasis);
})"
a urgent OUTAGE_REPORTED
b routine INSTALL_QUESTION
c needs_review NO_RULE_MATCHED
exit 6 modelUnavailable
快速开始
dsh plugin --profile web add dsh-batch-triage@0.1.4
batch_triage 现在可用了;规则能放下的工单就放下;放不下的返回 needs_review——绝不悄悄归为常规。
为什么规则优先
一批工单不适合每条都调一次模型:量大,值得看的少,而且每条都要一次往返,不管它需不需要。所以顺序和直觉相反。
预筛先跑每一条。 规则放下明确的案例——带堆栈的崩溃是紧急,「怎么安装」是常规——而且不追问任何东西就放下。只有剩下的残渣才可能送到模型,而这个版本根本不会送到模型:它会直接说明。
这个顺序不是优化。它是设计的主路径,也改变了这个工具的定位:预筛才是产品,模型只是兜底。
最重要的一条规则
除非有规则说了,否则一条工单永远不会是 routine。
所有无法分类的路径——正文为空、没有匹配规则、没配模型、预算耗尽——都产出 needs_review。把「我看不出来」变成「没什么可看的」,正是这个工具要防的唯一失败,测试套件从两个方向都钉住了它。
0.1.2 收紧了「有规则说了」允许的含义。规则依据的是短语,而一张工单不止一句话:当匹配到的短语是个问题,而另一句报告了某处坏了,问题规则就不能决定这张工单。它变成 needs_review,带 MALFUNCTION_REPORTED,而那条本来会吞掉它的规则留在 reasonCodes 里,让读者看到两半。
decidedBy 说明实际是哪一层决定的:
| 值 | 含义 |
| prefilter | 规则放下了它;reasonCodes 指明是哪条 |
| unavailable | 什么都放不下,也没配模型层 |
| budget | 触到上限,所以没评估 |
后两个都带 escalate: true。两者都不是对工单的判定。
规则看什么
结构化字段优先于正文:severity: critical、security: true、data_loss: true、reporter_tier: enterprise。报告人填过表单,就已经告诉你了,正文里任何措辞都压不低字段给出的结论。措辞报告的情况更糟,照样往上抬 —— 字段永远埋不掉一次故障,两者冲突时,条目同时带上两个原因码。
否则以任何规则声称的最高类别为准,表格按强度从高到低排列,同一类别内并列时取先列出的规则:
| 类别 | 规则 |
| urgent | outage、data_loss、security、crash_with_trace、blocked_workflow |
| needs_review | regression、wrong_result、performance、flaky |
| routine | install_question、usage_question、documentation、feature_request、thanks |
一张工单既报告故障、又把自己写成提问,绝不能被提问规则吞掉。这是一条测试 —— 而在 0.1.1 里,它是一条不可能失败的测试,因为它的测试夹具用了 outage 规则已经识别的措辞,夹具和规则共享同一个假设,优先级从未真正被检验。现在优先级按类别判定,不再按位置,这也意味着调用方传入的 rules 数组无法重排表格、把判定变成 fail-open。
只靠类别优先级还不够,下面六张实测工单就是原因。outage 不认识「returns 500 for every request」,于是没有任何严重度规则命中,提问规则仅凭其中一句话就定了整张工单。所以 routine 判定要多过一道检查:如果正文报告了故障 —— 报错、崩溃、「unusable」、5xx、记录被删、凭据泄露 —— 而措辞没有任何严重度规则能识别,条目就变成 needs_review,原因码 MALFUNCTION_REPORTED,不再是 routine。这道守卫只会拒绝 routine;它抬不到 urgent,也碰不了严重度规则已经做出的判定。
按类别定优先级,是刻意放弃「最具体者胜」。打分系统需要没人能辩护的权重;类别阶梯一个都不需要,表格还保持可检查 —— 一条从不触发的规则,是你一眼能看见的 bug。
修复所对照的措辞,逐字摘自审计。六张工单在 0.1.1 上全是 routine,退出码 0:
| 工单 | 0.1.1 | 0.1.2 |
| How do I install this? Also our production API returns 500 for every request. | routine INSTALL_QUESTION,退出码 0 | urgent OUTAGE_REPORTED,退出码 1 |
| Is there documentation for the auth flow? We are seeing records deleted from our database. | routine DOCUMENTATION_REQUEST,退出码 0 | urgent DATA_LOSS_REPORTED,退出码 1 |
| Feature request: please add CSV export. Meanwhile the app is unusable for our whole team. | routine FEATURE_REQUEST,退出码 0 | urgent OUTAGE_REPORTED,退出码 1 |
| How do I configure SSRF protection? Our pentest found we can read other users files. | routine INSTALL_QUESTION,退出码 0 | urgent SECURITY_REPORTED,退出码 1 |
| where can i find the logs? the service has been returning 503 all morning | routine INSTALL_QUESTION,退出码 0 | urgent OUTAGE_REPORTED,退出码 1 |
| What is the right way to rotate keys? Our API token leaked in a public repo. | routine USAGE_QUESTION,退出码 0 | urgent SECURITY_REPORTED,退出码 1 |
只是提问的工单不受影响:How do I install this on Windows? 仍然是 routine,一批全是 routine 条目也仍然退出 0。这道守卫是下限,不是偏向紧急。
守卫的代价,先说清楚,别等以后才发现。 它有意保守,所以只要提问提到失败类词,也会被上调:How do I handle errors returned by the parser? 输出 needs_review,而不是 routine。分类变了,退出码没变,因为预过滤器判定的 needs_review 在本次发布里不算发现项。这是真实存在的遗留缺口——守卫自己产出的条目仍然退出 0,所以上面六个例子必须凭自身理由落到 urgent,而不能只停在 needs_review。这一点写进了 CHANGELOG,而不是留给读者自己发现。
退出码
| 退出码 | 含义 |
| 0 | 已运行,且无需人工处理 |
| 1 | 已运行并发现问题——不是失败 |
| 2 | 调用无效(空批次、超出上限、条目格式错误) |
| 3 | 输入或策略无法执行(id 重复) |
| 4 | 空扫描 |
| 5 | 记录的预期未满足 |
| 6 | 所有需要模型的条目都被跳过 |
| 7 | 任何条目都还没到达模型,上限就已经是零 |
它们之间的优先级是 lib/exit.mjs 里一条有文档的阶梯,因为一次运行可能同时满足多个条件,顺序决定你被告知哪一个:
2 usage → 3 config → 4 empty scan → 7 zero budget →
6 model unavailable → 5 expectation → 1 findings → 0 clean
1–64 个条目的批次只能到达 0、1、2、3 和 6。另外三个是阶梯上的层级,这个批次运行器没有对应的产生者:
* 4 空扫描被 2 抢先:空批次在任何条目被扫描之前就作为用法错误拒绝,所以这里 emptyScan 永远不会为真。第 4 级是为直接调用 exitCode() 的调用方准备的。
* 5 预期完全没有产生者——本次发布没有 expect API。这一级是预留并写入文档的,不是凭空发明的。
* 7 零预算在加载时就被拒绝,因为 modelStateCap: 0 是配置错误(见下文)。7 只能通过 exitCode() 本身到达,或者通过一个从未经过 resolveConfig 的配置对象到达。
把阶梯读成「这些就是你将看到的全部结果」在另一个方向上也是错的;它是完整的优先级顺序,不是可观察退出码的完整清单。
其中两种排序值得说明:
* 用法错误优先于一切。 一次从未有效的运行不可能发现任何东西,所以报告发现就是在歪曲事实。
* 覆盖缺口优先于发现。 6 表示「这次运行没能覆盖它需要覆盖的全部内容」,这比 1 的「其中一部分需要人工处理」更强——而且它是超集,因为对 6 做出反应的调用方会去查看,并会在摘要里找到列出的紧急项。
第二种排序的隐患在于:调用方只读退出码,就断定这批没问题。所以摘要始终列出 urgentIds 和 escalatedIds,并有测试断言紧急项在覆盖缺口旁边依然保留。
对 CI 而言: {0, 1, 6} 都是成功运行,导出为 CI_ACCEPTED。把 1 当作失败的任务,会在每一批值得运行的批次上变红。
上限是决策,不是静默丢弃
预算负担不起的项是 needs_review,带 BUDGET_EXHAUSTED,摘要会统计 budgetRefusals。被截断的运行不能读起来像完整运行。
modelStateCap: 0 在加载时就被拒绝,而不是接受。它在同一次调用里禁止了调用方所要求的东西,把这种矛盾变成分诊结果,等于让工单为配置错误背锅。拒绝以 TRIAGE_BAD_CONFIG 报告,退出码 2,不是 3:上限为零是自相矛盾的请求,阶梯把它归类为无效调用,而不是无法读取的输入。没有任何东西到达模型,所以第 7 级永远不会到达——见退出码表下方的说明。
限制与校验
每次调用 1–64 项,其中 64 是默认的 maxItems 上限,不是它唯一能取的值:运维调高 maxItems,批次上限也随之调高,而预过滤器对批次大小是线性的。超过上限会被拒绝,而不是截断,因为截断的批次报告的是恰好先到达的那些项的摘要——读起来和整批的摘要一模一样。重复 id 会被拒绝,而不是合并:id 是答案的键,合并会丢掉一张工单,且无从分辨丢的是哪张。这种拒绝是退出码 3,不是 2:批次本身格式正确,无法满足的是身份映射。
failOn 做什么
failOn 决定哪些类别算作发现(退出码 1):
| 值 | 发现是…… |
| any(默认) | 紧急项、任何升级,或任何 needs_review |
| urgent | 仅紧急项 |
| none | 什么都不算——调用方要的是报告,不是闸门 |
needs_review 是「应该有人看看」的决策,无论它来自预过滤规则(regression、wrong_result、performance、flaky,字段 severity: high|medium)还是来自残留项(no rule matched、模型不可用、预算耗尽)。0.1.3 之前只有残留项计入,所以一批包含单张回归工单退出码是 0 clean,可规则早就说过它需要人工处理。这个缺口已经补上:在 any 下,规则判定的 needs_review 也算一条 finding。
退出码仍然优先于 finding。残留项没有模型客户端时,先退出 6(modelUnavailable),排在 finding 判定之前;用法或配置错误又优先于这两者。所以已发布的插件有两个可见情形:
| 批次 | failOn 的效果 |
| 含残留项(没有规则匹配) | 无论 failOn 是什么,都退出 6 |
| 每一项都已判定,至少一项为 needs_review | any → 1;urgent / none → 0 |
modelClient 是库级选项,故意不放进下面的 YAML 配置块:它是给测试用的接缝,也供宿主以编程方式提供客户端。本版本仍然从不调用它——modelClass 保持 unavailable。
从 0.1.2 迁移
如果某个 CI 任务依赖 failOn: any 对某批次返回 0,而该批次唯一的问题是规则判定的 needs_review(regression、wrong_result、performance、flaky,或 severity: high|medium),那么这个批次现在会退出 1。
挑你真正想要的政策:
- failOn: urgent —— 只有 urgent 项会让运行失败。这并非旧行为的精确还原:它还会忽略残留升级项,而旧的 any 是计入这些项的。
- failOn: none —— 只报告,从不拦截。
这个改动是有意为之:规则说了「该有人看一眼」,就不该产出绿色运行。failOn: any 仍是默认值。
tau 在这里能做什么、不能做什么
tau 是置信度上的升级阈值,而本版本没有置信度可供比较。所以它只做设计允许的那一件事:能让 needs_review 项升级,并且从不降级任何东西。一个被接受却毫无效果的选项,比一个被拒绝的选项更糟,因为调用方会以为某项检查已经做过。
配置
- insert:
- id: batch_triage
name: dsh-batch-triage
config:
maxItems: 64
tau: null
modelStateCap: null
tokenCap: null
failOn: any # any | urgent | none
timeoutMs: 20000
batchSize: 16
本版本中不起作用的选项
有四个被接受的键在没有模型层时不起作用。把它们列在一起,是因为另一种做法——默默接受——正是本项目在自身文档别处批评的行为。
| 键 | 状态 |
| policyId | 接受,但不加载任何策略文件 |
| tokenCap | 接受,但没有任何东西上报 input_tokens 来对照执行 |
| timeoutMs | 接受,但没有任何东西启动子进程去超时 |
| batchSize | 接受,但没有任何东西被发送到某处去分批 |
它们仍会做范围校验,所以 timeoutMs: 0 在加载时会被拒绝。这是有意为之,不是为了整洁:校验这部分以后仍然是对的当分级落地时,现在移除它意味着以后要在压力下重新加回来。
failOn 是个特例,值得单独说一句:它在已发布的路径上生效。一批条目全部判定完毕,其中至少有一个 needs_review,在 any 下退出码为 1,在 urgent / none 下为 0。只有残留条目(没有规则能归类、且没有模型客户端的条目)在 6 处压过发现层级。
规则遇到不认识的 severity 会怎样
不认识的 severity——P4、banana、kritisch——不会被当作缺失处理。丢掉它,真实的优先级就会悄悄变成 routine;提升为 urgent 又会凭空造出信号。所以它变成 needs_review,附带 FIELD_SEVERITY_UNRECOGNISED:字段对优先级说了些什么,而本版本不知道是什么,这属于提问,而不是往任一方向猜。
识别的词表故意做得很宽(最高层级接受 critical、blocker、sev1、s1、P0、urgent、emergency、showstopper、severity 1、1、highest),因为 0.1.0 只接受四个标签,severity: 'P0' 当时的行为跟完全没有 severity 一模一样。
本版本不包含的内容
模型层级。 设计规定用本地 150M Phocinae 模型作为残留条目的兜底,服务不可达时采用 fail-closed 规则。它不在本版本里。输出已经带上它将来要填的字段(modelClass、confidence、top2Margin、score),modelClass 报告为 unavailable,因为这是事实。
省略的理由和这个家族到处适用的一样:可测量的价值在确定性层级,而增加模型调用的层级需要和其他一切相同的证据标准——测量,而不是假设。如实把字段发布为 unavailable,好过发布一个未经测量的层级。
同样不在本版本里:policyId(从文件加载的具名预过滤策略)和 tokenCap 在模型会报告 input_tokens 之后的强制执行。两者离开模型层级都是空转。
环境要求
Node ^22.19.0 || >=24.0.0。无运行时依赖。@deepseek-ai/cordis 是可选 peer。
测试
npm test # 45 test cases, no host required
npm run verify:artifacts # what npm publish would actually ship
两者都在发布路径上运行:prepack 是 npm test && npm run verify:artifacts,所以停止触发的规则无法发布。0.1.2 之前可以——verify:artifacts 为每条规则都带了正样本,本来会变红,但发布途中没有任何东西运行它。
node --test 报告的是测试用例数,不是断言数:这套测试是 45 个用例,包含大约 170 个 assert 调用,很多在循环里。用例循环时这个区别很重要——一个用例在五次迭代的第三次失败,算一次失败,单看用例数不会告诉你失败在哪。
验证器检查行为,不只是结构:它运行真实的预过滤器,并且断言表里每条规则都仍能命中。匹配不上的规则,和一条什么都没找到的规则,两者无法区分;在这个检查出现之前,这个项目的家族里已经两次出现这种确切的故障。
随包发布两个技能产物,它们不是同一份文本:
* lib/skill.mjs 从实时规则表生成正文,createPlugin 向宿主注册的就是它。
* skills/batch-triage/SKILL.md 是手写文件,随包一起走。没有任何东西比对这两者,校验器只断言文件存在、且被 files[] 覆盖。改了规则表,这一份就得你自己更新。
License
Apache-2.0。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
Phocinae/dsh-batch-triage
用规则先给工单分类,拿不准的转人工复核
相关插件 · 其他
模型破甲清洗YuJunZhiXue/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 14,822已汉化DeepSeek 客户端
73
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 718已汉化DSH
71.2
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,261已汉化DSH
70.7
破甲评测WoYun520/dsh-purge
在本机分离宿主拦截与模型拒绝,做受控红队评测
★ 199已汉化DSH
69.7