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

60 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 阶段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|day`三槽;分别按Int32/UInt64/Int32、InvariantCulture解析 | 同上 |
| NewPlayerDataDic.ad | 已审`ConditionType:Id|Target|day`,以`;`连接 | 同上 |
空对象和空紧凑整体允许为空集合。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组模块通过。