Skip to content
SuperMarioYLPublic

About

面向工程团队的编码智能体复用闸门,每个新建文件和符号都必须先给出可核验的复用理由

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

English | 简体中文

ReuseGate — 每个新文件都必须向现有代码库证明自己

ReuseGate

ci python license

面向工程团队的编码智能体复用闸门:每个新建文件和符号,都必须先给出可核验的复用理由。

你的 Coding Agent 每天都在往仓库里塞没人要求的新文件。ReuseGate 把「懒即美德」类 Skill 从一句提示词升级成机器可核验的闸门:Agent 在新建任何文件、符号或服务之前,必须先对照现有 能力清单给出理由,而每一条理由都会留下可审计的记录。

为什么需要一道闸门

让 Agent「少写代码」的提示词和 Skill 已经很流行,但提示词只能施加压力,无法核验:Agent 答应了「先找现有的」,没有任何机制检查它是否真的找了。事后扫描器(查重、AI slop 检测) 能在合并后发现重复,但那时冗余代码已经落盘,反馈回路永远慢一步。

ReuseGate 把检查放进写入发生之前的那个瞬间:

  • 计划时拦截 — Claude Code 的 PreToolUse 钩子在 Write / Edit 落盘前调用闸门;
  • 机器可核验 — Agent 必须用一行 # reusegate: 路径:符号 引用清单里的现有能力, 闸门核验该引用真实存在、且排名在最近候选的前 k 名之内,否则记为 unjustified;
  • 只警告、不阻断 — 闸门永远返回 allow(v0.1 不阻断任何写入),需求文本随决策 一起回给 Agent,由 Agent 自己决定改为扩展现有模块;
  • 全程留痕 — 每次尝试(无论通过与否)都追加进 .reusegate/justifications.jsonl, 变成评审时读得懂的记录。

匹配完全确定性:归一化名称等价、rapidfuzz 相似度、token 指纹重叠。闸门内部没有 大模型、没有向量检索、没有网络请求——可解释、可复现、可调阈值。

ReuseGate 架构:Claude Code 钩子 → gate.py → 能力清单 / 需求文本 / 台账

十分钟上手

前提:Python 3.12+,一台装了 uv 的机器(pipx 同样可用)。

1. 安装 CLI

git clone https://github.com/SuperMarioYL/reusegate
cd reusegate
uv tool install .          # 之后 reusegate 在 PATH 上;pipx install . 亦可

2. 在你的仓库里建能力清单

$ cd your-repo
$ reusegate scan
reusegate: 49 files, 832 symbols (py 49) -> .reusegate/inventory.json

10k 行的示例仓库实测 0.2 秒完成扫描(tree-sitter 解析,Python / TypeScript / Go)。 想先看看效果,可以用 python3 docs/make_demo_repo.py /tmp/demo-repo 生成一个 10k 行 的样例仓库。

3. 把钩子接进 Claude Code

$ reusegate install claude-code
reusegate: PreToolUse hook wired in .claude/settings.json

这一步往仓库的 .claude/settings.json 写入 PreToolUse 钩子(matcher Edit|Write|MultiEdit|NotebookEdit),已有配置原样保留,可重复执行。

4. 让 Agent 正常干活

给 Agent 一个普通任务,比如「加一个日期格式化辅助函数」。当它伸手去写一个全新的 utils/format_date_v2.py 时,钩子在 Agent 循环内打断,给出机器核验过的要求(下面是 真实输出):

permissionDecision: allow
reusegate: before creating the new file `utils/format_date_v2.py`, cite the nearest
existing capability and justify create-vs-extend.

Nearest capabilities already in this inventory:
  1. src/time_utils.py:format_date  def format_date(raw: str, *, limit: int = 10) -> str  (score 65.0)
  ...

If you are extending an existing capability, add a citation header to the file instead
of creating a duplicate:

  # reusegate: src/time_utils.py:format_date

Agent 引用现有能力后再次尝试,闸门核验通过:

reusegate: justification accepted — `src/time_utils.py:format_date` ranks #1 within the
top-5 nearest (score 64.98).

于是它改为扩展现有的 src/time_utils.py,而不是新建重复文件。

5. 看报告

$ reusegate report               # 最近一次会话的尝试计数与全部理由记录
$ reusegate report --inventory   # 每个目录的能力计数

不装 Claude Code 也能直接体验钩子——事件 JSON 走 stdin,决策 JSON 走 stdout:

printf '%s' '{"tool_name":"Write","tool_input":{"file_path":"utils/format_date_v2.py","content":"def format_date(raw):\n    return raw.split(\"T\")[0]\n"}}' \
  | reusegate hook claude-code

演示:同一个任务,闸门关 vs 闸门开

同一份 10k 行样例仓库、同一个「加日期格式化」任务跑两遍。闸门关:Agent 自由发挥,留下 3 个新文件、2 个新符号、0 条记录。闸门开:0 个新文件,改为扩展现有符号,留下 2 条读得懂 的理由记录。完整录制见 assets/demo.cast(asciinema 格式,约 22 秒):

