Skip to content

Fix/analyzer warning reduction batch#295

Merged
GeWuYou merged 14 commits into
mainfrom
fix/analyzer-warning-reduction-batch
Apr 27, 2026
Merged

Fix/analyzer warning reduction batch#295
GeWuYou merged 14 commits into
mainfrom
fix/analyzer-warning-reduction-batch

Conversation

@GeWuYou

@GeWuYou GeWuYou commented Apr 27, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

发布说明

  • 重构

    • 在多目标框架下统一并改进内部同步(在 .NET9+ 使用新锁实现,旧目标保留兼容行为)
    • 统一异步 await/ConfigureAwait 行为,规范字符串比较为 Ordinal
  • 测试

    • 更新并收敛多处并发/同步相关测试以匹配新的同步与异步模式
  • 文档

    • 更新分析/追踪与技能说明以改进失败测试提取与报告格式
  • 任务

    • 扩展并归档分析器警告减少的跟踪与历史记录

GeWuYou added 11 commits April 27, 2026 07:40
- 修复 UiRouterBase 中缺少参数名的 ArgumentException 调用

- 更新 UI 键比较与层级字典为 Ordinal 语义,消除字符串与比较器相关警告
- 修复数据仓库异步存储调用的 ConfigureAwait(false) 使用,消除目标 MA0004 警告

- 更新 UnifiedSettingsDataRepository 的字符串键字典 comparer 为 StringComparer.Ordinal,消除目标 MA0002 警告

- 保留场景切换流程在当前上下文继续执行,并显式使用 ConfigureAwait(true) 说明上下文约束
- 迁移 Events、Property、State 与 Coroutine 中 7 个类型的监视器字段到 NET9_0_OR_GREATER 专用 Lock 模式
- 保持 net8.0 的 object 回退路径以兼容多目标构建
- 更新 BindableProperty 的同步注释以匹配新的多目标同步原语
- 修复 Core 与 Cqrs 中资源、日志、配置缓存的 MA0158 专用锁警告

- 修复 SaveRepository 与 SceneRouterBase 的残留分析器警告

- 更新 analyzer-warning-reduction 跟踪文档与最新构建验证结果
- 修复 SettingsModel 中异步仓储加载与保存流程缺少 ConfigureAwait(false) 的 analyzer 警告

- 保持设置模型初始化、保存、应用阶段的生命周期与事件触发语义不变
- 修复 RouterBase 中路由键比较的 MA0006,显式使用 Ordinal 字符串比较

- 修复 UiInteractionProfiles 中位掩码判定的 MA0099,改为与显式枚举值比较
- 重构 GameConfigBootstrap 的热重载启动流程,提取状态准备、结果提交与失败回滚辅助方法

- 保持现有锁保护、异常路径与监听句柄释放语义不变,消除 StartHotReload 的 MA0051 warning
- 修复 SettingsModel 与 GameConfigBootstrap 的残留 MA0158 专用锁警告

- 更新 analyzer-warning-reduction 恢复点与第二轮构建验证结果
- 修复 PauseStackManagerTests 并发测试中的锁声明,针对 net9 以上使用专用 Lock。

- 保持 net8.0 回退到 object 锁,确保多目标兼容且测试行为不变。
- 修复 Task.Run 内 await using 的异步释放上下文捕获 warning
- 保持 AsyncKeyLockManager 并发测试语义与可读性不变
- 更新 analyzer-warning-reduction 跟踪文档的第三轮结果与最新 stop-condition 指标

- 记录 Core.Tests 批次验证结果与默认收口建议
@coderabbitai

coderabbitai Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@GeWuYou has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 35 minutes and 51 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 79b9717c-4e46-4f8b-a1ee-dffefcc456d1

📥 Commits

Reviewing files that changed from the base of the PR and between 1c87272 and 067d72f.

📒 Files selected for processing (5)
  • .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py
  • .agents/skills/gframework-pr-review/scripts/test_fetch_current_pr_review.py
  • GFramework.Core.Tests/Extensions/AsyncExtensionsTests.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
📝 Walkthrough

Walkthrough

本 PR 在多处通过条件编译在 .NET 9.0+ 使用 System.Threading.Lock 替换 object 锁、在多个异步调用处添加或调整 ConfigureAwait(true/false)、强化若干字符串比较为 StringComparison.Ordinal、并重构部分同步启动流程与测试锁获取方式。

Changes

