# Config Loader

> Aria 项目级配置加载器（内部基础设施）。 查找、解析、验证 .aria/config.json 并合并默认值。 此 Skill 不直接触发，由其他 Skills 引用以读取项目配置。

- Skill: `10cg/config-loader` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add 10cg/config-loader`
- Raw SKILL.md: https://api.skillmd.com/api/skills/10cg/config-loader/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: 10cg (https://skillmd.com/u/10cg)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/10cg/config-loader

---


# 配置加载器 (Config Loader)

> **版本**: 1.0.0 | **角色**: 内部基础设施 Skill

## 职责

为所有需要读取项目配置的 Skills 提供统一的配置加载逻辑。

## 加载流程

```
1. 查找 .aria/config.json (项目根目录)
2. 如果存在 → 解析 JSON
3. 旧配置兼容映射 (见下方"旧配置兼容层"章节)
4. 验证字段类型和范围
5. 与 DEFAULTS.json 合并 (用户值覆盖默认值)
6. 返回完整配置对象
```

## 错误处理

| 场景 | 行为 |
|------|------|
| 文件缺失 | 静默返回 DEFAULTS.json 全部默认值 |
| JSON 格式错误 | 警告用户 + 返回默认值 |
| 字段类型错误 | 警告 + 使用该字段默认值 |
| 字段值超范围 | 警告 + clamp 到有效范围 |

## 字段验证规则

```yaml
workflow.auto_proceed:
  type: boolean
  default: false

state_scanner.confidence_threshold:
  type: integer
  range: [0, 100]
  default: 90

state_scanner.auto_execute_enabled:
  type: boolean
  default: false

state_scanner.auto_execute_rules:
  type: array of string
  valid_values: [commit_only, quick_fix, doc_only, feature_with_spec]
  default: [commit_only, quick_fix, doc_only]

state_scanner.audit_log_path:
  type: string
  default: ".aria/audit.log"

# Phase 1.12 — 本地/远程同步检测 (v2.9.0)
state_scanner.sync_check.enabled:
  type: boolean
  default: true

state_scanner.sync_check.check_submodules:
  type: boolean
  default: true

state_scanner.sync_check.check_remote:
  type: boolean
  default: false

# Phase 1.13 — Issue 感知扫描 (v2.9.0, opt-in)
state_scanner.issue_scan.enabled:
  type: boolean
  default: false

state_scanner.issue_scan.platform:
  type: string | null
  valid_values: [forgejo, github, null]
  default: null

state_scanner.issue_scan.platform_hostnames:
  type: object
  default:
    forgejo: ["forgejo.10cg.pub"]
    github: ["github.com"]
  # Forgejo hosts precedence (v1.30.0+, per OpenSpec aria-forgejo-hosts-parameterization):
  #   1. ARIA_FORGEJO_HOSTS env var (comma-separated)  ← highest
  #   2. .aria/config.json platform_hostnames.forgejo
  #   3. DEFAULTS.json fallback (forgejo.10cg.pub legacy)
  # Env override applies to forgejo key only; github key untouched.
  # Empty env (""/whitespace) and empty config list ([]) fall through to defaults.

state_scanner.issue_scan.cache_ttl_seconds:
  type: integer
  range: [60, 86400]
  default: 900

state_scanner.issue_scan.cache_path:
  type: string
  default: ".aria/cache/issues.json"

state_scanner.issue_scan.stage_timeout_seconds:
  type: integer
  range: [3, 60]
  default: 12

state_scanner.issue_scan.api_timeout_seconds:
  type: integer
  range: [1, 30]
  default: 5

state_scanner.issue_scan.limit:
  type: integer
  range: [1, 100]
  default: 20

state_scanner.issue_scan.label_filter:
  type: array of string
  default: []

