feat(ai): W1-AI-CLOSURE 超级 Sprint — 9 APP 全链路收口 + chat 上下文真激活

Phase 2.3 chat 上下文捕获链路从未真正激活到完整工作:
- 14 处 ai-float-button 补 sourcePage,chat.ts 三分支同步设 pageFilters.contextId
- 后端 page_context 4 层 BUG 修(列名错位 + RLS site_id 未重设)
- xcx_chat filters.pop 破坏 body.page_context 引用 — dict() 浅拷贝隔离
- chat 流式 markdown 实时解析(表格/标题/列表/加粗 + KPI 富卡)
- reference_card KPI 富卡接入 SSE 路径,db 真写入
- 维客线索 source 显示规则:AI 来源用机器人 icon 替代长文字

数据库:
- public.member_retention_clue 加 emoji + runtime_mode + sandbox_instance_id
- biz.ai_run_logs 加 assistant_id + 复合索引
- chk_ai_cache_type CHECK 约束 8 类应用名
- cache_type / app_type 命名统一(app6_note / app7_customer / app8_consolidation)
- 历史 emoji 抽取脚本 44/44 成功

后端 silent failure 修:
- cleanup_service WHERE app_type → cache_type(90 天清理 + 20K 上限重新生效)
- _build_ai_insight 字段错位修复(app4 → app7 + 字段对齐 prompt schema)
- task_manager talkingPoints 改 app5_tactics + tactics 字段
- task_manager aiSuggestion 改取 one_line_summary
- cache_service.CACHE_EXPIRY_DAYS 加 app2a_finance_area
- WS /ws/ai-cache 加 token + JWT + site_id 校验(P0 信息泄露漏洞)
- internal_ai token 改 hmac.compare_digest

工具/文档:
- main.py 加 RotatingFileHandler logs/backend.log + uvicorn /health 过滤
- 新建 utils/clue_category.py(VI 6 类配色 + emoji fallback + source 显示规则)
- 新建 utils/markdown.ts(轻量 md 转 rich-text 解析 + streaming 容错)
- audit + 数据库变更说明 + backlog §七 #14 收口 + #15-#38 残余子任务
- backlog 追加 §十一 App1 参数/MCP/沙箱审计 + §十二 百炼/SQL MCP 主任务线

实地 MCP 走查:14 入口数据层 + 5 代表入口 sourcePage 注入 + customer-detail 全模块 + chat md 渲染 + reference_card 富卡 都已验证。9 项预先 BUG/UX 登记 §七 #29-#38 后续修复。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Neo
2026-05-06 16:39:07 +08:00
parent c9c2bce101
commit 2dfc926f96
56 changed files with 1983 additions and 278 deletions

View File

