> **发布元数据**：DeepSeek Harness · Kimi K3（评测者确认）· R01
> **来源**：`deepseek-harness/输出/deepseek-harness/T02/R01/BENCHMARK_RESULT.md`
> **原始文件 SHA-256**：`be4ced16616047a85f540a2d1ce11ab23d061ff1479deadbd65c533e4989cbb3`
> 本公开副本已将评测机绝对路径归一化；下文 PASS/FAIL/BLOCKED 是执行报告自述状态，不等同于独立验收结论。

---

# BENCH-RUN T02 R01

状态：PASS

任务：只读分析 `python3 -m ledger list` 选择交易 CSV 的配置流程（优先级、相对路径解析、错误路径、最终读取模块）。未修改 workspace 内任何文件。

---

## 一、完整分析（均基于实际阅读源码 + 实际运行验证）

### 1. 调用链与最终读取模块

- 入口：`ledger/__main__.py`（第 1–4 行）调用 `ledger.cli.main()`。
- `ledger/cli.py` 中 `build_parser()`（第 26 行）定义全局参数 `--config` 和 `--data-file`（二者均注册在顶层 parser 上，须出现在子命令 `list` 之前）；`main()`（第 38 行）在第 42 行调用 `resolve_data_file(cli_path=args.data_file, environ=os.environ, config_path=args.config)`。
- 路径解析全部发生在 **`ledger/settings.py` 的 `resolve_data_file()`**（第 8–34 行）。
- 最终由 **`ledger/storage.py` 的 `load_transactions(path)`**（第 11 行）读取 CSV：第 13 行 `Path(path).open("r", encoding="utf-8", newline="")`，用 `csv.DictReader` 解析，必需列为 `{"id", "date", "category", "amount"}`（第 8 行 `_REQUIRED_COLUMNS`）。

### 2. 实际优先级（`ledger/settings.py` `resolve_data_file()`，第 13–30 行）

严格 if/elif 链，高到低：

1. **全局 `--data-file` 参数**（`cli_path`，第 13–14 行）：非空即选中，其余来源完全不读取。
2. **`LEDGER_DATA_FILE` 环境变量**（第 15–16 行）：`environ.get("LEDGER_DATA_FILE")` 为真值（非空字符串）时选中；空字符串视为未设置并继续下探（实测验证，见命令 11）。
3. **JSON 配置文件**（`--config`，第 17–28 行）：读取并解析 JSON，取 `data_file` 键。
4. **默认文件**（第 29–30 行）：以上皆无则返回 `DEFAULT_DATA_FILE`（第 5 行）= `Path(__file__).resolve().parent / "data" / "transactions.csv"`，即 workspace 内 `ledger/data/transactions.csv`（绝对锚定到包安装位置，与 CWD 无关）。

实测验证（命令 3）：`--data-file` 与环境变量同时给出时只用 `--data-file`；命令 4：环境变量与 `--config` 同时给出时只用环境变量（此时配置文件根本不会被打开解析）。

### 3. 相对路径如何解析（`ledger/settings.py` 第 31–34 行）

- 所有来源的路径先经 `Path(selected).expanduser()`（第 31 行，支持 `~`）。
- **仅当来自配置文件**时 `selected_base = config_file.parent`（第 28 行）；此时若 `data_file` 为相对路径，则**相对于配置文件所在目录**拼接（第 32–33 行），最后 `.resolve()` 归一化为绝对路径。实测命令 5：配置 `{"data_file": "rel.csv"}` 位于 `/tmp/t02_r01_verify/cfgdir/config_rel.json`，实际读取了同目录的 `cfgdir/rel.csv`。
- **`--data-file` 和环境变量的相对路径**没有 base，直接 `Path(selected).resolve()`（第 34 行），即**相对于进程当前工作目录（CWD）**解析。实测命令 10：在 `/tmp/t02_r01_verify` 下 `--data-file rel_cli.csv` 成功；在 workspace 下用同一相对名则报不存在（CWD 不同结果不同）。
- 注意：最终返回的是 resolve 后的绝对路径（macOS 上 `/tmp` 会归一化为 `/private/tmp`，见命令 9 的报错）。

### 4. 错误路径

统一由 `ledger/cli.py` `main()` 第 54–56 行捕获 `(FileNotFoundError, ValueError, OSError)`，向 **stderr** 打印 `ledger: error: <消息>` 并**返回退出码 2**（`__main__.py` 经 `SystemExit(main())` 转为进程退出码）。具体：

| 场景 | 抛出位置 | 异常 | 实测 stderr / 退出码 |
|---|---|---|---|
| 配置文件不存在 | `settings.py` 第 21–22 行 | `FileNotFoundError("config file not found: ...")` | `ledger: error: config file not found: /tmp/t02_r01_verify/nope.json`，exit=2 |
| 配置 JSON 格式错误（或编码错误） | `settings.py` 第 23–24 行 | `ValueError("invalid config file ...: ...")`（包装 `json.JSONDecodeError`/`UnicodeDecodeError`） | `ledger: error: invalid config file /tmp/t02_r01_verify/bad.json: Expecting value: line 1 column 1 (char 0)`，exit=2 |
| 配置缺少 `data_file`、非字符串或为空字符串（含 JSON 顶层非对象） | `settings.py` 第 25–27 行 | `ValueError("config must contain a non-empty string 'data_file'")` | 同消息，exit=2 |
| 目标 CSV 不存在（任一来源） | `storage.py` 第 13 行 `Path.open()` | 原生 `FileNotFoundError`（`OSError` 子类） | `ledger: error: [Errno 2] No such file or directory: '...'`，exit=2 |
| CSV 缺必需列 | `storage.py` 第 16–18 行 | `ValueError("missing CSV columns: ...")` | （未单独实测，代码路径明确） |
| CSV 行数据非法 | `storage.py` 第 27–28 行 | `ValueError("invalid transaction at line N: ...")` | （未单独实测，代码路径明确） |

