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

---

# BENCH-RUN T12 R01

- 状态：**PASS**（第一轮与第二轮均完成，全部检查通过）
- 冻结提交：`ed2390f2df8252f062abd9123e20f6fffca7e5ed`（workspace 为独立副本）
- 环境：Python 3.9.6（仅标准库，未新增依赖，未联网）
- 耗时：整体墙钟时间 UNKNOWN（未精确计时）；unittest 自报耗时见各轮原始输出（0.001s–0.002s 量级）

---

## 第一轮

### 题面
为 `python3 -m ledger summary` 增加 `--by-category`：启用时按原始类别文本**精确分组**，每行 `类别: 金额`，按类别 Unicode 码点升序；不启用时默认输出不变；新增可复用按类别汇总函数、测试、简短用法说明；不删改原测试。

### 实际改动
1. `ledger/summary.py`
   - 新增 `summarize_by_category(transactions)`：按 `item.category` 原始文本精确分组、金额按整数分求和，返回 `(category, total_cents)` 元组列表，按类别码点升序 `sorted(...)`。
   - 新增 `format_category_summary(rows)`：每行 `f"{category}: {format_money(total_cents)}"`，以 `\n` 连接（沿用 `ledger/formatting.py` 的 `format_money`）。
   - 原 `summarize` / `format_summary` 未改动。
2. `ledger/cli.py`
   - `summary` 子命令新增 `--by-category`（`action="store_true"`）。
   - `main` 中：`args.command == "summary"` 且 `args.by_category` 时输出 `format_category_summary(summarize_by_category(transactions))`，否则保持原 `format_summary(summarize(transactions))` 分支不变。
3. 新增 `tests/test_by_category.py`（第一轮版本，6 个测试）：精确大小写分组（`Food`/`food` 分开）、码点升序排序（含 `家庭` 非 ASCII）、空输入、格式化行、CLI `--by-category` 全量输出断言、默认 summary 输出不变断言。
4. `docs/usage.md`：新增“按类别汇总”小节（第一轮表述：按原始类别文本精确分组、码点升序）。

### 实际运行的命令与原始结果
基线确认（改动前）：
```
$ python3 -m unittest discover -s tests -v
Ran 4 tests in 0.001s
OK
```
第一轮中途一次失败（诚实记录）：本人新增测试将总额误写为 `$117.66`，实际为 `$117.56`，`test_default_summary_unchanged` FAIL 一次；修正测试期望值后复跑：
```
$ python3 -m unittest discover -s tests -v
test_default_fixture_loads (test_baseline.BaselineSmokeTests) ... ok
test_default_summary_shape (test_baseline.BaselineSmokeTests) ... ok
test_list_command_runs (test_baseline.BaselineSmokeTests) ... ok
test_valid_money_inputs (test_baseline.BaselineSmokeTests) ... ok
test_by_category_output (test_by_category.ByCategoryCliTests) ... ok
test_default_summary_unchanged (test_by_category.ByCategoryCliTests) ... ok
test_empty_input (test_by_category.SummarizeByCategoryTests) ... ok
test_exact_case_grouping (test_by_category.SummarizeByCategoryTests) ... ok
test_format_lines (test_by_category.SummarizeByCategoryTests) ... ok
test_sorted_by_unicode_codepoints (test_by_category.SummarizeByCategoryTests) ... ok
----------------------------------------------------------------------
Ran 10 tests in 0.001s
OK
```
CLI 手工验证（第一轮）：
```
$ python3 -m ledger summary
Transactions: 6
Total: $117.56
$ python3 -m ledger summary --by-category
Food: $11.95
Transit: $2.00
Travel: $100.10
food: $0.01
家庭: $3.50
```
（第一轮语义下 `Food` 与 `food` 精确分开，正确。）

第一轮完成后已先向用户给出完整小结，再进入第二轮。

---

## 第二轮（固定追问：casefold 分组）

### 补充约束
类别比较改为不区分大小写（Unicode `casefold`）；合并大小写不同类别时显示组内最小 `id` 记录的原始拼写；输出按 casefold 键升序；结果稳定且与 CSV 输入行顺序无关。

### 语义演进说明
第一轮 `summarize_by_category` 按原始类别精确分组（`Food`/`food` 两组）。第二轮最终约束将其演进为按 `category.casefold()` 分组、合并大小写变体。两轮语义在“大小写变体是否合并”上冲突，以第二轮最终约束为准：第一轮新增的 `tests/test_by_category.py` 中 `test_exact_case_grouping`、`test_by_category_output` 等按第二轮语义重写（`Food`/`food` 合并为 `Food: $11.96`），并补充第二轮专项测试。原基线测试 `tests/test_baseline.py` 两轮均未删改。

### 实际改动
1. `ledger/summary.py` — 重写 `summarize_by_category`：
   - 分组键 = `item.category.casefold()`；
   - 组内金额整数分求和；
   - 显示拼写 = 组内 `id` 最小（码点升序；并以 `(id, category)` 元组比较，id 相同时再按拼写码点，彻底排除输入顺序影响）记录的原始 `category`；
   - 返回列表按 casefold 键升序 `sorted(groups.items(), key=lambda pair: pair[0])`；
   - 排序键与显示选择仅依赖 casefold 键、id 与金额，不依赖输入顺序，保证稳定且与 CSV 行序无关。
   - `format_category_summary`、`summarize`、`format_summary` 未改动。
