From fb0a55f435dcf6fff792a47bc6bbd89e2b6c5dc9 Mon Sep 17 00:00:00 2001
From: gewuyou <95328647+GeWuYou@users.noreply.github.com>
Date: Mon, 27 Apr 2026 07:54:43 +0800
Subject: [PATCH] =?UTF-8?q?fix(analyzer):=20=E6=94=B6=E5=8F=A3=E9=A6=96?=
=?UTF-8?q?=E8=BD=AE=E5=B9=B6=E8=A1=8C=E8=AD=A6=E5=91=8A=E6=B8=85=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 修复 Core 与 Cqrs 中资源、日志、配置缓存的 MA0158 专用锁警告
- 修复 SaveRepository 与 SceneRouterBase 的残留分析器警告
- 更新 analyzer-warning-reduction 跟踪文档与最新构建验证结果
---
.../Configuration/ConfigurationManager.cs | 6 ++
.../Logging/Appenders/FileAppender.cs | 8 ++-
.../Logging/Appenders/RollingFileAppender.cs | 8 ++-
.../Logging/Filters/SamplingFilter.cs | 6 ++
GFramework.Core/Resource/ResourceCache.cs | 6 ++
GFramework.Core/Resource/ResourceHandle.cs | 8 ++-
GFramework.Core/Resource/ResourceManager.cs | 6 ++
GFramework.Cqrs/Internal/WeakKeyCache.cs | 6 ++
GFramework.Game/Data/SaveRepository.cs | 6 ++
GFramework.Game/Scene/SceneRouterBase.cs | 3 +-
.../analyzer-warning-reduction-tracking.md | 58 ++++++++++-------
.../analyzer-warning-reduction-trace.md | 65 +++++++++++++++++++
12 files changed, 160 insertions(+), 26 deletions(-)
diff --git a/GFramework.Core/Configuration/ConfigurationManager.cs b/GFramework.Core/Configuration/ConfigurationManager.cs
index 5eddcabb..a8d3566a 100644
--- a/GFramework.Core/Configuration/ConfigurationManager.cs
+++ b/GFramework.Core/Configuration/ConfigurationManager.cs
@@ -40,7 +40,13 @@ public class ConfigurationManager : IConfigurationManager
///
/// 用于保护监听器列表的锁
///
+#if NET9_0_OR_GREATER
+ // net9.0 及以上目标使用专用 Lock,以满足分析器对专用同步原语的建议。
+ private readonly System.Threading.Lock _watcherLock = new();
+#else
+ // net8.0 目标仍回退到 object 锁,以保持多目标编译兼容性。
private readonly object _watcherLock = new();
+#endif
///
/// 配置监听器字典(线程安全)
diff --git a/GFramework.Core/Logging/Appenders/FileAppender.cs b/GFramework.Core/Logging/Appenders/FileAppender.cs
index 74e75622..76cd47a6 100644
--- a/GFramework.Core/Logging/Appenders/FileAppender.cs
+++ b/GFramework.Core/Logging/Appenders/FileAppender.cs
@@ -13,7 +13,13 @@ public sealed class FileAppender : ILogAppender, IDisposable
private readonly string _filePath;
private readonly ILogFilter? _filter;
private readonly ILogFormatter _formatter;
+#if NET9_0_OR_GREATER
+ // net9.0 及以上目标使用专用 Lock,以满足分析器对专用同步原语的建议。
+ private readonly System.Threading.Lock _lock = new();
+#else
+ // net8.0 目标仍回退到 object 锁,以保持多目标编译兼容性。
private readonly object _lock = new();
+#endif
private bool _disposed;
private StreamWriter? _writer;
@@ -114,4 +120,4 @@ public sealed class FileAppender : ILogAppender, IDisposable
AutoFlush = true
};
}
-}
\ No newline at end of file
+}
diff --git a/GFramework.Core/Logging/Appenders/RollingFileAppender.cs b/GFramework.Core/Logging/Appenders/RollingFileAppender.cs
index 793c6dc9..ea9d91de 100644
--- a/GFramework.Core/Logging/Appenders/RollingFileAppender.cs
+++ b/GFramework.Core/Logging/Appenders/RollingFileAppender.cs
@@ -14,7 +14,13 @@ public sealed class RollingFileAppender : ILogAppender, IDisposable
private readonly string _baseFilePath;
private readonly ILogFilter? _filter;
private readonly ILogFormatter _formatter;
+#if NET9_0_OR_GREATER
+ // net9.0 及以上目标使用专用 Lock,以满足分析器对专用同步原语的建议。
+ private readonly System.Threading.Lock _lock = new();
+#else
+ // net8.0 目标仍回退到 object 锁,以保持多目标编译兼容性。
private readonly object _lock = new();
+#endif
private readonly int _maxFileCount;
private readonly long _maxFileSize;
private long _currentSize;
@@ -205,4 +211,4 @@ public sealed class RollingFileAppender : ILogAppender, IDisposable
// 获取当前文件大小
_currentSize = File.Exists(_baseFilePath) ? new FileInfo(_baseFilePath).Length : 0;
}
-}
\ No newline at end of file
+}
diff --git a/GFramework.Core/Logging/Filters/SamplingFilter.cs b/GFramework.Core/Logging/Filters/SamplingFilter.cs
index 20f2965a..5504d78e 100644
--- a/GFramework.Core/Logging/Filters/SamplingFilter.cs
+++ b/GFramework.Core/Logging/Filters/SamplingFilter.cs
@@ -91,7 +91,13 @@ public sealed class SamplingFilter : ILogFilter
///
private sealed class SamplingState
{
+#if NET9_0_OR_GREATER
+ // net9.0 及以上目标使用专用 Lock,以满足分析器对专用同步原语的建议。
+ private readonly System.Threading.Lock _lock = new();
+#else
+ // net8.0 目标仍回退到 object 锁,以保持多目标编译兼容性。
private readonly object _lock = new();
+#endif
private readonly ITimeProvider _timeProvider;
private long _count;
private long _lastAccessTicks;
diff --git a/GFramework.Core/Resource/ResourceCache.cs b/GFramework.Core/Resource/ResourceCache.cs
index cffa2908..5f6c51b6 100644
--- a/GFramework.Core/Resource/ResourceCache.cs
+++ b/GFramework.Core/Resource/ResourceCache.cs
@@ -14,7 +14,13 @@ internal sealed class ResourceCache
private const string PathCannotBeNullOrEmptyMessage = "Path cannot be null or whitespace.";
private readonly ConcurrentDictionary _cache = new(StringComparer.Ordinal);
+#if NET9_0_OR_GREATER
+ // net9.0 及以上目标使用专用 Lock,以满足分析器对专用同步原语的建议。
+ private readonly System.Threading.Lock _lock = new();
+#else
+ // net8.0 目标仍回退到 object 锁,以保持多目标编译兼容性。
private readonly object _lock = new();
+#endif
///
/// 获取已缓存资源的数量
diff --git a/GFramework.Core/Resource/ResourceHandle.cs b/GFramework.Core/Resource/ResourceHandle.cs
index e16b2049..5ecb73e2 100644
--- a/GFramework.Core/Resource/ResourceHandle.cs
+++ b/GFramework.Core/Resource/ResourceHandle.cs
@@ -11,7 +11,13 @@ namespace GFramework.Core.Resource;
/// 资源类型
internal sealed class ResourceHandle : IResourceHandle where T : class
{
+#if NET9_0_OR_GREATER
+ // net9.0 及以上目标使用专用 Lock,以满足分析器对专用同步原语的建议。
+ private readonly System.Threading.Lock _lock = new();
+#else
+ // net8.0 目标仍回退到 object 锁,以保持多目标编译兼容性。
private readonly object _lock = new();
+#endif
private readonly ILogger _logger = LoggerFactoryResolver.Provider.CreateLogger(nameof(ResourceHandle));
private readonly Action _onDispose;
private bool _disposed;
@@ -141,4 +147,4 @@ internal sealed class ResourceHandle : IResourceHandle where T : class
_logger.Error($"[ResourceHandle] Error disposing resource '{Path}': {ex.Message}");
}
}
-}
\ No newline at end of file
+}
diff --git a/GFramework.Core/Resource/ResourceManager.cs b/GFramework.Core/Resource/ResourceManager.cs
index 52e3a253..a6bef4cf 100644
--- a/GFramework.Core/Resource/ResourceManager.cs
+++ b/GFramework.Core/Resource/ResourceManager.cs
@@ -18,7 +18,13 @@ public class ResourceManager : IResourceManager
private readonly ResourceCache _cache = new();
private readonly ConcurrentDictionary _loaders = new();
+#if NET9_0_OR_GREATER
+ // net9.0 及以上目标使用专用 Lock,以满足分析器对专用同步原语的建议。
+ private readonly System.Threading.Lock _loadLock = new();
+#else
+ // net8.0 目标仍回退到 object 锁,以保持多目标编译兼容性。
private readonly object _loadLock = new();
+#endif
private readonly ILogger _logger = LoggerFactoryResolver.Provider.CreateLogger(nameof(ResourceManager));
private IResourceReleaseStrategy _releaseStrategy;
diff --git a/GFramework.Cqrs/Internal/WeakKeyCache.cs b/GFramework.Cqrs/Internal/WeakKeyCache.cs
index 54241dda..b632f1a2 100644
--- a/GFramework.Cqrs/Internal/WeakKeyCache.cs
+++ b/GFramework.Cqrs/Internal/WeakKeyCache.cs
@@ -16,7 +16,13 @@ internal sealed class WeakKeyCache
where TKey : class
where TValue : class
{
+#if NET9_0_OR_GREATER
+ // net9.0 及以上目标使用专用 Lock,以满足分析器对专用同步原语的建议。
+ private readonly System.Threading.Lock _gate = new();
+#else
+ // net8.0 目标仍回退到 object 锁,以保持多目标编译兼容性。
private readonly object _gate = new();
+#endif
private ConditionalWeakTable _entries = new();
///
diff --git a/GFramework.Game/Data/SaveRepository.cs b/GFramework.Game/Data/SaveRepository.cs
index 0c1f936c..68917b3d 100644
--- a/GFramework.Game/Data/SaveRepository.cs
+++ b/GFramework.Game/Data/SaveRepository.cs
@@ -33,7 +33,13 @@ public class SaveRepository : AbstractContextUtility, ISaveRepository
{
private readonly SaveConfiguration _config;
private readonly Dictionary> _migrations = new();
+#if NET9_0_OR_GREATER
+ // net9.0 及以上目标使用专用 Lock,以满足分析器对专用同步原语的建议。
+ private readonly System.Threading.Lock _migrationsLock = new();
+#else
+ // net8.0 目标仍回退到 object 锁,以保持多目标编译兼容性。
private readonly object _migrationsLock = new();
+#endif
private readonly IStorage _rootStorage;
///
diff --git a/GFramework.Game/Scene/SceneRouterBase.cs b/GFramework.Game/Scene/SceneRouterBase.cs
index 93f43379..0efc691b 100644
--- a/GFramework.Game/Scene/SceneRouterBase.cs
+++ b/GFramework.Game/Scene/SceneRouterBase.cs
@@ -11,6 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+using System;
using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Extensions;
using GFramework.Core.Logging;
@@ -111,7 +112,7 @@ public abstract class SceneRouterBase
/// 如果场景在栈中返回true,否则返回false。
public new bool Contains(string sceneKey)
{
- return Stack.Any(s => s.Key == sceneKey);
+ return Stack.Any(s => string.Equals(s.Key, sceneKey, StringComparison.Ordinal));
}
#endregion
diff --git a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
index 7e85bac2..5e21abeb 100644
--- a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
+++ b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
@@ -6,37 +6,51 @@
## 当前恢复点
-- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-073`
-- 当前阶段:`Phase 73`
+- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-075`
+- 当前阶段:`Phase 75`
- 当前焦点:
- - `2026-04-26` 主线程再次按 `$gframework-pr-review` 复核当前分支 PR `#291`,确认 latest-head 仍剩 `2` 条 open review thread,均指向 `ai-plan` 文档中的绝对路径记录
- - 当前批次同步 active todo/trace 与相关 archive trace:把 PR review 输出路径、临时 `dotnet` home 和失效 Windows fallback package folder 改写为仓库安全占位符
- - `dotnet clean` + `dotnet build` 的直接仓库根基线仍为 `639 Warning(s)`、`0 Error(s)`,因此本轮属于文档真值收口,而不是新的 warning 清理批次
+ - `2026-04-27` 按 `$gframework-batch-boot 50` 完成第一轮并行 warning 清理集成,当前先收口已验证改动,再进入下一轮低风险 slice
+ - 当前轮次已重新确认 `origin/main` 基线与 `HEAD` 同为 `617e0bf`,已提交 branch diff 现为 `12 / 50` files、`192` changed lines
+ - 当前主线程已整合 4 个 subagent 的首轮结果,并补修 `SaveRepository.cs` / `SceneRouterBase.cs` 的 touched-file 残留 warning;下一轮继续优先处理单文件、低耦合 warning
## 当前活跃事实
-- 当前 `origin/main` 基线提交为 `4ad880c`(`2026-04-25T14:35:38+08:00`)。
+- 当前 `origin/main` 基线提交为 `617e0bf`(`2026-04-26T12:17:15+08:00`)。
- 提权后的直接仓库根验证当前确认为:
- `dotnet clean`
- - 结果:成功;此前沙箱内 “Build FAILED but 0 errors” 的 clean 结果不是仓库真值
+ - 结果:成功;此前沙箱内缺失 Windows fallback package folder 的 clean 失败属于环境噪音,不是仓库真值
- `dotnet build`
- - 最新结果:成功;`639 Warning(s)`、`0 Error(s)`
-- 当前分支低风险批次文件:
- - `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md`
- - `ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md`
- - `ai-plan/public/analyzer-warning-reduction/archive/traces/analyzer-warning-reduction-history-rp062-rp071.md`
+ - 最新结果:成功;`430 Warning(s)`、`0 Error(s)`
+ - `dotnet build GFramework.sln -c Release`
+ - 最新结果:成功;`147 Warning(s)`、`0 Error(s)`
+- 当前分支 stop-condition 指标(已提交 `HEAD`):
+ - `git diff --name-only refs/remotes/origin/main...HEAD | wc -l`
+ - 最新结果:`12`
+ - `git diff --numstat refs/remotes/origin/main...HEAD`
+ - 最新结果:`192` changed lines
+- 当前批次已完成的 warning slice:
+ - `GFramework.Core` 事件 / 状态 / 属性 / 协程统计中的 `MA0158` 专用锁迁移
+ - `GFramework.Game/Data` 中 `DataRepository`、`UnifiedSettingsDataRepository`、`SaveRepository` 的 `ConfigureAwait` / 比较器 / 专用锁修正
+ - `GFramework.Game/Scene/SceneRouterBase.cs` 与 `GFramework.Game/UI/UiRouterBase.cs` 中的显式上下文 / 参数名 / 比较器修正
+- 当前批次待提交的集成改动:
+ - `GFramework.Core` / `GFramework.Cqrs` 第二组 `MA0158` 专用锁迁移
+ - `ai-plan/public/analyzer-warning-reduction/**` 的恢复点同步
- 当前批次验证结果:
- - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output `
- - 最新主线程结果:成功;确认 PR `#291` latest-head open review thread 为 `2`,两者都指向 `ai-plan` 文档中的绝对路径记录
+ - `dotnet clean`
+ - 最新主线程结果:提权直接执行成功,确认为当前权威 clean 基线
- `dotnet build`
- - 最新主线程结果:成功;`639 Warning(s)`、`0 Error(s)`;与当前权威仓库根基线一致
+ - 最新主线程结果:提权直接构建成功;`430 Warning(s)`、`0 Error(s)`
+ - `dotnet build GFramework.sln -c Release`
+ - 最新主线程结果:提权直接构建成功;`147 Warning(s)`、`0 Error(s)`
## 当前风险
-- `GFramework.Core`、`GFramework.Game`、`GFramework.Core.Tests`、`GFramework.Cqrs.Tests` 仍有较大 warning 基线。
- - 缓解措施:后续批次继续优先挑低风险、少文件、可独立验证的测试与局部逻辑切片。
-- 当前 review 相关真值要等新 head 推送后才能在 GitHub UI 中自动收口。
- - 缓解措施:本轮提交后立即重新执行 `$gframework-pr-review`,确认 PR `#291` 的 latest-head thread 与 nitpick 是否消失。
+- `GFramework.Game/Config/YamlConfigSchemaValidator*.cs` 仍然聚集多类高耦合 warning。
+ - 缓解措施:本轮先避开该热点,只清理低风险且 ownership 清晰的文件集合。
+- `MA0158` 迁移涉及 `net8.0` / `net9.0` / `net10.0` 多目标兼容。
+ - 缓解措施:复用 `StoreSelection.cs` 已存在的 `#if NET9_0_OR_GREATER` 专用锁模式,不在 `net8.0` 引入不兼容 API。
+- 本轮会并行使用多个 subagent,存在交叉修改风险。
+ - 缓解措施:每个 worker 仅拥有互不重叠的文件集合,并要求保留其他 agent 的并发更改。
## 活跃文档
@@ -58,6 +72,6 @@
## 下一步建议
-1. 推送包含本轮 absolute-path 脱敏的提交后,重新执行 `$gframework-pr-review`,确认 PR `#291` 的 latest-head open thread 是否已自动收口。
-2. 若 PR `#291` 已清零,继续以当前 `639 Warning(s)` 根基线为恢复点,按 `$gframework-batch-boot 50` 规则挑选下一个 1-3 文件的低风险热点。
-3. 若 GitHub 仍保留 review 信号,先确认它们是否仍指向新 head,再决定是否需要继续清理同主题下的其它历史 `ai-plan` 记录。
+1. 提交当前工作树里第二组锁迁移、`SaveRepository` / `SceneRouterBase` 补修与 `ai-plan` 同步,避免把两个批次混在同一组未提交改动里。
+2. 提交后重新计算 branch diff;若仍明显低于 `$gframework-batch-boot 50`,继续下发 2-3 个 `worker` subagent,优先处理 `SettingsModel.cs`、`RouterBase.cs`、`UiInteractionProfiles.cs` 等低风险单文件 warning。
+3. 若后续 branch diff 接近阈值,或剩余候选 slice 只剩 `YamlConfigSchemaValidator*` 这类高耦合热点,则在新的恢复点收口并等待下一轮。
diff --git a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
index a4a5b4d8..b22a466f 100644
--- a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
+++ b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
@@ -1,5 +1,70 @@
# Analyzer Warning Reduction 追踪
+## 2026-04-27 — RP-075
+
+### 阶段:完成 `$gframework-batch-boot 50` 第一轮并行 warning 清理集成
+
+- 触发背景:
+ - 用户要求先以权威构建输出建立 warning 基线,再把低风险 warning family 按文件边界拆给不同 subagent 并行清理
+ - 当前批次已完成首轮 worker 集成,但第二组锁迁移、主线程补修与 `ai-plan` 同步仍在工作树,需先收口提交再进入下一轮
+- 已接受的 delegated scope 与结果:
+ - worker-1:`GFramework.Core` 事件 / 状态 / 属性 / 协程统计中的 `MA0158`
+ - 结果:已提交 `8f2d959`,采用 `#if NET9_0_OR_GREATER` + `System.Threading.Lock` / `object` 双分支兼容模式
+ - worker-2:`GFramework.Core` / `GFramework.Cqrs` 资源、日志、配置缓存中的 `MA0158`
+ - 结果:改动已集成到工作树,待主线程与本轮 `ai-plan` 一并提交
+ - worker-3:`GFramework.Game/Data` 与 `SceneRouterBase.cs`
+ - 结果:已提交 `e3eec54`,主线程随后补修 `SceneRouterBase.Contains` 与 `SaveRepository._migrationsLock` 的 touched-file 残留 warning
+ - worker-4:`GFramework.Game/UI/UiRouterBase.cs`
+ - 结果:已提交 `7e13752`
+- 主线程验证里程碑:
+ - 提权 `dotnet clean`
+ - 结果:成功
+ - 提权 `dotnet build`
+ - 结果:成功;warning 从本轮批次建立时的 `639` 降到 `430`
+ - 提权 `dotnet build GFramework.sln -c Release`
+ - 结果:成功;`147 Warning(s)`、`0 Error(s)`
+ - `git diff --name-only refs/remotes/origin/main...HEAD | wc -l`
+ - 结果:`12`
+ - `git diff --numstat refs/remotes/origin/main...HEAD`
+ - 结果:`192` changed lines
+- 当前结论:
+ - 第一轮并行 warning 清理已经完成验证,且 warning 总量出现明显下降,可以继续按 batch 模式推进
+ - 当前 stop-condition 仍远低于 `$gframework-batch-boot 50`;但在派发下一轮之前,应该先提交当前工作树里的第二组锁迁移与恢复文档同步
+ - 下一轮优先目标保持“低风险、单文件、避免高耦合热点”,候选包括 `SettingsModel.cs`、`RouterBase.cs`、`UiInteractionProfiles.cs`
+
+## 2026-04-27 — RP-074
+
+### 阶段:按 `$gframework-batch-boot 50` 建立并行 warning 清理批次
+
+- 触发背景:
+ - 用户明确要求在拿到构建 warning 后分批指派给不同 subagent,以控制主线程上下文长度并提高 warning 清理效率
+ - 当前 worktree 映射到 `analyzer-warning-reduction` 主题,且该任务符合 batch candidate 条件:重复、可切片、可按文件边界独立验证
+- 基线与停止条件:
+ - 当前基线采用 `refs/remotes/origin/main`
+ - `origin/main` 与 `HEAD` 当前同为 `617e0bf`(`2026-04-26T12:17:15+08:00`)
+ - 主 stop condition 为 branch diff files 接近 `50`;当前为 `0 / 50`
+- 主线程实施:
+ - 先读取 `AGENTS.md`、`.ai/environment/tools.ai.yaml`、`ai-plan/public/README.md` 以及当前 topic 的 active todo/trace,确认批处理流程与 topic 上下文
+ - 先在沙箱内执行仓库根 `dotnet clean` / `dotnet build`;其中 `dotnet clean` 因缺失 Windows fallback package folder 失败,判定为环境噪音
+ - 按仓库规则提权重跑直接命令,确认权威基线为 `dotnet clean` 成功、`dotnet build` 成功且 `639 Warning(s)`、`0 Error(s)`
+ - 基于当前 warning 输出,预划分以下互不重叠的 subagent ownership:
+ - `GFramework.Core` / `GFramework.Cqrs` 的 `MA0158` 专用锁迁移
+ - `GFramework.Game/Data` 的 `MA0004` 与局部 `MA0002`
+ - `GFramework.Game/Scene/SceneRouterBase.cs`、`GFramework.Game/UI/UiRouterBase.cs` 的显式上下文 / 参数名 / 比较器修正
+- 验证里程碑:
+ - `dotnet clean`
+ - 结果:提权后成功;作为本轮 clean 真值
+ - `dotnet build`
+ - 结果:提权后成功;`639 Warning(s)`、`0 Error(s)`
+ - `git diff --name-only refs/remotes/origin/main...HEAD | wc -l`
+ - 结果:`0`
+ - `git diff --numstat refs/remotes/origin/main...HEAD`
+ - 结果:空输出
+- 当前结论:
+ - 本轮已经完成 batch boot 所需的权威警告基线建立,可以安全进入并行 worker 阶段
+ - 当前优先级应继续保持在低风险、少文件、可独立验证的 warning family 上,不直接扩展到 `YamlConfigSchemaValidator` 这类高耦合热点
+ - 下一步默认由主线程下发 disjoint worker 任务并在集成后重新计算 branch diff 与 warning 结果
+
## 2026-04-26 — RP-073
### 阶段:脱敏 analyzer-warning-reduction 文档中的绝对路径记录