docs(config): 添加游戏内容配置系统完整文档与验证工具实现#207
Conversation
- 新增游戏内容配置系统详细文档,涵盖 YAML 配置、JSON Schema 结构、目录组织等核心概念 - 实现配置验证工具,支持运行时校验、类型检查、引用验证等功能 - 提供完整的接入模板,包括项目结构、CSProj 配置、启动帮助器等推荐实践 - 集成 VS Code 插件支持,提供配置浏览、表单编辑、递归校验等开发期工具能力 - 实现热重载机制,支持开发期配置文件变更自动刷新运行时表 - 添加详细的 Schema 示例和 YAML 示例,展示怪物、物品等游戏内容配置的实际应用 - 提供 Architecture 接入模板,支持与现有架构的无缝集成 - 实现跨表引用校验,确保配置数据的一致性和完整性
Reviewer's Guide在 YAML 运行时验证器、Node.js 配置工具、VS Code 扩展、源码生成器和文档中新增对 JSON Schema 运行时 YAML const 校验失败的时序图sequenceDiagram
actor ConfigAuthor
participant YamlConfigLoader
participant YamlConfigSchemaValidator
participant YamlConfigSchemaNode
participant ConfigRegistry
ConfigAuthor->>YamlConfigLoader: Call LoadAsync(registry)
YamlConfigLoader->>YamlConfigSchemaValidator: Parse schema JSON
YamlConfigSchemaValidator->>YamlConfigSchemaValidator: ParseConstantValue for field with const
YamlConfigSchemaValidator->>YamlConfigSchemaNode: WithConstantValue(new YamlConfigConstantValue)
YamlConfigLoader->>YamlConfigSchemaValidator: Validate YAML document
loop For each YAML node
YamlConfigSchemaValidator->>YamlConfigSchemaValidator: BuildComparableNodeValue(node, schemaNode)
YamlConfigSchemaValidator->>YamlConfigSchemaValidator: ValidateConstantValue(tableName, yamlPath, displayPath, node, schemaNode)
YamlConfigSchemaValidator-->>YamlConfigSchemaValidator: Compare with schemaNode.ConstantValue.ComparableValue
end
alt Comparable value matches const
YamlConfigSchemaValidator-->>YamlConfigLoader: Node accepted
YamlConfigLoader->>ConfigRegistry: Register row
YamlConfigLoader-->>ConfigAuthor: LoadAsync completes
else Comparable value does not match const
YamlConfigSchemaValidator-->>YamlConfigLoader: Throw ConfigLoadException
YamlConfigLoader-->>ConfigAuthor: LoadAsync faulted with ConfigLoadException
ConfigAuthor-->>ConfigAuthor: Inspect message mentioning constant value
end
YAML 模式常量值支持的类图classDiagram
class YamlConfigSchemaNode {
+YamlConfigSchemaPropertyType NodeType
+YamlConfigConstantValue ConstantValue
+string SchemaPathHint
+YamlConfigArrayConstraints ArrayConstraints
+YamlConfigObjectConstraints ObjectConstraints
+string ReferenceTableName
+IReadOnlyCollection~string~ AllowedValues
+YamlConfigSchemaNode WithReferenceTable(string referenceTableName)
+YamlConfigSchemaNode WithConstantValue(YamlConfigConstantValue constantValue)
+static YamlConfigSchemaNode CreateObject(IReadOnlyDictionary~string,YamlConfigSchemaNode~ properties, IReadOnlyCollection~string~ requiredProperties, YamlConfigObjectConstraints objectConstraints, string schemaPathHint)
+static YamlConfigSchemaNode CreateArray(YamlConfigSchemaNode itemNode, YamlConfigArrayConstraints arrayConstraints, string schemaPathHint)
+static YamlConfigSchemaNode CreateScalar(YamlConfigSchemaPropertyType nodeType, string referenceTableName, IReadOnlyCollection~string~ allowedValues, YamlConfigScalarConstraints constraints, string schemaPathHint)
}
class YamlConfigConstantValue {
+YamlConfigConstantValue(string comparableValue, string displayValue)
+string ComparableValue
+string DisplayValue
}
class YamlConfigSchemaValidator {
+YamlConfigSchemaNode ParseObjectNode(string tableName, string schemaPath, string propertyPath, JsonElement element)
+YamlConfigSchemaNode ParseArrayNode(string tableName, string schemaPath, string propertyPath, JsonElement element)
+YamlConfigSchemaNode CreateScalarNode(string tableName, string schemaPath, string propertyPath, JsonElement element, YamlConfigSchemaPropertyType nodeType, string referenceTableName)
-YamlConfigConstantValue ParseConstantValue(string tableName, string schemaPath, string propertyPath, JsonElement element, YamlConfigSchemaNode schemaNode)
-string BuildComparableConstantValue(string tableName, string schemaPath, string propertyPath, string keywordName, JsonElement element, YamlConfigSchemaNode schemaNode)
-string BuildComparableConstantObjectValue(string tableName, string schemaPath, string propertyPath, string keywordName, JsonElement element, YamlConfigSchemaNode schemaNode)
-string BuildComparableConstantArrayValue(string tableName, string schemaPath, string propertyPath, string keywordName, JsonElement element, YamlConfigSchemaNode schemaNode)
-string BuildComparableConstantScalarValue(string tableName, string schemaPath, string propertyPath, string keywordName, JsonElement element, YamlConfigSchemaNode schemaNode)
-string NormalizeKeywordScalarValue(string tableName, string schemaPath, string propertyPath, string keywordName, YamlConfigSchemaPropertyType expectedType, JsonElement item)
-void ValidateConstantValue(string tableName, string yamlPath, string displayPath, YamlNode node, YamlConfigSchemaNode schemaNode)
-string BuildComparableNodeValue(YamlNode node, YamlConfigSchemaNode schemaNode)
}
class NodeValidation {
+string ReferenceTableName
+IReadOnlyCollection~string~ AllowedValues
+YamlConfigScalarConstraints Constraints
+YamlConfigArrayConstraints ArrayConstraints
+YamlConfigObjectConstraints ObjectConstraints
+YamlConfigConstantValue ConstantValue
+NodeValidation WithReferenceTable(string referenceTableName)
+NodeValidation WithConstantValue(YamlConfigConstantValue constantValue)
}
YamlConfigSchemaNode o-- NodeValidation : encapsulates
YamlConfigSchemaNode o-- YamlConfigConstantValue : holds
YamlConfigSchemaValidator ..> YamlConfigSchemaNode : creates and validates
YamlConfigSchemaValidator ..> YamlConfigConstantValue : parses
YamlConfigSchemaValidator ..> NodeValidation : uses
Node.js 工具链中 const 元数据与校验的流程图flowchart TD
A[Load JSON Schema file] --> B[parseSchemaNode for root]
B --> C[For each property
parseSchemaNode]
C --> D[applyConstMetadata
with raw const]
D --> E[formatSchemaConstEditableValue
-> constValue]
D --> F[formatSchemaConstDisplayValue
-> constDisplayValue]
D --> G[buildSchemaConstComparableValue
-> constComparableValue]
G --> G1{schemaNode.type}
G1 -->|object| H[buildSchemaConstObjectComparableValue
validate shape
normalize child values
sort keys
join key=value segments]
G1 -->|array| I[buildSchemaConstArrayComparableValue
validate array
normalize each item
preserve order]
G1 -->|scalar| J[buildSchemaConstScalarComparableValue
normalizeSchemaConstScalarValue
prefix with type and length]
E --> K[SchemaNode has
constValue]
F --> K
G --> K
subgraph Validation
L[validateNode
per YAML node] --> M[validateConstComparableValue]
M --> N{schemaNode.constComparableValue
is defined}
N -->|no| O[Skip const check]
N -->|yes| P[buildComparableNodeValue
for YAML node]
P --> Q{comparable equal
schema vs YAML}
Q -->|yes| R[Accept node]
Q -->|no| S[Push diagnostic
ValidationMessageKeys.constMismatch
with constDisplayValue or constValue]
end
K --> L
subgraph VS_Code_Form
T[collectFormFields / collectObjectArrayItemFields]
T --> U[getScalarFieldValue
uses constValue or defaultValue]
T --> V[renderFieldHint]
V --> W[webview.hint.const /
webview.hint.itemConst
using constDisplayValue]
end
K --> T
文件级变更
技巧与命令与 Sourcery 交互
自定义体验访问你的 dashboard 以:
获取帮助Original review guide in EnglishReviewer's GuideAdd first-class JSON Schema Sequence diagram for runtime YAML const validation failuresequenceDiagram
actor ConfigAuthor
participant YamlConfigLoader
participant YamlConfigSchemaValidator
participant YamlConfigSchemaNode
participant ConfigRegistry
ConfigAuthor->>YamlConfigLoader: Call LoadAsync(registry)
YamlConfigLoader->>YamlConfigSchemaValidator: Parse schema JSON
YamlConfigSchemaValidator->>YamlConfigSchemaValidator: ParseConstantValue for field with const
YamlConfigSchemaValidator->>YamlConfigSchemaNode: WithConstantValue(new YamlConfigConstantValue)
YamlConfigLoader->>YamlConfigSchemaValidator: Validate YAML document
loop For each YAML node
YamlConfigSchemaValidator->>YamlConfigSchemaValidator: BuildComparableNodeValue(node, schemaNode)
YamlConfigSchemaValidator->>YamlConfigSchemaValidator: ValidateConstantValue(tableName, yamlPath, displayPath, node, schemaNode)
YamlConfigSchemaValidator-->>YamlConfigSchemaValidator: Compare with schemaNode.ConstantValue.ComparableValue
end
alt Comparable value matches const
YamlConfigSchemaValidator-->>YamlConfigLoader: Node accepted
YamlConfigLoader->>ConfigRegistry: Register row
YamlConfigLoader-->>ConfigAuthor: LoadAsync completes
else Comparable value does not match const
YamlConfigSchemaValidator-->>YamlConfigLoader: Throw ConfigLoadException
YamlConfigLoader-->>ConfigAuthor: LoadAsync faulted with ConfigLoadException
ConfigAuthor-->>ConfigAuthor: Inspect message mentioning constant value
end
Class diagram for YAML schema constant value supportclassDiagram
class YamlConfigSchemaNode {
+YamlConfigSchemaPropertyType NodeType
+YamlConfigConstantValue ConstantValue
+string SchemaPathHint
+YamlConfigArrayConstraints ArrayConstraints
+YamlConfigObjectConstraints ObjectConstraints
+string ReferenceTableName
+IReadOnlyCollection~string~ AllowedValues
+YamlConfigSchemaNode WithReferenceTable(string referenceTableName)
+YamlConfigSchemaNode WithConstantValue(YamlConfigConstantValue constantValue)
+static YamlConfigSchemaNode CreateObject(IReadOnlyDictionary~string,YamlConfigSchemaNode~ properties, IReadOnlyCollection~string~ requiredProperties, YamlConfigObjectConstraints objectConstraints, string schemaPathHint)
+static YamlConfigSchemaNode CreateArray(YamlConfigSchemaNode itemNode, YamlConfigArrayConstraints arrayConstraints, string schemaPathHint)
+static YamlConfigSchemaNode CreateScalar(YamlConfigSchemaPropertyType nodeType, string referenceTableName, IReadOnlyCollection~string~ allowedValues, YamlConfigScalarConstraints constraints, string schemaPathHint)
}
class YamlConfigConstantValue {
+YamlConfigConstantValue(string comparableValue, string displayValue)
+string ComparableValue
+string DisplayValue
}
class YamlConfigSchemaValidator {
+YamlConfigSchemaNode ParseObjectNode(string tableName, string schemaPath, string propertyPath, JsonElement element)
+YamlConfigSchemaNode ParseArrayNode(string tableName, string schemaPath, string propertyPath, JsonElement element)
+YamlConfigSchemaNode CreateScalarNode(string tableName, string schemaPath, string propertyPath, JsonElement element, YamlConfigSchemaPropertyType nodeType, string referenceTableName)
-YamlConfigConstantValue ParseConstantValue(string tableName, string schemaPath, string propertyPath, JsonElement element, YamlConfigSchemaNode schemaNode)
-string BuildComparableConstantValue(string tableName, string schemaPath, string propertyPath, string keywordName, JsonElement element, YamlConfigSchemaNode schemaNode)
-string BuildComparableConstantObjectValue(string tableName, string schemaPath, string propertyPath, string keywordName, JsonElement element, YamlConfigSchemaNode schemaNode)
-string BuildComparableConstantArrayValue(string tableName, string schemaPath, string propertyPath, string keywordName, JsonElement element, YamlConfigSchemaNode schemaNode)
-string BuildComparableConstantScalarValue(string tableName, string schemaPath, string propertyPath, string keywordName, JsonElement element, YamlConfigSchemaNode schemaNode)
-string NormalizeKeywordScalarValue(string tableName, string schemaPath, string propertyPath, string keywordName, YamlConfigSchemaPropertyType expectedType, JsonElement item)
-void ValidateConstantValue(string tableName, string yamlPath, string displayPath, YamlNode node, YamlConfigSchemaNode schemaNode)
-string BuildComparableNodeValue(YamlNode node, YamlConfigSchemaNode schemaNode)
}
class NodeValidation {
+string ReferenceTableName
+IReadOnlyCollection~string~ AllowedValues
+YamlConfigScalarConstraints Constraints
+YamlConfigArrayConstraints ArrayConstraints
+YamlConfigObjectConstraints ObjectConstraints
+YamlConfigConstantValue ConstantValue
+NodeValidation WithReferenceTable(string referenceTableName)
+NodeValidation WithConstantValue(YamlConfigConstantValue constantValue)
}
YamlConfigSchemaNode o-- NodeValidation : encapsulates
YamlConfigSchemaNode o-- YamlConfigConstantValue : holds
YamlConfigSchemaValidator ..> YamlConfigSchemaNode : creates and validates
YamlConfigSchemaValidator ..> YamlConfigConstantValue : parses
YamlConfigSchemaValidator ..> NodeValidation : uses
Flow diagram for Node.js tooling const metadata and validationflowchart TD
A[Load JSON Schema file] --> B[parseSchemaNode for root]
B --> C[For each property
parseSchemaNode]
C --> D[applyConstMetadata
with raw const]
D --> E[formatSchemaConstEditableValue
-> constValue]
D --> F[formatSchemaConstDisplayValue
-> constDisplayValue]
D --> G[buildSchemaConstComparableValue
-> constComparableValue]
G --> G1{schemaNode.type}
G1 -->|object| H[buildSchemaConstObjectComparableValue
validate shape
normalize child values
sort keys
join key=value segments]
G1 -->|array| I[buildSchemaConstArrayComparableValue
validate array
normalize each item
preserve order]
G1 -->|scalar| J[buildSchemaConstScalarComparableValue
normalizeSchemaConstScalarValue
prefix with type and length]
E --> K[SchemaNode has
constValue]
F --> K
G --> K
subgraph Validation
L[validateNode
per YAML node] --> M[validateConstComparableValue]
M --> N{schemaNode.constComparableValue
is defined}
N -->|no| O[Skip const check]
N -->|yes| P[buildComparableNodeValue
for YAML node]
P --> Q{comparable equal
schema vs YAML}
Q -->|yes| R[Accept node]
Q -->|no| S[Push diagnostic
ValidationMessageKeys.constMismatch
with constDisplayValue or constValue]
end
K --> L
subgraph VS_Code_Form
T[collectFormFields / collectObjectArrayItemFields]
T --> U[getScalarFieldValue
uses constValue or defaultValue]
T --> V[renderFieldHint]
V --> W[webview.hint.const /
webview.hint.itemConst
using constDisplayValue]
end
K --> T
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
📝 WalkthroughWalkthrough在运行时、源生成器与工具链中引入并验证 JSON Schema 的 Changes
Sequence Diagram(s)sequenceDiagram
participant Schema as "Schema (file/Generator)"
participant Generator as "Source Generator"
participant Tool as "VSCode Tool"
participant Loader as "Yaml Loader"
participant Validator as "Runtime Validator"
participant Registry as "Config Registry"
Schema->>Generator: 提供含 `const` 的模式
Generator->>Schema: 在生成文档/注释中输出 `const` 描述
Schema->>Tool: 导出 `constValue`/`constDisplayValue`/`constComparableValue`
Tool->>Tool: 渲染字段提示、样例 YAML(优先显示/生成 const)
Loader->>Validator: 加载 YAML,逐节点执行验证(包含 const 检查)
Validator-->>Loader: 返回验证通过或抛出 ConstraintViolation(含路径与显示值)
Loader->>Registry: 仅在验证通过时写入配置注册表
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Hey - 我发现了 3 个问题,并留下了一些高层次的反馈:
- 在 VS Code 工具中,
collectFormFields和collectObjectArrayItemFields将propertySchema.constValue || propertySchema.defaultValue传给getScalarFieldValue,这样一来,一个合法的空字符串const会被忽略,而优先使用default。建议把constValue和defaultValue分开传入,或者显式检查是否为undefined而不是用||,以便保留空字符串常量。 - 在
BuildComparableConstantValue(C#)中,default分支会对不支持的节点类型抛出InvalidOperationException,这会在运行时表现为内部错误;建议将其改为抛出带有SchemaUnsupported的ConfigLoadException,这样当在不支持的类型上使用const时,schema 作者可以获得一致且可诊断的错误。 - 运行时时(C# 中的
BuildComparableConstant*)和工具侧(JS 中的buildSchemaConst*)都各自实现了一套 const 归一化/可比较键逻辑;可以考虑加上醒目的注释说明这两条路径必须保持同步,或者把共享规则抽出到一个小的规范 helper 中,以减少只在一侧修改时产生偏离的风险。
给 AI 代理的提示
Please address the comments from this code review:
## Overall Comments
- In the VS Code tooling, `collectFormFields` and `collectObjectArrayItemFields` pass `propertySchema.constValue || propertySchema.defaultValue` into `getScalarFieldValue`, so a valid empty-string `const` will be ignored in favor of `default`; consider passing `constValue` and `defaultValue` separately or checking explicitly for `undefined` instead of using `||` so empty-string constants are preserved.
- In `BuildComparableConstantValue` (C#) the default branch throws `InvalidOperationException` for unsupported node types, which will surface as an internal error at runtime; consider converting this into a `ConfigLoadException` with `SchemaUnsupported` so schema authors get a consistent, diagnosable error when `const` is used on an unsupported type.
- Both the runtime (`BuildComparableConstant*` in C#) and the tooling (`buildSchemaConst*` in JS) implement their own const normalization/comparable-key logic; it may be worth adding prominent comments that these two paths must stay in sync or factoring shared rules into a small spec helper to reduce the risk of divergence when one side is modified.
## Individual Comments
### Comment 1
<location path="tools/gframework-config-tool/src/configValidation.js" line_range="570" />
<code_context>
+ objectEntries.push([key, childComparableValue]);
+ }
+
+ objectEntries.sort((left, right) => left[0].localeCompare(right[0]));
+ return objectEntries.map(([key, value]) => `${key.length}:${key}=${value.length}:${value}`).join("|");
+}
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Use a locale-independent sort for const object key normalization.
The current use of `localeCompare` makes ordering dependent on the runtime locale and is slower than a simple ordinal comparison. For deterministic behavior across environments (and to match `string.CompareOrdinal` on the C# side), switch to a locale-independent comparison, e.g. comparing `left[0]` and `right[0]` directly or via `codePointAt(0)` and returning -1/0/1 accordingly.
```suggestion
objectEntries.sort((left, right) => {
if (left[0] < right[0]) {
return -1;
}
if (left[0] > right[0]) {
return 1;
}
return 0;
});
```
</issue_to_address>
### Comment 2
<location path="tools/gframework-config-tool/test/configValidation.test.js" line_range="68-77" />
<code_context>
+test("parseSchemaContent should capture const metadata for scalar, object, and array nodes", () => {
</code_context>
<issue_to_address>
**suggestion (testing):** Complement const metadata tests with coverage for comparable values and successful validation.
These tests confirm parsing and mismatch reporting, but we’re missing validation-side coverage. Please add: (1) a case where YAML matches scalar/object/array const values and `validateParsedConfig` yields no diagnostics; (2) a case that asserts `schemaNode.constComparableValue` is set and that `validateParsedConfig` respects the same normalization as `buildComparableNodeValue` (e.g., object key reordering and array order behavior); and (3) numeric and boolean const cases to exercise `normalizeSchemaConstScalarValue` (e.g., integer vs non-integer and boolean type mismatches).
Suggested implementation:
```javascript
test("parseSchemaContent should capture const metadata for scalar, object, and array nodes", () => {
const schema = parseSchemaContent(`
{
"type": "object",
"properties": {
"rarity": {
"type": "string",
"const": "common"
},
"reward": {
"type": "object",
"const": {
"gold": 100,
"items": [
"potion",
"sword"
]
}
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"const": [
"daily",
"quest"
]
},
"maxAttempts": {
"type": "integer",
"const": 3
},
"allowRetry": {
"type": "boolean",
"const": true
}
}
}
`);
const rarityNode = schema.properties.rarity;
assert.strictEqual(rarityNode.const, "common");
assert.ok(
rarityNode.constComparableValue,
"scalar const should have constComparableValue"
);
const rewardNode = schema.properties.reward;
assert.deepEqual(rewardNode.const, {
gold: 100,
items: ["potion", "sword"],
});
assert.ok(
rewardNode.constComparableValue,
"object const should have constComparableValue"
);
// Object key order should not affect constComparableValue
const reorderedRewardComparable = buildComparableNodeValue({
items: ["potion", "sword"],
gold: 100,
});
assert.deepEqual(
rewardNode.constComparableValue,
reorderedRewardComparable,
"object constComparableValue should be key-order-insensitive",
);
const tagsNode = schema.properties.tags;
assert.deepEqual(tagsNode.const, ["daily", "quest"]);
assert.ok(
tagsNode.constComparableValue,
"array const should have constComparableValue"
);
const maxAttemptsNode = schema.properties.maxAttempts;
assert.strictEqual(maxAttemptsNode.const, 3);
assert.ok(
maxAttemptsNode.constComparableValue,
"numeric const should have constComparableValue"
);
const allowRetryNode = schema.properties.allowRetry;
assert.strictEqual(allowRetryNode.const, true);
assert.ok(
allowRetryNode.constComparableValue,
"boolean const should have constComparableValue"
);
});
```
To fully implement your review comment, the following additional changes should be made elsewhere in the same test file, matching the existing testing conventions:
1. **Add a validation-success test** that uses the above schema and a YAML config whose values exactly match the scalar, object, array, numeric, and boolean const values:
- Parse the same schema via `parseSchemaContent`.
- Parse a YAML document (using the same helper the file already uses, e.g. `parseConfigContent` or equivalent).
- Call `validateParsedConfig(schema, parsedConfig, /* path/ctx as used in other tests */)`.
- Assert that the returned diagnostics array is empty (or that no diagnostics have `severity === "error"`, depending on existing conventions).
2. **Add a normalization/comparable-value validation test**:
- Use a schema with an object const like the `reward` node above and an array const like `tags`.
- Provide a YAML config where the object keys are in a different order (e.g. `{ items: ["potion", "sword"], gold: 100 }`) and the array is in the same order as the const.
- Call `validateParsedConfig` and assert that there are **no** const-mismatch diagnostics, demonstrating that `validateParsedConfig` uses the same normalization behavior as `buildComparableNodeValue`.
- Optionally, also include a negative case (e.g. array with different order/contents) and assert that `validateParsedConfig` reports a const mismatch diagnostic.
3. **Add numeric and boolean const validation tests** to exercise `normalizeSchemaConstScalarValue` through the validation path:
- A matching case: integer const vs integer YAML value, boolean const vs boolean YAML value → no diagnostics.
- A mismatching numeric case: schema `{"type": "integer", "const": 3}` vs YAML `3.5` or `"3"` → expect a const-mismatch diagnostic.
- A mismatching boolean case: schema `{"type": "boolean", "const": true}` vs YAML `"true"` or `0` → expect a const-mismatch diagnostic.
- Structure the assertions (diagnostic codes/messages, node paths) consistently with how other diagnostics are asserted in this file.
When adding these tests, reuse helper functions already imported in `configValidation.test.js` (e.g. schema/config parsing helpers, diagnostic helpers) and follow the same assertion style (`assert.deepEqual`, helper-based filtering of diagnostics, etc.) that the existing validation tests use.
</issue_to_address>
### Comment 3
<location path="tools/gframework-config-tool/test/configValidation.test.js" line_range="86" />
<code_context>
* @returns {string} Sample scalar value.
*/
function getSampleScalarValue(schemaNode) {
+ if (schemaNode.constValue !== undefined) {
+ return schemaNode.constValue;
+ }
+
if (schemaNode.defaultValue !== undefined) {
</code_context>
<issue_to_address>
**suggestion (testing):** Add a test to verify getSampleScalarValue prefers const over default.
`getSampleScalarValue` now prefers `schemaNode.constValue` over `defaultValue`, but there’s no test capturing this behavior. Please add a unit test with a scalar field that has both `const` and `default` and assert that the sample value/placeholder uses `const`. This will help prevent regressions where the UI diverges from the runtime `const` semantics.
</issue_to_address>帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进以后的评审。
Original comment in English
Hey - I've found 3 issues, and left some high level feedback:
- In the VS Code tooling,
collectFormFieldsandcollectObjectArrayItemFieldspasspropertySchema.constValue || propertySchema.defaultValueintogetScalarFieldValue, so a valid empty-stringconstwill be ignored in favor ofdefault; consider passingconstValueanddefaultValueseparately or checking explicitly forundefinedinstead of using||so empty-string constants are preserved. - In
BuildComparableConstantValue(C#) the default branch throwsInvalidOperationExceptionfor unsupported node types, which will surface as an internal error at runtime; consider converting this into aConfigLoadExceptionwithSchemaUnsupportedso schema authors get a consistent, diagnosable error whenconstis used on an unsupported type. - Both the runtime (
BuildComparableConstant*in C#) and the tooling (buildSchemaConst*in JS) implement their own const normalization/comparable-key logic; it may be worth adding prominent comments that these two paths must stay in sync or factoring shared rules into a small spec helper to reduce the risk of divergence when one side is modified.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In the VS Code tooling, `collectFormFields` and `collectObjectArrayItemFields` pass `propertySchema.constValue || propertySchema.defaultValue` into `getScalarFieldValue`, so a valid empty-string `const` will be ignored in favor of `default`; consider passing `constValue` and `defaultValue` separately or checking explicitly for `undefined` instead of using `||` so empty-string constants are preserved.
- In `BuildComparableConstantValue` (C#) the default branch throws `InvalidOperationException` for unsupported node types, which will surface as an internal error at runtime; consider converting this into a `ConfigLoadException` with `SchemaUnsupported` so schema authors get a consistent, diagnosable error when `const` is used on an unsupported type.
- Both the runtime (`BuildComparableConstant*` in C#) and the tooling (`buildSchemaConst*` in JS) implement their own const normalization/comparable-key logic; it may be worth adding prominent comments that these two paths must stay in sync or factoring shared rules into a small spec helper to reduce the risk of divergence when one side is modified.
## Individual Comments
### Comment 1
<location path="tools/gframework-config-tool/src/configValidation.js" line_range="570" />
<code_context>
+ objectEntries.push([key, childComparableValue]);
+ }
+
+ objectEntries.sort((left, right) => left[0].localeCompare(right[0]));
+ return objectEntries.map(([key, value]) => `${key.length}:${key}=${value.length}:${value}`).join("|");
+}
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Use a locale-independent sort for const object key normalization.
The current use of `localeCompare` makes ordering dependent on the runtime locale and is slower than a simple ordinal comparison. For deterministic behavior across environments (and to match `string.CompareOrdinal` on the C# side), switch to a locale-independent comparison, e.g. comparing `left[0]` and `right[0]` directly or via `codePointAt(0)` and returning -1/0/1 accordingly.
```suggestion
objectEntries.sort((left, right) => {
if (left[0] < right[0]) {
return -1;
}
if (left[0] > right[0]) {
return 1;
}
return 0;
});
```
</issue_to_address>
### Comment 2
<location path="tools/gframework-config-tool/test/configValidation.test.js" line_range="68-77" />
<code_context>
+test("parseSchemaContent should capture const metadata for scalar, object, and array nodes", () => {
</code_context>
<issue_to_address>
**suggestion (testing):** Complement const metadata tests with coverage for comparable values and successful validation.
These tests confirm parsing and mismatch reporting, but we’re missing validation-side coverage. Please add: (1) a case where YAML matches scalar/object/array const values and `validateParsedConfig` yields no diagnostics; (2) a case that asserts `schemaNode.constComparableValue` is set and that `validateParsedConfig` respects the same normalization as `buildComparableNodeValue` (e.g., object key reordering and array order behavior); and (3) numeric and boolean const cases to exercise `normalizeSchemaConstScalarValue` (e.g., integer vs non-integer and boolean type mismatches).
Suggested implementation:
```javascript
test("parseSchemaContent should capture const metadata for scalar, object, and array nodes", () => {
const schema = parseSchemaContent(`
{
"type": "object",
"properties": {
"rarity": {
"type": "string",
"const": "common"
},
"reward": {
"type": "object",
"const": {
"gold": 100,
"items": [
"potion",
"sword"
]
}
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"const": [
"daily",
"quest"
]
},
"maxAttempts": {
"type": "integer",
"const": 3
},
"allowRetry": {
"type": "boolean",
"const": true
}
}
}
`);
const rarityNode = schema.properties.rarity;
assert.strictEqual(rarityNode.const, "common");
assert.ok(
rarityNode.constComparableValue,
"scalar const should have constComparableValue"
);
const rewardNode = schema.properties.reward;
assert.deepEqual(rewardNode.const, {
gold: 100,
items: ["potion", "sword"],
});
assert.ok(
rewardNode.constComparableValue,
"object const should have constComparableValue"
);
// Object key order should not affect constComparableValue
const reorderedRewardComparable = buildComparableNodeValue({
items: ["potion", "sword"],
gold: 100,
});
assert.deepEqual(
rewardNode.constComparableValue,
reorderedRewardComparable,
"object constComparableValue should be key-order-insensitive",
);
const tagsNode = schema.properties.tags;
assert.deepEqual(tagsNode.const, ["daily", "quest"]);
assert.ok(
tagsNode.constComparableValue,
"array const should have constComparableValue"
);
const maxAttemptsNode = schema.properties.maxAttempts;
assert.strictEqual(maxAttemptsNode.const, 3);
assert.ok(
maxAttemptsNode.constComparableValue,
"numeric const should have constComparableValue"
);
const allowRetryNode = schema.properties.allowRetry;
assert.strictEqual(allowRetryNode.const, true);
assert.ok(
allowRetryNode.constComparableValue,
"boolean const should have constComparableValue"
);
});
```
To fully implement your review comment, the following additional changes should be made elsewhere in the same test file, matching the existing testing conventions:
1. **Add a validation-success test** that uses the above schema and a YAML config whose values exactly match the scalar, object, array, numeric, and boolean const values:
- Parse the same schema via `parseSchemaContent`.
- Parse a YAML document (using the same helper the file already uses, e.g. `parseConfigContent` or equivalent).
- Call `validateParsedConfig(schema, parsedConfig, /* path/ctx as used in other tests */)`.
- Assert that the returned diagnostics array is empty (or that no diagnostics have `severity === "error"`, depending on existing conventions).
2. **Add a normalization/comparable-value validation test**:
- Use a schema with an object const like the `reward` node above and an array const like `tags`.
- Provide a YAML config where the object keys are in a different order (e.g. `{ items: ["potion", "sword"], gold: 100 }`) and the array is in the same order as the const.
- Call `validateParsedConfig` and assert that there are **no** const-mismatch diagnostics, demonstrating that `validateParsedConfig` uses the same normalization behavior as `buildComparableNodeValue`.
- Optionally, also include a negative case (e.g. array with different order/contents) and assert that `validateParsedConfig` reports a const mismatch diagnostic.
3. **Add numeric and boolean const validation tests** to exercise `normalizeSchemaConstScalarValue` through the validation path:
- A matching case: integer const vs integer YAML value, boolean const vs boolean YAML value → no diagnostics.
- A mismatching numeric case: schema `{"type": "integer", "const": 3}` vs YAML `3.5` or `"3"` → expect a const-mismatch diagnostic.
- A mismatching boolean case: schema `{"type": "boolean", "const": true}` vs YAML `"true"` or `0` → expect a const-mismatch diagnostic.
- Structure the assertions (diagnostic codes/messages, node paths) consistently with how other diagnostics are asserted in this file.
When adding these tests, reuse helper functions already imported in `configValidation.test.js` (e.g. schema/config parsing helpers, diagnostic helpers) and follow the same assertion style (`assert.deepEqual`, helper-based filtering of diagnostics, etc.) that the existing validation tests use.
</issue_to_address>
### Comment 3
<location path="tools/gframework-config-tool/test/configValidation.test.js" line_range="86" />
<code_context>
* @returns {string} Sample scalar value.
*/
function getSampleScalarValue(schemaNode) {
+ if (schemaNode.constValue !== undefined) {
+ return schemaNode.constValue;
+ }
+
if (schemaNode.defaultValue !== undefined) {
</code_context>
<issue_to_address>
**suggestion (testing):** Add a test to verify getSampleScalarValue prefers const over default.
`getSampleScalarValue` now prefers `schemaNode.constValue` over `defaultValue`, but there’s no test capturing this behavior. Please add a unit test with a scalar field that has both `const` and `default` and assert that the sample value/placeholder uses `const`. This will help prevent regressions where the UI diverges from the runtime `const` semantics.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Greptile SummaryThis PR adds first-class support for JSON Schema Key changes:
Confidence Score: 4/5Safe to merge; no correctness or security issues — three P2 style suggestions remain. The prior review concern about localeCompare vs ordinal sort has been fully resolved by compareStringsOrdinal. The C# and JS comparable-key formats are aligned, the early-return ordering in scalar validation correctly prevents double-reporting, and both runtimes share the same comparison semantics. Test coverage is comprehensive across all three node types. The three P2 comments are non-blocking polish items. tools/gframework-config-tool/test/configValidation.test.js — integer const mismatch code path is not directly exercised; GFramework.Game/Config/YamlConfigSchemaValidator.cs — minor constructor guard semantics. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Schema JSON loaded] --> B[ParseConstantValue]
B --> C{const declared?}
C -->|No| D[ConstantValue is null - skip]
C -->|Yes| E[BuildComparableConstantValue]
E --> F{Node type?}
F -->|scalar| G[NormalizeKeywordScalarValue - format: type-len-value]
F -->|array| H[Ordered item list - format: bracket-len-item-comma]
F -->|object| I[Sort keys by CompareOrdinal - format: keyLen-key-valueLen-value pipe-sep]
G --> J[YamlConfigConstantValue stored on SchemaNode]
H --> J
I --> J
J --> L[YAML file loaded for validation]
L --> M[Type and structural checks run first]
M -->|type mismatch| N[Early return - const check skipped]
M -->|type ok| P[ValidateConstantValue called]
P --> Q[BuildComparableNodeValue on YAML node]
Q --> R{Ordinal equals ComparableValue?}
R -->|Yes| S[Validation passes]
R -->|No| T[Throw ConstraintViolation with DisplayValue]
Reviews (3): Last reviewed commit: "docs(config): 添加AI代理编码行为规范和配置验证工具测试" | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (1)
GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs (1)
366-410: 补齐Diagnostic断言,避免只测消息文本。这三组
const用例现在主要校验Message子串;如果后续仍然抛出ConfigLoadException,但FailureKind、DisplayPath或RawValue回归,测试还是会通过。建议像同文件其它约束测试一样,把这些结构化诊断字段也断言住,这样const的错误契约才算真正被固定下来。
Based on learnings Public API changes must be covered by unit or integration tests.Also applies to: 1247-1297, 1349-1404
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs` around lines 366 - 410, The test LoadAsync_Should_Throw_When_Scalar_Value_Does_Not_Match_Schema_Const only asserts exception message substrings; update it to also assert the structured Diagnostic fields on the thrown ConfigLoadException (e.g. check exception.Diagnostics or the Diagnostic object for FailureKind, DisplayPath and RawValue) so the contract for const failures is fixed; locate the assertion block after Assert.ThrowsAsync for ConfigLoadException and add assertions that FailureKind equals the expected kind (e.g. ConstantMismatch), DisplayPath points to "monster/rarity" (or the schema path used), and RawValue equals "rare" (the actual bad value) and still assert registry.Count == 0; apply the same pattern to the other const-related tests mentioned.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@GFramework.Game/Config/YamlConfigSchemaValidator.cs`:
- Around line 2924-2931: The constructor YamlConfigConstantValue(string
comparableValue, string displayValue) rejects empty strings via
ArgumentException.ThrowIfNullOrWhiteSpace, which fails for legal JSON Schema
const: {} that yields an empty comparable/display value; change the validation
to only guard against null (e.g., use ArgumentNullException.ThrowIfNull or
ArgumentException.ThrowIfNull) for both comparableValue and displayValue so
empty strings are accepted, leaving the assignments to ComparableValue and
DisplayValue unchanged.
- Around line 991-995: The sorting of object property keys in
YamlConfigSchemaValidator currently uses string.CompareOrdinal, which can
produce different orders than the JS toolchain's localeCompare; to ensure
deterministic, cross-platform comparable keys, change the sort to use
StringComparer.Ordinal explicitly (e.g., objectEntries.Sort((l,r) =>
StringComparer.Ordinal.Compare(l.Key, r.Key)) ) and add a validation step in
YamlConfigSchemaValidator that rejects or normalizes non-ASCII/non-normalized
property names (or emit a clear error) so runtime C# ordering always matches the
expected ordinal ordering used by the tooling.
In `@GFramework.SourceGenerators/Config/SchemaConfigGenerator.cs`:
- Around line 2455-2458: The code in SchemaConfigGenerator.cs currently skips
adding the const constraint when constDocumentation is an empty or whitespace
string because it uses string.IsNullOrWhiteSpace; update the check to only test
for null (e.g., constDocumentation != null) so an explicit empty string is
preserved, and adjust the appended text added to parts (the parts.Add call that
references constDocumentation) so the generated doc clearly represents
empty-string constants (for example include quotes around the value when
building the "const = ..." entry) — locate the constDocumentation variable and
the parts.Add(...) call in the SchemaConfigGenerator class and change the
condition and formatting accordingly.
In `@tools/gframework-config-tool/src/configValidation.js`:
- Around line 464-505: formatSchemaConstValue currently returns raw string
values (String(value)), causing diagnostic displays to lose JSON quoting for
string consts; update formatSchemaConstValue so that string consts are
JSON-serialized (return JSON.stringify(value) for typeof value === "string") so
that applyConstMetadata's constValue preserves JSON-style representation, while
constComparableValue continues to be produced by
buildSchemaConstComparableValue; adjust only formatSchemaConstValue (referenced
by applyConstMetadata, constValue, and buildSchemaConstComparableValue) to
ensure string consts are shown as quoted JSON in diagnostics.
- Around line 551-571: The comparator uses String.prototype.localeCompare which
yields culture-dependent ordering; change it to an ordinal (code-unit)
comparison so ordering matches the C# runtime. In
buildSchemaConstObjectComparableValue replace
objectEntries.sort((left,right)=>left[0].localeCompare(right[0])) with an
ordinal comparator such as objectEntries.sort((l,r)=> l[0] === r[0] ? 0 : l[0] <
r[0] ? -1 : 1). Make the same change in buildComparableNodeValue and
buildSchemaPropertiesComparable where keys are sorted so all JS sorts use the
same ordinal (a<b ? -1 : a> b ? 1 : 0) semantics as C# string.CompareOrdinal.
In `@tools/gframework-config-tool/src/extension.js`:
- Line 1375: The code uses truthy checks and || fallbacks that treat
empty-string const values as absent; update usages around
getScalarFieldValue(propertyValue, propertySchema.constValue ||
propertySchema.defaultValue) and other spots referencing
propertySchema.constValue or constValue to use nullish coalescing (??) instead
of ||, and replace truthy checks like if (constValue) with explicit !==
undefined checks (or constValue !== undefined && constValue !== null where
appropriate) so that const: "" is preserved for initial values and validation;
apply these fixes to the occurrences noted (around getScalarFieldValue, and the
blocks at the other listed lines).
---
Nitpick comments:
In `@GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs`:
- Around line 366-410: The test
LoadAsync_Should_Throw_When_Scalar_Value_Does_Not_Match_Schema_Const only
asserts exception message substrings; update it to also assert the structured
Diagnostic fields on the thrown ConfigLoadException (e.g. check
exception.Diagnostics or the Diagnostic object for FailureKind, DisplayPath and
RawValue) so the contract for const failures is fixed; locate the assertion
block after Assert.ThrowsAsync for ConfigLoadException and add assertions that
FailureKind equals the expected kind (e.g. ConstantMismatch), DisplayPath points
to "monster/rarity" (or the schema path used), and RawValue equals "rare" (the
actual bad value) and still assert registry.Count == 0; apply the same pattern
to the other const-related tests mentioned.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 12010b93-35f2-4c33-a00a-33be48311b49
📒 Files selected for processing (11)
GFramework.Game.Tests/Config/YamlConfigLoaderTests.csGFramework.Game/Config/YamlConfigSchemaValidator.csGFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorSnapshotTests.csGFramework.SourceGenerators.Tests/Config/snapshots/SchemaConfigGenerator/MonsterConfig.g.txtGFramework.SourceGenerators/Config/SchemaConfigGenerator.csdocs/zh-CN/game/config-system.mdtools/gframework-config-tool/src/configValidation.jstools/gframework-config-tool/src/extension.jstools/gframework-config-tool/src/localization.jstools/gframework-config-tool/src/localizationKeys.jstools/gframework-config-tool/test/configValidation.test.js
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Sourcery review
- GitHub Check: Code Quality & Security
- GitHub Check: Build and Test
- GitHub Check: Analyze (C#)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.cs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.cs: LoggerGenerator must automatically generate log fields and logging helper methods for classes decorated with [Log] attribute
PriorityGenerator must generate priority comparison implementations for classes decorated with [Priority] attribute
EnumExtensionsGenerator must generate enum extension capabilities for enums decorated with [GenerateEnumExtensions] attribute
ContextAwareGenerator must automatically implement IContextAware boilerplate logic for classes decorated with [ContextAware] attribute
**/*.cs: All public, protected, and internal types and members MUST include XML documentation comments (///) with<summary>,<param>,<returns>,<exception>, and<remarks>tags where applicable
Add inline comments for non-trivial logic, concurrency or threading behavior, performance-sensitive paths, workarounds, compatibility constraints, or edge cases in C# code
Core framework components such as Architecture, Module, System, Context, Registry, Service Module, and Lifecycle types MUST include high-level explanations of responsibilities, lifecycle, interaction with other components, why the abstraction exists, and when to use it instead of alternatives
Generated logic and generator pipelines MUST include comments explaining what is generated, why it is generated, the semantic assumptions the generator relies on, and any diagnostics or fallback behavior
Methods with non-trivial logic MUST document the core idea, key decisions, and edge case handling in C# code
Do not rely on implicit imports; declare every requiredusingexplicitly in C# files
Write null-safe code that respects nullable annotations instead of suppressing warnings by default in C# files
Use the namespace patternGFramework.{Module}.{Feature}with PascalCase segments in C# code
Follow standard C# naming: Types, methods, properties, events, and constants use PascalCase; Interfaces useIprefix; Parameters and locals use camelCase; Private fields use_camelCase
Use 4 spaces for i...
Files:
GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorSnapshotTests.csGFramework.SourceGenerators/Config/SchemaConfigGenerator.csGFramework.Game.Tests/Config/YamlConfigLoaderTests.csGFramework.Game/Config/YamlConfigSchemaValidator.cs
**/*.Tests/**/*.cs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.Tests/**/*.cs: Every non-trivial feature, bug fix, or behavior change MUST include tests or an explicit justification for why a test is not practical
Public API changes must be covered by unit or integration tests
When a public API defines multiple contract branches, tests MUST cover the meaningful variants, including null, empty, default, and filtered inputs when those branches change behavior
Regression fixes should include a test that fails before the fix and passes after it
Mirror the source structure in test projects whenever practical
Reuse existing architecture test infrastructure when relevant:ArchitectureTestsBase<T>,SyncTestArchitecture,AsyncTestArchitecture
Keep tests focused on observable behavior, not implementation trivia
Files:
GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorSnapshotTests.csGFramework.Game.Tests/Config/YamlConfigLoaderTests.cs
**/*.SourceGenerators.Tests/**/*.cs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.SourceGenerators.Tests/**/*.cs: Source generator changes MUST be covered by generator tests
Preserve snapshot-based verification patterns already used in the repository for source generator tests
When generator behavior changes intentionally, update snapshots together with the implementation in source generator tests
Files:
GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorSnapshotTests.cs
docs/**/*
📄 CodeRabbit inference engine (CLAUDE.md)
Documentation must be located in docs/ directory with Chinese content in docs/zh-CN/
Files:
docs/zh-CN/game/config-system.md
{README.md,docs/**/*.md}
📄 CodeRabbit inference engine (AGENTS.md)
Update the relevant
README.mdordocs/page when behavior, setup steps, architecture guidance, or user-facing examples change
Files:
docs/zh-CN/game/config-system.md
docs/**/*.md
📄 CodeRabbit inference engine (AGENTS.md)
docs/**/*.md: Keep code samples, package names, and command examples in documentation aligned with the current repository state
Prefer documenting behavior and design intent, not only API surface, in repository documentation
For integration-oriented features such as the AI-First config system, documentation MUST cover project directory layout and file conventions, required project or package wiring, minimal working usage example, and migration or compatibility notes when behavior changes
If an existing documentation page no longer reflects the current implementation, updating the documentation is part of fixing the code and cannot be deferred
Do not rely on 'the code is self-explanatory' for framework features that consumers need to adopt; write the adoption path down so future users do not need to rediscover it from source
Files:
docs/zh-CN/game/config-system.md
docs/zh-CN/**/*.md
📄 CodeRabbit inference engine (AGENTS.md)
When a feature is added, removed, renamed, or substantially refactored, contributors MUST update or create the corresponding user-facing integration documentation in
docs/zh-CN/in the same change
Files:
docs/zh-CN/game/config-system.md
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-09T12:37:37.585Z
Learning: Applies to docs/zh-CN/**/*.md : When a feature is added, removed, renamed, or substantially refactored, contributors MUST update or create the corresponding user-facing integration documentation in `docs/zh-CN/` in the same change
📚 Learning: 2026-04-09T12:37:37.585Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-09T12:37:37.585Z
Learning: Applies to **/*.SourceGenerators.Tests/**/*.cs : When generator behavior changes intentionally, update snapshots together with the implementation in source generator tests
Applied to files:
GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorSnapshotTests.csGFramework.SourceGenerators/Config/SchemaConfigGenerator.cs
📚 Learning: 2026-04-09T12:37:37.585Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-09T12:37:37.585Z
Learning: Applies to **/*.SourceGenerators.Tests/**/*.cs : Source generator changes MUST be covered by generator tests
Applied to files:
GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorSnapshotTests.csGFramework.SourceGenerators/Config/SchemaConfigGenerator.cs
📚 Learning: 2026-04-09T12:37:37.585Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-09T12:37:37.585Z
Learning: Applies to **/*.SourceGenerators.Tests/**/*.cs : Preserve snapshot-based verification patterns already used in the repository for source generator tests
Applied to files:
GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorSnapshotTests.cs
📚 Learning: 2026-04-09T12:37:37.585Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-09T12:37:37.585Z
Learning: Applies to **/*.Tests/**/*.cs : Public API changes must be covered by unit or integration tests
Applied to files:
GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorSnapshotTests.csGFramework.Game.Tests/Config/YamlConfigLoaderTests.cs
📚 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.SourceGenerators.Tests/Config/SchemaConfigGeneratorSnapshotTests.csGFramework.SourceGenerators/Config/SchemaConfigGenerator.csGFramework.Game.Tests/Config/YamlConfigLoaderTests.csGFramework.Game/Config/YamlConfigSchemaValidator.cs
📚 Learning: 2026-04-09T12:37:37.585Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-09T12:37:37.585Z
Learning: Applies to **/*.cs : Any change to public API, lifecycle semantics, module behavior, or extension points MUST update the related XML docs
Applied to files:
GFramework.SourceGenerators.Tests/Config/snapshots/SchemaConfigGenerator/MonsterConfig.g.txtGFramework.SourceGenerators/Config/SchemaConfigGenerator.cs
📚 Learning: 2026-04-09T12:37:37.585Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-09T12:37:37.585Z
Learning: Applies to docs/zh-CN/**/*.md : When a feature is added, removed, renamed, or substantially refactored, contributors MUST update or create the corresponding user-facing integration documentation in `docs/zh-CN/` in the same change
Applied to files:
docs/zh-CN/game/config-system.md
📚 Learning: 2026-04-09T12:37:37.585Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-09T12:37:37.585Z
Learning: Applies to docs/**/*.md : For integration-oriented features such as the AI-First config system, documentation MUST cover project directory layout and file conventions, required project or package wiring, minimal working usage example, and migration or compatibility notes when behavior changes
Applied to files:
docs/zh-CN/game/config-system.md
📚 Learning: 2026-04-05T15:30:46.211Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-05T15:30:46.211Z
Learning: Applies to **/*.cs : EnumExtensionsGenerator must generate enum extension capabilities for enums decorated with [GenerateEnumExtensions] attribute
Applied to files:
GFramework.SourceGenerators/Config/SchemaConfigGenerator.cs
📚 Learning: 2026-04-09T12:37:37.585Z
Learnt from: CR
Repo: GeWuYou/GFramework PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-09T12:37:37.585Z
Learning: Applies to **/*.Tests/**/*.cs : Regression fixes should include a test that fails before the fix and passes after it
Applied to files:
GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs
🔇 Additional comments (11)
GFramework.Game/Config/YamlConfigSchemaValidator.cs (3)
841-866:const约束解析逻辑实现正确。
ParseConstantValue方法与 JS 工具链保持一致的 comparable key 构建策略,在 schema 解析阶段完成预归一化,避免运行时重复解释 JSON 常量。实现清晰、符合预期。
1679-1719: 常量校验逻辑实现正确。
ValidateConstantValue复用了BuildComparableNodeValue构建的稳定比较键,与uniqueItems使用相同的归一化策略,确保对象字段顺序、数字字面量格式等不会导致伪差异。错误消息包含DisplayValue便于用户定位问题。
325-331: 节点创建后附加常量约束的模式一致且清晰。三类节点(对象、数组、标量)都采用先创建再
WithConstantValue的模式,保持了代码一致性,便于后续扩展其他约束类型。Also applies to: 391-396, 418-425
tools/gframework-config-tool/src/localizationKeys.js (1)
1-3: LGTM!新增的
constMismatch本地化键遵循现有命名模式,与localization.js中的消息条目配合使用。GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorSnapshotTests.cs (1)
91-100: 测试用例覆盖了const约束场景。
hp属性同时声明了const: 10和其他数值约束,能够有效验证生成器在多约束共存时的文档输出行为。基于 learnings,源代码生成器更改必须有测试覆盖,此处符合要求。GFramework.SourceGenerators.Tests/Config/snapshots/SchemaConfigGenerator/MonsterConfig.g.txt (1)
38-43: 快照正确反映了const约束的文档输出。
Hp属性的<remarks>块现在包含const = 10,约束顺序与SchemaConfigGenerator.TryBuildConstraintDocumentation的实现一致。快照与测试输入的 schema 变更同步更新,符合仓库的快照测试规范。tools/gframework-config-tool/src/localization.js (2)
107-107: 英文本地化条目正确且一致。新增的
webview.hint.const、webview.hint.itemConst和constMismatch消息遵循现有模式,与其他约束提示(如 minimum、maximum)保持格式统一。Also applies to: 121-121, 136-136
217-217: 中文本地化翻译准确。"固定值"准确传达了
const约束的语义,与default(默认值)形成清晰区分。校验消息属性"{displayPath}"必须匹配固定值 {value}表述清晰,符合中文用户习惯。Also applies to: 231-231, 246-246
tools/gframework-config-tool/test/configValidation.test.js (2)
68-102:const元数据解析覆盖面不错这段新增测试把 scalar/object/array 三类节点都覆盖到了,能有效防止
constValue提取回归。
229-291:const失配诊断测试设计合理同时覆盖了标量和复合结构失配,能验证校验器在多节点场景下的诊断输出稳定性。
docs/zh-CN/game/config-system.md (1)
15-15: 文档与const新能力对齐完整约束清单、运行时失败语义、轻量元数据和 VS Code 展示入口都同步到了同一页,集成信息完整且一致。
Based on learnings: When a feature is added, removed, renamed, or substantially refactored, contributors MUST update or create the corresponding user-facing integration documentation in
docs/zh-CN/in the same change.Also applies to: 661-662, 708-709, 814-815
- 实现配置架构解析器,支持JSON架构到递归树的转换 - 添加YAML解析器,支持根映射、缩进嵌套对象和数组结构 - 实现配置验证诊断功能,提供架构和YAML解析验证 - 添加表单更新应用功能,支持将表单更改安全写回YAML - 实现批编辑器字段提取,支持可编辑标量类型的识别 - 添加配置注释提取功能,将注释映射到逻辑字段路径 - 实现示例配置YAML生成功能,包含架构描述作为注释 - 添加精确十进制算术运算,用于multipleOf约束检查 - 实现标量类型兼容性验证,包括整数、数字、布尔值模式匹配 - 添加常量值元数据处理,支持工具比较对齐运行时行为
- 定义了代码风格、注释规则和文档要求 - 规定了测试覆盖范围和安全编码准则 - 实现了配置模式解析和验证功能 - 添加了常量值比较和枚举校验逻辑 - 集成了数字范围和字符串长度验证 - 支持对象数组和嵌套结构验证
Summary by Sourcery
在 YAML 运行时验证器、Node.js 工具链、VS Code 扩展和源码生成器中新增对 JSON Schema
const约束的通用支持,并在游戏配置系统文档中记录这一新行为。New Features:
const约束支持,并在运行时强制执行和提供诊断信息。const元数据,包括可比较键、可编辑值和本地化校验消息,并在 VS Code 表单编辑器中以类似默认值和提示的形式呈现。const约束信息。Enhancements:
enum和const在运行时和工具链中共享一致的比较语义。const支持,以及它与运行时验证、工具和热重载工作流的交互方式。Tests:
const违反与匹配情况,包括空对象场景。const元数据,以及为由 const 支持的字段生成示例 YAML 和 UI 行为。const约束会被保留在生成的 XML 文档中。Original summary in English
Summary by Sourcery
Add shared support for JSON Schema
constconstraints across the YAML runtime validator, Node.js tooling, VS Code extension, and source generator, and document the new behavior in the game config system docs.New Features:
constconstraints for scalar, array, and object fields in the YAML config schema validator with runtime enforcement and diagnostics.constmetadata in the Node.js config tooling, including comparable keys, editable values, and localized validation messages, and surface it in the VS Code form editor as default-like values and hints.constconstraint information in generated configuration type XML documentation and snapshot outputs.Enhancements:
enumandconstshare consistent comparison semantics in both runtime and tooling.constsupport and how it interacts with runtime validation, tools, and hot-reload workflows.Tests:
constviolations and matches, including empty-object cases.constmetadata, as well as sample YAML generation and UI behavior for const-backed fields.constconstraints, including empty-string constants, are preserved in generated XML documentation.新功能:
const约束支持。const元数据(包括 UI 提示和本地化诊断信息),并按照运行时比较语义一致地强制执行。const约束以默认字段值和可读性良好的提示形式呈现。const约束信息。增强改进:
enum和const在运行时和工具中共享相同的比较语义。const支持,以及其在运行时、工具和热重载工作流中的行为。测试:
const违规情况。const元数据,并在标量、对象和数组常量不匹配时报告校验错误。const约束。Original summary in English
Summary by Sourcery
在 YAML 运行时验证器、Node.js 工具链、VS Code 扩展和源码生成器中新增对 JSON Schema
const约束的通用支持,并在游戏配置系统文档中记录这一新行为。New Features:
const约束支持,并在运行时强制执行和提供诊断信息。const元数据,包括可比较键、可编辑值和本地化校验消息,并在 VS Code 表单编辑器中以类似默认值和提示的形式呈现。const约束信息。Enhancements:
enum和const在运行时和工具链中共享一致的比较语义。const支持,以及它与运行时验证、工具和热重载工作流的交互方式。Tests:
const违反与匹配情况,包括空对象场景。const元数据,以及为由 const 支持的字段生成示例 YAML 和 UI 行为。const约束会被保留在生成的 XML 文档中。Original summary in English
Summary by Sourcery
Add shared support for JSON Schema
constconstraints across the YAML runtime validator, Node.js tooling, VS Code extension, and source generator, and document the new behavior in the game config system docs.New Features:
constconstraints for scalar, array, and object fields in the YAML config schema validator with runtime enforcement and diagnostics.constmetadata in the Node.js config tooling, including comparable keys, editable values, and localized validation messages, and surface it in the VS Code form editor as default-like values and hints.constconstraint information in generated configuration type XML documentation and snapshot outputs.Enhancements:
enumandconstshare consistent comparison semantics in both runtime and tooling.constsupport and how it interacts with runtime validation, tools, and hot-reload workflows.Tests:
constviolations and matches, including empty-object cases.constmetadata, as well as sample YAML generation and UI behavior for const-backed fields.constconstraints, including empty-string constants, are preserved in generated XML documentation.Summary by CodeRabbit
const,表单提示与样例优先显示const值,生成文档/注释包含const描述。const不匹配产生清晰诊断(含路径与差异);对象比对忽略字段顺序,数组保留顺序,标量按规范化规则比较。const语义及跨工具一致性。