{"_id":"@57blocks_agb/ab-gate","_rev":"3-80759583579d2dbef8dab9f0348ef6d5","name":"@57blocks_agb/ab-gate","dist-tags":{"latest":"0.0.3"},"versions":{"0.0.1":{"name":"@57blocks_agb/ab-gate","version":"0.0.1","license":"UNLICENSED","_id":"@57blocks_agb/ab-gate@0.0.1","maintainers":[{"name":"evanliu57","email":"evan@57blocks.com"}],"bin":{"ab-gate":"dist/cli.js"},"dist":{"shasum":"72f6f60e2b6a68bcb77a1a5f5734206a5a8e39a1","tarball":"https://registry.npmjs.org/@57blocks_agb/ab-gate/-/ab-gate-0.0.1.tgz","fileCount":222,"integrity":"sha512-ccx6FqY3OYP241bZEdcEbWknm2ctu+Qd++DZnW5Kc1fYt8Qa4g5wDrd9FtfF+s1+7fahXxyCNWJ7T6lMDVQObA==","signatures":[{"sig":"MEUCIAdKqwbDfzpdqqJqxwgif6/Yqgr1bG8H5faI7aQ8gdjuAiEAlvf9qosGJ/o/UAEgmU3WfGf73yfZjKRnwQNmK7YCrgE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1194086},"main":"./dist/index.js","type":"module","_from":"file:57blocks_agb-ab-gate-0.0.1.tgz","types":"./dist/index.d.ts","scripts":{"test":"vitest run --passWithNoTests","build":"tsc -b","typecheck":"tsc -b"},"_npmUser":{"name":"evanliu57","email":"evan@57blocks.com"},"_resolved":"/private/var/folders/nz/j1h1h9wd01sggb8x9jtbjzr00000gn/T/01b9466a6f5f880a2809bb5f69e1f823/57blocks_agb-ab-gate-0.0.1.tgz","_integrity":"sha512-ccx6FqY3OYP241bZEdcEbWknm2ctu+Qd++DZnW5Kc1fYt8Qa4g5wDrd9FtfF+s1+7fahXxyCNWJ7T6lMDVQObA==","_npmVersion":"11.16.0","description":"**确定性门禁 CLI —— 与任何 agent 无关。**","directories":{},"_nodeVersion":"24.18.0","dependencies":{"@57blocks_agb/ab-core":"0.0.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/ab-gate_0.0.1_1788141334895_0.6714409618008477","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@57blocks_agb/ab-gate","version":"0.0.2","license":"UNLICENSED","_id":"@57blocks_agb/ab-gate@0.0.2","maintainers":[{"name":"evanliu57","email":"evan@57blocks.com"}],"bin":{"ab-gate":"dist/cli.js"},"dist":{"shasum":"81ac9085a1fa951e9f9508514210c202a3308214","tarball":"https://registry.npmjs.org/@57blocks_agb/ab-gate/-/ab-gate-0.0.2.tgz","fileCount":231,"integrity":"sha512-jgeZEUkGvbhh1d47MQ37MExviYKWC8kHBHRH3gc7VRjxYolAp93zlcRPhCmwpu0f3SD0gMVviTW0CzMjUHXpkQ==","signatures":[{"sig":"MEQCIHB/2reeEM7djY66S909HrSlPB8asBlY7/bREaqApPzvAiA5i5Atiag2TkoBJb9RrNEcov+ibWzQ3MTgEBXECaZp/w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1258833},"main":"./dist/index.js","type":"module","_from":"file:57blocks_agb-ab-gate-0.0.2.tgz","types":"./dist/index.d.ts","scripts":{"test":"vitest run --passWithNoTests","build":"tsc -b","typecheck":"tsc -b"},"_npmUser":{"name":"evanliu57","email":"evan@57blocks.com"},"_resolved":"/private/var/folders/nz/j1h1h9wd01sggb8x9jtbjzr00000gn/T/78a9263aa7060f8c40bb466f427e01c0/57blocks_agb-ab-gate-0.0.2.tgz","_integrity":"sha512-jgeZEUkGvbhh1d47MQ37MExviYKWC8kHBHRH3gc7VRjxYolAp93zlcRPhCmwpu0f3SD0gMVviTW0CzMjUHXpkQ==","_npmVersion":"11.16.0","description":"**确定性门禁 CLI —— 与任何 agent 无关。**","directories":{},"_nodeVersion":"24.18.0","dependencies":{"@57blocks_agb/ab-core":"0.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/ab-gate_0.0.2_1788229869702_0.7393641171730447","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"@57blocks_agb/ab-gate","version":"0.0.3","license":"UNLICENSED","type":"module","main":"./dist/index.js","publishConfig":{"access":"public"},"bin":{"ab-gate":"dist/cli.js"},"dependencies":{"@57blocks_agb/ab-core":"0.0.3"},"scripts":{"typecheck":"tsc -b","test":"vitest run --passWithNoTests","build":"tsc -b"},"types":"./dist/index.d.ts","_id":"@57blocks_agb/ab-gate@0.0.3","description":"**确定性门禁 CLI —— 与任何 agent 无关。**","_integrity":"sha512-t3gpVwuW4UuQH6cizJTFzQcVu43oexgk9+1Xv7x8wBBCki0tQu0is5K5XgbMvlm2EKx5FgF/pc5FY3Ik2LZh3g==","_resolved":"/private/var/folders/nz/j1h1h9wd01sggb8x9jtbjzr00000gn/T/50c5ac92a9c55eee08c1b6d88a06d224/57blocks_agb-ab-gate-0.0.3.tgz","_from":"file:57blocks_agb-ab-gate-0.0.3.tgz","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-t3gpVwuW4UuQH6cizJTFzQcVu43oexgk9+1Xv7x8wBBCki0tQu0is5K5XgbMvlm2EKx5FgF/pc5FY3Ik2LZh3g==","shasum":"709887b6ea5bbc527c9ec1bdc92666d6ece00c51","tarball":"https://registry.npmjs.org/@57blocks_agb/ab-gate/-/ab-gate-0.0.3.tgz","fileCount":267,"unpackedSize":1485086,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICqqkCHr5egJBksVQ4x2eJPKQ1EnztvZV3Cp3khXThzPAiAxC98PpTU+LVHyoLZaoqhXfMGq1DkNC1BVfu9X8CZvPQ=="}]},"_npmUser":{"name":"evanliu57","email":"evan@57blocks.com"},"directories":{},"maintainers":[{"name":"evanliu57","email":"evan@57blocks.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ab-gate_0.0.3_1788494261932_0.7514042267297008"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-31T01:55:34.707Z","modified":"2026-09-04T03:57:42.302Z","0.0.1":"2026-08-31T01:55:35.055Z","0.0.2":"2026-09-01T02:31:09.897Z","0.0.3":"2026-09-04T03:57:42.126Z"},"license":"UNLICENSED","description":"**确定性门禁 CLI —— 与任何 agent 无关。**","maintainers":[{"name":"evanliu57","email":"evan@57blocks.com"}],"readme":"# ab-gate\n\n**确定性门禁 CLI —— 与任何 agent 无关。**\n\n不管代码是 Claude Code 写的、Codex 写的还是人手写的，只要往仓库里提交就必须过。\n**门禁的基线强度不依赖任何 agent 的配合。**\n\n## 装\n\n```bash\npnpm exec ab-gate init            # 客户项目\npnpm exec ab-gate init --internal # 内部项目，全量采集\n```\n\n> **为什么是 `pnpm exec` 而不是 `npx`。** `npx` 在本地找不到这个 bin 时会**去 registry\n> 下载一个同名的包然后跑它** —— 而 `ab-gate` 这种短名字谁都能在 npm 上注册。\n> 同一套包里 `agb` 那个名字**已经是别人的了**（`agb@0.0.0`，与我们无关）。\n> `npm exec --no` 也拦不住（实测仍然打 404，说明它去过 registry）。\n>\n> 用 npm / yarn 的话，只看本地的写法是：写进 `package.json` 的 scripts，\n> 或直接敲 `./node_modules/.bin/ab-gate`。\n\n装三样：`.abrc.json`、`.git/hooks/pre-commit`（门禁）、`.git/hooks/post-commit`（采集）。\n\n```bash\npnpm exec ab-gate stack   # 先核对栈探测对不对 —— 探错了在 .abrc.json 的 stack 里覆盖\npnpm exec ab-gate check   # 跑门禁（默认只查 git 变更集，--all 全量）\npnpm exec ab-gate smoke   # 加跑 runtime 级（起服务 + HTTP 探活）\npnpm exec ab-gate list    # 看已注册的 gate\npnpm exec ab-gate report  # 聚合采集数据\n```\n\n`ab-gate init` 之后**第一件事是跑 `stack`**：探测错的适配器比没有适配器更糟，\n装完就核对一次，比等误报出现再回头查便宜得多。\n\n## 三级严重度\n\n| 级别 | 行为 | 数量 |\n|---|---|---|\n| `hard` | 阻断提交，退出码 1 | **5 条**（编译挂 / 构建挂 / schema 变更无 migration / schema 自动同步 / 未答的阻塞问题） |\n| `partial` | 驱动一次有界修复，**不阻断** | 绝大多数 |\n| `info` | 只写 JSONL | 命名/编号类 |\n\n这是防「门禁太严 → 同事 `--no-verify` 关掉」的核心机制：\n**一个误报最多代价是一次范围内的修复。**\n\n第 5 条与前四条不同：前四条判的是机器能看出来的失败，它判的是**人自己声明的\n阻塞**（`.ab/questions.json` 里写了 `blocks` 又没写 `answer`）。判据全部来自\n手写数据，所以误报率结构性为零 —— 不想被挡就写 `blocks: []`。\n\n五条 hard 里的「构建挂」落在**提交之后**：它是 `kind=build`，CI / `ab-gate build` /\nab-run 的交付判定跑，pre-commit 不跑。理由是同一条 —— 让每次提交等一分钟的门禁\n会被关掉，而被关掉的门禁强度是零。编译挂秒级，值得在提交点付；构建挂分钟级，\n它的自然拦截点在交付前而不是提交前。要让它也进 pre-commit：`AB_GATE_BUILD_ON_COMMIT=1`。\n\n因触发点没跑的 gate 会在结果行下面单独列出来 —— `hard=0` 和「这条 hard 本次\n没跑」长得一样，含义相反。\n\n## 与技术栈解耦\n\n判定逻辑与栈无关，栈的事实进适配器注册表：\n\n```\ngate（判定，与栈无关）→ 问 StackProfile → 由适配器表回答「这个栈里 X 长什么样」\n```\n\n首批：13 种语言 · 11 个前端框架 · 19 个后端框架 · 18 个数据层 · 8 种编译工具链 ·\n7 种模型形状。加一门语言 = 表里加一行，不改任何 gate。\n\n**探测不到 → gate 返回空。** 不猜、不降级、不报「可能有问题」——\n幻觉线索比没有线索更贵（v1 真实事故：按 tier 推断目录，在一个 RN monorepo 上\n报出「21 个端点全部未接线」，而那个 app 真真切切在调其中 16 个，\n修复循环把预算烧在了一个无关实体上）。\n\n`ab-gate list` 会把「哪些 gate 因为探不到对应栈而不跑」显示出来 ——\n**「没检查」必须可见，不能伪装成「检查通过」。**\n\n## 三种触发时机\n\n| kind | 什么时候跑 | 为什么 |\n|---|---|---|\n| static（默认） | 所有触发点，含 pre-write hook | 纯静态扫描，毫秒级 |\n| `[slow]` | git / CI（hook 里跳过） | 要起子进程（tsc），秒级 |\n| `[runtime]` | 只有 `ab-gate smoke` | 要把应用启起来 |\n\nhook 每写一个文件都会触发。在那里跑 tsc 会让人第一天就卸插件 ——\n而门禁强度不受影响：那条 hard 在 git pre-commit 上照样跑。\n\n## 采集\n\n两个 hook 职责相反：\n\n| hook | 干什么 | 失败时 |\n|---|---|---|\n| `pre-commit` | 跑门禁 | **阻断提交** |\n| `post-commit` | 记录人对 agent 产出的修正 | **吞掉** —— 提交已经发生，采集不能反过来影响它 |\n\n脚本本体在 `hooks/`，随包发布，`init` 装的就是这两份 —— 改哪份，装上的就是哪份。\n\n「人工修正」的判定口径：*一次人类提交改动了某个文件，而该文件上一次提交是\nagent 提交*。agent 提交的判据是 `Co-authored-by:` 尾注，\n在 `.abrc.json` 的 `agentCommitRe` 里可改。口径的**已知偏差**写在\n`src/lib/corrections.ts` 里 —— 那是给读数据的人看的，不是给写代码的人看的。\n\n## 关掉某条\n\n```jsonc\n// .abrc.json\n{ \"disabled\": [\"ctx-state-shape\"], \"severityOverrides\": { \"no-raw-http\": \"info\" } }\n```\n\n每条 gate 也认自己的 `AB_GATE_*=0` 环境变量，用于临时排查。\n\n## 相关文档\n\n- [`docs/PLAN.md`](../../docs/PLAN.md) §3 严重度 · §4.5 栈适配器 · §8 采集\n- [`docs/PORTING.md`](../../docs/PORTING.md) 每条 gate 的 v1 出处与偏离\n","readmeFilename":"README.md"}