Cohort / File(s) Summary
条件化同步原语(核心库)
GFramework.Core/Configuration/ConfigurationManager.cs, GFramework.Core/Coroutine/CoroutineStatistics.cs, GFramework.Core/Events/EventStatistics.cs, GFramework.Core/Events/FilterableEvent.cs, GFramework.Core/Events/PriorityEvent.cs, GFramework.Core/Events/WeakEvent.cs
为多处 lock 字段引入 #if NET9_0_OR_GREATER 分支,NET9+ 使用 System.Threading.Lock,旧目标框架保留 object。无逻辑变更。
条件化同步原语(日志/资源/状态)
GFramework.Core/Logging/Appenders/FileAppender.cs, GFramework.Core/Logging/Appenders/RollingFileAppender.cs, GFramework.Core/Logging/Filters/SamplingFilter.cs, GFramework.Core/Property/BindableProperty.cs, GFramework.Core/Resource/ResourceCache.cs, GFramework.Core/Resource/ResourceHandle.cs, GFramework.Core/Resource/ResourceManager.cs, GFramework.Core/State/StateMachine.cs
同样引入 NET9+ 的 System.Threading.Lock 替换方案,并规范化若干文件末尾换行。锁用法位置不变。
游戏模块/仓储:锁与异步控制
GFramework.Game/Config/GameConfigBootstrap.cs, GFramework.Game/Setting/SettingsModel.cs, GFramework.Game/Data/SaveRepository.cs, GFramework.Cqrs/Internal/WeakKeyCache.cs
引入条件化锁(NET9+ 使用 Lock),并在 GameConfigBootstrap 中拆分出三个私有同步辅助方法以整理热重载启动流程;SaveRepository 同时包含大量 ConfigureAwait 调整(见下)。
持久层与数据仓库:ConfigureAwait 应用
GFramework.Game/Data/DataRepository.cs, GFramework.Game/Data/UnifiedSettingsDataRepository.cs, GFramework.Game/Data/SaveRepository.cs
在读取/写入/备份/迁移等异步调用处统一添加 .ConfigureAwait(false)(SaveRepository 也调整了迁移字典的同步锁为条件化 Lock)。UnifiedSettingsDataRepository 还将若干字典改为显式 StringComparer.Ordinal
场景/路由/UI:比较语义与上下文保留
GFramework.Game/Routing/RouterBase.cs, GFramework.Game/Scene/SceneRouterBase.cs, GFramework.Game/UI/UiRouterBase.cs, GFramework.Game/UI/UiInteractionProfiles.cs
将键比较改为 string.Equals(..., StringComparison.Ordinal)(更明确的序数比较);SceneRouterBase 在若干生命周期回调 await 处显式使用 .ConfigureAwait(true) 保留上下文;UiInteractionProfiles 使用枚举掩码比较改为对比 UiInputActionMask.None
测试适配与并发测试重构
GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs, GFramework.Core.Tests/Concurrency/AsyncKeyLockManagerTests.cs, GFramework.Core.Tests/Pause/PauseStackManagerTests.cs, GFramework.Core.Tests/Extensions/AsyncExtensionsTests.cs, GFramework.Game.Tests/Setting/SettingsModelTests.cs
测试中引入 ConfigureAwait 使用调整、将锁获取改为框架感知的 Lock/lock 处理或使用块作用域的 await using,并新增测试辅助以在正确持锁上下文内创建并返回任务进行断言。部分测试增强对 ArgumentException.ParamName 的断言。
文档与工具链解析更新
ai-plan/public/analyzer-warning-reduction/..., .agents/skills/gframework-pr-review/..., ai-plan/public/.../archive/*
更新分析器警告消除计划文档与跟踪条目;改进 gframework-pr-review 脚本以结构化解析测试报告表格并导出 failed_test_details 字段。

Sequence Diagram(s)

(无序列图 — 本次变更主要为锁原语替换、await 配置与局部重构,未引入新的跨组件顺序控制流)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了主要变更内容:批量修复分析器警告,涵盖条件编译锁、ConfigureAwait调用、字符串比较等多个方面的改进。
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/analyzer-warning-reduction-batch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown

Summary

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Other ❓ Flaky 🍂 Duration ⏱️
2156 2155    ↓1 1    ↑1 0 0 0 35.3s    ↓1.1s

Test Results

failed 1 failed ↑1
passed 2155 passed ↓1

Details

tests 2156 tests
clock 35.3s ↓1.1s
tool nunit
build CI - Build & Test arrow-right build-and-test link #986
pull-request Fix/analyzer warning reduction batch link #295

Failed Tests

SettingsModelTests arrow-right RegisterMigration_During_Cache_Rebuild_Should_Not_Leave_Stale_Type_Cache

Insights

Average Tests per Run Total Flaky Tests Total Failed Slowest Test (p95)
2149 0 3 4.7s

Fail Rate

Fail Rate 0.00%
Test 📝 Results 📊 Passed ✅ Failed ❌ Fail Rate (%) 📈
ILogAppender_Flush_Should_Raise_OnFlushCompleted_Only_Once 31 30 1 3.23    ↓0.10
RegisterMigration_During_Cache_Rebuild_Should_Not_Leave_Stale_Type_Cache 38 37 1 2.63    ↑2.63
Run_Should_Assign_Globally_Unique_Reference_Metadata_Member_Names 39 38 1 2.56    ↓0.07

build-and-test: Run #986

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Pending ⏳ Other ❓ Flaky 🍂 Duration ⏱️
2156 2155 1 0 0 0 0 35.3s

Some tests failed!

Name Failure Message
❌ RegisterMigration_During_Cache_Rebuild_Should_Not_Leave_Stale_Type_Cache Multiple failures or warnings in test: 1) Assert.That(initializeTask.IsCompleted, Is.False) Expected: False But was: True
 at GFramework.Game.Tests.Setting.SettingsModelTests.<>c__DisplayClass4_0.<RegisterMigration_During_Cache_Rebuild_Should_Not_Leave_Stale_Type_Cache>b__3() in /home/runner/work/GFramework/GFramework/GFramework.Game.Tests/Setting/SettingsModelTests.cs:line 151

at NUnit.Framework.Assert.Multiple(TestDelegate testDelegate)
at GFramework.Game.Tests.Setting.SettingsModelTests.RegisterMigration_During_Cache_Rebuild_Should_Not_Leave_Stale_Type_Cache() in /home/runner/work/GFramework/GFramework/GFramework.Game.Tests/Setting/SettingsModelTests.cs:line 149
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
at GFramework.Game.Tests.Setting.SettingsModelTests.RegisterMigration_During_Cache_Rebuild_Should_Not_Leave_Stale_Type_Cache()

  1. Assert.That(registerTask.IsCompleted, Is.False)
    Expected: False
    But was: True
 at GFramework.Game.Tests.Setting.SettingsModelTests.<>c__DisplayClass4_0.<RegisterMigration_During_Cache_Rebuild_Should_Not_Leave_Stale_Type_Cache>b__3() in /home/runner/work/GFramework/GFramework/GFramework.Game.Tests/Setting/SettingsModelTests.cs:line 152

at NUnit.Framework.Assert.Multiple(TestDelegate testDelegate)
at GFramework.Game.Tests.Setting.SettingsModelTests.RegisterMigration_During_Cache_Rebuild_Should_Not_Leave_Stale_Type_Cache() in /home/runner/work/GFramework/GFramework/GFramework.Game.Tests/Setting/SettingsModelTests.cs:line 149
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
at GFramework.Game.Tests.Setting.SettingsModelTests.RegisterMigration_During_Cache_Rebuild_Should_Not_Leave_Stale_Type_Cache()

Slowest Tests

Test 📝 Results 📊 Duration (avg) ⏱️ Duration (p95) ⏱️
SendRequestAsync_Should_ResolveCqrsRuntime_OnlyOnce_When_AccessedConcurrently 39 4.1s 4.7s
Does_Not_Report_When_FieldInjectedModel_Is_Registered 39 2.2s 2.5s
Generates_Scene_Behavior_Boilerplate 39 1.9s 2.0s
CleanupDuringAcquire_Should_NotCauseRaceCondition 39 1.1s 1.1s
Append_ShouldNotBlock 39 1.0s 1.0s
Flush_Should_Raise_OnFlushCompleted_With_Sender_And_Result 32 63ms 1.0s
Context_Caching_Should_Improve_Performance 39 782ms 792ms
PendingCount_ShouldReflectQueuedEntries 39 501ms 501ms
Cleanup_Should_NotRemoveActiveLocks 39 404ms 406ms
Cleanup_Should_RemoveUnusedLocks 39 401ms 402ms

± Comparison with run #980 at 7da232d | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 39 runs.

Github Test Reporter by CTRF 💚

@greptile-apps

greptile-apps Bot commented Apr 27, 2026

Copy link
Copy Markdown

Greptile Summary

This PR reduces analyzer warnings across the GFramework.Core and GFramework.Game assemblies through three main changes: (1) multi-target lock modernization (System.Threading.Lock on .NET 9+, object on .NET 8), (2) systematic addition of ConfigureAwait to every await call in library code, and (3) standardizing string comparisons to StringComparison.Ordinal. Tests are updated to match, and the GameConfigBootstrap.StartHotReload logic is refactored into private helpers without any semantic change.

Confidence Score: 5/5

Safe to merge — all changes are analyzer-warning suppressions with no semantic regressions.

Every change is either a mechanical warning fix (ConfigureAwait, StringComparison.Ordinal, Lock type) or a structurally equivalent refactor (GameConfigBootstrap helper extraction). Tests are updated consistently and the SettingsModelTests.WithSynchronizationLockHeld helper correctly handles the Lock/Monitor semantic difference on .NET 9+. No P0/P1 findings were identified.

No files require special attention.

Important Files Changed

Filename Overview
GFramework.Game/Config/GameConfigBootstrap.cs Extracted BeginHotReloadStart / CompleteHotReloadStart / ResetHotReloadStartAfterFailure helper methods from StartHotReload; semantics are preserved and lock/field management is identical to the original.
GFramework.Game/Scene/SceneRouterBase.cs Adds ConfigureAwait(true) to all scene transition awaits (intentional for game-engine UI context) and switches Contains() to StringComparison.Ordinal.
GFramework.Core.Tests/Concurrency/AsyncKeyLockManagerTests.cs Migrates await using var to the await using ((...).ConfigureAwait(false)) block pattern so DisposeAsync is also configured; logic is unchanged.
GFramework.Core.Tests/Extensions/AsyncExtensionsTests.cs WithRetry_Should_Respect_ShouldRetry_Predicate changed from async Task to void (Assert.ThrowsAsync blocks); removes the racy Task.Delay(50) and adds richer exception assertions.
GFramework.Game.Tests/Setting/SettingsModelTests.cs Adds WithSynchronizationLockHeld helper that correctly uses Lock.EnterScope() on .NET 9+ (avoiding Monitor fallback when locking a System.Threading.Lock via reflection).
GFramework.Game/UI/UiRouterBase.cs ArgumentException gains paramName arg; Contains/IsTop/GetPagesByKey use StringComparison.Ordinal; TryGetValue replaces ContainsKey+index lookup for inner layer dictionary init.
GFramework.Game/Data/UnifiedSettingsDataRepository.cs Pervasive ConfigureAwait(false) additions; _typeRegistry and LoadAllAsync result dictionary now use StringComparer.Ordinal.
.agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py Replaces brittle positional regex stat extraction with structured Markdown table parsing; adds detailed failed-test HTML table parsing for richer CI report output.

Sequence Diagram

sequenceDiagram
    participant Caller
    participant GameConfigBootstrap
    participant Lock as _stateGate (Lock)
    participant Loader as YamlConfigLoader

    Caller->>GameConfigBootstrap: StartHotReload()
    GameConfigBootstrap->>Lock: BeginHotReloadStart() — acquire
    Lock-->>GameConfigBootstrap: loader (validated, flags set)
    GameConfigBootstrap->>Loader: EnableHotReload(Registry, options)
    Loader-->>GameConfigBootstrap: hotReload : IUnRegister

    GameConfigBootstrap->>Lock: CompleteHotReloadStart() — acquire
    alt Stop/Dispose arrived mid-start
        Lock-->>GameConfigBootstrap: shouldStop=true
        GameConfigBootstrap->>hotReload: UnRegister()
    else Normal completion
        Lock-->>GameConfigBootstrap: _hotReload assigned, hotReload=null
    end

    alt Exception in EnableHotReload or CompleteHotReloadStart
        GameConfigBootstrap->>Lock: ResetHotReloadStartAfterFailure()
        GameConfigBootstrap->>hotReload: UnRegister()
        GameConfigBootstrap-->>Caller: rethrow
    end
Loading

Reviews (3): Last reviewed commit: "fix(tooling): 收口PR评审遗留nitpick" | Re-trigger Greptile

@github-actions

github-actions Bot commented Apr 27, 2026

Copy link
Copy Markdown

⚠️MegaLinter analysis: Success with warnings

Descriptor Linter Files Fixed Errors Warnings Elapsed time
⚠️ CSHARP dotnet-format yes 1 no 5.38s
✅ REPOSITORY gitleaks yes no no 7.38s
✅ REPOSITORY trufflehog yes no no 6.33s

Detailed Issues

⚠️ CSHARP / dotnet-format - 1 error
Welcome to .NET 9.0!
---------------------
SDK Version: 9.0.114

----------------
Installed an ASP.NET Core HTTPS development certificate.
To trust the certificate, run 'dotnet dev-certs https --trust'
Learn about HTTPS: https://aka.ms/dotnet-https

----------------
Write your first app: https://aka.ms/dotnet-hello-world
Find out what's new: https://aka.ms/dotnet-whats-new
Explore documentation: https://aka.ms/dotnet-docs
Report issues and find source on GitHub: https://github.com/dotnet/core
Use 'dotnet --help' to see available commands or visit: https://aka.ms/dotnet-cli
--------------------------------------------------------------------------------------
Unhandled exception: System.Exception: Restore operation failed.
   at Microsoft.CodeAnalysis.Tools.CodeFormatter.OpenMSBuildWorkspaceAsync(String solutionOrProjectPath, WorkspaceType workspaceType, Boolean noRestore, Boolean requiresSemantics, String binaryLogPath, Boolean logWorkspaceWarnings, ILogger logger, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Tools.CodeFormatter.FormatWorkspaceAsync(FormatOptions formatOptions, ILogger logger, CancellationToken cancellationToken, String binaryLogPath)
   at Microsoft.CodeAnalysis.Tools.FormatCommandCommon.FormatAsync(FormatOptions formatOptions, ILogger`1 logger, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Tools.Commands.RootFormatCommand.FormatCommandDefaultHandler.InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken)
   at System.CommandLine.Invocation.InvocationPipeline.InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken)

See detailed reports in MegaLinter artifacts
Set VALIDATE_ALL_CODEBASE: true in mega-linter.yml to validate all sources, not only the diff

MegaLinter is graciously provided by OX Security
Show us your support by starring ⭐ the repository

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (6)
ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md (1)

31-44: 建议把“已完成 slice 明细”进一步归档,active 文档只保留摘要真值。

这里的明细已经较长,后续继续推进会让 active todo 膨胀。建议仅保留“当前恢复点核心事实 + 归档指针”,把已完成切片细节迁到 archive/todos 文档。

As per coding guidelines: “When completed and validated stages begin to accumulate, contributors MUST archive their detailed history out of the active todos/ and traces/ entry files in the same change, keeping only the current recovery point, active facts, active risks, immediate next step, and pointers to archive files.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md`
around lines 31 - 44, This active todo file contains too much completed detail
(sections like “当前批次已完成的 warning slice”, “当前批次已完成并提交的收口”, and “当前批次已完成的第三轮
slice”); move those detailed lists into a new archive document (e.g.,
archive/todos/analyzer-warning-reduction-archive.md) and replace them here with
a short summary that preserves only the current recovery point/core facts,
active risks, immediate next step, and a pointer/link to the archive file; keep
the existing identifiers (e.g., entries mentioning GFramework.Core,
GFramework.Game, and commit `fb0a55f`) as archive references so the active
document only contains the concise recovery summary and an archive pointer.
GFramework.Game/Scene/SceneRouterBase.cs (1)

224-224: 生命周期回调统一 ConfigureAwait(true),与 369 行设计说明对齐。

OnLoadAsync/OnPauseAsync/OnEnterAsync/OnExitAsync/OnUnloadAsync/OnResumeAsync 这些回调及 ExecuteEnterGuardsAsync/ExecuteLeaveGuardsAsync 的等待点保留同步上下文,符合"场景生命周期可能依赖引擎线程"的注释意图。

注意:父类 RouterBase 内部 ExecuteEnterGuardsAsync/ExecuteLeaveGuardsAsyncguard.CanEnterAsync/CanLeaveAsync 处使用了 ConfigureAwait(false),这意味着守卫自身的实现不能强假定回到捕获的同步上下文。当前 SceneRouterBase 在外层使用 ConfigureAwait(true) 没有问题(外层等待点会重新捕获上下文),但建议在守卫接口或文档中明确这一点,避免将来子类守卫误以为始终在引擎线程上恢复。

Also applies to: 237-237, 243-243, 250-250, 297-297, 306-306, 309-309, 318-318

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@GFramework.Game/Scene/SceneRouterBase.cs` at line 224, Change the await calls
for scene lifecycle callbacks and guard execution to capture the sync context by
using ConfigureAwait(true): specifically update awaits that call
ExecuteEnterGuardsAsync(sceneKey, param), ExecuteLeaveGuardsAsync(...), and the
lifecycle methods OnLoadAsync, OnPauseAsync, OnEnterAsync, OnExitAsync,
OnUnloadAsync, OnResumeAsync so they all append .ConfigureAwait(true) at the
await points; keep in mind RouterBase internally uses ConfigureAwait(false) when
calling guard.CanEnterAsync/CanLeaveAsync so add or update
documentation/comments on the guard interface/implementations to make clear
guards cannot assume resumption on the engine thread.
GFramework.Game/Config/GameConfigBootstrap.cs (1)

309-344: 可选:CompleteHotReloadStart 的参数复用 + 返回值语义略隐晦。

当前实现既改写入参 hotReload 又把它作为返回值返回(成功路径上恒为 null),调用方再用返回值覆盖自己的局部变量。逻辑无误,但读者需要走两遍栈才能确定 catch 中的 hotReload 实际持有的对象。可考虑改为显式返回 bool(或一个局部 out IUnRegister? handleToDispose),让"提交成功""需要释放""异常未提交"三种状态在签名上自解释,进一步降低后续维护时的心智负担。非阻塞,留给作者评估。

♻️ 备选签名示意
-    private IUnRegister? CompleteHotReloadStart(IUnRegister? hotReload)
+    /// <summary>
+    ///     在锁内提交热重载句柄;若期间收到 Stop/Dispose,则把句柄交还给调用方释放。
+    /// </summary>
+    /// <returns>需要在锁外释放的句柄;若已成功发布则返回 <see langword="null" />。</returns>
+    private IUnRegister? CompleteHotReloadStart(IUnRegister hotReload)
     {
-        var shouldStop = false;
         lock (_stateGate)
         {
             try
             {
                 ThrowIfDisposedCore();
-
-                if (_stopHotReloadAfterStart)
-                {
-                    shouldStop = true;
-                    _stopHotReloadAfterStart = false;
-                }
-                else
-                {
-                    _hotReload = hotReload;
-                    hotReload = null;
-                }
+                if (_stopHotReloadAfterStart)
+                {
+                    _stopHotReloadAfterStart = false;
+                    return hotReload; // caller unregisters outside the lock
+                }
+
+                _hotReload = hotReload;
+                return null;
             }
             finally
             {
                 _isStartingHotReload = false;
             }
         }
-
-        if (shouldStop)
-        {
-            hotReload?.UnRegister();
-            return null;
-        }
-
-        return hotReload;
     }

调用点相应改为:

-            hotReload = CompleteHotReloadStart(hotReload);
+            var handleToDispose = CompleteHotReloadStart(hotReload);
+            hotReload = null;
+            handleToDispose?.UnRegister();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@GFramework.Game/Config/GameConfigBootstrap.cs` around lines 309 - 344, The
current CompleteHotReloadStart(IUnRegister? hotReload) mutates its input and
returns the same parameter (null on success), which makes caller logic and
exception paths harder to follow; change the method signature to explicitly
return a bool success (or add an out IUnRegister? handleToDispose) so the three
states ("committed to _hotReload", "must dispose incoming handle", "not
committed/exception") are explicit, update the body to stop mutating and
returning the parameter (set _hotReload when committing, set shouldStop and
assign handleToDispose when needed, clear _isStartingHotReload in finally) and
update callers to use the new boolean/out contract, referencing
CompleteHotReloadStart, _hotReload, _stopHotReloadAfterStart,
_isStartingHotReload and IUnRegister/UnRegister in your changes.
GFramework.Core.Tests/Pause/PauseStackManagerTests.cs (1)

434-438: 条件编译切换到 System.Threading.Lock 的写法正确,可选优化命名空间。

#if NET9_0_OR_GREATER 条件编译以及 lock (lockObj)System.Threading.Lock 实例的使用是 C# 13/.NET 9 支持的官方模式,编译器会识别并发出 Lock.EnterScope(),行为正确。

可选优化:当前使用了完全限定名 System.Threading.Lock,由于仓库的 GlobalUsings.cs 已提供 System.Threading,可直接写 new Lock() 以保持代码风格一致;或者将测试中的 lockObj 改名为 pauseTokensLock 等更具语义的名称。

♻️ 命名空间简化示例
 `#if` NET9_0_OR_GREATER
-        var lockObj = new System.Threading.Lock();
+        var lockObj = new Lock();
 `#else`
         var lockObj = new object();
 `#endif`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@GFramework.Core.Tests/Pause/PauseStackManagerTests.cs` around lines 434 -
438, The conditional compilation block uses a fully-qualified
System.Threading.Lock instance named lockObj; update it to use the globally
imported type and clearer naming: replace "new System.Threading.Lock()" with
"new Lock()" under the NET9_0_OR_GREATER branch (relying on the GlobalUsings.cs
System.Threading import) and rename the variable lockObj to a more descriptive
name such as pauseTokensLock (update all usages in the PauseStackManagerTests
class accordingly) to keep style and semantics consistent.
GFramework.Core.Tests/Concurrency/AsyncKeyLockManagerTests.cs (1)

50-50: await using 嵌套 ConfigureAwait 写法过于冗余,建议简化。

await using ((await manager.AcquireLockAsync(...).ConfigureAwait(false)).ConfigureAwait(false)) 这种双重 ConfigureAwait(false) 的语法功能上正确(外层是对返回的 IAsyncDisposable 调用扩展方法返回 ConfiguredAsyncDisposable,内层是对 awaiter 的配置),但可读性较差。在 NUnit 测试上下文中并不存在 SynchronizationContextConfigureAwait(false) 本身并无运行时收益,仅是为了消除 CA2007 警告。

建议两选其一以提升可读性:

  1. 在测试项目级别抑制 CA2007(更简洁);
  2. 拆分为两步绑定句柄。
♻️ 拆分写法示例(以第 50 行为例)
-                await using ((await manager.AcquireLockAsync("same-key").ConfigureAwait(false)).ConfigureAwait(false))
-                {
-                    executionOrder.Add(index);
-                    await Task.Delay(10).ConfigureAwait(false);
-                }
+                var handle = await manager.AcquireLockAsync("same-key").ConfigureAwait(false);
+                await using (handle.ConfigureAwait(false))
+                {
+                    executionOrder.Add(index);
+                    await Task.Delay(10).ConfigureAwait(false);
+                }

Also applies to: 80-80, 124-124, 148-148, 306-306

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@GFramework.Core.Tests/Concurrency/AsyncKeyLockManagerTests.cs` at line 50,
The nested "await using" with double ConfigureAwait is verbose; simplify by
splitting the acquisition and disposal into two steps: call
manager.AcquireLockAsync(...) with ConfigureAwait(false) and assign to a local
(e.g. var handle = await
manager.AcquireLockAsync("same-key").ConfigureAwait(false)); then use await
using (handle) { ... } to dispose; alternatively suppress CA2007 at the test
project level if you prefer to remove ConfigureAwait calls entirely; update the
occurrences around manager.AcquireLockAsync and any tests using the same pattern
(those at the other noted locations) accordingly.
GFramework.Core/Events/PriorityEvent.cs (1)

24-30: 建议:将多目标锁类型的条件编译抽取为共享别名,避免在 15+ 文件中重复

当前 PR 在 PriorityEvent.csWeakEvent.csBindableProperty.csStateMachine.csStoreSelection.csCoroutineStatistics.csRollingFileAppender.csFileAppender.csSamplingFilter.csResourceCache.csResourceManager.csWeakKeyCache.cs(Cqrs)、SaveRepository.csGameConfigBootstrap.csSettingsModel.cs 等 15+ 个文件中重复了完全相同的 8 行 #if NET9_0_OR_GREATER 块。这违反了 DRY 原则,未来若要调整(例如添加 [SuppressMessage]、改用别的同步原语、或在 net8 后停止多目标),需要修改多处。

GFramework.Core/GlobalUsings.cs 已存在且包含项目范围的 global using 声明。可以在其中添加类型别名定义:

`#if` NET9_0_OR_GREATER
global using FrameworkLock = System.Threading.Lock;
`#else`
global using FrameworkLock = System.Object;
`#endif`

各使用点替换为单行声明(移除条件编译块),所有文件直接使用 private readonly FrameworkLock _lock = new();,从而消除重复。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@GFramework.Core/Events/PriorityEvent.cs` around lines 24 - 30, Extract the
target-framework conditional lock type into a shared type alias (e.g.,
FrameworkLock) in your global usings and replace the repeated `#if/`#else blocks:
add a FrameworkLock alias in GlobalUsings.cs with NET9_0_OR_GREATER mapping to
System.Threading.Lock and otherwise to System.Object, then in PriorityEvent.cs
(and the other files like WeakEvent.cs, BindableProperty.cs, StateMachine.cs,
etc.) remove the `#if/`#else block and declare the field as private readonly
FrameworkLock _syncRoot = new(); ensuring all usages of _syncRoot keep the same
identifier so no other call sites change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md`:
- Around line 33-155: The active trace has grown into an append-only changelog
(RP-074 through RP-077), which hinders quick recovery; refactor the document by
moving RP-074, RP-075, RP-076 and RP-077 content into an archive section or
separate archive file and leave only a concise active entry containing the
latest true-state marker (e.g., RP-078), a short "active risk / next steps"
bullet, and a pointer to the archived details; update the trace header and any
summary sections to reflect the new single-entry active-trace policy and add an
"Archive" link/reference so boot can immediately locate the current recovery
point.

In `@GFramework.Core.Tests/Extensions/AsyncExtensionsTests.cs`:
- Around line 230-233: 在 ThrowShouldNotRetry 方法中不要使用
nameof(parameterName)(它恒等于字面量 "parameterName"),改为直接使用传入的参数 value: 保持签名 static
Task<int> ThrowShouldNotRetry(string parameterName) 然后抛出 new
ArgumentException("Should not retry", parameterName); 并在相关测试中(调用
ThrowShouldNotRetry(nameof(taskFactory)) 的断言)展开
AggregateException.InnerExceptions[0] 并断言其 ParamName == "taskFactory"
以锁定该契约不被回归。

---

Nitpick comments:
In
`@ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md`:
- Around line 31-44: This active todo file contains too much completed detail
(sections like “当前批次已完成的 warning slice”, “当前批次已完成并提交的收口”, and “当前批次已完成的第三轮
slice”); move those detailed lists into a new archive document (e.g.,
archive/todos/analyzer-warning-reduction-archive.md) and replace them here with
a short summary that preserves only the current recovery point/core facts,
active risks, immediate next step, and a pointer/link to the archive file; keep
the existing identifiers (e.g., entries mentioning GFramework.Core,
GFramework.Game, and commit `fb0a55f`) as archive references so the active
document only contains the concise recovery summary and an archive pointer.

In `@GFramework.Core.Tests/Concurrency/AsyncKeyLockManagerTests.cs`:
- Line 50: The nested "await using" with double ConfigureAwait is verbose;
simplify by splitting the acquisition and disposal into two steps: call
manager.AcquireLockAsync(...) with ConfigureAwait(false) and assign to a local
(e.g. var handle = await
manager.AcquireLockAsync("same-key").ConfigureAwait(false)); then use await
using (handle) { ... } to dispose; alternatively suppress CA2007 at the test
project level if you prefer to remove ConfigureAwait calls entirely; update the
occurrences around manager.AcquireLockAsync and any tests using the same pattern
(those at the other noted locations) accordingly.

In `@GFramework.Core.Tests/Pause/PauseStackManagerTests.cs`:
- Around line 434-438: The conditional compilation block uses a fully-qualified
System.Threading.Lock instance named lockObj; update it to use the globally
imported type and clearer naming: replace "new System.Threading.Lock()" with
"new Lock()" under the NET9_0_OR_GREATER branch (relying on the GlobalUsings.cs
System.Threading import) and rename the variable lockObj to a more descriptive
name such as pauseTokensLock (update all usages in the PauseStackManagerTests
class accordingly) to keep style and semantics consistent.

In `@GFramework.Core/Events/PriorityEvent.cs`:
- Around line 24-30: Extract the target-framework conditional lock type into a
shared type alias (e.g., FrameworkLock) in your global usings and replace the
repeated `#if/`#else blocks: add a FrameworkLock alias in GlobalUsings.cs with
NET9_0_OR_GREATER mapping to System.Threading.Lock and otherwise to
System.Object, then in PriorityEvent.cs (and the other files like WeakEvent.cs,
BindableProperty.cs, StateMachine.cs, etc.) remove the `#if/`#else block and
declare the field as private readonly FrameworkLock _syncRoot = new(); ensuring
all usages of _syncRoot keep the same identifier so no other call sites change.

In `@GFramework.Game/Config/GameConfigBootstrap.cs`:
- Around line 309-344: The current CompleteHotReloadStart(IUnRegister?
hotReload) mutates its input and returns the same parameter (null on success),
which makes caller logic and exception paths harder to follow; change the method
signature to explicitly return a bool success (or add an out IUnRegister?
handleToDispose) so the three states ("committed to _hotReload", "must dispose
incoming handle", "not committed/exception") are explicit, update the body to
stop mutating and returning the parameter (set _hotReload when committing, set
shouldStop and assign handleToDispose when needed, clear _isStartingHotReload in
finally) and update callers to use the new boolean/out contract, referencing
CompleteHotReloadStart, _hotReload, _stopHotReloadAfterStart,
_isStartingHotReload and IUnRegister/UnRegister in your changes.

In `@GFramework.Game/Scene/SceneRouterBase.cs`:
- Line 224: Change the await calls for scene lifecycle callbacks and guard
execution to capture the sync context by using ConfigureAwait(true):
specifically update awaits that call ExecuteEnterGuardsAsync(sceneKey, param),
ExecuteLeaveGuardsAsync(...), and the lifecycle methods OnLoadAsync,
OnPauseAsync, OnEnterAsync, OnExitAsync, OnUnloadAsync, OnResumeAsync so they
all append .ConfigureAwait(true) at the await points; keep in mind RouterBase
internally uses ConfigureAwait(false) when calling
guard.CanEnterAsync/CanLeaveAsync so add or update documentation/comments on the
guard interface/implementations to make clear guards cannot assume resumption on
the engine thread.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b31a0b90-e1f1-4dc4-971e-4cb7f936850e

📥 Commits

Reviewing files that changed from the base of the PR and between 617e0bf and 72ebd26.

📒 Files selected for processing (30)
  • GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs
  • GFramework.Core.Tests/Concurrency/AsyncKeyLockManagerTests.cs
  • GFramework.Core.Tests/Extensions/AsyncExtensionsTests.cs
  • GFramework.Core.Tests/Pause/PauseStackManagerTests.cs
  • GFramework.Core/Configuration/ConfigurationManager.cs
  • GFramework.Core/Coroutine/CoroutineStatistics.cs
  • GFramework.Core/Events/EventStatistics.cs
  • GFramework.Core/Events/FilterableEvent.cs
  • GFramework.Core/Events/PriorityEvent.cs
  • GFramework.Core/Events/WeakEvent.cs
  • GFramework.Core/Logging/Appenders/FileAppender.cs
  • GFramework.Core/Logging/Appenders/RollingFileAppender.cs
  • GFramework.Core/Logging/Filters/SamplingFilter.cs
  • GFramework.Core/Property/BindableProperty.cs
  • GFramework.Core/Resource/ResourceCache.cs
  • GFramework.Core/Resource/ResourceHandle.cs
  • GFramework.Core/Resource/ResourceManager.cs
  • GFramework.Core/State/StateMachine.cs
  • GFramework.Cqrs/Internal/WeakKeyCache.cs
  • GFramework.Game/Config/GameConfigBootstrap.cs
  • GFramework.Game/Data/DataRepository.cs
  • GFramework.Game/Data/SaveRepository.cs
  • GFramework.Game/Data/UnifiedSettingsDataRepository.cs
  • GFramework.Game/Routing/RouterBase.cs
  • GFramework.Game/Scene/SceneRouterBase.cs
  • GFramework.Game/Setting/SettingsModel.cs
  • GFramework.Game/UI/UiInteractionProfiles.cs
  • GFramework.Game/UI/UiRouterBase.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
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build and Test
  • GitHub Check: Code Quality & Security
  • GitHub Check: Analyze (C#)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.cs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.cs: Apply [Log] attribute for automatic logging field and logging helper method generation
Apply [Priority] attribute for automatic priority comparison implementation generation
Apply [GenerateEnumExtensions] attribute to generate enumeration extension capabilities
Apply [ContextAware] attribute to automatically implement IContextAware boilerplate logic

**/*.cs: All public, protected, and internal types and members MUST include XML documentation comments (///) with <summary>, <param>, <returns>, <exception>, and <remarks> where applicable
Add inline comments for non-trivial logic, concurrency/threading behavior, performance-sensitive paths, workarounds, edge cases, registration order, lifecycle sequencing, and generated code assumptions
Core framework components such as Architecture, Module, System, Context, Registry, Service Module, and Lifecycle types MUST include high-level explanations of responsibilities, lifecycle, interactions, why the abstraction exists, and when to use it
Generated logic and generator pipelines MUST explain what is generated, why it is generated, semantic assumptions, and diagnostics or fallback behavior
Methods with non-trivial logic MUST document the core idea, key decisions, and edge case handling
Do not rely on implicit imports; declare every required using explicitly in C# files
Write null-safe code that respects nullable annotations instead of suppressing warnings by default
Use the namespace pattern GFramework.{Module}.{Feature} with PascalCase segments in C# files
Follow standard C# naming: types/methods/properties/events/constants in PascalCase, interfaces with I prefix, parameters and locals in camelCase, private fields in _camelCase
Use 4 spaces for indentation in C# files; do not use tabs
Use Allman braces in C# files
Keep using directives at the top of C# files and sort them consistently
Prefer one primary type per C# file unless the surrounding project already uses a different local pattern
Keep...

Files:

  • GFramework.Core/Events/EventStatistics.cs
  • GFramework.Core/Logging/Appenders/FileAppender.cs
  • GFramework.Core/Resource/ResourceCache.cs
  • GFramework.Core/Resource/ResourceManager.cs
  • GFramework.Core/Events/PriorityEvent.cs
  • GFramework.Core.Tests/Extensions/AsyncExtensionsTests.cs
  • GFramework.Core.Tests/Pause/PauseStackManagerTests.cs
  • GFramework.Core/Events/WeakEvent.cs
  • GFramework.Core/Logging/Filters/SamplingFilter.cs
  • GFramework.Core/Coroutine/CoroutineStatistics.cs
  • GFramework.Cqrs/Internal/WeakKeyCache.cs
  • GFramework.Core/Resource/ResourceHandle.cs
  • GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs
  • GFramework.Core/Logging/Appenders/RollingFileAppender.cs
  • GFramework.Core/Events/FilterableEvent.cs
  • GFramework.Game/Routing/RouterBase.cs
  • GFramework.Core/Configuration/ConfigurationManager.cs
  • GFramework.Game/UI/UiInteractionProfiles.cs
  • GFramework.Core/State/StateMachine.cs
  • GFramework.Core/Property/BindableProperty.cs
  • GFramework.Game/Setting/SettingsModel.cs
  • GFramework.Game/Config/GameConfigBootstrap.cs
  • GFramework.Game/UI/UiRouterBase.cs
  • GFramework.Game/Data/SaveRepository.cs
  • GFramework.Core.Tests/Concurrency/AsyncKeyLockManagerTests.cs
  • GFramework.Game/Data/DataRepository.cs
  • GFramework.Game/Scene/SceneRouterBase.cs
  • GFramework.Game/Data/UnifiedSettingsDataRepository.cs
ai-plan/public/*/traces/**

📄 CodeRabbit inference engine (AGENTS.md)

Contributors MUST maintain a matching execution trace under ai-plan/public/<topic>/traces/ for complex work, recording the current date, key decisions, validation milestones, and the immediate next step

Files:

  • ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
ai-plan/public/*/todos/**

📄 CodeRabbit inference engine (AGENTS.md)

ai-plan/public/*/todos/**: When working from a tracked implementation plan, contributors MUST update the corresponding tracking document under ai-plan/public/<topic>/todos/ in the same change
Tracking updates MUST reflect completed work, newly discovered issues, validation results, and the next recommended recovery point
Active tracking and trace files are recovery entrypoints, not append-only changelogs; they MUST stay concise enough for boot to locate the current recovery point quickly
Recovery documents MUST record the current phase, the active recovery point identifier, known risks, and the next recommended resume step so another contributor or subagent can continue the work safely
When completed and validated stages begin to accumulate, contributors MUST archive their detailed history out of the active todos/ and traces/ entry files in the same change, keeping only the current recovery point, active facts, active risks, immediate next step, and pointers to archive files
When a task spans multiple commits or is likely to exceed a single agent context window, update both the recovery document and the trace at each meaningful milestone before pausing or handing work off
If subagents are used on a complex task, the main agent MUST capture the delegated scope and any accepted findings in the active recovery document or trace before continuing implementation

Files:

  • ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
🧠 Learnings (15)
📚 Learning: 2026-04-06T12:45:43.921Z
Learnt from: GeWuYou
Repo: GeWuYou/GFramework PR: 190
File: GFramework.Game/Config/GameConfigBootstrap.cs:1-3
Timestamp: 2026-04-06T12:45:43.921Z
Learning: In the GeWuYou/GFramework repository, C# files may omit explicit `using System*` imports because the project-wide `GlobalUsings.cs` (referenced via manual global `using` directives) supplies common namespaces (e.g., `System`, `System.Threading`, `System.Threading.Tasks`). During code review, do not flag missing `using System...` directives in `.cs` files as long as `GlobalUsings.cs` is present/used to provide those namespaces.

Applied to files:

  • GFramework.Core/Events/EventStatistics.cs
  • GFramework.Core/Logging/Appenders/FileAppender.cs
  • GFramework.Core/Resource/ResourceCache.cs
  • GFramework.Core/Resource/ResourceManager.cs
  • GFramework.Core/Events/PriorityEvent.cs
  • GFramework.Core.Tests/Extensions/AsyncExtensionsTests.cs
  • GFramework.Core.Tests/Pause/PauseStackManagerTests.cs
  • GFramework.Core/Events/WeakEvent.cs
  • GFramework.Core/Logging/Filters/SamplingFilter.cs
  • GFramework.Core/Coroutine/CoroutineStatistics.cs
  • GFramework.Cqrs/Internal/WeakKeyCache.cs
  • GFramework.Core/Resource/ResourceHandle.cs
  • GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs
  • GFramework.Core/Logging/Appenders/RollingFileAppender.cs
  • GFramework.Core/Events/FilterableEvent.cs
  • GFramework.Game/Routing/RouterBase.cs
  • GFramework.Core/Configuration/ConfigurationManager.cs
  • GFramework.Game/UI/UiInteractionProfiles.cs
  • GFramework.Core/State/StateMachine.cs
  • GFramework.Core/Property/BindableProperty.cs
  • GFramework.Game/Setting/SettingsModel.cs
  • GFramework.Game/Config/GameConfigBootstrap.cs
  • GFramework.Game/UI/UiRouterBase.cs
  • GFramework.Game/Data/SaveRepository.cs
  • GFramework.Core.Tests/Concurrency/AsyncKeyLockManagerTests.cs
  • GFramework.Game/Data/DataRepository.cs
  • GFramework.Game/Scene/SceneRouterBase.cs
  • GFramework.Game/Data/UnifiedSettingsDataRepository.cs
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to **/*.cs : When adding caching, pooling, or shared mutable state, document thread-safety assumptions and failure modes in C#

Applied to files:

  • GFramework.Core/Resource/ResourceCache.cs
  • GFramework.Cqrs/Internal/WeakKeyCache.cs
📚 Learning: 2026-04-17T11:35:08.762Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-17T11:35:08.762Z
Learning: Applies to **/*.cs : Apply [Priority] attribute for automatic priority comparison implementation generation

Applied to files:

  • GFramework.Core/Events/PriorityEvent.cs
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to **/*.Tests.cs : Reuse existing architecture test infrastructure when relevant: `ArchitectureTestsBase<T>`, `SyncTestArchitecture`, `AsyncTestArchitecture`

Applied to files:

  • GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: When the goal is to inspect or reduce warnings, establish the warning baseline by running `dotnet clean` and then `dotnet build`, not repeated incremental builds

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to **/*.cs : When adding C# analyzers or suppressions, keep them minimal and justify them in code comments if the reason is not obvious

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to **/*.cs : When a C# method approaches analyzer complexity limits, extract named helper methods by semantic phase (parsing, normalization, validation, diagnostics) instead of silencing the warning

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
📚 Learning: 2026-04-16T13:26:01.780Z
Learnt from: GeWuYou
Repo: GeWuYou/GFramework PR: 235
File: GFramework.SourceGenerators.Tests/Rule/ContextAwareGeneratorSnapshotTests.cs:1-3
Timestamp: 2026-04-16T13:26:01.780Z
Learning: In the GeWuYou/GFramework repository, the test project `GFramework.SourceGenerators.Tests` provides `global using NUnit.Framework;` via its `GlobalUsings.cs`. Do not flag missing `using NUnit.Framework;` directives in test files within this project, as the global using already covers it. The project-wide GlobalUsings.cs pattern is used broadly to supply common namespaces (including NUnit, System.IO, etc.) without per-file imports.

Applied to files:

  • GFramework.Core.Tests/Concurrency/AsyncKeyLockManagerTests.cs
  • GFramework.Game/Scene/SceneRouterBase.cs
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to **/*.Tests.cs : Preserve snapshot-based verification patterns already used in the repository for source generator tests

Applied to files:

  • GFramework.Core.Tests/Concurrency/AsyncKeyLockManagerTests.cs
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to ai-plan/public/*/todos/** : Tracking updates MUST reflect completed work, newly discovered issues, validation results, and the next recommended recovery point

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to ai-plan/public/*/todos/** : When a task spans multiple commits or is likely to exceed a single agent context window, update both the recovery document and the trace at each meaningful milestone before pausing or handing work off

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to ai-plan/public/*/todos/** : When completed and validated stages begin to accumulate, contributors MUST archive their detailed history out of the active `todos/` and `traces/` entry files in the same change, keeping only the current recovery point, active facts, active risks, immediate next step, and pointers to archive files

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to ai-plan/public/*/todos/** : Recovery documents MUST record the current phase, the active recovery point identifier, known risks, and the next recommended resume step so another contributor or subagent can continue the work safely

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: For any multi-step refactor, migration, or cross-module task, contributors MUST create or adopt a dedicated recovery document under `ai-plan/public/<topic>/todos/` before making substantive code changes

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to ai-plan/public/*/todos/** : When working from a tracked implementation plan, contributors MUST update the corresponding tracking document under `ai-plan/public/<topic>/todos/` in the same change

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
🪛 LanguageTool
ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md

[grammar] ~130-~130: Ensure spelling is correct
Context: ...andidate 条件:重复、可切片、可按文件边界独立验证 - 基线与停止条件: - 当前基线采用 refs/remotes/origin/main - origin/mainHEAD 当前同为 617e0bf(`2026-04-26T12:17...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md

[uncategorized] ~12-~12: 数词与名词之间一般应存在量词,可能缺少量词。
Context: ...前阶段:Phase 78 - 当前焦点: - 2026-04-27 第三轮 Core.Tests 低风险 slice 已完成验证,当前建议在 `30 ...

(wa5)

🔇 Additional comments (34)
GFramework.Core/State/StateMachine.cs (1)

11-17: 这段条件编译锁实现看起来没问题。

在 .NET 9+ 使用 System.Threading.Lock、低版本回退 object 的做法清晰且兼容,多目标下的并发意图也有注释说明,改动质量良好。

GFramework.Cqrs/Internal/WeakKeyCache.cs (1)

19-25: 条件编译切换 Lock 原语,改动合理。

#if NET9_0_OR_GREATER 下使用 System.Threading.Lock,其余目标回退到 object,与仓库内其他同步点保持一致;lock (_gate) 在 C# 13 对 Lock 类型有专用语义,对 object 也兼容,行为语义保持不变。注释清晰说明了取舍,符合并发与多目标兼容性要求。

GFramework.Core/Logging/Filters/SamplingFilter.cs (1)

94-100: 条件编译切换至 System.Threading.Lock 实现合理。

lock 语句在 C# 13 中对 System.Threading.Lock 走基于模式的 EnterScope() 路径,对 object 仍走 monitor 路径,两种目标下语义一致,调用点 lock (_lock) 无需修改。注释清晰说明了多目标编译的取舍,符合最小化分析器适配的要求。

GFramework.Game/UI/UiInteractionProfiles.cs (1)

54-55: 语义改进:使用命名常量替代魔术数字

将按位与运算的比较目标从字面量 0 改为 UiInputActionMask.None 显著提升了代码的语义清晰度。这一修改明确表达了"检查是否未设置该标志"的意图,同时符合 Meziantou.Analyzer 关于标志枚举比较的最佳实践。

由于 UiInputActionMask.None 的值为 0(已在上下文片段 1 中确认),此更改在功能上等价,但提高了可维护性。

ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md (1)

17-32: 记录质量良好,当前恢复点信息完整。

这一段把验证里程碑(dotnet clean/dotnet build/diff 指标)和“本轮收口”决策写清楚了,便于接手者快速判断是否继续推进。

ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md (1)

9-15: 恢复文档关键恢复信息齐全。

已包含当前阶段/恢复点、已知风险与下一步建议,交接可读性达标。

Also applies to: 53-61, 82-84

GFramework.Game/UI/UiRouterBase.cs (4)

263-273: 字符串比较显式化为 Ordinal,符合分析器规范。

Stack.Peek().KeyuiKey 的默认 ==/Equals 在 .NET 中本就是 ordinal 比较,改成显式 StringComparison.Ordinal 不改变行为,但消除了 CA1307/CA1309 的告警,语义也更清晰。


296-296: nameof(layer) 异常 paramName 改进恰当。

抛出 ArgumentException 时携带参数名是 BCL 推荐做法,便于调用方诊断和满足 CA2208。

Also applies to: 314-314


596-600: TryGetValue 重构消除了双重查找,逻辑等价。

ContainsKey + 索引器二次查找改为 TryGetValue + 缺失时按需构造,既减少一次哈希查找又对齐文件后续 (HideResumeClearLayerHasVisibleInLayer) 的写法,行为保持一致。

附注:StringComparer.Ordinal 用于 instanceId 字典键。GenerateInstanceId 始终生成 ui_{D6} 形式且单调递增,从不会出现需要不同大小写比较语义的情况,因此 ordinal 是合适且可重复的选择。


606-607: 重入检查改用 ordinal 字符串比较,行为不变。

page.Key 的默认相等性已是 ordinal,显式化主要是为了一致性与分析器静音。layerDict.Values.Any(...) 在每次 Show 时仍是 O(n),但属于先前已有的开销,本次改动未引入新的复杂度。

GFramework.Game/Scene/SceneRouterBase.cs (2)

86-86: _transitionLock.WaitAsync()ConfigureAwait(true) 与 369 行说明一致。

锁获取后的 try/finally 中含 IsTransitioning 状态变更和 _transitionLock.Release(),保留同步上下文有助于在引擎主线程模型下确保状态可见性,这与文件 369 行的整体说明一致。

附注: WaitAsync() 当前未传入 CancellationToken。如未来需要在场景过渡期间支持取消(例如关卡加载途中用户退出),可考虑统一加入 token 入参,但属于另行设计的范畴,本 PR 无需处理。

Also applies to: 188-188, 266-266, 334-334


115-115: Contains 改用 ordinal 字符串比较,行为等价。

RouterBase.Contains/UiRouterBase.Contains 同步,字符串默认相等本就是 ordinal,显式化仅为分析器合规与可读性。

GFramework.Game/Routing/RouterBase.cs (1)

221-221: Contains / IsTop 改为显式 StringComparison.Ordinal,行为等价。

IRoute.Keystring,默认 == 在 .NET 上即 ordinal,本次改动只是消除分析器告警并使语义更明确,与 SceneRouterBase/UiRouterBase 的等价改动保持一致。

Also applies to: 240-240

GFramework.Game/Config/GameConfigBootstrap.cs (2)

23-27: 条件编译切换 Lock 的实现正确。

using System.Threading; 已在文件顶部声明,lock 语句在 C# 13 中对 System.Threading.Lock 有特化(自动调用 EnterScope),且全类都使用 lock (_stateGate) 模式,无需修改任何调用点。NET9 之前回退到 object 也保持二进制语义一致。


215-230: 生命周期状态机拆分后行为等价,并发竞态处理正确。

逐路径核对:

  • 正常路径:BeginHotReloadStart 在锁内置位 _isStartingHotReload=true 并清零 _stopHotReloadAfterStartEnableHotReload 在锁外执行(符合 I/O 不应在锁内的原则),CompleteHotReloadStart 在锁内发布 _hotReload 并通过 finally 清零 _isStartingHotReload
  • Stop/Dispose 与 watcher 创建竞态:_stopHotReloadAfterStart=true 时进入 shouldStop 分支,把新句柄留在局部变量并在锁外 UnRegister(),避免在锁内做 I/O。
  • 异常路径:若 EnableHotReloadCompleteHotReloadStart(含 ThrowIfDisposedCore)抛出,hotReload = CompleteHotReloadStart(hotReload) 的赋值不会发生,catchhotReload 仍持有原句柄,再由 ResetHotReloadStartAfterFailure 复位两个标志并 UnRegister(),状态最终一致。

Also applies to: 289-353

GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs (1)

174-180: LGTM!

TrackingPipelineBehavior.Handle 作为框架管线行为,会被生产代码路径调用,对下游 next 委托添加 ConfigureAwait(false) 是合理且符合管线行为通用约定的做法,与本 PR 的统一改造方向一致。

GFramework.Core/Configuration/ConfigurationManager.cs (1)

43-49: 模式正确,建议采用上一文件中的集中化方案

_watcherLock 的所有使用点(Line 139、156、173、263、284)均为简单的 lock(...) {} 语句,与 System.Threading.Lock 的模式锁定语义完全兼容,不存在 Monitor.EnterMonitor.Wait/Pulse 或将其作为 object 传递的用法,迁移安全。

参见 PriorityEvent.cs 的重复消除建议。

GFramework.Core/Coroutine/CoroutineStatistics.cs (1)

15-21: LGTM

_lockMaxExecutionTimeMsGetCountByPriorityGetCountByTagResetGenerateReportRecordStartRecordCompleteRecordFailure 中均仅用于 lock(...) {} 语句,与 System.Threading.Lock 的模式锁定兼容。无需进一步修改(重复代码问题见 PriorityEvent.cs 中的集中化建议)。

GFramework.Core/Logging/Appenders/FileAppender.cs (1)

16-22: LGTM

Dispose(Line 67)、Append(Line 90)、Flush(Line 101)三处均为简单的 lock(...) {} 用法,迁移到 System.Threading.Lock 安全可行。

GFramework.Core/Resource/ResourceHandle.cs (1)

14-20: LGTM

IsValidReferenceCountAddReferenceRemoveReferenceDispose 中所有 lock (_lock) 均为标准用法。DisposeInternal 在锁内被调用且文档已注明(Line 131),与 System.Threading.Lock 的模式语义无冲突。

GFramework.Core/Resource/ResourceCache.cs (1)

17-23: LGTM

_lockGetAddReferenceRemoveReferenceGetReferenceCountGetUnreferencedPaths 中的用法均为 lock(...) {},迁移到 System.Threading.Lock 安全。GetUnreferencedPaths 中在 foreach 内部反复获取释放锁的模式与之前一致,行为不变。

GFramework.Core/Property/BindableProperty.cs (1)

17-23: LGTM

Value setter(Line 50)、SetValueWithoutEventRegisterRegisterWithInitValueUnRegisterGetValue 中所有 lock(_lock) 调用均为标准 lock 语句,且回调在锁外触发(Line 66),与 System.Threading.Lock 完全兼容。

GFramework.Core/Logging/Appenders/RollingFileAppender.cs (1)

17-23: LGTM

Dispose(Line 71)、Append(Line 95)、Flush(Line 113)中的 lock 调用均为标准用法。RollFiles(Line 122)在锁内被调用,符合 System.Threading.Lock 的语义。

GFramework.Core/Resource/ResourceManager.cs (1)

21-27: LGTM:与 ResourceCache._lock 保持一致的条件编译模式

_loadLock 在 NET9+ 切换为 System.Threading.Lock 后,文件中所有 lock (_loadLock) 使用点(行 61、120、167、194、329)都直接对该字段类型加锁,编译器会绑定到 Lock.EnterScope() 路径;未发现将 _loadLock 作为 object 传递、或对其使用 Monitor.Wait/Pulse 的位置,因此语义在两个目标框架下保持一致。注释也按 guideline 要求解释了取舍。

GFramework.Core/Events/FilterableEvent.cs (1)

13-19: LGTM:同步原语切换符合仓库统一模式

条件编译与注释均与 EventStatisticsWeakEvent 等并发组件保持一致;_lock 字段类型化使用,所有 lock (_lock) 调用点(行 39/54/74/110/122/133/144)在 NET9+ 上都会走 Lock.EnterScope(),未观察到 Monitor.Wait/Pulse 等需要 object monitor 语义的依赖。

GFramework.Core/Events/EventStatistics.cs (1)

13-19: LGTM:锁原语切换不影响 Interlocked 与字典的混合并发模型

_lock 仅用于保护 _publishCountByType / _listenerCountByType 两个字典的复合操作,所有 lock (_lock) 站点(行 39、51、61、70、83、101、129、159)都直接对类型化字段加锁,与 Interlocked 计数器互不影响。条件编译与注释满足 "minimal and justify" 的 guideline。

GFramework.Core/Events/WeakEvent.cs (1)

13-19: LGTM:与其他事件类的 Lock 切换保持对齐

_weakHandlers 仍由 _lock 保护,Trigger 在锁内做存活快照、锁外调用回调、必要时再次加锁更新统计的模式没有变化;所有 lock (_lock) 使用点(行 39、54、79、117、129、143)均对类型化字段直接加锁,NET9+ 上会自动使用 Lock.EnterScope() 路径。

GFramework.Game/Setting/SettingsModel.cs (2)

32-38: 条件编译切换 Lock 类型 LGTM

NET9_0_OR_GREATER 分支使用 System.Threading.Lock、旧目标继续使用 object,与 GFramework.Game/Data/SaveRepository.cs_migrationsLock 模式保持一致。lock 语句在两种类型下均能正确生成(C# 13+ 在 Lock 上调用 EnterScope(),旧目标退化为 Monitor),且本文件中所有访问点(RegisterMigration Line 149、MigrateIfNeeded Line 335)均使用 lock 语句而非 Monitor.Enter 直接调用,多目标兼容性安全。


178-178: ConfigureAwait(false) 在生命周期方法中应用 LGTM

InitializeAsyncSaveAllAsyncApplyAllAsync 三个生命周期方法对外部仓库/applicator 调用统一加 .ConfigureAwait(false),与 PR 内 DataRepository.csUnifiedSettingsDataRepository.cs 的处理一致,符合库代码避免捕获同步上下文的最佳实践。后续 this.SendEvent(...) 同步调用不依赖捕获上下文,无副作用。

Also applies to: 222-222, 240-240

GFramework.Game/Data/SaveRepository.cs (2)

36-42: 条件编译 Lock 模式与 SettingsModel 一致 LGTM

GFramework.Game/Setting/SettingsModel.cs:32-38_migrationMapLock 保持完全相同的模式:NET9+ 使用 System.Threading.Lock,旧目标回退到 object。本文件内 RegisterMigration(Line 86)与 MigrateIfNeededAsync(Line 238)的 lock 语句对两种类型都有效,未使用 Monitor.Enter,多目标兼容性安全。


108-108: 全链路 ConfigureAwait(false) 覆盖 LGTM

ExistsAsyncLoadAsyncSaveAsyncDeleteAsyncListSlotsAsyncMigrateIfNeededAsync 的回写路径都补齐了 .ConfigureAwait(false),与同 PR 内其他仓储层的修改一致。Line 255 在迁移成功后回写存档之前未持有 _migrationsLock(迁移快照已在 Line 238-241 拍照),不会引入持锁 I/O 风险。

Also applies to: 120-123, 139-143, 153-153, 163-163, 180-180, 255-255

GFramework.Game/Data/DataRepository.cs (1)

55-57: ConfigureAwait(false) 在所有异步路径上的统一应用 LGTM

LoadAsyncSaveAsyncDeleteAsyncSaveAllAsync 以及私有辅助 SaveCoreAsync / BackupIfNeededAsync 均一致地使用 .ConfigureAwait(false),符合库代码避免捕获 SynchronizationContext 的惯例。SendEventawait 之后同步调用,事件分发不再绑定到调用方上下文 —— 这与该仓储类作为通用数据层的定位一致。

Also applies to: 75-75, 96-101, 118-118, 145-146, 161-161, 167-168

GFramework.Game/Data/UnifiedSettingsDataRepository.cs (2)

40-40: 显式 StringComparer.Ordinal 让键比较语义可见 LGTM

_typeRegistryLoadAllAsync 返回字典都显式声明 StringComparer.Ordinal,与 UnifiedSettingsFile.Sections 的默认 comparer(GFramework.Game/Data/UnifiedSettingsFile.cs:36)以及 CloneFile(Line 295-297)的回退分支保持语义一致。这样从注册、序列化文件到回放查询整条路径都使用同一种 ordinal 比较,避免了未来某处不慎引入大小写不敏感比较所导致的隐式破坏。IDataLocation.Key 由路径字面量构成,ordinal 是正确选择。

Also applies to: 177-177


70-70: 全链路 ConfigureAwait(false) 覆盖(含信号量与存储调用)LGTM

EnsureLoadedAsyncLoadAsyncSaveAsyncExistsAsyncDeleteAsyncSaveAllAsyncMutateAndPersistAsyncWriteUnifiedFileCoreAsync 中的 _lock.WaitAsync()Storage.*Async() 调用统一加 .ConfigureAwait(false),同步上下文不再被捕获,避免在 UI 宿主下意外回到 UI 线程持锁串行化。finally { _lock.Release(); } 仍在 catch 之外正确执行,临界区原子提交语义未受影响。

Also applies to: 88-90, 105-105, 116-119, 130-130, 152-163, 175-175, 221-229, 246-246, 255-255, 275-281

Comment thread GFramework.Core.Tests/Extensions/AsyncExtensionsTests.cs
GeWuYou added 2 commits April 27, 2026 09:19
- 修复 AsyncExtensionsTests 中 ArgumentException 的 ParamName 传递与断言契约

- 更新 analyzer warning reduction 的 active todo 与 trace 真值

- 归档 RP073-RP078 的历史恢复文档以收紧当前入口
- 更新 gframework-pr-review 脚本以提取 CTRF 测试摘要和失败用例详情

- 修复 SettingsModelTests 在 NET9+ 下错误使用 Monitor 持锁的并发测试语义

- 同步 analyzer-warning-reduction 的 active todo 与 trace 真值
@github-actions

Copy link
Copy Markdown

Summary

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Other ❓ Flaky 🍂 Duration ⏱️
2156 2156    ↑1 0    ↓1 0 0 0 37.7s    ↑2.4s

Test Results

passed 2156 passed ↑1

Details

tests 2156 tests
clock 37.7s ↑2.4s
tool nunit
build CI - Build & Test arrow-right build-and-test link #987
pull-request Fix/analyzer warning reduction batch link #295

Insights

Average Tests per Run Total Flaky Tests Total Failed Slowest Test (p95)
2149 0 3 4.7s

Fail Rate

Fail Rate 0.00%
Test 📝 Results 📊 Passed ✅ Failed ❌ Fail Rate (%) 📈
ILogAppender_Flush_Should_Raise_OnFlushCompleted_Only_Once 32 31 1 3.13    ↓0.10
RegisterMigration_During_Cache_Rebuild_Should_Not_Leave_Stale_Type_Cache 39 38 1 2.56    ↓0.07
Run_Should_Assign_Globally_Unique_Reference_Metadata_Member_Names 40 39 1 2.50    ↓0.06

build-and-test: Run #987

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Pending ⏳ Other ❓ Flaky 🍂 Duration ⏱️
2156 2156 0 0 0 0 0 37.7s

🎉 All tests passed!

Slowest Tests

Test 📝 Results 📊 Duration (avg) ⏱️ Duration (p95) ⏱️
SendRequestAsync_Should_ResolveCqrsRuntime_OnlyOnce_When_AccessedConcurrently 40 4.1s 4.7s
Does_Not_Report_When_FieldInjectedModel_Is_Registered 40 2.2s 2.4s
Generates_Scene_Behavior_Boilerplate 40 1.9s 2.0s
CleanupDuringAcquire_Should_NotCauseRaceCondition 40 1.1s 1.1s
Append_ShouldNotBlock 40 1.0s 1.0s
Flush_Should_Raise_OnFlushCompleted_With_Sender_And_Result 33 61ms 1.0s
Context_Caching_Should_Improve_Performance 40 781ms 791ms
PendingCount_ShouldReflectQueuedEntries 40 501ms 501ms
Cleanup_Should_NotRemoveActiveLocks 40 404ms 406ms
Cleanup_Should_RemoveUnusedLocks 40 401ms 402ms

± Comparison with run #986 at bbd27f5 | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 40 runs.

Github Test Reporter by CTRF 💚

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
GFramework.Core.Tests/Extensions/AsyncExtensionsTests.cs (1)

248-249: Task.Delay(50) 似乎是多余的。

Assert.ThrowsAsync<AggregateException> 内部会同步等待任务完成(或抛出),到达第 248 行时 taskFactory 已被恰好调用一次并抛出 ArgumentException,由于 shouldRetry 返回 false,重试路径不会被触发,因此不需要额外的 Task.Delay(50) 来"等待任务完成"。注释也容易让读者误以为存在异步竞态。建议移除该等待与注释,使测试意图更清晰、运行更快。

♻️ 建议的精简
-        await Task.Delay(50).ConfigureAwait(false); // 等待任务完成
-        Assert.That(attemptCount, Is.EqualTo(1)); // 不应该重试
+        Assert.That(attemptCount, Is.EqualTo(1)); // 不应该重试

如保留 async 签名仅是为了与其他用例风格一致,可在末尾追加 await Task.CompletedTask.ConfigureAwait(false); 或将方法改为同步 void 以避免编译器关于缺少 await 的告警。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@GFramework.Core.Tests/Extensions/AsyncExtensionsTests.cs` around lines 248 -
249, Remove the unnecessary await Task.Delay(50).ConfigureAwait(false) and its
comment from the test because Assert.ThrowsAsync<AggregateException> already
waits for the task to complete; the test verifies that taskFactory was invoked
once and shouldRetry returned false (so no retry occurs). Keep references to
attemptCount, taskFactory and shouldRetry intact; if you need to preserve the
async signature for consistency, append await
Task.CompletedTask.ConfigureAwait(false) at the end of the test method (or
alternatively convert the test to a synchronous void) to avoid compiler warnings
about missing awaits.
.agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py (1)

627-649: <tr> 正则硬编码两列,未来 Test Reporter 增加列时会静默退化。

parse_failed_test_details 假定每个 <tr> 严格只有两个 <td>Name / Failure Message)。若 GitHub Test Reporter / CTRF 后续在中间加入 StatusDuration 等列,整行就会匹配失败,函数会空返回,外层只能退回到 compact 列表,丧失你刚补回来的 failure message 详情。建议放宽到“前两个 <td> + 任意尾随 <td>”,让解析对列扩展更鲁棒。

♻️ 建议的容错正则(保持取前两列,但允许尾随列)
-    for name_cell, message_cell in re.findall(r"<tr>\s*<td>(.*?)</td>\s*<td>(.*?)</td>\s*</tr>", table_section.group("body"), re.S):
+    for name_cell, message_cell in re.findall(
+        r"<tr>\s*<td>(.*?)</td>\s*<td>(.*?)</td>(?:\s*<td>.*?</td>)*\s*</tr>",
+        table_section.group("body"),
+        re.S,
+    ):
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py
around lines 627 - 649, The regex in parse_failed_test_details currently
requires exactly two <td> cells per <tr>, so add resilience by changing the
re.findall pattern to capture the first two <td> cells and allow any number of
trailing <td> cells (e.g., match <tr> then capture first
<td>(...)</td>\s*<td>(...)</td> and then allow (?:\s*<td>.*?</td>)* before
</tr>), then continue using collapse_whitespace(strip_tags(...)) on the first
capture for name and normalize_failure_message on the second capture for
failure_message so extra columns are ignored but parsing of the Name and Failure
Message remains intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py:
- Around line 627-649: The regex in parse_failed_test_details currently requires
exactly two <td> cells per <tr>, so add resilience by changing the re.findall
pattern to capture the first two <td> cells and allow any number of trailing
<td> cells (e.g., match <tr> then capture first <td>(...)</td>\s*<td>(...)</td>
and then allow (?:\s*<td>.*?</td>)* before </tr>), then continue using
collapse_whitespace(strip_tags(...)) on the first capture for name and
normalize_failure_message on the second capture for failure_message so extra
columns are ignored but parsing of the Name and Failure Message remains intact.

In `@GFramework.Core.Tests/Extensions/AsyncExtensionsTests.cs`:
- Around line 248-249: Remove the unnecessary await
Task.Delay(50).ConfigureAwait(false) and its comment from the test because
Assert.ThrowsAsync<AggregateException> already waits for the task to complete;
the test verifies that taskFactory was invoked once and shouldRetry returned
false (so no retry occurs). Keep references to attemptCount, taskFactory and
shouldRetry intact; if you need to preserve the async signature for consistency,
append await Task.CompletedTask.ConfigureAwait(false) at the end of the test
method (or alternatively convert the test to a synchronous void) to avoid
compiler warnings about missing awaits.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1805e9b9-94c9-4e59-8c01-b2736d89ed46

📥 Commits

Reviewing files that changed from the base of the PR and between 72ebd26 and 1c87272.

📒 Files selected for processing (8)
  • .agents/skills/gframework-pr-review/SKILL.md
  • .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py
  • GFramework.Core.Tests/Extensions/AsyncExtensionsTests.cs
  • GFramework.Game.Tests/Setting/SettingsModelTests.cs
  • ai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp074-rp078.md
  • ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp073-rp078.md
  • ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
  • ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
✅ Files skipped from review due to trivial changes (1)
  • .agents/skills/gframework-pr-review/SKILL.md
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build and Test
  • GitHub Check: Code Quality & Security
  • GitHub Check: Analyze (C#)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.cs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.cs: Apply [Log] attribute for automatic logging field and logging helper method generation
Apply [Priority] attribute for automatic priority comparison implementation generation
Apply [GenerateEnumExtensions] attribute to generate enumeration extension capabilities
Apply [ContextAware] attribute to automatically implement IContextAware boilerplate logic

**/*.cs: All public, protected, and internal types and members MUST include XML documentation comments (///) with <summary>, <param>, <returns>, <exception>, and <remarks> where applicable
Add inline comments for non-trivial logic, concurrency/threading behavior, performance-sensitive paths, workarounds, edge cases, registration order, lifecycle sequencing, and generated code assumptions
Core framework components such as Architecture, Module, System, Context, Registry, Service Module, and Lifecycle types MUST include high-level explanations of responsibilities, lifecycle, interactions, why the abstraction exists, and when to use it
Generated logic and generator pipelines MUST explain what is generated, why it is generated, semantic assumptions, and diagnostics or fallback behavior
Methods with non-trivial logic MUST document the core idea, key decisions, and edge case handling
Do not rely on implicit imports; declare every required using explicitly in C# files
Write null-safe code that respects nullable annotations instead of suppressing warnings by default
Use the namespace pattern GFramework.{Module}.{Feature} with PascalCase segments in C# files
Follow standard C# naming: types/methods/properties/events/constants in PascalCase, interfaces with I prefix, parameters and locals in camelCase, private fields in _camelCase
Use 4 spaces for indentation in C# files; do not use tabs
Use Allman braces in C# files
Keep using directives at the top of C# files and sort them consistently
Prefer one primary type per C# file unless the surrounding project already uses a different local pattern
Keep...

Files:

  • GFramework.Core.Tests/Extensions/AsyncExtensionsTests.cs
  • GFramework.Game.Tests/Setting/SettingsModelTests.cs
ai-plan/public/*/traces/**

📄 CodeRabbit inference engine (AGENTS.md)

Contributors MUST maintain a matching execution trace under ai-plan/public/<topic>/traces/ for complex work, recording the current date, key decisions, validation milestones, and the immediate next step

Files:

  • ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
ai-plan/public/*/todos/**

📄 CodeRabbit inference engine (AGENTS.md)

ai-plan/public/*/todos/**: When working from a tracked implementation plan, contributors MUST update the corresponding tracking document under ai-plan/public/<topic>/todos/ in the same change
Tracking updates MUST reflect completed work, newly discovered issues, validation results, and the next recommended recovery point
Active tracking and trace files are recovery entrypoints, not append-only changelogs; they MUST stay concise enough for boot to locate the current recovery point quickly
Recovery documents MUST record the current phase, the active recovery point identifier, known risks, and the next recommended resume step so another contributor or subagent can continue the work safely
When completed and validated stages begin to accumulate, contributors MUST archive their detailed history out of the active todos/ and traces/ entry files in the same change, keeping only the current recovery point, active facts, active risks, immediate next step, and pointers to archive files
When a task spans multiple commits or is likely to exceed a single agent context window, update both the recovery document and the trace at each meaningful milestone before pausing or handing work off
If subagents are used on a complex task, the main agent MUST capture the delegated scope and any accepted findings in the active recovery document or trace before continuing implementation

Files:

  • ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
🧠 Learnings (14)
📚 Learning: 2026-04-06T12:45:43.921Z
Learnt from: GeWuYou
Repo: GeWuYou/GFramework PR: 190
File: GFramework.Game/Config/GameConfigBootstrap.cs:1-3
Timestamp: 2026-04-06T12:45:43.921Z
Learning: In the GeWuYou/GFramework repository, C# files may omit explicit `using System*` imports because the project-wide `GlobalUsings.cs` (referenced via manual global `using` directives) supplies common namespaces (e.g., `System`, `System.Threading`, `System.Threading.Tasks`). During code review, do not flag missing `using System...` directives in `.cs` files as long as `GlobalUsings.cs` is present/used to provide those namespaces.

Applied to files:

  • GFramework.Core.Tests/Extensions/AsyncExtensionsTests.cs
  • GFramework.Game.Tests/Setting/SettingsModelTests.cs
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to **/*.Tests.cs : Reuse existing architecture test infrastructure when relevant: `ArchitectureTestsBase<T>`, `SyncTestArchitecture`, `AsyncTestArchitecture`

Applied to files:

  • GFramework.Game.Tests/Setting/SettingsModelTests.cs
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to **/*.Tests.cs : Keep tests focused on observable behavior, not implementation trivia

Applied to files:

  • GFramework.Game.Tests/Setting/SettingsModelTests.cs
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to ai-plan/public/*/traces/** : Contributors MUST maintain a matching execution trace under `ai-plan/public/<topic>/traces/` for complex work, recording the current date, key decisions, validation milestones, and the immediate next step

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
  • ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp073-rp078.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to ai-plan/public/*/todos/** : Active tracking and trace files are recovery entrypoints, not append-only changelogs; they MUST stay concise enough for `boot` to locate the current recovery point quickly

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to ai-plan/public/*/todos/** : When completed and validated stages begin to accumulate, contributors MUST archive their detailed history out of the active `todos/` and `traces/` entry files in the same change, keeping only the current recovery point, active facts, active risks, immediate next step, and pointers to archive files

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
  • ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
  • ai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp074-rp078.md
  • ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp073-rp078.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to ai-plan/public/*/todos/** : When a task spans multiple commits or is likely to exceed a single agent context window, update both the recovery document and the trace at each meaningful milestone before pausing or handing work off

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to ai-plan/public/*/todos/** : Recovery documents MUST record the current phase, the active recovery point identifier, known risks, and the next recommended resume step so another contributor or subagent can continue the work safely

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to ai-plan/public/*/todos/** : Tracking updates MUST reflect completed work, newly discovered issues, validation results, and the next recommended recovery point

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
  • ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: For any multi-step refactor, migration, or cross-module task, contributors MUST create or adopt a dedicated recovery document under `ai-plan/public/<topic>/todos/` before making substantive code changes

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
  • ai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp074-rp078.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: When the goal is to inspect or reduce warnings, establish the warning baseline by running `dotnet clean` and then `dotnet build`, not repeated incremental builds

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp074-rp078.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to **/*.cs : Any change to public API, lifecycle semantics, module behavior, or extension points MUST update the related XML docs

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp074-rp078.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to {README.md,docs/**} : Public documentation MUST NOT include governance-only content such as inventory tables, coverage baselines, review queues, batch metrics, recovery points, trace summaries, or 'this still needs a later audit wave' notes

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp074-rp078.md
  • ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp073-rp078.md
📚 Learning: 2026-04-26T03:16:48.209Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T03:16:48.209Z
Learning: Applies to **/*.cs : When adding C# analyzers or suppressions, keep them minimal and justify them in code comments if the reason is not obvious

Applied to files:

  • ai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp074-rp078.md
🪛 LanguageTool
ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md

[uncategorized] ~12-~12: 您的意思是“"不"齐”?
Context: ...阶段:Phase 80 - 当前焦点: - 2026-04-27 已补齐 $gframework-pr-review 对 GitHub Test ...

(BU)


[uncategorized] ~34-~34: 您的意思是“"不"强”?
Context: ...e todo 仅保留恢复真值 - 本轮新增内容为 PR review 工具链补强与单个失败测试修正,不扩展 warning reduction 的热点清理边界...

(BU)

ai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp074-rp078.md

[uncategorized] ~15-~15: 数词与名词之间一般应存在量词,可能缺少量词。
Context: ...fb0a55f fix(analyzer): 收口首轮并行警告清理 - 第三轮 Core.Tests 低风险 slice: - `GFramework...

(wa5)

ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp073-rp078.md

[grammar] ~130-~130: Ensure spelling is correct
Context: ...andidate 条件:重复、可切片、可按文件边界独立验证 - 基线与停止条件: - 当前基线采用 refs/remotes/origin/main - origin/mainHEAD 当前同为 617e0bf(`2026-04-26T12:17...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🔇 Additional comments (7)
GFramework.Core.Tests/Extensions/AsyncExtensionsTests.cs (1)

230-253: 修复已落实,断言契约清晰。

ThrowShouldNotRetry 现在正确使用传入的 parameterName 作为 ArgumentExceptionparamName,并在断言中通过 InnerExceptions[0] 校验类型与 ParamName == nameof(taskFactory),锁定了之前指出的契约。改动符合预期。

GFramework.Game.Tests/Setting/SettingsModelTests.cs (1)

140-203: 测试持锁语义与生产代码对齐,重构合理。

WithSynchronizationLockHeldNET9_0_OR_GREATER 下优先把反射拿到的对象作为 System.Threading.Lock 进入 EnterScope(),否则回退到 lock (syncRoot),与 GFramework.Game/Setting/SettingsModel.cs_migrationMapLock 的条件编译声明完全一致;将任务创建/调度断言放入持锁回调并返回任务元组、再在锁外 await,避免了之前把 Lock 误降级为 Monitor 的并发误判。XML 文档、ArgumentNullException.ThrowIfNull 防御以及命名都满足规范要求。

.agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py (1)

494-582: 测试摘要解析增强结构化与可维护性良好。

clean_markdown_table_cellparse_markdown_tableparse_stats_table 的拆分把表格清洗、结构化、语义归一三个阶段分离,normalize_stat_header 用别名映射做稳定 key、未识别 header 也保留原 ascii 串而非静默丢弃,parse_duration_from_text 在无单位 token 时退化为原文本,整体能够同时兼容 ### Summary### build-and-test: 两种表格来源,输出形状向消费者稳定。

ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md (1)

3-50: 活跃 trace 已收敛到单恢复点,符合 recovery entrypoint 约束。

本轮把 RP-074~RP-077 明细迁出到 archive/traces/analyzer-warning-reduction-history-rp073-rp078.md,活跃 trace 仅保留 RP-080 当前真值、活跃风险、下一步与归档指针,回归到 boot 可快速定位恢复点的结构;RP-080 自身记录了触发背景、主线程实施、可复算的验证里程碑(脚本调用 + 过滤后的 dotnet test)与当前结论,与编码规范要求的“当前阶段、活跃恢复点、已知风险、下一步”完全对齐。

ai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp074-rp078.md (1)

1-40: RP074–RP078 归档内容完整,与活跃 todo 解耦干净。

按已完成批次摘要 / 批次验证快照(dotnet cleandotnet build 639→397、Core.Tests Release 0 warning)/ 延后候选三段组织,并把详细执行过程通过 analyzer-warning-reduction-history-rp073-rp078.md 的 traces 链接外指,让 active todo 不再承担历史日志职责,符合“archive their detailed history out of the active todos/ and traces/”的约束。

ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp073-rp078.md (1)

1-176: Trace 归档窗口与 todo 归档窗口一致,验证度量可追溯。

每个 RP 都按“触发背景 / delegated scope 与结果 / 主线程验证里程碑 / 当前结论”的统一结构组织,并保留了关键提交 SHA(如 fb0a55f650618be19e60ec106e539deafac9ce634ee3eec547e137528f2d959)和构建/分支度量(warning 639→430→405→397,files 0→12→22→26→30),后续若需要回溯任一波次的边界与降幅都可以直接定位。

ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md (1)

9-73: 活跃 todo 严格只留当前真值,并显式说明本轮验证边界。

恢复点推进到 RP-080 / Phase 80 后,活跃事实只保留 origin/main 基线 617e0bf、PR #295 当前 $gframework-pr-review 输出、定向 dotnet test --filter 的通过结果与 stop-condition 度量(30 files / 642 lines),并显式声明“GFramework.Core.Tests 当前仍有既有 analyzer / nullable warning 基线,本轮验证未将该项目 warning 清零”,避免了对未做之事的隐性背书;活跃文档区把 rp074–rp078 todo 与 rp073–rp078 trace 同步指向新归档,恢复路径自洽。

coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 27, 2026
- 修复 PR review 脚本对 failed-test 额外列表格的解析容错

- 清理 AsyncExtensionsTests 中多余的等待并保留参数名断言

- 补充脚本回归测试并同步 analyzer-warning-reduction 恢复点
@github-actions

Copy link
Copy Markdown

Summary

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Other ❓ Flaky 🍂 Duration ⏱️
2156 2156 0 0 0 0 37.2s    ↓506ms

Test Results

passed 2156 passed

Details

tests 2156 tests
clock 37.2s ↓506ms
tool nunit
build CI - Build & Test arrow-right build-and-test link #988
pull-request Fix/analyzer warning reduction batch link #295

Insights

Average Tests per Run Total Flaky Tests Total Failed Slowest Test (p95)
2149 0 3 4.7s

Fail Rate

Fail Rate 0.00%
Test 📝 Results 📊 Passed ✅ Failed ❌ Fail Rate (%) 📈
ILogAppender_Flush_Should_Raise_OnFlushCompleted_Only_Once 33 32 1 3.03    ↓0.10
RegisterMigration_During_Cache_Rebuild_Should_Not_Leave_Stale_Type_Cache 40 39 1 2.50    ↓0.06
Run_Should_Assign_Globally_Unique_Reference_Metadata_Member_Names 41 40 1 2.44    ↓0.06

build-and-test: Run #988

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Pending ⏳ Other ❓ Flaky 🍂 Duration ⏱️
2156 2156 0 0 0 0 0 37.2s

🎉 All tests passed!

Slowest Tests

Test 📝 Results 📊 Duration (avg) ⏱️ Duration (p95) ⏱️
SendRequestAsync_Should_ResolveCqrsRuntime_OnlyOnce_When_AccessedConcurrently 41 4.1s 4.7s
Does_Not_Report_When_FieldInjectedModel_Is_Registered 41 2.2s 2.4s
Generates_Scene_Behavior_Boilerplate 41 1.9s 2.0s
CleanupDuringAcquire_Should_NotCauseRaceCondition 41 1.1s 1.1s
Append_ShouldNotBlock 41 1.0s 1.0s
Flush_Should_Raise_OnFlushCompleted_With_Sender_And_Result 34 59ms 1.0s
Context_Caching_Should_Improve_Performance 41 781ms 791ms
PendingCount_ShouldReflectQueuedEntries 41 501ms 501ms
Cleanup_Should_NotRemoveActiveLocks 41 404ms 406ms
Cleanup_Should_RemoveUnusedLocks 41 401ms 402ms

± Comparison with run #987 at e70cf16 | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 41 runs.

Github Test Reporter by CTRF 💚

@GeWuYou GeWuYou merged commit b6a9fef into main Apr 27, 2026
7 checks passed
@GeWuYou GeWuYou deleted the fix/analyzer-warning-reduction-batch branch April 27, 2026 02:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant