diff --git a/ai-plan/public/README.md b/ai-plan/public/README.md index 86b3db70..a810a557 100644 --- a/ai-plan/public/README.md +++ b/ai-plan/public/README.md @@ -12,6 +12,11 @@ help the current worktree land on the right recovery documents without scanning ## Active Topics +- `analyzer-warning-reduction` + - Purpose: track the analyzer warning reduction branch, including the current recovery point, remaining warning + hotspots, and the next safe warning-reduction slice. + - Tracking: `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md` + - Trace: `ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md` - `ai-plan-governance` - Purpose: govern the `ai-plan/` directory model, startup index, and archive policy. - Tracking: `ai-plan/public/ai-plan-governance/todos/ai-plan-governance-tracking.md` @@ -27,6 +32,9 @@ help the current worktree land on the right recovery documents without scanning ## Worktree To Active Topic Map +- Branch: `fix/analyzer-warning-reduction-batch` + - Worktree hint: `GFramework-analyzer` + - Priority 1: `analyzer-warning-reduction` - Branch: `feat/ai-first-config` - Worktree hint: `GFramework-Ai-First-Config` - Priority 1: `ai-first-config-system` diff --git a/ai-plan/public/ai-plan-governance/todos/ai-plan-governance-tracking.md b/ai-plan/public/ai-plan-governance/todos/ai-plan-governance-tracking.md index 7e24954b..3f1e6d0b 100644 --- a/ai-plan/public/ai-plan-governance/todos/ai-plan-governance-tracking.md +++ b/ai-plan/public/ai-plan-governance/todos/ai-plan-governance-tracking.md @@ -20,6 +20,7 @@ - 将"主题内 `archive/` 已存在"升级为"active todo/trace 过长时必须归档已完成且已验证阶段"的显式规则 - 让 active `todos/` / `traces/` 只保留当前恢复点、活跃事实、活跃风险、下一步与 archive 指针 - 将 `ai-plan-governance`、`ai-first-config-system` 与 `cqrs-rewrite` 的历史阶段从默认启动入口移出 + - 将当前工作树遗留的 `local-plan` 示例迁入 `ai-plan/public//`,验证治理规则对新 topic 迁移同样成立 ### 已知风险 @@ -43,6 +44,12 @@ - `ai-plan-governance` 的 RP-002 至 RP-004 历史 - `ai-first-config-system` 截至 `2026-04-17` 的详细跟踪与执行 trace - `cqrs-rewrite` 截至 `RP-043` 的详细跟踪与执行 trace +- 已将当前工作树遗留的 analyzer warning reduction 恢复文档从 `local-plan/` 迁入: + - `ai-plan/public/analyzer-warning-reduction/todos/` + - `ai-plan/public/analyzer-warning-reduction/traces/` + - `ai-plan/public/analyzer-warning-reduction/archive/todos/` + - `ai-plan/public/analyzer-warning-reduction/archive/traces/` +- 已同步更新 `ai-plan/public/README.md`,将分支 `fix/analyzer-warning-reduction-batch` 映射到新 topic - 已同步更新 `AGENTS.md`、`ai-plan/README.md` 与 `gframework-boot`,明确 active 文档不是追加式日志,已完成且已验证阶段必须归档 ## 验证 @@ -53,6 +60,9 @@ - `wc -l ai-plan/public/ai-plan-governance/todos/ai-plan-governance-tracking.md ai-plan/public/ai-plan-governance/traces/ai-plan-governance-trace.md ai-plan/public/ai-first-config-system/todos/ai-first-config-system-tracking.md ai-plan/public/ai-first-config-system/traces/ai-first-config-system-trace.md ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md` - 结果:通过 - 备注:6 个 active 入口文件当前合计 `249` 行,已从治理前的 `3046` 行显著收短 +- `find ai-plan/public/analyzer-warning-reduction -maxdepth 3 -type f | sort` + - 结果:通过 + - 备注:新 topic 已按 `todos/`、`traces/` 与主题内 `archive/` 目录语义落位 - `dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release -p:RestoreFallbackFolders=` - 结果:通过 - 备注:`GFramework.Cqrs.Abstractions` 与 `GFramework.Core.Abstractions` 构建通过,`0 warning / 0 error` @@ -64,6 +74,6 @@ ## 下一步 -1. 后续只要某个 active 主题积累了多个已完成且已验证阶段,就在同一变更里将其细节迁入该主题自己的 `archive/` -2. 若某个主题整体完成,再将整个主题目录移入 `ai-plan/public/archive//` -3. 后续新增 topic 时,默认直接创建 `todos/`、`traces/` 与 `archive/`,不要再把历史阶段长期堆在 active 入口 \ No newline at end of file +1. 继续扫描是否还有遗留的 `local-plan` 或其他非 `ai-plan` 的 durable recovery 文档目录 +2. 后续只要某个 active 主题积累了多个已完成且已验证阶段,就在同一变更里将其细节迁入该主题自己的 `archive/` +3. 若某个主题整体完成,再将整个主题目录移入 `ai-plan/public/archive//` diff --git a/ai-plan/public/ai-plan-governance/traces/ai-plan-governance-trace.md b/ai-plan/public/ai-plan-governance/traces/ai-plan-governance-trace.md index e15f6019..a3683a0b 100644 --- a/ai-plan/public/ai-plan-governance/traces/ai-plan-governance-trace.md +++ b/ai-plan/public/ai-plan-governance/traces/ai-plan-governance-trace.md @@ -28,3 +28,22 @@ 1. 未来若 active 入口再次因为已完成阶段累积而膨胀,直接按同一模式归档,不再保留为追加式历史日志 2. 后续新增 topic 时,默认同步创建 `todos/`、`traces/` 与 `archive/` 目录 + +### 阶段:遗留 local-plan 迁移验证(RP-005) + +- 复核当前工作树后确认,仍存在未纳入 `ai-plan/` 的遗留恢复目录 `local-plan/` +- 将 `local-plan` 中属于 analyzer warning reduction 主题的 tracking / trace 拆分迁入: + - `ai-plan/public/analyzer-warning-reduction/todos/` + - `ai-plan/public/analyzer-warning-reduction/traces/` + - `ai-plan/public/analyzer-warning-reduction/archive/todos/` + - `ai-plan/public/analyzer-warning-reduction/archive/traces/` +- 为新 topic 补齐 active 入口与 archive 历史,并更新 `ai-plan/public/README.md` 的 active topics 与 worktree 映射 +- 删除旧 `local-plan` 文件,验证治理规则不仅适用于现有 topic,也适用于从 worktree 遗留目录迁入的新 topic +- 额外完成验证: + - `find ai-plan/public/analyzer-warning-reduction -maxdepth 3 -type f | sort` + - `dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release -p:RestoreFallbackFolders=` + +### 下一步 + +1. 后续若再发现 `local-plan` 一类目录,直接按 topic 归属迁入 `ai-plan/public//` +2. 保持新 topic 的 active 入口精简,避免把迁移动作变成简单目录平移 diff --git a/ai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp001.md b/ai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp001.md new file mode 100644 index 00000000..a5e40553 --- /dev/null +++ b/ai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp001.md @@ -0,0 +1,155 @@ +# Analyzer Warning Reduction History + +> 该文档于 `2026-04-19` 从旧 `local-plan/todos/analyzer-warning-reduction-tracking.md` 迁入,作为 +> `ANALYZER-WARNING-REDUCTION-RP-001` 的历史跟踪归档保留。 + +## Legacy Tracking Content + +## Goal + +Reduce the currently surfaced Meziantou analyzer warnings from the repository build by prioritizing low-risk, +behavior-preserving fixes first, then reassessing whether larger refactors are justified for remaining long-method and +file-structure warnings. + +## Current Recovery Point + +- Recovery point: `ANALYZER-WARNING-REDUCTION-RP-001` +- Current phase: `Phase 1` +- Active focus: + - capture the current warning clusters with `dotnet build ... -t:Rebuild -clp:Summary;WarningsOnly` + - fix low-risk runtime and generator warnings that do not require architectural rewrites + - keep this tracking document and the paired trace synchronized with subagent scope, accepted fixes, and validation + - keep the current checkpoint test-green for the targeted regressions introduced by warning-reduction edits + +## Planned Work + +- [x] Read `AGENTS.md` and `.ai/environment/tools.ai.yaml` before choosing commands. +- [x] Confirm the current warning set still reproduces in a clean rebuild-oriented build invocation. +- [x] Group warnings into independent work slices before delegating. +- [x] Record delegated ownership boundaries for parallel subagent work. +- [x] Reduce low-risk warnings in `GFramework.Core` / `GFramework.Cqrs`. +- [x] Reduce low-risk warnings in `GFramework.Godot`. +- [x] Reduce low-risk warnings in source generator projects without broad generator rewrites. +- [x] Rebuild the affected projects and record the remaining warning hotspots. +- [x] Repair the targeted test regressions introduced by the current warning-reduction checkpoint. +- [x] Apply the current CodeRabbit follow-up fixes for module-install ordering, logging factory null-safety/disposal, and + Godot YAML directory enumeration contracts. +- [x] Apply the latest CodeRabbit follow-up fixes for failure-path module tracking, logger-name validation, and + brittle test replacement. +- [x] Apply the latest CodeRabbit follow-up fixes for null appender-entry validation and async doc-sample correctness. +- [ ] Decide whether any remaining `MA0051` / file-structure warnings are safe to tackle in the same round. + +## Validation + +Planned validation commands: + +```bash +dotnet build GFramework.sln -c Release -t:Rebuild -nologo -clp:Summary;WarningsOnly +dotnet build GFramework.Core/GFramework.Core.csproj -c Release -t:Rebuild -nologo -clp:Summary;WarningsOnly +dotnet build GFramework.Godot/GFramework.Godot.csproj -c Release -t:Rebuild -nologo -clp:Summary;WarningsOnly +dotnet build GFramework.Core.SourceGenerators/GFramework.Core.SourceGenerators.csproj -c Release -t:Rebuild -nologo -clp:Summary;WarningsOnly +``` + +Results: + +- `dotnet build GFramework.Core.SourceGenerators/GFramework.Core.SourceGenerators.csproj -c Release --no-restore` + - passed with `0 Warning(s)` and `0 Error(s)`. +- `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release -t:Rebuild --no-restore -p:TargetFramework=net8.0 -p:UseSharedCompilation=false -nologo -clp:Summary;WarningsOnly` + - passed with `1 Warning(s)` and `0 Error(s)`. + - remaining warning: + - `GFramework.Cqrs/Internal/CqrsHandlerRegistrar.cs` `MA0051` long-method warning. +- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release -t:Rebuild --no-restore -p:UseSharedCompilation=false -p:TargetFramework=net8.0 -nologo -clp:Summary;WarningsOnly` + - first focused rebuild after the initial runtime-fix pass: `49 Warning(s)`, `0 Error(s)`. + - latest focused rebuild after the follow-up structural cleanup: `31 Warning(s)`, `0 Error(s)`. + - the remaining `net8.0` warnings are now concentrated in: + - generic/non-generic file-name collisions that cannot be fixed cheaply without API renames + - delegate-shape rules around specific callbacks + - a smaller set of long-method warnings + - a few collection-abstraction warnings on public configuration types +- `dotnet build GFramework.Godot/GFramework.Godot.csproj -c Release --no-restore -p:TargetFramework=net8.0 -p:UseSharedCompilation=false` + - worker validation reported a successful build after the Godot-owned fixes. + - remaining Godot-owned warnings reported by the worker: + - `GFramework.Godot/Setting/Data/LocalizationMap.cs` `MA0016` on the two public `Dictionary`-typed properties. + - broader direct `GFramework.Godot` builds still surface many `GFramework.Game` dependency warnings, so those results + should not be interpreted as unresolved Godot-owned work. +- `dotnet test GFramework.Core.Tests -c Release --filter "FullyQualifiedName~GetString_WithUnknownCompactFormatterArgs_ShouldIgnoreUnknownOptions|FullyQualifiedName~GetString_WithVariable_ShouldFormatCorrectly|FullyQualifiedName~GetString_WithMultipleVariables_ShouldFormatCorrectly|FullyQualifiedName~GetString_WithInvalidCompactFormatterArgs_ShouldFallbackToDefaultFormatting|FullyQualifiedName~GetString_WithCompactFormatterArgs_ShouldApplyOptions|FullyQualifiedName~GetString_WithCompactFormatter_ShouldFormatCorrectly|FullyQualifiedName~Ensure_Should_Create_ArgumentException_With_Message|FullyQualifiedName~RegisterCqrsHandlersFromAssemblies_WithNullAssemblyItem_Should_ThrowArgumentNullException"` + - passed with `0 Failed`, `8 Passed`, `0 Skipped`. + - regressions fixed in this validation step: + - `LocalizationString` placeholder formatting stopped replacing values after the regex switched to `RegexOptions.ExplicitCapture` while still reading unnamed capture groups. + - `ResultExtensions.Ensure` changed the observable `ArgumentException.Message` by adding a parameter name. + - `MicrosoftDiContainer.RegisterCqrsHandlersFromAssemblies` changed the null-item contract from `ArgumentNullException` to `ArgumentException`. +- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~NumericExtensionsTests|FullyQualifiedName~ResultTests|FullyQualifiedName~ResultExtensionsTests|FullyQualifiedName~LoggingConfigurationTests"` + - passed with `0 Failed`, `101 Passed`, `0 Skipped`. + - covered the new review-driven fixes for: + - `NumericExtensions.Between` null contract enforcement + - `Result` default-value safety in `Equals` / `GetHashCode` / `ToString` + - `ResultExtensions.Ensure` parameter-name contract + - `ConfigurableLoggerFactory` longest-prefix logger-level selection +- `dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~SettingsSystemTests|FullyQualifiedName~GodotLocalizationSettingsTests"` + - passed with `0 Failed`, `7 Passed`, `0 Skipped`. + - revalidated the `IApplyAbleSettings.ApplyAsync` rename through system and Godot localization callers. +- `dotnet build GFramework.Godot.Tests/GFramework.Godot.Tests.csproj -c Release` + - passed with `0 Error(s)`. +- `dotnet test GFramework.Godot.Tests/GFramework.Godot.Tests.csproj -c Release --filter "FullyQualifiedName~LoadAsync_Should_Use_Globalized_Res_Directory_Directly_When_Running_In_Editor"` + - passed with `0 Failed`, `1 Passed`, `0 Skipped`. + - used as the stable Godot-side smoke test after the review-driven changes to `SceneBehaviorBase`, + `AbstractArchitecture`, and `GodotYamlConfigEnvironment`. +- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~ConfigurableLoggerFactoryTests|FullyQualifiedName~LoggingConfigurationTests"` + - narrowed to `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~ConfigurableLoggerFactoryTests" -m:1` + - passed with `0 Failed`, `3 Passed`, `0 Skipped`. +- `dotnet test GFramework.Godot.Tests/GFramework.Godot.Tests.csproj -c Release --filter "FullyQualifiedName~LoadAsync_Should_Use_Globalized_Res_Directory_Directly_When_Running_In_Editor"` + - passed with `0 Failed`, `1 Passed`, `0 Skipped`. +- `dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~GodotLocalizationSettingsTests"` + - passed with `0 Failed`, `3 Passed`, `0 Skipped`. +- `dotnet build GFramework.sln -c Release` + - rerun serially as `dotnet build GFramework.sln -c Release -m:1` + - passed with `698 Warning(s)` and `0 Error(s)`. +- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~ConfigurableLoggerFactoryTests" -m:1` + - latest follow-up rerun passed with `0 Failed`, `5 Passed`, `0 Skipped`. +- `dotnet test GFramework.Godot.Tests/GFramework.Godot.Tests.csproj -c Release --filter "FullyQualifiedName~AbstractArchitectureModuleInstallationTests" -m:1` + - passed with `0 Failed`, `1 Passed`, `0 Skipped`. + - now directly covers the contract that `InstallGodotModule` throws before `module.Install(...)` when `_anchor` is unavailable. +- `dotnet build GFramework.sln -c Release -m:1` + - latest follow-up rerun passed with `847 Warning(s)` and `0 Error(s)`. +- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~ConfigurableLoggerFactoryTests" -m:1` + - latest null-appender validation rerun passed with `0 Failed`, `6 Passed`, `0 Skipped`. +- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release -m:1` + - latest focused release build passed with `79 Warning(s)` and `0 Error(s)`. + +## Known Risks + +- Many warnings are duplicated across target frameworks, so a small source edit can remove multiple reported instances; + warning counts must be interpreted by unique source location, not only raw line count. +- Some warning families such as `MA0158` (`System.Threading.Lock`) are not obviously safe in the current multi-targeted + `net8.0;net9.0;net10.0` runtime modules and may require conditional compilation or a broader policy decision. +- Several `MA0051` findings sit in very large files such as `SchemaConfigGenerator.cs` and `YamlConfigLoaderTests.cs`; + these may require more refactoring than is appropriate for a warning-reduction pass. +- A subset of the remaining `MA0048` warnings come from generic/non-generic type families that share the same base type + name, so the analyzer cannot be satisfied by a trivial file move alone. +- The current checkpoint has only been revalidated against the eight known regression tests above; a broader test rerun + is still pending if the next batch expands the edit surface again. +- The `GodotYamlConfigEnvironment` default-directory enumeration fix depends on host file-system and Godot native API + behavior; if a deterministic unit test cannot be kept stable in this WSL test host, retain build plus loader-smoke + validation and document the gap explicitly. +- The `AbstractArchitecture.InstallGodotModule` ordering fix can be asserted in pure managed code, but attempting to + exercise `AbstractArchitecture.Initialize()` directly in the current Godot test host crashes the native test + process. Keep this fix covered by project build plus adjacent Godot smoke tests unless a more stable harness is + introduced. +- The install-ordering regression is now covered by a stable direct-call Godot test. The destroy-observation path still + lacks a dedicated automated assertion because intercepting `GD.PushError` reliably in the current .NET test host is + not yet practical. +- Parallel `dotnet test` / `dotnet build` executions against the Windows-backed worktree still trigger transient + `obj/bin` file-lock failures; keep validation serial with `-m:1` in this environment. +- A direct Godot test that calls `GodotYamlConfigEnvironment.Default.ReadAllBytes("res://missing")` currently crashes the + .NET test host in this environment, so the missing-file contract fix for the default Godot file API path is covered + by code review plus project build and adjacent loader tests rather than a dedicated failing-path unit test. + +## Recommended Resume Step + +1. Continue from `ANALYZER-WARNING-REDUCTION-RP-001` only if the next batch is willing to take on structural fixes such + as long-method splits, delegate-shape rewrites, or public configuration-surface refactors. +2. Preserve the review-follow-up contracts now covered by tests: + `NumericExtensions.Between` null checking, `Result` default-value safety, longest-prefix logger-level selection, and + the `IApplyAbleSettings.ApplyAsync` rename. +3. If the next batch wants stronger Godot validation for missing-path reads, investigate a harness that can safely + exercise `FileAccess.GetFileAsBytes` failure paths without crashing the test host before adding a dedicated test. diff --git a/ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp001.md b/ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp001.md new file mode 100644 index 00000000..c93c21a2 --- /dev/null +++ b/ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp001.md @@ -0,0 +1,265 @@ +# Analyzer Warning Reduction History Trace + +> 该文档于 `2026-04-19` 从旧 `local-plan/traces/analyzer-warning-reduction-trace.md` 迁入,作为 +> `ANALYZER-WARNING-REDUCTION-RP-001` 的历史执行 trace 归档保留。 + +## Legacy Trace Content + +## 2026-04-18 + +### Stage: Discovery + +- Read `AGENTS.md` and `.ai/environment/tools.ai.yaml` before choosing commands. +- Confirmed the repository currently surfaces a large batch of Meziantou analyzer diagnostics during + `dotnet build GFramework.sln -c Release -nologo -clp:Summary;WarningsOnly`. +- Confirmed that `dotnet build ... -t:Rebuild` is required to force the compiler/analyzers to emit the warnings + reliably during project-level validation. +- Identified three independent work slices suitable for parallel handling: + - `GFramework.Core` plus closely related `GFramework.Cqrs` runtime warnings + - `GFramework.Godot` runtime warnings + - source generator warnings under `GFramework.Core.SourceGenerators`, `GFramework.Cqrs.SourceGenerators`, and + `GFramework.Godot.SourceGenerators` + +### Current Recovery Point + +- `ANALYZER-WARNING-REDUCTION-RP-001` + +### Stage: Delegation + +- Delegated `GFramework.Godot/**` low-risk warning reduction to worker `Newton`. + Scope: + - runtime-focused analyzer fixes only + - no edits outside `GFramework.Godot/**` except `GFramework.Godot.Tests/**` if validation strictly needs it + - avoid broad refactors and preserve behavior +- Delegated source generator low-risk warning reduction to worker `Aristotle`. + Scope: + - only `GFramework.Core.SourceGenerators/**`, `GFramework.Cqrs.SourceGenerators/**`, and + `GFramework.Godot.SourceGenerators/**` + - explicitly exclude `GFramework.Game.SourceGenerators/**` + - prioritize string-comparison, parameter-name, file/type-name, and localized method-splitting fixes + +### Stage: Main-Thread Focus + +- Reserved `GFramework.Core/**` and `GFramework.Cqrs/**` for the main thread because they dominate the current warning + surface and form the primary validation path. +- Confirmed the current worktree already contains an unrelated git status entry: + - `AD GFramework.Core/Directory.Build.props` + This file is not part of the current warning-reduction edit scope and must not be reverted. + +### Stage: Implementation + +- Applied low-risk runtime fixes across `GFramework.Core/**` and `GFramework.Cqrs/**`, including: + - `ConfigureAwait(false)` on context-independent asynchronous hot paths + - `StringComparer.Ordinal` / `StringComparison.Ordinal` for string-keyed collections and comparisons + - invariant-formatting fixes for logging/statistics paths + - targeted `ArgumentException` / `ArgumentNullException` overload cleanup + - localized file-structure cleanup for cache/config helper types +- Split a few file/type mismatches that were cheap to resolve without API churn: + - `GFramework.Cqrs/Internal/WeakTypePairCache.cs` + - `GFramework.Core/Logging/AppenderConfiguration.cs` + - `GFramework.Core/Logging/FilterConfiguration.cs` + - `GFramework.Core/Logging/ConfigurableLoggerFactory.cs` + - `GFramework.Core/Resource/ResourceCacheEntry.cs` + +### Stage: Worker Results + +- Worker `Aristotle` completed the source-generator slice and landed: + - `MA0006` string-comparison cleanup + - `MA0048` fix by renaming `LoggerDiagnostic.cs` to `LoggerDiagnostics.cs` + - localized `MA0015` cleanup + - small `MA0051` splits in `AutoRegisterModuleGenerator.cs` and `EnumExtensionsGenerator.cs` +- Worker `Newton` completed the Godot slice and landed: + - `ConfigureAwait(false)` cleanup where context capture was unnecessary + - string-comparison / comparer fixes + - invariant formatting and argument-overload cleanup + - file split for `GodotYamlConfigEnvironment` and `GodotYamlConfigDirectoryEntry` + - explicit observation of an async result in `AbstractArchitecture` +- Accepted residual worker findings: + - `GFramework.Core.SourceGenerators/Rule/ContextAwareGenerator.cs` still has a broader `MA0051` refactor remaining. + - `GFramework.Godot/Setting/Data/LocalizationMap.cs` still has two `MA0016` warnings on public `Dictionary`-typed + properties that were intentionally left unchanged to avoid public-surface / serialization impact. + +### Stage: Validation + +- Ran: + - `dotnet build GFramework.Core.SourceGenerators/GFramework.Core.SourceGenerators.csproj -c Release --no-restore` + - `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release -t:Rebuild --no-restore -p:TargetFramework=net8.0 -p:UseSharedCompilation=false -nologo -clp:Summary;WarningsOnly` + - `dotnet build GFramework.Core/GFramework.Core.csproj -c Release -t:Rebuild --no-restore -p:UseSharedCompilation=false -p:TargetFramework=net8.0 -nologo -clp:Summary;WarningsOnly` + - `dotnet build GFramework.Godot/GFramework.Godot.csproj -c Release --no-restore -p:TargetFramework=net8.0 -p:UseSharedCompilation=false` +- Results: + - `GFramework.Core.SourceGenerators`: `0 Warning(s)`, `0 Error(s)` + - `GFramework.Cqrs` (`net8.0` rebuild): `1 Warning(s)`, `0 Error(s)` + - `GFramework.Core` (`net8.0` rebuild): + - intermediate focused rebuild: `49 Warning(s)`, `0 Error(s)` + - latest focused rebuild: `31 Warning(s)`, `0 Error(s)` + - `GFramework.Godot`: worker-reported success after the Godot-owned fixes; broader direct builds still include a + large inherited `GFramework.Game` warning set from dependencies + +### Stage: Regression Repair + +- After the checkpoint commit, reproduced the user-reported test regressions from the current branch instead of + resuming warning cleanup blindly. +- Isolated the failures to three behavior changes: + - `LocalizationString` enabled `RegexOptions.ExplicitCapture` but still read unnamed capture groups, so every + localization placeholder fell back to the original token text. + - `ResultExtensions.Ensure` started constructing `ArgumentException` with a parameter name, which changed the + externally observed message contract covered by tests. + - `MicrosoftDiContainer.RegisterCqrsHandlersFromAssemblies` rejected null assembly items with `ArgumentException` + instead of the previously expected `ArgumentNullException`. +- Repaired the regressions by: + - switching the localization placeholder regex to named capture groups and reading those names explicitly + - restoring the message-only `ArgumentException` construction in `Ensure` + - restoring `ArgumentNullException` for null assembly entries in CQRS registration +- Revalidated with: + - `dotnet test GFramework.Core.Tests -c Release --filter "FullyQualifiedName~GetString_WithUnknownCompactFormatterArgs_ShouldIgnoreUnknownOptions|FullyQualifiedName~GetString_WithVariable_ShouldFormatCorrectly|FullyQualifiedName~GetString_WithMultipleVariables_ShouldFormatCorrectly|FullyQualifiedName~GetString_WithInvalidCompactFormatterArgs_ShouldFallbackToDefaultFormatting|FullyQualifiedName~GetString_WithCompactFormatterArgs_ShouldApplyOptions|FullyQualifiedName~GetString_WithCompactFormatter_ShouldFormatCorrectly|FullyQualifiedName~Ensure_Should_Create_ArgumentException_With_Message|FullyQualifiedName~RegisterCqrsHandlersFromAssemblies_WithNullAssemblyItem_Should_ThrowArgumentNullException"` +- Result: + - `8 Passed`, `0 Failed`, `0 Skipped` + +### Stage: Review Follow-Up + +- Applied a focused batch of review-driven fixes across `GFramework.Core`, `GFramework.Cqrs`, `GFramework.Godot`, + `GFramework.Game`, and the paired docs: + - completed missing XML exception contracts for public APIs such as `UiPageBehaviorFactory.Create` and + `ResourceManager.LoadAsync` / `PreloadAsync` + - aligned `NumericExtensions.Between` with its documented null contract + - removed duplicate XML documentation on `WaitForTask` + - made `Result` safe for `default(Result)` in equality, hashing, and string formatting + - restored Godot main-thread affinity by removing `ConfigureAwait(false)` from scene/module paths that touch node APIs + - observed async destroy failures in `AbstractArchitecture` instead of discarding them silently + - made `ConfigurableLoggerFactory.Dispose` idempotent under concurrent calls and switched logger-level lookup to + longest-prefix matching + - corrected CQRS weak-cache XML exception docs and weak-type-pair cache remarks + - changed `IApplyAbleSettings.Apply` to `ApplyAsync` and updated implementations, callers, tests, and settings docs + - fixed `GodotYamlConfigEnvironment` so Godot-path byte reads now throw on engine-reported read/open errors instead of + silently returning an empty byte array + +### Stage: Review Follow-Up Validation + +- Ran: + - `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~NumericExtensionsTests|FullyQualifiedName~ResultTests|FullyQualifiedName~ResultExtensionsTests|FullyQualifiedName~LoggingConfigurationTests"` + - `dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~SettingsSystemTests|FullyQualifiedName~GodotLocalizationSettingsTests"` + - `dotnet build GFramework.Godot.Tests/GFramework.Godot.Tests.csproj -c Release` + - `dotnet test GFramework.Godot.Tests/GFramework.Godot.Tests.csproj -c Release --filter "FullyQualifiedName~LoadAsync_Should_Use_Globalized_Res_Directory_Directly_When_Running_In_Editor"` +- Results: + - `GFramework.Core.Tests`: `101 Passed`, `0 Failed` + - `GFramework.Game.Tests`: `7 Passed`, `0 Failed` + - `GFramework.Godot.Tests` build: succeeded + - targeted `GFramework.Godot.Tests` smoke test: `1 Passed`, `0 Failed` +- Validation caveat: + - parallel `dotnet test` invocations against the Windows-backed worktree caused transient file-lock failures in + shared `obj/bin` outputs, so the final validation was rerun serially. + - a dedicated test for `GodotYamlConfigEnvironment.Default.ReadAllBytes("res://missing")` was attempted but removed + because the native Godot file API crashes the test host in this environment before managed assertions can observe + the failure. + +### Current Remaining Hotspots + +- `MA0051` long methods in: + - `GFramework.Cqrs/Internal/CqrsHandlerRegistrar.cs` + - `GFramework.Core/Architectures/ArchitectureLifecycle.cs` + - `GFramework.Core/Coroutine/CoroutineScheduler.cs` + - `GFramework.Core/Pause/PauseStackManager.cs` + - `GFramework.Core/StateManagement/Store.cs` +- `MA0048` file/type mismatches in generic/non-generic families and multi-type files such as: + - `AbstractCommand*` + - `AbstractAsyncCommand*` + - `AbstractQuery*` + - `EasyEventGeneric.cs` +- `MA0046` delegate-shape warnings in architecture/coroutine/logging callbacks. +- `MA0016` collection-abstraction warnings on some public logging configuration properties. + +### Immediate Next Step + +1. Stop at `ANALYZER-WARNING-REDUCTION-RP-001` for this batch unless the next round explicitly wants to take on the + remaining structural refactors. +2. If the next round resumes from this point, keep the restored localization / `Ensure` / CQRS registration test + contracts intact while tackling the remaining analyzer hotspots. + +### Stage: Review Follow-Up Batch 2 + +- Applied the current CodeRabbit follow-up fixes across `GFramework.Godot`, `GFramework.Core`, `GFramework.Cqrs`, and + `GFramework.Game.Tests`: + - moved `AbstractArchitecture.InstallGodotModule` anchor validation ahead of `module.Install(this)` so a missing + `SceneTree` anchor fails before any module-side effects occur + - normalized `ConfigurableLoggerFactory` configuration collections when JSON deserialization yields `null` + - merged `GetLogger(..., minLevel)` with `_config.MinLevel` using the stricter level and updated the XML contract + - added a compatibility disposal path for `AsyncLogAppender` + - made `GodotYamlConfigEnvironment` return `null` for inaccessible non-Godot directories and always call + `ListDirEnd()` for Godot directory iteration + - completed the missing XML exception contract on `WeakTypePairCache.GetValueOrDefaultForTesting` + - added XML summaries to the modified public `GodotLocalizationSettingsTests` methods +- Added focused regression tests for: + - `ConfigurableLoggerFactory` null-collection normalization + - caller `minLevel` lower-bound behavior + - factory disposal of `AsyncLogAppender` +- Planned validation for this batch: + - `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~ConfigurableLoggerFactoryTests|FullyQualifiedName~LoggingConfigurationTests"` + - `dotnet test GFramework.Godot.Tests/GFramework.Godot.Tests.csproj -c Release --filter "FullyQualifiedName~LoadAsync_Should_Use_Globalized_Res_Directory_Directly_When_Running_In_Editor"` + - `dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~GodotLocalizationSettingsTests"` + - `dotnet build GFramework.sln -c Release` +- Attempted to add a direct `AbstractArchitecture` regression test for the anchor-ordering change, but the current + Godot .NET test host crashes when initializing that runtime path. Removed the unstable test and kept the code change + covered by project build plus existing Godot loader smoke validation instead. + +### Stage: Review Follow-Up Batch 2 Validation + +- First attempted to run the targeted tests and solution build in parallel, but the Windows-backed worktree reproduced + the known `obj/bin` file-lock failures (`CS2012`, `MSB3026`, `MSB3883`). Switched all remaining validation to serial + invocations with `-m:1`. +- Ran: + - `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~ConfigurableLoggerFactoryTests" -m:1` + - `dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~GodotLocalizationSettingsTests" -m:1` + - `dotnet test GFramework.Godot.Tests/GFramework.Godot.Tests.csproj -c Release --filter "FullyQualifiedName~LoadAsync_Should_Use_Globalized_Res_Directory_Directly_When_Running_In_Editor" -m:1` + - `dotnet build GFramework.sln -c Release -m:1` +- Results: + - `GFramework.Core.Tests`: `3 Passed`, `0 Failed` + - `GFramework.Game.Tests`: `3 Passed`, `0 Failed` + - `GFramework.Godot.Tests` targeted smoke: `1 Passed`, `0 Failed` + - `GFramework.sln` release build: `698 Warning(s)`, `0 Error(s)` + +### Stage: Review Follow-Up Batch 3 + +- Applied the latest review-driven fixes across `GFramework.Godot`, `GFramework.Core`, `GFramework.Cqrs`, and + `GFramework.Core.Tests`: + - recorded Godot modules in `_extensions` immediately after `module.Install(this)` so failed attach paths still + participate in later teardown + - tightened `ConfigurableLoggerFactory.GetLogger` with explicit `name` null validation + - aligned the `minLevel` XML contract with the actual override precedence semantics + - added inline comments to the two-level weak cache `GetOrAdd` hot path + - replaced the reflection-based `AsyncLogAppender` disposal test with an observable post-disposal logger behavior + assertion +- Added a stable Godot-specific regression test that directly invokes `InstallGodotModule(...)` without going through + `Initialize()`, avoiding the native crash path while still covering the anchor-before-install contract. +- Documented the remaining test gap: + - the destroy-observation path introduced by `ObserveDestroyAsync` still lacks a dedicated automated assertion because + capturing `GD.PushError` deterministically in the current Godot .NET test host is not yet practical. + +### Stage: Review Follow-Up Batch 3 Validation + +- Ran: + - `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~ConfigurableLoggerFactoryTests" -m:1` + - `dotnet test GFramework.Godot.Tests/GFramework.Godot.Tests.csproj -c Release --filter "FullyQualifiedName~AbstractArchitectureModuleInstallationTests" -m:1` + - `dotnet build GFramework.sln -c Release -m:1` +- Results: + - `GFramework.Core.Tests`: `5 Passed`, `0 Failed` + - `GFramework.Godot.Tests` targeted install-ordering test: `1 Passed`, `0 Failed` + - `GFramework.sln` release build: `847 Warning(s)`, `0 Error(s)` + +### Stage: Review Follow-Up Batch 4 + +- Applied the latest review-driven fixes across `GFramework.Core`, `GFramework.Core.Tests`, and the Godot settings docs: + - made `ConfigurableLoggerFactory` reject `appenders` entries deserialized as `null` with an explicit + `InvalidOperationException` instead of deferring to an unclear downstream failure + - extended the constructor XML docs to describe that validation contract explicitly + - added a focused regression test for `appenders: [null]` + - fixed the `docs/zh-CN/godot/setting.md` audio examples so both `SetMasterVolume` samples compile while awaiting + `audioSettings.ApplyAsync()` + +### Stage: Review Follow-Up Batch 4 Validation + +- Ran: + - `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~ConfigurableLoggerFactoryTests" -m:1` + - `dotnet build GFramework.Core/GFramework.Core.csproj -c Release -m:1` +- Results: + - `GFramework.Core.Tests`: `6 Passed`, `0 Failed` + - `GFramework.Core` release build: `79 Warning(s)`, `0 Error(s)` 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 new file mode 100644 index 00000000..7fa5cf09 --- /dev/null +++ b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md @@ -0,0 +1,52 @@ +# Analyzer Warning Reduction 跟踪 + +## 目标 + +继续以“优先低风险、保持行为兼容”为原则收敛当前仓库的 Meziantou analyzer warnings,并在首轮大规模清理完成后, +判断剩余结构性 warning 是否值得在下一轮继续推进。 + +## 当前恢复点 + +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-001` +- 当前阶段:`Phase 1` +- 当前焦点: + - 已将旧 `local-plan/` 迁入 `ai-plan/public/analyzer-warning-reduction/`,active 入口只保留当前恢复信息 + - 基于现有剩余热点,评估 `MA0051`、`MA0048`、`MA0046` 与少量 `MA0016` 是否适合继续在同一主线上处理 + - 若继续推进,优先选择不引入 API rename、公共契约漂移或 Godot 宿主不稳定测试的切入点 + +## 当前状态摘要 + +- 已完成 `GFramework.Core`、`GFramework.Cqrs`、`GFramework.Godot` 与部分 source generator 的低风险 warning 清理 +- 已完成多轮 CodeRabbit follow-up 修复,并用定向测试与项目/解决方案构建验证了关键回归风险 +- 当前剩余 warning 已集中到长方法、文件/类型命名冲突、delegate 形状和少量公共集合抽象接口问题 + +## 当前活跃事实 + +- 当前主题仍是 active topic,因为剩余结构性 warning 是否继续推进尚未决策 +- `RP-001` 的详细实现历史、测试记录和 warning 热点清单已归档到主题内 `archive/` +- 当前工作树分支 `fix/analyzer-warning-reduction-batch` 已在 `ai-plan/public/README.md` 建立 topic 映射 + +## 当前风险 + +- 结构性重构风险:剩余 `MA0051` 与 `MA0048` 可能要求较大的文件拆分或类型重命名 + - 缓解措施:只在下一轮明确接受结构调整成本时再继续推进,不在恢复点模糊的情况下顺手扩面 +- 测试宿主稳定性风险:部分 Godot 失败路径在当前 .NET 测试宿主下仍不稳定 + - 缓解措施:继续优先使用稳定的 targeted test、项目构建和相邻 smoke test 组合验证 +- 多目标框架 warning 解释风险:同一源位置会在多个 target framework 下重复计数 + - 缓解措施:继续以唯一源位置和 warning 家族为主要决策依据,而不是只看原始 warning 总数 + +## 活跃文档 + +- 历史跟踪归档:[analyzer-warning-reduction-history-rp001.md](../archive/todos/analyzer-warning-reduction-history-rp001.md) +- 历史 trace 归档:[analyzer-warning-reduction-history-rp001.md](../archive/traces/analyzer-warning-reduction-history-rp001.md) + +## 验证说明 + +- `RP-001` 的详细 warning 清理、回归修复与定向验证命令均已迁入主题内历史归档 +- active 跟踪文件只保留当前恢复点、活跃事实、风险与下一步,不再重复保存已完成阶段的长篇历史 + +## 下一步 + +1. 若要继续该主题,先读 active tracking,再按需展开历史归档中的 warning 热点与验证记录 +2. 从 `MA0051`、`MA0048`、`MA0046` 中只选一个结构性切入点继续,不要在同一轮同时扩多个风险面 +3. 若本主题确认暂缓,可保持当前归档状态,不需要再恢复 `local-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 new file mode 100644 index 00000000..5e42fb93 --- /dev/null +++ b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md @@ -0,0 +1,32 @@ +# Analyzer Warning Reduction 追踪 + +## 2026-04-19 + +### 阶段:local-plan 迁移收口(RP-001) + +- 复核当前工作树后确认:`local-plan/` 仅保存 analyzer warning reduction 主题的 durable recovery state,不应继续作为 + worktree-root 遗留目录存在 +- 按 `ai-plan` 治理规则建立 `ai-plan/public/analyzer-warning-reduction/` 主题目录,并补齐: + - `todos/` + - `traces/` + - `archive/todos/` + - `archive/traces/` +- 将旧 `local-plan` 中的详细 tracking / trace 迁入主题内历史归档,保留 `RP-001` 的完整实现与验证上下文 +- 新建精简版 active tracking / trace 入口,并在 `ai-plan/public/README.md` 中建立 + `fix/analyzer-warning-reduction-batch` -> `analyzer-warning-reduction` 的 worktree 映射 +- 删除旧 `local-plan` 文件,避免 `boot` 或后续协作者继续从过时目录恢复 +- 验证通过: + - `find ai-plan/public/analyzer-warning-reduction -maxdepth 3 -type f | sort` + - `dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release -p:RestoreFallbackFolders=` + +### Archive Context + +- 历史跟踪归档: + - `ai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp001.md` +- 历史 trace 归档: + - `ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp001.md` + +### 下一步 + +1. 后续若继续 analyzer warning reduction,只从 `ai-plan/public/analyzer-warning-reduction/` 进入,不再恢复 `local-plan/` +2. 若 active 入口再次积累多轮已完成且已验证阶段,继续按同一模式迁入该主题自己的 `archive/`