# Layer L 多终端协调闸门 (multi-terminal-coordination; opt-out since
# coordination-claim-lifecycle-and-overlap Part A1)
# — coordination.enabled 承载 #133 AC-2 互斥不变式 (advanced-rules.md rule 1.54):
#   enabled==true  → cross-owner collision 由 phase1_gate 处理;
#   enabled==false → 切口2 advisory (rule 1.54) surface collision。两者在 enabled 上严格互斥。
state_scanner.coordination.enabled:
  type: boolean
  default: true                   # Part A1 (defect a): false→true — 2026-07-11 双子星撞车实证 opt-in 默认导致认领从不发生; advisory mode 保证翻转不阻断任何流程。显式设 false 可退回 rule 1.54 advisory。
                                  # 已知边界: runtime_probe._resolve_enabled_when 的缺键=off 是通用探针契约不随动 — 无此 key 的项目 coordination_probe 判 skipped (保守), 不误报 warn。
                                  # A.1 入口认领与 --heartbeat-only 心跳**同受本开关**: false ⇒ 两者皆零调用 (a1-entry-claim-duplicate-work-guard §2.5)。

# mode 与 enabled 正交 (仅 enabled==true 时相关), 不改 rule 1.54 disjointness (DEC-20260704-002 §1, R1-C2)
state_scanner.coordination.mode:
  type: string
  valid_values: [advisory, block]
  default: "advisory"             # advisory=放行+写推自己 claim+surface 告警 (advisory-over-hardlock); block=旧交互 abort/yield 语义

# 无人值守分支 (a1-entry-claim-duplicate-work-guard §2.3): 决定 A.1 检出重叠时向谁请裁
state_scanner.coordination.unattended:
  type: boolean
  default: false                  # false ⇒ A.1 overlap 非空时经 AskUserQuestion 请人裁; true ⇒ 零 AskUserQuestion, 改写「待复议」记录并置 awaiting_owner, 由产品负责人事后复议。
                                  # 取值路径: aria-runner 容器镜像内的 .aria/config.json (Layer 2 自主运行时); Nomad env 三腿契约属 follow-up, 本 key 不承载。
                                  # ⚠️ **不得以「AskUserQuestion 当前是否可用」做运行期推断** (D15): 有没有人可问是**配置事实**, 不是可以从工具可用性猜出来的东西 —— 猜错的方向恰好是「没人时默默替人做决定」。

# 远程引用新鲜度阈值 (state-scanner-stale-refs-false-parity Phase 0)
# — D15′/D18 阈值, 供 F1′ 双轴谓词 (evidence_grade) + 豁免资格判定使用。
#   由 multi_remote.py `_load_sync_freshness_config` 单独读取 (与 multi_remote 块正交)。
state_scanner.sync_freshness.evidence_window_seconds:
  type: integer
  default: 3600                   # 证据窗 (E): leg 的 fetched_at 在此窗内才算 "fresh" 直接证据

state_scanner.sync_freshness.hard_cap_days:
  type: integer
  default: 7                      # 墙钟硬顶: 超过即 expired, 豁免资格 (X) 一律不再成立

state_scanner.sync_freshness.k_min:
  type: integer
  default: 3                      # 连续未验证次数下限; 冷启动下 k_eff = k_min (fail-CLOSED)

tdd.strictness:
  type: string
  valid_values: [advisory, strict, superpowers]
  default: "advisory"

phase_b_developer.framework_build_check.enabled:
  type: boolean
  default: false                  # Aria #95: B.2.5 框架 build 验证开关

phase_b_developer.framework_build_check.command:
  type: string | null
  default: null                   # build 命令 (如 "npm run build"); null=no-op

phase_b_developer.framework_build_check.mode:
  type: string
  valid_values: [advisory, blocking]
  default: "advisory"             # advisory=警告不阻塞 / blocking=失败阻塞进 Phase C

benchmarks.require_before_merge:
  type: boolean
  default: true

benchmarks.skill_change_block_mode:
  type: string
  valid_values: [warn, block, off]
  default: "warn"

experiments.agent_team_audit:
  type: boolean
  default: false

