diff --git a/docs/tasks/README.md b/docs/tasks/README.md index 62c7fa84..5b664bbf 100644 --- a/docs/tasks/README.md +++ b/docs/tasks/README.md @@ -290,6 +290,7 @@ | — (产品口头拍板,无任务书) | `PROGRESS-settings-ui-20260919.md` | **设置面板布局与资料入口整理**:基线 `4f4cd684`;四分区继续共用固定 `.settings-modal`,桌面导航 176px→200px 并加分隔,内容区增加内边距,表单 cap 440px→560px,导航移除误导性右箭头;账户头像 48px→56px;“添加其他人”移到分组标题操作区。已同步 `frontend/DESIGN.md` 与合同测试;tsc 0、lint 0 error、定向测试 21/21;build 被 Windows Skill runtime symlink 权限阻塞,浏览器走查待受控环境;BUG-970 保持 `investigating` | 待验收 | `codex/settings-ui-20260919` | | `TASK-owner-case-purge-20260919.md` | `PROGRESS-owner-case-purge-20260919.md` | **上游库主案例与本机路径残留清除(只含本仓)**:镜像同步带进库主本人案例(敏感案例标识与本机路径)并被 `origin/staging` 命中,涉及无引用的 `versions/` 三快照、前端 fixture、Python 测试、整机扫描台账、会话转录及上游 SKILL 快照。运行时无特判不用动。产品拍板整体删除不留匿名版;fixture 统一虚构常量;`import_yinduzhanxing.py` 加隐私排除项 + 新增仓库级隐私守卫测试;上游 SKILL 快照等库主清完再重导入(BLOCKED 记录)。上游仓的清理指令另见 `UPSTREAM-INSTRUCTION-owner-case-purge-20260919.md`(交给库主,不在本仓执行)。BUG-972/973 | **已验收通过(2026-09-20,`497798ac`);未合入 staging,等产品放行** | 两轮:首轮未通过(1 个隐私守卫冲突:新增路径规则与答案键守卫冲突,该守卫在快速门 glob 内,合入会让门禁红)→ 修复单 `TASK-owner-case-purge-fix2-20260919.md` → `497798ac` 通过。Claude 在 Linux 全依赖环境独立复验:快速门 Python 步 859 passed / 0 failed(上一轮就是这步红),Python 全量 63 红与基线逐条相同、0 新红,收集数与删除清单已记录;tsc 0 / lint 0 error、120 warning 同基线 / `npm test` 失败清单为基线子集(少 1 条工作流 YAML,非回归)/ `○ /` Static、首屏 gzip 与基线字节相同(前端自首轮提交起零改动)。上游指令文件已逐字节还原为基线原文;12 个已删测试名与计数已落进度记录;BLOCKED 两条已划掉。校正 Skill 哈希包、注册表、上游快照、`frontend/src`、主 API 全程 0 改动;库主本机用户名 0 命中。遗留 P3:进度记录和 BUG 状态文字待后续对账修正 | | `TASK-consult-smalltalk-fastpath-20260920.md` | — | **普通对话寒暄轮快速通道**:真机一句「你好」触发完整窗口排盘(活动面板「已完成 4 步」)+ `## 先回答你的问题` + 400 字判词 + 扣 1 点。三层叠加:`index.ts` 两处「every turn 必调排盘」(BUG-922)与 `contractReady()` 的 `requireTool` 把排盘变成硬合同;`product-voice.ts` OPENER SHAPE 标「三种模式共用」;唯一的 chit-chat 豁免句只在 `natalSpokenReportContract` 里、只拼进本命 Agent(BUG-977)。计费侧「写回复」与「扣点」绑在 `complete_consultation_response` 同一次调用,`cancel` 只退款不写消息,所以今天没有「不扣点但保留对话」的通道。**产品拍板 a:不扣点、不排盘、回一句白话**;**分流不得用正则/关键词/长度阈值**,改为进 Agent 之前一次极短的结构化模型调用(复用本轮已选模型),fail-open 一律落回完整路径;BUG-922/923 的三处合同一个字不改;新增 `complete_consultation_free` 迁移。BUG-976/977 | 待领取 | — | +| `TASK-rectification-validation-integrity-20260920.md` | — | **生时校正验证体系补缺(纯离线评测,不改打分不改产品)**:会议要求把「推断真实出生时间」与「用户认可的参考盘」分开证明。核对结论——**产品口径侧四条已落地**(`accepted`≠`confirmed` 两条写入路径、确认门 fail-closed 且 `holdout` 为 `not_ready` 使 `confirmation_allowed` 不可能为真、采用不写 `reported_birth_time`、无任何把采用率当准确率的指标;运行时也无按生日走捷径的分支);**缺口全在评测本身**。三条:① 封存契约 `rectification_sealed_holdout.v1.json` 的三个打分哈希互不相同(封存 `f41c298d` / 契约记录 `99730c84` / 基线实测 `b15d9ea1`),`official_eval_trial_count: 0`——当前实现**从未产出过一次有效官方盲测**,唯一跑过那次已被资料审计作废(top-1 `0.15`,发布门要 `0.60`),可见的 `0.45` 自带「不得当发布指标」标记(BUG-978);② 全部离线评测的候选窗**以真值为圆心**(`_candidate_moments()`、`request_from_case()` 的 `true_time`),生产以申报时间为圆心(`ENGINE_SEARCH_RADIUS_MINUTES = 15`)——「真值掉出窗外」这一失败模式从不可见(BUG-979);③ v3 封存但每例仅 3 事件、v4 有 7+ 事件却已被看过并用于调参,**无口径干净又贴近真实会话的封存集**;六题回放的 `0.80/0.55/0.35` 是「真值方向最优答」的上帝视角上界,±30/±60 仍低于发布门(BUG-980)。T1 申报偏差敏感性 sweep、T2 有效重跑 + 契约对齐 + **防复发新测试**、T3 只出 v5 采集协议、T4 记录。**硬红线:不得改 12 个打分文件、不得用封存集调参、不得把 `status` 改 `ready`。** 家庭信息(父母职业/兄弟姐妹)在拿到基线数字前不开工——现有七领域全是带日期事件,静态属性没有输入口。前置:owner-case-purge 三提交仍未合入 staging。BUG-978~980 | 待领取 | — | ## 命名与归档 diff --git a/docs/tasks/TASK-rectification-validation-integrity-20260920.md b/docs/tasks/TASK-rectification-validation-integrity-20260920.md new file mode 100644 index 00000000..fd2e896a --- /dev/null +++ b/docs/tasks/TASK-rectification-validation-integrity-20260920.md @@ -0,0 +1,175 @@ +# TASK · 生时校正验证体系补缺:申报偏差评测与封存盲测有效重跑(2026-09-20) + +> 状态:待领取。**纯离线评测与契约对齐,不改任何打分逻辑、不改产品行为、不动确认门。** +> 起因:产品会议对「我们究竟在证明什么」提出边界要求(真实出生时间 vs 用户认可的参考盘必须分开证明)。Claude 2026-09-20 对代码、评测数据与线上口径做了逐条核对,结论见 §1。 +> **产品口径侧的四条要求(accepted≠confirmed、不承诺精确分钟、不覆盖原始资料、不拿用户认可当验证)核对下来已经落地**,本单不碰那一层;缺口全部在评测本身。 + +## 0. 基线与交付 + +- 基线:`origin/staging` = `fcad0637`(2026-09-20 实测核对)。 +- worktree `.worktrees/rectification-validation-20260920`,分支 `codex/rectification-validation-20260920`。 +- 改动落点:`scripts/research/**`、`tests/**`、`references/rectification_sealed_holdout.v1.json`、`docs/**`。前三项在 `deploy/gated-paths.txt` 内,推 staging 会触发门禁并重新发布镜像。 +- **前置依赖(不在本单,不阻塞开工)**:`TASK-owner-case-purge-20260919` 的三个提交 `fe9489e6` / `36c443bf` / `497798ac` 已验收通过但**尚未合入 `staging`**(已核:三者均不是 `origin/staging` 的祖先)。那条分支带着仓库级隐私守卫 `tests/test_repo_privacy_markers.py`。本单不依赖它即可执行,但**在它合入之前,任何「拿自己的案例试一下」的结果都不具备独立性**,不得当作验证证据。放行由产品负责人决定。 + +## 1. 事故实证 + +基线 `fcad0637`,行号按符号定位。 + +### 1.1 三个打分实现哈希互不相同,任何成绩都无法归属(BUG-978) + +`references/real_case_calibration/minute_rectification_holdout_v3.json` 的 `frozen_scoring` 对 12 个打分文件做 SHA-256 封存。三处哈希实测: + +| 来源 | 哈希前缀 | +| --- | --- | +| 封存值 `frozen_scoring.implementation_sha256` | `f41c298dd6cdcebe` | +| 契约文件记录的当前树 `current_tree_scorer.implementation_sha256` | `99730c84c6434f52` | +| **基线树实测**(`implementation_sha256(frozen_scoring.files)`) | `b15d9ea15227cd58` | + +三者两两不等——契约文件 `references/rectification_sealed_holdout.v1.json` 里的 `current_tree_scorer` 块本身已经过期。同一文件另有两处与现实不符:`source_audit_status` 仍写 `invalidated_after_replay`,而 v3 数据集在 2026-09-14 已改为 `corrected_known_date_errors`;`evaluated_on` 仍停在 `2026-07-21`。 + +后果记在该文件自己的字段里:`official_eval_implementation_hash_matches: false`、`official_eval_trial_count: 0`——**当前打分实现从未在封存集上产出过一次有效的官方盲测成绩**。 + +- 唯一跑过的那次(2026-07-21):top-1 `0.15`、top-3 `0.25`、MAE `6.95` 分钟、确认覆盖率 `0.0`,报告状态 `invalidated_after_source_audit`(资料审计发现两处错年,已在 `docs/research/holdout_v4_build_2026_09_14.md` 更正)。 +- 现在唯一能看到的较新数字(top-1 `0.45` / top-3 `0.50` / MAE `5.8`)来自 `current_tree_unfrozen_diagnostic` 块,该块自带 `is_blind_evaluation: false`、`results_already_seen: true`、`must_not_claim_as_release_metrics: true`、`must_not_use_for_tuning: true`。 + +预注册发布门(`minute_rectification_holdout_v3.json` 的 `release_metrics`):top-1 ≥ `0.60`、top-3 ≥ `0.85`、MAE ≤ `2.0` 分钟、误确认率 ≤ `0.05`、信息不足正确拒绝率 ≥ `0.90`。 + +**计算成本不是障碍**:基线树实测,20 例全量打分 ±10 档 `1.6 s`、±60 档 `8.6 s`。 + +### 1.2 所有离线评测的候选窗以真值为圆心,生产以申报时间为圆心(BUG-979) + +- `scripts/minute_rectification_blind_eval.py` 的 `_candidate_moments()` 以 `case["birth"]["time"]`(Astro-Databank AA 记录的真实分钟)为中心,向两侧各取 `candidate_radius_minutes` 分钟。 +- `scripts/minute_rectification_fact_blind_eval_v4.py` 直接 import 复用同一函数。 +- `scripts/research/probe_supply_after_six.py` 的 `request_from_case()` 同样以真值为心,局部变量名就叫 `true_time`,`start_time` / `end_time` 由它 ± 半径得到;`scripts/research/minute_resolution_sweep.py` 的 `scoring_request_for()` 调的就是它。 + +生产不是这样:`frontend/src/lib/rectification-agentic/v9/search-window.ts` 的 `ENGINE_SEARCH_RADIUS_MINUTES = 15`,窗以用户**申报**时间为中心(`frontend/src/lib/rectification-agentic/birth-time-provenance.ts` 文件头注释明写 "Scoring still uses reportedBirthTime as the search-window centre"),可放宽到 30 / 60 / 120。 + +后果:离线评测里真值**永远在窗正中心、永远在候选集里**。「申报偏差大于半径 → 真值根本不在候选里」这一失败模式在现有全部评测中不可见,其发生率从未被测量。全仓检索偏移窗相关键在评测脚本内 0 命中。 + +### 1.3 现无「口径干净且事件数贴近真实会话」的封存集(BUG-980) + +| 数据集 | 是否封存 | 每例事件 | 每例领域 | 可否当发布门 | +| --- | --- | ---: | ---: | --- | +| `minute_rectification_holdout_v3.json` | 是(`truth_hidden_from_ranker: true`) | **3** | 2–3 | 可,但事件数远低于真实会话 | +| `minute_rectification_holdout_v4.json` | **否**(`truth_hidden_from_ranker: false`) | ≥7 | ≥4 | **不可**,结果已被看过且用于 R1–R5 调参 | + +`docs/research/holdout_v4_build_2026_09_14.md` 自己写明 v4「是开放评价集,用来看尺度,不是第二份封存盲测」;真实会话每例 5–18 件事。 + +另:`docs/research/minute_resolution_2026_09_14.md` 记载六题回放用「**真值方向最优答**」。因此 0.80 / 0.55 / 0.35(±10 / ±30 / ±60)是**上帝视角上界**,不是产品表现;其中 ±30 与 ±60 两档仍低于 `0.60` 的发布门,而生产默认半径 ±15 正落在两档之间。 + +### 1.4 产品口径侧已经达标(不构成 BUG,记此以免重复排查) + +- `accepted` 与 `confirmed` 是两个状态、两条写入路径(`frontend/supabase/migrations/20260813010000_agentic_rectification_v9_agent_api.sql` 的 `accept_agentic_rectification_candidate_for_case` 与 confirm 函数),`selection_kind` 区分 `user_accepted` / `engine_confirmed`。 +- 采用候选写 `active_birth_time` / `birth_time`,**不写 `reported_birth_time`**——原始申报保留,且仍是搜索窗圆心。 +- 确认门 fail-closed:`scripts/rectification/decision_policy.py` 的 `apply_confirmation_decision()` 要求四闸同时通过,其一是 `scripts/rectification/sealed_holdout.py` 的 `holdout_passed()`。封存契约 `status: not_ready` 且 `confirmation_coverage_rate: 0.0`,因此 `confirmation_allowed` 今天在任何情况下都不可能为真。 +- 交付卡自带标签 `candidate_range_not_birth_time_truth` 与「采用只会把代表性时间写入当前排盘,不是已确认的唯一出生分钟」。 +- 全仓无「把采用率 / 满意度当准确率」的指标;无任何按特定生日走捷径的运行时分支(上游 `PL9_BAV_CELL_OVERRIDES`、`_known_case_regression_hint` 在本仓 0 命中)。 + +**关联记录:`BUG-098`**(公开候选门禁未明确独立 holdout 边界)。其防复发条写明「任何 holdout 完成声明必须先有稳定分区持久化与校准验收证据」。本单三条与之同源:那条措施**仍然有效,但从未被执行到底**,且没有任何测试守着它。 + +## 2. 根因 + +1. 封存契约文件 `references/rectification_sealed_holdout.v1.json` 是**人工维护**的(`scripts/rectification/sealed_holdout.py` 文件头注释:「A human updates ... after a valid passing evaluation」),没有任何测试断言它与数据集、与当前树哈希一致 —— 打分代码每改一次,它就更旧一次,而没有人会被提醒。 +2. 评测脚本是从「给定真实出生时间,能否把它排到第一」出发写的;产品解决的是「给定用户申报时间,真实时间在哪」。两者差一个偏移量,建评测时没有人把这个差异写成一项指标。 +3. v4 建立时就定性为开放评价集,此后没有人补上对应的封存孪生集,于是「事件数真实」与「口径干净」只能二选一。 + +## 3. 决策记录 + +- **2026-09-20 产品授权出本单**,覆盖核对结论中的两条行动:补申报偏差评测、重跑有效封存盲测;外加一条只出协议的封存集规划。 +- **本单只产出数字与结论,不改打分逻辑、不调参、不改产品行为。** 即便重跑成绩过了发布门,执行方**不得**把 `status` 改成 `ready`、不得让确认门打开 —— 过门是产品决策,另立单。 +- **家庭信息(父母职业、父母出生年份、兄弟姐妹)在本单产出基线数字之前不开工。** 核对已确认:现有七个领域全部是带日期事件,打分输入只认 `{id, domain, date, precision}` 四个字段(见 `scripts/minute_rectification_blind_eval.py` 的 `_request()`),静态家庭属性**没有输入口** —— 加它不是多问一道题,是新开一条打分通道。若产品另有决定,请在领取前更新本段。 +- 上游清除分支的放行是产品动作,不在本单(§0)。 + +## 4. 硬红线 + +1. **不得修改 `frozen_scoring.files` 里那 12 个打分文件中的任何一个**,也不得修改 `scripts/rectification/decision_policy.py`、`scripts/rectification/sealed_holdout.py` 的判定逻辑。本单是量,不是改。 +2. **不得把封存集 v3 用于任何调参**;不得因成绩难看而更换数据集、更换半径或剔除案例。剔除只允许发生在 `minute_rectification_holdout_validator.validate()` 判定为 `invalid_cases` 的情况下,且必须列出被剔案例与理由。 +3. **不得让 `references/rectification_sealed_holdout.v1.json` 的 `status` 变成 `ready`**,不得抬高 `confirmation_coverage_rate`。 +4. 新增的偏差评测必须与现有评测**并存**;不得改写 `_candidate_moments()` 与 `request_from_case()` 的现有行为(改了会让两轮历史结论不可比)。 +5. 任何数字进文档必须带口径:ayanamsa / node mode / 半径 / 步长 / 数据集 / 打分实现哈希前 16 位。**不得把非盲诊断写成发布指标。** +6. 不得写入真实用户资料;案例只用已登记的公开 AA 名人;不得在任何文档里写出生分钟或坐标。 +7. 不顺手升级依赖、不修不在本单内的 warning。 +8. `frontend/src/app/page.tsx` 与 `scripts/jyotish_api_server.py` 均不得增长(本单本不该碰前端与主 API,碰了说明跑偏)。 + +## 5. 任务分解 + +### T1 · 申报偏差评测(BUG-979) + +新增 `scripts/research/reported_offset_sweep.py`:在现有取候选方式之外,增加一个「模拟申报时间」的圆心。 + +- 对每个案例,把窗心从真值平移 `offset ∈ {0, ±3, ±5, ±8, ±10, ±15, ±20, ±30}` 分钟,半径取产品档位 `{15, 30, 60}`。 +- 每个(案例, 偏移, 半径)组合输出四项:**真值是否落在窗内**、真值在候选中的排名、头名与真值的分钟距离、交付区间是否覆盖真值。 +- 汇总成一张表:横轴偏移、纵轴半径,格子里是「真值在窗内的比例 / 头名命中 / 区间覆盖」。 +- 真值仍然**排完名之后**才揭晓;并列沿用现有哈希打破方式(`_opaque_winner`),**不得按接近真值挑选**。 + +验收标准: + +- `python3 scripts/research/reported_offset_sweep.py --json` 在基线树跑通,输出含上述四项与完整口径块(含打分实现哈希前 16 位)。 +- 新增 `tests/test_reported_offset_research.py`,至少断言:(a) 偏移为 0 时窗心等于真值且「真值在窗内」为 `1.0`;(b) 偏移绝对值大于半径时「真值在窗内」为 `0`;(c) 口径块字段齐全;(d) 并列打破不依赖真值。 +- 结论写进 `docs/research/reported_offset_2026_09_20.md`,**必须明确回答一句**:在半径 ±15 下,申报偏差多大时真值开始掉出窗外;以及现有放宽路径(30 / 60 / 120)能把这个比例救回多少。 +- 本任务**不需要**知道真实用户的申报偏差分布;它给的是「如果偏差是 X,会怎样」的敏感性曲线。真实分布怎么拿,进 T4 的遗留项。 + +### T2 · 封存盲测有效重跑与契约对齐(BUG-978) + +1. 冻结当前打分实现:把基线树实测哈希(`b15d9ea15227cd58…`,执行方自己重算确认)连同 12 个文件清单写进一次新的评测记录;**不改 v3 的 `frozen_scoring` 原值**(那是历史封存值,要留着做对照)。 +2. 在 v3 封存集上跑一次完整盲测,产出五项预注册指标:top-1、top-3、MAE、误确认率、信息不足正确拒绝率。 +3. 把 `references/rectification_sealed_holdout.v1.json` 更新到与现实一致:`source_audit_status` 取 v3 数据集当前值;`current_tree_scorer` 刷新到本次实测哈希与成绩;新增一个块记录本次重跑,注明它是**首次口径干净的官方盲测**,以及「v3 每例仅 3 件事,是下限口径,不代表真实会话」。`status` 保持 `not_ready`(§4.3)。 +4. 新增 `tests/test_sealed_holdout_contract_freshness.py`:断言契约文件的 `current_tree_scorer.implementation_sha256` 等于当前树实测值、`source_audit_status` 等于 v3 数据集里的值。**这条测试就是防复发** —— 它一红就说明打分代码改了而契约没跟上。 + +验收标准: + +- `.venv/bin/python -m pytest tests/test_sealed_holdout_contract_freshness.py tests/test_minute_rectification_holdout_validator.py tests/test_minute_rectification_fact_blind_eval_v4.py -q` 通过。 +- 契约文件三处过期字段全部对齐,且 `status` 仍为 `not_ready`、`confirmation_coverage_rate` 仍为 `0.0`。 +- 五项指标与发布门逐条对照写进 `docs/research/sealed_holdout_rerun_2026_09_20.md`,每项标「通过 / 未通过 / 不适用」。 +- **确认门行为零变化**:跑 `frontend/tests/rectification-confirmation-gate.test.ts` 与相关 pytest,结果与基线逐条相同。 +- 快速门 `python3 scripts/run_quality_gate.py --profile quick` 与基线逐条比对。 + +### T3 · 封存集 v5 采集协议(BUG-980,只出协议、不采集) + +写 `docs/research/sealed_holdout_v5_protocol_2026_09_20.md`: + +- v5 目标:**封存 + 每例 ≥7 件带年月事件 + ≥4 个领域**,即 v4 的口径、v3 的纪律。 +- 人物名单必须与 v3 / v4 的 20 例**不重叠**(那 20 例成绩已被看过)。列出 ≥25 个候选公开 AA 人物作为备选池,只写人物与资料来源类型,**不写出生分钟或坐标**。 +- 标注协议沿用 `holdout_v4_build_2026_09_14.md` 的四条(AA 记录、事件来自公开页且 `independent_of_birth_source=true`、工作日期须核实、三档半径写在数据集上),并补一条:**v5 建成后,在产出第一份成绩之前不得被任何人读取事件内容做调参**。 +- 工作量估算:按每例 7 件事、每件需一处可核实公开来源计,给出人工小时数区间。 +- 明确写出:「在 v5 就绪之前,任何对外的分钟级准确率说法都没有依据」,并指明 T2 的数字是下限口径、T1 的数字是敏感性而非准确率。 + +验收标准:文档含上述全部要素;候选池 ≥25 人且与现有 20 例无交集;不含任何出生分钟、坐标或真实用户资料。 + +### T4 · 记录 + +- `docs/BUG_HISTORY.md` 新增 `BUG-978` / `BUG-979` / `BUG-980`,状态按实际填(T1 / T2 完成的可写 `resolved` 并附证据;`BUG-980` 只出协议,保持 `investigating` 直到 v5 就绪)。三条都必须**关联 `BUG-098`**,并说明那条防复发措施为何没拦住。 +- `BLOCKED.md` 记一条:真实用户的申报偏差分布目前拿不到(需要有独立出生记录的真实用户样本,无受控账号),T1 只能给敏感性曲线。 +- `docs/research/ACTIVE_FRONTS.md` 加一节索引本单三份文档,并指回 `rectification_minute_resolution_closure_2026_09_14.md`。 +- `docs/tasks/README.md` 状态板加一行;**实现合入 staging 的同一次推送里改状态**。 +- `CHANGELOG.md` 不写(无用户可感知行为变化)。 + +## 6. 让步顺序 + +时间不够时按此顺序砍,砍掉的写进进度记录: + +1. **最先保 T2** —— 它最便宜(±10 档全量 1.6 s),且产出的是第一份能对着发布门看的数字。 +2. 其次保 T1 的 ±15 一档与 `{0, ±5, ±10, ±15, ±20}` 五个偏移;其余半径与偏移可后补。 +3. T3 候选池可从 25 人降到 15 人,但**协议正文与那句「在 v5 就绪之前没有依据」不得删**。 +4. **不得为赶工跳过 T2.4 那条防复发测试** —— 没有它,这三条明天会重新长出来(`BUG-098` 就是这么回来的)。 + +## 7. 开工前置命令 + +```bash +git fetch origin --prune +git worktree add -b codex/rectification-validation-20260920 \ + .worktrees/rectification-validation-20260920 origin/staging +cd .worktrees/rectification-validation-20260920 +git log --oneline -1 # 必须是 fcad0637 或其后代 +python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45 +``` + +本单属 `AGENTS.md` §9 的引擎 / 评测类任务,`pre_work_check.py` 必跑,并先读 `docs/research/pre_work_error_ledger.md`。 + +**另必读** `docs/research/rectification_minute_resolution_closure_2026_09_14.md` —— 它已经证伪了两条假设(加权重能拉开候选、簇合并把候选并没了),本单不得重走;它的第 6 节三条提醒(先确认指标口径、不要从 docstring 推断行为、真值覆盖率优先于区间宽度)对本单全部适用。 + +环境备忘:核对机上无 `.venv`,系统 `python3`(3.13)可直接 `import swisseph`;若执行方环境有 `.venv`,按 `AGENTS.md` §10 用 `.venv/bin/python`。 + +## 8. BUG 编号起点 + +`docs/BUG_HISTORY.md` 当前最大号 **975**;`TASK-consult-smalltalk-fastpath-20260920.md` 已占用 **976 / 977**。本单从 **BUG-978** 起,连续三条。开工时重新核对最大号,若已被占用则顺延并在进度记录里说明。