d6ee8cbb26
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
99 lines
11 KiB
Markdown
99 lines
11 KiB
Markdown
# 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 代为落地,可否决)
|
||
|
||
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_chart` 且 `status=accepted` 时把 `birth_time_accuracy="provisional"` + `candidate_range` 传进 workflow,与报告同一份 `birth_time_sensitivity`。`status=confirmed` 仍是 `confirmed`,不变。
|
||
3. **采样规则。** 窗口 ≤ 31 分钟逐分钟;> 31 分钟等距取 31 个样本(含起点、代表、终点),并在 `window` 里标 `sampled: true`。`flexible_birth_time_profile` 的 2~31 上限不改。
|
||
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 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.md` BUG-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. 开工前置命令
|
||
|
||
```bash
|
||
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。
|