Files
Jyotisha/docs/tasks/TASK-consultation-birth-accuracy-20260901.md
T
Jesse_ChenandClaude Fable 5.1 8db71aaf81 docs: product-level README, AGENTS.md split into code/reading parts, add CLAUDE.md, move task briefs to docs/tasks
- README.md is now the product/repo front door (architecture, repo map,
  local dev, test tiers, delivery flow, doc map). Engine positioning,
  VedAstro/Codex setup and the oracle/benchmark command reference move
  verbatim to docs/engine/README.md, docs/engine/vedastro-gateway.md and
  docs/benchmark/README.md. Capability badges realigned with the registry
  (91/78/8/0); tests/test_readme_badges.py was red on staging.
- AGENTS.md: Part A (environment truth, delivery, worktrees, record
  placement, bug workflow, growth freeze, frontend red lines, privacy,
  pre-work check, test tiers) and Part B (reading-rigor constraints).
  GitHub issue-tracker/triage boilerplate removed: GitHub is a read-only
  mirror. All strings locked by tests/ are preserved.
- CLAUDE.md added: roles, three working modes, task-brief sections,
  acceptance criteria, session discipline; imports AGENTS.md.
- 50 tracked TASK-*/PROGRESS-* files and 3 never-committed briefs move to
  docs/tasks/ with an index; REPO_LAYOUT.md merged into README.

Docs-only change (no gated path touched).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
2026-09-03 06:56:06 +00:00

