
Signoff Cli
io.github.ayuanxx-max由 GitHub 账号 ayuanxx-max 发布v4.1.9更新于 Nov 7, 2026
Five gates that make an agent's 'done' provable: run them, read the verdict, audit the record.
概览
把 SignOff 命令行工具的五道交付关卡封装为 MCP 工具,让助手在 git 仓库中运行检查、读取判决并审计记录。
- 可以做什么
- 运行五道关卡(验证、覆盖分级、任务卡队列、危险动作账本、反空话文档检查)并读取通过或失败的判决。
- 扫描暂存区或整个仓库的密钥泄露,输出时对值做遮蔽。
- 审计提交是否带有闸门标记与签名,并导出或合并本地账本。
- 检查与修复安装状态:status、doctor、explain,以及安装或卸载 git 钩子与 CI 工作流。
- 统计增量行覆盖率,并对发布物运行发布闸门。
- 适用场景
- 当助手在 git 仓库中声称任务已完成,而你希望这份声明有可执行的检查、留存的证据和提交级审计记录支撑时适用。也适合希望在提交前与 CI 中强制测试、覆盖率级别、密钥扫描和文档质量的团队。
- 运行要求
- 通过 npx 从 npm 包 signoff-cli 在本地运行,需要 Node 18 及以上和 git。未声明任何账号、API 密钥或环境变量。离线工作,不调用外部服务。
安装
在 SourceWeft 中
- 打开 控制台中的 Signoff Cli,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
落印 / SignOff
包名 4.0.0 起为
signoff-cli(曾用名dsh-signoff,旧包已标记 deprecated)。 命令仍是signoff;仓库地址仍是ayuanxx-max/signoff-cli。DSH 只是它最早的使用场景, 任意 git 仓库、任意语言都可以直接用。
中文名「落印」:印落纸面才算数,对应英文名 SignOff。曾用名「一诺过五关」「执印」。命令是
signoff; 包名 4.0.0 起为signoff-cli,仓库 4.1.0 起为ayuanxx-max/signoff-cli(由dsh-signoff改名,老地址 301)。
签下的那句“做完了”,得自己走过五道关才算数。
五道关卡,五条命令,退出码即判决;发版另加第六道 signoff release(见文末)。每一关都对应 agent 交付时的一种失败方式:靠记忆跑测试、把“有开发页”当验证、多个 agent 撞同一文件、危险动作做过就忘、文档里塞空话。SignOff 把这五种失败变成五个可执行的检查。
一张图看懂
六个层次从左到右:入口(CLI / git 钩子 / CI / Agent 面)都走同一个 guard.js;调度决定跑哪几关、
谁算通过;五关每关都写清“读什么、判什么、怎么修”;状态机说明一次提交里 marker 与 trailer 是怎么产生的;
产物是判断留下的证据;最右是外部依赖——只有 Node ≥18 与 git 是硬要求,其余都可缺。
判定没有“部分通过”:退出码 0 通过、1 任一关判红、2 用法或环境错。
上半部分按 0→5 的先后排:前置检查 → 安装 → 初始化 → 日常提交 → 红了怎么办 → 升级与卸载。
红框是必做,黄框是最容易踩的坑(--chain、--lock-test、npm proxy)。
下半部分三块是“不改你的流程、但会改变你看到的现象”:平台差异、环境差异,以及三条红线
(--no-verify、SIGNOFF_SKIP=1、调阈值让红变绿)。
两张图都由 Mermaid 生成,源文件在 docs/diagrams/src/,改文案重渲一次即可,
不用重画。
零接触:装一次,之后不用管
目标是一条命令之后不再需要任何操作:npm i -g signoff-cli 装完即生效,之后每次 git commit 都自动受五关约束。
npm 11 会把 postinstall 放进 allowlist 提示,可能不执行——所以还有一层兜底:在该仓库里第一次跑任何一关(比如 signoff p5 README.md)会自动把五关装好。
要放行安装脚本就加 npm i -g signoff-cli --allow-scripts=signoff-cli。
行为约定:
- 已 opt-in(有
.signoff/config.json):pre-commit 跑全套五关,PASS 才写 marker 和 trailer。 - 未 opt-in:只跑 P1(有测试才跑,没测试就明说"没检测到测试运行器"后放行),不写
.signoff配置、不带 trailer。 - 仓库自带的钩子不会被绕过:机器层先执行
.git/hooks/<stage>,它若是 signoff 的钩子就直接以它的判决为准。 - 提交
signoff.json等于「这个仓库同意 P1–P5」:.signoff/是 gitignore 的,声明文件进 git, 所以别人克隆下来第一次 commit 就会把 hooks / config / CI 自己补上。字段见docs/signoff.schema.json。 - 临时退出:
SIGNOFF_NO_BOOTSTRAP=1(不做自动安装)、SIGNOFF_NO_MACHINE=1(不跑机器层的轻量关)。 - 撤销机器层:
signoff uninstall --global。
一、案例:本次 DSH 2.0.22-next升级后在修复(dsh-session-fork-tree 0.9.34)bug里,五关各自做了什么?
这次修的是“升级 DSH 后,点侧栏「···」菜单,菜单闪一下就消失”。五关实际起了什么作用,逐条列出,包括没发挥作用的那一关。
一句话:P2 决定“修好没有”,P5 决定“我有没有说大话”,P1 只证明没弄坏别处,P4 事后抓住了我自己的一笔脏账,P3 全程没上场。 这个结论本身就是 SignOff 想要的输出:每一关都要能回答“发挥了没有”,不能只说“流程走过了”。
你不需要做什么,照常进行任务,由它来守护这个过程;
二、自动守护:装一次,之后不用记
signoff init 把五关接进 git 与 CI,一次安装,之后正常 git commit / git push / 开 PR 都由它先查:
只依赖 Node 18+:闸门本身是 Node 实现(lib/p*.js),没有 Python 也能跑完整五关,不存在降级模式。
三条稳定性措施:同一份暂存内容只判一次(命中缓存约 0 ms,反复 git commit --amend 不重复付时间);失败只打印失败那一关的尾部(完整日志在 .signoff/hook.log);超预算直接判红(默认 180 秒,--budget 可改)。
绕过的路仍然有,但不再无痕:signoff audit --range origin/main..HEAD 逐个提交核对标记与提交树——缺失就是绕过(git commit --no-verify),判红;SIGNOFF_SKIP=1 的提交写成 Signoff-Skip: 并记进 .signoff/skips.log,--strict 下同样判红。生成的 CI 里已经带这一步。
队友为什么也会被守住:先把 signoff-cli 放进 devDependencies(npm i -D signoff-cli),再 signoff init --prepare,它会把 signoff init --quiet 并进 package.json 的 prepare,队友 npm install 完钩子就有了。没这个依赖时 --prepare 会拒绝写入并提示——否则 npm install 会因为找不到 CLI 直接失败。
密钥扫描与提速(3.12.0 起)
- P1 之前先扫密钥:内置 16 条高信号规则(AWS / GitHub / GitLab / OpenAI / Google / Slack / Stripe / npm / SendGrid / 私钥块 / Azure / Discord webhook / 带密码的数据库 URL / 通用凭证)。
命中即失败;装了
gitleaks可用--engine gitleaks换全套规则,没装也不影响(纯 Node,无需二进制)。 - 值不会原样打印:只显示
AKIA…EF这种前缀 + 规则名 + 行号,避免把日志变成二次泄露。放行写在.signoff/config.json的secrets.allow。 - 未 opt-in 的仓库也扫:机器层守护走
--no-state,扫完不留任何文件。 - 运行器探测扩了 9 种:go / cargo / maven / gradle / dotnet / ruby / elixir / php / make(
tests/与package.json仍在最前)。 - 同一暂存树结果缓存:重复跑 0 ms;纯文档提交跳过测试。两个开关都可关:
SIGNOFF_NO_CACHE=1/SIGNOFF_NO_FAST=1。
签名与增量覆盖率(3.13.0 起)
- 提交自带签名:
signoff init --sign生成仓库本地 ed25519 密钥,commit-msg在Signoff-Pass:之外再写Signoff-Key:+Signoff-Sig:(对完整 tree 签名,单行 base64)。没有密钥就只写未签名的Signoff-Pass,不阻塞提交。 - 可以复核:
signoff audit --verify逐个提交验签,--require-signed把未签名也算失败。身份锚点是 仓库里提交的.signoff/allowed_signers(或signoff.json的allowed_signers):不在名单里只报self-signed,绝不报verified。 - 增量行覆盖率:
signoff cov --diff --min 80只算这次改动新增的行,读项目已有的coverage/lcov.info/coverage-final.json/ pythoncoverage json,不额外装运行器;没有覆盖率文件时报"没测过",不会假装通过。 - CI 直接标到行:
GITHUB_ACTIONS=true时,密钥/覆盖率发现输出::error file=…,line=…注解并写步骤摘要, PR 页面直接看到,不用翻日志。
可核对的凭证(3.15.0 起)
signoff p4 checkpoint 给账本签一个检查点,signoff p4 anchor 打出一行可以贴到发版说明里的锚点:
事后 signoff p4 verify --checkpoint --anchor <那一行> 能分辨四种情况:账本被截断、内容被改、
签名不属于受信 key、锚点与本机不一致。细节与边界(它不证明什么)见 docs/trust.md。
3.15.2 起还补了三件事:signoff p4 path 打印账本与检查点的真实位置(脚本不用猜);
guard 通过后自动续签检查点(同一份账本不重复签,不产生无意义改动);账本读取容忍 BOM
(Windows 编辑器与 Set-Content -Encoding utf8 的常见产物)。
能力矩阵与匿名竞品(3.15.2)
同一张表看"谁有什么"。竞品按类型匿名(不点名,避免把对比写成广告),对应关系与星标/下载数据
记录在 docs/signoff-positioning-3.15.2.md。
结论放在表后面而不是前面:前七行是它和其他工具的分野,最后两行是它的短板——托管面没有, 生态采用量也还没起来(1 star、周下载三位数),所以六维里"生态"给 3 分,不是 5 分。
上图是一次提交的完整路径:入口(git commit / 命令 / CI)→ 三层零接触 → guard 固定顺序跑 secrets → p5 → p1 → p2 → p4 → cov(opt-in)→ 判决 → 四层证据(marker → trailer → 账本 → 检查点 → 锚点)。红一关即停,退出码就是判决。
[落印 3.15.2 与匿名竞品:覆盖广度 vs 生态采用度]
上图横轴是生态采用度,纵轴是覆盖广度。落印落在左上角——功能全、采用低,这是它的真实位置: 它不在右上角跟平台级产品比采用,差异在"判决可以带走、可以事后核对"。
规则包、预设与编辑器(3.14.0 起)
- P5 规则包:
--pack zh|en|both。中文词表是默认值,行为不变;en用词边界匹配 (very不会命中delivery),both两套一起跑并按行去重。--rules rules.json追加自定义词表 (ai_words/absolute/adverbs/claims/placeholder),也可写进.signoff/config.json的p5或signoff.json的p5。 - 场景预设:
signoff init --preset node|python|go|java,一次给出预算、文档目录、覆盖率阈值和规则包;test_cmd仍交给自动探测,克隆到没有该脚本的机器也不会锁死。 - VS Code:
signoff init --editor vscode写.vscode/tasks.json(guard / all / secrets / cov / audit / status) 与 problem matcher,失败直接落到 Problems 面板;已存在的任务只合并不覆盖。
三、在其它代码过程里能干什么
四、在 DSH 任务里能干什么
- 发 npm / 改 profile / 改 cordis 配置:P4 先
ask取票(单次、10 分钟过期、绑定动作类别),再confirm落账,账里带回滚点;回滚点必须是真的 git ref,写一句“npm deprecate …”会被verify拒绝。 - 插件发版:P1 跑三套真实 DOM fixture,P2 把结果记进覆盖率表,P5 保证发布说明里没有
绝对化的收尾句。 - 长任务 / 跨天任务:P3 的卡片就是断点续传的凭据——scope、验收、回滚点三样齐了,换会话也能接上。
- 多分叉并行:不同分叉各拿一张卡,
plan先算出不会撞文件的波次,避免两个 agent 同时改同一处。 - 收尾:P5 的六条规则让“完成”这句话可以被机器反驳:无数字的
已验证、TODO、绝对化断言、AI 味词表(赋能/闭环/抓手…),命中即失败。 - 插件回归:
verify/scenarios/*.json是 P2 的输入格式,把 fixture 的 checks 数量直接变成覆盖率数字,不需要另写报表。
五、命令速查
每关都会把结果写到 .signoff/pN.json(P4 的账本在仓库内 .signoff/audit.log,不在仓库里时退回 ~/.signoff/audit.log;可用 SIGNOFF_HOME 改位置),便于 CI 存档与二次核对。
接入方式
- CLI(本体):
npm i -g signoff-cli,任何能起进程的地方都能调,退出码即判决。 - 技能:
integrations/skill/SKILL.md,把“退出码是判决、不许绕过、先 doctor 再 explain”教给 agent。 - MCP 服务器:
npx -y signoff-cli mcp(或integrations/mcp/server.js),给 Claude Desktop / DSH / IDE 用,五个工具,isError跟随退出码;官方 MCP Registry 条目为io.github.ayuanxx-max/signoff。 - 宿主插件:可行但不推荐(只有要画 UI 时才值得),理由见 docs/integrations.md。
推广与可发现性的现状和做法见 docs/promotion.md。
发布闸门(signoff release)
p1..p5 检查的是工作树,signoff release 检查的是发布物——这一段过去没有任何闸门覆盖,于是
注册表清单能把 packages[].version 钉在 3.9.4 上继续发布 40 个版本没有被发现。
它第一次运行就抓到一个真缺陷:files[] 漏了 integrations/,导致 3.9.3 起所有安装形态的
signoff mcp 都是 MODULE_NOT_FOUND,而注册表恰好教人用 npx signoff-cli mcp。现在 integrations/
已进包,--pre 为 14/14。
六、边界(先说清不做什么)
- 只读不改:五关不改你的代码,只在
.signoff/(P4 账本也在这里;非仓库目录才用~/.signoff/)写结果。 - P1 只看退出码:不做交互、不猜意图;命令怎么写由你给。
- P2 不生成断言:断言要人写;它只负责数、分级、拦住“没到 scenario 级”的降级。
- P4 是本机哈希链,不是外部公证:能发现事后改账,不能防有人连链一起重写。要更强证据得接外部时间戳。
- P5 是启发式:词表可以按团队改(
--allow <rule>放行某条),它拦住的是“明显没数字的断言”,不是全部坏文档。 - 钩子按仓库各装一次:
signoff init写在本机.git/hooks/,别人 clone 不会自动有;CI 那条才是全员生效。 - 测试命令是“查出来的”,不是“猜出来的”:按
package.json的test脚本 → vitest/jest/mocha 依赖 →Cargo.toml→go.mod→Makefile的test→ pytest → unittest 的顺序识别;signoff init/status/doctor都会写出用的是哪一条、从哪认出来的。tests/是空目录不算测试,不会让 p1 空跑一场报“没收集到用例”。 - 原有钩子不会被悄悄顶掉:
signoff init默认把现有钩子备份成<name>.signoff-backup(不串接);加--chain则存成<name>.local(Python/Node/PowerShell 钩子保留.py/.js/.ps1后缀,按后缀选解释器)并在我们的钩子里先执行——它失败就停,signoff uninstall会把它原样装回<name>。 - 账本可以跨仓库合并:
signoff p4 export --merge <另一个仓库的 audit.log>会逐文件重算哈希链,链断了的那份会被标出来并以 1 退出——合并视图不会替坏链背书。 - 同一仓库同时只跑一次钩子:
.signoff/lock是单实例锁(3.9.1 起是目录 +owner.json,用mkdir抢锁——O_EXCL在 SMB/NFS 上可能两边都成功),第二个提交会拿到“谁在占用”并退 1;锁的持有进程已死或超过 10 分钟自动作废。commit-msg不参与加锁——它不能把已经接受的提交再挡回去。 doctor只读:它从不安装、不改写、不删除,只把status/audit/p4 verify的结论摊开并给出修法;ok判 0,有fail判 1,不在仓库里判 2。- 安装点对不上就拒绝,不给出偏大的范围:
audit --since-install先确认安装点是 HEAD 的祖先(merge-base --is-ancestor),rebase、强推、换克隆之后那条提交不在当前历史里,会退 2 并让你跑signoff init --reset-install——审计结论不可信比审计报错更糟。 - 装钩子之前的历史不算账:
signoff init把当时的提交记进.signoff/installed.json,signoff audit --since-install从那里起算;普通audit遇到装钩子之前的缺失提交,会多打一行N of M missing commit(s) predate the install point,不用自己算范围。 - 钩子可绕过,但会留下证据:
git commit --no-verify不触发钩子,提交里就没有Signoff-Pass标记,signoff audit(CI 自动跑)判红;SIGNOFF_SKIP=1写Signoff-Skip并记进.signoff/skips.log,--strict下判红。 - 只需要 Node 18+:闸门与钩子都是 Node;没有 Python、没有其它解释器也能跑完整五关。
- 不联网:除
git与本地解释器外不调用外部服务。
English
Package name (since 4.0.0)
The package is signoff-cli; the former name dsh-signoff is deprecated. The command stays
signoff; the repository is ayuanxx-max/signoff-cli since 4.1.0 (renamed from dsh-signoff,
old URLs 301). Nothing about the tool is DSH-specific — any git repo and any language work.
At a glance (English)
[SignOff capabilities and relations]
Six layers, left to right: entry (CLI / git hooks / CI / agents) all go through one guard.js; dispatcher
decides which gates run and what counts as pass; the five gates (plus release, which guards what you publish) each state read → decide → fix; the state
machine shows how the marker and the trailer appear inside a single commit; artifacts are the evidence a
verdict leaves behind; external dependencies — only Node ≥18 and git are hard requirements.
There is no partial pass: exit 0 pass, 1 any gate red, 2 usage or environment error.
[User path: install, use, troubleshoot]
Stages 0 → 5 in order: precheck → install → init → daily commits → when it goes red → upgrade and uninstall.
Red boxes are must-do; amber boxes are the places people trip on (--chain when the repo already has husky
hooks, --lock-test when the test command differs per machine, a corporate npm proxy).
The lower half covers the three dimensions that change what you see without changing the flow: platform
differences, environment differences, and three red lines (--no-verify, SIGNOFF_SKIP=1, loosening
thresholds to turn red green).
"Done" is a promise. SignOff makes it walk through five gates before anyone signs it.
Five gates, five commands, the exit code is the verdict; publishing adds a sixth, signoff release. Each gate maps to one way agent work goes wrong: tests run from memory, a dev page mistaken for verification, parallel workers colliding on the same file, risky actions nobody recorded, documents padded with empty words.
Secrets and speed (since 3.12.0)
signoff secretsscans the index before P1 runs; the guard calls it first, always. Sixteen high-signal rules (AWS, GitHub, GitLab, OpenAI, Google, Slack, Stripe, npm, SendGrid, private-key blocks, Azure, Discord webhooks, credentialed DB URLs, genericpassword = "..."), plain Node, no binary.--engine gitleaksuses gitleaks when installed.- Values are masked in output (
AKIA…EF); allow a rule in.signoff/config.jsonundersecrets.allow. - The machine-wide guard scans secrets even in repos that never opted in (
--no-state: nothing written). - Runner detection now covers go / cargo / maven / gradle / dotnet / ruby / elixir / php / make.
- Same staged tree = cached verdict (0 ms); a docs-only commit skips the suite. Off switches:
SIGNOFF_NO_CACHE=1,SIGNOFF_NO_FAST=1.
Signed verdicts and change coverage (since 3.13.0)
signoff init --signcreates a repo-local ed25519 key;commit-msgthen addsSignoff-Key:+Signoff-Sig:next toSignoff-Pass:. The signature covers the full tree id and is a single base64 line, so it survives as a trailer. No key means an unsigned trailer - never a blocked commit.signoff audit --verifychecks each commit's signature;--require-signedmakes unsigned commits fail. Identity needs an anchor: a committed.signoff/allowed_signers(orallowed_signersinsignoff.json). A key that is not listed is reportedself-signed, neververified.signoff cov --diff --min 80counts only lines this change adds, reading the coverage file the project already writes (lcov, istanbul, python coverage json). No coverage file means "not measured", not "passed".- Under
GITHUB_ACTIONS=true, findings become::error file=...,line=...annotations plus a step summary, so a reviewer sees them on the diff.
Checkpointed evidence (since 3.15.0)
signoff p4 checkpoint signs the ledger head and Merkle root; signoff p4 anchor
prints one line to publish with the release. signoff p4 verify --checkpoint --anchor
then tells truncation, edits, untrusted keys and anchor drift apart. Scope and limits:
docs/trust.md.
Since 3.15.2: signoff p4 path prints where the ledger and checkpoint actually live (no guessing in
scripts); a passing guard re-signs the checkpoint (same ledger, same statement, no churn); ledger
reads tolerate a UTF-8 BOM, which Windows editors and Set-Content -Encoding utf8 leave behind.
Capabilities and anonymised peers (3.15.2)
One table for "who has what". Peers are anonymised by category so the comparison reads as a table,
not an advert; the mapping plus star/download figures live in
docs/signoff-positioning-3.15.2.md.
Read the last two rows as the honest part: no hosted surface, and adoption is still small (1 star, three-digit weekly downloads) — which is why "ecosystem" scores 3, not 5.
[SignOff 3.15.2 flow and four layers of evidence]
One commit end to end: entries (git commit / CLI / CI) → three zero-touch layers → guard runs secrets → p5 → p1 → p2 → p4 → cov (opt-in) → verdict → four layers of evidence (marker → trailer → ledger → checkpoint → anchor). First red stops; the exit code is the verdict.
[SignOff 3.15.2 vs anonymised peers]
Adoption on the x-axis, coverage breadth on the y. SignOff sits top-left: full-stack, low adoption. It does not compete on adoption with platform products; the difference is that a verdict can leave the machine and still be checked later.
Rule packs, presets and editors (since 3.14.0)
--pack zh|en|bothfor gate 5. Chinese stays the default so existing output is unchanged;enmatches on word boundaries (verydoes not fire ondelivery);bothruns the two packs and de-duplicates per line.--rules rules.jsonadds your ownai_words/absolute/adverbs/claims/placeholder, and the same object can live insignoff.json(p5).signoff init --preset node|python|go|javasets budget, docs, coverage threshold and rule pack.test_cmdstays auto-detected so a machine without that script still runs something.signoff init --editor vscodewrites.vscode/tasks.json(guard / all / secrets / cov / audit / status) plus problem matchers, so a failure lands in the Problems panel. Existing tasks are merged, never replaced.
Zero-touch
One command, then nothing: npm i -g signoff-cli writes a machine-wide core.hooksPath
(~/.signoff/hooks) and bootstraps the repo it is installed from.
npm 11 may hold postinstall behind its script allowlist (--allow-scripts=signoff-cli to allow it), so the
first gate command in a repo (signoff p5 README.md) installs the five gates as a fallback.
Committing signoff.json is the repository agreeing to P1-P5: .signoff/ is gitignored, the declaration is not,
so a clone builds the rest on its first commit. Fields: docs/signoff.schema.json.
Exit hatches: SIGNOFF_NO_BOOTSTRAP=1 (no auto install), SIGNOFF_NO_MACHINE=1 (skip the light guard),
signoff uninstall --global (remove the machine layer). A repo's own hook always runs first and keeps its verdict.
Case: what the five gates did in the 0.9.34 bug fix after the DSH 2.0.22-next upgrade
One line: P2 decides whether it is fixed, P5 decides whether I am overclaiming, P1 only proves nothing else broke, P4 caught my own dirty entry after the fact, P3 never left the bench.
You do not have to do anything differently — just carry on with your task, and it guards the process.
Auto-guard: install once, then it runs itself
signoff init wires the gates into git and CI, so an ordinary git commit, git push or pull request is checked first:
Requires Node 18+ only: the gates are pure Node (lib/p*.js), so no Python is needed and there is no degraded mode.
Three stability measures: the same staged tree is judged once (cache hit ~0 ms, so git commit --amend costs nothing); a failure prints only the tail of the failing gate (full log in .signoff/hook.log); exceeding the budget (default 180 s) is a red gate, not a silent twenty-minute hook.
A bypass leaves a trace: signoff audit --range origin/main..HEAD checks every commit's marker against its tree. Missing means the gates were skipped (git commit --no-verify) and is red; a SIGNOFF_SKIP=1 commit carries Signoff-Skip and turns red under --strict. The generated CI already runs this step.
Why a teammate ends up guarded too: with signoff-cli in devDependencies (npm i -D signoff-cli), signoff init --prepare appends signoff init --quiet to package.json's prepare, so their npm install installs the hooks; without it, CI is the backstop.
Beyond this fix: other code work
- New feature: card first (P3: goal / scope / acceptance / rollback), then a failing check wired into the hook (P1), then scenario assertions (P2), then a publish ticket (P4), then prose that every number supports (P5).
- Bug fix: freeze the reproduction as a command (P1
--run), add a reverse assertion that must go red on the old code (P2), split parallel work into waves (P3), keep one rollback point (P4), and publish only numbers (P5). - Refactor: scope bounds what may change and
collectflags out-of-scope edits (P3); zero-write and DOM-identity assertions prove behaviour did not move (P2). - CI:
signoff allis one command whose exit code is the verdict;--budgetcatches a suite that quietly got slower. - Multi-agent:
planemits waves where overlapping scopes never share a wave;collectreports both "changed a file nobody owns" and "card shipped nothing". - Handover: the coverage table (P2) plus the exported ledger (P4) are the first two things a new owner should read.
In DSH tasks
- npm publish, profile edits, cordis config changes: P4
askmints a single-use ticket (10 minute TTL, bound to the action category);confirmappends a hash-chained entry with a rollback point that must be a real git ref. - Plugin releases: P1 runs the real-DOM fixtures, P2 records them in the coverage ledger, P5 keeps the release notes free of absolute claims.
- Long or multi-day tasks: a card with scope, acceptance and rollback is the resume token - a new session can pick it up.
- Parallel forks: each fork takes a card;
plancomputes waves that cannot collide. - Closing: P5's six rules make "done" falsifiable by a machine: a numberless "verified", a
TODO, an absolute claim, or a banned buzzword fail the run. - Plugin regression:
verify/scenarios/*.jsonis P2's input, so fixture check counts become coverage numbers with no extra reporting.
Usage
Boundaries
- Read-only with respect to your code: results go to
.signoff/(the P4 ledger included;~/.signoff/only outside a repo). - P1 judges exit codes only.
- P2 counts and grades; it does not write assertions for you.
- P4 is a local hash chain, not external notarisation: it detects edits after the fact, and cannot stop someone rewriting the whole chain.
- P5 is heuristic; tune the word list with
--allow <rule>. - Hooks are installed per clone; a fresh clone needs
signoff initagain, while CI covers everyone. - Hooks are bypassable, but not silently:
git commit --no-verifyleaves noSignoff-Passmarker, sosignoff audit(run by CI) fails the range;SIGNOFF_SKIP=1leavesSignoff-Skipand is red under--strict. - Needs Node 18+ only; no Python and no other interpreter is required.
- No network calls; only
gitand the local interpreters.
Integrations
- CLI (the product):
npm i -g signoff-cli; anything that can spawn a process can run it, and the exit code is the verdict. - Skill:
integrations/skill/SKILL.mdteaches an agent the three things it gets wrong: the exit code is the verdict, never bypass a red gate, anddoctor/explaincome before touching config. - MCP server:
integrations/mcp/server.jsfor Claude Desktop / DSH / IDEs — five tools,isErrormirrors the exit code. - Host plugin: possible but not recommended; it only pays off when gate results must be rendered in a host UI. Reasoning in docs/integrations.md.
Discovery and promotion notes: docs/promotion.md.
Release gate (English)
p1..p5 read the working tree; signoff release reads the published artifact. --pre runs offline
(manifest consistency, npm pack, install into a temp dir, --version, an mcp initialize handshake -
14 checks); --post runs after publish and verifies npm dist-tags.latest, the MCP registry entry, and
every README image URL. Its first run found that files[] omitted integrations/, so every installed
copy since 3.9.3 had a signoff mcp that failed with MODULE_NOT_FOUND.
License
MIT
来源:README.md,提交 bb362d3
工具
0版本历史
1- v4.1.9最新Nov 7, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分