fix(memory): initialize candidates and enforce lifecycle rollout
Memind CI / Test, build, and release guards (push) Successful in 3m29s
Memind CI / Test, build, and release guards (push) Successful in 3m29s
This commit is contained in:
@@ -79,7 +79,16 @@ The additive user-scoped management API is:
|
||||
Lifecycle workers are disabled by default. When explicitly enabled they run
|
||||
expiration, conservative compaction observation, candidate promotion, and
|
||||
reflection observation according to the rollout mode; none of these operations
|
||||
blocks the chat path.
|
||||
blocks the chat path. `off` creates no worker scope and performs no lifecycle
|
||||
mutation, `canary` is always user-scoped to the configured rollout IDs, and only
|
||||
`active` permits an unscoped global worker run.
|
||||
|
||||
When candidate persistence is enabled, the Portal runtime idempotently creates
|
||||
`h5_memory_v2_candidates` before enabling the MySQL candidate store. DDL failure
|
||||
is fail-open for Portal chat and falls back to bounded in-memory candidates;
|
||||
`memind_adm` uses the same schema helper during bootstrap and fails startup rather
|
||||
than serving a permanently broken candidate API. The table is additive and must
|
||||
not be dropped as part of an application rollback.
|
||||
|
||||
The pgvector adapter does not create tables or generate embeddings. It only defines the adapter contract for a future semantic memory backend and requires explicit `enabled: true`, an injected PostgreSQL pool, and either an input embedding or an injected `embedQuery(...)` function.
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
| [mindspace-remote-page-sync-and-thumbnail.md](./mindspace-remote-page-sync-and-thumbnail.md) | ① remote 模式 public HTML 入库 sync ② storage 缺失时缩略图/读页回退 workspace HTML |
|
||||
| [page-data-delivery-contract.md](./page-data-delivery-contract.md) | 数据集注册、绑定、真实 page UUID 与交付验收 |
|
||||
| [h5-session-stream-replay.md](./h5-session-stream-replay.md) | Portal/Goose SSE 游标映射、断线续播与 Finish 终态恢复 |
|
||||
| [memory-v2-candidate-and-lifecycle.md](./memory-v2-candidate-and-lifecycle.md) | 候选记忆表幂等初始化、Portal fail-open、生命周期 off/canary/active 作用域 |
|
||||
|
||||
## 自动化
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# Memory V2 候选表与生命周期灰度守卫
|
||||
|
||||
## 已知故障
|
||||
|
||||
生产曾出现 `h5_memory_v2_candidates` 不存在:候选记忆写入和后台查询报错,
|
||||
但 Agent 召回仍在 shadow 模式执行,因此表现为“有召回事件、回答未注入、个人记忆状态降级”。
|
||||
|
||||
同时,生命周期 worker 只检查了 worker 开关;`expire()` 没有检查 rollout
|
||||
作用域。若忘却开关开启,即使 `MEMORY_LIFECYCLE_ROLLOUT_MODE=off`,定时器也可能
|
||||
归档全量用户的过期记忆。
|
||||
|
||||
## 必须保留的行为
|
||||
|
||||
1. `MEMORY_CANDIDATE_PERSISTENCE_ENABLED=1` 且 MySQL 可用时,Portal 必须先执行
|
||||
`ensurePersonalMemoryCandidateSchema()`,再创建候选记忆 store。
|
||||
2. 候选表 DDL 失败不能阻塞 Portal 聊天启动;Portal 应记录告警并退回 bounded-memory。
|
||||
3. memind_adm 必须在创建候选 store 前完成同一幂等建表;初始化失败时后台启动失败,
|
||||
不允许以“页面可用但候选接口持续报错”的半初始化状态运行。
|
||||
4. 生命周期 rollout 语义必须严格一致:
|
||||
- `off`:不得执行任何写操作,也不得启动 worker 定时器。
|
||||
- `canary`:只允许 `MEMORY_LIFECYCLE_ROLLOUT_USER_IDS` 中的用户。
|
||||
- `active`:才允许无 user scope 的全局任务。
|
||||
5. `forgetMemory()` 和 `expire()` 都必须同时满足功能开关与 rollout 作用域。
|
||||
|
||||
## 回归检查
|
||||
|
||||
```bash
|
||||
node --test memory-v2-personal-store.test.mjs memory-v2-lifecycle.test.mjs memory-v2-runtime.test.mjs
|
||||
npm test
|
||||
```
|
||||
|
||||
memind_adm 同时执行:
|
||||
|
||||
```bash
|
||||
node --test server/personal-memory-candidate-store.test.mjs
|
||||
npm test
|
||||
```
|
||||
|
||||
灰度上线后还必须验证:候选表存在、候选写入成功、后台可查询,以及一个测试用户完成
|
||||
“保存 → 候选 → 晋升 → 新会话召回 → 回答注入”的闭环。未通过前不得切换全量 active。
|
||||
|
||||
## 回滚
|
||||
|
||||
代码可以按标准 runtime/release 回滚;候选表是加法结构,回滚时保留空表或已有数据,
|
||||
不得为了代码回滚直接删除表。先把候选、生命周期和 Agent 注入模式切回 shadow/off。
|
||||
Reference in New Issue
Block a user