Files
Jyotisha/docs/tasks/TASK-report-blocked-repairs-20260902.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

172 lines
13 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.
# 任务书 · 个人报告全主题 blocked 修复(2026-09-02
基线:`origin/staging` @ `24a1cf37`
## 事故实证
2026-09-02 15:45 staging 真实生成的 personal_full 报告(请求主题 career/marriage/timing/wealth)四个主题**全部 blocked**,摘要退化为"报告主题尚未生成"。blocked 理由:
- career:缺少最低证据组 AmK、Transit
- marriage:缺少最低证据组 DK
- timing:缺少最低证据组 Transit
- wealth:缺少结构化分盘 D2、D11
已在本地用 `origin/staging @ 24a1cf37` 的前端提取层 + 同版本 Python 引擎(`scripts/jyotish_api_server.py`,虚构 smoke 出生数据,按 worker 的方式每主题一次 `/api/consultation_workflow`**完整复现**:blocked 主题与理由逐字一致。这是确定性缺陷,不是线上环境问题。
## 根因(已逐项定位,不需要重新猜)
**根因 1(wealth):分盘值形状不匹配,所有分盘图提取失败。**
引擎 `chart.modules.varga_full` 的值形状是:
```json
{ "ascendant": { "sign": "Gemini", "sign_index": 2, "degree": 21.027 },
"planets": { "Sun": { "sign": "Libra", "sign_index": 6, "degree": 15.23, "house": 5 }, ... },
"house_chart": [["Ketu"], [], ...], "division": ..., "name": ..., "meaning": ... }
```
`frontend/src/lib/personal-report-generation.ts``deriveVargaHousesFromEngine`(约 :336)读的是**大写 `Ascendant` + `sign_idx` + 顶层行星键** → 每张分盘都返回 null → bundle `charts` 只剩 D1。昨日 `45f190a1` 修了键名别名(`D2_Hora``D2`)并新增"claim card 主题缺结构化分盘图则降 blocked"的兜底(`demoteThemesMissingRequiredCharts`),但没修值形状——于是 wealth 从"write 后文档校验失败"变成"bundle 层 blocked"。`643f6f7a` 的 fixture 是按**旧形状手造**的,所以测试全绿、线上照挂。(2026-08-30 观察到的 `final_parse_rejected` 大概率同源。)
**根因 2timing、career 之一半):Transit 回执从不生成。**
引擎响应 `chart.modules.transits` 存在且 `status: "executed"`(含 sade_sati、triggers、search_period、boundary),但 `consumer_context.available_layers` 与 machine packet sections 里都没有 transit 名目,前端提取层从不为它 upsert 执行回执 → 要求 Transit 的 timing/career 自这套 claim gate 上线起从未通过。存量问题。
**根因 3career:AmK、marriage:DK):consultation 响应没有 Chara Karaka 数据。**
整个响应中无 Amatyakaraka/Darakaraka 数值层:`chart.modules.jaimini` 只有 `arudha_padas`guided topics 里 DK 的值是空占位符 `- H-`。引擎的 full-reading 路径有现成 karaka 计算(`scripts/jaimini.py`),但 `scripts/jyotish_api_server.py``_attach_local_consultation_layers` 没有把这层挂进 consultation 响应。**前端修不了,必须引擎响应新增字段。**
## 决策记录
产品负责人 2026-09-02 确认修复方向并授权:
- **(a)** 引擎侧允许在 consultation 响应中**新增** Chara Karaka 字段(这是 `TASK-report-skill-parity-20260901.md` 任务 0 预留的"响应新增字段"止损分支,正式启用)。仍然只许新增、不许改动既有字段的键名、形状或语义。
- **(b)** `643f6f7a` / 既有测试中按旧分盘形状手造的 fixture 与断言,属于"锁住本轮要修的缺陷本身",允许按红线 9 的程序修改(注明原值与原因)。
- **(c)** 主题最低证据组(`report-theme-evidence-plan.ts`)**不在授权范围内**:不得为了让主题通过而删除或放宽 AmK/DK/Transit/D2/D11 要求。修法只能是把证据真实供给上。
## 硬红线
1. **最低证据组一条不得放宽**(见决策记录 c)。`demoteThemesMissingRequiredCharts` 兜底保留,不得删除——修好值形状后它自然不触发。
2. **引擎改动只许响应新增字段**:不改既有字段、不改排盘算法、不改 full-reading 路径;新增层必须复用 `scripts/jaimini.py` 既有实现,不得重写 karaka 算法。
3. **fixture 必须来自真实引擎响应**(golden),不得再手造形状。任务 0 是门控:先落 golden fixture 与形状契约测试,任务 1–3 的实现测试必须建立在它之上。
4. 上一轮任务书(`TASK-report-skill-parity-20260901.md`)的红线继续有效:输入隔离不放松、writer 输出 schema 只可收紧、`assertionLevel` 推导与 consensus ≥2 verified 防升级校验一字不改、本轮不改数据库结构、章节串行、telemetry 只记指标名与数值。
5. 隐私红线:fixture 与测试只用虚构 smoke 出生数据;golden fixture 入库前确认不含任何真实用户资料。
6. 推 staging 前 `./node_modules/.bin/tsc --noEmit` 必须通过(**不要用 `npx tsc`**,会装到空包 `tsc@2.0.4`)。不得改 `.gitea/workflows/**`,不得自行提升 main。
7. Python 侧改动必须带单元测试(`.venv` + unittest/pytest,按仓内既有测试形式),并真实跑过。
让步顺序:数据不损坏 > 证据纪律不回退 > 功能与测试不回归 > 可验证的修复 > 成本 > 代码整洁。
## 开工前置
```bash
git fetch origin --prune
git worktree add -b codex/report-blocked-repairs-20260902 \
../.worktrees/report-blocked-repairs-20260902 origin/staging
```
`pre_work_error_ledger.md`,跑 `scripts/pre_work_check.py`,读 `frontend/AGENTS.md`,在 `docs/BUG_HISTORY.md` 检索(BUG-486 及相邻条目与本轮直接相关)。
**先读这几处再动手**
- `frontend/src/lib/personal-report-generation.ts` —— `deriveVargaHousesFromEngine`:336 附近)、`readAllVargaCharts` / `readVargaHouses``VARGA_KEY_ALIASES` 已存在)、`demoteThemesMissingRequiredCharts`、receipt upsert 逻辑
- `frontend/src/lib/report-theme-evidence-plan.ts` —— 各主题 `requiredTechniqueGroups`(只读,不改)
- `scripts/jyotish_api_server.py` —— `_attach_local_consultation_layers``execute_consultation_workflow`
- `scripts/jaimini.py` —— 既有 Chara Karaka 实现
- `git show 45f190a1``git show 643f6f7a` —— 昨日两次治标修复的全部内容
## 复现方法(验收也用它)
起本地引擎:`.venv/bin/python scripts/jyotish_api_server.py --port 5200`。用虚构出生数据(如 1993-06-15 10:30lat 36.42 / lon 114.21 / tz 8)按 worker 的调用方式(`entryMode: "direct_chart"`question `请为个人报告计算 <theme> 主题证据`)对 career/marriage/timing/wealth 各调一次 `runConsultationWorkflow`,把 4 个响应喂给 `buildReportEvidenceBundleV2`,检查 `claimCards` / `blockedSections` / `executionLedger` / `charts`。修复前的预期输出(用于确认复现成功):claimCards 为空、四主题全在 blockedSections、charts 只有 D1。
---
## 任务 0P0,门控)· Golden fixture 与形状契约
### 做法
- 用上述复现方法捕获 4 个主题的真实响应,裁剪成 fixture(保留 `chart.modules.varga_full`(至少 D2/D9/D10/D11/D24 各一张完整值)、`modules.transits``modules.jaimini``consumer_context`、machine packet sections;删除与提取无关的大块字段以控制体积),入库为测试资产。
- 新增形状契约测试:断言 varga_full 值的真实形状(小写 `ascendant``sign_index``planets` 字典、`house_chart`),并断言 `modules.transits.status` 字段存在。**这个测试在修复前就应该通过**(它锁的是引擎真实形状,不是前端行为)。
-`643f6f7a` 手造的旧形状 fixture 替换为 golden 派生数据;按红线 9 在改动处注明原值与原因。
### 验收
- 形状契约测试直接对 golden fixture 通过;PROGRESS 记录 fixture 的捕获命令与裁剪规则。
---
## 任务 1(P0)· 修分盘值形状,复活结构化分盘图
### 做法
`deriveVargaHousesFromEngine` 兼容真实形状,规则:
- 上升:`varga.ascendant ?? varga.Ascendant`;星座索引 `sign_index ?? sign_idx ?? signIndex(sign)`;度数 `degree ?? degree_in_sign`
- 行星:优先读 `varga.planets` 字典(每行星有 `sign_index``house`,宫位可直接用 `house`,无 `house` 时按整星座宫从上升推导);`planets` 不存在时退回旧的顶层行星键路径(保持对旧形状的兼容,两种形状都要有测试)。
- 不吸收 `house_chart` 以外来源不明的字段;未知键一律不复制。
### 验收
- 单元测试双形状覆盖(golden 新形状 + 既有旧形状)。
- 复现管线跑通后:`charts` 至少含 D1/D2/D9/D10/D11/D24wealth 出 claim card`demoteThemesMissingRequiredCharts` 不触发;D2/D11 回执 executed。
- education / migration_home 等依赖分盘的主题在补充复现(9 主题全请求)中同样解锁,PROGRESS 记录逐主题结果。
---
## 任务 2P0)· Transit 执行回执
### 做法
提取层读 `chart.modules.transits``status === "executed"` 时 upsert `Transit` 回执(`status: "partial"``executed: true`,与 ashtakavarga/dasha_sub_periods 的既有读取方式同风格);`status` 缺失或非 executed 时不产回执(fail closed,不得默认 executed)。
### 验收
- 单元测试:executed / 缺失 / 其他 status 三种输入。
- 复现管线:timing 出 claim cardcareer 的 blocked 理由只剩 AmK(在任务 3 完成前)。
---
## 任务 3P0)· 引擎挂 Chara Karaka + 前端 AmK/DK 回执
### 做法
- 引擎:`_attach_local_consultation_layers` 调用 `scripts/jaimini.py` 既有实现,把 Chara Karaka 挂到 `chart.modules.jaimini.chara_karakas`(结构建议:`{ "AmK": { "planet": ..., ... }, "DK": { ... }, ... }`,具体键名以 jaimini.py 现有输出为准,**新增字段不改既有 `arudha_padas`**)。带 Python 单元测试。
- 前端:从 `modules.jaimini.chara_karakas` 中 AmK/DK 的存在性 upsert `AmK` / `DK` 回执(`partial` + `executed: true`);数据缺失时不产回执。
- golden fixture 用引擎修复后的响应重新捕获(或叠加一份含 karakas 的 golden),形状契约测试同步覆盖新层。
### 验收
- Python 测试:consultation 响应含 `chara_karakas` 且 AmK/DK 数据来自 jaimini.py 现有输出。
- 复现管线:**career/marriage/timing/wealth 四主题全部出 claim cardblockedSections 为空**`executionLedger` 中 AmK/DK/Transit/D2/D11 均 executed。
### 止损
-`jaimini.py` 现有实现无法在 consultation 输入上直接复用(缺参数、口径冲突),**停下**写 `BLOCKED.md`,不得重写算法、不得放宽最低证据组来绕过。
---
## 任务 4(P1)· 端到端与既有欠账
- 全套质量门:frontend `tsc --noEmit` / `eslint`0 error/ `tsx --test`(失败清单与基线逐条比对)/ `next build`Python 相关测试真实跑过。
- 部署后(委托方核对 health gitCommit)真实生成一份 personal_full 报告,验收:四主题有正文、不再全 blocked;顺带补上一轮欠的交付物——真实 writer 输出回溯抽查(≥3 处)与每章实测 `inputTokens`/墙钟对照(对照基线与 2 倍线裁决记录见 `PROGRESS-report-skill-parity-20260901.md``BLOCKED.md` 对应条目)。
## 不在本轮范围
- 主题最低证据组的增删改(决策记录 c)。
- 引擎排盘算法、full-reading 路径、varga_full 既有形状的任何改动。
- 知识包内容、writer prompt、成本优化(沿用已裁决结论)。
- 章节并发、模型更换、计费、数据库结构。
## 收尾
- PROGRESS 文件名写 `PROGRESS-report-blocked-repairs-20260902.md`
- `docs/BUG_HISTORY.md` 新增条目(编号先对远端确认;根因 1 与 BUG-486 关联,注明 45f190a1/643f6f7a 是治标、本轮治本)。
- 建议两次推送:任务 0+1+2(纯前端)一次;任务 3(引擎+前端)一次。staging push 触发全量构建+部署,全链路约 20 分钟,推送后核对 `https://staging.jyotisha.chat/api/health``.deployment.gitCommit`
- 不自行提升 main。
## 交付物清单
1. Golden fixture(真实响应派生)+ 形状契约测试;643f6f7a 旧 fixture 的替换说明
2. `deriveVargaHousesFromEngine` 双形状兼容 + 测试;复现管线中 charts/D2/D11 复活证据
3. Transit 回执提取 + 三态测试
4. 引擎 `chara_karakas` 新增层 + Python 测试;前端 AmK/DK 回执 + 测试
5. 复现管线修复前后对照:blockedSections 从 4 → 0claimCards 从 0 → 4(9 主题全请求的逐主题表)
6. 部署后真实报告验收 + 上一轮欠账(writer 输出回溯抽查、实测 tokens/墙钟对照)
7. `docs/BUG_HISTORY.md` 条目、`BLOCKED.md`(任何触发止损的项)、`PROGRESS-report-blocked-repairs-20260902.md`
8. 全套质量门实际输出(frontend 四件 + Python 测试)