# 群成员与已读详情审查记录（2026-09-08）

## 结论与范围

审查覆盖本任务插件两次实现提交（04b7294、9725042）、Chat 分页提交（8145eee）及对应合同；以下问题已修复并补回归验证。当前方案在既有 Host / SQLite / Browser Store 内收敛，没有新增框架、依赖、服务或持久化状态机。测试支持这些具体结论，不代表对任意环境作“绝无缺陷”的保证。

## 已修复的问题

| 级别 | 问题与影响 | 修复与证据 |
| --- | --- | --- |
| P1 | 两个资料任务占满后，分页生产者等待空位，慢头像拖慢整群名单 | 基础分页独立推进；仅资料队列最多两个在途。member-directory-review 测试在两个任务持续阻塞时仍完成 150 人/3 页 |
| P1 | 取消、失权、成员变更之后，旧请求或迟到缓存可能回写 | 传播 AbortSignal；失权取消缓存恢复；刷新代次与既有 runtime cache epoch 阻止旧写入。contract/paging/store 测试覆盖取消、失权、重试及晚到结果 |
| P1 | presentation 被当作名单，可以重新创建已移除成员 | Page 与 Presentation 使用独立类型；Browser/SQLite 共用 applyMemberUpdate。只有 membership 创建实体，资料只能补齐已有实体或明确移除；不增加 tombstone 状态 |
| P1 | 旧组件的 subscribe 可以激活旧账号，回滚当前数据作用域 | 账号激活仅由运行时生命周期负责；订阅按账号隔离，未激活订阅不请求网络，旧订阅不能影响当前账号 |
| P1 | 缺少 items 的异常响应被当成空数组，可能删除有效成员 | Host 先验证数组、来源、身份、状态、游标及批次边界，再接受移除事实；错误保留原数据 |
| P1 | 缓存中的角色被用于管理能力判断 | 删除重复 selfRole/selfStatus 及 fallbackRole；权限只取 group.settings，缓存不授予管理能力 |
| P2 | 一个成员头像失败导致整批姓名/统计不更新；基础页的零统计被当成真实结果 | 按成员记录资料失败，仅保留不可用头像；已读到的名称与统计正常更新。基础统计显式未知；后端分页独立 DTO 不输出残留统计 |
| P2 | 旧成员缓存覆盖当前已读详情姓名；账号变化后详情本地状态残留 | 当前已读查询姓名优先，缓存只补缺失项；详情按账号、运行代次、消息标识隔离，退出登录清行 |
| P2 | 同名成员/未知邀请人按名字合并，混淆不同身份 | invitees 仅按 memberRef 合并；缺少邀请人 ID 时不以名字合并事件；同名测试保留两个人 |
| P2 | 500 个缓存行立即订阅所有头像，形成无关网络负载 | 复用现有头像 hook，通过 IntersectionObserver 按可见性订阅；500 行/0 可见为 0 请求，8 行可见只加载 8 个 |
| P2 | 缓存字段和入群事件校验不足，损坏数据可能进入渲染；清理失效引用可能清掉同时修复的缓存 | 成员、事件、人物均按白名单投影和类型校验；精确删除失效引用，不清空并发的新快照 |
| P2 | 容量查询反复扫描 JSON；隐藏详情的已排队刷新仍可能运行 | 持久化 payload_bytes，容量查询求和小整数；隐藏时清定时器，回调复核前台状态和观察者 |
| P2 | 新 UI 同时保留分页/全量路径与双构造器，形成迭代过渡态 | 删除新 UI 的全量降级和旧构造器；移除旧完整查询对新缓存的写入。Tools 描述只保留业务用途和参数语义 |

## 最终数据边界

- Chat 拥有成员事实；分页为实时游标遍历，缺席不是删除。完整遍历后对缺席缓存成员按 ID 核验，只应用明确状态。
- Host 校验账号/群绑定引用，统一提供分页、资料和缓存。SQLite 是有界展示缓存；缓存不会替代服务端请求，也不决定读权限或写权限。
- Browser 每个账号/群一份成员 Store，按稳定身份差量合并；组件只订阅和保存交互状态。重复打开抽屉不重复读取名单。
- 消息参与范围、已读/未读仍来自已读接口，不能从当前成员名单推算。basicOnly 是轻量展示投影；既有完整 API 服务其原有调用方，不是新 UI 回退。
- 保留必要的取消/代次、短期失败状态、容量上限和一次性 SQLite 结构迁移。没有新增双格式缓存 reader、全量替换、兼容回退或业务状态机。

## 验证

- 插件全量：431 个文件通过、4 个文件跳过；4672 项通过、5 项跳过。typecheck、build、可执行入口及 Windows 凭据 helper 构建校验通过。
- 新增/扩展测试覆盖：成员流转、缓存重开、账号/群隔离、失权、并发取消、畸形响应、部分资料失败、可见头像、姓名优先级、同名身份及隐藏详情刷新。
- Chat：相关 Handler/领域测试、go vet 通过；Mongo 7.0.14 实际验证 500 人/10 页、无重复或跨群，explain 使用原有索引且无 COLLSCAN/SORT。
- 官方 DSH 0.1.1-rc.2 ToolRuntime：三个新工具真实注册、携带会话上下文执行、卸载通过。仓外 Consumer 从 tgz 安装、公开 SDK 编译及调用通过：缓存 499 人、基础页 49 个活跃成员（另 1 个已退群）、有效后续游标、资料姓名正确。
- 本机独立 DSH Profile + 真实 Host/SQLite + 合成远端：冷启动 500 人最终为 10 次基础分页、10 次资料请求，无 members/list 回退；打开抽屉不重复刷新。随后远端改名/退群，UI 与 SQLite 同时收敛到 499 人；缓存字节数 387264，与实际 UTF-8 字节数一致。
- 再次停止并重启 Host、改变端口：缓存请求在 669ms 发出、688ms 返回，740ms 时 499 行可见（相对于页面导航；相对于成员请求约 70ms）。远端分页已于 670ms 发出，但仍在 2 秒模拟延迟中；此时关闭抽屉可正常输入并清空草稿，未发送消息。
- OpenSpec strict 校验通过。所有源改动位于任务 worktree；没有改动插件版本、依赖、锁文件、用户客户端或生产环境。

## 发布与验证边界

新成员 UI 只走分页，必须先部署 Chat 分页接口，再接入插件；后端缺少该接口时保留已有缓存并报告请求错误。该后端改动用于真实分页和轻量名单，不是实现本地缓存的前提。

本机缺少 Docker，后端 Docker E2E 未运行通过；Mongo 全包有初版交付时已在未修改 master 9f649eac 复现的既有失败。本次新分页的原生 Mongo 等价场景通过。没有宣称后端全量门禁全绿。

浏览器验收使用合成业务远端，不能替代正式服务器负载、生产消息发送或 Windows/Linux 实机验收；没有生产延迟保证。未部署、推送、创建 PR 或替换用户安装版本。

验收远端 fixture 未实现 Arko 资料、内测群状态和部分会话偏好接口，浏览器对应 502 已按 operation 定位，不属于成员分页/缓存结果；因此未把该隔离场景称为全产品 E2E。最后一轮缓存事件校验修复后，重新打包安装并复验 499 行及改名、正式 Tools 和仓外 SDK。

复验期间 official/dev 前进到 6429e25（含发布 0.1.47、输入框样式和交织卡片改动）。本报告全量测试对应本任务原始基线 121f68e 加本任务实现和审查修复，不冒充最新 dev 集成验收；发布前仍需在最终目标上集成并执行相应门禁。
