From 1b85b532926c0adaec6b26429d79490713a2d49b Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 25 Apr 2026 15:25:57 +0800 Subject: [PATCH] =?UTF-8?q?refactor(game):=20=E6=94=B6=E6=95=9B=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8C=96=E8=BF=81=E7=A7=BB=E8=BF=90=E8=A1=8C=E5=99=A8?= =?UTF-8?q?=E9=95=BF=E6=96=B9=E6=B3=95=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构 VersionedMigrationRunner 的迁移主循环,拆分版本校验、迁移解析与结果校验 helper - 更新 analyzer warning reduction 的 active tracking 与 trace,记录新的 649 条根构建基线 --- .../Internal/VersionedMigrationRunner.cs | 181 ++++++++++++++---- .../analyzer-warning-reduction-tracking.md | 37 ++-- .../analyzer-warning-reduction-trace.md | 23 +++ 3 files changed, 179 insertions(+), 62 deletions(-) diff --git a/GFramework.Game/Internal/VersionedMigrationRunner.cs b/GFramework.Game/Internal/VersionedMigrationRunner.cs index 9c628cc2..349d9031 100644 --- a/GFramework.Game/Internal/VersionedMigrationRunner.cs +++ b/GFramework.Game/Internal/VersionedMigrationRunner.cs @@ -92,11 +92,7 @@ internal static class VersionedMigrationRunner ArgumentException.ThrowIfNullOrWhiteSpace(migrationKind); var currentVersion = getVersion(data); - if (currentVersion > targetVersion) - { - throw new InvalidOperationException( - $"{subjectName} is version {currentVersion}, which is newer than the current runtime version {targetVersion}."); - } + EnsureRuntimeVersionIsSupported(currentVersion, targetVersion, subjectName); if (currentVersion == targetVersion) { @@ -107,43 +103,148 @@ internal static class VersionedMigrationRunner while (currentVersion < targetVersion) { - var migration = resolveMigration(currentVersion); - if (migration is null) - { - throw new InvalidOperationException( - $"No {migrationKind} is registered for {subjectName} from version {currentVersion}."); - } - - current = applyMigration(migration, current) - ?? throw new InvalidOperationException( - $"{migrationKind} for {subjectName} from version {currentVersion} returned null."); - - var migratedVersion = getVersion(current); - var declaredTargetVersion = getToVersion(migration); - - if (declaredTargetVersion != migratedVersion) - { - throw new InvalidOperationException( - $"{migrationKind} for {subjectName} declared target version {declaredTargetVersion} " + - $"but returned version {migratedVersion}."); - } - - if (migratedVersion <= currentVersion) - { - throw new InvalidOperationException( - $"{migrationKind} for {subjectName} must advance beyond version {currentVersion}."); - } - - if (migratedVersion > targetVersion) - { - throw new InvalidOperationException( - $"{migrationKind} for {subjectName} produced version {migratedVersion}, " + - $"which exceeds the current runtime version {targetVersion}."); - } - - currentVersion = migratedVersion; + var migration = GetRequiredMigration(resolveMigration, currentVersion, subjectName, migrationKind); + var result = ApplyMigrationStep( + migration, + current, + currentVersion, + targetVersion, + getVersion, + getToVersion, + applyMigration, + subjectName, + migrationKind); + current = result.Data; + currentVersion = result.Version; } return current; } + + /// + /// 拒绝比当前运行时更高的数据版本,避免迁移器在未知版本上继续执行。 + /// + /// 数据当前版本。 + /// 运行时支持的目标版本。 + /// 迁移主体名称。 + /// 数据版本高于运行时版本时抛出。 + private static void EnsureRuntimeVersionIsSupported(int currentVersion, int targetVersion, string subjectName) + { + if (currentVersion > targetVersion) + { + throw new InvalidOperationException( + $"{subjectName} is version {currentVersion}, which is newer than the current runtime version {targetVersion}."); + } + } + + /// + /// 解析当前版本必须存在的下一步迁移器,避免在调用循环中重复拼接相同错误。 + /// + /// 迁移描述类型。 + /// 迁移解析委托。 + /// 当前版本。 + /// 迁移主体名称。 + /// 迁移类别名称。 + /// 已解析的迁移器。 + /// 缺少迁移器时抛出。 + private static TMigration GetRequiredMigration( + Func resolveMigration, + int currentVersion, + string subjectName, + string migrationKind) + { + var migration = resolveMigration(currentVersion); + if (migration is null) + { + throw new InvalidOperationException( + $"No {migrationKind} is registered for {subjectName} from version {currentVersion}."); + } + + return migration; + } + + /// + /// 执行单步迁移并验证声明目标版本、结果版本与运行时上限之间的一致性。 + /// + /// 迁移数据类型。 + /// 迁移描述类型。 + /// 当前步骤的迁移器。 + /// 迁移前数据。 + /// 迁移前版本。 + /// 运行时目标版本。 + /// 数据版本读取委托。 + /// 迁移器目标版本读取委托。 + /// 迁移执行委托。 + /// 迁移主体名称。 + /// 迁移类别名称。 + /// 迁移后的数据与新版本号。 + /// + /// 迁移结果为空、声明目标版本不匹配、版本未前进或超出运行时版本时抛出。 + /// + private static (TData Data, int Version) ApplyMigrationStep( + TMigration migration, + TData current, + int currentVersion, + int targetVersion, + Func getVersion, + Func getToVersion, + Func applyMigration, + string subjectName, + string migrationKind) + where TData : class + { + var migratedData = applyMigration(migration, current) + ?? throw new InvalidOperationException( + $"{migrationKind} for {subjectName} from version {currentVersion} returned null."); + var migratedVersion = getVersion(migratedData); + ValidateMigrationResult( + currentVersion, + targetVersion, + migratedVersion, + getToVersion(migration), + subjectName, + migrationKind); + return (migratedData, migratedVersion); + } + + /// + /// 校验单步迁移结果与声明目标版本一致,并确保版本严格单调递增且不越过运行时版本。 + /// + /// 迁移前版本。 + /// 运行时目标版本。 + /// 迁移后实际版本。 + /// 迁移器声明的目标版本。 + /// 迁移主体名称。 + /// 迁移类别名称。 + /// + /// 声明目标版本不匹配、版本未前进或超出运行时版本时抛出。 + /// + private static void ValidateMigrationResult( + int currentVersion, + int targetVersion, + int migratedVersion, + int declaredTargetVersion, + string subjectName, + string migrationKind) + { + if (declaredTargetVersion != migratedVersion) + { + throw new InvalidOperationException( + $"{migrationKind} for {subjectName} declared target version {declaredTargetVersion} " + + $"but returned version {migratedVersion}."); + } + + if (migratedVersion <= currentVersion) + { + throw new InvalidOperationException( + $"{migrationKind} for {subjectName} must advance beyond version {currentVersion}."); + } + + if (migratedVersion > targetVersion) + { + throw new InvalidOperationException( + $"{migrationKind} for {subjectName} produced version {migratedVersion}, " + + $"which exceeds the current runtime version {targetVersion}."); + } + } } diff --git a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md index 9787b506..c3bee7f0 100644 --- a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md +++ b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md @@ -6,38 +6,35 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-066` -- 当前阶段:`Phase 66` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-067` +- 当前阶段:`Phase 67` - 当前焦点: - - `2026-04-25` 已先提交 `6a704f3` `fix(analyzer): 固化沙箱外验证并清理测试噪音`,把 AGENTS / active ai-plan 真值修正与 4 文件测试噪音批次一起收口 - - 当前单文件批次聚焦 `GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs`,已收敛 4 个根构建直接确认的 `MA0051` - - 提权后的直接仓库根基线已从 `656 Warning(s)` 降至 `652 Warning(s)`,说明本轮单文件批次有效 - - `GFramework.Game.Tests` 的直接受影响 Release build 当前为 `0 Warning(s)`、`0 Error(s)` - - 本批次落地后,branch diff 相对 `origin/main` 将从 `7 files` 推进到 `8 files`,仍显著低于 `$gframework-batch-boot 50` 阈值 + - `2026-04-25` 已连续提交 `6a704f3` `fix(analyzer): 固化沙箱外验证并清理测试噪音` 与 `be26640` `test(game-tests): 收敛热重载长方法 warning` + - 当前单文件批次聚焦 `GFramework.Game/Internal/VersionedMigrationRunner.cs`,通过拆分迁移主循环中的职责收敛根构建直接确认的 `MA0051` + - 提权后的直接仓库根基线已从 `652 Warning(s)` 降至 `649 Warning(s)`,说明本轮 runtime 单文件批次继续有效 + - `GFramework.Game` 的直接受影响 `Release` build 当前为 `0 Warning(s)`、`0 Error(s)` + - 本轮只新增 1 个源码唯一文件,branch diff 仍显著低于 `$gframework-batch-boot 50` 阈值 ## 当前活跃事实 - 当前 `origin/main` 基线提交为 `4ad880c`(`2026-04-25T14:35:38+08:00`)。 -- `6a704f3` 落地后,当前 committed branch diff 相对 `origin/main` 为: - - `git diff --name-only origin/main...HEAD | wc -l`:`7` - - `git diff --numstat origin/main...HEAD`:累计 `104` added、`123` deleted - 提权后的直接仓库根验证当前确认为: - `dotnet clean` - 结果:成功;此前沙箱内 “Build FAILED but 0 errors” 的 clean 结果不是仓库真值 - `dotnet build` - - 最新结果:成功;`652 Warning(s)`、`0 Error(s)` + - 最新结果:成功;`649 Warning(s)`、`0 Error(s)` - 已提交的低风险批次文件: - `AGENTS.md` - `GFramework.Ecs.Arch.Tests/Ecs/EcsAdvancedTests.cs` - `GFramework.Game.Tests/Config/GameConfigBootstrapTests.cs` - `GFramework.Game.Tests/Config/GeneratedConfigConsumerIntegrationTests.cs` + - `GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs` - `GFramework.Game.Tests/Config/YamlConfigTextValidatorTests.cs` + - `GFramework.Game/Internal/VersionedMigrationRunner.cs` - `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md` - `ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md` -- 当前待提交批次文件: - - `GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs` - 当前批次验证结果: - - `dotnet build GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release` + - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` - 最新主线程结果:成功;`0 Warning(s)`、`0 Error(s)` ## 当前风险 @@ -66,16 +63,12 @@ - `dotnet clean` - 当前结果:成功;在提权后的直接 shell 中可正常完成仓库根 clean - `dotnet build` - - 当前结果:成功;`652 Warning(s)`、`0 Error(s)` -- `dotnet build GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release` + - 当前结果:成功;`649 Warning(s)`、`0 Error(s)` +- `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` - 当前结果:成功;`0 Warning(s)`、`0 Error(s)` -- `git diff --name-only origin/main...HEAD | wc -l` - - 当前结果:`7` -- `git diff --numstat origin/main...HEAD` - - 当前结果:累计 `104` added、`123` deleted ## 下一步建议 -1. 提交当前 `YamlConfigLoaderTests.cs` 单文件批次后,继续按 `$gframework-batch-boot 50` 规则重算 branch diff,并挑选下一个 1-3 文件的低风险热点。 -2. 下一轮优先从 `GFramework.Cqrs.Tests` 或 `GFramework.Game` 中继续选择单文件 `MA0051` / 测试噪音切片,避免过早推高 review 范围。 +1. 以当前 `649 Warning(s)` 根基线为新恢复点,继续按 `$gframework-batch-boot 50` 规则重算 branch diff,并挑选下一个 1-3 文件的低风险热点。 +2. 下一轮优先从 `GFramework.Cqrs.Tests` 或 `GFramework.Game` 中继续选择单文件 `MA0051`、`MA0016` 或测试噪音切片,避免过早推高 review 范围。 3. 后续凡是沙箱内 `.NET` 验证再次出现无诊断失败、pipe/socket 权限问题或与普通 shell 不一致的结果,直接申请沙箱外重跑同一命令,不再扩散 workaround 型命令噪音。 diff --git a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md index 2e3dd9c8..58cc8941 100644 --- a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md +++ b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md @@ -1,5 +1,28 @@ # Analyzer Warning Reduction 追踪 +## 2026-04-25 — RP-067 + +### 阶段:收口 Game runtime 单文件长方法切片,并继续压低根构建 warning 基线 + +- 触发背景: + - `RP-066` 收尾后,当前分支已通过 `be26640` 把 `YamlConfigLoaderTests.cs` 的 4 个 `MA0051` 落地,仓库根基线降到 `652 Warning(s)` + - 主线程随后切到 `GFramework.Game/Internal/VersionedMigrationRunner.cs`,继续挑选单文件、低风险、可独立验证的 runtime warning 切片 +- 主线程实施: + - 将 `MigrateToTargetVersion` 中的运行时版本校验、迁移解析、单步应用与结果一致性校验拆分为具名 helper + - 为新增 helper 补齐 XML 注释,保持该共享迁移执行器的职责边界可读,并避免仅靠机械拆分留下语义不清的私有方法 + - 保持外部行为不变,只收敛长方法 warning,不扩展到存储或日志相关调用方 +- 验证里程碑: + - `dotnet clean` + - 结果:成功 + - `dotnet build` + - 结果:成功;`649 Warning(s)`、`0 Error(s)`,相较 `RP-066` 的 `652` 再下降 `3` + - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` + - 结果:成功;`0 Warning(s)`、`0 Error(s)` +- 当前结论: + - `VersionedMigrationRunner.cs` 这个 runtime 单文件批次已被主线程收口,并继续压低仓库根 warning 基线 + - 本轮只新增 1 个源码唯一文件,branch diff 仍显著低于 `$gframework-batch-boot 50` 的主停止阈值 + - 下一轮可以继续挑选 `GFramework.Cqrs.Tests` 或 `GFramework.Game` 的单文件轻量切片,并保持主线程验证、subagent 并行探索的节奏 + ## 2026-04-25 — RP-066 ### 阶段:主线程回收停滞的单文件批次,并继续压低根构建 warning 基线