From 672e51e68e7ee9ec7a11f0910b06d393c1bae174 Mon Sep 17 00:00:00 2001 From: Tyke Chen <190473011+chentyke@users.noreply.github.com> Date: Mon, 20 Jul 2026 17:03:11 +0800 Subject: [PATCH] docs: define unified FastAPI delivery plan --- .../PULL_REQUEST_TEMPLATE/unified-platform.md | 63 ++++++++ docs/unified-fastapi-platform/README.md | 88 +++++++++++ .../agent-operating-model.md | 118 +++++++++++++++ docs/unified-fastapi-platform/architecture.md | 141 ++++++++++++++++++ docs/unified-fastapi-platform/decisions.md | 82 ++++++++++ .../unified-fastapi-platform/quality-gates.md | 117 +++++++++++++++ .../real-environment-handoff.md | 90 +++++++++++ .../unified-fastapi-platform/risk-register.md | 27 ++++ docs/unified-fastapi-platform/roadmap.md | 90 +++++++++++ main/manager-api-fastapi/README.md | 5 + 10 files changed, 821 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE/unified-platform.md create mode 100644 docs/unified-fastapi-platform/README.md create mode 100644 docs/unified-fastapi-platform/agent-operating-model.md create mode 100644 docs/unified-fastapi-platform/architecture.md create mode 100644 docs/unified-fastapi-platform/decisions.md create mode 100644 docs/unified-fastapi-platform/quality-gates.md create mode 100644 docs/unified-fastapi-platform/real-environment-handoff.md create mode 100644 docs/unified-fastapi-platform/risk-register.md create mode 100644 docs/unified-fastapi-platform/roadmap.md diff --git a/.github/PULL_REQUEST_TEMPLATE/unified-platform.md b/.github/PULL_REQUEST_TEMPLATE/unified-platform.md new file mode 100644 index 00000000..165c0385 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/unified-platform.md @@ -0,0 +1,63 @@ +## 计划工作包 + +- 里程碑:M? +- 计划 PR:P?? +- 负责人角色: +- 依赖 PR/Commit: +- 目标分支:`refactor/unified-fastapi-platform` + +## 用户可见结果 + + + +## 范围 + +- 包含: +- 不包含: +- 临时文件所有权: + +## 契约影响 + +- [ ] 不改变公开契约 +- [ ] REST API +- [ ] OTA/设备鉴权 +- [ ] WebSocket/音频/MQTT 帧 +- [ ] 数据库/Redis/文件 +- [ ] Provider 配置或结果 + +说明: + +## 验证证据 + +```text +# 列出可重复执行的命令及结果,不要只写“测试通过”。 +``` + +- [ ] 相关 Tier A 门禁通过 +- [ ] 相关隔离集成/协议/差分通过 +- [ ] 文档和生成产物一致 +- [ ] 没有未解释的 skip、xfail 或 warning 增长 + +## 风险与回滚 + +- 风险登记项: +- 失败表现: +- 回滚方式: +- 未执行项目及原因: + +## 审阅重点 + +- [ ] 兼容性 +- [ ] 安全/密钥 +- [ ] 并发/取消/资源释放 +- [ ] 数据迁移 +- [ ] 部署/可观测性 +- [ ] 测试证据完整性 + +## 合并检查 + +- [ ] 已同步最新目标分支 +- [ ] 本 PR 的目标不是 `main` +- [ ] 实现者与 Reviewer 不是同一角色 +- [ ] PR 只包含一个计划工作包或可独立回滚切片 +- [ ] 路线图状态和证据链接将在合并后更新 diff --git a/docs/unified-fastapi-platform/README.md b/docs/unified-fastapi-platform/README.md new file mode 100644 index 00000000..a93864a3 --- /dev/null +++ b/docs/unified-fastapi-platform/README.md @@ -0,0 +1,88 @@ +# 统一 FastAPI 平台开发计划 + +状态:规划基线 + +更新时间:2026-07-20 + +## 1. 项目目标 + +把 `manager-api-fastapi`、`manager-web` 和 `xiaozhi-server` 组织成同一套可版本化、可测试、 +可部署和可回滚的平台,同时保持当前用户可见功能、设备协议和已存数据可用。 + +这里的“统一”指同一代码库、同一发布版本和同一公网入口,不要求所有职责运行在同一个 +Uvicorn worker。生产环境保留 API、实时连接和定时任务的独立进程边界,轻量环境可以使用 +单 worker 的 `all` 运行模式。 + +## 2. 完成定义 + +进入真实环境验收前,仓库必须同时满足: + +1. 管理端页面及其现有操作均由统一发行物提供。 +2. 管理 REST API、设备 OTA、WebSocket、Vision、MCP、IoT 和 MQTT 桥接协议均有自动化契约测试。 +3. 虚拟设备可以完成连接、绑定、对话、中断、工具调用、断线和重连的端到端流程。 +4. 所有 Provider 均完成接口适配和 Fake/契约验证;无需真实凭证的路径全部自动通过。 +5. MySQL、Redis、文件、配置热更新、jobs、升级和回滚均经过隔离集成测试。 +6. 统一 Docker/Compose 发行物可启动,健康检查、日志、指标和优雅停机可验证。 +7. 所有尚未验证的风险只依赖真实设备、真实外部服务或目标生产环境,并已列入交接清单。 + +达到以上条件后,项目状态为 `RC / 等待真实环境验收`,不能提前表述为生产验收完成。 + +## 3. 范围 + +包含: + +- `manager-api-fastapi` 已有管理 API、数据库、Redis、文件和 jobs 能力。 +- `manager-web` 的构建、静态交付、PWA 和浏览器业务流程。 +- `xiaozhi-server` 的设备 WebSocket、音频会话、Provider、Vision、MCP、IoT、插件和网关桥接能力。 +- 本地轻量配置模式与数据库控制台模式,但共享一套实现,不保留重复路由。 +- CI、镜像、部署、可观测性、迁移、回滚和真实测试交接。 + +不包含: + +- 改变现有业务规则或重新设计管理端产品体验。 +- 在没有凭证时声称云 Provider 已真实联调。 +- 把外部 MQTT/UDP gateway、RAGFlow 或云模型服务复制进本仓库。 +- 在没有真实 ESP32 和目标环境时批准生产上线。 + +## 4. 不可破坏的兼容边界 + +- 设备 OTA URL、请求头、响应字段及激活行为。 +- `/xiaozhi/v1/` 的 WebSocket 握手、文本消息、Opus 帧和 MQTT 桥接帧。 +- Device-ID、Client-ID、服务密钥和 HMAC Token 语义。 +- 已有数据库数据、用户权限、智能体配置、模型标识及文件资产。 +- 当前 Web、Mobile 和设备仍在使用的公开 API;内部自调用不属于兼容边界。 +- 已启用 Provider 的配置字段和可观察结果。 + +## 5. 工作原则 + +1. 先记录现状,再替换实现:没有特征测试的行为不得直接重写。 +2. 以可工作的纵向切片提交 PR,避免一次性迁移整个实时服务。 +3. 共享代码,隔离运行职责:API、realtime、jobs 可以使用同一镜像但独立启动。 +4. 新旧实现可并行对照且可回滚,删除旧入口必须是最后阶段。 +5. Provider 按能力族批量适配,默认不为每个供应商启动独立 Agent。 +6. 每个 PR 只有一个明确负责人和一个独立审阅角色。 +7. 自动化可以判断的事项不等待人工;真实环境不可替代的事项不得用 Mock 冒充通过。 + +## 6. 文档导航 + +- [目标架构](architecture.md) +- [阶段路线图与 PR 队列](roadmap.md) +- [多岗位 Agent 协作模型](agent-operating-model.md) +- [质量门禁](quality-gates.md) +- [架构与交付决策](decisions.md) +- [风险登记册](risk-register.md) +- [真实环境测试交接](real-environment-handoff.md) + +## 7. 当前基线 + +- FastAPI 管理 API 已形成 154 条 Java 路由兼容基线和现有测试报告,但逐路由直接深度差分 + 目前只覆盖 21/154;其余成功路径和副作用证据必须在 M5 前补齐。 +- manager-web 的 i18n、unit、snapshot 和生产构建已有绿色记录。 +- xiaozhi-server 可通过 Python 语法编译,但缺少正式自动化单测和设备协议回归套件。 +- FastAPI、部署文档和脚本已作为集成分支基线提交;后续重构只通过目标为该分支的 PR 进入。 +- 真实 RAGFlow、短信、语音、MQTT/MCP 和 ESP32 尚未验收。 + +项目状态以 [roadmap.md](roadmap.md) 的阶段门禁为唯一进度来源。 + +开发期间以 `refactor/unified-fastapi-platform` 为长期集成分支。所有规划和实现 PR 均合入该分支, +不会在纯 Agent 阶段向 `main` 创建 PR。 diff --git a/docs/unified-fastapi-platform/agent-operating-model.md b/docs/unified-fastapi-platform/agent-operating-model.md new file mode 100644 index 00000000..497d01bd --- /dev/null +++ b/docs/unified-fastapi-platform/agent-operating-model.md @@ -0,0 +1,118 @@ +# 多岗位 Agent 协作模型 + +## 1. 岗位与责任 + +| 岗位 | 主要责任 | 不负责 | +| --- | --- | --- | +| PM / 集成负责人 | 范围、优先级、依赖、PR 队列、风险、最终门禁 | 代替专项 Agent 编写所有业务实现 | +| 架构负责人 | 接口边界、ADR、跨模块依赖、并发和状态模型 | 未经测试直接大规模搬迁代码 | +| Realtime 工程 Agent | ASGI WebSocket、DeviceSession、音频队列和生命周期 | 修改管理业务规则 | +| Backend 工程 Agent | 应用服务、配置、数据库、Redis、bootstrap | 修改设备协议 | +| Provider 工程 Agent | 按能力族适配已有 Provider | 改变供应商可见配置语义 | +| Frontend/交付 Agent | manager-web 构建、静态托管和路由 | 重做页面产品设计 | +| Platform/SRE Agent | CI、镜像、Compose、健康、指标、升级回滚 | 在缺少证据时批准上线 | +| QA Agent | 特征测试、差分、虚拟设备、E2E、性能和故障注入 | 为使测试变绿而放宽契约 | +| 独立 Reviewer | 安全、兼容、并发、资源和证据审阅 | 与实现者共享同一结论来源 | + +## 2. 工作包准入 + +分配给 Agent 前,工作包必须明确: + +- 目标和不在范围内的事项。 +- 允许修改的目录和禁止修改的公共接口。 +- 上游依赖及其版本/提交。 +- 必须新增或保持的测试。 +- 完成命令和预期证据。 +- 需要升级给 PM 的决策点。 + +工作包模板: + +```text +目标: +用户可见结果: +允许修改: +禁止修改: +输入契约: +输出契约: +必须运行: +完成条件: +已知风险: +``` + +## 3. 资源控制 + +1. 默认使用一个实现 Agent;只有文件所有权互斥且确有关键路径收益时才并行。 +2. 同时活动的实现 Agent 不超过三个,另保留一个集成/审阅角色。 +3. 不为单个 Provider 启动一个 Agent;按能力族分组,出现特有失败时再拆分。 +4. 不让两个 Agent 重复做全仓审计。审阅 Agent 只读取 PR diff、契约和相关文件。 +5. 大型上下文按目录和接口裁剪;交接必须写入文档或 PR,不依赖聊天记忆。 +6. 长耗时集成、容器、性能测试只在相关代码变化、里程碑收口或夜间任务运行。 +7. 发现范围外缺陷时记录后移,不顺手扩张当前 PR。 + +## 4. 文件所有权与冲突避免 + +活动 PR 必须声明临时所有权: + +| 范围 | 默认岗位 | +| --- | --- | +| `app/realtime/**`、协议测试 | Realtime | +| `app/application/**`、`app/domain/**` | Architecture/Backend | +| `app/providers/**` | 对应 Provider 能力族 | +| `app/api/**`、现有 routers/services | Backend | +| `main/manager-web/**`、gateway 静态配置 | Frontend/交付 | +| Docker、Compose、CI | Platform/SRE | +| `tests/e2e/**`、虚拟设备、差分工具 | QA | +| 本目录路线图、风险和交接文档 | PM/集成 | + +需要跨所有权修改时,先由当前所有者提供最小接口,再继续实现;禁止在合并阶段才发现公共接口冲突。 + +## 5. 分支与 PR 规则 + +- 长期集成分支:`refactor/unified-fastapi-platform`;纯 Agent 阶段的开发 PR 均以它为目标。 +- 工作分支命名:`platform/-`。 +- 分支名、Commit 和 PR 标题遵守仓库禁用词要求。 +- Commit 使用结果导向格式,例如 `test: add device protocol characterization`。 +- 一个 PR 只交付一个计划工作包或一个可独立回滚的纵向切片。 +- PR 描述必须列出阶段、依赖、契约影响、验证命令、风险和回滚方法。 +- 实现者不得作为唯一 Reviewer;高风险协议、鉴权、迁移和并发 PR 必须有专项审阅。 +- 合并前同步最新目标分支并重新运行必需门禁。 +- 不允许未解释的 skip、仅本机通过、手工修改测试数据或把 Mock 结果描述成真实联调。 +- 未经项目所有者明确批准,不创建以 `main` 为目标的 PR。 + +可选 PR 模板位于 `.github/PULL_REQUEST_TEMPLATE/unified-platform.md`。 + +## 6. PR 生命周期 + +```text +Ready work package + -> implementation + local tests + -> draft PR + evidence + -> independent review + -> required CI gates + -> PM dependency/risk check + -> merge + -> roadmap evidence link +``` + +发生以下任一情况必须暂停并升级: + +- 需要改变设备公开协议或现有数据语义。 +- 需要真实凭证、真实设备或目标环境才能判断实现方向。 +- 同一测试在旧实现上也失败,且无法确定基线行为。 +- 依赖冲突要求删除现有 Provider。 +- PR 需要跨越两个以上尚未完成的里程碑。 + +## 7. Agent 交接格式 + +```text +完成内容: +变更文件: +契约变化:无 / 具体说明 +执行过的命令与结果: +未执行项目及原因: +遗留风险: +下一工作包可依赖的接口: +建议 Reviewer 重点: +``` + +没有上述交接或可重复证据的工作不进入集成分支。 diff --git a/docs/unified-fastapi-platform/architecture.md b/docs/unified-fastapi-platform/architecture.md new file mode 100644 index 00000000..ef8978d6 --- /dev/null +++ b/docs/unified-fastapi-platform/architecture.md @@ -0,0 +1,141 @@ +# 目标架构 + +## 1. 架构决策 + +统一平台采用“模块化单体代码库、按职责运行”的结构: + +```text +Public HTTP/WSS + | + v +Gateway / static web + | | | + | | +--> /mcp/vision/explain + | +--------------------> /xiaozhi/v1/ -> realtime + +-------------------------------> /xiaozhi/* -> api + +api ----------- application services -------- database / redis / object files +realtime ------ application services -------- provider adapters +jobs ---------- application services -------- scheduled work +``` + +同一发布版本提供四个角色: + +| 角色 | 职责 | 扩缩容方式 | +| --- | --- | --- | +| `gateway` | manager-web、TLS、静态缓存、HTTP/WS 路由 | 无状态横向扩展 | +| `api` | 管理 REST、OTA、文件和内部服务端 API | 多 worker/多副本 | +| `realtime` | 设备 WebSocket、音频会话、Vision、Provider 和工具 | 按连接与模型容量扩展 | +| `jobs` | 定时同步、清理和异步补偿 | Redis 租约保证单任务所有权 | + +开发环境可以用一个命令启动全部角色;生产环境不得要求 realtime 与 API 共享 worker。 + +## 2. 建议代码边界 + +```text +main/manager-api-fastapi/ +├── app/ +│ ├── api/ # HTTP 路由和请求适配 +│ ├── application/ # 用例服务;HTTP、WS、jobs 共用 +│ ├── domain/ # 稳定业务对象和接口 +│ ├── realtime/ # ASGI WebSocket、会话和协议 +│ ├── providers/ # VAD/ASR/LLM/VLLM/TTS/Memory/Intent/Tools +│ ├── infrastructure/ # MySQL、Redis、文件、外部客户端 +│ └── jobs/ +├── web/ # manager-web 构建集成或其产物约定 +├── tests/ +│ ├── unit/ +│ ├── contract/ +│ ├── integration/ +│ ├── protocol/ +│ └── e2e/ +└── deploy/ +``` + +迁移期间允许现有目录继续存在;目录调整必须跟随可运行的纵向切片,不做只有移动文件的超大 PR。 + +## 3. 关键内部接口 + +### 3.1 应用服务 + +Realtime 不再通过 HTTP 调用同一平台。以下能力通过应用服务接口复用: + +- 获取全局配置和设备专属 Agent 配置。 +- 设备绑定、激活、在线状态和通讯录查找。 +- 聊天记录、音频、摘要、标题和工具调用上报。 +- OTA、文件和参数读取。 + +HTTP 只是这些服务的一个适配器。服务方法不接收 FastAPI `Request`,也不返回 HTTP Response。 + +### 3.2 实时会话 + +每个连接由一个 `DeviceSession` 拥有,至少包含: + +- 握手元数据与设备鉴权。 +- 有界输入/输出音频队列。 +- 文本协议路由。 +- VAD/ASR/LLM/TTS/工具调用任务。 +- 取消、超时、断线保存和资源关闭。 + +使用 ASGI WebSocket 抽象,不让 Provider 依赖 Starlette 或 `websockets.ServerConnection`。 + +### 3.3 Provider + +Provider 通过能力协议注册,配置标识保持现状。同步 SDK 必须通过受限线程池或专用执行器调用, +禁止在事件循环中直接进行阻塞网络或长时间 CPU 工作。 + +Provider 按以下能力族迁移: + +1. VAD + ASR。 +2. LLM + VLLM + Memory + Intent。 +3. TTS。 +4. Tools + MCP + IoT + 插件。 + +本地 Torch/FunASR/Sherpa 等能力作为可选依赖组和镜像 profile,基础 API 镜像不强制加载模型。 + +## 4. 配置与控制面 + +- 数据库是完整模式下的配置事实来源。 +- Redis 保存有版本号的缓存,并通过 Pub/Sub 广播配置失效和控制事件。 +- worker 原子替换共享配置;现有会话可完成当前轮次,新会话使用新版本。 +- `server.secret`、SM2 密钥和其他必需系统参数由并发安全的 bootstrap 初始化。 +- 进程重启交给容器编排或服务管理器,业务代码不自行 fork、spawn 或 `os._exit()`。 +- 轻量模式使用文件配置适配器,但进入相同应用服务,不复制 OTA 或会话实现。 + +## 5. 路由与兼容策略 + +| 公共入口 | 所有者 | 迁移策略 | +| --- | --- | --- | +| `/` | manager-web | 构建产物由 gateway 托管,保留 PWA scope | +| `/xiaozhi/*` | api | 保留当前调用方契约 | +| `/xiaozhi/ota/` | api | 完整模式只保留数据库驱动实现 | +| `/xiaozhi/v1/` | realtime | 保持设备协议,gateway 支持 Upgrade | +| `/mcp/vision/explain` | realtime | 独立设备鉴权域,不继承管理用户鉴权 | + +迁移期可以继续监听 8000/8002/8003 作为兼容别名;最终公网地址由 gateway 统一,OTA 返回值和 +系统参数必须在切换前验证。 + +## 6. 部署档位 + +### Lite + +- 单 worker。 +- 文件或数据库配置。 +- 可将 API、realtime 和 jobs 放在同一进程用于本地体验。 +- 不作为生产容量结论的依据。 + +### Production + +- gateway、API、realtime、jobs 独立进程或容器。 +- 共享 MySQL、Redis 和明确的持久化卷。 +- realtime 按模型内存和连接数单独扩容。 +- 发布时先摘流,等待连接排空,再终止旧实例。 + +## 7. 架构完成门禁 + +- 公开契约清单有可执行测试。 +- API 与 realtime 不通过环回 HTTP 互调。 +- 多 realtime worker 的配置更新能够广播到全部实例。 +- realtime 停止时不产生孤儿线程、遗留任务或自行启动的新进程。 +- Lite 与 Production 使用相同业务实现。 +- 旧 xiaozhi-server 入口只有在新实现通过全部自动门禁后才能删除。 diff --git a/docs/unified-fastapi-platform/decisions.md b/docs/unified-fastapi-platform/decisions.md new file mode 100644 index 00000000..858ecf63 --- /dev/null +++ b/docs/unified-fastapi-platform/decisions.md @@ -0,0 +1,82 @@ +# 架构与交付决策 + +本文件记录跨 PR 的稳定决策。普通实现 PR 不得顺手改变已接受决策;需要变更时,先提交新的 +决策记录并说明替代关系。 + +## D001:统一代码库,按职责运行 + +- 状态:Accepted +- 决策:gateway、API、realtime 和 jobs 使用同一发布版本,但生产环境独立运行。 +- 原因:REST、长连接、模型内存和定时任务的扩缩容及故障边界不同。 +- 后果:允许 Lite 单 worker `all` 模式;生产容量不得由 Lite 推断。 +- 重新评估:有证据证明单进程能够满足模型内存、多 worker 配置一致性和故障隔离。 + +## D002:只冻结外部行为 + +- 状态:Accepted +- 决策:设备、调用方、数据和已启用 Provider 的可观察行为保持;内部类、库、线程模型、目录和 + 自调用方式可以重构。 +- 原因:目标是保留现有功能,不保留实现偶然性。 +- 后果:manager-web 与后端可以协同调整内部接口,但设备固件契约必须保持。 +- 重新评估:产品所有者批准公开行为变更并提供迁移方案。 + +## D003:特征测试先于 realtime 重构 + +- 状态:Accepted +- 决策:M1 的黄金报文、虚拟设备和 Fake Provider 是 ASGI 会话重构的前置条件。 +- 原因:xiaozhi-server 当前没有正式协议回归套件。 +- 后果:不能以“代码更整洁”为由跳过旧行为记录。 +- 重新评估:无。 + +## D004:应用服务替代内部 HTTP 自调用 + +- 状态:Accepted +- 决策:完整模式下 API 与 realtime 共享应用服务端口,不通过环回 HTTP 调用自己。 +- 原因:减少密钥复制、网络重试和同进程/多进程语义差异。 +- 后果:HTTP router 只负责协议适配,长连接不持有数据库 Session。 +- 重新评估:跨语言或跨安全域部署成为明确需求。 + +## D005:Redis 承担配置版本事件,不承担事实来源 + +- 状态:Accepted +- 决策:数据库是完整配置事实来源;Redis 缓存有版本的快照并广播失效/控制事件。 +- 原因:支持多 realtime worker 一致更新和 Java 回滚期兼容。 +- 后果:配置事件必须可观测,worker 必须暴露当前版本。 +- 重新评估:引入独立且受运维支持的消息系统。 + +## D006:Provider 按能力族迁移 + +- 状态:Accepted +- 决策:按 VAD/ASR、LLM/VLLM/Memory/Intent、TTS、Tools/MCP/IoT 四组迁移。 +- 原因:限制 Agent 数量、统一契约并避免每个供应商重复搭建测试框架。 +- 后果:只有出现供应商特有阻塞时才拆分单独工作包。 +- 重新评估:某 Provider 需要独立进程或不可兼容的系统依赖。 + +## D007:集成分支承载全部开发 PR + +- 状态:Accepted +- 决策:纯 Agent 阶段所有 PR 目标为 `refactor/unified-fastapi-platform`。 +- 原因:项目所有者要求开发 PR 不进入主分支,并需要统一的长期集成点。 +- 后果:PM 负责持续同步上游并在每个里程碑重跑消费者与协议清单。 +- 重新评估:仅由项目所有者明确批准。 + +## D008:真实环境是独立验收门 + +- 状态:Accepted +- 决策:ESP32、真实 Provider、MQTT/RAGFlow 和目标网络只能在 M8 判定。 +- 原因:Mock 和模拟不能证明硬件、供应商及生产网络事实。 +- 后果:M7 可以形成 RC,但不能发布正式版本或描述为生产通过。 +- 重新评估:所需真实资产已经安全接入自动化环境。 + +## 新决策模板 + +```text +ID / 日期 / 状态 +背景: +决策: +备选方案: +后果: +验证方式: +重新评估触发条件: +Owner / 关联 PR: +``` diff --git a/docs/unified-fastapi-platform/quality-gates.md b/docs/unified-fastapi-platform/quality-gates.md new file mode 100644 index 00000000..4513ed56 --- /dev/null +++ b/docs/unified-fastapi-platform/quality-gates.md @@ -0,0 +1,117 @@ +# 质量门禁 + +## 1. 原则 + +自动测试负责证明“实现符合可观察的现有行为”;真实测试负责证明“设备、供应商和生产网络确实 +按预期工作”。两类证据不得互相替代。 + +## 2. 测试层次 + +| 层次 | 目标 | 典型内容 | 运行时机 | +| --- | --- | --- | --- | +| 静态 | 快速发现格式、类型、依赖问题 | Ruff、Mypy、前端 lint/type、配置校验 | 每次提交 | +| 单元 | 验证纯逻辑与状态转换 | Token、协议解析、队列、配置版本、Provider DTO | 每次提交 | +| 特征/契约 | 冻结现有可观察行为 | 旧服务黄金报文、API envelope、设备帧、Provider 请求 | 每个 PR | +| 隔离集成 | 验证真实本地依赖 | MySQL、Redis、文件、jobs、Pub/Sub、事务 | 每个相关 PR | +| 模拟 E2E | 验证用户和设备流程 | manager-web、虚拟设备、Fake Provider、统一 gateway | 每个里程碑 | +| 差分 | 比较旧/新实现 | REST、OTA、WS 会话和副作用 | M1 起持续运行 | +| 非功能 | 容量和恢复 | 多连接、背压、断线、摘流、资源泄漏、安全 | M6/M7 | +| 真实环境 | 外部事实 | ESP32、云 Provider、MQTT/RAGFlow、目标部署 | M8 | + +## 3. CI 分层 + +### Tier A:快速门禁 + +目标是在常规 PR 中快速反馈,建议控制在 10 分钟内: + +- FastAPI Ruff、Mypy、unit/contract pytest。 +- manager-web i18n、unit、snapshot。 +- xiaozhi-server/迁移代码语法与导入检查。 +- 路由、消费者和生成文档一致性。 +- Secret 扫描和部署配置静态检查。 + +从 P01 建立覆盖率基线后,变更行覆盖率不得低于 85%,协议解析和会话状态机的分支覆盖率 +不得低于 90%,全局覆盖率不得下降。覆盖率用于发现遗漏,不允许为了数字制造无行为价值的测试。 + +### Tier B:PR 集成门禁 + +- 隔离 MySQL/Redis。 +- manager-web 生产构建及浏览器关键路径。 +- 虚拟设备完整对话流程。 +- Fake Provider 覆盖成功、超时、断流、取消和错误映射。 +- API/realtime/jobs 镜像构建与 Compose readiness。 +- 修改范围对应的旧/新差分。 + +### Tier C:里程碑门禁 + +- 全量旧/新差分。 +- 多 realtime worker 配置广播。 +- 并发连接和 60 分钟模拟 soak。 +- 优雅摘流、进程终止、Redis/MySQL 短暂故障恢复。 +- 依赖漏洞、鉴权边界和恶意输入测试。 +- 支持架构的镜像构建或至少可重复的构建证明。 + +Tier C 不在每个小 PR 重复运行,以节约资源;相关核心代码变化或阶段收口时必须运行。 + +性能采用相同 runner 上的新旧实现相对比较。初始自动门槛为: + +- Fake Provider 下业务错误率为 0。 +- WebSocket 握手和控制消息 p95 回退不超过 15%。 +- 可完成会话吞吐回退不超过 10%。 +- 每个 realtime PR 运行 20 个虚拟连接、5 分钟;RC 运行 100 个虚拟连接、60 分钟。 +- 测试结束后 RSS、线程、async task、文件描述符和临时文件不得持续线性增长。 + +这些指标只约束模拟回归,不代表真机容量结论;如固定测试机不足,PR 必须记录实际档位,不能 +静默降低门槛。 + +## 4. 必须建立的协议场景 + +虚拟设备测试至少覆盖: + +1. OTA 获取 WebSocket/MQTT 信息和未绑定激活码。 +2. WebSocket header 与 query 参数两种握手。 +3. hello、listen、abort、ping、iot、mcp、server 控制消息。 +4. Opus 音频输入、ASR 文本、LLM 流、TTS 文本及音频输出。 +5. 唤醒、连续对话、主动中断、无语音超时。 +6. 设备绑定前后的行为。 +7. Provider 超时、断流、无内容、限流和取消。 +8. 客户端断线、服务摘流和重连。 +9. MQTT gateway 16 字节桥接帧的编码与解码。 +10. 配置更新只影响约定的当前或后续会话。 + +黄金数据必须脱敏、可提交且带版本说明。不能从一次偶然运行直接认定为规范;旧代码、文档和至少 +一个调用方必须交叉确认。 + +## 5. PR 合并门禁 + +所有 PR: + +- 计划工作包和文件所有权明确。 +- 新行为有测试,重构行为有特征/差分证据。 +- 相关 Tier A 全绿。 +- 无未解释 skip、xfail、warning 激增或生成文件漂移。 +- 文档和配置随行为同步。 +- 回滚方法明确。 + +高风险 PR 额外要求: + +- 设备协议:协议 Reviewer + 虚拟设备差分。 +- 鉴权/密钥:Security Reviewer + 失败路径和密钥泄露检查。 +- 数据迁移:全新库、已有库、重复执行和回滚测试。 +- 并发/任务:取消、超时、资源关闭和故障注入。 +- Provider 公共接口:所有能力族契约测试通过。 + +## 6. RC 自动化退出条件 + +只有满足以下全部条件,才能转入真实测试: + +- 所有计划 PR P00-P12 已合并或明确取消并记录理由。 +- 公开兼容边界全部关联到自动测试。 +- 虚拟设备和 manager-web E2E 全绿。 +- 所有 Provider 适配器通过 Fake/契约矩阵。 +- 没有 P0/P1 内部缺陷;P2 风险有接受或后续方案。 +- 统一发行物在干净环境完成安装、升级和回滚。 +- 模拟负载下没有无界内存、线程、任务或文件增长。 +- 未验证项逐条映射到真实环境交接用例。 + +满足这些条件代表“纯 Agent 阶段完成”,不代表真实 Provider 或硬件已经通过。 diff --git a/docs/unified-fastapi-platform/real-environment-handoff.md b/docs/unified-fastapi-platform/real-environment-handoff.md new file mode 100644 index 00000000..5c61e9e4 --- /dev/null +++ b/docs/unified-fastapi-platform/real-environment-handoff.md @@ -0,0 +1,90 @@ +# 真实环境测试交接 + +## 1. 何时交接 + +只有 [质量门禁](quality-gates.md) 的 RC 自动化退出条件全部满足,才进入本清单。以下情况不属于 +真实环境阻塞,必须由开发阶段解决: + +- 本地依赖无法安装或镜像无法构建。 +- 虚拟设备协议不一致。 +- Fake Provider 成功/错误/取消契约失败。 +- 数据库、Redis、文件权限或配置广播失败。 +- 缺少测试脚本、日志字段或复现步骤。 + +## 2. 外部资产 + +| 资产 | 最低要求 | 提供方 | +| --- | --- | --- | +| ESP32 | 至少一台生产使用型号;记录固件版本 | Hardware QA | +| 网络 | 局域网与公网 WSS;可控制弱网/断网 | Ops/QA | +| 模型凭证 | 实际计划启用的 ASR、LLM、TTS,必要时 VLLM | Service owner | +| MQTT/UDP | 受支持版本的 gateway、broker 和端口 | Integration/Ops | +| RAGFlow | 受支持版本、测试数据集和访问凭证 | Knowledge owner | +| 可选服务 | 短信、声纹、语音克隆、MCP、Memory | 对应服务 owner | +| 目标主机 | 计划上线的 CPU/GPU/架构、Docker/Compose 或编排平台 | Ops | +| 域名证书 | HTTPS/WSS 域名、证书和反向代理权限 | Ops | + +凭证不得写入 Issue、PR、测试产物或仓库;通过部署环境的 Secret 管理提供。 + +## 3. 必测场景 + +### 设备与音频 + +- 首次启动、OTA、激活和绑定。 +- WebSocket 鉴权和长连接保持。 +- 唤醒、单轮/连续对话、打断、静音超时和重连。 +- 真实麦克风、扬声器、AEC、Opus 帧节奏和中文/非中文语音。 +- 弱网、高延迟、短时断网和服务滚动发布。 + +### Provider + +- 每个计划启用 Provider 的成功、流式、空结果、超时、限流和凭证错误。 +- ASR 音频格式、TTS 音频参数、LLM 工具调用及取消行为。 +- 供应商控制台侧请求量、错误和费用符合预期。 + +### 外部集成 + +- MQTT/UDP 上下行音频与控制消息。 +- RAGFlow 上传、解析、检索、删除和故障补偿。 +- Vision 图片上传、鉴权、大小/格式限制和真实结果。 +- 按实际启用范围验证短信、声纹、语音克隆、MCP 和通讯录呼叫。 + +### 部署 + +- 全新安装、已有数据升级、滚动发布和回滚。 +- 非 root 文件权限、模型卷、上传卷和日志采集。 +- API、realtime、jobs 独立健康与告警。 +- 目标容量下的连接数、CPU/GPU、内存、带宽和响应时间。 + +## 4. 证据格式 + +每条真实用例记录: + +```text +Case ID: +日期/测试人: +硬件与固件: +服务版本/Commit: +外部服务及版本: +网络与部署环境: +步骤: +预期: +实际: +日志/指标/录屏位置: +结果:Pass / Fail / Blocked +缺陷链接: +``` + +敏感字段在上传前脱敏。失败必须能关联到服务器会话 ID、设备 ID 的脱敏标识和时间窗口。 + +## 5. 上线判定 + +生产批准至少要求: + +- 选定 ESP32/固件矩阵通过。 +- 实际启用的 Provider 和外部集成通过,不要求未启用供应商全部真实联调。 +- 目标环境升级与回滚演练通过。 +- 没有 P0/P1 缺陷。 +- 监控、告警、值守和回滚负责人明确。 + +未提供的外部能力应标记为“未验收/不可启用”,不得以自动化 Mock 结果改为 Pass。 diff --git a/docs/unified-fastapi-platform/risk-register.md b/docs/unified-fastapi-platform/risk-register.md new file mode 100644 index 00000000..35f085c9 --- /dev/null +++ b/docs/unified-fastapi-platform/risk-register.md @@ -0,0 +1,27 @@ +# 风险登记册 + +| ID | 风险 | 概率/影响 | 缓解措施 | 触发升级条件 | Owner | +| --- | --- | --- | --- | --- | --- | +| R01 | xiaozhi-server 缺少正式协议测试,重构造成隐性漂移 | 高/高 | M1 先建立黄金报文、虚拟设备和旧/新差分 | 无法从旧代码和调用方确定行为 | QA + Realtime | +| R02 | REST API worker 与实时模型共享进程导致内存和延迟失控 | 高/高 | 同代码库、独立运行角色;Lite 仅单 worker | 生产方案要求单进程多 worker | Architecture | +| R03 | `websockets`、PyYAML 及重模型依赖冲突 | 高/高 | 统一锁文件、Provider extras、镜像 profile | 必须删除现有 Provider 才能解析 | Platform + Provider | +| R04 | `server.secret`/SM2 首次初始化或轮换不一致 | 高/高 | 并发安全 bootstrap、单一事实来源、广播测试 | 任一 worker 使用不同密钥 | Backend + Security | +| R05 | 配置热更新只到达部分 realtime worker | 中/高 | Redis 版本事件、ack/指标、全 worker 集成测试 | 版本长时间不一致 | Backend + SRE | +| R06 | 线程、任务或 SDK 阻塞事件循环 | 高/高 | DeviceSession 所有权、有界执行器、soak/lag 指标 | 负载下 API/WS 延迟无界增长 | Realtime + QA | +| R07 | manager-web Service Worker 缓存旧 API/资源 | 中/中 | 保留 scope、版本化资源、升级 E2E | 新旧前端混用造成不可恢复错误 | Frontend | +| R08 | OTA 双实现或公网 URL/端口切换破坏旧固件 | 中/高 | 完整/轻量 profile、兼容别名、OTA 差分 | 需要升级固件才能连接 | Architecture + QA | +| R09 | 本地模型文件、FFmpeg、libopus 和写目录未正确打包 | 高/中 | 显式卷、非 root 权限、profile 构建测试 | 干净容器无法启动选定能力 | Platform | +| R10 | Mock 掩盖真实供应商流式和错误行为 | 高/高 | Fake 只证明契约;M8 真实矩阵单独验收 | 需要凭证才能决定公共设计 | QA + External QA | +| R11 | MQTT/UDP gateway、RAGFlow 等外部项目版本漂移 | 中/高 | 固定支持版本、录制契约、真实交接清单 | 外部接口文档与实际不一致 | Integration | +| R12 | 上游 `main` 持续变化导致长分支难以合并 | 高/中 | 小 PR、每次合并后变基、每阶段重跑调用方清单 | 冲突改变公共契约 | PM/集成 | +| R13 | PR 并行过多造成重复实现和冲突 | 中/中 | 最多三个实现工作包、文件所有权、唯一负责人 | 两个 PR 修改同一协议核心 | PM/集成 | +| R14 | 现有未跟踪 FastAPI 基线没有进入远端 | 高/高 | P00 优先提交并建立 PR | 后续 Agent 无稳定基线 | PM/集成 | + +## 风险处理规则 + +- P0:立即停止受影响工作包,PM 和架构负责人决策。 +- P1:不得合并相关 PR,必须有修复或明确的外部阻塞证据。 +- P2:可以带风险进入后续阶段,但必须有 Owner、验证计划和截止阶段。 +- 外部阻塞:只有满足 [真实环境测试交接](real-environment-handoff.md) 的定义才能标记,不能把内部未完成项转嫁给真实测试。 + +每个里程碑收口时重新评估概率、影响和 Owner;关闭风险必须附测试、PR 或决策记录链接。 diff --git a/docs/unified-fastapi-platform/roadmap.md b/docs/unified-fastapi-platform/roadmap.md new file mode 100644 index 00000000..b6da9a4b --- /dev/null +++ b/docs/unified-fastapi-platform/roadmap.md @@ -0,0 +1,90 @@ +# 阶段路线图与 PR 队列 + +## 1. 里程碑 + +| 阶段 | 目标 | 主要交付物 | 负责人角色 | 依赖 | 退出门禁 | +| --- | --- | --- | --- | --- | --- | +| M0 基线 | 建立可审阅的 FastAPI 与计划基线 | 当前实现、兼容报告、计划文档、首个 PR | PM/集成 | 无 | 基线测试可重复,变更范围清楚 | +| M1 可执行契约 | 把“现有功能”转换成测试资产 | 协议清单、黄金报文、虚拟设备、Fake Provider | QA + Realtime | M0 | 旧服务完整模拟会话可重复 | +| M2 统一发行入口 | 纳入 manager-web 与统一网关 | 前端构建、静态托管、路由、统一 Compose | Platform + Frontend | M0 | 页面/API/WS 路由冒烟通过 | +| M3 共享核心 | 消除配置和业务能力的内部 HTTP 自调用 | bootstrap、应用服务接口、配置版本与广播 | Backend + Architecture | M1 | API/旧 realtime 均可使用共享接口 | +| M4 ASGI 实时内核 | 建立不依赖真实 Provider 的新会话运行时 | WebSocket 适配、DeviceSession、背压、取消和鉴权 | Realtime | M1、M3 | Fake 全会话与旧协议一致 | +| M5 Provider 迁移 | 接回全部现有能力 | 四个 Provider 能力族适配、契约测试 | Provider 专项 | M4 | 所有 Provider 可构造且契约通过 | +| M6 平台硬化 | 达到可部署候选质量 | 多进程、优雅摘流、指标、安全、负载和故障测试 | Platform + QA | M2、M4、M5 | 自动质量门禁全部绿色 | +| M7 切换准备 | 删除自动化范围内的未知项 | 新旧差分、升级/回滚演练、旧入口弃用方案 | PM + Reviewer | M6 | 只剩真实环境清单中的阻塞项 | +| M8 真实验收 | 外部人员/环境介入 | ESP32、真实 Provider、MQTT/RAGFlow、目标环境报告 | External QA/Ops | M7 | 不属于纯 Agent 阶段 | + +## 2. 推荐 PR 队列 + +PR 必须按可独立验证的纵向能力拆分。编号是计划标识,不是 GitHub 实际编号。 + +| 计划 PR | 内容 | 建议目标分支 | 可并行关系 | +| --- | --- | --- | --- | +| P00 | 开发计划、Agent 协作和质量门禁 | `refactor/unified-fastapi-platform` | FastAPI 基线直接推送后创建 | +| P01 | CI 快速门禁和测试目录重组 | `refactor/unified-fastapi-platform` | 与 P02 并行 | +| P02 | manager-web 构建、gateway 路由和统一 Compose | 同上 | 与 P01 并行 | +| P03 | 设备协议清单、黄金报文和虚拟设备 | 同上 | 与 P02 并行 | +| P04 | 系统密钥 bootstrap、共享配置接口和版本事件 | P01 + P03 | 阻塞 P06 | +| P05 | 聊天/设备配置等内部 HTTP 调用改为应用服务端口 | P04 | 可按用例拆成两个 PR | +| P06 | ASGI WebSocket 握手、鉴权和协议适配层 | P03 + P04 | 与 P05 后半段并行 | +| P07 | DeviceSession 生命周期、队列、取消和 Fake 对话链路 | P06 | 阻塞 Provider 迁移 | +| P08-A | VAD/ASR Provider 适配 | P07 | 与 P08-B/C 并行 | +| P08-B | LLM/VLLM/Memory/Intent 适配 | P07 | 与 P08-A/C 并行 | +| P08-C | TTS Provider 适配 | P07 | 与 P08-A/B 并行 | +| P09 | Tools/MCP/IoT/插件及 Vision | P08-B | 可与 P08 收尾并行 | +| P10 | 配置广播、管理控制、优雅摘流与健康指标 | P07 + P08 | 与 P09 并行 | +| P11 | 全栈模拟 E2E、新旧差分和负载/故障测试 | P02 + P09 + P10 | 集成收口 | +| P12 | 发行、升级、回滚、弃用和真实测试交接 | P11 | 纯 Agent 最后一个 PR | + +所有开发 PR 默认以长期集成分支 `refactor/unified-fastapi-platform` 为目标。存在未合并依赖时使用 +堆叠 PR;依赖合并后及时变基到最新集成分支。纯 Agent 阶段不向 `main` 创建 PR;真实环境验收 +完成后,也只有在项目所有者明确批准时才讨论主分支集成。不得让多个 PR 同时修改同一协议核心文件。 + +## 3. 建议容量分配 + +以下比例用于分配 Agent 和审阅资源,不是完成度承诺: + +| 工作域 | 参考占比 | 原因 | +| --- | ---: | --- | +| manager-web 与 gateway | 15% | 构建已可用,主要缺静态交付和浏览器 E2E | +| manager-api 深度兼容与共享服务 | 25% | 路由齐全,但成功写入、副作用和 bootstrap 仍需补强 | +| realtime、会话与 Provider | 45% | 缺少协议测试,且存在线程、模型和长连接重构 | +| CI、部署、安全与交接 | 15% | 需要从零建立 PR 门禁和统一发行证据 | + +容量应随风险登记和测试证据调整,不按代码行数机械分配。 + +## 4. 并行执行窗口 + +为控制资源和冲突,同一时间最多开放三个实现工作包: + +1. 一个核心依赖链工作包,例如 P04/P06/P07。 +2. 一个交付或前端工作包,例如 P02/P10。 +3. 一个测试/独立审阅工作包,例如 P03/P11。 + +Provider 阶段允许三个能力族并行,但每个能力族只分配一个实现 Agent;共享接口由架构负责人 +预先冻结,任何接口变更先更新 ADR 和契约测试。 + +## 5. 阶段状态规则 + +每个阶段只有四种状态: + +- `Not started`:依赖未完成。 +- `Ready`:依赖完成且工作包说明已批准。 +- `In progress`:已有唯一负责人和活动 PR。 +- `Done`:PR 合并且退出门禁有证据链接。 + +不得使用“代码写完”代替 `Done`。失败、跳过、未执行和缺少外部环境必须分别记录。 + +## 6. 每周/每轮进度摘要 + +```text +当前阶段: +已合并 PR: +活动 PR(负责人 / 门禁): +本轮新增证据: +阻塞项(内部 / 真实环境): +风险变化: +下一轮最多三个工作包: +``` + +路线图由 PM/集成负责人维护;实现 Agent 只更新自己 PR 的证据和工作包状态。 diff --git a/main/manager-api-fastapi/README.md b/main/manager-api-fastapi/README.md index 8e60e536..94e0a5ee 100644 --- a/main/manager-api-fastapi/README.md +++ b/main/manager-api-fastapi/README.md @@ -36,3 +36,8 @@ uv run python scripts/extract_java_routes.py --output compatibility/java-routes. Migration, container, differential-contract, and cutover instructions are maintained in the repository-level migration documents under `docs/manager-api-fastapi-*.md`. + +The cross-module plan for integrating manager-web and the xiaozhi-server realtime runtime is +maintained in `docs/unified-fastapi-platform/README.md`. It defines the staged PR queue, agent +ownership, automated quality gates, and the boundary where real hardware and external service +validation become mandatory.