From f776d09f6865de1d0e9901ad43c962727d58c97f Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Wed, 6 May 2026 09:25:59 +0800 Subject: [PATCH] =?UTF-8?q?fix(ai-first-config):=20=E6=94=B6=E5=8F=A3?= =?UTF-8?q?=E5=BC=80=E6=94=BE=E5=AF=B9=E8=B1=A1=E8=AF=84=E5=AE=A1=E8=B7=9F?= =?UTF-8?q?=E8=BF=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复 Runtime、Generator 与 Tooling 中开放对象关键字校验的不可达 additionalProperties 分支 - 补充 Tooling 对 additionalProperties false 的正向回归测试 - 更新游戏配置接入文档与 ai-plan 跟踪,记录 PR #325 的核验结论和验证结果 --- .../Config/SchemaConfigGenerator.cs | 7 --- .../Config/YamlConfigSchemaValidator.cs | 7 --- .../todos/ai-first-config-system-tracking.md | 1 + .../traces/ai-first-config-system-trace.md | 44 +++++++++++++++++++ docs/zh-CN/game/index.md | 3 +- .../src/configValidation.js | 4 -- .../test/configValidation.test.js | 17 +++++++ 7 files changed, 63 insertions(+), 20 deletions(-) diff --git a/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs b/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs index d99ab1cf..f52de49d 100644 --- a/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs +++ b/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs @@ -966,13 +966,6 @@ public sealed class SchemaConfigGenerator : IIncrementalGenerator return true; } - if (string.Equals(keywordName, "additionalProperties", StringComparison.Ordinal) && - element.TryGetProperty("additionalProperties", out var additionalPropertiesElement) && - additionalPropertiesElement.ValueKind == JsonValueKind.False) - { - return true; - } - diagnostic = Diagnostic.Create( ConfigSchemaDiagnostics.UnsupportedOpenObjectKeyword, CreateFileLocation(filePath), diff --git a/GFramework.Game/Config/YamlConfigSchemaValidator.cs b/GFramework.Game/Config/YamlConfigSchemaValidator.cs index fca06040..45381133 100644 --- a/GFramework.Game/Config/YamlConfigSchemaValidator.cs +++ b/GFramework.Game/Config/YamlConfigSchemaValidator.cs @@ -392,13 +392,6 @@ internal static partial class YamlConfigSchemaValidator return; } - if (string.Equals(keywordName, "additionalProperties", StringComparison.Ordinal) && - element.TryGetProperty("additionalProperties", out var additionalPropertiesElement) && - additionalPropertiesElement.ValueKind == JsonValueKind.False) - { - return; - } - throw ConfigLoadExceptionFactory.Create( ConfigLoadFailureKind.SchemaUnsupported, tableName, 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 65de61d8..4c713c76 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 @@ -93,6 +93,7 @@ - active 跟踪文件只保留当前恢复点、当前状态和下一步,不再重复堆积已完成阶段的完整历史 - 最近验证摘要:`2026-04-30` 已完成 Tooling / Docs reader-facing 收口与工具 parser 边界收紧,详细命令、批次背景与验证结果保留在 trace 的 `2026-04-30` 分阶段记录中 - 最近验证摘要:`2026-05-06` 已完成开放对象关键字边界收口;Runtime / Generator / Tooling 现统一拒绝 `patternProperties`、`propertyNames`、`unevaluatedProperties`,并保留 `additionalProperties: false` 作为唯一共享闭合对象入口;详细命令与批次背景保留在 trace 的 `2026-05-06` 记录中 +- 最近验证摘要:`2026-05-06` 已按 PR `#325` latest review follow-up 移除三端开放对象校验中的不可达 `additionalProperties: false` 放行分支,补齐 Tooling 正向回归,并同步拆分 reader-facing docs 对开放对象边界的表述;细节与验证命令保留在 trace 的 `2026-05-06` 追加记录中 - PR `#306` follow-up 摘要:已按 latest open review threads 补齐 Generator `anyOf` 对称回归、Tooling schema type 白名单、object-array 直系收集边界,以及 reader-facing docs 的显式 `additionalProperties: false` / adoption guidance 说明;细节和验证命令保留在 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 dc52f567..45956eda 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 @@ -280,3 +280,47 @@ 1. 继续盘点下一批不会改变生成类型形状、也不会重新打开对象形状的共享关键字 2. Tooling / Docs 如继续并发推进,优先补真实采用示例,不再重复扩写开放对象边界清单 3. 若后续 batch 再触碰 schema contract,继续保持 Runtime / Generator / Tooling 三端同步失败语义与 reader-facing docs 一致 + +### 阶段:PR #325 latest review follow-up 收口(AI-FIRST-CONFIG-RP-003) + +- 已使用 `gframework-pr-review` 抓取并复核 PR `#325` 的 latest review body、未解决 latest-head 线程、MegaLinter 摘要与测试报告 +- 本轮按“仅修复本地仍成立项”收口 5 条 review 信号: + - Runtime / Generator / Tooling 三端均移除开放对象关键字校验中的不可达 `additionalProperties: false` 放行分支 + - Tooling 测试补齐 `additionalProperties: false` 的正向回归,避免共享允许边界后续回退 + - `docs/zh-CN/game/index.md` 将开放对象边界说明拆成并列语句,避免把 `patternProperties` / `propertyNames` / `unevaluatedProperties` 误读成 `additionalProperties` 的变体 +- 本轮没有跟进 stale 信号: + - PR 当前 failed checks 为 `0` + - latest test report 为 `2280 passed / 0 failed` + - MegaLinter 仅保留 `dotnet-format` 摘要噪音,未提供需要额外修复的新代码格式差异 + +### 验证 + +- 2026-05-06:`python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/gframework-current-pr-review.json` + - 结果:通过 + - 备注:确认 PR `#325` 仍有 3 条 CodeRabbit nitpick 与 2 条 Greptile open threads,需要本地核验 +- 2026-05-06:`node --test ./test/*.test.js`(`tools/gframework-config-tool`) + - 结果:通过(134 tests) + - 备注:新增 `additionalProperties: false` 正向回归后,工具端继续显式接受唯一共享闭合对象入口 +- 2026-05-06:`dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~YamlConfigLoaderAllOfTests"` + - 结果:通过(18 tests) + - 备注:运行时开放对象关键字回归保持通过,未引入额外诊断路径漂移 +- 2026-05-06:`dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~SchemaConfigGeneratorTests"` + - 结果:通过(57 tests) + - 备注:生成器开放对象关键字诊断回归保持通过,移除不可达分支未影响既有诊断契约 +- 2026-05-06:`dotnet build GFramework.Game/GFramework.Game.csproj -c Release` + - 结果:通过(0 warnings, 0 errors) +- 2026-05-06:`dotnet build GFramework.Game.SourceGenerators/GFramework.Game.SourceGenerators.csproj -c Release` + - 结果:通过(0 warnings, 0 errors) +- 2026-05-06:`python3 scripts/license-header.py --check` + - 结果:环境受限 + - 备注:仓库脚本默认通过 `git ls-files` 枚举文件,在当前 WSL worktree 绑定下返回 `128`;已改为对受影响文件执行 targeted check 并通过 +- 2026-05-06:`python3 scripts/license-header.py --check --paths GFramework.Game/Config/YamlConfigSchemaValidator.cs GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs tools/gframework-config-tool/src/configValidation.js tools/gframework-config-tool/test/configValidation.test.js` + - 结果:通过 +- 2026-05-06:`git diff --check` + - 结果:通过 + +### 下一步 + +1. 执行本轮受影响 Tooling / Runtime / Generator 定向验证,并确认没有新增 warning 或格式漂移 +2. 若验证通过,重新抓取 PR `#325` review 状态,区分哪些 open threads 会随推送自动折叠 +3. 继续把 PR review follow-up 约束在“latest unresolved thread + 本地仍成立问题”,不回头追旧 summary 噪音 diff --git a/docs/zh-CN/game/index.md b/docs/zh-CN/game/index.md index b764d7bb..08036b88 100644 --- a/docs/zh-CN/game/index.md +++ b/docs/zh-CN/game/index.md @@ -86,8 +86,7 @@ IStorage storage = new FileStorage("GameData", serializer); 这条工作流的正式契约,以 `GFramework.Game` Runtime 和 `GFramework.Game.SourceGenerators` 当前共享支持的 schema 子集为准。`VS Code` 配置工具主要负责编辑期提示和表单辅助,不单独扩展运行时可接受的 schema 形状。 -开始接入时,建议先把 schema 约束控制在共享子集内,并尽早确认像 `additionalProperties: false`(需显式设置为 `false`;省略或 `true` 视为非 `false`,`patternProperties` / `propertyNames` / `unevaluatedProperties` 也不属于共享子集)这类已收口的对象边界,以及 -`oneOf` / `anyOf` 当前会被直接拒绝,而不是在工具里看起来“可以先写”。如果你的配置模型需要更深层的嵌套数组、联合分支或其他超出共享子集的复杂 +开始接入时,建议先把 schema 约束控制在共享子集内,并尽早确认像 `additionalProperties: false` 这类已收口的对象边界:它必须显式设置为 `false`,省略或 `true` 都视为非 `false`。`patternProperties` / `propertyNames` / `unevaluatedProperties` 当前也不属于共享子集。`oneOf` / `anyOf` 当前会被直接拒绝,而不是在工具里看起来“可以先写”。如果你的配置模型需要更深层的嵌套数组、联合分支或其他超出共享子集的复杂 shape,优先回到 raw YAML 和 schema 设计本体处理,再决定是否拆分结构或调整约束方式。 完整约定见: diff --git a/tools/gframework-config-tool/src/configValidation.js b/tools/gframework-config-tool/src/configValidation.js index 6a4b5418..60e31f8e 100644 --- a/tools/gframework-config-tool/src/configValidation.js +++ b/tools/gframework-config-tool/src/configValidation.js @@ -1285,10 +1285,6 @@ function validateUnsupportedOpenObjectKeyword(schemaNode, displayPath) { return; } - if (unsupportedKeyword === "additionalProperties" && schemaNode.additionalProperties === false) { - return; - } - throw new Error( `Schema property '${displayPath}' uses unsupported '${unsupportedKeyword}' metadata. ` + "The current config schema subset only accepts 'additionalProperties: false' and rejects keywords that reopen object shapes so fields remain closed and strongly typed."); diff --git a/tools/gframework-config-tool/test/configValidation.test.js b/tools/gframework-config-tool/test/configValidation.test.js index c276f31d..dd9bd723 100644 --- a/tools/gframework-config-tool/test/configValidation.test.js +++ b/tools/gframework-config-tool/test/configValidation.test.js @@ -228,6 +228,23 @@ test("parseSchemaContent should reject unsupported additionalProperties forms", /unsupported 'additionalProperties' metadata/u); }); +test("parseSchemaContent should allow explicit additionalProperties false", () => { + assert.doesNotThrow(() => parseSchemaContent(` + { + "type": "object", + "properties": { + "reward": { + "type": "object", + "additionalProperties": false, + "properties": { + "itemCount": { "type": "integer" } + } + } + } + } + `)); +}); + test("parseSchemaContent should reject unsupported open-object keywords", () => { assert.throws( () => parseSchemaContent(`