dsh-needle · 隐含需求雷达
在会话日志的干草堆里,找出那根真正扎人的针。
dsh-needle 是一个 DeepSeek Harness(DSH)Host-only 插件。它只读本地会话日志,把三类信号挖出来并按稳定阈值排序:反复出现的工具失败、用户说了不止一次的请求、用户明确纠正过的做法。每一条达标需求都能生成一份产品简报:问题、脱敏证据、交付形态建议、验收标准、非目标。
全程离线:不调用模型、不发网络请求、不写会话日志。唯一的写入是工作区里的扫描产物 .dsh/needle/latest.json 与 report.md。
它解决什么问题
一个用了两周的 DSH 用户,会话日志里通常已经堆着答案:
- 同一个
pwsh失败签名出现十几次,每次都要重试两三轮; - 同一件事在三个会话里说了三遍(“把微信接进来”“再试一下”),说明第一次没做成;
- 用户明确纠正过“不要这样,应该那样”,但下一个会话又犯了。
这些不是“模型不够聪明”,而是产品缺口:缺一个工具、缺一条流程、缺一处配置。问题在于没人系统地把它们挖出来——人会疲劳,模型只看得到当前会话,市场分析只看得到别人的插件。
dsh-needle 把这件事做成三个可复跑的工具:扫描、简报、报告。它判断的是可观察的摩擦与重复,不是“用户想要什么”的猜想。
它怎么工作
$DSH_HOME/sessions/<workspace>/<session-id>/session.v4.jsonl.zstd
│
├─ 逐帧解码(DSH 是多帧追加的 zstd 流)
├─ 事件配对(tool/call 提供工具名,tool/result 提供输出)
├─ 失败签名归一化(路径、UUID、数字、耗时 → 占位符)
├─ 三类候选:工具摩擦 / 重复请求 / 用户纠正
├─ 稳定阈值过滤
└─ 排名 → 需求简报(证据已脱敏)
逐帧解码:DSH 的会话日志是多个 zstd 帧拼接追加的。zstdDecompressSync 只解第一帧,看起来就像“这个会话没有内容”。插件逐帧解码,并容忍正在写入的会话留下的半截尾帧——这类尾帧有时会被 zlib 解成不完整的文本而不报错,所以帧之间会补换行,让残片落在独立(无效)的一行,而不是污染前一条有效事件。
事件配对:tool/result 本身不带工具名,必须回到对应的 tool/call 取。不配对就只能得到“某个工具失败了”,无法归因。
签名归一化:C:\work\a\file.txt 和 C:\work\b\file.txt 是同一个失败;id 3f2b1c4d-… 和 id 9a8b7c6d-… 也是。归一化之后,跨会话的同一失败才能归并成一条需求。
稳定阈值(避免把一次性不顺当成需求):
| 类型 | 达标条件 |
|---|---|
| 工具摩擦 | 同一失败签名出现在 ≥2 个会话,或在同一会话出现 ≥3 次 |
| 重复请求 | 同一请求(归一化后)出现 ≥2 次 |
| 用户纠正 | 同一纠正出现 ≥2 次,或出现在 ≥2 个会话 |
交付形态建议:plugin(需要工具/拦截/确定性检查)、skill(需要流程纪律)、config(环境/权限/网络/编码问题)、docs(写进 AGENTS.md 就够了)。建议只是起点,不是结论。
脱敏:所有证据片段在统计、落盘、渲染之前都会过一遍 redact:GitHub / 模型 API / AWS / Slack / npm token、JWT、Bearer 头、--token、password=、client_secret: 等一律替换为 <redacted:…>。40 位十六进制不动——那通常是 git SHA,抹掉反而破坏普通输出。
三个工具
needle_scan
扫描时间窗口内的会话,返回达标需求。
{
"hours": 24, // 可选,1-720,默认取配置(24)
"maxSessions": 20 // 可选,1-200,默认 20
}
返回 needs[]:id、kind、title、occurrences、sessions[]、evidence[](已脱敏)、suggestion.form。
同时把完整扫描结果写到 .dsh/needle/latest.json,报告写到 .dsh/needle/report.md。
needle_brief
把一条需求渲染成产品简报(Markdown):问题、证据、为什么建议这个形态、下一步、验收标准、非目标。
{ "needId": "need-1a2b3c4d5e" } // 省略则取排名第一的需求
needle_report
把最近一次扫描渲染成完整 Markdown 报告:总览表、逐条简报、方法与边界。可直接贴进 issue 或提交进仓库。
{ "limit": 10 } // 可选,1-20
安装
方式 A · 从源码链接(推荐给本地开发)
git clone https://github.com/Daphne999/dsh-needle.git
dsh plugin --profile <profile> add link:"$PWD/dsh-needle"
方式 B · 从 tarball
npm pack # 生成 dsh-needle-0.1.0.tgz
dsh plugin --profile <profile> add ./dsh-needle-0.1.0.tgz
方式 C · 写进 profile
// ~/.dsh/profiles/<profile>/package.json
"dependencies": { "dsh-needle": "link:/abs/path/to/dsh-needle" },
"dsh": { "profile": { "bundles": [ /* ... */ "dsh-needle" ] } }
装完重启宿主。插件列表里会出现「Needle 隐含需求雷达」,会话里多出 needle_* 三个工具。
配置
写在 profile 的 patch 行里(cordis.patch.yml):
- id: dsh-needle
config:
sessionRoot: "C:\\Users\\me\\.dsh\\sessions" # 默认 $DSH_HOME/sessions
hours: 24 # 默认窗口
maxSessions: 20 # 默认上限
evidenceDir: ".dsh/needle" # 产物目录(相对工作区)
它和已有插件的区别
市场里已经有一批“看会话”的插件,但它们回答的是不同的问题:
- 会话健康体检(如
agent-clinic)诊断的是“这次会话哪里不健康”(token 浪费、上下文膨胀、失败循环),产出的是诊断项与处方;dsh-needle不判断健康与否,只按跨会话稳定性排序需求。 - 经验演化(如
dsh-soul)会记录重复纠正与工具错误,并把经验编译成运行组件的改动;dsh-needle不改任何东西,产出的是给人看的需求简报。 - 市场日报(如
dsh-daily)看的是插件市场的下载量与空白,产出的是“生态里还缺什么”;dsh-needle看的是你自己的会话,产出的是“你反复被什么卡住”。 - 记忆/反思插件把经验写回记忆或规则,产出的是“下次记住”。
dsh-needle 的落点是需求发现:从本机会话里找出“反复发生、值得做成产品”的那几件事,并给出可直接开工的简报(含形态建议与验收标准)。它不替你做市场判断,也不自动生成插件——它负责把证据摆到你面前。
边界
- 只读本地日志:不写、不改名、不删除任何会话文件;产物只落在工作区
.dsh/needle/。 - 阈值会漏:低频但重要的需求不会被排上来。这是设计取舍——宁可漏,不硬造。
- 失败签名是启发式的:不同根因可能被归并成一条,同一根因也可能被拆成两条。证据片段是给人复核的。
- 依赖 Node 的 zstd 支持(
node:zlib,Node ≥ 22.15 / DSH 自带运行时满足)。 - 只解析文本事件:图片、二进制附件、工具私有格式不参与统计。
- 跨工作区:默认读
$DSH_HOME/sessions下的全部工作区;用sessionRoot收窄。 - 建议形态不是结论:
plugin/skill/config/docs由错误文本与工具名启发式判断,人仍需拍板。
不做什么
- 不调用模型:没有 LLM 打分、没有“让模型总结隐含需求”。同一份日志永远得到同一份结果,可 diff。
- 不联网:不上传、不查询市场、不访问任何 API。
- 不自动生成插件或 skill:简报是给人看的,不是自动发布的流水线。
- 不修改会话日志、不注入提示词、不拦截工具。
- 不判断业务价值:影响面(会话数/次数)只是排序依据。
自验
node --test --test-isolation=none test/*.test.mjs # 单元/集成测试
node scripts/smoke.mjs # 端到端:造日志 → 扫描 → 简报 → 报告
测试覆盖:多帧 zstd 解码、半截尾帧、mtime 过滤、事件配对、签名归一化、稳定阈值、脱敏(含落盘产物)、工具参数校验、空会话目录、配置项。
--test-isolation=none 是因为部分 Windows 沙箱环境不允许 Node 测试运行器为每个文件创建管道式子进程;不加这个参数时测试本身会因为 spawn EPERM 失败,与插件代码无关。
隐私
- 证据片段只保留到 220 字符,且先脱敏再统计。
- 产物(
latest.json/report.md)里同样只有脱敏后的片段。 - 插件不读环境变量里的凭据,也不读
~/.dsh/.env。 - 如果日志里出现过密钥,请仍然把它当作已泄露处理:脱敏只能减少二次传播,不能撤回已经存在的记录。
License
MIT。见 LICENSE。
No comments yet. Be the first to write one.