asciinema play assets/demo.cast    # 或直接阅读下面这段真实输出

reusegate report --delta baseline.json after_off.json after_on.json 的真实输出:

┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┓
┃ metric              ┃ gate OFF ┃ gate ON ┃
┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━┩
│ new files           │        3 │       0 │
│ new symbols         │        2 │       0 │
│ extended symbols    │        0 │       1 │
│ justified records   │        0 │       1 │
│ unjustified records │        0 │       1 │
└─────────────────────┴──────────┴─────────┘

gate OFF — new files
  + utils/compat_shim.py
  + utils/date_extra.py
  + utils/format_date_v2.py
gate OFF — new symbols
  + utils/date_extra.py:days_between
  + utils/format_date_v2.py:format_date
gate ON — extended symbols
  ~ src/time_utils.py:format_date

想复现:python3 docs/make_demo_repo.py <目录> 生成样例仓库,assets/demo.tape 是这次录制的逐条命令脚本(重新录制: asciinema rec --overwrite --output-format asciicast-v2 --window-size 110x34 -c "bash assets/demo.tape" assets/demo.cast)。

五个阶段:scan → install → gate → cite → report

它如何判定「有理由」

一次写入能否通过,由四条确定性规则决定,没有自由发挥的空间:

  1. 没有引用 → unjustified(内容里找不到 reusegate: 引用行);
  2. 引用不存在 → unjustified(清单里没有那个路径或符号);
  3. 引用存在但排名在 top-k 之外 → unjustified(所引能力与要写的东西并不相近);
  4. 引用存在且排名在前 k(默认 k=5)→ justified。

匹配信号只有三个,全部确定性:归一化 token 等价(format_date_v2 与 format_date 的 token 集合相同,因为 v2 这类重复标记会被剥掉)、rapidfuzz 名称相似度、 名称 + 签名的 token 指纹 Jaccard 重叠。v0.1 的目标恰恰是先量化误报率:台账里每一条 unjustified 都可以人工复核,为后续阈值调优提供依据。

边界与已知限制:

  • 仅警告:v0.1 永不阻断写入;闸门返回 allow,需求文本放在 permissionDecisionReason 里随决策回传;
  • 语言:Python、TypeScript(含 TSX)、Go 的顶层函数 / 类 / 方法;
  • 清单是本地的:.reusegate/ 只在你的仓库里,闸门运行时无任何网络请求;
  • 清单会过期:代码大改后重新 reusegate scan 即可(亚秒级)。
ReuseGate 集成面:CLI 命令、语言、产物

在现有工作流里的位置

环节 提示词 / Skill 事后扫描器 计划时闸门(ReuseGate)
介入时机 任务开始前 写入 / 合并之后 写入发生前的那个瞬间
核验方式 无(靠 Agent 自觉) 检测已落盘的重复 对照清单核验引用
输出 改变了对话语气 问题清单 可审计的理由台账
能否扭转 Agent 行为 间接 不能(代码已存在) 能(Agent 仍在循环里)

这不是「又一个查重工具」:查重回答「哪里重复了」,ReuseGate 回答「这次新建有没有理由」。

路线图

  • v0.1 — scan 能力清单(py / ts / tsx / go)、install claude-code、 PreToolUse 钩子、report 会话 / 目录 / OFF-vs-ON 报告、51 个测试、CI
  • v0.2 — 用真实台账调优阈值;误报率达标后引入可选的硬阻断模式
  • 更多入口 — Cursor / Gemini CLI 适配器、git hook、CI 模式
  • 团队版 — 多仓库台账聚合、组织级复用看板、CI 策略(见下)

付费

ReuseGate 采用 自托管开源核心 + 团队版授权 的形态:

  • 开源核心(本仓库,MIT):单仓库的清单、闸门与台账,功能完整,数据不出你的内网—— 闸门运行时本身无任何网络依赖。
  • 团队版(试点中):面向 5–50 人工程团队的多仓库台账聚合、组织级复用看板、 CI 级策略(例如「未给出理由的新文件使 CI 失败」)。按座订阅,¥1,500/座/年 (前十个试点团队享创始人折扣,签授权文件即可,无授权服务器)。

想加入试点:在 Issues 里开一个标题 带 [team-pilot] 的帖子,附上你们当前的 Agent 栈描述即可。

开发

git clone https://github.com/SuperMarioYL/reusegate && cd reusegate
uv venv && uv pip install -e .[dev]
.venv/bin/pytest -q              # 测试
.venv/bin/ruff check src tests   # lint

发布流程:更新 VERSION 与 CHANGELOG.md,打 vX.Y.Z 标签推送,Release 工作流会把 wheel + sdist 构建进 dist/ 并附 sha256 校验和。

许可证

MIT © 2026 SuperMarioYL

MIT © 2026 SuperMarioYL

About

面向工程团队的编码智能体复用闸门,每个新建文件和符号都必须先给出可核验的复用理由

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages