research(rectification): offline R1/R2/R3 — answer-flip tolerance, V1/V2 rerun, dasha shift arithmetic

- R1: flipping 1 answer keeps truth in range 98-100% but cuts head hit by
  a third or more; 2 flips squeeze truth out in 7-10% of ±30/±60 replays
  (two flips = 8 points = SEPARATION_LEAD).
- R2: weights do apply (research scorer == production at V0); V1/V2 are
  identity at ±30/±60 by construction and leave six-question metrics
  unchanged at ±10 -> no_benefit (measured). Supplementary V1n does not
  pass the gate.
- R3: boundary shift is ~3.8 days/minute (1.3-5.9), not 1.1; the 45-day
  gate is ~8-34 minutes. The _representative_pairs hypothesis is refuted
  (all-pairs adds no dated probes); the bottleneck is monthly evaluation.
  New finding recorded as BUG-1048 (investigating): _boundary_windows
  year-straddle exemption and positional zip misalignment bypass the gate.
- Dated errata appended (no deletions) to the 09-14/09-16 briefs and
  research docs; README board row -> 待验收. No production code, scoring,
  thresholds, gates or Skill changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
This commit is contained in:
Jesse_Chen
2026-09-26 14:47:48 +08:00
co-authored by Claude Opus 5.5
parent 7203d94e9c
commit 0f5442cea2
19 changed files with 19012 additions and 1 deletions
@@ -0,0 +1,79 @@
# 进度 · 生时校正三项离线研究(2026-09-26)
## 范围
- 任务书:`docs/tasks/TASK-rectification-offline-research-20260926.md`
- 分支:`codex/rectification-offline-research-20260926`,worktree `.worktrees/rectification-offline-research-20260926`。开工基线 `origin/staging` @ `abb05b67`;测量在快进后的 `7ddce2c9` 上完成;提交最后变基到 `7203d94e`(其间只新增 `scripts/research/fewer_probes_card_replay.py` 与文档,引擎与打分代码未变,测量结果不受影响)。**本地提交,未推送。**
- 执行方式:产品授权 Claude 子代理直接执行。
- 报告:`docs/research/rectification_offline_research_2026_09_26.md`(三节 + 一句话结论 + 是否立实现单)
- 性质:离线研究。**未改线上代码、打分、阈值、出题闸门、Skill、workflow。** 研究脚本在一次调用内临时替换模块属性(`event_probes._representative_pairs`、`event_probes._boundary_windows`、`event_probes._evaluate_contexts` 计数包装、研究模块 `precision_gate_lib.varga_factor`),调用结束立即恢复,脚本末尾断言已恢复,并断言线上闸门仍是 45 / 30。
- 数据:v4 公开 AA 开放集(20 例)与虚构时刻。没有真实用户资料。**开放集回放,不是盲测,不是准确率。**
## 开工预检
- 读了 `AGENTS.md`(Part A、Part B B4)、`CLAUDE.md`、任务书、closure / minute_resolution / cluster_width / precision_gate / holdout_v4 / guided_collect_holdout 各文档、BUG-692、`event_probes.py`(`_boundary_windows`、`_representative_pairs`、`_union_boundary_dates`、`_evaluate_contexts`、`guided_collect_windows`)、`decision_policy.py`、v4 回放脚本、上一轮审计的 `shift.py` / `repo_shift.py`、`docs/research/pre_work_error_ledger.md`(重点 ERR-110 / ERR-111)。
- `python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45`:**exit 0**。remote verified,碎片扫描、外部引擎适配器诊断、5 个 focused 目标全部通过。本机没有复现台账里 09-24 / 09-25 的 `.workbuddy` 镜像断言失败,与 09-26 BUG-1047 预检记录一致。无新台账条目。
- 本机没有 `.venv`,系统 `python3`(带 swisseph、pytest)运行全部命令。
## 完成
| 项 | 脚本 | 结果 | 耗时 |
| --- | --- | --- | ---: |
| R1 答错容错 | `scripts/research/answer_flip_tolerance.py` | `docs/research/answer_flip_tolerance_2026_09_26.json` | ~1 分钟 |
| R2 V1/V2 重跑 | `scripts/research/varga_sensitivity_rerun.py` | `docs/research/varga_sensitivity_rerun_2026_09_26.json` | ~16 分钟 |
| R3a 每分钟位移 | `scripts/research/dasha_shift_per_minute.py` | `docs/research/dasha_shift_per_minute_2026_09_26.json` | 1 秒 |
| R3c 配对推断 | `scripts/research/representative_pairs_probe.py` | `docs/research/representative_pairs_probe_2026_09_26.json` | ~6 分钟 |
| 共用纯函数 | `scripts/research/offline_research_20260926_lib.py` | — | — |
| 回归测试 | `tests/test_offline_research_20260926.py`(5 条,只测研究纯函数) | 5 passed | — |
全部运行错误 0 例。
## 关键数字
- **R1**:不答错的基线与 09-14 G0 逐项一致(0.80 / 0.55 / 0.40;15 / 33 / 56;20/20)。答错 1 题:真值在区间 1.000 / 0.989 / 0.981,头名 0.58 / 0.33 / 0.24(同批不答错为 0.94 / 0.61 / 0.44)。答错 2 题:真值在区间 0.996 / 0.926 / 0.898,头名 0.40 / 0.08 / 0.06;±30 有 9/18 例、±60 有 12/18 例至少一种组合挤出真值。真值从未被淘汰(需 3 次强冲突)。随机抽样(种子 20260926,每格 30 次)与穷举一致。
- **R2**:研究计分器 V0 与线上 0 / 2060 候选有差。V1 / V2 在 ±30 / ±60 上 0 个候选分数变化(系数全截断到 1 / 不丢分盘),±10 上 168 / 159 个候选分数变化,六题后指标与 V0 完全相同 → `no_benefit`(已实测)。补充 V1n 头名 0.85 / 0.60 / 0.50,宽度 15 / 33 / 73,不过门。
- **R3a**:每分钟边界位移中位 3.82 天(p10 1.58、p90 5.00、范围 1.34–5.85,n=2000),差分与解析式一致,仓库 `_vim_start_dates` 中位 4.05(n=299 子样本),边界整体平移(对齐后差值 ≤1 天)。45 天闸门 ↔ 中位 11.8 分钟(7.7–33.5)。
- **R3c**:全部两两配对 vs 线上配对,带日期题(截断前)4.85 vs 4.80(±10 初始)、3.25 vs 3.30(±10 刷新),其余半径差异 ≤0.1;没有带日期题的例子数完全相同 → 推断被推翻。边界月份能分开代表的比例:初始 3.2–4.5%,刷新约 0.4–0.5%。严格闸门(研究补丁)下 ±10 初始没有带日期题的例子 4 → 8。
## 同机复跑(BUG-985:只做同机 A/B,不写死跨机哈希)
| 脚本 | 复跑方式 | 结果 |
| --- | --- | --- |
| R1 | `PYTHONHASHSEED=12345` 再跑一次 | JSON 逐字节一致 |
| R3a | `PYTHONHASHSEED=999` 再跑一次 | JSON 逐字节一致 |
| R3c | `PYTHONHASHSEED=4242 … --no-write` | summary 与已存 JSON 完全一致 |
| R2 | `PYTHONHASHSEED=4242 … --no-write` | proof 摘要与 12 行指标与已存 JSON 完全一致 |
## 文档改动(只加勘误段,不删原文)
- `docs/tasks/TASK-rectification-precision-adaptive-boundary-research-20260914.md`:1.1 天 / 122 天每度 / 换算表
- `docs/tasks/TASK-rectification-open-collect-invite-20260914.md`:D1b 依据句
- `docs/tasks/TASK-rectification-precision-gate-guided-collect-20260916.md`:实证第 5 条「20 分钟≈22 天,题池必然为空」
- `docs/research/precision_gate_2026_09_14.md`:M1b V1/V2 → `no_benefit`(已实测)
- `docs/research/rectification_minute_resolution_closure_2026_09_14.md`:新增 §7 勘误与补充
- `docs/BUG_HISTORY.md`:BUG-692 加一条补充;新增 **BUG-1048**(`investigating`,闸门跨年豁免 + zip 错位,未修)。开工时最大号是 BUG-1047;合入前请再核对一次编号,避免与并行分支冲突。
- `docs/tasks/README.md`:本单状态改为「待验收」。
线上引导文案**未改**;改写建议写在报告 §R3「改正与文案建议」。
## 测试
- `python3 -m pytest tests/test_offline_research_20260926.py tests/test_bug_history_workflow.py`:7 passed
- `python3 -m pytest tests/test_repo_privacy_markers.py`(新文件暂存后):全部 passed
- `python3 -m pytest tests/test_rectification_validation_integrity_gate.py tests/test_minute_resolution_research.py tests/test_cluster_width_research.py`:全部 passed(没有改冻结评分文件,见 ERR-110)
- 快速门 `python3 scripts/run_quality_gate.py --profile quick`:Python 部分 **948 passed / 1 skipped**(含隐私、校正完整性门禁);随后 `npm test` 步骤 exit 127,原因是本 worktree 没有 `frontend/node_modules`(环境缺口,本单没有前端改动),整体报 `Quality gate failed`。不记为通过。快速门没有改动任何跟踪文件。
## 偏离与注意
1. **R2 加了一个任务书没有的补充方案 V1n。** 原因:V1 按定义在宽窗上截断成恒等,只报告「V1/V2 无变化」回答不了「按敏感度配权有没有用」。V1n 单列、标「补充」,不参与原判定。
2. **R3c 加了「严格闸门」对照**,由此发现 BUG-1048。只做测量,不修。任何修改都要按 ERR-110 重新冻结 sealed holdout 记录。
3. `scripts/research/precision_gate_sweep.py` 重跑会整篇覆盖 `docs/research/precision_gate_2026_09_14.md`,冲掉 09-15 与 09-26 两段手写勘误(既有风险,本单未改那个脚本)。
4. 六题回放沿用 09-14 设计,题目不随作答重出。R1 因此测不到「答错后后续题被带偏」的影响,报告里已写明。
5. v4 回放复现不出真机上「六题后问完了」的现象(±10 刷新阶段平均还有 3.25 道新的带日期题)。真机原因需要真机统计(`TASK-rectification-telemetry-20260926.md`),本单不下结论。
6. `scripts/research/**` 与 `tests/**` 在门禁路径里,推送会触发 staging 门禁。本单未推送。
## 未做
- 未推送、未合入 staging、未部署(按指令)。
- 未改线上引导文案(任务书要求只给建议)。
- 未评估 BUG-1048 两个漏洞放出来的题目在真人作答下是否可靠。
+1 -1
View File
@@ -37,7 +37,7 @@
| --- | --- | --- | --- | --- |
| `TASK-rectification-fewer-probes-card-20260926.md` | [PROGRESS](PROGRESS-rectification-fewer-probes-card-20260926.md) | **减少无效追问 + 卡片区间为主**:引导补件离线新增达标 0 → 上限 6→2、定向题问完门槛未达直接出卡;卡片区间为主标题、代表分钟副标题,第一二名差距 ≥5 个百分点才显示百分比,否则写「目前区分不开」。不放宽任何置信度。先做 | 待验收 | `codex/rectification-fewer-probes-card-20260926`(未推送;D1 改在前端每校正 2 道,引擎常量因冻结评分身份未动;回放真值不降、宽度中位 ±1 分钟、提问 11.4→7.8;Skill 10.0.30) |
| `TASK-rectification-telemetry-20260926.md` | — | **匿名聚合统计**:每会话一行只存数字 / 枚举(题数分类、宽度、差距、停止原因、门槛达标、耗时、版本),管理后台只看汇总、保留 180 天;动表须 test:db。排在 fewer-probes 后 | 待领取 | — |
| `TASK-rectification-offline-research-20260926.md` | — | **三项离线研究**:答错 1–2 题的容错、V1/V2 分盘配权正确重跑、改正「1 分钟≈1.1 天」(实测中位 3.8 天)并核实 `_representative_pairs` 推断。不改线上 | 待领取 | — |
| `TASK-rectification-offline-research-20260926.md` | `PROGRESS-rectification-offline-research-20260926.md` | **三项离线研究**:答错 1–2 题的容错、V1/V2 分盘配权正确重跑、改正「1 分钟≈1.1 天」(实测中位 3.8 天)并核实 `_representative_pairs` 推断。不改线上。结论(`docs/research/rectification_offline_research_2026_09_26.md`):R1 答错 1 题真值在区间 98–100%、头名降三到四成,答错 2 题 ±30/±60 挤出 7–10%(两道反答=8 分=淘汰线);R2 权重生效,V1/V2 在 ±30/±60 按定义恒等、±10 六题后指标不变 → `no_benefit`(已实测);R3 3.8 天/分钟复现,45 天闸≈8–34 分钟,`_representative_pairs` 推断被推翻(全配对题数不变,卡在逐月评估),另记 BUG-1048 `investigating`(闸门跨年豁免 + zip 错位)。三项均不建议立实现单 | 待验收 | `codex/rectification-offline-research-20260926`(本地未推) |
| `TASK-rectification-code-split-20260926.md` | — | **代码拆分(只搬不改)**:聊天组件 2043 行 / 35 useState、`POST` 926 行、`runV9AgentTurn` 1047 行,269 处切源码测试;拆分 + 增长合同 + 切片测试改调用函数。排在 fewer-probes、telemetry 之后 | 待领取 | — |
| `TASK-rectification-dup-question-20260926.md` | `PROGRESS-rectification-dup-question-20260926.md` | **同一轮问题出现两次(BUG-1045,复发自 BUG-585,BUG-969 拼回题干、去重只在刷新路径)+ 同一道选择题连画两张(BUG-1046:提交失败不回滚本地已答 + 兜底问题块条件过宽;H2 漏收回合)**。先于 latency 单 | 已验收(Claude 09-26 直接执行:子代理复现 A 与 B-H1(选择题提交 409 / 网络错误不回滚本地已答);Claude 变基到含 BUG-1043/1044 的 staging 后独立复验 tsc/lint 0、全量 3981 条失败名单与基线逐条一致、四路由 ○、gzip 不变) | `e4c1c7a3`(已部署 `f1d16405`,health 一致) |
| `TASK-rectification-latency-20260926.md` | `PROGRESS-rectification-latency-20260926.md` | **每轮等待过长(BUG-1047)**:一轮打字回答串行 5 次开思考的模型调用,分类在开流前且无超时。产品定:收尾两步不动、分类保持思考只加 10 秒超时、发出后立即出确定性进度句并按阶段更新;补埋点;服务端无口吻优化须 A/B 逐位一致。排在 dup-question 之后 | 已验收(Claude 09-26 直接执行:子代理实现 D1–D4 与 D5 两项;Claude 用 Node 22 独立复验 tsc/lint 0、全量 4002 条失败名单与 Node 22 基线逐条一致(24 条均为 Docker/DB)、四路由 ○、gzip 不变。D5 第 1 项(探针复用)输出逐字节一致但触发冻结打分身份,Claude 建议暂不做) | `86ff9a40`(已部署 `8a409434`,health 一致) |
@@ -90,3 +90,12 @@ cd frontend && npm ci
## 7. BUG 编号起点
- 起点 **BUG-689**(当前最大号 688)。
## 勘误(2026-09-26 离线研究 R3)
§2 D1b 的依据句有误,原文保留不删。
- 错误:「出生时间每差 1 分钟,Vimshottari 大运边界只平移约 1.1 天」。实测中位约 **3.8 天**(1.3–5.9,按出生星宿主星分两档)。
- 错误:「只有日精度的事件才有可能分开相隔几分钟的候选」。改正:记得到月的事件,在候选相隔约 8 分钟以上(慢的星宿约 20 分钟以上)时就能稳定分开;记得到天(容许几天误差)的事件能分开相隔约 2–5 分钟的候选。v4 开放集上把日精度降成月精度,头名与宽度都不变(`docs/research/precision_gate_2026_09_14.md` M0),「记得到天明显更有用」仍不能写成已证实。
- 本单的自由文本邀请已在 BUG-740 删除,线上现为引导题 + 年 / 月选择器(日期可选)。依据句的建议改写与文案建议见 `docs/research/rectification_offline_research_2026_09_26.md` §R3「改正与文案建议」。线上文案本次未改。
- 复跑:`python3 scripts/research/dasha_shift_per_minute.py`。
@@ -131,3 +131,22 @@ python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45
## 7. BUG 编号
- 研究单,**不新增 BUG 编号**。
## 勘误(2026-09-26 离线研究 R3)
§1 的换算有误,原文保留不删。
- 错误:「Vimshottari 1° ≈ 122 天」「出生时间每差 1 分钟,所有 Vimshottari 边界整体平移约 1.1 天」。Vimshottari 120 年覆盖 9 个星宿(120°),**平均 1° ≈ 365 天**(太阳 164 天 / 度到金星 548 天 / 度)。
- 实测(2000 个虚构时刻):每分钟平移**中位 3.8 天**,p10 1.6、p90 5.0,全范围 1.3–5.9,按出生星宿主星分两档(太阳 / 火星 / 计都 / 月亮约 1.5–2.5;木星 / 水星 / 罗睺 / 土星 / 金星约 4–5)。仓库 `_vim_start_dates` 复核一致。「所有边界整体平移同一个天数」这一点是对的。
- 换算表改正:
| 候选相隔 | 边界相差(中位 / p10–p90) | 45 天闸 | 30 天闸(刷新) |
| --- | ---: | --- | --- |
| 40 分钟 | ≈ 153 天 / 63–200 | 全部可出题 | 全部可出题 |
| 20 分钟 | ≈ 76 天 / 32–100 | 66% 可出题 | 94% 可出题 |
| 10 分钟 | ≈ 38 天 / 16–50 | 27% 可出题 | 54% 可出题 |
| 2 分钟 | ≈ 7.6 天 / 3–10 | 不可 | 不可 |
- 45 天闸门对应中位 **11.8 分钟**(全范围 7.7–33.5),30 天对应中位 7.8 分钟,不是 40 / 27 分钟。
- 因此「剩余候选挤在 20 分钟内 → 大运边界全在三周内 → 被闸门整批丢掉」的推断不成立。另外核实了 `_representative_pairs`(只配相邻 + 首尾)不是出不来题的原因:改成全部两两配对,带日期的题数不变。真正的卡点在逐月评估。
- 出处与复跑命令:`docs/research/rectification_offline_research_2026_09_26.md` §R3;`python3 scripts/research/dasha_shift_per_minute.py`、`python3 scripts/research/representative_pairs_probe.py`。
@@ -175,3 +175,12 @@ Bug 检索(§5 硬约束):`BUG-687`、`BUG-689`、`BUG-646`~`648`、`BUG
## 9. BUG 编号起点
**BUG-740**(基线最大 BUG-739)。开工时重新核对。
## 勘误(2026-09-26 离线研究 R3)
§1 事故实证第 5 条有误,原文保留不删。
- 错误:「窗口收到 20 分钟时边界位移约 22 天,**自动点选题池必然为空**,这是『问完了』的算术原因」。改正:每分钟平移中位约 3.8 天,20 分钟对应边界差中位约 76 天(p10–p90 为 32–100 天),66% 能过 45 天闸、94% 能过 30 天刷新闸。
- v4 开放集回放里,六题后刷新阶段平均还能出 3.25 道新的带日期题(±10),1900 年后出生的 18 例里只有 1 例为 0。任务书推断的「`_representative_pairs` 只配相邻 + 首尾」也不是原因:改成全部两两配对,题数不变。卡点在逐月评估,只有约 0.4% 的边界月份能把剩余代表分到两边。真机上「问完了」的真实原因未定,需要真机统计。
- 本单的决策(出卡门槛、引导补经历)不依赖这条算术,不受影响。
- 出处与复跑:`docs/research/rectification_offline_research_2026_09_26.md` §R3;`python3 scripts/research/representative_pairs_probe.py`。