2. `tests/test_by_category.py` — 重写为第二轮语义（13 个测试中的 9 个新测试）：
   - `test_casefold_merges_case_variants`：`Food`+`food` 合并为一组；
   - `test_display_spelling_comes_from_smallest_id`：显示拼写取自最小 id 记录（`fOoD` id `A-01`），与输入顺序无关；
   - `test_casefold_unicode_merge`：`STRASSE`/`Straße` 经 casefold 合并（验证非 lower 语义）；
   - `test_sorted_by_casefold_key`：按 casefold 键升序（含 `家庭`）；
   - `test_independent_of_input_order`：同一组记录正序/逆序输入结果完全相同；
   - 保留空输入、格式化行、CLI 输出（更新期望值 `Food: $11.96`）、默认 summary 不变断言。
3. `docs/usage.md` — “按类别汇总”小节更新为 casefold 语义说明。
4. `ledger/cli.py` 第二轮无改动（第一轮接入的 `--by-category` 直接复用新语义）。

### 实际运行的命令与原始结果
```
$ python3 -m unittest discover -s tests -v
test_default_fixture_loads (test_baseline.BaselineSmokeTests) ... ok
test_default_summary_shape (test_baseline.BaselineSmokeTests) ... ok
test_list_command_runs (test_baseline.BaselineSmokeTests) ... ok
test_valid_money_inputs (test_baseline.BaselineSmokeTests) ... ok
test_by_category_output (test_by_category.ByCategoryCliTests) ... ok
test_default_summary_unchanged (test_by_category.ByCategoryCliTests) ... ok
test_casefold_merges_case_variants (test_by_category.SummarizeByCategoryTests) ... ok
test_casefold_unicode_merge (test_by_category.SummarizeByCategoryTests) ... ok
test_display_spelling_comes_from_smallest_id (test_by_category.SummarizeByCategoryTests) ... ok
test_empty_input (test_by_category.SummarizeByCategoryTests) ... ok
test_format_lines (test_by_category.SummarizeByCategoryTests) ... ok
test_independent_of_input_order (test_by_category.SummarizeByCategoryTests) ... ok
test_sorted_by_casefold_key (test_by_category.SummarizeByCategoryTests) ... ok
----------------------------------------------------------------------
Ran 13 tests in 0.002s
OK
```
CLI 实际验证（第二轮后，基线数据）：
```
$ python3 -m ledger summary
Transactions: 6
Total: $117.56          # 默认输出与第一轮、冻结基线一致，未变
$ python3 -m ledger summary --by-category
Food: $11.96            # Food(A-02 1200) + Food(A-01 -5) + food(C-01 1) = 1196；显示拼写取自组内最小 id A-01 的 "Food"
Transit: $2.00
Travel: $100.10
家庭: $3.50
```
与输入行顺序无关验证（临时 CSV 放 /tmp，未污染 workspace 基准数据）：
```
$ cat /tmp/t12_order_a.csv   # 与基线同序
$ cat /tmp/t12_order_b.csv   # 完全逆序的相同 6 条记录
$ python3 -m ledger --data-file /tmp/t12_order_a.csv summary --by-category   # EXIT 0
$ python3 -m ledger --data-file /tmp/t12_order_b.csv summary --by-category   # EXIT 0
$ diff /tmp/t12_out_a.txt /tmp/t12_out_b.txt
IDENTICAL: 与输入行顺序无关
```
两份输出均为：
```
Food: $11.96
Transit: $2.00
Travel: $100.10
家庭: $3.50
```

### 冻结文件未改动确认
```
$ git status --short
 M docs/usage.md
 M ledger/cli.py
 M ledger/summary.py
?? tests/test_by_category.py
$ git diff --stat -- tests/test_baseline.py ledger/data/transactions.csv   # 无输出，两者未改动
```

---

## 尚未完成的要求
无。两轮要求（CLI 标志、可复用函数、测试、用法说明、casefold 合并、最小 id 拼写、casefold 键升序、顺序无关、默认输出不变、基线测试不删改）均已完成并实际验证。

## 会话隔离说明
- 所有读写严格限制在 workspace 副本 `<评测根目录>/deepseek-harness/输出/deepseek-harness/T12/R01/workspace` 内；临时验证 CSV 仅写入 `/tmp`（t12_order_a.csv / t12_order_b.csv / t12_out_a.txt / t12_out_b.txt），未触碰题目源文件、基准仓库或其他运行目录。
- 仅使用 Python 标准库（argparse/csv/unittest/datetime 等既有依赖），未联网、未新增任何依赖、未修改既有测试 `tests/test_baseline.py`、未改动基准数据 `ledger/data/transactions.csv`。
- 本文件仅记录实际执行过的命令与检查；所有 “OK / PASS” 结论均来自上方列出的真实运行输出。
