test(cqrs): 收敛剩余 PR304 review 跟进

- 修复 fallback failure 测试夹具的并行执行与 stream state 文档命名问题

- 归档 cqrs-rewrite 历史 trace 与验证记录并压缩 active 恢复入口

- 更新当前验证结果与下一步,保持 PR304 review follow-up 可恢复
This commit is contained in:
gewuyou 2026-04-30 09:23:01 +08:00
parent 98021f59e7
commit 72ce0f1199
6 changed files with 171 additions and 426 deletions

View File

@ -10,6 +10,7 @@ namespace GFramework.Cqrs.Tests.Cqrs;
/// 验证 CQRS handler registrar 在 reflection fallback 元数据失效时的可观察告警行为。 /// 验证 CQRS handler registrar 在 reflection fallback 元数据失效时的可观察告警行为。
/// </summary> /// </summary>
[TestFixture] [TestFixture]
[NonParallelizable]
internal sealed class CqrsHandlerRegistrarFallbackFailureTests internal sealed class CqrsHandlerRegistrarFallbackFailureTests
{ {
private ILoggerFactoryProvider? _originalLoggerFactoryProvider; private ILoggerFactoryProvider? _originalLoggerFactoryProvider;

View File

@ -8,19 +8,20 @@ namespace GFramework.Cqrs.Tests.Cqrs;
/// </summary> /// </summary>
internal static class DispatcherStreamContextRefreshState internal static class DispatcherStreamContextRefreshState
{ {
private static readonly Lock SyncRoot = new(); private static readonly Lock _syncRoot = new();
private static int _nextHandlerInstanceId; private static int _nextHandlerInstanceId;
private static readonly List<DispatcherPipelineContextSnapshot> _handlerSnapshots = []; private static readonly List<DispatcherPipelineContextSnapshot> _handlerSnapshots = [];
/// <summary> /// <summary>
/// 获取每次建流时记录的快照副本。 /// 获取每次建流时记录的快照副本。
/// 共享状态通过 <c>SyncRoot</c> 串行化,避免并行测试写入抖动。
/// </summary> /// </summary>
/// <returns>当前已记录的 handler 上下文快照副本。</returns>
/// <remarks>共享状态通过 <c>_syncRoot</c> 串行化,避免并行测试写入抖动。</remarks>
public static IReadOnlyList<DispatcherPipelineContextSnapshot> HandlerSnapshots public static IReadOnlyList<DispatcherPipelineContextSnapshot> HandlerSnapshots
{ {
get get
{ {
lock (SyncRoot) lock (_syncRoot)
{ {
return _handlerSnapshots.ToArray(); return _handlerSnapshots.ToArray();
} }
@ -30,6 +31,7 @@ internal static class DispatcherStreamContextRefreshState
/// <summary> /// <summary>
/// 为新的 handler 测试实例分配稳定编号。 /// 为新的 handler 测试实例分配稳定编号。
/// </summary> /// </summary>
/// <returns>单调递增的 handler 实例编号。</returns>
public static int AllocateHandlerInstanceId() public static int AllocateHandlerInstanceId()
{ {
return Interlocked.Increment(ref _nextHandlerInstanceId); return Interlocked.Increment(ref _nextHandlerInstanceId);
@ -38,9 +40,13 @@ internal static class DispatcherStreamContextRefreshState
/// <summary> /// <summary>
/// 记录 handler 在当前建流中观察到的上下文。 /// 记录 handler 在当前建流中观察到的上下文。
/// </summary> /// </summary>
/// <param name="dispatchId">触发本次记录的稳定分发标识。</param>
/// <param name="instanceId">观察到该上下文的 handler 实例编号。</param>
/// <param name="context">当前分发注入到 handler 的架构上下文。</param>
/// <remarks>写入过程通过 <c>_syncRoot</c> 串行化,确保快照列表保持稳定顺序。</remarks>
public static void Record(string dispatchId, int instanceId, IArchitectureContext context) public static void Record(string dispatchId, int instanceId, IArchitectureContext context)
{ {
lock (SyncRoot) lock (_syncRoot)
{ {
_handlerSnapshots.Add(new DispatcherPipelineContextSnapshot(dispatchId, instanceId, context)); _handlerSnapshots.Add(new DispatcherPipelineContextSnapshot(dispatchId, instanceId, context));
} }
@ -49,9 +55,10 @@ internal static class DispatcherStreamContextRefreshState
/// <summary> /// <summary>
/// 清空历史记录与实例编号,避免跨测试污染断言。 /// 清空历史记录与实例编号,避免跨测试污染断言。
/// </summary> /// </summary>
/// <remarks>重置过程通过 <c>_syncRoot</c> 串行化,避免读取端观察到半清理状态。</remarks>
public static void Reset() public static void Reset()
{ {
lock (SyncRoot) lock (_syncRoot)
{ {
_nextHandlerInstanceId = 0; _nextHandlerInstanceId = 0;
_handlerSnapshots.Clear(); _handlerSnapshots.Clear();

View File

@ -0,0 +1,91 @@
# CQRS 重写迁移验证归档(至 RP-062
## 说明
- 本文件归档原 active tracking 中累积的历史验证命令与阶段性验证结论。
- `boot` 默认恢复入口应回到 `ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md`,不要再从这里挑选旧命令作为当前下一步。
## 原验证记录
- `RP-043` 之前的详细阶段记录、定向验证命令和阶段性决策均已移入主题内归档
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherCacheTests"`
- 结果:通过
- 备注:`5/5` 测试通过;本轮新增 cached executor 上下文刷新回归,确认 executor 复用时仍按当次分发重新注入上下文
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsReflectionFallbackAttributeTests"`
- 结果:通过
- 备注:`5/5` 测试通过;本轮锁定 fallback attribute 的公开归一化合同与空参数防御语义
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherCacheTests"`
- 结果:通过
- 备注:`7/7` 测试通过;本轮新增 cached notification / stream binding 上下文刷新回归,确认 binding 复用时仍按当次分发重新注入上下文
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherContextValidationTests"`
- 结果:通过
- 备注:`3/3` 测试通过;本轮锁定默认 dispatcher 对非 `IArchitectureContext` 上下文的 request / notification / stream 失败语义,且未引入新增 warning
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsHandlerRegistrarFallbackFailureTests"`
- 结果:通过
- 备注:`3/3` 测试通过;本轮锁定 registrar 在 fallback 元数据失效时的 warning 语义,且保持 generated registry 主路径不回退
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false`
- 结果:通过
- 备注:`63/63` 测试通过;当前沙箱限制了 MSBuild named pipe验证需在提权环境下运行
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`14/14` 测试通过;本轮覆盖 pointer / function pointer 合同拒绝、fallback 诊断与现有精确注册路径
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~Reports_Compilation_Error_And_Skips_Precise_Registration_For_Hidden_Pointer_Response|FullyQualifiedName~Reports_Diagnostic_And_Skips_Registry_When_Fallback_Metadata_Is_Required_But_Runtime_Contract_Lacks_Fallback_Attribute|FullyQualifiedName~Emits_Assembly_Level_Fallback_Metadata_When_Fallback_Is_Required_And_Runtime_Contract_Is_Available"`
- 结果:通过
- 备注:`3/3` 测试通过;本轮直接覆盖 PR #261 指向的 3 个 pointer / function pointer 回归场景
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsHandlerRegistrarTests"`
- 结果:通过
- 备注:`11/11` 测试通过;本轮覆盖 registrar 的 supported handler interface 缓存与 duplicate mapping 去重路径
- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release`
- 结果:通过
- 备注:`0 warning / 0 error`
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`17/17` 测试通过;本轮覆盖字符串 fallback 合同兼容路径与直接 `Type` fallback 元数据优先级
- `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release`
- 结果:通过
- 备注:`0 warning / 0 error`
- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release`
- 结果:通过
- 备注:`0 warning / 0 error`
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsHandlerRegistrarTests"`
- 结果:通过
- 备注:`13/13` 测试通过;本轮覆盖 mixed fallback metadata 的 registrar 消费路径
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`18/18` 测试通过;本轮覆盖 mixed fallback metadata 的双特性发射路径
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/gframework-pr-review.json`
- 结果:通过
- 备注:确认当前分支对应 `PR #302`latest head review 仍有 `3` 条 open AI threads其中 MegaLinter 仅报告 `dotnet-format` restore failure 噪音
- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release`
- 结果:通过
- 备注:`0 warning / 0 error`
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`18/18` 测试通过;本轮直接覆盖 fallback preamble 排版与特性个数断言收紧
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsHandlerRegistrarTests"`
- 结果:通过
- 备注:`13/13` 测试通过;本轮确认 mixed fallback metadata 的 registrar 消费路径未回归
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`21/21` 测试通过;本轮新增多维数组、交错数组与外部程序集隐藏元素类型的 precise runtime type lookup 回归
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`22/22` 测试通过;本轮新增“外部程序集隐藏泛型定义 + 可见类型实参”的 precise registration 回归,确认仍走定向运行时类型重建
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherCacheTests"`
- 结果:通过
- 备注:`4/4` 测试通过;本轮覆盖 request pipeline executor 的首次创建、复用与双行为顺序回归
- `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release`
- 结果:通过
- 备注:`0 warning / 0 error`;本轮确认 dispatcher request pipeline 形状缓存未破坏 `net8.0` / `net9.0` / `net10.0` 目标构建
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers|FullyQualifiedName~RegisterHandlers_Should_Cache_Loadable_Types_Across_Containers|FullyQualifiedName~Dispatcher_Should_Cache_Request_Pipeline_Executors_Per_Behavior_Count"`
- 结果:通过
- 备注:`3/3` 测试通过;本轮确认无捕获缓存工厂没有破坏 registrar / dispatcher 现有缓存行为
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`22/22` 测试通过;本轮新增外部程序集隐藏泛型定义的 precise registration 回归
- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release`
- 结果:通过
- 备注:`0 warning / 0 error`;本轮确认删除 pointer runtime-reconstruction 残留后生成器项目仍可正常构建
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`22/22` 测试通过;本轮确认 pointer / function pointer 拒绝语义保持不变,且未回归既有 precise runtime type lookup 场景

View File

@ -0,0 +1,35 @@
# CQRS 重写迁移追踪归档RP-046 至 RP-061
## 说明
- 本文件承接从 active trace 中迁出的已完成阶段细节。
- `boot` 默认恢复入口应回到 `ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md`,不要从本归档直接挑选旧阶段作为当前恢复点。
## 覆盖范围
- `CQRS-REWRITE-RP-046``CQRS-REWRITE-RP-061`
- 对应 active trace 清理前的 `2026-04-20``2026-04-29` 历史阶段记录
## 归档摘要
- `RP-046`generated registry 激活反射收敛,补齐私有无参构造兼容回归
- `RP-047`pointer precise runtime type 方案探索,后续已被 `RP-050` 明确覆盖并废弃
- `RP-048`registrar handler-interface 反射缓存
- `RP-049`registrar duplicate mapping 索引收敛
- `RP-050`pointer / function pointer 泛型合同拒绝
- `RP-051`direct fallback 元数据优先级收敛
- `RP-052`mixed fallback 元数据拆分
- `RP-053`precise runtime type lookup 数组回归补强
- `RP-054`:低风险并行批次收口
- `RP-055`:缓存工厂闭包收敛
- `RP-056`pointer runtime-reconstruction 残留清理
- `RP-057`cached executor 上下文刷新回归
- `RP-058`delegated fallback attribute 合同测试
- `RP-059`notification / stream binding 上下文刷新回归
- `RP-060`dispatcher 上下文前置条件失败语义回归
- `RP-061`registrar fallback 失败分支回归
## 备注
- 若后续需要恢复这些阶段的详细上下文,应以对应提交、测试文件与本主题源码为准。
- 当前 active trace 已不再保留这些阶段的逐段叙述,以保证 `boot` 能直接落到 `RP-062`

View File

@ -138,101 +138,28 @@ CQRS 迁移与收敛。
- 当前 `dotnet build GFramework.sln -c Release` 在 WSL 环境仍会受顶层 `GFramework.csproj` 的 Windows NuGet fallback 配置影响 - 当前 `dotnet build GFramework.sln -c Release` 在 WSL 环境仍会受顶层 `GFramework.csproj` 的 Windows NuGet fallback 配置影响
- 当前 `GFramework.Cqrs.Tests` 仍直接引用 `GFramework.Core`,说明测试已按模块意图拆分,但 runtime 物理迁移尚未完全切断依赖 - 当前 `GFramework.Cqrs.Tests` 仍直接引用 `GFramework.Core`,说明测试已按模块意图拆分,但 runtime 物理迁移尚未完全切断依赖
- `RegisterMediatorBehavior``MediatorCoroutineExtensions``ContextAwareMediator*Extensions` 仍作为兼容层存在,未来真正移除时仍需单独规划弃用窗口
## 活跃文档 ## 活跃文档
- 历史跟踪归档:[cqrs-rewrite-history-through-rp043.md](../archive/todos/cqrs-rewrite-history-through-rp043.md) - 历史跟踪归档:[cqrs-rewrite-history-through-rp043.md](../archive/todos/cqrs-rewrite-history-through-rp043.md)
- 验证历史归档:[cqrs-rewrite-validation-history-through-rp062.md](../archive/todos/cqrs-rewrite-validation-history-through-rp062.md)
- 历史 trace 归档:[cqrs-rewrite-history-through-rp043.md](../archive/traces/cqrs-rewrite-history-through-rp043.md) - 历史 trace 归档:[cqrs-rewrite-history-through-rp043.md](../archive/traces/cqrs-rewrite-history-through-rp043.md)
- `RP-046``RP-061` trace 归档:[cqrs-rewrite-history-rp046-through-rp061.md](../archive/traces/cqrs-rewrite-history-rp046-through-rp061.md)
## 验证说明 ## 验证说明
- `RP-043` 之前的详细阶段记录、定向验证命令和阶段性决策均已移入主题内归档 - `RP-043` 之前的详细阶段记录、定向验证命令和阶段性决策均已移入主题内归档
- active 跟踪文件只保留当前恢复点、当前活跃事实、风险和下一步,避免 `boot` 在默认入口中重复扫描 1000+ 行历史 trace - `RP-046``RP-062` 的历史验证命令与阶段性结果已移入验证归档active tracking 只保留当前恢复入口需要的最新验证
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherCacheTests"` - `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --format json --json-output /tmp/current-pr-review.json`
- 结果:通过 - 结果:通过
- 备注:`5/5` 测试通过;本轮新增 cached executor 上下文刷新回归,确认 executor 复用时仍按当次分发重新注入上下文 - 备注:确认当前分支对应 `PR #304`,并定位到仍需本地复核的 CodeRabbit / Greptile open thread
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsReflectionFallbackAttributeTests"` - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release`
- 结果:通过 - 结果:通过
- 备注:`5/5` 测试通过;本轮锁定 fallback attribute 的公开归一化合同与空参数防御语义 - 备注:`0 warning / 0 error`;本轮确认 XML 文档补齐、`NonParallelizable``_syncRoot` 命名与 `ai-plan` 收敛未引入新增编译问题
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherCacheTests"` - `bash scripts/validate-csharp-naming.sh`
- 结果:通过 - 结果:通过
- 备注:`7/7` 测试通过;本轮新增 cached notification / stream binding 上下文刷新回归,确认 binding 复用时仍按当次分发重新注入上下文 - 备注:使用显式 `GIT_DIR` / `GIT_WORK_TREE` 绑定重跑后,`1045` 个 tracked C# 文件的命名校验全部通过;本轮 `_syncRoot` 改名未引入命名规则回归
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherContextValidationTests"`
- 结果:通过
- 备注:`3/3` 测试通过;本轮锁定默认 dispatcher 对非 `IArchitectureContext` 上下文的 request / notification / stream 失败语义,且未引入新增 warning
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsHandlerRegistrarFallbackFailureTests"`
- 结果:通过
- 备注:`3/3` 测试通过;本轮锁定 registrar 在 fallback 元数据失效时的 warning 语义,且保持 generated registry 主路径不回退
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false`
- 结果:通过
- 备注:`63/63` 测试通过;当前沙箱限制了 MSBuild named pipe验证需在提权环境下运行
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`14/14` 测试通过;本轮覆盖 pointer / function pointer 合同拒绝、fallback 诊断与现有精确注册路径
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~Reports_Compilation_Error_And_Skips_Precise_Registration_For_Hidden_Pointer_Response|FullyQualifiedName~Reports_Diagnostic_And_Skips_Registry_When_Fallback_Metadata_Is_Required_But_Runtime_Contract_Lacks_Fallback_Attribute|FullyQualifiedName~Emits_Assembly_Level_Fallback_Metadata_When_Fallback_Is_Required_And_Runtime_Contract_Is_Available"`
- 结果:通过
- 备注:`3/3` 测试通过;本轮直接覆盖 PR #261 指向的 3 个 pointer / function pointer 回归场景
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsHandlerRegistrarTests"`
- 结果:通过
- 备注:`11/11` 测试通过;本轮覆盖 registrar 的 supported handler interface 缓存与 duplicate mapping 去重路径
- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release`
- 结果:通过
- 备注:`0 warning / 0 error`
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`17/17` 测试通过;本轮覆盖字符串 fallback 合同兼容路径与直接 `Type` fallback 元数据优先级
- `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release`
- 结果:通过
- 备注:`0 warning / 0 error`
- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release`
- 结果:通过
- 备注:`0 warning / 0 error`
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsHandlerRegistrarTests"`
- 结果:通过
- 备注:`13/13` 测试通过;本轮覆盖 mixed fallback metadata 的 registrar 消费路径
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`18/18` 测试通过;本轮覆盖 mixed fallback metadata 的双特性发射路径
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/gframework-pr-review.json`
- 结果:通过
- 备注:确认当前分支对应 `PR #302`latest head review 仍有 `3` 条 open AI threads其中 MegaLinter 仅报告 `dotnet-format` restore failure 噪音
- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release`
- 结果:通过
- 备注:`0 warning / 0 error`
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`18/18` 测试通过;本轮直接覆盖 fallback preamble 排版与特性个数断言收紧
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsHandlerRegistrarTests"`
- 结果:通过
- 备注:`13/13` 测试通过;本轮确认 mixed fallback metadata 的 registrar 消费路径未回归
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`21/21` 测试通过;本轮新增多维数组、交错数组与外部程序集隐藏元素类型的 precise runtime type lookup 回归
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`22/22` 测试通过;本轮新增“外部程序集隐藏泛型定义 + 可见类型实参”的 precise registration 回归,确认仍走定向运行时类型重建
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherCacheTests"`
- 结果:通过
- 备注:`4/4` 测试通过;本轮覆盖 request pipeline executor 的首次创建、复用与双行为顺序回归
- `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release`
- 结果:通过
- 备注:`0 warning / 0 error`;本轮确认 dispatcher request pipeline 形状缓存未破坏 `net8.0` / `net9.0` / `net10.0` 目标构建
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers|FullyQualifiedName~RegisterHandlers_Should_Cache_Loadable_Types_Across_Containers|FullyQualifiedName~Dispatcher_Should_Cache_Request_Pipeline_Executors_Per_Behavior_Count"`
- 结果:通过
- 备注:`3/3` 测试通过;本轮确认无捕获缓存工厂没有破坏 registrar / dispatcher 现有缓存行为
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`22/22` 测试通过;本轮新增外部程序集隐藏泛型定义的 precise registration 回归
- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release`
- 结果:通过
- 备注:`0 warning / 0 error`;本轮确认删除 pointer runtime-reconstruction 残留后生成器项目仍可正常构建
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- 结果:通过
- 备注:`22/22` 测试通过;本轮确认 pointer / function pointer 拒绝语义保持不变,且未回归既有 precise runtime type lookup 场景
## 下一步 ## 下一步
1. 继续 `Phase 8` 主线,优先再找一个收益明确且写集独立的 generator 或 registrar/dispatcher 热点;当前工作区若提交 registrar fallback 失败分支回归批次,相对 `origin/main` 的累计 diff 将达到 `32 files`,仍低于本轮 `gframework-batch-boot 50` 的主要 stop condition 1. push 当前 follow-up 提交后,重新执行 `$gframework-pr-review`,确认 `PR #304` 的 latest unresolved threads 是否已刷新为已解决,或仅剩新增有效项
2. 若继续文档主线,优先再扫教程入口页与 API 参考中的 CQRS 采用说明,确认是否还有旧 Command / Query 迁移口径残留
3. 若后续再出现新的 PR review 或 review thread 变化,再重新执行 `$gframework-pr-review` 作为独立验证步骤

View File

@ -2,352 +2,36 @@
## 2026-04-30 ## 2026-04-30
### 阶段PR #304 review follow-up 收敛CQRS-REWRITE-RP-062 ### 阶段PR #304 剩余 review follow-up 收敛CQRS-REWRITE-RP-062
- 本轮使用 `$gframework-pr-review` 重新抓取当前分支 PR - 本轮再次执行 `$gframework-pr-review`,确认当前分支 `feat/cqrs-optimization` 仍对应 `PR #304`
- 当前分支 `feat/cqrs-optimization` 对应 `PR #304` - 本地复核后继续收敛了上一轮遗留的 review 项:
- latest review 信号主要由 `7` 条 CodeRabbit nitpick 与 `2` 条 Greptile open threads 组成 - `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarFallbackFailureTests.cs` 已补 `NonParallelizable`
- MegaLinter 仍只给出 `dotnet-format``Restore operation failed`未附带当前仍成立的文件级格式问题CTRF 汇总为 `2203/2203` passed - `GFramework.Cqrs.Tests/Cqrs/DispatcherStreamContextRefreshState.cs` 已改用 `_syncRoot` 命名,并补齐缺失的 XML 文档标签
- 本地复核后接受并收敛的 review follow-up - `GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.cs` 三个内部 `Handle(...)` 已补齐 XML `param` / `returns`
- `GFramework.Cqrs/Internal/CqrsDispatcher.cs` - `DispatcherNotificationContextRefreshNotification``DispatcherStreamContextRefreshRequest` 已补 `DispatchId` XML 参数注释
- 为 `_pipelineExecutors``RequestPipelineInvocation.GetContinuation(...)` 补齐线程模型与失败模式说明 - `cqrs-rewrite` active tracking / trace 已压缩为当前恢复入口,并将已完成阶段的详细历史移入 archive
- 将 request pipeline invoker 从“按 `behaviorCount` 重复创建”收敛为“binding 内创建一次、executor 缓存复用” - 验证:
- `GFramework.Cqrs.Tests/Cqrs/*.cs` - `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release`
- 将 `DispatcherPipelineContextRefreshState``DispatcherNotificationContextRefreshState``DispatcherStreamContextRefreshState``DispatcherPipelineOrderState` 切换为 `System.Threading.Lock` 保护的共享状态 - 结果:通过,`0 warning / 0 error`
- 将 pipeline 顺序记录从公开可变 `List<string>` 收敛为 `Record(...)` + 快照只读访问
- 为 `CqrsDispatcherCacheTests` 添加 `[NonParallelizable]`,并补齐反射辅助方法的 XML `param` / `returns`
- 将 `CqrsRegistrationServiceTests` 的 debug 日志断言改为锁定语义片段而非整句文本
- 将 `CqrsHandlerRegistrarFallbackFailureTests` 的缓存字段诊断改为显式指出 `CqrsHandlerRegistrar` 耦合点
- `GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs`
- 将 precise runtime type lookup 的数组 / 外部泛型回归断言从局部变量名绑定改为稳定的语义片段断言
- 验证过程与结果:
- 首次把多个 `dotnet` restore / test 并发跑在同一 worktree 时,`GFramework.Cqrs.Tests` 出现 `*.nuget.g.props already exists` 竞争;该失败属于本地并发 restore 冲突,不代表代码问题
- 串行重跑后确认:
- `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release`
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-restore --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherCacheTests|FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsRegistrationServiceTests|FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsHandlerRegistrarFallbackFailureTests"`
- 在第一次串行测试中暴露 `MA0158 Use System.Threading.Lock` warning 后,已同轮切换同步原语并准备重跑无 warning 验证
- 结果:
- 本轮把仍成立的 PR review 评论全部收敛到本地代码或测试基础设施
- 下一步应以“重跑无 warning 验证 + 提交本轮 follow-up”为恢复入口而不是继续扩写新的 CQRS 优化切片
## 2026-04-29 ## 活跃事实
### 阶段registrar fallback 失败分支回归CQRS-REWRITE-RP-061 - 当前主题仍处于 `Phase 8`
- `PR #304` 的本地 follow-up 已再次收口一轮,后续需要在 push 后重新观察 GitHub 的 unresolved thread 刷新结果
- 已完成阶段的详细执行历史不再留在 active trace默认恢复入口只保留当前恢复点、活跃事实、风险与下一步
- 本轮继续按 `gframework-batch-boot 50` 的并行约束,把一个与主线程写集独立的新测试文件交给 worker ## 当前风险
- delegated scope`GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarFallbackFailureTests.cs`
- delegated objective锁定 registrar 在 fallback 元数据失效时的 warning 语义,而不扩张到 runtime 实现修改
- 主线程接受结果前的复核结论:
- 该文件只复用现有 generated-registry 测试替身与捕获型日志工厂,不修改 `CqrsHandlerRegistrarTests.cs` 与生产代码
- 三个用例分别覆盖 named fallback 无法解析、named fallback 解析抛异常、direct fallback 类型跨程序集三条失败分支
- 主线程已复核并重新执行定向验证:
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsHandlerRegistrarFallbackFailureTests"`
- `3/3` passed
- 结果:
- 当前 registrar 仍保持“跳过无效 fallback 条目 + 记录 warning”的既有语义
- 若连同当前工作区一起计算,当前分支相对 `origin/main` 的累计 diff 将达到 `32 files`
### 阶段dispatcher 上下文前置条件失败语义回归CQRS-REWRITE-RP-060 - 当前 `dotnet build GFramework.sln -c Release` 在 WSL 环境仍会受顶层 `GFramework.csproj` 的 Windows NuGet fallback 配置影响
- 远端 review thread 在本地提交前不会自动刷新GitHub 上看到的 open 状态可能暂时滞后于当前代码
- 延续 `gframework-batch-boot 50``Phase 8` 主线,本轮选择一个新的单文件测试切片:锁定默认 dispatcher 对“仅实现 `ICqrsContext`、但未实现 `IArchitectureContext` 的上下文”会如何失败 ## Archive Context
- 主线程先复核当前公开契约与实现后确认:
- `GFramework.Cqrs.Abstractions.Cqrs.ICqrsRuntime` 的 XML 文档已经把这类失败语义写成公开契约
- `CqrsDispatcher.PrepareHandler(...)` 当前正是唯一的上下文前置条件检查点,因此本轮最稳妥的切片仍是测试补强,而不是继续改 runtime
- 已完成的测试补强:
- 新增 `GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.cs`
- 通过 `CqrsRuntimeFactory.CreateRuntime(...)` + `Mock<IIocContainer>` 构造最小 runtime分别锁定 request、notification、stream 三条路径的失败语义
- 三个测试都只在需要上下文注入的 handler 已解析出来时触发,避免把“找不到 handler”与“上下文不满足注入前置条件”混淆成同一种异常
- 定向验证已通过:
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherContextValidationTests"`
- `3/3` passed
- 结果:
- 本轮只补测试,不改 `GFramework.Cqrs/Internal/CqrsDispatcher.cs`
- 若连同当前工作区一起计算,当前分支相对 `origin/main` 的累计 diff 将达到 `31 files`
### 阶段notification / stream binding 上下文刷新回归CQRS-REWRITE-RP-059
- 延续 `gframework-batch-boot 50``Phase 8` 主线,本轮继续沿着上一批 dispatcher cached executor 上下文回归往外扩一圈,但只覆盖 notification / stream 两条非 request 路径
- 主线程先复核 `CqrsDispatcher` 当前实现后确认:
- `PublishAsync(...)``CreateStream(...)` 都会在命中缓存 binding 后重新解析 handler并在调用前执行 `PrepareHandler(...)`
- 因此本轮最稳妥的切片仍是测试补强,而不是继续改 runtime
- 已完成的测试补强:
- 在 `GFramework.Cqrs.Tests/Cqrs/` 新增 `DispatcherNotificationContextRefresh*``DispatcherStreamContextRefresh*` 测试替身,记录重复分发时 handler 实例身份与 `ArchitectureContext`
- `CqrsDispatcherCacheTests` 新增 `Dispatcher_Should_Reinject_Current_Context_When_Reusing_Cached_Notification_Dispatch_Binding`
- `CqrsDispatcherCacheTests` 新增 `Dispatcher_Should_Reinject_Current_Context_When_Reusing_Cached_Stream_Dispatch_Binding`
- 定向验证已通过:
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherCacheTests"`
- `7/7` passed
- 结果:
- 本轮未暴露新的 runtime 实现缺口,因此没有改动 `GFramework.Cqrs/Internal/CqrsDispatcher.cs`
- 若连同当前工作区一起计算,当前分支相对 `origin/main` 的累计 diff 将达到 `29 files`,继续低于 `gframework-batch-boot 50` 的主要 stop condition
### 阶段delegated fallback attribute 合同测试CQRS-REWRITE-RP-058
- 本轮按 `gframework-batch-boot 50` 的并行约束,把一个与主线程写集完全独立的叶子级测试文件交给 worker
- delegated scope`GFramework.Cqrs.Tests/Cqrs/CqrsReflectionFallbackAttributeTests.cs`
- delegated objective锁定 `CqrsReflectionFallbackAttribute` 的公开归一化合同,而不扩张到 registrar / generator / dispatcher 实现
- 已接受的 worker 结果:
- 新增 `CqrsReflectionFallbackAttributeTests`,覆盖空 marker、字符串 fallback 名称的去空/去重/排序、直接 `Type` fallback 的去空/去重/排序,以及两个重载对空参数数组的防御行为
- worker 已独立验证 `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsReflectionFallbackAttributeTests"`,结果为 `5/5` passed
- 该叶子级测试批次已作为独立提交落地:`86a24e00` `test(cqrs): 新增 ReflectionFallbackAttribute 合同测试`
### 阶段cached executor 上下文刷新回归CQRS-REWRITE-RP-057
- 延续 `gframework-batch-boot 50``Phase 8` 主线,本轮只处理一个窄写集测试批次:为 cached request pipeline executor 增加“重复分发仍重新注入上下文”的回归
- 先复核上一轮 request pipeline executor 形状缓存实现与测试边界后确认:
- 当前 runtime 只允许本轮写集落在 `GFramework.Cqrs.Tests/Cqrs/`,除非测试直接打出 `CqrsDispatcher` 的真实缺陷
- 目标是锁定 executor 缓存不会跨分发保留旧 `ArchitectureContext`,且不扩张到 notification / stream 路径
- 已完成的测试补强:
- 在 `GFramework.Cqrs.Tests/Cqrs/` 新增 `DispatcherPipelineContextRefreshRequest``DispatcherPipelineContextRefreshBehavior``DispatcherPipelineContextRefreshRequestHandler``DispatcherPipelineContextRefreshState``DispatcherPipelineContextSnapshot`
- `DispatcherPipelineContextRefreshBehavior``DispatcherPipelineContextRefreshRequestHandler` 都基于 `CqrsContextAwareHandlerBase` 记录当次看到的 `ArchitectureContext`
- `CqrsDispatcherCacheTests` 新增 `Dispatcher_Should_Reinject_Current_Context_When_Reusing_Cached_Request_Pipeline_Executor`,断言同一个 cached executor 在两次分发间保持 executor 形状复用,但 handler 不会被 executor 黏住,且 handler / behavior 都会观察到本次分发的新上下文
- 调试过程中的结论:
- 初版断言曾要求 behavior 实例编号跨分发变化,随后确认这是错误假设
- `MicrosoftDiContainer.RegisterCqrsPipelineBehavior<TBehavior>()` 对已闭合的 pipeline behavior 使用的是 `AddSingleton(...)`
- 因此本轮最终锁定的是“singleton behavior 也必须重新注入上下文”,而不是强行要求 behavior 生命周期为 transient
- 定向验证已通过:
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherCacheTests"`
- `5/5` passed
- 结果:
- 本轮未暴露新的 runtime 实现缺口,因此没有改动 `GFramework.Cqrs/Internal/CqrsDispatcher.cs`
- 当前分支相对 `origin/main` 的累计提交 diff 仍为 `14 files`,继续低于 `gframework-batch-boot 50` 的主要 stop condition
### 阶段pointer runtime-reconstruction 残留清理CQRS-REWRITE-RP-056
- 延续 `gframework-batch-boot 50``Phase 8` 主线,本轮只处理一个写集很窄的 generator 清理切片:删除 `CqrsHandlerRegistryGenerator` 里已经不可达的 pointer runtime-reconstruction 残留
- 先复核当前实现后确认:
- `TryCreateRuntimeTypeReference` 已在入口直接拒绝 `IPointerTypeSymbol``IFunctionPointerTypeSymbol`
- `CanReferenceFromGeneratedRegistry` 也已统一把 pointer / function pointer 判定为不可直接引用
- 但 `RuntimeTypeReferenceSpec``AppendRuntimeTypeReferenceResolution(...)``ContainsExternalAssemblyTypeLookup(...)` 仍残留 pointer 子结构与 `MakePointerType()` 分支,属于已失效的死代码
- 已完成的清理:
- `GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.Models.cs` 已移除 `PointerElementTypeReference`
- `GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.SourceEmission.cs` 已移除 pointer 运行时重建分支与 `AppendPointerRuntimeTypeReferenceResolution(...)`
- `GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.RuntimeTypeReferences.cs` 已移除 pointer 外部程序集查找递归
- direct / named / mixed fallback 逻辑未改动pointer / function pointer 拒绝语义保持不变
- 定向验证已通过:
- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release`
- `0 warning / 0 error`
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- `22/22` passed
### 阶段缓存工厂闭包收敛CQRS-REWRITE-RP-055
- 延续 `gframework-batch-boot 50``Phase 8` 主线,本轮在不扩大语义面的前提下继续做一个更窄的 runtime 微切片:把弱缓存 / 并发缓存入口剩余的捕获型工厂收敛为 `static lambda + state`
- 先复核当前 runtime 热点后确认:
- `CqrsDispatcher` 的 notification / stream / request binding 与 pipeline executor 缓存仍存在少量可消除的捕获型工厂
- `CqrsHandlerRegistrar` 的程序集元数据缓存与可加载类型缓存也仍通过捕获 `logger` 的 lambda 建值
- 这些入口都只影响内部缓存建值,不触碰 handler / behavior 生命周期和 fallback 合同
- 已完成的收敛:
- `CqrsDispatcher` 现为 notification / stream / request binding 命中路径改用无捕获工厂pipeline executor 缓存改为显式状态对象承载 `requestType`
- `CqrsHandlerRegistrar` 现为 `AssemblyMetadataCache``LoadableTypesCache` 改用 `static` 工厂 + `logger` 显式状态参数
- 该批次没有改动 `RequestPipelineInvocation``next` 语义,也没有缓存 handler / behavior 实例
- 同轮继续补了一个独立 generator 覆盖缺口:
- `GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs` 新增“外部程序集隐藏泛型定义 + 可见类型实参”的 precise registration 回归
- 该回归锁定生成器会输出 `ResolveReferencedAssemblyType("...ProtectedEnvelope\`1")` 与 `MakeGenericType(typeof(string))` 的组合,而不是退回程序集级字符串 fallback
- 定向验证已通过:
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~RegisterHandlers_Should_Cache_Assembly_Metadata_Across_Containers|FullyQualifiedName~RegisterHandlers_Should_Cache_Loadable_Types_Across_Containers|FullyQualifiedName~Dispatcher_Should_Cache_Request_Pipeline_Executors_Per_Behavior_Count"`
- `3/3` passed
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- `22/22` passed
- `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release`
- `0 warning / 0 error`
### 阶段低风险并行批次收口CQRS-REWRITE-RP-054
- 继续按 `gframework-batch-boot 50` 推进 `Phase 8`,本轮先完成批次评估后再并行拆分写集,避免把 generator、runtime 与 docs 改动揉进同一片上下文
- 先复核当前 worktree、active tracking 与 `origin/main` 基线后确认:
- 当前分支头最初与 `origin/main` 对齐,批次阈值从 `0 files / 0 lines` 起算
- 本轮可以安全拆成三个互不冲突的切片request pipeline executor 形状缓存、precise runtime type lookup 数组回归补强、CQRS 入口文档对齐
- 主线程保留集成与验证职责subagent 只负责各自写集
- 本轮继续收口一个更窄的 generator 覆盖缺口:
- 在 `GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs` 新增“外部程序集隐藏泛型定义 + 可见类型实参”的 precise registration 回归
- 该回归锁定生成器会输出 `ResolveReferencedAssemblyType("...ProtectedEnvelope\`1")` 与 `MakeGenericType(typeof(string))` 的组合,而不是退回程序集级字符串 fallback
- 定向测试 `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"` 通过,结果为 `22/22` passed因此本轮未触发 `RuntimeTypeReferences` / `SourceEmission` 的实现修正
- 已接受并整合的并行写集:
- docs 切片:更新 `GFramework.Cqrs/README.md``docs/zh-CN/core/cqrs.md``docs/zh-CN/api-reference/index.md`,明确 generated registry 优先、targeted fallback 只补剩余 handler
- generator 切片:在 `GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs` 新增多维数组、交错数组、外部程序集隐藏元素类型三组 precise lookup 回归
- dispatcher 切片:在 `GFramework.Cqrs/Internal/CqrsDispatcher.cs` 中将 request pipeline 从“每次分发重建 next 链”收敛为“binding 内按 behaviorCount 缓存 executor 形状”,并补充 dispatcher cache / 顺序回归
- docs 切片已作为独立提交落地:
- `66830ba2` `docs(cqrs): 更新入口与回退语义说明`
- 本轮定向验证已通过:
- `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release`
- `0 warning / 0 error`
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsDispatcherCacheTests"`
- `4/4` passed
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- `21/21` passed
- 本轮停止时,当前工作区相对 `origin/main` 的累计 diff 为 `13 files / 709 lines`
- 结论:
- primary stop condition `50 files` 尚未触发,本轮停止是因为三条低风险切片已收口完毕
- 下一批更适合重新做一轮热点筛选,而不是在同一轮继续扩写集
### 阶段precise runtime type lookup 数组回归补强CQRS-REWRITE-RP-053
- 延续 `gframework-batch-boot 50``Phase 8` 主线,本轮选择一个更窄的 generator 覆盖缺口:锁定 precise runtime type lookup 下数组类型形态的回归
- 先复核当前实现后确认:
- `TryCreateRuntimeTypeReference` 已会把 `IArrayTypeSymbol` 递归建模为 `RuntimeTypeReferenceSpec.FromArray(element, rank)`
- `AppendArrayRuntimeTypeReferenceResolution` 已按 `ArrayRank == 1` 发射 `MakeArrayType()`,按 `rank > 1` 发射 `MakeArrayType(rank)`
- 当前缺口主要是测试面不足,尚未显式覆盖多维数组、交错数组、外部程序集隐藏元素类型这三类 precise lookup 场景
- 已在 `GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs` 补充三组回归:
- 隐藏元素类型的多维数组响应,锁定 `MakeArrayType(2)` 发射
- 隐藏元素类型的交错数组响应,锁定递归 `MakeArrayType().MakeArrayType()` 发射
- 外部程序集隐藏元素类型的多维数组响应,锁定 `ResolveReferencedAssemblyType(...)``MakeArrayType(2)` 的组合
- 本轮定向测试全部通过,未暴露数组发射缺陷:
- 因此没有修改 `GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.SourceEmission.cs`
- 也没有改动 `CqrsHandlerRegistryGenerator.RuntimeTypeReferences.cs`
- fallback 合同选择逻辑与 direct / named / mixed fallback 排版路径保持不变
- 定向验证已通过:
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- `21/21` passed
### 阶段mixed fallback 元数据拆分CQRS-REWRITE-RP-052
- 延续 `gframework-batch-boot 50``Phase 8` 主线,本轮把上一批的“全部可直接引用 fallback handlers 走 `Type[]`”继续推进到 mixed 场景
- 先复核现状后确认:
- `CqrsHandlerRegistrar` 已天然支持读取多个 `CqrsReflectionFallbackAttribute` 实例
- 上一批真正阻止 mixed 场景继续收敛的点,是 runtime attribute 本身尚未开放多实例,以及 generator 只能二选一发射单个 fallback 特性
- 已在 `GFramework.Cqrs/CqrsReflectionFallbackAttribute.cs` 中将特性约束改为 `AllowMultiple = true`,并补充注释说明多个实例的用途
- 已在 `GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs` 中扩展 fallback 合同探测:
- 探测 runtime 是否支持 `params string[]`
- 探测 runtime 是否支持 `params Type[]`
- 探测 runtime 是否允许多个 `CqrsReflectionFallbackAttribute` 实例
- 已在 `CqrsHandlerRegistryGenerator.Models.cs``CqrsHandlerRegistryGenerator.SourceEmission.cs` 中重构 fallback 发射模型:
- fallback 元数据现在可表示为一个或多个程序集级特性实例
- 当 fallback handlers 全部可直接引用时,继续优先输出单个 `Type[]` 特性
- 当 fallback 同时包含可直接引用与仅能按名称恢复的 handlers且 runtime 支持多实例时,拆分输出一条 `Type[]` 特性和一条字符串特性
- 若 runtime 不支持多实例或缺少相应构造函数,仍整体回退到字符串元数据,避免 mixed 场景漏注册
- 已补充 runtime 与 generator 双侧回归:
- `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs` 新增 mixed fallback metadata 用例,锁定 registrar 只对字符串条目调用一次 `Assembly.GetType(...)`
- `GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs` 新增 mixed fallback emission 用例,锁定 generator 会输出两个程序集级 fallback 特性实例
- 同步更新:
- `GFramework.Cqrs.SourceGenerators/README.md`
- `docs/zh-CN/source-generators/cqrs-handler-registry-generator.md`
- 说明 mixed 场景现在会拆分 `Type` 元数据与字符串元数据
- 定向验证已通过:
- `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release`
- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release`
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsHandlerRegistrarTests"`
- `13/13` passed
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- `18/18` passed
- 随后按 `$gframework-pr-review` 重新拉取当前分支 PR 审查数据:
- 当前 worktree `feat/cqrs-optimization` 已对应 `PR #302`
- latest head commit 仍有 `3` 条 open AI review threadsGreptile 指向 generator preamble 的死参数与多实例 fallback 特性空行CodeRabbit 指向 mixed/direct fallback 测试断言过宽
- MegaLinter 仍只暴露 `dotnet-format``Restore operation failed`,未给出本地仍成立的格式文件线索,因此按环境噪音处理
- 本轮已继续收口 `RP-052` 的 follow-up
- 在 `GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.SourceEmission.cs` 中移除已不再参与判断的 `generationEnvironment` 透传参数
- 调整多实例 fallback 特性发射时的换行策略,避免最后一个 fallback 特性与 `CqrsHandlerRegistryAttribute` 之间保留多余空行
- 在 `GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs` 中补强 direct/mixed fallback 发射断言,锁定特性实例个数、拒绝空 marker并确保 mixed 场景的程序集级 preamble 排版稳定
- 在 `GFramework.Cqrs.Tests/Cqrs/ReflectionFallbackNotificationContainer.cs` 中为 `DirectFallbackHandlerType` 补齐 `<returns>` XML 文档
- 本轮 review follow-up 验证已通过:
- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release`
- `0 warning / 0 error`
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- `18/18` passed
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsHandlerRegistrarTests"`
- `13/13` passed
## 2026-04-20
### 阶段direct fallback 元数据优先级收敛CQRS-REWRITE-RP-051
- 重新按 `gframework-batch-boot 50` 恢复 `Phase 8` 后,先复核当前 worktree 的恢复入口、`origin/main` 基线与分支规模:
- worktree 仍映射到 `cqrs-rewrite`
- 基线按批处理约定固定为 `origin/main`
- 本轮开始前分支累计 diff 为 `0 files / 0 lines`
- 结合当前代码热点与历史归档后,选择本轮批次目标为“继续收敛 generator fallback 元数据,进一步减少 runtime 按字符串类型名回查 handler 的场景”
- 已在 `GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs` 中新增 runtime fallback 合同探测:
- 识别 `CqrsReflectionFallbackAttribute` 是否支持 `params string[]`
- 识别 `CqrsReflectionFallbackAttribute` 是否支持 `params Type[]`
- 已在 `GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.Models.cs`
`CqrsHandlerRegistryGenerator.SourceEmission.cs` 中收敛 fallback 发射策略:
- 当本轮所有 fallback handlers 都可被生成代码直接引用,且 runtime 支持 `params Type[]` 时,生成器现优先发射 `typeof(...)` 形式的程序集级 fallback 元数据
- 当 fallback handlers 中仍存在不能直接引用的实现类型时,生成器继续整体回退到字符串元数据,避免 mixed 场景下部分 handler 走 `Type[]`、其余 handler 丢失恢复入口
- 已在 `GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs` 补充回归:
- 锁定 runtime 同时暴露字符串与 `Type` 两类 fallback 构造函数时,生成器优先选择直接 `Type` 元数据
- 保留现有字符串 fallback 合同测试,确保旧 contract 兼容路径不回退
- 同步更新:
- `GFramework.Cqrs.SourceGenerators/README.md`
- `docs/zh-CN/source-generators/cqrs-handler-registry-generator.md`
- 说明“可直接引用的 fallback handlers 会优先走 `typeof(...)` 元数据,减少运行时字符串回查”
- 定向验证已通过:
- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release`
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- `17/17` passed
- 额外修正:
- active tracking 中原先引用的 `ai-plan/migration/CQRS_MODULE_SPLIT_PLAN.md` 在当前 worktree 已不存在;本轮已移除该失效路径,后续以 active tracking / trace 作为默认恢复入口
### 阶段pointer / function pointer 泛型合同拒绝CQRS-REWRITE-RP-050
- 重新执行 `$gframework-pr-review` 后,确认当前分支对应 `PR #261`,状态仍为 `OPEN`
- latest reviewed commit 当前剩余 `1` 条 open CodeRabbit thread指向 `RP-047` 历史记录仍把 `MakePointerType()` precise registration 写成现行路径
- 本地核对后确认该评论有效:当前 pointer / function pointer 语义已由 `RP-050` 收敛为 fallback / diagnostic 路径,历史追踪必须显式标注 `RP-047` 已废弃,避免后续恢复时误回滚到旧方案
- 已在 `GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs` 中收紧 `TryCreateRuntimeTypeReference``CanReferenceFromGeneratedRegistry`
- pointer / function pointer 现统一视为不可精确生成的 CQRS 泛型合同,生成器会保守回退到既有 fallback / diagnostic 路径,而不再发射运行时 `MakeGenericType(...)` 风险代码
- 已在 `GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs` 中补充输入源诊断分离,并将相关测试改为显式断言 `CS0306` 与 fallback / diagnostic 结果
- 已同步修正 `ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md``RP-047` 段落,明确其已被 `RP-050` 覆盖,且不得恢复 `MakePointerType()` precise registration
- 定向验证已通过:
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~Reports_Compilation_Error_And_Skips_Precise_Registration_For_Hidden_Pointer_Response|FullyQualifiedName~Reports_Diagnostic_And_Skips_Registry_When_Fallback_Metadata_Is_Required_But_Runtime_Contract_Lacks_Fallback_Attribute|FullyQualifiedName~Emits_Assembly_Level_Fallback_Metadata_When_Fallback_Is_Required_And_Runtime_Contract_Is_Available"`
- `3/3` passed
- 扩展验证已通过:
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- `14/14` passed
### 阶段registrar duplicate mapping 索引收敛CQRS-REWRITE-RP-049
- 已将 `CqrsHandlerRegistrar` 的重复 handler mapping 判定从逐条线性扫描 `IServiceCollection` 收敛为单次构建的本地映射索引
- reflection fallback 或重复类型输入场景下,后续 duplicate mapping 判定改为 `HashSet` 命中,不再重复遍历已有服务描述符
- `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs` 已补充“程序集枚举返回重复 handler 类型时仍只注册一份映射”的回归
- 定向验证已通过:
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsHandlerRegistrarTests"`
- `11/11` passed
- 当前沙箱限制 MSBuild named pipe因此验证在提权环境下执行
### 阶段registrar handler-interface 反射缓存CQRS-REWRITE-RP-048
- 已在 `CqrsHandlerRegistrar` 中新增按 `Type` 弱键缓存的 supported handler interface 元数据reflection 注册路径现会复用已筛选且排序好的接口列表
- 同一 handler 类型跨容器重复注册时,不再重复执行 `GetInterfaces()` 与支持接口筛选;缓存仍保持卸载安全,不会长期钉住 collectible 类型
- `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs` 已补充 registrar 静态缓存清理与 supported interface 缓存复用回归
- 定向验证已通过:
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~GFramework.Cqrs.Tests.Cqrs.CqrsHandlerRegistrarTests"`
- `10/10` passed
- 当前沙箱限制 MSBuild named pipe因此验证在提权环境下执行
### 阶段pointer precise runtime type 覆盖扩展CQRS-REWRITE-RP-047已由 RP-050 覆盖)
- 曾在 `CqrsHandlerRegistryGenerator` 中尝试补充 pointer 类型的 runtime type 递归建模与源码发射,计划通过 `MakePointerType()` 还原隐藏 pointer 响应类型
- 该方案后续已被 `RP-050` 明确废弃pointer / function pointer 不能作为 CQRS 泛型合同的 precise registration 输入,当前实现统一回到 fallback / diagnostic 路径,不能恢复到 `MakePointerType()` 精确注册
- 已同步收紧 function pointer 签名的可直接生成判定,只有当签名中的返回值与参数类型均可从 generated registry 安全引用时才走静态注册
- 已保留含隐藏类型 function pointer handler 的 fallback / 诊断回归覆盖,确保 pointer 支持扩展不会误删原有程序集级 fallback 契约边界
- 后续若需恢复当前 pointer / function pointer 行为,应以 `RP-050` 为权威记录,而不是继续沿用本阶段的旧设计假设
- 定向验证与 `CqrsHandlerRegistryGeneratorTests` 全组验证均已通过:
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~Generates_Precise_Service_Type_For_Hidden_Pointer_Response|FullyQualifiedName~Reports_Diagnostic_And_Skips_Registry_When_Fallback_Metadata_Is_Required_But_Runtime_Contract_Lacks_Fallback_Attribute|FullyQualifiedName~Emits_Assembly_Level_Fallback_Metadata_When_Fallback_Is_Required_And_Runtime_Contract_Is_Available"`
- `3/3` passed
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
- `14/14` passed
- 当前沙箱限制 MSBuild named pipe因此验证在提权环境下执行
### 阶段generated registry 激活反射收敛CQRS-REWRITE-RP-046
- 已在 `CqrsHandlerRegistrar` 中将 generated registry 的无参构造激活改为类型级缓存工厂
- 默认路径优先使用一次性动态方法直接创建 registry避免后续每次命中缓存仍走 `ConstructorInfo.Invoke`
- 若运行环境不允许动态方法,则保留原有反射激活回退,确保 generated registry 路径不因运行时限制失效
- 已补充“私有无参构造 generated registry 仍可激活”的回归测试,覆盖现有生成器产物兼容性
- 定向验证已通过:
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false`
- `63/63` passed
- 当前沙箱限制 MSBuild named pipe因此验证在提权环境下执行
### Archive Context
- 历史跟踪归档:
- `ai-plan/public/cqrs-rewrite/archive/todos/cqrs-rewrite-history-through-rp043.md`
- 历史 trace 归档: - 历史 trace 归档:
- `ai-plan/public/cqrs-rewrite/archive/traces/cqrs-rewrite-history-through-rp043.md` - `ai-plan/public/cqrs-rewrite/archive/traces/cqrs-rewrite-history-through-rp043.md`
- `ai-plan/public/cqrs-rewrite/archive/traces/cqrs-rewrite-history-rp046-through-rp061.md`
### 当前下一步 ## 当前下一步
1. 回到 `Phase 8` 主线,优先再找一个写集独立的 generator 或 runtime 热点pointer runtime-reconstruction 残留已清空,后续不要恢复任何 `MakePointerType()` 发射路径 1. push 当前 follow-up 提交后,重新执行 `$gframework-pr-review`,确认 `PR #304` 的 latest unresolved threads 是否已刷新为已解决,或仅剩新增有效项
2. 若继续文档主线,优先补齐 `docs/zh-CN/api-reference` 与教程入口页中仍过时的 CQRS API / 命名空间表述
3. 若后续 review thread 或 PR 状态再次变化,再重新执行 `$gframework-pr-review` 复核远端信号