Skip to content

fix(game-config): 收紧开放对象关键字边界#325

Merged
GeWuYou merged 2 commits into
mainfrom
feat/ai-first-config
May 6, 2026
Merged

fix(game-config): 收紧开放对象关键字边界#325
GeWuYou merged 2 commits into
mainfrom
feat/ai-first-config

Conversation

@GeWuYou

@GeWuYou GeWuYou commented May 6, 2026

Copy link
Copy Markdown
Owner
  • 修复 Runtime、Generator 与 Tooling 对 patternProperties、propertyNames、unevaluatedProperties 的静默接受风险

  • 补充三端对称回归测试与 reader-facing 文档边界说明

  • 更新 ai-plan 恢复点、验证记录与下一步指针

Summary by CodeRabbit

发布说明

  • Bug 修复

    • 加强了 JSON Schema 验证,现仅允许 additionalProperties: false 用于闭合对象定义。patternPropertiespropertyNamesunevaluatedProperties 等其他开放对象关键字现将被正确拒绝,并提供更明确的错误提示。
  • 文档更新

    • 更新了配置系统文档,明确说明支持的 JSON Schema 功能边界和限制。

- 修复 Runtime、Generator 与 Tooling 对 patternProperties、propertyNames、unevaluatedProperties 的静默接受风险

- 补充三端对称回归测试与 reader-facing 文档边界说明

- 更新 ai-plan 恢复点、验证记录与下一步指针
@coderabbitai

coderabbitai Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@GeWuYou has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 40 minutes and 8 seconds before requesting another review.

To continue reviewing without waiting, purchase usage credits in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1fe0f73c-b531-474b-ab3b-07da593200ef

📥 Commits

Reviewing files that changed from the base of the PR and between cb6dd8a and f776d09.

📒 Files selected for processing (7)
  • GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs
  • GFramework.Game/Config/YamlConfigSchemaValidator.cs
  • 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
  • docs/zh-CN/game/index.md
  • tools/gframework-config-tool/src/configValidation.js
  • tools/gframework-config-tool/test/configValidation.test.js
📝 Walkthrough

Walkthrough

在 C# 运行时验证器、源代码生成器和 JavaScript 工具中添加了对不支持的开放对象关键字(patternPropertiespropertyNamesunevaluatedProperties)的专用检测逻辑,同时允许 additionalProperties: false,并更新了相应的测试和文档。

Changes

开放对象关键字边界约束

Layer / File(s) Summary
验证 Helper 实现
GFramework.Game/Config/YamlConfigSchemaValidator.cs, tools/gframework-config-tool/src/configValidation.js
新增 TryGetUnsupportedOpenObjectKeywordNamegetUnsupportedOpenObjectKeywordName 辅助方法,用于逐个检测不支持的开放对象关键字(additionalProperties 非 false、patternPropertiespropertyNamesunevaluatedProperties),返回第一个匹配的关键字或 null。
验证逻辑集成
GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs, GFramework.Game/Config/YamlConfigSchemaValidator.cs, tools/gframework-config-tool/src/configValidation.js
重构验证方法以使用新 helper;特殊处理允许 additionalProperties: false 通过;对其他不支持的关键字报告具体的关键字名称和统一的拒绝理由。
单元测试覆盖
GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs, GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs, tools/gframework-config-tool/test/configValidation.test.js
新增参数化测试方法,覆盖 patternPropertiespropertyNamesunevaluatedProperties 的拒绝场景;验证错误消息包含关键字名称和重开对象形状的拒绝说明。
文档和计划更新
GFramework.Game.SourceGenerators/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, docs/zh-CN/game/config-system.md, docs/zh-CN/game/index.md, tools/gframework-config-tool/README.md
更新不支持特性列表和配置系统文档;补充阶段追踪和开发计划,明确阐述开放对象关键字的边界约束:仅接受 additionalProperties: false,其他相关关键字在运行时、生成器和工具中被拒绝。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 分钟

Possibly related PRs

  • GeWuYou/GFramework#306:主 PR 直接扩展了 PR #306 引入的闭对象验证逻辑,通过添加针对性的不支持开放对象关键字检测并保留 additionalProperties: false 的允许情况。
  • GeWuYou/GFramework#273:两个 PR 都修改了 SchemaConfigGenerator.cs 中的 JSON Schema 验证逻辑。
  • GeWuYou/GFramework#211:两个 PR 都修改了 YamlConfigSchemaValidatorSchemaConfigGenerator 的验证代码;主 PR 扩展了 PR #211 引入的验证逻辑以涵盖更多开放对象关键字。
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题清晰、简洁,准确概括了本次提交的主要目标——收紧开放对象关键字的边界限制。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ai-first-config

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown

