MIA-249 · Zero full-service downtime

Group Memory
在线 Cutover

当前讨论的可持续更新快照:把 Session Memory 上移为 Group Memory,同时让最终 v0.0.4 Server 只部署一次、Matrix 不出现整站维护窗。

2026-08-18Local only未同步 Issue后续持续更新
一句话方案

发布的就是同一个最终 v0.0.4 Server。cutover 前它兼容旧 Session owner;Matrix 淘汰旧实例后,同一镜像自动完成原子 cutover;成功后同一批 Server 无需重部署,下一次请求自动使用 Group owner。

已确认的外部前提

Matrix

先启动新实例,等 Ready 后再 kill 旧实例,具备没有服务空档的基础。

MIA-303

唯一明确要求停止旧 Server / 专用维护窗的业务动作是 MIA-249 cutover。

其余数据动作

migration 254、255–259 additive DDL 与 avatar repair 均不要求整站停机。

Self-host 边界

仓库 Helm 仍是单副本 Recreate;它不是 Matrix 托管发布的事实来源,未来自托管需另审。

当前判断:只要 MIA-249 在线 cutover 在真实 staging 通过,v0.0.4 有机会取消业务维护窗。

已拍板的产品与技术选择

不创造新产品概念。用户仍只理解 Ungrouped 的 Session Memory 和已分组的 Group Memory;pre-activation / active 只属于发布内部状态。
同一最终 Server,只部署一次。所谓“桥接”只是最终 Server 在 activation 前的兼容运行状态。cutover 后不换镜像、不重新发版。
采用更连续的旧 Turn 行为。旧 Turn继续普通回复;只有恰好在 cutover 后替换 Memory 的旧 Turn发生可重试冲突。
对外 interface 不变。Server按 placement 与 activation 解析 owner;客户端和 Agent不提交任意 Group ID。

新 Turn会装载升级后的 rollica-work-memory Skill,并得到 Group 内容/revision。已经开始运行的旧 Turn不会被部署中途重新注入 prompt,所以它保留启动时冻结的 owner snapshot 与 revision。

在线 cutover 时序

1
在线扫描与 additive DDL提前处理所有超限;production 继续走 MIA-303 DBA Gate。
2
Matrix 部署最终 Serveractivation=legacy,因此新实例 Ready 时仍严格使用旧 Session owner。
3
Matrix 淘汰旧实例发布流程必须证明旧 binary已全部退出,不能仅凭分支名推断。
4
同镜像 Cutover Job取得 advisory lock,在锁内重建最终 manifest 与容量检查。
5
原子写入同一事务写 Group Memory、merge evidence、manifest hash 与 activation=active。
6
无需重新部署最终 Server下一次请求读到 active,自动切换到 Group owner并公布 capability。
零整站停机的精确定义:登录、Issue、历史会话、普通消息和无关 API始终可用;提交 cutover 的短事务中,Memory、placement和相关 owner snapshot写入可以等待数据库锁,但不能丢失或误写。

Cutover Job 的权限与动作边界

硬边界:DBA Schema Package 负责造表、加列、索引、function 和 trigger;Cutover Job 只负责读旧 Memory、写 Group Memory 与迁移凭证、切换 activation。两者不是同一个 SQL 包。
DBA Schema Package(255–260)Application Cutover Job
大白话造好新柜子、账本和防误写门锁搬书、填搬运凭证、打开新柜子的内部开关
SQLDDL:CREATE/ALTER TABLE、column、index、constraint、function、triggerDML:SELECT、INSERT、UPDATE,以及临时事务锁
权限DBA审批,schema owner / migration roleMatrix自动运行,受限 app/cutover DML role
时机提前完成最终 Server Ready且旧 Server全退后执行一次
失败不允许进入 cutover产品数据整笔回滚,legacy继续服务,Matrix step变红

Cutover Job绝不执行 migration,也不建表、加列、建索引、创建或替换 function/trigger。migration 260所需的 rollout/attempt表、activation字段和迟到写保护trigger必须由DBA预先准备。production Server与Job均使用 MULTICA_MIGRATION_MODE=check;schema不完整就零业务写入失败,不能自行补结构。

1
只读验房检查255–260精确schema contract、activation=legacy与既有completion;缺对象直接退出。
2
登记attempt在已存在的表写started、attempt ID、版本与时间;不写Memory正文、身份、标题或路径。
3
短时写 fence取得advisory lock与相关表锁,让Memory/placement/owner snapshot写入排队;不改变表结构,无关功能继续。
4
读取、排序、计算读取Session与目标Group Memory,确定性拼接并计算计数、codepoints、bytes与hash;不调用LLM。
5
容量预判任何Group超限都在产品写入前停止。
6
主事务搬运写Group Memory、逐来源exact evidence、completion/hash和activation=active;旧Session原文保留,不DELETE/TRUNCATE/DROP。
7
提交与报告释放锁,现有Server自动切换owner;只输出状态、计数、attempt ID与hash。
失败也有记录,但不会留下半套Memory:Group Memory、evidence、completion和activation在同一个产品数据事务中一起回滚。attempt audit用独立小事务保留started/failed与稳定错误码,使Matrix和数据库都能说明失败原因。

成功后重跑只返回 already_applied,不会再次append;失败后可基于仍然权威的legacy数据重算。Cutover Job使用不具备DDL权限的数据库role,因此未来代码即使误写 ALTER TABLE,PostgreSQL也会拒绝。

当前 work_group_memory_cutover apply本来就只有读取、事务锁、Group Memory UPDATE/UPSERT、merge evidence INSERT和completion INSERT,没有DDL。online activation可以调整编排和状态机,但不能突破这条权限边界。

在线模式的 manifest

用户在线期间可以合法编辑 Memory,早期 manifest漂移是正常的。最终计划必须在持锁事务内重建;若超限则零写入回滚。提交的实际 hash仍持久化审计。是否仅在新的 --online-activate 模式取消 operator-supplied expected hash,仍待实现前确认。

旧 Turn 为什么仍可能发生 Memory 冲突

S1 revision=5,S2 revision=3

S1 是“回答时保持简洁”;S2 是“所有日期用北京时间”。Turn T已在 S1开始,只拿到 S1 revision=5。

Group revision=2

两份文本被确定性拼成完整 Group Memory。

旧 T 请求替换 Memory

T提交“回答简洁;金额保留两位小数”,但它不知道 S2 的北京时间规则。

拒绝旧全文覆盖

普通回复照常完成;Memory调用返回 owner_changed/revision_conflict,让 Agent基于最新 Group全文重试。

如果直接接受旧 T 的全文替换,S2 的“北京时间”规则会被静默删除。冲突不是 API 改名造成的,而是 CAS 在阻止拿旧全文覆盖新全文。

Skill 与接口为什么不能消灭这个窗口

  • 新 Skill只影响之后开始并重新装载 Skill 的 Turn。
  • 正在运行的模型不会在部署中途重新注入 prompt。
  • API 路径不变只保证调用兼容,不会把旧 task snapshot自动改成 Group revision。

待确认 owner change是否返回当前 Group全文/revision;Agent是否自动重读并安全重试一次。

migration 260 的迟到写保护

应用层正确实现后,大多数请求都会安全路由。数据库 trigger是最后一道防线,避免 active 后又产生“接口报告成功、Group却看不到”的旧 Session写入。

慢请求跨 cutover

activation 前决定写 Session,随后被表锁挡住,activation 后恢复;若代码没有复检,可能写回旧 row。

旧实例迟退

探针或编排异常时,旧 binary多活一小段时间,仍不理解 Group owner。

旧路径遗漏

某条 task-token/CLI写路径若漏用 owner fence,可能绕过 resolver。

未来回归

重构或人工 SQL误把 grouped Session row当成仍可写。

trigger 的窄规则:activation=active 且 Session当前仍属于 Group时,普通 INSERT/UPDATE不得产生新的权威 Session Memory。
  • Ungrouped Session仍合法读写自己的 Memory。
  • Group → Ungrouped 后创建空 Session Memory仍允许。
  • Ungrouped → Group append/reset必须由 placement事务与 exact evidence证明。
  • 恢复工具走受控审计通路,不保留永久 bypass。

待 SQL 设计 trigger最终采用直接拒绝,还是仅允许带 exact evidence 的受控写。

失败不能静默

cutover不能是 Server后台 fire-and-forget。它必须是 Matrix发布流程等待结果的必需 Job:失败时事务回滚、Server继续 legacy服务,但整次 Group Memory release gate必须变红。

呈现位置必须显示作用
Matrix 发布步骤succeeded/failed、稳定错误码、计数、attempt ID、成功 hash发布人第一时间知道是否完成;失败不能标绿
数据库 rollout 状态phase、attempt、时间、结果、非敏感错误码、实际 hash重启后仍可回答“切没切成功”
MIA-303最终计数、结论、回滚或重试结果正式 Go/No-Go 与跨系统审计

