fix(rectification): 有题就接着问,题问完才出卡;引导窗口不再硬贴领域
出卡时机只看题源有没有空:撤回「门槛达标就短路采集线」的写法,同时 按 D2 保住「题源全空就按现行规则出卡」——门槛只在还有题可问时挡住 出卡,precision_gate_met 改成只上报(新挂在决策与公开投影上),不再 单独决定时机。引导窗口题在无领域轨道上改问开放题,一个时间窗只问一 次;录入卡提交的是「YYYY 年 M 月,<领域>方面有一件事」,不再是题干 的三选一列表。记忆化 golden 只补一个新键并冻结墙钟。离线回放改成注 入真值方向的边界事件,另跑一组反方向对照。Skill 10.0.28。 BUG-747~752 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
a396bbe076
commit
dc732825d8
@@ -0,0 +1,187 @@
|
||||
# 进度 · 出卡精度门槛 + 引导式补经历(验收修复单,2026-09-16)
|
||||
|
||||
- 任务书:`docs/tasks/TASK-rectification-precision-gate-guided-collect-fix-20260916.md`(F1~F7 + 决策 D6)
|
||||
- 基线:`origin/staging` @ **`a396bbe0`**(第二轮已 rebase;上一版基线 `302ff085`,代码基线 `cfb41daf`)
|
||||
- 分支 / 工作树:`codex/rectification-precision-gate-guided-collect-fix-20260916` / `.worktrees/rectification-precision-gate-guided-collect-fix-20260916`
|
||||
- BUG:**747~752**。开工时最大号是 743;实现期间另一会话把侧栏统一那一单合入 staging,占掉了 744~746,所以本单整体后移到 747 起。rebase 后 `docs/BUG_HISTORY.md` 里 743 → 744 → … → 752 连续。
|
||||
- 开工检索(AGENTS §5):BUG-733、654、656、740~743 已逐条读完;BUG-733 的防复发条本轮补了一句(见下)。
|
||||
|
||||
## 0. rebase 到 `a396bbe0`
|
||||
|
||||
第二轮已 `git rebase origin/staging`(侧栏统一那 4 笔:`d9d34723`、`fb77c865`、`22edabbc`、`a396bbe0`)。
|
||||
|
||||
- **自动合并**:`frontend/DESIGN.md`、`frontend/src/app/page.tsx`。page.tsx 以对方的结构为准,只保留本单那一处 `rectificationDeclaration` 合并(`declaredTime` + `birthDate` 一个对象展开)。
|
||||
- **手工解冲突 3 个**,都在文档、都是「两侧各自追加」:
|
||||
- `CHANGELOG.md`:两条都保留,本单那条在上(后写的在前)。
|
||||
- `docs/BUG_HISTORY.md`:以 staging 版本为底,重新插入本单对 BUG-733 的那一行补注,再把本单的 BUG-747~752 整块追加到 BUG-746 之后。结果 `## BUG-` 共 739 条,末尾 743 → 744 → … → 752 连续。
|
||||
- `docs/tasks/README.md`:侧栏单那一行取对方的(已验收状态),本单那一行取自己的;两行都在。
|
||||
- BUG 编号 **747~752 不变**(744~746 已被侧栏轮占用)。
|
||||
|
||||
## 0.1 结论先行(全部在 `a396bbe0` 上重测;基线也在 `a396bbe0` 上用一次性 worktree 重跑)
|
||||
|
||||
| 项 | 基线 `a396bbe0` | 本分支 |
|
||||
| --- | --- | --- |
|
||||
| `tsc --noEmit` | 0 错 | **0 错** |
|
||||
| `npm run lint` | 0 error / 115 warning | **0 error / 115 warning** |
|
||||
| `npm test` | 3399 条 / **47 红** | **3405 条 / 31 红**;31 红与基线逐条同名,**0 条新红**,基线 47 红里的 16 条全部转绿 |
|
||||
| `pytest tests/test_rectification_*.py tests/test_event_probes_guided_windows.py` | — | **193 passed** |
|
||||
| `next build --webpack` | `○ /` | **`○ /`**(`/chart`、`/ephemeris` 也仍是 Static) |
|
||||
| 首屏 gzip | 583,765 | **582,800**(−965 B,**−0.17 %**) |
|
||||
| `frontend/src/app/page.tsx` | 1836 行 | **1835 行**(−1,未增长) |
|
||||
| Skill | 10.0.27 | **10.0.28**,sha256 `f0bb8295…cffe` |
|
||||
|
||||
## 1. F1 · 记忆化 golden(BUG-747)
|
||||
|
||||
- `tests/golden/rectification_engine_memoization_v1.json` 只追加 `guided_collect_windows` 一个键。`git diff --stat` = **`1 file changed, 62 insertions(+)`**,`git diff` 里只有一段 `+ "guided_collect_windows": [ … ]`,插在 `discriminating_event_probes` 之后(与 live receipt 的键序一致),CRLF 行尾保持不变。**没有删除或修改任何既有行。**
|
||||
- 未放宽 `_assert_tiered_equal`(键集合仍是严格相等),未调用 `write_golden()`。
|
||||
- 顺带修了一个同族隐患:`_golden_payload()` 现在把 `scripts.rectification.event_probes` 的 `date` 换成 `_FrozenDate`(`today() == FROZEN_TODAY = 2026-09-16`)。窗口年份来自 `date.today()`,不冻结的话这份 golden 会在跨年时自己变红。冻结后生成的值与本机实跑一致,所以 golden 内容没有因此改变。
|
||||
- `docs/BUG_HISTORY.md` 的 BUG-733 条目补了一行「2026-09-16 因 receipt 新增键重生成,diff 仅此一键」。
|
||||
|
||||
## 2. F2 + F3 · 断言处置清单(BUG-748 / BUG-751)
|
||||
|
||||
先按 F3 改代码,再逐条看断言。**没有删任何测试,没有 skip 任何测试。**
|
||||
|
||||
### 2.1 代码改动(F3 + D6)
|
||||
|
||||
`core/rectification-decision.ts`
|
||||
|
||||
```
|
||||
mayDeliverOnPrecision(input):
|
||||
userStopped === true → true
|
||||
precisionGateMet 与 guidedCollectExhausted 都缺省 → true(门槛不参与,helper 路径回到 317e9f18)
|
||||
否则 guidedCollectExhausted === true
|
||||
&& refreshExhausted !== false
|
||||
&& targetedCollectExhausted !== false (= 所有题源都问完)
|
||||
```
|
||||
|
||||
**口径(D2 + D6,第二轮修正)**:门槛只在**还有题可问时**挡住出卡。题源全空就是 D2 说的「用户确实补不出来」,卡片、采用按钮、三句正文照现行规则给,不加「未达门槛」标注。
|
||||
写全是 `userStopped || allExhausted || (precisionGateMet && allExhausted)`,化简后就是 `userStopped || allExhausted`。
|
||||
**按 D2 + D6,10 分钟门槛不改变出卡时机,本轮实际生效的是题源变多(引导窗口题 + 跳过线重问 + 七条线全部轮到)、线问完才出。**
|
||||
`precisionGateMet` 保留计算,并新挂到 `RectificationDecision.precisionGateMet` 与 `publicNextAction().precision_gate_met`(helper 路径不传 flag 时为 `null`),只上报、不决定时机。
|
||||
|
||||
撤回的三处短路(全部回到原判断):
|
||||
|
||||
1. `coverageBlocks` 分支的 `const narrowingOpen = stillNeedNarrowing(input) && !mayDeliverOnPrecision(input)`
|
||||
2. `!separation.sufficient` 分支的 `if (stillNeedNarrowing(input) && !mayDeliverOnPrecision(input))`
|
||||
3. `if (input.datedMethodCollectOpen === true && !input.userStopped && !mayDeliverOnPrecision(input))`
|
||||
|
||||
保留门槛的五个最终交付分支:`tied_first` 耗尽、`!sufficient` 的 exhausted / adopt_representative / offer、顶层 exhausted。
|
||||
|
||||
`v9/decision-from-dossier.ts` 的 `narrowingExhaustion`:`guidedCollectExhausted` 改为 `refreshDone && guidedCollectExhausted(...)`,即引导池空但刷新没试过不算问完。
|
||||
|
||||
新增三条单测(`rectification-precision-gate-20260916.test.ts`):
|
||||
|
||||
| 单测 | 断言 |
|
||||
| --- | --- |
|
||||
| `empty guided pool with refresh untried does not deliver` | `refreshExhausted: false` + 池空 + 门槛达标 → `ask_fact_collection`、`canOfferRange=false`;`mayDeliverOnPrecision` 直接返回 false |
|
||||
| `gate met but the targeted line is still open keeps asking` | `precisionGateMet: true` + `targetedCollectExhausted: false` → `ask_fact_collection` |
|
||||
| `every line asked but the gate unmet still delivers under the existing rules` | 池空 + 门槛未达 → `canOfferRange=true`、`sessionOutcomeAllowsDelivery=true`,且 `precisionGateMet` 仍报 `false`(D2:题源空了就按现行规则出卡,不加标注) |
|
||||
| `the precision gate is reported on a collect exit too` | 采集出口上 `decision.precisionGateMet === false`、`publicNextAction().precision_gate_met === false`;helper 路径(不传 flag)为 `null` |
|
||||
|
||||
### 2.2 十六条基线红(任务书 §2 F2 表)
|
||||
|
||||
| # | 文件 :: 用例 | 处置 |
|
||||
| --- | --- | --- |
|
||||
| 1 | `adopt-flow-fix-20260903` :: collect-phase nonterminal exit… | **改断言(三栏)**:`adopt_representative/offer_provisional_range/publicCanAdopt=true` → `collect_evidence/ask_fact_collection/false`;随之 `repaired.persisted` false→true、repair 警告 false→true、`store.focus` null→非空。D1(13 分钟、14:13:13 并列)+ D6,本用例回到 BUG-648 之前的采集出口,与题名一致 |
|
||||
| 2 | `adopt-flow-fix-20260903` :: skipped opening collect other still yields education… | **改断言(三栏)**:`plan.next_followup = null` → 学业线 `collect:targeted:education`;下半段 `educationPlan.next_followup.domain` `horary` → `education`。D5 七条线全部轮到,题名要的「yields education」正是这一条 |
|
||||
| 3 | `adopt-narration-20260904` :: fourteen-probe case decides offer_provisional_range… | **仅改代码即恢复绿**(F3 撤回短路后 helper 路径回到原语义),断言未动 |
|
||||
| 4 | `adopt-narration-20260904` :: family collect declined vs extra distinguish declined… | **改断言(三栏)**:`/搬家|换城市|还能把剩下的候选分开/` → 两侧都匹配 `/现在还剩 .+ 里 \d+ 个候选/`。D5 之后迁居已覆盖,剩下的线是财务与健康;题名要的「两侧同一个 adopt 决策、都落库」不变 |
|
||||
| 5 | `answer-choice` :: answering the last discriminator persists a year-locked family collect focus… | **改断言(三栏)**:`setFocus === undefined` → 写入 `collect:targeted:education`;末条「没有 focus 带 `p_asked_turn_id === TURN_ID`」改成「写入的 focus 只能是这道新问题」——`linkFocusAskedTurn` 把新问题挂到本轮刚追加的 assistant turn,而夹具让这个 id 恰好等于 `TURN_ID`,旧断言在这个夹具里已无法区分两者 |
|
||||
| 6 | `choice-card` :: family coverage without a renderable discriminator still collects the next dated domain | **改断言(三栏)**:`plan.next_followup = null` → 迁居线 `collect:targeted:relocation`。题名要的「still collects the next dated domain」正是这一条 |
|
||||
| 7 | `collect-direction-20260904` :: holdout remaining domain uses the server collect stem… | **改断言(三栏)**:`choice_frame === null` → `choice_kind === "existence"`;`USER_COLLECT_QUESTION.education` → `TARGETED_EXISTENCE_PROMPT.education`,另加一条「不得是反向核对口吻」的断言,保住题名的原意 |
|
||||
| 8 | `collect-direction-20260904` :: four scoreable events stop dated collect… | **改断言(三栏)**:`intent != collect_method_evidence` → `== collect_method_evidence` 且 `collection_key` 必须是 `collect:(targeted|guided):`(走定向七条线,不是旧的领域轮盘) |
|
||||
| 9 | `collect-direction-20260904` :: separated candidates stop leftover dated collect once the training gate is open | **改断言(三栏)**:`sessionOutcome != collect_evidence` → `== collect_evidence`、`nextAction = ask_fact_collection`、`userAction.id = ask_method_followup` |
|
||||
| 10 | `convergence-budget` :: dossier and post-inference decisions share the half-uncertain stop rule | **改断言(三栏)**:`stopReason = "probe_pool_exhausted"` → `null`,并显式断言两条路径的 `stopReason` 与 `nextAction` 一致(题名要的「share the rule」) |
|
||||
| 11 | `decide-next-action` :: separated candidates stay in collect while dated method collect is still open | **仅改代码即恢复绿**,断言未动 |
|
||||
| 12 | `delivery-vs-collect-20260914` :: POST idle persist and GET decideFromDossier agree on a first-place tie | **改断言(三栏)**:`getDelivers = true` → `false`(D1 并列时门槛恒假);「POST 与 GET 同口径」那条不变 |
|
||||
| 13 | `superseded-focus` :: duplicate_focus on the last collect ask does not emit delivery copy | **改断言(三栏)**:`p_target_domain != relationship` → 改断言写入的是 `collect:(targeted|guided):` 问题(夹具本身叫 `relationshipOpenDossier`,这条线是开着的);`!= finance` 与「不得播交付文案」保留 |
|
||||
| 14 | `targeted-collect-cards-20260913` :: A resolves existence then asks the year; B/C close only that line | **改断言(三栏)**:题干 `结过婚或订过婚吗?` → `TARGETED_EXISTENCE_PROMPT.relationship`(T4b 问整个领域);`targetedCollectExhausted` 从「拒答 4 条即耗尽」改成「4 条 → false、七条 → true」 |
|
||||
| 15 | `targeted-collect-cards-20260913` :: personality D9/D10 stay out of the scoring pool… | **改断言(三栏)**:`narrow_hint` 含 `不限领域` → 不得含 `不限领域`,改为匹配引导句 `现在还剩 … 里 N 个候选`(D3 删自由文本邀请) |
|
||||
| 16 | `tied-first-fix-20260914` :: tied first place with no probe still collects while targeted questions remain | **仅改代码即恢复绿**,断言未动(这正是 F3 说的 BUG-654 规则回来了) |
|
||||
|
||||
### 2.3 D5/D6 连锁打红的另外 25 条(任务书未列,本轮一并处置)
|
||||
|
||||
撤回 `datedMethodCollectOpen` / `stillNeedNarrowing` 两处短路之后,cfb41daf 的 T4b(`remainingTargetedDomains` 不再按分盘层剔除,七个 `CollectKind` 全部轮到)就重新挡住了交付——这是 D5 + D6 的**预期**结果,但 cfb41daf 用短路把它盖住了,所以这 25 条在基线上是绿的。全部按「原值 / 新值 / 原因」三栏改:
|
||||
|
||||
| 文件 | 条数 | 处置摘要 |
|
||||
| --- | ---: | --- |
|
||||
| `coverage-collect` | 4 | `offer_provisional_range` / `ready_to_adopt` → `ask_fact_collection` + `collect_evidence`;`canAdopt` 仍是引擎能力位,保持 true |
|
||||
| `provisional-adopt` | 6 | 公开投影 `can_adopt` / `session_outcome` 翻到采集侧;`canRenderRectificationSelectionCards` true→false;`buildNextUserAction` `adopt_representative`→`ask_method_followup`;`selectionAllowed` true→false |
|
||||
| `range-offer-deadend` | 2 | `ready_to_adopt`→`ask_fact_collection`、`decision.canAdopt` true→false(零拆分探针被 drop 的断言保留) |
|
||||
| `eight-method` | 1 | `rectification-offer-candidates` 由「可走」改为 `assert.rejects(/offer_not_allowed/)` |
|
||||
| `collect-direction-20260904` | 1 | 同上(offer-candidates 仍被挡) |
|
||||
| `exhaustion-exit-20260906` | 1 | `adopt_representative`→`collect_evidence`、`stopReason`→null、旁白由三句交付改为引导句 |
|
||||
| `occupation-coverage-exit` | 1 | `canOfferRange` true→false、`collect_evidence` / `ask_fact_collection` |
|
||||
| `holdout-renderable` | 1 | `offer/ready` → `ask_fact_collection`,`validated_range` 断言保留 |
|
||||
| `collect-stall` | 1 | 只改夹具:补齐 education / career / relationship 三条拒答(D5 之后七条线都要轮到),断言全部保持原样(`publicCanAdopt=true`、`persisted=false`、不写 focus) |
|
||||
| `adopt-flow-fix-20260903` | 1 | `adopt_representative nonterminal exit…`:第二轮修正口径后无需改动,夹具与断言均恢复原样 |
|
||||
| `answer-choice` | 1 | `last structured choice…`:`ready_to_adopt` / `can_adopt=true` → `ask_fact_collection` / false(这条的原因是 D5 的线没问完,不是门槛) |
|
||||
| `decision-authority` | 1 | 公开字段深比较补 `precision_gate_met`(BUG-692 要求不得改成部分匹配,所以补字段而不是放宽比较) |
|
||||
| `probe-pool-exhausted-20260911` | 1 | T3 第二轮修正后恢复原样;T4 只把末条旁白正则补上引导句(`persistNextInterviewIfIdle` 自己重算决策,写的是采集侧区间旁白) |
|
||||
| `open-collect-invite-20260914` | 0 | 第二轮修正口径后恢复原样,无改动 |
|
||||
| `surface-contract` | 1 | `declaredTime={rectificationDeclaredTime}` → `{...rectificationDeclaration}`(F7) |
|
||||
| `ingest-p0` / `delivery-report-facts` / `tie-break-entry-20260913` / `v9-contracts` | 4 | Skill 版本 10.0.27 → 10.0.28 |
|
||||
|
||||
另有 10 个文件只是 `RECTIFICATION_SKILL_VERSION` 常量断言随 bump 改数字(`collect-stall`、`confirmation-gate`、`delivery-report-facts`、`eight-method`、`exhaustion-exit`、`ingest-p0`、`occupation-coverage-exit`、`range-offer-deadend`、`replay-20260911`、`spoken-collect`、`v9-agent`、`v9-contracts`、`v9-entry-routing`、`window-cluster-cap`、`yearless-probe-downgrade`、`skill-registry`),每处都带一行三栏注释。
|
||||
|
||||
### 2.4 最终红清单
|
||||
|
||||
`npm test` fail=31,与基线 31 条**逐条同名**:无 Docker 的 database / deployment / staging 套件,以及 `[eval]` 路径别名那一组。
|
||||
测试总数 3399 → **3405**(+6,全部是新增;**没有删除、没有 skip**):精度门槛 5 条(引导池空但刷新未试不交付、门槛达标但定向线未问完继续问、题源全空即使门槛未达也照现行规则出卡、采集出口也上报门槛、helper 路径上报 null)+ F4 的 3 条 + F6 的 1 条,其中 2 条是把既有用例改写后新增的姊妹条。
|
||||
|
||||
## 3. F4 · 无领域轨道的窗口改成开放题(BUG-749)
|
||||
|
||||
- `scripts/rectification/event_probes.py`:删掉 `fallback[unlayered_index % len(fallback)]` 轮询;`vim` / `nara` 轨道的窗口 `domain = GUIDED_ANY_DOMAIN = "any"`;`nara:d9` / `nara:d10` 保持 `relationship` / `career`,该领域被拒答时也退回 `"any"`。`declined_domains` 现在只用于剔除例子与 d9/d10 的固定领域。
|
||||
- 前端:`GUIDED_ANY_DOMAIN` / `GuidedWindowDomain` / `normalizeGuidedWindowDomain` / `guidedAnyExamples` / `firstOpenCollectKind`;`guidedWindowPrompt(window, openDomains)` 对 `any` 写「YYYY 年 M 到 M 月之间,有没有什么事,比如<口语 ≤3 个>?」,口语从 `KIND_ORAL` 表取、剔除 declined 与已覆盖,**没有按领域写 if**;全部领域都关掉时退化成「有没有什么事?」。`windowAlreadyAsked` 改成只比对(年, month_lo, month_hi),换个领域标签不重问。A 之后 `pendingGuidedYearWindow` 把 `any` 解析成第一个仍开放的领域,录入卡芯片默认落在它上面(`resolveEntryDomain` 另有防御)。
|
||||
- 单测:Python 7 条(真实引擎 20 分钟窗 golden 非空、无领域轨道 = `any`、d9/d10 保留固定领域、拒答领域退回 `any`、split 均衡排序、跨年拆分);前端 3 条(开放题干口语 ≤3、同一窗口只问一次、芯片默认第一开放领域)。
|
||||
|
||||
## 4. F5 · 离线回放改成注入真值方向(BUG-752)
|
||||
|
||||
`scripts/research/guided_collect_holdout_replay.py` 新增 `window_boundary_dates()`:按 `guided_collect_windows` 自己的循环重算(轨道, index),拿回**每个候选**在该窗口上的边界日期。`truth` 组注入真值候选自己的那个月,`opposite` 组注入「剩余候选里离真值最远的那一个」的同一边界。三档半径都跑,`minute_rectification_holdout_v4.json` 20 例,**351.6 s,错误 0**,未用让步(没有只跑 ±10/±30)。
|
||||
|
||||
| 半径 | 方向 | 20 例达标 | 其中六题后本来就达标 | **靠引导件补上** | 达标件数中位 | 每例窗口数中位 |
|
||||
| --- | --- | ---: | ---: | ---: | ---: | ---: |
|
||||
| ±10 | truth | 3 | 3 | **0** | 0 | 6 |
|
||||
| ±10 | opposite | 3 | 3 | **0** | 0 | 6 |
|
||||
| ±30 | truth | 1 | 1 | **0** | 0 | 6 |
|
||||
| ±30 | opposite | 1 | 1 | **0** | 0 | 6 |
|
||||
| ±60 | truth | 0 | 0 | **0** | — | 6 |
|
||||
| ±60 | opposite | 0 | 0 | **0** | — | 6 |
|
||||
|
||||
原始表 `docs/research/guided_collect_holdout_2026_09_16.json`(含每例的 `injected`,形如 `19:24:2026-05-08`,可核对注入确实落在不同候选的边界上)。
|
||||
|
||||
口径说明与观察:
|
||||
|
||||
- 上一轮「0/20」的写法**不成立**(注入的是窗口左端点),这一轮按真值边界注入之后**结论仍然一样**:没有一例是「六题后未达、补引导件后达标」。这次的数字可以作数。
|
||||
- truth 与 opposite 两组数字完全相同,说明在这个 holdout 上,把事件放在真值的边界还是放在最远候选的边界,对 D1 门槛没有可测差别。
|
||||
- 每例都有 6 个窗口(上限就是 6),所以不是「题不够」。
|
||||
- 窗口年份集中在 2025–2026:排序先按 split 均衡、再按靠近今天,`lo = 出生年 + 5`、`hi = min(今年, 出生年+80)`。真人补经历时这几年确实最容易记得,但对名人 holdout 来说这些年份多半没有可用事件。
|
||||
- **这不是合入门槛**,产品据此决定 10 分钟门槛是否要调,或者引导题源是否还要换一条路。
|
||||
|
||||
## 5. F6 · 录入卡提交文本(BUG-750)
|
||||
|
||||
`formatEventDateEntryMessage` → 「YYYY 年 M 月(D 日),<领域标签>方面有一件事」,标签取 `RANGE_DELIVERY_DOMAIN_LABEL`。单测断言两种日期形态与「不含『或』」。**没有**改成 `set-focus` / `batch` 的结构化写入(任务书给的是「或」二选一),走的仍是现有带年月证据路径。
|
||||
|
||||
## 6. F7 · page.tsx 与 golden fixture
|
||||
|
||||
- `page.tsx` **1838 → 1837**:`rectificationDeclaredTime` 常量改成 `rectificationDeclaration = { declaredTime, birthDate }`,JSX 里两行 prop 合成一行 `{...rectificationDeclaration}`。
|
||||
**偏离**:任务书写的是「把那一行挪进 `conversational-birth-time-rectification.tsx` 内部取档案」。做不到而且不划算——该组件没有档案来源:`RectificationCaseSnapshotPayload` 的 `case` 段只有 `status / accepted_time / confirmed_time / candidate_range / stage / birth_time_source`,**没有 birth_date**;要在组件里拿档案得新开一次 `/api/account` 读取或改服务端合同,为了省一行代码多一次网络请求并不合算。行数目标已达成,记在这里由验收方判断。
|
||||
- `tests/test_event_probes_guided_windows.py` 重写:新增 `_real_built()`,用 `build_candidate_static_context` 对公开 1990-01-01 北京测试盘的 12:00–12:20(**20 分钟窗**,5 个采样分钟)跑真实引擎,断言窗口非空并逐字段校验;`test_declined_domains_are_removed` 改成 `test_declined_domains_fall_back_to_open_windows`,用真实引擎结果做,**`skipTest` 全部删除**(文件里已无 `skipTest`)。手造 static contexts 只留在排序与跨年两条纯结构断言里。
|
||||
|
||||
## 7. 记录
|
||||
|
||||
- `docs/BUG_HISTORY.md`:BUG-747~752(本分支内连续;744~746 属侧栏统一单,见 §0),BUG-733 补一行。
|
||||
- `CHANGELOG.md`:2026-09-16 「问完所有线才出卡,时间窗不再硬贴一个领域」,写明 Skill 10.0.28。
|
||||
- `frontend/DESIGN.md`:`guided-collect` 行改写(开放窗口题干、一窗一问、录入卡提交文本),`candidates` 行写明门槛是必要条件而非充分条件。
|
||||
- `frontend/docs/VOICE.md`:新增两行(开放窗口题干、录入卡提交文本),已对照既有口径。
|
||||
- `docs/tasks/README.md`:本单状态板改「已实现,待验收」+ 分支名 + 进度记录名。
|
||||
- 真机清单沿用 `docs/testing/rectification-guided-collect-20260916.md`(六条),本轮没有新增浏览器级验收项。
|
||||
- 未写入任何真实出生资料;示例只用公开名人 holdout 与 1990-01-01 测试盘。
|
||||
|
||||
## 8. 偏离与未做
|
||||
|
||||
1. **F7 的 `birthDate` 没有挪进组件内部**(理由见 §6),改用 props 合并把 page.tsx 降回 1837 行。
|
||||
2. **(第一轮偏离,已修正)** 第一轮按修复单 F3 §2 的字面实现了「门槛未达即使线问完也只进 collect」,与主单 D2「引导题源也空了就按现行规则出卡」冲突,会造出「没有题也没有卡」的死角。产品第二轮拍板以 D2 为准:门槛只在还有题可问时挡出卡,题源全空照现行规则出卡。当前实现是修正后的版本,本记录各处数字也是修正后重测的。
|
||||
3. **F2 实际处置 41 条而非 16 条**:任务书的 16 条表是在 cfb41daf 上数的,那一版用 `!mayDeliverOnPrecision` 短路盖住了 D5 带来的「七条线全部轮到」,撤回短路后另有 25 条既有断言跟着变。全部按三栏改,清单见 §2.3。
|
||||
4. `run_quality_gate.py --profile quick` 的最后一级是 `npm test`,本机无 Docker,那 31 条与基线同名的失败照旧;前面各级(JSON、capabilities、fragments、BPHS、CORE_PYTEST_TARGETS)通过。
|
||||
5. 浏览器级验收(登录态 / Chrome)、staging 部署核对仍是环境缺口,留给 `docs/testing/rectification-guided-collect-20260916.md`。
|
||||
@@ -253,7 +253,7 @@
|
||||
| `RECONCILE-20260916.md` | — | **对账清单(不是任务书)**:状态板与现实脱节(09-15~16 那 10 份早已合入却仍写「待领取/待验收」,本轮已修正),所以另外 7 份 09-10~14 的单**不能拿 README 当证据**——它们没有 `PROGRESS-*.md`,但引用的 BUG 号都是 `resolved`。要么被别的单顺带修了没留记录,要么压根没做。每行回一个「做了/没做」即可。另附三条我已查到确定没做的证据、两条状态未闭环的、以及 BLK-001 仍红(2026-09-16 在 `4f643aa0` 复跑确认) | 待产品负责人 / 执行方回填 | — |
|
||||
| `TASK-rectification-precision-gate-guided-collect-20260916.md` | `PROGRESS-rectification-precision-gate-guided-collect-20260916.md` | **出卡加精度门槛 + 引导式补经历**:真机 30 分钟窗给 5 件事 / 3 领域就出卡,区间 20 分钟、5 候选并列 26/26/20%,卡下只有自由文本邀请。产品拍板 D1 出卡门槛「宽度 ≤10 分钟且前两名差 >3 个百分点且不并列」;D2 用户说没有了仍按现行规则出卡(保留永远给结果);D3 门槛未达改为系统点名逐题问 + 类型芯片 + 年/月选择器录入,删自由文本邀请;D4 跳过的线换问法再问一次(拒绝不重问,改 BUG-687 口径);D5 时间点题答「没发生」不关领域、存在性题问整个领域、七条线一张表不许按领域写死。引擎新增 `guided_collect_windows`(边界不设 45 天闸门、含小运),不改打分与 lead。Skill 10.0.27。附 T6 两条核实:B/C/D 回执文案对调、性格题后范围回弹 8 分钟。BUG-740~743 | **已验收:未通过(带修复单)** | `cfb41daf`;tsc/lint/Static/gzip(+0.44%) 通过,D1~D5 单测通过;但 `npm test` 新增 16 红(校正既有断言未跟上)+ memoization golden 因 receipt 新键红(门禁级,staging 仍部署 317e9f18);引导窗口领域轮询分配、回放未按真值注入、录入卡走模型轮 → `TASK-rectification-precision-gate-guided-collect-fix-20260916.md` |
|
||||
| `TASK-sidebar-unify-20260916.md` | `PROGRESS-sidebar-unify-20260916.md` | **侧栏统一成一个组件 + 次级页共享外壳 + 跳转不整页刷新(纯前端)**:`/` 用 `AppSidebar`、四个次级页用另写的 `AppNavRail`,两套标记结构共用一份 CSS,会话行少 `.session-main` 一层(无内边距 / 44px 高 / 当前项标记、留 44px 空列)、页脚 56px 菜单 vs 44px 文字;首页进次级页是 `window.location.assign` 整页刷新,次级页各自在组件里挂 `SecondaryShell`、无共享 layout 无缓存,每次跳转重拉 `/api/sessions` + `/api/account`;折叠状态不持久。产品拍板 D1 只留一个 `AppSidebar`(操作回调可选 = 只读模式,D9「不带写操作」维持)、D2 路由组 `app/(secondary)/` layout 承载外壳、D3 改 `<Link>`、D4 模块级 60 s 缓存 + 首页写操作失效、D5 折叠状态存 cookie、D6 回首页慢的启动链另开一单。实测:接口 TTFB 0.63~0.90 s,回 `/` 启动链串行 ≥4 次往返 + 揭幕闸门 4 s。BUG-744~746 | 已验收(2026-09-16,Opus 子代理实现 `22edabbc`,门禁全绿、失败清单与基线逐条相同;折叠状态取 localStorage 触发让步 1;真机清单待走) | `codex/sidebar-unify-20260916` |
|
||||
| `TASK-rectification-precision-gate-guided-collect-fix-20260916.md` | — | **验收修复单**:F1 `decision_receipt` 新增 `guided_collect_windows` 让 `test_rectification_engine_memoization` golden 红(在 CORE_PYTEST_TARGETS,staging 未部署 cfb41daf);F2 16 条既有校正断言红未按三栏改;F3 `mayDeliverOnPrecision` 缺省即放行、短路 BUG-654 且 `guidedCollectExhausted` 不含 refresh;F4 无领域轨道窗口轮询贴领域、一窗只问一领域;F5 离线回放注入 month_lo 非真值方向、0/20 不作数;F6 录入卡合成「或」列表句走模型轮;F7 page.tsx +1、手造 fixture。D6 产品已拍板:门槛只是必要条件,仍问完线再出。BUG 段 744 起 | 待领取 | 与主单同文件;开工基线 3391 / 47 |
|
||||
| `TASK-rectification-precision-gate-guided-collect-fix-20260916.md` | `PROGRESS-rectification-precision-gate-guided-collect-fix-20260916.md` | **验收修复单**:F1 `decision_receipt` 新增 `guided_collect_windows` 让 `test_rectification_engine_memoization` golden 红(在 CORE_PYTEST_TARGETS,staging 未部署 cfb41daf);F2 16 条既有校正断言红未按三栏改;F3 `mayDeliverOnPrecision` 缺省即放行、短路 BUG-654 且 `guidedCollectExhausted` 不含 refresh;F4 无领域轨道窗口轮询贴领域、一窗只问一领域;F5 离线回放注入 month_lo 非真值方向、0/20 不作数;F6 录入卡合成「或」列表句走模型轮;F7 page.tsx +1、手造 fixture。D6 产品已拍板:门槛只是必要条件,仍问完线再出。BUG 段 744 起 | **已实现,待验收** | `codex/rectification-precision-gate-guided-collect-fix-20260916`;进度记录 `PROGRESS-rectification-precision-gate-guided-collect-fix-20260916.md`;BUG-747~752;Skill 10.0.28;已 rebase 到 `a396bbe0`;`npm test` 3405 / 31 红(基线 `a396bbe0` 实测 3399 / 47,红清单逐条同名、0 条新红),`pytest tests/test_rectification_*.py tests/test_event_probes_guided_windows.py` 193 passed;首屏 gzip 583,765 → 582,800(−0.17%),`page.tsx` 1836 → 1835 |
|
||||
|
||||
## 命名与归档
|
||||
|
||||
|
||||
Reference in New Issue
Block a user