experiments.agent_team_audit_points:
  type: array of string
  valid_values: [pre_merge, post_implementation, post_spec]
  default: [pre_merge]

audit.enabled:
  type: boolean
  default: false

audit.mode:
  type: string
  valid_values: [adaptive, manual, convergence, challenge]
  default: "adaptive"

audit.max_rounds:
  type: integer
  range: [1, 20]
  default: 5
  # drift guard 完整功能需 max_rounds >= 3 (DRIFT_TERMINATED 需 consecutive_refocus >= 2,
  # 至少 3 轮; max_rounds < 3 时 drift guard 降级为 max_rounds 兜底)

# audit.drift_guard.* — 多轮审计 Drift Guard 阈值与模式开关 (#17, v1.44.0)
audit.drift_guard.warn_threshold:
  type: number
  range: [0, 1]
  default: 0.2
  # 域外 → warn + default

audit.drift_guard.refocus_threshold:
  type: number
  range: [0, 1]
  default: 0.5
  # 约束 >= warn_threshold, 违反 → warn + 单向 clamp (refocus_threshold 抬升到 warn_threshold)

audit.drift_guard.convergence_mode:
  type: boolean
  default: false
  # challenge 默认开 + convergence 可选 (本字段) + post_closure 由模式选择阶段屏蔽

audit.checkpoints.*:
  type: string
  valid_values: [off, convergence, challenge]
  valid_keys: [post_brainstorm, post_spec, post_planning, post_implementation,
               mid_implementation, mid_post_spec, pre_merge, post_closure]
  default: "off"

# mid_post_spec (Aria #79): Phase B 实施期 spec 漂移条件触发的快速校验。
# trigger=spec_drift_detected; 恒 max_rounds=1; scope 限漂移点; advisory。
# 见 audit.mid_post_spec block + agent-team-audit/audit-points.md。

# Phase C.2.4 — Pre-Merge Precondition Gate (v1.3.0+, Forgejo Issue #60)
phase_c_integrator.pre_merge_gate.enabled:
  type: boolean
  default: true

phase_c_integrator.pre_merge_gate.ci_backends:
  type: null | array of {name: string} | array of string
  default: null  # null/missing = auto-detect via static BACKENDS list; [] = explicit disable; non-empty list = user-specified order
  # v1.31.0+ replaces legacy `primitive_preference` (alias still works, emits DeprecationWarning, removed in v2.0)
  # Supported names: "aether-ci-cli" (real), "github-actions" (stub v1.31.0+)
  # See aria/skills/phase-c-integrator/SKILL.md §C.2.4.X CI Backends

phase_c_integrator.pre_merge_gate.no_ci_fallback:
  type: string
  valid_values: [skip_with_warning, abort]
  default: "skip_with_warning"
  # v1.31.0+ replaces legacy `no_aether_fallback` (alias still works, emits DeprecationWarning, removed in v2.0)

phase_c_integrator.pre_merge_gate.wait_timeout_seconds:
  type: integer
  range: [60, 7200]
  default: 1800

phase_c_integrator.pre_merge_gate.wait_check_intervals:
  type: array of integer
  default: [30, 60, 120, 300, 300]
  # 数组耗尽后重复 intervals[-1] 直到 wait_timeout_seconds

phase_c_integrator.pre_merge_gate.primitive_call_timeout_seconds:
  type: integer
  range: [5, 300]
  default: 30

phase_c_integrator.pre_merge_gate.poll_chunk_seconds:
  type: integer
  range: [1, 30]
  default: 5

phase_c_integrator.pre_merge_gate.user_escape_hatch:
  type: boolean
  default: true

phase_c_integrator.pre_merge_gate.path_coverage_enabled:
  type: boolean
  default: true
  # v1.65.0+ — aria-plugin #122 路径覆盖感知 not_applicable 态,
  # 详见 aria/skills/phase-c-integrator/SKILL.md §C.2.4 步骤 2.5