Memory正文、用户身份、Group标题与绝对路径不得进入日志或 Issue。当前尚未验证 Matrix已有主动失败通知,所以只能承诺“步骤显式失败 + 持久状态”;若平台没有通知能力,再单独评估飞书等通知及其 Secret/owner成本。

内部状态模型

Phase有效 ownerCapability行为
legacyGrouped Session仍用 Session row隐藏旧语义正常服务,可重复 preflight
activating持锁事务冻结隐藏无关请求继续,相关写请求等待
activeGrouped Session只用 Group row公布新语义,旧 owner写入被拒绝

失败不增加 waiting 产品状态:事务回到 legacy,但 attempt持久化为 failed,Matrix gate同时失败。

明确不采用

  • 未 cutover 就整站 fatal exit 的 startup gate。
  • 正常发布时让人手抄 preflight hash、UUID和 apply命令。
  • 先发“桥接版”、cutover后再发第二版 Server。
  • 长期双读/双写 Session与 Group Memory。
  • 让 LLM在 cutover中总结、去重或改写原文。
  • 为了所有旧 Turn清零而长时间暂停整个 Work。
  • 只写日志但把 cutover失败的发布标绿。

预计实现改动

  1. migration 260:rollout/activation、attempt evidence、active后的 grouped Session迟到写保护。
  2. Server resolver:legacy严格复现旧 owner,active使用 Group owner;相关事务共享 activation fence。
  3. Cutover coordinator:在线幂等模式、锁内重建与写入、结构化 stdout和稳定 exit code;只使用受限DML role,schema只检查不自动迁移。
  4. Shared frontend:capability动态刷新与 owner/revision conflict双语处理。
  5. Matrix:最终 Server Ready → 淘汰旧实例 → 同镜像 Job → release gate,不二次部署。
  6. 验证:真实 PostgreSQL竞态、慢写、旧 Turn、重复 Job、故障注入、production-shaped rehearsal及独立 Review循环。

尚待继续讨论

  1. Matrix在旧实例全部退出后,用什么精确 post-rollout机制启动一次性 Job。
  2. Matrix现有失败通知能力、入口和接收人。
  3. 旧 Turn Memory冲突是自动重读重试一次,还是明确失败交给下一 Turn。
  4. online activation是否仅在新模式取消预批准 expected hash。
  5. migration 260 trigger对 Ungrouped → Group append/reset 的精确允许条件。
  6. activation后 Shared frontend如何即时刷新 capability,并让旧 Client得到 upgrade_required

分端架构影响

层级影响
Webchanged — activation后刷新 capability;旧 Turn/旧 Client冲突使用清楚的双语反馈。
Desktopchanged — 复用 Shared frontend;cutover无需第二次安装或重启。
Mobile Web / PWAchanged — 与 Web共用能力刷新,无原生 App特例。
Shared frontendchanged — capability刷新、owner/revision conflict和短暂等待状态。
Serverchanged — 同一 binary支持 pre-activation旧 owner与 active Group owner。
Databasechanged — migration 260、attempt evidence、online activation和迟到写保护。
Daemon / CLI / Runtimechanged — 沿用 MIA-249 Skill升级;不新增 cutover协议,旧 task snapshot兼容冲突。
Deploymentchanged — Matrix在滚动完成后运行同镜像 Job并把结果作为 release gate。
Cross-cuttingchanged — 零整站停机、版本交叠、失败显性化、幂等重试与回滚成为合同。

运维 / 发布成本

  • 新增人工配置:暂定 0。正常 cutover自动执行,不要求人输入 epoch/hash。
  • 一次性实现:Matrix post-rollout Job/gate、migration 260、rollout status、staging真实演练。
  • 既有成本:DBA提前审批并执行独立的255–260 additive DDL package;真实数据扫描、候选冻结与最终Go/No-Go仍归MIA-303。Cutover Job不夹带DDL。
  • 待确认:若 Matrix无主动失败通知而产品要求推送,则新增通知渠道、Secret和长期 owner。
  • 回滚:activation前/事务失败保持 legacy;成功后走 ledger/manifest forward recovery,不 destructive down。

Upstream Sync Impact

继续沿用现有 owner resolver、cutover command和 additive schema seam,不新增第二套产品 API。主要冲突面是 startup/activation、Work Context owner resolver、migration 260与部署 runbook;Matrix编排与通用 self-host Helm隔离。