Files
Jyotisha/docs/tasks/TASK-rectification-range-reading-20260906.md
T

11 KiB
Raw Blame History

TASK · 生时校正:可信区间成为一等公民,报告与对话按"稳定层 / 分钟敏感层"读盘(2026-09-06

  • 基线:origin/staging @ b938c76a(文档头 211f9bb2
  • 分支:codex/rectification-range-reading-20260906
  • 执行方:coding agent;验收:Claude
  • 串行:排在 TASK-rectification-convergence-exit-fix-20260906.mdBUG-565567)与 TASK-rectification-explain-layer-20260906.md 之后,三者都改 adopt-narration.ts / rectification-agentic-chat.tsx
  • 涉及文件:frontend/supabase/migrations/(新迁移)、frontend/src/lib/report-candidate-range.tsfrontend/src/lib/personal-report-route-core.tsfrontend/src/lib/consultation-route-service.tsfrontend/src/lib/consultation-birth-time-mode.tsfrontend/src/mastra/consultation-workflow.tsfrontend/src/lib/rectification-agentic/v9/tool-service.tsadopt-narration.tsscripts/jyotish_engine.py::_candidate_minutesscripts/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 L5068personal-report-route-core.ts::resolveReportBirthTimeSensitivityInput
2 采用(acceptRPC 只写 p_result_id / p_candidate_id,可信区间不落库;profile 上只有 active_birth_time + birth_time_status=accepteduncertainty_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=acceptedverified_chart 模式,按 active_birth_time 当精确分钟排盘;birth_time_accuracy / candidate_range 只在报告路径传,聊天不传 consultation-route-service.ts L254、L515consultation-workflow.ts L2223
5 校正采用轮只交付代表分钟 + 八法报告;没有"这段区间里哪些主题稳定"的话 adopt-narration.ts、SKILL.md §9
6 declared_birth_window 聊天模式已存在(未校正的时段用户),只做输出守卫降级,不做稳定/敏感分层 consultation-birth-time-mode.ts L8495

2. 决策记录(PM 代为落地,可否决)

  1. 采用即落库可信区间。 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 上"目前范围"同源)。用户改选候选时重写。
  2. 报告与聊天优先读它。 read_report_candidate_range 先返回 adopted_credible_range,没有再退回 candidate_range;聊天 verified_chartstatus=accepted 时把 birth_time_accuracy="provisional" + candidate_range 传进 workflow,与报告同一份 birth_time_sensitivitystatus=confirmed 仍是 confirmed,不变。
  3. 采样规则。 窗口 ≤ 31 分钟逐分钟;> 31 分钟等距取 31 个样本(含起点、代表、终点),并在 window 里标 sampled: trueflexible_birth_time_profile 的 231 上限不改。
  4. 校正采用轮多一段话。 采用旁白在八法报告之后加"稳定 / 随分钟变"两句(服务端从 theme_sensitivity 生成,模型不得自编),例:"这 27 分钟里,事业方向、性格底色的判断是稳定的;婚恋(D9)和学业(D24)会随分钟变,看盘时按范围读。"
  5. declared_birth_window 模式也用同一分层:时段用户没做校正也能拿到"这个时段里稳定的是什么",但窗口 > 31 分钟按 3 采样,措辞里必须写明"只是粗看"。
  6. 不动任何门:采用门、确认门、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
  • 测试总数 ≥ 开工实测;tsc 0 错;lint 0 errorrun_quality_gate.py --profile quick

4. 任务分解

A1 落库(BUG-568:报告敏感度窗口用的是开工窗口)

  • 迁移 agentic_rectification_cases.adopted_credible_range jsonb nullaccept_agentic_rectification_candidate_for_case_v2 新增可选参数 p_credible_range jsonbtool-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.tsverified_chartbirth_time_status=accepted 时加载 adopted_credible_range(复用 loadReportCandidateRange),把 birth_time_accuracy="provisional"candidate_range 放进 workflow 输入;consultation-workflow.tsbirth_time_sensitivity.theme_sensitivity 映射到 consumer_context.answer_policy.minute_sensitive_themes: string[];系统提示块加一句固定说明(服务端文案),敏感主题的应期结论走 guardPreciseTimingOutput 同级降级。
  • 验收:consultation-*.test.ts 新增——accepted + 有区间 → workflow 输入含 candidate_rangeanswer_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 新增 runV9RangeReadingadopt-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.md BUG-568CHANGELOG.mddocs/tasks/PROGRESS-rectification-range-reading-20260906.mddocs/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

验收(Claude2026-09-07origin/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 idSQL 取 updated_at desc limit 1,可接受),birth_time_accuracy=provisional + candidate_range 进 workflowminute_sensitive_themes 进 answer_policy 并触发输出守卫
A4 采用旁白 通过。稳定/敏感两句由 theme_sensitivity 生成,带边界句,引擎不可用静默省略
A5 declared_birth_window 通过(「这只是粗看」)
A6 记录 通过

部署提醒:staging 当前 b938c76a,本轮两条新迁移(2026090602000020260906030000)未应用,部署前先跑 Migrate Staging Database。