diff --git a/AGENTS.md b/AGENTS.md index 8e7f61d..a80c47d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -66,15 +66,15 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri | 项 | 值 | |---|---| -| `main` | 下表全部 gate 实测于 `a5bbbba`(PR #113,D5 C5 收口) | -| `pytest -p no:warnings` | **2606 passed**(⚠️ 不要再传 `-q`:`pyproject.toml` 已含 `addopts="-q"`,叠成 `-qq` 会吞掉摘要行) | +| `main` | 下表全部 gate 实测于 `4e73ac1`(PR #116,D5 C6 收口) | +| `pytest -p no:warnings` | **2669 passed + 1 skipped**(⚠️ 不要再传 `-q`:`pyproject.toml` 已含 `addopts="-q"`,叠成 `-qq` 会吞掉摘要行) | | `ruff check .` | clean | | phase0 锚(`run-phase0 --config config/example.yaml`) | **ic 0.9600 / annual 0.8408**(自 P0 起从未变过,任何改动都不许动它) | | `qt.exec_baseline_freeze --verify` | **77/77 @ `45c14aa`** | | `validate-config` | 32/32 | | 唯一 OPEN 的 PR | #38(历史遗留,保持 OPEN) | -**当前主线 = 因子层深度重构(设计 v3.2,D0–D7)。D5 C5 已收口(PR #113):11 因子 × 3 模式 33 格全绿,C5 通过 ⇒ 满足 C6 前置条件之一。** F1 残桶前视缺陷另立 correctness PR #112 修复(panels `unclassified` 729,029 → 0)。**下一步 = Step 4 / C6:删 11 个旧 runner**(owner 2026-07-28 已裁定退役重生成能力;前置条件另有 R16 覆盖数非降的逐条核销,且改造 PR 与删除 PR 必须分开)。 +**当前主线 = 因子层深度重构(设计 v3.2,D0–D7)。D5 已全部收口**:C5 四腿对账 33 格全绿(#113),**C6 完成(#115 改造 + #116 删除)——11 个旧 runner 归零,决策③「杀第二条因子取数路径」收尾**,三个重生成工具退役为 verify-only、D1 基线 frozen-forever、校验已接进 C5 harness 的三个读入点。**下一步 = Step 5 / D6a–d 存量收口**(`aggregate → factors.minute` 的 shim 日落、`asof_daily_features` 的 `mmp_ew` hook 需要新家),然后 D7 收官全量重评估(**exec-only**)。 > **接手必读(唯一入口)**:[`tmp/design/HANDOFF_2026-07-30_claude_code.md`](tmp/design/HANDOFF_2026-07-30_claude_code.md) > ——含当前截面、F1–F5 裁定速查表、六步路线、派发/评审/限额的具体操作法、陷阱清单。 @@ -146,6 +146,6 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri ## 路线图 -1. **因子层重构收尾(当前主线)**:~~F1 残桶 correctness PR (#112)~~ → ~~C5 audit PR (#113)~~ → ~~C5 进度文档~~ → **C6 删 11 个旧 runner(下一步)** → D6a–d 存量收口 → D7 收官全量重评估(**exec-only**)。 +1. **因子层重构收尾(当前主线)**:~~F1 (#112)~~ → ~~C5 audit (#113)~~ → ~~C5 进度文档 (#114)~~ → ~~C6 改造 (#115) + C6 删除 (#116)~~ → **D6a–d 存量收口(下一步)** → D7 收官全量重评估(**exec-only**)。 2. **因子研究**:十一因子无一到 Adopt ⇒ 下一步优先做**换手/成本敏感的组合层验证**与更长 holdout,而不是继续堆新因子;补 PR #79 的 review;修订 HTML compendium。 3. **可选、须单独显式 goal**:I5g(强制 partial-fill / volume-cap);数据层 D6(`PanelStore` append/partition,仅当因子研究需要可复用派生面板时才启动);schema 守卫接 live `data-update`。 diff --git a/CLAUDE.md b/CLAUDE.md index 8e7f61d..a80c47d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -66,15 +66,15 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri | 项 | 值 | |---|---| -| `main` | 下表全部 gate 实测于 `a5bbbba`(PR #113,D5 C5 收口) | -| `pytest -p no:warnings` | **2606 passed**(⚠️ 不要再传 `-q`:`pyproject.toml` 已含 `addopts="-q"`,叠成 `-qq` 会吞掉摘要行) | +| `main` | 下表全部 gate 实测于 `4e73ac1`(PR #116,D5 C6 收口) | +| `pytest -p no:warnings` | **2669 passed + 1 skipped**(⚠️ 不要再传 `-q`:`pyproject.toml` 已含 `addopts="-q"`,叠成 `-qq` 会吞掉摘要行) | | `ruff check .` | clean | | phase0 锚(`run-phase0 --config config/example.yaml`) | **ic 0.9600 / annual 0.8408**(自 P0 起从未变过,任何改动都不许动它) | | `qt.exec_baseline_freeze --verify` | **77/77 @ `45c14aa`** | | `validate-config` | 32/32 | | 唯一 OPEN 的 PR | #38(历史遗留,保持 OPEN) | -**当前主线 = 因子层深度重构(设计 v3.2,D0–D7)。D5 C5 已收口(PR #113):11 因子 × 3 模式 33 格全绿,C5 通过 ⇒ 满足 C6 前置条件之一。** F1 残桶前视缺陷另立 correctness PR #112 修复(panels `unclassified` 729,029 → 0)。**下一步 = Step 4 / C6:删 11 个旧 runner**(owner 2026-07-28 已裁定退役重生成能力;前置条件另有 R16 覆盖数非降的逐条核销,且改造 PR 与删除 PR 必须分开)。 +**当前主线 = 因子层深度重构(设计 v3.2,D0–D7)。D5 已全部收口**:C5 四腿对账 33 格全绿(#113),**C6 完成(#115 改造 + #116 删除)——11 个旧 runner 归零,决策③「杀第二条因子取数路径」收尾**,三个重生成工具退役为 verify-only、D1 基线 frozen-forever、校验已接进 C5 harness 的三个读入点。**下一步 = Step 5 / D6a–d 存量收口**(`aggregate → factors.minute` 的 shim 日落、`asof_daily_features` 的 `mmp_ew` hook 需要新家),然后 D7 收官全量重评估(**exec-only**)。 > **接手必读(唯一入口)**:[`tmp/design/HANDOFF_2026-07-30_claude_code.md`](tmp/design/HANDOFF_2026-07-30_claude_code.md) > ——含当前截面、F1–F5 裁定速查表、六步路线、派发/评审/限额的具体操作法、陷阱清单。 @@ -146,6 +146,6 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri ## 路线图 -1. **因子层重构收尾(当前主线)**:~~F1 残桶 correctness PR (#112)~~ → ~~C5 audit PR (#113)~~ → ~~C5 进度文档~~ → **C6 删 11 个旧 runner(下一步)** → D6a–d 存量收口 → D7 收官全量重评估(**exec-only**)。 +1. **因子层重构收尾(当前主线)**:~~F1 (#112)~~ → ~~C5 audit (#113)~~ → ~~C5 进度文档 (#114)~~ → ~~C6 改造 (#115) + C6 删除 (#116)~~ → **D6a–d 存量收口(下一步)** → D7 收官全量重评估(**exec-only**)。 2. **因子研究**:十一因子无一到 Adopt ⇒ 下一步优先做**换手/成本敏感的组合层验证**与更长 holdout,而不是继续堆新因子;补 PR #79 的 review;修订 HTML compendium。 3. **可选、须单独显式 goal**:I5g(强制 partial-fill / volume-cap);数据层 D6(`PanelStore` append/partition,仅当因子研究需要可复用派生面板时才启动);schema 守卫接 live `data-update`。 diff --git a/docs/progress/07_factor_layer_refactor.md b/docs/progress/07_factor_layer_refactor.md index 4c115ff..f6a2894 100644 --- a/docs/progress/07_factor_layer_refactor.md +++ b/docs/progress/07_factor_layer_refactor.md @@ -47,3 +47,15 @@ - **重跑射程是实测不是论证**:扰动 `qt/factor_eval_reconcile.py` 后重算 5 个因子 `code_hash` → **5/5 逐字不变**;**负对照**扰动 `factors/compute/minute/primitives.py`(在 shared set 内)→ **5/5 全变** ⇒ 探针非空、harness 在 code_hash 射程之外、store 不失效。 - **已登记、本 PR 不改**:`_make_logger` truncate;jump 的 reports 腿对**值改动**实际不设闸(593 个 diff 里 **518** 个走既有更正承载登记 #11、`with_book(decision)` 是 report-only #13 ⇒ 值级依据应看 `no_book`/`bookclose` 两个 strict 格与 panels 腿,**结构性增删仍设闸**)。 - gates(lead 独立重跑):pytest **2606 passed** / ruff clean / phase0 锚 **0.9600·0.8408** / **32/32** configs / `--verify` **77/77 @ 45c14aa** / secret **0** / 陈旧措辞 grep **0** / 审计报告 `TBD` **0** / 编目对 main **纯追加(0 删除行)** / 冻结基线**今日 0 个文件被写**。 +- ✅ **D5 C6(PR #115 改造 + #116 删除,owner 2026-07-28 裁定「退役重生成能力」;两个 PR 分开、各带评审)**:**决策③「杀第二条因子取数路径」到此收尾——11 个旧 runner 归零。** + - **改造(#115)**:`qt/panel_freeze.py` / `qt/panel_reconcile.py` / `qt/hand_anchors_engine_values.py` 的重生成恒 raise `RegenerationRetiredError`(**旧参数仍被 parser 接受**,否则用户拿到的是 `unrecognized arguments` 而非退役说明),验证路径保留并加强:panel_freeze 新增**以前不存在的一条路**——逐面板重算 canonical hash + 整条 manifest 行,对 **git 里的**哈希表核,gitignored `manifest.json` 作第二见证互核(实跑 15/15);新增 `qt/frozen_manifest_doc.py`(文档表解析器)。`qt/cli.py` **11 个 `run-eval-*` 收敛到 `run-factor-eval`**,映射**从 `FACTOR_TO_REPORT_NAME` 派生**(评审进程内扰动该表验证:旧名失效、新名生效)。**R16 59 条逐条核销通过 ⇒ 删除的准入证**。 + - **删除(#116)**:删 **11 个 `qt/eval_*.py` + 10 个 `tests/test_eval_*_runner.py`**(`test_eval_contract_v1.py` / `test_eval_figures.py` **不是** runner 测试,保留)。可达性含动态形式(`importlib`/`__import__`/字符串拼名/glob)自查 + 评审独立复核。**node-ID removed 59,落在被删文件之外 0 条**;commit 措辞 "GONE WITH THE CAPABILITY … claims no replacement",**不为其中任何一条声称有测试替代**。R16 删前删后 **56/56 覆盖非降**;审计脚本删后 rc=1 **只**来自它 [1]/[2] 的删前口径,**没有把脚本改绿**(那会掩盖这个区分,§六.16 用在审计脚本上)。 + - **把校验接进 C5 harness 的三个裸读点**:`run_panels_mode`(冻结 D1 面板)/ `run_anchors_mode`(**`--mode anchors` 单跑时唯一的冻结面板读入点**)/ `load_anchor_rows`(anchors JSON)。面板侧 `verified_frozen_panel_path` 成为**唯一网关**(AST 强制),**按因子校验而非整棵扫**(0.2s vs 3.0s——为读 1 个而验 15 个,会把校验变成大家去关掉的东西)。**jump 分叉承重**:两棵树的 `jump_amount_corr_20.parquet` 是**两个不同定义**(v1.0 未截断 / v1.1 已截断,canonical `b6359f12…` vs `fafda485…`),路由**按路径读、不从 factor id 重推**;评审实测**拿 D1 的期望核 PR-C 字节 → 正确拒绝**。 + - **顺带查出冻结目录并不是不可变的**:普查 113 个文件,`exec_baseline` 77 + `panels` 14 + `panels_d2` 14 + `pr_c` 1 有 git 哈希覆盖,**7 个没有**(分级:3 个 `manifest.json` 字节未钉但内容三方互核 / 3 个 `.md` 可推导 / **只有 `hand_anchors_d2.json` 真正无保护**)。**而它恰是唯一被实际覆盖过的**——2026-07-25 一次 `hand_anchor_rows` 重跑冲掉 engine 比较记录(现 20 pending / **0 compared**),填回它的工具本轮退役 ⇒ `hand_anchors --verify` **永久红**(措辞 `NOT VERIFIED (nothing recorded)` 与 FAILED 区分、**未进任何 gates 清单**)。**丢的是可再验证性,不是结论**(D2 手算锚「88 行 0 失配」仍在 PR #89 与本文件在案)。⇒ 编目写明:**「冻结基线一个字节未写」是关于某次操作的陈述,不是关于该目录不可变的陈述。** + - **anchors 记录的 manifest 射程,经两轮才写准(本轮最值得留的一段)**:新增 git 里的 `docs/factors/d5_hand_anchor_record_manifest.json` 钉 sha + 清单。**先写宽了**——声称能抓「`daily_engine_compared` 悄悄归零」,而**那个 case 在当前 pin 状态上已不可能再发生**(损失已发生,被 pin 的是损失之后的状态,那个字段**已经在地板上**)。**改窄后又写窄了**——写成"抓行数/键集变化",而 `all_ok_frozen14` 是**布尔判定标志**、既非计数也非键、**却一直在被比较**(⚠️ 这句偏窄的措辞**是 lead 转述的**,实现方**按测量否掉了它**,理由"照抄会把同一个缺陷装进 fix 里")。**最终射程 = 形状(三个计数 + 键集 + 判定标志)**,豁免重述为**"形状未变"而非"重跑这个动作"**。评审在真实 pin 形态跑**六条带 6/6 与措辞一致**,并实测**动机形态的真实方向**(manifest 若 pin 在记录仍有 20 行时、记录随后丢掉 + 刷新 sha → **REFUSED**)⇒「当初若 pin 得早就能抓住」是**跑出来的不是推理**。**那条"承认限制"的测试被刻意做成会在检查被加强时变红**——评审真加了第 6 个 inventory 字段验证,**它红了** ⇒ **声明不可能再次比代码宽**。 + - **`hand_anchor_rows` 不再静默覆盖冻结记录**:目标已存在即拒绝,除非显式 `--allow-overwrite`;拒绝信息按**差集**算出"这次跑不会重新产生的键";**检查前移到 ~7 分钟计算之前**(在长跑结束才拒绝,教出来的是反射性加 override)。**明确否决 D-3**(读回旧文件 carry forward 自己不产生的键):会把**对着旧引擎值算出的**比较结果与**刚重算的**值拼进同一文件 ⇒ **内部不自洽的记录,比诚实的缺失更糟**;**因为它很诱人所以写进案卷**(禁翻烧饼)。 + - **`.gitignore` 规则终于表达了它一直想表达的意思**:`git add -A` 曾把一个**指向本机绝对路径的 `artifacts` 符号链接**提交进来——**被 `test_frozen_bytes_are_untracked_while_the_manifest_is_tracked` 抓住**(该测试守的正是整个校验设计赖以成立的 git/gitignore 分家:字节与哈希若都在 git 里,一个 commit 就能把两者一起挪走)。根因 `artifacts/` **带斜杠**既不匹配符号链接也不匹配 `artifacts_local_phase0/`(**后者无人守**)⇒ 改为 `artifacts`(无斜杠)+ 新增 `artifacts_local_phase0/`;**代价写在规则旁:那两个路径从此在 `git status` 里不可见。** + - **评审最值得记的一击**:**「只钉函数、没钉接线」这个洞,在三个读入点里活下来一个。** 面板侧修好后有两道守卫,而记录侧六条测试把 `verify_anchor_record` 这个**函数**测得很扎实、**却没有一条说 `load_anchor_rows` 必须调用它** ⇒ 把那行换成 `pass`,**全量套件 2661 passed / rc=0、与未变异树逐数相同**。实现方原话:**「一个只在学到它的地方被应用的教训,等于没被应用。」** 修法用**行为测试承重而非 AST**,并把理由做成 **mutation #24**:保留调用、只吞掉异常 ⇒ **AST 通过、行为测试红** —— **把"优先行为"从论断变成了可复跑的性质**。 + - **方法论新增(本轮换来的)**:① **一个失败的 mutation 逼出了更好的设计**——首版针对接线的 mutation 没牙(只钉"路由"没钉"接线"),正是它促成单一网关重构;② **"把自己的守卫说弱"比"说强"更难被自己发现**——说强会被 mutation 打红,**说弱不会;没有任何 mutation 会因为文档太谦虚而失败** ⇒ 只能靠**拿措辞去对实测行为**,且必须由**别人**做;③ **控制组必须先 ACCEPTED**,否则后面每个 REFUSED 都是空的(与"mutation 必须先断言落地"是同一道理的两面)。 + - ⚠️ **同一个协议洞复发三次**(评审两次发现**树在它测量期间被改动**:一次因 lead 收到主报告就派返工而评审仍有追加项、一次因实现方声明停手后自审出真缺陷**直接改了**)。**两次都是"与预期矛盾的观察"抓住的,不是测试。** 三方各补一条才闭合:**lead** 等全部条目交付且明确收工才派返工;**评审**每份报告显式声明是否收工;**实现方**声明停手后非经指派不得恢复工作——**哪怕自己发现真缺陷,也先报告再动手**。**两次污染都被逐条厘清射程而非笼统作废,无一轮重来**,靠两条定界规矩:**刻度是「哪次测量读了哪份文本」不是 commit 时间戳**(工作树**先于** commit 改变,实证一次探针跑在 commit 前 90 秒却已读到新文本);**「没动可执行代码」要用剥掉 docstring 后的 `ast.dump` 精确比来量**。 + - gates(lead 独立重跑):pytest **2669 passed + 1 skipped** / ruff clean / phase0 锚 **0.9600·0.8408** / **32/32** configs / `exec_baseline --verify` **77/77 @ 45c14aa** / 三个重生成入口 **rc=1**(loud)/ 两个 `--verify` OK / 旧 CLI 名 **rc=1** + 迁移提示、新名 rc=0 / `git add -A --dry-run` 无可暂存项 / secret **0** / 冻结基线**自 2026-07-25 起 0 写入**。实现方 mutation **31/31 有牙**,评审两轮各自独立写 mutation 复现关键项。 diff --git a/docs/progress/pr_ledger.md b/docs/progress/pr_ledger.md index 00b9688..b87a335 100644 --- a/docs/progress/pr_ledger.md +++ b/docs/progress/pr_ledger.md @@ -21,3 +21,6 @@ | #112 | `amp_marginal_anomaly_vol` 残桶 correctness fix(单独成 PR,非重构一部分) | | #113 | D5 C5 四腿全量对账收口(F2/F3/F4 扩类 + F5 修复 + NIT-1 + 审计报告) | | #114 | 进度文档(F1 + D5 C5) | +| #115 | D5 C6 改造:三个重生成工具退役为 verify-only + CLI 收敛 + R16 核销 | +| #116 | D5 C6 删除:删 11 个旧 runner + 10 测试,校验接进 C5 harness 三个读入点 | +| #117 | 进度文档(D5 C6) |