# 阶段3B实施任务书:固定会话与串行同步 日期:2026-09-22。工作方式已由用户调整为:**主会话完成文档与最终审查;另一位AI负责实现和自测。** 本任务书是3B实施的唯一直接入口;完整技术依据仍为《阶段3缓存同步方案与评审-2026-09-22.md》及其独立方案审查。 ## 1. 当前基线与目标 - 阶段2 `PlayerKVClient/PlayerKVModels` 已验收;正式地址固定 `http://s101.local:18080/`。 - 阶段3A `PlayerKVSyncModels/PlayerKVCacheStore/PlayerKVSyncState` 已验收:主测试86项、独立127断言、Unity编译0错误。 - 3B目标:把一个已认证且固定的 `S101AccountSession`、一个3A缓存命名空间和一个独立 `PlayerKVClient` 组合为单账号owner;所有Get恢复、Set、Delete和立即票据由单一调度器串行执行。 - 本批不接 `UserService`、`PlayFabMgr`、`CustomServerMgr`、玩法或全局容器;不访问正式服;不打包。 ## 2. 所有权和允许改动 实施AI拥有: - 新增 `Client/Assets/Scripts/Services/PlayerData/PlayerKVSessionOwner.cs` 及meta。 - 新增 `Client/Assets/Scripts/Services/PlayerData/PlayerKVSyncCoordinator.cs` 及meta。 - 新增 `CodexOutput/upserver/KVSyncCoordinatorTests/`,直接编译实际生产源码。 - 新增自己的实施日志 `CodexOutput/upserver/阶段3B实施记录-2026-09-22.md`。 - 可最小修改 `KVContractTests/KVContractTests.csproj` 与 `KVSyncTests/KVSyncTests.csproj`:将现有 `PlayerData/*.cs` 通配符改成各阶段实际需要的显式生产文件列表,使原42/86项回归命令在新增3B源码后仍能独立运行。不得修改两个目录的Program.cs、既有日志或测试语义。 默认禁止修改: - 已验收的3A三个文件、阶段2两个文件、`S101AccountSession.cs`。 - `UserService`、`PlayFabMgr`、`CustomServerMgr`、`RTService`、玩法、配置、SDK、服务器代码及共享状态/TODO。 若实际实现证明3A缺少必要的窄接口,先在实施记录中写明:现象、不能在3B文件内安全解决的原因、最小签名和新增测试;暂停该处并通知主会话。不得先改3A再补说明。不得整批回退或整理工作区。 上述两个csproj例外仅用于固定回归编译边界:`KVContractTests`显式包含阶段2两个文件;`KVSyncTests`显式包含阶段2两个文件及3A三个文件。3B自有测试显式包含阶段2、3A、3B生产文件和 `S101AccountSession.cs`。禁止用额外MSBuild命令行注入来掩盖原项目本身已无法构建。 ## 3. 必须形成的公开语义 具体类型名可小幅调整,但以下行为和信息不能丢失。 ### 3.1 Owner创建 提供异步创建入口,输入至少包括: - 已认证 `S101AccountSession`;创建时固定其 `ApiBaseUri`、规范化 `PlayerId` 和当前 `CookieContainer`。 - 缓存根目录、调用方不可变epoch、`Func isCurrent` 或等价归属检查。 - owner生命周期token。 创建时验证session非null、已认证、cookie非null、账号/API与缓存归属一致。使用捕获的CookieContainer创建owner专属 `HttpClientHandler`:`UseCookies=true`、`AllowAutoRedirect=false`,再创建owner专属HttpClient和已验收的PlayerKVClient。owner不Dispose认证session,不调用session.Login,不复用CustomServerMgr transport。 测试需要internal注入HttpMessageHandler/transport factory及可控调度钩子;生产公开入口不能允许任意运行期换Cookie或换账号。 创建流程:打开3A状态 → 获取操作租约 → `GetAsync(null, ownerToken)` → 再核对epoch/isCurrent/session归属 → 成功才 `Reconcile`。Get失败调用明确的read-failure路径;禁止将失败映射为 `{}`。创建失败必须收尾HttpClient和状态锁;返回结构化错误,不打印存档值、Cookie或响应正文。 ### 3.2 Coordinator编辑与票据 提供: - 远端Set编辑、localOnly编辑、Delete;返回3A写入结果及远端编辑票据。localOnly不创建远端票据。 - `FlushAsync`:捕获调用时水位,只处理该水位内版本;同一owner任何时刻最多一个变更HTTP在途。 - `WaitForTicketAsync(ticket, cancellationToken)`:取消只停止该等待者,不撤销已持久化pending、不取消共享Flush或同批其他票据。 票据至少固定owner实例/epoch、key和sequence。最终状态必须可区分:`Confirmed`、`Superseded`、`Blocked`、`Unknown`、`Cancelled`。不得用单个bool掩盖Unknown/Superseded。 - 精确sequence被HTTP成功且确认快照落盘:Confirmed。 - 尚未发送的旧sequence被同key新版本覆盖:Superseded。 - 进入unknown、冲突、认证失效、存储错误或owner关闭:按事实返回Unknown/Blocked/Cancelled,不能误报Confirmed。 - Wait调用者取消:该等待返回Cancelled,但查询同一票据的事实状态仍由协调器继续更新。 ### 3.3 单通道调度 - 初始化Get、恢复Get、Set、Delete通过同一个调度入口串行;不得并行发两个KV变更请求。 - `FlushAsync`在开始时记录最大sequence水位。循环调用3A `BeginBatch(watermark)`;空批次结束。 - Set批将batch items转为字符串字典;Delete批转为key列表。请求数据必须来自已持久化batch快照。 - HTTP 200后调用3A `ConfirmBatch`,只有确认快照落盘成功才完成票据。 - HTTP失败后按 `PlayerKVResult.MayHaveCommitted` 调用3A `FailBatch`;401/403同时标记认证失效。任何MayHaveCommitted=true都冻结为Unknown,不自动重试。 - 只有有正面证据“未进入传输”时可按false失败并允许以后重新Get;不要根据400/401自行推断未写。 - Flush汇总至少报告Confirmed/Superseded/Blocked/Unknown数量及最终错误类别;调用者取消等待不成为共享HTTP token。 ### 3.4 原子准入、失效与Close Owner内需要一个短临界区统一完成:检查closing/closed、登记实际操作、取得租约。操作退出必须finally归还。禁止“先检查状态,稍后登记”。 `CloseAsync`: 1. 在同一准入门内原子置closing,禁止新操作;重复调用返回同一个关闭任务。 2. 退出锁后取消owner token;取消回调可能同步执行,不能持锁Cancel。 3. 结束尚未完成的被动票据等待;等待者本身不算必须drain的实际操作。 4. 等待已登记的初始化/调度/磁盘操作全部退出,不持admission/state/dispatch锁等待。 5. 最后依次释放协调器transport、3A state/file lease和owner资源,只执行一次。 Close不隐式Flush。已发送写被Close取消时仍可能提交,必须保留active/unknown证据;不能为了让新owner快速打开而强制释放锁。若transport不响应取消,关闭任务保持未完成,同命名空间新owner应Busy。 每个await前后检查owner epoch、`isCurrent(epoch)` 和lifetime。旧成功、旧401、迟到取消只能更新旧owner命名空间的可靠证据,不能向新owner发布事件、不能换用新Cookie重发、不能触发无归属全局重登。 ## 4. 结果模型和日志要求 - 结果模型可放 `PlayerKVSyncCoordinator.cs`;不要为两个简单enum额外扩大生产文件。 - 不把 `PlayerKVError` 直接当完整同步状态;保留HTTP错误和缓存/票据状态两个层次。 - 日志/异常只允许账号是否匹配、epoch、数量、sequence、HTTP状态/错误类别;禁止存档值、完整请求JSON、Cookie和服务器正文。 - 任何异常都必须转换为结构化结果或使创建失败并可靠收尾;后台任务异常不得成为未观察异常。 ## 5. 实施顺序和检查点 实施AI必须按顺序更新自己的实施记录: 1. 固定接口草图、锁顺序及文件边界;确认不需要改3A。 2. 实现Coordinator纯调度和结果模型,先配HttpMessageHandler替身测试。 3. 实现SessionOwner创建/归属/Close,补并发交错测试。 4. 完整离线测试、原3A/阶段2测试回归、Unity编译。 5. 生成最终源码hash、列明未执行项,停止开发并交还主会话审查。 不得自行进入3C、访问s101、接游戏入口、修改状态/TODO、打包、提交或发布。 ## 6. 3B验收矩阵 至少覆盖: 1. 创建:未认证、错误账号/API、Get 200空字典、Get401/403/协议/网络/取消、打开缓存Busy/RecoveryRequired;失败不留锁/transport。 2. Cookie:两个owner各自独立Cookie/handler;捕获后调用方切session或Dispose,旧owner不借新Cookie;禁止自动重登。 3. 串行:Set/Delete交错、批10、51+key、Flush水位、连续编辑时Flush可结束,最多一个HTTP在途。 4. 多版本:v1在途产生v2;v1确认后v2保留;尚未发送v1被v2替换时v1票据Superseded。 5. 票据:两票据同批,其中一个等待取消不影响HTTP/另一票据;取消Flush等待不撤销目标;重复等待得到一致事实。 6. 故障:预发送取消、发出后取消、超时、网络、400/401/403/500、HTTP200后磁盘确认失败、active写前磁盘失败;逐项核对unknown、pending和票据。 7. 换号/代际:101请求在途→失效→102 owner;101迟到200/401不改变102状态,不使用102 Cookie,不发布全局事件。同号新epoch同样隔离。 8. Close:检查与登记交错、并发Update/Flush/Close、Cancel同步回调重入、重复Close、transport延迟/忽略取消、文件锁仅实际收尾后释放。 9. 回归:KVContractTests 42、KVSyncTests 86保持通过;新增测试直接编译实际生产源码;Unity编译0错误,新文件无新增警告。 允许测试使用合成API和Cookie、任务目录缓存;不允许正式服写入或真实业务key。测试必须有确定超时,不能无限等待。 ## 7. 实施AI交付格式 完成时只报告: - 修改/新增文件及SHA256。 - 新增测试数量、分组、命令和退出码。 - 阶段2/3A回归及Unity编译结果。 - 独立说明哪些是合成传输证据,哪些尚未验收。 - 已知限制或任何偏离任务书的点。 主会话收到交付后将逐文件审查、复跑关键测试、检查工作区差异,并决定通过、要求返工或补裁决。实施AI不得自行宣布3B最终验收通过。