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>
7.7 KiB
7.7 KiB
2026-05-06 · W1-AI-CLOSURE Schema 修复 + 命名统一
关联迁移:
db/zqyy_app/migrations/20260506__ai_closure_schema_fixes.sql完整审计:
docs/audit/changes/2026-05-06__w1_ai_closure_super_sprint.md
变更说明
新增列
| 表 | 列 | 类型 | 默认值 | 用途 |
|---|---|---|---|---|
public.member_retention_clue |
emoji |
varchar(8) |
'' |
维客线索独立 emoji 字段(App8 prompt 输出 emoji 直接写入,不再嵌 summary 字符串) |
public.member_retention_clue |
runtime_mode |
varchar(20) |
'live' |
运行模式 live/sandbox(与其他 7 张 ai_* 表对齐) |
public.member_retention_clue |
sandbox_instance_id |
varchar(64) |
'live' |
sandbox 模式写入隔离实例 ID |
biz.ai_run_logs |
assistant_id |
bigint NULL |
NULL | App4/App5 这类 (assistant, member) 二元任务的助教 ID,便于失败定位 |
新增索引
idx_ai_run_logs_assistant_memberONbiz.ai_run_logs (site_id, assistant_id, member_id, created_at DESC) WHERE assistant_id IS NOT NULL
CHECK 约束更新
chk_ai_cache_type重建:8 类应用名(app2_finance/app2a_finance_area/app3_clue/app4_analysis/app5_tactics/app6_note/app7_customer/app8_consolidation),与 prompt 文件名 + CacheTypeEnum 完全对齐
数据 UPDATE(命名统一)
biz.ai_cache.cache_type:app7_customer_analysis→app7_customer(42 行)app8_clue_consolidated→app8_consolidation(72 行)app6_note_analysis→app6_note(测试库 0 行,生产可能有)
biz.ai_run_logs.app_type:app8_consolidate→app8_consolidation(123 行)app8_clue_consolidated→app8_consolidation(测试库 0 行)app6_note_analysis/app7_customer_analysis→ 应用名(测试库 0 行)
public.member_retention_clue.runtime_mode:全部 NULL 填'live'(44 行)
历史 emoji 回填(独立脚本)
scripts/ops/backfill_retention_clue_emoji.py — 把 summary 嵌入的首 emoji 抽到 emoji 列(测试库 44/44 行成功,可重入)。
兼容性影响
ETL 影响
- 无直接影响。ETL 不写 ai_cache / ai_run_logs / member_retention_clue,只是注释里"客户基础信息" → "客户基础" 的字面量调整(
apps/etl/connectors/feiqiu/tasks/dws/member_consumption_task.py+member_visit_task.py)。
后端 API 影响
customer_service._build_ai_insight:cache_type 从app4_analysis(错位)改为正确的app7_customer,加site_id过滤 + 字段对齐 App7Result schema(strategies[].title/content)customer_service._build_retention_clues:加site_id过滤 + 字段补齐(detail/source/recorded_by_name/emoji)task_manager.pyaiSuggestion:取one_line_summary替代不存在的app4.summarytask_manager.pytalkingPoints:cache_typeapp5_talking_points(不存在)→app5_tactics+ 字段tactics[].scenario/scriptcleanup_service.py:WHERE app_type=%sBUG 修(应是cache_type)— 90 天清理 + 20K 上限重新生效cache_service.CACHE_EXPIRY_DAYS:补app2a_finance_area: 0(64 区域组合不再永不过期)dispatcher._write_retention_clue:emoji 独立写入(不再拼 summary)+ 加 runtime_mode/sandbox_instance_id 五元组隔离xcx_chat:ReferenceCardschema 补link/source_page字段;get_messagesSQL 加AND role IN ('user','assistant')过滤 system 行;build_reference_cardKPI 富卡接入 SSE 路径- WS
/ws/ai-cache/{site_id}+/ws/ai-alerts/{site_id}:加?token=query 参数 + JWT 校验 + site_id 一致性校验
小程序影响
customer-detail.ts:clues 类型 4 字段 → 6 字段(tag/tagColor/emoji/text/source/desc);_loadAIInsightcache_type 改app7_customer+ 字段s.title/s.contentcustomer-detail.wxml:clue-card props 字段对齐 +wx:if空态隐藏 + ai-float-button 补 sourcePagetask-detail.ts/wxml/json:retentionClues tagColor 6 类;talkingPoints 类型 string[] → TacticItem[];整页补 ai-float-button + json 注册组件chat.ts:三分支(task/customer/coach)补sourcePage+pageFilters.contextId,Phase 2.3 链路真正激活- 14 处 wxml ai-float-button 全部补 sourcePage
admin-web 影响
AIOperations.tsxCACHE_TYPE_OPTIONS8 类对齐(去除 _analysis / _consolidated 后缀)AIRunLogs.tsxRUN_LOG_APP_TYPE_OPTIONS删除旧app8_consolidate(数据已 UPDATE 到app8_consolidation)__tests__/adminAiAppTypes.test.ts:测试断言不再固化"双名共存",改为统一命名
回滚策略
迁移文件末尾有完整"回滚参考"块,按以下顺序执行:
BEGIN;
-- 1. DROP 新约束
ALTER TABLE biz.ai_cache DROP CONSTRAINT IF EXISTS chk_ai_cache_type;
-- 2. UPDATE 命名回滚(注意:旧名 app8_consolidate vs app8_clue_consolidated 已合并,
-- 回滚无法精确还原,只能选其一,以下示例选 ai_cache 旧描述名)
UPDATE biz.ai_run_logs SET app_type = 'app8_consolidate' WHERE app_type = 'app8_consolidation';
UPDATE biz.ai_run_logs SET app_type = 'app7_customer_analysis' WHERE app_type = 'app7_customer';
UPDATE biz.ai_run_logs SET app_type = 'app6_note_analysis' WHERE app_type = 'app6_note';
UPDATE biz.ai_cache SET cache_type = 'app8_clue_consolidated' WHERE cache_type = 'app8_consolidation';
UPDATE biz.ai_cache SET cache_type = 'app7_customer_analysis' WHERE cache_type = 'app7_customer';
UPDATE biz.ai_cache SET cache_type = 'app6_note_analysis' WHERE cache_type = 'app6_note';
-- 3. ADD 旧约束
ALTER TABLE biz.ai_cache ADD CONSTRAINT chk_ai_cache_type CHECK (cache_type IN
('app2_finance','app2a_finance_area','app3_clue','app4_analysis','app5_tactics',
'app6_note_analysis','app7_customer_analysis','app8_clue_consolidated'));
-- 4. DROP 索引 + 列
DROP INDEX IF EXISTS biz.idx_ai_run_logs_assistant_member;
ALTER TABLE biz.ai_run_logs DROP COLUMN IF EXISTS assistant_id;
ALTER TABLE public.member_retention_clue
DROP COLUMN IF EXISTS sandbox_instance_id,
DROP COLUMN IF EXISTS runtime_mode,
DROP COLUMN IF EXISTS emoji;
-- 5. emoji 反向回填(若需要)— 把 emoji 列拼回 summary
UPDATE public.member_retention_clue
SET summary = emoji || ' ' || summary, emoji = '' WHERE emoji != '';
COMMIT;
代码侧:git revert <commit_hash>。
验证 SQL(已在测试库 PASS)
-- 1. 新列存在
SELECT column_name FROM information_schema.columns
WHERE table_schema='public' AND table_name='member_retention_clue'
AND column_name IN ('emoji','runtime_mode','sandbox_instance_id');
-- 预期 3 行
-- 2. assistant_id 列存在
SELECT column_name FROM information_schema.columns
WHERE table_schema='biz' AND table_name='ai_run_logs' AND column_name='assistant_id';
-- 预期 1 行
-- 3. 旧 cache_type 0 残留
SELECT cache_type, count(*) FROM biz.ai_cache
WHERE cache_type IN ('app6_note_analysis','app7_customer_analysis',
'app8_clue_consolidated','app8_consolidate')
GROUP BY 1;
-- 预期 0 行
-- 4. 旧 app_type 0 残留
SELECT app_type, count(*) FROM biz.ai_run_logs
WHERE app_type IN ('app6_note_analysis','app7_customer_analysis',
'app8_consolidate','app8_clue_consolidated')
GROUP BY 1;
-- 预期 0 行
-- 5. emoji 回填覆盖率(回填脚本跑后)
SELECT
count(*) FILTER (WHERE emoji != '') AS filled,
count(*) FILTER (WHERE emoji = '') AS empty,
count(*) AS total
FROM public.member_retention_clue;
-- 预期 filled=44, empty=0, total=44(测试库)
关联
- 完整审计:
docs/audit/changes/2026-05-06__w1_ai_closure_super_sprint.md - backlog 登记:
docs/_overview/architecture-evolution-backlog.md§七 #14 主体收口 + #15-#28 残余子任务 - 关联表 RLS 迁移(P1-1 public → biz schema):§七 #21 后续 sprint