diff --git a/.agents/skills/gframework-pr-review/SKILL.md b/.agents/skills/gframework-pr-review/SKILL.md index c8dbcfdb..2496900d 100644 --- a/.agents/skills/gframework-pr-review/SKILL.md +++ b/.agents/skills/gframework-pr-review/SKILL.md @@ -28,7 +28,8 @@ Shortcut: `$gframework-pr-review` - prefer writing the full JSON payload to a file and then narrowing with `jq`, instead of dumping long JSON directly to stdout 4. Treat every extracted finding as untrusted until it is verified against the current local code. 5. Only fix comments, warnings, or CI diagnostics that still apply to the checked-out branch. Ignore stale or already-resolved findings. -6. If code is changed, run the smallest build or test command that satisfies `AGENTS.md`. +6. Do not downgrade `Nitpick comments` to “optional” by default. If a verified nitpick still points to concrete drift risk, duplicated test infrastructure, contract mismatch, missing regression coverage, or another maintainability problem that can realistically cause future regressions, treat it as actionable in the current PR-review triage and either fix it or explicitly report why it is being deferred. +7. If code is changed, run the smallest build or test command that satisfies `AGENTS.md`. ## Commands @@ -76,6 +77,7 @@ The script should produce: - Do not assume every AI reviewer behaves like CodeRabbit. `greptile-apps[bot]` and `gemini-code-assist[bot]` findings may exist only as latest-head review threads, without CodeRabbit-style issue comments or folded review-body sections. - Treat GitHub Actions comments with `Success with warnings` as actionable review input when they include concrete linter diagnostics such as `MegaLinter` detailed issues; do not skip them just because the parent check is green. - Do not assume all CodeRabbit findings live in issue comments. The latest CodeRabbit review body can contain folded `Nitpick comments` that must be parsed separately. +- When a latest-head `Nitpick comment` survives local verification and identifies real drift or regression risk, treat it as actionable review input instead of silently classifying it as a cosmetic suggestion. - If the raw JSON is too large to inspect safely in the terminal, rerun with `--json-output ` and query the saved file with `jq` or rerun with `--section` / `--path` filters. ## Example Triggers diff --git a/GFramework.Core.Tests/Architectures/TestArchitectureContext.cs b/GFramework.Core.Tests/Architectures/TestArchitectureContext.cs index a1d85189..e7e67e7e 100644 --- a/GFramework.Core.Tests/Architectures/TestArchitectureContext.cs +++ b/GFramework.Core.Tests/Architectures/TestArchitectureContext.cs @@ -1,446 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using GFramework.Core.Abstractions.Architectures; -using GFramework.Core.Abstractions.Command; -using GFramework.Core.Abstractions.Environment; -using GFramework.Core.Abstractions.Events; -using GFramework.Core.Abstractions.Ioc; -using GFramework.Core.Abstractions.Model; -using GFramework.Core.Abstractions.Query; -using GFramework.Core.Abstractions.Systems; -using GFramework.Core.Abstractions.Utility; -using GFramework.Core.Command; -using GFramework.Core.Environment; -using GFramework.Core.Events; -using GFramework.Core.Ioc; -using GFramework.Core.Query; -using GFramework.Cqrs.Abstractions.Cqrs; -using ICommand = GFramework.Core.Abstractions.Command.ICommand; - namespace GFramework.Core.Tests.Architectures; /// /// 为 提供最小可用的架构上下文测试桩。 /// /// -/// 该类型只实现当前测试切片会触达的基础行为,其余 CQRS 入口显式抛出 , -/// 避免测试误把未覆盖能力当成可用实现。 +/// 共享的容器解析、事件总线协作与 legacy CQRS 失败契约由 提供, +/// 当前类型仅作为默认测试上下文命名入口,供现有测试与派生替身继续复用。 /// -public class TestArchitectureContext : IArchitectureContext +public class TestArchitectureContext : TestArchitectureContextBase { - private readonly MicrosoftDiContainer _container = new(); - private readonly EventBus _eventBus = new(); - - /// - /// 获取用于解析测试服务的依赖注入容器。 - /// - public IIocContainer Container => _container; - - /// - /// 获取测试事件总线实例。 - /// - /// - /// 返回同一个缓存事件总线,以便 与 - /// 在同一份订阅状态上协作。 - /// - public IEventBus EventBus => _eventBus; - - /// - /// 获取测试命令执行器实例。 - /// - public ICommandExecutor CommandExecutor => new CommandExecutor(); - - /// - /// 获取测试查询执行器实例。 - /// - public IQueryExecutor QueryExecutor => new QueryExecutor(); - - /// - /// 获取默认测试环境对象。 - /// - public IEnvironment Environment => new DefaultEnvironment(); - - /// - /// 获取指定类型的服务实例。 - /// - /// 服务类型。 - /// 已注册的服务实例。 - /// 未注册服务时抛出。 - public TService GetService() where TService : class - { - return _container.GetRequired(); - } - - /// - /// 获取指定类型的所有服务实例。 - /// - /// 服务类型。 - /// 服务实例列表。 - public IReadOnlyList GetServices() where TService : class - { - return _container.GetAll(); - } - - /// - /// 获取指定类型的模型实例。 - /// - /// 模型类型。 - /// 已注册的模型实例。 - /// 未注册模型时抛出。 - public TModel GetModel() where TModel : class, IModel - { - return _container.GetRequired(); - } - - /// - /// 获取指定类型的所有模型实例。 - /// - /// 模型类型。 - /// 模型实例列表。 - public IReadOnlyList GetModels() where TModel : class, IModel - { - return _container.GetAll(); - } - - /// - /// 获取指定类型的系统实例。 - /// - /// 系统类型。 - /// 已注册的系统实例。 - /// 未注册系统时抛出。 - public TSystem GetSystem() where TSystem : class, ISystem - { - return _container.GetRequired(); - } - - /// - /// 获取指定类型的所有系统实例。 - /// - /// 系统类型。 - /// 系统实例列表。 - public IReadOnlyList GetSystems() where TSystem : class, ISystem - { - return _container.GetAll(); - } - - /// - /// 获取指定类型的工具实例。 - /// - /// 工具类型。 - /// 已注册的工具实例。 - /// 未注册工具时抛出。 - public virtual TUtility GetUtility() where TUtility : class, IUtility - { - return _container.GetRequired(); - } - - /// - /// 获取指定类型的所有工具实例。 - /// - /// 工具类型。 - /// 工具实例列表。 - public IReadOnlyList GetUtilities() where TUtility : class, IUtility - { - return _container.GetAll(); - } - - /// - /// 获取指定类型的所有服务实例,并按优先级排序。 - /// - /// 服务类型。 - /// 按优先级排序后的服务实例列表。 - public IReadOnlyList GetServicesByPriority() where TService : class - { - return _container.GetAllByPriority(); - } - - /// - /// 获取指定类型的所有系统实例,并按优先级排序。 - /// - /// 系统类型。 - /// 按优先级排序后的系统实例列表。 - public IReadOnlyList GetSystemsByPriority() where TSystem : class, ISystem - { - return _container.GetAllByPriority(); - } - - /// - /// 获取指定类型的所有模型实例,并按优先级排序。 - /// - /// 模型类型。 - /// 按优先级排序后的模型实例列表。 - public IReadOnlyList GetModelsByPriority() where TModel : class, IModel - { - return _container.GetAllByPriority(); - } - - /// - /// 获取指定类型的所有工具实例,并按优先级排序。 - /// - /// 工具类型。 - /// 按优先级排序后的工具实例列表。 - public IReadOnlyList GetUtilitiesByPriority() where TUtility : class, IUtility - { - return _container.GetAllByPriority(); - } - - /// - /// 发送无参数事件。 - /// - /// 事件类型。 - public void SendEvent() where TEvent : new() - { - _eventBus.Send(); - } - - /// - /// 发送带参数事件。 - /// - /// 事件类型。 - /// 事件实例。 - public void SendEvent(TEvent e) where TEvent : class - { - ArgumentNullException.ThrowIfNull(e); - _eventBus.Send(e); - } - - /// - /// 注册事件处理器。 - /// - /// 事件类型。 - /// 事件处理委托。 - /// 用于测试的事件注销句柄。 - public IUnRegister RegisterEvent(Action handler) - { - ArgumentNullException.ThrowIfNull(handler); - return _eventBus.Register(handler); - } - - /// - /// 取消注册事件处理器。 - /// - /// 事件类型。 - /// 事件处理委托。 - public void UnRegisterEvent(Action onEvent) - { - ArgumentNullException.ThrowIfNull(onEvent); - _eventBus.UnRegister(onEvent); - } - - /// - /// 测试桩:异步发送统一 CQRS 请求。 - /// - /// 响应类型。 - /// 要发送的请求。 - /// 取消令牌。 - /// 请求响应任务。 - /// 该测试桩不支持此成员。 - public ValueTask SendRequestAsync( - IRequest request, - CancellationToken cancellationToken = default) - { - throw new NotSupportedException(); - } - - /// - /// 测试桩:同步发送统一 CQRS 请求。 - /// - /// 响应类型。 - /// 要发送的请求。 - /// 请求响应。 - /// 该测试桩不支持此成员。 - public TResponse SendRequest(IRequest request) - { - throw new NotSupportedException(); - } - - /// - /// 测试桩:异步发送 CQRS 命令并返回响应。 - /// - /// 命令响应类型。 - /// 要发送的命令。 - /// 取消令牌。 - /// 命令响应任务。 - /// 该测试桩不支持此成员。 - public ValueTask SendCommandAsync( - GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand command, - CancellationToken cancellationToken = default) - { - throw new NotSupportedException(); - } - - /// - /// 测试桩:同步发送 CQRS 命令并返回响应。 - /// - /// 命令响应类型。 - /// 要发送的命令。 - /// 命令响应。 - /// 该测试桩不支持此成员。 - public TResponse SendCommand(GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand command) - { - throw new NotSupportedException(); - } - - /// - /// 测试桩:异步发送 CQRS 查询并返回结果。 - /// - /// 查询结果类型。 - /// 要发送的查询。 - /// 取消令牌。 - /// 查询结果任务。 - /// 该测试桩不支持此成员。 - public ValueTask SendQueryAsync( - GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery query, - CancellationToken cancellationToken = default) - { - throw new NotSupportedException(); - } - - /// - /// 测试桩:同步发送 CQRS 查询并返回结果。 - /// - /// 查询结果类型。 - /// 要发送的查询。 - /// 查询结果。 - /// 该测试桩不支持此成员。 - public TResponse SendQuery(GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery query) - { - throw new NotSupportedException(); - } - - /// - /// 测试桩:异步发布 CQRS 通知。 - /// - /// 通知类型。 - /// 要发布的通知。 - /// 取消令牌。 - /// 通知发布任务。 - /// 该测试桩不支持此成员。 - public ValueTask PublishAsync( - TNotification notification, - CancellationToken cancellationToken = default) where TNotification : INotification - { - throw new NotSupportedException(); - } - - /// - /// 测试桩:创建 CQRS 流式请求响应序列。 - /// - /// 流式响应元素类型。 - /// 流式请求。 - /// 取消令牌。 - /// 异步响应流。 - /// 该测试桩不支持此成员。 - public IAsyncEnumerable CreateStream( - IStreamRequest request, - CancellationToken cancellationToken = default) - { - throw new NotSupportedException(); - } - - /// - /// 测试桩:异步发送无返回值 CQRS 命令。 - /// - /// 命令类型。 - /// 要发送的命令。 - /// 取消令牌。 - /// 命令发送任务。 - /// 该测试桩不支持此成员。 - public ValueTask SendAsync(TCommand command, CancellationToken cancellationToken = default) - where TCommand : IRequest - { - throw new NotSupportedException(); - } - - /// - /// 测试桩:异步发送带返回值的 CQRS 请求。 - /// - /// 响应类型。 - /// 要发送的请求。 - /// 取消令牌。 - /// 请求响应任务。 - /// 该测试桩不支持此成员。 - public ValueTask SendAsync( - IRequest command, - CancellationToken cancellationToken = default) - { - throw new NotSupportedException(); - } - - /// - /// 发送旧版命令。 - /// - /// 命令对象。 - /// 该测试桩不支持旧版命令执行入口。 - public void SendCommand(ICommand command) - { - throw new NotSupportedException(); - } - - /// - /// 发送旧版带返回值命令。 - /// - /// 返回值类型。 - /// 命令对象。 - /// 此方法始终抛出异常,不返回结果。 - /// 该测试桩不支持旧版命令执行入口。 - public TResult SendCommand(ICommand command) - { - throw new NotSupportedException(); - } - - /// - /// 异步发送旧版命令。 - /// - /// 命令对象。 - /// 已失败的任务。 - public Task SendCommandAsync(IAsyncCommand command) - { - return Task.FromException(new NotSupportedException()); - } - - /// - /// 异步发送旧版带返回值命令。 - /// - /// 返回值类型。 - /// 命令对象。 - /// 已失败的任务。 - public Task SendCommandAsync(IAsyncCommand command) - { - return Task.FromException(new NotSupportedException()); - } - - /// - /// 发送旧版查询请求。 - /// - /// 查询结果类型。 - /// 查询对象。 - /// 此方法始终抛出异常,不返回结果。 - /// 该测试桩不支持旧版查询执行入口。 - public TResult SendQuery(IQuery query) - { - throw new NotSupportedException(); - } - - /// - /// 异步发送旧版查询请求。 - /// - /// 查询结果类型。 - /// 异步查询对象。 - /// 已失败的任务。 - public Task SendQueryAsync(IAsyncQuery query) - { - return Task.FromException(new NotSupportedException()); - } - - /// - /// 获取当前环境对象。 - /// - /// 默认测试环境对象。 - public IEnvironment GetEnvironment() - { - return Environment; - } } diff --git a/GFramework.Core.Tests/Architectures/TestArchitectureContextBase.cs b/GFramework.Core.Tests/Architectures/TestArchitectureContextBase.cs new file mode 100644 index 00000000..a0fe74cf --- /dev/null +++ b/GFramework.Core.Tests/Architectures/TestArchitectureContextBase.cs @@ -0,0 +1,451 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using GFramework.Core.Abstractions.Architectures; +using GFramework.Core.Abstractions.Command; +using GFramework.Core.Abstractions.Environment; +using GFramework.Core.Abstractions.Events; +using GFramework.Core.Abstractions.Ioc; +using GFramework.Core.Abstractions.Model; +using GFramework.Core.Abstractions.Query; +using GFramework.Core.Abstractions.Systems; +using GFramework.Core.Abstractions.Utility; +using GFramework.Core.Command; +using GFramework.Core.Environment; +using GFramework.Core.Events; +using GFramework.Core.Ioc; +using GFramework.Core.Query; +using GFramework.Cqrs.Abstractions.Cqrs; +using ICommand = GFramework.Core.Abstractions.Command.ICommand; + +namespace GFramework.Core.Tests.Architectures; + +/// +/// 为架构相关测试替身提供共享的 基础实现。 +/// +/// +/// 该基类统一维护容器解析、共享 语义,以及 legacy / CQRS 入口的显式失败契约, +/// 以避免多个测试上下文因为并行复制实现而在后续演进中发生语义漂移。 +/// +public abstract class TestArchitectureContextBase : IArchitectureContext +{ + private readonly MicrosoftDiContainer _container = new(); + private readonly DefaultEnvironment _environment = new(); + private readonly EventBus _eventBus = new(); + + /// + /// 获取用于解析测试服务的依赖注入容器。 + /// + public IIocContainer Container => _container; + + /// + /// 获取测试事件总线实例。 + /// + /// + /// 返回同一个缓存事件总线,以便 与 + /// 在同一份订阅状态上协作。 + /// + public IEventBus EventBus => _eventBus; + + /// + /// 获取测试命令执行器实例。 + /// + public ICommandExecutor CommandExecutor => new CommandExecutor(); + + /// + /// 获取测试查询执行器实例。 + /// + public IQueryExecutor QueryExecutor => new QueryExecutor(); + + /// + /// 获取默认测试环境对象。 + /// + public IEnvironment Environment => _environment; + + /// + /// 获取指定类型的服务实例。 + /// + /// 服务类型。 + /// 已注册的服务实例。 + /// 未注册服务时抛出。 + public TService GetService() where TService : class + { + return _container.GetRequired(); + } + + /// + /// 获取指定类型的所有服务实例。 + /// + /// 服务类型。 + /// 服务实例列表。 + public IReadOnlyList GetServices() where TService : class + { + return _container.GetAll(); + } + + /// + /// 获取指定类型的模型实例。 + /// + /// 模型类型。 + /// 已注册的模型实例。 + /// 未注册模型时抛出。 + public TModel GetModel() where TModel : class, IModel + { + return _container.GetRequired(); + } + + /// + /// 获取指定类型的所有模型实例。 + /// + /// 模型类型。 + /// 模型实例列表。 + public IReadOnlyList GetModels() where TModel : class, IModel + { + return _container.GetAll(); + } + + /// + /// 获取指定类型的系统实例。 + /// + /// 系统类型。 + /// 已注册的系统实例。 + /// 未注册系统时抛出。 + public TSystem GetSystem() where TSystem : class, ISystem + { + return _container.GetRequired(); + } + + /// + /// 获取指定类型的所有系统实例。 + /// + /// 系统类型。 + /// 系统实例列表。 + public IReadOnlyList GetSystems() where TSystem : class, ISystem + { + return _container.GetAll(); + } + + /// + /// 获取指定类型的工具实例。 + /// + /// 工具类型。 + /// 已注册的工具实例。 + /// 未注册工具时抛出。 + public virtual TUtility GetUtility() where TUtility : class, IUtility + { + return _container.GetRequired(); + } + + /// + /// 获取指定类型的所有工具实例。 + /// + /// 工具类型。 + /// 工具实例列表。 + public IReadOnlyList GetUtilities() where TUtility : class, IUtility + { + return _container.GetAll(); + } + + /// + /// 获取指定类型的所有服务实例,并按优先级排序。 + /// + /// 服务类型。 + /// 按优先级排序后的服务实例列表。 + public IReadOnlyList GetServicesByPriority() where TService : class + { + return _container.GetAllByPriority(); + } + + /// + /// 获取指定类型的所有系统实例,并按优先级排序。 + /// + /// 系统类型。 + /// 按优先级排序后的系统实例列表。 + public IReadOnlyList GetSystemsByPriority() where TSystem : class, ISystem + { + return _container.GetAllByPriority(); + } + + /// + /// 获取指定类型的所有模型实例,并按优先级排序。 + /// + /// 模型类型。 + /// 按优先级排序后的模型实例列表。 + public IReadOnlyList GetModelsByPriority() where TModel : class, IModel + { + return _container.GetAllByPriority(); + } + + /// + /// 获取指定类型的所有工具实例,并按优先级排序。 + /// + /// 工具类型。 + /// 按优先级排序后的工具实例列表。 + public IReadOnlyList GetUtilitiesByPriority() where TUtility : class, IUtility + { + return _container.GetAllByPriority(); + } + + /// + /// 发送无参数事件。 + /// + /// 事件类型。 + public void SendEvent() where TEvent : new() + { + _eventBus.Send(); + } + + /// + /// 发送带参数事件。 + /// + /// 事件类型。 + /// 事件实例。 + /// + public void SendEvent(TEvent e) where TEvent : class + { + ArgumentNullException.ThrowIfNull(e); + _eventBus.Send(e); + } + + /// + /// 注册事件处理器。 + /// + /// 事件类型。 + /// 事件处理委托。 + /// 用于测试的事件注销句柄。 + /// + public IUnRegister RegisterEvent(Action handler) + { + ArgumentNullException.ThrowIfNull(handler); + return _eventBus.Register(handler); + } + + /// + /// 取消注册事件处理器。 + /// + /// 事件类型。 + /// 事件处理委托。 + /// + public void UnRegisterEvent(Action onEvent) + { + ArgumentNullException.ThrowIfNull(onEvent); + _eventBus.UnRegister(onEvent); + } + + /// + /// 测试桩:异步发送统一 CQRS 请求。 + /// + /// 响应类型。 + /// 要发送的请求。 + /// 取消令牌。 + /// 请求响应任务。 + /// 该测试桩不支持此成员。 + public ValueTask SendRequestAsync( + IRequest request, + CancellationToken cancellationToken = default) + { + throw new NotSupportedException(); + } + + /// + /// 测试桩:同步发送统一 CQRS 请求。 + /// + /// 响应类型。 + /// 要发送的请求。 + /// 请求响应。 + /// 该测试桩不支持此成员。 + public TResponse SendRequest(IRequest request) + { + throw new NotSupportedException(); + } + + /// + /// 测试桩:异步发送 CQRS 命令并返回响应。 + /// + /// 命令响应类型。 + /// 要发送的命令。 + /// 取消令牌。 + /// 命令响应任务。 + /// 该测试桩不支持此成员。 + public ValueTask SendCommandAsync( + GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand command, + CancellationToken cancellationToken = default) + { + throw new NotSupportedException(); + } + + /// + /// 测试桩:同步发送 CQRS 命令并返回响应。 + /// + /// 命令响应类型。 + /// 要发送的命令。 + /// 命令响应。 + /// 该测试桩不支持此成员。 + public TResponse SendCommand(GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand command) + { + throw new NotSupportedException(); + } + + /// + /// 测试桩:异步发送 CQRS 查询并返回结果。 + /// + /// 查询结果类型。 + /// 要发送的查询。 + /// 取消令牌。 + /// 查询结果任务。 + /// 该测试桩不支持此成员。 + public ValueTask SendQueryAsync( + GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery query, + CancellationToken cancellationToken = default) + { + throw new NotSupportedException(); + } + + /// + /// 测试桩:同步发送 CQRS 查询并返回结果。 + /// + /// 查询结果类型。 + /// 要发送的查询。 + /// 查询结果。 + /// 该测试桩不支持此成员。 + public TResponse SendQuery(GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery query) + { + throw new NotSupportedException(); + } + + /// + /// 测试桩:异步发布 CQRS 通知。 + /// + /// 通知类型。 + /// 要发布的通知。 + /// 取消令牌。 + /// 通知发布任务。 + /// 该测试桩不支持此成员。 + public ValueTask PublishAsync( + TNotification notification, + CancellationToken cancellationToken = default) + where TNotification : INotification + { + throw new NotSupportedException(); + } + + /// + /// 测试桩:创建 CQRS 流式请求响应序列。 + /// + /// 流式响应元素类型。 + /// 流式请求。 + /// 取消令牌。 + /// 异步响应流。 + /// 该测试桩不支持此成员。 + public IAsyncEnumerable CreateStream( + IStreamRequest request, + CancellationToken cancellationToken = default) + { + throw new NotSupportedException(); + } + + /// + /// 测试桩:异步发送无返回值 CQRS 命令。 + /// + /// 命令类型。 + /// 要发送的命令。 + /// 取消令牌。 + /// 命令发送任务。 + /// 该测试桩不支持此成员。 + public ValueTask SendAsync(TCommand command, CancellationToken cancellationToken = default) + where TCommand : IRequest + { + throw new NotSupportedException(); + } + + /// + /// 测试桩:异步发送带返回值的 CQRS 请求。 + /// + /// 响应类型。 + /// 要发送的请求。 + /// 取消令牌。 + /// 请求响应任务。 + /// 该测试桩不支持此成员。 + public ValueTask SendAsync( + IRequest command, + CancellationToken cancellationToken = default) + { + throw new NotSupportedException(); + } + + /// + /// 发送旧版命令。 + /// + /// 命令对象。 + /// 该测试桩不支持旧版命令执行入口。 + public void SendCommand(ICommand command) + { + throw new NotSupportedException(); + } + + /// + /// 发送旧版带返回值命令。 + /// + /// 返回值类型。 + /// 命令对象。 + /// 此方法始终抛出异常,不返回结果。 + /// 该测试桩不支持旧版命令执行入口。 + public TResult SendCommand(ICommand command) + { + throw new NotSupportedException(); + } + + /// + /// 异步发送旧版命令。 + /// + /// 命令对象。 + /// 已失败的任务。 + public Task SendCommandAsync(IAsyncCommand command) + { + return Task.FromException(new NotSupportedException()); + } + + /// + /// 异步发送旧版带返回值命令。 + /// + /// 返回值类型。 + /// 命令对象。 + /// 已失败的任务。 + public Task SendCommandAsync(IAsyncCommand command) + { + return Task.FromException(new NotSupportedException()); + } + + /// + /// 发送旧版查询请求。 + /// + /// 查询结果类型。 + /// 查询对象。 + /// 此方法始终抛出异常,不返回结果。 + /// 该测试桩不支持旧版查询执行入口。 + public TResult SendQuery(IQuery query) + { + throw new NotSupportedException(); + } + + /// + /// 异步发送旧版查询请求。 + /// + /// 查询结果类型。 + /// 异步查询对象。 + /// 已失败的任务。 + public Task SendQueryAsync(IAsyncQuery query) + { + return Task.FromException(new NotSupportedException()); + } + + /// + /// 获取当前环境对象。 + /// + /// 默认测试环境对象。 + public IEnvironment GetEnvironment() + { + return Environment; + } +} diff --git a/GFramework.Core.Tests/Architectures/TestArchitectureContextV3.cs b/GFramework.Core.Tests/Architectures/TestArchitectureContextV3.cs index 313864cd..b67a6d98 100644 --- a/GFramework.Core.Tests/Architectures/TestArchitectureContextV3.cs +++ b/GFramework.Core.Tests/Architectures/TestArchitectureContextV3.cs @@ -1,426 +1,16 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using GFramework.Core.Abstractions.Architectures; -using GFramework.Core.Abstractions.Command; -using GFramework.Core.Abstractions.Environment; -using GFramework.Core.Abstractions.Events; -using GFramework.Core.Abstractions.Model; -using GFramework.Core.Abstractions.Query; -using GFramework.Core.Abstractions.Systems; -using GFramework.Core.Abstractions.Utility; -using GFramework.Core.Environment; -using GFramework.Core.Events; -using GFramework.Core.Ioc; -using GFramework.Cqrs; -using GFramework.Cqrs.Abstractions.Cqrs; -using ICommand = GFramework.Core.Abstractions.Command.ICommand; - namespace GFramework.Core.Tests.Architectures; /// /// 为 提供最小实现的架构上下文测试桩。 /// /// -/// 该类型仅用于验证 的上下文传递行为,因此仅保留当前测试切片需要的容器、 -/// 环境与接口实现。所有不在本测试范围内的 CQRS 调用均明确抛出 , -/// 以避免误把测试桩当作真实运行时上下文使用。 +/// 共享的容器解析、事件总线协作与 legacy CQRS 失败契约由 提供, +/// 当前类型只补充 需要的上下文实例标识。 /// -public class TestArchitectureContextV3 : IArchitectureContext +public class TestArchitectureContextV3 : TestArchitectureContextBase { - private readonly MicrosoftDiContainer _container = new(); - private readonly DefaultEnvironment _environment = new(); - private readonly EventBus _eventBus = new(); - /// /// 获取或初始化用于区分测试上下文实例的标识。 /// public int Id { get; init; } - - /// - /// 获取指定类型的服务实例。 - /// - /// 服务类型。 - /// 已注册的服务实例。 - /// 未注册或存在多个同类型实例时抛出。 - public TService GetService() where TService : class - { - return _container.GetRequired(); - } - - /// - /// 获取指定类型的所有服务实例。 - /// - /// 服务类型。 - /// 所有已注册的服务实例。 - public IReadOnlyList GetServices() where TService : class - { - return _container.GetAll(); - } - - /// - /// 获取指定类型的模型实例。 - /// - /// 模型类型。 - /// 已注册的模型实例。 - /// 未注册或存在多个同类型实例时抛出。 - public TModel GetModel() where TModel : class, IModel - { - return _container.GetRequired(); - } - - /// - /// 获取指定类型的所有模型实例。 - /// - /// 模型类型。 - /// 所有已注册的模型实例。 - public IReadOnlyList GetModels() where TModel : class, IModel - { - return _container.GetAll(); - } - - /// - /// 获取指定类型的系统实例。 - /// - /// 系统类型。 - /// 已注册的系统实例。 - /// 未注册或存在多个同类型实例时抛出。 - public TSystem GetSystem() where TSystem : class, ISystem - { - return _container.GetRequired(); - } - - /// - /// 获取指定类型的所有系统实例。 - /// - /// 系统类型。 - /// 所有已注册的系统实例。 - public IReadOnlyList GetSystems() where TSystem : class, ISystem - { - return _container.GetAll(); - } - - /// - /// 获取指定类型的工具实例。 - /// - /// 工具类型。 - /// 已注册的工具实例。 - /// 未注册或存在多个同类型实例时抛出。 - public TUtility GetUtility() where TUtility : class, IUtility - { - return _container.GetRequired(); - } - - /// - /// 获取指定类型的所有工具实例。 - /// - /// 工具类型。 - /// 所有已注册的工具实例。 - public IReadOnlyList GetUtilities() where TUtility : class, IUtility - { - return _container.GetAll(); - } - - /// - /// 获取指定类型的所有服务实例,并按优先级排序。 - /// - /// 服务类型。 - /// 按优先级排序后的服务实例。 - public IReadOnlyList GetServicesByPriority() where TService : class - { - return _container.GetAllByPriority(); - } - - /// - /// 获取指定类型的所有系统实例,并按优先级排序。 - /// - /// 系统类型。 - /// 按优先级排序后的系统实例。 - public IReadOnlyList GetSystemsByPriority() where TSystem : class, ISystem - { - return _container.GetAllByPriority(); - } - - /// - /// 获取指定类型的所有模型实例,并按优先级排序。 - /// - /// 模型类型。 - /// 按优先级排序后的模型实例。 - public IReadOnlyList GetModelsByPriority() where TModel : class, IModel - { - return _container.GetAllByPriority(); - } - - /// - /// 获取指定类型的所有工具实例,并按优先级排序。 - /// - /// 工具类型。 - /// 按优先级排序后的工具实例。 - public IReadOnlyList GetUtilitiesByPriority() where TUtility : class, IUtility - { - return _container.GetAllByPriority(); - } - - /// - /// 发送无参数事件。 - /// - /// 事件类型。 - public void SendEvent() where TEvent : new() - { - _eventBus.Send(); - } - - /// - /// 发送带参数事件。 - /// - /// 事件类型。 - /// 事件实例。 - /// - public void SendEvent(TEvent e) where TEvent : class - { - ArgumentNullException.ThrowIfNull(e); - _eventBus.Send(e); - } - - /// - /// 注册事件处理器。 - /// - /// 事件类型。 - /// 事件处理回调。 - /// 用于注销回调的句柄。 - /// - public IUnRegister RegisterEvent(Action handler) - { - ArgumentNullException.ThrowIfNull(handler); - return _eventBus.Register(handler); - } - - /// - /// 取消事件处理器注册。 - /// - /// 事件类型。 - /// 要取消的事件回调。 - /// - public void UnRegisterEvent(Action onEvent) - { - ArgumentNullException.ThrowIfNull(onEvent); - _eventBus.UnRegister(onEvent); - } - - /// - /// 异步发送新版 CQRS 请求。 - /// - /// 响应类型。 - /// 要发送的请求。 - /// 取消令牌。 - /// 请求响应任务。 - /// 该测试桩不支持此成员。 - public ValueTask SendRequestAsync( - IRequest request, - CancellationToken cancellationToken = default) - { - throw new NotSupportedException(); - } - - /// - /// 同步发送新版 CQRS 请求。 - /// - /// 响应类型。 - /// 要发送的请求。 - /// 请求响应。 - /// 该测试桩不支持此成员。 - public TResponse SendRequest(IRequest request) - { - throw new NotSupportedException(); - } - - /// - /// 异步发送新版 CQRS 命令并返回响应。 - /// - /// 命令响应类型。 - /// 要发送的命令。 - /// 取消令牌。 - /// 命令响应任务。 - /// 该测试桩不支持此成员。 - public ValueTask SendCommandAsync( - GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand command, - CancellationToken cancellationToken = default) - { - throw new NotSupportedException(); - } - - /// - /// 同步发送新版 CQRS 命令并返回响应。 - /// - /// 命令响应类型。 - /// 要发送的命令。 - /// 命令响应。 - /// 该测试桩不支持此成员。 - public TResponse SendCommand(GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand command) - { - throw new NotSupportedException(); - } - - /// - /// 异步发送新版 CQRS 查询并返回结果。 - /// - /// 查询结果类型。 - /// 要发送的查询。 - /// 取消令牌。 - /// 查询结果任务。 - /// 该测试桩不支持此成员。 - public ValueTask SendQueryAsync( - GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery query, - CancellationToken cancellationToken = default) - { - throw new NotSupportedException(); - } - - /// - /// 同步发送新版 CQRS 查询并返回结果。 - /// - /// 查询结果类型。 - /// 要发送的查询。 - /// 查询结果。 - /// 该测试桩不支持此成员。 - public TResponse SendQuery(GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery query) - { - throw new NotSupportedException(); - } - - /// - /// 发布通知消息。 - /// - /// 通知类型。 - /// 通知实例。 - /// 取消令牌。 - /// 通知发布任务。 - /// 该测试桩不支持此成员。 - public ValueTask PublishAsync( - TNotification notification, - CancellationToken cancellationToken = default) - where TNotification : INotification - { - throw new NotSupportedException(); - } - - /// - /// 创建流式请求结果。 - /// - /// 流元素类型。 - /// 流式请求。 - /// 取消令牌。 - /// 流式响应序列。 - /// 该测试桩不支持此成员。 - public IAsyncEnumerable CreateStream( - IStreamRequest request, - CancellationToken cancellationToken = default) - { - throw new NotSupportedException(); - } - - /// - /// 异步发送无返回值请求命令。 - /// - /// 命令类型。 - /// 要发送的命令。 - /// 取消令牌。 - /// 命令发送任务。 - /// 该测试桩不支持此成员。 - public ValueTask SendAsync(TCommand command, CancellationToken cancellationToken = default) - where TCommand : IRequest - { - throw new NotSupportedException(); - } - - /// - /// 异步发送带返回值请求。 - /// - /// 响应类型。 - /// 要发送的请求。 - /// 取消令牌。 - /// 请求响应任务。 - /// 该测试桩不支持此成员。 - public ValueTask SendAsync( - IRequest command, - CancellationToken cancellationToken = default) - { - throw new NotSupportedException(); - } - - /// - /// 发送旧版无返回值命令。 - /// - /// 要发送的命令。 - /// 该测试桩不支持旧版命令执行入口。 - public void SendCommand(ICommand command) - { - throw new NotSupportedException(); - } - - /// - /// 发送旧版带返回值命令。 - /// - /// 命令响应类型。 - /// 要发送的命令。 - /// 此方法始终抛出异常,不返回结果。 - /// 该测试桩不支持旧版命令执行入口。 - public TResult SendCommand(GFramework.Core.Abstractions.Command.ICommand command) - { - throw new NotSupportedException(); - } - - /// - /// 异步发送旧版无返回值命令。 - /// - /// 要发送的命令。 - /// 已失败的任务。 - public Task SendCommandAsync(IAsyncCommand command) - { - return Task.FromException(new NotSupportedException()); - } - - /// - /// 异步发送旧版带返回值命令。 - /// - /// 命令响应类型。 - /// 要发送的命令。 - /// 已失败的任务。 - public Task SendCommandAsync(IAsyncCommand command) - { - return Task.FromException(new NotSupportedException()); - } - - /// - /// 发送旧版查询请求。 - /// - /// 查询结果类型。 - /// 要发送的查询。 - /// 此方法始终抛出异常,不返回结果。 - /// 该测试桩不支持旧版查询执行入口。 - public TResult SendQuery(GFramework.Core.Abstractions.Query.IQuery query) - { - throw new NotSupportedException(); - } - - /// - /// 异步发送旧版查询请求。 - /// - /// 查询结果类型。 - /// 要发送的查询。 - /// 已失败的任务。 - public Task SendQueryAsync(IAsyncQuery query) - { - return Task.FromException(new NotSupportedException()); - } - - /// - /// 获取当前测试上下文绑定的环境实例。 - /// - /// 默认测试环境实例。 - public IEnvironment GetEnvironment() - { - return _environment; - } } diff --git a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md index bc0e5d04..be8ac1bb 100644 --- a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md +++ b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md @@ -6,13 +6,12 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-090` -- 当前阶段:`Phase 90` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-091` +- 当前阶段:`Phase 91` - 当前焦点: - - `2026-04-28` 再次执行 `$gframework-pr-review`,确认 `PR #300` 最新 head 仍显示 `6` 条 CodeRabbit open threads,但本地复核后只有事件 API 回归覆盖仍然成立 - - 已在 `TestArchitectureContextBehaviorTests.cs` 补齐 `UnRegisterEvent` 行为与 `SendEvent` / `RegisterEvent` / `UnRegisterEvent` 的空参数契约测试 - - 已整理 `TestResourceLoader.cs` 的命名空间缩进,收口本轮顺手处理的局部格式噪音 - - `dotnet format --verify-no-changes` 当前仍会暴露 `GFramework.Core.Tests` 项目里跨多个无关文件的既有 `FINALNEWLINE`、`CHARSET`、`WHITESPACE` 基线,本轮不扩展到整项目格式波次 + - `2026-04-28` 继续收口 `PR #300` 的剩余 nitpick:已把 `TestArchitectureContext` / `TestArchitectureContextV3` 的重复 `IArchitectureContext` 测试实现抽到共享基类 `TestArchitectureContextBase` + - 已将 “本地验证后仍然成立的 nitpick 不得默认降级为可选项” 写入 `.agents/skills/gframework-pr-review/SKILL.md` + - `dotnet format --verify-no-changes` 的 `GFramework.Core.Tests` 既有 `FINALNEWLINE`、`CHARSET`、`WHITESPACE` 基线仍保持独立,不与本轮共享基类重构混提 ## 当前活跃事实 @@ -20,12 +19,10 @@ - 当前直接验证结果: - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - 最新结果:成功;`0 Warning(s)`、`0 Error(s)` - - `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~TestArchitectureContextBehaviorTests"` - - 最新结果:成功;`9` 通过、`0` 失败 - - `dotnet format GFramework.Core.Tests/GFramework.Core.Tests.csproj --verify-no-changes --no-restore` - - 最新结果:失败;暴露 `GFramework.Core.Tests` 项目中跨多个未触碰文件的既有 `FINALNEWLINE`、`CHARSET`、`WHITESPACE` 诊断,本轮新增写集未引入 `git diff --check` 异常 + - `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~ArchitectureServicesTests|FullyQualifiedName~ContextAwareServiceExtensionsTests|FullyQualifiedName~TestArchitectureContextBehaviorTests|FullyQualifiedName~RegistryInitializationHookBaseTests|FullyQualifiedName~ArchitectureContextTests"` + - 最新结果:成功;`67` 通过、`0` 失败 - 当前批次摘要: - - 当前工作树包含 `4` 个已修改文件,分别位于 `GFramework.Core.Tests` 与 `ai-plan/public/analyzer-warning-reduction` + - 当前工作树包含 `6` 个已修改文件与 `1` 个新增文件,分别位于 `GFramework.Core.Tests`、`.agents/skills/gframework-pr-review/` 与 `ai-plan/public/analyzer-warning-reduction` - 本轮没有触碰 `Mediator/*`、`YamlConfigSchemaValidator*` 或 `GFramework.Core.Tests` 的整项目格式基线波次 ## 当前风险 @@ -60,6 +57,6 @@ ## 下一步建议 -1. 提交本轮 `PR #300` review follow-up 与 `ai-plan` 同步。 -2. 若需要继续收口 PR 线程,可单独评估是否接受 `TestArchitectureContext` / `TestArchitectureContextV3` 的共享 helper nitpick。 +1. 提交本轮 `PR #300` nitpick follow-up、技能规则更新与 `ai-plan` 同步。 +2. 推送后重新执行 `$gframework-pr-review`,确认该 nitpick thread 是否随最新 head 自动收口。 3. 若要清理 `dotnet format` 基线,另开 `GFramework.Core.Tests` 格式治理切片,不与当前 PR review 修复混提。 diff --git a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md index 3f293957..5d2477e9 100644 --- a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md +++ b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md @@ -1,23 +1,21 @@ # Analyzer Warning Reduction 追踪 -## 2026-04-28 — RP-090 +## 2026-04-28 — RP-091 -### 阶段:复核 `PR #300` 最新 review 真值并补齐事件 API 回归覆盖 +### 阶段:收口 `PR #300` 的共享测试基础设施 nitpick,并升级 PR-review triage 规则 - 触发背景: - - 用户再次执行 `$gframework-pr-review` - - `fetch_current_pr_review.py --json-output /tmp/gframework-current-pr-review.json` 返回 `PR #300`,latest head 仍显示 `6` 条 CodeRabbit open threads;本地复核后,`Task.CompletedTask` 强转、`RegisterLifecycleHook` 语义、`TestResourceLoader` 文档与 `PartialGeneratedNotificationHandlerRegistry` XML 契约都已在当前 head 上成立,唯一仍未锁住的是事件 API 回归覆盖 + - 用户追问 `TestArchitectureContext` / `TestArchitectureContextV3` 的共享基础设施 nitpick 是否已经处理完成 + - 同时要求把“本地验证后仍然成立的 nitpick 不能默认降级为可选项”写入 `AGENTS.md` 或 `$gframework-pr-review` - 主线程实施: - - 为 `TestArchitectureContext` 与 `TestArchitectureContextV3` 新增共享测试数据源,补齐 `SendEvent` / `RegisterEvent` / `UnRegisterEvent` 的空参数异常契约 - - 新增 `UnRegisterEvent_Should_Stop_Dispatch` 回归测试,防止后续把注销路径退化成 `no-op` - - 整理 `TestResourceLoader.cs` 的命名空间缩进,避免当前修改继续叠加局部格式噪音 + - 新增 `TestArchitectureContextBase`,把容器解析、共享 `EventBus` 行为,以及 legacy / CQRS 失败契约统一收敛到一处 + - 将 `TestArchitectureContext` 与 `TestArchitectureContextV3` 收窄为薄包装类型,只保留各自的命名入口与 `Id` 差异 + - 更新 `.agents/skills/gframework-pr-review/SKILL.md`,明确要求:latest-head `Nitpick comment` 一旦本地验证仍成立且指向真实漂移/回归风险,就必须作为 actionable review input 处理,而不是默认视作可选 - 验证里程碑: - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - 结果:成功;`0 Warning(s)`、`0 Error(s)` - - `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~TestArchitectureContextBehaviorTests"` - - 结果:成功;`9` 通过、`0` 失败 - - `dotnet format GFramework.Core.Tests/GFramework.Core.Tests.csproj --verify-no-changes --no-restore` - - 结果:失败;输出落在 `ObjectExtensionsTests.cs`、多处 `FINALNEWLINE` 与若干 `CHARSET` 基线文件,均不属于本轮写集 + - `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~ArchitectureServicesTests|FullyQualifiedName~ContextAwareServiceExtensionsTests|FullyQualifiedName~TestArchitectureContextBehaviorTests|FullyQualifiedName~RegistryInitializationHookBaseTests|FullyQualifiedName~ArchitectureContextTests"` + - 结果:成功;`67` 通过、`0` 失败 - `git diff --check` - 结果:成功;无新增 whitespace / conflict-marker 问题 @@ -30,8 +28,8 @@ ## 下一步 -1. 提交本轮 `PR #300` follow-up 与 `ai-plan` 同步。 -2. 若继续收口 PR 线程,单独评估是否接受 `TestArchitectureContext` / `TestArchitectureContextV3` 的共享 helper nitpick。 +1. 提交本轮共享基类重构、技能规则更新与 `ai-plan` 同步。 +2. 推送后重新执行 `$gframework-pr-review`,确认剩余 PR 线程是否已经下降。 ## 历史归档指针