内容
# paranoia-local
本地MCP服务器,对您的代码变更和计划提供**冷的、对手性的第二意见** —— 来自**另一个**前沿编码代理,在其独立的订阅上运行,对您的仓库具有**完全的读取权限**。
将其安装到Claude Code中,代码审查由Codex(GPT-5.6)执行。将其安装到Codex中,代码审查由Claude Code(Fable 5)执行。MCP服务器只是它们之间的通道。
一个工具具有不同的形态:[`arbitrate`](#arbitrate--deciding-not-reviewing) 不进行审查,而是**做出决定** —— 它让两个供应商同时运行,相互竞争,并计算出判决。
```
┌──────────────┐ "paranoia: critique this branch" ┌──────────────┐
│ Claude Code │ ───────────────────────────────────► │ paranoia-local│
│ (your work) │ │ (MCP, local)│
└──────────────┘ └──────┬───────┘
│ codex exec (read-only, your repo)
┌──────▼───────┐
│ Codex / GPT-5.6│ ← reads the whole repo,
│ cold reviewer │ decides what to open
└──────────────┘
```
## 为什么
Claude(或Codex)可以审查自己的工作,但它会带着相同的偏见进行审查,这些偏见是它自己编写的。而**不同的**模型具有**新鲜**的上下文,可以提供真正独立的第二意见。该工具将这些功能封装成一个MCP调用。
与仅看到组装后的有效载荷的API密钥审查者相比,本地代理审查者更**强大** —— 它拥有**整个**仓库和git历史,并且可以自行决定读取哪些内容。它会打开调用站点,跟踪影响范围,检查测试和配置文件,并读取git历史记录 —— 而这些是仅限于差异的审查者无法做到的。
- **更强大** — 它拥有整个仓库和git历史,并且可以决定读取哪些内容。
- **更便宜** — 它在您现有的ChatGPT / Claude **订阅**上运行,而不是按米计费的API令牌。
- **更安全** — 审查者以只读方式运行(Codex的OS沙箱;Claude的只读工具允许列表),在临时git工作树中,因此它无法触及您的工作。
## 工具
| 工具 | 功能 |
|---|---|
| `critique_branch` | 对git分支/差异或脏工作树的对抗性审查。五部分审查(有效/无效/风险/空白/改进)带有`[BLOCKER]`/`[MAJOR]`/`[MINOR]`/`[OUT-OF-SCOPE]`标签。 |
| `critique_plan` | 对计划或设计文档的对抗性审查。带有`repo_path`,审查者读取实际代码以测试计划关于当前行为的假设 —— 一个建立在错误假设上的计划是最危险的。 |
| `query` | 快速双重检查一个事实或点。不完整的审查 —— 较低的推理努力,直接答案带有引文和置信度。 |
| `rebut` | 争议特定发现。恢复**相同**的审查会话,并附上您的反证据;它会让步或持有新的引文。比冷重新一轮更便宜、更高分辨率。 |
| `arbitrate` | 在2-4个选项之间做出决定。**两个**引擎独立冷判断,相互竞争,选择一个固定的快照;Python计算判决。详见下文。 |
每次审查都在其页脚返回一个`session_ref` —— 将其传递给`rebut`。
## `arbitrate` — 做出决定,而不是审查
其他四个工具为您提供第二意见。`arbitrate`为您提供一个**决定**:您给它2-4个选项,它在`CONVERGED`时返回,只有当两个前沿供应商独立判断并选择相同的选项,并且有理由引用它们各自的理由。
```json
{
"name": "arbitrate",
"arguments": {
"repo_path": "/Users/you/Work/my-project",
"decision": "选择 position-size 阈值的数字类型。",
"options": [
{"id": "opt-float", "statement": "将其存储为浮点数。"},
{"id": "opt-decimal", "statement": "将其存储为十进制数。"}
],
"stakes": "内部 CLI,单个团队,仅在日志行中使用。",
"files": [{"path": "scripts/lib/registry.py", "reason": "编写者"}]
}
}
```
发生的事情,以及每一步的原因 —— 决策工具仅在**独立性**方面具有价值,因此大部分机制都用于防止两个供应商因其他原因达成一致:
1. **一个快照。** 工作树被固定在一个提交上,每个决策者都有自己的工作树,以便它们可以在同一个固定的树上自由搜索。Git **历史记录**仍然是活跃的 —— 工作树附加到您的实际仓库中 —— 因此服务器会在运行前后消化每个引用和引用日志,如果有任何移动,则返回`FAILED`,而不是报告无法描述的协议。
2. **消除歧义。** 由Opus代理消除偏见 —— 消除倡导,平等选项 —— 然后由**另一个供应商**按字段进行验证,确保不会引入任何偏见。
3. **平衡的呈现。** 一个决策者按规范顺序查看选项,另一个决策者按相反顺序,并在**不透明的决策者标签**下,以便您的排序或ID不会泄露。两个决策者都不知道另一个决策者的存在。
4. **Python计算判决。** 没有模型对判决进行仲裁。
5. **在分歧时,** 一轮协调只会进行`path:line`引用和服务器本身读取的字节 —— 从不另一个模型的文本 —— 并且只有在有真正的新证据时才会进行。
### 结果
| 结果 | 含义 |
|---|---|
| `CONVERGED` | 一致,无阻塞,每个投票都有一个有争议的引用。 |
| `BLOCKED` | 他们同意一个选项,其中一个选项标记为`[MAJOR]`/`[FATAL]`。 |
| `REFRAME_REQUIRED` | 决策者提出了一个更好的未列出的选项。赋予它一个ID并重新运行。 |
| `UNRESOLVED` | 仍然存在分歧,或者协议没有被任何人证实,或者有分歧但没有新的内容需要协调。 |
| `FAILED` | 预检、清理、解析或仓库引用在运行过程中移动。 |
回复以机器可读的尾部结束,其字段始终存在:
`ARBITRATION`, `SELECTED`, `ADVISORY`, `AUTHORITY-POLICY`, `CLEANING`, `SNAPSHOT`, `ORDER-SEED`, `REFS-MOVED`, `AUDIT`, `ROUNDS`.
### 塑造输入
在任何花费之前,都会检查框架是否符合数值边界,而一个形状自然会符合这些边界:
> 将每个共享事实和**特定选项的完整规范**放入`context` —— 前缀为“如果采用拟议的规则”。将每个选项语句限制在它采用的内容和结果上。
原因在于结构。“采用X,并具有此优先顺序和不变性”比“不采用”具有更多的机制,因此以明显的方式编写的作用范围决策会因构造而破坏均衡绑定 —— 缩短较长的选项只会删除决策者需要的规范。
### 在依赖它之前需要知道的事情
- **必须安装两个CLI。** 与审查工具不同,`arbitrate`驱动`codex` **和** `claude`,无论您将服务器安装到哪个服务器。没有单一供应商模式:针对一个供应商的两次轮询不是仲裁。
- **`ADVISORY`不会阻塞。** 每个决策者报告他们是否认为人类所有者应该授权该决策。报告后者,但**不阻塞** —— `CONVERGED`带有`ADVISORY: human-owner`仍然是`CONVERGED`。强制执行是您的政策,而不是工具的政策。
- **从未改变其主意的供应商不会被要求引用另一个供应商的证据。** 在第二轮中,携带证据的要求仅适用于其选择**更改**的供应商 —— 这就是它的用途,因为放弃是更改。为保持原位且从未在第一轮中证实的供应商只需要一个解决的引用,**前提是第一轮的决定性引用也解决了**;在第一轮中根本没有证实的保持者必须像移动者一样以获得的证据为基础。
### 趋同环
`critique_branch`和`critique_plan`接受一个`already_raised`数组:一个带有行号和文件路径的单行声明,已经从前几轮中接受。审查者被告知不要重述它们,而要寻找他们遗漏的内容。驱动循环从调用者 —— 从调用者生成一个新的审查,每轮都提供越来越大的`already_raised`列表 —— 直到发现收敛或降噪。(永远不要粘贴审查者的文本;只需重复的声明 + 引用。)
**两个校准杠杆使循环保持比例并终止** —— 根据需要为每轮调整它们(它们存在,因为未经校准的冷审查者默认为最大妄想,并且会针对20+轮制造边际/硬化发现):
- **`stakes`** — 实际部署上下文/威胁模型/规模(例如,“单个用户本地CLI,信任输入,无多租户”)。审查者将其视为**合法关注边界**:假设的发现者、规模或故障模式超出此范围的,将被丢弃或标记为`[OUT-OF-SCOPE]`,而不会被强制修复。省略它,审查者会假设一个**适中的内部工具**,而不是一个敌对的/高规模的服务。**在`.paranoia.toml`中为每个项目设置一次**;按需覆盖以收紧。这是减少范围扩大性的单个最高杠杆。
- **`round`** — 基于1的循环轮次。**每冷轮递增**。在`round >= 3`时,审查者仅报告阻止合并的作用域发现(`[MAJOR]`或更高),并且在没有剩余发现时在五部分格式中说`CONVERGED`。
操作员配方:在`.paranoia.toml`中设置`stakes`,然后循环`already_raised` + `round`(1, 2, 3, …)。**当计算出的`CONVERGENCE:` trailer显示`NOT-BLOCKED`并且轮次返回`CONVERGED`或仅`[OUT-OF-SCOPE]`/`[MINOR]`项时停止** — trailer控制,当它显示`BLOCKED`时,审查者的`CONVERGED`无效(参见下面的类闭包)。折叠`[FATAL]`/作用域`[MAJOR]`发现;单独记录`[OUT-OF-SCOPE]`发现,而不是扩大设计以修复它们。
**两个信号表明循环出错,都是通过实践总结出来的:**
- *相同的缺陷不断重新出现,具有新的措辞。* 您正在修复实例,而不是类。那就是类闭包的作用,以防止这种情况发生。
- *发现不再关注您的差异,而是关注想象中的输入。* 权益不对,代码不正确。收紧`stakes`并重新运行该轮,而不是整合它引发的内容。
### 类闭包(`class_closure`,**默认开启**,适用于`critique_branch`)
一个收敛循环,每轮报告一个缺陷实例,可以运行十轮,而单个不变式一直被违反 —— 每轮,操作员修复命中的站点,而下一轮发现一个兄弟节点。该协议没有地方放置**类**:发现是`file:line`形状的,`already_raised`告诉审查者不要再查看那里,并且第3轮严重性地板计量泄漏到每轮一个实例。
启用类闭包后,审查者会以 **类注册表** 结束审查:对于每个缺陷类,不变式,严重性和 **正则表达式以匹配仅违规** (或`PROCEDURE`,当正则表达式无法表达它时)。然后服务器:
- **每轮重新运行每个注册的谓词**,针对审查快照 — `git grep -l -z` 决定,因此二进制blob中的违规行为仍然算数;
- **将存活的匹配项** 注入下一个数据包,**在`already_raised`之后**,并具有明确的优先级;
- **用Python计算判决** 并追加:
```
LINEAGE: 9f2c1a4b0e77 (记录了8轮)
CLASS-REGISTER: 解析 1
CLASS-CLOSURE: 1 open, 2 closed, 3 surviving matches, 0 exempt, 1 unmechanized
CONVERGENCE: BLOCKED — 1个未关闭的类(es):
3f2a91c4 每个打开状态都必须在v2打开集中(机械化:3个匹配(es))
```
当类的谓词返回**零匹配**时,类关闭,并在它再次匹配时重新打开。只有`BLOCKER`/`MAJOR`类会阻塞;`MINOR`和`OUT-OF-SCOPE`类被跟踪并提供建议,因此该机制不会陷入边际发现的困境。
**它不做什么。** 它保证了**注册**的类的持久性。审查者发现了一个类却没有注册它,与从未发现它的人无法区分,因此没有任何解析空间 — 因此,审查文本中没有被解析的内容。`NOT-BLOCKED`因此仅表示“没有未关闭的阻塞类”,永远不会表示更改是正确的。
#### 处理循环
**您无需执行任何操作来启用此功能。** 像之前一样运行 `critique_branch`,并递增 `round`。您唯一需要做的新事情是 *读取 trailer 而不是 review 自身的 `CONVERGED`* — 当两者不一致时,trailer 会指示并说明原因。
当一个循环返回 `BLOCKED` 时,您有三种合法的应对措施:
1. **修复剩余的匹配项。** 它们在类下列出,格式为 `path:line: text`。
这是正常情况,也是整个功能的重点。
2. **豁免一个误报的正则表达式** — 谓词匹配了一行实际上并不违反不变性的行。
3. **请求下一个审阅者纠正类** — 如果严重性错误,谓词错误,或者一个非机械化的类确实已关闭。您不能自己执行此操作;请参见下文 *Corrections are the reviewer's*。
**豁免一个匹配项。** 直接复制区块中的三个字段:
```jsonc
// 区块内容: 3f2a91c4 → src/app.py:17: legacy_open(state)
{
"repo_path": "/path/to/repo", "round": 4,
"exempt": [{
"class_id": "3f2a91c4",
"path": "src/app.py",
"line": 17,
"line_text": " legacy_open(state)" // 原样,包括缩进
}]
}
```
`line_text` 必须精确到字节:豁免是根据它进行密钥生成的,**如果该行发生任何变化,它就会失效**,因此匹配项会重新浮现,您需要重新豁免它。这种设计是故意的 — 它倾向于阻塞,而不是倾向于静默解除警报。每个豁免都会显示给后续审阅者,并附上不变性和谓词,以便提出异议。`unexempt` 使用相同的 `class_id`/`path`/`line`,并撤销一个。
二进制 blob 中的匹配项(`binary match (line not shown)`)**无法豁免** — 没有行或文本可以作为密钥。相反,请缩小谓词的 `PATHSPEC`。
**纠正由审阅者负责,而不是您。** 错误的严重性、过宽或无法运行的谓词,以及已关闭但又重新出现的非机械化类,都由下一个**冷启动审阅者** 通过发出寄存器转换 — `RECLASSIFY`、`SUPERSEDE`、`CLOSED`、`REOPEN` 来修复。这是故意的:它保持每个逃逸都是有记录的对抗性判断,而不是操作员自行决定覆盖阻塞器。实际上,您可以提示审阅者这样做,例如通过 `focus`:
> “类 3f2a91c4 注册为 MAJOR,但其影响是化妆品 — 如果您同意,请重新分类。 类 91b0e77d 的模式也匹配一致的调用站点;如果您可以编写一个更窄的模式,请替换它。”
审阅者会看到确切的语法;您不需要引用它。
**您可能会遇到的其他 trailer 行。**
| 行 | 含义 | 操作 |
|---|---|---|
| `CLASS-CLOSURE-WARNING: … closed in the round it was registered` | 谓词从一开始就匹配不到任何内容 — 通常是太过狭窄,无法捕捉到它所描述的内容 | 请求下一个审阅者 `SUPERSEDE` 它,或确认它确实已经修复 |
| `BLOCKED — register debt from round N` | 两次尝试解析寄存器失败 | 无:下一个带有良好寄存器的循环将清除它 |
| `CLASS-REGISTER: NONE` vs `parsed 3` | 没有类/转换 vs 已接受三个记录 | 无 — `NONE` 在干净的循环中是正常的 |
| `unmechanized: awaiting reviewer CLOSED or RECLASSIFY` | 一个语义类无法被正则表达式检查 | 它会在审阅者判断它关闭之前阻塞 — 当您认为它关闭时,请提示 |
| `STATE-UNAVAILABLE` | 行动状态无法读取、写入或前一轮的写入可能未完成 | 消息会显示绝对路径。请修复或删除该文件,然后重新运行 |
`STATE-UNAVAILABLE` 的恢复是手动的:自动启动一个新的行动会丢弃每个跟踪的类,然后报告 `NOT-BLOCKED`,将存储故障转为假阳性。
**状态存储位置。** `~/.paranoia/lineages/<id>.json`,由存储库 + `base_ref` + 审查分支键控。**固定且独立于 `--log-dir`**,后者仅是审计日志目录 — 从日志目录派生它意味着操作员在静默移动日志时,会得到一个空的行动记录。`PARANOIA_STATE_ROOT` 重新定位它。trailer 始终打印 `LINEAGE: <id> (记录的循环:N)`,因此如果 `N` 与预期不符,则循环已静默分离 — 通常是因为 `base_ref` 或分支在循环中更改。请传递 `lineage` 以显式固定;当审查的引用不是分支(分离的 HEAD 或原始提交)时,需要这样做。
**设置。** `class_closure` 是一个调用参数和 `.paranoia.toml` 键(默认为 `true`);`lineage`、`exempt` 和 `unexempt` 仅为调用参数。`class_closure: false` 完全恢复了以前的行为 — 没有 trailer,不写入状态。
完整的设计、其背后的十六个计划审查循环以及针对实现的八个代码审查循环:
[`docs/class_closure_plan.md`](docs/class_closure_plan.md)。
### 收敛包模式(`converge`,**默认启用**)
每个冷启动循环都会重新收集相同的方向 — 重新读取已触摸的文件并重新运行 `git`,这会增加每次循环的成本。因此,`critique_branch` 默认在 **收敛模式** 下运行(通过传递 `converge: false` 或在 `.paranoia.toml` 中设置它来恢复旧版就地审查)。在收敛模式下,服务器**预先收集一个确定性的证据包**(审查快照中的每个已触摸文件的完整内容 — 二进制/大文件会被标记而不是嵌入 — 以及差异),并将其与审查者一起提供一个包感知提示,以便审查者验证而不是重新收集。审查是在**物质化工作树** 中运行的,该工作树是在请求时捕获的快照,因此证据是一个一致的时间点视图,后续的实时编辑无法扰乱,并且 `already_raised` 总是受包预算(`max_packet_chars`,默认为 400k)的保护。确定性和按需 — 没有持久的会话或句柄;独立于审查引擎。(端到端节省是计划验收基准测试的对象;该机制消除了收集步骤,但请将幅度视为有待该测量值。)
## 安装
### 先决条件
- Python 3.11+
- `git` 在 `PATH` 上
- 审查代理的 CLI 已安装并在订阅上登录:
- [Codex CLI](https://developers.openai.com/codex)(`codex`,≥ 0.144)并使用 ChatGPT 计划登录
或
- [Claude Code](https://code.claude.com)(`claude`)并使用 Claude 计划登录。
- **`arbitrate` 需要两个**,无论您将其安装到哪个供应商,都需要:
- 两个审查工具仅需要另一个代理的 CLI,如上所述。
### 安装服务器
```bash
git clone https://github.com/subvertnormality/paranoia-local
cd paranoia-local
pip install -e .
```
这会在您的 `PATH` 上安装一个 `paranoia-local` 可执行文件 — Claude Code 和 Codex MCP 条目都会启动该可执行文件。
### 连接到 Claude Code(评论由 Codex 执行)
```bash
claude mcp add paranoia -- paranoia-local --engine codex
```
添加到您的 `~/.claude/CLAUDE.md` 中,以便仅在请求时才使用它:
```
在未明确要求对抗性审查、批评或第二意见时,请勿调用 paranoia MCP 服务器。
```
### 连接到 Codex(评论由 Claude Code 执行)
注册服务器(这会将 `[mcp_servers.paranoia]` 表写入 `~/.codex/config.toml`):
```bash
codex mcp add paranoia -- paranoia-local --engine claude
```
然后 **您必须添加超时键** — `codex mcp add` 不会设置它们,而默认值太低。编辑 `~/.codex/config.toml` 以使条目读取:
```toml
[mcp_servers.paranoia]
command = "paranoia-local"
args = ["--engine", "claude"]
# REQUIRED: 一个代理审查涉及许多工具使用转折,并且运行数分钟。
# Codex 的默认 MCP 工具超时时间为 60 秒,启动时间为 10 秒,这会中止每次审查。
# 给工具一个小时和 30 秒的启动时间。
tool_timeout_sec = 3600
startup_timeout_sec = 30
```
验证它生效:
```bash
codex mcp get paranoia
# tool_timeout_sec: 3600
# startup_timeout_sec: 30
```
> **超时陷阱。** 完整的审查涉及许多工具使用转折,并且可能需要几分钟。
> Claude Code 的标准输入输出 MCP 空闲超时时间(~30 分钟)开箱即用;
> **Codex 默认超时时间为 60 秒** (`tool_timeout_sec`) 和 10 秒启动超时 (`startup_timeout_sec`),
> 并且两者都必须如上所示提高,否则每次审查都会失败。 3600 秒是一个慷慨的上限 —
> 单次审查时间为数分钟,多轮收敛循环是单独的调用,每个调用都在限制下,远低于该限制。
> 对于非常大的存储库,请进一步提高。
## 用法
在 Claude Code 中:
> “使用 paranoia 在 main 分支上审查此分支。意图:在 `withdraw()` 中添加透支保护。”
代理调用:
```json
{
"name": "critique_branch",
"arguments": {
"repo_path": "/Users/you/Work/my-project",
"base_ref": "main",
"head_ref": "HEAD",
"diff_intent": "Add overdraft protection to withdraw()."
}
}
```
## 每个存储库的默认值 — `.paranoia.toml`
在存储库根目录中放置一个 `.paranoia.toml` 文件,以便调用者停止重复输入上下文。顶级或 `[paranoia]` 下的键。优先级:**调用参数 > `.paranoia.toml` > 内置默认值**。
```toml
project_summary = "A booking API. Python/FastAPI, Postgres. Auth via short-lived JWTs."
base_ref = "develop"
web_search = true # allow external methodology/library cross-checks
isolate = true # review inside a throwaway worktree
# stakes: the deployment reality the reviewer must stay proportionate to (see
# "Convergence loop"). Set once here so every review is calibrated to the project.
stakes = "Internal booking API, single team, authenticated first-party callers, ~1k req/min."
# model / effort overrides also honoured
```
## 常见参数
四个审查工具接受:
- `engine` — 为本次调用覆盖审阅引擎(`codex` | `claude`)。
- `model` — 覆盖审阅模型(默认为引擎的最强模型:`gpt-5.6-sol` / `claude-fable-5`)。
- `effort` — `low` | `medium` | `high`。审查默认为 `high`;`query` 默认为 `medium`。
- `web_search` — 允许审阅者交叉检查外部方法/库声明(默认为 `true`)。
**`arbitrate` 故意没有 `engine` 或 `model`。** 它运行两个供应商,因此单个覆盖只能降低它以适应其中一个供应商,或者将一个供应商的模型名称发送给另一个 CLI。它接受 `models: {codex?, claude?}` 进行每个供应商的覆盖,以及 `cleaner_model`,并遵守 `effort` 和 `web_search`。
## 安全模型
- **只读。** Codex 在其 OS 沙盒(`--sandbox read-only`)下运行;Claude 运行带有只读工具允许列表(`Read`、`Grep`、`Glob`、`git` 读取,作用域 `git` 读取,Web 搜索)和显式否定的写入工具。
审查者无法编辑您的代码、运行您的测试套件或在不选择 Web 搜索的情况下访问网络。
- **Hermetic — 审计存储库无法扩大审查者。** Claude 引擎使用 `--setting-sources ""` 启动,因此它加载 **no** `.claude` 设置文件。没有此设置,`claude -p` 合并审查存储库的 `.claude/settings.local.json` 和您的全局 `~/.claude/settings.json` 位于 paranoia 的允许列表之上 — 而这些通常授予 `Bash(python3:*)`、`Bash(git commit:*)`、`Bash(python -m pytest …)` 等,静默地向审查者提供任意代码执行和可写的 git 访问权限。加载零设置源使 paranoia 的 `--allowedTools` 成为唯一的权限。
这是 **仅限于启动的审查子进程** 的标志 — 它不读取、不写入或影响任何交互式 `claude` 会话或设置文件。(Codex 已经涵盖了 OS 级别的只读沙盒,它没有任何存储库设置可以放松。)
- **隔离。** 提交的审查在目标引用的临时 `git worktree` 中运行,因此它们永远不会与您的工作树发生冲突,并且可以审查一个未检出的分支。(脏工作树审查必须在实时存储库中运行,但为只读访问。)
- **无 API 密钥,无遥测,尽量减少状态。** 服务器外壳调用您已经登录的 CLI。每个审查都会在 `~/.paranoia/logs/` 中写入一个本地审计记录(源 + `rebut` 会话引用)。在 `converge` 模式下(如下),它还会为审阅的快照创建一个短暂的 git 工作树和一些 **未引用的** git 对象(审阅的快照)。在干净退出后,它们都会被清理(最佳努力),并且不会创建任何引用。硬崩溃时 — 或罕见的拆卸失败 —
可以留下工作树注册(及其存在的快照对象),直到下一个 `git worktree prune`/`git gc` — 运行任一命令即可回收它们。您的工作树和索引永远不会被触摸。
**一个可选例外:** `arbitrate` with `retain_snapshot: true` 创建 `refs/paranoia/arbitrate/<stamp>` 以使其证据在 `git gc` 生存。默认为 **off** 以保持上述承诺,并且它是整个服务器中唯一写入引用的模式。可以使用 `git update-ref -d <ref>` 删除一个。
## 速率限制
审查会占用您的订阅的代理使用池。繁重的收敛循环涉及许多代理转折 — 在较小的计划上可以达到 5 小时窗口。请使用 `query`(较低努力)进行快速检查,并为需要它们的更改保留完整的 multi-round `critique_branch` 循环。
`arbitrate` 很昂贵,它是 **同时消耗两个** 订阅的单个调用:通常 4 次代理转折,最多 8 次(清理重试和协调回合)。它的清理程序和评估者是简短的文本转折;决策转折是真正的成本。
## 开发
```bash
pip install -e '.[dev]'
python -m pytest # unit + integration (integration uses fake CLIs; no quota)
```
每个模块都经过 TDD 测试。引擎子进程边界被依赖注入,因此整个堆栈都经过单元测试,无需花费订阅配额;单独的集成测试驱动实际的子进程运行器对抗假 `codex`/`claude` 二进制文件在 `PATH` 上。
## 许可证
MIT © 2026 Andrew Hillel
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器