From 95ad98d653127cfc3d0be08d50e90dfbd4ae07f0 Mon Sep 17 00:00:00 2001 From: shaofl <2899218482@qq.com> Date: Sat, 25 Jul 2026 16:28:11 -0700 Subject: [PATCH] docs: record refactor step D5b (PR #99) and the confirmed jump_amount_corr look-ahead --- AGENTS.md | 3 ++- CLAUDE.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 9758df9..eaace27 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -57,7 +57,7 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri ## 开发约定 - **交流中文**;代码/注释/commit message 用**英文**。 -- **Git**:feature 分支 + PR。**PR #1(P0+P1)、#2(P2-1)、#3(P2-2)、#4(进度文档)、#5(P2-3)、#6(进度文档)、#7(P2-4)、#8(进度文档)、#9(P3-1)、#10(进度文档)、#11(P3-2)、#12(P3-3)、#13(进度文档)、#14(P3-4)、#15(进度文档)、#16(P3-5)、#17(进度文档)、#18(P3-6)、#19(P3-7)、#20(进度文档)、#21(P3-8)、#22(进度文档)、#23(P4-1)、#24(进度文档)、#25(P4-2)、#28(tushare 权限/限频探测 + capability registry)、#29(I1–I4 分钟级 intraday pipeline,4 commit 一 PR)、#30(进度文档)、#31(P4-3 因子支撑端点缓存 + 21:00 data updater,2 commit 一 PR)、#33(P-I5a 事件驱动回测架构重构 + opt-in 分钟尾盘 event model,4 commit 一 PR)、#35(P-I5b 分钟尾盘执行期 raw stk_limit 涨跌停可行性,4 commit 一 PR)、#37(P-I5c MMP 分钟因子端到端 opt-in alpha)、#39(P-I5d MMP 五分位分组回测 standalone,含 I5c plumbing)、#41(数据层 D1 契约文档 + token 解析去重)、#43(数据层 D2 TushareCache specs/parsers 拆分)、#45(数据层 D3 report-only 数据质量层)、#47(数据层 D3b default-off `data-update` 质量报告钩子)、#49(数据层 D4 coverage ledger 批量写 + 进程内查找缓存)、#51(数据层 D5 opt-in 有界并发 + 全局限频器)、#53(P-I5e MMP 五分位 CSI300 独立泛化检验,负结果)、#55(P-I5f 分钟尾盘执行流动性/容量诊断,report-only)、#57(数据层 schema 注册表 + default-off drift 守卫)、#59(数据层 全A 增量 auto-warm + systemd 定时,default-off)、#61(数据层 全A 历史回填 `data-backfill`,分块/续跑/失败隔离)、#62(进度文档)、#63(因子评估契约层 `analytics/eval/` + StandardFactorEvaluator + dashboard + PR-C 因子,4 commit 一 PR)、#64–#73(PR-D…PR-M 十个分钟因子复现,**一因子一分支一 PR**)、#74(因子评估契约 v0.8 + v0.9 判定门修复)、#75(尾盘执行价 VWAP + 分钟持有期收益复权)、#76(报告披露修正 + I5f 名义按真实规模重测)、#77(`adj_factor` 下降质量检查)、#78(#76 的 follow-up:扫描式正则守卫被七种改写实测证否 → 闸门描述改单一来源)、#79(十一因子改 14:51 VWAP exec-to-exec 基准,**评审未返回、靠自查合并**)、#82(闸门/成交价描述全仓清扫,12 处;#78 守卫射程不足的修正)、#80(进度文档)、#84(因子层重构 D0 纸面契约:availability policy 常量 + 预指派表 + 性质编目)、#85(进度文档)、#86(因子层重构 D1:registry + PanelField requires + FactorSpec 契约 v1.0)、#87(因子层重构 D1 面板冻结:14 因子 raw 基线 + manifest)、#88(进度文档)、#89(因子层重构 D2:minute primitives + ops + 11 因子迁移,与冻结基线逐位一致)、#90(进度文档)、#91(因子层重构 D3:store 层——稀疏值存储 + key/指纹 + tail-recompute + R5 fina 视界统一)、#92(进度文档)、#93(因子层重构 D4:FactorService + decision-view materializer + pooled 饱和填充)、#94(进度文档)、#95(因子层重构 D5a:exec 基线冻结 + 11 runner 差异编目 + 可行性探测)、#96(进度文档)、#97(因子层重构 D4b:per-symbol 流式物化)均已 merge 到 `main`**;**OPEN 未合并:#38**(见 P-I5d 处置,未获授权关闭)。commit 用 conventional 格式,**无 attribution**(不加 Co-Authored-By)。 +- **Git**:feature 分支 + PR。**PR #1(P0+P1)、#2(P2-1)、#3(P2-2)、#4(进度文档)、#5(P2-3)、#6(进度文档)、#7(P2-4)、#8(进度文档)、#9(P3-1)、#10(进度文档)、#11(P3-2)、#12(P3-3)、#13(进度文档)、#14(P3-4)、#15(进度文档)、#16(P3-5)、#17(进度文档)、#18(P3-6)、#19(P3-7)、#20(进度文档)、#21(P3-8)、#22(进度文档)、#23(P4-1)、#24(进度文档)、#25(P4-2)、#28(tushare 权限/限频探测 + capability registry)、#29(I1–I4 分钟级 intraday pipeline,4 commit 一 PR)、#30(进度文档)、#31(P4-3 因子支撑端点缓存 + 21:00 data updater,2 commit 一 PR)、#33(P-I5a 事件驱动回测架构重构 + opt-in 分钟尾盘 event model,4 commit 一 PR)、#35(P-I5b 分钟尾盘执行期 raw stk_limit 涨跌停可行性,4 commit 一 PR)、#37(P-I5c MMP 分钟因子端到端 opt-in alpha)、#39(P-I5d MMP 五分位分组回测 standalone,含 I5c plumbing)、#41(数据层 D1 契约文档 + token 解析去重)、#43(数据层 D2 TushareCache specs/parsers 拆分)、#45(数据层 D3 report-only 数据质量层)、#47(数据层 D3b default-off `data-update` 质量报告钩子)、#49(数据层 D4 coverage ledger 批量写 + 进程内查找缓存)、#51(数据层 D5 opt-in 有界并发 + 全局限频器)、#53(P-I5e MMP 五分位 CSI300 独立泛化检验,负结果)、#55(P-I5f 分钟尾盘执行流动性/容量诊断,report-only)、#57(数据层 schema 注册表 + default-off drift 守卫)、#59(数据层 全A 增量 auto-warm + systemd 定时,default-off)、#61(数据层 全A 历史回填 `data-backfill`,分块/续跑/失败隔离)、#62(进度文档)、#63(因子评估契约层 `analytics/eval/` + StandardFactorEvaluator + dashboard + PR-C 因子,4 commit 一 PR)、#64–#73(PR-D…PR-M 十个分钟因子复现,**一因子一分支一 PR**)、#74(因子评估契约 v0.8 + v0.9 判定门修复)、#75(尾盘执行价 VWAP + 分钟持有期收益复权)、#76(报告披露修正 + I5f 名义按真实规模重测)、#77(`adj_factor` 下降质量检查)、#78(#76 的 follow-up:扫描式正则守卫被七种改写实测证否 → 闸门描述改单一来源)、#79(十一因子改 14:51 VWAP exec-to-exec 基准,**评审未返回、靠自查合并**)、#82(闸门/成交价描述全仓清扫,12 处;#78 守卫射程不足的修正)、#80(进度文档)、#84(因子层重构 D0 纸面契约:availability policy 常量 + 预指派表 + 性质编目)、#85(进度文档)、#86(因子层重构 D1:registry + PanelField requires + FactorSpec 契约 v1.0)、#87(因子层重构 D1 面板冻结:14 因子 raw 基线 + manifest)、#88(进度文档)、#89(因子层重构 D2:minute primitives + ops + 11 因子迁移,与冻结基线逐位一致)、#90(进度文档)、#91(因子层重构 D3:store 层——稀疏值存储 + key/指纹 + tail-recompute + R5 fina 视界统一)、#92(进度文档)、#93(因子层重构 D4:FactorService + decision-view materializer + pooled 饱和填充)、#94(进度文档)、#95(因子层重构 D5a:exec 基线冻结 + 11 runner 差异编目 + 可行性探测)、#96(进度文档)、#97(因子层重构 D4b:per-symbol 流式物化)、#98(进度文档)、#99(因子层重构 D5b:评估契约 v1.0 + 诊断通道 + 14:50 可见性守卫;**C4 中止上报**)均已 merge 到 `main`**;**OPEN 未合并:#38**(见 P-I5d 处置,未获授权关闭)。commit 用 conventional 格式,**无 attribution**(不加 Co-Authored-By)。 - **不过度设计**:按路线图 MVP 先打通一条端到端链路,再加层(architecture.html §11,Phase 0→3)。 - **secrets** 一律走外部 `.config.json`;repo `.gitignore` 已排除数据产物(`*.parquet`等)、缓存、`tmp/`(仅留架构文档)。 - 文件小而专(<800 行),immutable 优先。 @@ -373,6 +373,7 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri - **D3(PR #91,整步已关账——store 层,纯附加未接线)**:`factors/store/`(hashing/code_hash/fingerprint/keys/values/run_registry/incremental,全 <800 行)+ **R5 前置修复**(`fina_tail_days` 单一真相迁至 `data.cache.fina_tail_days`,回测 `_build_cache` 与 data-update 两 builder 统一传 fina 400 尾 override——回测 read-through 现会补 fina 尾窗,行为变更已披露;`data_update.fina_tail_days` 删除对 repo 外旧 YAML 属 breaking,仓内两 config 已迁)。key = params_hash + code_hash(自身模块 + 枚举共享集{minute primitives/ops/base/spec} + **one-hop 直接项目内 import 折叠**:AST 自动派生、无手工清单、不做传递闭包——评审 MEDIUM 实测 `reversal_20` 可 build 且值=−momentum 而 momentum.py 取值面不入 key = 陈旧复用洞,据此修;改 momentum → candidates 系 key 变、financial/分钟系不变,无全局过度失效)+ view + 数据指纹(schema-version 维 = data/clean PIT 承重模块内容 hash;`price_level` 另掺 per-symbol adj_factor 事件表 hash 含锚值,收官集零成员不豁免 fixture 测试)。存储:单文件 parquet date 排序 / 原子写 tmp+`os.replace` / per-artifact O_CREAT|O_EXCL 锁(两进程 gap-fill 零丢行实测;锁 neuter mutation 证明锁对原子写也承重)/ JSONL append-only 运行注册表(no-secret:sanitize_text 过自由文本,redaction 测试钉住)/ 损坏文件=miss / **不建 coverage ledger**(值确定性可重算)/ 启动一致性断言(registry 条目必须命中代码注册表)。tail-recompute:`w_overlap=max(W_dep, 端点修订视界)`——W_dep=传递 lookback 深度经 **`FactorSpec.lookback_depth`(optional 附加字段,contract v1.1)**声明、store 消费点 HARD-REQUIRE(14 真实因子未声明 → loud 报错,声明属预注册动作留 D4);视界经 `revision_horizon()` 从 live config 派生(调大 refresh_recent_days → 重叠窗变宽 mutation 实证,无硬编码 14/400);重叠 NaN-aware bitwise,失配按 adjustment 分类(returns_invariant→loud 上游回改记录 / price_level→预期);schema 指纹失配 → schema_void_full 全量重算不误报 revision;§六.18 teeth(headline 深度欠采 → 假 mismatch)测试钉住。#adjustment NET-NEW 性质测试钉本格:扰动 qfq 锚 → returns_invariant 真因子(日频 volatility_20 + 分钟 valley_relative_vwap)逐 bit 不变,批量 census 9/5/0 ≡ D0 表。评审 APPROVE-WITH-NITS(0 CRIT/HIGH,1 MEDIUM+3 LOW+1 NIT;MEDIUM/LOW-1/LOW-3 合并前修于 `fd906f4` 并经 delta 复核三项 CLOSED——评审亲手重跑 momentum on-disk mutation 5/5、allowlist 注入、锁 neuter,并猎杀「不可能失败的测试」零发现)。留 D4 注记:materializer 必须传 live `data.cache.fina_tail_days` 勿靠 400 默认;two-hop 组合链是 one-hop 折叠的已知边界(今日无实例,设计明令不做传递遍历器);`availability_policy` 编辑会 over-invalidate 其 importer 的 store(安全方向、D4/D5 churn 期真实重算成本);单点填≡批量填(P8)是 D4 验收项。gates:**2031 passed**(=1955+76)/ ruff / 31 configs / phase0 锚不变 / provisional 锚绿 / secret 0。 - **D4(PR #93,整步已关账——FactorService + materializer;四轮评审揪出两个 HIGH + 一项设计修正)**:`factors/service.py`(frozen `DecisionPoint` + `cross_section`/`panel` **都 read-through 读 D3 store**,miss 触发唯一引擎,配对合法性复用 D0 `require_legal_pairing` 构造期强制)+ decision-view materializer(R18 **全** policy-lag:日线非-open ≤ d−1、**open[d] 字段级例外从 policy 表派生**、daily_basic/fina ≤ d−1、分钟 ≤14:50;ex-date 只暴露**布尔**的类型边界;`CacheHorizonConfig` 从 live config 构造缺属性即 raise)+ process 编排下沉 `factors/process/orchestrate.py`(`_process_factors` 薄委托逐字行为保持)+ 14 因子 `lookback_depth` 预注册(参数化派生+测试钉死)+ 热路径计时 smoke(真实缓存 cache-only 40 票共享读 ≈2.0x,诚实标注不外推)。**评审故事(P8 单点填≡批量填连揪三层真缺陷)**:①【设计修正】valid-day **pooled** 因子(8/11 分钟因子按滚动机制码检划分,非按观察到分歧的 3 个——#82 教训)trailing N 个**有效日**的日历深度数据依赖、**无界** → **证否 v3.2 §3.3 R4「W_dep=各 lookback 之和」假设**,固定 40 日 trim 使单点填 vs 批量填 finite↔NaN 分歧;②首版不动点判据(值稳定+nbars 稳定)被评审构造 **>1 chunk 停牌 gap 反例**击穿(finite-vs-finite 静默错值)→ 改**结构性判据**(锁定单调性:丢窗口头部 baseline_days 交易日其余分类 FINAL;锁定区 output-date 计数 ≥ lookback_days,gap-immune)+ provider 显式 `earliest_available`(nbars 推断删除,中段 gap 不许当 data start),上版「divergence is gone」overclaim 在 commit message 开篇更正;③判据循环只遍历**有输出的** symbol → 长停牌票**无否决权被静默丢出截面**(撞 I5a 红线)→ 改遍历**请求的** symbol 列表,评审 fixture(600519 丢名复现 + 锁定偏移 416.0 vs 438.0 静默错值)全部落成 committed 测试 + 源码级 mutation 双 witness(rc=1/rc=0,评审亲手用自己未改动的脚本独立复跑确认)。`_MAX_SATURATION_CHUNKS` 耗尽改 loud raise(红线 #9)+ raise 分支有测试。**代价如实入 docstring**:凑不满 lookback 有效日的票拖全 universe 扩到声明 floor;per-symbol 饱和起点是 D5 优化**且非纯优化**(`intraday_amp_cut` 截面 z-score 耦合)。**早期区域量化(D5 面板腿归因名目)**:分钟缓存真实起点 **2015-01-05** → D1 冻结基线(锚 2021-07-01)对 pooled 因子属 **anchor 截断**,饱和加载在 2021-07→10 五票上 ridge 有 157/184 cell 不同(79 NaN→finite,按月递减至零)——D5 对账须具名归因「saturation vs anchor truncation」。JC1 已裁定:P8 逐 bit 对滚动因子降为 ≤1e-12 可归因浮点重排(实测 floor ~3.5e-18,真缺行效应 ≥7 个数量级于容差;NaN mask 必须精确)。留 D5/D6:声明 floor 应从分钟 coverage ledger 派生 per-symbol(现为硬编码常量,声明偏晚会静默截断);`valley_price_quantile` 分钟绑定 DEFERRED(loud 报错,已声明 pooled,D5 绑定继承饱和路径**不许**固定 trim 绕过);零输出否决语义已被测试+mutation 钉住,D5 为性能回退它=放回 HIGH;blanket shift 依赖「因子输入面板只含端点列」的 D6 wiring 契约。gates:**2098 passed**(=2031+67)/ ruff / 31 configs / phase0 锚不变 / provisional 锚绿 / secret 0。 - **D4b(PR #97,实施期修订 A1 新插入的迁移步——per-symbol 流式物化;改因子取值路径,自带四腿验收)**:materializer 改「逐票读 → 立刻聚合到日频 → 丢弃」,**切口落在截面 combine 之前**。**规模(真实评估面 CSI500 995 票 × 5 年,cache-only `live_calls=0`)**:名义最大单帧 **122.2 GB → 0.066 GB**、峰值 RSS **~115 GB → 0.964 GB**(可用 56 GB,占 1.7%);三种加载几何各跑一因子(pooled×截面 / pooled / bounded)全部 995/995 票、**每次请求 1 票**;峰值稳定 0.73–0.96 GB,**由「一票 bars + 日频面板」决定而非 universe 决定**;扩到 floor 的代价只落在那 84 只 late 票(40 次调用/14.95s),不再拖着 911 只陪跑(dense 票 1.0 次/0.59s)。**四腿**:① D4 既有 31 测试原样通过(P8 四 regime / 锁定偏移 / 零输出否决 / exhaustion loud raise),评审证其**真在测新路径**(单文件即覆盖 `materialize.py` 86%,per-symbol helper 体均被覆盖);② 手算锚 18 行**零项目 import**(运行时守卫断言 `sys.modules` 无 factors/qt/data/runtime/alpha,653 模块 0 命中),`volume_peak_count` 9/9 精确 0.0、`intraday_amp_cut` ≤1.998e-15;③ 逐格对账真实缓存 40 票×6 月 vs 整 universe 单帧(3,711,400 行):10/10 index 相同、**NaN 集合差异全 0**、5 个逐位相同、最差残差 3.275e-14,`intraday_amp_cut` 在 **4,720** 个真实 cell 上对上(评审以 **main 真引擎**为参照复跑得 **max|abs|=0.000e+00**,比文档的 2.5e-14 更干净——因两侧加载几何相同,已写进文档);④ 规模证明如上,且 `--mode reconcile` 使 §6.1 那张最承重的表**可从仓库复跑**(评审亲跑:10 行×4 列与文档逐格一致,且**非空对账**——参照侧完全不经 `materialize_range`,只在被检验的加载几何上不同)。**评审带来的头号反转**:实现方把 per-symbol trim 描述为「更保守的语义细化」,评审证明它在**修 D4 的真缺陷**——同一稀疏 fixture 跨引擎对照,3 个 bounded 因子各动 1 cell,**三个都是 D4b == 几何无关真值、D4 ≠ 真值**(`jump` 0.0901 vs 0.1571;另两个 D4 给 **NaN** 而 D4b 给正确 finite);union trim 给稀疏票喂的自有交易日不足 `lookback_depth` = 红线 #6 的 load-geometry 依赖。且四个旧 runner **逐票读全窗口、根本没有 union trim** ⇒ per-symbol trim 是**朝 D1 冻结基线靠拢**——实现方给 D5 的预警「稀疏票对不上先看这里」**方向反了**(反在安全侧),已订正为指向饱和深度/anchor 截断。超集性质经评审证严(子集第 k 大 ≤ 超集第 k 大),反例构造失败。**MED-1(D4b 新引入的唯一真引擎缺陷)**:请求含重复 symbol 时逐票流式会独立处理每个重复项——48→52 行、4 个重复 (date,symbol),`intraday_amp_cut` 更因重复票**两次进入截面**而 **48/48 共享 cell 全部变值**(D4 免疫是靠 provider 的 `isin` 幂等吸收)→ 改**保序去重**(而非 loud raise:去重**精确复现单帧引擎对同一调用的返回**、保持「只改内存剖面」,raise 会新拒绝前一引擎接受过的输入);评审跨引擎复核修后 0 差异。**另两条「说法与事实相反」**:MED-2 一处 docstring 称旧 mutation 写法「cannot fail」,评审原样跑在 D4b 上是 **FAIL**——它其实是 **cannot pass**(性质保住、只换写法,属 §六.16 而非偷改测试;计数 70→**72**=70 单点填+2 批量填);MED-3 可行性文档声明了一条「本步绝不允许 finite↔NaN 翻转」的政策,而 per-symbol trim **能且实测确实产生**(3 个 bounded 里 2 个 NaN→finite),40 票样本只是没触发 → 改为如实陈述。**lead 合并前补的闭环**:派生 id 列表只守住了「加了因子却没进对账」一个方向;评审实测另一方向——把某因子从**两张 binding 表都删掉**,该文件 53 passed、全量 2169 passed **全绿**,因子从每条 parametrize 里静默消失。故新增闭包测试,真相源改为**`factors/compute/minute` 下定义的全部 `Factor` 子类**,未分类即红(mutation witness:删 `PeakIntervalKurtosisFactor` occurrences 4→0 先断言落地 → 转红;还原后 `binding.py` 逐字节相同、58 passed)。**A1 点名的致命陷阱未踩**:`factors/service.py` diff **0 行**(不许在 service 层按 symbol 分批——`_ensure_coverage` 只按日期判缺口会静默丢名)。gates:**2174 passed / 1 skipped**(= 2117 + 57,**node-ID 集合证 0 个既有测试被挤掉**)/ ruff / 31 configs / phase0 锚不变 / secret 0 / `exec_baseline --verify` 77/77 head 未变 / 冻结面板 mtime 未变。留 D5:扩张步长(late 票 40 次重读,纯性能但仍是加载几何改动、欠自己的对账,**刻意没夹带**);声明 floor 仍是 universe 级硬编码常量未按票从 coverage ledger 派生;`valley_price_quantile` 仍 DEFERRED,D5 绑定**继承流式路径不许固定 trim 绕过**;10 个因子只跑了 3 个的全规模证明(几何全覆盖,评审证未测因子的加载参数与已测者相同或被支配);日频路径仍整 universe 单帧(995×1210 行,量级小,未动)。 + - **D5b(PR #99,D5 后四块只交付了 C3——**C4 中止、C5/C6 未做、什么也没删**;中止本身是本步最重要的产出)**:**发现并(两方独立)确认一个真实前视缺陷**:`jump_amount_corr_20` 是十一个分钟因子中**唯一**不做 14:50 截断的(`decision_time`/`prepare_visible_minute_bars` 引用数 **0**,其余 4–10),旧 runner 用 `end+23:59:59` 取整日 bar 直接喂它、全程无补救。**exec_to_exec 下日 d 的入场锚是当天 14:51 bar 的 VWAP**,而值用到 d 的 14:50–15:00 bar ⇒ **信息集越过自己的入场锚**。扰动实测(两方各用不同票/不同窗口,前置断言两腿齐全):实现方 12 票/2021H2 **1,477/1,477 格全移动**(max|diff| 1.276)、其余 9 个 bound 因子 **0 格**;评审另 12 票/2023H1 **1,373/1,373**(max|diff| 1.054)、**其余全部 11 条 0 格**(并补测了实现方漏掉的 `valley_price_quantile_stats` 与 `mmp_ew`);评审再加一刀**只扰动 `bar_end >= 14:51`**(执行 bar 本身及其后)→ **1,363/1,363 移动**——**信号看到了自己成交的那一分钟及其后 9 分钟**。而其已发布 artifact 明写 `spec.decision_cutoff="14:50:00"`/`return_basis="exec_to_exec"`/`execution_window="[14:51:00,14:56:59]"`,verdict **Watch**、predictive 轴 **PASS**(|NW-t| 15.19)——**报告声明了它没有执行的检查**。**既有测试为何没抓到**:`test_pit_perturbing_future_bars_does_not_change_factor_at_d` 守的是**跨日**边界,其 fixture session 只有 09:31–09:36 六根 bar、**根本不存在 14:50 边界**;日内边界只在 **PR #79** 把入场锚从 `close(d)` 移到 `14:51(d)` 之后才承重,而 #79 评审未返回、这**恰在其「未独立核」清单射程内**。**裁定(设计文档实施期修订 A3)**:用户 2026-07-19 常设授权明写「全日数据因子一律截断到 14:50……授权直接截断,不必逐因子再问」,而该因子**建于此授权之前** ⇒ 加截断是**补用既有授权**非新研究决策;**但评审的程序性修正已采纳**——从重构视角它仍是定义变更、而授权来自研究侧不来自重构 ⇒ **必须单独成 PR、显式标注 correctness fix,不许进 D5 任何 commit**(已另派)。幅度实测 pearson **r=0.9993**、mean|diff| 0.0042——**缺陷是结构性的必须撤回,但修正代价大概率很小;verdict 存活与否必须由真正的重跑给出、不许由相关系数推定**。**交付的 C3(评估契约 v1.0)**:`EvalConfig.view`/`return_basis` 构造期经 D0 `require_legal_pairing` 强制配对;provenance 增 requires/adjustment/overnight_boundary/lookback_depth + `eval_contract_version`;跨口径汇总**缺 view/basis 列拒渲染**(声明了列却留空同样拒);**判定门一个数没动**(评审证 6 个文件 md5 与 main 逐字节相同,8 个门值逐值钉死)。**评审两轮 APPROVE-WITH-NITS,2 MEDIUM 全关**:**MEDIUM-1「守卫守不住自己」**——声称钉住 identity 修复的测试是对**函数源码做子串匹配**,评审把赋值掏空、两个 token 留**注释**里 → 每份 exec artifact 都会继承调用方 close 身份而实际按 exec 收益打分,**52 passed 全仓无一抓住**(#78 教训的翻版,且放行的恰是同一 commit 刚修的缺陷)→ 抽 `exec_identity()` 改**行为断言**,评审原样重跑逃逸 **4 failed**,并验了**假阳性**方向(重构进 helper 不误报,58 passed)。**MEDIUM-2「假声明上升一层」**——exec 路径无条件声明 `view=decision`,但 with_book 的因子簿是 close(d)+当晚 daily_basic(**§1.1 自己列为「已经咬过人的活缺陷」**),且 jump 连 no_book 格都不成立;而该字段定义是「**因子值**取自哪个信息集」,with_book 有**两个**信息集、一个字段表达不了 → **这正是该字段被造出来防的那种缺陷、只是上升一层**。**现在修免费**(还没 artifact 带它),C5 一跑就写进 22 份。修法:**先拆两个事实**(②单独不成立——登记例外并不能让 `view=decision` 在 with_book 上变成真话)→ 新增 `EvalConfig.book_view`(唯一知情方声明)+ `subject_view(factor_id)` **从事实派生**(deny list `NOT_DECISION_CUTOFF_SAFE` 放**因子侧**——「它是关于**值**的事实」,由可见性测试**测量**而非声明,本地副本已删)。**刻意不校验 `book_view`×basis 配对**,评审的裁定值得作通则记下:**失配摧毁意义 → 拦;失配只带来已披露、方向已知的偏 → 记**(close-view 书是 Incremental 轴的控制变量、偏的方向已预注册;拦它不会让信息集不混,只会让 artifact 说不出它混了)。**并落一个有意的响亮阻断**:jump 现在派生出非法配对 → 其 exec 评估 loud raise(截断修正落地即解除,删 deny list 一条)——在它被修正前**不存在**它的诚实 exec artifact,阻断优于假声明(红线 #9)。**实现方又一次自查出同形缺口**(单测说不了调用方怎么接线:with_book 传 `book_view=None` → **28 测试全绿**)并照实上报、补端到端断言读**两份实际写出的 JSON**。**另三个前提问题已裁定并立项**:(a) 3/11 因子的覆盖率披露无法由 store 供给(每次披露必重算,已写成行为并测试锁定);(b) `valley_price_quantile` 会被 materializer 二次滞后成 close_{d-2},评审实测第三条路**逐比特等价**(`max|diff|=0.000e+00`、`Series.equals=True`,破坏对照 7.3e-2 证非空过)⇒ 属实现变更可授权,落地须**两侧都钉**等价性测试 + 左端多一天历史;(c) **store key 无 universe 维(存量 CRITICAL,对 D6/D7)**——评审拆成**两个独立失效模式**:① `_ensure_coverage` 缺口判定**只按日期不按 (date,symbol)** ⇒ 第二批「无缺口」直接返回、那批票**静默从截面消失**,影响**全部 11 因子**(**讽刺**:A1 否决「按票分批」出路的理由一字不差就是这条,**红线写在文档里而服务层身上就带着它**);② `intraday_amp_cut` 的 z-score 在物化期发生 ⇒ 存储值是 universe 的函数而 key 不这么说(实测:12 票灌 → 24 票读同一 store → **provider 调用 0 次、24 行而非 48、存活 24 格全错** max|Δ| 0.159–0.186)。**「给 key 加 universe 维」被否**(过度失效 10 个 universe 无关因子;**PIT universe 在一个日期区间上根本不是单一集合、该维度定义不出来**;跨指数存储爆炸),改为 **store 只存 per-symbol 中间量、截面 combine 移到读出装配**(`MinuteStreamBinding` 本就是 per_symbol+combine 两段,切在两段之间,正合红线 #7)⇒ 立为 **D4c,D5 C4 的前置**(设计文档修订 A2)。(d) 运维陷阱:真实评估 universe **996** 而冻结分钟面板 **995**(`300114.SZ` 无分钟 bar;**冻结面板自证**——三个日频书因子面板各 996 含它、十个分钟面板全 995 不含它),而 `saturation_probe` 默认 universe 从 995 面板派生。**编目 §七之二 已在任何 artifact 重生成之前登记漂移**(`eval_config` +3 键 / 顶层 +1 / Markdown +4 行全为新增 ⇒ C5 **逐字节对账已知不成立**、能成立的是值级 + 结构性断言;另登记 exec 侧 no_book 与 with_book 的 `eval_config` **首次合法地不同**、不得当回归;jump 的 loud raise 属有意阻断及解除方式)。gates:**2227 passed + 1 skipped**(2228 收集 = main 2175 +46 +7,**0 个既有测试被挤掉**)/ ruff / 31 configs / phase0 锚不变 / secret 0 / `exec_baseline --verify` 77/77 @ `45c14aa` / 冻结面板 mtime 未变。**方法论新增两条**:① **「失配摧毁意义 → 拦;失配只带偏 → 记」**(见上);② **lead 与评审共用同一 worktree 时,测量与变异会打架**——本轮 lead 跑 gates 时 `git status` 一度显示 1 个改动(评审正在做 mutation),故合并前在评审收工后重跑了一遍干净 gates。 - **D5a(PR #95,D5 的前三块——冻结/编目/探测;探测结论迫使插入新迁移步 D4b)**:**C1 冻结 exec 对账基线**(`qt/exec_baseline_freeze.py`)——22 份 exec artifact 是后续一切对账的参照,却 **gitignored 只存在于本机**,且设计假定的耐久副本 `scratchpad/baseline_reports/` **早已不存在**;新 runner 沿用同名输出路径,**跑一次就毁掉唯一基线**,随后的「对账」会比对刚被自己覆盖的文件(= 本仓在案的 `compare_postmerge.py` 空对账形态)。实冻 **77 个文件**(不是交办的 44——同族还有 11 份 `_exec_basis_sanity.md` + 22 张 dashboard,同样单份不可再生),**sha256 manifest 入 git**(字节留 gitignored,哈希只能经评审 diff 变动),每次读都验哈希,读取器结构性拒绝 live 路径(直连/symlink 别名/`..` 三种绕过全拒)。**provenance 按证据强度分级**:观察到的是 77 文件共享毫秒级 mtime(批量拷贝签名),对照 44 份 close 基准的 11 个递进 mtime 与 #74 重跑窗口吻合;「字节出自 #79 run」标注为**推断非观察**,字段名故意叫 `frozen_at_git_head` 而非 `producing_sha`。**C2 编目 11 runner 差异**(§六.5「未编目的差异算失败」)——用 **AST 级比对**而非抽读证明完整性(`_build_book_factors`/`_write_report`/`_section_payload` 11 份逐字符相同;其余 helper 剥掉字符串常量后坍缩成 1 组),另记 **7 个既有 bug**(只标不修)与 `FactorSpec` 16→20 键漂移(来自 #86/#91,须预登记否则对账时会被当 D5 回归去追)。**探测(`qt/saturation_probe.py`,可复跑工具非一次性脚本):D4 的 materializer 在真实评估面上跑不了**——995 票中 **84 票**首根 1min bar ≥ emit_start ⇒ pooled 饱和**永远无法提前终止、必打到 floor**(D4 已披露的代价在全规模是**构造性**兑现);磁盘 8.18/16.43 GB,名义内存 52.7/122.2 GB,而 **frame:峰值RSS 实测 2.2–2.45×**(`minute_bars` 逐票读完 `pd.concat`,parts 与结果同时在内存)⇒ 评估窗真实峰值 **≈115 GB vs 可用 56 GB**;**不止 pooled**——bounded 路径同样整 universe 单帧(`materialize.py:262`),光评估窗就超可用内存约一倍。**三条更便宜的出路全部证否**:按票分批会因 `service._ensure_coverage` 的缺口判定**只按日期不按 (date,symbol)** 而**静默丢名**(I5a 红线);按时间分块只救 3 个 bounded 因子;缩短窗口不动 pooled 加载左端(锚在 floor)。**关门的是 `intraday_amp_cut`**(**同时 pooled × 截面**)——按票分批毁其截面、按时间分块管不住其深度,两轴都绕不开。切口位置已实测:纯因子逐票 ≡ 整 universe **逐位相同**(728/1524 个可比 cell `max|diff|=0.0`),`intraday_amp_cut` 逐票 **1860 finite → 0** ⇒ **切口必须落在截面 combine 之前**。**暴露的设计层缺口(照实记)**:§八只给**决策热路径**(20 日尾窗)定过规模预算,**从未给评估路径定规模**,所以「整 universe 单帧」在设计评审里没人拦;而旧 runner docstring 白纸黑字写着 "the multi-year all-symbol minute panel is NEVER materialized"——**D4 的加载几何相对被替换对象是回归**,只是 D4 验收跑在 40 票 smoke 上看不见。lead 提的「复用 `panel_freeze.py` 的加载形态代替 D4b」**已证否**:它没有自己的加载形态,是 import 11 个 runner 调其私有 `_load_*_panel`——「复用」等于保留决策③要杀的第二条取数路径;可复用的是**形状**不是调用路径。⇒ **插入迁移步 D4b(per-symbol 流式物化)**,设计文档记为实施期修订 A1;C3–C6 刻意未开始(修 materializer 是改取值路径,须自带四腿验收,混进 D5 当「让 run 跑起来」正是本项目反复抓到的形态)。**评审两轮**:首轮 BLOCK 1 HIGH——被文档称作「幂等」的再冻结命令**静默销毁 provenance**(未改动树上跑,输出 `copied: 0 / already ok: 77` 报纯成功,git 里却清空 `source_note` 并把 `frozen_at_git_head` 改指向重跑者 = **主动的假声明**,而 **16 个测试全程绿灯**)→ 改为 provenance 继承 + 内容不变则一个字节不写 + **恒跑断言**(`source_note` 非空 / head ^[0-9a-f]{40}$ / sha256 合法 hex(原只验长度)/ `size_bytes`>0),评审逐条 mutation 四条全红;另修 2 MEDIUM(**本 PR 自己 suite 里的空 mutation**——那条 git-tracking 测试全程不碰 git,注释掉 `.gitignore` 仍通过 → 改查 **git 索引** `git ls-files -- `;**C6 爆炸半径漏编目 3 个 runner importer**,含**生产 D1 冻结基线的 `panel_freeze.py` 本身**,其重跑流程是「旧 SHA + 当前分支文件」的混合式、两种 C6 处置下都会失效)。**方法论(三个空 mutation,全部照实记)**:实现方两次(tamper 测试替换了文件里**不存在**的字节串;git 索引 mutation 用 `git add -f` 被 symlink 拒绝执行 → 什么也没改、测试**为错误的理由通过**),评审一次(它建议的 `git ls-files --error-unmatch` 对「未跟踪」与「路径不存在」**返回相同 rc=1**,据此的断言会在**最需要它的机器上空过**)——**三次都不是被测试抓住的,而是被「与预期矛盾的观察」抓住的;评审建议本身也需要 mutation 证据**。**顺带更正一条长期误诊**:「本机 pytest 摘要行被环境吞掉」是假的——`pyproject.toml:53` 已有 `addopts="-q"`,我们再传 `-q` 就是 `-qq`;去掉即出现 `N passed` 摘要行(点计数仍是有用的交叉校验,本轮就抓到 2113 vs 2114 之差,但它从来不是因为摘要不可得才必须存在)。gates:**2117 collected**(2116 passed + 1 skipped——跳的是字节绑定测试,其字节 gitignored;manifest 自洽测试**无 skipif 恒跑**)/ ruff / 31 configs / phase0 锚不变 / secret 0 / `--verify` 77/77 且 head 仍 `45c14aa` / 冻结面板 mtime 未变。 - ✅ 质量门(**当前 `main` @ `f432dc5` 实测**:`python -m pytest -p no:warnings` **1776 passed**、`ruff` clean、`validate-config` **31/31 配置逐个 OK**、`run-phase0`(demo)**ic 0.9600 / annual 0.8408 不变**)。构成对得上:`aa19968` 实测 **1740** → #78 加 2(含钉住破折号闭合的那条)= **1742** → #79 加 34(两个新测试文件,0 个既有测试被挤掉)= **1776**。新增测试分组(`--collect-only` 实数,`aa19968` 口径):**因子评估契约层 contract=337 + standard=113 + figures=7 / 十一因子(factor + eval runner,21 文件)=421 / PR#75 exec-vwap-basis=46 / D3 market quality 15→21(含 #77 `decreasing_adj_factor` 及其相对-vs-绝对尺度 mutation 测试)**。历史分组(旧 793 基线):`pytest` **793 passed**(P0=97 / P1=78 / P2-1=22 / P2-2=22 / P2-3=14 / P2-4=8 / P3-1=10 / P3-2=18 / P3-3=16 / P3-4=15 / P3-5=22 / P3-6=27 / P3-7=25+1 throttle / P3-8=8 / P4-1=28 / P4-2=17 / **intraday I1 schema=14 + feed=9 / I2 cache=10 / I3 aggregate=13 / I4 execution=10 / P4-3 cache=10 + updater=7 / P-I5a event-backtest=19 / P-I5b exec-feasibility=16 / P-I5c mmp-minute=18 / P-I5d mmp-quintile=19 / P-I5e 仅 config(无新测试,`test_cache_config` 的 config glob 自动 +1)/ P-I5f intraday-liquidity=17(+ `test_cache_config` config glob 自动 +1)/ D1 token-dedup index-feed +2 / D2 cache-modularization +5 / D3 data-quality market=15 + intraday=12 + report=14 / D3b data-update-quality=18 / D4 coverage-ledger-scaling=13 / D5 scheduler=9 + concurrency=12 / schema-registry-guard=62 / all-A-incremental=12 / all-A-backfill=22**);当时 `ruff` clean、`validate-config` 20 配置(data_update + phase_i5a…phase_i5f)+ `run-phase0`(demo)均 OK(**ic 0.9600 / annual 0.8408 自 P0 起从未变过**)。 - ⚠️ 剩余(已显式披露):日线 only、demo 路径非真数据、旧三因子无信号(P3-3/P3-4 实证;但其组合在 2024-2026 holdout 上 SSE50/CSI300/CSI500 全正、CSI500 高达 +17.8%——小样本/regime 翻转的持续例证);value/低波信号获得**独立样本符号级确认**(P3-7 SSE50/CSI300 量级衰减;P3-8 CSI500 泛化成立且更强),组合级盈利能力仍未确立(排名跨 cell 翻转);subset 报告文件名已可配置(P3-8 起不再互覆盖)。**分钟因子侧新增披露**:十一个复现因子全部 EXPLORATORY、**封顶 Watch,无一到 Adopt**,1× 费率下净多空为正的只有 2 个(PR-F/PR-L,且 PR-L 扛不住 2×)——**IC 强 ≠ 可交易**;MMP 的唯一正面证据(I5d)在修正引擎上退化、I5e 负结果加强;I5f 的容量结论已按**真实 100 万名义**重写(1000 万口径的"约半数不足"作废);**日频除权审计已完成**(GENUINE、无 vintage 接缝、评估池暴露 1/603,258,不重述任何因子结果),**分钟路径的复权缺陷已在 PR #75 修**;exec-to-exec 改基准已随 **PR #79 合并**,close-to-close 与 exec 两套 artifact 并存;⚠️ **#79 的 code review 未返回、靠自查合并**,其"未独立核"清单(五条 mutation 声称 / 十一个 runner 改动是否机械等同 / `execution_capacity` 透传)仍待后续检查——若查出问题,重述 exec 基准数字而非 close-to-close;schema 守卫**仍未接** live `data-update` 暖跑路径;HTML compendium(`artifacts/reports/factor_compendium.html`)**还读 v0.8 结果,待按最终结果修订**。 diff --git a/CLAUDE.md b/CLAUDE.md index 9758df9..eaace27 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -57,7 +57,7 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri ## 开发约定 - **交流中文**;代码/注释/commit message 用**英文**。 -- **Git**:feature 分支 + PR。**PR #1(P0+P1)、#2(P2-1)、#3(P2-2)、#4(进度文档)、#5(P2-3)、#6(进度文档)、#7(P2-4)、#8(进度文档)、#9(P3-1)、#10(进度文档)、#11(P3-2)、#12(P3-3)、#13(进度文档)、#14(P3-4)、#15(进度文档)、#16(P3-5)、#17(进度文档)、#18(P3-6)、#19(P3-7)、#20(进度文档)、#21(P3-8)、#22(进度文档)、#23(P4-1)、#24(进度文档)、#25(P4-2)、#28(tushare 权限/限频探测 + capability registry)、#29(I1–I4 分钟级 intraday pipeline,4 commit 一 PR)、#30(进度文档)、#31(P4-3 因子支撑端点缓存 + 21:00 data updater,2 commit 一 PR)、#33(P-I5a 事件驱动回测架构重构 + opt-in 分钟尾盘 event model,4 commit 一 PR)、#35(P-I5b 分钟尾盘执行期 raw stk_limit 涨跌停可行性,4 commit 一 PR)、#37(P-I5c MMP 分钟因子端到端 opt-in alpha)、#39(P-I5d MMP 五分位分组回测 standalone,含 I5c plumbing)、#41(数据层 D1 契约文档 + token 解析去重)、#43(数据层 D2 TushareCache specs/parsers 拆分)、#45(数据层 D3 report-only 数据质量层)、#47(数据层 D3b default-off `data-update` 质量报告钩子)、#49(数据层 D4 coverage ledger 批量写 + 进程内查找缓存)、#51(数据层 D5 opt-in 有界并发 + 全局限频器)、#53(P-I5e MMP 五分位 CSI300 独立泛化检验,负结果)、#55(P-I5f 分钟尾盘执行流动性/容量诊断,report-only)、#57(数据层 schema 注册表 + default-off drift 守卫)、#59(数据层 全A 增量 auto-warm + systemd 定时,default-off)、#61(数据层 全A 历史回填 `data-backfill`,分块/续跑/失败隔离)、#62(进度文档)、#63(因子评估契约层 `analytics/eval/` + StandardFactorEvaluator + dashboard + PR-C 因子,4 commit 一 PR)、#64–#73(PR-D…PR-M 十个分钟因子复现,**一因子一分支一 PR**)、#74(因子评估契约 v0.8 + v0.9 判定门修复)、#75(尾盘执行价 VWAP + 分钟持有期收益复权)、#76(报告披露修正 + I5f 名义按真实规模重测)、#77(`adj_factor` 下降质量检查)、#78(#76 的 follow-up:扫描式正则守卫被七种改写实测证否 → 闸门描述改单一来源)、#79(十一因子改 14:51 VWAP exec-to-exec 基准,**评审未返回、靠自查合并**)、#82(闸门/成交价描述全仓清扫,12 处;#78 守卫射程不足的修正)、#80(进度文档)、#84(因子层重构 D0 纸面契约:availability policy 常量 + 预指派表 + 性质编目)、#85(进度文档)、#86(因子层重构 D1:registry + PanelField requires + FactorSpec 契约 v1.0)、#87(因子层重构 D1 面板冻结:14 因子 raw 基线 + manifest)、#88(进度文档)、#89(因子层重构 D2:minute primitives + ops + 11 因子迁移,与冻结基线逐位一致)、#90(进度文档)、#91(因子层重构 D3:store 层——稀疏值存储 + key/指纹 + tail-recompute + R5 fina 视界统一)、#92(进度文档)、#93(因子层重构 D4:FactorService + decision-view materializer + pooled 饱和填充)、#94(进度文档)、#95(因子层重构 D5a:exec 基线冻结 + 11 runner 差异编目 + 可行性探测)、#96(进度文档)、#97(因子层重构 D4b:per-symbol 流式物化)均已 merge 到 `main`**;**OPEN 未合并:#38**(见 P-I5d 处置,未获授权关闭)。commit 用 conventional 格式,**无 attribution**(不加 Co-Authored-By)。 +- **Git**:feature 分支 + PR。**PR #1(P0+P1)、#2(P2-1)、#3(P2-2)、#4(进度文档)、#5(P2-3)、#6(进度文档)、#7(P2-4)、#8(进度文档)、#9(P3-1)、#10(进度文档)、#11(P3-2)、#12(P3-3)、#13(进度文档)、#14(P3-4)、#15(进度文档)、#16(P3-5)、#17(进度文档)、#18(P3-6)、#19(P3-7)、#20(进度文档)、#21(P3-8)、#22(进度文档)、#23(P4-1)、#24(进度文档)、#25(P4-2)、#28(tushare 权限/限频探测 + capability registry)、#29(I1–I4 分钟级 intraday pipeline,4 commit 一 PR)、#30(进度文档)、#31(P4-3 因子支撑端点缓存 + 21:00 data updater,2 commit 一 PR)、#33(P-I5a 事件驱动回测架构重构 + opt-in 分钟尾盘 event model,4 commit 一 PR)、#35(P-I5b 分钟尾盘执行期 raw stk_limit 涨跌停可行性,4 commit 一 PR)、#37(P-I5c MMP 分钟因子端到端 opt-in alpha)、#39(P-I5d MMP 五分位分组回测 standalone,含 I5c plumbing)、#41(数据层 D1 契约文档 + token 解析去重)、#43(数据层 D2 TushareCache specs/parsers 拆分)、#45(数据层 D3 report-only 数据质量层)、#47(数据层 D3b default-off `data-update` 质量报告钩子)、#49(数据层 D4 coverage ledger 批量写 + 进程内查找缓存)、#51(数据层 D5 opt-in 有界并发 + 全局限频器)、#53(P-I5e MMP 五分位 CSI300 独立泛化检验,负结果)、#55(P-I5f 分钟尾盘执行流动性/容量诊断,report-only)、#57(数据层 schema 注册表 + default-off drift 守卫)、#59(数据层 全A 增量 auto-warm + systemd 定时,default-off)、#61(数据层 全A 历史回填 `data-backfill`,分块/续跑/失败隔离)、#62(进度文档)、#63(因子评估契约层 `analytics/eval/` + StandardFactorEvaluator + dashboard + PR-C 因子,4 commit 一 PR)、#64–#73(PR-D…PR-M 十个分钟因子复现,**一因子一分支一 PR**)、#74(因子评估契约 v0.8 + v0.9 判定门修复)、#75(尾盘执行价 VWAP + 分钟持有期收益复权)、#76(报告披露修正 + I5f 名义按真实规模重测)、#77(`adj_factor` 下降质量检查)、#78(#76 的 follow-up:扫描式正则守卫被七种改写实测证否 → 闸门描述改单一来源)、#79(十一因子改 14:51 VWAP exec-to-exec 基准,**评审未返回、靠自查合并**)、#82(闸门/成交价描述全仓清扫,12 处;#78 守卫射程不足的修正)、#80(进度文档)、#84(因子层重构 D0 纸面契约:availability policy 常量 + 预指派表 + 性质编目)、#85(进度文档)、#86(因子层重构 D1:registry + PanelField requires + FactorSpec 契约 v1.0)、#87(因子层重构 D1 面板冻结:14 因子 raw 基线 + manifest)、#88(进度文档)、#89(因子层重构 D2:minute primitives + ops + 11 因子迁移,与冻结基线逐位一致)、#90(进度文档)、#91(因子层重构 D3:store 层——稀疏值存储 + key/指纹 + tail-recompute + R5 fina 视界统一)、#92(进度文档)、#93(因子层重构 D4:FactorService + decision-view materializer + pooled 饱和填充)、#94(进度文档)、#95(因子层重构 D5a:exec 基线冻结 + 11 runner 差异编目 + 可行性探测)、#96(进度文档)、#97(因子层重构 D4b:per-symbol 流式物化)、#98(进度文档)、#99(因子层重构 D5b:评估契约 v1.0 + 诊断通道 + 14:50 可见性守卫;**C4 中止上报**)均已 merge 到 `main`**;**OPEN 未合并:#38**(见 P-I5d 处置,未获授权关闭)。commit 用 conventional 格式,**无 attribution**(不加 Co-Authored-By)。 - **不过度设计**:按路线图 MVP 先打通一条端到端链路,再加层(architecture.html §11,Phase 0→3)。 - **secrets** 一律走外部 `.config.json`;repo `.gitignore` 已排除数据产物(`*.parquet`等)、缓存、`tmp/`(仅留架构文档)。 - 文件小而专(<800 行),immutable 优先。 @@ -373,6 +373,7 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri - **D3(PR #91,整步已关账——store 层,纯附加未接线)**:`factors/store/`(hashing/code_hash/fingerprint/keys/values/run_registry/incremental,全 <800 行)+ **R5 前置修复**(`fina_tail_days` 单一真相迁至 `data.cache.fina_tail_days`,回测 `_build_cache` 与 data-update 两 builder 统一传 fina 400 尾 override——回测 read-through 现会补 fina 尾窗,行为变更已披露;`data_update.fina_tail_days` 删除对 repo 外旧 YAML 属 breaking,仓内两 config 已迁)。key = params_hash + code_hash(自身模块 + 枚举共享集{minute primitives/ops/base/spec} + **one-hop 直接项目内 import 折叠**:AST 自动派生、无手工清单、不做传递闭包——评审 MEDIUM 实测 `reversal_20` 可 build 且值=−momentum 而 momentum.py 取值面不入 key = 陈旧复用洞,据此修;改 momentum → candidates 系 key 变、financial/分钟系不变,无全局过度失效)+ view + 数据指纹(schema-version 维 = data/clean PIT 承重模块内容 hash;`price_level` 另掺 per-symbol adj_factor 事件表 hash 含锚值,收官集零成员不豁免 fixture 测试)。存储:单文件 parquet date 排序 / 原子写 tmp+`os.replace` / per-artifact O_CREAT|O_EXCL 锁(两进程 gap-fill 零丢行实测;锁 neuter mutation 证明锁对原子写也承重)/ JSONL append-only 运行注册表(no-secret:sanitize_text 过自由文本,redaction 测试钉住)/ 损坏文件=miss / **不建 coverage ledger**(值确定性可重算)/ 启动一致性断言(registry 条目必须命中代码注册表)。tail-recompute:`w_overlap=max(W_dep, 端点修订视界)`——W_dep=传递 lookback 深度经 **`FactorSpec.lookback_depth`(optional 附加字段,contract v1.1)**声明、store 消费点 HARD-REQUIRE(14 真实因子未声明 → loud 报错,声明属预注册动作留 D4);视界经 `revision_horizon()` 从 live config 派生(调大 refresh_recent_days → 重叠窗变宽 mutation 实证,无硬编码 14/400);重叠 NaN-aware bitwise,失配按 adjustment 分类(returns_invariant→loud 上游回改记录 / price_level→预期);schema 指纹失配 → schema_void_full 全量重算不误报 revision;§六.18 teeth(headline 深度欠采 → 假 mismatch)测试钉住。#adjustment NET-NEW 性质测试钉本格:扰动 qfq 锚 → returns_invariant 真因子(日频 volatility_20 + 分钟 valley_relative_vwap)逐 bit 不变,批量 census 9/5/0 ≡ D0 表。评审 APPROVE-WITH-NITS(0 CRIT/HIGH,1 MEDIUM+3 LOW+1 NIT;MEDIUM/LOW-1/LOW-3 合并前修于 `fd906f4` 并经 delta 复核三项 CLOSED——评审亲手重跑 momentum on-disk mutation 5/5、allowlist 注入、锁 neuter,并猎杀「不可能失败的测试」零发现)。留 D4 注记:materializer 必须传 live `data.cache.fina_tail_days` 勿靠 400 默认;two-hop 组合链是 one-hop 折叠的已知边界(今日无实例,设计明令不做传递遍历器);`availability_policy` 编辑会 over-invalidate 其 importer 的 store(安全方向、D4/D5 churn 期真实重算成本);单点填≡批量填(P8)是 D4 验收项。gates:**2031 passed**(=1955+76)/ ruff / 31 configs / phase0 锚不变 / provisional 锚绿 / secret 0。 - **D4(PR #93,整步已关账——FactorService + materializer;四轮评审揪出两个 HIGH + 一项设计修正)**:`factors/service.py`(frozen `DecisionPoint` + `cross_section`/`panel` **都 read-through 读 D3 store**,miss 触发唯一引擎,配对合法性复用 D0 `require_legal_pairing` 构造期强制)+ decision-view materializer(R18 **全** policy-lag:日线非-open ≤ d−1、**open[d] 字段级例外从 policy 表派生**、daily_basic/fina ≤ d−1、分钟 ≤14:50;ex-date 只暴露**布尔**的类型边界;`CacheHorizonConfig` 从 live config 构造缺属性即 raise)+ process 编排下沉 `factors/process/orchestrate.py`(`_process_factors` 薄委托逐字行为保持)+ 14 因子 `lookback_depth` 预注册(参数化派生+测试钉死)+ 热路径计时 smoke(真实缓存 cache-only 40 票共享读 ≈2.0x,诚实标注不外推)。**评审故事(P8 单点填≡批量填连揪三层真缺陷)**:①【设计修正】valid-day **pooled** 因子(8/11 分钟因子按滚动机制码检划分,非按观察到分歧的 3 个——#82 教训)trailing N 个**有效日**的日历深度数据依赖、**无界** → **证否 v3.2 §3.3 R4「W_dep=各 lookback 之和」假设**,固定 40 日 trim 使单点填 vs 批量填 finite↔NaN 分歧;②首版不动点判据(值稳定+nbars 稳定)被评审构造 **>1 chunk 停牌 gap 反例**击穿(finite-vs-finite 静默错值)→ 改**结构性判据**(锁定单调性:丢窗口头部 baseline_days 交易日其余分类 FINAL;锁定区 output-date 计数 ≥ lookback_days,gap-immune)+ provider 显式 `earliest_available`(nbars 推断删除,中段 gap 不许当 data start),上版「divergence is gone」overclaim 在 commit message 开篇更正;③判据循环只遍历**有输出的** symbol → 长停牌票**无否决权被静默丢出截面**(撞 I5a 红线)→ 改遍历**请求的** symbol 列表,评审 fixture(600519 丢名复现 + 锁定偏移 416.0 vs 438.0 静默错值)全部落成 committed 测试 + 源码级 mutation 双 witness(rc=1/rc=0,评审亲手用自己未改动的脚本独立复跑确认)。`_MAX_SATURATION_CHUNKS` 耗尽改 loud raise(红线 #9)+ raise 分支有测试。**代价如实入 docstring**:凑不满 lookback 有效日的票拖全 universe 扩到声明 floor;per-symbol 饱和起点是 D5 优化**且非纯优化**(`intraday_amp_cut` 截面 z-score 耦合)。**早期区域量化(D5 面板腿归因名目)**:分钟缓存真实起点 **2015-01-05** → D1 冻结基线(锚 2021-07-01)对 pooled 因子属 **anchor 截断**,饱和加载在 2021-07→10 五票上 ridge 有 157/184 cell 不同(79 NaN→finite,按月递减至零)——D5 对账须具名归因「saturation vs anchor truncation」。JC1 已裁定:P8 逐 bit 对滚动因子降为 ≤1e-12 可归因浮点重排(实测 floor ~3.5e-18,真缺行效应 ≥7 个数量级于容差;NaN mask 必须精确)。留 D5/D6:声明 floor 应从分钟 coverage ledger 派生 per-symbol(现为硬编码常量,声明偏晚会静默截断);`valley_price_quantile` 分钟绑定 DEFERRED(loud 报错,已声明 pooled,D5 绑定继承饱和路径**不许**固定 trim 绕过);零输出否决语义已被测试+mutation 钉住,D5 为性能回退它=放回 HIGH;blanket shift 依赖「因子输入面板只含端点列」的 D6 wiring 契约。gates:**2098 passed**(=2031+67)/ ruff / 31 configs / phase0 锚不变 / provisional 锚绿 / secret 0。 - **D4b(PR #97,实施期修订 A1 新插入的迁移步——per-symbol 流式物化;改因子取值路径,自带四腿验收)**:materializer 改「逐票读 → 立刻聚合到日频 → 丢弃」,**切口落在截面 combine 之前**。**规模(真实评估面 CSI500 995 票 × 5 年,cache-only `live_calls=0`)**:名义最大单帧 **122.2 GB → 0.066 GB**、峰值 RSS **~115 GB → 0.964 GB**(可用 56 GB,占 1.7%);三种加载几何各跑一因子(pooled×截面 / pooled / bounded)全部 995/995 票、**每次请求 1 票**;峰值稳定 0.73–0.96 GB,**由「一票 bars + 日频面板」决定而非 universe 决定**;扩到 floor 的代价只落在那 84 只 late 票(40 次调用/14.95s),不再拖着 911 只陪跑(dense 票 1.0 次/0.59s)。**四腿**:① D4 既有 31 测试原样通过(P8 四 regime / 锁定偏移 / 零输出否决 / exhaustion loud raise),评审证其**真在测新路径**(单文件即覆盖 `materialize.py` 86%,per-symbol helper 体均被覆盖);② 手算锚 18 行**零项目 import**(运行时守卫断言 `sys.modules` 无 factors/qt/data/runtime/alpha,653 模块 0 命中),`volume_peak_count` 9/9 精确 0.0、`intraday_amp_cut` ≤1.998e-15;③ 逐格对账真实缓存 40 票×6 月 vs 整 universe 单帧(3,711,400 行):10/10 index 相同、**NaN 集合差异全 0**、5 个逐位相同、最差残差 3.275e-14,`intraday_amp_cut` 在 **4,720** 个真实 cell 上对上(评审以 **main 真引擎**为参照复跑得 **max|abs|=0.000e+00**,比文档的 2.5e-14 更干净——因两侧加载几何相同,已写进文档);④ 规模证明如上,且 `--mode reconcile` 使 §6.1 那张最承重的表**可从仓库复跑**(评审亲跑:10 行×4 列与文档逐格一致,且**非空对账**——参照侧完全不经 `materialize_range`,只在被检验的加载几何上不同)。**评审带来的头号反转**:实现方把 per-symbol trim 描述为「更保守的语义细化」,评审证明它在**修 D4 的真缺陷**——同一稀疏 fixture 跨引擎对照,3 个 bounded 因子各动 1 cell,**三个都是 D4b == 几何无关真值、D4 ≠ 真值**(`jump` 0.0901 vs 0.1571;另两个 D4 给 **NaN** 而 D4b 给正确 finite);union trim 给稀疏票喂的自有交易日不足 `lookback_depth` = 红线 #6 的 load-geometry 依赖。且四个旧 runner **逐票读全窗口、根本没有 union trim** ⇒ per-symbol trim 是**朝 D1 冻结基线靠拢**——实现方给 D5 的预警「稀疏票对不上先看这里」**方向反了**(反在安全侧),已订正为指向饱和深度/anchor 截断。超集性质经评审证严(子集第 k 大 ≤ 超集第 k 大),反例构造失败。**MED-1(D4b 新引入的唯一真引擎缺陷)**:请求含重复 symbol 时逐票流式会独立处理每个重复项——48→52 行、4 个重复 (date,symbol),`intraday_amp_cut` 更因重复票**两次进入截面**而 **48/48 共享 cell 全部变值**(D4 免疫是靠 provider 的 `isin` 幂等吸收)→ 改**保序去重**(而非 loud raise:去重**精确复现单帧引擎对同一调用的返回**、保持「只改内存剖面」,raise 会新拒绝前一引擎接受过的输入);评审跨引擎复核修后 0 差异。**另两条「说法与事实相反」**:MED-2 一处 docstring 称旧 mutation 写法「cannot fail」,评审原样跑在 D4b 上是 **FAIL**——它其实是 **cannot pass**(性质保住、只换写法,属 §六.16 而非偷改测试;计数 70→**72**=70 单点填+2 批量填);MED-3 可行性文档声明了一条「本步绝不允许 finite↔NaN 翻转」的政策,而 per-symbol trim **能且实测确实产生**(3 个 bounded 里 2 个 NaN→finite),40 票样本只是没触发 → 改为如实陈述。**lead 合并前补的闭环**:派生 id 列表只守住了「加了因子却没进对账」一个方向;评审实测另一方向——把某因子从**两张 binding 表都删掉**,该文件 53 passed、全量 2169 passed **全绿**,因子从每条 parametrize 里静默消失。故新增闭包测试,真相源改为**`factors/compute/minute` 下定义的全部 `Factor` 子类**,未分类即红(mutation witness:删 `PeakIntervalKurtosisFactor` occurrences 4→0 先断言落地 → 转红;还原后 `binding.py` 逐字节相同、58 passed)。**A1 点名的致命陷阱未踩**:`factors/service.py` diff **0 行**(不许在 service 层按 symbol 分批——`_ensure_coverage` 只按日期判缺口会静默丢名)。gates:**2174 passed / 1 skipped**(= 2117 + 57,**node-ID 集合证 0 个既有测试被挤掉**)/ ruff / 31 configs / phase0 锚不变 / secret 0 / `exec_baseline --verify` 77/77 head 未变 / 冻结面板 mtime 未变。留 D5:扩张步长(late 票 40 次重读,纯性能但仍是加载几何改动、欠自己的对账,**刻意没夹带**);声明 floor 仍是 universe 级硬编码常量未按票从 coverage ledger 派生;`valley_price_quantile` 仍 DEFERRED,D5 绑定**继承流式路径不许固定 trim 绕过**;10 个因子只跑了 3 个的全规模证明(几何全覆盖,评审证未测因子的加载参数与已测者相同或被支配);日频路径仍整 universe 单帧(995×1210 行,量级小,未动)。 + - **D5b(PR #99,D5 后四块只交付了 C3——**C4 中止、C5/C6 未做、什么也没删**;中止本身是本步最重要的产出)**:**发现并(两方独立)确认一个真实前视缺陷**:`jump_amount_corr_20` 是十一个分钟因子中**唯一**不做 14:50 截断的(`decision_time`/`prepare_visible_minute_bars` 引用数 **0**,其余 4–10),旧 runner 用 `end+23:59:59` 取整日 bar 直接喂它、全程无补救。**exec_to_exec 下日 d 的入场锚是当天 14:51 bar 的 VWAP**,而值用到 d 的 14:50–15:00 bar ⇒ **信息集越过自己的入场锚**。扰动实测(两方各用不同票/不同窗口,前置断言两腿齐全):实现方 12 票/2021H2 **1,477/1,477 格全移动**(max|diff| 1.276)、其余 9 个 bound 因子 **0 格**;评审另 12 票/2023H1 **1,373/1,373**(max|diff| 1.054)、**其余全部 11 条 0 格**(并补测了实现方漏掉的 `valley_price_quantile_stats` 与 `mmp_ew`);评审再加一刀**只扰动 `bar_end >= 14:51`**(执行 bar 本身及其后)→ **1,363/1,363 移动**——**信号看到了自己成交的那一分钟及其后 9 分钟**。而其已发布 artifact 明写 `spec.decision_cutoff="14:50:00"`/`return_basis="exec_to_exec"`/`execution_window="[14:51:00,14:56:59]"`,verdict **Watch**、predictive 轴 **PASS**(|NW-t| 15.19)——**报告声明了它没有执行的检查**。**既有测试为何没抓到**:`test_pit_perturbing_future_bars_does_not_change_factor_at_d` 守的是**跨日**边界,其 fixture session 只有 09:31–09:36 六根 bar、**根本不存在 14:50 边界**;日内边界只在 **PR #79** 把入场锚从 `close(d)` 移到 `14:51(d)` 之后才承重,而 #79 评审未返回、这**恰在其「未独立核」清单射程内**。**裁定(设计文档实施期修订 A3)**:用户 2026-07-19 常设授权明写「全日数据因子一律截断到 14:50……授权直接截断,不必逐因子再问」,而该因子**建于此授权之前** ⇒ 加截断是**补用既有授权**非新研究决策;**但评审的程序性修正已采纳**——从重构视角它仍是定义变更、而授权来自研究侧不来自重构 ⇒ **必须单独成 PR、显式标注 correctness fix,不许进 D5 任何 commit**(已另派)。幅度实测 pearson **r=0.9993**、mean|diff| 0.0042——**缺陷是结构性的必须撤回,但修正代价大概率很小;verdict 存活与否必须由真正的重跑给出、不许由相关系数推定**。**交付的 C3(评估契约 v1.0)**:`EvalConfig.view`/`return_basis` 构造期经 D0 `require_legal_pairing` 强制配对;provenance 增 requires/adjustment/overnight_boundary/lookback_depth + `eval_contract_version`;跨口径汇总**缺 view/basis 列拒渲染**(声明了列却留空同样拒);**判定门一个数没动**(评审证 6 个文件 md5 与 main 逐字节相同,8 个门值逐值钉死)。**评审两轮 APPROVE-WITH-NITS,2 MEDIUM 全关**:**MEDIUM-1「守卫守不住自己」**——声称钉住 identity 修复的测试是对**函数源码做子串匹配**,评审把赋值掏空、两个 token 留**注释**里 → 每份 exec artifact 都会继承调用方 close 身份而实际按 exec 收益打分,**52 passed 全仓无一抓住**(#78 教训的翻版,且放行的恰是同一 commit 刚修的缺陷)→ 抽 `exec_identity()` 改**行为断言**,评审原样重跑逃逸 **4 failed**,并验了**假阳性**方向(重构进 helper 不误报,58 passed)。**MEDIUM-2「假声明上升一层」**——exec 路径无条件声明 `view=decision`,但 with_book 的因子簿是 close(d)+当晚 daily_basic(**§1.1 自己列为「已经咬过人的活缺陷」**),且 jump 连 no_book 格都不成立;而该字段定义是「**因子值**取自哪个信息集」,with_book 有**两个**信息集、一个字段表达不了 → **这正是该字段被造出来防的那种缺陷、只是上升一层**。**现在修免费**(还没 artifact 带它),C5 一跑就写进 22 份。修法:**先拆两个事实**(②单独不成立——登记例外并不能让 `view=decision` 在 with_book 上变成真话)→ 新增 `EvalConfig.book_view`(唯一知情方声明)+ `subject_view(factor_id)` **从事实派生**(deny list `NOT_DECISION_CUTOFF_SAFE` 放**因子侧**——「它是关于**值**的事实」,由可见性测试**测量**而非声明,本地副本已删)。**刻意不校验 `book_view`×basis 配对**,评审的裁定值得作通则记下:**失配摧毁意义 → 拦;失配只带来已披露、方向已知的偏 → 记**(close-view 书是 Incremental 轴的控制变量、偏的方向已预注册;拦它不会让信息集不混,只会让 artifact 说不出它混了)。**并落一个有意的响亮阻断**:jump 现在派生出非法配对 → 其 exec 评估 loud raise(截断修正落地即解除,删 deny list 一条)——在它被修正前**不存在**它的诚实 exec artifact,阻断优于假声明(红线 #9)。**实现方又一次自查出同形缺口**(单测说不了调用方怎么接线:with_book 传 `book_view=None` → **28 测试全绿**)并照实上报、补端到端断言读**两份实际写出的 JSON**。**另三个前提问题已裁定并立项**:(a) 3/11 因子的覆盖率披露无法由 store 供给(每次披露必重算,已写成行为并测试锁定);(b) `valley_price_quantile` 会被 materializer 二次滞后成 close_{d-2},评审实测第三条路**逐比特等价**(`max|diff|=0.000e+00`、`Series.equals=True`,破坏对照 7.3e-2 证非空过)⇒ 属实现变更可授权,落地须**两侧都钉**等价性测试 + 左端多一天历史;(c) **store key 无 universe 维(存量 CRITICAL,对 D6/D7)**——评审拆成**两个独立失效模式**:① `_ensure_coverage` 缺口判定**只按日期不按 (date,symbol)** ⇒ 第二批「无缺口」直接返回、那批票**静默从截面消失**,影响**全部 11 因子**(**讽刺**:A1 否决「按票分批」出路的理由一字不差就是这条,**红线写在文档里而服务层身上就带着它**);② `intraday_amp_cut` 的 z-score 在物化期发生 ⇒ 存储值是 universe 的函数而 key 不这么说(实测:12 票灌 → 24 票读同一 store → **provider 调用 0 次、24 行而非 48、存活 24 格全错** max|Δ| 0.159–0.186)。**「给 key 加 universe 维」被否**(过度失效 10 个 universe 无关因子;**PIT universe 在一个日期区间上根本不是单一集合、该维度定义不出来**;跨指数存储爆炸),改为 **store 只存 per-symbol 中间量、截面 combine 移到读出装配**(`MinuteStreamBinding` 本就是 per_symbol+combine 两段,切在两段之间,正合红线 #7)⇒ 立为 **D4c,D5 C4 的前置**(设计文档修订 A2)。(d) 运维陷阱:真实评估 universe **996** 而冻结分钟面板 **995**(`300114.SZ` 无分钟 bar;**冻结面板自证**——三个日频书因子面板各 996 含它、十个分钟面板全 995 不含它),而 `saturation_probe` 默认 universe 从 995 面板派生。**编目 §七之二 已在任何 artifact 重生成之前登记漂移**(`eval_config` +3 键 / 顶层 +1 / Markdown +4 行全为新增 ⇒ C5 **逐字节对账已知不成立**、能成立的是值级 + 结构性断言;另登记 exec 侧 no_book 与 with_book 的 `eval_config` **首次合法地不同**、不得当回归;jump 的 loud raise 属有意阻断及解除方式)。gates:**2227 passed + 1 skipped**(2228 收集 = main 2175 +46 +7,**0 个既有测试被挤掉**)/ ruff / 31 configs / phase0 锚不变 / secret 0 / `exec_baseline --verify` 77/77 @ `45c14aa` / 冻结面板 mtime 未变。**方法论新增两条**:① **「失配摧毁意义 → 拦;失配只带偏 → 记」**(见上);② **lead 与评审共用同一 worktree 时,测量与变异会打架**——本轮 lead 跑 gates 时 `git status` 一度显示 1 个改动(评审正在做 mutation),故合并前在评审收工后重跑了一遍干净 gates。 - **D5a(PR #95,D5 的前三块——冻结/编目/探测;探测结论迫使插入新迁移步 D4b)**:**C1 冻结 exec 对账基线**(`qt/exec_baseline_freeze.py`)——22 份 exec artifact 是后续一切对账的参照,却 **gitignored 只存在于本机**,且设计假定的耐久副本 `scratchpad/baseline_reports/` **早已不存在**;新 runner 沿用同名输出路径,**跑一次就毁掉唯一基线**,随后的「对账」会比对刚被自己覆盖的文件(= 本仓在案的 `compare_postmerge.py` 空对账形态)。实冻 **77 个文件**(不是交办的 44——同族还有 11 份 `_exec_basis_sanity.md` + 22 张 dashboard,同样单份不可再生),**sha256 manifest 入 git**(字节留 gitignored,哈希只能经评审 diff 变动),每次读都验哈希,读取器结构性拒绝 live 路径(直连/symlink 别名/`..` 三种绕过全拒)。**provenance 按证据强度分级**:观察到的是 77 文件共享毫秒级 mtime(批量拷贝签名),对照 44 份 close 基准的 11 个递进 mtime 与 #74 重跑窗口吻合;「字节出自 #79 run」标注为**推断非观察**,字段名故意叫 `frozen_at_git_head` 而非 `producing_sha`。**C2 编目 11 runner 差异**(§六.5「未编目的差异算失败」)——用 **AST 级比对**而非抽读证明完整性(`_build_book_factors`/`_write_report`/`_section_payload` 11 份逐字符相同;其余 helper 剥掉字符串常量后坍缩成 1 组),另记 **7 个既有 bug**(只标不修)与 `FactorSpec` 16→20 键漂移(来自 #86/#91,须预登记否则对账时会被当 D5 回归去追)。**探测(`qt/saturation_probe.py`,可复跑工具非一次性脚本):D4 的 materializer 在真实评估面上跑不了**——995 票中 **84 票**首根 1min bar ≥ emit_start ⇒ pooled 饱和**永远无法提前终止、必打到 floor**(D4 已披露的代价在全规模是**构造性**兑现);磁盘 8.18/16.43 GB,名义内存 52.7/122.2 GB,而 **frame:峰值RSS 实测 2.2–2.45×**(`minute_bars` 逐票读完 `pd.concat`,parts 与结果同时在内存)⇒ 评估窗真实峰值 **≈115 GB vs 可用 56 GB**;**不止 pooled**——bounded 路径同样整 universe 单帧(`materialize.py:262`),光评估窗就超可用内存约一倍。**三条更便宜的出路全部证否**:按票分批会因 `service._ensure_coverage` 的缺口判定**只按日期不按 (date,symbol)** 而**静默丢名**(I5a 红线);按时间分块只救 3 个 bounded 因子;缩短窗口不动 pooled 加载左端(锚在 floor)。**关门的是 `intraday_amp_cut`**(**同时 pooled × 截面**)——按票分批毁其截面、按时间分块管不住其深度,两轴都绕不开。切口位置已实测:纯因子逐票 ≡ 整 universe **逐位相同**(728/1524 个可比 cell `max|diff|=0.0`),`intraday_amp_cut` 逐票 **1860 finite → 0** ⇒ **切口必须落在截面 combine 之前**。**暴露的设计层缺口(照实记)**:§八只给**决策热路径**(20 日尾窗)定过规模预算,**从未给评估路径定规模**,所以「整 universe 单帧」在设计评审里没人拦;而旧 runner docstring 白纸黑字写着 "the multi-year all-symbol minute panel is NEVER materialized"——**D4 的加载几何相对被替换对象是回归**,只是 D4 验收跑在 40 票 smoke 上看不见。lead 提的「复用 `panel_freeze.py` 的加载形态代替 D4b」**已证否**:它没有自己的加载形态,是 import 11 个 runner 调其私有 `_load_*_panel`——「复用」等于保留决策③要杀的第二条取数路径;可复用的是**形状**不是调用路径。⇒ **插入迁移步 D4b(per-symbol 流式物化)**,设计文档记为实施期修订 A1;C3–C6 刻意未开始(修 materializer 是改取值路径,须自带四腿验收,混进 D5 当「让 run 跑起来」正是本项目反复抓到的形态)。**评审两轮**:首轮 BLOCK 1 HIGH——被文档称作「幂等」的再冻结命令**静默销毁 provenance**(未改动树上跑,输出 `copied: 0 / already ok: 77` 报纯成功,git 里却清空 `source_note` 并把 `frozen_at_git_head` 改指向重跑者 = **主动的假声明**,而 **16 个测试全程绿灯**)→ 改为 provenance 继承 + 内容不变则一个字节不写 + **恒跑断言**(`source_note` 非空 / head ^[0-9a-f]{40}$ / sha256 合法 hex(原只验长度)/ `size_bytes`>0),评审逐条 mutation 四条全红;另修 2 MEDIUM(**本 PR 自己 suite 里的空 mutation**——那条 git-tracking 测试全程不碰 git,注释掉 `.gitignore` 仍通过 → 改查 **git 索引** `git ls-files -- `;**C6 爆炸半径漏编目 3 个 runner importer**,含**生产 D1 冻结基线的 `panel_freeze.py` 本身**,其重跑流程是「旧 SHA + 当前分支文件」的混合式、两种 C6 处置下都会失效)。**方法论(三个空 mutation,全部照实记)**:实现方两次(tamper 测试替换了文件里**不存在**的字节串;git 索引 mutation 用 `git add -f` 被 symlink 拒绝执行 → 什么也没改、测试**为错误的理由通过**),评审一次(它建议的 `git ls-files --error-unmatch` 对「未跟踪」与「路径不存在」**返回相同 rc=1**,据此的断言会在**最需要它的机器上空过**)——**三次都不是被测试抓住的,而是被「与预期矛盾的观察」抓住的;评审建议本身也需要 mutation 证据**。**顺带更正一条长期误诊**:「本机 pytest 摘要行被环境吞掉」是假的——`pyproject.toml:53` 已有 `addopts="-q"`,我们再传 `-q` 就是 `-qq`;去掉即出现 `N passed` 摘要行(点计数仍是有用的交叉校验,本轮就抓到 2113 vs 2114 之差,但它从来不是因为摘要不可得才必须存在)。gates:**2117 collected**(2116 passed + 1 skipped——跳的是字节绑定测试,其字节 gitignored;manifest 自洽测试**无 skipif 恒跑**)/ ruff / 31 configs / phase0 锚不变 / secret 0 / `--verify` 77/77 且 head 仍 `45c14aa` / 冻结面板 mtime 未变。 - ✅ 质量门(**当前 `main` @ `f432dc5` 实测**:`python -m pytest -p no:warnings` **1776 passed**、`ruff` clean、`validate-config` **31/31 配置逐个 OK**、`run-phase0`(demo)**ic 0.9600 / annual 0.8408 不变**)。构成对得上:`aa19968` 实测 **1740** → #78 加 2(含钉住破折号闭合的那条)= **1742** → #79 加 34(两个新测试文件,0 个既有测试被挤掉)= **1776**。新增测试分组(`--collect-only` 实数,`aa19968` 口径):**因子评估契约层 contract=337 + standard=113 + figures=7 / 十一因子(factor + eval runner,21 文件)=421 / PR#75 exec-vwap-basis=46 / D3 market quality 15→21(含 #77 `decreasing_adj_factor` 及其相对-vs-绝对尺度 mutation 测试)**。历史分组(旧 793 基线):`pytest` **793 passed**(P0=97 / P1=78 / P2-1=22 / P2-2=22 / P2-3=14 / P2-4=8 / P3-1=10 / P3-2=18 / P3-3=16 / P3-4=15 / P3-5=22 / P3-6=27 / P3-7=25+1 throttle / P3-8=8 / P4-1=28 / P4-2=17 / **intraday I1 schema=14 + feed=9 / I2 cache=10 / I3 aggregate=13 / I4 execution=10 / P4-3 cache=10 + updater=7 / P-I5a event-backtest=19 / P-I5b exec-feasibility=16 / P-I5c mmp-minute=18 / P-I5d mmp-quintile=19 / P-I5e 仅 config(无新测试,`test_cache_config` 的 config glob 自动 +1)/ P-I5f intraday-liquidity=17(+ `test_cache_config` config glob 自动 +1)/ D1 token-dedup index-feed +2 / D2 cache-modularization +5 / D3 data-quality market=15 + intraday=12 + report=14 / D3b data-update-quality=18 / D4 coverage-ledger-scaling=13 / D5 scheduler=9 + concurrency=12 / schema-registry-guard=62 / all-A-incremental=12 / all-A-backfill=22**);当时 `ruff` clean、`validate-config` 20 配置(data_update + phase_i5a…phase_i5f)+ `run-phase0`(demo)均 OK(**ic 0.9600 / annual 0.8408 自 P0 起从未变过**)。 - ⚠️ 剩余(已显式披露):日线 only、demo 路径非真数据、旧三因子无信号(P3-3/P3-4 实证;但其组合在 2024-2026 holdout 上 SSE50/CSI300/CSI500 全正、CSI500 高达 +17.8%——小样本/regime 翻转的持续例证);value/低波信号获得**独立样本符号级确认**(P3-7 SSE50/CSI300 量级衰减;P3-8 CSI500 泛化成立且更强),组合级盈利能力仍未确立(排名跨 cell 翻转);subset 报告文件名已可配置(P3-8 起不再互覆盖)。**分钟因子侧新增披露**:十一个复现因子全部 EXPLORATORY、**封顶 Watch,无一到 Adopt**,1× 费率下净多空为正的只有 2 个(PR-F/PR-L,且 PR-L 扛不住 2×)——**IC 强 ≠ 可交易**;MMP 的唯一正面证据(I5d)在修正引擎上退化、I5e 负结果加强;I5f 的容量结论已按**真实 100 万名义**重写(1000 万口径的"约半数不足"作废);**日频除权审计已完成**(GENUINE、无 vintage 接缝、评估池暴露 1/603,258,不重述任何因子结果),**分钟路径的复权缺陷已在 PR #75 修**;exec-to-exec 改基准已随 **PR #79 合并**,close-to-close 与 exec 两套 artifact 并存;⚠️ **#79 的 code review 未返回、靠自查合并**,其"未独立核"清单(五条 mutation 声称 / 十一个 runner 改动是否机械等同 / `execution_capacity` 透传)仍待后续检查——若查出问题,重述 exec 基准数字而非 close-to-close;schema 守卫**仍未接** live `data-update` 暖跑路径;HTML compendium(`artifacts/reports/factor_compendium.html`)**还读 v0.8 结果,待按最终结果修订**。