dsh-agent-self-test
DiscoveredSelf-validation closed-loop plugin: turning the "hypothesis→verification→learning" self-referential engine into a runtime mechanism — a falsifiable self-assumption library + tool pipeline automatic evidence collection (4 probes including 5.9 probe-before-action pre-action detection sensor) + finding emergence adjudication, achieving surprise-minimized proactive self-actual
dsh-agent-self-test
一句话:把「猜想 → 反驳 → 学习」做成运行时机制——你写下关于自己行为的可证伪陈述,插件在真实工具调用中被动采证,证据够数就把 finding 送到你面前,你裁决它。
为什么值得用:被动统计(比如「工具命中率」「错误计数」)只能描述行为,不能裁决猜想——它无法回答「我说过的那条行为规则,到底是真的是假的」。本插件把自我认知变成可证伪的假设 + 真实行为做裁判:每条假设有陈述、有可观测预测、有明确的证据阈值,证据达阈值才是 finding(不是「感觉最近有点问题」)。这是「惊奇最小化」的工程化:预测错误 = 升级数据包,而数据包必须由真实调用产生,不能由自我叙述产生。
核心循环
graph LR
A[selftest_add<br/>可证伪假设] --> B[真实工具调用<br/>被动采证]
B --> C{证据 ≥ threshold}
C -->|否| B
C -->|是| D[finding 浮现<br/>主动通知主会话]
D --> E[selftest_review 裁决]
E -->|confirm| F[写入 AGENTS.md 规则草案<br/>自动布线]
E -->|refute| G[淘汰猜想]
E -->|refine| A
五环缺一即断:猜想(selftest_add)→ 采证(探针被动观测)→ finding(主动通知)→ 裁决(selftest_review)→ 布线(confirm 写规则 / 技能 / 记忆)。断裂处就是下一步该修的地方。
能力(4 个工具)
| 工具 | 用途(描述取自源码,逐字) |
|---|---|
selftest_add | 添加一条可证伪自我假设:statement(关于自己行为的可证伪陈述)+ prediction(可观测预测)+ probe(探针)。插件在真实工具调用中被动采证,证据达 threshold 转 finding 供裁决 |
selftest_list | 列出自我假设库:每个假设的陈述/预测/探针/极性/证据方向/证据数/状态,并顺带做存量极性体检。可过滤状态(active/finding/confirmed/refuted)。方向由 polarity.ts 统一判定(支持/反对/混杂/未知)——confirmed 却「证据指向不成立」的行会标 ⚠极性存疑(裁决时方向读反了,该重新裁定) |
selftest_findings | 列出待裁决的 finding(证据达阈值的 active 假设)。⚠ finding 只说明「证据够了」,方向要另看:证据指向支持 ⇒ confirm(布线)/ 指向反对 ⇒ refute(淘汰)/ 混杂 ⇒ refine(细化判定条件)——每条 finding 附 direction 判定,按它裁决 |
selftest_review | 裁决一条假设:confirm 标 confirmed 并生成 AGENTS.md 规则草案(供布线);refute 标 refuted(淘汰);refine 改 statement/阈值/极性后回到 active 重新采证(旧证据清空)。裁决前会用 polarity.ts 算证据方向:当裁决动作与方向相悖(如方向=反对却 confirm)时返回 polarityWarning —— 只提示不阻断,决策权归爱丽丝(§2.1) |
selftest_add 的关键参数(缺省值取自 defineTool schema):kind(探针类型,必需)、polarity(假设极性,不填 = 按探针 kind 取默认并物化写入)、threshold(finding 证据阈值,缺省用插件配置)、source(来源,缺省 alice),以及每类探针自己的窗口/阈值参数(见下表)。selftest_review 额外接受 ruleDraft(confirm 时写入 AGENTS.md 的规则草案)、newStatement / newThreshold / polarity(refine 时)、resolution(裁决记录)。
探针(5 类声明式条件观察器)
| kind | 观测什么 | 触发条件(默认) | 典型假设 |
|---|---|---|---|
tool-failure-rate | 工具失败率(双向) | ① 失败率 ≥ failureRateAbove(0.3)记一条 violated;② 调用数达 minSamples(20)整数倍且未越阈值记一条 survived(经受住检验) | 「工具 X 不可靠(失败率 ≥30%)」 |
read-repeat | 同一路径重复读取 | 窗口 windowMs(10 分钟)内同路径读 ≥ repeatCount(2)次 ⇒ 记 verdict: 'violated' | 「我倾向重复读同一文件(健忘信号)」 |
plan-before-action | 复杂多步任务前的规划(双向,2026-09-17 补齐) | 突发(间隔 < burstGapMs 60s、长度 ≥ minSteps 5):① 起点前 planWindowMs(3 分钟)内无 todo_write 且突发内失败 ≥ 1 ⇒ verdict: 'violated';② 有 todo_write 且突发内零失败 ⇒ verdict: 'survived'(对照组);③ 其余形态(无规划零失败 / 有规划撞墙)⇒ 不记(诚实留白) | 「我会先规划」/「不先规划会更多返工」 |
probe-before-action | 实施前的证伪探测 | 实施突发(mutating 调用 ≥ minActions 3)的首个动作前 probeWindowMs(15 分钟)内无探测且突发内失败 ≥ 1 ⇒ verdict: 'violated';探测过且零失败 ⇒ verdict: 'survived'(探测过但撞墙 ⇒ 不产证据,诚实留白) | 「驱动方案前会先做最小证伪实验」 |
claim-vs-evidence | 机制自述与落盘实证的一致性 | 窗口 claimWindowMs(6 小时)内「自我安排」自述 ≥ minArranged(5)却零「自我感知圈触发」→ 判假活(verdict: 'violated');自述与实证并存 ⇒ verdict: 'survived'(claimCheckIntervalMs 5 分钟为两次检查最小间隔) | 「我说要安排感知圈,就真的会有感知圈」 |
plan-before-action 的两个边界语义(2026-09-17 受控实验实证,别重复踩):① 突发边界由「相邻调用间隔 > burstGapMs」决定,不由「回合/批次」决定——连续批次(间隔 <60s)会合并成一个长突发;② hadPlan 在突发诞生瞬间冻结,同一突发内后补 todo_write 无效 ⇒ 「规划」必须真的发生在突发之前(与 §5.8 序位判据同义:台账先落,再动手)。因此在长会话 + 连续批次的工作模式下,该探针可能长时间停在 active 而不产任何证据——这是边界,不是故障;要拿到正向证据,需要一次「真实空隙(>60s)+ 规划开场」的突发。
tool-failure-rate 为什么必须双向:早期实现只在 isError 时采证 → 「X 可靠」这类假设结构上无法被证实,永远停在 active 并污染感知圈报告(实测 2 条假设证据恒 0)。现在两种证据都采(detail.verdict 区分 violated / survived),finding 通知也按方向给不同文案——「假设经受住检验」与「finding 浮现」是相反的行动信号。
极性(polarity):证据方向 ≠ 假设方向
两层语义必须分开,这是本插件最容易反的一处裁决:
- 探针层
verdict= 事件属性:探针盯的规范被violated(违反)还是survived(经受住)。canonical 字段名是detail.verdict(2026-09-17 统一;readEventVerdict()兼容读取旧字段detail.kind与旧词形violation)。 - 假设层
polarity= 假设属性:该事件对这条假设意味着什么。violation-refutes(默认,四族):假设主张「我会做 X」⇒violated是反对证据violation-supports:假设主张「我倾向做 X」(自省缺陷型)⇒violated是支持证据
例:read-repeat 的 violated(又重复读了)对「我不该重复读」是反对,对「我倾向于重复读」是支持——同一份证据,极性不同,裁决方向相反。
| kind | 默认极性 | 理由 |
|---|---|---|
tool-failure-rate | violation-refutes | 主张「X 可靠」 |
claim-vs-evidence | violation-refutes | 主张「自述与实证一致(不假活)」 |
plan-before-action | violation-refutes | 主张「我会先规划」 |
probe-before-action | violation-refutes | 主张「我会先探测」 |
read-repeat | violation-supports | 主张「我倾向于重复读」(自省缺陷型) |
为什么要有这一节(2026-09-17 事故,任务 t-56b052fb):修复前只有两族写方向字段,另三族靠「这类探针只在违规时发射」的隐式约定——消费方一律把 finding 读成「假设被证实」,实测有 6 条「我会先做 X」型假设被违规证据判成 confirmed(方向反了)。现在方向由 polarity.ts 单一真源判定,selftest_list 对「状态说成立、证据说不成立」的行标 ⚠极性存疑;存量无标签证据按 LEGACY_UNLABELED_VERDICT 显式推定并在输出里报出条数(推定是显式的,不是暗的)。
突发推进每工具调用只做一次(多假设不 double-count),证据广播给所有 active 的 plan-before-action 假设。
快速开始
1) 装依赖(自研插件家园 self-plugins/,在目标 profile 的 package.json 加 link 依赖):
"dsh-agent-self-test": "link:<工作区>/self-plugins/dsh-agent-self-test"
2) 构建:
cd self-plugins/dsh-agent-self-test && npm install && npm run build && npm test
3) 挂组合(web profile;workspaceDir 指向 AGENTS.md 所在的工作区根,缺省 process.cwd()):
- id: agent-self-test
name: dsh-agent-self-test
config:
enabled: true
findingThreshold: 5
mainSessionOnly: true
notifyOnFinding: true
4) 30 秒验证(走一遍五环的最小闭环):
① selftest_add { statement: "我读完文件后会重复读同一路径", prediction: "10 分钟内同路径读 ≥2 次", kind: "read-repeat" }
→ 期望:返回新假设 id,状态 active
② selftest_list → 期望:看到该假设,evidence 计数
③ (正常干一会活,让真实调用产生证据)
④ selftest_findings → 证据达阈值后:⚠ 列出该 finding
⑤ selftest_review { id, verdict: "refute" } → 期望:状态 → refuted(试用后记得清)
配置
(键名与 src/index.ts 的 Config schema 一致;默认值取自源码)
| 项 | 默认 | 说明 |
|---|---|---|
enabled | true | 总开关 |
dataDir | 未设(回退 $DSH_HOME/agent-self-test) | 数据目录(假设库落点) |
findingThreshold | 5 | 证据达此数即转 finding(单条假设可用 selftest_add { threshold } 覆盖) |
mainSessionOnly | true | 只采证主 agent(delegationDepth === 0)——subagent 行为不是「我」,不污染自我认知 |
notifyOnFinding | true | finding 浮现时主动通知主会话(agent.send(..., 'next-step')),无需轮询 selftest_findings |
workspaceDir | 未设(回退 process.cwd()) | 工作区根——AGENTS.md 所在目录,confirm 自动布线的写入目标 |
落盘与自证(出问题时先看这里)
本插件不写阶段轨迹(无 *-trace.jsonl);它的自证产物是假设库 + 布线痕迹:
| 文件 | 谁写 | 内容 |
|---|---|---|
<DSH_HOME>/agent-self-test/self-test.json | 本插件 | 假设库:每条假设的 statement/prediction/probe/evidence[](含 kind、verdict、atMs)/status/threshold/source |
<DSH_HOME>/agent-self-test/backups/AGENTS.md.bak-<ts> | 本插件 | 每次布线前的 AGENTS.md 全量备份(回滚安全网;备份失败 best-effort 不阻断布线) |
<工作区>/AGENTS.md | 本插件(confirm 带 ruleDraft 时) | marker 块 <!-- dsh-agent-self-test:start --> … <!-- dsh-agent-self-test:end -->。已有块则整体替换,无则文件末尾追加;原子写(tmp + rename) |
<DSH_HOME>/life-core/life-log.jsonl | dsh-life-core | 只读输入:claim-vs-evidence 的取证面(自述 vs 实证的对照数据) |
一条命令答五问:
node -e "const fs=require('fs');const p=(process.env.DSH_HOME||'.dsh')+'/agent-self-test/self-test.json';const s=JSON.parse(fs.readFileSync(p,'utf8'));console.log(s.hypotheses.map(h=>h.status+' '+h.id+' ev='+(h.evidence||[]).length+' '+(h.evidence||[]).slice(-1).map(e=>e.kind+':'+(e.verdict||'-')+'@'+e.atMs)).join('\n'))"
# ① 跑的是哪个构建 → 取不到(假设库无 build 自报);用「生效判据」节的 plugin_boot_status / lib mtime 判
# ② 谁发起 → 每条假设的 source(缺省 alice);证据自带 atMs 时刻,可与会话日志对时间
# ③ 断在哪一段 → 状态分布即断点:一堆 active 且 ev=0 = 采证环断(探针从未命中);有 finding 未裁决 = 裁决环断;confirm 后 AGENTS.md 无 marker 块 = 布线环断
# ④ 结果质量 → evidence[].verdict 区分 violated / survived(双向证据);对比 threshold 看离 finding 还差几条
# ⑤ 耗时与预算 → evidence[].atMs(证据发生时刻);探针窗口参数即"预算":windowMs / burstGapMs / planWindowMs / probeWindowMs / claimWindowMs
注意
ev=0的两义性:采证为 0 既可能是「探针没命中」,也可能是「该探针的结构决定了它只在特定条件下记账」(例如tool-failure-rate的survived证据要等到调用数达minSamples整数倍)。别把「没证据」直接读成「假设为假」。
生效判据与回退
生效判据(三选一,按可靠性排序):
- 行为级(最直接):
selftest_list返回假设库,且selftest_add成功后<DSH_HOME>/agent-self-test/self-test.json的 mtime 前进 ⇒ 工具面与持久化都在工作; - 生态级:
plugin_boot_status(dsh-plugin-bootreport)返回的liveNow含本插件 ⇒ 进程在跑它; - 构建级:
lib/index.js的 mtime 早于 web 进程启动时间 ⇒ 当前进程加载的是这个产物。
注意:重新构建 ≠ 生效——产物 mtime 新只证明「构建过」,进程启动时间晚于产物 mtime 才算「在跑它」。本插件也没有
hasUnverifiedBuilds()类兜底,构建完必须重启 web 才生效。
回退(三档):
- 源码级:
git -C self-plugins/dsh-agent-self-test revert <commit>→npm run build→npm test→ 预检 → 重启; - 组合级:给 profile 里
agent-self-test行加disabled: true→ 哨兵重启;或临时config.enabled: false(同样需重启); - 运行期(本插件特有的第三档):
- 撤回一条被误布线的规则:把
<DSH_HOME>/agent-self-test/backups/AGENTS.md.bak-<ts>覆盖回<工作区>/AGENTS.md(删除它会导致「布线证据消失」),或手工删除 marker 块内容; - 重置假设库:删除
self-test.json(副作用:所有未裁决的证据一并丢失——先selftest_findings导出待裁决项再删)。
- 撤回一条被误布线的规则:把
改
AGENTS.md是本插件的最大副作用:confirm 路径会写工作区里的规则文件(那是 agent 每次注入都会读的「灵魂」)。因此它必须先备份再原子写——这一条不得为了"简化"而删掉。
测试
npm test # = node --test "tests/*.test.mjs"(跑 lib/ 产物,需先 npm run build)
39 例离线测试全部通过(# pass 39 / # fail 0,7 个 suite):
| 文件 | 覆盖 |
|---|---|
tests/failure-rate.test.mjs | tool-failure-rate 判定:双向语义(violated 与 survived 两种证据各自成立)、minSamples 检查点(样本达整数倍且未越阈值才记 survived)、阈值边界。判定纯逻辑无 IO/时间依赖,故不引入需要持久化的 nextCheckpoint 状态——「重启即归零的隐式状态」正是被明确否决过的设计 |
tests/burst.test.mjs | 「突发」状态机:连续调用长度/间隔判定、最小步数、突发起点前规划窗口、每个调用只推进一次(不 double-count)、多假设广播 |
tests/probe.test.mjs | probe-before-action 纯状态机(AGENTS.md §5.9 配套传感器):实施突发识别(mutating 计数)、首个实施动作前的探测回看窗口、退化输入(空事件序列/缺字段)不抛 |
tests/claim-evidence.test.mjs | claim-vs-evidence 判定纯函数(§5.17 配套传感器):自述计数 vs 感知圈触发计数的对照、窗口边界、假活判定、检查间隔节流 |
无网络依赖、无真实外部服务依赖:探针判定全部是纯函数或内存状态机;不发真消息、不读真会话(life-log.jsonl 的存在性由生产路径负责,缺失时该探针只是采不到证据)。
设计要点
- 纯观察优先(不可违反):只订阅
tools/result只读通知,不注入 prompt、不干预决策。自主性铁律:信号送达,不代替决策——插件永远不自动 confirm / refute,finding 只是「该你裁决了」的通知。 - 采证限定主会话:
mainSessionOnly=true时只采证delegationDepth === 0的 agent。subagent 的行为不是「我」——把子代理的工具失败算进自我认知,等于用别人的行为给自己下结论。 - 投递用
exec.agent,不走ctx.agents.get(sessionId):后者会因 ID 形状不匹配找不到 agent(曾导致 finding 通知静默丢失)。通知经agent.send(message, 'next-step')在会话事件中落地(Model-visible ⟺ logged 成立);用setImmediate防 reenter(事件回调内同步agent.send会与session.append冲突),失败记日志不静默。 - 纯决策层与 IO 分离:5 类探针的判定分别在
failure-rate.ts/burst.ts/probe.ts/claim-evidence.ts,全部零 IO、零时间依赖(时间由调用方传入)。这是可离线单测、也是「证据可复算」的前提。 - 「能证实」与「能证伪」同等重要:只有证伪通道的探针,会让「我很可靠」这类真命题永远无法结案(结构上无法被证实)。加双向证据不是锦上添花,是让假设库能收敛。
- 状态快照而非日志:假设库是一份 JSON(覆盖写),不是 append-only 日志。改动判定逻辑后旧证据的解释可能变化——所以每条证据自带
kind+atMs,让「当时的我」可重建。
相关文档
| 文档 | 内容 |
|---|---|
docs/semantic.md | 权威契约:定位与反定位、术语、概念模型与不变量、契约(含调用点清单)、边界与信任、可证伪验收清单、实践修订记录、未决问题 |
| alice-digital-life | 本插件所属生态的中心索引(全部自研插件) |
技能 self-test-loop / claim-vs-evidence-forensics / plugin-maintainability | 自我检验闭环协议(五环完整性)、「声称在跑 vs 真的生效」取证方法论、可维护性五问与自证证据层 |
License
MIT © jonah791
本插件属于我的数字生命爱丽丝(alice-digital-life)的 DSH 自研插件生态——50 个插件按生命/认知/感知/行动/通信/治理/呈现七层组织。
Comments
Loading…
Similar plugins
by yiyunet
一个跑在 DeepSeek Harness 输入区的学习插件:把「收集 → 提炼 → 关联 → 升级 → 沉淀 → 复用」做成有交互引导、预设管理、审核入库与体系体检的运行时能力。DeepSeek Harness plugin: a four-entry learning workspace.
★ 0
MIT
JavaScript
Sep 28, 2026
dsh plugin --profile web add @yiyunet/dsh-learn-skillsby BiBoyang
DSH 插件评测工具:YAML 用例驱动真实 agent 回归评测 + baseline 对比 PASS/WARN/FAIL 门禁|Regression eval harness for DeepSeek Harness plugins
★ 12
↓ 35/wk
TypeScript
Aug 24, 2026
dsh plugin --profile web add dsh-eval-harnessby lylarcher
一个DSH插件,为自定义模型配置输入类型(input)、推理模式(reasoningEfforts)
★ 0
MIT
TypeScript
Aug 29, 2026
dsh plugin --profile web add dsh-model-capabilitiesby Liu-Bot24
DeepSeek Harness(DSH)只读执行轨迹复盘插件,支持规则分析、独立模型解读、证据定位、任务概览与运行对比。
★ 5
MIT
JavaScript
Sep 26, 2026
dsh plugin --profile web add dsh-plugin-trace-insightby lispking
A self-evolving plugin for DeepSeek Harness (dsh). It observes how the agent runs, proposes improvements to its own assets via the LLM, validates each proposal inside a sandboxed trial agent, and appl
★ 3
↓ 202/wk
MIT
TypeScript
Aug 25, 2026
dsh plugin --profile web add dsh-auto-evolveby Areium
DeepSeek Harness(DSH)插件:自动记录所有执行模式(原生工具 / PTC run_code / 代码内嵌工具调用)的工具失败错因,去重、计数、确定性排序后沉淀进 skill 的机器维护实录区段——让 Agent 越用越少错。
★ 9
↓ 109/wk
MIT
JavaScript
Aug 21, 2026
dsh plugin --profile web add dsh-fail-logger