98 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 任务书 · 咨询侧出生时间精度真值传递:填了准确时间不应被当作"未校正按范围交互"2026-09-01
基线:`origin/staging` @ 当前 tip(含 PR #47 合并 `b98777aa`)。
## 0. 用户报告与定性
用户在初始化(onboarding)填了**准确出生时间**(如医院记录),咨询时模型仍说"没做过生时校正,就按一个时间范围来交互"。经静态溯源,这不是模型幻觉,是**三处叠加的真值传递断裂**——模型每一轮都被服务端明确告知"未校正":
### 根因 1 · 前端从不把时间来源/精度传给引擎(P0)
Profile 里存有 `birth_time_source``hospital_record` / `family_exact` / `approximate` / `period_only` / `unknown`)和 `birth_time_status``accepted` / `confirmed` 表示已完成校正采用)。但 `consultation-route-service.ts``serverChartFromProfile`(约 :309)构造的 `toolInput` 只有 `year/month/day/hour/minute/city/lat/lon/tz`——**`declared_accuracy``time_source` 从未发出**。全前端 grep `declared_accuracy|time_source` 零个发送点。
### 根因 2 · 引擎默认值把所有人降到 '5min',且 '5min' 档位缺失(P0/P1
`scripts/jyotish_api_server.py``run_rectification_gate`(约 :2219)与 `_compute_rectification_gate`(约 :8610):收不到字段就默认 `declared_accuracy='minute'``time_source='family_clear'``get_effective_accuracy``'5min'`。而:
- `_PRECISE_BIRTH_TIME_ACCURACY = ('minute', 'rectified')`:1806)——`'5min'` 不算精确 → **每次咨询**都执行 `add_domain_layer('birth_time uncertain boundary', 'not_auto_rectified', ...)`(约 :1857),边界文案"Birth-time uncertainty requires candidate windows and event evidence"进入模型上下文;
- `birth_time_rectifier.ACCURACY_MATRIX` **没有 `'5min'` 键**`get_enabled_vargas('5min')` 落到 `'unknown'` 档 → 只开 `D1` + `D9(warn)`headline 变成"可读主盘,但高敏分盘需要降级"(已实测复现:`get_effective_accuracy('minute','family_clear')=='5min'`enabled 只有 `{'D1': 'enabled', 'D9': 'enabled_with_warning'}`;对照 `('minute',''hospital')=='minute'` 时 D1/D9/D10/D5/D4 全开)。
### 根因 3 · mastra workflow 把 not_auto_rectified 硬编码进每次咨询(P0
`mastra/consultation-workflow.ts:695``rectification: { boundary: "not_auto_rectified", ... }` ——**无条件硬编码**,不看模式、不看引擎 gate 的实际输出。`mastra/index.ts:55` 的系统指令又要求 "Treat rectification.boundary=not_auto_rectified as final"。两者叠加,模型每轮都被指示"该出生时间未校正"。
### 影响面
- 自报医院精确时间的用户:被当作未校正、按范围交互——本任务书的直接投诉。
- **已付费完成校正并采用时间的 `verified_chart` 用户:同样被告知未校正**——`'rectified'` 这个精度值前端从未发出过,付费成果在咨询里零体现。这是对校正商业价值的直接损害。
- `UNVERIFIED_BIRTH_TIME_NOTICE`("使用未校正填报时间;分钟敏感结论的置信度已降低")对 hospital 级来源同样一刀切。
## 1. 硬红线
1. **真实性不放宽。** `'rectified'` 精度只允许在 `birth_time_status ∈ {accepted, confirmed}``active_birth_time` 存在时声明;不得让未校正用户获得 rectified 待遇。医院记录按 `('minute','hospital')` 处理是 skill 方法论本来的定义(`birth_time_rectifier.ACCURACY_RULES`),不属于放宽。
2. **输出守卫机制保留。** `createBirthTimeModeOutputGuard` / `guardPreciseTimingOutput` 的机制不动;改变的只是喂给它和模型的**精度事实**。`declared_birth_window` / `general_no_birth_time` 两档行为完全不变。
3. **不动生时校正产品本身**rectification-agentic、引擎 v5 打分、Round A/2/tails 全部成果)。
4. 分级降级仍要诚实:`family_exact → '5min'``approximate → '15min'` 的降级保留,只是**表达**从"未校正按范围"改为"按你填报的 HH:MM 排盘,分钟敏感结论标注精度"。
5. `cd frontend && ./node_modules/.bin/tsc --noEmit` 通过(不要用 `npx tsc`);前端 `consultation-*`/`consult-*`/`chat-*``rectification-*` 测试 fail=0Python 用 `.venv``tests/test_rectification_*.py` 与受影响模块全绿。
6. 不改 `.gitea/workflows/**`;无凭据不得声称已在真实环境验证。
## 2. 开工前置
```bash
git fetch origin --prune
git worktree add -b codex/consultation-birth-accuracy-20260901 \
../.worktrees/consultation-birth-accuracy-20260901 origin/staging
```
`frontend/AGENTS.md``docs/BUG_HISTORY.md`。**行号只是线索,按符号名定位。**
## 任务 0(门控)· 先写不变量,先让它红
前端(新文件 `frontend/tests/consultation-birth-accuracy.test.ts` 或并入 `consultation-birth-time-mode.test.ts`+ Python 各写:
1. **verified_chart 用户**workflow 请求携带 `declared_accuracy='rectified'`;模型消费上下文的 `rectification.boundary` **不是** `not_auto_rectified`;不含"按时间范围交互"类指令。
2. **hospital_record 未校正用户**:请求携带 `('minute','hospital')`;引擎 gate `effective_accuracy='minute'`、无 `birth_time_uncertainty_boundary` 域边界、D9/D10 enabled。
3. **family_exact / approximate**:分别得 `'5min'` / `'15min'`,保留降级但边界文案为"精度标注"式,不是"需要候选窗/按范围交互"式。
4. **Python 档位**`get_enabled_vargas('5min')``get_enabled_vargas('15min')` 不再落到 `'unknown'`(见任务 C)。
5. **守卫回归**`declared_birth_window` / `general_no_birth_time` 行为逐字节不变(现有 `consultation-birth-time-mode.test.ts` 9 条必须保持全绿)。
跑一遍确认 1-4 是红的。
## 任务 A(P0)· 前端把出生时间真值映射进引擎请求
`consultation-route-service.ts``serverChartFromProfile` / workflow 请求构造处,按 profile 真值附加两个字段:
| profile 状态 | declared_accuracy | time_source |
|---|---|---|
| `accepted` / `confirmed`verified_chart | `rectified` | (引擎忽略或传 `rectified` |
| `hospital_record` | `minute` | `hospital` |
| `family_exact` | `minute` | `family_clear` |
| `approximate` | `15min` | (任意) |
映射函数单独导出、可单测;`declared_birth_window` / `general_no_birth_time` 不走 chart workflow,不受影响。字段随 `runConsultationWorkflow` 的 body 传至 Python`run_rectification_gate` 已按 `body.get('declared_accuracy')` 读取,服务端无需改协议)。
## 任务 BP0)· mastra 停止硬编码 not_auto_rectified
`mastra/consultation-workflow.ts`(约 :695):`rectification.boundary` 改为**透传引擎 gate 的真实结论**——`effective_accuracy ∈ {'minute','rectified'}` 且无 lagna 边界敏感时给非限制值(如 `precision_ok` / 直接省略 boundary),否则才是 `not_auto_rectified``mastra/index.ts:55` 的指令改为条件化表述("当 boundary=not_auto_rectified 时……"语义已是条件式,确认无别处无条件复述)。同步检查 `consultation-tools.ts:500` 附近对该字段的消费逻辑。
## 任务 CP1)· 引擎补 '5min'/'15min' 档位与分级文案
`scripts/birth_time_rectifier.py`
- `ACCURACY_MATRIX``'5min'` 键(建议:D1/D9/D10 enabledD5/D4 warnD7 warnD30/D60 disabled——比 `'minute'` 保守一档、比 `'15min'` 宽一档,D10 必须可用否则事业咨询全瘸)。`'15min'` 键已存在,确认其被正确命中而非落 `'unknown'`
- `_compute_rectification_gate` 的 headline/next_action 分三级:precise(无警示)/ 轻降级("按填报时间排盘,分钟敏感结论已标注精度")/ 重降级(现文案)。"建议先做事件反验"只出现在 lagna 边界敏感或 `approximate` 以下。
## 任务 D(P1)· 面向用户的文案分级
- `UNVERIFIED_BIRTH_TIME_NOTICE` 按来源分级:`hospital_record` →"使用你填报的出生时间(医院记录)排盘";`family_exact` → 现文案弱化版;`approximate` → 现文案。消费点同步。
- 检索模型指令与提示词中所有"按时间范围来交互 / 未校正"类表述(`generalNoMinuteInstruction` / `declaredWindowInstruction` 之外的),确认只在真实低精度档触发。
## 验收标准
1. 任务 0 五组不变量全绿;改动前 1-4 为红的证据贴 PR。
2. `tsc --noEmit` exit 0`npx tsx --test tests/consult*.test.ts tests/consultation-*.test.ts tests/chat-*.test.ts tests/rectification-*.test.ts` 全部 fail=0,逐套贴数字。
3. Python`.venv` 下受影响模块 + `tests/test_rectification_*.py` 全绿;`_expand_pytest_targets` 钉子保持。
4. **前后对照贴 PR**hospital_record 用户与 verified_chart 用户的 workflow 消费上下文(rectification 块 + answer_policy)改动前后各一份;确认 `not_auto_rectified` 只剩低精度档出现。
5. 说明 family_exact 保留 '5min' 降级的理由(方法论:家人记忆非医院记录)已写进 PR,供产品复核是否接受。
6. 未在真实环境验证的部分如实注明;建议与 PR #47 的九步点测单合并执行一次真实环境复核(补一条:hospital 精确时间用户咨询不再被告知"未校正按范围")。