Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
15 KiB
PROGRESS · 生时校正:减少无效追问 + 交付卡以区间为主(2026-09-26)
- 任务书:
docs/tasks/TASK-rectification-fewer-probes-card-20260926.md - 分支:
codex/rectification-fewer-probes-card-20260926,基线origin/stagingabb05b67(代码与线上8a409434相同) - 执行:Claude 子代理(直接执行模式,产品授权)。未推送。
- 产品调整,不开 BUG 号。Skill 10.0.29 → 10.0.30。
结论先行
| 决策 | 做了什么 | 状态 |
|---|---|---|
| D1 引导补经历最多 2 条 | 前端题池按 每个校正最多 2 道 引导窗口题(GUIDED_WINDOW_CASE_LIMIT = 2)。引擎 GUIDED_COLLECT_LIMIT 没有改,见下方「偏离」 |
完成(实现位置偏离任务书字面) |
| D2 定向题问完直接出卡 | 能挡住出卡的线只剩「七条定向线 + 跳过线一次重问 + 进行中的年月追问」;没问到的引导窗口题不再挡卡(cardHoldingLinesExhausted)。区间、淘汰、采用门、确认门、刷新未试不出卡(BUG-654/656)都不变 |
完成 |
| D3 区间为主标题 | 主标题「目前范围 05:00–05:15(对照了 N 件经历)」不变,下面加副标题「最可能 05:07」(代表分钟) | 完成 |
| D4 百分比只在差距明显时显示 | 第一名比第二名高 ≥5 个百分点才每列写「相对可能性 N%」;否则不写数字,卡上一句「这几个时刻目前区分不开,补一件带年月的经历能帮助分开。」只有一列时两样都不写 | 完成 |
| D5 不做 | 没改打分、淘汰阈值、确认门、45 天闸门 | 遵守 |
| 硬红线 1 离线回放 | 真值在区间内的比例没有下降(±30、±60 各多保住 1 例);区间宽度中位差 1 分钟(±10 窄 1,±30、±60 宽 1);平均提问 11.4 → 7.8 | 字面「不变」未完全满足,数字如实列在下面,请验收方裁决 |
偏离:D1 为什么不改 GUIDED_COLLECT_LIMIT
任务书写「GUIDED_COLLECT_LIMIT 由 6 改为 2」。这个常量在 scripts/rectification/event_probes.py,而该文件属于冻结评分身份(scripts/research/sealed_holdout_rerun.py PRODUCTION_FILES)。实测改这一行后 Python 快速门 4 条失败(tests/test_rectification_validation_integrity_gate.py:frozen_record_mismatch / production_scoring_sha256 不等),且记忆化 golden 也要改。BUG-1047 的防复发写明:改冻结评分文件(即使输出不变)必须在任务书里列出重新冻结验证记录。本任务书没有授权重新冻结,所以:
- 引擎仍按 6 条排好序给窗口;前端题池在同一个校正里只问前两道没问过的窗口,第三道起不再出(新一轮引擎回执带来的新窗口也不会变成第三道)。
- 对用户效果与「上限 2」相同,而且比「每张回执 2 条」更严(原来答完一题后引擎换了候选集,会再冒出新窗口)。
event_probes.py、golden 零改动;验证完整性门禁 4 条保持绿。
若产品仍要引擎侧也改成 2,需要另开一单写明 sealed holdout / reported offset 重新冻结。
离线回放(硬红线 1)
脚本 scripts/research/fewer_probes_card_replay.py,结果 docs/research/fewer_probes_card_replay_2026_09_26.json。
口径与 guided_collect_holdout_2026_09_16.json 同源:同一份 v4 开放集(20 例公开 AA 名人数据)、同样六道辨别题按真值作答、同样把引导窗口事件注入在真值候选自己的边界日期上(truth,理想作答),另跑 opposite(离真值最远的剩余候选的边界)做对照;三档半径 ±10 / ±30 / ±60。直接复用 guided_collect_holdout_replay.py 的 posterior_state、precision_gate、window_boundary_dates、synthetic_event。
与 09-16 脚本的唯一区别:09-16 在第一次达到精度门槛时就停(量「几件能达标」);这里按上线规则比较最终交付区间:
- 改前:引导池问完才出卡(BUG-751),回执里的窗口(上限 6)全部问。
- 改后:一个校正最多问前两道窗口(D1),七条定向线问完就出卡(D2)。
- 七条定向线两边相同,不建模;提问数 = 6 道辨别题 + 问到的引导窗口题。
truth(理想作答)
| 半径 | 六题后:真值在区间内 / 宽度中位 | 改前:真值在区间内 / 宽度中位 / 平均提问 | 改后:真值在区间内 / 宽度中位 / 平均提问 | 区间完全相同的例数 |
|---|---|---|---|---|
| ±10 | 20/20 · 15 | 20/20 · 15 · 11.4 | 20/20 · 14 · 7.8 | 18/20 |
| ±30 | 20/20 · 33 | 19/20 · 33 · 11.4 | 20/20 · 34 · 7.8 | 13/20 |
| ±60 | 20/20 · 56 | 19/20 · 52 · 11.4 | 20/20 · 53 · 7.8 | 14/20 |
opposite(对照)
| 半径 | 改前:真值在区间内 / 宽度中位 / 平均提问 | 改后:真值在区间内 / 宽度中位 / 平均提问 | 区间完全相同 |
|---|---|---|---|
| ±10 | 20/20 · 15 · 11.4 | 20/20 · 15 · 7.8 | 19/20 |
| ±30 | 20/20 · 33 · 11.4 | 20/20 · 34 · 7.8 | 17/20 |
| ±60 | 20/20 · 54 · 11.4 | 20/20 · 53 · 7.8 | 14/20 |
- 平均引导窗口题:改前 5.4 → 改后 1.8(有的例子引擎给不满 6 / 2 条)。
- 精度门槛达标例数两边相同(±10:2/20;±30:1/20;±60:0/20),与 09-16「引导补件新增达标 0 例」一致。
- 120 行里 25 行最终区间不同:改后更窄 6 行、更宽 19 行。
- 改前丢了真值的两例都是多问出来的:±60 一例被收成 13 分钟、±30 一例被收成 5 分钟,真值都落在外面;改后这两例都保住真值(区间 55 / 35 分钟)。也就是说,多问的窗口题有时把区间收窄到错误的位置。
- 与红线的差距:宽度中位差 1 分钟、真值比例只升不降。字面「均不变」不成立,只能说「真值不降、宽度中位 ±1 分钟」。不改代码去凑这个数。
方法局限(继承自 09-16 同口径,未修)
- 窗口年份上限取
today.year,不看月份,所以注入的事件可能落在 2026-09-16 之后(09-16 JSON 里就有2026-10-27这类注入日期)。两边同口径,比较仍成立,但它不是真实用户能报出的事。 - 改前模型只问一张回执里的窗口;真实线上答完一题后引擎会换回执、可能再冒出新窗口,所以改前真实提问数 ≥ 11.4,节省幅度只会更大。
- 七条定向线不建模,提问数只算辨别题 + 引导题。
实现清单
| 文件 | 改动 |
|---|---|
frontend/src/lib/rectification-agentic/v9/collection-question-pool.ts |
新增 GUIDED_WINDOW_CASE_LIMIT = 2,guidedWindowPool 在本校正已问满 2 道窗口时返回空;新增 cardHoldingLinesExhausted(进行中的年月追问 + 跳过线重问 + 七条定向线,不含窗口) |
frontend/src/lib/rectification-agentic/v9/decision-from-dossier.ts |
narrowingExhaustion 的 guidedCollectExhausted 改用 cardHoldingLinesExhausted(仍要求刷新已试) |
frontend/src/lib/rectification-agentic/v9/method-followup.ts |
出卡状态(sessionOutcomeAllowsDelivery)下,计划的收尾补问不再带引导窗口——否则卡出来了,下面还挂着一道「某年某月之间有没有什么事」、「更像这个」被锁。跳过线重问与七条定向线照旧 |
frontend/src/lib/rectification-agentic/core/rectification-decision.ts |
只改注释:mayDeliverOnPrecision 逻辑不变 |
frontend/src/lib/rectification-agentic/user-copy.ts |
RANGE_DELIVERY_PERCENT_MIN_GAP = 5、rangeDeliveryShowsPercents、rangeDeliveryMostLikely、rangeDeliveryIndistinct,并登记到 listUserVisibleCopy |
frontend/src/components/rectification-range-delivery.tsx |
副标题「最可能 HH:MM」;按 D4 显示百分比或那一句 |
frontend/src/app/globals.css |
.rectification-range-delivery__most-likely、.rectification-range-delivery__indistinct |
frontend/DESIGN.md / frontend/docs/VOICE.md |
交付卡一节、出卡时机、D3/D4 文案 |
skills/jyotish-birth-time-rectification/**、versions/10.0.30/、skills/skill-package-registry.json、case-status.ts |
Skill bump 10.0.30(sha256 ade7b748…102c,10.0.29 标 deprecated、快照保留,历史校正按绑定版本打开不受影响——BUG-621) |
scripts/research/fewer_probes_card_replay.py、docs/research/fewer_probes_card_replay_2026_09_26.json |
离线回放 |
Skill 为什么要 bump:原 SKILL.md 写「所有线(含引导窗口题、跳过线重问、未覆盖领域题)问完后……才交付目前范围」,candidate-comparison.md 写「每列写相对可能性」,都与 D2 / D4 相反,不改会让 Agent 读到错误规则。改了三处:SKILL.md 出卡句 + 引导题「一次校正最多两道」;conversation-strategy.md 同步(它还残留 10.0.27 的「出卡须 precision_gate_met」旧句,一并改正);candidate-comparison.md 卡片结构与百分比规则。
测试
前端(Node 22.14.0)
| 项 | 结果 |
|---|---|
tsc --noEmit |
0 错 |
npm run lint |
0 error(126 warnings,均为既有;改动文件无新增 warning) |
npm test |
4012 条 / 24 fail / 27 skip;基线(同代码 origin/staging,Node 22)4002 / 24 / 27 |
| 失败清单对比 | 24 条与基线逐条同名(全部是 Docker / DB 套件),新增失败 0 |
| 测试名单对比 | 消失 0;新增 10(frontend/tests/rectification-fewer-probes-card-20260926.test.ts) |
npm run build -- --webpack |
通过;/ 仍 ○ (Static) |
首屏 gzip(rootMainFiles 4 个文件) |
130933 B,与基线 130933 B 相同(0%) |
新增 10 条测试覆盖:D4 阈值(5 点、顺序无关、单列不显示);D3 标题与副标题;D4 差距 ≥5 显示三列百分比且无那句;差距 <5 无任何数字、只有一句、三列与排序不变;文案登记与 VOICE 一致;D1 每校正 2 道(:next 重问算同一道、进行中的不算、满额后落到定向线);D2 窗口未问不挡卡、跳过线重问与进行中的年月追问仍挡卡;D2 门槛未达也按现行规则出卡、确认门不开;D2 出卡状态(completed_with_range / provisional_range / adopt_representative)的下一问不是引导窗口题,采集状态仍会问。
改动的既有断言(三栏已写在测试文件里)
只有 Skill 版本号:15 个文件里的 RECTIFICATION_SKILL_VERSION / skill_version / 包路径 "10.0.29" → "10.0.30",4 个文件里的 /^version: 10\.0\.29$/ → 10\.0\.30,skill-registry.test.ts 的版本与 sha256。每处上方一行「原值 / 新值 / 原因:D2 出卡句与 D4 卡上百分比规则写进 Skill(2026-09-26)」。没有其他既有断言被改动或弱化。
Python
| 项 | 结果 |
|---|---|
快速门 pytest 集(gate-pytest-args) |
948 passed / 1 skipped,与基线相同 |
tests/test_event_probes_guided_windows.py、tests/test_rectification_engine_memoization.py |
通过(event_probes.py 与 golden 未改) |
截图(真实 Chrome 151 headless,CDP,虚构数据)
组件用 renderToStaticMarkup 渲染、挂 next build 产出的正式 CSS,在真实浏览器里截:docs/testing/rectification-fewer-probes-card-20260926/
| 文件 | 内容 |
|---|---|
gap-wide-1280.png / gap-wide-390.png |
45% / 30% / 25%:副标题「最可能 05:07」,三列都有「相对可能性」 |
gap-narrow-1280.png / gap-narrow-390.png |
35% / 33% / 32%:无任何百分比,卡上一句「这几个时刻目前区分不开……」 |
两种宽度页面 scrollWidth 等于视口(无横向滚动),「更像这个」最小高度 44px。这不是登录态整页走查——完整对话里的出卡时机与文案要真机看,清单见 docs/testing/rectification-fewer-probes-card-20260926.md。
观察(未改,留给产品)
- 差距 <5 时卡上可能同时出现三句「分不开」:说明行里的「这几个候选按现有信息分不开。」(线都问完时)、参考题用过时的「这两分钟按现有信息分不开,参考题已经用过。」和新加的 D4 句。本单按任务书只加 D4 句,没删另外两句。
- 副标题「最可能 HH:MM」在差距 <5 时仍显示(任务书 D3 无条件)。它和「目前区分不开」并存,读起来略拧;边界句「这只是代表性候选……」仍在卡底。
- 送卡时若本校正还没问满 2 道引导窗口,交付旁白末尾仍会写「现在还剩 …… 再对照几件经历会更准」,这是邀请用户自己补,不是系统还会追问。
- 候选已经明显分开(
separation.sufficient)那条老路径不经过精度门槛,采集计划里若还有引导窗口题(本校正不足 2 道时)仍会先问——这不是「为门槛追问」,且受每校正 2 道上限约束,本单未改。
环境缺口
- 无 Docker:24 条 DB / 部署套件与基线同样失败,已逐条比对。
- 无登录态与模型凭据:真实对话里的出卡时机、Agent 旁白是否遵守新 Skill 句,留待部署后按
docs/testing/清单真机走查。 - 未推送、未部署。
验收(Claude,2026-09-26)
基于 origin/staging 7ddce2c9 rebase 后独立复跑(Node 22.14):
| 项 | 结果 |
|---|---|
tsc --noEmit |
0 错 |
npm run lint |
0 error(126 warning,均为既有) |
npm test |
4012 / 24 fail / 27 skip;失败名单与基线 test15.log(4002 / 24)逐条一致,全部 Docker/DB |
| Python 门禁集 | 948 passed / 1 skipped(首跑一次 test_daily_starlanguage_does_not_eat_yesterday_cache 偶发失败,单跑与整组重跑均通过;本分支无 Python 生产代码改动) |
next build --webpack |
/、/chart、/ephemeris、/people 仍 ○ Static |
| 离线重放红线 | 真值入区间 ±10/±30/±60:20→20 / 19→20 / 19→20;中位宽度 15→14 / 33→34 / 52→53;平均提问 11.4→7.8。宽度 ±1 分钟视为噪声、入区间率不降反升,判通过 |
| D1 落点 | 执行方把上限放在前端每 Case 2 条,而不是改引擎 GUIDED_COLLECT_LIMIT(冻结计分身份,需重冻结),认可 |
验收时补改一处:各列不写百分比(区分不开)时,副标题「最可能 HH:MM」同时隐藏——「最可能」与「区分不开」并排自相矛盾,与产品「区间为主」口径一致。同步改 DESIGN / VOICE / CHANGELOG / 真机清单与 Skill candidate-comparison.md(10.0.30 未发布,快照同改,包哈希 926db1ab…3a13 → ade7b748…102c)。定向复跑 rectification* + skill* 1490 条 0 fail,tsc 0。
遗留给产品:区间 < 5 分差时卡上可能同时出现范围说明、平局句与「区分不开」句;截图见同目录,真机时看是否嫌重复。