@@ -50,6 +50,7 @@
| 2026-05-06 | 追加 §七 全局收口洞口清单 + §八 文档规范化整理大工程 | Neo 反思项目全局控制度,5 问追溯调研后立项 |
| 2026-05-06 | §七 收口 #1 #2 完成 + 追加 #6~#13 + 新增 §九 全栈产品文档体系登记 | docs/roadmap/BACKLOG.md 60+ 项发现 + Wave 0 全栈文档体系实证 + 累积基线 33 项对账 |
| 2026-05-06 | §七 追加 #14 AI 9 APP 全链路未完成(P0)+ 新增 §十 专题登记 | Neo 提出 AI 9 APP(8 prompt + 1 chat 实时)在接口/入库/后端处理/前端展示 4 环节有未完成,优先级很高 |
| 2026-05-06 | §七 #14 主体收口(超级 Sprint)+ 追加 #15-#28 残余子任务 | 超级 Sprint 完成 49 文件改动,5 个 silent failure 修复 + chat sourcePage 全链路 + WS 鉴权;新发现 14 项独立子任务登记 |
---
@@ -76,7 +77,31 @@ Neo 发现"项目全局的控制度不够,有很多东西被漏了,到处都没
| 11 | (累积基线遗留)ETL 库完整 GUC 传递 26 视图 | 累积基线 3.5.5 | ⏳ 未收口 | P1 | 推迟 F1-5b Wave C(已规划)|
| 12 | (累积基线遗留)finance_area_daily 会员分桶 vs DWS 规范 | 累积基线 3.7.2 | ⏳ 未收口 | P1 | 数据质量 Review,上线灰度期 |
| 13 | (累积基线遗留)RLS 视图 pg_get_viewdef 全量重建 | 累积基线 3.7.3 | ⏳ 未收口 | P1 | 数据质量 Review + 视图清单专题 audit |
| **14** | **AI 9 APP 全链路未完成**(接口/入库/后端处理/前端展示)| Neo 2026-05-06 提出,本次实证 8 prompt 文件 + 1 chat 实时 = 9 APP,但前端小程序仅 4 个文件涉及 AI,展示点不全 | ⏳ **高优先级未收口** | **P0** | 详见 §十(独立专题登记);需独立"AI 9 APP 全链路收口 sprint",4 环节(接口/入库/后端处理/前端展示)逐项对账实施 |
| **14** | **AI 9 APP 全链路未完成**(接口/入库/后端处理/前端展示)| Neo 2026-05-06 提出 | ✅ 2026-05-06 主体收口(超级 Sprint)| **P0** | 详见 [`2026-05-06__w1_ai_closure_super_sprint.md`](../audit/changes/2026-05-06__w1_ai_closure_super_sprint.md) — 49 文件改动 + 1 数据库迁移 + 5 个 silent failure 修复 + chat sourcePage 全链路接通 + WS 鉴权;残余 14 项独立子任务登记为 #15-#28 |
| 15 | `/api/retention-clue` POST/DELETE 三端点无认证(P0-3 安全洞)| 超级 Sprint 调研发现 | ⏳ 未收口 | 🔴 **P0** | **Sprint 后立即独立修** — 加 `Depends(require_approved)` + site_id 从 JWT |
| 16 | 时光机日期切换 AI 数据初始化机制 | Neo 2026-05-06 提出 | ⏳ 未收口 | P1 | F1-6 阶段 B 必做 — 切日期时该实例 cache 空触发批量初始化 + 预算保护 |
| 17 | App8 落库静默吞排查(67 cache → 44 入库,差 23 条)| 超级 Sprint 调研发现 | ⏳ 未收口 | P1 | 独立 audit 数据质量 review |
| 18 | App3 daily budget 超限 45% 失败率 | 超级 Sprint 调研发现 | ⏳ 未收口 | P2 | 生产灰度前复核 daily 预算上限 |
| 19 | tenant-admin 新增"创建维客线索"功能(POST 端点 + UI)| 超级 Sprint 调研:source='manual' 字段已设计但 UI 录入入口缺失 | ⏳ 未收口 | P2 | 独立 M sprint(~ 2h):POST 端点 + 前端表单 + 用户校验 |
| 20 | MCP 沙箱场景 B 走查(切沙箱模式只读验证)| 超级 Sprint 跳过(避免污染 prod)| ⏳ 未收口 | P2 | F1-6 阶段 B 必做 |
| 21 | RLS 迁移(P1-1 public → biz schema + app.v_*)| Neo 已批选 A 但未执行 | ⏳ 未收口 | P1 | F1-6 阶段 B 收尾后 |
| 22 | chat-history 新建/删除按钮 | 超级 Sprint UX 增量 | ⏳ 未收口 | P2 | 独立小 sprint |
| 23 | `ai_conversations.source_page/source_context` 冗余孤儿列(已建未用)| 超级 Sprint 调研发现 | ⏳ 未收口 | P2 | 决策弃用还是启用 |
| 24 | admin-web 全 snake_case → camelCase 大改造 | 超级 Sprint 调研:admin 与 xcx 端命名风格分裂 | ⏳ 未收口 | P2 | 影响面巨大,独立 sprint |
| 25 | admin-web WS 客户端补 `?token=` query 参数 | 超级 Sprint P0-9 仅修后端 | ⏳ 未收口 | 🔴 **P0 安全** | **与 #15 一起立即修** — 否则 admin 监控页 WS 全部 close 4401 |
| 26 | prompt/Pydantic/前端类型四端单一权威源 spec | 超级 Sprint 调研发现 | ⏳ 未收口 | P2 | 架构级,需 spec |
| 27 | `cache_service._row_to_dict` datetime 强转 ISO 字符串丢 tz | 超级 Sprint 调研登记 P1 但未做(怕破坏现有调用方)| ⏳ 未收口 | P2 | 改保留 datetime 对象,由 Pydantic 序列化 |
| 28 | `ai_run_logs.assistant_id` 列已加,历史回填仍未做(不阻塞功能,定位用) | 超级 Sprint 仅加列 | ⏳ 未收口 | P2 | 独立回填脚本(可选)|
| 29 | `_text_coach_detail` SQL `hire_date` 列不存在 | 复盘 chat 上下文走查实证 | ⏳ 未收口 | P1 | 看 dim_assistant 实际列名,改 SQL — 影响 coach-detail 入口 chat 上下文 |
| 30 | `_text_board_finance` SQL `items_sum` 列不存在(应用 DWD-DOC #1 合成表达式) | 复盘 chat 上下文走查实证 | ⏳ 未收口 | P1 | 改用 `(table_charge_money + goods_money + assistant_pd_money + assistant_cx_money + electricity_money)` 或对应 v_dws 视图字段 — 影响 board-finance 入口 chat 上下文 |
| 31 | `_text_board_customer` SQL `sh.items_sum`#30 | 复盘 chat 上下文走查实证 | ⏳ 未收口 | P1 | 同 #30 解法 — 影响 board-customer 入口 chat 上下文 |
| 32 | `_text_performance` SQL `sc.performance_tier` 列不存在 | 复盘 chat 上下文走查实证 | ⏳ 未收口 | P1 | 看 dws_assistant_task_monthly 等表实际列,改 SQL — 影响 performance 入口 chat 上下文 |
| 33 | **App1 chat 调用全链路审计** — 拉起参数完整性 / 本地 MCP 查询 / 沙箱边界收口 | Neo 2026-05-06 提出 | ⏳ 未收口 | **P1** | 详见 §十一(独立专题登记)— 独立 sprint 评估 |
| 34 | **百炼调取 + 本地 SQL MCP 任务** 全部接入主任务线追踪 | Neo 2026-05-06 提出 | ⏳ 未收口 | **P1** | 详见 §十二(独立专题登记)— 独立 sprint 评估 |
| 35 | chat md 渲染:`---` 水平分割线未特殊处理(被当作普通段落) | 复盘 chat md 走查发现 | ⏳ 未收口 | P2 | `mdToRichHtml``<hr>` 处理(rich-text 支持 hr) |
| 36 | `_text_task_detail` SQL `coach_tasks_member_view / coach_tasks_assistant_view` 视图不存在 | 14 入口走查实证 | ⏳ 未收口 | P1 | 看实际 dim_member / dim_assistant FDW 视图,改 SQL — 影响 task-detail 入口 chat 上下文 |
| 37 | 4 个入口缺 `_text_*` 实现 → chat 拿不到页面上下文(`coach-service-records` / `performance-records` / `notes` / `chat-history`)| 14 入口走查实证 | ⏳ 未收口 | P2 | 加到 `SUPPORTED_PAGE_TYPES` + 实现各自 `_text_*` 函数;或者把 wxml sourcePage 映射到已支持 page(coach-service-records → coach-detail 等)|
| 38 | customer-detail 频繁 navigate 切换时偶发 `pageState='error'` | 14 入口走查实证(loadDetail 手动调可重现成功,onLoad 触发时偶发失败) | ⏳ 未收口 | P2 | 看 onShow auth-guard 与 onLoad loadDetail 的并发竞争,加 lock 或重试 |
### 收口原则
- 每项洞口完成后,出对应 audit 文档(`docs/audit/changes/2026-05-XX__closure_*.md`)
@@ -231,3 +256,60 @@ Neo 2026-05-06 反思时提出:"AI 方面 9 个 APP 的处理还没有完成,在
### 与现有 backlog 关系
本项与 §一 DWD 孤立 + Core 中间件、§八 文档规范化大工程并列为"L 级长期工程",
但**优先级 P0 高于其他**(Neo 强调"优先级很高")。F1-6 阶段 B 收尾后,优先启动本项。
---
## 十一、App1 chat 调用全链路审计(P1,独立 sprint)
### 触发背景
Neo 2026-05-06 W1-AI-CLOSURE 复盘时提出:"App1 要传入的参数是否已经传入?对于拉起、访问本地 MCP 查询,如果有沙箱的设置,如何收口查询边界?相关联的措施整理需求并记录。"
### 审计维度
1. **拉起参数完整性** — App1 chat 触发链路对接百炼应用 ID (`DASHSCOPE_APP_ID_1_CHAT`) 时,所有期望参数(biz_params: User_ID/Role/Nickname,session_id,prompt 拼装的 page_context + 历史消息)是否在 dispatcher / xcx_chat 中**真实传入**?
2. **本地 MCP 查询** — chat 路径上百炼应用是否真正用到本地 MCP server(`apps/mcp-server/`)?MCP server 在 `.mcp.json` 注册的 PostgreSQL 只读连接,App1 拉起时是否调用?调用频率 / 失败回退?
3. **沙箱边界收口** — 当门店进入 sandbox 模式(`biz.site_runtime_context.mode='sandbox'`),chat 应用的查询边界:
- prompt 注入的 `current_time` 是否走 `as_runtime_business_now_str(site_id)`?✅(W1-AI-CLOSURE 已实证)
- page_context 注入的客户消费数据是否过滤 `business_date` 上界?(F1-6 阶段 B 范围)
- 本地 MCP 查询是否传入 sandbox_instance_id 隔离?
- 百炼应用拉取的工具调用结果是否带沙箱上下文?
### 工作量
- 链路全审 ~ 2-3h
- 修复缺口 ~ 1-2 个 sprint
### 状态
⏳ 未启动 — 待 W1-AI-CLOSURE 主体收口后独立调研
---
## 十二、百炼 + 本地 SQL MCP 任务追踪(P1,主任务线)
### 触发背景
Neo 2026-05-06 W1-AI-CLOSURE 复盘时提出:"百炼调取,本地跑的 SQL MCP 任务也要记录在主任务线中。"
### 当前缺口
1. **百炼 API 调用记录**`biz.ai_run_logs` 表已记录 dispatcher 调用(8 个 prompt 应用),但 App1 chat 的百炼调用(`call_app_stream`)目前**未写入 ai_run_logs**(只写 `ai_messages`)。chat 调用的成功率 / latency / token / 失败原因没有统一观测面板。
2. **本地 MCP server 调用记录**`apps/mcp-server/` 提供 PostgreSQL 只读 MCP 工具,百炼应用通过 MCP 协议调用本地 SQL 时,**调用日志没有持久化**(MCP server 可能只在 stdout 输出)。无法追踪:
- 百炼实际调了哪些 SQL?
- 调用成功率 / 错误率?
- 单次调用 token 消耗 / 时间?
- 沙箱 site_id 是否正确隔离?
3. **任务线统一面板** — admin-web 的 AIRunLogs 当前只看 dispatcher 8 个 prompt 应用的日志,**chat + MCP 调用没纳入面板**,运维盲点。
### 收口动作建议
1. `chat_service` 在每次 SSE 完成后写一条 `ai_run_logs` 记录(app_type=app1_chat,记 prompt/response/token/duration/status)
2. mcp-server 加调用日志中间件(可写到 `biz.mcp_call_logs` 新表 / 或复用 `ai_run_logs` + app_type='mcp_xxx')
3. admin-web AIRunLogs 面板加 `app_type IN ('app1_chat', 'mcp_*')` 筛选项
4. 关联到 dashboard:百炼应用 + chat + MCP 三类调用的统一观测视图
### 工作量
- 后端写入 ~ 1h
- mcp-server 拦截器 ~ 1h
- admin-web 面板补 ~ 1h
- 总:~ 3h(单 sprint 范围)
### 状态
⏳ 未启动 — 与 §十一 配套,作为独立"AI 调用观测性"sprint 推进