docs(tasks): sync2 + chart-render acceptance — fix brief for web-path dasha_info (BUG-609)

This commit is contained in:
Jesse_Chen
2026-09-09 08:20:30 +00:00
parent 4e974b7601
commit 26ef220f2b
@@ -0,0 +1,109 @@
# TASK · 上游同步二修复单(网页婚恋路径拿不到大运 / 围栏失败会打断报告)— 2026-09-09
- 基线:`origin/staging` @ `04ad3325``TASK-upstream-sync2-20260909` 实现,已验收;`TASK-report-chart-render-20260909` 实现 `2fdcb14f` 同批在 staging)。
- 分支:`codex/upstream-sync2-fix-20260909`worktree `.worktrees/upstream-sync2-fix-20260909`
- 验收结论摘要(`04ad3325`):定向 Python 176 通过;quick 门 708 通过 / 1 失败(`test_shadbala_endpoint_returns_ranked_planet_strength`,验收机缺 `timezonefinder`,环境缺口);真实 `pl9-export` 时间系统表 5 + 10 行正确;api_server 11300 行(上限 11363)。前端(`2fdcb14f`):tsc 0 错、lint 0 error、`npm test` 2991 / 2949 通过 / 28 失败(无 Docker 基线同 28/ 14 跳过;`next build --webpack` `/` Static`globals.css` gzip 35290 → 35630+0.96%)。
## 1. 事故实证
### P1 · 网页咨询路径的婚恋三层分类永远没有大运命中
`04ad3325` 起本地 API`scripts/jyotish_api_server.py --port 5299`)对 `/api/consultation_workflow``theme=marriage`,虚构出生 1990-06-15 10:30 北京)实测:
| 观察 | 值 |
| --- | --- |
| `thematic_report.themes.marriage.evidence` | `D1-7th-house``Spouse-status-yoga``DK-UL-Dasha timing``Romantic-activation` |
| `Romantic-activation.details.hits` | `[]`(只有 `natal_structure: ["7H_Moon"]` |
| `Relationship-formation` / `Legal-marriage` | 不出现 |
| `thematic_report.themes.marriage.timing.dasha_period` | `Saturn-Unknown` |
| `chart.modules.dasha` 的键 | `current_md / remaining_years / total_years / start_date / periods / birth_balance / …`**没有** `maha_dasha` / `antar_dasha`,也没有 `vimshottari_analysis``current_md` 是出生时大运(Rahu),不是当前 |
| `chart.modules.dasha_sub_periods.current` | `{"mahadasha": {"lord": "Saturn", …}, "antardasha": {"lord": "Jupiter", …}}`(正确的当前 MD/AD |
链路:`_thematic_dasha_info`L6555)只从 `chart['dasha']``dasha['vimshottari_analysis']['current']``maha_dasha` / `antar_dasha`;咨询路径 `full_reading_used=false``dasha = full_modules.get('dasha')`L5425)是 chart 模块的 `dasha`,没有 `vimshottari_analysis`。于是传进 `analyze_relationship``dasha_info` 只有 `current_md`(出生 MD),`MD_AD_KEYS = ('maha_dasha','mahadasha','antar_dasha','antardasha','bhukti')` 一个都对不上 → `event_class_split.*.hits` 恒空。
**后果**:任务书 §2 的核心目标(按 MD/AD 把心动 / 成对 / 领证分开)在网页聊天路径上是空转,只剩本命结构观察;同时 `report_orchestrator.py` L701 那句「婚姻相关宫位与 karaka 将被激活,是缔结或调整伴侣关系的关键期」仍随 `timing.dasha_period``Saturn-Unknown`)无条件输出——这正是 BUG-608 要拆掉的合并式「婚恋机会」,只是换了个文件。
### P2 · 围栏构造在 try 外,任何一张分盘出 ValueError 会让整份长报告 500
`scripts/jyotish_engine.py` `_render_south_chart`L4226):`render_south_indian_chart``try` 内,失败返回 `_图盘生成失败_`;但紧接的 `build_chart_block(...)``try` 外,`resolve_chart_id` / `_sign_name``raise ValueError('chart id missing' / 'ascendant sign missing')`。分盘 `Ascendant` 行的 `sign` 不在英文 12 星座内(例如引擎某分盘输出 `sign_idx` 而无 `sign`、或中文星座名)时,`render_pl9_markdown` 整体抛错,`/api/reports/<id>/professional-reference``pl9-export` 一起失败。22 张 golden 都是正常路径,没有覆盖这个分支。
### P3 · `/api/health` 的 `version` 写死 `6.9.14`
`scripts/jyotish_api_server.py` L3402 `'version': '6.9.14'`L7000 另一处 `6.9.15`),`jyotish_vedic.__version__` 已是 `6.9.16`。健康检查报的 Skill 版本与实际不符(`5d35731f` 引入,非本轮回归,顺带修)。
## 2. 根因
- P1`_thematic_dasha_info` 是为 `/api/thematic_report` 走 full reading 时写的,前提是 `dasha``vimshottari_analysis`;咨询路径 09-06 起改为复用 chart 模块后这个前提就没了,但当时只影响一句 legacy `timing`,没人发现。BUG-608 把 `dasha_info` 接上后,这条断链第一次有了产品后果。
- P2:任务书 §5 任务 1 写「失败路径不加围栏」,执行方理解为「SVG 失败不加」,没把围栏自身的失败纳入。
- P3:版本字符串散落三处,没有从 `jyotish_vedic.__version__` 读。
## 3. 决策记录
| 决策 | 内容 |
| --- | --- |
| D1 | `dasha_info` 的当前 MD/AD/PD 一律从 `chart.modules.dasha_sub_periods.current``_consultation_dasha_sub_periods` L1432,按请求参考日切出)取;缺失时再回退 `vimshottari_analysis`;两者都缺时**不**从 `dasha.periods` 手算——日期只许来自引擎已切好的边界。 |
| D2 | `report_orchestrator.py` 婚恋主题的 `activation_description` 改为按 `event_class_split` 出句:有 `legal_marriage` MD/AD 命中才可写「缔结」;只有 `romantic_activation` 时写「感情被激活的观察期,不等于领证」;没有命中时不出「关键期」句,`timing` 保留日期但 `activation_description` 写「本期无婚恋事件类命中」。`Saturn-Unknown` 这种 AD 缺失时不得拼 `-Unknown`,改用 MD 单独显示。 |
| D3 | 围栏失败只丢围栏、保留 SVG;不新增用户可见文案。 |
| D4 | 三处版本字符串统一读 `jyotish_vedic.__version__`。 |
不推翻 `TASK-upstream-sync2-20260909` 任何红线。
## 4. 硬红线
1. `scripts/jyotish_api_server.py` 净增 ≤ 15 行(当前 11300,上限 11363);`_thematic_dasha_info` 改动就地,不新增 handler。
2. `/api/consultation_workflow` 契约只增不改;`thematic_report.themes.marriage.timing` 现有键保留。
3. `relationship_analysis.py` / `relationship_event_class_evidence.py` 不改逻辑;P1 只修喂数。
4. 前端不动。
## 5. 任务分解
### 任务 1 · 喂正确的 MD/ADP1)
- `_thematic_dasha_info(chart, dasha)`:先读 `chart.get('modules', {}).get('dasha_sub_periods', {}).get('current')`,映射 `mahadasha.lord → maha_dasha``antardasha.lord → antar_dasha``pratyantardasha.lord → pratyantar_dasha`(若存在);再按原逻辑回退 `vimshottari_analysis`
- 新测试 `tests/test_thematic_dasha_info_source.py`:构造 chart(含 `dasha_sub_periods.current` Saturn/Jupiter)与无 `vimshottari_analysis` 的 dasha → 返回 `maha_dasha='Saturn', antar_dasha='Jupiter'`;无 `dasha_sub_periods` 但有 `vimshottari_analysis` → 走回退;两者都无 → 不含 `maha_dasha`
- 端到端:`tests/test_relationship_event_class_evidence.py` 加一条走 `_derived_marriage_evidence` 的用例,输入来自真实 `/api/consultation_workflow` 响应(把本轮实测的 1990-06-15 虚构盘响应存为 `tests/golden/upstream_sync2/consultation_marriage_1990_fictional.json`,只保留 `chart.modules.dasha / dasha_sub_periods / planets / ascendant``thematic_report.themes.marriage`),断言 `Romantic-activation``Relationship-formation` 至少一条 `details.hits` 非空(Saturn MD / Jupiter ADJupiter 为该盘 7L 或 DK 之一时命中;若该盘不命中,换一个命中的虚构出生并写明)。
验收:新测试绿;重跑本单 §1 的 curl,`hits` 非空、`timing.dasha_period` 不再含 `Unknown`
### 任务 2 · 婚恋 activation 句按事件类出(P1 后半)
- `scripts/report_orchestrator.py` L701 附近:婚恋主题 `activation_description``event_class_split` 派生(见 D2);`dasha_period` 在 AD 缺失时只写 MD。
- 测试:`tests/test_report_orchestrator_marriage_timing.py`(或就近既有文件)三例:仅 romantic → 含「不等于领证」;legal MD/AD 命中 → 可含「缔结」;无命中 → 不含「关键期」「缔结」。
验收:`grep -n "缔结或调整伴侣关系的关键期" scripts/report_orchestrator.py` 只在 legal 分支出现。
### 任务 3 · 围栏失败不打断报告(P2)
- `_render_south_chart``build_chart_block``try/except Exception`,失败返回 `svg`(不带围栏),并 `logging.warning` 一次(不含地名 / 用户串)。
- `tests/test_report_chart_block.py` 加一条:`ascendant_row={'sign': '白羊'}``render_pl9_markdown` 不抛、Markdown 含 `<svg` 且该处无 ```jyotish-chart。
### 任务 4 · 版本字符串(P3)
- L3402、L7000、L7120 三处改为 `jyotish_vedic.__version__`fallback 后缀保留);`tests/test_api_server_security.py` 或就近健康检查测试断言 `version == __version__`
### 任务 5 · 记录
- `docs/BUG_HISTORY.md`**BUG-609**P1,关联 BUG-608、BUG-555 咨询复用 chart 模块)、**BUG-610**P2,关联 BUG-607)、**BUG-611**P3)。
- `docs/tasks/PROGRESS-upstream-sync2-fix-20260909.md``CHANGELOG.md` 一条(婚恋 activation 句按事件类出)。
- `docs/testing/upstream-sync2-20260909.md` 补一条:staging 上问「我什么时候会结婚」,回答里的大运名要与页面时间轴当前 MD/AD 一致,且不出现 `Unknown`
## 6. 让步顺序
1. 任务 4P3)。
2. 任务 2 的「AD 缺失只写 MD」可先只做 `Unknown` 不拼。
3. **不可砍**:任务 1、任务 2 主体、任务 3、任务 5。
## 7. 开工前置命令
```bash
git -C /workspace/Jyotisha status -sb | head -1
git fetch origin --prune
git worktree add -b codex/upstream-sync2-fix-20260909 .worktrees/upstream-sync2-fix-20260909 origin/staging
cd .worktrees/upstream-sync2-fix-20260909
.venv/bin/python -m pytest tests/test_relationship_event_class_evidence.py tests/test_report_chart_block.py tests/test_consultation_workflow_domains.py -q # 基线
.venv/bin/python scripts/jyotish_api_server.py --port 5299 & # 复现 §1 的 curl
```
## 8. BUG 编号起点
`docs/BUG_HISTORY.md` 当前最大 `BUG-608`;本单 **BUG-609 / 610 / 611**,开工时重新核对。