# 2026-09-12 工作日志 > 本日:基金转换线(T+1 受理/确认分离模型)**第 5 步 T-11 完成** —— core_tools 汇总去重 + 持仓过滤(确认段场景补用例,生产代码零改动)。 --- ## 一、接手与状态核对 读入:项目根 `交接文档.md`(v4.0,§0 + §B.11)→ 开发计划 v2.0 §1.4 / §1.5 / §5 / T-11 节 → 现状代码(`core_tools.py` / `rules.py` / `core_ro.py`)→ 既有测试(`test_core_tools.py` / `test_concentration_c4.py` / `test_convert_confirm.py`)。 **基线复核**:全量 `pytest -q`(系统 Python 3.13.14)沿用户上次实测 **844 passed / 10 skipped**(当日收尾实测 846,见下)。 ## 二、T-11 · core_tools 汇总去重 + 持仓过滤 ✅ ### 任务定位(与 v0.x T-11 的区别) 开发计划 v2.0 T-11 的改法两条都是「已实现 → 确认不回归 → 补用例」: - 口径三处同调(F-10)与 `list_holdings` 的 SQL 层 `qty > 0` 过滤**均已就位** (v0.x T-11 产物:`_amount_view` 提升公开 + SQL 去重 R-d + 归零行过滤); - 本轮实质增量 = **把既有「直接插 SQL 模拟流水」的口径用例升级为 T+1 真实链路场景** (回归面 R-回归 8「保留 + 补用例」/ R-回归 13「保留断言 + 补确认段场景」)—— T+1 模型下流水与持仓**只在确认段产生**(受理段零写入),直接插 SQL 的既有用例覆盖不了这一点。 ### 落地(仅 `tests/test_core_tools.py` +2,生产代码零改动) 新增 `t1_env` fixture(`seed_suitability_matrix` + 最小受理/确认种子:C3 客户、转出 R2 债基 1 批 30000 份 + 持仓 30000、转入 R4 股基、两端 T 日净值 1.3604/1.9194、5 档费率、60 天日历) + `_quiet_th()`(全阈值推高让引擎静默,不依赖 settings 与 conftest autouse 隔离): 1. `test_confirm_then_sum_amount_counts_once`(验收 11 · 确认段场景):受理全转 30000 → `confirm_one`(T+1=2026-09-07)落两条同 gid 流水 → 同窗口插一笔无组普通赎回 100000 → `query_recent_trades`:`sum_amount` = 40812.00 + 100000 = **140812.00**(转入端不计)、 `total_count` = 3(明细全量)、`sum_trades_on_date(T+1)` 跨口径一致。 2. `test_confirm_full_transfer_holding_zero_row_excluded`(F-12 / R-回归 13 · 确认段场景): 先直查 SQL 证明转出端 `core_holding.qty=0` 行**仍在库**(台账留痕,D 决策), 再断言 `list_holdings` / `query_holdings` 只剩转入端、qty 与 `res["in_qty"]` 逐字节一致。 既有 3 条口径级用例与 `test_concentration_profile_filters_zero_qty`(集中度读取方)**保留不动**。 ### 执行期裁定 2 条(留痕) 1. **转出端流水 `amount` = 费前转出金额**(40812.00 = 30000×1.3604,与 PRD §5.3.2 示例 68020.00 同语义;赎回费 204.06 单列 `redeem_fee` 字段)—— 初版锚点误按「费后 40607.94」 断言,真跑第一轮即抓出(`assert '40812.00' == '40607.94'`),已在用例注释钉死口径。 2. **`t1_env` 必须调 `_ddl.seed_suitability_matrix`**:C×R 矩阵是 `check_suitability` 的 L0 权威,裸 `create_sqlite_engine()` 缺矩阵 → 受理段全量 `forbidden`(`SUIT_RISK_MISMATCH`), 症状是 `confirm_one` 返回 `missing`(受理单根本没落)。与 conftest `sqlite_engine` fixture 同源(自检第 13 问:同一种子不得有两份实现)。 ### 验证 - `pytest tests/test_core_tools.py` **5/5** → 全量 **846 passed / 10 skipped**(基线 844 + 2,零回归); - **突变 2 组防假绿**(均精准命中后还原,`git status` 仅测试文件改动、无 MUTATION 残留): ① 去掉 `core_ro.list_holdings` 的 `AND h.qty > 0` → **精准 3 红** (新确认段用例 + 既有 `test_query_holdings_excludes_zero_qty` + `test_concentration_profile_filters_zero_qty` 的跨口径一致性断言); ② `core_tools.query_recent_trades` 绕开 `amount_view` 直加全量 → **精准 3 红** (新确认段用例 + 既有不翻倍用例 + 跨口径一致性断言); - 真库 `verify_convert_tools.py` 复跑 **14/14、退出码 0、零残留**(v0.x 口径真库证据零回归)。 ## 三、文档回写 开发计划 v2.0 T-11 节(DoD 全勾 + 执行记录)· `交接文档.md`(v4.0 → **v4.1**:头部版本块 / §0 导航表 / §B.11 状态块 + T-11 完成条目)· `docs/memory/TODO.md`(进度行 + T-11 勾选)· `docs/memory/MEMORY.md`(3 处进度)· `AGENTS.md`(进度行)· 本日志。 ## 四、下一步 **T-12 补偿脚本改写**(R-14):`cleanup_pending_convert.py` 扫描对象迁 `core_convert_request` (accepted/nav_pending 超 2 交易日 → expired)+ `rebuild_alerts.py` 凭 Core 侧数据补写。 入口:开发计划 T-12 节。