← 返回列表
未验证
记住哪些做法行不通——并在它所依赖的代码发生变化时自动让其失效。
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/16 · 已提供中文文档
编码代理的反驳台账:记住哪些做法没有奏效,并在其所依赖的代码发生变化时自动使其过期。DSH 插件 + CLI,无需构建步骤。
综合分
30.5
GitHub 分
30.5
用户评分
—
★ Stars
1
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add liyixuan201211/dsh-deadend该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/18(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
dsh-deadend
记住哪些做法行不通——并在它所依赖的代码发生变化时自动让其失效。
一个面向编码代理的反驳账本,以 DeepSeek Harness 插件的形式提供。
dsh plugin --profile web add github:liyixuan201211/dsh-deadend
无需安装即可试用:
npx --yes github:liyixuan201211/dsh-deadend --help
中文:一个失败账本。agent 每一轮新会话都会用同样的乐观重试同样的失败,代价重复支付。本插件把“试过且走不通”的方案记在仓库里,并在下一次尝试前先查一遍。关键在于:每条记录都带锚点(决定其真伪的文件的哈希)——锚点没变就拦截,锚点一变就自动降级为“待复测”,因为当初那个世界已经不在了。
问题不在于遗忘,而在于记错了。
面向 agent 的每一种记忆系统存储的都是哪些做法有效:事实、偏好、摘要、嵌入。几乎没有系统存储哪些做法失败了。于是失败循环不断重复——同一个坏掉的安装、同一次两小时的绕路,每个会话一次,永远如此。
显而易见的修复方案是列出一份“行不通的事”清单。这个显而易见的修复方案也是错的,而且比什么都不做更糟:
六个月前的一条笔记说“X 行不通”,而它是针对此后已经改变的代码写的,它会自信地阻止一个如今有效的修复方案。
过期的拦截不是无害的烦扰。它是工具在对你撒谎,而撒谎的工具会被关掉。负面知识的难点不在于记录它——而在于让它失效。
核心思路:锚点
每条记录都带有锚点:即那些内容必须发生变化、该失败才会不再成立的文件。
| 锚点 | 含义 | check 退出码 |
|---|---|---|
| 全部未变 | 权威——它仍然失败 | 3 |
| 任一已变 / 已删除 | 可疑——重新测试它 | 4 |
| 一无所知 | 无阻塞 | 0 |
| 记录被拒绝(无锚点) | record 拒绝 | 5 |
有效性由内容判定,而非由时钟判定。没有 MAX_AGE_DAYS,没有校准——而且它是自我维护的,因为无需任何人记得去让任何东西过期。
record 拒绝创建没有锚点的记录。 这是强制执行的,而非建议:
$ deadend record --title "go build fails on cgo" --cmd "go build ./..."
Refusing to record: no anchors.
A dead end with nothing to watch can never expire, and a claim that can
never expire is indistinguishable from a bug. Name the files whose content
would have to change for this failure to stop being true.
Suggested anchors (they exist here):
--anchor package.json
Or pass --unanchored if this genuinely has no local artifact — it will
block forever, and deadend status will keep saying so.
不可衰减的情况确实存在(上游 API 限制、vendored 依赖),--unanchored 允许这种情况——但会大声提示,并在 deadend status 中计数,这样你始终知道自己的哪些断言是不可证伪的。
它长什么样
在重新运行某个代价高昂的操作之前,先问一下:
deadend check --cmd "npm install sharp" --log /tmp/last-install.log
⛔ BLOCKED — 1 recorded dead end matches, and its anchors are unchanged.
────────────────────────────────────────────────────────────────────────
dd_50e127c7d9c5 npm install sharp 失败:darwin-arm64 没有预构建二进制文件
匹配 完全相同的命令
记录于 2026-09-13(今天)
尝试 npm install sharp → 退出码 1
症状 Error: Cannot find module sharp-darwin-arm64.node
原因 sharp 提供预构建二进制文件,但此平台/架构没有对应的二进制文件
替代方案 npm rebuild sharp --build-from-source
锚点 2 个中 2 个未变 — 仍然权威
✓ package.json
✓ package-lock.json
证据 install.log
────────────────────────────────────────────────────────────────────────
这不是一条禁令——而是一个曾经为真的断言,连同其证据。
如果你认为情况已经变化,请重新测试并重新确认:
deadend verify dd_50e127c7d9c5 --still-fails --log
现在修改 package-lock.json 中的一行,然后再次询问:
⚠ 可疑 — 有 1 条已记录的死胡同匹配,但它所描述的情况已经改变。
锚点 2 个中 1 个已变 — 不再权威
✓ package.json
✗ package-lock.json f25e7d29 → 55eaf97b
重新测试它:现在可能可以工作了。
仍然失败? deadend verify dd_50e127c7d9c5 --still-fails
现在可用? deadend verify dd_50e127c7d9c5 --now-works
这种转变——先是权威性地被阻塞,然后在证据发生变化的那一刻诚实地降级——就是整个插件的核心。
记录一次失败
deadend record \
--title "npm install sharp fails: no prebuilt binary for darwin-arm64" \
--cmd "npm install sharp" --exit 1 --log /tmp/last-install.log \
--why "sharp ships prebuilt binaries and publishes none for this platform/arch" \
--retry "npm rebuild sharp --build-from-source (needs libvips)" \
--anchor package.json --anchor package-lock.json \
--evidence /tmp/last-install.log --tag native
--log 值得费这个功夫。失败会以规范化的形式进行哈希——
行号和列号、绝对路径、临时目录、摘要、UUID、
时间戳、时长和 ANSI 颜色都会被移除——因此相同的故障
可以在不同会话、不同机器以及措辞不同的命令中被识别出来:
记录为: python app.py + ModuleNotFoundError: No module named numpy
仍能捕获:python3 app.py --verbose,相同失败,不同命令
deadend check --cmd "python3 app.py --verbose" --log ./run.log # -> exit 3
命令
deadend check [--cmd C] [--log F|-] [--symptom T] [--title T] [-q] [--json]
deadend record -t TITLE [--cmd C] [--exit N] [--log F|-] [--why W] [--retry R]
[--anchor PATH]... [--unanchored] [--evidence E]... [--tag T]...
deadend verify (--still-fails | --now-works) [--log F] [--note N]
deadend list [--status active|suspect|retired] [--all] [--json]
deadend show [--json]
deadend status [--json] 计数,以及需要关注的条目
deadend merge (使用 - 表示 stdin)
deadend gc [--dry-run] [--drop-retired] [--drop-undecayable]
deadend init
退出码就是接口,所以 check 可以与任何 shell 或 CI 门禁组合:
deadend check --cmd "npm install sharp" -q || echo "already ruled out; not retrying"
匹配是分层的,所以它绝不会误报
| 强度 | 匹配 | 决定性? |
|---|---|---|
| 3 | 完全相同的失败签名 | 是 |
| 2 | 完全相同的规范化命令 | 是 |
| 1 | 同一命令族,或相似标题 | 否 — 显示为相关 |
强度为 1 的匹配永远不会改变判定。npm install sharp 失败并不能说明 npm install left-pad 的任何问题,所以安装其他东西永远不会被阻止——它只会被提及,并附上先前的记录。一个阻止太多东西的门禁会被禁用,那样谁也保护不了。
命令规范化会去除空白和前置包装器(sudo、time、env),仅此而已。标志是命令的一部分。
账本存放在你的仓库中
/.deadend/ledger.jsonl # 仅追加的事件日志,每行一个 JSON 对象
不在 ~/.cache 中,也不是每台机器一份。这是影响最大的设计决策:
- 可审查。 它以 + {"v":1,"event":"record",…} 的形式出现在拉取请求中——一个你可以反驳的主张。
- 可共享。 你的下一次会话、你的队友、他们的智能体以及 CI 都会继承它。每台机器一份的缓存只能保护一台机器。
- 可审计。 每次变更都保留其理由:verify 追加一条观察记录而不是覆盖,gc 将历史折叠进条目,因此压缩永远不会丢失任何一条。
- 并发安全。 记录是追加操作;不存在读-改-写的竞态。
身份由内容派生(dd_ + sha256(title | command | signature | anchor paths)),因此两个克隆记录同一个反驳会产生相同的 id,合并账本就是集合并集,而不是去重问题。
完整格式:skills/deadend/reference/schema.md。
合并账本
身份由内容派生,因此同一个反驳被记录两次——由两个队友,或者由你在两台机器上——会具有相同的 id,合并就是集合并集,而不是去重问题。这正是将账本提交到共享仓库之所以可行的原因。
deadend merge ../other-clone/.deadend/ledger.jsonl # or - for stdin
added 3
updated 1
unchanged 7
total 11
当双方都知道某个 id 时,更新时间较晚的观察记录在状态和锚点上胜出,历史记录和备注会被合并,因此双方都不会丢失任何一条。
在 CI 中使用它
check 通过其退出码进行报告,因此账本可以在一行中成为门禁:
- name: Do not re-run a known dead end
run: |
npx --yes github:liyixuan201211/dsh-deadend check --cmd "npm install sharp" -q
exit 3 = still authoritative: fail
exit 4 = anchors changed: re-test, do not fail
exit 0 = clear
而且,由于不可证伪的条目正是这个工具存在的目的所要应对的失败模式
为了防止,当账本本身发生漂移时,让构建失败是值得的:
- name: Keep the ledger falsifiable
run: |
npx --yes github:liyixuan201211/dsh-deadend status --json > ledger.json
node -e '
const j = require("./ledger.json");
if (j.attention.length > 0) {
console.error("ledger needs attention:");
for (const a of j.attention) console.error(" " + a.id + " " + a.why);
process.exit(1);
}'
诚实的定位
记录失败并不是一个新想法,本插件也不声称它是。最接近的现有工作是 Claude Code 插件 dead-end-registry,它从对话记录中挖掘被回退的做法;此外还有关于失败感知共享记忆的学术研究(Negative Knowledge,ICML 2026 AI4Research workshop),以及自动化研究模板中作为协调机制的“死胡同登记表”。
| | 现有工作 | dsh-deadend |
|---|---|---|
| 捕获内容 | 从对话记录中挖掘的被回退做法 | 你陈述的、带证据的驳斥 |
| 存放位置 | ~/.claude/…,每台机器各自存放 | .deadend/ledger.jsonl,位于仓库中 |
| 匹配方式 | 对提示词进行关键词匹配 | 归一化的失败签名 + 命令身份 |
| 提取方式 | 启发式(+ 可选的模型处理) | 确定性的、离线的、无模型 |
| 过期 | 挂钟时间(例如 60 天) | 证伪器的内容哈希 |
| 不可衰减的声明 | 不加以区分 | 默认拒绝;允许时大声提示 |
| 接口 | 编辑器钩子 | 退出码,可与任何 shell 或 CI 组合 |
基于时间的过期在两个方向上都是错误的:太慢(一次依赖升级使今早的死胡同失效,却要 60 天后才清除它)和太快(一个关于被冻结依赖的死胡同在第 61 天毫无理由地消失)。最后三行是本文的贡献。完整推理见:reference/decay.md。
设计说明
无启动时代码。 cordis.patch.yml 故意是一个空补丁。一个主题为“不要重复错误”的插件,没有理由为每个 profile 向 DSH 进程插入代码。其载荷是一个 skill 加上一个 CLI,由该 skill 通过可见的 shell 工具运行。
事件日志,而非可变文档。 仅追加意味着没有读-改-写竞争、干净的 diff,以及为每次状态变更保留原因。
suspect 从不存储。 它在每次读取时从锚点重新计算。存储的陈旧标志本身也会变陈旧——这正是要避免的 bug。
拒绝而非静默写入坏条目。 record 会拒绝不存在的锚点、重复条目以及没有锚点的条目,而不是写入日后会悄悄误导人的内容。
作为 DSH 插件安装
dsh plugin --profile web add github:liyixuan201211/dsh-deadend
这会安装该 skill(skills/deadend/),它教会 agent 检查
在重试之前,并在失败后记录。该 bundle 补丁不会向启动图添加任何内容;如果你想验证这一点,请查看 cordis.patch.yml、package.json(没有生命周期脚本)和 src/。
开发
需要 Node >= 20。源码是带有 JSDoc 类型的纯 ESM JavaScript,因此没有构建步骤,也没有安装时脚本——而且发布后的 bin 在安装后确实可以运行。(它们不能是 TypeScript:Node 拒绝为 node_modules 内的文件剥离类型,而这正是该包在安装或通过 npx 运行时所在的位置。installable CI 任务对此进行防护。)
npm test # 74 tests
npm run typecheck # tsc --noEmit over the JSDoc types
npm run check # both
src/
cli.js exit-code contract and argument parsing
engine.js record / check / verify / gc, and the verdict rules
anchors.js hashing paths, detecting decay, suggesting anchors
fingerprint.js normalising failure output into a stable signature
model.js data model and event-log replay
ledger.js locating and reading/writing .deadend/ledger.jsonl
report.js human-readable rendering
index.js programmatic API
许可证
MIT。同作者(liyixuan201211)的其他插件
扫码进群