fix(ai-first-config): 收口条件分支评审跟进

- 修复 Runtime 条件分支 schema 坏形状的诊断路径,改为指向具体 if/then/else 分支
- 新增 else 缺失 if 的运行时回归测试,保持与 Generator 覆盖对称
- 更新 ai-plan 跟踪与 trace,记录 PR #262 follow-up 验证并消除重复标题
This commit is contained in:
GeWuYou 2026-04-20 18:07:23 +08:00
parent 8a39f0a932
commit 5f2442dbcd
4 changed files with 65 additions and 12 deletions

View File

@ -313,6 +313,47 @@ public sealed class YamlConfigLoaderIfThenElseTests
});
}
/// <summary>
/// 验证缺少 <c>if</c> 却声明 <c>else</c> 时,会在 schema 解析阶段被拒绝。
/// </summary>
[Test]
public void LoadAsync_Should_Throw_When_Else_Is_Declared_Without_If()
{
CreateConfigFile(
"monster/slime.yaml",
BuildMonsterConfigYaml(
"""
bonus: 1
"""));
CreateSchemaFile(
"schemas/monster.schema.json",
BuildMonsterSchema(
DefaultRewardPropertiesJson,
"""
"else": {
"type": "object",
"required": ["bonus"],
"properties": {
"bonus": { "type": "integer" }
}
}
"""));
var loader = CreateMonsterRewardLoader();
var registry = CreateRegistry();
var exception = Assert.ThrowsAsync<ConfigLoadException>(async () => await loader.LoadAsync(registry));
Assert.Multiple(() =>
{
Assert.That(exception, Is.Not.Null);
Assert.That(exception!.Diagnostic.FailureKind, Is.EqualTo(ConfigLoadFailureKind.SchemaUnsupported));
Assert.That(exception.Diagnostic.DisplayPath, Is.EqualTo("reward"));
Assert.That(exception.Message, Does.Contain("must declare 'if' when using 'then' or 'else'"));
Assert.That(registry.Count, Is.EqualTo(0));
});
}
/// <summary>
/// 验证条件分支不能要求父对象未声明的字段。
/// </summary>

View File

