docs: revise M4 design per independent review (3I/6M) and register wiki entity

This commit is contained in:
2026-07-22 05:12:45 -04:00
parent c95c70b69b
commit ee1bc403ad
5 changed files with 34 additions and 11 deletions
@@ -35,14 +35,14 @@
**CHS 漂移**(5ac9f59→7eb8482,135 文件 +9818/1853,治理关键文件仅 44+/83):
- positioning 子系统重构为纯图像模板分类(`TemplateVascularPositioner`),**position worker 不再消费 VLM**;`PositionCallScheduler` 端口与 `load_single_vlm_capacity` 已删除。
- 影响修订三条:迁移文档 §2"load_single_vlm_capacity 保留改读库聚合"作废;§6-S3"VLM 灰度先切 position worker"作废(VLM 消费点收敛为 extractors.py/classifiers.py,同属 pipeline worker,灰度只剩一段);调用点清单中 vascular_positioner.py:329 一行作废。
- governance/invokers/limiter/scripts/selector/streaming/errors/judge/contracts_limiter **零实质变更**(仅格式化),迁移文档其余 file:line 证据仍有效
- governance/invokers/limiter/scripts/selector/streaming/errors/judge/contracts_limiter **零实质变更**(仅格式化);迁移文档其余证据**语义有效,行号以实施时实测为准**(tracking/config/container/ports 有小幅行号漂移)
## 4. 决策 1:迁移工作区机制
| 方案 | 内容 | 优点 | 缺点 |
|---|---|---|---|
| A 直接改 reference/(用户原话方向) | 放开 pre-tool-guard 对 reference/ 的写拦截(文件工具 + Bash 的 checkout/sed/rm 等),CLAUDE.md 铁律措辞同步改;在 reference/<proj> 内切 feature 分支实施 | 与用户直觉一致;路径最少 | ① 钩子里 `git checkout` 也在拦截清单,A 必须动钩子,硬边界整体弱化(误删保护一并失去);② 分支切走后**旧版治理代码从工作区消失**,而迁移全程要逐段对照旧实现验证 shim 等价性,只能靠 `git show` 翻历史;③ 迁移文档/ARCHITECTURE 的 file:line 证据在工作区失效 |
| **B git worktree(推荐)** | 保持 reference/ 只读与钩子零改动;`git -C reference/<proj> worktree add /Users/yuchengzhang/Projects/m4-worktrees/<proj> -b feat/polygateway-migration`;实施全部发生在 worktree(路径不含 reference/,钩子天然放行;`worktree`/`commit`/`push` 子命令均不在拦截清单) | ① 硬边界一行不改;② reference/ 本体停在 main:旧版代码、蓝本、file:line 证据全程可对照——这正是"迁移前先做旧版行为审计"的物理保障;③ commit/push 走同一 origin,与 A 的 git 效果完全相同;④ 项目自带 `using-git-worktrees` skill,惯例现成 | 多一个目录;用户在别处打开项目时需知道实施分支在 worktree 里(向用户交代路径即可) |
| **B git worktree(推荐)** | 保持 reference/ 工作区只读与钩子零改动;`git -C reference/<proj> worktree add /Users/yuchengzhang/Projects/m4-worktrees/<proj> -b feat/polygateway-migration`;实施全部发生在 worktree(路径不含 reference/,钩子天然放行;`worktree`/`commit`/`push` 子命令均不在拦截清单) | ① 硬边界一行不改;② reference/ 本体停在 main:旧版代码、蓝本、file:line 证据全程可对照——这正是"迁移前先做旧版行为审计"的物理保障;③ commit/push 走同一 origin,与 A 的 git 效果完全相同;④ 项目自带 `using-git-worktrees` skill,惯例现成 | 多一个目录,且在 PolyGateway 工作目录之外——**前置**: 需把 `/Users/yuchengzhang/Projects/m4-worktrees/` 加入工具写权限(settings `additionalDirectories` 或人类门口头授权),否则实施期逐次询问;② 措辞澄清: worktree 的 add/commit/push 会向 `reference/<proj>/.git` 写入 refs 与对象,"只读"实质收窄为"工作区文件与 main 检出不变"——本设计将此收窄视为可接受并明示 |
| C 外部独立 clone | 在项目外重新 clone 两仓库实施 | 与 B 同等隔离 | 双份仓库易漂移(reference/ 更新后 clone 不同步);B 是 C 的严格上位 |
**推荐 B**。它交付的正是用户要的东西(在项目本体仓库的 feature 分支上真实迁移、可 push),但不付出硬边界与蓝本对照的代价;用户拍板 A 的实质诉求是"能改真仓库",B 完全满足。若人类门坚持 A,则钩子改法为:reference/ 写拦截整段替换为"仅拦 rm -rf 类危险命令",CLAUDE.md §1/§5 的"只读勿改"措辞改为"M4 起为迁移工作区;蓝本对照以 git 历史为准"。
@@ -63,7 +63,7 @@ judge(`core/eval/judge.py`,快照后零变更)默认 provider=anthropic,同步
| 方案 | 内容 | 权衡 |
|---|---|---|
| **走实验室 OpenAI 兼容中转(推荐)** | judge 配 `JUDGE__{PROVIDER}__1__*` 指向实验室中转网关,claude 模型名经中转;`_call_llm` `asyncio.run(client.chat(...))`(Judge 端口同步、runner 无事件循环,桥接安全),解析换库 `JsonRepairStrategy` | 零库改动;**前置确认**: 中转网关是否代理 judge 所需 claude 模型(人类门时确认,不通则回退方案 3) |
| **走实验室 OpenAI 兼容中转(推荐)** | judge 配 `JUDGE__{PROVIDER}__1__*` 指向实验室中转网关,claude 模型名经中转;`_call_llm`同步桥接,解析换库 `JsonRepairStrategy`。**桥接方案钉死**: 每次调用一个完整 `asyncio.run(...)`,client 的构造(from_env)与 `aclose()` 都在该协程内完成——httpx 连接池绑定事件循环,跨 `asyncio.run` 复用常驻 client 会触发 "Event loop is closed"(经典坑);judge 是低频评估路径,放弃连接复用换正确性。备选(judge 调用量大时): 常驻单线程事件循环 + `run_coroutine_threadsafe` | 零库改动;**前置确认**: 中转网关是否代理 judge 所需 claude 模型(人类门时确认,不通则回退方案 3) |
| 库新增 Anthropic 原生 transport | D2 有端口预留 | 新子系统 = 新公共承诺 + 独立设计与测试,为单一消费点开新承诺违反 YAGNI;M4 内否决,留 D2 储备 |
| judge 暂缓收编 | judge.py 保持裸调,标注技术债 | 违背"全量迁移"验收口径;仅作中转不可用时的降级,需用户显式同意 |
@@ -78,7 +78,7 @@ judge(`core/eval/judge.py`,快照后零变更)默认 provider=anthropic,同步
| G3 | `.env`/`.env.example` 改键(平铺单源 → `LLM__{PROVIDER}__1__*`;新增 namespace 等;凭据先读 .env 真实值再写) | `from_env()` 无缺配置报错 | commit |
| G4 | 装配进 api lifespan 与 arq worker 入口(显式 `retryable_exceptions=(TransientError, AllSourcesExhausted)` + `aclose()`) | govdoc 业务测试绿;注错验证步级重试可触发 | commit |
| G5 | `retrieval/embedding.py` 删除换 `EmbeddingClient`(映射: batch_size→`EMBED__BATCH_SIZE`、dimension→`EMBED__EXPECTED_DIM`、on_usage→遥测) | retrieval 相关测试绿 | commit |
| G6 | 删 llm/ 六文件 + test_breaker.py;改写 types.py(re-export)/protocols.py(删 TelemetryRecorder)/test_imports.py;docagent-core pyproject 移除 redis extra、根 pyproject 加 polygateway | `make ci` 全绿 + import-linter 过 | commit |
| G6 | 删 llm/ 六文件 + test_breaker.py;改写 types.py(re-export)/protocols.py(删 TelemetryRecorder)/test_imports.py;docagent-core pyproject 移除 redis extra、根 pyproject 加 polygateway;**Makefile install 行同步改**(现硬编码 `docagent-core[redis,dev]`,extra 删除后引用失效) | `make ci` 全绿 + import-linter 过 | commit |
| G7 | 验收: 验收公式逐项核对 + 冒烟/回归(§9)+ 独立 verifier | ci 输出 + verifier 报告 | — |
GovDoc 特有事实(迁移文档 §1): 装配层从未存在、`GovernedLLMClient` 零生产调用方、零异常捕获点——业务代码对治理层消费零改动,风险≈0;缓存 key 全变无成本(未上生产)。
@@ -104,11 +104,11 @@ CHS 特有约束: 遥测后端配 `PGW_TELEMETRY_BACKEND=postgres` 指 PG 实例
| 项目 | 冒烟(已定) | 回归候选 |
|---|---|---|
| GovDoc | G2 的 spike: AgentLoop 真实调用 + 遥测/缓存命中实测 | 无旧遥测基线(骨架期),**建议冒烟即回归**;可加"重跑同请求缓存命中率非零"一条 |
| CHS | 单张真实样本走完整提取 pipeline(worktree 内,治理走库) | (a)**小批对拍(建议)**: 选 20-50 张真实样本,旧版(reference/ main)与新版(worktree)各跑提取,对比结构化结果一致率 + 错误率/延迟(新版读库遥测,旧版读运行日志);(b) testing 环境 docker 部署跑 e2e;(c) 只冒烟不批跑。样本量、一致率阈值、跑批环境届时拍板 |
| CHS | 单张真实样本走完整提取 pipeline(worktree 内,治理走库) | (a)**小批对拍(建议)**: 选 20-50 张真实样本,旧版(reference/ main)与新版(worktree)各跑提取,对比结构化结果一致率 + 错误率/延迟(新版读库遥测,旧版读运行日志);(b) testing 环境 docker 部署跑 e2e;(c) 只冒烟不批跑。**先行写死两条**: 新旧两轮**串行执行**(并行则对同一真实上游 RPM 双份消耗,同"禁止双栈并跑"精神);旧版跑批同样只用实验室 Redis db3 与 PG polygateway 库,不触生产后端。样本量、一致率阈值、跑批环境届时拍板 |
## 10. v1.0 发布清单(两项目验收全过后)
① 库版本 bump `1.0.0` + 汇总 changelog;② `python -m build` 出 wheel+sdist;③ twine 上传 Gitea PyPI(token 用户提供,写 `~/.pypirc` 或环境变量,不入任何仓库);④ 一次性干净 conda 环境从 Gitea index 回装,重跑两项目测试套件绿;⑤ 两项目 pyproject 定稿 `==1.0.*` 并记录安装命令;⑥ 打 git tag `v1.0.0`;⑦ 文档同步(§15)。发布后库仓库亦推送至 Gitea 托管(用户提及"托管到 gitea",与 GitHub 双远端或迁移,人类门确认)。
① 库版本 bump `1.0.0` + 汇总 changelog + **库自身 `make ci` 重跑全绿(发布门)**;② `python -m build` 出 wheel+sdist;③ twine 上传 Gitea PyPI(token 用户提供,写 `~/.pypirc` 或环境变量,不入任何仓库);④ 一次性干净 conda 环境从 Gitea index 回装,重跑两项目测试套件绿;⑤ 两项目 pyproject 定稿 `==1.0.*` 并记录安装命令;⑥ 打 git tag `v1.0.0`;⑦ 文档同步(§15)。发布后库仓库亦推送至 Gitea 托管(用户提及"托管到 gitea",与 GitHub 双远端或迁移,人类门确认)。
## 11. 旧版行为审计
@@ -116,7 +116,7 @@ CHS 特有约束: 遥测后端配 `PGW_TELEMETRY_BACKEND=postgres` 指 PG 实例
## 12. 非功能维度
- **并发与取消**: 治理层行为全部由库承载(M1-M3 已验收);项目侧新增物仅 shim(纯映射,无状态)与装配代码。CHS `asyncio.run` 桥接点(judge)在同步 runner 线程调用,无嵌套事件循环风险(实施时以 `asyncio.get_running_loop()` 探测断言钉住)。CancelledError 穿透:shim 不含 try/except 包裹,天然穿透。
- **并发与取消**: 治理层行为全部由库承载(M1-M3 已验收);项目侧新增物仅 shim(纯映射,无状态)与装配代码。CHS judge 桥接按 §6 钉死: client 构造与 aclose 均在单次 `asyncio.run` 协程内,杜绝 httpx 连接池跨事件循环复用;同步 runner 线程无嵌套循环风险(实施时以 `asyncio.get_running_loop()` 探测断言钉住)。CancelledError 穿透:shim 不含 try/except 包裹,天然穿透。
- **降级方向**: 继承库铁律(缓存/遥测静默、限流/熔断报错);GovDoc B15 步级重试作为业务侧兜底显式保留(G4 注入库异常类型,静默失效风险以注错测试钉死)。
- **幂等与重复**: 迁移步骤均以 commit 为回滚点、可重入(重复执行 editable install/改键无副作用);Gitea 同版本重复上传会被 409 拒绝,重发布必须 bump 版本。
- **持久化与原子性**: 项目侧不新增持久化;CHS 生产切换的 Redis key 前缀切换风险(短暂限流清零)已在迁移文档 §8 论述,手册中标注低峰执行。
@@ -125,7 +125,7 @@ CHS 特有约束: 遥测后端配 `PGW_TELEMETRY_BACKEND=postgres` 指 PG 实例
- 缺口回补的判定口径: 迁移中任何"库能力不足以让原测试通过/原行为复现"即边界缺口 → 回补进库(走库侧常规红绿流程 + 小版本)→ 项目侧重验;禁止在项目侧用变通代码掩盖库缺口。
- 项目侧新增代码(shim/装配)的失败路径: 全部落库四分类语义,shim 不吞不改异常类型;每个 shim 有先失败后通过的单测证据(测试结果门照旧)。
- 测试基线纪律: 迁移前基线的 pass/skip 剖面留档;迁移后全绿且 skip 不增;两项目测试在各自 conda 环境跑,不与库 soak 并跑(Redis db3 FLUSHDB 冲突)。
- 测试基线纪律: 迁移前基线的 pass/skip 剖面留档,并同步留存**预期测试增删清单**(G6/C6 删除的自测文件导致分母变化,核对时按清单修正);迁移后全绿且 skip 不增;两项目测试在各自 conda 环境跑,不与库 soak 并跑(Redis db3 FLUSHDB 冲突)。
## 14. 风险
@@ -139,7 +139,7 @@ CHS 特有约束: 遥测后端配 `PGW_TELEMETRY_BACKEND=postgres` 指 PG 实例
## 15. 文档同步清单(实施尾声执行)
① ROADMAP §1/§5: M4 范围改两项目、VT 标注放弃(2026-07-22 用户拍板)、状态推进;② ARCHITECTURE §11.2: 标注 VT 已放弃不迁移(能力倒推记录保留);§13 Q1/Q6 落拍板结果;③ migrations/video-tree-trm5.md 头部标注放弃;④ migrations/{govdoc-saas,chsanalyzer}.md: 漂移修订(§3)与实施结果回写;⑤ CLAUDE.md: 若人类门选方案 A 则改 reference/ 铁律措辞,选 B 则零改动;⑥ 库 README/发布说明: Gitea 安装命令
① ROADMAP §1/§5: M4 范围改两项目、VT 标注放弃(2026-07-22 用户拍板)、状态推进;② ARCHITECTURE §11.2: 标注 VT 已放弃不迁移(能力倒推记录保留);§13 Q1/Q6 落拍板结果;③ migrations/video-tree-trm5.md 头部标注放弃;④ migrations/chsanalyzer.md: 漂移修订(§3)与实施结果回写;migrations/govdoc-saas.md: extras 名更正(文中 `[redis,telemetry-sqlite]` 不存在,实为 `[redis,structured]`)、"不迁 embedding 待 Q3"已被拍板推翻(G5 迁移)、实施结果回写;⑤ CLAUDE.md: 若人类门选方案 A 则改 reference/ 铁律措辞;选 B 则钩子与铁律条文零改动,但"只读"语义收窄(§4-B ②)在 CLAUDE.md reference/ 条目加一行括注;⑥ 库 README/发布说明: Gitea 安装命令;⑦ **迁移合并后 reference/ 本体收尾同步**: 用户在各项目远端合并 feature 分支后,`git -C reference/<proj> pull --ff-only`(不在钩子拦截清单)把本体推进到迁移后 main,并移除 worktree(`git worktree remove`)——蓝本自此指向迁移后代码,属预期终态
## 16. 被否决的备选汇总
+14
View File
@@ -0,0 +1,14 @@
---
type: design
node_id: design:m4-migration
title: "M4 迁移验证设计(GovDoc→CHS,发 v1.0)"
date: 2026-07-22
---
# M4 迁移验证设计(GovDoc→CHS,发 v1.0)
正文: `2026-07-22-m4-migration-design.md`
- **选定方案**: 迁移工作区用 git worktree(reference/ 本体保持只读、钩子零改动,worktree 在项目外承载 feature 分支);依赖两阶段(开发期 editable → 验收后发 v1.0.0 至 Gitea PyPI 回装);CHS judge 走实验室 OpenAI 兼容中转。
- **被否决备选及理由**: 直接改 reference/ + 放开钩子(硬边界弱化、旧版蓝本对照丢失——若人类门坚持则按 §4-A 的钩子改法执行);外部独立 clone(双份漂移);全程 wheel 分发(迭代慢)与 git+https(放弃 pip index 价值,留作退路);Anthropic 原生 transport(单一消费点开新公共承诺,违 YAGNI);为 VT 放弃回收库能力(任务外变更)。
- **范围拍板**: VT 项目已放弃不迁移(2026-07-22 用户),v1.0 验收改两项目。