# 阶段4A交付与验收矩阵 日期:2026-09-23。最新状态:**外部实施复核已完成,主会话核对版本并逐条裁决,4A限定阶段关闭;4B仅方案准备、未编码。** 见[独立复核](阶段4A独立实施复核-2026-09-23.md)及[关闭裁决](阶段4A实施复核裁决与关闭-2026-09-23.md)。下列测试是原交付记录;独立复跑和P3保留项以关闭裁决为准。 设计及补审放行依据:《阶段4A差异裁决与实施批准-2026-09-23.md》。所有4A网络测试均为替身;没有访问正式服、没有打包。 ## 1. 本阶段可观察效果 - Owner可读取当前Ready会话的独立不可变本地合并快照;未Ready不会被包装成空存档,过期/关闭优先返回StaleOrClosing。 - 桥接只拥有KV Owner,不销毁登录session。固定句柄永远指向原Owner,旧回调不会借用新账号。 - Open/Close按任务链串行;Close立即撤销入口、等待旧传输与Owner关闭完成后才允许新Owner;排队取消不提前放开屏障。 - 正常初始Get失败后可重新Open;Close失败保留任务与Owner并阻止重开。Unknown不自动重试,Close不隐式Flush。 - 这些是独立层能力。游戏仍未接入这个桥接,不能据此称玩法存档已经迁移。 ## 2. 文件和完整SHA256 | 文件 | SHA256 | |---|---| | PlayerKVSessionOwner.cs | BFB5AC0DF38BCACC341646292ACAA71606F2DC5FECF91535785D222EAFACF7B5 | | PlayerKVLocalReadResult.cs | 9A00AA0ECEA286FC4474729A1BFABDD3D5A1453182B5FCB91D11CD81724481AF | | PlayerKVGameSessionBridge.cs | DD888351BFA4BBA03E953F39E11362AF8EA9F76FB56AC1CB77D9053C81227363 | 生产路径均为Client/Assets/Scripts/Services/PlayerData。 新增两份meta;三份旧csproj各新增一行Compile;新增KVGameBridgeTests宿主和证据。 所有10个新增/修改源码、meta、csproj的完整hash见[final-source-hashes.json](KVGameBridgeTests/final-source-hashes.json)。 边界证据: - [owner-diff-check.json](KVGameBridgeTests/owner-diff-check.json):去除新增读接口及辅助后,Owner原文件hash完全匹配。 - [project-diff-check.json](KVGameBridgeTests/project-diff-check.json):三个旧csproj各只有已审一行Compile新增。 - [scope-hash-check.json](KVGameBridgeTests/scope-hash-check.json):其他7份基线生产文件、3C测试Program及既有3B/Review Program未变。3C历史证据未改;其旧源码hash仍表示当时版本,4A新增接口记录在本阶段。 ## 3. 命令与运行结果 命令工作目录C:/projects/ft;使用已有离线依赖。新宿主首次restore受沙箱NuGet配置读取限制,提权读取后成功。测试期间无正式网络请求。 | 命令 | 结果 | 证据(KVGameBridgeTests/) | |---|---|---| | dotnet run --no-restore --project CodexOutput/upserver/KVGameBridgeTests | 退出0,18组,测试断言221+最终脱敏检查5;失败0,无编译警告 | runs/20260923080423_b6797743868d42ee98f87ff7b4b91dd1/result.json | | dotnet run --no-restore --project CodexOutput/upserver/KVContractTests | 退出0,42/42 | stage2.log | | dotnet run --no-restore --project CodexOutput/upserver/KVSyncTests | 退出0,86/86 | stage3a.log | | dotnet run --no-restore --project CodexOutput/upserver/KVSyncCoordinatorTests | 退出0,29/29 | stage3b.log | | dotnet run --no-restore --project CodexOutput/upserver/KVSyncCoordinatorReviewTests | 退出0,1项通过 | stage3b-review.log | | dotnet run --no-restore --project CodexOutput/upserver/KVStage3CTests -- --offline | 退出0,8/8 | stage3c-offline.log及3C的新离线run | | dotnet build --no-restore CodexOutput/upserver/KVLiveTests/KVLiveTests.csproj | 退出0,0错误/0警告;没有运行 | live-build-only.log | | uloop compile --project-path C:/projects/ft/Client --wait-for-domain-reload true | 退出0,0错误/0警告 | unity-compile.json | Unity初次连接失败,确认该项目Editor未运行;启动项目指定2022.3.62f2c1后,get-version确认DataPath=C:/projects/ft/Client/Assets、CLI Loop 2.2.0,再编译通过。没有PlayMode或打包。unity.log保留首次失败,unity-compile.json是最终结果;unity-editor.log是本地原始编辑器诊断,不作为脱敏交付JSON。 三个旧csproj在测试后仅规范为原换行格式,使移除新增一行后字节内容相等;没有改变已测编译条目/源码/行为,不重复整套回归。 ## 4. A1–A12逐项矩阵 以下为原交付技术验证;现已由外部独立复核及主会话逐条裁决接受,详见关闭裁决§3。 | 编号 | 具体用例/实际观察 | 结论 | |---|---|---| | A1 | A1-ready-merged-detached-snapshot:baseline/pending/localOnly合并、Delete缺席、快照不可修改且后续写不改变旧快照、携带Owner/玩家/epoch | 通过 | | A2 | A2-validation-cancellation-and-reopen:未认证、ID/API不符、提前取消0Handler;A2-close-during-initial-get:忽略取消Get不提前返回、不发布句柄,收尾后可重开 | 通过 | | A3 | initial-read-failure-releases-slot、busy-recovery-storage-errors:失败后可重开;conflict-unknown-no-empty-save:Conflict/Unknown/StorageError拒读,Data=null;close/create-cleanup-failure-blocks-reopen:清理异常不丢槽位/Task、后续CloseFailed | 通过 | | A4 | A4-A6-A7-close-drain-queue-cancellation-stale-handle:101写传输闸门忽略取消,Close/102 Open仍未完成;释放后才开102,MaxActive=1 | 通过 | | A5 | A5-repeat-open-close-single-owner:同账号重复Open不同Owner且旧句柄失效;重复Close返回同一Task | 通过 | | A6 | 旧101句柄Update/Delete/Flush/Read/Wait拒绝;102快照为空且写请求数不变 | 通过 | | A7 | 关闭未完成时排队Open取消立即返回Cancelled;原Close及后来的有效Open仍受闸门约束并完成 | 通过 | | A8 | read-during-flush-preserves-batch:在途Flush时合并视图正确、不改变发送数/批次;epoch-invalidated-after-read:读后归属失效拒绝;stale-priority-over-not-ready:异常分支优先Stale;read-close-reentry-drains-lease:Close等待读租约,读不发布失效快照 | 通过 | | A9 | login-session-dispose-or-relogin:session提前Dispose或重登换Cookie后,读/写/Wait拒绝,桥接仍完成Close且0变更发送 | 通过 | | A10 | pending-reopen-no-implicit-flush:关闭0写,同账号新session重开读到pending,再显式Flush确认 | 通过 | | A11 | default-transport-configuration只构造并检查默认handler,无Send;所有实际登录/Get/写走synthetic.invalid替身;输出扫描0敏感命中 | 通过 | | A12 | 42/86/29、Review、3C离线、KVLiveTests只build、Unity通过;源码范围及三个csproj单行差异核验通过 | 通过 | 补充:A3-write-unknown-retains-ticket-semantics验证Unknown票据保留,不返回可玩数据、不再次发写。 并发由TaskCompletionSource闸门、读边界回调和token事件控制,未使用Sleep推断顺序。 ## 5. 脱敏与传输边界 [artifact-and-transport-check.json](KVGameBridgeTests/artifact-and-transport-check.json):4A result.json中fixture key/value、Cookie/Token敏感字段、用户名路径均0命中;accessedFormalServer=false。 证据依据是实际调用路径:登录及Bridge内部工厂均替换为限定synthetic.invalid的Handler,默认HttpClientHandler仅反射获取并检查配置,KVLiveTests仅构建。该字段不是独立网络抓包结果。 缓存仅位于新测试run/cache,保留合成值和故障证据。故意Close失败案例保守保留锁到测试进程退出,属于离线反例,无正式账号遗留。 ## 6. 自审、限制与下一步 [限定代码自审](阶段4A限定代码自审-2026-09-23.md)及外部独立实施复核均完成,无待修复P1/P2;P3-1偶发测试失败根因未定位,按关闭裁决保留后续跟踪。 Close失败不自动恢复;同一桥接会返回CloseFailed。业务调用者需保持固定句柄,不能自行把旧回调转成“当前账号”保存。isCurrent应为轻量归属判定,不可同步等待自己的Close。新接口不承诺游戏存档已迁移,也不改变3A/3B保守恢复语义。 4A已关闭。下一步审查[4B分期与4B1方案](阶段4B分期与4B1登录存档准备方案-待评审-2026-09-23.md),通过并裁决后才编码,不直接继续游戏接线。