From 3ced56be8b1b76ad7865cd0d2f291e9c08215a7f Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Sun, 3 May 2026 13:24:24 +0800 Subject: [PATCH] =?UTF-8?q?chore(godot):=20=E5=A4=84=E7=90=86=20Godot=20?= =?UTF-8?q?=E6=97=A5=E5=BF=97=20PR=20=E5=8F=8D=E9=A6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复 GodotLogAppender 测试对结构化属性顺序的依赖 - 移除 GodotLogger 未使用的私有格式化包装方法 - 更新 ai-plan 默认索引和 trace 恢复记录,避免归档主题与重复标题干扰 boot --- .../Logging/GodotLogAppenderTests.cs | 7 +++- .../Logging/GodotLoggerSettingsLoaderTests.cs | 7 ++-- GFramework.Godot/Logging/GodotLogger.cs | 5 --- ai-plan/public/README.md | 15 ------- .../todos/godot-logging-core-sink-tracking.md | 21 +++++++--- .../traces/godot-logging-core-sink-trace.md | 41 +++++++++++++++++-- 6 files changed, 62 insertions(+), 34 deletions(-) diff --git a/GFramework.Godot.Tests/Logging/GodotLogAppenderTests.cs b/GFramework.Godot.Tests/Logging/GodotLogAppenderTests.cs index d16e73b9..dd98e173 100644 --- a/GFramework.Godot.Tests/Logging/GodotLogAppenderTests.cs +++ b/GFramework.Godot.Tests/Logging/GodotLogAppenderTests.cs @@ -38,7 +38,12 @@ public sealed class GodotLogAppenderTests var result = appender.Render(entry); - Assert.That(result, Is.EqualTo("20260503|INF|Game.Services.Inventory|Ready | Scene=Boot, Score=12.5")); + Assert.Multiple(() => + { + Assert.That(result, Does.StartWith("20260503|INF|Game.Services.Inventory|Ready | ")); + Assert.That(result, Does.Contain("Scene=Boot")); + Assert.That(result, Does.Contain("Score=12.5")); + }); } /// diff --git a/GFramework.Godot.Tests/Logging/GodotLoggerSettingsLoaderTests.cs b/GFramework.Godot.Tests/Logging/GodotLoggerSettingsLoaderTests.cs index 749ac715..74db1f6b 100644 --- a/GFramework.Godot.Tests/Logging/GodotLoggerSettingsLoaderTests.cs +++ b/GFramework.Godot.Tests/Logging/GodotLoggerSettingsLoaderTests.cs @@ -192,8 +192,8 @@ public sealed class GodotLoggerSettingsLoaderTests [Test] public void StructuredProperties_Should_Skip_Blank_Keys_And_Trim_Valid_Keys() { - var formatProperties = typeof(GodotLogger).GetMethod( - "FormatProperties", + var toPropertiesDictionary = typeof(GodotLogger).GetMethod( + "ToPropertiesDictionary", BindingFlags.NonPublic | BindingFlags.Static); var properties = new (string Key, object? Value)[] { @@ -202,7 +202,8 @@ public sealed class GodotLoggerSettingsLoaderTests (" Player ", 42) }; - var result = formatProperties?.Invoke(null, [properties]); + var dictionary = toPropertiesDictionary?.Invoke(null, [properties]) as IReadOnlyDictionary; + var result = GodotLogAppender.FormatProperties(dictionary); Assert.That(result, Is.EqualTo(" | Player=42")); } diff --git a/GFramework.Godot/Logging/GodotLogger.cs b/GFramework.Godot/Logging/GodotLogger.cs index 763d480e..87adeebe 100644 --- a/GFramework.Godot/Logging/GodotLogger.cs +++ b/GFramework.Godot/Logging/GodotLogger.cs @@ -133,11 +133,6 @@ public sealed class GodotLogger : AbstractLogger _appender.Append(entry); } - private static string FormatProperties((string Key, object? Value)[]? properties) - { - return GodotLogAppender.FormatProperties(ToPropertiesDictionary(properties)); - } - private static IReadOnlyDictionary ToPropertiesDictionary( (string Key, object? Value)[]? properties) { diff --git a/ai-plan/public/README.md b/ai-plan/public/README.md index 98876db1..53b6415f 100644 --- a/ai-plan/public/README.md +++ b/ai-plan/public/README.md @@ -73,18 +73,3 @@ help the current worktree land on the right recovery documents without scanning - Branch: `docs/sdk-update-documentation` - Worktree hint: `GFramework-update-documentation` - Priority 1: `documentation-full-coverage-governance` - -## Archived Topics - -- `analyzer-warning-reduction` - - Archive root: `ai-plan/public/archive/analyzer-warning-reduction/` - - Note: 长期 warning-reduction 分支已收尾;PR #301 的最终 review follow-up 已本地闭环,后续仅作为历史恢复材料保留。 -- `cqrs-cache-docs-hardening` - - Archive root: `ai-plan/public/archive/cqrs-cache-docs-hardening/` - - Note: archived topics stay outside the default `boot` context until a user explicitly requests historical review. -- `documentation-governance-and-refresh` - - Archive root: `ai-plan/public/archive/documentation-governance-and-refresh/` - - Note: PR #268 已合并;文档治理与 Godot 栏目刷新阶段已完成,后续仅作为历史恢复材料保留。 -- `godot-logging-compliance-polish` - - Archive root: `ai-plan/public/archive/godot-logging-compliance-polish/` - - Note: PR #314 已合并到 `origin/main`;Godot logging 宿主集成、热重载、结构化输出和 review follow-up 已收尾,后续 Core appender / sink 统一评估应新建 active topic。 diff --git a/ai-plan/public/godot-logging-core-sink/todos/godot-logging-core-sink-tracking.md b/ai-plan/public/godot-logging-core-sink/todos/godot-logging-core-sink-tracking.md index 0c04f2bf..af8ac022 100644 --- a/ai-plan/public/godot-logging-core-sink/todos/godot-logging-core-sink-tracking.md +++ b/ai-plan/public/godot-logging-core-sink/todos/godot-logging-core-sink-tracking.md @@ -7,12 +7,13 @@ ## 当前恢复点 -- 恢复点编号:`GODOT-LOGGING-CORE-SINK-RP-002` -- 当前阶段:`Godot appender 最小实现已验证` +- 恢复点编号:`GODOT-LOGGING-CORE-SINK-RP-003` +- 当前阶段:`PR review follow-up 已验证` - 当前焦点: - `GFramework.Godot.Logging.GodotLogAppender` 已作为 Core `ILogAppender` 的 Godot 宿主落点落地 - `GodotLogger` 保留原有 `ILogger` 入口,但底层输出委托给 appender - Godot / Core logging 文档已说明 provider 与 appender 的组合边界 + - PR #315 最新 AI review 中仍适用的测试稳定性、dead private wrapper、boot index 与 trace heading 问题已处理 ## 已知输入 @@ -29,7 +30,8 @@ 2. 已完成:确认现有 Core `ILogAppender` 足够承载 Godot 输出,无需新增第二套 sink API 3. 已完成:保留 `GodotLog` / `GodotLoggerFactoryProvider` 入口,并让 `GodotLogger` 底层走 `GodotLogAppender` 4. 已完成:补充 `GodotLogAppender` targeted tests 与 `docs/zh-CN/` adoption guidance -5. 待确认:是否还需要在后续阶段补一个配置化 factory 示例,把 `GodotLogAppender` 与文件 / async appender 显式组合 +5. 已完成:处理 PR #315 最新 review follow-up,移除默认 boot index 的 archived topics 区块并消除 trace 重复 heading +6. 待确认:是否还需要在后续阶段补一个配置化 factory 示例,把 `GodotLogAppender` 与文件 / async appender 显式组合 ## 验证 @@ -42,9 +44,16 @@ - `dotnet build GFramework.Godot -c Release` - 结果:通过,`0 warning / 0 error` - 备注:验证受影响运行时项目 +- `dotnet format GFramework.Godot --verify-no-changes --no-restore --include GFramework.Godot/Logging/GodotLogger.cs` + - 结果:通过 +- `dotnet format GFramework.Godot.Tests --verify-no-changes --no-restore --include GFramework.Godot.Tests/Logging/GodotLogAppenderTests.cs GFramework.Godot.Tests/Logging/GodotLoggerSettingsLoaderTests.cs` + - 结果:通过 +- `dotnet format GFramework.sln --verify-no-changes --no-restore` + - 结果:失败 + - 备注:失败集中在仓库既有的 whitespace、final newline 与 charset 诊断,跨 `GFramework.Core`、`GFramework.Cqrs`、`GFramework.Game.Abstractions` 等未触碰项目;本轮改动用 scoped format 验证 ## 下一步 -1. 提交当前 appender 实现、测试、文档与 tracking 更新 -2. 如继续扩展本主题,优先评估是否需要示例化 `CompositeLogger + GodotLogAppender + FileAppender`,而不是新增 API -3. 若无新增需求,本主题可在 PR 验证通过后归档 +1. 提交当前 PR review follow-up +2. 等待 PR #315 复查并确认 CodeRabbit / Greptile 线程是否关闭 +3. 如继续扩展本主题,优先评估是否需要示例化 `CompositeLogger + GodotLogAppender + FileAppender`,而不是新增 API diff --git a/ai-plan/public/godot-logging-core-sink/traces/godot-logging-core-sink-trace.md b/ai-plan/public/godot-logging-core-sink/traces/godot-logging-core-sink-trace.md index 78abfb76..45ae1e36 100644 --- a/ai-plan/public/godot-logging-core-sink/traces/godot-logging-core-sink-trace.md +++ b/ai-plan/public/godot-logging-core-sink/traces/godot-logging-core-sink-trace.md @@ -18,13 +18,13 @@ - 不新增第二套业务日志 API;`GodotLog` 应保持为 Godot 宿主便利入口 - 不在已归档的 `godot-logging-compliance-polish` topic 中继续扩张新需求 -### 验证 +### RP-001 验证 - `dotnet build GFramework.sln -c Release` - 结果:通过,`0 warning / 0 error` - 备注:本次 build 在创建 active topic 前执行,用于验证归档维护对解决方案无影响;实现阶段需要重新跑受影响项目验证 -### 下一步 +### RP-001 下一步 1. 只读盘点 Core logging 抽象与 Godot logger/provider 的耦合点 2. 记录候选设计,明确哪些能力进入 Core,哪些保留在 Godot 宿主层 @@ -47,14 +47,47 @@ - Godot 输出可作为 Core appender 被自定义 factory / `CompositeLogger` 组合 - 文件、JSON、namespace filter、async 等仍由 Core logging 组件负责,Godot 包只提供宿主控制台落点 -### 验证 +### RP-002 验证 - `dotnet test GFramework.Godot.Tests -c Release` - 结果:通过,`75 passed / 0 failed / 0 skipped` - `dotnet build GFramework.Godot -c Release` - 结果:通过,`0 warning / 0 error` -### 下一步 +### RP-002 下一步 1. 提交当前 appender 实现与文档更新 2. 若继续推进本主题,优先补充组合示例或归档 topic,不新增第二套日志 API + +### RP-003 PR Review Follow-up + +- 使用 `$gframework-pr-review` 抓取 PR #315 最新 review payload: + - CodeRabbit:3 个 open thread,分别指向 appender test 顺序依赖、默认 boot index 包含 archived topic、trace 重复 heading + - Greptile:1 个 open thread,指出 `GodotLogger.FormatProperties` 为 dead private wrapper + - Gemini Code Assist:无 open thread + - GitHub Test Reporter:`2264 passed / 0 failed` + - MegaLinter:`dotnet-format` 报 restore failure;本地进一步验证时发现 solution-wide format 还有既有 repo-wide 诊断 +- 已实施: + - `GodotLogAppenderTests` 改为验证固定前缀与结构化属性集合内容,不再依赖 `Dictionary` 枚举顺序 + - 移除 `GodotLogger.FormatProperties` private wrapper,并把既有结构化属性测试改为验证生产路径使用的 `ToPropertiesDictionary` 与 `GodotLogAppender.FormatProperties` + - 从 `ai-plan/public/README.md` 移除 archived topics 区块,默认 boot index 只保留 active topic 与 worktree map + - 将 trace 中重复的 `### 验证` / `### 下一步` 改为 `RP-001` 与 `RP-002` 前缀,避免 MD024 anchor 冲突 + +### RP-003 验证 + +- `dotnet test GFramework.Godot.Tests -c Release` + - 结果:通过,`75 passed / 0 failed / 0 skipped` +- `dotnet build GFramework.Godot -c Release` + - 结果:通过,`0 warning / 0 error` +- `dotnet format GFramework.Godot --verify-no-changes --no-restore --include GFramework.Godot/Logging/GodotLogger.cs` + - 结果:通过 +- `dotnet format GFramework.Godot.Tests --verify-no-changes --no-restore --include GFramework.Godot.Tests/Logging/GodotLogAppenderTests.cs GFramework.Godot.Tests/Logging/GodotLoggerSettingsLoaderTests.cs` + - 结果:通过 +- `dotnet format GFramework.sln --verify-no-changes --no-restore` + - 结果:失败 + - 备注:失败为仓库既有的跨项目 whitespace、final newline 与 charset 诊断;本轮改动文件已通过 scoped format 验证 + +### RP-003 下一步 + +1. 提交 PR review follow-up +2. 等待 PR #315 复查,确认 CodeRabbit / Greptile open threads 是否关闭