lzf_0626
9490e5043b
记忆系统演示文档 + 修掉两处会让演示断链的真问题
## 新增:docs/演示用/记忆系统演示文档-2026-09-14.md
按"操作 → 看到什么 → 这体现什么"写,五个场景(探针看存储 / 记住一件事 / 谁能读谁读不到 /
画像版本与投影 / 停 Worker),每个场景配可复现命令与**实测输出**,另附建议顺序与时长、
六条问答话术、演示前自检清单、受控信号词表摘录。
配套两个新工具(都已实跑):
- `tools/memory_demo_chain.py`:一键走完"客户说 → 候选 → 客户确认 → 管理员批准 →
记忆与画像自动收敛",打印演示前后对比(实测 2 秒收敛)。
- `tools/memory_recall_demo.py`:同一客户换六个身份召回,当场看出"客户只读自己 /
员工要权限码+归属 / 运营读不到 / 管理员有权限码但没归属也读不到"。
## 修掉两处会让演示当场断链的问题(都是真机复现的)
1. **候选批准后画像字段不收敛**
`CustomerProfileCandidateService._promote` 只写画像快照、**不投**
`profile.rebuild_requested`,而 `user_facts` 与画像字段是 `ProfileAssemblyService`
的重建链路写的。后果:批准后记忆变 active、快照版本 +1,但**画像字段停在旧值**
(客户说"三年以内",画像里还是"十年以上"),要等一次无关的重建才收敛 ——
而"客户说完 → 批准 → 画像变了"正是演示主线。
现补一条重建事件(走事件而不是就地重建:本方法所在事务还没提交,
另开 session 看不到刚写入的记忆)。
2. **画像快照的唯一键从来没起作用,而且埋雷**
`uk_profile_snapshot_current` 建在列 `current_customer_id` 上(不是 `is_current`),
但 `ProfileAssemblyService._write_snapshot` 旧行只置 `is_current=False`(不清该列)、
新行**不写**该列(实测 13 行该列全 NULL)。
后果:只要客户**先被重建过一次**,旧 current 行仍占着 `current_customer_id=9001`,
下一次"批准画像候选"就会撞 `Duplicate entry '9001' for key
uk_profile_snapshot_current` → **整次批准 500**(本次实测踩到)。
现按唯一键的真实语义写:清旧行的该列、新行显式写客户号。
(`ProfileGenerationService` / 候选路径本来就是这么写的,只有这一处没对齐。)
## 守卫
新增 `tests/integration/test_profile_snapshot_current_invariant_mysql.py`:
按真实顺序"先重建再批准候选",断言 ① 只有一条 current 且它占着唯一键、
② 历史版本已归还该列、③ 批准不再 500、④ 批准投出了重建事件。
修复前这条用例会在第 ② 步失败。
## 验证
- `pytest tests/unit tests/contract` → 1490 passed, 2 skipped, 0 failed
- 新增集成用例通过;真机实测演示主线:候选 → verified → active → **2 秒内**
`user_facts` 与 `fin_customer_profile.investment_horizon` 都变成新值
- `mypy tools/memory_demo_chain.py tools/memory_recall_demo.py` → 0 错;ruff 全绿
## 文档
`docs/44-演示流程.md`:配套文档清单与"记忆链路"备选场景都指向新演示文档。
2026-09-15 00:55:44 +08:00
..
2026-09-14 21:40:05 +08:00
2026-09-09 21:55:37 +08:00
2026-09-13 22:08:04 +08:00
2026-09-11 20:28:21 +08:00
2026-09-14 18:13:10 +08:00
2026-09-11 22:31:51 +08:00
2026-09-11 15:08:37 +08:00
2026-09-11 14:12:56 +08:00
2026-09-14 18:22:56 +08:00
2026-09-11 20:50:41 +08:00
2026-09-14 20:14:50 +08:00
2026-09-11 17:32:47 +08:00
2026-09-11 16:57:47 +08:00
2026-09-15 00:55:44 +08:00
2026-09-11 14:46:40 +08:00
2026-09-15 00:41:59 +08:00
2026-09-15 00:41:59 +08:00
2026-09-11 16:11:30 +08:00
2026-09-11 16:11:30 +08:00
2026-09-11 14:46:40 +08:00
2026-09-11 14:44:29 +08:00
2026-09-14 22:32:26 +08:00
2026-09-11 16:57:47 +08:00
2026-09-11 16:12:38 +08:00
2026-09-10 21:43:39 +08:00
2026-09-12 12:50:14 +08:00
2026-09-09 21:55:37 +08:00
2026-09-11 16:57:47 +08:00
2026-09-14 18:22:56 +08:00
2026-09-10 18:42:44 +08:00
2026-09-11 22:31:51 +08:00
2026-09-11 14:46:40 +08:00
2026-09-11 14:46:40 +08:00
2026-09-10 22:08:15 +08:00
2026-09-12 11:15:24 +08:00
2026-09-11 18:42:42 +08:00
2026-09-11 16:57:47 +08:00
2026-09-10 20:22:42 +08:00
2026-09-14 00:30:06 +08:00
2026-09-13 20:39:36 +08:00
2026-09-12 14:11:42 +08:00
2026-09-11 16:57:47 +08:00
2026-09-14 21:26:03 +08:00
2026-09-11 22:31:51 +08:00
2026-09-11 16:57:47 +08:00
2026-09-12 12:50:14 +08:00
2026-09-09 21:55:37 +08:00
2026-09-14 01:07:43 +08:00
2026-09-14 01:07:43 +08:00
2026-09-14 22:16:29 +08:00
2026-09-11 16:57:47 +08:00
2026-09-11 16:57:47 +08:00
2026-09-10 09:23:22 +08:00
2026-09-09 21:55:37 +08:00
2026-09-14 18:22:56 +08:00
2026-09-11 19:20:32 +08:00
2026-09-11 12:47:01 +08:00
2026-09-12 12:10:10 +08:00
2026-09-11 12:47:01 +08:00
2026-09-14 23:27:44 +08:00
2026-09-15 00:55:44 +08:00
2026-09-12 10:45:40 +08:00
2026-09-11 16:42:31 +08:00
2026-09-10 21:55:03 +08:00
2026-09-14 21:26:03 +08:00
2026-09-09 21:55:37 +08:00
2026-09-11 16:57:47 +08:00
2026-09-14 18:13:10 +08:00
2026-09-14 18:13:10 +08:00
2026-09-14 18:13:10 +08:00
2026-09-11 16:57:47 +08:00
2026-09-14 18:13:10 +08:00
2026-09-14 18:13:10 +08:00
2026-09-14 18:13:10 +08:00
2026-09-14 20:35:46 +08:00
2026-09-14 00:30:06 +08:00
2026-09-11 21:22:56 +08:00
2026-09-11 14:14:50 +08:00
2026-09-10 21:03:44 +08:00
2026-09-10 21:03:44 +08:00
2026-09-13 19:17:56 +08:00
2026-09-12 15:56:50 +08:00
2026-09-11 14:16:07 +08:00
2026-09-11 11:42:53 +08:00
2026-09-11 14:24:45 +08:00
2026-09-10 21:03:44 +08:00
2026-09-12 15:56:50 +08:00
2026-09-13 23:51:45 +08:00
2026-09-14 01:41:02 +08:00
2026-09-11 09:49:21 +08:00
2026-09-12 16:30:56 +08:00
2026-09-12 15:56:50 +08:00
2026-09-11 19:37:26 +08:00
2026-09-14 18:13:10 +08:00
2026-09-11 16:57:47 +08:00
2026-09-11 21:03:58 +08:00
2026-09-11 16:57:47 +08:00
2026-09-15 00:10:23 +08:00