GFramework/ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md
gewuyou 96729ddcf1 test(cqrs): 补充基准与生成器回归基础设施
- 新增独立的 GFramework.Cqrs.Benchmarks 项目并引入 request、notification 对比场景

- 补充 request 与 stream invoker provider 的 mixed direct/reflected 顺序回归测试

- 更新 solution、meta-package 排除规则与 CQRS ai-plan 恢复点
2026-05-06 08:57:59 +08:00

299 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CQRS 重写迁移追踪
## 2026-04-30
### 阶段:历史 PR #307 active 入口收敛CQRS-REWRITE-RP-076
- 继续沿用 `$gframework-pr-review``PR #307` 做 latest-head triage本轮只处理仍成立的 `ai-plan` 恢复入口问题
- 主线程确认当前远端权威信号:
- 当时分支对应 `PR #307`,状态为 `OPEN`
- 远端 `CTRF` 最新汇总为 `2247/2247` passed
- `MegaLinter` 仅剩 `dotnet-format``Restore operation failed` 环境噪音
- 仍未闭环的 review 重点集中在 `cqrs-rewrite` active tracking / trace 仍保留过多历史锚点,而非新的运行时代码缺陷
- 本轮决策:
- 将 active tracking 收敛为单一恢复入口,只保留 `RP-076``PR #307`、活跃风险、最近权威验证与下一推荐步骤
- 将 active trace 收敛为当前阶段的关键事实与决策,不再在默认恢复入口中保留 `RP-062` 之后的长阶段流水账
- 新增 `archive/traces/cqrs-rewrite-history-rp062-through-rp076.md` 承接 `RP-062``RP-076` 的详细 trace 历史,保持旧阶段仍可追溯
### 验证RP-076
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --format json --json-output <temporary-json-output>`
- 结果:通过
- 备注:确认 `PR #307` 的当前 review 重点已收敛到 `ai-plan` 文档收尾
- `dotnet build GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Stream_Invoker_Provider_Metadata_When_Runtime_Lacks_Stream_Provider_Interface|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Stream_Invoker_Provider_Metadata_When_Runtime_Lacks_Stream_Descriptor_Enumerator|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Stream_Invoker_Provider_Metadata_When_Runtime_Lacks_Stream_Descriptor_Type|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Stream_Invoker_Provider_Metadata_When_Runtime_Lacks_Stream_Descriptor_Entry_Type|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Stream_Invoker_Provider_Metadata_When_Runtime_Contract_Is_Available"`
- 结果:通过,`5/5` passed
### 当前下一步RP-076
1. 当时继续按 `PR #307` 的 latest-head review 收尾,优先保持 active tracking 与 active trace 的单一锚点一致
2. 若继续推进代码切片,先复核 request 侧是否仍存在与 stream invoker gate 对称的生成合同遗漏
3. 进入下一批前继续使用最小 Release build 或 targeted test 作为权威验证,避免把环境噪音误判为代码问题
## 2026-05-04
### 阶段request invoker provider gate 对称回归CQRS-REWRITE-RP-077
- 使用 `$gframework-batch-boot 25` 继续 `feat/cqrs-optimization` 的 CQRS 收口批次
- 批次目标:在 branch diff 相对 `origin/main` 接近 `25` 个文件前,补齐低风险的 generator 合同回归切片
- 本轮先确认当前 worktree 已无 `local-plan` 遗留恢复入口,随后转入 `cqrs-rewrite` 的 request / stream invoker provider gate 对称性复核
- 结论:
- 生产代码已经同时检查 request provider、enumerator、descriptor 与 descriptor entry 四项 runtime 合同
- request 侧测试只覆盖缺少 provider / enumerator缺少 descriptor / descriptor entry 的回归覆盖落后于 stream 侧
- 已补齐:
- `Does_Not_Emit_Request_Invoker_Provider_Metadata_When_Runtime_Lacks_Request_Descriptor_Type`
- `Does_Not_Emit_Request_Invoker_Provider_Metadata_When_Runtime_Lacks_Request_Descriptor_Entry_Type`
- source emission XML 文档同步说明 provider gate 依赖完整 descriptor / descriptor entry 合同
### 验证RP-077
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Request_Invoker_Provider_Metadata_When_Runtime_Lacks_Request_Descriptor_Type|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Request_Invoker_Provider_Metadata_When_Runtime_Lacks_Request_Descriptor_Entry_Type|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Request_Invoker_Provider_Metadata_When_Runtime_Lacks_Request_Provider_Interface|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Emit_Request_Invoker_Provider_Metadata_When_Runtime_Lacks_Request_Descriptor_Enumerator"`
- 结果:通过,`4/4` passed
- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `python3 scripts/license-header.py --check`
- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行,避免脚本内部 plain `git ls-files` 误判仓库上下文
- `git diff --check`
- 结果:通过
### 当前下一步RP-077
1. 继续使用 `origin/main` 作为 `$gframework-batch-boot 25` 的基线,复算 branch diff 后决定是否还能接下一批
2. 若继续推进代码切片,优先查找 request / stream invoker provider runtime 合同之外的同类对称测试缺口
### 阶段mixed fallback attribute usage 回归CQRS-REWRITE-RP-078
- 继续沿用 `$gframework-batch-boot 25`,当前 branch diff 仍低于阈值
- 复核 fallback metadata runtime contract 后确认:
- mixed fallback 在 runtime 允许多个 fallback attribute 实例时已有直接 `Type` + 字符串拆分回归
- runtime 同时支持 `params Type[]` / `params string[]` 但不允许多个 fallback attribute 实例时,缺少锁定“整体回退到单个字符串 attribute”的回归
- 已补齐:
- `Emits_String_Fallback_Metadata_For_Mixed_Fallback_When_Runtime_Disallows_Multiple_Fallback_Attributes`
- `ReplaceAttributeUsageForType` 测试辅助方法,用于构造 runtime attribute usage 变体而不复制大型 source fixture
### 验证RP-078
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_String_Fallback_Metadata_For_Mixed_Fallback_When_Runtime_Disallows_Multiple_Fallback_Attributes"`
- 结果:通过,`1/1` passed
- `python3 scripts/license-header.py --check`
- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
- `git diff --check`
- 结果:通过
### 当前下一步RP-078
1. 继续复算 branch diff vs `origin/main`,若仍低于 `25` 个文件可继续下一批
2. 下一批优先查看 fallback metadata 与 generated invoker provider 之外是否还有同类 runtime contract gate 回归缺口
### 阶段:基础 generated registry contract gate 回归CQRS-REWRITE-RP-079
- 继续沿用 `$gframework-batch-boot 25`,当前 branch diff 仍低于阈值
- 复核 generator 基础启用条件后确认:缺少 `ICqrsHandlerRegistry`runtime 不具备承载 generated registry 的基础接口合同,应整体跳过发射
- 已补齐:
- `Does_Not_Generate_Registry_When_Runtime_Lacks_Handler_Registry_Interface`
### 验证RP-079
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Generate_Registry_When_Runtime_Lacks_Handler_Registry_Interface"`
- 结果:通过,`1/1` passed
- `python3 scripts/license-header.py --check`
- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
- `git diff --check`
- 结果:通过
### 当前下一步RP-079
1. 继续复算 branch diff vs `origin/main`,若仍低于 `25` 个文件可继续下一批
2. 下一批优先复核基础 generation gate 中其他必需 runtime contracts 是否也需要同类回归覆盖
### 阶段:基础 generated registry contract gate 扩展回归CQRS-REWRITE-RP-080
-`RP-079` 的单一 handler registry interface 缺失回归扩展为基础 generation gate 参数化测试
- 已补齐缺失分支:
- `ICqrsHandlerRegistry`
- `INotificationHandler<TNotification>`
- `IStreamRequestHandler<TRequest, TResponse>`
- `CqrsHandlerRegistryAttribute`
- stream handler interface 变体采用类型重命名构造 runtime metadata miss避免删除命名空间尾部单行接口时引入输入编译错误
### 验证RP-080
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Generate_Registry_When_Runtime_Lacks_Required_Generation_Contract"`
- 结果:通过,`4/4` passed
- `python3 scripts/license-header.py --check`
- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
- `git diff --check`
- 结果:通过
### 当前下一步RP-080
1. 继续复算 branch diff vs `origin/main`,若仍低于 `25` 个文件可继续下一批
2. 下一批优先复核基础 generation gate 中 logging / DI 依赖是否已有合适的输入编译安全回归覆盖方式
### 阶段:基础 generated registry external contract gate 回归CQRS-REWRITE-RP-081
- 延续 `RP-080` 的参数化基础 generation gate 测试,将外部 logging / DI 依赖也纳入同一组静默跳过回归
- 已补齐缺失分支:
- `GFramework.Core.Abstractions.Logging.ILogger`
- `Microsoft.Extensions.DependencyInjection.IServiceCollection`
- 两个变体均通过类型重命名构造 runtime metadata miss保持输入源码可编译避免把依赖缺失测试误写成编译失败测试
### 验证RP-081
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Generate_Registry_When_Runtime_Lacks_Required_Generation_Contract"`
- 结果:通过,`6/6` passed
- `python3 scripts/license-header.py --check`
- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
- `git diff --check`
- 结果:通过
### 当前下一步RP-081
1. 继续复算 branch diff vs `origin/main`,若仍低于 `25` 个文件可继续下一批
2. 下一批优先复核基础 generation gate 中 request handler contract 与 handler registry attribute 以外是否还有可安全构造的缺失分支
### 阶段:基础 generated registry request handler gate 回归CQRS-REWRITE-RP-082
- 延续 `RP-081` 的基础 generation gate 参数化测试,补齐 `IRequestHandler<TRequest,TResponse>` 缺失分支
- 该变体同样通过类型重命名构造 runtime metadata miss保持输入源码可编译
- 至此基础 generation gate 中可安全构造的缺失分支已覆盖:
- request handler interface
- notification handler interface
- stream handler interface
- handler registry interface
- handler registry attribute
- logging interface
- DI service collection interface
### 验证RP-082
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Does_Not_Generate_Registry_When_Runtime_Lacks_Required_Generation_Contract"`
- 结果:通过,`7/7` passed
- `python3 scripts/license-header.py --check`
- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
- `git diff --check`
- 结果:通过
### 当前下一步RP-082
1. 继续复算 branch diff vs `origin/main`,若仍低于 `25` 个文件可继续下一批
2. 下一批优先复核基础 generation gate 之外的 runtime contract 或 fallback selection 分支;基础 gate 的可安全构造缺失分支已覆盖
### 阶段PR #323 review 锚点收敛CQRS-REWRITE-RP-082
- 使用 `$gframework-pr-review` 重新拉取当前分支 PR review payload确认当前分支对应 `PR #323`,状态为 `OPEN`
- 本轮 latest-head open AI thread 仅指出 active tracking 中仍保留 `PR #307` 作为当前 PR 锚点;本地复核后确认该反馈仍成立
- 已将 active tracking 的当前 PR 锚点、活跃事实、最近 PR review 备注和下一推荐步骤统一到 `PR #323`
- `PR #307` 仅保留为历史 PR 说明和较早 trace 段落,不再作为 active 恢复入口
### 验证PR #323 review
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --format json --json-output <temporary-json-output>`
- 结果:通过
- 备注:确认 `PR #323` 只有 1 个 CodeRabbit open thread指向 active tracking 的 PR 锚点漂移
- 远端 `CTRF` 最新汇总为 `2274/2274` passed
- `MegaLinter` 当前仅报告 `dotnet-format``Restore operation failed` 环境噪音,未提供本地仍成立的文件级格式诊断
- `git diff --check`
- 结果:通过
- `python3 scripts/license-header.py --check`
- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
- `dotnet build GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
### 当前下一步PR #323 review
1. 若 review 重新触发后仍有 latest-head open thread继续以 `PR #323` 为当前唯一 PR 恢复锚点复核
2. 后续若继续推进代码切片,优先复核基础 generation gate 之外的 runtime contract 或 fallback selection 分支
## 2026-05-06
### 阶段mixed invoker provider 排序回归CQRS-REWRITE-RP-083
- 使用 `$gframework-batch-boot 50` 继续 `feat/cqrs-optimization` 的 CQRS 收口批次
- 批次目标:在 branch diff 相对 `origin/main` 接近 `50` 个文件前,继续补齐低风险的 generator runtime contract / emission 回归
- 本轮基线选择:
- `origin/main a8c6c11e`committer date `2026-05-05 13:14:24 +0800`
- `main a8c6c11e`committer date `2026-05-05 13:14:24 +0800`
- 当前分支 `feat/cqrs-optimization a8c6c11e`committer date `2026-05-05 13:14:24 +0800`
- 启动时 branch diff vs `origin/main``0` files / `0` lines因此继续选择低风险测试回归切片
- 本轮复核 `CreateGeneratedRegistrySourceShape` 与 invoker emission 路径后确认:
- 现有测试已覆盖 request / stream provider 的单一 direct 场景、单一 reflected-implementation 场景、precise reflected 跳过边界,以及各项 runtime contract 缺失分支
- 尚未锁定“同一 registry 同时包含 direct registration 与 reflected-implementation registration”时的 descriptor 顺序与 `Invoke*HandlerN` 编号稳定性
- 已补齐:
- `Emits_Request_Invoker_Provider_Metadata_In_Stable_Order_For_Mixed_Direct_And_Reflected_Implementations`
- `Emits_Stream_Invoker_Provider_Metadata_In_Stable_Order_For_Mixed_Direct_And_Reflected_Implementations`
- 两组 source fixture`MixedRequestInvokerProviderSource``MixedStreamInvokerProviderSource`
- 通过新增回归,显式锁定以下约束:
- provider descriptor 条目按稳定实现排序输出
- `InvokeRequestHandler0/1``InvokeStreamHandler0/1` 的方法编号随 emission 顺序连续增长
- 隐藏实现类型不会破坏 direct registration 与 reflected-implementation registration 的混合发射
### 验证RP-083
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Request_Invoker_Provider_Metadata_In_Stable_Order_For_Mixed_Direct_And_Reflected_Implementations|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Stream_Invoker_Provider_Metadata_In_Stable_Order_For_Mixed_Direct_And_Reflected_Implementations"`
- 结果:通过,`2/2` passed
### 当前 stop-condition 度量RP-083
- primary metricbranch diff files vs `origin/main`
- 当前说明active batch 尚未提交时,基于 `HEAD` 的 branch diff 仍显示 `0` files / `0` lines提交本批后再以新 `HEAD` 复算累计 branch diff
### 当前下一步RP-083
1. 提交本轮 mixed invoker provider 排序回归后,复算 branch diff vs `origin/main`,确认 `50` 文件阈值仍有充足余量
2. 若继续推进代码切片,优先复核 invoker provider 之外的 runtime contract 或 fallback selection 分支
### 阶段benchmark 基础设施引入CQRS-REWRITE-RP-084
- 用户明确将当前长期分支目标上提为:系统性吸收 `ai-libs/Mediator` 的实现思路与设计哲学,并将可取部分纳入 `GFramework.Cqrs`
- 本轮据此调整批次目标,不再把关注点收缩到单个 generator 回归,而是建立能持续比较和吸收设计差异的 benchmark 基础设施
- 参考 `ai-libs/Mediator` 的 benchmark 设计后,本轮采纳的核心结构包括:
- 独立 benchmark 项目壳,而非扩展现有 NUnit 测试项目
- 共享 `Fixture` 输出并校验场景配置
- `Request` / `Notification` 两个 messaging 场景作为首批最小落点
- 自定义列 `CustomColumn`,为后续矩阵扩展保留可读结果标签
- 本轮新增:
- `GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj`
- `GFramework.Cqrs.Benchmarks/Program.cs`
- `GFramework.Cqrs.Benchmarks/CustomColumn.cs`
- `GFramework.Cqrs.Benchmarks/Messaging/Fixture.cs`
- `GFramework.Cqrs.Benchmarks/Messaging/BenchmarkContext.cs`
- `GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs`
- `GFramework.Cqrs.Benchmarks/Messaging/NotificationBenchmarks.cs`
- `GFramework.Cqrs.Benchmarks/README.md`
- 设计取舍:
- 使用最小 `ICqrsContext` marker避免把完整 `ArchitectureContext` 初始化成本混入 steady-state dispatch
- 直接复用 `GFramework.Cqrs.CqrsRuntimeFactory``MicrosoftDiContainer`,让基准聚焦于 runtime dispatch / publish
- 外部对照组先接入 `MediatR`,保持与 `Mediator` benchmark 的对照哲学一致;但本轮仍只做最小 request / notification 场景
- 暂不把 source generator benchmark、cold-start 独立工程或完整 pipeline / stream 矩阵一起引入,避免首批 scope 失控
- 兼容性修正:
- 在根 `GFramework.csproj` 中显式排除 `GFramework.Cqrs.Benchmarks/**`,避免 meta-package 意外编译 benchmark 源码
- 将 benchmark 项目加入 `GFramework.sln`,保持仓库级工作流完整
### 验证RP-084
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `GIT_DIR=<worktree-git-dir> GIT_WORK_TREE=<worktree-root> python3 scripts/license-header.py --check`
- 结果:通过
- `git diff --check`
- 结果:通过
### 当前 stop-condition 度量RP-084
- primary metricbranch diff files vs `origin/main`
- 当前说明:本轮仍在 `50` 文件阈值以内,可继续按 benchmark 场景或 CQRS runtime 对照能力分批推进
### 当前下一步RP-084
1. 继续扩展 `GFramework.Cqrs.Benchmarks`,优先补齐 pipeline、stream、cold-start 与 generated invoker provider 对照场景
2. 当后续有具体 runtime 优化切片时,用该 benchmark 项目验证是否真正吸收到了 `Mediator` 的低开销 dispatch 设计收益