# Gitea Workflow 研究与决策 ## 需求 - Gitea 实例级 Webhook 指向 cc-web;用户在 Issue/PR 普通评论中 `@ccweb-bot`。 - 未登记仓库首次合法触发自动接入,clone 到可配置工作区根目录。 - 同一仓库串行、不同仓库并行;任务队列、会话映射和回执状态必须持久化。 - 所有后台会话固定使用 Codex App 与 yolo;Gitea 是唯一主交互入口。 - Agent 通过官方 `gitea-mcp` 读取上下文、研究、修改和回帖;cc-web 负责状态与最终兜底。 ## 本地代码发现 - `server.js` 已有持久会话创建、`handleMessage`、Codex App 线程、MCP 配置和 turn 完成路径。 - `codexAppThreadConfig()` 已将运行时 MCP 组装成 `thread/start.config`;可扩展为工作流专属 `gitea` 配置。 - `handleCodexAppTurnComplete()` 是最合适的 turn 完成监听点。 - `handleInternalMcpApi()` 是 cc-web 内部 MCP API,不应暴露为 Gitea 公网 Webhook。 - 项目无 Node SQLite 依赖;现有会话和配置以 JSON 文件持久化,工作流状态可采用原子 JSON 文件或新增独立存储模块。 ## 官方 gitea-mcp - 官方仓库:`https://gitea.com/gitea/gitea-mcp`。 - 支持本机 stdio 与 HTTP;本任务选择 stdio。 - 支持 `GITEA_HOST`、`GITEA_ACCESS_TOKEN`,可通过 `-t stdio -H ` 启动。 - 工具覆盖 Issue、PR、仓库、文件、分支、提交、Release、Actions 等。 - 支持 scope/tool 过滤,但用户要求 MVP 开放全部写权限;必须配套暂停、中止和审计。 ## 外部方案 - Matea:最接近完整 Gitea Webhook Agent 网关,可参考其签名、去重、队列和状态机;社区规模仍小。 - wshm:支持多 Forge 和后台同步,但不是 cc-web 会话桥接。 - pi-dispatch:队列、预算和沙箱值得参考,但使用 pi Agent。 - gitea-claude-agent:验证 `@机器人 → 多轮澄清 → PR` 交互,但依赖 Gitea Actions。 ## 关键技术约束 - Webhook 必须在验签、delivery 去重、Bot 自评论过滤后才创建任务。 - 每个 turn 生成唯一标识,正常最终评论由 MCP 发送;Webhook/API 查询确认真实回帖。 - 任务完成但没有回帖时,只允许在同一会话发起一次“只补发回执、不重复修改”的隐藏 turn。 - 回执仍失败才使用 Bot Token 走 Gitea REST 兜底。 - 共享工作区有未提交修改时不 reset、不覆盖;当前会话可继续,其他会话排队。 ## 已落地实现 - 主服务入口为 `lib/gitea-workflow-service.js`,底层组合 `domain/store/queue`;避免同时维护两套运行时状态。 - `server.js` 只负责实例化配置、Webhook 路由、工作区 runner、Codex App turn 桥接和管理 API。 - 管理配置中的 Secret/Token 保存到独立 0600 文件,GET 配置只返回“是否已配置”;保存后重启使运行时闭环读取新凭据。 - 回帖核验只接受 `kind=final|fallback` 的隐藏标识,状态评论不会误判为最终回帖;查询异常也只进行一次“只补发回执”补偿。