Summary

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Other ❓ Flaky 🍂 Duration ⏱️
2280    ↑58 2280    ↑58 0 0 0 0 36.4s    ↓717ms

Test Results

passed 2280 passed ↑58

Details

tests 2280 tests ↑58
clock 36.4s ↓717ms
tool nunit
build CI - Build & Test arrow-right build-and-test link #1058
pull-request fix(game-config): 收紧开放对象关键字边界 link #325

Insights

Average Tests per Run Total Flaky Tests Total Failed Slowest Test (p95)
2160 0 0 4.7s

build-and-test: Run #1058

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Pending ⏳ Other ❓ Flaky 🍂 Duration ⏱️
2280 2280 0 0 0 0 0 36.4s

🎉 All tests passed!

Slowest Tests

Test 📝 Results 📊 Duration (avg) ⏱️ Duration (p95) ⏱️
SendRequestAsync_Should_ResolveCqrsRuntime_OnlyOnce_When_AccessedConcurrently 11 2.7s 4.7s
CreateStream_Should_ResolveCqrsRuntime_OnlyOnce_When_AccessedConcurrently 4 4.2s 4.7s
Does_Not_Report_When_FieldInjectedModel_Is_Registered 11 2.1s 2.3s
Generates_Scene_Behavior_Boilerplate 11 1.9s 2.0s
CleanupDuringAcquire_Should_NotCauseRaceCondition 11 1.1s 1.1s
Append_ShouldNotBlock 11 1.0s 1.0s
Context_Caching_Should_Improve_Performance 11 782ms 791ms
StartHotReload_Should_Update_Registered_Table_When_Config_File_Changes 11 208ms 643ms
PendingCount_ShouldReflectQueuedEntries 11 501ms 501ms
Cleanup_Should_NotRemoveActiveLocks 11 404ms 406ms

± Comparison with run #1022 at 7656067 | 🎉 No failed tests detected across all runs. | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 11 runs.

Github Test Reporter by CTRF 💚

@greptile-apps

greptile-apps Bot commented May 6, 2026

Copy link
Copy Markdown

Greptile Summary

This PR tightens the open-object keyword boundary across all three enforcement layers (Runtime, Source Generator, VS Code Tooling) by explicitly rejecting patternProperties, propertyNames, and unevaluatedProperties instead of silently accepting them. Previously, only additionalProperties (non-false) was actively guarded; these other keywords could slip through undetected and reopen object shapes, drifting from the closed-field contract.

  • Runtime & Generator (C#): Extracted TryGetUnsupportedOpenObjectKeywordName helper that checks all four open-object keywords; replaced the old additionalProperties-only inline guard (and removed the previously-flagged unreachable additionalProperties: false branches) in both YamlConfigSchemaValidator.cs and SchemaConfigGenerator.cs.
  • Tooling (JS): Added equivalent getUnsupportedOpenObjectKeywordName helper in configValidation.js, wired into validateUnsupportedOpenObjectKeyword, with the same dead-code early-return removed.
  • Tests & Docs: Symmetric three-case parameterised regression tests added for all three platforms; reader-facing documentation updated to enumerate the rejected keywords explicitly.

Confidence Score: 5/5

Safe to merge — the change closes a silent-acceptance gap without altering any existing accepted schema shapes.

All three enforcement layers (Runtime, Generator, Tooling) are updated symmetrically with the same keyword set, previously-flagged dead-code branches are removed, and every new rejection path is covered by a parameterised regression test. No accepted schema shapes are affected; only schemas that were previously accepted incorrectly are now correctly rejected.

No files require special attention.

Important Files Changed

Filename Overview
GFramework.Game/Config/YamlConfigSchemaValidator.cs Replaced inline additionalProperties-only guard with TryGetUnsupportedOpenObjectKeywordName helper that now also rejects patternProperties, propertyNames, and unevaluatedProperties; previously-flagged dead-code branch removed.
GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs Same helper refactor as the Runtime validator — old inline guard replaced by TryGetUnsupportedOpenObjectKeywordName; previously-flagged unreachable additionalProperties: false branch removed.
tools/gframework-config-tool/src/configValidation.js New getUnsupportedOpenObjectKeywordName helper added and wired into validateUnsupportedOpenObjectKeyword; dead-code early-return for additionalProperties: false removed, symmetry with C# implementations maintained.
GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs Adds three-case parameterised regression test (patternProperties / propertyNames / unevaluatedProperties) covering Runtime rejection path with correct diagnostic assertions.
GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs Adds symmetric three-case parameterised test for Generator diagnostic GF_ConfigSchema_016, matching Runtime and Tooling regression coverage.
tools/gframework-config-tool/test/configValidation.test.js Adds explicit allow-test for additionalProperties: false and three separate reject-tests for patternProperties, propertyNames, unevaluatedProperties to complete Tooling regression parity.
docs/zh-CN/game/config-system.md Updated supported/rejected keyword lists to explicitly call out the three new rejected open-object keywords alongside the existing oneOf/anyOf rejections.
docs/zh-CN/game/index.md Refactored onboarding paragraph to enumerate patternProperties/propertyNames/unevaluatedProperties as separate rejected keywords rather than implying they are variants of additionalProperties.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Schema node encountered] --> B{TryGetUnsupportedOpenObjectKeywordName}

    B --> C{additionalProperties present?}
    C -- "Yes, value ≠ false" --> D[Return 'additionalProperties' ❌]
    C -- "No / value = false" --> E{patternProperties present?}

    E -- Yes --> F[Return 'patternProperties' ❌]
    E -- No --> G{propertyNames present?}

    G -- Yes --> H[Return 'propertyNames' ❌]
    G -- No --> I{unevaluatedProperties present?}

    I -- Yes --> J[Return 'unevaluatedProperties' ❌]
    I -- No --> K[Return null ✅ — object is closed]

    K --> L[Continue parsing / code generation]
    D & F & H & J --> M[Emit error diagnostic / throw ConfigLoadException]
