Suite

配置智能诊断

Suite ConfigDiagnosticEngine、配置快照、差异检测、版本迁移与自动修复

配置智能诊断

Suite 内置配置智能诊断引擎(ConfigDiagnosticEngine),在不修改玩家原配置文件的前提下,对宿主和所有模块的配置进行版本检测、结构合并、类型校验和自动修复建议。

架构总览

graph TB
    subgraph 诊断引擎
        CDE["ConfigDiagnosticEngine"]
        ML["MigrationLoader"]
        MOE["MigrationOperationExecutor"]
        TC["TypeCoercer"]
        YCS["YamlConfigSynchronizer"]
    end
 
    subgraph 数据
        Spec["ModuleConfigSpec<br/>配置规范"]
        Defaults["jar 内默认配置"]
        Live["玩家现有配置"]
        Proposal["修复建议 yml"]
        Report["诊断报告"]
    end
 
    subgraph 产物
        Diagnosis["diagnosis/<br/>时间戳目录"]
        Backup["backup/<br/>配置备份"]
    end
 
    CDE --> Spec
    CDE --> Defaults
    CDE --> Live
    CDE --> YCS
    CDE --> ML
    CDE --> MOE
    CDE --> TC
    CDE --> Proposal
    CDE --> Report
    Report --> Diagnosis
    CDE --> Backup

诊断流程

ConfigDiagnosticEngine.diagnose() 对单个 ModuleConfigSpec 跑完整流程,任何阶段都不会动玩家原 yml 文件

flowchart TD
    A["加载 jar 内默认配置"] --> B["加载玩家现有配置"]
    B --> C{"文件存在?"}
    C -->|"否"| D["默认值视作 proposal<br/>报告 MISSING_DEFAULT"]
    C -->|"是"| E["版本检测"]
    E --> F{"live版本 < 当前版本?"}
    F -->|"是"| G["应用 migration"]
    F -->|"否"| H["结构合并 dry-run"]
    G --> H
    H --> I["差异检测"]
    I --> J["类型/值校验"]
    J --> K["生成 proposal yml"]
    K --> L["生成 Markdown 报告"]

阶段详解

1. 加载默认配置

从模块 jar 内读取默认配置资源(通过 resourceOpener,支持外部模块的 ClassLoader)。

2. 加载现有配置

加载玩家 data/<moduleId>/config.yml,若文件不存在则直接把默认值视作 proposal。

3. 版本检测与迁移

比较 liveVersioncurrentVersion

  • liveVersion < currentVersion 且有 migration 目录 → 应用迁移操作
  • liveVersion < currentVersion 但无 migration → 仅升级版本号字段

4. 结构合并 dry-run

YamlConfigSynchronizer.merge() 在 live 副本上执行结构合并:

  • 新增路径(jar 默认有但玩家没有)→ 报告 MISSING_DEFAULT(INFO)
  • 废弃路径(玩家有但 jar 默认没有)→ 报告 OBSOLETE_KEY(WARN)
  • modules 节特殊处理:用户可自由配置任意模块开关,不对 modules.* 路径生成 OBSOLETE_KEY

5. 类型/值校验

ValidationRule 列表校验每个字段:

校验项说明
必填字段required=true 且值为 null → ERROR
类型匹配值类型与 ValueType 不匹配 → 尝试自动转换
范围校验Number 值超出 min/max → WARN

类型不匹配时,TypeCoercer 尝试自动转换(如 "12"12),转换成功报告 TYPE_MISMATCH(WARN),转换失败报告 TYPE_MISMATCH(ERROR)。

6. 生成产物

  • proposal yml:修复后的完整配置(写入 diagnosis/<时间戳>/ 目录)
  • Markdown 报告:人类可读的诊断报告

配置规范 ModuleConfigSpec

每个模块通过 AXSModule.configSpecs() 声明其配置规范:

public List<ModuleConfigSpec> configSpecs() {
    return List.of(ModuleConfigSpec.basic(
        "mymodule",
        new ConfigSyncSpec("config.yml", "config.yml",
            SyncPolicy.builder()
                .dynamicSection("currencies")
                .build()
        )
    ));
}

ConfigSyncSpec

字段说明
resourcePathjar 内默认配置资源路径
targetRelativePath玩家配置文件相对路径
policy同步策略(含动态节声明)

SyncPolicy

SyncPolicy 声明哪些配置节是动态的(用户可自由扩展),不对这些节做废弃键检测:

SyncPolicy.builder()
    .dynamicSection("currencies")   // 货币节动态
    .dynamicSection("keybinds")     // 按键节动态
    .build()

ValidationRule

ValidationRule.of("settings.refresh-interval-ticks", ValueType.INTEGER)
    .required(true)
    .min(1)
    .max(3600)

版本迁移

模块可通过 migration 文件声明版本间的配置迁移操作。

MigrationLoader

从 jar 内 migrationFolder 目录加载迁移描述符,按版本号排序:

List<ConfigMigrationDescriptor> descriptors = MigrationLoader.loadAll(
    spec.ownerId(), spec.migrationFolder(), cl, resourceOpener);

迁移执行

按版本号顺序应用迁移操作,仅执行 fromVersion 与当前版本匹配的迁移:

for (ConfigMigrationDescriptor descriptor : descriptors) {
    if (descriptor.fromVersion() != currentVersion) continue;
    for (MigrationOperation op : descriptor.operations()) {
        MigrationOperationExecutor.execute(live, op);
    }
    currentVersion = descriptor.toVersion();
}

诊断报告

ConfigIssue

每条诊断问题包含:

字段说明
ownerId配置所有者(模块 ID 或 axs-core
resourcePath资源路径
path配置路径
kind问题类型
severity严重级别
oldValue旧值
newValue新值
message描述信息
changeSource变更来源

ConfigIssueKind

类型说明
MISSING_DEFAULT缺失默认键
OBSOLETE_KEY废弃键
VERSION_UPGRADE版本升级
TYPE_MISMATCH类型不匹配
VALUE_OUT_OF_RANGE值超出范围
MIGRATION_FAILED迁移失败

ConfigIssueSeverity

级别说明
INFO信息提示
WARN警告
ERROR错误

ChangeSource

来源说明
JAR_NEWjar 新增字段
USER_DEPRECATED用户保留的废弃字段

诊断时机

时机写盘说明
模块加载前registerModuleConfigSpecs 立即跑诊断(dry-run)
宿主启动末尾runConfigDiagnosis(null, false) 全量诊断,仅控制台摘要
手动诊断命令runConfigDiagnosis(ownerId, true) 写 proposal 和 Markdown

产物目录

plugins/ArcartX-Suite/
├── diagnosis/
│   └── 2026-07-31_12-00-00/       按时间戳分目录
│       ├── axs-core.config.yml.proposal.yml
│       ├── axs-core.config.yml.report.md
│       └── <moduleId>.config.yml.proposal.yml
└── backup/                        配置备份

保留期清理

RetentionCleaner 在宿主启动时清理过期的诊断和备份目录:

配置默认值说明
诊断保留期7 天超过 7 天的 diagnosis 目录删除
备份保留期60 天超过 60 天的 backup 目录删除
最大保留数5每类最多保留 5 个目录

宿主配置诊断

宿主自身的 config.yml 也作为一个 ModuleConfigSpec 参与诊断:

hostConfigSpecs.add(ModuleConfigSpec.basic(
    "axs-core",
    new ConfigSyncSpec("config.yml", "config.yml",
        SyncPolicy.builder()
            .dynamicSection("currencies")
            .dynamicSection("keybinds")
            .build()
    )
));

currencieskeybinds 节声明为动态节,用户可自由扩展,不做废弃键检测。