# 阶段4C2拉杆收鱼与奖励保存方案独立审查 日期:2026-09-24。审查者:ZCode会话。独立性声明:未参与4C2方案编写与实施;此前参与为4C1方案/实施两轮审查。本轮只读+hash重算+源码抽查,未启动Unity/正式网络/许可/消费。 ## 受审hash核对 `KVFishingRewardDesign/plan-review-hashes.json`:items **319/319重算全部一致**;plannedAbsent 5项(两个新增源码及meta、KVFishingRewardTests目录)**全部确认不存在**。 ## 总判定 **接受。** 方案以最小改动推进真实奖励保存,边界、分段、票据与失败合同完整诚实,且已主动吸收4C1三项教训(首跑退出取消语义、工具强杀规避、LongPress适配)。无P1/P2;P3四条不阻塞。 ## 九项逐条回答 **1. 范围:够小且必要。** 7旧文件+2新增是"完整拉杆→结算→奖励→恢复"的最小接线面(每文件对应§2表的一个具体接点);不建通用交易框架(路线2否决正确)、不做无归属全局Flush(路线3否决正确——不能防止重复发奖且无法证明归属)。未见可再缩减而不丢原副作用的替代。 **2. 事件/异步边界:完整。** 本审查直接核实:`PiercingFish(int waitingZone)`入口存在(:524口径)、`OnShow`(:311)中`SetBotCount`(:365)确实早于`Success`(:488)——方案"捕获必须早于SetBotCount"的判断正确;S1(PerfectStrikeCount)/S2(FishEnd至FishingEndEvent)/S3(SetBotCount前至最终保存)三段边界与源码链吻合。分段finally释放collecting、段内无await、ShowUI移出捕获后由可观察Task持有——避免异步资源等待期间混入其他业务 ✓。GuideNext经§3.4"无活动引导"准入+FullCombo引导状态检查+白名单中PiercingToComboB/EternalDeath的await后资格检查覆盖;战斗帧驱动(ControlFishOutWater→IsCaughtFish)有停止推进与过期不设IsCaughtFish条款 ✓。 **3. 鱼记录三态:源码判断准确。** 本审查直接证实`SetGetFishCount`=`fishData[fishId].TotalNum += count`**纯内存无保存**(:998–1003)——"未破纪录收鱼漏存数量"缺口属实;`SetWeight`(:935)仅破纪录保存与方案一致。`SaveCaughtFishForKVLoop`→原`SetFishData`恰补一次保存不加数量、保持原`Map_5_{AreaID}`序列化与卡数据 ✓;首次鱼NewFish默认(CheckFishData先建档)由C2-02覆盖 ✓。 **4. 公式与顺序:保持。** S3顺序表把SaveFishingFrequency/任务/Buff/Guide/SetProficiency/现金事件/AddGold/SetFishWeight/引导通知→最终鱼种→最终主档逐一定序,**主档在全部成就事件后**;SetProficiency正确界定为挑战积分而非通用经验;0现金仍保存次数/鱼种在§6明示;异步展示(Tween/音频/评级)移到确认后只展示已计算结果 ✓。 **5. v3与旧许可边界:清楚。** v1/v2语义原样、v2可显示可拉杆但无新放行;v3恰一消费+一结算;**C1 Continued≠C2奖励完成**明确;取消按RewardConfirmed区分(等待中Fault、完成后仅撤销继续资格——直接吸收4C1首跑教训);重复Panel/FishEnd须原进程动作绑定非各自bool ✓。 **6. 票据诚实:完备且比4C1更严。** 奖励动作自有封存记录、不混入已完成消费票据;每key最终原票据Confirmed+同动作同key跨段(S1↔S3)合法替代;**段外实际变值写经outside-segment采样拒绝验收**(即使后被S3覆盖也不掩盖)——比4C1更严;最后localOnly拒绝、Unknown/401/部分提交不退款不补发不冒充;"已扣费或部分写成功但未呈现奖励"的失败如实允许记录、不称原子 ✓。 **7. §3准入:具体、可执行、保守。** 19条GetFishCount分级(3条活跃Type1须频次≥3+解锁就绪;30200350–65须真实服务时间过EndTime≥120秒且校验条件/时段/分支字段而非仅ID)✓;引导/巡游(GetFishSwimToMap==0)/挑战(State 0/3或时间不允许)/收集/礼包/对战Item全部只读预检、无法可靠读取即拒绝 ✓;活动Open/Close观察不记通过 ✓;"这些是可执行边界不是已通过声明"的定位诚实。 **8. 数据矩阵与真实验收:足以证明奖励保存。** §6矩阵到字段级(19槽仅消费/奖励项、goldRM不增、Map键仅目标鱼、任务键仅实际变更者、预期不变键清单);本期必须**新消费一次**且上次鱼不可恢复(诚实);C3c明确规避已知会超时强杀的`uloop launch --quit`并要求已核实的无强杀关闭路径、无法满足则保持验收未完成 ✓;C3d新进程新缓存恢复对账、自然时间变化按旧公式解释 ✓。 **9. 可批准按§9检查点实施:可以。** C0–C4顺序合同完整(红测先行、准入全过才发v3许可、失败不自动二次付费)。 ## P3清单(不阻塞) - **P3-1**:C2-12"目标鱼数量最大重量"读回断言建议同时校验`Map_5_{AreaID}`中**其他鱼与卡数据字节不变**(§6已列"其他鱼保持",落为显式逐键断言更利于对账工具自动化)。 - **P3-2**:S3段内"原OnShow引导通知"在无引导准入下预期无操作——若运行中意外触发引导开启即终止已覆盖;建议事件流记录该通知调用次数(预期0相关)作辅助证据。 - **P3-3**:`SaveCaughtFishForKVLoop`要求"数据已存在"——建议实现时断言`fishData.ContainsKey`且TotalNum已含本次增量(与S3前值快照比对),防止空档误保存。 - **P3-4**:C3b的LongPress 0.15秒适配沿用4C1已验证参数——建议把该参数与UIButton阈值校验写入固定操作脚本(4C1 P3-1的延续)。 ## 保留项 本期通过≠完整捕鱼系统/4C整体/热换号/G4/普通用户开放;自然失败不计成功;P2-α、身份、tickets、4D、最终打包不变。方案自述"未编码、未运行测试、未启用许可、未发生新消费"与本审查观察一致。 ## 结论 **接受4C2方案,批准按§9检查点实施(主会话逐条裁决后)。** 建议P3四条随裁决采纳为实施说明。