Independent researcher working on AI agent verification. I build small tools that check claims — mine and other people's — and publish the runs where the answer came back no.
GitHub · ORCID 0009-0002-6843-3390 · Google Scholar
1. precheck — an agent cannot pass a check it was not allowed to write
The acceptance check is frozen before the work starts and hash-locked, so rewriting it afterwards voids every verdict issued after that point. Once a check passes, the tool breaks the artifact the check just approved and runs the check again: a check that still passes on broken input was never evidence for anything.
python demo.pyin a checkout, run 2026-10-10 — withreplicas: 3changed to0the check still exits0, andauditreports2 check/mutation pair(s) survived- 19 unit tests, zero dependencies, standard library only, no network; CI green on Python 3.8 / 3.11 / 3.13 across Linux, Windows and macOS (9/9)
- On PyPI:
pip install precheck(v0.1.2) - Ships a GitHub Action
2. greencheck — mutation testing aimed at quality gates
It edits your configs and schemas in small ways — drop a line, blank a value, set a number to zero — and reports the ones your gate still accepts.
python -m greencheck.cli mutate --gate "..." --target examples/mutate-demo/inputin a checkout, run 2026-10-10 — 12 mutants, 11 caught, 1 escaped (blank-value:config.json:4:"replicas":)- 72 tests, zero dependencies, standard library only; CI green on Python 3.9 / 3.11 / 3.13 across Linux, Windows and macOS (9/9)
- On PyPI:
pip install greencheck(v0.3.1) - Its own output calls the result "questions, not findings": an escaped mutant may be a legal input, and the tool cannot tell you which without someone who knows what the gate is for
3. self-auditing-agent — an AI that audits itself in public
A published record of one run: every conclusion, the command that produced it, the bugs found in the audit tooling along the way, and the findings that were withdrawn. A stranger can re-run the core result.
- Volume 1 — a 74-minute forensic audit of an unfamiliar third-party system, a real gap found in it (the vulnerable pattern is reproduced offline in the repo), 4 bugs of its own, and one false discovery it caught itself
- The core finding reproduces with one command:
python repro/verify_sql_gap.py - The same repository turns its own gates into mutation targets and publishes which mutants escape
4. agent-pushgate — privacy gates on the manual push path
Automated export pipelines usually have a leak gate; a hand-typed git commit && git push usually has none, and that is where private material tends to escape. Six checks run on the pre-push hook — the working tree, the commit messages, the exact object range being sent, the hook installation itself, landing, and ledger discipline. Any non-zero return, including "cannot decide", refuses the push.
- Local commits are untouched: stopping is reversible, publishing is not
- 6 self-test and 3 falsification scripts; every gate is fed input it must reject. CI green on Linux and Windows × Python 3.9 and 3.13 (4/4 cells)
git push --no-verifybypasses it entirely, so one self-test measures that hole rather than pretending it is not there- Zero third-party dependencies, standard library only; the deny-list lives outside the repository
5. retrieval-abstention-bench — can a retrieval layer tell when the answer is not in the corpus?
Four question sets over four public-domain novels: one answerable, three unanswerable by construction. The false ones are built by swapping an entity anchor for a real entity that sits far away in the text, and whether they are genuinely unanswerable is checked numerically instead of asserted — a hand-written negative set only covers the cases its author imagined.
python bench/cli.py verifyin a checkout, run 2026-10-11 — 14 self-checks and 7 falsification cases, 33 s, exit 0; an oracle retriever drives the metric to 1.000 and a retriever that returns nothing drives it to 0.000- Headline cell, a zero-dependency BM25 retriever: declines 3.3% of the answerable questions and 86.0% of the unanswerable ones — 82.7 points apart, 95% CI 77.7 to 87.3
- No LLM, no network, no API key, standard library only; the exam is frozen with a sha256, and
verifyfails if a recorded threshold no longer matches the code - One criterion is easier than it should be on the cross-book tier (AUC 0.634 against 0.520 on the same-book tier), because the swapped anchor occurs nowhere in the target book at all; the headline rests on the criterion that has no such shortcut
- CI green on Python 3.9 and 3.12
6. hermes-degeneracy-guard — a looping model cannot quietly write its loop into a file
Hermes truncates runaway text, but by design it lets a provider-confirmed tool call through even when its arguments repeat. This plugin sits at pre_tool_call; when arguments look like a loop rather than data, it asks the user through Hermes' own approval gate instead of guessing, and unattended runs fail closed.
hermes plugins doctor degeneracy-guard --ci, run 2026-10-19 —OK,5 hook(s);hermes plugins validate—Validation passed, security scansafe- 37 tests, including the approval path driven through Hermes' real plugin manager and a corpus of legitimate repetitive data that must not prompt
- Two hold-out sets with the numbers as measured, misses included
- CI on Python 3.11–3.14 against a pinned Hermes commit, and weekly against Hermes main; standard library only
7. authority-chain — every rewrite an agent makes to its own rules is auditable
A hash-chained SQLite event log. A write must name the revision it read, or it is refused; a stale write is queued, not lost; protected documents need a human countersign bound to the exact content.
- README quick start, run verbatim in an empty environment in CI — ends with
chain_status INTACT - 87 tests; every refusal code in
docs/errors.mdis exercised by a test, and a test fails if a new code is documented without one - An installed copy keeps its ledger in the user data directory, not inside the package
- CI on Python 3.9 / 3.11 / 3.13; no runtime dependencies
8. agent-runaway-bench — what agent frameworks do when the model loops mid-reply
One fake endpoint speaking both OpenAI wires, and the same measurement for every framework: whether the client sends an output cap, and how much it reads before hanging up.
- At
5fc490e, Hermes's chat-completions stream stops the loop at 16,074 characters; the other five clients, across four frameworks, read all 300,048 and hand the loop back as the answer - Hermes's own Bedrock and Codex streams missed the guard at that commit; reported upstream as #141477 with a fix in #141479
- Standard library only, no keys, no spend;
loop_server.pyis the whole harness
9. hermes-provenance-gate — an agent cannot quietly record a decision the user never made
A Hermes plugin that checks every memory and skill write for sentences like "the user decided …" or "用户决定 …" and asks for the user's own words: a quote that appears verbatim in what the user typed this session, shares key words with the decision, and does not drop a negation.
- Observe mode by default: flagged writes are recorded and
reportlists them; block mode refuses them and tells the model how to fix the write - Measured on 133 lines an independent reviewer wrote and labelled before reading the code: precision 1.000, recall 0.694, published with the misses
- Three independent audits; every bypass they found is now a test, end to end through a real Hermes agent
Issues and pull requests sent to projects I do not own are kept in upstream-contributions: the text as filed, the text as it stands now, the patches, the raw API payloads, and the output produced while the work was done. A platform record is not permanent — a repository can be renamed or made private, a comment can be edited, a pull request can turn into a 404. That repository is the copy that does not depend on someone else's server.
- NousResearch/hermes-agent ·
hermes plugins validaterejects the legacyhooks:manifest key that the loader accepts · #141339 - NousResearch/hermes-agent · fix(plugins): validate accepts the legacy hooks: manifest key the loader reads · #141340
- NousResearch/hermes-agent · feat(plugin-catalog): add degeneracy-guard · #141341
- NousResearch/hermes-agent · Bedrock and Codex streams don't cut a repetition loop mid-stream (#130551 covers chat_completions and Anthropic only) · #141477
- NousResearch/hermes-agent · fix(agent): cut runaway repetition loops mid-stream on Bedrock and Codex · #141479
- NousResearch/hermes-agent · feat(plugin-catalog): add provenance-gate · #141935 · merged 2026-10-20 by @teknium1
The record is archived and citable: 10.5281/zenodo.23470460.
An AI system earns trust to the extent that it lets you check where it went wrong.
Three rules follow:
| Rule | In practice |
|---|---|
| Evidence before assertion | Every claim carries the command that produced it and its output |
| A gate must be able to say no | Gates are fed inputs that should fail; a check that cannot return a negative is not a check |
| Record the failures | Bugs, false alarms and withdrawn findings are published; a success-only showcase is not credible |
- Recovery or Repetition? Feedback Policy and Verbatim Relay in a Two-Agent Language-Model Loop. Research Square, 2026-10-08. DOI 10.21203/rs.3.rs-11287076/v1
- Can One Agent Restore Another? Multi-Agent Verification Through Independent Constraint Sources. Research Square, 2026-08-13. DOI 10.21203/rs.3.rs-10651733/v1
- Volume or Coupling? A Scale-Dependent Dissociation in Constraint Recovery of Language-Model Loops. Zenodo, 2026-07-05. DOI 10.5281/zenodo.21200851
独立研究者。做可被验证的事,并公开我被验证错了的部分。
GitHub · ORCID 0009-0002-6843-3390 · Google Scholar
1. precheck — 让 agent 用「它无权编写」的检查自证
验收检查在动工前就冻结并锁进哈希链,事后改一个字,那之后的全部结论作废。检查通过后,它改坏刚被批准的产物再跑一遍:在坏输入上照样通过的检查,从来就不是证据。
- 仓内取一份代码跑
python demo.py(2026-10-10 实测)——replicas: 3改成0,检查照样exit 0,audit报2 check/mutation pair(s) survived - 19 个单测、零依赖、纯标准库、不联网;CI 在 Python 3.8 / 3.11 / 3.13 × Linux / Windows / macOS 全绿(9/9)
- 已上 PyPI:
pip install precheck(v0.1.2) - 自带 GitHub Action
2. greencheck — 专查质量门禁的变异测试工具
它在你的配置和 schema 上做小改动——删一行、把值清空、把数字改成 0——然后报告哪些门禁照样收下了。
- 仓内取一份代码实跑(2026-10-10):12 个变异,11 个被拦,1 个逃过(
blank-value:config.json:4:"replicas":) - 72 个测试、零依赖、纯标准库;CI 在 Python 3.9 / 3.11 / 3.13 × Linux / Windows / macOS 全绿(9/9)
- 已上 PyPI:
pip install greencheck(v0.3.1) - 它自己的输出写着「这些是问题、不是结论」:逃过的变异可能是合法输入,没有懂这条门禁要干什么的人,工具分不出来
3. self-auditing-agent — 一个会自我审计的 AI
一份公开的运行档案:每个结论、产出它的那条命令、审计工具自己出的 bug、以及被撤回的发现。陌生的人可以复跑核心结果。
- 第一卷——74 分钟取证审计一个陌生第三方系统;在它里面找到一个真缺口(漏洞模式已在仓库里离线复现);4 个自己的 bug;1 个假发现是自己抓出来的
- 核心发现一条命令可复现:
python repro/verify_sql_gap.py - 同一个仓库把自己门禁当变异靶子,公开哪些变异逃了过去
4. agent-pushgate — 手工推送前的隐私闸
自动导出的那条路径通常有闸,手打 git commit && git push 通常没有,私密内容多半从这儿漏出去。六个检查串在 pre-push 钩子上——工作树、提交信息、这次要送的确切对象范围、钩子有没有真装上、落地、台账纪律。任何一个返回非 0(含「判不了」)就拒绝这次推送。
- 本地提交不受影响:停下来是可逆的,公开不可逆
- 6 个自证 + 3 个证伪脚本;每个闸都拿「必须被拒的输入」喂过。CI 在 Linux 与 Windows × Python 3.9 / 3.13 四格全绿
git push --no-verify能整个绕过它——所以有一条自证把这个洞实测出来,不假装它不存在- 零第三方依赖、纯标准库;禁止名单不进仓
5. retrieval-abstention-bench — 检索层知不知道「库里根本没有答案」
四部公有领域小说、四套题:一套可答,三套构造性不可答。假题的做法是把实体锚点换成一个真实但离得很远的实体,它到底可不可答由距离规则算出来,不是拍脑袋断言——手写的负样本只能覆盖作者想得到的那几个。
- 仓内取一份代码跑
python bench/cli.py verify(2026-10-11 实测)——14 项自检 + 7 条证伪,33 秒,exit 0;oracle 检索器把指标顶到 1.000,空检索器把它压到 0.000 - 头条格(零依赖 BM25):可答题弃答 3.3%,不可答题弃答 86.0%——相差 82.7 个百分点,95% CI 77.7 ~ 87.3
- 不用 LLM、不联网、不要 API key、纯标准库;考试封了 sha256,
verify发现记录的阈值与代码不符就报红 - 有一条判据在跨书档上比它该有的更容易(AUC 0.634,同书档 0.520),因为换过去的锚点在目标书里完全不出现;头条压在没这条捷径的判据上
- CI 在 Python 3.9 / 3.12 全绿
6. hermes-degeneracy-guard —— 陷入死循环的模型,没法悄悄把循环写进文件
Hermes 会截断失控的文本,但对于厂商已确认的工具调用,就算参数在重复,也会特意放行。这个插件挂在 pre_tool_call 上:参数看起来像循环、不像数据时,它不替用户做决定,而是借 Hermes 自带的审批机制请用户确认;没人值守时,默认拦下。
- 2026-10-19 运行
hermes plugins doctor degeneracy-guard --ci:OK,5 个钩子;hermes plugins validate通过,安全扫描 safe - 37 个测试,包括用 Hermes 真实插件管理器驱动的确认流程,以及一套「不能被打扰」的正常重复数据语料
- 两套留出集,按实测数字如实公布,包括漏判
- CI 在钉住的 Hermes 版本上跑 Python 3.11–3.14,每周再对 Hermes 主干跑一次;只用标准库
7. authority-chain —— Agent 每一次改写自己的规则,都可审计
一个用哈希链串起来的 SQLite 事件日志。写入必须写明读到的版本号,否则拒绝;过期的写入进入冲突队列,不会丢失;受保护的文档需要人工会签,签名绑定具体内容。
- CI 在空白环境里原样运行 README 快速上手,以
chain_status INTACT结束 - 87 个测试;
docs/errors.md里每个拒绝码都有测试覆盖,新增的码没有测试就会让测试失败 - 安装后账本存放在用户数据目录,不放在包目录里
- CI 跑 Python 3.9 / 3.11 / 3.13;没有运行时依赖
8. agent-runaway-bench — 模型在回复中途陷进循环时,各家框架怎么办
一个假端点同时说两种 OpenAI 线路,所有框架用同一把尺子量:客户端有没有自带输出上限,以及它读了多长才挂断。
5fc490e时,Hermes 的 chat-completions 通道在 16,074 字符处掐断;其余四个框架的五个客户端把 300,048 字符全读完,把循环原样当成答案- Hermes 自己的 Bedrock 与 Codex 通道在该提交上漏了这个守卫;已作为 #141477 报给上游,修复在 #141479
- 纯标准库、不要 key、不花钱;整个装置就是
loop_server.py
9. hermes-provenance-gate — agent 不能悄悄记下用户从没做过的决定
一个 Hermes 插件:每次写记忆或技能时,找出"用户决定……""the user decided …"这类句子,要求附上用户原话——必须逐字出现在用户本次会话里打的字中,和决定内容有共同关键词,且没有丢掉否定词。
- 默认只记录、不拦截,
report列出所有可疑写入;打开拦截模式后直接拒绝,并告诉模型怎么改 - 在一份独立审计员先写好、先标注、后看代码的 133 条盲测集上:查准率 1.000,查全率 0.694,漏掉的句子一并公开
- 经过三轮独立审计;审计找到的每一个绕过办法都已写成测试,经真实 Hermes agent 端到端验证
提给不属于我的项目的 issue 和 PR,都留了一份在 upstream-contributions:提交当时的原文、现在平台上的原文、补丁、API 原始返回,以及当时实际跑出来的输出。平台上的记录不保证长期存在——仓库可能改名、转私有,评论可能被编辑,PR 可能变成 404;那一份是我自己的副本,不依赖别人的服务器。
- NousResearch/hermes-agent ·
hermes plugins validaterejects the legacyhooks:manifest key that the loader accepts · #141339 - NousResearch/hermes-agent · fix(plugins): validate accepts the legacy hooks: manifest key the loader reads · #141340
- NousResearch/hermes-agent · feat(plugin-catalog): add degeneracy-guard · #141341
- NousResearch/hermes-agent · Bedrock and Codex streams don't cut a repetition loop mid-stream (#130551 covers chat_completions and Anthropic only) · #141477
- NousResearch/hermes-agent · fix(agent): cut runaway repetition loops mid-stream on Bedrock and Codex · #141479
- NousResearch/hermes-agent · feat(plugin-catalog): add provenance-gate · #141935 · merged 2026-10-20 by @teknium1
这份记录有永久编号,可以被引用:10.5281/zenodo.23470460。
一个 AI 值得多少信任,取决于它在多大程度上让人查它错在哪。
由此三条规则:
| 规则 | 落地形态 |
|---|---|
| 证据先于断言 | 每条结论都带着产出它的命令和输出 |
| 门禁必须能说「不」 | 门禁只用必须失败的输入去喂;不能输出否定的判据不算判据 |
| 记录失败 | bug、误报、被撤回的发现全部公开;只放成功路径的展示不可信 |
- Recovery or Repetition? Feedback Policy and Verbatim Relay in a Two-Agent Language-Model Loop. Research Square,2026-10-08。DOI 10.21203/rs.3.rs-11287076/v1
- Can One Agent Restore Another? Multi-Agent Verification Through Independent Constraint Sources. Research Square,2026-08-13。DOI 10.21203/rs.3.rs-10651733/v1
- Volume or Coupling? A Scale-Dependent Dissociation in Constraint Recovery of Language-Model Loops. Zenodo,2026-07-05。DOI 10.5281/zenodo.21200851
— Simin (Simon) Yuan

