From 104ac25dc36394080eb37f3e9ab65ed469c8cda4 Mon Sep 17 00:00:00 2001
From: gewuyou <95328647+GeWuYou@users.noreply.github.com>
Date: Wed, 29 Apr 2026 08:38:23 +0800
Subject: [PATCH] =?UTF-8?q?refactor(game):=20=E6=8B=86=E5=88=86=20schema?=
=?UTF-8?q?=20=E6=A0=A1=E9=AA=8C=E6=A8=A1=E5=9E=8B=E7=B1=BB=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 拆分 schema model 类型到独立同名文件
- 清理 schema 校验模型的文件命名 analyzer 告警
- 更新 warning reduction 批处理收口状态
---
.../Config/YamlConfigAllowedValue.cs | 32 +
.../Config/YamlConfigArrayConstraints.cs | 47 +
.../YamlConfigArrayContainsConstraints.cs | 41 +
.../Config/YamlConfigConditionalSchemas.cs | 41 +
.../Config/YamlConfigConstantValue.cs | 32 +
.../Config/YamlConfigNumericConstraints.cs | 55 +
.../Config/YamlConfigObjectConstraints.cs | 67 ++
.../Config/YamlConfigReferenceUsage.cs | 74 ++
.../Config/YamlConfigScalarConstraints.cs | 31 +
GFramework.Game/Config/YamlConfigSchema.cs | 44 +
.../Config/YamlConfigSchemaNode.cs | 330 ++++++
.../Config/YamlConfigSchemaPropertyType.cs | 37 +
.../Config/YamlConfigSchemaValidator.cs | 947 ------------------
.../Config/YamlConfigStringConstraints.cs | 58 ++
.../YamlConfigStringFormatConstraint.cs | 33 +
.../Config/YamlConfigStringFormatKind.cs | 42 +
.../analyzer-warning-reduction-tracking.md | 24 +-
.../analyzer-warning-reduction-trace.md | 18 +-
18 files changed, 990 insertions(+), 963 deletions(-)
create mode 100644 GFramework.Game/Config/YamlConfigAllowedValue.cs
create mode 100644 GFramework.Game/Config/YamlConfigArrayConstraints.cs
create mode 100644 GFramework.Game/Config/YamlConfigArrayContainsConstraints.cs
create mode 100644 GFramework.Game/Config/YamlConfigConditionalSchemas.cs
create mode 100644 GFramework.Game/Config/YamlConfigConstantValue.cs
create mode 100644 GFramework.Game/Config/YamlConfigNumericConstraints.cs
create mode 100644 GFramework.Game/Config/YamlConfigObjectConstraints.cs
create mode 100644 GFramework.Game/Config/YamlConfigReferenceUsage.cs
create mode 100644 GFramework.Game/Config/YamlConfigScalarConstraints.cs
create mode 100644 GFramework.Game/Config/YamlConfigSchema.cs
create mode 100644 GFramework.Game/Config/YamlConfigSchemaNode.cs
create mode 100644 GFramework.Game/Config/YamlConfigSchemaPropertyType.cs
create mode 100644 GFramework.Game/Config/YamlConfigStringConstraints.cs
create mode 100644 GFramework.Game/Config/YamlConfigStringFormatConstraint.cs
create mode 100644 GFramework.Game/Config/YamlConfigStringFormatKind.cs
diff --git a/GFramework.Game/Config/YamlConfigAllowedValue.cs b/GFramework.Game/Config/YamlConfigAllowedValue.cs
new file mode 100644
index 00000000..60077ef5
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigAllowedValue.cs
@@ -0,0 +1,32 @@
+namespace GFramework.Game.Config;
+
+///
+/// 表示一个节点上声明的单个 enum 候选值。
+/// 该模型同时保留稳定比较键与原始 JSON 文本,分别供运行时匹配和诊断输出复用。
+///
+internal sealed class YamlConfigAllowedValue
+{
+ ///
+ /// 初始化一个枚举候选值模型。
+ ///
+ /// 用于与 YAML 节点比较的稳定键。
+ /// 用于诊断输出的原始 JSON 文本。
+ public YamlConfigAllowedValue(string comparableValue, string displayValue)
+ {
+ ArgumentNullException.ThrowIfNull(comparableValue);
+ ArgumentException.ThrowIfNullOrWhiteSpace(displayValue);
+
+ ComparableValue = comparableValue;
+ DisplayValue = displayValue;
+ }
+
+ ///
+ /// 获取用于运行时比较的稳定键。
+ ///
+ public string ComparableValue { get; }
+
+ ///
+ /// 获取用于诊断输出的原始 JSON 文本。
+ ///
+ public string DisplayValue { get; }
+}
diff --git a/GFramework.Game/Config/YamlConfigArrayConstraints.cs b/GFramework.Game/Config/YamlConfigArrayConstraints.cs
new file mode 100644
index 00000000..64ddaf3c
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigArrayConstraints.cs
@@ -0,0 +1,47 @@
+namespace GFramework.Game.Config;
+
+///
+/// 表示一个数组节点上声明的元素数量、去重与 contains 匹配计数约束。
+/// 该模型与标量约束拆分保存,避免数组节点继续共享不适用的标量字段。
+///
+internal sealed class YamlConfigArrayConstraints
+{
+ ///
+ /// 初始化数组约束模型。
+ ///
+ /// 最小元素数量约束。
+ /// 最大元素数量约束。
+ /// 是否要求数组元素唯一。
+ /// 数组 contains 约束;未声明时为空。
+ public YamlConfigArrayConstraints(
+ int? minItems,
+ int? maxItems,
+ bool uniqueItems,
+ YamlConfigArrayContainsConstraints? containsConstraints)
+ {
+ MinItems = minItems;
+ MaxItems = maxItems;
+ UniqueItems = uniqueItems;
+ ContainsConstraints = containsConstraints;
+ }
+
+ ///
+ /// 获取最小元素数量约束。
+ ///
+ public int? MinItems { get; }
+
+ ///
+ /// 获取最大元素数量约束。
+ ///
+ public int? MaxItems { get; }
+
+ ///
+ /// 获取是否要求数组元素唯一。
+ ///
+ public bool UniqueItems { get; }
+
+ ///
+ /// 获取数组 contains 约束;未声明时返回空。
+ ///
+ public YamlConfigArrayContainsConstraints? ContainsConstraints { get; }
+}
diff --git a/GFramework.Game/Config/YamlConfigArrayContainsConstraints.cs b/GFramework.Game/Config/YamlConfigArrayContainsConstraints.cs
new file mode 100644
index 00000000..a61800f8
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigArrayContainsConstraints.cs
@@ -0,0 +1,41 @@
+namespace GFramework.Game.Config;
+
+///
+/// 表示数组节点声明的 contains 匹配约束。
+/// 该模型把 contains 子 schema 与匹配数量边界聚合在一起,避免数组节点再额外散落多组相关成员。
+///
+internal sealed class YamlConfigArrayContainsConstraints
+{
+ ///
+ /// 初始化数组 contains 约束模型。
+ ///
+ /// contains 子 schema。
+ /// 最小匹配数量;为 时按 JSON Schema 语义默认 1。
+ /// 最大匹配数量。
+ public YamlConfigArrayContainsConstraints(
+ YamlConfigSchemaNode containsNode,
+ int? minContains,
+ int? maxContains)
+ {
+ ArgumentNullException.ThrowIfNull(containsNode);
+
+ ContainsNode = containsNode;
+ MinContains = minContains;
+ MaxContains = maxContains;
+ }
+
+ ///
+ /// 获取 contains 子 schema。
+ ///
+ public YamlConfigSchemaNode ContainsNode { get; }
+
+ ///
+ /// 获取最小匹配数量;未显式声明时返回空,由调用方按默认值 1 解释。
+ ///
+ public int? MinContains { get; }
+
+ ///
+ /// 获取最大匹配数量。
+ ///
+ public int? MaxContains { get; }
+}
diff --git a/GFramework.Game/Config/YamlConfigConditionalSchemas.cs b/GFramework.Game/Config/YamlConfigConditionalSchemas.cs
new file mode 100644
index 00000000..7d4bbbf2
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigConditionalSchemas.cs
@@ -0,0 +1,41 @@
+namespace GFramework.Game.Config;
+
+///
+/// 表示一个对象节点上声明的 object-focused if / then / else 条件约束。
+/// 三个分支都共享父对象已声明字段集合,不会把分支 schema 扩展成新的生成类型形状。
+///
+internal sealed class YamlConfigConditionalSchemas
+{
+ ///
+ /// 初始化条件分支约束模型。
+ ///
+ /// 条件判断 schema。
+ /// 条件命中时需要满足的 schema。
+ /// 条件未命中时需要满足的 schema。
+ public YamlConfigConditionalSchemas(
+ YamlConfigSchemaNode ifSchema,
+ YamlConfigSchemaNode? thenSchema,
+ YamlConfigSchemaNode? elseSchema)
+ {
+ ArgumentNullException.ThrowIfNull(ifSchema);
+
+ IfSchema = ifSchema;
+ ThenSchema = thenSchema;
+ ElseSchema = elseSchema;
+ }
+
+ ///
+ /// 获取条件判断 schema。
+ ///
+ public YamlConfigSchemaNode IfSchema { get; }
+
+ ///
+ /// 获取条件命中时需要满足的 schema。
+ ///
+ public YamlConfigSchemaNode? ThenSchema { get; }
+
+ ///
+ /// 获取条件未命中时需要满足的 schema。
+ ///
+ public YamlConfigSchemaNode? ElseSchema { get; }
+}
diff --git a/GFramework.Game/Config/YamlConfigConstantValue.cs b/GFramework.Game/Config/YamlConfigConstantValue.cs
new file mode 100644
index 00000000..48caa4c5
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigConstantValue.cs
@@ -0,0 +1,32 @@
+namespace GFramework.Game.Config;
+
+///
+/// 表示一个节点上声明的 const 约束。
+/// 该模型同时保留稳定比较键与原始 JSON 文本,分别供运行时匹配和诊断输出复用。
+///
+internal sealed class YamlConfigConstantValue
+{
+ ///
+ /// 初始化常量约束模型。
+ ///
+ /// 用于与 YAML 节点比较的稳定键。
+ /// 用于诊断输出的原始常量文本。
+ public YamlConfigConstantValue(string comparableValue, string displayValue)
+ {
+ ArgumentNullException.ThrowIfNull(comparableValue);
+ ArgumentException.ThrowIfNullOrWhiteSpace(displayValue);
+
+ ComparableValue = comparableValue;
+ DisplayValue = displayValue;
+ }
+
+ ///
+ /// 获取用于运行时比较的稳定键。
+ ///
+ public string ComparableValue { get; }
+
+ ///
+ /// 获取用于诊断输出的原始 JSON 常量文本。
+ ///
+ public string DisplayValue { get; }
+}
diff --git a/GFramework.Game/Config/YamlConfigNumericConstraints.cs b/GFramework.Game/Config/YamlConfigNumericConstraints.cs
new file mode 100644
index 00000000..977eb007
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigNumericConstraints.cs
@@ -0,0 +1,55 @@
+namespace GFramework.Game.Config;
+
+///
+/// 表示标量节点上声明的数值范围与步进约束。
+/// 该类型只覆盖整数 / 浮点共享的关键字,避免字符串字段继续暴露不相关的成员。
+///
+internal sealed class YamlConfigNumericConstraints
+{
+ ///
+ /// 初始化数值约束模型。
+ ///
+ /// 最小值约束。
+ /// 最大值约束。
+ /// 开区间最小值约束。
+ /// 开区间最大值约束。
+ /// 数值步进约束。
+ public YamlConfigNumericConstraints(
+ double? minimum,
+ double? maximum,
+ double? exclusiveMinimum,
+ double? exclusiveMaximum,
+ double? multipleOf)
+ {
+ Minimum = minimum;
+ Maximum = maximum;
+ ExclusiveMinimum = exclusiveMinimum;
+ ExclusiveMaximum = exclusiveMaximum;
+ MultipleOf = multipleOf;
+ }
+
+ ///
+ /// 获取最小值约束。
+ ///
+ public double? Minimum { get; }
+
+ ///
+ /// 获取最大值约束。
+ ///
+ public double? Maximum { get; }
+
+ ///
+ /// 获取开区间最小值约束。
+ ///
+ public double? ExclusiveMinimum { get; }
+
+ ///
+ /// 获取开区间最大值约束。
+ ///
+ public double? ExclusiveMaximum { get; }
+
+ ///
+ /// 获取数值步进约束。
+ ///
+ public double? MultipleOf { get; }
+}
diff --git a/GFramework.Game/Config/YamlConfigObjectConstraints.cs b/GFramework.Game/Config/YamlConfigObjectConstraints.cs
new file mode 100644
index 00000000..01b460f9
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigObjectConstraints.cs
@@ -0,0 +1,67 @@
+namespace GFramework.Game.Config;
+
+///
+/// 表示一个对象节点上声明的属性数量约束、字段依赖约束、条件子 schema 与组合约束。
+/// 该模型将对象级约束与数组 / 标量约束拆开保存,避免运行时节点继续暴露无关成员。
+///
+internal sealed class YamlConfigObjectConstraints
+{
+ ///
+ /// 初始化对象约束模型。
+ ///
+ /// 最小属性数量约束。
+ /// 最大属性数量约束。
+ /// 对象内字段依赖约束。
+ /// 对象内条件 schema 约束。
+ /// 对象内组合 schema 约束。
+ /// 对象内条件分支约束。
+ public YamlConfigObjectConstraints(
+ int? minProperties,
+ int? maxProperties,
+ IReadOnlyDictionary>? dependentRequired,
+ IReadOnlyDictionary? dependentSchemas,
+ IReadOnlyList? allOfSchemas,
+ YamlConfigConditionalSchemas? conditionalSchemas)
+ {
+ MinProperties = minProperties;
+ MaxProperties = maxProperties;
+ DependentRequired = dependentRequired;
+ DependentSchemas = dependentSchemas;
+ AllOfSchemas = allOfSchemas;
+ ConditionalSchemas = conditionalSchemas;
+ }
+
+ ///
+ /// 获取最小属性数量约束。
+ ///
+ public int? MinProperties { get; }
+
+ ///
+ /// 获取最大属性数量约束。
+ ///
+ public int? MaxProperties { get; }
+
+ ///
+ /// 获取对象内字段依赖约束。
+ /// 键表示“触发字段”,值表示“触发字段出现后还必须存在的同级字段集合”。
+ ///
+ public IReadOnlyDictionary>? DependentRequired { get; }
+
+ ///
+ /// 获取对象内条件 schema 约束。
+ /// 键表示“触发字段”,值表示“触发字段出现后当前对象还必须满足的额外 schema 子树”。
+ ///
+ public IReadOnlyDictionary? DependentSchemas { get; }
+
+ ///
+ /// 获取对象内 allOf 组合约束。
+ /// 每个条目都表示“当前对象还必须额外满足的 focused constraint block”。
+ ///
+ public IReadOnlyList? AllOfSchemas { get; }
+
+ ///
+ /// 获取对象内 object-focused if / then / else 条件约束。
+ /// 该模型会先用 if 试匹配当前对象,再只对命中的分支叠加 focused constraint block。
+ ///
+ public YamlConfigConditionalSchemas? ConditionalSchemas { get; }
+}
diff --git a/GFramework.Game/Config/YamlConfigReferenceUsage.cs b/GFramework.Game/Config/YamlConfigReferenceUsage.cs
new file mode 100644
index 00000000..ba9ff1ea
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigReferenceUsage.cs
@@ -0,0 +1,74 @@
+namespace GFramework.Game.Config;
+
+///
+/// 表示单个 YAML 文件中提取出的跨表引用。
+/// 该模型保留源文件、字段路径和目标表等诊断信息,以便加载器在批量校验失败时给出可定位的错误。
+///
+internal sealed class YamlConfigReferenceUsage
+{
+ ///
+ /// 初始化一个跨表引用使用记录。
+ ///
+ /// 源 YAML 文件路径。
+ /// 定义该引用的 schema 文件路径。
+ /// 声明引用的字段路径。
+ /// YAML 中的原始标量值。
+ /// 目标配置表名称。
+ /// 引用值的 schema 标量类型。
+ public YamlConfigReferenceUsage(
+ string yamlPath,
+ string schemaPath,
+ string propertyPath,
+ string rawValue,
+ string referencedTableName,
+ YamlConfigSchemaPropertyType valueType)
+ {
+ ArgumentNullException.ThrowIfNull(yamlPath);
+ ArgumentNullException.ThrowIfNull(schemaPath);
+ ArgumentNullException.ThrowIfNull(propertyPath);
+ ArgumentNullException.ThrowIfNull(rawValue);
+ ArgumentNullException.ThrowIfNull(referencedTableName);
+
+ YamlPath = yamlPath;
+ SchemaPath = schemaPath;
+ PropertyPath = propertyPath;
+ RawValue = rawValue;
+ ReferencedTableName = referencedTableName;
+ ValueType = valueType;
+ }
+
+ ///
+ /// 获取源 YAML 文件路径。
+ ///
+ public string YamlPath { get; }
+
+ ///
+ /// 获取定义该引用的 schema 文件路径。
+ ///
+ public string SchemaPath { get; }
+
+ ///
+ /// 获取声明引用的字段路径。
+ ///
+ public string PropertyPath { get; }
+
+ ///
+ /// 获取 YAML 中的原始标量值。
+ ///
+ public string RawValue { get; }
+
+ ///
+ /// 获取目标配置表名称。
+ ///
+ public string ReferencedTableName { get; }
+
+ ///
+ /// 获取引用值的 schema 标量类型。
+ ///
+ public YamlConfigSchemaPropertyType ValueType { get; }
+
+ ///
+ /// 获取便于诊断显示的字段路径。
+ ///
+ public string DisplayPath => PropertyPath;
+}
diff --git a/GFramework.Game/Config/YamlConfigScalarConstraints.cs b/GFramework.Game/Config/YamlConfigScalarConstraints.cs
new file mode 100644
index 00000000..df632030
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigScalarConstraints.cs
@@ -0,0 +1,31 @@
+namespace GFramework.Game.Config;
+
+///
+/// 聚合一个标量节点上声明的数值约束与字符串约束。
+/// 该包装层保留“标量字段有约束”的统一入口,同时把不同语义的约束分成更小的专用模型。
+///
+internal sealed class YamlConfigScalarConstraints
+{
+ ///
+ /// 初始化标量约束模型。
+ ///
+ /// 数值约束分组。
+ /// 字符串约束分组。
+ public YamlConfigScalarConstraints(
+ YamlConfigNumericConstraints? numericConstraints,
+ YamlConfigStringConstraints? stringConstraints)
+ {
+ NumericConstraints = numericConstraints;
+ StringConstraints = stringConstraints;
+ }
+
+ ///
+ /// 获取数值约束分组。
+ ///
+ public YamlConfigNumericConstraints? NumericConstraints { get; }
+
+ ///
+ /// 获取字符串约束分组。
+ ///
+ public YamlConfigStringConstraints? StringConstraints { get; }
+}
diff --git a/GFramework.Game/Config/YamlConfigSchema.cs b/GFramework.Game/Config/YamlConfigSchema.cs
new file mode 100644
index 00000000..e3ae2f0c
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigSchema.cs
@@ -0,0 +1,44 @@
+namespace GFramework.Game.Config;
+
+///
+/// 表示已解析并可用于运行时校验的 JSON Schema。
+/// 该模型保留根节点与引用依赖集合,避免运行时引入完整 schema 引擎。
+///
+internal sealed class YamlConfigSchema
+{
+ ///
+ /// 初始化一个可用于运行时校验的 schema 模型。
+ ///
+ /// Schema 文件路径。
+ /// 根节点模型。
+ /// Schema 声明的目标引用表名称集合。
+ public YamlConfigSchema(
+ string schemaPath,
+ YamlConfigSchemaNode rootNode,
+ IReadOnlyCollection referencedTableNames)
+ {
+ ArgumentNullException.ThrowIfNull(schemaPath);
+ ArgumentNullException.ThrowIfNull(rootNode);
+ ArgumentNullException.ThrowIfNull(referencedTableNames);
+
+ SchemaPath = schemaPath;
+ RootNode = rootNode;
+ ReferencedTableNames = referencedTableNames;
+ }
+
+ ///
+ /// 获取 schema 文件路径。
+ ///
+ public string SchemaPath { get; }
+
+ ///
+ /// 获取根节点模型。
+ ///
+ public YamlConfigSchemaNode RootNode { get; }
+
+ ///
+ /// 获取 schema 声明的目标引用表名称集合。
+ /// 该信息用于热重载时推导受影响的依赖表闭包。
+ ///
+ public IReadOnlyCollection ReferencedTableNames { get; }
+}
diff --git a/GFramework.Game/Config/YamlConfigSchemaNode.cs b/GFramework.Game/Config/YamlConfigSchemaNode.cs
new file mode 100644
index 00000000..35509bef
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigSchemaNode.cs
@@ -0,0 +1,330 @@
+namespace GFramework.Game.Config;
+
+///
+/// 表示单个 schema 节点的最小运行时描述。
+/// 同一个模型同时覆盖对象、数组和标量,便于递归校验逻辑只依赖一种树结构。
+///
+internal sealed class YamlConfigSchemaNode
+{
+ private readonly NodeChildren _children;
+ private readonly NodeValidation _validation;
+
+ private YamlConfigSchemaNode(
+ YamlConfigSchemaPropertyType nodeType,
+ NodeChildren children,
+ NodeValidation validation,
+ string schemaPathHint)
+ {
+ ArgumentNullException.ThrowIfNull(children);
+ ArgumentNullException.ThrowIfNull(validation);
+ ArgumentNullException.ThrowIfNull(schemaPathHint);
+
+ _children = children;
+ _validation = validation;
+ NodeType = nodeType;
+ Properties = children.Properties;
+ RequiredProperties = children.RequiredProperties;
+ ItemNode = children.ItemNode;
+ ReferenceTableName = validation.ReferenceTableName;
+ AllowedValues = validation.AllowedValues;
+ Constraints = validation.Constraints;
+ ArrayConstraints = validation.ArrayConstraints;
+ ObjectConstraints = validation.ObjectConstraints;
+ ConstantValue = validation.ConstantValue;
+ NegatedSchemaNode = validation.NegatedSchemaNode;
+ SchemaPathHint = schemaPathHint;
+ }
+
+ ///
+ /// 获取节点类型。
+ ///
+ public YamlConfigSchemaPropertyType NodeType { get; }
+
+ ///
+ /// 获取对象属性集合;非对象节点时返回空。
+ ///
+ public IReadOnlyDictionary? Properties { get; }
+
+ ///
+ /// 获取对象必填属性集合;非对象节点时返回空。
+ ///
+ public IReadOnlyCollection? RequiredProperties { get; }
+
+ ///
+ /// 获取数组元素节点;非数组节点时返回空。
+ ///
+ public YamlConfigSchemaNode? ItemNode { get; }
+
+ ///
+ /// 获取目标引用表名称;未声明跨表引用时返回空。
+ ///
+ public string? ReferenceTableName { get; }
+
+ ///
+ /// 获取节点允许值集合;未声明 enum 时返回空。
+ ///
+ public IReadOnlyCollection? AllowedValues { get; }
+
+ ///
+ /// 获取标量范围与长度约束;未声明时返回空。
+ ///
+ public YamlConfigScalarConstraints? Constraints { get; }
+
+ ///
+ /// 获取对象属性数量约束;未声明时返回空。
+ ///
+ public YamlConfigObjectConstraints? ObjectConstraints { get; }
+
+ ///
+ /// 获取数组元素数量约束;未声明时返回空。
+ ///
+ public YamlConfigArrayConstraints? ArrayConstraints { get; }
+
+ ///
+ /// 获取节点常量约束;未声明 const 时返回空。
+ ///
+ public YamlConfigConstantValue? ConstantValue { get; }
+
+ ///
+ /// 获取节点声明的 not 子 schema;未声明时返回空。
+ ///
+ public YamlConfigSchemaNode? NegatedSchemaNode { get; }
+
+ ///
+ /// 获取用于诊断显示的 schema 路径提示。
+ /// 当前节点本身不记录独立路径,因此对象校验会回退到所属根 schema 路径。
+ ///
+ public string SchemaPathHint { get; }
+
+ ///
+ /// 创建对象节点描述。
+ ///
+ /// 对象属性集合。
+ /// 对象必填属性集合。
+ /// 对象属性数量约束。
+ /// 用于错误信息的 schema 文件路径提示。
+ /// 对象节点模型。
+ public static YamlConfigSchemaNode CreateObject(
+ IReadOnlyDictionary? properties,
+ IReadOnlyCollection? requiredProperties,
+ YamlConfigObjectConstraints? objectConstraints,
+ string schemaPathHint)
+ {
+ return new YamlConfigSchemaNode(
+ YamlConfigSchemaPropertyType.Object,
+ new NodeChildren(properties, requiredProperties, itemNode: null),
+ new NodeValidation(
+ referenceTableName: null,
+ allowedValues: null,
+ constraints: null,
+ arrayConstraints: null,
+ objectConstraints,
+ constantValue: null,
+ negatedSchemaNode: null),
+ schemaPathHint);
+ }
+
+ ///
+ /// 创建数组节点描述。
+ ///
+ /// 数组元素节点。
+ /// 数组节点允许值集合。
+ /// 数组元素数量约束。
+ /// 用于错误信息的 schema 文件路径提示。
+ /// 数组节点模型。
+ public static YamlConfigSchemaNode CreateArray(
+ YamlConfigSchemaNode itemNode,
+ IReadOnlyCollection? allowedValues,
+ YamlConfigArrayConstraints? arrayConstraints,
+ string schemaPathHint)
+ {
+ return new YamlConfigSchemaNode(
+ YamlConfigSchemaPropertyType.Array,
+ new NodeChildren(properties: null, requiredProperties: null, itemNode),
+ new NodeValidation(
+ referenceTableName: null,
+ allowedValues,
+ constraints: null,
+ arrayConstraints,
+ objectConstraints: null,
+ constantValue: null,
+ negatedSchemaNode: null),
+ schemaPathHint);
+ }
+
+ ///
+ /// 创建标量节点描述。
+ ///
+ /// 标量节点类型。
+ /// 目标引用表名称。
+ /// 标量允许值集合。
+ /// 标量范围与长度约束。
+ /// 用于错误信息的 schema 文件路径提示。
+ /// 标量节点模型。
+ public static YamlConfigSchemaNode CreateScalar(
+ YamlConfigSchemaPropertyType nodeType,
+ string? referenceTableName,
+ IReadOnlyCollection? allowedValues,
+ YamlConfigScalarConstraints? constraints,
+ string schemaPathHint)
+ {
+ return new YamlConfigSchemaNode(
+ nodeType,
+ NodeChildren.None,
+ new NodeValidation(
+ referenceTableName,
+ allowedValues,
+ constraints,
+ arrayConstraints: null,
+ objectConstraints: null,
+ constantValue: null,
+ negatedSchemaNode: null),
+ schemaPathHint);
+ }
+
+ ///
+ /// 基于当前节点复制一个只替换引用表名称的新节点。
+ /// 该方法用于把数组级别的 ref-table 语义挂接到元素节点上。
+ ///
+ /// 新的目标引用表名称。
+ /// 复制后的节点。
+ public YamlConfigSchemaNode WithReferenceTable(string referenceTableName)
+ {
+ return new YamlConfigSchemaNode(
+ NodeType,
+ _children,
+ _validation.WithReferenceTable(referenceTableName),
+ SchemaPathHint);
+ }
+
+ ///
+ /// 基于当前节点复制一个只替换 enum 允许值集合的新节点。
+ ///
+ /// 新的允许值集合。
+ /// 复制后的节点。
+ public YamlConfigSchemaNode WithAllowedValues(IReadOnlyCollection? allowedValues)
+ {
+ return new YamlConfigSchemaNode(
+ NodeType,
+ _children,
+ _validation.WithAllowedValues(allowedValues),
+ SchemaPathHint);
+ }
+
+ ///
+ /// 基于当前节点复制一个只替换常量约束的新节点。
+ ///
+ /// 新的常量约束。
+ /// 复制后的节点。
+ public YamlConfigSchemaNode WithConstantValue(YamlConfigConstantValue? constantValue)
+ {
+ return new YamlConfigSchemaNode(
+ NodeType,
+ _children,
+ _validation.WithConstantValue(constantValue),
+ SchemaPathHint);
+ }
+
+ ///
+ /// 基于当前节点复制一个只替换 not 子 schema 的新节点。
+ ///
+ /// 新的 negated schema。
+ /// 复制后的节点。
+ public YamlConfigSchemaNode WithNegatedSchemaNode(YamlConfigSchemaNode? negatedSchemaNode)
+ {
+ return new YamlConfigSchemaNode(
+ NodeType,
+ _children,
+ _validation.WithNegatedSchemaNode(negatedSchemaNode),
+ SchemaPathHint);
+ }
+
+ private sealed class NodeChildren
+ {
+ public NodeChildren(
+ IReadOnlyDictionary? properties,
+ IReadOnlyCollection? requiredProperties,
+ YamlConfigSchemaNode? itemNode)
+ {
+ Properties = properties;
+ RequiredProperties = requiredProperties;
+ ItemNode = itemNode;
+ }
+
+ public static NodeChildren None { get; } = new(properties: null, requiredProperties: null, itemNode: null);
+
+ public IReadOnlyDictionary? Properties { get; }
+
+ public IReadOnlyCollection? RequiredProperties { get; }
+
+ public YamlConfigSchemaNode? ItemNode { get; }
+ }
+
+ private sealed class NodeValidation
+ {
+ public NodeValidation(
+ string? referenceTableName,
+ IReadOnlyCollection? allowedValues,
+ YamlConfigScalarConstraints? constraints,
+ YamlConfigArrayConstraints? arrayConstraints,
+ YamlConfigObjectConstraints? objectConstraints,
+ YamlConfigConstantValue? constantValue,
+ YamlConfigSchemaNode? negatedSchemaNode)
+ {
+ ReferenceTableName = referenceTableName;
+ AllowedValues = allowedValues;
+ Constraints = constraints;
+ ArrayConstraints = arrayConstraints;
+ ObjectConstraints = objectConstraints;
+ ConstantValue = constantValue;
+ NegatedSchemaNode = negatedSchemaNode;
+ }
+
+ public static NodeValidation None { get; } = new(
+ referenceTableName: null,
+ allowedValues: null,
+ constraints: null,
+ arrayConstraints: null,
+ objectConstraints: null,
+ constantValue: null,
+ negatedSchemaNode: null);
+
+ public string? ReferenceTableName { get; }
+
+ public IReadOnlyCollection? AllowedValues { get; }
+
+ public YamlConfigScalarConstraints? Constraints { get; }
+
+ public YamlConfigArrayConstraints? ArrayConstraints { get; }
+
+ public YamlConfigObjectConstraints? ObjectConstraints { get; }
+
+ public YamlConfigConstantValue? ConstantValue { get; }
+
+ public YamlConfigSchemaNode? NegatedSchemaNode { get; }
+
+ public NodeValidation WithReferenceTable(string referenceTableName)
+ {
+ return new NodeValidation(referenceTableName, AllowedValues, Constraints, ArrayConstraints,
+ ObjectConstraints, ConstantValue, NegatedSchemaNode);
+ }
+
+ public NodeValidation WithAllowedValues(IReadOnlyCollection? allowedValues)
+ {
+ return new NodeValidation(ReferenceTableName, allowedValues, Constraints, ArrayConstraints,
+ ObjectConstraints, ConstantValue, NegatedSchemaNode);
+ }
+
+ public NodeValidation WithConstantValue(YamlConfigConstantValue? constantValue)
+ {
+ return new NodeValidation(ReferenceTableName, AllowedValues, Constraints, ArrayConstraints,
+ ObjectConstraints, constantValue, NegatedSchemaNode);
+ }
+
+ public NodeValidation WithNegatedSchemaNode(YamlConfigSchemaNode? negatedSchemaNode)
+ {
+ return new NodeValidation(ReferenceTableName, AllowedValues, Constraints, ArrayConstraints,
+ ObjectConstraints, ConstantValue, negatedSchemaNode);
+ }
+ }
+}
diff --git a/GFramework.Game/Config/YamlConfigSchemaPropertyType.cs b/GFramework.Game/Config/YamlConfigSchemaPropertyType.cs
new file mode 100644
index 00000000..725819dc
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigSchemaPropertyType.cs
@@ -0,0 +1,37 @@
+namespace GFramework.Game.Config;
+
+///
+/// 表示当前运行时 schema 校验器支持的属性类型。
+///
+internal enum YamlConfigSchemaPropertyType
+{
+ ///
+ /// 对象类型。
+ ///
+ Object,
+
+ ///
+ /// 整数类型。
+ ///
+ Integer,
+
+ ///
+ /// 数值类型。
+ ///
+ Number,
+
+ ///
+ /// 布尔类型。
+ ///
+ Boolean,
+
+ ///
+ /// 字符串类型。
+ ///
+ String,
+
+ ///
+ /// 数组类型。
+ ///
+ Array
+}
diff --git a/GFramework.Game/Config/YamlConfigSchemaValidator.cs b/GFramework.Game/Config/YamlConfigSchemaValidator.cs
index 4350e035..42d187ce 100644
--- a/GFramework.Game/Config/YamlConfigSchemaValidator.cs
+++ b/GFramework.Game/Config/YamlConfigSchemaValidator.cs
@@ -3650,950 +3650,3 @@ internal static partial class YamlConfigSchemaValidator
!string.Equals(tag, "tag:yaml.org,2002:null", StringComparison.Ordinal);
}
}
-
-///
-/// 表示已解析并可用于运行时校验的 JSON Schema。
-/// 该模型保留根节点与引用依赖集合,避免运行时引入完整 schema 引擎。
-///
-internal sealed class YamlConfigSchema
-{
- ///
- /// 初始化一个可用于运行时校验的 schema 模型。
- ///
- /// Schema 文件路径。
- /// 根节点模型。
- /// Schema 声明的目标引用表名称集合。
- public YamlConfigSchema(
- string schemaPath,
- YamlConfigSchemaNode rootNode,
- IReadOnlyCollection referencedTableNames)
- {
- ArgumentNullException.ThrowIfNull(schemaPath);
- ArgumentNullException.ThrowIfNull(rootNode);
- ArgumentNullException.ThrowIfNull(referencedTableNames);
-
- SchemaPath = schemaPath;
- RootNode = rootNode;
- ReferencedTableNames = referencedTableNames;
- }
-
- ///
- /// 获取 schema 文件路径。
- ///
- public string SchemaPath { get; }
-
- ///
- /// 获取根节点模型。
- ///
- public YamlConfigSchemaNode RootNode { get; }
-
- ///
- /// 获取 schema 声明的目标引用表名称集合。
- /// 该信息用于热重载时推导受影响的依赖表闭包。
- ///
- public IReadOnlyCollection ReferencedTableNames { get; }
-}
-
-///
-/// 表示单个 schema 节点的最小运行时描述。
-/// 同一个模型同时覆盖对象、数组和标量,便于递归校验逻辑只依赖一种树结构。
-///
-internal sealed class YamlConfigSchemaNode
-{
- private readonly NodeChildren _children;
- private readonly NodeValidation _validation;
-
- private YamlConfigSchemaNode(
- YamlConfigSchemaPropertyType nodeType,
- NodeChildren children,
- NodeValidation validation,
- string schemaPathHint)
- {
- ArgumentNullException.ThrowIfNull(children);
- ArgumentNullException.ThrowIfNull(validation);
- ArgumentNullException.ThrowIfNull(schemaPathHint);
-
- _children = children;
- _validation = validation;
- NodeType = nodeType;
- Properties = children.Properties;
- RequiredProperties = children.RequiredProperties;
- ItemNode = children.ItemNode;
- ReferenceTableName = validation.ReferenceTableName;
- AllowedValues = validation.AllowedValues;
- Constraints = validation.Constraints;
- ArrayConstraints = validation.ArrayConstraints;
- ObjectConstraints = validation.ObjectConstraints;
- ConstantValue = validation.ConstantValue;
- NegatedSchemaNode = validation.NegatedSchemaNode;
- SchemaPathHint = schemaPathHint;
- }
-
- ///
- /// 获取节点类型。
- ///
- public YamlConfigSchemaPropertyType NodeType { get; }
-
- ///
- /// 获取对象属性集合;非对象节点时返回空。
- ///
- public IReadOnlyDictionary? Properties { get; }
-
- ///
- /// 获取对象必填属性集合;非对象节点时返回空。
- ///
- public IReadOnlyCollection? RequiredProperties { get; }
-
- ///
- /// 获取数组元素节点;非数组节点时返回空。
- ///
- public YamlConfigSchemaNode? ItemNode { get; }
-
- ///
- /// 获取目标引用表名称;未声明跨表引用时返回空。
- ///
- public string? ReferenceTableName { get; }
-
- ///
- /// 获取节点允许值集合;未声明 enum 时返回空。
- ///
- public IReadOnlyCollection? AllowedValues { get; }
-
- ///
- /// 获取标量范围与长度约束;未声明时返回空。
- ///
- public YamlConfigScalarConstraints? Constraints { get; }
-
- ///
- /// 获取对象属性数量约束;未声明时返回空。
- ///
- public YamlConfigObjectConstraints? ObjectConstraints { get; }
-
- ///
- /// 获取数组元素数量约束;未声明时返回空。
- ///
- public YamlConfigArrayConstraints? ArrayConstraints { get; }
-
- ///
- /// 获取节点常量约束;未声明 const 时返回空。
- ///
- public YamlConfigConstantValue? ConstantValue { get; }
-
- ///
- /// 获取节点声明的 not 子 schema;未声明时返回空。
- ///
- public YamlConfigSchemaNode? NegatedSchemaNode { get; }
-
- ///
- /// 获取用于诊断显示的 schema 路径提示。
- /// 当前节点本身不记录独立路径,因此对象校验会回退到所属根 schema 路径。
- ///
- public string SchemaPathHint { get; }
-
- ///
- /// 创建对象节点描述。
- ///
- /// 对象属性集合。
- /// 对象必填属性集合。
- /// 对象属性数量约束。
- /// 用于错误信息的 schema 文件路径提示。
- /// 对象节点模型。
- public static YamlConfigSchemaNode CreateObject(
- IReadOnlyDictionary? properties,
- IReadOnlyCollection? requiredProperties,
- YamlConfigObjectConstraints? objectConstraints,
- string schemaPathHint)
- {
- return new YamlConfigSchemaNode(
- YamlConfigSchemaPropertyType.Object,
- new NodeChildren(properties, requiredProperties, itemNode: null),
- new NodeValidation(
- referenceTableName: null,
- allowedValues: null,
- constraints: null,
- arrayConstraints: null,
- objectConstraints,
- constantValue: null,
- negatedSchemaNode: null),
- schemaPathHint);
- }
-
- ///
- /// 创建数组节点描述。
- ///
- /// 数组元素节点。
- /// 数组节点允许值集合。
- /// 数组元素数量约束。
- /// 用于错误信息的 schema 文件路径提示。
- /// 数组节点模型。
- public static YamlConfigSchemaNode CreateArray(
- YamlConfigSchemaNode itemNode,
- IReadOnlyCollection? allowedValues,
- YamlConfigArrayConstraints? arrayConstraints,
- string schemaPathHint)
- {
- return new YamlConfigSchemaNode(
- YamlConfigSchemaPropertyType.Array,
- new NodeChildren(properties: null, requiredProperties: null, itemNode),
- new NodeValidation(
- referenceTableName: null,
- allowedValues,
- constraints: null,
- arrayConstraints,
- objectConstraints: null,
- constantValue: null,
- negatedSchemaNode: null),
- schemaPathHint);
- }
-
- ///
- /// 创建标量节点描述。
- ///
- /// 标量节点类型。
- /// 目标引用表名称。
- /// 标量允许值集合。
- /// 标量范围与长度约束。
- /// 用于错误信息的 schema 文件路径提示。
- /// 标量节点模型。
- public static YamlConfigSchemaNode CreateScalar(
- YamlConfigSchemaPropertyType nodeType,
- string? referenceTableName,
- IReadOnlyCollection? allowedValues,
- YamlConfigScalarConstraints? constraints,
- string schemaPathHint)
- {
- return new YamlConfigSchemaNode(
- nodeType,
- NodeChildren.None,
- new NodeValidation(
- referenceTableName,
- allowedValues,
- constraints,
- arrayConstraints: null,
- objectConstraints: null,
- constantValue: null,
- negatedSchemaNode: null),
- schemaPathHint);
- }
-
- ///
- /// 基于当前节点复制一个只替换引用表名称的新节点。
- /// 该方法用于把数组级别的 ref-table 语义挂接到元素节点上。
- ///
- /// 新的目标引用表名称。
- /// 复制后的节点。
- public YamlConfigSchemaNode WithReferenceTable(string referenceTableName)
- {
- return new YamlConfigSchemaNode(
- NodeType,
- _children,
- _validation.WithReferenceTable(referenceTableName),
- SchemaPathHint);
- }
-
- ///
- /// 基于当前节点复制一个只替换 enum 允许值集合的新节点。
- ///
- /// 新的允许值集合。
- /// 复制后的节点。
- public YamlConfigSchemaNode WithAllowedValues(IReadOnlyCollection? allowedValues)
- {
- return new YamlConfigSchemaNode(
- NodeType,
- _children,
- _validation.WithAllowedValues(allowedValues),
- SchemaPathHint);
- }
-
- ///
- /// 基于当前节点复制一个只替换常量约束的新节点。
- ///
- /// 新的常量约束。
- /// 复制后的节点。
- public YamlConfigSchemaNode WithConstantValue(YamlConfigConstantValue? constantValue)
- {
- return new YamlConfigSchemaNode(
- NodeType,
- _children,
- _validation.WithConstantValue(constantValue),
- SchemaPathHint);
- }
-
- ///
- /// 基于当前节点复制一个只替换 not 子 schema 的新节点。
- ///
- /// 新的 negated schema。
- /// 复制后的节点。
- public YamlConfigSchemaNode WithNegatedSchemaNode(YamlConfigSchemaNode? negatedSchemaNode)
- {
- return new YamlConfigSchemaNode(
- NodeType,
- _children,
- _validation.WithNegatedSchemaNode(negatedSchemaNode),
- SchemaPathHint);
- }
-
- private sealed class NodeChildren
- {
- public NodeChildren(
- IReadOnlyDictionary? properties,
- IReadOnlyCollection? requiredProperties,
- YamlConfigSchemaNode? itemNode)
- {
- Properties = properties;
- RequiredProperties = requiredProperties;
- ItemNode = itemNode;
- }
-
- public static NodeChildren None { get; } = new(properties: null, requiredProperties: null, itemNode: null);
-
- public IReadOnlyDictionary? Properties { get; }
-
- public IReadOnlyCollection? RequiredProperties { get; }
-
- public YamlConfigSchemaNode? ItemNode { get; }
- }
-
- private sealed class NodeValidation
- {
- public NodeValidation(
- string? referenceTableName,
- IReadOnlyCollection? allowedValues,
- YamlConfigScalarConstraints? constraints,
- YamlConfigArrayConstraints? arrayConstraints,
- YamlConfigObjectConstraints? objectConstraints,
- YamlConfigConstantValue? constantValue,
- YamlConfigSchemaNode? negatedSchemaNode)
- {
- ReferenceTableName = referenceTableName;
- AllowedValues = allowedValues;
- Constraints = constraints;
- ArrayConstraints = arrayConstraints;
- ObjectConstraints = objectConstraints;
- ConstantValue = constantValue;
- NegatedSchemaNode = negatedSchemaNode;
- }
-
- public static NodeValidation None { get; } = new(
- referenceTableName: null,
- allowedValues: null,
- constraints: null,
- arrayConstraints: null,
- objectConstraints: null,
- constantValue: null,
- negatedSchemaNode: null);
-
- public string? ReferenceTableName { get; }
-
- public IReadOnlyCollection? AllowedValues { get; }
-
- public YamlConfigScalarConstraints? Constraints { get; }
-
- public YamlConfigArrayConstraints? ArrayConstraints { get; }
-
- public YamlConfigObjectConstraints? ObjectConstraints { get; }
-
- public YamlConfigConstantValue? ConstantValue { get; }
-
- public YamlConfigSchemaNode? NegatedSchemaNode { get; }
-
- public NodeValidation WithReferenceTable(string referenceTableName)
- {
- return new NodeValidation(referenceTableName, AllowedValues, Constraints, ArrayConstraints,
- ObjectConstraints, ConstantValue, NegatedSchemaNode);
- }
-
- public NodeValidation WithAllowedValues(IReadOnlyCollection? allowedValues)
- {
- return new NodeValidation(ReferenceTableName, allowedValues, Constraints, ArrayConstraints,
- ObjectConstraints, ConstantValue, NegatedSchemaNode);
- }
-
- public NodeValidation WithConstantValue(YamlConfigConstantValue? constantValue)
- {
- return new NodeValidation(ReferenceTableName, AllowedValues, Constraints, ArrayConstraints,
- ObjectConstraints, constantValue, NegatedSchemaNode);
- }
-
- public NodeValidation WithNegatedSchemaNode(YamlConfigSchemaNode? negatedSchemaNode)
- {
- return new NodeValidation(ReferenceTableName, AllowedValues, Constraints, ArrayConstraints,
- ObjectConstraints, ConstantValue, negatedSchemaNode);
- }
- }
-}
-
-///
-/// 表示一个节点上声明的 const 约束。
-/// 该模型同时保留稳定比较键与原始 JSON 文本,分别供运行时匹配和诊断输出复用。
-///
-internal sealed class YamlConfigConstantValue
-{
- ///
- /// 初始化常量约束模型。
- ///
- /// 用于与 YAML 节点比较的稳定键。
- /// 用于诊断输出的原始常量文本。
- public YamlConfigConstantValue(string comparableValue, string displayValue)
- {
- ArgumentNullException.ThrowIfNull(comparableValue);
- ArgumentException.ThrowIfNullOrWhiteSpace(displayValue);
-
- ComparableValue = comparableValue;
- DisplayValue = displayValue;
- }
-
- ///
- /// 获取用于运行时比较的稳定键。
- ///
- public string ComparableValue { get; }
-
- ///
- /// 获取用于诊断输出的原始 JSON 常量文本。
- ///
- public string DisplayValue { get; }
-}
-
-///
-/// 表示一个节点上声明的单个 enum 候选值。
-/// 该模型同时保留稳定比较键与原始 JSON 文本,分别供运行时匹配和诊断输出复用。
-///
-internal sealed class YamlConfigAllowedValue
-{
- ///
- /// 初始化一个枚举候选值模型。
- ///
- /// 用于与 YAML 节点比较的稳定键。
- /// 用于诊断输出的原始 JSON 文本。
- public YamlConfigAllowedValue(string comparableValue, string displayValue)
- {
- ArgumentNullException.ThrowIfNull(comparableValue);
- ArgumentException.ThrowIfNullOrWhiteSpace(displayValue);
-
- ComparableValue = comparableValue;
- DisplayValue = displayValue;
- }
-
- ///
- /// 获取用于运行时比较的稳定键。
- ///
- public string ComparableValue { get; }
-
- ///
- /// 获取用于诊断输出的原始 JSON 文本。
- ///
- public string DisplayValue { get; }
-}
-
-///
-/// 表示一个对象节点上声明的属性数量约束、字段依赖约束、条件子 schema 与组合约束。
-/// 该模型将对象级约束与数组 / 标量约束拆开保存,避免运行时节点继续暴露无关成员。
-///
-internal sealed class YamlConfigObjectConstraints
-{
- ///
- /// 初始化对象约束模型。
- ///
- /// 最小属性数量约束。
- /// 最大属性数量约束。
- /// 对象内字段依赖约束。
- /// 对象内条件 schema 约束。
- /// 对象内组合 schema 约束。
- /// 对象内条件分支约束。
- public YamlConfigObjectConstraints(
- int? minProperties,
- int? maxProperties,
- IReadOnlyDictionary>? dependentRequired,
- IReadOnlyDictionary? dependentSchemas,
- IReadOnlyList? allOfSchemas,
- YamlConfigConditionalSchemas? conditionalSchemas)
- {
- MinProperties = minProperties;
- MaxProperties = maxProperties;
- DependentRequired = dependentRequired;
- DependentSchemas = dependentSchemas;
- AllOfSchemas = allOfSchemas;
- ConditionalSchemas = conditionalSchemas;
- }
-
- ///
- /// 获取最小属性数量约束。
- ///
- public int? MinProperties { get; }
-
- ///
- /// 获取最大属性数量约束。
- ///
- public int? MaxProperties { get; }
-
- ///
- /// 获取对象内字段依赖约束。
- /// 键表示“触发字段”,值表示“触发字段出现后还必须存在的同级字段集合”。
- ///
- public IReadOnlyDictionary>? DependentRequired { get; }
-
- ///
- /// 获取对象内条件 schema 约束。
- /// 键表示“触发字段”,值表示“触发字段出现后当前对象还必须满足的额外 schema 子树”。
- ///
- public IReadOnlyDictionary? DependentSchemas { get; }
-
- ///
- /// 获取对象内 allOf 组合约束。
- /// 每个条目都表示“当前对象还必须额外满足的 focused constraint block”。
- ///
- public IReadOnlyList? AllOfSchemas { get; }
-
- ///
- /// 获取对象内 object-focused if / then / else 条件约束。
- /// 该模型会先用 if 试匹配当前对象,再只对命中的分支叠加 focused constraint block。
- ///
- public YamlConfigConditionalSchemas? ConditionalSchemas { get; }
-}
-
-///
-/// 表示一个对象节点上声明的 object-focused if / then / else 条件约束。
-/// 三个分支都共享父对象已声明字段集合,不会把分支 schema 扩展成新的生成类型形状。
-///
-internal sealed class YamlConfigConditionalSchemas
-{
- ///
- /// 初始化条件分支约束模型。
- ///
- /// 条件判断 schema。
- /// 条件命中时需要满足的 schema。
- /// 条件未命中时需要满足的 schema。
- public YamlConfigConditionalSchemas(
- YamlConfigSchemaNode ifSchema,
- YamlConfigSchemaNode? thenSchema,
- YamlConfigSchemaNode? elseSchema)
- {
- ArgumentNullException.ThrowIfNull(ifSchema);
-
- IfSchema = ifSchema;
- ThenSchema = thenSchema;
- ElseSchema = elseSchema;
- }
-
- ///
- /// 获取条件判断 schema。
- ///
- public YamlConfigSchemaNode IfSchema { get; }
-
- ///
- /// 获取条件命中时需要满足的 schema。
- ///
- public YamlConfigSchemaNode? ThenSchema { get; }
-
- ///
- /// 获取条件未命中时需要满足的 schema。
- ///
- public YamlConfigSchemaNode? ElseSchema { get; }
-}
-
-///
-/// 聚合一个标量节点上声明的数值约束与字符串约束。
-/// 该包装层保留“标量字段有约束”的统一入口,同时把不同语义的约束分成更小的专用模型。
-///
-internal sealed class YamlConfigScalarConstraints
-{
- ///
- /// 初始化标量约束模型。
- ///
- /// 数值约束分组。
- /// 字符串约束分组。
- public YamlConfigScalarConstraints(
- YamlConfigNumericConstraints? numericConstraints,
- YamlConfigStringConstraints? stringConstraints)
- {
- NumericConstraints = numericConstraints;
- StringConstraints = stringConstraints;
- }
-
- ///
- /// 获取数值约束分组。
- ///
- public YamlConfigNumericConstraints? NumericConstraints { get; }
-
- ///
- /// 获取字符串约束分组。
- ///
- public YamlConfigStringConstraints? StringConstraints { get; }
-}
-
-///
-/// 表示标量节点上声明的数值范围与步进约束。
-/// 该类型只覆盖整数 / 浮点共享的关键字,避免字符串字段继续暴露不相关的成员。
-///
-internal sealed class YamlConfigNumericConstraints
-{
- ///
- /// 初始化数值约束模型。
- ///
- /// 最小值约束。
- /// 最大值约束。
- /// 开区间最小值约束。
- /// 开区间最大值约束。
- /// 数值步进约束。
- public YamlConfigNumericConstraints(
- double? minimum,
- double? maximum,
- double? exclusiveMinimum,
- double? exclusiveMaximum,
- double? multipleOf)
- {
- Minimum = minimum;
- Maximum = maximum;
- ExclusiveMinimum = exclusiveMinimum;
- ExclusiveMaximum = exclusiveMaximum;
- MultipleOf = multipleOf;
- }
-
- ///
- /// 获取最小值约束。
- ///
- public double? Minimum { get; }
-
- ///
- /// 获取最大值约束。
- ///
- public double? Maximum { get; }
-
- ///
- /// 获取开区间最小值约束。
- ///
- public double? ExclusiveMinimum { get; }
-
- ///
- /// 获取开区间最大值约束。
- ///
- public double? ExclusiveMaximum { get; }
-
- ///
- /// 获取数值步进约束。
- ///
- public double? MultipleOf { get; }
-}
-
-///
-/// 表示标量节点上声明的字符串长度、模式与 format 约束。
-/// 该模型将正则原文、预编译正则和共享 format 枚举绑定保存,
-/// 保证诊断内容与运行时匹配逻辑保持一致。
-///
-internal sealed class YamlConfigStringConstraints
-{
- ///
- /// 初始化字符串约束模型。
- ///
- /// 最小长度约束。
- /// 最大长度约束。
- /// 正则模式约束原文。
- /// 已编译的正则表达式。
- /// 字符串 format 约束。
- public YamlConfigStringConstraints(
- int? minLength,
- int? maxLength,
- string? pattern,
- Regex? patternRegex,
- YamlConfigStringFormatConstraint? formatConstraint)
- {
- MinLength = minLength;
- MaxLength = maxLength;
- Pattern = pattern;
- PatternRegex = patternRegex;
- FormatConstraint = formatConstraint;
- }
-
- ///
- /// 获取最小长度约束。
- ///
- public int? MinLength { get; }
-
- ///
- /// 获取最大长度约束。
- ///
- public int? MaxLength { get; }
-
- ///
- /// 获取正则模式约束原文。
- ///
- public string? Pattern { get; }
-
- ///
- /// 获取已编译的正则表达式。
- ///
- public Regex? PatternRegex { get; }
-
- ///
- /// 获取字符串 format 约束。
- ///
- public YamlConfigStringFormatConstraint? FormatConstraint { get; }
-}
-
-///
-/// 表示一个已归一化的字符串 format 约束。
-/// 该模型同时保留 schema 原文与共享枚举,方便诊断信息稳定展示,又避免运行时校验反复解析字符串。
-///
-internal sealed class YamlConfigStringFormatConstraint
-{
- ///
- /// 初始化字符串 format 约束模型。
- ///
- /// schema 中声明的 format 名称。
- /// 归一化后的共享 format 枚举。
- public YamlConfigStringFormatConstraint(
- string schemaName,
- YamlConfigStringFormatKind kind)
- {
- ArgumentException.ThrowIfNullOrWhiteSpace(schemaName);
-
- SchemaName = schemaName;
- Kind = kind;
- }
-
- ///
- /// 获取 schema 中声明的 format 名称。
- ///
- public string SchemaName { get; }
-
- ///
- /// 获取归一化后的共享 format 枚举。
- ///
- public YamlConfigStringFormatKind Kind { get; }
-}
-
-///
-/// 表示当前 Runtime / Generator / Tooling 共享支持的字符串 format 子集。
-///
-internal enum YamlConfigStringFormatKind
-{
- ///
- /// 表示 yyyy-MM-dd 形式的日期。
- ///
- Date,
-
- ///
- /// 表示带显式时区偏移的 RFC 3339 日期时间。
- ///
- DateTime,
-
- ///
- /// 表示 day-time duration 形式的持续时间。
- ///
- Duration,
-
- ///
- /// 表示基础电子邮件地址格式。
- ///
- Email,
-
- ///
- /// 表示带显式时区偏移的 RFC 3339 时间。
- ///
- Time,
-
- ///
- /// 表示绝对 URI。
- ///
- Uri,
-
- ///
- /// 表示连字符分隔的 UUID 文本。
- ///
- Uuid
-}
-
-///
-/// 表示一个数组节点上声明的元素数量、去重与 contains 匹配计数约束。
-/// 该模型与标量约束拆分保存,避免数组节点继续共享不适用的标量字段。
-///
-internal sealed class YamlConfigArrayConstraints
-{
- ///
- /// 初始化数组约束模型。
- ///
- /// 最小元素数量约束。
- /// 最大元素数量约束。
- /// 是否要求数组元素唯一。
- /// 数组 contains 约束;未声明时为空。
- public YamlConfigArrayConstraints(
- int? minItems,
- int? maxItems,
- bool uniqueItems,
- YamlConfigArrayContainsConstraints? containsConstraints)
- {
- MinItems = minItems;
- MaxItems = maxItems;
- UniqueItems = uniqueItems;
- ContainsConstraints = containsConstraints;
- }
-
- ///
- /// 获取最小元素数量约束。
- ///
- public int? MinItems { get; }
-
- ///
- /// 获取最大元素数量约束。
- ///
- public int? MaxItems { get; }
-
- ///
- /// 获取是否要求数组元素唯一。
- ///
- public bool UniqueItems { get; }
-
- ///
- /// 获取数组 contains 约束;未声明时返回空。
- ///
- public YamlConfigArrayContainsConstraints? ContainsConstraints { get; }
-}
-
-///
-/// 表示数组节点声明的 contains 匹配约束。
-/// 该模型把 contains 子 schema 与匹配数量边界聚合在一起,避免数组节点再额外散落多组相关成员。
-///
-internal sealed class YamlConfigArrayContainsConstraints
-{
- ///
- /// 初始化数组 contains 约束模型。
- ///
- /// contains 子 schema。
- /// 最小匹配数量;为 时按 JSON Schema 语义默认 1。
- /// 最大匹配数量。
- public YamlConfigArrayContainsConstraints(
- YamlConfigSchemaNode containsNode,
- int? minContains,
- int? maxContains)
- {
- ArgumentNullException.ThrowIfNull(containsNode);
-
- ContainsNode = containsNode;
- MinContains = minContains;
- MaxContains = maxContains;
- }
-
- ///
- /// 获取 contains 子 schema。
- ///
- public YamlConfigSchemaNode ContainsNode { get; }
-
- ///
- /// 获取最小匹配数量;未显式声明时返回空,由调用方按默认值 1 解释。
- ///
- public int? MinContains { get; }
-
- ///
- /// 获取最大匹配数量。
- ///
- public int? MaxContains { get; }
-}
-
-///
-/// 表示单个 YAML 文件中提取出的跨表引用。
-/// 该模型保留源文件、字段路径和目标表等诊断信息,以便加载器在批量校验失败时给出可定位的错误。
-///
-internal sealed class YamlConfigReferenceUsage
-{
- ///
- /// 初始化一个跨表引用使用记录。
- ///
- /// 源 YAML 文件路径。
- /// 定义该引用的 schema 文件路径。
- /// 声明引用的字段路径。
- /// YAML 中的原始标量值。
- /// 目标配置表名称。
- /// 引用值的 schema 标量类型。
- public YamlConfigReferenceUsage(
- string yamlPath,
- string schemaPath,
- string propertyPath,
- string rawValue,
- string referencedTableName,
- YamlConfigSchemaPropertyType valueType)
- {
- ArgumentNullException.ThrowIfNull(yamlPath);
- ArgumentNullException.ThrowIfNull(schemaPath);
- ArgumentNullException.ThrowIfNull(propertyPath);
- ArgumentNullException.ThrowIfNull(rawValue);
- ArgumentNullException.ThrowIfNull(referencedTableName);
-
- YamlPath = yamlPath;
- SchemaPath = schemaPath;
- PropertyPath = propertyPath;
- RawValue = rawValue;
- ReferencedTableName = referencedTableName;
- ValueType = valueType;
- }
-
- ///
- /// 获取源 YAML 文件路径。
- ///
- public string YamlPath { get; }
-
- ///
- /// 获取定义该引用的 schema 文件路径。
- ///
- public string SchemaPath { get; }
-
- ///
- /// 获取声明引用的字段路径。
- ///
- public string PropertyPath { get; }
-
- ///
- /// 获取 YAML 中的原始标量值。
- ///
- public string RawValue { get; }
-
- ///
- /// 获取目标配置表名称。
- ///
- public string ReferencedTableName { get; }
-
- ///
- /// 获取引用值的 schema 标量类型。
- ///
- public YamlConfigSchemaPropertyType ValueType { get; }
-
- ///
- /// 获取便于诊断显示的字段路径。
- ///
- public string DisplayPath => PropertyPath;
-}
-
-///
-/// 表示当前运行时 schema 校验器支持的属性类型。
-///
-internal enum YamlConfigSchemaPropertyType
-{
- ///
- /// 对象类型。
- ///
- Object,
-
- ///
- /// 整数类型。
- ///
- Integer,
-
- ///
- /// 数值类型。
- ///
- Number,
-
- ///
- /// 布尔类型。
- ///
- Boolean,
-
- ///
- /// 字符串类型。
- ///
- String,
-
- ///
- /// 数组类型。
- ///
- Array
-}
diff --git a/GFramework.Game/Config/YamlConfigStringConstraints.cs b/GFramework.Game/Config/YamlConfigStringConstraints.cs
new file mode 100644
index 00000000..efb75840
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigStringConstraints.cs
@@ -0,0 +1,58 @@
+using System.Text.RegularExpressions;
+
+namespace GFramework.Game.Config;
+
+///
+/// 表示标量节点上声明的字符串长度、模式与 format 约束。
+/// 该模型将正则原文、预编译正则和共享 format 枚举绑定保存,
+/// 保证诊断内容与运行时匹配逻辑保持一致。
+///
+internal sealed class YamlConfigStringConstraints
+{
+ ///
+ /// 初始化字符串约束模型。
+ ///
+ /// 最小长度约束。
+ /// 最大长度约束。
+ /// 正则模式约束原文。
+ /// 已编译的正则表达式。
+ /// 字符串 format 约束。
+ public YamlConfigStringConstraints(
+ int? minLength,
+ int? maxLength,
+ string? pattern,
+ Regex? patternRegex,
+ YamlConfigStringFormatConstraint? formatConstraint)
+ {
+ MinLength = minLength;
+ MaxLength = maxLength;
+ Pattern = pattern;
+ PatternRegex = patternRegex;
+ FormatConstraint = formatConstraint;
+ }
+
+ ///
+ /// 获取最小长度约束。
+ ///
+ public int? MinLength { get; }
+
+ ///
+ /// 获取最大长度约束。
+ ///
+ public int? MaxLength { get; }
+
+ ///
+ /// 获取正则模式约束原文。
+ ///
+ public string? Pattern { get; }
+
+ ///
+ /// 获取已编译的正则表达式。
+ ///
+ public Regex? PatternRegex { get; }
+
+ ///
+ /// 获取字符串 format 约束。
+ ///
+ public YamlConfigStringFormatConstraint? FormatConstraint { get; }
+}
diff --git a/GFramework.Game/Config/YamlConfigStringFormatConstraint.cs b/GFramework.Game/Config/YamlConfigStringFormatConstraint.cs
new file mode 100644
index 00000000..97c3a262
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigStringFormatConstraint.cs
@@ -0,0 +1,33 @@
+namespace GFramework.Game.Config;
+
+///
+/// 表示一个已归一化的字符串 format 约束。
+/// 该模型同时保留 schema 原文与共享枚举,方便诊断信息稳定展示,又避免运行时校验反复解析字符串。
+///
+internal sealed class YamlConfigStringFormatConstraint
+{
+ ///
+ /// 初始化字符串 format 约束模型。
+ ///
+ /// schema 中声明的 format 名称。
+ /// 归一化后的共享 format 枚举。
+ public YamlConfigStringFormatConstraint(
+ string schemaName,
+ YamlConfigStringFormatKind kind)
+ {
+ ArgumentException.ThrowIfNullOrWhiteSpace(schemaName);
+
+ SchemaName = schemaName;
+ Kind = kind;
+ }
+
+ ///
+ /// 获取 schema 中声明的 format 名称。
+ ///
+ public string SchemaName { get; }
+
+ ///
+ /// 获取归一化后的共享 format 枚举。
+ ///
+ public YamlConfigStringFormatKind Kind { get; }
+}
diff --git a/GFramework.Game/Config/YamlConfigStringFormatKind.cs b/GFramework.Game/Config/YamlConfigStringFormatKind.cs
new file mode 100644
index 00000000..bb13a63c
--- /dev/null
+++ b/GFramework.Game/Config/YamlConfigStringFormatKind.cs
@@ -0,0 +1,42 @@
+namespace GFramework.Game.Config;
+
+///
+/// 表示当前 Runtime / Generator / Tooling 共享支持的字符串 format 子集。
+///
+internal enum YamlConfigStringFormatKind
+{
+ ///
+ /// 表示 yyyy-MM-dd 形式的日期。
+ ///
+ Date,
+
+ ///
+ /// 表示带显式时区偏移的 RFC 3339 日期时间。
+ ///
+ DateTime,
+
+ ///
+ /// 表示 day-time duration 形式的持续时间。
+ ///
+ Duration,
+
+ ///
+ /// 表示基础电子邮件地址格式。
+ ///
+ Email,
+
+ ///
+ /// 表示带显式时区偏移的 RFC 3339 时间。
+ ///
+ Time,
+
+ ///
+ /// 表示绝对 URI。
+ ///
+ Uri,
+
+ ///
+ /// 表示连字符分隔的 UUID 文本。
+ ///
+ Uuid
+}
diff --git a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
index 920e3240..cc61a5bb 100644
--- a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
+++ b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md
@@ -12,7 +12,8 @@
- `2026-04-29` 使用 `$gframework-batch-boot 50` 从 clean build warning 基线继续分批清理 analyzer warnings
- 已接受三个 worker 的 `GFramework.Cqrs.Tests/Mediator/*` 独立切片,三个 Mediator 测试文件的 warning 已清零
- 主线程补齐 `YamlConfigSchemaValidator` 运行时正则 timeout 与 ordinal 字符串比较,先收掉低风险 `MA0009` / `MA0006`
- - 当前停止条件为相对 `origin/main` 接近 `50` 个变更文件;本轮尚未接近阈值,下一批可继续处理 `GFramework.Game/Config/YamlConfigSchemaValidator*`
+ - 已收口两个 Game 追加切片:`YamlConfigSchemaValidator.ObjectKeywords.cs` 方法拆分与 schema model 类型拆文件
+ - 当前停止条件为相对 `origin/main` 接近 `50` 个变更文件;本轮按用户要求到此结束,不再继续开新切片
## 当前活跃事实
@@ -21,27 +22,30 @@
- `dotnet clean -p:RestoreFallbackFolders= -v:quiet`
- 最新结果:成功;标准 `dotnet clean` 仍会先命中当前 WSL 环境的 Windows NuGet fallback 目录,已按既有环境口径先执行 `dotnet restore GFramework.sln -p:RestoreFallbackFolders= --disable-parallel` 后清理
- `dotnet build -p:RestoreFallbackFolders= -clp:WarningsOnly -v:minimal -m:1 -nodeReuse:false`
- - 最新结果:成功;`75` warnings、`0` errors;warning 从本轮基线 `236` 降到 `75`
+ - 最新结果:成功;`15` warnings、`0` errors;warning 从本轮基线 `236` 降到 `15`
- `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release -p:RestoreFallbackFolders= -m:1 -nodeReuse:false -clp:Summary`
- 最新结果:成功;`0 Warning(s)`、`0 Error(s)`
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~Mediator"`
- 最新结果:成功;`45` 通过、`0` 失败
- `dotnet build GFramework.Game/GFramework.Game.csproj -c Release -p:RestoreFallbackFolders= -m:1 -nodeReuse:false -clp:Summary`
- - 最新结果:成功;`75 Warning(s)`、`0 Error(s)`;剩余均为 `YamlConfigSchemaValidator*` 的 `MA0048` / `MA0051`
+ - 最新结果:成功;`0 Warning(s)`、`0 Error(s)`
- `dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~YamlConfigLoaderTests|FullyQualifiedName~YamlConfigSchemaValidatorTests"`
- 最新结果:成功;`80` 通过、`0` 失败
- 当前批次摘要:
- - 当前已提交分支相对 `origin/main...HEAD` 包含 `3` 个变更文件;本次主线程待提交的 `GFramework.Game/Config/YamlConfigSchemaValidator.cs` 与 `ai-plan` 文档会把累计变更推到约 `6` 个文件,低于 `50` 个文件阈值
+ - 当前分支提交后预计相对 `origin/main...HEAD` 包含 `22` 个变更文件,低于 `50` 个文件阈值
- 已完成 worker 切片:
- `ed269d4`:`MediatorArchitectureIntegrationTests.cs`,清理 `MA0048` / `MA0004` / `MA0016`
- `121df44`:`MediatorAdvancedFeaturesTests.cs`,清理 `MA0048` / `MA0004` / `MA0015`
- `9109eec`:`MediatorComprehensiveTests.cs`,清理 `MA0048` / `MA0004` / `MA0016` / `MA0002` / `MA0015`
- 主线程切片:`YamlConfigSchemaValidator.cs` 正则 timeout 与 ordinal equality,清理 `MA0009` / `MA0006`
+ - Game 追加切片:
+ - `1395b84`:`YamlConfigSchemaValidator.ObjectKeywords.cs`,清理该文件 `MA0051`
+ - 待提交:将 `YamlConfigSchemaValidator.cs` 末尾 schema model 类型拆到独立同名文件,清理 `MA0048`
## 当前风险
-- `GFramework.Game/Config/YamlConfigSchemaValidator*` 仍然是仓库根 warning 热点,剩余 `45` 条 `MA0048` 与 `30` 条 `MA0051`。
- - 缓解措施:下一批优先把 `YamlConfigSchemaValidator.cs` 末尾 schema model 类型拆到独立文件,再评估 `MA0051` 方法拆分。
+- `GFramework.Game/Config/YamlConfigSchemaValidator.cs` 仍有 `5` 个 `MA0051` 方法长度 warning,跨 `net8.0` / `net9.0` / `net10.0` 重复为 `15` 条。
+ - 缓解措施:下一轮只做主 validator 方法拆分,不再混入拆文件或正则安全修复。
- 标准 `dotnet clean` 在当前 WSL 环境仍会读取失效的 Windows fallback package folder。
- 缓解措施:本主题验证继续沿用 `-p:RestoreFallbackFolders=`,必要时先执行 solution restore 刷新 Linux 侧资产。
@@ -65,12 +69,12 @@
- 权威验证结果统一维护在“当前活跃事实”。
- `GFramework.Cqrs.Tests` 的当前受影响项目 Release 构建已清零,并通过 Mediator 定向测试回归。
-- `GFramework.Game` 当前低风险正则 / 字符串比较切片通过 Release 构建与 config 定向测试;剩余 warning 属于拆文件与复杂度拆分。
+- `GFramework.Game` 当前 Release 构建已清零,并通过 config 定向测试;仓库 Debug 构建剩余 warning 属于主 validator 方法复杂度拆分。
- `git diff --check` 结果为空,说明本轮新增改动没有引入新的尾随空格或冲突标记。
- warning reduction 的仓库级真值以同轮 `dotnet build`、定向 `dotnet test` 与 `git diff --check` 为准,并与 trace 中的验证里程碑保持一致。
## 下一步建议
-1. 提交主线程 `YamlConfigSchemaValidator` 正则安全补丁与本轮 `ai-plan` 同步。
-2. 继续下一批 `GFramework.Game/Config/YamlConfigSchemaValidator.cs` 末尾 schema model 类型拆文件,目标清理 `MA0048`。
-3. 再评估 `YamlConfigSchemaValidator.ObjectKeywords.cs` 与主 validator 的 `MA0051` 方法拆分,避免单批触碰过多高耦合逻辑。
+1. 提交 schema model 拆文件与本轮 `ai-plan` 收口。
+2. 下一轮只处理 `GFramework.Game/Config/YamlConfigSchemaValidator.cs` 剩余 `MA0051` 方法拆分。
+3. 保持 `RestoreFallbackFolders=` 验证口径,避免当前 WSL fallback package folder 干扰。
diff --git a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
index 95d3f165..f6b4be3f 100644
--- a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
+++ b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md
@@ -17,27 +17,33 @@
- 主线程实施:
- 在 `GFramework.Game/Config/YamlConfigSchemaValidator.cs` 为固定格式正则与 schema `pattern` 正则补充 timeout,避免运行时正则输入继续触发 `MA0009`
- 将三处字符串等值比较改为 ordinal `string.Equals`,清理 `MA0006`
+ - 接受 `1395b84` 的 `YamlConfigSchemaValidator.ObjectKeywords.cs` 方法拆分,清理该文件 `MA0051`
+ - 收口被中止 worker 留下的 schema model 拆文件变更,将 `YamlConfigSchemaValidator.cs` 末尾类型移动到同名文件,清理 `MA0048`
- 验证里程碑:
- `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release -p:RestoreFallbackFolders= -m:1 -nodeReuse:false -clp:Summary`
- 结果:成功;`0 Warning(s)`、`0 Error(s)`
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~Mediator"`
- 结果:成功;`45` 通过、`0` 失败
- `dotnet build GFramework.Game/GFramework.Game.csproj -c Release -p:RestoreFallbackFolders= -m:1 -nodeReuse:false -clp:Summary`
- - 结果:成功;`75 Warning(s)`、`0 Error(s)`
+ - 结果:成功;`0 Warning(s)`、`0 Error(s)`
- `dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~YamlConfigLoaderTests|FullyQualifiedName~YamlConfigSchemaValidatorTests"`
- 结果:成功;`80` 通过、`0` 失败
- `dotnet clean -p:RestoreFallbackFolders= -v:quiet`
- 结果:成功
- `dotnet build -p:RestoreFallbackFolders= -clp:WarningsOnly -v:minimal -m:1 -nodeReuse:false`
- - 结果:成功;`75` warnings、`0` errors
+ - 中间结果:成功;`75` warnings、`0` errors
+ - `dotnet clean -p:RestoreFallbackFolders= -v:quiet`
+ - 结果:成功
+ - `dotnet build -p:RestoreFallbackFolders= -clp:Summary -v:minimal -m:1 -nodeReuse:false`
+ - 结果:成功;`15 Warning(s)`、`0 Error(s)`
- `git diff --check`
- 结果:成功;无新增 whitespace / conflict-marker 问题
- 当前指标:
- - warning 总数:`236` -> `75`
- - 剩余 warning 分布:`GFramework.Game/Config/YamlConfigSchemaValidator.cs` `60` 条,`GFramework.Game/Config/YamlConfigSchemaValidator.ObjectKeywords.cs` `15` 条;规则为 `MA0048` `45` 条、`MA0051` `30` 条
- - 已提交分支 diff:`3` 个文件;主线程待提交后预计约 `6` 个文件,低于 `50` 个文件阈值
+ - warning 总数:`236` -> `15`
+ - 剩余 warning 分布:`GFramework.Game/Config/YamlConfigSchemaValidator.cs` 的 `MA0051` `15` 条(5 个方法跨 3 个 TFM)
+ - 本轮提交后预计分支 diff:`22` 个文件,低于 `50` 个文件阈值
- 下一步:
- - 提交主线程 Game / ai-plan 同步后,继续 `YamlConfigSchemaValidator.cs` 末尾 schema model 类型拆文件,优先清理 `MA0048`
+ - 按用户要求本轮到此结束;下一轮只处理 `YamlConfigSchemaValidator.cs` 剩余 `MA0051` 方法拆分
## 2026-04-28 — RP-092