即：配置类错误在 `settings.py` 内被改写成带上下文的消息；文件不存在错误为原生 errno 消息。所有可预见错误均不产生 traceback，退出码恒为 2；解析参数本身的错误由 argparse 处理（也为退出码 2，argparse 自身行为）。

### 5. 不确定项

- 无实质性不确定项。所有关键结论（优先级顺序、相对路径基准、各错误消息与退出码）均经实际运行验证。CSV 内容级错误（缺列、坏行）两条路径未逐一运行验证，但代码路径直接可见，已如实标注。

---

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

环境：Python 3.9.6（/Applications/Xcode.app .../python3）。临时文件全部在 `/tmp/t02_r01_verify`，workspace 未被写入。

准备：
```
TMP=/tmp/t02_r01_verify; mkdir -p "$TMP/cfgdir"
printf 'id,date,category,amount\nt1,2024-01-05,food,12.34\n' > "$TMP/custom.csv"
printf 'id,date,category,amount\ncfg1,2024-02-02,books,9.99\n' > "$TMP/cfgdir/rel.csv"
```

1. 默认文件（cd 到 workspace）：`python3 -m ledger list`
   输出 6 行交易（A-02/A-01/B-01/C-01/D-01/E-01，来自 `ledger/data/transactions.csv`），`exit=0`。
2. 环境变量：`LEDGER_DATA_FILE="$TMP/custom.csv" python3 -m ledger list`
   输出 `t1 | 2024-01-05 | food | $12.34`，`exit=0`。
3. CLI 胜过环境变量：`LEDGER_DATA_FILE=/nonexistent/env.csv python3 -m ledger --data-file "$TMP/custom.csv" list`
   输出 custom.csv 内容，`exit=0`（不存在的环境变量路径被完全忽略）。
4. 环境变量胜过配置：`LEDGER_DATA_FILE="$TMP/custom.csv" python3 -m ledger --config "$TMP/config_abs.json" list`（config_abs.json 内容为 `{"data_file": "/nonexistent/cfg.csv"}`）
   输出 custom.csv 内容，`exit=0`。
5. 配置相对路径基于配置目录：`python3 -m ledger --config "$TMP/cfgdir/config_rel.json" list`（内容为 `{"data_file": "rel.csv"}`，CWD=workspace）
   输出 `cfg1 | 2024-02-02 | books | $9.99`，`exit=0` —— 解析到 `cfgdir/rel.csv` 而非 CWD。
6. 配置不存在：`python3 -m ledger --config "$TMP/nope.json" list`
   stderr：`ledger: error: config file not found: /tmp/t02_r01_verify/nope.json`，`exit=2`。
7. 配置 JSON 损坏：`python3 -m ledger --config "$TMP/bad.json" list`（内容 `not json {`）
   stderr：`ledger: error: invalid config file /tmp/t02_r01_verify/bad.json: Expecting value: line 1 column 1 (char 0)`，`exit=2`。
8. 配置无 `data_file`：`python3 -m ledger --config "$TMP/nodata.json" list`（内容 `{"other": 1}`）
   stderr：`ledger: error: config must contain a non-empty string 'data_file'`，`exit=2`。
9. `--data-file` 不存在：`python3 -m ledger --data-file "$TMP/missing.csv" list`
   stderr：`ledger: error: [Errno 2] No such file or directory: '/private/tmp/t02_r01_verify/missing.csv'`，`exit=2`。
10. CLI 相对路径基于 CWD：在 `/tmp/t02_r01_verify` 下 `PYTHONPATH=<workspace> python3 -m ledger --data-file rel_cli.csv list`
    输出 `r1 | 2024-03-03 | misc | $1.00`，`exit=0`；在 workspace 下用同一相对名则 stderr `... No such file or directory: '<workspace>/rel_cli.csv'`，`exit=2`。
    （首次在 /tmp 下未设 PYTHONPATH 时 `python3 -m ledger` 报 `No module named ledger`，exit=1，说明包未安装、依赖 CWD/PYTHONPATH 导入。）
10b. 配置指向缺失 CSV：`--config cfgdir/config_missing.json`（`{"data_file": "nothere.csv"}`）
    stderr：`ledger: error: [Errno 2] No such file or directory: '/private/tmp/t02_r01_verify/cfgdir/nothere.csv'`，`exit=2`。
11. 空环境变量下探：`LEDGER_DATA_FILE="" python3 -m ledger list` → 使用默认文件，输出同命令 1，`exit=0`。

只读性核验：`cd workspace && git status --porcelain` 输出为空，`git rev-parse HEAD` = `ed2390f2df8252f062abd9123e20f6fffca7e5ed`（与冻结提交一致）。

---

## 三、耗时

UNKNOWN（未计时；实际为一次交互式会话内完成）。

## 四、未完成项

无。（CSV 内容级错误路径未逐一运行验证，仅依据代码，已在分析中标注；不构成题面要求的缺漏。）

## 五、会话隔离说明

- 本次运行仅在本运行目录的独立 workspace 副本（`.../T02/R01/workspace`，冻结提交 ed2390f2df8252f062abd9123e20f6fffca7e5ed）内进行只读操作；`git status` 干净，HEAD 未变，未修改题目源文件、基准仓库或其他运行目录。
- 临时验证文件全部创建于 `/tmp/t02_r01_verify`，未污染 workspace。
- 未联网、未安装依赖（包通过 CWD/PYTHONPATH 直接导入）、未修改任何测试。
- 本结果文件写于运行目录根部 `.../T02/R01/BENCHMARK_RESULT.md`，位于 workspace 之外。
