-
Notifications
You must be signed in to change notification settings - Fork 3
doc(SPEC): cover the mixed-mode contract merge; main goes green again #112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| # contract.py —— 规范 | ||
|
|
||
| <!-- verified-against: 2026-08-28 --> | ||
|
|
||
| `LOC ~181 · 跨仓库公开契约面 · refactor-status: ok` | ||
|
|
||
| ## 职责 | ||
| 本 copilot 的**对外消费契约**:一个 review bot(或任何宿主)被允许 import 的 | ||
| 一切都住在这里,此外的任何 import 都不受支持。它的存在源于一次真实事故: | ||
| 下游仓库曾经用 `importlib` 伸进 `thin_mcp_server` 拿四个 `_direct_*` 私有名, | ||
| 一次重命名就让另一个仓库在运行期断裂、且没有任何构建期信号。 | ||
|
|
||
| ## 公开契约(`__all__`) | ||
| `DIRECT_API_VERSION` / `STRICT_API_VERSION`(`"1.0.0"`,形状变化到消费方 | ||
| 必须察觉时递增);`capabilities(max_strict_workers=1, | ||
| supports_file_locking=True) -> dict`(版本/能力握手:`supports_expected_head`、 | ||
| `supports_structured_result`、`supports_post_false`、`supports_file_locking`、 | ||
| `max_strict_workers`);`build_review_result(run_dir) -> dict`(结构化评审 | ||
| 结果:`contract_version`、`run_id`、`state`、`reviewed_head_sha`、`verdict`、 | ||
| `summary_markdown`、`comments`、`stale`/`expected_head_sha`/ | ||
| `actual_head_sha`、`diagnostics`);`unknown_run_result(run_id)`(显式 | ||
| `state: unknown`,绝不抛错 —— 丢响应和还在跑必须可区分); | ||
| `sanitize_comments` 与 `COMMENT_FIELDS`;以及从 `direct_routing` 再导出的 | ||
| `direct_knowledge_routes` / `direct_execution_budget` / | ||
| `direct_completion_result` / `direct_mandatory_review_guides`。 | ||
|
|
||
| ## 不变量 | ||
| - **依赖方向单向、由测试钉住**:本模块 import 数据层(`run_status`、 | ||
| `run_trace`),**绝不** import 任何 MCP server 模块;server 向下 import | ||
| 这里。`test_contract.py::test_contract_imports_no_server_module` 钉住。 | ||
| - `build_review_result` **只读 run 已持久化的东西**:对已完成、进行中、 | ||
| 评审步之前就死掉的 run 都成立;JSON 读取 fail-soft(早死的 run 合法地 | ||
| 缺文件)。 | ||
| - verdict 是**字段**不是 Markdown 刮取;stale 是**数据** | ||
| (`stale`/`expected`/`actual`),不是从散文推断。 | ||
| - `sanitize_comments` 按 `COMMENT_FIELDS` 白名单 | ||
| (file/line/severity/comment/evidence/suggestion)——内部记账键 | ||
| (`_verified`、`corroborated_by` 等)绝不泄进消费方输出。 | ||
| - 本模块自身保持仓库中立;仓库专属的 Direct 路由表住在 | ||
| `direct_routing.py`(见其页)。 | ||
|
|
||
| ## 边界 —— 不属于这里 | ||
| 不调模型、不执行 run、不做策略强制(`mcp_policy`)、不实现 Direct 路由 | ||
| (委托 `direct_routing`)。 | ||
|
|
||
| ## 依赖(允许) | ||
| `run_status`、`run_trace`、`direct_routing` —— 只向下。消费方: | ||
| `mcp_server.py`(capabilities / build_review_result / unknown_run_result) | ||
| 与仓库外的 reviewbot(`direct_*` 四件套)。 | ||
|
|
||
| ## 扩展点 | ||
| 消费方需要的新字段 → 加进 `build_review_result` 并递增 API 版本; | ||
| 新的 Direct helper → 在 `direct_routing` 实现、在这里再导出。 | ||
|
|
||
| ## 测试 | ||
| `test_contract.py`(23 例:verdict 字段化、评论白名单、stale 即终局事实、 | ||
| 早死 run 的降级结果、unknown-run 显式化、能力上报、import 方向、 | ||
| 本模块仓库中立)。 | ||
|
|
||
| ## 重构备注 | ||
| 新模块(PR2 mixed-mode contract 拆分)。保持它薄:任何"顺手在这里实现" | ||
| 的诱惑都在重造 thin_mcp_server 的巨石。 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| # direct_routing.py —— 规范 | ||
|
|
||
| <!-- verified-against: 2026-08-28 --> | ||
|
|
||
| `LOC ~768 · Direct 模式知识路由(表 + 机制) · refactor-status: known-debt` | ||
|
|
||
| ## 职责 | ||
| Direct 模式的知识路由:owner/model 路由表和选路机制。从 | ||
| `thin_mcp_server.py` **逐字迁出**(下游曾经 `importlib` 拿它的私有名), | ||
| 公开面由 `contract.py` 再导出。它显式携带仓库专属知识 —— 这正是 | ||
| `contract.py` 必须保持中立而这里不必的原因;把表外置到 | ||
| `adapters/<repo>/` 是**未被这次搬迁改变的既有欠账**。 | ||
|
|
||
| ## 公开契约 | ||
| 经 `contract.py` 再导出的四个名字:`direct_knowledge_routes`、 | ||
| `direct_execution_budget`、`direct_completion_result`、 | ||
| `direct_mandatory_review_guides`。其余全部下划线私有 —— 仅供 | ||
| `thin_mcp_server` 既有调用点/测试使用(它继续直接 import 下划线名)。 | ||
|
|
||
| ## 不变量 | ||
| - **repo 守卫最先跑**:不支持的仓库在任何路由计算之前被拒 —— 修的是一个 | ||
| 真实历史 bug(守卫曾排在空 intent 提前返回之后,向不支持的仓库泄漏 | ||
| owner 知识)。 | ||
| - **quick map fail-closed**:`_direct_quick_map` 返回内嵌代码地图与状态 | ||
| `{ok, truncated, unavailable}`,`truncated` 不是装饰 —— 把残图当全图 | ||
| 与缺图同罪、且更难察觉;`_direct_route` 据此置 | ||
| `read_required = status != "ok"`("自己去打开"是真回退,"什么都不给 | ||
| 又不许看"不是)。 | ||
| - **changed files 校验选择、绝不静默替换选择**:title/body 选 owner, | ||
| diff 只报告支持或矛盾;scope-fallback 是最后手段且永远显式 | ||
| (`status="scope_fallback"`)。 | ||
| - `_direct_execution_budget` 是**硬顶**预算字典(`hard_ceiling=True`、 | ||
| 一次有界扩展);docs-only PR 走更便宜的 profile。 | ||
| - `_direct_completion_result` 是**机械结构门**,不校验证据真假: | ||
| 单条最终评论、`subtraction_signal ∈ {none, triggered}`、 | ||
| `evidence_head_sha` 7–40 位十六进制、`existing_feedback_status` 枚举、 | ||
| `finding_dispositions` 的 anchor/disposition/existing_thread/ | ||
| head_recheck 约束。 | ||
| - 叶子模块:**绝不** import 任何 server 模块 | ||
| (`test_contract.py::test_direct_routing_does_not_import_a_server_module`)。 | ||
|
|
||
| ## 边界 —— 不属于这里 | ||
| 不执行、不调模型;只有路由表 + 机制。多 adapter 桥接经 | ||
| `_normalize_repo`/`_adapter_for_repo` 走 `adapters/`。 | ||
|
|
||
| ## 依赖(允许) | ||
| stdlib + `.adapters`(AdapterError / AdapterRegistry / RepoAdapter)。 | ||
| 位于 `contract.py` 和 `thin_mcp_server.py` 之下。 | ||
|
|
||
| ## 扩展点 | ||
| 新 owner 路由/模型规则 → 表数据;跨仓库通用化 → 外置进 | ||
| `adapters/<repo>/routing`(既有欠账的正解,不是在这里再长表)。 | ||
|
|
||
| ## 测试 | ||
| `test_contract.py`(公开家、import 方向、中立性豁免); | ||
| `test_thin_mcp_server.py` / `test_thin_mcp.py`(经新家继续锻炼全部 | ||
| 下划线函数:路由、预算、完成门)。 | ||
|
|
||
| ## 重构备注 | ||
| 768 行里约 500 行是表数据。`known-debt` 指的就是表:机制是稳定的, | ||
| 表的归宿在 adapter 数据面(见结构重组计划 Stage 8 的 routing.yaml 方案)。 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For supported adapter-backed repositories such as
afd-plugin,_adapter_changed_file_routesbypasses_direct_route, stores_direct_quick_map(...)as a tuple, and hardcodesread_required=False. Forafd_plugin/config.py, the public router therefore returnsquick_map: ('', 'unavailable')while telling the host not to read the page, so the asserted fail-closed invariant and the resulting knowledge-read budget are false for an entire supported review path.Useful? React with 👍 / 👎.