From 6a704f3aa7f6c1403959e57da589c9de276179e6 Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 25 Apr 2026 14:58:06 +0800 Subject: [PATCH 01/12] =?UTF-8?q?fix(analyzer):=20=E5=9B=BA=E5=8C=96?= =?UTF-8?q?=E6=B2=99=E7=AE=B1=E5=A4=96=E9=AA=8C=E8=AF=81=E5=B9=B6=E6=B8=85?= =?UTF-8?q?=E7=90=86=E6=B5=8B=E8=AF=95=E5=99=AA=E9=9F=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新 AGENTS.md,要求沙箱内 .NET 验证异常时必须申请沙箱外重跑同一命令并以其结果为准 - 修复 4 个测试文件中的冗余 DoesNotThrow 包装,收敛低风险 warning 噪音 - 刷新 analyzer-warning-reduction active todo 与 trace,清理把沙箱噪音当成环境阻塞的恢复信息 --- AGENTS.md | 9 ++ .../Ecs/EcsAdvancedTests.cs | 11 +- .../Config/GameConfigBootstrapTests.cs | 2 +- ...GeneratedConfigConsumerIntegrationTests.cs | 9 +- .../Config/YamlConfigTextValidatorTests.cs | 22 ++- .../analyzer-warning-reduction-tracking.md | 143 ++++++------------ .../analyzer-warning-reduction-trace.md | 31 ++++ 7 files changed, 104 insertions(+), 123 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 570d1da8..92fad88c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -33,6 +33,13 @@ All AI agents and contributors must follow these rules when writing, reviewing, baseline from a non-incremental repository-root build by running `dotnet clean` and then `dotnet build`. - Contributors MUST NOT treat a repeated incremental `dotnet build` result as authoritative for warning inspection when a clean baseline has not been captured in the same round. +- If a direct `dotnet clean`、`dotnet build`、or `dotnet test` command fails inside the agent sandbox with missing + diagnostics, `Permission denied`, MSBuild pipe/socket errors, or other environment-only noise that does not match a + normal shell invocation, contributors MUST request permission and rerun the same direct command outside the sandbox + before concluding that the repository or toolchain is broken. +- For repository truth, contributors MUST prefer the result of the original direct command executed outside the sandbox + over sandbox-only failures, workaround-heavy variants, or speculative environment flags unless the user explicitly + asks for a non-default command shape. - If the task changes multiple projects or shared abstractions, prefer a solution-level or affected-project `dotnet build ... -c Release`; otherwise use the smallest build command that still proves the result compiles. - When a task adds a feature or modifies code, contributors MUST run a Release build for every directly affected @@ -235,6 +242,8 @@ All generated or modified code MUST include clear and meaningful comments where ### Validation Commands Use the smallest command set that proves the change, then expand if the change is cross-cutting. +If a sandboxed agent run reports environment-specific .NET failures, rerun the same direct command outside the sandbox +and treat that unsandboxed result as authoritative for validation and warning baselines. ```bash # Check warnings from the default repository build entrypoint diff --git a/GFramework.Ecs.Arch.Tests/Ecs/EcsAdvancedTests.cs b/GFramework.Ecs.Arch.Tests/Ecs/EcsAdvancedTests.cs index 7bf6e347..9873a262 100644 --- a/GFramework.Ecs.Arch.Tests/Ecs/EcsAdvancedTests.cs +++ b/GFramework.Ecs.Arch.Tests/Ecs/EcsAdvancedTests.cs @@ -60,11 +60,8 @@ public class EcsAdvancedTests InitializeEcsModule(); _world!.Create(new Position(0, 0)); - Assert.DoesNotThrow(() => - { - World.Destroy(_world); - _world = null; - }); + World.Destroy(_world); + _world = null; } [Test] @@ -124,7 +121,7 @@ public class EcsAdvancedTests _world = _container!.Get(); - Assert.DoesNotThrow(() => _ecsModule.Update(1.0f)); + _ecsModule.Update(1.0f); } [Test] @@ -211,4 +208,4 @@ public class EcsAdvancedTests Assert.That(_world.Has(entity3), Is.False); Assert.That(_world.Has(entity3), Is.True); } -} \ No newline at end of file +} diff --git a/GFramework.Game.Tests/Config/GameConfigBootstrapTests.cs b/GFramework.Game.Tests/Config/GameConfigBootstrapTests.cs index 1670c9b2..10285b6a 100644 --- a/GFramework.Game.Tests/Config/GameConfigBootstrapTests.cs +++ b/GFramework.Game.Tests/Config/GameConfigBootstrapTests.cs @@ -167,7 +167,7 @@ public class GameConfigBootstrapTests continueInitialization.Set(); - Assert.DoesNotThrowAsync(() => firstInitializeTask); + Assert.That(async () => await firstInitializeTask.ConfigureAwait(false), Throws.Nothing); Assert.Multiple(() => { diff --git a/GFramework.Game.Tests/Config/GeneratedConfigConsumerIntegrationTests.cs b/GFramework.Game.Tests/Config/GeneratedConfigConsumerIntegrationTests.cs index ca20065c..b92acaac 100644 --- a/GFramework.Game.Tests/Config/GeneratedConfigConsumerIntegrationTests.cs +++ b/GFramework.Game.Tests/Config/GeneratedConfigConsumerIntegrationTests.cs @@ -198,11 +198,10 @@ public class GeneratedConfigConsumerIntegrationTests Assert.That(yaml.EndsWith("\n", StringComparison.Ordinal), Is.True); }); - Assert.DoesNotThrow(() => - MonsterConfigBindings.ValidateYaml(_rootPath, "monster/generated.yaml", yaml)); - - Assert.DoesNotThrowAsync(async () => - await MonsterConfigBindings.ValidateYamlAsync(_rootPath, "monster/generated.yaml", yaml).ConfigureAwait(false)); + MonsterConfigBindings.ValidateYaml(_rootPath, "monster/generated.yaml", yaml); + Assert.That( + async () => await MonsterConfigBindings.ValidateYamlAsync(_rootPath, "monster/generated.yaml", yaml).ConfigureAwait(false), + Throws.Nothing); var invalidYaml = """ id: 3 diff --git a/GFramework.Game.Tests/Config/YamlConfigTextValidatorTests.cs b/GFramework.Game.Tests/Config/YamlConfigTextValidatorTests.cs index 5e9350c6..85f5d8ce 100644 --- a/GFramework.Game.Tests/Config/YamlConfigTextValidatorTests.cs +++ b/GFramework.Game.Tests/Config/YamlConfigTextValidatorTests.cs @@ -54,16 +54,15 @@ public sealed class YamlConfigTextValidatorTests } """); - Assert.DoesNotThrow(() => - YamlConfigTextValidator.Validate( - "monster", - schemaPath, - "monster/generated.yaml", - """ - id: 1 - name: Slime - hp: 10 - """)); + YamlConfigTextValidator.Validate( + "monster", + schemaPath, + "monster/generated.yaml", + """ + id: 1 + name: Slime + hp: 10 + """); } /// @@ -169,8 +168,7 @@ public sealed class YamlConfigTextValidatorTests hp: 10 """; - Assert.DoesNotThrow(() => - YamlConfigTextValidator.Validate("monster", schemaPath, "monster/generated.yaml", yaml)); + YamlConfigTextValidator.Validate("monster", schemaPath, "monster/generated.yaml", yaml); File.WriteAllText( schemaPath, 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 7ea2c6e7..5cdb06be 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,85 +6,46 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-064` -- 当前阶段:`Phase 64` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-065` +- 当前阶段:`Phase 65` - 当前焦点: - - `2026-04-25` 当前 turn 先执行 `$gframework-pr-review`,复核 PR #288 的 latest-head unresolved 线程与折叠评论 - - 已收敛一批经本地复核后仍成立的 review 建议,包括 `ThrowIfNull` 回退、测试桩 XML 注释修正、`FileStorage` 资源所有权、`SceneRouterBase` 线程亲和语义与若干测试噪音 - - 已确认用户在 WSL 下直接执行的标准 `dotnet build -c Release` 路径可用;前一轮失败主要来自主线程附加的 workaround 参数而非仓库本身不可构建 - - 基线 `origin/main` 仍为 `9964962`(`2026-04-24T23:05:53+08:00`) - - 当前累计 branch diff 相对 `origin/main` 为 `75` 个文件、`2098` 行,已触达本轮 `75 files` 阈值 - - `RP-061` 之后已接受 2 个批次提交:`03c73a8`、`9ce1fa6` - - 当前默认恢复入口不再继续扩写集;若要继续 analyzer reduction,优先重新抓取 PR #288 的 unresolved 线程并按最新 head 再做一轮收口 + - `2026-04-25` 已确认此前一批 `dotnet clean` / `dotnet build` / `dotnet test` 异常主要来自 agent 沙箱环境,而不是仓库或 WSL 默认 shell 本身 + - 已用提权后的直接命令重新建立仓库根基线:`dotnet clean` 成功,`dotnet build` 结果为 `656 Warning(s)`、`0 Error(s)` + - 当前 `HEAD` 与 `origin/main` 对齐;基于 `$gframework-batch-boot 50` 的 committed branch diff 现为 `0 files / 0 lines` +- 当前活跃写集是 4 个测试噪音清理文件,属于新的低风险 warning-reduction 批次;提交前需由主线程在沙箱外重新验证 + - 主线程已完成该批次的沙箱外复核,当前可安全并入本轮提交 + - 已决定把“沙箱内 .NET 验证失败时必须申请沙箱外重跑并以该结果为准”写入 `AGENTS.md`,避免后续继续扩散伪环境阻塞 ## 当前活跃事实 -- 当前 `origin/main` 基线提交为 `9964962`(`2026-04-24T23:05:53+08:00`)。 -- 本轮 `Core.Tests` 低风险机械型清理已落地到: - - `ArchitectureAdditionalCqrsHandlersTests.cs` - - `RegistryInitializationHookBaseTests.cs` - - `CommandCoroutineExtensionsTests.cs` - - `TaskCoroutineExtensionsTests.cs` - - `WaitForTaskTTests.cs` - - `AsyncExtensionsTests.cs` - - `LogContextTests.cs` - - `PauseStackManagerTests.cs` -- 本 turn 结合 PR #288 latest-head review 额外收敛了以下仍然成立的问题: - - `AsyncExtensionsTests.cs`:修复 `WithTimeoutAsync` 无返回值测试中错误返回 `ConfiguredTaskAwaitable` 导致的 `CS0029` / `CS1662` - - `ContextAwareCommandExtensions.cs` - - `ContextAwareQueryExtensions.cs` - - `ContextAwareEventExtensions.cs` - - `AsyncExtensions.cs` - - `AsyncKeyLockManagerTests.cs`:去掉两处不会产生额外价值的 `Assert.DoesNotThrowAsync(() => Task.WhenAll(...))` 包装,并把取消断言改为直接消费 `ValueTask.AsTask()` - - `AsyncArchitectureTests.cs` - - `ArchitectureLifecycleBehaviorTests.cs` - - `StateMachineSystemTests.cs` - - `RegistryInitializationHookBaseTests.cs` - - `NumericExtensions.cs` - - `StringExtensions.cs` - - `StoreBuilder.cs` - - `StoreSelection.cs` - - `ArchitectureServicesTests.cs` - - `GameContextTests.cs` - - `RollingFileAppenderTests.cs` - - `TaskCoroutineExtensionsTests.cs` - - `WaitForTaskTests.cs` - - `ScopedStorage.cs` - - `FileStorage.cs` - - `SceneRouterBase.cs` -- 当前 PR review 观察: - - PR:`#288` - - latest reviewed commit:`70c42b579f70c90ab5461a02e611c0fbd8d8a6f2` - - 抓取时 `coderabbitai[bot]` 有 `6` 个 open threads,`greptile-apps[bot]` 有 `2` 个 open threads - - `Actionable comments posted: 7` 与 `outside diff + nitpick = 19` 并不等于必须全收;本 turn 仅接受经本地复核后仍成立且不与仓库约束冲突的建议 -- 本轮 `Core` runtime 低风险机械型清理已落地到: - - `AsyncExtensions.cs` - - `CollectionExtensions.cs` - - `ContextAwareCommandExtensions.cs` - - `ContextAwareEnvironmentExtensions.cs` - - `ContextAwareEventExtensions.cs` - - `ContextAwareQueryExtensions.cs` - - `ContextAwareServiceExtensions.cs` - - `GuardExtensions.cs` - - `NumericExtensions.cs` - - `StoreEventBusExtensions.cs` - - `StringExtensions.cs` - - `StoreBuilder.cs` - - `StoreSelection.cs` -- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net8.0 -p:RestoreFallbackFolders="" -v minimal` 当前结果为 `0 Warning(s)`、`0 Error(s)`,可作为本轮 runtime 变更的最终最小 Release build 验证。 -- `GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-incremental` 在 `03c73a8` 提交前的最近一次可信主线程结果为 `198 Warning(s)`、`0 Error(s)`;该观测值覆盖了 `ArchitectureContextTests`、`ArchitectureServicesTests`、`GameContextTests`、`ResultTests`、`AsyncTestModel`、`AsyncTestSystem` 与 `ContextAwareEnvironmentExtensionsTests` 的 7 文件批次。 -- 当前累计 branch diff 相对 `origin/main` 为 `75` 个文件、`2098` 行;本轮主停止条件已经达到。 +- 当前 `origin/main` 基线提交为 `4ad880c`(`2026-04-25T14:35:38+08:00`)。 +- `fix/analyzer-warning-reduction-batch` 当前 `HEAD` 等于 `origin/main`;因此 shorthand 阈值 `$gframework-batch-boot 50` 的当前 committed 规模为: + - `git diff --name-only origin/main...HEAD | wc -l`:`0` + - `git diff --numstat origin/main...HEAD`:`0 added / 0 deleted` +- 提权后的直接仓库根验证已经确认: + - `dotnet clean` + - 结果:成功;此前沙箱内 “Build FAILED but 0 errors” 的 clean 结果不是仓库真值 + - `dotnet build` + - 结果:成功;`656 Warning(s)`、`0 Error(s)`,当前 warning reduction 应以此为总基线 +- 当前待集成的低风险批次文件: + - `GFramework.Game.Tests/Config/GameConfigBootstrapTests.cs` + - `GFramework.Game.Tests/Config/GeneratedConfigConsumerIntegrationTests.cs` + - `GFramework.Game.Tests/Config/YamlConfigTextValidatorTests.cs` + - `GFramework.Ecs.Arch.Tests/Ecs/EcsAdvancedTests.cs` +- 上述批次的 worker 侧验证结果: + - `dotnet build GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release` + - 最新主线程结果:成功;`0 Warning(s)`、`0 Error(s)` + - `dotnet build GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj -c Release` + - 最新主线程结果:成功;`0 Warning(s)`、`0 Error(s)` ## 当前风险 -- `dotnet clean GFramework.sln -c Release` 与 `dotnet clean GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release` 仍无法稳定提供新的 clean 基线。 - - 缓解措施:后续若继续整仓 warning reduction,需要单独定位 clean 失败原因,或明确继续沿用 direct build 观测值作为临时真值。 +- active `ai-plan` 之外的历史归档仍保留一部分沙箱内 workaround / 假阻塞记录。 + - 缓解措施:active todo/trace 已刷新为新真值;历史归档保留为时间线,不再作为默认恢复入口。 - 当前 worktree 仍存在未跟踪的 `.codex` 目录。 - - 缓解措施:提交当前批次时只暂存 analyzer-warning-reduction 相关源码与 `ai-plan` 文件,避免把工作目录辅助文件混入提交。 -- 将分支继续推过 `75 files` 会明显降低本轮 reviewability。 - - 缓解措施:当前恢复点默认停止;如需继续,建议在新 turn 明确新的文件阈值或先 rebase / refresh baseline。 -- `GFramework.Core`、`GFramework.Game`、`GFramework.Core.Tests` 当前都仍存在模块级历史 warning 基线。 - - 缓解措施:本 turn 已确保本次 touched files 不再引入新的编译错误,并消化了当前 PR review 中仍成立的高信号问题;若要继续 warning reduction,应开新批次按模块系统化收敛。 + - 缓解措施:提交时只暂存 analyzer-warning-reduction 相关源码与 `ai-plan` / `AGENTS.md` 变更。 +- `GFramework.Core`、`GFramework.Game`、`GFramework.Core.Tests`、`GFramework.Cqrs.Tests` 仍有较大 warning 基线。 + - 缓解措施:后续批次继续优先挑低风险、少文件、可独立验证的测试与局部逻辑切片。 ## 活跃文档 @@ -100,35 +61,21 @@ ## 验证说明 -- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net8.0 -p:RestoreFallbackFolders="" -v minimal` - - 历史结果:成功;`0 Warning(s)`、`0 Error(s)` -- `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-incremental --no-restore -p:RestoreFallbackFolders= -v:diag` - - 历史结果:失败;`MSB4276`,默认 SDK resolver 无法解析 `Microsoft.NET.SDK.WorkloadAutoImportPropsLocator`,属于当前 WSL / dotnet 10 环境阻塞 -- `DOTNET_CLI_HOME=/tmp/dotnet-home MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net8.0 -p:RestoreFallbackFolders="" -v minimal` - - 结果:失败;`MSB4018`,`ResolvePackageAssets` 命中失效 Windows fallback package folder `D:\Tool\Development Tools\Microsoft Visual Studio\Shared\NuGetPackages` -- `DOTNET_CLI_HOME=/tmp/dotnet-home MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net9.0 -p:RestoreFallbackFolders="" -v minimal` - - 结果:失败;`MSB4018`,原因同上 -- `DOTNET_CLI_HOME=/tmp/dotnet-home MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-restore -p:TargetFramework=net10.0 -p:RestoreFallbackFolders="" -v minimal` - - 结果:失败;`MSB4018`,原因同上 -- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` - - 结果:成功;定位到 PR `#288`,提取 latest-head unresolved AI review threads、MegaLinter 与 Docstring Coverage 信号 -- `dotnet restore GFramework.sln -p:RestoreFallbackFolders="" -v minimal` - - 结果:成功;已刷新 WSL 原生 restore 元数据,清除先前的 stale fallback package folder 阻塞 -- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release` - - 结果:成功;`28 Warning(s)`、`0 Error(s)` -- `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` - - 结果:成功;`329 Warning(s)`、`0 Error(s)` -- `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - - 结果:成功;`137 Warning(s)`、`0 Error(s)` -- `dotnet restore GFramework.Core.Tests/GFramework.Core.Tests.csproj -p:TestTargetFrameworks=net8.0 -p:RestoreFallbackFolders="" -v minimal` - - 结果:失败;`NU1201`,`GFramework.Tests.Common` 仅支持 `net10.0`,因此不能用 `net8.0` 旁路验证 `Core.Tests` +- `dotnet clean` + - 当前结果:成功;在提权后的直接 shell 中可正常完成仓库根 clean +- `dotnet build` + - 当前结果:成功;`656 Warning(s)`、`0 Error(s)` +- `dotnet build GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release` + - 当前结果:成功;`0 Warning(s)`、`0 Error(s)` +- `dotnet build GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj -c Release` + - 当前结果:成功;`0 Warning(s)`、`0 Error(s)` - `git diff --name-only origin/main...HEAD | wc -l` - - 当前结果:`75` + - 当前结果:`0` - `git diff --numstat origin/main...HEAD` - - 当前结果:累计 `1083` added、`1015` deleted,即 `2098` changed lines + - 当前结果:`0 added / 0 deleted` ## 下一步建议 -1. 当前 turn 已按标准 WSL `dotnet build` 路径完成 `Core` / `Game` / `Core.Tests` Release build 验证;后续若继续 PR #288 收尾,优先重新抓取 unresolved threads,确认哪些线程已可直接 resolve。 -2. 若后续要继续 `Core` / `Core.Tests` / `Game` warning reduction,应以当前标准 build 输出为新真值,而不是继续沿用上一轮带 workaround 参数的失败命令。 -3. 若要开启下一轮批处理,优先选择新的 stop-condition(例如新的 file 阈值、warning 目标或限定到单模块)后再继续。 +1. 集成并复核当前 4 文件测试噪音批次后,用沙箱外 `dotnet build GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release` 与 `dotnet build GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj -c Release` 重新确认结果。 +2. 下一轮 warning reduction 继续优先处理 `GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs` 的长方法切片;它仍是已确认的单文件低风险热点,适合继续用 worker 独立推进。 +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 f6394342..2faf0967 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,36 @@ # Analyzer Warning Reduction 追踪 +## 2026-04-25 — RP-065 + +### 阶段:确认 .NET 验证噪音来自沙箱,并把无沙箱直跑写成仓库规则 + +- 触发背景: + - 用户明确指出“之前很多清理、构建、测试报错像是环境问题,需要申请权限在沙箱外执行”,并要求把该解决方案写入 `AGENTS.md` + - 主线程随后在同一 worktree 中对比了沙箱内与提权后直接 shell 的 `dotnet clean` / `dotnet build` +- 主线程实施: + - 在沙箱内直接运行 `dotnet clean` 时再次复现“Build FAILED but 0 errors”的无诊断噪音 + - 申请提权后重新执行同一条 `dotnet clean`,确认命令可正常完成,说明先前 clean 失败并非仓库真值 + - 在同一提权上下文直接执行 `dotnet build`,拿到当前仓库根权威基线:`656 Warning(s)`、`0 Error(s)` + - 关闭正在运行的 warning-reduction worker,把工作重心切到仓库治理与 active recovery 文档净化 + - 更新 `AGENTS.md`,新增规则:当沙箱内 `dotnet clean` / `dotnet build` / `dotnet test` 产生缺少诊断、权限错误或其他环境噪音时,必须申请沙箱外重跑同一条直接命令,并以该结果为准 + - 刷新 active todo/trace,把“环境阻塞”从默认恢复入口中降级为历史噪音,不再作为当前真值 +- 并行工作: + - worker 收敛了 4 个低风险测试噪音文件: + - `GFramework.Game.Tests/Config/GameConfigBootstrapTests.cs` + - `GFramework.Game.Tests/Config/GeneratedConfigConsumerIntegrationTests.cs` + - `GFramework.Game.Tests/Config/YamlConfigTextValidatorTests.cs` + - `GFramework.Ecs.Arch.Tests/Ecs/EcsAdvancedTests.cs` + - worker 验证: + - `dotnet build GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release` + - worker 初次结果:成功;随后主线程在同一提权环境复核后确认当前为 `0 Warning(s)`、`0 Error(s)` + - `dotnet build GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj -c Release` + - 主线程复核:成功;`0 Warning(s)`、`0 Error(s)` +- 当前结论: + - 本仓库当前在 agent 沙箱内执行 `.NET` 验证时,确实可能出现假失败或缺失诊断 + - 当前应把“提权后的直接 `dotnet` 命令输出”视为仓库真值,而不是继续围绕沙箱噪音扩展 workaround 命令形态 + - `fix/analyzer-warning-reduction-batch` 当前 `HEAD` 已与 `origin/main` 对齐;新的 `$gframework-batch-boot 50` 轮次从 `0 files / 0 lines` committed diff 开始 + - 下一轮低风险热点仍是 `GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs` 的 `4` 个 `MA0051` + ## 2026-04-25 — RP-064 ### 阶段:按标准 WSL build 路径复核 PR #288 建议并完成本轮收口 From be26640b584f90057d03d576131b16c168c4bf7f Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 25 Apr 2026 15:13:22 +0800 Subject: [PATCH 02/12] =?UTF-8?q?test(game-tests):=20=E6=94=B6=E6=95=9B?= =?UTF-8?q?=E7=83=AD=E9=87=8D=E8=BD=BD=E9=95=BF=E6=96=B9=E6=B3=95=20warnin?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构 YamlConfigLoaderTests 的热重载夹具与回调接线,消化 4 个 MA0051 长方法警告 - 更新 analyzer-warning-reduction active todo 与 trace,记录 652 条根构建 warning 的新基线 - 保持 GFramework.Game.Tests 的 Release build 为 0 Warning 和 0 Error --- .../Config/YamlConfigLoaderTests.cs | 503 +++++++++--------- .../analyzer-warning-reduction-tracking.md | 50 +- .../analyzer-warning-reduction-trace.md | 27 + 3 files changed, 312 insertions(+), 268 deletions(-) diff --git a/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs b/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs index ecb44a4f..4b04ae0b 100644 --- a/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs +++ b/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs @@ -1,4 +1,5 @@ using System.IO; +using GFramework.Core.Abstractions.Events; using GFramework.Game.Abstractions.Config; using GFramework.Game.Config; @@ -2789,83 +2790,15 @@ public class YamlConfigLoaderTests [Test] public async Task EnableHotReload_Should_Keep_Previous_State_When_Contains_Reference_Dependency_Breaks() { - CreateConfigFile( - "item/potion.yaml", - """ - id: potion - name: Potion - """); - CreateConfigFile( - "monster/slime.yaml", - """ - id: 1 - name: Slime - dropItemIds: - - potion - """); - CreateSchemaFile( - "schemas/item.schema.json", - """ - { - "type": "object", - "required": ["id", "name"], - "properties": { - "id": { "type": "string" }, - "name": { "type": "string" } - } - } - """); - CreateSchemaFile( - "schemas/monster.schema.json", - """ - { - "type": "object", - "required": ["id", "name", "dropItemIds"], - "properties": { - "id": { "type": "integer" }, - "name": { "type": "string" }, - "dropItemIds": { - "type": "array", - "minContains": 1, - "contains": { - "type": "string", - "x-gframework-ref-table": "item" - }, - "items": { - "type": "string" - } - } - } - } - """); - - var loader = new YamlConfigLoader(_rootPath) - .RegisterTable("item", "item", "schemas/item.schema.json", - static config => config.Id) - .RegisterTable("monster", "monster", "schemas/monster.schema.json", - static config => config.Id); - var registry = new ConfigRegistry(); - await loader.LoadAsync(registry); - - var reloadFailureTaskSource = - new TaskCompletionSource<(string TableName, Exception Exception)>(TaskCreationOptions - .RunContinuationsAsynchronously); - var hotReload = loader.EnableHotReload( - registry, - onTableReloadFailed: (tableName, exception) => - reloadFailureTaskSource.TrySetResult((tableName, exception)), - debounceDelay: TimeSpan.FromMilliseconds(150)); + var (loader, registry) = await CreateLoadedContainsReferenceHotReloadScenarioAsync().ConfigureAwait(false); + var (reloadFailureTaskSource, hotReload) = EnableHotReloadWithFailureCapture(loader, registry); try { - CreateConfigFile( - "item/potion.yaml", - """ - id: elixir - name: Elixir - """); + CreateConfigFile("item/potion.yaml", UpdatedItemConfigContent); - var failure = await WaitForTaskWithinAsync(reloadFailureTaskSource.Task, TimeSpan.FromSeconds(5)); + var failure = await WaitForTaskWithinAsync(reloadFailureTaskSource.Task, TimeSpan.FromSeconds(5)) + .ConfigureAwait(false); var diagnosticException = failure.Exception as ConfigLoadException; Assert.Multiple(() => @@ -2958,65 +2891,17 @@ public class YamlConfigLoaderTests [Test] public async Task EnableHotReload_Should_Support_Options_Object() { - CreateConfigFile( - "monster/slime.yaml", - """ - id: 1 - name: Slime - hp: 10 - """); - CreateSchemaFile( - "schemas/monster.schema.json", - """ - { - "type": "object", - "required": ["id", "name"], - "properties": { - "id": { "type": "integer" }, - "name": { "type": "string" }, - "hp": { "type": "integer" } - } - } - """); - - var loader = new YamlConfigLoader(_rootPath) - .RegisterTable( - new YamlConfigTableRegistrationOptions( - "monster", - "monster", - static config => config.Id) - { - SchemaRelativePath = "schemas/monster.schema.json" - }); - var registry = new ConfigRegistry(); - await loader.LoadAsync(registry); - - var reloadTaskSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - var hotReload = loader.EnableHotReload( - registry, - new YamlConfigHotReloadOptions - { - OnTableReloaded = tableName => reloadTaskSource.TrySetResult(tableName), - DebounceDelay = TimeSpan.FromMilliseconds(150) - }); + var (loader, registry) = await CreateLoadedMonsterHotReloadScenarioAsync(useOptionsObject: true) + .ConfigureAwait(false); + var (reloadTaskSource, hotReload) = EnableHotReloadWithReloadCapture(loader, registry, useOptionsObject: true); try { - CreateConfigFile( - "monster/slime.yaml", - """ - id: 1 - name: Slime - hp: 25 - """); + CreateConfigFile("monster/slime.yaml", UpdatedMonsterConfigContent); - var tableName = await WaitForTaskWithinAsync(reloadTaskSource.Task, TimeSpan.FromSeconds(5)); - - Assert.Multiple(() => - { - Assert.That(tableName, Is.EqualTo("monster")); - Assert.That(registry.GetTable("monster").Get(1).Hp, Is.EqualTo(25)); - }); + var tableName = await WaitForTaskWithinAsync(reloadTaskSource.Task, TimeSpan.FromSeconds(5)) + .ConfigureAwait(false); + AssertMonsterHotReloadUpdated(tableName, registry); } finally { @@ -3050,60 +2935,15 @@ public class YamlConfigLoaderTests [Test] public async Task EnableHotReload_Should_Keep_Previous_Table_When_Schema_Change_Makes_Reload_Fail() { - CreateConfigFile( - "monster/slime.yaml", - """ - id: 1 - name: Slime - hp: 10 - """); - CreateSchemaFile( - "schemas/monster.schema.json", - """ - { - "type": "object", - "required": ["id", "name"], - "properties": { - "id": { "type": "integer" }, - "name": { "type": "string" }, - "hp": { "type": "integer" } - } - } - """); - - var loader = new YamlConfigLoader(_rootPath) - .RegisterTable("monster", "monster", "schemas/monster.schema.json", - static config => config.Id); - var registry = new ConfigRegistry(); - await loader.LoadAsync(registry); - - var reloadFailureTaskSource = - new TaskCompletionSource<(string TableName, Exception Exception)>(TaskCreationOptions - .RunContinuationsAsynchronously); - var hotReload = loader.EnableHotReload( - registry, - onTableReloadFailed: (tableName, exception) => - reloadFailureTaskSource.TrySetResult((tableName, exception)), - debounceDelay: TimeSpan.FromMilliseconds(150)); + var (loader, registry) = await CreateLoadedMonsterHotReloadScenarioAsync().ConfigureAwait(false); + var (reloadFailureTaskSource, hotReload) = EnableHotReloadWithFailureCapture(loader, registry); try { - CreateSchemaFile( - "schemas/monster.schema.json", - """ - { - "type": "object", - "required": ["id", "name", "rarity"], - "properties": { - "id": { "type": "integer" }, - "name": { "type": "string" }, - "hp": { "type": "integer" }, - "rarity": { "type": "string" } - } - } - """); + CreateSchemaFile("schemas/monster.schema.json", MonsterSchemaWithRarityContent); - var failure = await WaitForTaskWithinAsync(reloadFailureTaskSource.Task, TimeSpan.FromSeconds(5)); + var failure = await WaitForTaskWithinAsync(reloadFailureTaskSource.Task, TimeSpan.FromSeconds(5)) + .ConfigureAwait(false); var diagnosticException = failure.Exception as ConfigLoadException; Assert.Multiple(() => @@ -3130,75 +2970,15 @@ public class YamlConfigLoaderTests [Test] public async Task EnableHotReload_Should_Keep_Previous_State_When_Dependency_Table_Breaks_Cross_Table_Reference() { - CreateConfigFile( - "item/potion.yaml", - """ - id: potion - name: Potion - """); - CreateConfigFile( - "monster/slime.yaml", - """ - id: 1 - name: Slime - dropItemId: potion - """); - CreateSchemaFile( - "schemas/item.schema.json", - """ - { - "type": "object", - "required": ["id", "name"], - "properties": { - "id": { "type": "string" }, - "name": { "type": "string" } - } - } - """); - CreateSchemaFile( - "schemas/monster.schema.json", - """ - { - "type": "object", - "required": ["id", "name", "dropItemId"], - "properties": { - "id": { "type": "integer" }, - "name": { "type": "string" }, - "dropItemId": { - "type": "string", - "x-gframework-ref-table": "item" - } - } - } - """); - - var loader = new YamlConfigLoader(_rootPath) - .RegisterTable("item", "item", "schemas/item.schema.json", - static config => config.Id) - .RegisterTable("monster", "monster", "schemas/monster.schema.json", - static config => config.Id); - var registry = new ConfigRegistry(); - await loader.LoadAsync(registry); - - var reloadFailureTaskSource = - new TaskCompletionSource<(string TableName, Exception Exception)>(TaskCreationOptions - .RunContinuationsAsynchronously); - var hotReload = loader.EnableHotReload( - registry, - onTableReloadFailed: (tableName, exception) => - reloadFailureTaskSource.TrySetResult((tableName, exception)), - debounceDelay: TimeSpan.FromMilliseconds(150)); + var (loader, registry) = await CreateLoadedCrossTableReferenceHotReloadScenarioAsync().ConfigureAwait(false); + var (reloadFailureTaskSource, hotReload) = EnableHotReloadWithFailureCapture(loader, registry); try { - CreateConfigFile( - "item/potion.yaml", - """ - id: elixir - name: Elixir - """); + CreateConfigFile("item/potion.yaml", UpdatedItemConfigContent); - var failure = await WaitForTaskWithinAsync(reloadFailureTaskSource.Task, TimeSpan.FromSeconds(5)); + var failure = await WaitForTaskWithinAsync(reloadFailureTaskSource.Task, TimeSpan.FromSeconds(5)) + .ConfigureAwait(false); var diagnosticException = failure.Exception as ConfigLoadException; Assert.Multiple(() => @@ -3223,6 +3003,243 @@ public class YamlConfigLoaderTests } } + private const string ItemSchemaContent = + """ + { + "type": "object", + "required": ["id", "name"], + "properties": { + "id": { "type": "string" }, + "name": { "type": "string" } + } + } + """; + + private const string InitialMonsterConfigContent = + """ + id: 1 + name: Slime + hp: 10 + """; + + private const string UpdatedMonsterConfigContent = + """ + id: 1 + name: Slime + hp: 25 + """; + + private const string MonsterSchemaContent = + """ + { + "type": "object", + "required": ["id", "name"], + "properties": { + "id": { "type": "integer" }, + "name": { "type": "string" }, + "hp": { "type": "integer" } + } + } + """; + + private const string MonsterSchemaWithRarityContent = + """ + { + "type": "object", + "required": ["id", "name", "rarity"], + "properties": { + "id": { "type": "integer" }, + "name": { "type": "string" }, + "hp": { "type": "integer" }, + "rarity": { "type": "string" } + } + } + """; + + private const string UpdatedItemConfigContent = + """ + id: elixir + name: Elixir + """; + + private const string MonsterDropArrayConfigContent = + """ + id: 1 + name: Slime + dropItemIds: + - potion + """; + + private const string MonsterDropArraySchemaContent = + """ + { + "type": "object", + "required": ["id", "name", "dropItemIds"], + "properties": { + "id": { "type": "integer" }, + "name": { "type": "string" }, + "dropItemIds": { + "type": "array", + "minContains": 1, + "contains": { + "type": "string", + "x-gframework-ref-table": "item" + }, + "items": { + "type": "string" + } + } + } + } + """; + + private const string MonsterDropConfigContent = + """ + id: 1 + name: Slime + dropItemId: potion + """; + + private const string MonsterDropSchemaContent = + """ + { + "type": "object", + "required": ["id", "name", "dropItemId"], + "properties": { + "id": { "type": "integer" }, + "name": { "type": "string" }, + "dropItemId": { + "type": "string", + "x-gframework-ref-table": "item" + } + } + } + """; + + /// + /// 创建并加载标准 monster 热重载夹具,供重载成功与 schema 失败场景复用。 + /// + /// 是否通过选项对象注册表。 + /// 已完成首次加载的加载器与注册表。 + private async Task<(YamlConfigLoader Loader, ConfigRegistry Registry)> CreateLoadedMonsterHotReloadScenarioAsync( + bool useOptionsObject = false) + { + CreateConfigFile("monster/slime.yaml", InitialMonsterConfigContent); + CreateSchemaFile("schemas/monster.schema.json", MonsterSchemaContent); + + var loader = useOptionsObject + ? new YamlConfigLoader(_rootPath).RegisterTable( + new YamlConfigTableRegistrationOptions( + "monster", + "monster", + static config => config.Id) + { + SchemaRelativePath = "schemas/monster.schema.json" + }) + : new YamlConfigLoader(_rootPath) + .RegisterTable("monster", "monster", "schemas/monster.schema.json", + static config => config.Id); + var registry = new ConfigRegistry(); + await loader.LoadAsync(registry).ConfigureAwait(false); + return (loader, registry); + } + + /// + /// 创建并加载 contains 子 schema 引用场景,供热重载依赖回滚测试复用。 + /// + /// 已完成首次加载的加载器与注册表。 + private async Task<(YamlConfigLoader Loader, ConfigRegistry Registry)> + CreateLoadedContainsReferenceHotReloadScenarioAsync() + { + var loader = CreateItemBackedMonsterLoader( + MonsterDropArrayConfigContent, + MonsterDropArraySchemaContent, + static config => config.Id, + ("item/potion.yaml", "potion", "Potion")); + var registry = new ConfigRegistry(); + await loader.LoadAsync(registry).ConfigureAwait(false); + return (loader, registry); + } + + /// + /// 创建并加载跨表单值引用场景,供热重载依赖回滚测试复用。 + /// + /// 已完成首次加载的加载器与注册表。 + private async Task<(YamlConfigLoader Loader, ConfigRegistry Registry)> + CreateLoadedCrossTableReferenceHotReloadScenarioAsync() + { + var loader = CreateItemBackedMonsterLoader( + MonsterDropConfigContent, + MonsterDropSchemaContent, + static config => config.Id, + ("item/potion.yaml", "potion", "Potion")); + var registry = new ConfigRegistry(); + await loader.LoadAsync(registry).ConfigureAwait(false); + return (loader, registry); + } + + /// + /// 以统一的失败回调配置启用热重载,避免每个测试重复接线相同的通知逻辑。 + /// + /// 已完成首次加载的加载器。 + /// 要复用的配置注册表。 + /// 失败通知任务源与取消注册句柄。 + private static (TaskCompletionSource<(string TableName, Exception Exception)> TaskSource, IUnRegister Registration) + EnableHotReloadWithFailureCapture(YamlConfigLoader loader, ConfigRegistry registry) + { + var reloadFailureTaskSource = + new TaskCompletionSource<(string TableName, Exception Exception)>(TaskCreationOptions + .RunContinuationsAsynchronously); + var hotReload = loader.EnableHotReload( + registry, + onTableReloadFailed: (tableName, exception) => + reloadFailureTaskSource.TrySetResult((tableName, exception)), + debounceDelay: TimeSpan.FromMilliseconds(150)); + return (reloadFailureTaskSource, hotReload); + } + + /// + /// 以统一的成功回调配置启用热重载,避免相同的防抖与回调装配在测试中重复出现。 + /// + /// 已完成首次加载的加载器。 + /// 要复用的配置注册表。 + /// 是否通过选项对象启用热重载。 + /// 成功通知任务源与取消注册句柄。 + private static (TaskCompletionSource TaskSource, IUnRegister Registration) EnableHotReloadWithReloadCapture( + YamlConfigLoader loader, + ConfigRegistry registry, + bool useOptionsObject = false) + { + var reloadTaskSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var hotReload = useOptionsObject + ? loader.EnableHotReload( + registry, + new YamlConfigHotReloadOptions + { + OnTableReloaded = tableName => reloadTaskSource.TrySetResult(tableName), + DebounceDelay = TimeSpan.FromMilliseconds(150) + }) + : loader.EnableHotReload( + registry, + onTableReloaded: tableName => reloadTaskSource.TrySetResult(tableName), + debounceDelay: TimeSpan.FromMilliseconds(150)); + return (reloadTaskSource, hotReload); + } + + /// + /// 断言标准 monster 热重载成功后,通知表名与刷新后的生命值都符合预期。 + /// + /// 热重载回调返回的表名。 + /// 承载刷新结果的注册表。 + private static void AssertMonsterHotReloadUpdated(string tableName, ConfigRegistry registry) + { + Assert.Multiple(() => + { + Assert.That(tableName, Is.EqualTo("monster")); + Assert.That(registry.GetTable("monster").Get(1).Hp, Is.EqualTo(25)); + }); + } + /// /// 为对象数组 contains 子集匹配场景创建加载器,避免测试方法体被大段固定 schema 稀释。 /// 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 5cdb06be..9787b506 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,37 +6,39 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-065` -- 当前阶段:`Phase 65` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-066` +- 当前阶段:`Phase 66` - 当前焦点: - - `2026-04-25` 已确认此前一批 `dotnet clean` / `dotnet build` / `dotnet test` 异常主要来自 agent 沙箱环境,而不是仓库或 WSL 默认 shell 本身 - - 已用提权后的直接命令重新建立仓库根基线:`dotnet clean` 成功,`dotnet build` 结果为 `656 Warning(s)`、`0 Error(s)` - - 当前 `HEAD` 与 `origin/main` 对齐;基于 `$gframework-batch-boot 50` 的 committed branch diff 现为 `0 files / 0 lines` -- 当前活跃写集是 4 个测试噪音清理文件,属于新的低风险 warning-reduction 批次;提交前需由主线程在沙箱外重新验证 - - 主线程已完成该批次的沙箱外复核,当前可安全并入本轮提交 - - 已决定把“沙箱内 .NET 验证失败时必须申请沙箱外重跑并以该结果为准”写入 `AGENTS.md`,避免后续继续扩散伪环境阻塞 + - `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` 阈值 ## 当前活跃事实 - 当前 `origin/main` 基线提交为 `4ad880c`(`2026-04-25T14:35:38+08:00`)。 -- `fix/analyzer-warning-reduction-batch` 当前 `HEAD` 等于 `origin/main`;因此 shorthand 阈值 `$gframework-batch-boot 50` 的当前 committed 规模为: - - `git diff --name-only origin/main...HEAD | wc -l`:`0` - - `git diff --numstat origin/main...HEAD`:`0 added / 0 deleted` -- 提权后的直接仓库根验证已经确认: +- `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` - - 结果:成功;`656 Warning(s)`、`0 Error(s)`,当前 warning reduction 应以此为总基线 -- 当前待集成的低风险批次文件: + - 最新结果:成功;`652 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/YamlConfigTextValidatorTests.cs` - - `GFramework.Ecs.Arch.Tests/Ecs/EcsAdvancedTests.cs` -- 上述批次的 worker 侧验证结果: + - `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` - 最新主线程结果:成功;`0 Warning(s)`、`0 Error(s)` - - `dotnet build GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj -c Release` - - 最新主线程结果:成功;`0 Warning(s)`、`0 Error(s)` ## 当前风险 @@ -64,18 +66,16 @@ - `dotnet clean` - 当前结果:成功;在提权后的直接 shell 中可正常完成仓库根 clean - `dotnet build` - - 当前结果:成功;`656 Warning(s)`、`0 Error(s)` + - 当前结果:成功;`652 Warning(s)`、`0 Error(s)` - `dotnet build GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release` - 当前结果:成功;`0 Warning(s)`、`0 Error(s)` -- `dotnet build GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj -c Release` - - 当前结果:成功;`0 Warning(s)`、`0 Error(s)` - `git diff --name-only origin/main...HEAD | wc -l` - - 当前结果:`0` + - 当前结果:`7` - `git diff --numstat origin/main...HEAD` - - 当前结果:`0 added / 0 deleted` + - 当前结果:累计 `104` added、`123` deleted ## 下一步建议 -1. 集成并复核当前 4 文件测试噪音批次后,用沙箱外 `dotnet build GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release` 与 `dotnet build GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj -c Release` 重新确认结果。 -2. 下一轮 warning reduction 继续优先处理 `GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs` 的长方法切片;它仍是已确认的单文件低风险热点,适合继续用 worker 独立推进。 +1. 提交当前 `YamlConfigLoaderTests.cs` 单文件批次后,继续按 `$gframework-batch-boot 50` 规则重算 branch diff,并挑选下一个 1-3 文件的低风险热点。 +2. 下一轮优先从 `GFramework.Cqrs.Tests` 或 `GFramework.Game` 中继续选择单文件 `MA0051` / 测试噪音切片,避免过早推高 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 2faf0967..2e3dd9c8 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,32 @@ # Analyzer Warning Reduction 追踪 +## 2026-04-25 — RP-066 + +### 阶段:主线程回收停滞的单文件批次,并继续压低根构建 warning 基线 + +- 触发背景: + - `RP-065` 收尾后,`fix/analyzer-warning-reduction-batch` 已通过 `6a704f3` 把 AGENTS / active ai-plan 真值修正和 4 文件测试噪音批次提交到分支 + - 原先负责 `YamlConfigLoaderTests.cs` 的 worker 长时间无结果,主线程收回该单文件批次以避免继续阻塞 +- 主线程实施: + - 关闭停滞 worker,直接重构 `GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs` + - 通过提取固定夹具内容、热重载接线 helper 与共享断言,收敛以下 4 个长方法 warning: + - `EnableHotReload_Should_Keep_Previous_State_When_Contains_Reference_Dependency_Breaks` + - `EnableHotReload_Should_Support_Options_Object` + - `EnableHotReload_Should_Keep_Previous_Table_When_Schema_Change_Makes_Reload_Fail` + - `EnableHotReload_Should_Keep_Previous_State_When_Dependency_Table_Breaks_Cross_Table_Reference` + - 在第一次仓库根重建中命中了两个 `CS0411` 泛型推断错误,主线程随即补上显式类型参数并重新建立 clean/build 基线 +- 验证里程碑: + - `dotnet clean` + - 结果:成功 + - `dotnet build` + - 结果:成功;`652 Warning(s)`、`0 Error(s)`,相较 `RP-065` 的 `656` 再下降 `4` + - `dotnet build GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release` + - 结果:成功;`0 Warning(s)`、`0 Error(s)` +- 当前结论: + - `YamlConfigLoaderTests.cs` 这 4 个根构建直接确认的 `MA0051` 已被消化 + - 当前分支在 `6a704f3` 之后的下一提交只会新增 1 个唯一文件,因此 branch diff 仍明显低于 `$gframework-batch-boot 50` 阈值 + - 下一轮可继续选择新的单文件或小写集热点,而不必暂停当前 batch loop + ## 2026-04-25 — RP-065 ### 阶段:确认 .NET 验证噪音来自沙箱,并把无沙箱直跑写成仓库规则 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 03/12] =?UTF-8?q?refactor(game):=20=E6=94=B6=E6=95=9B?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=8C=96=E8=BF=81=E7=A7=BB=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E5=99=A8=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 基线 From a7fa70e4fe97159b51fcfaed802bdcdf3970f856 Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 25 Apr 2026 15:29:26 +0800 Subject: [PATCH 04/12] =?UTF-8?q?fix(core-tests):=20=E6=B8=85=E7=90=86=20L?= =?UTF-8?q?ogContextTests=20=E5=BC=82=E6=AD=A5=E7=AD=89=E5=BE=85=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复异步测试中的 await 链 MA0004 warning - 保持 LogContext 在线程隔离场景下的断言行为不变 --- GFramework.Core.Tests/Logging/LogContextTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GFramework.Core.Tests/Logging/LogContextTests.cs b/GFramework.Core.Tests/Logging/LogContextTests.cs index cdd1f731..59f468f6 100644 --- a/GFramework.Core.Tests/Logging/LogContextTests.cs +++ b/GFramework.Core.Tests/Logging/LogContextTests.cs @@ -157,7 +157,7 @@ public class LogContextTests using (LogContext.Push("TaskId", "Task1")) { task1Values.Add(LogContext.Current["TaskId"]); - await Task.Delay(50); + await Task.Delay(50).ConfigureAwait(false); task1Values.Add(LogContext.Current["TaskId"]); } }); @@ -167,12 +167,12 @@ public class LogContextTests using (LogContext.Push("TaskId", "Task2")) { task2Values.Add(LogContext.Current["TaskId"]); - await Task.Delay(50); + await Task.Delay(50).ConfigureAwait(false); task2Values.Add(LogContext.Current["TaskId"]); } }); - await Task.WhenAll(task1, task2); + await Task.WhenAll(task1, task2).ConfigureAwait(false); Assert.That(task1Values, Has.All.EqualTo("Task1")); Assert.That(task2Values, Has.All.EqualTo("Task2")); From 9f6204d6e2bf323fe7dd68bc6709cdad1c2e2c6a Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 25 Apr 2026 15:30:09 +0800 Subject: [PATCH 05/12] =?UTF-8?q?fix(core-tests):=20=E6=94=B6=E5=8F=A3=20L?= =?UTF-8?q?oggerTests=20=E6=97=A5=E5=BF=97=E9=9B=86=E5=90=88=E6=8A=BD?= =?UTF-8?q?=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复 TestLogger.Logs 暴露 List 实现类型导致的 MA0016 warning - 保持测试桩内部写入顺序和现有测试访问方式不变 --- GFramework.Core.Tests/Logging/LoggerTests.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/GFramework.Core.Tests/Logging/LoggerTests.cs b/GFramework.Core.Tests/Logging/LoggerTests.cs index ccc207a3..3bba60a4 100644 --- a/GFramework.Core.Tests/Logging/LoggerTests.cs +++ b/GFramework.Core.Tests/Logging/LoggerTests.cs @@ -425,6 +425,8 @@ public class LoggerTests /// public sealed class TestLogger : AbstractLogger { + private readonly List _logs = new(); + /// /// 初始化TestLogger的新实例 /// @@ -435,9 +437,9 @@ public sealed class TestLogger : AbstractLogger } /// - /// 获取记录的日志条目列表 + /// 获取按写入顺序保存的日志条目只读视图 /// - public List Logs { get; } = new(); + public IReadOnlyList Logs => _logs; /// /// 将日志信息写入内部存储 @@ -447,7 +449,7 @@ public sealed class TestLogger : AbstractLogger /// 相关异常(可选) protected override void Write(LogLevel level, string message, Exception? exception) { - Logs.Add(new LogEntry(level, message, exception)); + _logs.Add(new LogEntry(level, message, exception)); } /// @@ -457,4 +459,4 @@ public sealed class TestLogger : AbstractLogger /// 日志消息 /// 相关异常(可选) public sealed record LogEntry(LogLevel Level, string Message, Exception? Exception); -} \ No newline at end of file +} From 58ba6c011e005a6ed2e83c7ec6c65b6290d60802 Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 25 Apr 2026 15:39:32 +0800 Subject: [PATCH 06/12] =?UTF-8?q?test(cqrs-tests):=20=E6=94=B6=E6=95=9B?= =?UTF-8?q?=E5=A4=84=E7=90=86=E5=99=A8=E6=B3=A8=E5=86=8C=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构 CqrsHandlerRegistrarTests 的缓存元数据用例,拆分装配、断言与 verify helper - 更新 analyzer warning reduction 的 active tracking 与 trace,记录并行 subagent 批次和 645 条根构建基线 --- .../Cqrs/CqrsHandlerRegistrarTests.cs | 148 +++++++++++------- .../analyzer-warning-reduction-tracking.md | 37 +++-- .../analyzer-warning-reduction-trace.md | 36 +++++ 3 files changed, 150 insertions(+), 71 deletions(-) diff --git a/GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs b/GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs index 8bcdeff3..dcbfbd2a 100644 --- a/GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs +++ b/GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs @@ -327,27 +327,7 @@ internal sealed class CqrsHandlerRegistrarTests [Test] public void RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers() { - var generatedAssembly = new Mock(); - generatedAssembly - .SetupGet(static assembly => assembly.FullName) - .Returns("GFramework.Core.Tests.Cqrs.CachedMetadataAssembly, Version=1.0.0.0"); - generatedAssembly - .Setup(static assembly => assembly.GetCustomAttributes(typeof(CqrsHandlerRegistryAttribute), false)) - .Returns([new CqrsHandlerRegistryAttribute(typeof(PartialGeneratedNotificationHandlerRegistry))]); - generatedAssembly - .Setup(static assembly => assembly.GetCustomAttributes(typeof(CqrsReflectionFallbackAttribute), false)) - .Returns( - [ - new CqrsReflectionFallbackAttribute( - ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType.FullName!) - ]); - generatedAssembly - .Setup(static assembly => assembly.GetType( - ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType.FullName!, - false, - false)) - .Returns(ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType); - + var generatedAssembly = CreateCachedMetadataAssembly(); var firstContainer = new MicrosoftDiContainer(); var secondContainer = new MicrosoftDiContainer(); @@ -356,43 +336,8 @@ internal sealed class CqrsHandlerRegistrarTests firstContainer.Freeze(); secondContainer.Freeze(); - var firstRegistrations = firstContainer.GetAll>() - .Select(static handler => handler.GetType()) - .ToArray(); - var secondRegistrations = secondContainer.GetAll>() - .Select(static handler => handler.GetType()) - .ToArray(); - - Assert.Multiple(() => - { - Assert.That( - firstRegistrations, - Is.EqualTo( - [ - typeof(GeneratedRegistryNotificationHandler), - ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType - ])); - Assert.That( - secondRegistrations, - Is.EqualTo( - [ - typeof(GeneratedRegistryNotificationHandler), - ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType - ])); - }); - - generatedAssembly.Verify( - static assembly => assembly.GetCustomAttributes(typeof(CqrsHandlerRegistryAttribute), false), - Times.Once); - generatedAssembly.Verify( - static assembly => assembly.GetCustomAttributes(typeof(CqrsReflectionFallbackAttribute), false), - Times.Once); - generatedAssembly.Verify( - static assembly => assembly.GetType( - ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType.FullName!, - false, - false), - Times.Once); + AssertGeneratedRegistryNotificationHandlers(firstContainer, secondContainer); + VerifyCachedMetadataAssemblyLookups(generatedAssembly); } /// @@ -526,6 +471,93 @@ internal sealed class CqrsHandlerRegistrarTests ClearCache(GetRegistrarCacheField("SupportedHandlerInterfacesCache")); } + /// + /// 创建一个携带 generated registry 与 reflection fallback 元数据的程序集替身, + /// 用于验证 registrar 是否会跨容器复用程序集级元数据。 + /// + private static Mock CreateCachedMetadataAssembly() + { + var generatedAssembly = new Mock(); + generatedAssembly + .SetupGet(static assembly => assembly.FullName) + .Returns("GFramework.Core.Tests.Cqrs.CachedMetadataAssembly, Version=1.0.0.0"); + generatedAssembly + .Setup(static assembly => assembly.GetCustomAttributes(typeof(CqrsHandlerRegistryAttribute), false)) + .Returns([new CqrsHandlerRegistryAttribute(typeof(PartialGeneratedNotificationHandlerRegistry))]); + generatedAssembly + .Setup(static assembly => assembly.GetCustomAttributes(typeof(CqrsReflectionFallbackAttribute), false)) + .Returns( + [ + new CqrsReflectionFallbackAttribute( + ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType.FullName!) + ]); + generatedAssembly + .Setup(static assembly => assembly.GetType( + ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType.FullName!, + false, + false)) + .Returns(ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType); + return generatedAssembly; + } + + /// + /// 断言两个容器都获得了相同的 generated-registry 与 reflection-fallback 处理器集合。 + /// + private static void AssertGeneratedRegistryNotificationHandlers( + MicrosoftDiContainer firstContainer, + MicrosoftDiContainer secondContainer) + { + var firstRegistrations = GetGeneratedRegistryNotificationHandlerTypes(firstContainer); + var secondRegistrations = GetGeneratedRegistryNotificationHandlerTypes(secondContainer); + + Assert.Multiple(() => + { + Assert.That(firstRegistrations, Is.EqualTo(GetExpectedGeneratedRegistryNotificationHandlerTypes())); + Assert.That(secondRegistrations, Is.EqualTo(GetExpectedGeneratedRegistryNotificationHandlerTypes())); + }); + } + + /// + /// 读取容器中针对 generated notification 的 handler 运行时类型列表。 + /// + private static Type[] GetGeneratedRegistryNotificationHandlerTypes(MicrosoftDiContainer container) + { + return container.GetAll>() + .Select(static handler => handler.GetType()) + .ToArray(); + } + + /// + /// 获取 generated registry 与 reflection fallback 共同组成的预期 handler 顺序。 + /// + private static Type[] GetExpectedGeneratedRegistryNotificationHandlerTypes() + { + return + [ + typeof(GeneratedRegistryNotificationHandler), + ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType + ]; + } + + /// + /// 断言程序集级 generated registry / fallback 元数据只会被读取一次。 + /// + private static void VerifyCachedMetadataAssemblyLookups(Mock generatedAssembly) + { + generatedAssembly.Verify( + static assembly => assembly.GetCustomAttributes(typeof(CqrsHandlerRegistryAttribute), false), + Times.Once); + generatedAssembly.Verify( + static assembly => assembly.GetCustomAttributes(typeof(CqrsReflectionFallbackAttribute), false), + Times.Once); + generatedAssembly.Verify( + static assembly => assembly.GetType( + ReflectionFallbackNotificationContainer.ReflectionOnlyHandlerType.FullName!, + false, + false), + Times.Once); + } + /// /// 通过反射读取 registrar 的静态缓存对象。 /// 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 c3bee7f0..2d1d182f 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,14 +6,14 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-067` -- 当前阶段:`Phase 67` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-068` +- 当前阶段:`Phase 68` - 当前焦点: - - `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` 阈值 + - `2026-04-25` 主线程已提交 `1b85b53` `refactor(game): 收敛版本化迁移运行器长方法 warning` + - 并行 subagent 批次已提交 `a7fa70e` `fix(core-tests): 清理 LogContextTests 异步等待 warning` 与 `9f6204d` `fix(core-tests): 收口 LoggerTests 日志集合抽象` + - 当前主线程单文件批次聚焦 `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs`,通过拆分缓存元数据测试的装配、断言与 verify helper 收敛根构建直接确认的 `MA0051` + - 提权后的直接仓库根基线已从 `649 Warning(s)` 降至 `645 Warning(s)`,说明本轮 3 文件并行批次继续有效 + - `GFramework.Cqrs.Tests` 与 `GFramework.Core.Tests` 的直接受影响 `Release` build 当前均已通过,branch diff 仍显著低于 `$gframework-batch-boot 50` 阈值 ## 当前活跃事实 @@ -22,9 +22,12 @@ - `dotnet clean` - 结果:成功;此前沙箱内 “Build FAILED but 0 errors” 的 clean 结果不是仓库真值 - `dotnet build` - - 最新结果:成功;`649 Warning(s)`、`0 Error(s)` + - 最新结果:成功;`645 Warning(s)`、`0 Error(s)` - 已提交的低风险批次文件: - `AGENTS.md` + - `GFramework.Core.Tests/Logging/LogContextTests.cs` + - `GFramework.Core.Tests/Logging/LoggerTests.cs` + - `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs` - `GFramework.Ecs.Arch.Tests/Ecs/EcsAdvancedTests.cs` - `GFramework.Game.Tests/Config/GameConfigBootstrapTests.cs` - `GFramework.Game.Tests/Config/GeneratedConfigConsumerIntegrationTests.cs` @@ -34,7 +37,11 @@ - `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md` - `ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md` - 当前批次验证结果: - - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` + - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` + - 最新主线程结果:成功;`155 Warning(s)`、`0 Error(s)` + - `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CqrsHandlerRegistrarTests.RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers"` + - 最新主线程结果:成功;`Passed 1/1` + - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - 最新主线程结果:成功;`0 Warning(s)`、`0 Error(s)` ## 当前风险 @@ -63,12 +70,16 @@ - `dotnet clean` - 当前结果:成功;在提权后的直接 shell 中可正常完成仓库根 clean - `dotnet build` - - 当前结果:成功;`649 Warning(s)`、`0 Error(s)` -- `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` + - 当前结果:成功;`645 Warning(s)`、`0 Error(s)` +- `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` + - 当前结果:成功;`155 Warning(s)`、`0 Error(s)` +- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CqrsHandlerRegistrarTests.RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers"` + - 当前结果:成功;`Passed 1/1` +- `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - 当前结果:成功;`0 Warning(s)`、`0 Error(s)` ## 下一步建议 -1. 以当前 `649 Warning(s)` 根基线为新恢复点,继续按 `$gframework-batch-boot 50` 规则重算 branch diff,并挑选下一个 1-3 文件的低风险热点。 -2. 下一轮优先从 `GFramework.Cqrs.Tests` 或 `GFramework.Game` 中继续选择单文件 `MA0051`、`MA0016` 或测试噪音切片,避免过早推高 review 范围。 +1. 以当前 `645 Warning(s)` 根基线为新恢复点,继续按 `$gframework-batch-boot 50` 规则重算 branch diff,并挑选下一个 1-3 文件的低风险热点。 +2. 下一轮优先从 `GFramework.Cqrs.Tests`、`GFramework.Core.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 58cc8941..6316d76e 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,41 @@ # Analyzer Warning Reduction 追踪 +## 2026-04-25 — RP-068 + +### 阶段:吸收并行 subagent 小批次,并继续压低仓库根 warning 基线 + +- 触发背景: + - `RP-067` 收尾后,当前分支的仓库根基线已降到 `649 Warning(s)`,branch diff 仅 `9 files` + - 用户明确允许主线程与 subagent 在不冲突的写集上并行推进,因此本轮继续按 `$gframework-batch-boot 50` 规则拆成 3 个单文件切片 +- 接受的委派范围: + - worker `Averroes` + - 文件:`GFramework.Core.Tests/Logging/LogContextTests.cs` + - 目标:收敛 `Push_InAsyncContext_ShouldIsolateAcrossThreads()` 内的 `MA0004` + - 结果:提交 `a7fa70e` `fix(core-tests): 清理 LogContextTests 异步等待 warning` + - worker `Laplace` + - 文件:`GFramework.Core.Tests/Logging/LoggerTests.cs` + - 目标:把 `TestLogger.Logs` 从 `List` 收口为集合抽象以修复 `MA0016` + - 结果:提交 `9f6204d` `fix(core-tests): 收口 LoggerTests 日志集合抽象` +- 主线程实施: + - 本地重构 `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs` + - 将 `RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers()` 中的 mock 装配、handler 类型读取、预期集合断言与 metadata lookup verify 拆分为具名 helper + - 在吸收两个 worker 提交后,主线程重新执行直接受影响模块与仓库根验证,确保并行切片合并后的真值一致 +- 验证里程碑: + - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` + - 结果:成功;`155 Warning(s)`、`0 Error(s)` + - `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CqrsHandlerRegistrarTests.RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers"` + - 结果:成功;`Passed 1/1` + - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` + - 结果:成功;`0 Warning(s)`、`0 Error(s)` + - `dotnet clean` + - 结果:成功 + - `dotnet build` + - 结果:成功;`645 Warning(s)`、`0 Error(s)`,相较 `RP-067` 的 `649` 再下降 `4` +- 当前结论: + - 并行 3 文件批次已确认有效,且主线程已把 subagent 的负责范围和验证结果收口进 active trace + - 当前分支距离 `$gframework-batch-boot 50` 的停止阈值仍有充足空间,可以继续用“主线程验证 + subagent 并行单文件切片”的节奏推进 + - 下一轮可优先回到 `GFramework.Cqrs.Tests` 或 `GFramework.Game` 的单文件 `MA0051` / `MA0016` 热点 + ## 2026-04-25 — RP-067 ### 阶段:收口 Game runtime 单文件长方法切片,并继续压低根构建 warning 基线 From 4edfe53cd988fd7d026b65a904478b73d5ef1d72 Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 25 Apr 2026 15:54:27 +0800 Subject: [PATCH 07/12] =?UTF-8?q?test(cqrs-tests):=20=E6=94=B6=E6=95=9B?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=97=A5=E5=BF=97=E4=B8=8E=E8=A1=8C=E4=B8=BA?= =?UTF-8?q?=E9=9B=86=E5=90=88=E6=8A=BD=E8=B1=A1=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复 TestLogger 与 MediatorAdvancedFeaturesTests 的集合抽象暴露问题,保持测试语义不变 - 更新 analyzer warning reduction 的 active tracking 与 trace,记录新的 640 条根构建基线和委派范围 --- GFramework.Cqrs.Tests/Logging/TestLogger.cs | 6 ++-- .../Mediator/MediatorAdvancedFeaturesTests.cs | 26 ++++++++++++--- .../analyzer-warning-reduction-tracking.md | 32 +++++++++---------- .../analyzer-warning-reduction-trace.md | 28 ++++++++++++++++ 4 files changed, 69 insertions(+), 23 deletions(-) diff --git a/GFramework.Cqrs.Tests/Logging/TestLogger.cs b/GFramework.Cqrs.Tests/Logging/TestLogger.cs index c0432bc7..1b857438 100644 --- a/GFramework.Cqrs.Tests/Logging/TestLogger.cs +++ b/GFramework.Cqrs.Tests/Logging/TestLogger.cs @@ -21,6 +21,8 @@ namespace GFramework.Cqrs.Tests.Logging; /// public sealed class TestLogger : AbstractLogger { + private readonly List _logs = []; + /// /// 初始化测试日志记录器。 /// @@ -33,7 +35,7 @@ public sealed class TestLogger : AbstractLogger /// /// 获取当前测试期间捕获到的日志条目。 /// - public List Logs { get; } = []; + public IReadOnlyList Logs => _logs; /// /// 将日志写入内存,供断言使用。 @@ -43,7 +45,7 @@ public sealed class TestLogger : AbstractLogger /// 关联异常。 protected override void Write(LogLevel level, string message, Exception? exception) { - Logs.Add(new LogEntry(level, message, exception)); + _logs.Add(new LogEntry(level, message, exception)); } /// diff --git a/GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs b/GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs index fe8f4413..410691eb 100644 --- a/GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs +++ b/GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs @@ -368,7 +368,10 @@ public sealed class TestBehaviorRequestHandler : IRequestHandler LoggedMessages { get; set; } = new(); + /// + /// 记录测试行为写入的日志消息,同时避免向调用方暴露具体集合实现。 + /// + public static IList LoggedMessages { get; set; } = new List(); } public sealed record TestValidatedRequest : IRequest @@ -467,8 +470,19 @@ public sealed record TestCircuitBreakerRequest : IRequest // 复杂场景相关类 public class SagaData { - public List CompletedSteps { get; } = new(); - public List CompensatedSteps { get; } = new(); + /// + /// 获取 Saga 已成功执行的步骤集合。 + /// + public IList CompletedSteps { get; } = new List(); + + /// + /// 获取 Saga 失败后已执行补偿的步骤集合。 + /// + public IList CompensatedSteps { get; } = new List(); + + /// + /// 获取或设置 Saga 是否已经完整结束。 + /// public bool IsCompleted { get; set; } } @@ -489,7 +503,11 @@ public sealed record TestExternalServiceRequest : IRequest public sealed record TestDatabaseRequest : IRequest { public string Data { get; init; } = string.Empty; - public List Storage { get; init; } = new(); + + /// + /// 获取或初始化用于模拟数据库写入的可变存储集合,同时避免泄漏具体集合实现。 + /// + public IList Storage { get; init; } = new List(); } #endregion 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 2d1d182f..ce1813ea 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,14 +6,14 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-068` -- 当前阶段:`Phase 68` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-069` +- 当前阶段:`Phase 69` - 当前焦点: - - `2026-04-25` 主线程已提交 `1b85b53` `refactor(game): 收敛版本化迁移运行器长方法 warning` - - 并行 subagent 批次已提交 `a7fa70e` `fix(core-tests): 清理 LogContextTests 异步等待 warning` 与 `9f6204d` `fix(core-tests): 收口 LoggerTests 日志集合抽象` - - 当前主线程单文件批次聚焦 `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs`,通过拆分缓存元数据测试的装配、断言与 verify helper 收敛根构建直接确认的 `MA0051` - - 提权后的直接仓库根基线已从 `649 Warning(s)` 降至 `645 Warning(s)`,说明本轮 3 文件并行批次继续有效 - - `GFramework.Cqrs.Tests` 与 `GFramework.Core.Tests` 的直接受影响 `Release` build 当前均已通过,branch diff 仍显著低于 `$gframework-batch-boot 50` 阈值 + - `2026-04-25` 主线程已提交 `58ba6c0` `test(cqrs-tests): 收敛处理器注册缓存测试 warning` + - 当前并行双文件批次聚焦 `GFramework.Cqrs.Tests/Logging/TestLogger.cs` 与 `GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs` + - 主线程收敛 `TestLogger.Logs` 的集合抽象暴露问题,worker 则在 `MediatorAdvancedFeaturesTests.cs` 内收敛一组低风险 `MA0016` + - 提权后的直接仓库根基线已从 `645 Warning(s)` 降至 `640 Warning(s)`,说明本轮双文件 `Cqrs.Tests` 批次继续有效 + - `GFramework.Cqrs.Tests` 的直接受影响 `Release` build 当前为 `0 Warning(s)`、`0 Error(s)`,branch diff 仍显著低于 `$gframework-batch-boot 50` 阈值 ## 当前活跃事实 @@ -22,12 +22,14 @@ - `dotnet clean` - 结果:成功;此前沙箱内 “Build FAILED but 0 errors” 的 clean 结果不是仓库真值 - `dotnet build` - - 最新结果:成功;`645 Warning(s)`、`0 Error(s)` + - 最新结果:成功;`640 Warning(s)`、`0 Error(s)` - 已提交的低风险批次文件: - `AGENTS.md` - `GFramework.Core.Tests/Logging/LogContextTests.cs` - `GFramework.Core.Tests/Logging/LoggerTests.cs` - `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs` + - `GFramework.Cqrs.Tests/Logging/TestLogger.cs` + - `GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs` - `GFramework.Ecs.Arch.Tests/Ecs/EcsAdvancedTests.cs` - `GFramework.Game.Tests/Config/GameConfigBootstrapTests.cs` - `GFramework.Game.Tests/Config/GeneratedConfigConsumerIntegrationTests.cs` @@ -38,11 +40,9 @@ - `ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md` - 当前批次验证结果: - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` - - 最新主线程结果:成功;`155 Warning(s)`、`0 Error(s)` - - `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CqrsHandlerRegistrarTests.RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers"` - - 最新主线程结果:成功;`Passed 1/1` - - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - 最新主线程结果:成功;`0 Warning(s)`、`0 Error(s)` + - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` + - 上一轮主线程结果:成功;`0 Warning(s)`、`0 Error(s)` ## 当前风险 @@ -70,16 +70,14 @@ - `dotnet clean` - 当前结果:成功;在提权后的直接 shell 中可正常完成仓库根 clean - `dotnet build` - - 当前结果:成功;`645 Warning(s)`、`0 Error(s)` + - 当前结果:成功;`640 Warning(s)`、`0 Error(s)` - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` - - 当前结果:成功;`155 Warning(s)`、`0 Error(s)` -- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CqrsHandlerRegistrarTests.RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers"` - - 当前结果:成功;`Passed 1/1` + - 当前结果:成功;`0 Warning(s)`、`0 Error(s)` - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - 当前结果:成功;`0 Warning(s)`、`0 Error(s)` ## 下一步建议 -1. 以当前 `645 Warning(s)` 根基线为新恢复点,继续按 `$gframework-batch-boot 50` 规则重算 branch diff,并挑选下一个 1-3 文件的低风险热点。 +1. 以当前 `640 Warning(s)` 根基线为新恢复点,继续按 `$gframework-batch-boot 50` 规则重算 branch diff,并挑选下一个 1-3 文件的低风险热点。 2. 下一轮优先从 `GFramework.Cqrs.Tests`、`GFramework.Core.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 6316d76e..1dc87ea8 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,33 @@ # Analyzer Warning Reduction 追踪 +## 2026-04-25 — RP-069 + +### 阶段:继续收口 Cqrs.Tests 双文件集合抽象 warning,并刷新新的仓库根基线 + +- 触发背景: + - `RP-068` 收尾后,当前分支的仓库根基线已降到 `645 Warning(s)`,branch diff 仍远低于 `$gframework-batch-boot 50` + - 为保持批次小而连续,主线程继续留在 `GFramework.Cqrs.Tests` 项目内,选取两个不涉及跨文件重构的 `MA0016` 切片 +- 接受的委派范围: + - worker `Chandrasekhar` + - 文件:`GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs` + - 目标:在同一文件内收敛 `TestLoggingBehavior.LoggedMessages`、`SagaData`、`TestDatabaseRequest` 的集合抽象暴露问题 + - 结果:未自行提交;主线程接受其工作树改动并纳入本轮批次 +- 主线程实施: + - 本地修改 `GFramework.Cqrs.Tests/Logging/TestLogger.cs` + - 将 `Logs` 从 `List` 收口为 `IReadOnlyList`,保留私有 `_logs` 作为内部存储 + - 与 worker 的 `MediatorAdvancedFeaturesTests.cs` 改动合并后,重新执行 `GFramework.Cqrs.Tests` 与仓库根验证,确认双文件批次的净效果 +- 验证里程碑: + - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` + - 结果:成功;`0 Warning(s)`、`0 Error(s)` + - `dotnet clean` + - 结果:成功 + - `dotnet build` + - 结果:成功;`640 Warning(s)`、`0 Error(s)`,相较 `RP-068` 的 `645` 再下降 `5` +- 当前结论: + - `Cqrs.Tests` 双文件批次已确认有效,并继续压低仓库根 warning 基线 + - 当前分支距离 `$gframework-batch-boot 50` 的停止阈值仍有很大空间,可以继续按“主线程小切片 + subagent 并行单文件”推进 + - 下一轮可优先回到 `GFramework.Core.Tests` 或继续选择新的 `GFramework.Cqrs.Tests` 单文件热点 + ## 2026-04-25 — RP-068 ### 阶段:吸收并行 subagent 小批次,并继续压低仓库根 warning 基线 From a75194337e44f5b80d89f5163f45d6d819a3b1b5 Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 25 Apr 2026 17:18:01 +0800 Subject: [PATCH 08/12] =?UTF-8?q?fix(pr-review):=20=E6=94=B6=E5=8F=A3?= =?UTF-8?q?=E5=BD=93=E5=89=8D=20PR=20=E4=BB=8D=E6=9C=89=E6=95=88=E7=9A=84?= =?UTF-8?q?=20review=20=E5=BB=BA=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复 AGENTS 中 latest-head review thread 指向的英文标点一致性问题 - 删除 MediatorAdvancedFeaturesTests 中未使用的 TestLoggingBehavior 测试基础设施 - 重构 VersionedMigrationRunner 的迁移执行上下文传递并补充对应 XML 文档 - 更新 analyzer warning reduction 的 active tracking 与 trace,记录 PR #291 复核结果和 639 条根构建基线 --- AGENTS.md | 2 +- .../Mediator/MediatorAdvancedFeaturesTests.cs | 8 -- .../Internal/VersionedMigrationRunner.cs | 80 ++++++++++--------- .../analyzer-warning-reduction-tracking.md | 30 ++++--- .../analyzer-warning-reduction-trace.md | 29 +++++++ 5 files changed, 91 insertions(+), 58 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 92fad88c..87bd8d49 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -33,7 +33,7 @@ All AI agents and contributors must follow these rules when writing, reviewing, baseline from a non-incremental repository-root build by running `dotnet clean` and then `dotnet build`. - Contributors MUST NOT treat a repeated incremental `dotnet build` result as authoritative for warning inspection when a clean baseline has not been captured in the same round. -- If a direct `dotnet clean`、`dotnet build`、or `dotnet test` command fails inside the agent sandbox with missing +- If a direct `dotnet clean`, `dotnet build`, or `dotnet test` command fails inside the agent sandbox with missing diagnostics, `Permission denied`, MSBuild pipe/socket errors, or other environment-only noise that does not match a normal shell invocation, contributors MUST request permission and rerun the same direct command outside the sandbox before concluding that the repository or toolchain is broken. diff --git a/GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs b/GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs index 410691eb..b89bc871 100644 --- a/GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs +++ b/GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs @@ -366,14 +366,6 @@ public sealed class TestBehaviorRequestHandler : IRequestHandler - /// 记录测试行为写入的日志消息,同时避免向调用方暴露具体集合实现。 - /// - public static IList LoggedMessages { get; set; } = new List(); -} - public sealed record TestValidatedRequest : IRequest { public int Value { get; init; } diff --git a/GFramework.Game/Internal/VersionedMigrationRunner.cs b/GFramework.Game/Internal/VersionedMigrationRunner.cs index 349d9031..029de5e9 100644 --- a/GFramework.Game/Internal/VersionedMigrationRunner.cs +++ b/GFramework.Game/Internal/VersionedMigrationRunner.cs @@ -23,6 +23,19 @@ namespace GFramework.Game.Internal; /// internal static class VersionedMigrationRunner { + /// + /// 复用一次迁移链执行期间不会变化的上下文,避免多个 helper 重复传递同一组委托和消息元数据。 + /// + /// 迁移数据类型。 + /// 迁移描述类型。 + private readonly record struct MigrationExecutionContext( + Func GetVersion, + Func GetToVersion, + Func ApplyMigration, + string SubjectName, + string MigrationKind) + where TData : class; + /// /// 校验迁移注册是否表示一次有效的前向升级。 /// @@ -99,21 +112,24 @@ internal static class VersionedMigrationRunner return data; } + var context = new MigrationExecutionContext( + getVersion, + getToVersion, + applyMigration, + subjectName, + migrationKind); + var current = data; while (currentVersion < targetVersion) { - var migration = GetRequiredMigration(resolveMigration, currentVersion, subjectName, migrationKind); + var migration = GetRequiredMigration(resolveMigration, currentVersion, in context); var result = ApplyMigrationStep( migration, current, currentVersion, targetVersion, - getVersion, - getToVersion, - applyMigration, - subjectName, - migrationKind); + in context); current = result.Data; currentVersion = result.Version; } @@ -140,24 +156,24 @@ internal static class VersionedMigrationRunner /// /// 解析当前版本必须存在的下一步迁移器,避免在调用循环中重复拼接相同错误。 /// + /// 迁移数据类型。 /// 迁移描述类型。 /// 迁移解析委托。 /// 当前版本。 - /// 迁移主体名称。 - /// 迁移类别名称。 + /// 本轮迁移链共享的执行上下文。 /// 已解析的迁移器。 /// 缺少迁移器时抛出。 - private static TMigration GetRequiredMigration( + private static TMigration GetRequiredMigration( Func resolveMigration, int currentVersion, - string subjectName, - string migrationKind) + in MigrationExecutionContext context) + where TData : class { var migration = resolveMigration(currentVersion); if (migration is null) { throw new InvalidOperationException( - $"No {migrationKind} is registered for {subjectName} from version {currentVersion}."); + $"No {context.MigrationKind} is registered for {context.SubjectName} from version {currentVersion}."); } return migration; @@ -172,11 +188,7 @@ internal static class VersionedMigrationRunner /// 迁移前数据。 /// 迁移前版本。 /// 运行时目标版本。 - /// 数据版本读取委托。 - /// 迁移器目标版本读取委托。 - /// 迁移执行委托。 - /// 迁移主体名称。 - /// 迁移类别名称。 + /// 本轮迁移链共享的执行上下文。 /// 迁移后的数据与新版本号。 /// /// 迁移结果为空、声明目标版本不匹配、版本未前进或超出运行时版本时抛出。 @@ -186,64 +198,60 @@ internal static class VersionedMigrationRunner TData current, int currentVersion, int targetVersion, - Func getVersion, - Func getToVersion, - Func applyMigration, - string subjectName, - string migrationKind) + in MigrationExecutionContext context) where TData : class { - var migratedData = applyMigration(migration, current) + var migratedData = context.ApplyMigration(migration, current) ?? throw new InvalidOperationException( - $"{migrationKind} for {subjectName} from version {currentVersion} returned null."); - var migratedVersion = getVersion(migratedData); + $"{context.MigrationKind} for {context.SubjectName} from version {currentVersion} returned null."); + var migratedVersion = context.GetVersion(migratedData); ValidateMigrationResult( currentVersion, targetVersion, migratedVersion, - getToVersion(migration), - subjectName, - migrationKind); + context.GetToVersion(migration), + in context); return (migratedData, migratedVersion); } /// /// 校验单步迁移结果与声明目标版本一致,并确保版本严格单调递增且不越过运行时版本。 /// + /// 迁移数据类型。 + /// 迁移描述类型。 /// 迁移前版本。 /// 运行时目标版本。 /// 迁移后实际版本。 /// 迁移器声明的目标版本。 - /// 迁移主体名称。 - /// 迁移类别名称。 + /// 本轮迁移链共享的执行上下文。 /// /// 声明目标版本不匹配、版本未前进或超出运行时版本时抛出。 /// - private static void ValidateMigrationResult( + private static void ValidateMigrationResult( int currentVersion, int targetVersion, int migratedVersion, int declaredTargetVersion, - string subjectName, - string migrationKind) + in MigrationExecutionContext context) + where TData : class { if (declaredTargetVersion != migratedVersion) { throw new InvalidOperationException( - $"{migrationKind} for {subjectName} declared target version {declaredTargetVersion} " + + $"{context.MigrationKind} for {context.SubjectName} declared target version {declaredTargetVersion} " + $"but returned version {migratedVersion}."); } if (migratedVersion <= currentVersion) { throw new InvalidOperationException( - $"{migrationKind} for {subjectName} must advance beyond version {currentVersion}."); + $"{context.MigrationKind} for {context.SubjectName} must advance beyond version {currentVersion}."); } if (migratedVersion > targetVersion) { throw new InvalidOperationException( - $"{migrationKind} for {subjectName} produced version {migratedVersion}, " + + $"{context.MigrationKind} for {context.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 ce1813ea..4486dcc9 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,14 +6,14 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-069` -- 当前阶段:`Phase 69` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-070` +- 当前阶段:`Phase 70` - 当前焦点: - - `2026-04-25` 主线程已提交 `58ba6c0` `test(cqrs-tests): 收敛处理器注册缓存测试 warning` - - 当前并行双文件批次聚焦 `GFramework.Cqrs.Tests/Logging/TestLogger.cs` 与 `GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs` - - 主线程收敛 `TestLogger.Logs` 的集合抽象暴露问题,worker 则在 `MediatorAdvancedFeaturesTests.cs` 内收敛一组低风险 `MA0016` - - 提权后的直接仓库根基线已从 `645 Warning(s)` 降至 `640 Warning(s)`,说明本轮双文件 `Cqrs.Tests` 批次继续有效 - - `GFramework.Cqrs.Tests` 的直接受影响 `Release` build 当前为 `0 Warning(s)`、`0 Error(s)`,branch diff 仍显著低于 `$gframework-batch-boot 50` 阈值 + - `2026-04-25` 主线程按 `$gframework-pr-review` 复核当前分支 PR `#291` 的 latest-head AI review threads、nitpick 与 MegaLinter 信号 + - 当前批次只吸收本地仍成立且修复成本明确的 3 项:`AGENTS.md` 英文标点一致性、`MediatorAdvancedFeaturesTests.cs` 中未使用的 `TestLoggingBehavior`、`VersionedMigrationRunner.cs` 的迁移上下文参数对象化 + - `dotnet clean` + `dotnet build` 的直接仓库根基线已从 `640 Warning(s)` 降至 `639 Warning(s)`,说明本轮 PR review follow-up 继续有效 + - `GFramework.Game` 的直接受影响 `Release` build 当前为 `326 Warning(s)`、`0 Error(s)`;`GFramework.Cqrs.Tests` 为 `149 Warning(s)`、`0 Error(s)` + - CodeRabbit 提到的 `TestLogger` 重复实现与 `YamlConfigLoaderTests.cs` 常量位置仅属于可选整理,本轮未纳入修复写集 ## 当前活跃事实 @@ -22,7 +22,7 @@ - `dotnet clean` - 结果:成功;此前沙箱内 “Build FAILED but 0 errors” 的 clean 结果不是仓库真值 - `dotnet build` - - 最新结果:成功;`640 Warning(s)`、`0 Error(s)` + - 最新结果:成功;`639 Warning(s)`、`0 Error(s)` - 已提交的低风险批次文件: - `AGENTS.md` - `GFramework.Core.Tests/Logging/LogContextTests.cs` @@ -39,8 +39,10 @@ - `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md` - `ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md` - 当前批次验证结果: + - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` + - 最新主线程结果:成功;`326 Warning(s)`、`0 Error(s)` - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` - - 最新主线程结果:成功;`0 Warning(s)`、`0 Error(s)` + - 最新主线程结果:成功;`149 Warning(s)`、`0 Error(s)` - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - 上一轮主线程结果:成功;`0 Warning(s)`、`0 Error(s)` @@ -70,14 +72,16 @@ - `dotnet clean` - 当前结果:成功;在提权后的直接 shell 中可正常完成仓库根 clean - `dotnet build` - - 当前结果:成功;`640 Warning(s)`、`0 Error(s)` + - 当前结果:成功;`639 Warning(s)`、`0 Error(s)` +- `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` + - 当前结果:成功;`326 Warning(s)`、`0 Error(s)` - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` - - 当前结果:成功;`0 Warning(s)`、`0 Error(s)` + - 当前结果:成功;`149 Warning(s)`、`0 Error(s)` - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - 当前结果:成功;`0 Warning(s)`、`0 Error(s)` ## 下一步建议 -1. 以当前 `640 Warning(s)` 根基线为新恢复点,继续按 `$gframework-batch-boot 50` 规则重算 branch diff,并挑选下一个 1-3 文件的低风险热点。 -2. 下一轮优先从 `GFramework.Cqrs.Tests`、`GFramework.Core.Tests` 或 `GFramework.Game` 中继续选择单文件 `MA0051`、`MA0016` 或测试噪音切片,避免过早推高 review 范围。 +1. 以当前 `639 Warning(s)` 根基线为新恢复点,继续按 `$gframework-batch-boot 50` 规则重算 branch diff,并挑选下一个 1-3 文件的低风险热点。 +2. 下一轮优先从 `GFramework.Game` 或 `GFramework.Cqrs.Tests` 中继续选择单文件 `MA0051`、`MA0016` 或 review 新暴露的低风险 warning 切片,避免把“可选整理”与 warning 收敛混成大改。 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 1dc87ea8..8332b6ba 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,34 @@ # Analyzer Warning Reduction 追踪 +## 2026-04-25 — RP-070 + +### 阶段:按 PR #291 latest-head review 收口仍有效的小批次,并刷新新的仓库根基线 + +- 触发背景: + - 用户显式要求执行 `$gframework-pr-review`,当前分支对应 PR `#291` + - 抓取结果显示 latest-head 只有 1 条未解决 review thread 指向 `AGENTS.md` 英文标点不一致;同时最新 CodeRabbit review body 还包含 `VersionedMigrationRunner.cs` 参数过多与 `MediatorAdvancedFeaturesTests.cs` 未使用测试基础设施这两条本地仍成立的建议 + - MegaLinter 仅报出 `dotnet-format` restore 失败,test report 为 `2156 passed / 0 failed`,因此本轮重点改为“只吸收仍有效且低风险的 review 建议” +- 主线程实施: + - 将 `AGENTS.md` 中英文规则段的 `dotnet clean` / `dotnet build` / `dotnet test` 列表标点改为英文逗号,直接消化 latest-head open thread + - 删除 `GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs` 中未被任何测试引用的 `TestLoggingBehavior` 静态类型,移除无收益的可变测试基础设施 + - 在 `GFramework.Game/Internal/VersionedMigrationRunner.cs` 内引入私有 `MigrationExecutionContext`,把多处 helper 共享的不变迁移上下文收口为参数对象,并同步补齐新增泛型 helper 的 XML 文档 + - 明确拒绝把 `TestLogger` 重复实现与 `YamlConfigLoaderTests.cs` 常量位置这类“可选整理”混入本轮 warning 收敛批次 +- 验证里程碑: + - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` + - 结果:成功;确认 PR `#291` latest-head open review threads 为 `1`,MegaLinter 仅有 `dotnet-format` restore 失败,tests 为 `2156 passed` + - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` + - 结果:成功;`326 Warning(s)`、`0 Error(s)` + - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` + - 结果:成功;`149 Warning(s)`、`0 Error(s)` + - `dotnet clean` + - 结果:成功 + - `dotnet build` + - 结果:成功;`639 Warning(s)`、`0 Error(s)`,相较 `RP-069` 的 `640` 再下降 `1` +- 当前结论: + - PR #291 当前最有价值的 review follow-up 已被主线程吸收,且没有把“可选整理”误当成必须修复项 + - 当前仓库根 warning 基线继续下降到 `639`,说明这轮 review 驱动的小批次仍符合 analyzer warning reduction 主题 + - 下一轮可继续围绕 `GFramework.Game` 或 `GFramework.Cqrs.Tests` 选择新的单文件低风险热点,或在新 head 推送后重新抓取 PR review 判断是否还有剩余有效线程 + ## 2026-04-25 — RP-069 ### 阶段:继续收口 Cqrs.Tests 双文件集合抽象 warning,并刷新新的仓库根基线 From 67675a02f70421ca0c10dedaa5d632b325e75410 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 25 Apr 2026 17:24:24 +0800 Subject: [PATCH 09/12] =?UTF-8?q?chore(git):=20=E6=B7=BB=E5=8A=A0=20.codex?= =?UTF-8?q?=20=E5=88=B0=20git=20=E5=BF=BD=E7=95=A5=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 .gitignore 文件中添加 .codex 条目 - 防止 .codex 目录被意外提交到版本控制系统 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5f35f8bd..01581041 100644 --- a/.gitignore +++ b/.gitignore @@ -23,5 +23,6 @@ ai-plan/public/* !ai-plan/public/**/*.md ai-plan/private/ ai-libs/ +.codex # tool .venv/ From 1b199e9f175d1cbcc4a62bf01d98eab3cca2870b Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 25 Apr 2026 20:01:07 +0800 Subject: [PATCH 10/12] =?UTF-8?q?fix(ai-plan):=20=E5=90=8C=E6=AD=A5=20PR29?= =?UTF-8?q?1=20=E6=B4=BB=E8=B7=83=E6=81=A2=E5=A4=8D=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新 active todo 到 RP-071 并同步 .codex / .gitignore 当前真值\n- 补充 PR #291 latest-head review 复核结果与本轮完成校验记录\n- 保留 non-blocking nitpick 作为后续独立文档收口项 --- .../analyzer-warning-reduction-tracking.md | 32 ++++++++++--------- .../analyzer-warning-reduction-trace.md | 22 +++++++++++++ 2 files changed, 39 insertions(+), 15 deletions(-) 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 4486dcc9..d416af8e 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,14 +6,13 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-070` -- 当前阶段:`Phase 70` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-071` +- 当前阶段:`Phase 71` - 当前焦点: - - `2026-04-25` 主线程按 `$gframework-pr-review` 复核当前分支 PR `#291` 的 latest-head AI review threads、nitpick 与 MegaLinter 信号 - - 当前批次只吸收本地仍成立且修复成本明确的 3 项:`AGENTS.md` 英文标点一致性、`MediatorAdvancedFeaturesTests.cs` 中未使用的 `TestLoggingBehavior`、`VersionedMigrationRunner.cs` 的迁移上下文参数对象化 - - `dotnet clean` + `dotnet build` 的直接仓库根基线已从 `640 Warning(s)` 降至 `639 Warning(s)`,说明本轮 PR review follow-up 继续有效 - - `GFramework.Game` 的直接受影响 `Release` build 当前为 `326 Warning(s)`、`0 Error(s)`;`GFramework.Cqrs.Tests` 为 `149 Warning(s)`、`0 Error(s)` - - CodeRabbit 提到的 `TestLogger` 重复实现与 `YamlConfigLoaderTests.cs` 常量位置仅属于可选整理,本轮未纳入修复写集 + - `2026-04-25` 主线程再次按 `$gframework-pr-review` 复核当前分支 PR `#291`,确认 latest-head 仅剩 1 条 open review thread,指向 active todo 中已过时的 `.codex` 风险描述 + - 当前批次只同步 active todo/trace 到 `chore(git)` 之后的新真值:`.codex` 已被 `.gitignore` 排除,`.gitignore` 也应进入“已提交的低风险批次文件”清单 + - `dotnet clean` + `dotnet build` 的直接仓库根基线仍为 `639 Warning(s)`、`0 Error(s)`,因此本轮属于文档真值收口,而不是新的 warning 清理批次 + - CodeRabbit 剩余的 `VersionedMigrationRunner.cs` 上下文一致性建议与 active trace 归档建议仍属 non-blocking nitpick,本轮不扩大写集去吸收可选整理 ## 当前活跃事实 @@ -25,6 +24,7 @@ - 最新结果:成功;`639 Warning(s)`、`0 Error(s)` - 已提交的低风险批次文件: - `AGENTS.md` + - `.gitignore` - `GFramework.Core.Tests/Logging/LogContextTests.cs` - `GFramework.Core.Tests/Logging/LoggerTests.cs` - `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs` @@ -39,6 +39,10 @@ - `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md` - `ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md` - 当前批次验证结果: + - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` + - 最新主线程结果:成功;确认 PR `#291` latest-head open review threads 为 `1`,唯一仍成立项为 active todo 中过时的 `.codex` 风险描述 + - `dotnet build` + - 最新主线程结果:成功;`0 Warning(s)`、`0 Error(s)`;该次为增量 Debug 构建,只作为完成校验,warning 权威基线仍以 `dotnet clean` 后的 `639 Warning(s)` 为准 - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` - 最新主线程结果:成功;`326 Warning(s)`、`0 Error(s)` - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` @@ -48,10 +52,8 @@ ## 当前风险 -- active `ai-plan` 之外的历史归档仍保留一部分沙箱内 workaround / 假阻塞记录。 - - 缓解措施:active todo/trace 已刷新为新真值;历史归档保留为时间线,不再作为默认恢复入口。 -- 当前 worktree 仍存在未跟踪的 `.codex` 目录。 - - 缓解措施:提交时只暂存 analyzer-warning-reduction 相关源码与 `ai-plan` / `AGENTS.md` 变更。 +- active `ai-plan` 之外的历史归档仍保留一部分沙箱内 workaround / 假阻塞记录,且 active trace 中 RP-062 ~ RP-064 的详细历史尚未进一步归档。 + - 缓解措施:本轮已把 `.codex` 风险从 active todo 中收口;后续如单独处理 trace 轻量化,可把该 nitpick 作为独立文档提交。 - `GFramework.Core`、`GFramework.Game`、`GFramework.Core.Tests`、`GFramework.Cqrs.Tests` 仍有较大 warning 基线。 - 缓解措施:后续批次继续优先挑低风险、少文件、可独立验证的测试与局部逻辑切片。 @@ -72,7 +74,7 @@ - `dotnet clean` - 当前结果:成功;在提权后的直接 shell 中可正常完成仓库根 clean - `dotnet build` - - 当前结果:成功;`639 Warning(s)`、`0 Error(s)` + - 当前结果:成功;最近一次增量 Debug 构建为 `0 Warning(s)`、`0 Error(s)`,但 warning 权威基线仍以提权后的 `dotnet clean` + `dotnet build` 结果 `639 Warning(s)`、`0 Error(s)` 为准 - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` - 当前结果:成功;`326 Warning(s)`、`0 Error(s)` - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` @@ -82,6 +84,6 @@ ## 下一步建议 -1. 以当前 `639 Warning(s)` 根基线为新恢复点,继续按 `$gframework-batch-boot 50` 规则重算 branch diff,并挑选下一个 1-3 文件的低风险热点。 -2. 下一轮优先从 `GFramework.Game` 或 `GFramework.Cqrs.Tests` 中继续选择单文件 `MA0051`、`MA0016` 或 review 新暴露的低风险 warning 切片,避免把“可选整理”与 warning 收敛混成大改。 -3. 后续凡是沙箱内 `.NET` 验证再次出现无诊断失败、pipe/socket 权限问题或与普通 shell 不一致的结果,直接申请沙箱外重跑同一命令,不再扩散 workaround 型命令噪音。 +1. 推送包含本轮 active todo/trace 同步的提交后,重新执行 `$gframework-pr-review`,确认 PR `#291` 的最后一条 latest-head open thread 是否已自动收口。 +2. 若 PR `#291` 仍只剩 nitpick,继续以当前 `639 Warning(s)` 根基线为恢复点,按 `$gframework-batch-boot 50` 规则挑选下一个 1-3 文件的低风险热点。 +3. 后续如需处理文档 nitpick,优先把 active trace 中 RP-062 ~ RP-064 的详细历史归档出默认恢复入口,而不是与 warning 收敛批次混做。 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 8332b6ba..2f7a6940 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,27 @@ # Analyzer Warning Reduction 追踪 +## 2026-04-25 — RP-071 + +### 阶段:同步 PR #291 latest-head 对 active todo 的唯一剩余线程 + +- 触发背景: + - 用户再次显式要求执行 `$gframework-pr-review`,当前分支仍对应 PR `#291` + - 最新抓取结果显示 latest-head open review thread 只剩 `1` 条,且不再指向源码 warning,而是指向 `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md` 中已过时的 `.codex` 风险描述 + - `.gitignore` 已在当前分支的 `chore(git)` 提交中加入 `.codex`,因此 active todo 若继续保留“当前 worktree 仍存在未跟踪的 `.codex` 目录”会与当前 head 真值冲突 +- 主线程实施: + - 重新运行 PR review 抓取脚本,确认 PR `#291` 仍为 `OPEN`,且 latest-head 唯一 open thread 是 CodeRabbit 针对 active todo 的文档同步建议 + - 更新 active todo 恢复点为 `RP-071`,将 `.gitignore` 纳入“已提交的低风险批次文件”,并移除已过时的 `.codex` 活跃风险描述 + - 在 active todo 中明确保留当前仍未采纳的两条 non-blocking nitpick:`VersionedMigrationRunner.cs` 的上下文一致性建议,以及 active trace 归档 RP-062 ~ RP-064 的建议 +- 验证里程碑: + - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` + - 结果:成功;确认 PR `#291` latest-head open review threads 为 `1`,唯一路径为 `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md:54` + - `dotnet build` + - 结果:成功;`0 Warning(s)`、`0 Error(s)`;该次为增量 Debug 构建,只作为本轮文档同步的完成校验,warning 权威基线仍保持 `RP-070` 记录的 `639 Warning(s)` +- 当前结论: + - 当前 PR `#291` 唯一仍成立的 latest-head thread 已被本地文档同步吸收,后续只需在新 head 推送后复核 GitHub 状态 + - 剩余 CodeRabbit nitpick 仍是可选整理项,本轮保持 analyzer-warning-reduction 的小写集策略,不把它们混入当前提交 + - 下一轮默认先推送并重新抓取 PR review;若 open thread 清零,则继续回到 warning 热点选择 + ## 2026-04-25 — RP-070 ### 阶段:按 PR #291 latest-head review 收口仍有效的小批次,并刷新新的仓库根基线 From c39cb5c9dc41b457eb1322f3d63242375cb6c183 Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 25 Apr 2026 22:07:12 +0800 Subject: [PATCH 11/12] =?UTF-8?q?docs(ai-plan):=20=E6=94=B6=E5=8F=A3=20PR2?= =?UTF-8?q?91=20=E5=89=A9=E4=BD=99=E6=96=87=E6=A1=A3=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 归档 RP-062 至 RP-071 的 active trace 详细记录并缩短默认恢复入口 - 更新 analyzer warning tracking 文档的验证真值维护位置并同步最新 PR review 状态 --- ...r-warning-reduction-history-rp062-rp071.md | 321 ++++++++++++++++++ .../analyzer-warning-reduction-tracking.md | 39 +-- .../analyzer-warning-reduction-trace.md | 312 +---------------- 3 files changed, 351 insertions(+), 321 deletions(-) create mode 100644 ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp062-rp071.md diff --git a/ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp062-rp071.md b/ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp062-rp071.md new file mode 100644 index 00000000..06308a1e --- /dev/null +++ b/ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp062-rp071.md @@ -0,0 +1,321 @@ +# Analyzer Warning Reduction 追踪历史(RP-062 至 RP-071) + +## 范围说明 + +本归档承接 `RP-062` 至 `RP-071` 的 active trace 明细,保留 active 入口在 `RP-072` 压缩前的执行背景、验证里程碑与 PR review 跟进记录。 + +## superseded by + +- [analyzer-warning-reduction-trace.md](../../traces/analyzer-warning-reduction-trace.md) + +--- + +# Analyzer Warning Reduction 追踪 + +## 2026-04-25 — RP-071 + +### 阶段:同步 PR #291 latest-head 对 active todo 的唯一剩余线程 + +- 触发背景: + - 用户再次显式要求执行 `$gframework-pr-review`,当前分支仍对应 PR `#291` + - 最新抓取结果显示 latest-head open review thread 只剩 `1` 条,且不再指向源码 warning,而是指向 `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md` 中已过时的 `.codex` 风险描述 + - `.gitignore` 已在当前分支的 `chore(git)` 提交中加入 `.codex`,因此 active todo 若继续保留“当前 worktree 仍存在未跟踪的 `.codex` 目录”会与当前 head 真值冲突 +- 主线程实施: + - 重新运行 PR review 抓取脚本,确认 PR `#291` 仍为 `OPEN`,且 latest-head 唯一 open thread 是 CodeRabbit 针对 active todo 的文档同步建议 + - 更新 active todo 恢复点为 `RP-071`,将 `.gitignore` 纳入“已提交的低风险批次文件”,并移除已过时的 `.codex` 活跃风险描述 + - 在 active todo 中明确保留当前仍未采纳的两条 non-blocking nitpick:`VersionedMigrationRunner.cs` 的上下文一致性建议,以及 active trace 归档 RP-062 ~ RP-064 的建议 +- 验证里程碑: + - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` + - 结果:成功;确认 PR `#291` latest-head open review threads 为 `1`,唯一路径为 `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md:54` + - `dotnet build` + - 结果:成功;`0 Warning(s)`、`0 Error(s)`;该次为增量 Debug 构建,只作为本轮文档同步的完成校验,warning 权威基线仍保持 `RP-070` 记录的 `639 Warning(s)` +- 当前结论: + - 当前 PR `#291` 唯一仍成立的 latest-head thread 已被本地文档同步吸收,后续只需在新 head 推送后复核 GitHub 状态 + - 剩余 CodeRabbit nitpick 仍是可选整理项,本轮保持 analyzer-warning-reduction 的小写集策略,不把它们混入当前提交 + - 下一轮默认先推送并重新抓取 PR review;若 open thread 清零,则继续回到 warning 热点选择 + +## 2026-04-25 — RP-070 + +### 阶段:按 PR #291 latest-head review 收口仍有效的小批次,并刷新新的仓库根基线 + +- 触发背景: + - 用户显式要求执行 `$gframework-pr-review`,当前分支对应 PR `#291` + - 抓取结果显示 latest-head 只有 1 条未解决 review thread 指向 `AGENTS.md` 英文标点不一致;同时最新 CodeRabbit review body 还包含 `VersionedMigrationRunner.cs` 参数过多与 `MediatorAdvancedFeaturesTests.cs` 未使用测试基础设施这两条本地仍成立的建议 + - MegaLinter 仅报出 `dotnet-format` restore 失败,test report 为 `2156 passed / 0 failed`,因此本轮重点改为“只吸收仍有效且低风险的 review 建议” +- 主线程实施: + - 将 `AGENTS.md` 中英文规则段的 `dotnet clean` / `dotnet build` / `dotnet test` 列表标点改为英文逗号,直接消化 latest-head open thread + - 删除 `GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs` 中未被任何测试引用的 `TestLoggingBehavior` 静态类型,移除无收益的可变测试基础设施 + - 在 `GFramework.Game/Internal/VersionedMigrationRunner.cs` 内引入私有 `MigrationExecutionContext`,把多处 helper 共享的不变迁移上下文收口为参数对象,并同步补齐新增泛型 helper 的 XML 文档 + - 明确拒绝把 `TestLogger` 重复实现与 `YamlConfigLoaderTests.cs` 常量位置这类“可选整理”混入本轮 warning 收敛批次 +- 验证里程碑: + - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` + - 结果:成功;确认 PR `#291` latest-head open review threads 为 `1`,MegaLinter 仅有 `dotnet-format` restore 失败,tests 为 `2156 passed` + - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` + - 结果:成功;`326 Warning(s)`、`0 Error(s)` + - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` + - 结果:成功;`149 Warning(s)`、`0 Error(s)` + - `dotnet clean` + - 结果:成功 + - `dotnet build` + - 结果:成功;`639 Warning(s)`、`0 Error(s)`,相较 `RP-069` 的 `640` 再下降 `1` +- 当前结论: + - PR #291 当前最有价值的 review follow-up 已被主线程吸收,且没有把“可选整理”误当成必须修复项 + - 当前仓库根 warning 基线继续下降到 `639`,说明这轮 review 驱动的小批次仍符合 analyzer warning reduction 主题 + - 下一轮可继续围绕 `GFramework.Game` 或 `GFramework.Cqrs.Tests` 选择新的单文件低风险热点,或在新 head 推送后重新抓取 PR review 判断是否还有剩余有效线程 + +## 2026-04-25 — RP-069 + +### 阶段:继续收口 Cqrs.Tests 双文件集合抽象 warning,并刷新新的仓库根基线 + +- 触发背景: + - `RP-068` 收尾后,当前分支的仓库根基线已降到 `645 Warning(s)`,branch diff 仍远低于 `$gframework-batch-boot 50` + - 为保持批次小而连续,主线程继续留在 `GFramework.Cqrs.Tests` 项目内,选取两个不涉及跨文件重构的 `MA0016` 切片 +- 接受的委派范围: + - worker `Chandrasekhar` + - 文件:`GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs` + - 目标:在同一文件内收敛 `TestLoggingBehavior.LoggedMessages`、`SagaData`、`TestDatabaseRequest` 的集合抽象暴露问题 + - 结果:未自行提交;主线程接受其工作树改动并纳入本轮批次 +- 主线程实施: + - 本地修改 `GFramework.Cqrs.Tests/Logging/TestLogger.cs` + - 将 `Logs` 从 `List` 收口为 `IReadOnlyList`,保留私有 `_logs` 作为内部存储 + - 与 worker 的 `MediatorAdvancedFeaturesTests.cs` 改动合并后,重新执行 `GFramework.Cqrs.Tests` 与仓库根验证,确认双文件批次的净效果 +- 验证里程碑: + - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` + - 结果:成功;`0 Warning(s)`、`0 Error(s)` + - `dotnet clean` + - 结果:成功 + - `dotnet build` + - 结果:成功;`640 Warning(s)`、`0 Error(s)`,相较 `RP-068` 的 `645` 再下降 `5` +- 当前结论: + - `Cqrs.Tests` 双文件批次已确认有效,并继续压低仓库根 warning 基线 + - 当前分支距离 `$gframework-batch-boot 50` 的停止阈值仍有很大空间,可以继续按“主线程小切片 + subagent 并行单文件”推进 + - 下一轮可优先回到 `GFramework.Core.Tests` 或继续选择新的 `GFramework.Cqrs.Tests` 单文件热点 + +## 2026-04-25 — RP-068 + +### 阶段:吸收并行 subagent 小批次,并继续压低仓库根 warning 基线 + +- 触发背景: + - `RP-067` 收尾后,当前分支的仓库根基线已降到 `649 Warning(s)`,branch diff 仅 `9 files` + - 用户明确允许主线程与 subagent 在不冲突的写集上并行推进,因此本轮继续按 `$gframework-batch-boot 50` 规则拆成 3 个单文件切片 +- 接受的委派范围: + - worker `Averroes` + - 文件:`GFramework.Core.Tests/Logging/LogContextTests.cs` + - 目标:收敛 `Push_InAsyncContext_ShouldIsolateAcrossThreads()` 内的 `MA0004` + - 结果:提交 `a7fa70e` `fix(core-tests): 清理 LogContextTests 异步等待 warning` + - worker `Laplace` + - 文件:`GFramework.Core.Tests/Logging/LoggerTests.cs` + - 目标:把 `TestLogger.Logs` 从 `List` 收口为集合抽象以修复 `MA0016` + - 结果:提交 `9f6204d` `fix(core-tests): 收口 LoggerTests 日志集合抽象` +- 主线程实施: + - 本地重构 `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs` + - 将 `RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers()` 中的 mock 装配、handler 类型读取、预期集合断言与 metadata lookup verify 拆分为具名 helper + - 在吸收两个 worker 提交后,主线程重新执行直接受影响模块与仓库根验证,确保并行切片合并后的真值一致 +- 验证里程碑: + - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` + - 结果:成功;`155 Warning(s)`、`0 Error(s)` + - `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CqrsHandlerRegistrarTests.RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers"` + - 结果:成功;`Passed 1/1` + - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` + - 结果:成功;`0 Warning(s)`、`0 Error(s)` + - `dotnet clean` + - 结果:成功 + - `dotnet build` + - 结果:成功;`645 Warning(s)`、`0 Error(s)`,相较 `RP-067` 的 `649` 再下降 `4` +- 当前结论: + - 并行 3 文件批次已确认有效,且主线程已把 subagent 的负责范围和验证结果收口进 active trace + - 当前分支距离 `$gframework-batch-boot 50` 的停止阈值仍有充足空间,可以继续用“主线程验证 + subagent 并行单文件切片”的节奏推进 + - 下一轮可优先回到 `GFramework.Cqrs.Tests` 或 `GFramework.Game` 的单文件 `MA0051` / `MA0016` 热点 + +## 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 基线 + +- 触发背景: + - `RP-065` 收尾后,`fix/analyzer-warning-reduction-batch` 已通过 `6a704f3` 把 AGENTS / active ai-plan 真值修正和 4 文件测试噪音批次提交到分支 + - 原先负责 `YamlConfigLoaderTests.cs` 的 worker 长时间无结果,主线程收回该单文件批次以避免继续阻塞 +- 主线程实施: + - 关闭停滞 worker,直接重构 `GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs` + - 通过提取固定夹具内容、热重载接线 helper 与共享断言,收敛以下 4 个长方法 warning: + - `EnableHotReload_Should_Keep_Previous_State_When_Contains_Reference_Dependency_Breaks` + - `EnableHotReload_Should_Support_Options_Object` + - `EnableHotReload_Should_Keep_Previous_Table_When_Schema_Change_Makes_Reload_Fail` + - `EnableHotReload_Should_Keep_Previous_State_When_Dependency_Table_Breaks_Cross_Table_Reference` + - 在第一次仓库根重建中命中了两个 `CS0411` 泛型推断错误,主线程随即补上显式类型参数并重新建立 clean/build 基线 +- 验证里程碑: + - `dotnet clean` + - 结果:成功 + - `dotnet build` + - 结果:成功;`652 Warning(s)`、`0 Error(s)`,相较 `RP-065` 的 `656` 再下降 `4` + - `dotnet build GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release` + - 结果:成功;`0 Warning(s)`、`0 Error(s)` +- 当前结论: + - `YamlConfigLoaderTests.cs` 这 4 个根构建直接确认的 `MA0051` 已被消化 + - 当前分支在 `6a704f3` 之后的下一提交只会新增 1 个唯一文件,因此 branch diff 仍明显低于 `$gframework-batch-boot 50` 阈值 + - 下一轮可继续选择新的单文件或小写集热点,而不必暂停当前 batch loop + +## 2026-04-25 — RP-065 + +### 阶段:确认 .NET 验证噪音来自沙箱,并把无沙箱直跑写成仓库规则 + +- 触发背景: + - 用户明确指出“之前很多清理、构建、测试报错像是环境问题,需要申请权限在沙箱外执行”,并要求把该解决方案写入 `AGENTS.md` + - 主线程随后在同一 worktree 中对比了沙箱内与提权后直接 shell 的 `dotnet clean` / `dotnet build` +- 主线程实施: + - 在沙箱内直接运行 `dotnet clean` 时再次复现“Build FAILED but 0 errors”的无诊断噪音 + - 申请提权后重新执行同一条 `dotnet clean`,确认命令可正常完成,说明先前 clean 失败并非仓库真值 + - 在同一提权上下文直接执行 `dotnet build`,拿到当前仓库根权威基线:`656 Warning(s)`、`0 Error(s)` + - 关闭正在运行的 warning-reduction worker,把工作重心切到仓库治理与 active recovery 文档净化 + - 更新 `AGENTS.md`,新增规则:当沙箱内 `dotnet clean` / `dotnet build` / `dotnet test` 产生缺少诊断、权限错误或其他环境噪音时,必须申请沙箱外重跑同一条直接命令,并以该结果为准 + - 刷新 active todo/trace,把“环境阻塞”从默认恢复入口中降级为历史噪音,不再作为当前真值 +- 并行工作: + - worker 收敛了 4 个低风险测试噪音文件: + - `GFramework.Game.Tests/Config/GameConfigBootstrapTests.cs` + - `GFramework.Game.Tests/Config/GeneratedConfigConsumerIntegrationTests.cs` + - `GFramework.Game.Tests/Config/YamlConfigTextValidatorTests.cs` + - `GFramework.Ecs.Arch.Tests/Ecs/EcsAdvancedTests.cs` + - worker 验证: + - `dotnet build GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release` + - worker 初次结果:成功;随后主线程在同一提权环境复核后确认当前为 `0 Warning(s)`、`0 Error(s)` + - `dotnet build GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj -c Release` + - 主线程复核:成功;`0 Warning(s)`、`0 Error(s)` +- 当前结论: + - 本仓库当前在 agent 沙箱内执行 `.NET` 验证时,确实可能出现假失败或缺失诊断 + - 当前应把“提权后的直接 `dotnet` 命令输出”视为仓库真值,而不是继续围绕沙箱噪音扩展 workaround 命令形态 + - `fix/analyzer-warning-reduction-batch` 当前 `HEAD` 已与 `origin/main` 对齐;新的 `$gframework-batch-boot 50` 轮次从 `0 files / 0 lines` committed diff 开始 + - 下一轮低风险热点仍是 `GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs` 的 `4` 个 `MA0051` + +## 2026-04-25 — RP-064 + +### 阶段:按标准 WSL build 路径复核 PR #288 建议并完成本轮收口 + +- 触发背景: + - 用户指出“在 WSL 里直接执行 `dotnet build` 可以成功”,要求主线程按普通路径重新验证,而不是继续使用带 `MSBuildEnableWorkloadResolver=false`、`--no-restore`、手工 `TargetFramework` 的 workaround 命令 + - 当前任务仍属于 PR #288 review follow-up,因此本轮重点改为“区分哪些 AI 建议值得采纳”以及“用真实 WSL build 结果验证” +- 主线程实施: + - 重新抓取 PR #288 review,确认 latest-head open threads 为 `CodeRabbit 6 + Greptile 2` + - 复核 `outside diff + nitpick` 的 19 条建议,只采纳本地仍成立的建议;拒绝把“评论总数”机械等同于“必须全改” + - 完成以下高信号修复: + - `ContextAware*` / `AsyncExtensions` / `NumericExtensions` / `StringExtensions` / `StoreBuilder`:回退为 `ArgumentNullException.ThrowIfNull(...)` + - `ArchitectureServicesTests` / `GameContextTests`:同步 XML `` 到 `NotSupportedException` + - `RegistryInitializationHookBaseTests`:修复 override 可空签名实现,避免再次引入编译错误 + - `RollingFileAppenderTests` / `TaskCoroutineExtensionsTests` / `WaitForTaskTests` / `ScopedStorage`:移除无收益噪音代码 + - `FileStorage`:通过 `leaveOpen: true` 修正 `FileStream` 的双重释放语义 + - `SceneRouterBase`:统一显式 `ConfigureAwait(true)` 并补齐引擎线程亲和说明 + - `StoreSelection`:保留 `net9.0+` 的 `System.Threading.Lock`,同时修正条件编译旁的注释写法,避免 `CS1587` +- 验证里程碑: + - `dotnet restore GFramework.sln -p:RestoreFallbackFolders="" -v minimal` + - 结果:成功;证明先前 `MSB4018` 来自 stale restore 元数据,而不是当前 WSL 默认 build 路径本身不可用 + - `dotnet build GFramework.Core/GFramework.Core.csproj -c Release` + - 结果:成功;`28 Warning(s)`、`0 Error(s)` + - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` + - 结果:成功;`329 Warning(s)`、`0 Error(s)` + - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` + - 结果:成功;`137 Warning(s)`、`0 Error(s)` +- 当前结论: + - 用户关于“WSL 里直接 `dotnet build` 可行”的判断正确 + - 前一轮失败的核心原因不是仓库不可构建,而是主线程附加的 workaround 参数改变了 MSBuild 行为 + - 本轮已完成 PR #288 中一组仍成立的建议修复,并重新拿到标准 WSL 路径下的 Release build 验证 + - 剩余 review 线程需要在新 head 上重新抓取后再决定是否逐条 resolve + +## 2026-04-25 — RP-063 + +### 阶段:先收口 PR #288 latest-head 编译错误,再暂停在环境阻塞点并准备提交 + +- 触发背景: + - 用户显式要求先执行 `$gframework-pr-review`,并指出 `AsyncExtensionsTests.cs(126,23)` 当前存在 `CS0029` / `CS1662` 构建错误 + - 当前 worktree 仍是 `fix/analyzer-warning-reduction-batch`,因此本 turn 继续沿用 `analyzer-warning-reduction` 的 active recovery 文档 +- 主线程实施: + - 运行 PR review 抓取脚本,确认当前分支对应 PR `#288` + - 核对 latest-head unresolved review threads 后,优先修复 `AsyncExtensionsTests.cs` 中 `ct => Task.Delay(...).ConfigureAwait(false)` 错误返回 `ConfiguredTaskAwaitable` 的问题 + - 顺手收敛多处已被 latest review 点名且本地仍成立的低风险残留: + - 测试中的 `async` 无 `await` + - `ValueTask` 断言包装 + - `RegistryInitializationHookBaseTests.cs` 的可空返回签名 + - `NumericExtensions.cs`、`StringExtensions.cs`、`StoreBuilder.cs` 的 Allman 花括号残留 + - `StoreSelection.cs` 在 `net9.0+` 下切到 `System.Threading.Lock`,同时保留 `net8.0` 兼容分支 +- 验证里程碑: + - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` + - 结果:成功;确认 PR `#288` 的 latest-head unresolved AI review threads 共 `9` 个,其中 `AsyncExtensionsTests.cs:126` 为 critical 编译错误 + - `DOTNET_CLI_HOME=/tmp/dotnet-home MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net8.0 -p:RestoreFallbackFolders="" -v minimal` + - 结果:失败;`MSB4018`,`ResolvePackageAssets` 仍读取失效 Windows fallback package folder `D:\Tool\Development Tools\Microsoft Visual Studio\Shared\NuGetPackages` + - `DOTNET_CLI_HOME=/tmp/dotnet-home MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net9.0 -p:RestoreFallbackFolders="" -v minimal` + - 结果:失败;原因同上 + - `DOTNET_CLI_HOME=/tmp/dotnet-home MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-restore -p:TargetFramework=net10.0 -p:RestoreFallbackFolders="" -v minimal` + - 结果:失败;原因同上 +- 当前结论: + - 用户点名的 `AsyncExtensionsTests.cs` 编译错误已在源码层修复 + - 本 turn 未能拿到新的可通过 Release build,阻塞点已从先前记录的 `MSB4276` 收敛为当前 `obj/*.csproj.nuget.g.props` 中 stale Windows fallback package folder 导致的 `MSB4018` + - 用户随后要求“先不管这个了,先提交吧”,因此本 turn 在记录环境阻塞后先执行提交收口 + +## 2026-04-25 — RP-062 + +### 阶段:触达 `$gframework-batch-boot 75` 停止阈值并收口到 `75 files / 2098 lines` + +- 触发背景: + - `RP-061` 收尾时分支相对 `origin/main` 仍只有 `48` 个已提交文件,距离本轮 `75 files` 停止条件还有明显空间 + - 用户明确允许继续委派 subagent,因此主线程继续把低风险机械型写集拆成互不重叠的 test / runtime 小批次 + - 本轮主目标不是继续深挖单个高上下文热点,而是用新的低风险文件精确把 branch diff 推到阈值后停止 +- 主线程实施: + - 先接受并提交 7 文件 `Core.Tests` 收尾批次为 `03c73a8` `test(core-tests): 收敛测试桩与辅助类型 warning` + - 随后主线程与多个 worker 并行收口以下新增文件: + - `ArchitectureAdditionalCqrsHandlersTests.cs` + - `RegistryInitializationHookBaseTests.cs` + - `CommandCoroutineExtensionsTests.cs` + - `TaskCoroutineExtensionsTests.cs` + - `WaitForTaskTTests.cs` + - `AsyncExtensionsTests.cs` + - `LogContextTests.cs` + - `PauseStackManagerTests.cs` + - `AsyncExtensions.cs` + - `CollectionExtensions.cs` + - `ContextAwareCommandExtensions.cs` + - `ContextAwareEnvironmentExtensions.cs` + - `ContextAwareEventExtensions.cs` + - `ContextAwareQueryExtensions.cs` + - `ContextAwareServiceExtensions.cs` + - `GuardExtensions.cs` + - `NumericExtensions.cs` + - `StoreEventBusExtensions.cs` + - `StringExtensions.cs` + - `StoreBuilder.cs` + - `StoreSelection.cs` + - 将上述 22 文件批次收口为 `9ce1fa6` `refactor(core): 收敛 Core 扩展与测试的机械 warning` +- 验证里程碑: + - `dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net8.0 -p:RestoreFallbackFolders="" -v minimal` + - 结果:成功;`0 Warning(s)`、`0 Error(s)` + - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-incremental --no-restore -p:RestoreFallbackFolders= -v:diag` + - 结果:失败;`MSB4276`,默认 SDK resolver 缺少 `Microsoft.NET.SDK.WorkloadAutoImportPropsLocator` + - `dotnet restore GFramework.Core.Tests/GFramework.Core.Tests.csproj -p:TestTargetFrameworks=net8.0 -p:RestoreFallbackFolders="" -v minimal` + - 结果:失败;`NU1201`,`GFramework.Tests.Common` 仅支持 `net10.0`,不能作为 `Core.Tests` 的 net8 旁路验证 + - `git diff --name-only origin/main...HEAD | wc -l` + - 结果:`75` + - `git diff --numstat origin/main...HEAD` + - 结果:累计 `1083` added、`1015` deleted,即 `2098` changed lines +- 当前结论: + - 本轮 `$gframework-batch-boot 75` 已精确达到主停止条件,默认恢复点应停止在 `9ce1fa6` + - `Core` runtime 的本轮机械型改动已有可通过的最小 Release build 验证 + - `Core.Tests` 的继续推进当前首先受 `MSB4276` 环境阻塞影响;下一轮若要继续,应先修复构建环境,再重新建立 warning 基线 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 d416af8e..55b2c98f 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,13 +6,12 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-071` -- 当前阶段:`Phase 71` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-072` +- 当前阶段:`Phase 72` - 当前焦点: - - `2026-04-25` 主线程再次按 `$gframework-pr-review` 复核当前分支 PR `#291`,确认 latest-head 仅剩 1 条 open review thread,指向 active todo 中已过时的 `.codex` 风险描述 - - 当前批次只同步 active todo/trace 到 `chore(git)` 之后的新真值:`.codex` 已被 `.gitignore` 排除,`.gitignore` 也应进入“已提交的低风险批次文件”清单 + - `2026-04-25` 主线程再次按 `$gframework-pr-review` 复核当前分支 PR `#291`,确认 latest-head 仍剩 `1` 条 open review thread 与 `1` 条 nitpick,均指向 active `ai-plan` 文档 + - 当前批次只同步 active todo/trace 到最新 review 真值:压缩 active trace,并把重复维护的验证结果改回单一权威区块 - `dotnet clean` + `dotnet build` 的直接仓库根基线仍为 `639 Warning(s)`、`0 Error(s)`,因此本轮属于文档真值收口,而不是新的 warning 清理批次 - - CodeRabbit 剩余的 `VersionedMigrationRunner.cs` 上下文一致性建议与 active trace 归档建议仍属 non-blocking nitpick,本轮不扩大写集去吸收可选整理 ## 当前活跃事实 @@ -22,7 +21,7 @@ - 结果:成功;此前沙箱内 “Build FAILED but 0 errors” 的 clean 结果不是仓库真值 - `dotnet build` - 最新结果:成功;`639 Warning(s)`、`0 Error(s)` -- 已提交的低风险批次文件: +- 当前分支低风险批次文件: - `AGENTS.md` - `.gitignore` - `GFramework.Core.Tests/Logging/LogContextTests.cs` @@ -38,11 +37,12 @@ - `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` + - `ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp062-rp071.md` - 当前批次验证结果: - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` - - 最新主线程结果:成功;确认 PR `#291` latest-head open review threads 为 `1`,唯一仍成立项为 active todo 中过时的 `.codex` 风险描述 + - 最新主线程结果:成功;确认 PR `#291` latest-head open review thread 为 `1`、CodeRabbit nitpick 为 `1`,两者都指向 active `ai-plan` 文档入口 - `dotnet build` - - 最新主线程结果:成功;`0 Warning(s)`、`0 Error(s)`;该次为增量 Debug 构建,只作为完成校验,warning 权威基线仍以 `dotnet clean` 后的 `639 Warning(s)` 为准 + - 最新主线程结果:成功;`0 Warning(s)`、`0 Error(s)`;该次为增量 Debug 构建,只作为本轮文档同步完成校验,warning 权威基线仍以 `dotnet clean` 后的 `639 Warning(s)` 为准 - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` - 最新主线程结果:成功;`326 Warning(s)`、`0 Error(s)` - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` @@ -52,10 +52,10 @@ ## 当前风险 -- active `ai-plan` 之外的历史归档仍保留一部分沙箱内 workaround / 假阻塞记录,且 active trace 中 RP-062 ~ RP-064 的详细历史尚未进一步归档。 - - 缓解措施:本轮已把 `.codex` 风险从 active todo 中收口;后续如单独处理 trace 轻量化,可把该 nitpick 作为独立文档提交。 - `GFramework.Core`、`GFramework.Game`、`GFramework.Core.Tests`、`GFramework.Cqrs.Tests` 仍有较大 warning 基线。 - 缓解措施:后续批次继续优先挑低风险、少文件、可独立验证的测试与局部逻辑切片。 +- 当前 review 相关真值要等新 head 推送后才能在 GitHub UI 中自动收口。 + - 缓解措施:本轮提交后立即重新执行 `$gframework-pr-review`,确认 PR `#291` 的 latest-head thread 与 nitpick 是否消失。 ## 活跃文档 @@ -65,25 +65,18 @@ - [analyzer-warning-reduction-history-rp001.md](../archive/todos/analyzer-warning-reduction-history-rp001.md) - [analyzer-warning-reduction-history-rp002-rp041.md](../archive/todos/analyzer-warning-reduction-history-rp002-rp041.md) - 历史 trace 归档: + - [analyzer-warning-reduction-history-rp062-rp071.md](../archive/traces/analyzer-warning-reduction-history-rp062-rp071.md) - [analyzer-warning-reduction-history-rp001.md](../archive/traces/analyzer-warning-reduction-history-rp001.md) - [analyzer-warning-reduction-history-rp002-rp041.md](../archive/traces/analyzer-warning-reduction-history-rp002-rp041.md) - [analyzer-warning-reduction-history-rp042-rp048.md](../archive/traces/analyzer-warning-reduction-history-rp042-rp048.md) ## 验证说明 -- `dotnet clean` - - 当前结果:成功;在提权后的直接 shell 中可正常完成仓库根 clean -- `dotnet build` - - 当前结果:成功;最近一次增量 Debug 构建为 `0 Warning(s)`、`0 Error(s)`,但 warning 权威基线仍以提权后的 `dotnet clean` + `dotnet build` 结果 `639 Warning(s)`、`0 Error(s)` 为准 -- `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` - - 当前结果:成功;`326 Warning(s)`、`0 Error(s)` -- `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` - - 当前结果:成功;`149 Warning(s)`、`0 Error(s)` -- `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - - 当前结果:成功;`0 Warning(s)`、`0 Error(s)` +- 权威验证结果统一维护在“当前活跃事实”和“当前批次验证结果”。 +- 后续若刷新构建或 PR review 真值,只更新上述权威区块,不在本节重复抄录。 ## 下一步建议 -1. 推送包含本轮 active todo/trace 同步的提交后,重新执行 `$gframework-pr-review`,确认 PR `#291` 的最后一条 latest-head open thread 是否已自动收口。 -2. 若 PR `#291` 仍只剩 nitpick,继续以当前 `639 Warning(s)` 根基线为恢复点,按 `$gframework-batch-boot 50` 规则挑选下一个 1-3 文件的低风险热点。 -3. 后续如需处理文档 nitpick,优先把 active trace 中 RP-062 ~ RP-064 的详细历史归档出默认恢复入口,而不是与 warning 收敛批次混做。 +1. 推送包含本轮 active todo/trace 同步的提交后,重新执行 `$gframework-pr-review`,确认 PR `#291` 的 latest-head open thread 与 nitpick 是否已自动收口。 +2. 若 PR `#291` 已清零,继续以当前 `639 Warning(s)` 根基线为恢复点,按 `$gframework-batch-boot 50` 规则挑选下一个 1-3 文件的低风险热点。 +3. 若 GitHub 仍保留 review 信号,先确认它们是否指向新 head,再决定是否需要继续细化 active `ai-plan` 入口。 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 2f7a6940..22bcb5b5 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,315 +1,31 @@ # Analyzer Warning Reduction 追踪 -## 2026-04-25 — RP-071 +## 2026-04-25 — RP-072 -### 阶段:同步 PR #291 latest-head 对 active todo 的唯一剩余线程 +### 阶段:收口 PR #291 剩余的 active ai-plan 文档 review - 触发背景: - 用户再次显式要求执行 `$gframework-pr-review`,当前分支仍对应 PR `#291` - - 最新抓取结果显示 latest-head open review thread 只剩 `1` 条,且不再指向源码 warning,而是指向 `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md` 中已过时的 `.codex` 风险描述 - - `.gitignore` 已在当前分支的 `chore(git)` 提交中加入 `.codex`,因此 active todo 若继续保留“当前 worktree 仍存在未跟踪的 `.codex` 目录”会与当前 head 真值冲突 + - 最新抓取结果确认 latest-head 还剩 `1` 条 open review thread,指向 active trace 入口过长;同时 CodeRabbit 还有 `1` 条 nitpick,指向 active todo 中重复维护验证结果 + - 这两项问题都仍然成立,且都属于 active `ai-plan` 入口维护问题,不涉及新的源码 warning 修复 - 主线程实施: - - 重新运行 PR review 抓取脚本,确认 PR `#291` 仍为 `OPEN`,且 latest-head 唯一 open thread 是 CodeRabbit 针对 active todo 的文档同步建议 - - 更新 active todo 恢复点为 `RP-071`,将 `.gitignore` 纳入“已提交的低风险批次文件”,并移除已过时的 `.codex` 活跃风险描述 - - 在 active todo 中明确保留当前仍未采纳的两条 non-blocking nitpick:`VersionedMigrationRunner.cs` 的上下文一致性建议,以及 active trace 归档 RP-062 ~ RP-064 的建议 + - 将 `ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md` 压缩为只保留当前恢复点与归档指针 + - 将 `RP-062` 至 `RP-071` 的详细 trace 迁入 [analyzer-warning-reduction-history-rp062-rp071.md](../archive/traces/analyzer-warning-reduction-history-rp062-rp071.md) + - 同步更新 active todo,移除重复的验证结果抄录,改为只在权威区块维护构建与 PR review 真值 - 验证里程碑: - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` - - 结果:成功;确认 PR `#291` latest-head open review threads 为 `1`,唯一路径为 `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md:54` + - 结果:成功;确认 PR `#291` latest-head open review thread 为 `1`,CodeRabbit nitpick 为 `1`,两者都指向 active `ai-plan` 文档 - `dotnet build` - - 结果:成功;`0 Warning(s)`、`0 Error(s)`;该次为增量 Debug 构建,只作为本轮文档同步的完成校验,warning 权威基线仍保持 `RP-070` 记录的 `639 Warning(s)` + - 结果:成功;`0 Warning(s)`、`0 Error(s)`;该次为增量 Debug 构建,只作为本轮文档同步完成校验,warning 权威基线仍保持 `639 Warning(s)`、`0 Error(s)` - 当前结论: - - 当前 PR `#291` 唯一仍成立的 latest-head thread 已被本地文档同步吸收,后续只需在新 head 推送后复核 GitHub 状态 - - 剩余 CodeRabbit nitpick 仍是可选整理项,本轮保持 analyzer-warning-reduction 的小写集策略,不把它们混入当前提交 - - 下一轮默认先推送并重新抓取 PR review;若 open thread 清零,则继续回到 warning 热点选择 - -## 2026-04-25 — RP-070 - -### 阶段:按 PR #291 latest-head review 收口仍有效的小批次,并刷新新的仓库根基线 - -- 触发背景: - - 用户显式要求执行 `$gframework-pr-review`,当前分支对应 PR `#291` - - 抓取结果显示 latest-head 只有 1 条未解决 review thread 指向 `AGENTS.md` 英文标点不一致;同时最新 CodeRabbit review body 还包含 `VersionedMigrationRunner.cs` 参数过多与 `MediatorAdvancedFeaturesTests.cs` 未使用测试基础设施这两条本地仍成立的建议 - - MegaLinter 仅报出 `dotnet-format` restore 失败,test report 为 `2156 passed / 0 failed`,因此本轮重点改为“只吸收仍有效且低风险的 review 建议” -- 主线程实施: - - 将 `AGENTS.md` 中英文规则段的 `dotnet clean` / `dotnet build` / `dotnet test` 列表标点改为英文逗号,直接消化 latest-head open thread - - 删除 `GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs` 中未被任何测试引用的 `TestLoggingBehavior` 静态类型,移除无收益的可变测试基础设施 - - 在 `GFramework.Game/Internal/VersionedMigrationRunner.cs` 内引入私有 `MigrationExecutionContext`,把多处 helper 共享的不变迁移上下文收口为参数对象,并同步补齐新增泛型 helper 的 XML 文档 - - 明确拒绝把 `TestLogger` 重复实现与 `YamlConfigLoaderTests.cs` 常量位置这类“可选整理”混入本轮 warning 收敛批次 -- 验证里程碑: - - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` - - 结果:成功;确认 PR `#291` latest-head open review threads 为 `1`,MegaLinter 仅有 `dotnet-format` restore 失败,tests 为 `2156 passed` - - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` - - 结果:成功;`326 Warning(s)`、`0 Error(s)` - - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` - - 结果:成功;`149 Warning(s)`、`0 Error(s)` - - `dotnet clean` - - 结果:成功 - - `dotnet build` - - 结果:成功;`639 Warning(s)`、`0 Error(s)`,相较 `RP-069` 的 `640` 再下降 `1` -- 当前结论: - - PR #291 当前最有价值的 review follow-up 已被主线程吸收,且没有把“可选整理”误当成必须修复项 - - 当前仓库根 warning 基线继续下降到 `639`,说明这轮 review 驱动的小批次仍符合 analyzer warning reduction 主题 - - 下一轮可继续围绕 `GFramework.Game` 或 `GFramework.Cqrs.Tests` 选择新的单文件低风险热点,或在新 head 推送后重新抓取 PR review 判断是否还有剩余有效线程 - -## 2026-04-25 — RP-069 - -### 阶段:继续收口 Cqrs.Tests 双文件集合抽象 warning,并刷新新的仓库根基线 - -- 触发背景: - - `RP-068` 收尾后,当前分支的仓库根基线已降到 `645 Warning(s)`,branch diff 仍远低于 `$gframework-batch-boot 50` - - 为保持批次小而连续,主线程继续留在 `GFramework.Cqrs.Tests` 项目内,选取两个不涉及跨文件重构的 `MA0016` 切片 -- 接受的委派范围: - - worker `Chandrasekhar` - - 文件:`GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs` - - 目标:在同一文件内收敛 `TestLoggingBehavior.LoggedMessages`、`SagaData`、`TestDatabaseRequest` 的集合抽象暴露问题 - - 结果:未自行提交;主线程接受其工作树改动并纳入本轮批次 -- 主线程实施: - - 本地修改 `GFramework.Cqrs.Tests/Logging/TestLogger.cs` - - 将 `Logs` 从 `List` 收口为 `IReadOnlyList`,保留私有 `_logs` 作为内部存储 - - 与 worker 的 `MediatorAdvancedFeaturesTests.cs` 改动合并后,重新执行 `GFramework.Cqrs.Tests` 与仓库根验证,确认双文件批次的净效果 -- 验证里程碑: - - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` - - 结果:成功;`0 Warning(s)`、`0 Error(s)` - - `dotnet clean` - - 结果:成功 - - `dotnet build` - - 结果:成功;`640 Warning(s)`、`0 Error(s)`,相较 `RP-068` 的 `645` 再下降 `5` -- 当前结论: - - `Cqrs.Tests` 双文件批次已确认有效,并继续压低仓库根 warning 基线 - - 当前分支距离 `$gframework-batch-boot 50` 的停止阈值仍有很大空间,可以继续按“主线程小切片 + subagent 并行单文件”推进 - - 下一轮可优先回到 `GFramework.Core.Tests` 或继续选择新的 `GFramework.Cqrs.Tests` 单文件热点 - -## 2026-04-25 — RP-068 - -### 阶段:吸收并行 subagent 小批次,并继续压低仓库根 warning 基线 - -- 触发背景: - - `RP-067` 收尾后,当前分支的仓库根基线已降到 `649 Warning(s)`,branch diff 仅 `9 files` - - 用户明确允许主线程与 subagent 在不冲突的写集上并行推进,因此本轮继续按 `$gframework-batch-boot 50` 规则拆成 3 个单文件切片 -- 接受的委派范围: - - worker `Averroes` - - 文件:`GFramework.Core.Tests/Logging/LogContextTests.cs` - - 目标:收敛 `Push_InAsyncContext_ShouldIsolateAcrossThreads()` 内的 `MA0004` - - 结果:提交 `a7fa70e` `fix(core-tests): 清理 LogContextTests 异步等待 warning` - - worker `Laplace` - - 文件:`GFramework.Core.Tests/Logging/LoggerTests.cs` - - 目标:把 `TestLogger.Logs` 从 `List` 收口为集合抽象以修复 `MA0016` - - 结果:提交 `9f6204d` `fix(core-tests): 收口 LoggerTests 日志集合抽象` -- 主线程实施: - - 本地重构 `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs` - - 将 `RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers()` 中的 mock 装配、handler 类型读取、预期集合断言与 metadata lookup verify 拆分为具名 helper - - 在吸收两个 worker 提交后,主线程重新执行直接受影响模块与仓库根验证,确保并行切片合并后的真值一致 -- 验证里程碑: - - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` - - 结果:成功;`155 Warning(s)`、`0 Error(s)` - - `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CqrsHandlerRegistrarTests.RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers"` - - 结果:成功;`Passed 1/1` - - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - - 结果:成功;`0 Warning(s)`、`0 Error(s)` - - `dotnet clean` - - 结果:成功 - - `dotnet build` - - 结果:成功;`645 Warning(s)`、`0 Error(s)`,相较 `RP-067` 的 `649` 再下降 `4` -- 当前结论: - - 并行 3 文件批次已确认有效,且主线程已把 subagent 的负责范围和验证结果收口进 active trace - - 当前分支距离 `$gframework-batch-boot 50` 的停止阈值仍有充足空间,可以继续用“主线程验证 + subagent 并行单文件切片”的节奏推进 - - 下一轮可优先回到 `GFramework.Cqrs.Tests` 或 `GFramework.Game` 的单文件 `MA0051` / `MA0016` 热点 - -## 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 基线 - -- 触发背景: - - `RP-065` 收尾后,`fix/analyzer-warning-reduction-batch` 已通过 `6a704f3` 把 AGENTS / active ai-plan 真值修正和 4 文件测试噪音批次提交到分支 - - 原先负责 `YamlConfigLoaderTests.cs` 的 worker 长时间无结果,主线程收回该单文件批次以避免继续阻塞 -- 主线程实施: - - 关闭停滞 worker,直接重构 `GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs` - - 通过提取固定夹具内容、热重载接线 helper 与共享断言,收敛以下 4 个长方法 warning: - - `EnableHotReload_Should_Keep_Previous_State_When_Contains_Reference_Dependency_Breaks` - - `EnableHotReload_Should_Support_Options_Object` - - `EnableHotReload_Should_Keep_Previous_Table_When_Schema_Change_Makes_Reload_Fail` - - `EnableHotReload_Should_Keep_Previous_State_When_Dependency_Table_Breaks_Cross_Table_Reference` - - 在第一次仓库根重建中命中了两个 `CS0411` 泛型推断错误,主线程随即补上显式类型参数并重新建立 clean/build 基线 -- 验证里程碑: - - `dotnet clean` - - 结果:成功 - - `dotnet build` - - 结果:成功;`652 Warning(s)`、`0 Error(s)`,相较 `RP-065` 的 `656` 再下降 `4` - - `dotnet build GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release` - - 结果:成功;`0 Warning(s)`、`0 Error(s)` -- 当前结论: - - `YamlConfigLoaderTests.cs` 这 4 个根构建直接确认的 `MA0051` 已被消化 - - 当前分支在 `6a704f3` 之后的下一提交只会新增 1 个唯一文件,因此 branch diff 仍明显低于 `$gframework-batch-boot 50` 阈值 - - 下一轮可继续选择新的单文件或小写集热点,而不必暂停当前 batch loop - -## 2026-04-25 — RP-065 - -### 阶段:确认 .NET 验证噪音来自沙箱,并把无沙箱直跑写成仓库规则 - -- 触发背景: - - 用户明确指出“之前很多清理、构建、测试报错像是环境问题,需要申请权限在沙箱外执行”,并要求把该解决方案写入 `AGENTS.md` - - 主线程随后在同一 worktree 中对比了沙箱内与提权后直接 shell 的 `dotnet clean` / `dotnet build` -- 主线程实施: - - 在沙箱内直接运行 `dotnet clean` 时再次复现“Build FAILED but 0 errors”的无诊断噪音 - - 申请提权后重新执行同一条 `dotnet clean`,确认命令可正常完成,说明先前 clean 失败并非仓库真值 - - 在同一提权上下文直接执行 `dotnet build`,拿到当前仓库根权威基线:`656 Warning(s)`、`0 Error(s)` - - 关闭正在运行的 warning-reduction worker,把工作重心切到仓库治理与 active recovery 文档净化 - - 更新 `AGENTS.md`,新增规则:当沙箱内 `dotnet clean` / `dotnet build` / `dotnet test` 产生缺少诊断、权限错误或其他环境噪音时,必须申请沙箱外重跑同一条直接命令,并以该结果为准 - - 刷新 active todo/trace,把“环境阻塞”从默认恢复入口中降级为历史噪音,不再作为当前真值 -- 并行工作: - - worker 收敛了 4 个低风险测试噪音文件: - - `GFramework.Game.Tests/Config/GameConfigBootstrapTests.cs` - - `GFramework.Game.Tests/Config/GeneratedConfigConsumerIntegrationTests.cs` - - `GFramework.Game.Tests/Config/YamlConfigTextValidatorTests.cs` - - `GFramework.Ecs.Arch.Tests/Ecs/EcsAdvancedTests.cs` - - worker 验证: - - `dotnet build GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release` - - worker 初次结果:成功;随后主线程在同一提权环境复核后确认当前为 `0 Warning(s)`、`0 Error(s)` - - `dotnet build GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj -c Release` - - 主线程复核:成功;`0 Warning(s)`、`0 Error(s)` -- 当前结论: - - 本仓库当前在 agent 沙箱内执行 `.NET` 验证时,确实可能出现假失败或缺失诊断 - - 当前应把“提权后的直接 `dotnet` 命令输出”视为仓库真值,而不是继续围绕沙箱噪音扩展 workaround 命令形态 - - `fix/analyzer-warning-reduction-batch` 当前 `HEAD` 已与 `origin/main` 对齐;新的 `$gframework-batch-boot 50` 轮次从 `0 files / 0 lines` committed diff 开始 - - 下一轮低风险热点仍是 `GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs` 的 `4` 个 `MA0051` - -## 2026-04-25 — RP-064 - -### 阶段:按标准 WSL build 路径复核 PR #288 建议并完成本轮收口 - -- 触发背景: - - 用户指出“在 WSL 里直接执行 `dotnet build` 可以成功”,要求主线程按普通路径重新验证,而不是继续使用带 `MSBuildEnableWorkloadResolver=false`、`--no-restore`、手工 `TargetFramework` 的 workaround 命令 - - 当前任务仍属于 PR #288 review follow-up,因此本轮重点改为“区分哪些 AI 建议值得采纳”以及“用真实 WSL build 结果验证” -- 主线程实施: - - 重新抓取 PR #288 review,确认 latest-head open threads 为 `CodeRabbit 6 + Greptile 2` - - 复核 `outside diff + nitpick` 的 19 条建议,只采纳本地仍成立的建议;拒绝把“评论总数”机械等同于“必须全改” - - 完成以下高信号修复: - - `ContextAware*` / `AsyncExtensions` / `NumericExtensions` / `StringExtensions` / `StoreBuilder`:回退为 `ArgumentNullException.ThrowIfNull(...)` - - `ArchitectureServicesTests` / `GameContextTests`:同步 XML `` 到 `NotSupportedException` - - `RegistryInitializationHookBaseTests`:修复 override 可空签名实现,避免再次引入编译错误 - - `RollingFileAppenderTests` / `TaskCoroutineExtensionsTests` / `WaitForTaskTests` / `ScopedStorage`:移除无收益噪音代码 - - `FileStorage`:通过 `leaveOpen: true` 修正 `FileStream` 的双重释放语义 - - `SceneRouterBase`:统一显式 `ConfigureAwait(true)` 并补齐引擎线程亲和说明 - - `StoreSelection`:保留 `net9.0+` 的 `System.Threading.Lock`,同时修正条件编译旁的注释写法,避免 `CS1587` -- 验证里程碑: - - `dotnet restore GFramework.sln -p:RestoreFallbackFolders="" -v minimal` - - 结果:成功;证明先前 `MSB4018` 来自 stale restore 元数据,而不是当前 WSL 默认 build 路径本身不可用 - - `dotnet build GFramework.Core/GFramework.Core.csproj -c Release` - - 结果:成功;`28 Warning(s)`、`0 Error(s)` - - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` - - 结果:成功;`329 Warning(s)`、`0 Error(s)` - - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - - 结果:成功;`137 Warning(s)`、`0 Error(s)` -- 当前结论: - - 用户关于“WSL 里直接 `dotnet build` 可行”的判断正确 - - 前一轮失败的核心原因不是仓库不可构建,而是主线程附加的 workaround 参数改变了 MSBuild 行为 - - 本轮已完成 PR #288 中一组仍成立的建议修复,并重新拿到标准 WSL 路径下的 Release build 验证 - - 剩余 review 线程需要在新 head 上重新抓取后再决定是否逐条 resolve - -## 2026-04-25 — RP-063 - -### 阶段:先收口 PR #288 latest-head 编译错误,再暂停在环境阻塞点并准备提交 - -- 触发背景: - - 用户显式要求先执行 `$gframework-pr-review`,并指出 `AsyncExtensionsTests.cs(126,23)` 当前存在 `CS0029` / `CS1662` 构建错误 - - 当前 worktree 仍是 `fix/analyzer-warning-reduction-batch`,因此本 turn 继续沿用 `analyzer-warning-reduction` 的 active recovery 文档 -- 主线程实施: - - 运行 PR review 抓取脚本,确认当前分支对应 PR `#288` - - 核对 latest-head unresolved review threads 后,优先修复 `AsyncExtensionsTests.cs` 中 `ct => Task.Delay(...).ConfigureAwait(false)` 错误返回 `ConfiguredTaskAwaitable` 的问题 - - 顺手收敛多处已被 latest review 点名且本地仍成立的低风险残留: - - 测试中的 `async` 无 `await` - - `ValueTask` 断言包装 - - `RegistryInitializationHookBaseTests.cs` 的可空返回签名 - - `NumericExtensions.cs`、`StringExtensions.cs`、`StoreBuilder.cs` 的 Allman 花括号残留 - - `StoreSelection.cs` 在 `net9.0+` 下切到 `System.Threading.Lock`,同时保留 `net8.0` 兼容分支 -- 验证里程碑: - - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` - - 结果:成功;确认 PR `#288` 的 latest-head unresolved AI review threads 共 `9` 个,其中 `AsyncExtensionsTests.cs:126` 为 critical 编译错误 - - `DOTNET_CLI_HOME=/tmp/dotnet-home MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net8.0 -p:RestoreFallbackFolders="" -v minimal` - - 结果:失败;`MSB4018`,`ResolvePackageAssets` 仍读取失效 Windows fallback package folder `D:\Tool\Development Tools\Microsoft Visual Studio\Shared\NuGetPackages` - - `DOTNET_CLI_HOME=/tmp/dotnet-home MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net9.0 -p:RestoreFallbackFolders="" -v minimal` - - 结果:失败;原因同上 - - `DOTNET_CLI_HOME=/tmp/dotnet-home MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-restore -p:TargetFramework=net10.0 -p:RestoreFallbackFolders="" -v minimal` - - 结果:失败;原因同上 -- 当前结论: - - 用户点名的 `AsyncExtensionsTests.cs` 编译错误已在源码层修复 - - 本 turn 未能拿到新的可通过 Release build,阻塞点已从先前记录的 `MSB4276` 收敛为当前 `obj/*.csproj.nuget.g.props` 中 stale Windows fallback package folder 导致的 `MSB4018` - - 用户随后要求“先不管这个了,先提交吧”,因此本 turn 在记录环境阻塞后先执行提交收口 - -## 2026-04-25 — RP-062 - -### 阶段:触达 `$gframework-batch-boot 75` 停止阈值并收口到 `75 files / 2098 lines` - -- 触发背景: - - `RP-061` 收尾时分支相对 `origin/main` 仍只有 `48` 个已提交文件,距离本轮 `75 files` 停止条件还有明显空间 - - 用户明确允许继续委派 subagent,因此主线程继续把低风险机械型写集拆成互不重叠的 test / runtime 小批次 - - 本轮主目标不是继续深挖单个高上下文热点,而是用新的低风险文件精确把 branch diff 推到阈值后停止 -- 主线程实施: - - 先接受并提交 7 文件 `Core.Tests` 收尾批次为 `03c73a8` `test(core-tests): 收敛测试桩与辅助类型 warning` - - 随后主线程与多个 worker 并行收口以下新增文件: - - `ArchitectureAdditionalCqrsHandlersTests.cs` - - `RegistryInitializationHookBaseTests.cs` - - `CommandCoroutineExtensionsTests.cs` - - `TaskCoroutineExtensionsTests.cs` - - `WaitForTaskTTests.cs` - - `AsyncExtensionsTests.cs` - - `LogContextTests.cs` - - `PauseStackManagerTests.cs` - - `AsyncExtensions.cs` - - `CollectionExtensions.cs` - - `ContextAwareCommandExtensions.cs` - - `ContextAwareEnvironmentExtensions.cs` - - `ContextAwareEventExtensions.cs` - - `ContextAwareQueryExtensions.cs` - - `ContextAwareServiceExtensions.cs` - - `GuardExtensions.cs` - - `NumericExtensions.cs` - - `StoreEventBusExtensions.cs` - - `StringExtensions.cs` - - `StoreBuilder.cs` - - `StoreSelection.cs` - - 将上述 22 文件批次收口为 `9ce1fa6` `refactor(core): 收敛 Core 扩展与测试的机械 warning` -- 验证里程碑: - - `dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net8.0 -p:RestoreFallbackFolders="" -v minimal` - - 结果:成功;`0 Warning(s)`、`0 Error(s)` - - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-incremental --no-restore -p:RestoreFallbackFolders= -v:diag` - - 结果:失败;`MSB4276`,默认 SDK resolver 缺少 `Microsoft.NET.SDK.WorkloadAutoImportPropsLocator` - - `dotnet restore GFramework.Core.Tests/GFramework.Core.Tests.csproj -p:TestTargetFrameworks=net8.0 -p:RestoreFallbackFolders="" -v minimal` - - 结果:失败;`NU1201`,`GFramework.Tests.Common` 仅支持 `net10.0`,不能作为 `Core.Tests` 的 net8 旁路验证 - - `git diff --name-only origin/main...HEAD | wc -l` - - 结果:`75` - - `git diff --numstat origin/main...HEAD` - - 结果:累计 `1083` added、`1015` deleted,即 `2098` changed lines -- 当前结论: - - 本轮 `$gframework-batch-boot 75` 已精确达到主停止条件,默认恢复点应停止在 `9ce1fa6` - - `Core` runtime 的本轮机械型改动已有可通过的最小 Release build 验证 - - `Core.Tests` 的继续推进当前首先受 `MSB4276` 环境阻塞影响;下一轮若要继续,应先修复构建环境,再重新建立 warning 基线 + - 本轮只吸收当前仍成立的 PR review 文档项,不扩展到新的 warning 清理切片 + - 当前仓库根 warning 权威基线仍保持 `639 Warning(s)`、`0 Error(s)`;本轮目标是让 active 恢复入口重新变短且不重复维护真值 + - 下一轮默认先推送本轮同步并重新执行 `$gframework-pr-review`,确认 PR `#291` 的 open thread 与 nitpick 是否已自动收口 ## 历史归档指针 +- 最新 trace 归档: + - [analyzer-warning-reduction-history-rp062-rp071.md](../archive/traces/analyzer-warning-reduction-history-rp062-rp071.md) - 早期 trace 归档: - [analyzer-warning-reduction-history-rp001.md](../archive/traces/analyzer-warning-reduction-history-rp001.md) - [analyzer-warning-reduction-history-rp002-rp041.md](../archive/traces/analyzer-warning-reduction-history-rp002-rp041.md) From 3a3359b4956c070071bb7e2f8df95fad8827a0a5 Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Sun, 26 Apr 2026 08:27:24 +0800 Subject: [PATCH 12/12] =?UTF-8?q?docs(ai-plan):=20=E8=84=B1=E6=95=8F=20ana?= =?UTF-8?q?lyzer=20warning=20=E8=B7=9F=E8=B8=AA=E8=B7=AF=E5=BE=84=E8=AE=B0?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新 analyzer-warning-reduction active todo/trace 的 PR review 真值与恢复点 - 脱敏 archive trace 中的临时输出路径与 Windows fallback package folder 记录 - 补充 dotnet build 验证结果并保持 639 Warning(s) 基线说明 --- ...r-warning-reduction-history-rp062-rp071.md | 14 +++---- .../analyzer-warning-reduction-tracking.md | 37 +++++-------------- .../analyzer-warning-reduction-trace.md | 24 ++++++------ 3 files changed, 28 insertions(+), 47 deletions(-) diff --git a/ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp062-rp071.md b/ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp062-rp071.md index 06308a1e..42285dbf 100644 --- a/ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp062-rp071.md +++ b/ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp062-rp071.md @@ -25,7 +25,7 @@ - 更新 active todo 恢复点为 `RP-071`,将 `.gitignore` 纳入“已提交的低风险批次文件”,并移除已过时的 `.codex` 活跃风险描述 - 在 active todo 中明确保留当前仍未采纳的两条 non-blocking nitpick:`VersionedMigrationRunner.cs` 的上下文一致性建议,以及 active trace 归档 RP-062 ~ RP-064 的建议 - 验证里程碑: - - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` + - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output ` - 结果:成功;确认 PR `#291` latest-head open review threads 为 `1`,唯一路径为 `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md:54` - `dotnet build` - 结果:成功;`0 Warning(s)`、`0 Error(s)`;该次为增量 Debug 构建,只作为本轮文档同步的完成校验,warning 权威基线仍保持 `RP-070` 记录的 `639 Warning(s)` @@ -48,7 +48,7 @@ - 在 `GFramework.Game/Internal/VersionedMigrationRunner.cs` 内引入私有 `MigrationExecutionContext`,把多处 helper 共享的不变迁移上下文收口为参数对象,并同步补齐新增泛型 helper 的 XML 文档 - 明确拒绝把 `TestLogger` 重复实现与 `YamlConfigLoaderTests.cs` 常量位置这类“可选整理”混入本轮 warning 收敛批次 - 验证里程碑: - - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` + - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output ` - 结果:成功;确认 PR `#291` latest-head open review threads 为 `1`,MegaLinter 仅有 `dotnet-format` restore 失败,tests 为 `2156 passed` - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` - 结果:成功;`326 Warning(s)`、`0 Error(s)` @@ -258,13 +258,13 @@ - `NumericExtensions.cs`、`StringExtensions.cs`、`StoreBuilder.cs` 的 Allman 花括号残留 - `StoreSelection.cs` 在 `net9.0+` 下切到 `System.Threading.Lock`,同时保留 `net8.0` 兼容分支 - 验证里程碑: - - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` + - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output ` - 结果:成功;确认 PR `#288` 的 latest-head unresolved AI review threads 共 `9` 个,其中 `AsyncExtensionsTests.cs:126` 为 critical 编译错误 - - `DOTNET_CLI_HOME=/tmp/dotnet-home MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net8.0 -p:RestoreFallbackFolders="" -v minimal` - - 结果:失败;`MSB4018`,`ResolvePackageAssets` 仍读取失效 Windows fallback package folder `D:\Tool\Development Tools\Microsoft Visual Studio\Shared\NuGetPackages` - - `DOTNET_CLI_HOME=/tmp/dotnet-home MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net9.0 -p:RestoreFallbackFolders="" -v minimal` + - `DOTNET_CLI_HOME= MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net8.0 -p:RestoreFallbackFolders="" -v minimal` + - 结果:失败;`MSB4018`,`ResolvePackageAssets` 仍读取失效 Windows fallback package folder `` + - `DOTNET_CLI_HOME= MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net9.0 -p:RestoreFallbackFolders="" -v minimal` - 结果:失败;原因同上 - - `DOTNET_CLI_HOME=/tmp/dotnet-home MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-restore -p:TargetFramework=net10.0 -p:RestoreFallbackFolders="" -v minimal` + - `DOTNET_CLI_HOME= MSBuildEnableWorkloadResolver=false dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-restore -p:TargetFramework=net10.0 -p:RestoreFallbackFolders="" -v minimal` - 结果:失败;原因同上 - 当前结论: - 用户点名的 `AsyncExtensionsTests.cs` 编译错误已在源码层修复 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 55b2c98f..7e85bac2 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,11 +6,11 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-072` -- 当前阶段:`Phase 72` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-073` +- 当前阶段:`Phase 73` - 当前焦点: - - `2026-04-25` 主线程再次按 `$gframework-pr-review` 复核当前分支 PR `#291`,确认 latest-head 仍剩 `1` 条 open review thread 与 `1` 条 nitpick,均指向 active `ai-plan` 文档 - - 当前批次只同步 active todo/trace 到最新 review 真值:压缩 active trace,并把重复维护的验证结果改回单一权威区块 + - `2026-04-26` 主线程再次按 `$gframework-pr-review` 复核当前分支 PR `#291`,确认 latest-head 仍剩 `2` 条 open review thread,均指向 `ai-plan` 文档中的绝对路径记录 + - 当前批次同步 active todo/trace 与相关 archive trace:把 PR review 输出路径、临时 `dotnet` home 和失效 Windows fallback package folder 改写为仓库安全占位符 - `dotnet clean` + `dotnet build` 的直接仓库根基线仍为 `639 Warning(s)`、`0 Error(s)`,因此本轮属于文档真值收口,而不是新的 warning 清理批次 ## 当前活跃事实 @@ -22,33 +22,14 @@ - `dotnet build` - 最新结果:成功;`639 Warning(s)`、`0 Error(s)` - 当前分支低风险批次文件: - - `AGENTS.md` - - `.gitignore` - - `GFramework.Core.Tests/Logging/LogContextTests.cs` - - `GFramework.Core.Tests/Logging/LoggerTests.cs` - - `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs` - - `GFramework.Cqrs.Tests/Logging/TestLogger.cs` - - `GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs` - - `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` - `ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp062-rp071.md` - 当前批次验证结果: - - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` - - 最新主线程结果:成功;确认 PR `#291` latest-head open review thread 为 `1`、CodeRabbit nitpick 为 `1`,两者都指向 active `ai-plan` 文档入口 + - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output ` + - 最新主线程结果:成功;确认 PR `#291` latest-head open review thread 为 `2`,两者都指向 `ai-plan` 文档中的绝对路径记录 - `dotnet build` - - 最新主线程结果:成功;`0 Warning(s)`、`0 Error(s)`;该次为增量 Debug 构建,只作为本轮文档同步完成校验,warning 权威基线仍以 `dotnet clean` 后的 `639 Warning(s)` 为准 - - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` - - 最新主线程结果:成功;`326 Warning(s)`、`0 Error(s)` - - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release` - - 最新主线程结果:成功;`149 Warning(s)`、`0 Error(s)` - - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - - 上一轮主线程结果:成功;`0 Warning(s)`、`0 Error(s)` + - 最新主线程结果:成功;`639 Warning(s)`、`0 Error(s)`;与当前权威仓库根基线一致 ## 当前风险 @@ -77,6 +58,6 @@ ## 下一步建议 -1. 推送包含本轮 active todo/trace 同步的提交后,重新执行 `$gframework-pr-review`,确认 PR `#291` 的 latest-head open thread 与 nitpick 是否已自动收口。 +1. 推送包含本轮 absolute-path 脱敏的提交后,重新执行 `$gframework-pr-review`,确认 PR `#291` 的 latest-head open thread 是否已自动收口。 2. 若 PR `#291` 已清零,继续以当前 `639 Warning(s)` 根基线为恢复点,按 `$gframework-batch-boot 50` 规则挑选下一个 1-3 文件的低风险热点。 -3. 若 GitHub 仍保留 review 信号,先确认它们是否指向新 head,再决定是否需要继续细化 active `ai-plan` 入口。 +3. 若 GitHub 仍保留 review 信号,先确认它们是否仍指向新 head,再决定是否需要继续清理同主题下的其它历史 `ai-plan` 记录。 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 22bcb5b5..a4a5b4d8 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,26 +1,26 @@ # Analyzer Warning Reduction 追踪 -## 2026-04-25 — RP-072 +## 2026-04-26 — RP-073 -### 阶段:收口 PR #291 剩余的 active ai-plan 文档 review +### 阶段:脱敏 analyzer-warning-reduction 文档中的绝对路径记录 - 触发背景: - 用户再次显式要求执行 `$gframework-pr-review`,当前分支仍对应 PR `#291` - - 最新抓取结果确认 latest-head 还剩 `1` 条 open review thread,指向 active trace 入口过长;同时 CodeRabbit 还有 `1` 条 nitpick,指向 active todo 中重复维护验证结果 - - 这两项问题都仍然成立,且都属于 active `ai-plan` 入口维护问题,不涉及新的源码 warning 修复 + - 最新抓取结果确认 latest-head 还剩 `2` 条 open review thread,分别指向 active todo 与 archive trace 中记录的绝对路径 + - active trace 当前也保留了同类 `/tmp` 路径记录;虽然这次 review 没直接点名,但继续保留会留下同一类治理缺口 - 主线程实施: - - 将 `ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md` 压缩为只保留当前恢复点与归档指针 - - 将 `RP-062` 至 `RP-071` 的详细 trace 迁入 [analyzer-warning-reduction-history-rp062-rp071.md](../archive/traces/analyzer-warning-reduction-history-rp062-rp071.md) - - 同步更新 active todo,移除重复的验证结果抄录,改为只在权威区块维护构建与 PR review 真值 + - 将 active todo 与 active trace 中的 PR review 输出路径改写为 `--json-output ` + - 将 [analyzer-warning-reduction-history-rp062-rp071.md](../archive/traces/analyzer-warning-reduction-history-rp062-rp071.md) 里的临时 `dotnet` home、PR review 输出路径和失效 Windows fallback package folder 改写为仓库安全占位符 + - 同步刷新 active todo 中的 review 真值,把当前恢复点更新到 `RP-073` - 验证里程碑: - - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json` - - 结果:成功;确认 PR `#291` latest-head open review thread 为 `1`,CodeRabbit nitpick 为 `1`,两者都指向 active `ai-plan` 文档 + - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output ` + - 结果:成功;确认 PR `#291` latest-head open review thread 为 `2`,两者都指向 `ai-plan` 文档中的绝对路径记录 - `dotnet build` - - 结果:成功;`0 Warning(s)`、`0 Error(s)`;该次为增量 Debug 构建,只作为本轮文档同步完成校验,warning 权威基线仍保持 `639 Warning(s)`、`0 Error(s)` + - 结果:成功;`639 Warning(s)`、`0 Error(s)`;与当前权威仓库根基线一致 - 当前结论: - 本轮只吸收当前仍成立的 PR review 文档项,不扩展到新的 warning 清理切片 - - 当前仓库根 warning 权威基线仍保持 `639 Warning(s)`、`0 Error(s)`;本轮目标是让 active 恢复入口重新变短且不重复维护真值 - - 下一轮默认先推送本轮同步并重新执行 `$gframework-pr-review`,确认 PR `#291` 的 open thread 与 nitpick 是否已自动收口 + - 当前仓库根 warning 权威基线仍保持 `639 Warning(s)`、`0 Error(s)`;本轮目标是让 analyzer-warning-reduction 主题下当前入口不再记录绝对路径 + - 下一轮默认先推送本轮同步并重新执行 `$gframework-pr-review`,确认 PR `#291` 的 open thread 是否已自动收口 ## 历史归档指针