保存独立KV用户服务、固定会话存档与原业务接线,以及C3d资料缓存和C3e本人统计写。 保留原PF/AGG路线、业务公式和时序;榜单读取、好友资料、公告、匹配及首场景闸仍待完成。 验证:ServiceHost两条件各33组646断言;Unity CLI Loop编译0错误269警告。 包含相关方案、评审裁决、测试及状态文档。未操作服务器、正式账号或打包。
58 lines
11 KiB
Markdown
58 lines
11 KiB
Markdown
# M2 合批正式独立方案审查
|
||
|
||
日期:2026-09-29。审查人:原 ZCode(独立侧),按[一次性正式前审提示词](M2-合批原ZCode一次性正式前审提示词-2026-09-29.md)执行。只读客户端源码;未读/改任何服务器代码,未调用正式 101/102,未进入 Play,未打包。
|
||
|
||
## 1. 基线核验
|
||
|
||
- manifest `M2-合批正式受审基线.json` SHA256 实测 `DBC965EDBF48FADA4C1508F2662562F4FD72C01711D8E2FE2022AC4956896EF3`,与提示词一致。
|
||
- **2165/2165 项长度与 SHA256 全部一致,0 缺失 0 漂移**;12 个 expectedAbsent(新源码/测试与 .meta)全部仍不存在。开发侧[自核 JSON](M2-合批正式前审包自核.json) 与本审查独立结果一致。
|
||
- 基线含 2165 项只读快照 + 110 现存白名单文件;本文不因列入基线授权任何白名单外修改。
|
||
|
||
## 2. 总裁决:**有条件 PASS —— 批准在候选白名单 110+12 文件与方案 §2–§7 行为边界内连续编码**
|
||
|
||
无 P1 阻断。2 项 P2 为批内必须落实的精确设计点(不阻止开工),4 项 P3 登记修正。依据:①基线零漂移;②方案全部可抽验事实声明经源码核验属实(见 §3);③结构设计与既有全部裁决链(双提供方约束、纠偏、预审裁决、复核裁决)一致无回退;④外部能力缺口与客户端可编码范围正确分离;⑤奖励持久性限制如实声明未偷换协议。
|
||
|
||
## 3. 提示词风险清单逐项结论
|
||
|
||
**3.1 独立 KVUserService 是否真正摆脱旧类与 SDK 类型 —— 成立。** 方案 §2.1/2.3/2.6 的组合是充分解:LoginStage 按冻结选择注册新类(唯一注入源,`LoginStage.cs:24` 现状核实);从 `IUserService` 移除 `EntityKey entityKey`(当前为 PlayFab DTO,`UserService.cs:6,66`)使"新类零 PF 类型引用"与"实现共用契约"同时成立——这是唯一解且方案已选;Duel 三处真实访问(`EventFishingDuelPanel.cs:634-635,748`)改经 PlayFabUserService 具体能力,该文件在白名单内。`IKVUserLoadReceiver`(消费者仅 Bind)与 `IKVUserLifecycle`(消费者仅 PFLoginAct/QuitAct,复用 `CloseKVForValidationAsync`/`ObserveKVQuitAsync` 既有签名,不加第三关闭器)均有实际调用者,符合 AGENTS.md。CustomId:**接口现状确为 `{ get; }`(`UserService.cs:70`),本批加 setter 是必要的**——见 §6 审查者错误披露。
|
||
|
||
**3.2 共用存档契约必要且足够简单 —— 成立。** 消费者=台账 202 项 business-store 调用(否则每文件重复分流);`IPlayerSaveStore`/`PlayerSaveStores` 职责限于选择后读写语义、固定实例绑定与确认,未新增第二开关/Owner;KV 实现直用 KVMgr 四入口与原 handle,PF 实现委托 PlayFabMgr 原缓存/写入;公共结果不含 PF DTO。固定 store 一次绑定、40 秒单调度者(Lifetime 内)、await 前捕获/await 后验证、失败≠缺键、remoteStore=false、`WriteAndConfirmAsync` 仅 Confirmed 为真——与 KVMgr/Guard/票据既有合同吻合(`KVMgr.cs:7-51`、`PlayFabMgr.cs:202-243,323-354` 复核)。Core→Services 新依赖未引入:新文件在 Services/PlayerData 引用 Core 的 KVMgr/PlayFabMgr 是正确方向;`Core/KVMgr` 物理搬迁明确保留待办,未冒充已解决。
|
||
|
||
**3.3 台账规则与白名单覆盖 —— 独立核证通过。** 台账 224 项唯一 ID,规则分布 202 business-store / 11 retain-pf-and-used-validation / 8 retain-pf-move-formal-only / 2 confirmed-consumption / 1 retain-agg;PF 内部、AGG、受控验证调用保留不误改(样本 B3-C012 `PlayFabMgr.CompareDatas` retain ✓、B3-C087/B3-C175/B3-C179/B3-C181 与源码逐一相符 ✓)。**全客户端 83 个含 `PlayFabMgr.Instance` 的文件中 82 个在白名单内,唯一例外 `UserService.KVGameplayLoop.cs` 是按设计不改的 kv-loop 通道**;台账 224 条路径全部落在白名单内(独立复算,非引用自核 JSON)。
|
||
|
||
**3.4 本地配置 LoginDays=0 的含义 —— 表述准确。** [配置投影](M2-合批动态配置投影.json):tbfishingevent.json 1466 行(实测 `cfgData/tbfishingevent.json` 恰为 1466 行 ✓)、70 组分支、直接 LoginDays=0、TriggerPack 同 0,附 hash 与"仅本地投影"警告。方案按全部代码可达分支迁存档、不删活动、不 froze 配置,正确。
|
||
|
||
**3.5 奖励/消耗动作的可实施范围 —— 批准方案 §6 全表,含两个真实旧缺陷修复。** 逐项源码核验:邮件批量 `TakeReward` 确实"请求 `EMailState.HasRead` 后按 `HasReward` 筛选"(`InGameMailHandler.cs:448-468`,单件版 :426-431 用 `RewardTaken` 正确)——修为 RewardTaken+请求前冻结未领集合,正确且需对照回归(方案已列);`FriendService.GetInvitedListCount→SetLinkAwardData→InviteLinkRewardCount`(`FriendService.cs:29-63`)✓;两个 confirmed-consumption 恰为 `FishingBehaviorB.cs:839-857`(ConsumeBaitOnPlayfab→SyncDataImmidiate)与 `FishingTurntablePanel.cs:580-584`(ConsumeOnPlayfab)✓。Survey 尾数:现状为十六进制转数再 `%10`(`SurveyService.cs:56-69`),方案"KV 十进制 %10、PF 保留十六进制"与代码吻合。**持久性限制的声明是本方案最诚实的一段**:多键确认无事务回滚、邮件"服务端已置已领/物品未落 KV"跨系统窗口如实保留、不靠自动重放补偿——接受此边界划分:本批准"代码迁移+普通成功回归",**不批"奖励完整通关"**,最终报告须逐动作列风险(方案 §6 末段已自我设限,维持)。
|
||
|
||
**3.6 外部能力三分 —— 划分正确。** [集中问题单](M2-客户端致服务端线上合同集中问题单-2026-09-29.md)四项(新 ID 兼容、KV 等级榜聚合、跨账号公开资料、PF 好友列表+匹配替代)全部是服务端实现依赖,不是产品再决策。客户端可编码范围(独立服务/个人 KV/原游戏服按新 ID 接线)不被挂起;功能运行放行与最终通关分别受聚合/资料/好友/匹配入口约束;无猜测路由与空成功适配器。
|
||
|
||
**3.7 formal 测试宿主 —— 方向正确。** ServiceHost Program/Stubs/csproj 迁真实 KVUserService、PF SDK stub 记调用计数、不允许 stub 成功身份;对既有 90 组用例"计数可能有竞态、比较命名用例和失败数"的提醒合理。
|
||
|
||
**3.8 清账与完成声明 —— 完整。** 闲置 formal 分支静态重扫后删除(不整文件删)、PF/AGG/验证入口保留、命名与物理分层延后、"全链实证前不称 M2 完成"——与最终门控清单一启约束。
|
||
|
||
## 4. 发现清单(一次汇总)
|
||
|
||
| 编号 | 级别 | 内容 | 必要修正 |
|
||
|---|---|---|---|
|
||
| P2-1 | P2 | `LastLoginTime` 三分映射机制未定死:接口为非 nullable `DateTime`(`UserService.cs:59`),`TimeRefreshManager.GetLastLoginTime()` 现直接转发 `_userService?.LastLoginTime`(`TimeRefreshManager.cs:106-108`),服务非 null 时**永不为 null**——"缺键 MinValue 哨兵→映射 null"必须在 TimeRefreshManager 显式加 MinValue 判别,且读侧须能区分"MinValue=缺失哨兵 / parse 失败=畸形错误 / 正常值"三种;写侧"首场景每日消费完成后才写本次 LoginTime"的确切时点要落到实施清单。做错会静默破坏每日重置分支(`:74-81`) | C1/C2 内把该机制写成三行精确规则并入测试职责(缺失→null→首次登录分支;畸形→资料错误;正常→比对 DayOfYear) |
|
||
| P2-2 | P2 | KV 登录链的分析/广告初始化未列出:`OnYinDunLogin`(易盾上报)与 `InitTapJoy`(ANDROID,读 `TapJoy_Diamond`)仅挂在 PF `LoginCore`(`UserService.cs:219,223`);M31 已有 `KVTapJoyBalance` 字段但无消费决定。首批 101/102 桌面验证不受影响,移动端 KV 会缺风控上报/广告余额恢复 | 批内明确:KV 链暂缓并登记清账(推荐,因属移动端平台链),或给出 KVTapJoyBalance 消费点;写入最终门控清单,不得静默丢失 |
|
||
| P3-a | P3 | 两处阶段闸(`PFLoginAct` formalKV 早退 :98-115 与 `LoginStage.RequestNextAct` :114-115)须**同步最后解除**,避免半开状态(登录页已放行而场景闸仍拦,或反之) | 实施顺序固定为 C3 全绿后一次移除两闸 |
|
||
| P3-b | P3 | `AggUserService.cs` 在白名单但唯一关联 B3-C168 为 retain-agg(不改),条目应注明"预期零改动或移出",防止顺手扩面 | 白名单定稿时写明 |
|
||
| P3-c | P3 | `ChatService.WaitingForLogin`(PF 链 `UserService.cs:217` 调用)在 KV 链的对应时序未点名——方案 §5"先订阅或 Init 发现已授权"原则已覆盖,实施时验证 Chat 仅靠 EvtAPISvrLoginSuccess 即可初始化 | C1 验证项 |
|
||
| P3-d | P3 | 台账 `runtimeVerified:false` 全量与 `reviewStatus:candidate-not-approved` 全量正确,但最终集成时须逐项翻转为已验(含首场景 PF 调用计数=0 的解除闸证据) | C3 交付物 |
|
||
|
||
## 5. 批准范围(明确边界)
|
||
|
||
- **文件**:候选白名单 110 现存 + 12 新增,逐文件 scope 与 callIds 约束("非任意文件重构");`UserService.KVGameplayLoop.cs`、`PlayerKVEditorValidationHost.cs`、`DevIAPService.cs`、`AiHelpManager.cs`、`EventPartnerInvitedPanel.cs` 等**白名单外文件零修改**(后两者经接口取值无需改,前者属不改但回归)。
|
||
- **行为**:方案 §2(服务/DI/契约/关闭)、§3(身份资料发布)、§4(存档契约与台账 202 项)、§5(首场景与动态活动)、§6(奖励确认与两个旧缺陷修复)、§7(外部依赖只登记)。
|
||
- **阶段闸**:`FishingStage` 双闸保留至 C3 首场景 PF 调用计数=0 且合成回归全绿(P3-a)。
|
||
- **不批准**:奖励"完整通关"声明、等级榜聚合/他人资料/好友列表/匹配的功能放行、真实 Player/SignalR/线上操作验收、任何服务器代码读写、打包。
|
||
|
||
## 6. 审查者错误披露(更正记录)
|
||
|
||
本审查者上一轮报告 P3a 声称"`IUserService.CustomId` 已声明 `get; set;`"——**与源码不符**。复核事实:`UserService.cs:70` 为 `string CustomId { get; }`(getter-only),setter 仅在具体类(:131),`PFLoginAct.cs:88,168` 的下转正因接口缺 setter 而存在。主会话裁决的否决正确,本方案 §2.2 的接口 setter 修订必要。此为本审查侧单方事实错误,非开发侧文档问题;记录在案以防复发(对接口成员的读写性必须逐字符核对声明而非凭记忆)。
|
||
|
||
## 7. 批内开发规范确认
|
||
|
||
按纠偏与提示词:获批后一个编码端在 §5 边界内连续实施;常规编译/测试失败自修并记日志,不再送审;仅新线上合同、架构/协议变更、白名单越界、不可逆真实操作须停下做针对差异的补审。C4 做一次全量独立实施复核。本报告即该轮前审的完整结论——**主会话重核本报告与基线 hash 后即可逐项裁决并冻结白名单,无需再征询审查侧意见**。
|