d6ee8cbb26
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
11 KiB
11 KiB
TASK · 生时校正:可信区间成为一等公民,报告与对话按"稳定层 / 分钟敏感层"读盘(2026-09-06)
- 基线:
origin/staging@b938c76a(文档头211f9bb2) - 分支:
codex/rectification-range-reading-20260906 - 执行方:coding agent;验收:Claude
- 串行:排在
TASK-rectification-convergence-exit-fix-20260906.md(BUG-565~567)与TASK-rectification-explain-layer-20260906.md之后,三者都改adopt-narration.ts/rectification-agentic-chat.tsx - 涉及文件:
frontend/supabase/migrations/(新迁移)、frontend/src/lib/report-candidate-range.ts、frontend/src/lib/personal-report-route-core.ts、frontend/src/lib/consultation-route-service.ts、frontend/src/lib/consultation-birth-time-mode.ts、frontend/src/mastra/consultation-workflow.ts、frontend/src/lib/rectification-agentic/v9/tool-service.ts、adopt-narration.ts、scripts/jyotish_engine.py::_candidate_minutes、scripts/rectification/api_service.py(新函数) - 不改:
scripts/jyotish_api_server.py主体(只允许一行薄注册)、frontend/src/app/page.tsx、任何采用/确认门 - BUG 编号起点:BUG-568(开工时复核;565~567 已被修复单预留)
0. 为什么做这件事
昨天的 20 例公开 holdout 校准说明引擎原始分在分钟级几乎没有区分力(见父单 TASK-rectification-convergence-exit-20260906.md 验收段与 BUG-560)。既然大多数校正最后都停在一个 10~30 分钟的可信区间,产品最诚实、也最有价值的交付就是:告诉用户这段区间里哪些结论稳定、哪些结论随分钟变,而不是把代表分钟当成精确时间去排盘。上游 yinduzhanxing 的 FlexibleBirthTimeProfile 合同(稳定证据 / 分钟敏感证据分开、多分钟区间不建单分钟盘)就是这个思路;它的四个脚本 9-03 已经同步进本仓,引擎 _build_birth_time_sensitivity 也已经在报告链上跑,但接的是错的窗口。
1. 现状实证(代码定位,非猜测)
| # | 事实 | 位置 |
|---|---|---|
| 1 | 报告的 birth_time_sensitivity 窗口来自 RPC read_report_candidate_range,它返回 agentic_rectification_cases.candidate_range——即校正开工时的搜索窗口(填报时间 ±15 分钟,或时段 4~6 小时),不是 latest_result.credible_range |
frontend/supabase/migrations/20260904010000_read_report_candidate_range.sql L50–68;personal-report-route-core.ts::resolveReportBirthTimeSensitivityInput |
| 2 | 采用(accept)RPC 只写 p_result_id / p_candidate_id,可信区间不落库;profile 上只有 active_birth_time + birth_time_status=accepted,uncertainty_before/after 仍是填报值 |
tool-service.ts L1726 accept_agentic_rectification_candidate_for_case_v2 |
| 3 | 引擎窗口 >15 分钟时只取 3 个样本(起点 / 代表 / 终点)做稳定-敏感分类,27 分钟区间等于只看 3 个分钟 | jyotish_engine.py::_candidate_minutes L2191 |
| 4 | 聊天:birth_time_status=accepted → verified_chart 模式,按 active_birth_time 当精确分钟排盘;birth_time_accuracy / candidate_range 只在报告路径传,聊天不传 |
consultation-route-service.ts L254、L515;consultation-workflow.ts L22–23 |
| 5 | 校正采用轮只交付代表分钟 + 八法报告;没有"这段区间里哪些主题稳定"的话 | adopt-narration.ts、SKILL.md §9 |
| 6 | declared_birth_window 聊天模式已存在(未校正的时段用户),只做输出守卫降级,不做稳定/敏感分层 |
consultation-birth-time-mode.ts L84–95 |
2. 决策记录(PM 代为落地,可否决)
- 采用即落库可信区间。
accept_agentic_rectification_candidate_for_case_v2同时写入adopted_credible_range jsonb({start_time,end_time,representative_time,width_minutes,source:"inference_credible_range"}),来源 = 采用那一刻决策层的credibleRange(与 UI 上"目前范围"同源)。用户改选候选时重写。 - 报告与聊天优先读它。
read_report_candidate_range先返回adopted_credible_range,没有再退回candidate_range;聊天verified_chart且status=accepted时把birth_time_accuracy="provisional"+candidate_range传进 workflow,与报告同一份birth_time_sensitivity。status=confirmed仍是confirmed,不变。 - 采样规则。 窗口 ≤ 31 分钟逐分钟;> 31 分钟等距取 31 个样本(含起点、代表、终点),并在
window里标sampled: true。flexible_birth_time_profile的 2~31 上限不改。 - 校正采用轮多一段话。 采用旁白在八法报告之后加"稳定 / 随分钟变"两句(服务端从
theme_sensitivity生成,模型不得自编),例:"这 27 分钟里,事业方向、性格底色的判断是稳定的;婚恋(D9)和学业(D24)会随分钟变,看盘时按范围读。" declared_birth_window模式也用同一分层:时段用户没做校正也能拿到"这个时段里稳定的是什么",但窗口 > 31 分钟按 3 采样,措辞里必须写明"只是粗看"。- 不动任何门:采用门、确认门、
MIN_SEPARATION_LEAD、报告的birthTimePolicy枚举都不改。
3. 硬红线
- 迁移只加列 + 改一个 RPC;必须真跑
npm run test:db --prefix frontend(无 Docker 时写BLOCKED.md,不得标通过)。 adopted_credible_range不得反向改写candidate_range(那是开工基线,重算指纹依赖它)。- 稳定 / 敏感句只允许来自
theme_sensitivity,不得由模型补写;文案对照frontend/docs/VOICE.md,保留"不是已确认的唯一出生分钟"边界句。 scripts/jyotish_api_server.py只允许薄注册一行;新逻辑进scripts/rectification/api_service.py。- 测试总数 ≥ 开工实测;
tsc0 错;lint 0 error;run_quality_gate.py --profile quick。
4. 任务分解
A1 落库(BUG-568:报告敏感度窗口用的是开工窗口)
- 迁移
agentic_rectification_cases.adopted_credible_range jsonb null;accept_agentic_rectification_candidate_for_case_v2新增可选参数p_credible_range jsonb;tool-service.ts采用时从decision.credibleRange+representativeTime组装传入;改选时覆盖。 read_report_candidate_range:优先adopted_credible_range,否则原逻辑。- 验收:
rectification-v9-database.test.ts新增采用后读回区间用例(Docker);无 Docker 时 SQL 单元断言写进BLOCKED.md并附手工 psql 验证步骤。
A2 引擎采样
_candidate_minutes(start, representative, end):≤31 全取;>31 等距 31 点;返回值不变(list[str])。- 验收:
tests/test_jyotish_engine_birth_time_sensitivity*.py(若无则新建)——27 分钟窗口返回 27 个样本;60 分钟返回 31 个且含起点/代表/终点。
A3 聊天接同一份敏感度
consultation-route-service.ts:verified_chart且birth_time_status=accepted时加载adopted_credible_range(复用loadReportCandidateRange),把birth_time_accuracy="provisional"与candidate_range放进 workflow 输入;consultation-workflow.ts把birth_time_sensitivity.theme_sensitivity映射到consumer_context.answer_policy.minute_sensitive_themes: string[];系统提示块加一句固定说明(服务端文案),敏感主题的应期结论走guardPreciseTimingOutput同级降级。- 验收:
consultation-*.test.ts新增——accepted + 有区间 → workflow 输入含candidate_range,answer_policy.minute_sensitive_themes非空;confirmed → 不含。
A4 校正采用轮的"范围读盘"
scripts/rectification/api_service.py新增range_reading(request):输入出生资料 + 区间 + 代表分钟,内部调_build_birth_time_sensitivity,返回{window, stable_themes[], sensitive_themes[], claim_boundary};jyotish_api_server.py只加一行注册/api/rectification/v5/range_reading。engine-client.ts新增runV9RangeReading;adopt-narration.ts在采用旁白追加两句(决策 4);rectification-offer-candidates工具返回里带range_reading,SKILL 不改(措辞由服务端旁白承载)。- 验收:
rectification-adopt-narration*.test.ts新增——给定 theme_sensitivity fixture,旁白含"稳定"与"随分钟变"两句且含边界句;引擎不可用时旁白不带这两句、不报错。
A5 declared_birth_window 复用(决策 5)
- 同 A3 路径,
birth_time_accuracy="approximate",candidate_range= 声明时段;措辞加"只是粗看"。 - 验收:一条 consultation 测试。
A6 记录
docs/BUG_HISTORY.mdBUG-568;CHANGELOG.md;docs/tasks/PROGRESS-rectification-range-reading-20260906.md;docs/testing/rectification-range-reading-20260906.md(真实环境:采用后新建对话,回答里对婚恋/学业类问题出现范围口径;报告出生时间敏感度节的窗口等于采用时的"目前范围");frontend/DESIGN.md若采用旁白布局有变。
5. 让步顺序
A1 + A2 + A4 是核心,不可拆;A3 必做;A5 可后置到同分支第二次提交;A6 不可省。
6. 开工前置命令
git fetch origin --prune
git worktree add -b codex/rectification-range-reading-20260906 .worktrees/rectification-range-reading-20260906 origin/staging
cd .worktrees/rectification-range-reading-20260906
ln -s /workspace/Jyotisha/frontend/node_modules frontend/node_modules
ln -s /workspace/Jyotisha/.venv .venv
cd frontend && ls tests/rectification-*.test.ts tests/consultation-*.test.ts tests/agent-voice-copy-contract.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_v5_services.py -q
grep -o "^## BUG-5[0-9][0-9]" docs/BUG_HISTORY.md | tail -1
验收(Claude,2026-09-07,origin/staging @ 814c924e)
| 项 | 结论 |
|---|---|
| A1 落库 + RPC | 通过(代码审阅)。迁移 20260906020000_adopted_credible_range.sql:加列、六参采用函数、read_report_candidate_range 优先 adopted_credible_range;不改 candidate_range。Docker test:db 由执行方在有 Docker 的机器跑 37/0,本机无 Docker,按环境缺口记,不重复宣称 |
| A2 引擎采样 | 通过。≤31 逐分钟;>31 等距 31 点;approximate 且 >31 才 3 采样(决策 5);flexible_birth_time_profile 上限 15→31(任务书按 31 写,仓库原值 15,执行方如实记录) |
| A3 聊天 | 通过。verified_chart(accepted) 加载最近一个 candidate_accepted Case 的区间(不带 case id,SQL 取 updated_at desc limit 1,可接受),birth_time_accuracy=provisional + candidate_range 进 workflow,minute_sensitive_themes 进 answer_policy 并触发输出守卫 |
| A4 采用旁白 | 通过。稳定/敏感两句由 theme_sensitivity 生成,带边界句,引擎不可用静默省略 |
| A5 declared_birth_window | 通过(「这只是粗看」) |
| A6 记录 | 通过 |
部署提醒:staging 当前 b938c76a,本轮两条新迁移(20260906020000、20260906030000)未应用,部署前先跑 Migrate Staging Database。