Files
ai-customer-service/docs/REVIEW_REPORT_2026-05-06.md

291 lines
12 KiB
Markdown
Raw Permalink 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.
# 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 BFAIL**
- **生产灰度 Gate CFAIL**
### 是否可进入下一阶段
- **是否可按“整体生产可上线”口径放行:否**
- **是否可按“多平台能力已完成”口径汇报:否**
- **是否可按“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 平台能力:未通过**
- **真实共享预生产门禁:未通过**
- **生产放行门禁:未通过**