@ -441,9 +441,9 @@ internal static partial class YamlConfigSchemaValidator
throw ConfigLoadExceptionFactory.Create(
ConfigLoadFailureKind.SchemaUnsupported,
tableName,
$"{DescribeObjectSchemaTarget(propertyPath)} in schema file '{schemaPath}' must declare '{keywordName}' as an object-valued schema.",
$"{DescribeObjectSchemaTarget(conditionalSchemaPath)} in schema file '{schemaPath}' must declare '{keywordName}' as an object-valued schema.",
schemaPath: schemaPath,
displayPath: GetDiagnosticPath(propertyPath));
displayPath: GetDiagnosticPath(conditionalSchemaPath));
}
ValidateInlineObjectSchemaTargetsAgainstParentObject(

View File

@ -23,6 +23,8 @@
- 缓解措施:继续为新增共享关键字补齐三端测试覆盖,优先保证 C# Runtime 与 Generator 回归通过,并记录 JS 测试与构建验证
- PR review 信号漂移风险CodeRabbit 可能把建议折叠在 latest review body而不是 issue comments
- 缓解措施:`gframework-pr-review` 现已同时解析 latest review body并输出 declared / parsed 数量以便快速识别解析缺口
- PR follow-up 残留风险PR `#262` 最新 review thread 仍有少量 open comments且 nitpick body 解析仍存在 declared / parsed 缺口
- 缓解措施:先以 latest unresolved thread 为准逐条本地核验;已确认并补齐运行时诊断路径与 `else without if` 回归测试,剩余解析缺口单独留在 skill 后续处理
- 非阻塞项回退风险:将 VS Code 功能标为非阻塞但导致主线回退的风险
- 缓解措施C# 主线补齐新关键字时仍需在 `configValidation.js``extension.js` 中同步落地,只是不让复杂表单控件阻塞发布
@ -49,6 +51,12 @@
- `gframework-pr-review` 现已解析 latest CodeRabbit review body 中 folded `Nitpick comments`
- text 输出会显示 `CodeRabbit nitpick comments: X declared, Y parsed`,避免再次静默遗漏
- 已按 5 条 nitpick 更新 VS Code tool hints、shared validation helper以及对称分支测试覆盖
- PR `#262` 最新 follow-up
- 最新抓取结果显示仍有 2 条 actionable comments 与 1 条已解析 nitpick 需要本地核验
- `SchemaConfigGenerator` 的分支级诊断定位已在当前分支,无需重复修改
- `YamlConfigSchemaValidator` 已补齐 `conditionalSchemaPath` 诊断路径,避免 `reward[then]` / `reward[else]` 坏形状误报到父路径
- `YamlConfigLoaderIfThenElseTests` 已新增运行时 `else` 缺失 `if` 回归,避免 Runtime / Generator 覆盖漂移
- active trace 已将重复的 `### 验证` 标题改为专用 PR follow-up 标题,消除 `MD024`
- 分支同步状态:
- `feat/ai-first-config` 已 rebase 到 `origin/feat/ai-first-config`
- 当前已解决“ahead / behind 同时存在”的分支差异,不再 behind 远端
@ -74,14 +82,14 @@
- `2026-04-17` 之前的详细实现记录与定向验证命令已归档到历史 tracking / trace
- active 跟踪文件只保留当前恢复点、当前状态和下一步,不再重复堆积已完成阶段的完整历史
- `2026-04-20` 当前恢复点验证:
- `python3 .codex/skills/gframework-pr-review/scripts/fetch_current_pr_review.py`:通过(`CodeRabbit nitpick comments: 5 declared, 5 parsed`
- `python3 .codex/skills/gframework-pr-review/scripts/fetch_current_pr_review.py`:通过(`CodeRabbit actionable comments: 2``CodeRabbit nitpick comments: 2 declared, 1 parsed`
- `bun run test``tools/gframework-config-tool`):通过
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~SchemaConfigGeneratorTests"`:通过
- `dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~YamlConfigLoaderIfThenElseTests"`:通过
- `dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~YamlConfigLoaderIfThenElseTests"`:通过8 tests新增 `else without if` 运行时回归)
- `dotnet build GFramework.sln -c Release`:通过(存在仓库既有 analyzer warning无新增错误
## 下一步
1. 先用 `GFramework.Game/Config/YamlConfigSchemaValidator.cs``GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs``tools/gframework-config-tool/src/configValidation.js` 盘点下一批候选关键字
2. 优先判断 `oneOf` / `anyOf` 是否存在可接受的 object-focused 子集;如果仍会引入生成类型形状漂移,就直接跳过
3. 在下一批关键字之前保持“Runtime / Generator / Tooling 三端一致且不做属性合并”这条筛选线
1. 提交并推送当前 PR `#262` follow-up 修复后,重新抓取一次 PR review确认 open thread 是否已清空或只剩 parser gap
2. 若 PR review 已收口,再回到 `GFramework.Game/Config/YamlConfigSchemaValidator.cs``GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs``tools/gframework-config-tool/src/configValidation.js` 盘点下一批候选关键字
3. 优先判断 `oneOf` / `anyOf` 是否存在可接受的 object-focused 子集;若仍会引入生成类型形状漂移,就直接跳过

View File

@ -78,20 +78,24 @@
- rebase 过程中 Git 跳过了远端已具备的 commit `76488dc`
- 当前分支已不再 behind 远端,仅保留本地领先提交
### 验证
### PR `#262` review follow-up 验证
- 2026-04-20`python3 .codex/skills/gframework-pr-review/scripts/fetch_current_pr_review.py`
- 结果:通过
- 备注:输出 `CodeRabbit nitpick comments: 5 declared, 5 parsed`
- 备注:输出 `CodeRabbit actionable comments: 2``CodeRabbit nitpick comments: 2 declared, 1 parsed`,并暴露剩余 review follow-up
- 2026-04-20运行时条件分支 follow-up
- 结果:已补齐
- 备注:`YamlConfigSchemaValidator` 现对非 object 的 `if` / `then` / `else` 使用分支级诊断路径;运行时测试新增 `else` 缺失 `if` 回归
- 2026-04-20`bun run test``tools/gframework-config-tool`
- 结果通过118 tests
- 2026-04-20`dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~SchemaConfigGeneratorTests"`
- 结果通过46 tests
- 2026-04-20`dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~YamlConfigLoaderIfThenElseTests"`
- 结果通过7 tests
- 结果通过8 tests
- 备注:新增 `LoadAsync_Should_Throw_When_Else_Is_Declared_Without_If` 后,运行时回归覆盖保持对称
- 2026-04-20`dotnet build GFramework.sln -c Release`
- 结果:通过
- 备注:存在仓库既有 analyzer warning但无新增错误
- 结果:通过(历史记录)
- 备注:存在仓库既有 analyzer warning但无新增错误;本轮只需重新验证受影响测试切片
### 下一步