# ai-customer-service 最新审查报告(2026-05-06) > 审查时间:2026-05-06 > 代码基线:`ee3a31e77c00d47802e7b3a54057467b3a713400` > 审查方式:小龙主审 + 双视角 QA 复核 + 现有门禁文档对照 > 目标:给出当前代码与放行状态的真实结论,回收过期结论,并把问题转成可执行整改基线。 > 配套任务板:`docs/REMEDIATION_TASK_BOARD_2026-05-06.md` --- ## 0. 阶段门控结论 ### 总结论 - **代码级门禁:PARTIAL / 不稳定** - **sub2api 单平台主链:PASS WITH RISKS** - **newapi 平台能力:FAIL** - **真实共享预生产 Gate B:FAIL** - **生产灰度 Gate C:FAIL** ### 是否可进入下一阶段 - **是否可按“整体生产可上线”口径放行:否** - **是否可按“多平台能力已完成”口径汇报:否** - **是否可按“sub2api 单平台代码级链路已可用”口径汇报:是,但必须同时声明关键风险与未完成门禁** ### 当前最小可接受口径 1. 代码级门禁已通过 2. sub2api 的 webhook → outbox → callback worker 主链已接通 3. newapi 当前未通过,不应按已接入汇报 4. 真实共享预生产 / 灰度环境证据未闭环,因此不能按生产可上线口径放行 --- ## 1. 审查输入与证据来源 ### 1.1 已读取的关键代码 - `cmd/ai-customer-service/main.go` - `internal/app/app.go` - `internal/http/router.go` - `internal/http/handlers/platform_webhook_handler.go` - `internal/http/handlers/platform_webhook_security.go` - `internal/platformadapter/sub2api_adapter.go` - `internal/platformadapter/newapi_adapter.go` - `internal/service/platformevents/builder.go` - `internal/service/platformdelivery/worker.go` - `internal/store/postgres/platform_event_store.go` ### 1.2 已读取的关键文档 - `docs/CODE_REVIEW_REPORT.md` - `docs/RECTIFICATION_REVIEW_REPORT_V2.md` - `docs/REVIEW_REPORT_2026-05-04.md` - `docs/P0_P1_P2_RECTIFICATION_EXECUTION_BOARD.md` - `docs/PRODUCTION_LAUNCH.md` - `test/QA_GATE_STATUS.md` - `prd/PRODUCTION_CHECKLIST.md` ### 1.3 已采纳的实测依据 - 本轮主审曾捕获两次 `go test ./...` 失败信号: - `test/e2e/sub2api_callback_flow_test.go:186` - 一次实际 `event[0].type = message.processing`,预期 `message.received` - 本轮复核再次实际 `event[0].type = reply.generated`,预期 `message.received` - 两次都伴随 `platform callback event delivery failed` 与 `sql: database is closed` - 曾有并行 QA 复核在当时现态仓库上复跑 `go test ./... -count=1`:通过 - 但本轮再次实测 `go test ./... -count=1`:失败 - 因此当前最真实口径应为:`go build ./...`、`go vet ./...` 通过;`go test ./...` 存在不稳定失败,代码级门禁不能再写成稳定 PASS ### 1.4 证据解释原则 - `go build ./...`、`go vet ./...` 当前可支持通过结论 - `go test ./...` 当前不能稳定支持通过口径,应视为不稳定失败状态 - 真实失败信号不能被抹掉,应作为当前事实与稳定性风险保留 - 不以历史报告或角色自报覆盖当前代码与命令事实 --- ## 2. 当前真实状态 ### 2.1 已成立的事实 1. `sub2api` 主链路已真实接通,不是只有定义没有调用 2. `newapi` 不是“待联调”,而是“入口未实现但装配可开”的未通过状态 3. 代码级门禁与本地/仓库内验证不能等同于真实预生产或生产放行 4. 当前最主要的阻塞,不再是早期报告中的旧 P0,而是: - 平台能力口径失真 - callback / outbox 一致性与扩展性边界未收口 - 真实环境放行证据未闭环 ### 2.2 已不应继续沿用的旧结论 以下表述对当前代码已不再成立,不应继续作为“当前事实”引用: 1. `RateLimiter` 存在 P0 并发写问题 2. ticket resolve/close 不区分不存在与状态冲突 3. 后台接口“完全无鉴权” 4. prod 默认仍可 fallback 到 memory 5. readiness 相关生产约束仍未收紧 说明: - 这些项在旧报告中曾成立或部分成立,但已与当前代码和现有门禁文档不一致 - 继续引用会造成报告漂移 ### 2.3 仍然成立的高层判断 1. 当前项目还不是完整 PRD 意义上的完整 AI 客服系统 2. 当前不能按“整体生产可上线”口径放行 3. 文档漂移仍是风险,只是漂移重心已经从早期代码 P0 转向旧报告口径过期 --- ## 3. 关键调用链路核查 ### 3.1 sub2api 主链路核查 #### 结论 - **PASS WITH RISKS** #### 四层核查 1. 定义 - `PlatformAdapter` 接口存在 - `Sub2APIAdapter` 已实现 - `Worker`、`PlatformEventStore`、event builder 均存在 2. 装配 - `internal/app/app.go` 会在配置开启时注册 `sub2api` adapter - 在 `platformEvents != nil` 且配置满足时启动 `sub2api` worker 3. 调用 - `router` → `PlatformWebhookHandler` - `PlatformWebhookHandler` → `registry.Resolve(platform)` → adapter `ParseInbound` - `dialog.Process` 后进入 `BuildInboundEvents` - `InsertPendingBatch` 写入 outbox - worker `RunOnce` / `deliver` 发起 callback 4. 入口 - `/api/v1/customer-service/platforms/sub2api/webhook` #### 结论解释 - 这条链路是实链路,不是“有结构、没接线” - 但它仍然带有一致性、并发和稳定性风险,不能直接放大为“平台回调系统已生产级完成” ### 3.2 newapi 主链路核查 #### 结论 - **FAIL** #### 直接证据 1. `internal/platformadapter/newapi_adapter.go:20-21` - `ParseInbound` 直接返回 `501 not implemented` 2. `internal/app/app.go:129-130` - 当 `cfg.PlatformAdapters.NewAPI.Enabled` 时,仍会注册 `newapi` adapter 3. `internal/app/app.go:186-187` - `startWorker("newapi", cfg.PlatformAdapters.NewAPI)` 仍可能启动 `newapi` callback worker #### 结论解释 - 当前状态不是“newapi 已接通但未验证”,而是“配置上看似支持,真实入口未实现” - 这是典型 `call_chain_gap + implementation_gap` --- ## 4. 自动化与验证结果结论 | 检查项 | 结论 | 说明 | |---|---|---| | 代码级门禁 | PARTIAL / 不稳定 | `go build ./...`、`go vet ./...` 当前通过;`go test ./... -count=1` 本轮再次失败于 `test/e2e/sub2api_callback_flow_test.go:186` | | sub2api 主链存在性 | PASS | 入口、调用、outbox、worker 四层均可追踪 | | newapi 平台能力 | FAIL | 入口未实现但装配仍可打开 | | callback worker 基本投递能力 | PASS | 成功/失败/重试/死信路径存在 | | callback_target 契约一致性 | FAIL | 字段存在,但 worker 不消费该字段 | | outbox 并发投递安全性 | PARTIAL | `ListDue` 无 claim / `skip locked`,多实例下有重复投递窗口 | | outbox 强一致性 | PARTIAL | 非严格 transactional outbox | | 真实共享预生产 Gate B | FAIL | 当前仍缺真实共享预生产复跑与留痕 | | 生产灰度 Gate C | FAIL | 当前仍缺真实监控接线、灰度稳定性与回滚证据 | --- ## 5. 问题清单 ### Critical #### C-01 真实共享预生产 / 生产放行证据未闭环 - 影响:不能按“生产可上线”口径放行 - 证据: - `test/QA_GATE_STATUS.md` - `prd/PRODUCTION_CHECKLIST.md` - 当前状态:代码级通过,但真实共享预生产 Gate B 和生产 Gate C 仍未通过 - 建议:继续按 Gate B / Gate C 在真实共享环境复跑并留痕 ### Important #### I-01 newapi 平台入口未实现但仍可装配/启动 worker - 影响:对外口径容易失真,误报为“平台已支持” - 证据: - `internal/platformadapter/newapi_adapter.go:20-21` - `internal/app/app.go:129-130` - `internal/app/app.go:186-187` - 建议:二选一收口 1. 禁止未实现平台被注册/启动 worker 2. 补完整 newapi ingress 实现与对等测试 #### I-02 平台启用状态与真实可用能力未统一建模 - 影响:未完成平台也可能启动 callback worker,形成半接通状态 - 证据:`internal/app/app.go:158-187` - 建议:把 adapter 注册条件、worker 启动条件、入口可用条件收成同一门控 #### I-03 `callback_target` 契约与运行时行为不一致 - 影响:数据模型表达了能力,运行时并未支持,后续易造成静默错投或错误认知 - 证据: - event builder 写入 `callback_target` - `worker.go` 实际只使用 `Worker.CallbackURL` - 建议:删除伪能力,或真正按 event target 路由 #### I-04 outbox 多实例并发投递风险未收口 - 影响:水平扩展时可能重复投递 - 证据:`internal/store/postgres/platform_event_store.go:78-86` 的 `ListDue` 仅查询,不做 claim / 锁定 - 建议:补 claim 机制、`FOR UPDATE SKIP LOCKED` 或显式限定单实例运行边界 #### I-05 严格事务外盒未成立 - 影响:业务主写成功但 outbox 写失败时,一致性不可保证 - 证据:业务处理与 `InsertPendingBatch` 不在同一事务中 - 建议:后续评估 transactional outbox 或明确记录一致性边界 #### I-06 sub2api callback E2E 已再次复现失败,说明链路存在现实不稳定性 - 影响:当前 `go test ./...` 不能稳定通过,代码级门禁不能再按稳定 PASS 对外汇报 - 证据:本轮复核再次在 `test/e2e/sub2api_callback_flow_test.go:186` 失败,实际出现 `reply.generated` 先于 `message.received`,并伴随 `sql: database is closed` - 建议:先把该问题提升为当前优先闭环项,做定向稳定性定位与修复,再恢复代码级门禁口径 ### Minor #### M-01 旧 review 文档存在显著漂移 - 影响:继续引用会误导后续判断 - 典型文档: - `docs/CODE_REVIEW_REPORT.md` - `docs/PRODUCTION_EXECUTION_PLAN.md` - 建议:以后续新报告和任务板为准,逐步回收旧结论 --- ## 6. Gap Taxonomy Summary | Gap Type | 具体表现 | 主责任方向 | |---|---|---| | design_gap | 平台启用 / 平台可用性门控未统一;多实例投递策略未正式定义 | TechLead | | implementation_gap | newapi 入口未实现;callback_target 运行时未消费 | Engineer | | test_gap | newapi 缺对等测试;sub2api callback E2E 已复现不稳定失败,需优先定位与修复 | QA / Engineer | | evidence_gap | 真实共享预生产 / 灰度环境证据未闭环 | QA / DevOps | | call_chain_gap | newapi 看似支持但入口未接通 | TechLead / Engineer | | contract_gap | callback_target 字段与 worker 真实行为不一致 | TechLead | --- ## 7. 与旧报告的关系 ### 7.1 可以继续保留的主结论 - 当前不能按“整体生产可上线”口径放行 - 代码级通过不等于预生产和生产放行通过 - 文档漂移仍需持续治理 ### 7.2 必须回收的过期口径 - 旧版把若干已修复问题继续当作当前 P0 - 旧版把“无鉴权 / prod fallback / readiness 过宽”继续描述为当前代码事实 - 旧版若暗示“修完早期两个 P0 即可灰度”,现阶段已不再成立 ### 7.3 新基线文件 后续应以以下文件作为当前基线: - `docs/REVIEW_REPORT_2026-05-06.md` - `docs/REMEDIATION_TASK_BOARD_2026-05-06.md` - `test/QA_GATE_STATUS.md` - `prd/PRODUCTION_CHECKLIST.md` --- ## 8. 后续执行建议 ### 最短闭环顺序 1. 先定位并修复 `sub2api` callback E2E 不稳定失败,恢复 `go test ./...` 稳定通过能力 2. 收口平台能力矩阵 3. 收口平台启用 / worker 启动统一门控 4. 处理 newapi 假接通 5. 补 newapi 对等验证 6. 在共享预生产环境复跑 Gate B 并留痕 7. 在共享预生产 / 灰度环境补监控接线与回滚证据 ### 对应任务板 - 详见:`docs/REMEDIATION_TASK_BOARD_2026-05-06.md` --- ## 9. 最终判定 **当前项目应被定义为:** > **`go build ./...` 与 `go vet ./...` 当前通过,但 `go test ./...` 已再次实测失败,说明代码级门禁并不稳定;sub2api 单平台回调主链已可用,但仍带重要一致性/并发/稳定性风险;newapi 当前未通过;真实共享预生产与生产放行门禁未闭环,因此不能按“整体生产可上线”或“多平台已完成”口径汇报。** 正式门控结论: - **代码级门禁:部分通过 / 当前不稳定** - **sub2api 单平台主链:通过,但带重要风险且 E2E 当前不稳定** - **newapi 平台能力:未通过** - **真实共享预生产门禁:未通过** - **生产放行门禁:未通过**