fix(mobile): keep message list anchored after send - #3192
Conversation
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: de9a58e01e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
| Filename | Overview |
|---|---|
| apps/mobile/src/session/remoteSessionStore.ts | 增加 live 行时间锚定、离线 cohort 配对、逐 identity transport ownership、stale replay 隔离及精确清理逻辑。 |
| apps/mobile/src/session/MessageRenderer.tsx | 将有界落底校验复用于发送跟随、内容增长和断路恢复,并加入动画与 mVCP settle 协调。 |
| apps/mobile/src/session/messagePaging.ts | 新增 live createdAt 钳制逻辑,使临时行进入主机时间域并保持确定性排序。 |
| apps/mobile/src/session/messageScroll.ts | 提供 mVCP 安静窗及动画后校验延迟的纯函数与常量。 |
| apps/mobile/src/tests/remoteSessionStore.test.ts | 扩展多轮重锚、离线恢复、截断窗口和跨 transport streaming 调和的回归覆盖。 |
| apps/mobile/src/tests/messageScroll.test.ts | 覆盖有界 anchor verifier、mVCP settle 和动画校验延迟。 |
| apps/mobile/src/tests/messageListVirtualization.test.ts | 锁定 MessageRenderer 的显式跟随、历史意图清理和 settle-aware verifier 接线。 |
Sequence Diagram
sequenceDiagram
participant Host as 主机
participant Transport as Device Link
participant Store as remoteSessionStore
participant List as MessageRenderer
Host->>Transport: live assistant / user / persisted push
Transport->>Store: 带 deviceId 的事件
Store->>Store: 记录 provisional identity 与 transport ownership
Host->>Transport: 权威 session/window
Transport->>Store: userSendAt 与持久化消息
Store->>Store: 按轮次重锚并调和 live 行
Store-->>List: 排序后的消息窗口
List->>List: scrollToEnd 后等待动画与 mVCP settle
List->>List: 有界校验并补滚至最新消息
Reviews (24): Last reviewed commit: "fix(mobile): guard truncated reply recon..." | Re-trigger Greptile
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7969a47c3c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
这条 PR 需要维护者确认后才能合并:它改的是发送后消息列表的锚点/滚动,属于用户看得见的交互。 请维护者直接在 PR 上 Approve;若要改,请 Request Changes。讨论 issue:#3196 |
|
命中 UI 路径(mobile 消息列表/分页/远程会话 store)但 description 未附界面效果证据。建议补充改动后效果:截图/录屏,或改动后界面的 HTML 页面,便于确认界面符合 DESIGN.md。缺 UI 证据不阻断审查。 |
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1a2b045851
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f272bf2691
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d7fbef930a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bd16eafa33
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7bf30f5627
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cc808401f1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 366d0fc480
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fa713255cf
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e9db4fd92f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e00520e163
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b1833f3dfb
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d9e4d78e81
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
当 host 的 assistant push 与已完成的 live 行逐字段相同(例如旧版/compact push 不带 rowid、两者同毫秒且 agentMeta 都为 null)时,这个早退会跳过下方新增的 pending identity 清理。该已落库回复因此仍被当作 provisional;若下一条 user push 先于更新后的 session 元数据到达,它会消费该残留 identity,并把上一轮回复重排到新问题之后。即使消息内容无变化,也应在返回前为权威 assistant echo 清除 reconciliation/host-anchor 状态。
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Signed-off-by: Shao-Wu Hu <271197399+hushaowu-rh@users.noreply.github.com>
|
已独立复现并在 04a39e9 修复 Codex review 4997561787。权威 persisted assistant echo 即使与现有 live 行逐字段相同,也会在 equality early return 前退休 pending reconciliation/host-anchor identity;实时 transport replay 显式不走该清理路径,因此不会提前消费身份。新增“相同 persisted echo 清理身份”和“相同 live replay 保留身份”两条回归。验证:focused 320/320、Mobile 全量 3752/3752、Mobile typecheck、test:scope、test:smoke、根 test:unit、DCO(24 commits)与 git diff --check 均通过。 |
|
@hushaowu-rh 先说结论:这个需求很简单——用户发出一条消息后,列表停在最新消息,后面的流式输出也继续跟着。主机时间对齐、重连配对这些都是很小的边角,不用再往下抠了。 桌面端其实已经修过同一件事,可以当参考,不必另起一套:
手机端按这个做就够了。首版那个「发送后再校验一次有没有真滚到底」是对的。后面为了对齐主机时间、重连身份加的那一大套,建议先收住,别再补边界。临时回复先老实待在列表尾,或待在对应那条问题后面,不要跟正式消息抢时间排序。 还有一个具体点:现在 120ms 安静窗绑在 真机我来测,你这边没有开发环境没关系。你先按上面收一版,我拿到之后帮你在真机上走发送、长回复、翻历史再发送。 |
|
@hushaowu-rh 我这边直接帮你补了一笔,只改发送后跟上这件事:流式更新换 推不进你的 fork 分支(没有 push 权限),commit 在这里: 你本地可以这样收进来: git fetch https://github.com/makecindy/cindy.git dash/fix-pr-3192-send-follow
git cherry-pick f687a3970
git push真机我来测,你不用搭环境。 |
dashhuang
left a comment
There was a problem hiding this comment.
发送后跟到最新,这个需求可以合。真机我这边测;安静窗那笔小修复我们随后跟进。
MagicLizi
left a comment
There was a problem hiding this comment.
审查通过:发送后列表锚定与时钟序修复对得上描述,未发现 P0/P1。CI 全绿。机器人静默期已超时放行(copilot / Codex 意见可能后到)。
|
合了。发送后列表乱跳这件事在手机上特别烦,现在发出去还能停在该停的地方。 |
这次改了什么
摘要
修复 Mobile 会话屏在发送消息后列表不停留在最新消息、反而停在旧消息位置的问题。两个根因:(1) 发送后的贴底滚动只发一次
scrollToEnd且不校验是否真的到达内容底部——命令可能被始终开启的maintainVisibleContentPosition吸收,或按尚未测量完成的旧 metrics 计算落点,静默停在旧消息上;原有的校验/补滚循环只在会话冷启动锚定时运行一次。(2) 流式 assistant 行用手机时钟打createdAt,与主机时钟落库行混排;手机时钟偏快时,刚发送的消息会被排序到旧的流式行之前,列表尾部被旧行占住。修复:把冷启动的有界校验/补滚复用到发送跟随(
followLatestRequestKey)与内容增长补滚(handleContentSize)两条路径;显式跟随会清除已被发送动作取代的历史浏览意图。新增纯函数clampLiveRowCreatedAt:会话已有主机域 watermark 时,把临时 live 行固定到该 watermark;既避免慢设备时钟把 live 行插到已知行之前,也避免快设备时钟压过随后到达的主机持久化行。进一步补齐空消息窗场景:没有消息 watermark 时改用会话的主机域活动时间,避免短 live 行残留在首个持久化行之后;用户手动向下滚回底部时也会清除旧的历史浏览意图,后续内容增长可重新触发贴底校验。进一步修复 review 发现的边界:死区内轻拖没有真正解除贴底时,校验继续以 nearBottom 实态运行;首个 live 行早于会话元数据或消息窗口时先标记为 provisional,首个主机元数据或持久化消息到达后重锚,且多帧 delta/final 不会丢失该标记。权威最新消息窗口现在也能作为首个主机时间来源触发重锚;当首个权威行是 user 时先插入再重锚,保持问题在 live 回复之前,而 assistant 持久化尾行仍保留在临时 live 行之后。主机时间水位还会排除仍待重锚的 provisional live 行和本地 system card,确保多条 distinct live 行都在首个权威水位到达后一起收口。旧会话列表快照以及既有 assistant/tool 尾行现在只提供临时时间锚,直到当前轮 user 或其他权威消息到达才完成重锚;user 行到达时会显式保持问题在对应 live 回复之前。连续多轮 provisional live 回复会按 user push 顺序一对一逐条重锚,保持U1 → A1 → U2 → A2。若尾部虽是 user,但会话userSendAt已前进,则将它识别为上一轮 user,当前 live 行仍保持 provisional,直到本轮 user push 到达。最新 review 进一步收紧 pending 身份生命周期:延迟的 assistant/tool push 只提供临时时间水位,不再批量消费待重锚回复;最新 user 窗口只有在尾行时间不早于会话userSendAt时才完成配对,避免旧回复被下一轮 user 重复认领。权威窗口一次带回多轮 user 时,会让窗口内最新 user 后缀与最新 pending 回复后缀按顺序一对一配对;实时 user push 也只在不早于会话 userSendAt 时消费当前 pending 身份,已有本轮发送标记时只认领最新 pending 回复;动画贴底则等待既有 1400ms settle 窗口结束后再启动无动画校验补滚,避免平滑滚动被两帧后的 retry 打断成瞬移。短暂离线时同时保留 live-window 保护身份与 host-anchor 身份,避免重连窗口在权威 assistant 回声前丢失回复,并让权威 user 行恢复问题 → 回复顺序;已知早于userSendAt的旧 user push / 窗口不再改写当前回复的时间锚或位置。最新反馈继续补齐两条边界:pending host-anchor 身份记录首次绑定的userSendAt,重连时只与对应发送窗口内的 user 行配对,旧轮回复不会被新轮问题认领;LegendList 的普通 data append 与流式 size 变化会记录短 mVCP settle 安静窗,两套贴底 verifier 在窗口内使用独立 wait 预算,不再约 200ms 内耗尽 retry。本轮 review 继续补齐:软离线前尚无会话元数据或仍停在 32ms 微批中的 live 回复会按 transport device 冻结空 sendAt 身份,重连后的新轮 user 不会认领旧回复,而迟到的旧轮 user 仍可恢复原顺序;同一 userSendAt 下的多条 live assistant 行会按原顺序整体移动到对应 user 之后;截断持久化回声在保留完整 live 内容时也会吸收权威 createdAt。新 head 继续处理两条有效反馈:设备 hard remove 会同时依据 session 索引与 maker transport ownership 回收元数据前的 32ms 文本批次、provisional 行和 host-anchor 身份;若同一 session ID 已由 re-link 后的 current shard 接管,则只清旧 transport 的临时状态,不误删新设备窗口。元数据前同一 Maker turn 的多条 live block 会共享本地轮次 cohort,首个权威 user 行按原序整体消费,而缺少 turn 边界的旧 producer 仍保留逐条配对兼容语义。本轮新 review 进一步修复三条边界:权威窗口中的 user 行也参与 sendAt 区间分隔,避免中间轮次身份已消费后旧回复跨轮;pending host-anchor 的 transport ownership 改为逐 identity 记录并支持共享 ownership,hard remove 只清理被移除 transport 独占的 provisional 行且在无剩余 owner 时完整回收 runtime;多个离线未绑定 cohort 的实时 user 回补按最小 unboundRoundId 顺序消费,避免 A2→U1 反向配对。本次进一步在 32ms 文本微批内把 transport device 作为硬边界:deviceId 切换时先 flush 旧 batch,避免 stale/current transport 的 delta 串批、错误归属或在移除设备时误删当前回复。当两个 transport 的 batch 都已 flush 时,同一 persistId 的 streaming assembly 也会在 deviceId 切换时重置旧 live 文本,避免 current 回复继续拼接 stale 内容。最新修复将 streaming transport ownership 按 session 内 identity 独立记录,避免交错的 persistId 相互覆盖;soft-offline / finalization 仅清 active pointer,保留身份 ownership 直到权威调和或精确回收;stale indexed shard hard remove 在 current transport 已先到但 session list 尚未到达时只清 stale transport 状态;已持久化 assistant 行的相同 final 重放不会被误标为 provisional transport ownership。
本次继续修复权威重连窗口与 transport ownership 的边界:多个离线未绑定 cohort 仅在窗口 user 数量与 cohort 数量精确一致时按轮次顺序配对,截断或多出 user 的窗口保持 pending,避免把回复挂到错误轮次;stale transport 在权威 current transport 已拥有 pending assembly 时会在 clientId 迁移前被拒绝,且 ownership 跨 done 边界保留,避免重放改写临时 identity、覆盖 current 内容或插入重复回复;已持久化 assistant 行同样拒绝非权威重放。
本次新反馈继续收紧两处调和边界:多个离线未绑定 cohort 只有在最新窗口明确覆盖到会话起点时才允许按位置配对,头部截断但 user 数量恰好相等的窗口仍保持 pending;权威 persisted assistant echo 即使与 live 行逐字段相同,也会清理 pending reconciliation identity,而实时 transport replay 不会提前退休该身份。
变更类型
feat新功能fix缺陷修复refactor/perf重构或性能优化docs/test/chore文档、测试或工程维护范围
evaluateMobileAnchorVerify,卸载/切会话可取消);显式跟随重置已过期的历史浏览意图;流式行时间戳锚定纯函数及接线;空消息窗 provisional live 行及元数据/持久化消息重锚;多帧流式标记保持;权威最新窗口重锚及 user/assistant 同戳顺序;多条 provisional live 行与本地 system card 的水位隔离;旧会话快照和 assistant/tool 尾行保持 provisional 直到当前轮权威消息重锚;连续多轮 provisional reply 与 user push 一对一按序配对;延迟的非 user push 不消费无关 pending 身份,匹配本轮userSendAt的 user 最新窗口才完成配对,实时 user push 同样排除较旧轮次,权威多轮/截断窗口只让最新 pending 后缀匹配窗口内 user 后缀;动画贴底等待 settle 后再校验补滚;用更新的会话userSendAt识别旧 user 尾行并等待本轮 user push;短暂离线后同时保留 provisional 回复的窗口保护与 host-anchor 身份直到权威重锚、持久化调和或会话回收;已知旧轮次 user push / 窗口不改写当前回复锚点;死区轻拖后的贴底校验;手动回到底部时清除旧历史浏览意图;pending host-anchor 按首次userSendAt绑定并按发送窗口配对,阻止离线旧回复跨轮认领;普通 data/size 变化驱动 mVCP settle 安静窗,贴底校验在窗口内等待;软离线前无元数据或尚在微批中的 live 回复按 transport device 冻结未绑定身份,同一发送轮次的多条 assistant 行保序整体落到对应 user 之后,截断持久化回声保留完整内容时仍吸收权威 createdAt;hard remove 按 transport ownership 清理未索引 batch / provisional 行 / host-anchor,并保护已由 current shard 接管的同 session 窗口;元数据前同一 Maker turn 的多条 live block 共享轮次 cohort 并由首个 user 行整体消费;权威窗口 user 行参与 sendAt 边界分隔;pending identity 逐行记录 transport ownership 并精确回收 stale transport;多个离线未绑定 cohort 按轮次到达顺序恢复;跨 transport 的 32ms text-delta batch 在 deviceId 切换时先 flush,且同一 persistId 的已落地 streaming assembly 会按 transport 重置;权威重连窗口仅在 user/cohort 数量精确一致时按离线轮次顺序配对,截断或多出 user 时保守保持 pending;canonical current transport 的 pending assembly 在 clientId 迁移前及 done 边界后都拒绝 stale replay,已持久化 assistant 行也不被非权威 transport 改写或认领;对应回归测试compareMessageOrder排序规则本身;重开 resync 的窗口替换策略UI 变化
不涉及:无视觉样式、布局或文案变化;仅修复既有"发送后贴底跟随"交互未按预期生效的缺陷,恢复原设计行为,因此无新界面效果可截图。
怎么验证的
自动验证
手工验证
不涉及视觉变化;未做真机录屏。滚动校验逻辑与排序钳制均以确定性单元测试覆盖。
未执行的验证
apps/mobile无 ESLint 配置与lint脚本(仓库既有状态,非本 PR 引入),故未跑 ESLint。风险
风险分类
影响与回滚
createdAt打点及按轮次有序重锚、离线 pending 身份的发送轮次与 transport device 绑定、同轮多 assistant 的保序成组重锚、截断回声的权威时间吸收、hard remove 的 transport-owned 临时状态回收、stale/current 同 session 隔离、同一 persistId 的 streaming assembly transport 隔离、per-identity ownership、soft-offline ownership 保留、stale indexed replacement transport 保护与持久化 replay ownership 隔离、权威重连窗口的多 cohort 顺序与歧义保护、canonical current/stale replay 的 clientId 迁移前与 done 后 ownership 保护,以及常开 mVCP 的 settle 感知;持久化数据、协议、Desktop 均不受影响提交前检查
git commit -s,见 DCO)🤖 Generated with Claude Code