Files
ft/CodexOutput/upserver/阶段4B2检查点2字段差异补审方案-2026-09-23.md

6.6 KiB
Raw Blame History

阶段4B2检查点2字段差异补审方案

日期:2026-09-23。状态:待外部差异评审,尚未批准以下两项语义修订。

修订2整包已经外部审查并由主会话逐条裁决、批准受控实施;该事实不撤回。检查点1的Lease/Registry和原4B1回归已完成。检查点2在把字段合同映射到实际codec时发现以下两处冲突。本文件是明确的局部修订提案,不覆盖原受审附件,不把实施中新发现写成已经通过。

本轮未修改M08/M23或其他业务模块,没有用错误合同先做Apply。检查点2尚未完成,检查点3/4不越序启动。

1. D1:旧AD与顶层AchievementData并非相同JSON值类型

证据(路径相对项目根):

  • Client/Assets/Scripts/DataCenter/DataCenter.PlayerData.cs:992起,NewPlayerDataDic.AD调用LoadAchievementDataToObject;顶层AchievementData调用另一个LoadAchievementData。
  • Client/Assets/Scripts/DataCenter/AchievementDataManager.cs:35起:LoadAchievementData读取Dictionary<ConditionType, AchievementData>,而LoadAchievementDataToObject读取Dictionary<ConditionType, string>,把每个字符串按|切分后调用AchievementData.ToObject。
  • AchievementData的三个字段分别为Id:Int32、Target:UInt64、day:Int32。
  • 受审附件§3.1将LDD、AD统一描述为分别同LuckDataDic、AchievementData的旧JSON格式。因此AD会被错误实现成对象值;合法旧字符串值会被拒绝,反而可能接受现有该入口不支持的对象值。单纯增加严格校验不能解决这个格式定义错误。

建议修订: 仅替换附件§3.1的AD格式定义,其余优先级不变:

表示 严格读取合同 规范数据
顶层AchievementData JSON对象;每个键为已定义ConditionType,值为AchievementData对象;Id/Target/day按声明整数类型检查 ConditionType→(Id, Target, day)
NewPlayerDataDic.AD JSON对象;每个键为已定义ConditionType,值必须是字符串,恰好`Id Target
NewPlayerDataDic.ad 已审`ConditionType:Id Target

空对象和空紧凑整体允许为空集合。JSON null、对象值冒充旧AD字符串、缺槽/多槽、空记录、溢出、重复JSON属性、枚举归一化后重复键和未定义枚举拒绝为Malformed。不把坏AD转换为对象格式重试,也不回落其他合法表示掩盖错误。所有现存表示先独立严格解码,再按已审“共有字段冲突则ConflictingRepresentations、一致选新”规则处理:ad > AD > 顶层AchievementData,选中表示整字典替换,不合并旧账号条目。

验收新增:三种表示各有合法/缺失/坏值;AD字符串正例及对象值反例;Target超过UInt64、重复枚举别名、三者共存一致/冲突;AD损坏而ad合法仍失败。只用合成枚举记录,不使用真实账号档。应用M08同对象A→B缺失后为空集合,且零保存/事件。

2. D2:FootPrint的64位合同与32位实际承载矛盾

证据:Client/Assets/Scripts/Services/FootPrintService.cs中LoadData先ulong.Parse,再转EFootPrint;同文件声明public enum EFootPrint : int,私有字段及公开属性也是这个枚举。原附件§3要求UInt64并“保持原值位宽”,但§5只指定替换_footPrint。例如合成值4294967296仅第32位为1,直接转32位枚举会丢失该位;不能把解析器接受UInt64当成真实模块保留了64位。

建议修订: 不更改公开枚举基础类型或IFootPrintService/PF原方法。在同一白名单FootPrintService.cs增加仅受控KV适配使用的ulong完整位集字段及internal只读验证访问:

  1. Decode使用UInt64纯值;不根据当前已声明8个枚举位拒绝未声明高位,不收紧既定64位输入域。
  2. Reset同时清空完整位集和现有_footPrint。
  3. Replace直接保存完整UInt64;同时把低32位按明确的unchecked转换投影到_footPrint,供现有32位枚举视图表示。完整位集才是受控KV加载的完整状态;公开枚举视图不能声称反映全部64位。
  4. 不改变旧LoadData/UpdateFootPrint/UploadData,不新增公开接口,不允许受控加载后进入玩法。guard仍必须阻止受控范围内UploadData触发PF写入口。
  5. 4B3未来读写路由须另审如何消费完整位集;本补审不批准通过旧UploadData保存64位KV状态,也不承诺受控范围退出后该对象可以用于玩法。

这一方案增加M23明确的KV加载字段及Reset断言,属于需要补审的状态合同变化。另两条路线均不建议:把公开enum改为ulong会扩大PF/调用方兼容面;拒绝高32位会缩窄已审UInt64合同并引入新的拒档政策。

验收新增:0、低位组合、2^31、2^32、UInt64.MaxValue完整值保持;低32位视图符合既有枚举位操作;负值、超UInt64拒绝;A高位→B缺失时完整字段与视图同时归零。真实对象在Unity宿主验证,离线算术/DTO测试不替代该项。PF原方法源码不变且既定默认PF行为回归仍执行。

3. 范围、顺序和审批理由

只修正AD codec合同和M23完整位集承载;没有新增业务文件白名单、额外功能、联网或持久化授权。基线和原外部报告保持不变。本补审通过后由主会话逐项裁决,形成附件覆盖层,继续检查点2所有31组,再按原顺序3/4。检查点1成果无需重做,后续最终回归仍覆盖它。

暂停相关代码的依据是用户“方案完整评审后编码”要求,以及主方案§9:“如构建依赖、公开接口、白名单不够,先形成差异方案并补审”,附件§5关于新增状态/消费差异先补审的边界。这里不是重新索取修订2实施授权,而是对新发现的具体格式与状态合同冲突送审。

P2-α真实档兼容性与迁移/用户产品确认的启用门保持。4B1保持关闭;4B2实施中、未交付验收;4B3未启动、G4未通过。固定地址http://s101.local:18080/,只用Unity CLI Loop,不使用UnitySkills,暂不打包。

4. 外部审查应逐项回答

  • D1:源码证据、三种表示及规范化优先级是否正确,边界和测试是否足够。
  • D2:完整64位保存+旧32位视图是否满足本阶段受控合同,是否存在必须修改公开面/旧PF路径的隐藏依赖。
  • 两项修订是否仍在既有文件边界内;给出通过/退回及P1/P2/P3清单,不以“代码实现时决定”代替裁决。
  • 本轮是设计差异补审,不代替未来4B2完整独立实施复核,不把检查点1局部证据解释为31组模块通过。