Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
7.1 KiB
7.1 KiB
TASK · 领域命名审计:health / health_pressure 与 occupation / other 两组别名在十处比较里各走各的,统一成一处归并(2026-09-09)
- 基线:
origin/staging@4067aff8 - 分支:
codex/rectification-domain-alias-audit-20260909,基于origin/staging;与codex/rectification-skipped-health-deadend-20260909(BUG-626/627)串行——本单包含它的决策 1,若它先合入则本单只补其余站点 - 执行方:coding agent;验收:Claude
- 涉及文件:
frontend/src/lib/rectification-agentic/v9/method-followup.ts、core/candidate-contrast-packet.ts、v9/server-focus.ts、scripts/rectification/event_probes.py、scripts/rectification/refinement_packet.py、scripts/rectification/contracts.py - BUG 编号起点:BUG-628(
docs/BUG_HISTORY.md当前最大 BUG-627) - 优先级:P1(产品追问"其他领域会不会出现同样的问题":健康线还有六处同类漏洞;职业线一处;其余五个领域全线一致,无问题)
1. 审计结论
三套词汇并存:
| 层 | 健康 | 职业 |
|---|---|---|
证据账本(EVIDENCE_DOMAINS、引擎事件、contracts.py) |
health(health_pressure 仅作 v1 兼容) |
occupation |
焦点 / 拒答记录(DB target_domain 约束,persistableFocusDomain) |
health |
other |
| 计划层、引擎探针 / 分盘层 / 盘外提示、题干与关键词表 | health_pressure |
occupation |
教育、事业、感情、迁居、财务、家人六个领域三层同名,逐站核过,没有同类问题。
2. 逐站清单(健康)
| # | 位置 | 比较的两边 | 后果 | 现状 |
|---|---|---|---|---|
| H1 | method-followup.ts::holdoutFollowupFor !declined.has(item.domain) |
拒答记录 health vs 盘外提示 health_pressure |
拒答 / 跳过的健康线被当作"没用过"再问,撞同 id 焦点静默 | BUG-626 |
| H2 | 同函数 occupied |
账本 health vs 提示 health_pressure |
已修(BUG-590 决策 4) | 已修 |
| H3 | remainingReverseVerifyProbes L718 declined.has(probe.domain) |
拒答 health vs 引擎探针 health_pressure |
采用后核对仍会问拒答过的健康线 | 未修 |
| H4 | remainingConflictProbes L789 同上 |
同上 | 区分题仍会问拒答过的健康线 | 未修 |
| H5 | probeYearAlreadyCovered L427 item.domain !== domain |
账本 health vs 探针 health_pressure |
用户已报 2024-10 受伤,仍可能被问"2024 年 10 月前后有没有生病受伤" | 未修 |
| H6 | 引擎 oos_blind_prompts covered 用事件域 |
事件 health vs 目录 health_pressure |
有健康事件时仍下发"还没用过健康压力这条线"(真实 Case JSON 已见) | 未修 |
| H7 | 引擎 _event_years(events, "health_pressure") → _existence_blocked_years |
同上 | 已报年份不阻断健康探针,出重复 / 引导题 | 未修 |
| H8 | 引擎 volunteered 集合(VOLUNTEER_ONLY 含 health_pressure) |
事件 health 永远不等于 health_pressure |
用户主动报了健康事件,D30 层仍被当"未主动提及"永不进入探针顺序——健康线被系统性低用 | 未修 |
| H9 | candidate-contrast-packet.ts L237 item.domain === "health_pressure" || HEALTH_RE.test(summary) |
用摘要正则补别名 | 能工作,但是靠文案猜;摘要不含关键词就漏 | 改为归并 |
| H10 | datedCollectDomainBlocked / hasConfirmedHealth / declinedHealth |
已归并 | — | 已修 |
3. 逐站清单(职业)
| # | 位置 | 后果 | 现状 |
|---|---|---|---|
| O1 | declinedDomains 对职业焦点得到 other,declined.has("occupation") 永远为假(L1348 / L1386 / L1957 三处) |
靠 occupationCollectFocusClosed 按 questionId 前缀兜底;L1957 的兜底还额外要求 careerCovered——事业未覆盖时拒答职业会被再问 |
部分修 |
| O2 | declinedDomains 把职业拒答记成 other 塞进集合 |
目前无人查 declined.has("other"),无害 |
顺手清理 |
4. 决策记录
- 一个归并函数,两侧各一份,语义相同。 TS:
canonicalCollectDomain(raw, questionId?):health→health_pressure;target_domain === "other"且questionId以collect:occupation:开头 →occupation;其余原样。放在v9/domain-alias.ts,method-followup.ts、candidate-contrast-packet.ts全部经它比较;hasConfirmedHealth/declinedHealth改为它的薄封装并保留。Python:event_probes.py加canonical_domain(raw)(health→health_pressure),_event_years、oos_blind_prompts.covered、volunteered三处经它;contracts.py的 v1 兼容项不动。 - DB 不改:
target_domain约束仍是health/other;归并只发生在读取侧。persistableFocusDomain不变。 - H8 单独确认产品口径:健康线本来就是"只有用户主动说才问"(SKILL.md §5),修完归并后主动报过健康事件的用户会开始收到 D30 层探针——这是原设计意图,不是新行为;进度记录写明。
- 不动门槛、四选项合同、
SCORE_DELTA;Skill 不 bump。
5. 任务分解
- 5.1 TS 归并函数 + H1/H3/H4/H5/H9/O1 六站改用;用例——每站一条:账本
health+ 拒答health+ 探针health_pressure→ 不再问;职业拒答(topicother+collect:occupation:id)→declined.has("occupation")语义成立且事业未覆盖时也不再问职业。 - 5.2 Python 归并 + H6/H7/H8;用例(
tests/test_rectification_event_probes.py)——事件域health2024-10 →oos_blind_prompts不含health_pressure;_existence_blocked_years("health_pressure")含 2024;volunteered含health_pressure,D30 进入顺序。 - 5.3 源码合同:
agent-voice-copy-contract或新合同测试锁"method-followup.ts里除归并函数外不得出现字面量"health"比较"(grep -n '"health"'只允许在domain-alias.ts)。 - 5.4 记录:BUG-628(关联 BUG-590 决策 4、BUG-626、BUG-586 决策 2);
CHANGELOG.md;PROGRESS-…;CONTEXT.md术语表补一条"领域别名:health ≡ health_pressure,occupation 在焦点层存为 other"。
6. 让步顺序
5.1 与 5.2 必做同一提交;5.3 必做(防第三次复发);5.4 不可省。
7. 开工前置命令
git fetch origin --prune
git worktree add -b codex/rectification-domain-alias-audit-20260909 .worktrees/rectification-domain-alias-audit-20260909 origin/staging
cd .worktrees/rectification-domain-alias-audit-20260909
ln -s /workspace/Jyotisha/frontend/node_modules frontend/node_modules
ln -s /workspace/Jyotisha/.venv .venv
grep -n '"health"' frontend/src/lib/rectification-agentic/v9/method-followup.ts frontend/src/lib/rectification-agentic/core/candidate-contrast-packet.ts scripts/rectification/event_probes.py scripts/rectification/refinement_packet.py
cd frontend && ./node_modules/.bin/tsc --noEmit; npm run lint 2>&1 | tail -1
ls tests/rectification-*.test.ts | grep -v database | xargs npx tsx --test 2>&1 | grep -E "^# (tests|pass|fail)"
cd .. && .venv/bin/python -m pytest tests/test_rectification_event_probes.py tests/test_rectification_v5_services.py -q