Fix/analyzer warning reduction batch#295
Conversation
- 修复 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 批次验证结果与默认收口建议
|
Warning Rate limit exceeded
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 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 configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthrough本 PR 在多处通过条件编译在 .NET 9.0+ 使用 Changes
Sequence Diagram(s)(无序列图 — 本次变更主要为锁原语替换、await 配置与局部重构,未引入新的跨组件顺序控制流) Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Summary
Test ResultsDetails
Failed TestsSettingsModelTests Insights
Fail Rate
build-and-test: Run #986
❌ Some tests failed!
Slowest Tests
± Comparison with run #980 at 7da232d | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 39 runs. Github Test Reporter by CTRF 💚 |
|
| 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
Reviews (3): Last reviewed commit: "fix(tooling): 收口PR评审遗留nitpick" | Re-trigger Greptile
✅
|
| Descriptor | Linter | Files | Fixed | Errors | Warnings | Elapsed time |
|---|---|---|---|---|---|---|
| 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

Show us your support by starring ⭐ the repository
There was a problem hiding this comment.
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/andtraces/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/ExecuteLeaveGuardsAsync在guard.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 测试上下文中并不存在SynchronizationContext,ConfigureAwait(false)本身并无运行时收益,仅是为了消除 CA2007 警告。建议两选其一以提升可读性:
- 在测试项目级别抑制 CA2007(更简洁);
- 拆分为两步绑定句柄。
♻️ 拆分写法示例(以第 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.cs、WeakEvent.cs、BindableProperty.cs、StateMachine.cs、StoreSelection.cs、CoroutineStatistics.cs、RollingFileAppender.cs、FileAppender.cs、SamplingFilter.cs、ResourceCache.cs、ResourceManager.cs、WeakKeyCache.cs(Cqrs)、SaveRepository.cs、GameConfigBootstrap.cs、SettingsModel.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
📒 Files selected for processing (30)
GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Core.Tests/Concurrency/AsyncKeyLockManagerTests.csGFramework.Core.Tests/Extensions/AsyncExtensionsTests.csGFramework.Core.Tests/Pause/PauseStackManagerTests.csGFramework.Core/Configuration/ConfigurationManager.csGFramework.Core/Coroutine/CoroutineStatistics.csGFramework.Core/Events/EventStatistics.csGFramework.Core/Events/FilterableEvent.csGFramework.Core/Events/PriorityEvent.csGFramework.Core/Events/WeakEvent.csGFramework.Core/Logging/Appenders/FileAppender.csGFramework.Core/Logging/Appenders/RollingFileAppender.csGFramework.Core/Logging/Filters/SamplingFilter.csGFramework.Core/Property/BindableProperty.csGFramework.Core/Resource/ResourceCache.csGFramework.Core/Resource/ResourceHandle.csGFramework.Core/Resource/ResourceManager.csGFramework.Core/State/StateMachine.csGFramework.Cqrs/Internal/WeakKeyCache.csGFramework.Game/Config/GameConfigBootstrap.csGFramework.Game/Data/DataRepository.csGFramework.Game/Data/SaveRepository.csGFramework.Game/Data/UnifiedSettingsDataRepository.csGFramework.Game/Routing/RouterBase.csGFramework.Game/Scene/SceneRouterBase.csGFramework.Game/Setting/SettingsModel.csGFramework.Game/UI/UiInteractionProfiles.csGFramework.Game/UI/UiRouterBase.csai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.mdai-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 requiredusingexplicitly in C# files
Write null-safe code that respects nullable annotations instead of suppressing warnings by default
Use the namespace patternGFramework.{Module}.{Feature}with PascalCase segments in C# files
Follow standard C# naming: types/methods/properties/events/constants in PascalCase, interfaces withIprefix, 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
Keepusingdirectives 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.csGFramework.Core/Logging/Appenders/FileAppender.csGFramework.Core/Resource/ResourceCache.csGFramework.Core/Resource/ResourceManager.csGFramework.Core/Events/PriorityEvent.csGFramework.Core.Tests/Extensions/AsyncExtensionsTests.csGFramework.Core.Tests/Pause/PauseStackManagerTests.csGFramework.Core/Events/WeakEvent.csGFramework.Core/Logging/Filters/SamplingFilter.csGFramework.Core/Coroutine/CoroutineStatistics.csGFramework.Cqrs/Internal/WeakKeyCache.csGFramework.Core/Resource/ResourceHandle.csGFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Core/Logging/Appenders/RollingFileAppender.csGFramework.Core/Events/FilterableEvent.csGFramework.Game/Routing/RouterBase.csGFramework.Core/Configuration/ConfigurationManager.csGFramework.Game/UI/UiInteractionProfiles.csGFramework.Core/State/StateMachine.csGFramework.Core/Property/BindableProperty.csGFramework.Game/Setting/SettingsModel.csGFramework.Game/Config/GameConfigBootstrap.csGFramework.Game/UI/UiRouterBase.csGFramework.Game/Data/SaveRepository.csGFramework.Core.Tests/Concurrency/AsyncKeyLockManagerTests.csGFramework.Game/Data/DataRepository.csGFramework.Game/Scene/SceneRouterBase.csGFramework.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 underai-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 forbootto 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 activetodos/andtraces/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.csGFramework.Core/Logging/Appenders/FileAppender.csGFramework.Core/Resource/ResourceCache.csGFramework.Core/Resource/ResourceManager.csGFramework.Core/Events/PriorityEvent.csGFramework.Core.Tests/Extensions/AsyncExtensionsTests.csGFramework.Core.Tests/Pause/PauseStackManagerTests.csGFramework.Core/Events/WeakEvent.csGFramework.Core/Logging/Filters/SamplingFilter.csGFramework.Core/Coroutine/CoroutineStatistics.csGFramework.Cqrs/Internal/WeakKeyCache.csGFramework.Core/Resource/ResourceHandle.csGFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.csGFramework.Core/Logging/Appenders/RollingFileAppender.csGFramework.Core/Events/FilterableEvent.csGFramework.Game/Routing/RouterBase.csGFramework.Core/Configuration/ConfigurationManager.csGFramework.Game/UI/UiInteractionProfiles.csGFramework.Core/State/StateMachine.csGFramework.Core/Property/BindableProperty.csGFramework.Game/Setting/SettingsModel.csGFramework.Game/Config/GameConfigBootstrap.csGFramework.Game/UI/UiRouterBase.csGFramework.Game/Data/SaveRepository.csGFramework.Core.Tests/Concurrency/AsyncKeyLockManagerTests.csGFramework.Game/Data/DataRepository.csGFramework.Game/Scene/SceneRouterBase.csGFramework.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.csGFramework.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.csGFramework.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/main 与 HEAD 当前同为 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().Key与uiKey的默认==/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+ 缺失时按需构造,既减少一次哈希查找又对齐文件后续 (Hide、Resume、ClearLayer、HasVisibleInLayer) 的写法,行为保持一致。附注:
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.Key是string,默认==在 .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并清零_stopHotReloadAfterStart,EnableHotReload在锁外执行(符合 I/O 不应在锁内的原则),CompleteHotReloadStart在锁内发布_hotReload并通过finally清零_isStartingHotReload。- Stop/Dispose 与 watcher 创建竞态:
_stopHotReloadAfterStart=true时进入shouldStop分支,把新句柄留在局部变量并在锁外UnRegister(),避免在锁内做 I/O。- 异常路径:若
EnableHotReload或CompleteHotReloadStart(含ThrowIfDisposedCore)抛出,hotReload = CompleteHotReloadStart(hotReload)的赋值不会发生,catch中hotReload仍持有原句柄,再由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.Enter、Monitor.Wait/Pulse或将其作为object传递的用法,迁移安全。参见
PriorityEvent.cs的重复消除建议。GFramework.Core/Coroutine/CoroutineStatistics.cs (1)
15-21: LGTM
_lock在MaxExecutionTimeMs、GetCountByPriority、GetCountByTag、Reset、GenerateReport、RecordStart、RecordComplete、RecordFailure中均仅用于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
IsValid、ReferenceCount、AddReference、RemoveReference、Dispose中所有lock (_lock)均为标准用法。DisposeInternal在锁内被调用且文档已注明(Line 131),与System.Threading.Lock的模式语义无冲突。GFramework.Core/Resource/ResourceCache.cs (1)
17-23: LGTM
_lock在Get、AddReference、RemoveReference、GetReferenceCount、GetUnreferencedPaths中的用法均为lock(...) {},迁移到System.Threading.Lock安全。GetUnreferencedPaths中在foreach内部反复获取释放锁的模式与之前一致,行为不变。GFramework.Core/Property/BindableProperty.cs (1)
17-23: LGTM
Valuesetter(Line 50)、SetValueWithoutEvent、Register、RegisterWithInitValue、UnRegister、GetValue中所有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:同步原语切换符合仓库统一模式条件编译与注释均与
EventStatistics、WeakEvent等并发组件保持一致;_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),且本文件中所有访问点(RegisterMigrationLine 149、MigrateIfNeededLine 335)均使用lock语句而非Monitor.Enter直接调用,多目标兼容性安全。
178-178:ConfigureAwait(false)在生命周期方法中应用 LGTM
InitializeAsync、SaveAllAsync、ApplyAllAsync三个生命周期方法对外部仓库/applicator 调用统一加.ConfigureAwait(false),与 PR 内DataRepository.cs、UnifiedSettingsDataRepository.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
ExistsAsync、LoadAsync、SaveAsync、DeleteAsync、ListSlotsAsync与MigrateIfNeededAsync的回写路径都补齐了.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
LoadAsync、SaveAsync、DeleteAsync、SaveAllAsync以及私有辅助SaveCoreAsync/BackupIfNeededAsync均一致地使用.ConfigureAwait(false),符合库代码避免捕获SynchronizationContext的惯例。SendEvent在await之后同步调用,事件分发不再绑定到调用方上下文 —— 这与该仓储类作为通用数据层的定位一致。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
_typeRegistry与LoadAllAsync返回字典都显式声明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
EnsureLoadedAsync、LoadAsync、SaveAsync、ExistsAsync、DeleteAsync、SaveAllAsync、MutateAndPersistAsync与WriteUnifiedFileCoreAsync中的_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
- 修复 AsyncExtensionsTests 中 ArgumentException 的 ParamName 传递与断言契约 - 更新 analyzer warning reduction 的 active todo 与 trace 真值 - 归档 RP073-RP078 的历史恢复文档以收紧当前入口
- 更新 gframework-pr-review 脚本以提取 CTRF 测试摘要和失败用例详情 - 修复 SettingsModelTests 在 NET9+ 下错误使用 Monitor 持锁的并发测试语义 - 同步 analyzer-warning-reduction 的 active todo 与 trace 真值
Summary
Test ResultsDetails
Insights
Fail Rate
build-and-test: Run #987
🎉 All tests passed!Slowest Tests
± Comparison with run #986 at bbd27f5 | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 40 runs. Github Test Reporter by CTRF 💚 |
There was a problem hiding this comment.
🧹 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 后续在中间加入Status、Duration等列,整行就会匹配失败,函数会空返回,外层只能退回到 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
📒 Files selected for processing (8)
.agents/skills/gframework-pr-review/SKILL.md.agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.pyGFramework.Core.Tests/Extensions/AsyncExtensionsTests.csGFramework.Game.Tests/Setting/SettingsModelTests.csai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp074-rp078.mdai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp073-rp078.mdai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.mdai-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 requiredusingexplicitly in C# files
Write null-safe code that respects nullable annotations instead of suppressing warnings by default
Use the namespace patternGFramework.{Module}.{Feature}with PascalCase segments in C# files
Follow standard C# naming: types/methods/properties/events/constants in PascalCase, interfaces withIprefix, 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
Keepusingdirectives 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.csGFramework.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 underai-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 forbootto 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 activetodos/andtraces/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.csGFramework.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.mdai-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.mdai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.mdai-plan/public/analyzer-warning-reduction/archive/todos/analyzer-warning-reduction-history-rp074-rp078.mdai-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.mdai-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.mdai-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.mdai-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/main 与 HEAD 当前同为 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作为ArgumentException的paramName,并在断言中通过InnerExceptions[0]校验类型与ParamName == nameof(taskFactory),锁定了之前指出的契约。改动符合预期。GFramework.Game.Tests/Setting/SettingsModelTests.cs (1)
140-203: 测试持锁语义与生产代码对齐,重构合理。
WithSynchronizationLockHeld在NET9_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_cell→parse_markdown_table→parse_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 clean、dotnet build639→397、Core.TestsRelease 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(如
fb0a55f、650618b、e19e60e、c106e53、9deafac、9ce634e、e3eec54、7e13752、8f2d959)和构建/分支度量(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 度量(30files /642lines),并显式声明“GFramework.Core.Tests当前仍有既有 analyzer / nullable warning 基线,本轮验证未将该项目 warning 清零”,避免了对未做之事的隐性背书;活跃文档区把 rp074–rp078 todo 与 rp073–rp078 trace 同步指向新归档,恢复路径自洽。
- 修复 PR review 脚本对 failed-test 额外列表格的解析容错 - 清理 AsyncExtensionsTests 中多余的等待并保留参数名断言 - 补充脚本回归测试并同步 analyzer-warning-reduction 恢复点
Summary
Test ResultsDetails
Insights
Fail Rate
build-and-test: Run #988
🎉 All tests passed!Slowest Tests
± Comparison with run #987 at e70cf16 | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 41 runs. Github Test Reporter by CTRF 💚 |
Summary by CodeRabbit
发布说明
重构
测试
文档
任务