Files
cc-web/.planning/2026-08-23-gitea-workflow/plan-review.md

135 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Gitea Workflow 实施计划审查
审查日期:2026-08-24
审查范围:`task_plan.md`、`findings.md`、`Gitea Workflow TO DO list.csv` 及用户目标“完整实现 Gitea Webhook → Codex App 持久会话 → 官方 gitea-mcp → Gitea 回执的可靠工作流,并提供管理页面、队列、恢复、测试和文档”。本审查只产生本文件,不修改业务代码或其它计划文件。
## 结论
当前计划在“阶段主题”层面与 CSV 基本一致,但还不能作为可直接执行和可验收的实施基线。建议先补齐 Phase 1 的协议、状态机、数据模型和安全设计,再进入实现;否则最容易出现“功能链路能跑一次,但重启、重复 Webhook、回执失败或并发时不可靠”的假完成。
建议结论:**有条件通过,暂不进入核心编码**。以下 P0 项未关闭前,不应把 CSV 中的核心实现项标记为 DONE。
## 计划与 CSV 一致性
| 计划范围 | 对应 CSV | 一致性 | 审查意见 |
|---|---|---|---|
| Phase 1 需求、协议、设计(`task_plan.md:13-18`) | 1、2 | 基本一致 | CSV 第 1 项为 `IN_PROGRESS`,与计划“进行中”一致;但“已完成边界汇总”和“设计文档尚在编写”的完成定义没有拆开。 |
| Phase 2 状态、Webhook、工作区(`task_plan.md:20-25`) | 3、4 | 基本一致 | 计划把队列/恢复和工作区放在同一阶段,CSV 分成两项;缺少明确前置依赖、交付物和负责人。 |
| Phase 3 Codex App、MCP、回执(`task_plan.md:27-32`) | 5 | 基本一致 | CSV 将线程注入、监听、补触发、REST 兜底合成一项,无法分别验收可靠性。 |
| Phase 4 管理界面、测试(`task_plan.md:34-39`) | 6、7 | 基本一致 | 计划中的重启恢复、并发、自触发回归没有在 CSV 中单列,容易被“测试已补充”掩盖。 |
| Phase 5 整合、验证、交付(`task_plan.md:41-45`) | 8、9、10 | 一致 | 但“解决冲突”“协议形状检查”“文档/审计”均没有明确输出文件、命令和通过阈值。 |
总体上,CSV 的 10 项与计划的 15 个子项不是一一映射关系。建议在计划和 CSV 中增加稳定的任务 ID(例如 P1-01、P2-02),并为每项写明 `交付物 / 依赖 / 验收命令或证据 / 负责人`;否则状态同步只能凭文字判断。
## P0 阻断项
### P0-1:Phase 1 没有可执行的退出条件
计划只写“核验协议”“完成 PRD、状态机、数据模型和安全设计”(`task_plan.md:16-17`),没有指定文档路径、协议版本、决策结果或评审证据。`findings.md` 目前只有研究结论,没有状态转移表、字段定义、接口契约或威胁模型。
进入 Phase 2 前至少应产出并评审:
- Webhook 请求/响应和签名头的版本化协议矩阵;官方 `gitea-mcp` 版本、启动参数、stdio 生命周期和工具能力清单。
- 任务/会话/回执状态机(状态、事件、合法转移、重试上限、超时、取消、死信、人工恢复)。
- 持久化数据模型、唯一键、索引、迁移/版本策略和崩溃恢复规则。
- 线程、任务、Webhook delivery、评论和回执之间的关联契约。
- 安全威胁模型与密钥生命周期设计。
### P0-2:持久化方案无法证明并发安全和崩溃一致性
`findings.md:17` 仅指出现有 JSON 持久化或“新增独立存储模块”,但没有做出选择。队列、去重、状态转移、会话映射和回执确认若继续散落写 JSON,会遇到并发覆盖、半写文件、重复消费和重启丢失;这与目标中的“持久化、可靠、可恢复”直接冲突。
计划必须明确单一事实源及原子性边界:至少要定义 inbox(Webhook 去重)、任务状态、会话映射、outbox(评论/补发意图)如何在一次事务或等价原子操作中落盘;并定义锁、文件替换、fsync、备份/恢复和 schema 迁移。若采用 JSON,需证明单写者/进程锁和崩溃恢复;若不能证明,应在计划中选择具备事务语义的存储。
### P0-3:状态机、幂等和回执可靠性没有闭环
`findings.md:34-39` 给出了“先验签/去重/过滤”“最多一次隐藏补触发”“REST 兜底”的原则,但没有定义可判定的幂等键、评论标记、确认窗口、重复运行保护或失败终态。尤其“任务完成但没有回帖”时,如何区分 MCP 调用已成功但查询延迟、调用超时、网络重试导致重复评论,当前不可执行。
需要补充:
- delivery、任务、turn、评论发送各自的唯一 ID 及跨表关联。
- 评论内容中的稳定 run/attempt 标记或等价查询条件,保证 MCP、补触发和 REST 兜底不会重复发同一回执。
- Gitea 查询的最终一致性轮询窗口、退避、最大次数和“未知”状态;未知不能直接当失败重跑。
- 重试分类(网络/5xx、4xx 权限、超时、进程崩溃)、退避与死信/人工重放策略。
- 重启时每个状态的恢复动作,特别是 `running`、`waiting_user`、`receipt_pending` 和 `cancel_requested`。
### P0-4:三方协议的真实形状和版本未锁定
`findings.md:19-25` 只记录官方仓库和大致参数,`task_plan.md:29-30` 也没有 app-server 方法、事件类型或 MCP 注入字段。没有固定版本和 mock 契约,无法验收“线程级注入”和“turn 状态监听”是否真的走原生协议。
应在 Phase 1 固化并纳入 mock/回归断言:
- Gitea Webhook 事件类型、评论字段路径、签名算法/头、delivery ID、超时和 HTTP 返回语义。
- Codex App `initialize/initialized`、能力探测、`thread/start`、线程恢复、turn 事件和取消/中止的确切参数形状。
- `thread/start.config.mcp_servers.*` 的线程级 env 注入、stdio 子进程启动/退出、超时和错误事件;不得退回动态工具或进程级来源上下文。
- 官方 `gitea-mcp` 版本/校验和、`GITEA_HOST` 与 token 注入方式、工具列表和权限边界。
### P0-5:全写权限下的安全边界不足
计划确认“开放官方 gitea-mcp 全部写权限”(`task_plan.md:63`),但安全设计只写 HMAC 和 Token 分离(`task_plan.md:62`)。这不足以支撑公网 Webhook 和自动接入。至少要覆盖重放、密钥轮换、日志脱敏、仓库/主机 allowlist、请求体大小和限流、路径穿越、命令注入、工作区权限、MCP 子进程隔离,以及管理页面的认证/授权/CSRF。
同时要明确 Bot 自评论过滤不能只依赖用户名:应定义稳定的 bot identity、来源 delivery/run 标记和异常情况下的 fail-closed 行为,避免自触发风暴(`findings.md:34-36`)。
### P0-6:跨模块写冲突和整合策略未规划
Phase 5 写“整合子任务改动并解决冲突”(`task_plan.md:43`),但没有任务分区、文件所有权、接口冻结点或整合顺序。预期热点很可能包括 `server.js`、配置/持久化模块、Codex App turn 路径、MCP 配置、路由和前端状态;多个实现项若直接改同一入口,会产生不可审计的隐式冲突。
进入实现前应把工作拆成不重叠边界(例如 domain/state、webhook/queue、workspace、app-server adapter、API/UI、tests/docs),先冻结共享接口,再按依赖顺序合并;禁止以“最后人工解决冲突”作为验收条件。
## P1 重要遗漏与可执行性问题
### 1. 队列与恢复
Phase 2 只列“状态、队列、去重和恢复”(`task_plan.md:22`),缺少全局并发上限为 2 的调度算法、公平性、每仓库串行锁的租约/心跳、进程崩溃后的 stale runner 判定、优雅停机、取消排队与中止 turn 的区别、超时、死信和人工重放。应为每一类恢复场景写出输入、状态变化和预期结果,并加入 kill/restart 测试。
### 2. Webhook 与自动接入
`findings.md:5-7` 未定义配置校验、首次接入的授权边界、仓库 URL/owner/repo 的规范化、默认分支和私有仓库权限失败处理。需要明确先快速返回 HTTP,再异步入队还是同步处理;验签失败、重复 delivery、非评论事件、非目标评论、Bot 自评论分别返回什么,避免 Gitea 重试风暴。
### 3. 工作区与 Git 认证
`findings.md:40` 的“脏工作区不 reset、不覆盖”是原则,不是行为契约。要决定脏状态时任务是失败、暂停、继续当前会话还是创建隔离 worktree;定义分支/ref 切换、fetch 冲突、仓库删除、磁盘不足、凭据泄露(命令行/日志/remote config)和清理策略。持久 checkout 与“同仓库串行”还需明确锁的持有范围。
### 4. Codex App 会话与 waiting_user
计划确认会话键(`task_plan.md:59`)和固定 `codexapp + yolo`(`task_plan.md:58`),但没有说明首次建线程、重启后的线程恢复、线程不存在/过期、app-server 断线、turn 超时及取消后的映射。`waiting_user`(`task_plan.md:31`、`task_plan.md:64`)没有定义由哪类 Gitea 评论恢复、是否阻塞同仓库、超时/过期和最大连续轮数;“连续评论投递”也没有顺序和幂等规则。
### 5. 管理 API 与前端
Phase 4 只写“实现管理 API 和前端页面”(`task_plan.md:36`),没有端点契约、权限角色、敏感配置展示规则、暂停/停用/取消/中止的并发控制、审计记录格式、分页过滤、实时刷新和错误提示。管理页面不能成为绕过队列状态机的第二套写入口;所有操作应复用同一领域命令和审计链。
### 6. 测试与验收证据
CSV 第 7、9 项虽覆盖“测试、构建、协议验收”,但没有测试矩阵、通过阈值或运行命令。至少应覆盖:重复/乱序 Webhook、伪造/重放签名、Bot 自触发、首次接入、同仓库并发、不同仓库并发上限、脏工作区、clone/fetch 失败、app-server 断线、MCP 缺失/工具报错、turn 中止、waiting_user、MCP 成功但查询延迟、补触发成功/失败、REST 兜底、进程 kill 后恢复、密钥轮换和管理 API 未授权。
协议测试不能只断言“调用成功”,还要断言真实参数形状、线程级 env、没有重复顶层字段、调用的是 MCP 工具而非动态工具,并保存 mock 输入/输出作为审计证据。应明确单元/集成/E2E 的最小通过标准和 CI/本地命令。
### 7. 运维、可观测性与交付
用户目标包含队列、恢复和文档,但计划未列指标、结构化日志、关联 ID、告警、数据保留、备份恢复、升级/回滚、配置校验和运行手册。Phase 5 的“文档、审计和最终交付”(`task_plan.md:45`)应明确至少包括架构/状态机、部署配置、Webhook 配置、密钥轮换、故障处理、恢复/重放、权限说明和已知限制。
## 建议的执行顺序与退出条件
1. **先完成 Phase 1 冻结契约**:补齐上述协议矩阵、状态机、schema/迁移、领域命令、错误/重试表、安全威胁模型和 mock fixture;每项有文档路径和评审人。
2. **再实现持久化领域核心**:先落地 inbox、任务、会话、outbox、审计的原子状态转移和恢复算法,再接 Webhook/工作区,避免入口先写出不可恢复的副作用。
3. **接入 Codex App 与 gitea-mcp**:以固定版本和协议 mock 验证线程级配置、turn 事件、取消/重连;所有回执发送经过幂等 outbox。
4. **最后接 API/UI 和故障测试**:API/UI 只发领域命令;并发、重启、自触发和回执异常测试必须在标记 Phase 4 完成前通过。
5. **Phase 5 交付门槛**:构建、静态检查、全测试和协议形状断言均有可复现命令;文档、审计样例、恢复演练记录和回滚方案齐全。
推荐把每个阶段的状态改成“未开始/进行中/阻塞/完成”,并在完成条件中引用证据文件或测试名称,而不是只保留勾选框。
## 最小验收清单(对应用户目标)
- Webhook:合法评论可入队;伪造、重放、重复 delivery、非目标事件和 Bot 自评论均按契约处理。
- 持久会话:会话键稳定;重启后任务、锁、turn 和 waiting_user 状态可恢复且不重复执行。
- 官方 MCP:固定版本、线程级配置、凭据不落盘/不泄露;读写工具调用可被 mock 和审计验证。
- 回执:成功评论可确认;未知状态不会盲目重跑;只允许一次补触发,之后 REST 兜底仍幂等。
- 队列/并发:同仓库串行、不同仓库并行、全局上限 2 可证明;暂停、取消、终止和死信可操作。
- 管理面:认证授权、审计、状态查询和运维操作与领域状态机一致,不暴露 token/secret。
- 可靠性测试:覆盖崩溃恢复、并发、网络/权限/协议失败和自触发回归,并有可重复命令与结果。
- 文档交付:架构、配置、部署、密钥、故障恢复、重放、回滚和已知限制齐全。
## 审查结论摘要
CSV 与计划没有明显的宏观漏项,但粒度、状态和验收证据不一致;当前最大的风险不是缺少页面或接口,而是持久化原子性、状态机幂等、三方协议形状和全写权限安全边界尚未冻结。补齐 P0 并将其转成带 ID/依赖/证据的任务后,计划才具备可靠实施条件。