phase_c_integrator.pre_merge_gate.no_run_prompt_after_observations:
  type: integer
  range: [2, null]  # int >= 2 (阈值 1 会把新分支首推的单次瞬时零 run 当异常提示)
  default: 3
  # v1.66.5+ — aria-plugin #152 pr_ci_status="not_found" (远端零 run) 连续观测达此次数
  # 才提示用户人工核验; 详见 aria/skills/phase-c-integrator/SKILL.md §C.2.4 步骤 6
```

## 旧配置兼容层

在步骤 3（验证之前）执行以下检测和映射，确保旧配置用户无缝升级到新 `audit` 体系。

### 触发条件

同时满足以下两点时触发兼容映射：

1. `experiments.agent_team_audit === true`
2. 配置文件中不存在 `audit` 块（即 `audit` 字段为 `undefined`）

### 映射规则

```
experiments.agent_team_audit: true
  → audit.enabled: true
  → audit.mode: "manual"

experiments.agent_team_audit_points 数组元素映射:
  "post_spec"            → audit.checkpoints.post_spec: "convergence"
  "post_implementation"  → audit.checkpoints.post_implementation: "convergence"
  "pre_merge"            → audit.checkpoints.pre_merge: "convergence"
```

未在 `agent_team_audit_points` 中出现的检查点保持默认值 `"off"`。

新增的 4 个检查点（`post_brainstorm`, `post_planning`, `mid_implementation`, `post_closure`）不在旧配置中，映射后均为 `"off"`。

### 迁移提示

兼容映射生效时，必须向用户输出以下提示（仅在实际触发时显示，不影响正常加载）：

```
[config-loader] 检测到旧版审计配置 (experiments.agent_team_audit)。
已自动映射到新配置格式:
  audit.enabled: true
  audit.mode: "manual"
  audit.checkpoints: { <映射结果列表> }

建议将 .aria/config.json 迁移到新格式以获得完整功能（7 个检查点、多轮收敛、挑战模式）。
参考: openspec/changes/auto-audit-system/proposal.md
```

### 不触发条件

- `experiments.agent_team_audit: false`（或缺失）→ 跳过兼容映射，正常加载
- 已存在 `audit` 块 → 跳过兼容映射，用户显式配置优先

## 与 .claude/tdd-config.json 的优先级关系

```
优先级 (高 → 低):
  .aria/config.json tdd.strictness     ← 项目统一配置 (推荐)
  .claude/tdd-config.json              ← 遗留配置 (向后兼容)
  Skill 内置默认值 (DEFAULTS.json)     ← 兜底
```

当 `.aria/config.json` 存在时，其 `tdd.strictness` 覆盖 `.claude/tdd-config.json` 中的对应字段。`.claude/tdd-config.json` 中的细粒度字段 (`skip_patterns`, `test_patterns`) 不在 `.aria/config.json` 中重复，继续在原位生效。

## 调用方式

其他 Skill 在执行前通过以下模式读取配置：

```
1. 检查 .aria/config.json 是否存在
2. 如果存在，读取并解析
3. 提取所需字段，缺失字段使用 DEFAULTS.json 中的默认值
4. 字段验证参照上述规则
```

## 消费方 Skills

| Skill | 读取字段 |
|-------|---------|
| state-scanner | `state_scanner.*`, `workflow.auto_proceed` |
| workflow-runner | `workflow.auto_proceed` |
| tdd-enforcer | `tdd.strictness` |
| branch-finisher | `benchmarks.require_before_merge` |
| phase-c-integrator | `experiments.agent_team_audit*`, `audit.*` |
| phase-b-developer | `experiments.agent_team_audit*`, `audit.*` |
| audit-engine | `audit.*` |

## 默认值文件

所有默认值集中管理在 [`DEFAULTS.json`](./DEFAULTS.json)。

---

**最后更新**: 2026-06-11 (#17 audit-drift-guard — Drift Guard 原始目的锚定)

