GFramework/ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md
gewuyou 0baa662ae4 test(cqrs-benchmarks): 隔离并发 benchmark 运行工件
- 新增 benchmark 入口 artifacts suffix 解析与独立 host 工作目录重启逻辑

- 更新 benchmark README 并发运行约定,补充隔离命令示例

- 更新 cqrs-rewrite 恢复文档,记录并发验证结果与后续恢复点
2026-05-11 08:58:18 +08:00

493 lines
65 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 重写迁移跟踪
## 目标
围绕 `GFramework` 当前的双轨 CQRS 现状,继续完成以“去外部依赖、降低反射、收口公开入口”为目标的
CQRS 迁移与收敛。
## 当前恢复点
- 恢复点编号:`CQRS-REWRITE-RP-131`
- 当前阶段:`Phase 8`
- 当前 PR 锚点:`待重新抓取`
- 当前结论:
- 当前 `RP-131` 继续沿用 `$gframework-batch-boot 50`,并把上一波定位到的 BenchmarkDotNet 并行运行冲突真正收口到 benchmark 入口层:`Program.cs` 现在支持 `--artifacts-suffix <suffix>`,并在声明 suffix 时自动把当前 benchmark 运行重启到独立的 host 工作目录
- 本轮继续沿用已复核的基线:`origin/main` 与本地 `main` 当前都在 `699d0b48``2026-05-09 18:39:38 +0800`);当前分支相对 `origin/main` 的累计 branch diff 仍约为 `9 files changed, 953 insertions(+), 83 deletions(-)`,离 `$gframework-batch-boot 50` 还有明显余量
- 本轮写面收敛在 benchmark 入口与文档两处:`GFramework.Cqrs.Benchmarks/Program.cs``GFramework.Cqrs.Benchmarks/README.md`;没有扩散到 benchmark 业务逻辑文件、`GFramework.Cqrs` runtime 或测试项目
- `Program.cs` 当前约定为:
- 解析并剥离仓库自定义参数 `--artifacts-suffix <suffix>`,避免把它误传给 BenchmarkDotNet CLI
- 支持通过环境变量回退复用同一套 suffix / artifacts path 约定
- 当 suffix 存在时,先把当前 benchmark 宿主输出复制到 `BenchmarkDotNet.Artifacts/<suffix>/host/`,再从该隔离宿主目录重启运行,使 BenchmarkDotNet 自动生成的 `GFramework.Cqrs.Benchmarks-Job-*` 项目、`OutDir` 与最终 results 都落到 suffix 私有目录下
- 并发 smoke 已直接证明这套隔离生效:`RequestLifetimeBenchmarks.SendRequest_*``StreamInvokerBenchmarks.Stream_*` 在两个终端并发 short-job 时,分别落到 `BenchmarkDotNet.Artifacts/req-lifetime-a/host/...``BenchmarkDotNet.Artifacts/stream-invoker-b/host/...`,不再共享同一 `.../bin/Release/net10.0/GFramework.Cqrs.Benchmarks-Job-JWUHXL-1/` 生成目录,也没有再出现 `.dll.config being used by another process`
- `README` 已同步新的运行约定:当两个带 `--filter` 的 benchmark 需要并发执行时,必须为每个进程传入不同的 `--artifacts-suffix`;该约束只服务于本地输出隔离,不代表 benchmark 业务语义本身需要额外依赖
- 下一推荐步骤:
- 若继续 benchmark 线,可重新利用新的并发运行隔离约定,单开一波更稳定的 `StreamInvokerBenchmarks` `DrainAll` 排序复核,或并行推进其他不冲突的 benchmark smoke
- 若上下文预算仍允许,下一批更适合继续保持在 `GFramework.Cqrs.Benchmarks` 单模块,避免过早把 review 面重新扩到 runtime 或测试层
- 更早的 `RP-123` 及之前阶段细节以下方 trace 与归档为准active 入口不再重复展开旧阶段流水。
- 当前分支相对 `origin/main` 的累计 branch diff 启动时为 `9 files`,仍明显低于 `$gframework-batch-boot 50` 的停止阈值;这一批继续保持单模块、低风险、可直接评审的 benchmark 边界
- 当前 `RP-113` 已继续沿用 `$gframework-batch-boot 50`,并把 notification 线从 benchmark 对照推进到实际 runtime 能力:新增公开内置 `TaskWhenAllNotificationPublisher`,让 `GFramework.Cqrs` 在保留默认顺序发布器的同时,提供与 `Mediator` `TaskWhenAllPublisher` 对齐的并行 notification publish 策略
- `TaskWhenAllNotificationPublisher` 当前语义明确为:零处理器静默完成,单处理器直接透传,多处理器并行启动并等待全部结束;它不保留默认顺序发布器的“首个异常立即停止”语义,而是把全部处理器的失败/取消结果收敛到同一个返回任务
- 本轮同时补齐 `CqrsNotificationPublisherTests` 对新内置策略的回归,并更新 `GFramework.Cqrs/README.md``docs/zh-CN/core/cqrs.md`,把切换方式和语义边界写回用户可见文档;当前已提交 branch diff 仍明显低于 `$gframework-batch-boot 50` 的停止阈值
- 这一批选择真正落一个内置 publisher strategy而不是继续加 notification benchmark 维度;原因是 `RP-111` / `RP-112` 已经把 notification gap 量化清楚,下一步更高价值的是开始收口“能力差距”而不是继续重复建立对照数据
- 当前 `RP-112` 已继续沿用 `$gframework-batch-boot 50`,并在 `RP-111` 的单处理器 notification 对照基础上补齐固定 `4 handler` 的 fan-out publish benchmark新增 `NotificationFanOutBenchmarks`,对比 baseline、`GFramework.Cqrs`、NuGet `Mediator` concrete runtime 与 `MediatR`
- `NotificationFanOutBenchmarks` 当前 short-job 基线约为 baseline `8.302 ns / 0 B``Mediator` `4.314 ns / 0 B``MediatR` `230.304 ns / 1256 B``GFramework.Cqrs` `434.413 ns / 408 B`;这说明 notification fan-out 的差距已经不只体现在单处理器 publish而是在固定 4 处理器场景下依然保持相近量级
- 本轮仍然只扩 benchmark 对照口径,没有直接修改 notification runtime 或 publisher 策略语义;原因是当前更高价值的事实是先量化“单处理器”和“固定 fan-out”两条 notification 路径的外部差距,再决定下一批是否值得切进 publisher strategy 或 runtime 热点
- 当前 `RP-111` 已继续沿用 `$gframework-batch-boot 50`,并按 skill 规则重新以 `origin/main` 作为基线复核:`origin/main` = `7ca21af9``2026-05-08 16:12:20 +0800`),本地 `main` = `c2d22285` 已落后,当前分支 `feat/cqrs-optimization``origin/main` 的累计 branch diff 为 `0 files / 0 lines`;基于“上下文预算优先、单批可评审边界次之”的停止规则,本轮选择 `NotificationBenchmarks` 这一条仍缺 `Mediator` concrete runtime 对照的单模块 benchmark 切片,而不是为了对称性继续扩展 notification runtime seam
- `NotificationBenchmarks` 现已从双方对照扩成三方对照:新增 NuGet `Mediator` source-generated concrete runtime 宿主与 `PublishNotification_Mediator()``BenchmarkNotification` / `BenchmarkNotificationHandler` 也同步接上 `Mediator` 的 notification 合同;当前 short-job 基线约为 `Mediator` `1.108 ns / 0 B``MediatR` `97.173 ns / 416 B``GFramework.Cqrs` `291.582 ns / 392 B`
- 本轮只把“notification publish 的高性能外部对照”补齐到 benchmark 层,而没有直接新增 generated notification invoker/provider 或 runtime 语义调整;原因是 notification dispatch 现有反射委托本就只在首次命中时缓存,继续加一层 provider 对 steady-state publish 的收益信号不如先把 `Mediator` concrete runtime 对照补齐来得清晰
- 当前 `RP-110` 已再次使用 `$gframework-pr-review` 复核 `PR #341` latest-head review`BenchmarkHostFactory` 的 legacy runtime alias 防守式类型检查、benchmark 宿主定向 generated registry 激活、以及 `CqrsDispatcher.SendAsync(...)` 的 faulted `ValueTask` 失败语义在当前 head 均已实质收口;本轮仅继续接受仍然成立的 CodeRabbit nitpick`SendAsync_Should_Return_Faulted_ValueTask_When_Handler_Is_Missing()` 补齐 `HasRegistration(...)` / `GetAll(...)` 防御性 mock并删除 trace 中重复 `本轮权威验证``本轮下一步` 段落
- 当前 `RP-109` 已使用 `$gframework-pr-review` 复核 `PR #341` latest-head reviewbenchmark 宿主改为定向激活当前场景的 generated registry避免同一 benchmark 程序集里的其他 registry 扩大冻结服务索引与 `HasRegistration` 基线;`BenchmarkHostFactory` 为 legacy runtime alias 注册补齐防守式类型检查与 stream lifetime 运行时注释;`CqrsDispatcher.SendAsync(...)` 在保留 direct-return 热路径的同时恢复 faulted `ValueTask` 失败语义,并补齐 generated registry 定向接线与 request fault 语义回归测试;`.agents/skills/gframework-batch-boot/SKILL.md` 的 MD005 缩进也已顺手修正
- `GFramework.Cqrs` 已完成对外部 `Mediator` 的生产级替代,当前主线已从“是否可替代”转向“仓库内部收口与能力深化顺序”
- `dispatch/invoker` 生成前移已扩展到 request / stream 路径,`RP-077` 已补齐 request invoker provider gate 与 stream gate 对称的 descriptor / descriptor entry runtime 合同回归
- `RP-078` 已补齐 mixed fallback metadata 在 runtime 不允许多个 fallback attribute 实例时的单字符串 attribute 回退回归
- `RP-079` 已补齐 runtime 缺少 generated handler registry interface 时的 generator 静默跳过回归
- `RP-080` 已将基础 generation gate 回归扩展到 notification handler interface、stream handler interface 与 registry attribute 缺失分支
- `RP-081` 已继续补齐基础 generation gate 的 logging 与 DI runtime contract 缺失分支
- 当前 `RP-082` 已补齐基础 generation gate 的 request handler runtime contract 缺失分支
- `RP-083` 已补齐 mixed direct / reflected-implementation request 与 stream invoker provider 发射顺序回归
- `RP-084` 已引入独立 `GFramework.Cqrs.Benchmarks` 项目,作为持续吸收 `Mediator` benchmark 组织方式的第一落点
- `RP-085` 已补齐 stream request benchmark对齐 `Mediator` messaging benchmark 的第二个核心场景
- `RP-086` 已补齐 request pipeline `0 / 1 / 4` 数量矩阵,开始把 benchmark 关注点从单纯 messaging steady-state 扩展到行为编排开销
- `RP-087` 已补齐 request startup benchmark把 initialization 与 cold-start 维度正式纳入 `GFramework.Cqrs.Benchmarks`
- 当前 `RP-088` 已补齐 request invoker reflection / generated-provider 对照,开始直接量化 dispatcher 预热 generated descriptor 的收益
- 当前 `RP-089` 已补齐 stream invoker reflection / generated-provider 对照,使 generated descriptor 预热收益从 request 扩展到 stream 路径
- 当前 `RP-090` 已收敛 `PR #326` benchmark review统一 benchmark 最小宿主构建、冻结 GFramework 容器、限制 MediatR 扫描范围,并恢复 request startup cold-start 对照
- 当前 `RP-091` 已把 benchmark 项目发布面隔离与包清单校验前移到 PR`GFramework.Cqrs.Benchmarks` 明确保持不可打包,`publish.yml``ci.yml` 复用同一份 packed-modules 校验脚本
- `RP-092` 已补齐 request handler `Singleton / Transient` 生命周期矩阵 benchmark并明确把 `Scoped` 对照留到具备真实显式作用域边界的宿主模型后再评估
- `RP-093` 已把 `GFramework.Core` 的 legacy `SendCommand` / `SendQuery` 兼容入口收敛到底层统一 `GFramework.Cqrs` runtime同时补充 `Mediator` 未吸收能力差距复核
- `RP-094` 已按 `PR #334` latest-head review 收口 legacy bridge 的测试注册方式、模块运行时依赖契约、异步取消语义、XML 文档缺口与兼容文档回退边界
- `RP-095` 已继续收口 `PR #334` 剩余 review把 legacy 同步 bridge 的阻塞等待统一切到线程池隔离 helper、补齐 `ArchitectureContext` / executor 共享 dispatch helper、修正 bridge fixture 的并行与容器释放约束,并为 runtime bridge 与 async void command cancellation 增补回归测试
- `RP-096` 已再次使用 `$gframework-pr-review` 复核 `PR #334` latest-head review确认仍显示为 open 的 AI threads 在本地代码中已无新增仍成立的运行时 / 测试 / 文档缺陷,剩余差异主要是 GitHub thread 未 resolve 的状态滞后
- `RP-097` 已继续收口 `PR #334` latest-head nitpick`AsyncQueryExecutorTests` / `CommandExecutorTests` 补齐可观察的上下文保留断言,并让 `RecordingCqrsRuntime` 在测试替身返回错误响应类型时抛出带请求/类型信息的诊断异常
- 当前 `RP-098` 已再次使用 `$gframework-pr-review` 复核 `PR #334` latest-head review并收口 `LegacyCqrsDispatchHelper.TryResolveDispatchContext(...)` 过宽吞掉 `InvalidOperationException` 的真实运行时诊断退化问题;现在仅把“上下文尚未就绪”视为允许 fallback 的信号,并为 fallback / 异常冒泡分别补齐回归测试
- `RP-099` 已补齐 `GFramework.Cqrs` 的最小 stream pipeline seam新增 `IStreamPipelineBehavior<,>` / `StreamMessageHandlerDelegate<,>``RegisterCqrsStreamPipelineBehavior<TBehavior>()`、dispatcher 侧 stream pipeline executor 缓存与 generated stream invoker 兼容回归,以及 `Architecture` 公开注册入口与对应文档说明
- 当前 `RP-100` 已使用 `$gframework-pr-review` 复核 `PR #339` latest-head review收口 `RegisterCqrsStreamPipelineBehavior<TBehavior>()` 的异常契约文档、为 `StreamPipelineInvocation.GetContinuation(...)` 补齐并发 continuation 缓存说明、抽取 `MicrosoftDiContainer` 的 CQRS 行为注册公共逻辑,并顺手修复当前 branch diff 内 `ICqrsRequestInvokerProvider.cs` 的 XML 缩进格式问题
- 当前 `RP-101` 已按用户新增 benchmark 诉求收口 request 热路径:为 `IIocContainer` 新增不激活实例的 `HasRegistration(Type)`、让 dispatcher 在 `0 pipeline` 场景下跳过空行为解析,并为 `MicrosoftDiContainer` 的热路径查询补齐 debug-level 守卫,避免无效日志字符串分配
- 当前 `RP-102` 已把 `GFramework.Cqrs.Benchmarks``Mediator` 对照组收口为官方 NuGet 引用(`Mediator.Abstractions` / `Mediator.SourceGenerator` `3.0.2`),不再使用本地 `ai-libs/Mediator` project reference`RequestBenchmarks` 现已新增 source-generated concrete `Mediator` 对照方法,并通过 `RequestLifetimeBenchmarks` 复核 hot path 收口后的新基线
- 当前 `RP-102` 已将 `BenchmarkDotNet.Artifacts/` 收口为默认忽略路径,并把 request steady-state / lifetime benchmark 复跑升级为 CQRS 性能相关改动的默认回归门槛;当前阶段目标明确为“持续逼近 source-generated `Mediator`,并至少稳定超过反射版 `MediatR`
- 当前 `RP-103` 已使用 `$gframework-pr-review` 复核 `PR #340` latest-head review修复 `CreateStream_Should_Throw_When_Stream_Pipeline_Behavior_Context_Does_Not_Implement_IArchitectureContext` 因 strict mock 未配置 `HasRegistration(Type)` 产生的 CI 失败,收紧 `MicrosoftDiContainer.HasRegistration(Type)` 到与 `GetAll(Type)` 一致的服务键可见性语义,补齐 `IIocContainer.HasRegistration(Type)` 的异常/XML 契约与 `docs/zh-CN/core/ioc.md` 的用户接入说明,并同步 benchmark 注释与 active tracking/trace 到当前 PR 锚点
- 当前 `RP-104` 已继续沿用 `$gframework-batch-boot 50` 压 request 热路径:先把 `CqrsDispatcher.SendAsync(...)` 改成 direct-return `ValueTask`,移除 dispatcher 自身的 `async/await` 状态机;再让 `MicrosoftDiContainer.HasRegistration(Type)` 在冻结后复用预构建的服务键索引,避免每次命中零 pipeline request 都线性扫描全部描述符;本轮 benchmark 表明第一刀显著压低 steady-state / lifetime request第二刀在当前短跑下主要确认“无回退、收益不明显”
- 当前 `RP-105` 已继续沿用 `$gframework-batch-boot 50` 压默认 request steady-state为 benchmark 最小宿主补齐 CQRS runtime / registrar / registration service 基础设施,让 `RequestBenchmarks` 不再只测反射路径,而是通过 handwritten generated registry + `RegisterCqrsHandlersFromAssembly(...)` 真实接上 generated request invoker provider本轮 benchmark 表明默认 request 路径进一步从约 `70.298 ns / 32 B` 压到约 `65.296 ns / 32 B``Singleton / Transient` lifetime 也同步收敛到约 `68.772 ns / 32 B``73.157 ns / 56 B`
- 当前 `RP-106` 已把同一套 generated-provider 宿主收口扩展到 `RequestPipelineBenchmarks`:新增 handwritten `GeneratedRequestPipelineBenchmarkRegistry`,并让 `RequestPipelineBenchmarks` 改走 `RegisterCqrsHandlersFromAssembly(...)` + benchmark CQRS 基础设施预接线;本轮 benchmark 表明 `0 pipeline` steady-state 进一步收敛到约 `64.755 ns / 32 B``1 pipeline``353.141 ns / 536 B``4 pipeline` 在短跑噪音下维持约 `555.083 ns / 896 B`
- 当前 `RP-107` 已把默认 stream steady-state 宿主也切到 generated-provider 路径:新增 handwritten `GeneratedDefaultStreamingBenchmarkRegistry`,让 `StreamingBenchmarks` 改走 `RegisterCqrsHandlersFromAssembly(...)` 并在 setup/cleanup 清理 dispatcher cache同时将 `gframework-boot` / `gframework-batch-boot` 的默认停止规则改为“AI 上下文预算优先,建议在预计接近约 80% 安全上下文占用前收口”,不再把 changed files 误当作唯一阈值
- 当前 `RP-108` 已补齐 stream handler `Singleton / Transient` 生命周期矩阵 benchmark新增 `StreamLifetimeBenchmarks``GeneratedStreamLifetimeBenchmarkRegistry`,让 stream 生命周期对照沿用 generated-provider 宿主接线而不是退回纯反射路径;本轮 benchmark 表明 `Singleton` 下 baseline / `GFramework.Cqrs` / `MediatR``80.144 ns / 137.515 ns / 229.242 ns``Transient` 下约 `77.198 ns / 144.998 ns / 228.185 ns`
- `ai-plan` active 入口现以 `RP-122` 为最新恢复锚点;`PR #340``PR #339``PR #334``PR #331``PR #326``PR #323``PR #307` 与其他更早阶段细节均以下方归档或说明为准
## 当前活跃事实
- 当前分支为 `feat/cqrs-optimization`
- 本轮 `$gframework-batch-boot 50``origin/main` (`d85828c5`, `2026-05-09 12:25:41 +0800`) 为基线;本地 `main` (`c2d22285`, `2026-05-06 21:34:59 +0800`) 已落后,不作为 branch diff 基线
- 当前已提交分支相对 `origin/main` 的累计 branch diff 为 `21 files``1344 insertions / 194 deletions`),仍明显低于 `$gframework-batch-boot 50``50 files` 停止阈值
- 当前用于收口 `PR #345` review 的写面额外覆盖 `AGENTS.md``GFramework.Cqrs.Benchmarks/README.md``ai-plan/public/cqrs-rewrite/**`;本轮代码层面的唯一触点保持在 `StreamLifetimeBenchmarks.cs`
- 当前 `PR #345` latest-head review body 已本地复核完毕;仍成立并已吸收的反馈集中在 `AGENTS.md` 术语说明、`StreamLifetimeBenchmarks` 的取消/注释细节,以及 benchmark README / `ai-plan` 恢复入口漂移
- 当前批次后的默认停止依据已改为 AI 上下文预算:若下一轮预计会让活动对话、已加载 recovery 文档、验证输出与当前 diff 接近约 `80%` 安全上下文占用,应在当前自然批次边界停止,即使 branch diff 仍有余量
- `GFramework.Cqrs.Benchmarks` 作为 benchmark 基础设施项目,必须持续排除在 NuGet / GitHub Packages 发布集合之外
- `GFramework.Cqrs.Benchmarks` 现已覆盖 request steady-state、pipeline 数量矩阵、startup、request/stream generated invoker以及 request handler `Singleton / Transient` 生命周期矩阵
- `GFramework.Cqrs.Benchmarks` 当前以 NuGet 方式引用 `Mediator.Abstractions` / `Mediator.SourceGenerator` `3.0.2``ai-libs/Mediator` 只保留为本地源码/README 对照资料,不再参与 benchmark 项目编译
- 当前 request steady-state benchmark 已形成 baseline / `Mediator` / `MediatR` / `GFramework.Cqrs` 四方对照:最新约 `5.608 ns / 32 B``5.445 ns / 32 B``57.071 ns / 232 B``64.825 ns / 32 B`
- 当前 request lifetime benchmark 已对齐 generated-provider 宿主路径:`Singleton` 下 baseline / `GFramework.Cqrs` / `MediatR` 约为 `5.012 ns / 32 B``49.612 ns / 32 B``51.796 ns / 232 B``Transient` 下约为 `3.962 ns / 32 B``50.480 ns / 56 B``50.284 ns / 232 B`
- 当前 request pipeline benchmark 已改为与默认 request steady-state 相同的 generated-provider 宿主接线路径:`0 pipeline``64.755 ns / 32 B``1 pipeline``353.141 ns / 536 B``4 pipeline``555.083 ns / 896 B`
- 当前 stream steady-state benchmark 也已切到 generated-provider 宿主接线路径baseline 约 `5.535 ns / 32 B``MediatR``59.499 ns / 232 B``GFramework.Cqrs``66.778 ns / 32 B`
- 当前 stream lifetime benchmark 已更新为 `Observation=FirstItem / DrainAll` 双口径:`Singleton + FirstItem` 下 baseline / generated / reflection / `MediatR` 约为 `48.704 ns / 216 B``94.629 ns / 216 B``95.417 ns / 216 B``152.886 ns / 608 B``Singleton + DrainAll` 下约为 `73.335 ns / 280 B``118.860 ns / 280 B``119.632 ns / 280 B``205.629 ns / 672 B`
- `Transient + FirstItem` 下 baseline / reflection / generated / `MediatR` 约为 `48.293 ns / 216 B``97.628 ns / 240 B``100.011 ns / 240 B``154.149 ns / 608 B``Transient + DrainAll` 下约为 `78.466 ns / 280 B``124.174 ns / 304 B``116.780 ns / 304 B``220.040 ns / 672 B`
- 本轮已验证旧 benchmark 劣化的两个主热点:`0 pipeline` 场景下仍解析空行为列表,以及容器查询热路径在 debug 禁用时仍构造日志字符串;两者收口后,`GFramework.Cqrs` request 路径不再出现额外数百字节分配
- `HasRegistration(Type)` 现在只把“同一服务键已注册”或“开放泛型服务键可闭合到目标类型”视为命中,不再把“仅以具体实现类型自注册”的行为误判为接口服务已注册;该语义与 `Get(Type)` / `GetAll(Type)` 已重新对齐
- `GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.cs` 已同步适配 `HasRegistration(Type)` fast-path避免 strict mock 因缺少新调用配置而在上下文失败语义断言前提前抛出 `Moq.MockException`
- `GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.cs` 现连“handler 缺失但仍返回 faulted `ValueTask`”这条 request 失败语义回归也显式为 `HasRegistration(Type)` / `GetAll(Type)` 预留了防御性 mock不再依赖 dispatcher 先判空 handler、后探测 pipeline 的内部顺序
- `docs/zh-CN/core/ioc.md` 已新增 `HasRegistration(Type)` 的使用语义、热路径用途与“按服务键而非可赋值关系判断”的示例说明
- 当前 request steady-state 仍落后于 source-generated `Mediator``MediatR`,但差距已从“额外数百字节分配 + 近 300ns”收敛到“零 pipeline fast-path 仍慢约 `31ns` / `3.6x``Mediator`”;下一批若继续压 request dispatch应优先评估默认路径吸收 generated invoker/provider 的空间
- 本轮 `SendAsync(...)` 的 direct-return `ValueTask` 改动已证明确实是有效热点:同样的短跑配置下,`GFramework.Cqrs` steady-state request 从约 `83.823 ns` 下探到 `69-70 ns` 区间
- 冻结后 `HasRegistration(Type)` 服务键索引化在当前短跑下没有带来同等量级的可见收益,但也没有引入功能回退或额外分配;后续若继续压零 pipeline request应优先重新评估“默认 request 路径进一步吸收 generated invoker/provider”而不是继续堆叠同层级微优化
- 默认 `RequestBenchmarks``RequestPipelineBenchmarks``StreamingBenchmarks` 现在都已通过 handwritten generated registry + 真实 `RegisterCqrsHandlersFromAssembly(...)` 宿主接线命中 generated invoker provider不再只代表纯反射 binding 路径
- `gframework-boot``gframework-batch-boot` 现明确把“上下文预算接近约 80%”视为默认优先停止信号branch diff files / lines 仅保留为次级仓库范围指标
- 当前性能回归门槛已收紧为:只要改动触达 `GFramework.Cqrs` request dispatch、DI 热路径、invoker/provider、pipeline 或 benchmark 宿主,就必须至少复跑 `RequestBenchmarks.SendRequest_*``RequestLifetimeBenchmarks.SendRequest_*`
- 当前阶段的性能验收目标已明确为:默认 request steady-state 路径不要求超过 source-generated `Mediator`,但必须持续逼近它,并至少稳定快于基于反射 / 扫描的 `MediatR`
- `GFramework.Core` 当前已通过内部 bridge request / handler 把 legacy `ICommand``IAsyncCommand``IQuery``IAsyncQuery` 接到统一 `ICqrsRuntime`
- 标准 `Architecture` 初始化路径会自动扫描 `GFramework.Core` 程序集中的 legacy bridge handler因此旧 `SendCommand(...)` / `SendQuery(...)` 无需改变用法即可进入统一 pipeline
- `CommandExecutor``QueryExecutor``AsyncQueryExecutor` 仍保留“无 runtime 时直接执行”的回退路径,用于不依赖容器的隔离单元测试
- `LegacyCqrsDispatchHelper` 现统一负责 runtime dispatch context 解析,以及 legacy 同步 bridge 对 `ICqrsRuntime.SendAsync(...)` 的线程池隔离等待
- `ArchitectureContext``CommandExecutor``QueryExecutor` 的同步 CQRS/legacy bridge 入口不再直接在调用线程上阻塞 `SendAsync(...).GetAwaiter().GetResult()`
- `GFramework.Core.Tests` 现通过 `InternalsVisibleTo("GFramework.Core.Tests")` 直接实例化内部 bridge handler不再依赖字符串反射装配测试桥接注册
- 使用 `LegacyBridgePipelineTracker``ArchitectureContextTests``ArchitectureModulesBehaviorTests` 现都显式标记为 `NonParallelizable`
- `ArchitectureContextTests.CreateFrozenBridgeContext(...)` 现把冻结容器所有权显式交回调用方,并在每个 bridge 用例的 `finally` 中释放
- `CommandExecutorModule``QueryExecutorModule``AsyncQueryExecutorModule` 现改为 `GetRequired<ICqrsRuntime>()` 并在 XML 文档里显式声明注册顺序契约,避免 runtime 缺失时静默回退
- `LegacyAsyncQueryDispatchRequestHandler``LegacyAsyncCommandResultDispatchRequestHandler``LegacyAsyncCommandDispatchRequestHandler` 现都通过 `ThrowIfCancellationRequested()` + `WaitAsync(cancellationToken)` 显式保留调用方取消可见性
- 相对 `ai-libs/Mediator`当前仍未完全吸收的能力集中在五类facade 公开入口、telemetry、notification publisher 策略、生成器配置与诊断、生命周期/缓存公开配置面
- 发布工作流已有 packed modules 校验,但 PR 工作流此前没有等价的 solution pack 产物名单校验
- 本地 `dotnet pack GFramework.sln -c Release --no-restore -o <temp-dir>` 当前只产出 14 个预期包,未复现 benchmark `.nupkg`
- `PR #334``2026-05-07` 的 latest-head review 当前显示 `CodeRabbit 10` / `Greptile 5` 个 open thread本轮再次复核后确认其中大部分仍是已实质修复但未 resolve 的 stale thread`LegacyCqrsDispatchHelper.TryResolveDispatchContext(...)` 的异常边界仍需要继续收口
- benchmark 场景现统一通过 `BenchmarkHostFactory` 构建最小宿主GFramework 侧在 runtime 分发前显式 `Freeze()` 容器MediatR 侧只扫描当前场景需要的 handler / behavior 类型
- `RequestStartupBenchmarks` 已恢复 `ColdStart_GFrameworkCqrs` 结果产出,不再命中 `No CQRS request handler registered`
- `BenchmarkDotNet` 在当前 agent 沙箱里会因自动生成的 bootstrap 脚本异常失败;同一 `dotnet run --no-build` 命令在沙箱外执行通过,因此本轮以沙箱外结果作为 benchmark 权威验证
- 已新增手动触发的 benchmark workflow默认只验证 benchmark 项目 Release build只有显式提供过滤器时才执行 BenchmarkDotNet 运行;过滤器输入现通过环境变量传入 shell避免 workflow_dispatch 输入直接插值到命令行
- 远端 `CTRF` 最新汇总为 `2311/2311` passedrun `#1079`, 2026-05-07
- `MegaLinter` 当前只暴露 `dotnet-format``Restore operation failed` 环境噪音,尚未提供本地仍成立的文件级格式诊断
- `LegacyCqrsDispatchHelper.TryResolveDispatchContext(...)` 现在只会把“Context 尚未设置”或“当前没有活动上下文”识别为可安全 fallback 的缺上下文信号;其他 `InvalidOperationException` 将继续向上传播,避免把真实运行时故障误判成 legacy 直执行场景
- `CommandExecutorTests` 已新增“缺上下文继续 fallback”和“意外 `InvalidOperationException` 必须冒泡”的回归,防止后续再次放宽该异常过滤面
- `PR #334` 当前 latest-head open AI feedback 经过本轮本地复核与修复后,应主要剩余待 GitHub 重新索引的状态差异或已实质关闭但未 resolve 的 thread
- `GFramework.Core.Tests` 中 legacy bridge 的“保留上下文”回归现在同时断言 bridge request 类型与目标对象执行期观察到的 `IArchitectureContext`
- `RecordingCqrsRuntime` 对非 `Unit` 响应已显式校验返回值类型;若测试工厂返回了 `null` 或错误装箱类型,异常会直接指出 request 类型与期望/实际响应类型
- `PR #339` 当前 latest-head review 仍显示 `2` 个 CodeRabbit open thread 与 `2` 个 nitpick本轮本地复核后确认
- `GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.cs``Per_Behavior_Count` 拼写已在当前 head 修正,属于 stale thread
- `GFramework.Core.Abstractions/Ioc/IIocContainer.cs` 的流式行为注册入口此前确实缺少 `<exception>` / `<remarks>` 契约说明,现已补齐并同步到 `IArchitecture` / `Architecture` / `ArchitectureModules`
- `GFramework.Cqrs/Internal/CqrsDispatcher.cs``StreamPipelineInvocation.GetContinuation(...)` 线程模型说明此前少于 request 对称路径,现已补齐并发 `next()` 时 continuation 缓存的语义边界
- `GFramework.Core/Ioc/MicrosoftDiContainer.cs` 的 request / stream 行为注册逻辑此前存在重复实现,现已抽取共享私有 helper 以避免后续生命周期或校验逻辑漂移
- 本地 `dotnet format GFramework.Cqrs/GFramework.Cqrs.csproj --verify-no-changes` 显示当前 diff 内仍有 `GFramework.Cqrs/ICqrsRequestInvokerProvider.cs` 的空白格式问题,本轮已修复;同一次命令报出的多条 `CHARSET` 提示集中在未触达的历史文件,不视为 `PR #339` 本轮新增 triage 结论
## 当前风险
- 当前 `_requestBehaviorPresenceCache` 依赖“同一 dispatcher 生命周期内request pipeline 行为注册在容器冻结后保持稳定”这一约束;若未来引入运行时动态增删 request behavior 的模型,需要重新评估这类实例级 presence cache 的失效策略
- 当前 `_streamBehaviorPresenceCache` 也依赖“同一 dispatcher 生命周期内stream pipeline 行为注册在容器冻结后保持稳定”这一约束;若后续引入运行期动态增删 stream behavior 或按 scope 改写可见性的模型,需要同步设计失效策略,而不能继续假设实例级缓存永久有效
- 标准架构启动路径现在已经有“自定义 notification publisher 不被默认顺序策略短路”的集成回归;但若后续再引入第三种仓库内置策略或新的启动快捷入口,仍需要同步补这条生产路径验证,不能只看 `CqrsTestRuntime` 测试宿主
- 顶层 `GFramework.sln` / `GFramework.csproj` 在 WSL 下仍可能受 Windows NuGet fallback 配置影响,完整 solution 级验证成本高于模块级验证
- 若后续新增 benchmark / example / tooling 项目但未同步校验发布面solution 级 `dotnet pack` 仍可能在 tag 发布前才暴露异常包
- `RequestStartupBenchmarks` 为了量化真正的单次 cold-start引入了 `InvocationCount=1` / `UnrollFactor=1` 的专用 job该配置会触发 BenchmarkDotNet 的 `MinIterationTime` 提示,后续若要做稳定基线比较,还需要决定是否引入批量外层循环或自定义 cold-start harness
- 当前 benchmark 宿主仍刻意保持“单根容器最小宿主”模型;若要公平比较 `Scoped` handler 生命周期,需要先引入显式 scope 创建与 scope 内首次解析的对照基线
- 当前 `Mediator` concrete runtime 对照已覆盖 steady-state request、单处理器 notification publish 与固定 `4 handler` notification fan-out若要把 `Transient` / `Scoped` 生命周期矩阵、stream 生命周期矩阵或更大 fan-out 矩阵也纳入同一组对照,需要按 `Mediator` 官方 benchmark 的做法拆分 compile-time lifetime / 场景配置,而不是在同一编译产物里混用多个 runtime 变量
- 当前 stream 生命周期矩阵尚未接入 `Mediator` concrete runtime若要继续对齐 `Mediator` 官方 benchmark 的 compile-time lifetime 设计,需要为 stream 场景补专门的 build-time 配置,而不是在当前统一宿主里临时拼接
- `BenchmarkDotNet.Artifacts/` 现已加入仓库忽略规则;若后续确实需要提交新的基准报告,应显式挑选结果文件或改走文档归档,而不是直接纳入整个生成目录
- 当前 `GFramework.Cqrs` request steady-state 仍慢于 `MediatR`;在“至少超过反射版 `MediatR`”这个阶段目标达成前,任何相关改动都不能只看功能 build/test 结果,必须附带 benchmark 回归数据
- 仓库内部仍保留旧 `Command` / `Query` API、`LegacyICqrsRuntime` alias 与部分历史命名语义,后续若不继续分批收口,容易混淆“对外替代已完成”与“内部收口未完成”
- 若继续扩大 generated invoker 覆盖面,需要持续区分“可静态表达的合同”与 `PreciseReflectedRegistrationSpec` 等仍需保守回退的场景
- legacy bridge 当前只为已有 `Command` / `Query` 兼容入口接到统一 request pipeline若后续要继续对齐 `Mediator`,仍需要单独设计 stream pipeline、telemetry 与 facade 公开面,而不是把这次 bridge 当成“全部收口完成”
- `LegacyBridgePipelineTracker` 仍是进程级静态测试辅助;虽然现在已在相关 fixture 清理阶段重置并补充线程安全说明,但若将来扩大并行 bridge fixture 数量,仍要继续控制共享状态扩散
- stream pipeline 当前只在“单次建流”层面包裹 handler 调用;若后续需要 per-item 拦截、元素级重试或流内 metrics 聚合,仍需额外设计更细粒度 contract而不是把本轮 seam 直接等同于元素级 middleware
- `PR #339` 在 GitHub 上仍有 1 个已本地失效但未 resolve 的 stale test-thread若后续 head 再次变化,需要重新抓取 latest-head review 确认未解决线程是否收敛
- 若后续继续依赖 `HasRegistration(Type)` 做热路径短路,新增测试替身或 strict mock 时必须同步配置该调用,否则容易在真正业务断言之前被 mock 框架短路成环境性失败
- `PR #345` 当前 latest-head review 仍以 CodeRabbit review body 的 `4` 条 actionable comments 为主;最新本地复核后,仍成立的问题集中在 `AGENTS.md` 术语说明、`StreamLifetimeBenchmarks` 的取消/文档细节,以及 benchmark README / `ai-plan` 恢复入口漂移
## 最近权威验证
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- 备注:覆盖 benchmark 入口 `--artifacts-suffix` 隔离实现、`README` 命令示例与 `ai-plan` 更新后的最小 Release build
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release --no-build -- --artifacts-suffix req-lifetime-a --filter "*RequestLifetimeBenchmarks.SendRequest_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:本次 auto-generated benchmark 项目已在 `BenchmarkDotNet.Artifacts/req-lifetime-a/host/...` 下执行;`Singleton` 约为 baseline `5.189 ns``MediatR` `52.765 ns``GFramework.Cqrs` `60.938 ns`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release --no-build -- --artifacts-suffix stream-invoker-b --filter "*StreamInvokerBenchmarks.Stream_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:本次 auto-generated benchmark 项目已在 `BenchmarkDotNet.Artifacts/stream-invoker-b/host/...` 下执行;`DrainAll` 约为 baseline `77.82 ns`、generated `130.37 ns`、reflection `139.08 ns``MediatR` `245.23 ns`
- `python3 scripts/license-header.py --check --paths GFramework.Cqrs.Benchmarks/Program.cs GFramework.Cqrs.Benchmarks/README.md ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md`
- 结果:通过
- `git --git-dir=<repo>/.git/worktrees/GFramework-cqrs --work-tree=. diff --check`
- 结果:通过
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- 备注:覆盖 `BenchmarkHostFactory` scoped stream helper、`StreamLifetimeBenchmarks` scoped 生命周期矩阵与 `README` 同步后的最小 Release build
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release --no-build -- --filter "*StreamLifetimeBenchmarks*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:`StreamLifetimeBenchmarks` 已稳定跑出 `24` 个 case`Scoped + DrainAll` 当前约为 baseline `81.20 ns / 280 B``MediatR` `428.66 ns / 1224 B`、generated `692.05 ns / 3888 B`、reflection `716.61 ns / 3888 B`
- `python3 scripts/license-header.py --check --paths GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs GFramework.Cqrs.Benchmarks/README.md ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md`
- 结果:通过
- `git --git-dir=<repo>/.git/worktrees/GFramework-cqrs --work-tree=. diff --check`
- 结果:通过
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- 备注:覆盖 `StreamLifetimeBenchmarks` 的代码收口与 benchmark `README` 同步后的最小 Release build
- `python3 scripts/license-header.py --check --paths AGENTS.md GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs GFramework.Cqrs.Benchmarks/README.md ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md`
- 结果:通过
- `git --git-dir=<repo>/.git/worktrees/GFramework-cqrs --work-tree=. diff --shortstat d85828c5...HEAD`
- 结果:通过
- 备注:当前分支相对 `origin/main` 的累计 diff 为 `21 files changed, 1344 insertions(+), 194 deletions(-)`
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release --no-build -- --filter "*RequestLifetimeBenchmarks.SendRequest_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:宿主已对齐 generated-provider 路径;`Singleton` 下 baseline / `GFramework.Cqrs` / `MediatR` 约为 `5.012 ns / 32 B``49.612 ns / 32 B``51.796 ns / 232 B``Transient` 下约为 `3.962 ns / 32 B``50.480 ns / 56 B``50.284 ns / 232 B`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release --no-build -- --filter "*StreamLifetimeBenchmarks*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:已产出 `baseline / GFramework reflection / GFramework generated / MediatR` 四方矩阵;`Singleton` 下约为 `79.602 / 120.553 / 111.547 / 208.381 ns``Transient` 下约为 `76.351 / 119.632 / 129.166 / 213.420 ns`
- `python3 scripts/license-header.py --check --paths ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md`
- 结果:通过
- `python3 scripts/license-header.py --check --paths GFramework.Cqrs/Internal/CqrsDispatcher.cs GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.cs GFramework.Cqrs.Tests/Cqrs/CqrsNotificationPublisherTests.cs GFramework.Cqrs.Tests/Cqrs/NotificationPublisherRegistrationExtensionsTests.cs GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.cs ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md`
- 结果:通过
- `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- 备注:首轮与 `GFramework.Cqrs.Tests` 并行构建时曾出现 `MSB3026` 单次复制重试;串行重跑同一命令后稳定通过
- `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CqrsDispatcherContextValidationTests|FullyQualifiedName~CqrsNotificationPublisherTests|FullyQualifiedName~NotificationPublisherRegistrationExtensionsTests|FullyQualifiedName~CqrsDispatcherCacheTests"`
- 结果:通过,`30/30` passed
- `git diff --check`
- 结果:通过
- `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~CqrsDispatcherCacheTests"`
- 结果:通过,`11/11` passed
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release --no-build -- --filter "*RequestBenchmarks.SendRequest_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:默认 request steady-state 当前约为 baseline `5.876 ns / 32 B``Mediator` `5.275 ns / 32 B``GFramework.Cqrs` `51.717 ns / 32 B``MediatR` `56.108 ns / 232 B`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release --no-build -- --filter "*RequestLifetimeBenchmarks.SendRequest_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:`Singleton` 下 baseline / `GFramework.Cqrs` / `MediatR``5.720 ns / 52.490 ns / 56.890 ns``Transient` 下约 `5.814 ns / 57.746 ns / 55.545 ns`
- `python3 scripts/license-header.py --check --paths GFramework.Cqrs/Internal/CqrsDispatcher.cs GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherCacheTests.cs`
- 结果:通过
- `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~ArchitectureModulesBehaviorTests"`
- 结果:通过,`5/5` passed
- `python3 scripts/license-header.py --check --paths GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs`
- 结果:通过
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release --no-build -- --filter "*NotificationFanOutBenchmarks*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:本轮对称化 MediatR handler 后fixed `4 handler` fan-out 对照约为 `Mediator` `3.598 ns / 0 B`、baseline `7.033 ns / 0 B``MediatR` `257.533 ns / 1256 B``GFramework.Cqrs` 顺序 `409.557 ns / 408 B``TaskWhenAll` `484.531 ns / 496 B`
- `python3 scripts/license-header.py --check --paths GFramework.Cqrs.Benchmarks/Messaging/NotificationFanOutBenchmarks.cs GFramework.Cqrs/README.md docs/zh-CN/core/cqrs.md ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md`
- 结果:通过
- `git diff --check`
- 结果:通过
- 备注:仅剩 `GFramework.sln` 的历史 CRLF 提示,无本轮新增 diff 格式问题
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release --no-build -- --filter "*NotificationFanOutBenchmarks*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:历史基线(`RP-112`)固定 `4 handler` notification fan-out 对照约为 baseline `8.302 ns / 0 B``Mediator` `4.314 ns / 0 B``MediatR` `230.304 ns / 1256 B``GFramework.Cqrs` `434.413 ns / 408 B`
- `python3 scripts/license-header.py --check --paths GFramework.Cqrs.Benchmarks/Messaging/NotificationFanOutBenchmarks.cs GFramework.Cqrs.Benchmarks/README.md`
- 结果:通过
- `git diff --check`
- 结果:通过
- 备注:仅剩 `GFramework.sln` 的历史 CRLF 提示,无本轮新增 diff 格式问题
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release --no-build -- --filter "*NotificationBenchmarks*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注notification publish 三方对照当前约为 `Mediator` `1.108 ns / 0 B``MediatR` `97.173 ns / 416 B``GFramework.Cqrs` `291.582 ns / 392 B`
- `python3 scripts/license-header.py --check --paths GFramework.Cqrs.Benchmarks/Messaging/NotificationBenchmarks.cs GFramework.Cqrs.Benchmarks/README.md`
- 结果:通过
- `git diff --check`
- 结果:通过
- 备注:仅剩 `GFramework.sln` 的历史 CRLF 提示,无本轮新增 diff 格式问题
- `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- 备注:并行验证首轮曾因 `build``test` 同时写入同一输出 DLL 触发 `MSB3026` 单次复制重试;改为串行重跑同一命令后稳定通过
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsDispatcherContextValidationTests"`
- 结果:通过,`6/6` passed
- `python3 scripts/license-header.py --check --paths GFramework.Cqrs.Tests/Cqrs/CqrsDispatcherContextValidationTests.cs`
- 结果:通过
- `git diff --check`
- 结果:通过
- 备注:仅剩 `GFramework.sln` 的历史 CRLF 提示,无本轮新增 diff 格式问题
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --format json --json-output /tmp/current-pr-review.json`
- 结果:通过
- 备注:确认当前分支对应 `PR #342`latest-head 当前显示 `CodeRabbit 4` / `Greptile 3` open thread其中真正仍成立的是 benchmark handler 对称性、README / 中文文档示例与恢复文档锚点漂移,其余历史 thread 需要按当前 head 继续甄别
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json`
- 结果:通过
- 备注:确认当前分支对应 `PR #340`latest-head 当前显示 `CodeRabbit 2` / `Greptile 2` open thread`CTRF` 报告中唯一失败测试为 `CreateStream_Should_Throw_When_Stream_Pipeline_Behavior_Context_Does_Not_Implement_IArchitectureContext`
- `dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~MicrosoftDiContainerTests"`
- 结果:通过,`52/52` passed
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CqrsDispatcherContextValidationTests"`
- 结果:通过,`4/4` passed
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*RequestBenchmarks.SendRequest_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注按新性能回归门槛复跑后steady-state request 对照约为 baseline `5.300 ns / 32 B``Mediator` `4.964 ns / 32 B``MediatR` `57.993 ns / 232 B``GFramework.Cqrs` `83.823 ns / 32 B`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*RequestLifetimeBenchmarks.SendRequest_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:按新性能回归门槛复跑后,`Singleton``GFramework.Cqrs` / `MediatR``83.183 ns / 32 B` vs `60.915 ns / 232 B``Transient` 下约 `86.243 ns / 56 B` vs `59.644 ns / 232 B`
- `env GIT_DIR=... GIT_WORK_TREE=... python3 scripts/license-header.py --check`
- 结果:通过
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `python3 scripts/license-header.py --check --paths GFramework.Cqrs.Benchmarks/Messaging/GeneratedStreamLifetimeBenchmarkRegistry.cs GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs GFramework.Cqrs.Benchmarks/README.md`
- 结果:通过
- `git diff --check`
- 结果:通过
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*RequestBenchmarks.SendRequest_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注steady-state request 对照约为 baseline `5.336 ns / 32 B``Mediator` `5.564 ns / 32 B``MediatR` `53.307 ns / 232 B``GFramework.Cqrs` `64.745 ns / 32 B`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*RequestLifetimeBenchmarks.SendRequest_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:`Singleton` 下 baseline / `MediatR` / `GFramework.Cqrs``4.309 ns / 51.923 ns / 67.981 ns``Transient` 下约 `5.029 ns / 54.435 ns / 76.437 ns`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*StreamLifetimeBenchmarks*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:`Singleton` 下 baseline / `GFramework.Cqrs` / `MediatR``80.144 ns / 137.515 ns / 229.242 ns``Transient` 下约 `77.198 ns / 144.998 ns / 228.185 ns`
- `git diff --check`
- 结果:通过
- 备注:当前仅保留 `GFramework.sln` 的历史 CRLF 警告,无本轮新增 diff 格式错误
- `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~MicrosoftDiContainerTests"`
- 结果:通过,`52/52` passed
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CqrsDispatcherCacheTests|FullyQualifiedName~CqrsDispatcherContextValidationTests"`
- 结果:通过,`14/14` passed
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release --no-build -- --filter "*RequestBenchmarks.SendRequest_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:本轮两批热路径收口后的最新 steady-state request 对照约为 baseline `6.141 ns / 32 B``Mediator` `6.674 ns / 32 B``MediatR` `61.803 ns / 232 B``GFramework.Cqrs` `70.298 ns / 32 B`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release --no-build -- --filter "*RequestLifetimeBenchmarks.SendRequest_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:最新 lifetime request 对照约为 `Singleton` 下 baseline / `MediatR` / `GFramework.Cqrs` = `4.706 ns / 52.197 ns / 73.005 ns``Transient` 下 = `4.571 ns / 50.175 ns / 74.757 ns`
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `python3 scripts/license-header.py --check --paths GFramework.Cqrs.Benchmarks/Messaging/GeneratedDefaultRequestBenchmarkRegistry.cs GFramework.Cqrs.Benchmarks/Messaging/BenchmarkHostFactory.cs GFramework.Cqrs.Benchmarks/Messaging/RequestBenchmarks.cs GFramework.Cqrs.Benchmarks/README.md`
- 结果:通过
- `git diff --check`
- 结果:通过
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*RequestBenchmarks.SendRequest_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:默认 steady-state request 对照现约为 baseline `5.013 ns / 32 B``Mediator` `5.747 ns / 32 B``MediatR` `51.588 ns / 232 B``GFramework.Cqrs` `65.296 ns / 32 B`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*RequestLifetimeBenchmarks.SendRequest_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:最新 lifetime request 对照约为 `Singleton` 下 baseline / `MediatR` / `GFramework.Cqrs` = `4.817 ns / 48.177 ns / 68.772 ns``Transient` 下 = `4.841 ns / 51.753 ns / 73.157 ns`
- `env GIT_DIR=... GIT_WORK_TREE=... python3 scripts/license-header.py --check`
- 结果:通过
- `git diff --check`
- 结果:通过
- 备注:仍仅保留 `GFramework.sln` 的历史 CRLF 警告,无本轮新增 diff 格式问题
- `dotnet pack GFramework.sln -c Release --no-restore -o /tmp/gframework-pack-validation -p:IncludeSymbols=false`
- 结果:通过
- 备注:当前本地产物仅包含 14 个预期发布包,未生成 `GFramework.Cqrs.Benchmarks.*.nupkg`
- `bash scripts/validate-packed-modules.sh /tmp/gframework-pack-validation`
- 结果:通过
- 备注:共享脚本确认 actual package set 与预期 14 个发布包完全一致
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~MicrosoftDiContainerTests"`
- 结果:通过,`51/51` passed
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*RequestBenchmarks.SendRequest_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:最新 steady-state request 对照约为 baseline `5.969 ns / 32 B``Mediator` `6.242 ns / 32 B``MediatR` `53.818 ns / 232 B``GFramework.Cqrs` `85.504 ns / 32 B`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*RequestLifetimeBenchmarks.SendRequest_*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:`Singleton``GFramework.Cqrs` / `MediatR``84.066 ns / 32 B` vs `56.096 ns / 232 B``Transient` 下约 `90.652 ns / 56 B` vs `57.207 ns / 232 B`
- `python3 scripts/license-header.py --check`
- 结果:通过
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*RequestStartupBenchmarks*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过
- 备注:`ColdStart_GFrameworkCqrs` 已恢复出数,最新本地输出约 `220-292 us`MediatR 对照约 `575-616 us`;当前仅剩 BenchmarkDotNet 对单次 cold-start 场景的 `MinIterationTime` 提示
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- 备注:用于验证本轮 request invoker / pipeline / stream invoker 调整与 benchmark workflow 改动后的 Release 编译结果
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --format json --json-output /tmp/current-pr-review.json`
- 结果:通过
- 备注:确认当前分支对应 `PR #334``CodeRabbit` latest review 已 `APPROVED`,但 latest-head 仍显示 `10` 个 open thread、`Greptile` 仍显示 `3` 个 open thread本地逐项复核后未发现新的仍成立缺陷最新 CI 测试汇总为 `2311/2311` passed`MegaLinter` 仅剩 `dotnet-format` restore 环境噪音
- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json`
- 结果:通过
- 备注:确认当前分支对应 `PR #339`latest-head 显示 `2` 个 CodeRabbit open thread 与 `2` 个 nitpick本轮本地接受并修复的问题集中在流式行为注册入口 XML 契约、stream continuation 线程说明与 `MicrosoftDiContainer` 的重复注册逻辑,测试方法拼写线程已在当前 head 失效
- `dotnet format GFramework.Cqrs/GFramework.Cqrs.csproj --verify-no-changes`
- 结果:发现当前 diff 内 `GFramework.Cqrs/ICqrsRequestInvokerProvider.cs` 的空白格式问题;其余 `CHARSET` 提示集中在未触达的历史文件
- `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CqrsDispatcherCacheTests"`
- 结果:通过,`10/10` passed
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~ArchitectureModulesBehaviorTests"`
- 结果:通过,`4/4` passed
- `env GIT_DIR=... GIT_WORK_TREE=... python3 scripts/license-header.py --check`
- 结果:通过
- `git diff --check`
- 结果:通过
- `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~CommandExecutorTests|FullyQualifiedName~AsyncQueryExecutorTests"`
- 结果:通过,`19/19` passed
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json`
- 结果:通过
- 备注:确认当前分支对应 `PR #334`;最新 review 仍为 `CodeRabbit APPROVED (2026-05-07T12:20:24Z)`latest-head 显示 `CodeRabbit 10` / `Greptile 5` open thread本轮接受并修复的仍成立问题收敛到 `LegacyCqrsDispatchHelper.TryResolveDispatchContext(...)` 的过宽异常吞掉逻辑
- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~CommandExecutorTests|FullyQualifiedName~QueryExecutorTests"`
- 结果:通过,`25/25` passed
- `python3 scripts/license-header.py --check`
- 结果:通过
- `git diff --check`
- 结果:通过
- `python3 scripts/license-header.py --check`
- 结果:通过
- `git diff --check`
- 结果:通过
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --format json --json-output <temporary-json-output>`
- 结果:通过
- 备注:确认当前分支对应 `PR #331`,本轮 latest-head open AI feedback 已收敛到 `dotnet pack --no-build`、共享包校验脚本跨平台兼容性与 active 文档 PR 锚点同步
- `python3 scripts/license-header.py --check`
- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE` 后运行
- `git diff --check`
- 结果:通过
- `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release -- --filter "*RequestLifetimeBenchmarks*" --job short --warmupCount 1 --iterationCount 1 --launchCount 1`
- 结果:通过(以沙箱外 `--no-build` 权威结果为准)
- 备注:`Singleton` 下 baseline / MediatR / GFramework 均值约 `5.633 ns / 58.687 ns / 301.731 ns``Transient` 下约 `5.044 ns / 52.274 ns / 287.863 ns`
- `python3 scripts/license-header.py --check`
- 结果:通过
- 备注:当前 WSL worktree 需要显式绑定 `GIT_DIR` / `GIT_WORK_TREE`
- `git diff --check`
- 结果:通过
- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~ArchitectureContextTests|FullyQualifiedName~CommandExecutorTests|FullyQualifiedName~QueryExecutorTests|FullyQualifiedName~AsyncQueryExecutorTests"`
- 结果:通过,`45/45` passed
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release`
- 结果:通过,`1644/1644` passed
- `env GIT_DIR=... GIT_WORK_TREE=... python3 scripts/license-header.py --check`
- 结果:通过
- `git diff --check`
- 结果:通过
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/current-pr-review.json`
- 结果:通过
- 备注:确认当前分支对应 `PR #334`;仍有效的 latest-head review 已收敛到 legacy bridge 测试装配、运行时依赖契约、异步取消、XML 文档与兼容文档边界
- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- 备注:修复新增 XML 文档 warning 后复跑,当前 `GFramework.Core` 三个 target framework 均已干净通过
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~ArchitectureContextTests|FullyQualifiedName~ArchitectureModulesBehaviorTests|FullyQualifiedName~CommandExecutorTests|FullyQualifiedName~QueryExecutorTests|FullyQualifiedName~AsyncQueryExecutorTests"`
- 结果:通过,`48/48` passed
- 备注:覆盖 legacy bridge 兼容入口、测试装配、执行器 runtime fallback 与相关模块行为
- `env GIT_DIR=... GIT_WORK_TREE=... python3 scripts/license-header.py --check`
- 结果:通过
- `git diff --check`
- 结果:通过
- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release`
- 结果:通过,`0 warning / 0 error`
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~ArchitectureContextTests|FullyQualifiedName~ArchitectureModulesBehaviorTests|FullyQualifiedName~CommandExecutorTests|FullyQualifiedName~QueryExecutorTests|FullyQualifiedName~AsyncQueryExecutorTests|FullyQualifiedName~LegacyAsyncCommandDispatchRequestHandlerTests"`
- 结果:通过,`54/54` passed
- 备注:覆盖 legacy 同步 bridge 的同步上下文隔离、bridge fixture 容器释放,以及 async void command cancellation 可见性
- `env GIT_DIR=... GIT_WORK_TREE=... python3 scripts/license-header.py --check`
- 结果:通过
## 下一推荐步骤
1. 若下一轮继续压 request steady-state优先挑选仍能减少常量热路径查询/分支的切片;继续避开“类型级 `IContextAware` 判定缓存”这条已验证无收益的热点假设
2. 若下一轮转向 benchmark 对齐,优先评估 `request scoped host + compile-time lifetime` 对照,而不是继续并行跑多个 BenchmarkDotNet 任务去争用同一自动生成目录
3. 若下一轮回到 notification 线,应把问题重新收敛到“是否值得公开第三种仓库内置 publisher strategy”或“是否需要 `IServiceCollection` 版本的公开入口”,而不是继续重复扩同层级回归
## 活跃文档
- 历史跟踪归档:[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)
- `RP-063``RP-074` 验证归档:[cqrs-rewrite-validation-history-rp063-through-rp074.md](../archive/todos/cqrs-rewrite-validation-history-rp063-through-rp074.md)
- `RP-062``RP-076` trace 归档:[cqrs-rewrite-history-rp062-through-rp076.md](../archive/traces/cqrs-rewrite-history-rp062-through-rp076.md)
- CQRS 与 Mediator 评估归档:[cqrs-vs-mediator-assessment-rp063.md](../archive/todos/cqrs-vs-mediator-assessment-rp063.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)
## 说明
- `PR #261``PR #302``PR #305``PR #307` 及更早阶段的详细过程已不再作为 active 恢复入口;如需追溯,以对应归档文件或历史 trace 段落为准
- active tracking 仅保留当前恢复点、当前风险、最近权威验证与下一推荐步骤,避免 `boot` 落到历史阶段细节