> **发布元数据**：MiniMax Code · Kimi K3（评测者确认）· R01
> **来源**：`minimax-code/输出/minimax-code/T02/R01/BENCHMARK_RESULT.md`
> **原始文件 SHA-256**：`521e43bf4f3631edd9ca186aaa3ca8d2ff303fc3068957716797c09009449c3a`
> **规程说明**：本工具报告记载 12 题在单个批量会话中执行；与冻结会话隔离规程不符，本轮暂不进入严格排名。
> 本公开副本已将评测机绝对路径归一化；下文 PASS/FAIL/BLOCKED 是执行报告自述状态，不等同于独立验收结论。

---

# BENCHMARK_RESULT

BENCH-RUN T02 R01

## 题面（逐字）

> # T02：配置优先级与错误路径（只读）
>
> 只读分析 `python3 -m ledger list` 选择交易 CSV 的配置流程。追踪默认文件、JSON 配置文件、`LEDGER_DATA_FILE` 环境变量和全局 `--data-file` 参数；说明实际优先级、相对路径如何解析、配置格式错误或目标文件不存在时的处理，以及最终由哪个模块读取。每项附真实相对路径和函数/类名。不要修改文件；不确定时明确标出，不要猜。

## 状态：PASS

## 分析（源码直接阅读 + 在 workspace 内以只读命令逐场景实测，Python 3.9.6）

### 1. 四个配置来源与选择入口
选择逻辑全部在 `ledger/settings.py` 的 `resolve_data_file(cli_path=None, environ=None, config_path=None)`（settings.py:8）。四个来源：

- 全局参数 `--data-file`：在 `ledger/cli.py` `build_parser()`（cli.py:29）注册为全局选项，由 `main()`（cli.py:42）以 `cli_path=args.data_file` 传入。
- 环境变量 `LEDGER_DATA_FILE`：`main()` 传 `environ=os.environ`，`resolve_data_file` 在 settings.py:15 读取。
- JSON 配置文件 `--config`：cli.py:28 注册，settings.py:17–28 读取并解析。
- 默认文件：`ledger/settings.py` 模块级常量 `DEFAULT_DATA_FILE`（settings.py:5）= `Path(__file__).resolve().parent / "data" / "transactions.csv"`，即包内 `ledger/data/transactions.csv`。

### 2. 实际优先级（settings.py:13–30 的 if/elif 链，均经实测）

`--data-file` ＞ `LEDGER_DATA_FILE` ＞ `--config` 的 `data_file` ＞ 默认文件。

- 判断用的是真值测试（`if cli_path:` / `elif environ.get("LEDGER_DATA_FILE"):`），因此空字符串视为未设置：实测 `LEDGER_DATA_FILE=`（空）回退到默认文件，输出首行 `A-02 | ...`（场景 11）。
- 实测 `--data-file` 与指向不存在路径的环境变量同时存在时使用 `--data-file`（场景 3，exit=0）。
- **配置文件只在前两者都缺省时才被读取**：实测环境变量有效 + `--config` 指向不存在文件时不报错、使用环境变量的文件（场景 4，exit=0），证明 config 分支根本未执行。
- 无任何来源时返回 `DEFAULT_DATA_FILE`（settings.py:30，提前 return）。

### 3. 相对路径解析（settings.py:31–34）

- 所有来源先做 `Path(selected).expanduser()`（`~` 展开；此行为来自源码直接阅读，未实测）。
- 仅当来源是配置文件时，`selected_base = config_file.parent`（settings.py:28），相对路径相对**配置文件所在目录**拼接（settings.py:32–33），最后 `.resolve()` 归一为绝对路径。实测：`--config ../scratch/cfg/good.json` 内含 `"data_file": "alt2.csv"`，实际读取的是 `../scratch/cfg/alt2.csv`（场景 5，输出 `Z-02` 行）。
- 来源是 `--data-file` 或环境变量时 `selected_base is None`，相对路径由 `Path.resolve()` 相对**进程当前工作目录**解析（标准库 `pathlib` 语义）。实测 cwd 为 workspace 时 `LEDGER_DATA_FILE=../scratch/alt.csv` 正确读取（场景 2）。
- `DEFAULT_DATA_FILE` 分支直接 return、不再 `.resolve()`，但它由 `__file__.resolve()` 构造，本身已是绝对路径（直接阅读结论）。

### 4. 错误路径（全部实测）