Loading

Reviews (2): Last reviewed commit: "fix(ai-first-config): 收口开放对象评审跟进" | Re-trigger Greptile

Comment thread GFramework.Game/Config/YamlConfigSchemaValidator.cs Outdated
Comment thread tools/gframework-config-tool/src/configValidation.js Outdated
@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown

⚠️MegaLinter analysis: Success with warnings

Descriptor Linter Files Fixed Errors Warnings Elapsed time
⚠️ CSHARP dotnet-format yes 1 no 6.17s
✅ REPOSITORY gitleaks yes no no 9.36s
✅ REPOSITORY trufflehog yes no no 8.22s

Detailed Issues

⚠️ CSHARP / dotnet-format - 1 error
Welcome to .NET 9.0!
---------------------
SDK Version: 9.0.114

----------------
Installed an ASP.NET Core HTTPS development certificate.
To trust the certificate, run 'dotnet dev-certs https --trust'
Learn about HTTPS: https://aka.ms/dotnet-https

----------------
Write your first app: https://aka.ms/dotnet-hello-world
Find out what's new: https://aka.ms/dotnet-whats-new
Explore documentation: https://aka.ms/dotnet-docs
Report issues and find source on GitHub: https://github.com/dotnet/core
Use 'dotnet --help' to see available commands or visit: https://aka.ms/dotnet-cli
--------------------------------------------------------------------------------------
Unhandled exception: System.Exception: Restore operation failed.
   at Microsoft.CodeAnalysis.Tools.CodeFormatter.OpenMSBuildWorkspaceAsync(String solutionOrProjectPath, WorkspaceType workspaceType, Boolean noRestore, Boolean requiresSemantics, String binaryLogPath, Boolean logWorkspaceWarnings, ILogger logger, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Tools.CodeFormatter.FormatWorkspaceAsync(FormatOptions formatOptions, ILogger logger, CancellationToken cancellationToken, String binaryLogPath)
   at Microsoft.CodeAnalysis.Tools.FormatCommandCommon.FormatAsync(FormatOptions formatOptions, ILogger`1 logger, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Tools.Commands.RootFormatCommand.FormatCommandDefaultHandler.InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken)
   at System.CommandLine.Invocation.InvocationPipeline.InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken)

See detailed reports in MegaLinter artifacts
Set VALIDATE_ALL_CODEBASE: true in mega-linter.yml to validate all sources, not only the diff

MegaLinter is graciously provided by OX Security
Show us your support by starring ⭐ the repository

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
docs/zh-CN/game/index.md (1)

89-91: ⚡ Quick win

建议把开放对象关键字从 additionalProperties: false 的括注中拆出,避免读者误读为后者的子形态。

当前括号内同时表达了“additionalProperties: false 必须显式”和“其他三个开放对象关键字也不在共享子集内”两件事,容易让读者把 patternProperties / propertyNames / unevaluatedProperties 当作 additionalProperties 的另一种取值。建议拆成两条并列描述,与 config-system.md 第 815 行的写法保持一致。

📝 建议改写
-开始接入时,建议先把 schema 约束控制在共享子集内,并尽早确认像 `additionalProperties: false`(需显式设置为 `false`;省略或 `true` 视为非 `false`,`patternProperties` / `propertyNames` / `unevaluatedProperties` 也不属于共享子集)这类已收口的对象边界,以及
-`oneOf` / `anyOf` 当前会被直接拒绝,而不是在工具里看起来“可以先写”。如果你的配置模型需要更深层的嵌套数组、联合分支或其他超出共享子集的复杂
-shape,优先回到 raw YAML 和 schema 设计本体处理,再决定是否拆分结构或调整约束方式。
+开始接入时,建议先把 schema 约束控制在共享子集内,并尽早确认这些已收口的对象边界:
+
+- `additionalProperties` 必须显式设置为 `false`;省略或写成 `true` 都视为非 `false`,会被直接拒绝
+- `patternProperties` / `propertyNames` / `unevaluatedProperties` 不属于共享子集,会在解析或生成阶段直接拒绝
+- `oneOf` / `anyOf` 当前同样会被直接拒绝,而不是在工具里看起来“可以先写”
+
+如果你的配置模型需要更深层的嵌套数组、联合分支或其他超出共享子集的复杂 shape,优先回到 raw YAML 和 schema 设计本体处理,再决定是否拆分结构或调整约束方式。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/zh-CN/game/index.md` around lines 89 - 91, The current sentence bundles
two points and risks readers treating patternProperties / propertyNames /
unevaluatedProperties as values of additionalProperties; split the parenthetical
into two parallel statements: one stating that additionalProperties must be
explicitly set to false (omitting or true is not false) and a separate sentence
listing that patternProperties, propertyNames, and unevaluatedProperties are not
part of the shared subset. Also keep the existing note that oneOf / anyOf are
rejected, mirroring the style used elsewhere (e.g., the config-system wording)
so each constraint is clearly separated and unambiguous.
tools/gframework-config-tool/test/configValidation.test.js (1)

231-286: ⚡ Quick win

建议补一条 additionalProperties: false 的正向回归用例。

当前新增块把 3 个开放对象关键字的拒绝路径覆盖得很好;建议再显式断言 additionalProperties: false 可通过,避免“允许边界”后续被回归破坏。

可参考的补充测试
 test("parseSchemaContent should reject unsupported open-object keywords", () => {
+    assert.doesNotThrow(() => parseSchemaContent(`
+        {
+          "type": "object",
+          "properties": {
+            "reward": {
+              "type": "object",
+              "additionalProperties": false,
+              "properties": {
+                "itemCount": { "type": "integer" }
+              }
+            }
+          }
+        }
+    `));
+
     assert.throws(
         () => parseSchemaContent(`
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/gframework-config-tool/test/configValidation.test.js` around lines 231
- 286, Add a positive regression test confirming parseSchemaContent accepts
objects with "additionalProperties": false: inside the same suite (near the
other parseSchemaContent assertions) add a test case that calls
parseSchemaContent with a schema where a nested object (e.g., the "reward"
property) includes "additionalProperties": false and valid "properties" (like
"itemCount") and assert it does NOT throw; reference the existing test pattern
and the parseSchemaContent function so the new case sits alongside the
unsupported-keyword asserts to prevent future regressions.
GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs (1)

964-974: ⚡ Quick win

建议移除不可达分支,避免后续规则漂移

Line 969-972 这段放行在当前实现下不会命中:TryGetUnsupportedOpenObjectKeywordName(Line 1005-1007)已经把 additionalProperties: false 过滤掉了。保留该分支会让后续维护者误判真实生效路径。

♻️ 建议修改
     diagnostic = null;
     if (TryGetUnsupportedOpenObjectKeywordName(element) is not { } keywordName)
     {
         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),
         Path.GetFileName(filePath),
         displayPath,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs` around
lines 964 - 974, 当前在 SchemaConfigGenerator.cs 中对 keywordName
的后续分支检查(string.Equals(keywordName, "additionalProperties", ...) &&
element.TryGetProperty("additionalProperties", out var
additionalPropertiesElement) && additionalPropertiesElement.ValueKind ==
JsonValueKind.False)是不可达的,因为 TryGetUnsupportedOpenObjectKeywordName 已经在
TryGetUnsupportedOpenObjectKeywordName(...) 中对 additionalProperties: false
做了过滤;请删除这段冗余检查并保留最初的早期返回逻辑(即只用 TryGetUnsupportedOpenObjectKeywordName(...)
的结果进行返回),以避免规则语义漂移并消除误导性分支(定位符:TryGetUnsupportedOpenObjectKeywordName,
keywordName, additionalPropertiesElement)。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@docs/zh-CN/game/index.md`:
- Around line 89-91: The current sentence bundles two points and risks readers
treating patternProperties / propertyNames / unevaluatedProperties as values of
additionalProperties; split the parenthetical into two parallel statements: one
stating that additionalProperties must be explicitly set to false (omitting or
true is not false) and a separate sentence listing that patternProperties,
propertyNames, and unevaluatedProperties are not part of the shared subset. Also
keep the existing note that oneOf / anyOf are rejected, mirroring the style used
elsewhere (e.g., the config-system wording) so each constraint is clearly
separated and unambiguous.

In `@GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs`:
- Around line 964-974: 当前在 SchemaConfigGenerator.cs 中对 keywordName
的后续分支检查(string.Equals(keywordName, "additionalProperties", ...) &&
element.TryGetProperty("additionalProperties", out var
additionalPropertiesElement) && additionalPropertiesElement.ValueKind ==
JsonValueKind.False)是不可达的,因为 TryGetUnsupportedOpenObjectKeywordName 已经在
TryGetUnsupportedOpenObjectKeywordName(...) 中对 additionalProperties: false
做了过滤;请删除这段冗余检查并保留最初的早期返回逻辑(即只用 TryGetUnsupportedOpenObjectKeywordName(...)
的结果进行返回),以避免规则语义漂移并消除误导性分支(定位符:TryGetUnsupportedOpenObjectKeywordName,
keywordName, additionalPropertiesElement)。

In `@tools/gframework-config-tool/test/configValidation.test.js`:
- Around line 231-286: Add a positive regression test confirming
parseSchemaContent accepts objects with "additionalProperties": false: inside
the same suite (near the other parseSchemaContent assertions) add a test case
that calls parseSchemaContent with a schema where a nested object (e.g., the
"reward" property) includes "additionalProperties": false and valid "properties"
(like "itemCount") and assert it does NOT throw; reference the existing test
pattern and the parseSchemaContent function so the new case sits alongside the
unsupported-keyword asserts to prevent future regressions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fcc39d3f-a1aa-4467-b101-5280d18ef609

📥 Commits

Reviewing files that changed from the base of the PR and between a8c6c11 and cb6dd8a.

📒 Files selected for processing (12)
  • GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs
  • GFramework.Game.SourceGenerators/README.md
  • GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs
  • GFramework.Game/Config/YamlConfigSchemaValidator.cs
  • GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs
  • 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
  • docs/zh-CN/game/config-system.md
  • docs/zh-CN/game/index.md
  • tools/gframework-config-tool/README.md
  • tools/gframework-config-tool/src/configValidation.js
  • tools/gframework-config-tool/test/configValidation.test.js
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Analyze (C#)
  • GitHub Check: Code Quality & Security
🧰 Additional context used
📓 Path-based instructions (9)
**/*.cs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.cs: Apply [Log] attribute for automatic logging field and logging helper method generation
Apply [Priority] attribute for automatic priority comparison implementation generation
Apply [GenerateEnumExtensions] attribute to generate enumeration extension capabilities
Apply [ContextAware] attribute to automatically implement IContextAware boilerplate logic

**/*.cs: All public, protected, and internal types and members MUST include XML documentation comments (///) in C#
XML documentation MUST use <summary>, <param>, <returns>, <exception>, and <remarks> where applicable, and explain intent, contract, and usage constraints instead of restating syntax
If a C# member participates in lifecycle, threading, registration, or disposal behavior, document that behavior explicitly
Core framework components (Architecture, Module, System, Context, Registry, Service Module, Lifecycle types) MUST include high-level explanations of responsibilities, lifecycle, interaction with other components, why abstraction exists, and when to use instead of alternatives
Generated logic and source generator pipelines MUST explain what is generated, why it is generated, semantic assumptions the generator relies on, and any diagnostics or fallback behavior
Do not rely on implicit imports. Declare every required using explicitly in C#
Write null-safe code that respects nullable annotations instead of suppressing warnings by default in C#
Use namespace pattern GFramework.{Module}.{Feature} with PascalCase segments in C#
Follow standard C# naming: Types/methods/properties/events/constants use PascalCase, Interfaces use I prefix, Parameters and locals use camelCase, Private fields use _camelCase
Use Allman braces style for C#
Keep using directives at the top of the file and sort them consistently in C#
Prefer one primary type per file unless surrounding project already uses different local pattern
Prefer explicit, readable code over clever shorthand in framework internals
M...

Files:

  • GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs
  • GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs
  • GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs
  • GFramework.Game/Config/YamlConfigSchemaValidator.cs
**/*[!.]*

📄 CodeRabbit inference engine (AGENTS.md)

For files with shebang lines, keep shebang as first line and place license header immediately after it

Files:

  • GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs
  • ai-plan/public/ai-first-config-system/traces/ai-first-config-system-trace.md
  • GFramework.Game.SourceGenerators/README.md
  • docs/zh-CN/game/index.md
  • tools/gframework-config-tool/test/configValidation.test.js
  • GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs
  • tools/gframework-config-tool/README.md
  • tools/gframework-config-tool/src/configValidation.js
  • ai-plan/public/ai-first-config-system/todos/ai-first-config-system-tracking.md
  • GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs
  • docs/zh-CN/game/config-system.md
  • GFramework.Game/Config/YamlConfigSchemaValidator.cs
**/*.{cs,ts,tsx,js,jsx,py,sh}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{cs,ts,tsx,js,jsx,py,sh}: All generated or modified code MUST include clear and meaningful comments where required by documentation rules
Comments MUST NOT be trivial, redundant, or misleading. Prefer explaining why and when, not just what. Code should remain understandable without requiring external context
Avoid obvious comments such as // increment i

Files:

  • GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs
  • tools/gframework-config-tool/test/configValidation.test.js
  • GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs
  • tools/gframework-config-tool/src/configValidation.js
  • GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs
  • GFramework.Game/Config/YamlConfigSchemaValidator.cs
**/*.{cs,ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{cs,ts,tsx,js,jsx,py}: Add inline comments for non-trivial logic, concurrency/threading behavior, performance-sensitive paths, workarounds/compatibility constraints/edge cases, and registration order/lifecycle sequencing/generated code assumptions
Methods with non-trivial logic MUST document core idea, key decisions, and edge case handling
Separate logical blocks with blank lines when it improves readability
Unless there is clear and documented reason to keep file large, keep single source file under roughly 800-1000 lines
Validate external or user-controlled input before it reaches file system, serialization, reflection, code generation, or process boundaries
Do not build command strings, file paths, type names, or generated code from untrusted input without strict validation or allow-listing
Avoid logging secrets, tokens, credentials, or machine-specific sensitive data
Prefer least-privilege behavior for file, process, and environment access

Files:

  • GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs
  • tools/gframework-config-tool/test/configValidation.test.js
  • GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs
  • tools/gframework-config-tool/src/configValidation.js
  • GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs
  • GFramework.Game/Config/YamlConfigSchemaValidator.cs
**/*.{csproj,cs}

📄 CodeRabbit inference engine (AGENTS.md)

Framework runtime, abstractions, and meta-package projects MUST NOT reference *.SourceGenerators* projects or packages, and MUST NOT use source-generator attributes

Files:

  • GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs
  • GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs
  • GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs
  • GFramework.Game/Config/YamlConfigSchemaValidator.cs
**/*.{cs,ts,tsx,js,jsx,py,sh,xml,csproj,props,targets}

📄 CodeRabbit inference engine (AGENTS.md)

Use 4 spaces for indentation. Do not use tabs

Files:

  • GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs
  • tools/gframework-config-tool/test/configValidation.test.js
  • GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs
  • tools/gframework-config-tool/src/configValidation.js
  • GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs
  • GFramework.Game/Config/YamlConfigSchemaValidator.cs
**/*.{cs,ts,tsx,js,jsx,py,sh,xml}

📄 CodeRabbit inference engine (AGENTS.md)

Keep line length readable. Around 120 characters is preferred upper bound

Files:

  • GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs
  • tools/gframework-config-tool/test/configValidation.test.js
  • GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs
  • tools/gframework-config-tool/src/configValidation.js
  • GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs
  • GFramework.Game/Config/YamlConfigSchemaValidator.cs
**/*.{md,mdx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{md,mdx}: Keep code samples, package names, and command examples aligned with current repository state in documentation
When public page references XML docs or API coverage, convert evidence into reader-facing guidance: explain which types/namespaces/entry points readers should inspect and why
For integration-oriented features such as AI-First config system, documentation MUST cover: project directory layout/file conventions, required project/package wiring, minimal working example, migration/compatibility notes
When examples are rewritten, preserve only parts that remain true. Delete or replace speculative examples instead of lightly editing into another inaccurate form

Files:

  • ai-plan/public/ai-first-config-system/traces/ai-first-config-system-trace.md
  • GFramework.Game.SourceGenerators/README.md
  • docs/zh-CN/game/index.md
  • tools/gframework-config-tool/README.md
  • ai-plan/public/ai-first-config-system/todos/ai-first-config-system-tracking.md
  • docs/zh-CN/game/config-system.md
docs/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Documentation should be organized with Chinese content in docs/zh-CN/ and structured to include getting started, module-specific capabilities (Core, Game, Godot, ECS), source generator usage, tutorials, best practices, and troubleshooting

Files:

  • docs/zh-CN/game/index.md
  • docs/zh-CN/game/config-system.md
🧠 Learnings (2)
📚 Learning: 2026-04-06T12:45:43.921Z
Learnt from: GeWuYou
Repo: GeWuYou/GFramework PR: 190
File: GFramework.Game/Config/GameConfigBootstrap.cs:1-3
Timestamp: 2026-04-06T12:45:43.921Z
Learning: In the GeWuYou/GFramework repository, C# files may omit explicit `using System*` imports because the project-wide `GlobalUsings.cs` (referenced via manual global `using` directives) supplies common namespaces (e.g., `System`, `System.Threading`, `System.Threading.Tasks`). During code review, do not flag missing `using System...` directives in `.cs` files as long as `GlobalUsings.cs` is present/used to provide those namespaces.

Applied to files:

  • GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs
  • GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs
  • GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs
  • GFramework.Game/Config/YamlConfigSchemaValidator.cs
📚 Learning: 2026-04-16T13:25:59.124Z
Learnt from: GeWuYou
Repo: GeWuYou/GFramework PR: 235
File: GFramework.SourceGenerators.Tests/Rule/ContextAwareGeneratorSnapshotTests.cs:1-3
Timestamp: 2026-04-16T13:25:59.124Z
Learning: In the GeWuYou/GFramework repo, treat `global using NUnit.Framework;` as provided project-wide by `GFramework.SourceGenerators.Tests/GlobalUsings.cs` (via GlobalUsings.cs). Do not require or flag missing per-file `using NUnit.Framework;` directives in test `.cs` files under `GFramework.SourceGenerators.Tests/`, since the project-wide global usings already include NUnit (along with other common namespaces).

Applied to files:

  • GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs
🪛 LanguageTool
ai-plan/public/ai-first-config-system/traces/ai-first-config-system-trace.md

[uncategorized] ~243-~243: 能愿动词不能成为‘把’字句、‘被’字句的谓语动词。应该是:"可能把……这"。
Context: ...接失败 - reader-facing docs 也已同步更新,避免采用文档继续把这类关键字描述成“也许工具没做但运行时可能支持”的灰区 ### 关键决定 - `additionalPropertie...

(wa3)


[uncategorized] ~281-~281: 您的意思是“"不"真实”?
Context: ...开对象形状的共享关键字 2. Tooling / Docs 如继续并发推进,优先补真实采用示例,不再重复扩写开放对象边界清单 3. 若后续 batch 再触碰 s...

(BU)

tools/gframework-config-tool/README.md

[style] ~143-~143: Try using a descriptive adverb here.
Context: ...nd unevaluatedProperties are rejected on purpose, as are unsupported combinators such ...

(ON_PURPOSE_DELIBERATELY)

🔇 Additional comments (10)
ai-plan/public/ai-first-config-system/traces/ai-first-config-system-trace.md (1)

235-282: 新增 trace 章节结构清晰,记录完整。

恢复点编号、Stop Condition、验证命令与下一步均与既有章节风格保持一致,能直接给后续 boot 提供恢复入口。

GFramework.Game.SourceGenerators/README.md (1)

84-86: 关键字列表与运行时/工具/Chinese docs 三端对齐,方向正确。

补齐 patternProperties / propertyNames / unevaluatedProperties 后,本 README 与 docs/zh-CN/game/config-system.md 第 815 行、tools/gframework-config-tool/README.md 第 118-119/127-128/142-144 行的能力边界描述保持一致。

docs/zh-CN/game/config-system.md (1)

815-822: 两处文档边界描述清晰、与三端实现一致。

第 815 行把“仅接受 additionalProperties: false”和“其他开放对象关键字直接拒绝”分开表达,第 822 行把它们一并补入回退清单。读者从这两段就能完整看到当前共享子集对开放对象关键字的整体收口。

tools/gframework-config-tool/README.md (1)

118-144: 英文 README 边界说明与运行时实现一致。

三处更新(quick-start checklist / raw YAML 回退清单 / Current Constraints)共同明确:仅 additionalProperties: false 属于共享子集,patternProperties / propertyNames / unevaluatedProperties 会被显式拒绝。措辞与 configValidation.js 抛出的诊断消息可对齐。

tools/gframework-config-tool/src/configValidation.js (1)

1273-1295: 收紧边界的实现与 C# 端 TryGetUnsupportedOpenObjectKeywordName 镜像一致。

getUnsupportedOpenObjectKeywordName 通过 hasOwnProperty.call 判断关键字存在,并在 additionalProperties 上把“严格等于 false”作为唯一通过条件,与 GFramework.Game/Config/YamlConfigSchemaValidator.cs:384-440TryGetUnsupportedOpenObjectKeywordName / ValidateUnsupportedOpenObjectKeywords 完全对称。错误消息中引用具体的 unsupportedKeyword,与新增的 JS / .NET 回归断言匹配。

备注:validateUnsupportedOpenObjectKeyword 中行 1288 的二次判断在当前实现下不可达,仅作为与 C# 镜像写法的防御冗余,无需在本轮修改。

Also applies to: 1385-1411

GFramework.Game/Config/YamlConfigSchemaValidator.cs (1)

390-440: 这段开放对象关键字收紧实现是正确的。

关键词识别与错误信息已做到“命中哪个报哪个”,并且与“仅允许 additionalProperties: false”的边界目标一致。

GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs (1)

998-1015: 开放对象关键字检测拆分得很好

把关键字识别收敛到 TryGetUnsupportedOpenObjectKeywordName 后,规则边界更集中,诊断也更容易保持三端一致,这个改动方向很好。

GFramework.Game.Tests/Config/YamlConfigLoaderAllOfTests.cs (1)

451-498: 参数化回归用例覆盖面到位

这一组 TestCase 很好地把开放对象关键字的拒绝行为固定下来,并且断言了关键字名与错误语义,能有效防止 Runtime 边界回退。

GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs (1)

1968-2018: 参数化回归覆盖完整,边界语义断言到位。

这段新增测试对三个开放对象关键字做了对称覆盖,并且同时校验了关键字名与统一拒绝语义,和本次边界收紧目标一致。

ai-plan/public/ai-first-config-system/todos/ai-first-config-system-tracking.md (1)

15-15: 跟踪文档与实现边界已对齐,风险与下一步指针表达清晰。

新增内容准确反映了开放对象关键字的收口策略和三端一致性,且验证时间点与行动项可追踪性良好。

Also applies to: 24-25, 46-48, 95-95, 101-101

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 6, 2026
- 修复 Runtime、Generator 与 Tooling 中开放对象关键字校验的不可达 additionalProperties 分支

- 补充 Tooling 对 additionalProperties false 的正向回归测试

- 更新游戏配置接入文档与 ai-plan 跟踪,记录 PR #325 的核验结论和验证结果
@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown

Summary

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Other ❓ Flaky 🍂 Duration ⏱️
2280 2280 0 0 0 0 38.3s    ↑1.9s

Test Results

passed 2280 passed

Details

tests 2280 tests
clock 38.3s ↑1.9s
tool nunit
build CI - Build & Test arrow-right build-and-test link #1059
pull-request fix(game-config): 收紧开放对象关键字边界 link #325

Insights

Average Tests per Run Total Flaky Tests Total Failed Slowest Test (p95)
2170 0 0 4.7s

build-and-test: Run #1059

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Pending ⏳ Other ❓ Flaky 🍂 Duration ⏱️
2280 2280 0 0 0 0 0 38.3s

🎉 All tests passed!

Slowest Tests

Test 📝 Results 📊 Duration (avg) ⏱️ Duration (p95) ⏱️
SendRequestAsync_Should_ResolveCqrsRuntime_OnlyOnce_When_AccessedConcurrently 12 2.4s 4.7s
CreateStream_Should_ResolveCqrsRuntime_OnlyOnce_When_AccessedConcurrently 5 4.2s 4.7s
Does_Not_Report_When_FieldInjectedModel_Is_Registered 12 2.1s 2.3s
Generates_Scene_Behavior_Boilerplate 12 1.9s 2.0s
CleanupDuringAcquire_Should_NotCauseRaceCondition 12 1.1s 1.1s
Append_ShouldNotBlock 12 1.0s 1.0s
Context_Caching_Should_Improve_Performance 12 782ms 791ms
StartHotReload_Should_Update_Registered_Table_When_Config_File_Changes 12 204ms 643ms
PendingCount_ShouldReflectQueuedEntries 12 501ms 501ms
Cleanup_Should_NotRemoveActiveLocks 12 404ms 406ms

± Comparison with run #1058 at 3859fea | 🎉 No failed tests detected across all runs. | 🍂 No flaky tests detected across all runs. | ⏱️ Measured over 12 runs.

Github Test Reporter by CTRF 💚

@GeWuYou GeWuYou merged commit c01abac into main May 6, 2026
7 checks passed
@GeWuYou GeWuYou deleted the feat/ai-first-config branch May 6, 2026 01:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant