Files
ft/CodexOutput/upserver/阶段3B实施记录-2026-09-22.md

110 lines
12 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.
# 阶段3B实施记录
> **最终状态更新(2026-09-22):** 检查点7仍按历史记录定性为内部子Agent产生的候选修复;用户另开的外部开发AI已在检查点8独立核对、保留该实现、重新取证并按任务书§7正式交付。主会话文档终审现已通过,阶段3B完成。该更新不改写检查点7的流程纠错事实。
日期:2026-09-22。执行者:独立实施AI。最终验收归主会话。
## 检查点1:接口、锁顺序与边界
- 直接任务书:`阶段3B实施任务书-2026-09-22.md`;同时读取完整阶段3方案、3A验收和只读审查清单。
- 生产文件边界仅新增 `PlayerKVSessionOwner.cs`、`PlayerKVSyncCoordinator.cs` 及其meta;不修改3A、阶段2和现有登录代码。
- Owner公开异步创建入口显式接收期望API、账号、epoch、`isCurrent`及生命周期token;固定捕获已认证session的CookieContainer,创建独立且禁止重定向的transport。
- Coordinator提供remote Set、localOnly、Delete、有限水位Flush及票据等待;票据等待取消不传入共享HTTP。
- 锁顺序:Owner短准入门只做closing/登记/归还;Coordinator短票据门只更新票据;dispatch semaphore串行网络和状态转换;3A state自行保护磁盘状态。任何门内均不await,Close在准入门外Cancel并等待实际操作归零。
- 创建Get、Flush Set/Delete共用dispatch semaphore。HTTP等待期间不持3A状态锁;批次必须先由3A `BeginBatch`持久化后发送。
- 已核对3A现有公开接口足以完成本批,不需要改动3A。
状态:检查点1完成,进入Coordinator纯调度实现与替身测试。
## 检查点2进行中:Coordinator首次落盘
- 已新增结果模型、远端/本地编辑票据、单dispatch通道、水位Flush、批次Set/Delete、MayHaveCommitted映射、票据等待取消隔离及关闭票据收尾。
- 已新增SessionOwner首次实现及meta,用于尽早让编译和测试暴露接口问题;检查点2/3仍需以替身测试验证后才算完成。
- 发现既有两个回归项目使用PlayerData通配符,会把3B的S101依赖误纳入阶段2/3A隔离宿主。主会话已补充书面边界,允许只修改两个csproj:阶段2显式编译两文件,3A显式编译阶段2两文件与3A三文件;Program、日志和测试语义不变。3B自有项目同样显式列出七个PlayerData文件和S101AccountSession,不以额外MSBuild注入掩盖失败。
- 首批7个替身用例已通过,涵盖空Get创建、Cookie固定、编辑确认、发送前替换、localOnly、等待取消隔离、HTTP500未知和双owner Cookie隔离。继续补齐批次、水位、故障和Close交错。
## 检查点2:Coordinator纯调度完成
- Set、Delete和恢复Get共用单一dispatch semaphore;批次只从3A已持久化active快照生成,最多10项并保持操作类型顺序。
- Flush在调用时固定sequence水位和本次票据集合;更高版本留待下一次Flush。恢复自磁盘、没有本进程票据的pending仍计入本次汇总。
- 票据固定owner实例、epoch、key和sequence,区分Confirmed、Superseded、Blocked、Unknown、Cancelled;单个等待者取消不改变票据事实或共享HTTP。
- MayHaveCommitted严格冻结为Unknown;HTTP200后确认落盘失败也返回Unknown。没有自动重试或自动解除unknown。
- 检查点2完成。
## 检查点3:SessionOwner与Close完成
- 创建入口显式核对期望API、规范账号、epoch和isCurrent;固定捕获已认证session的CookieContainer,生产handler为UseCookies=true、AllowAutoRedirect=false,owner不Dispose认证session。
- 创建打开3A状态后,在owner实际操作租约内执行完整Get/Reconcile;失败关闭transport和文件租约,Busy/RecoveryRequired/认证及传输错误结构化返回。
- admission门原子完成closing检查和实际操作登记;Close在门外取消owner token、终结被动票据、等待已登记操作退出,再释放transport和3A文件锁。重复Close返回同一任务。
- 增加RefreshAsync,恢复Get仍走同一dispatch通道和固定Cookie;调用方等待取消不转交共享传输。
- 检查点3完成。
## 检查点4:离线验证与回归
命令:
```powershell
dotnet run --project C:\projects\ft\CodexOutput\upserver\KVSyncCoordinatorTests\KVSyncCoordinatorTests.csproj
dotnet run --project C:\projects\ft\CodexOutput\upserver\KVContractTests\KVContractTests.csproj
dotnet run --project C:\projects\ft\CodexOutput\upserver\KVSyncTests\KVSyncTests.csproj
uloop compile --project-path C:/projects/ft/Client --wait-for-domain-reload true
```
结果:
- 3B新增28组替身/磁盘交错测试通过,退出码0。覆盖创建错误及锁释放、Cookie/双账号隔离、Set/Delete和10/51项批次、水位/多版本、票据取消、400/401/403/500/网络/超时、写前及确认磁盘故障、epoch失效、Close幂等/延迟transport/同步取消回调重入/排队Flush、恢复pending统计。
- 阶段2回归42项通过,退出码0;阶段3A回归86项通过,退出码0。两个既有Program和测试语义未改,只按主会话补裁决把csproj通配符改为显式阶段源码列表。
- C盘Unity 2022.3.62f2c1、CLI Loop 2.2.0显式项目编译成功:0错误、274条基线警告;新增PlayerData文件无新增警告。
- 原始概要见`KVSyncCoordinatorTests/Latest.log`、`Regression-summary.log`和`unity-compile-final.json`。
- 检查点4完成。
## 检查点5:交付边界与限制
- 最终源码SHA256见`KVSyncCoordinatorTests/final-source-hashes.json`。
- 所有网络证据均来自实际PlayerKVClient配合合成HttpMessageHandler和合成Cookie;没有访问s101、没有真实Cookie/业务存档值、没有正式服写入。
- 未执行3C限定正式服联调、游戏入口接线、PlayFab替换/SDK删除、真机文件系统与最终打包;未修改共享TODO/状态,未提交或发布。
- transport故意忽略取消时,Close按设计保持等待并占用文件锁;测试仅在显式释放合成transport后完成。
- 本记录只说明实施与自测完成,3B是否验收通过由主会话逐文件审查及复跑后裁决。
状态:任务书五个检查点已执行,停止开发并交还主会话审查。
## 检查点6:接手收尾修复与全量复验(主会话ZCode按用户指令完成)
- 用户指令:原实施AI于检查点5后停止;由主会话(ZCode)接手收尾,仍遵守任务书边界,完成后交发布任务者按审查清单审查。
- 修复初检发现的一处健壮性边界(仅改 `PlayerKVSessionOwner.cs`,未新增文件):`FlushAsync` 的水位捕获(`CaptureWatermark`)原在 `TryEnter` 之后、租约作用域之外执行,若其抛出异常会泄漏操作租约,`CloseAsync` 将永久等待drain并占用文件锁。修复:移入 `RunFlushAsync` 的租约 `using` 作用域,异常按任务书§4转为结构化Protocol结果;同时 `WaitForTicket`同类的 `WaitForFlushAsync` 取消路径不再误报 `ReadFailed`,改返回当前 `state.Status`。`PlayerKVSyncCoordinator.cs` 未改动(hash与原交付一致)。
- 全量复验(2026-09-22 16:4x–17:1x):KVSyncCoordinatorTests 28项通过退出码0;KVContractTests 42项通过退出码0;KVSyncTests 86项通过退出码0。Unity CLI Loop 2.2.0 `--force-recompile true` 全量重编+get-logs核查:错误0条、PlayerData新模块警告0条(证据:`unity-compile-final.json`、`unity-compile-full.json`、`unity-errors-final.json`、`unity-warnings-final.json`)。
- `final-source-hashes.json` 已更新:仅 `PlayerKVSessionOwner.cs` 变更为 `30694BA436FA99C7008AB8477E3835F4E12C8A0586FFD0723CADD35E96927517`,其余7个文件与原交付一致。
- 已知限制不变:全部网络证据来自合成HttpMessageHandler/Cookie;未执行3C正式服联调、游戏入口接线、真机文件系统与最终打包;transport故意忽略取消时Close按设计保持等待。本记录不宣布3B验收通过,最终裁决归发布任务者按《阶段3B审查清单-2026-09-22.md》审查后作出。
## 检查点7:主会话阻塞项返工
- 主会话复现:一个Flush占用dispatch时,RefreshAsync排队;CloseAsync取消owner token后,Coordinator的`dispatch.WaitAsync(ownerToken)`抛出`OperationCanceledException`,原`RunRefreshAsync`会把异常暴露给业务层。
- 最小修复仅修改`PlayerKVSessionOwner.cs`:`RunRefreshAsync`在操作租约作用域内将排队/关闭取消及transport释放映射为`PlayerKVError.Cancelled`,网络异常映射为Network,其余内部异常映射为Protocol;所有路径均由`using`归还租约。
- 新增确定性交错测试`queued-refresh-close-returns-structured-result`:阻塞Flush、排队Refresh、Close、释放transport,验证Close完成且Refresh返回Cancelled而不抛异常。
- 复验:3B 29组通过、阶段2 42项通过、3A 86项通过,退出码均为0;C盘Unity CLI Loop编译0错误(本轮输出271条既有运行时警告,PlayerData无新增警告)。
- 最新SHA256:`PlayerKVSessionOwner.cs`=`F2F0430B4E6E24620CF182A3FE4B83A2AC4024FED6C808B0102E31F26934A2FA`;`Program.cs`=`506A21020C00463C26D93BE7CF479BD93A08B5013B390AE910C93C9F9D53B740`。其余已存证源码未修改。
## 检查点8:外部开发AI独立核对与正式交付(2026-09-22)
执行者:外部开发AI(ZCode,用户另开的独立会话),按《其他AI接手提示词-阶段3B-R1与终验.md》执行。本检查点不修改任何生产代码与测试,仅独立核对、复跑取证并按任务书§7正式交付。
**候选实现独立审查结论:保留现有候选实现,不重做。** 依据:
1. R1触发路径核对:`RefreshAsync`排队于被Flush占用的dispatch时,`CloseAsync`取消owner token,`Coordinator.InitializeAsync`的`dispatch.WaitAsync(ownerToken)`抛出`OperationCanceledException`;候选修复在`RunRefreshAsync`的操作租约`using`作用域内将其映射为结构化`PlayerKVError.Cancelled`(`ObjectDisposedException`→Cancelled、`HttpRequestException`/`IOException`→Network、其余→Protocol),满足任务书§4;所有路径经`using`归还租约,CloseAsync不会永久等待。
2. 未观察异常核对:`RunRefreshAsync`全路径返回结构化结果、不再抛出,等待者提前取消后共享任务无未观察异常;等待者取消仍不取消共享HTTP(`WaitForRefreshAsync`/`WaitForFlushAsync`仅结束该等待)。
3. 测试确定性核对:`queued-refresh-close-returns-structured-result`使用TaskCompletionSource同步(无sleep),真实复现“Flush占用dispatch→Refresh排队→Close取消→释放transport”,断言Refresh返回Cancelled且Close完成。
4. 检查点6的FlushAsync租约作用域修复完好保留;`PlayerKVSyncCoordinator.cs`未改动。
**独立复跑证据(本会话自有取证,不沿用主会话/子Agent结果):**
| 命令 | 结果 | 退出码 |
|---|---|---|
| `dotnet run --project KVSyncCoordinatorTests` | 29/29通过 | 0 |
| `dotnet run --project KVContractTests` | 42/42通过 | 0 |
| `dotnet run --project KVSyncTests` | 86/86通过 | 0 |
| `uloop compile --force-recompile true` + get-logs | 错误0条、PlayerData模块警告0条(控制台累计警告463条为历史运行留存的非PlayerData条目) | 0 |
**交付(任务书§7):** 生产文件2个+meta、测试项目1个、本记录,最终SHA256与`KVSyncCoordinatorTests/final-source-hashes.json`逐项一致(`PlayerKVSessionOwner.cs`=`F2F0430B…`、`PlayerKVSyncCoordinator.cs`=`026210CA…`、`Program.cs`=`506A2102…`,含两个旧csproj)。Unity证据:`unity-compile-final.json`/`unity-compile-full.json`/`unity-errors-final.json`/`unity-warnings-final.json`。全部网络证据来自合成HttpMessageHandler/Cookie,未访问s101、无真实业务key。未执行:3C限定正式服联调与诊断导出、游戏入口接线、PlayFab替换、SDK删除、真机文件系统、最终打包。已知限制:transport故意忽略取消时Close按设计保持等待;`tickets`字典在Owner生命周期内保留全部票据(3C需加数量诊断,游戏接线前评估有界历史)。无偏离任务书项。
3B是否最终验收通过,由主会话按《阶段3B审查清单-2026-09-22.md》对本交付独立终审裁决;本记录不自行宣布验收通过。