From 040bcb99e48614da15d93d4554250ef5df1b161c Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 30 Apr 2026 15:03:47 +0800 Subject: [PATCH] =?UTF-8?q?fix(ai-first-config):=20=E6=94=B6=E5=8F=A3?= =?UTF-8?q?=E5=BD=93=E5=89=8D=20PR=20=E5=AE=A1=E6=9F=A5=E9=81=97=E7=95=99?= =?UTF-8?q?=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 anyOf 对称运行时回归测试,覆盖组合关键字拒绝分支 - 更新 Game Abstractions README 的配置系统链接显示名,避免暴露原始路径 - 精简 active tracking 的批次级验证细节并补充恢复指针 - 清理 trace 中重复日期标题,消除 MD024 风险 --- GFramework.Game.Abstractions/README.md | 2 +- .../Config/YamlConfigLoaderAllOfTests.cs | 54 +++++++++++++++++++ .../todos/ai-first-config-system-tracking.md | 17 +----- .../traces/ai-first-config-system-trace.md | 6 --- 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/GFramework.Game.Abstractions/README.md b/GFramework.Game.Abstractions/README.md index 40693bc5..dbdd00c6 100644 --- a/GFramework.Game.Abstractions/README.md +++ b/GFramework.Game.Abstractions/README.md @@ -278,4 +278,4 @@ public sealed class ContinueGameCommandHandler - 最常见。公共层依赖 abstractions,应用层或引擎层依赖 runtime For configuration-specific adoption decisions, treat `GFramework.Game` and -[`docs/zh-CN/game/config-system.md`](../docs/zh-CN/game/config-system.md) as the authoritative next step. +[配置系统](../docs/zh-CN/game/config-system.md) as the authoritative next step. diff --git a/GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs b/GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs index af840c96..017c6dff 100644 --- a/GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs +++ b/GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs @@ -324,6 +324,60 @@ public sealed class YamlConfigLoaderAllOfTests }); } + /// + /// 验证运行时会显式拒绝当前共享子集尚未支持的 anyOf。 + /// + [Test] + public void LoadAsync_Should_Throw_When_Object_Schema_Declares_Unsupported_AnyOf() + { + CreateConfigFile( + "monster/slime.yaml", + BuildMonsterConfigYaml( + """ + itemCount: 3 + """)); + CreateSchemaFile( + "schemas/monster.schema.json", + BuildMonsterSchema( + DefaultRewardPropertiesJson, + """ + [ + { + "type": "object", + "required": ["itemCount"], + "properties": { + "itemCount": { "type": "integer" } + } + } + ] + """, + """ + "anyOf": [ + { + "type": "object", + "required": ["bonus"], + "properties": { + "bonus": { "type": "integer" } + } + } + ] + """)); + + var loader = CreateMonsterRewardLoader(); + var registry = CreateRegistry(); + + var exception = Assert.ThrowsAsync(() => loader.LoadAsync(registry)); + + Assert.Multiple(() => + { + Assert.That(exception, Is.Not.Null); + Assert.That(exception!.Diagnostic.FailureKind, Is.EqualTo(ConfigLoadFailureKind.SchemaUnsupported)); + Assert.That(exception.Diagnostic.DisplayPath, Is.EqualTo("reward")); + Assert.That(exception.Message, Does.Contain("unsupported combinator keyword 'anyOf'")); + Assert.That(registry.Count, Is.EqualTo(0)); + }); + } + /// /// 验证运行时接受显式声明的 additionalProperties: false, /// 因为这与当前闭合对象字段集语义保持一致。 diff --git a/ai-plan/public/ai-first-config-system/todos/ai-first-config-system-tracking.md b/ai-plan/public/ai-first-config-system/todos/ai-first-config-system-tracking.md index cbfa6585..f2bcd033 100644 --- a/ai-plan/public/ai-first-config-system/todos/ai-first-config-system-tracking.md +++ b/ai-plan/public/ai-first-config-system/todos/ai-first-config-system-tracking.md @@ -85,21 +85,8 @@ - `2026-04-17` 之前的详细实现记录与定向验证命令已归档到历史 tracking / trace - active 跟踪文件只保留当前恢复点、当前状态和下一步,不再重复堆积已完成阶段的完整历史 -- `2026-04-20` 当前恢复点验证: - - `python3 .codex/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --pr 262 --format json`:通过(`CodeRabbit outside-diff comments: 1 declared, 1 parsed`,`CodeRabbit nitpick comments: 2 declared, 2 parsed`) - - `bun run test`(`tools/gframework-config-tool`):通过(122 tests;包含条件分支坏形状回归) - - `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~SchemaConfigGeneratorTests"`:通过 - - `dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~YamlConfigLoaderIfThenElseTests"`:通过(8 tests;新增 `else without if` 运行时回归) - - `dotnet build GFramework.sln -c Release`:通过(存在仓库既有 analyzer warning,无新增错误) -- `2026-04-30` Tooling lane 收口验证: - - `dotnet build GFramework.sln -c Release`:通过(0 Warnings, 0 Errors;本轮仅改 ai-plan 文件,确认没有伴随未验证的代码漂移) -- `2026-04-30` Tooling / Docs reader-facing 收口: - - `git diff --check -- docs/zh-CN/game/config-tool.md docs/zh-CN/game/config-system.md tools/gframework-config-tool/README.md ai-plan/public/ai-first-config-system/todos/ai-first-config-system-tracking.md ai-plan/public/ai-first-config-system/traces/ai-first-config-system-trace.md`:通过 - - 已补齐工具能力边界、`additionalProperties: false` / `oneOf` / `anyOf` 说明、工具与 Runtime 契约关系,以及复杂 shape 的 raw YAML 回退路径 -- `2026-04-30` Tooling parser 边界收紧: - - `bun run test`(`tools/gframework-config-tool`):通过(4 test files) - - 已让工具侧对 `additionalProperties` 的共享边界与 Runtime / Generator 对齐,只接受 `additionalProperties: false` - - 已让数组 `items` / `contains` 子 schema 必须显式声明 object-shaped 且带 `type`,避免 tuple-array 或缺失类型的坏形状被工具侧宽松吞掉 +- 最近验证摘要:`2026-04-30` 已完成 Tooling / Docs reader-facing 收口与工具 parser 边界收紧,详细命令、批次背景与验证结果保留在 trace 的 `2026-04-30` 分阶段记录中 +- PR review 跟进指针:当前分支的 latest review follow-up 与后续本地核验结论以 `ai-first-config-system-trace.md` 为准,active tracking 不再重复展开逐条命令历史 ## 下一步 diff --git a/ai-plan/public/ai-first-config-system/traces/ai-first-config-system-trace.md b/ai-plan/public/ai-first-config-system/traces/ai-first-config-system-trace.md index 7c7a1cb4..1b6139f3 100644 --- a/ai-plan/public/ai-first-config-system/traces/ai-first-config-system-trace.md +++ b/ai-plan/public/ai-first-config-system/traces/ai-first-config-system-trace.md @@ -136,8 +136,6 @@ 2. 不再重复评估 `oneOf` / `anyOf` 的 object-focused 子集,除非未来主线明确接受联合形状生成 3. 若后续关键字需要新诊断编号或文档边界说明,继续保持 Runtime / Generator / Tooling 同步收口 -## 2026-04-30 - ### 阶段:Tooling lane 收口整理(AI-FIRST-CONFIG-RP-003) - 已把 Tooling / Docs 后续动作从 active 入口的主线叙述中剥离,改成 backlog 文件里的非阻塞并行 lane @@ -165,8 +163,6 @@ 2. 若另开 Tooling / Docs batch,先读取 `ai-first-config-system-csharp-experience-next.md` 的并行 lane,再把结果摘要写回 active tracking / trace 3. 继续保持 active 入口精简,不在默认恢复文件中追加 UI 细节、治理台账或面向读者的文档草稿 -## 2026-04-30 - ### 阶段:Tooling / Docs reader-facing 边界补齐(AI-FIRST-CONFIG-RP-003) - 已在 `config-tool.md`、`config-system.md` 和 `tools/gframework-config-tool/README.md` 明确 reader-facing 能力边界 @@ -190,8 +186,6 @@ 1. Tooling / Docs 后续若继续推进,优先补真实采用示例,而不是重复扩写边界清单 2. 主线代码批次继续以 Runtime / Generator / Tooling 三端共享关键字收口为中心 -## 2026-04-30 - ### 阶段:Tooling parser 坏形状拒绝收紧(AI-FIRST-CONFIG-RP-003) - 已在 `tools/gframework-config-tool/src/configValidation.js` 收紧工具侧 schema parser 边界