# M2:KVMgr层级依赖纠偏意见(主会话,待完整方案审查) 日期:2026-09-29。用户指出:PlayFabMgr原本作为存档底层入口,KVMgr也应提供底层函数,上层业务和Service依赖它,不能由KVMgr反向调用外部Service。此意见成立;本文纠正[M2底稿](M2-旧方法与调用方合并设计底稿.md)的层级表述,不修改B02受审交付或生产代码。 ## 源码事实与责任 当前`Client/Assets/Scripts/Core/KVMgr.cs`只有四个显式handle入口,没有直接Resolve或调用`UserService`、`CustomServerMgr`、UI或业务模型;它调用`PlayerKVGameSessionHandle`的读、写、Flush、Wait。这一部分是薄存档门面。问题是`KVMgr`位于`Core`,却引用位于`Services/PlayerData`的`PlayerKVGameLoadGuard`、`PlayerKVGameSessionHandle`、`KVSnapshot`和结果类型;尤其`PlayerKVGameLoadGuard`由`PlayerKVGameLoadCoordinator`进入/释放,属于加载阶段的编排门。`KVMgr`直接检查它,形成了底层存档入口对上层加载规则的反向依赖。当前均在同一HotUpdate编译域,编译通过不证明层级合理。 B02修订2的目标和审查仅是四入口**逐字行为等价搬迁**,所以原PlayFabMgr块中的guard检查被原样搬入KVMgr。复核PASS证明等价和兼容,不证明层级设计正确。主会话此前把“等价”误当成“可沿此结构扩展”,这一推论撤回。B02的44项hash和限定关闭事实保持,不倒改受审源码;纠偏属于下一完整设计和独立审查范围。 ## 应有依赖方向 ```text 玩法/UI/数据模型 → 业务操作或所属Service → KVMgr存档入口 → 固定会话Handle/Owner/KV存储 ↑ 登录/加载/退出编排 ── 发布或撤销原Handle、控制存档可用阶段 ``` - `KVMgr`只负责显式handle的键读、键写、Flush和原票据等待,以及这些操作自身的输入、句柄状态和结果;不获取当前账号,不调用Service、业务事件或UI,不管理登录、31模块Apply或生命周期。 - 登录/加载Service拥有认证、解码、31模块Apply、原handle发布和关闭屏障。业务操作在首次模型变化前捕获由所属Service显式传入的原handle,之后只向KVMgr传它;旧回调不能重新查“当前”Service或Owner。 - 加载期间禁止外部读写的门必须落在**存储模块可供上层控制的准入契约**:加载编排调用其Enter/Exit,KVMgr只检查同模块的准入状态;不得让KVMgr反向依赖`PlayerKVGameLoadCoordinator`或业务Service。旧PlayFabMgr上的Legacy禁写诊断仍须保持,不能因移动guard而失效。 - 文件/命名空间应表达同一逻辑模块。建议把KVMgr及其直接使用的准入契约归入`PlayerDataStorage`存储模块(现有句柄/Owner所在模块),上层`UserService`、`PlayerKVGameLoadCoordinator`只从外部调用它。无需为改目录一次搬动整个KV引擎;具体文件白名单和Unity meta/GUID处理须在完整方案中列清。 ## 路线比较与建议 | 方案 | 影响 | 裁量 | |---|---|---| | 推荐:存储模块内的薄KVMgr+下沉准入契约,上层显式发布原handle | 定向修正guard依赖;保留现有Handle/Owner/缓存/同步引擎及四入口结果合同,需验证加载禁写与旧PF诊断 | 作为M2正式方案的优先路线 | | Core单独定义接口/DTO,Services实现并注入KVMgr | 编译层级最显式,但现有结果、Handle、Owner类型要抽取/适配,改动面大 | 当前最小迁移不采用 | | 保持Core→Services/PlayerData和现有guard检查,直接扩展旧PF兼容函数 | 眼前改动少,但继续强化反向依赖,正式接线更难审 | 不作为后续设计基线 | 此处的“下沉准入契约”**不是**新增全局当前账号或第二套缓存。它只表达当前加载阶段是否允许外部KV调用;原handle仍由上层操作显式持有。是否移动现有`PlayerKVGameLoadGuard`本体或抽出共享的最小状态,必须以当前21处guard引用和加载竞争测试为边界做一次完整设计,不能在编码时临时选。 ## 下一份完整方案必须补齐 1. 精确分层图、KVMgr/准入契约/会话Service的源码白名单和调用方向;显式说明Core与`Services/PlayerData`现状如何纠正,以及Unity meta/GUID如何保留。 2. 准入门的时序:Prepare、31模块Apply/通知、发布、拒绝、Revoke、Close;原handle在加载中的内部读取与外部KVMgr读取必须区分,旧PF side-effect计数仍可检测。 3. 实际业务方如何得到原handle,哪一处捕获、何时撤销;读三态、写Accepted/uncertain、原票据Wait与旧epoch停止规则不变。 4. 既有B02 Route/B01/故障测试、B2加载guard、Unity双构建及必要业务回归;不因目录/准入调整重写存档格式或玩法计算。 在以上方案完整评审、主会话裁决前,不调整`KVMgr.cs`、guard、句柄、Service或业务调用。固定地址`http://s101.local:18080/`;仅用Unity CLI Loop,不使用UnitySkills,暂不打包。