- `--config` 文件不存在：settings.py:21–22 抛 `FileNotFoundError("config file not found: ...")`。实测 stderr `ledger: error: config file not found: /nonexistent/cfg.json`，exit=2（场景 6）。
- 配置 JSON 语法错误（或 UTF-8 解码失败）：settings.py:23–24 捕获 `json.JSONDecodeError`/`UnicodeDecodeError` 后抛 `ValueError("invalid config file ...: ...")`。实测 stderr `ledger: error: invalid config file ../scratch/bad.json: Expecting property name enclosed in double quotes: ...`，exit=2（场景 7）。
- 配置合法但不是 dict、缺 `data_file`、值为非字符串或空串：settings.py:26–27 抛 `ValueError("config must contain a non-empty string 'data_file'")`。实测 exit=2（场景 8，仅测了"键缺失"一种；其余分支为源码直接阅读结论，未逐一实测）。
- **目标 CSV 不存在**：`resolve_data_file` 不做存在性检查（源码直接阅读）；异常在读取阶段由 `ledger/storage.py` `load_transactions` 的 `Path(path).open(...)`（storage.py:13）抛出 `FileNotFoundError`。实测 stderr `ledger: error: [Errno 2] No such file or directory: '/nonexistent/data.csv'`，exit=2（场景 9）。
- 以上三类异常都被 `ledger/cli.py` `main()` 的 `except (FileNotFoundError, ValueError, OSError)`（cli.py:54）捕获：向 stderr 打印 `ledger: error: {exc}` 并 `return 2`（cli.py:55–56），`ledger/__main__.py` 的 `SystemExit(main())` 使进程以状态 2 退出。
- 附带观察：`--config`/`--data-file` 是全局选项，必须出现在子命令之前；`python3 -m ledger list --data-file ...` 被 argparse 以 `unrecognized arguments` 拒绝，exit=2（场景 10。这是 argparse 子解析器结构的行为，实测确认）。

### 5. 最终读取者

`ledger/storage.py` 的 `load_transactions(path)`（storage.py:11）——由 `ledger/cli.py` `main()`（cli.py:43）以 `resolve_data_file` 的返回值直接调用，以 `encoding="utf-8"` 只读打开并解析 CSV（行数据校验与对象构造见 storage.py:15–28，日期 `date.fromisoformat`、金额 `ledger/money.py` `parse_money`）。

### 6. 不确定项（如实标注）

- `expanduser()` 的 `~` 展开、Windows 平台路径语义：仅源码阅读结论，未实测（本机为 macOS 14 arm64）。
- 配置为合法 JSON 但 `data_file` 为非字符串/空串的分支：与"键缺失"共用 settings.py:26–27 同一 `raise`，只实测了键缺失。

## 实际改动的文件

无（本题只读）。workspace 运行前后 `git status --porcelain` 均为 0 行。测试用 scratch 文件创建于 `输出/minimax-code/T02/R01/scratch/`（workspace 之外），验证后已删除。

## 实际运行的命令与原始结果

全部在 `输出/minimax-code/T02/R01/workspace/` 下、`PYTHONDONTWRITEBYTECODE=1` 执行：

```
1. python3 -m ledger list                        → 默认文件输出 A-02 等 6 行，exit=0
2. LEDGER_DATA_FILE=../scratch/alt.csv python3 -m ledger list
   → Z-01 | 2025-05-05 | Test | $1.23，exit=0
3. LEDGER_DATA_FILE=/nonexistent/env.csv python3 -m ledger --data-file ../scratch/alt.csv list
   → Z-01 行，exit=0（--data-file 优先于 env）
4. LEDGER_DATA_FILE=../scratch/alt.csv python3 -m ledger --config /nonexistent/cfg.json list
   → Z-01 行，exit=0（env 优先，config 未被读取）
5. python3 -m ledger --config ../scratch/cfg/good.json list
   → Z-02 | 2025-06-06 | TestCfg | $4.56，exit=0（相对路径相对配置目录解析）
6. python3 -m ledger --config /nonexistent/cfg.json list
   → ledger: error: config file not found: /nonexistent/cfg.json，exit=2
7. python3 -m ledger --config ../scratch/bad.json list
   → ledger: error: invalid config file ../scratch/bad.json: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)，exit=2
8. python3 -m ledger --config ../scratch/nodata.json list
   → ledger: error: config must contain a non-empty string 'data_file'，exit=2
9. python3 -m ledger --data-file /nonexistent/data.csv list
   → ledger: error: [Errno 2] No such file or directory: '/nonexistent/data.csv'，exit=2
10. python3 -m ledger list --data-file ../scratch/alt.csv
    → ledger: error: unrecognized arguments: --data-file ../scratch/alt.csv，exit=2
11. LEDGER_DATA_FILE= python3 -m ledger list
    → 默认文件输出，exit=0（空环境变量视为未设置）
```

## 尚未完成的要求

无。

## 会话隔离状态

本题在 `输出/minimax-code/T02/R01/workspace/` 独立副本中只读执行（冻结提交 ed2390f2df8252f062abd9123e20f6fffca7e5ed）。实际执行为单个批量会话内按题隔离的独立 workspace；scratch 文件未进入 workspace，用后已删。其余会话级隔离元数据：UNKNOWN。

## 耗时

约 3 分钟（秒级精确耗时 UNKNOWN）。
