From e37f8272badba33759060f2ff410f412250389a2 Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Wed, 2 Sep 2026 09:40:44 +0000 Subject: [PATCH] =?UTF-8?q?docs(report):=20add=20blocked-repairs=20task=20?= =?UTF-8?q?brief=20=E2=80=94=20varga=20shape,=20transit=20receipt,=20karak?= =?UTF-8?q?as=20layer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_016P5RoqzmUQEbeC2qjAkeGr --- TASK-report-blocked-repairs-20260902.md | 171 ++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 TASK-report-blocked-repairs-20260902.md diff --git a/TASK-report-blocked-repairs-20260902.md b/TASK-report-blocked-repairs-20260902.md new file mode 100644 index 00000000..2a58ee5b --- /dev/null +++ b/TASK-report-blocked-repairs-20260902.md @@ -0,0 +1,171 @@ +# 任务书 · 个人报告全主题 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` 大概率同源。) + +**根因 2(timing、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 上线起从未通过。存量问题。 + +**根因 3(career: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:30,lat 36.42 / lon 114.21 / tz 8)按 worker 的调用方式(`entryMode: "direct_chart"`,question `请为个人报告计算 主题证据`)对 career/marriage/timing/wealth 各调一次 `runConsultationWorkflow`,把 4 个响应喂给 `buildReportEvidenceBundleV2`,检查 `claimCards` / `blockedSections` / `executionLedger` / `charts`。修复前的预期输出(用于确认复现成功):claimCards 为空、四主题全在 blockedSections、charts 只有 D1。 + +--- + +## 任务 0(P0,门控)· 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/D24;wealth 出 claim card,`demoteThemesMissingRequiredCharts` 不触发;D2/D11 回执 executed。 +- education / migration_home 等依赖分盘的主题在补充复现(9 主题全请求)中同样解锁,PROGRESS 记录逐主题结果。 + +--- + +## 任务 2(P0)· 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 card;career 的 blocked 理由只剩 AmK(在任务 3 完成前)。 + +--- + +## 任务 3(P0)· 引擎挂 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 card,blockedSections 为空**;`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 → 0,claimCards 从 0 → 4(9 主题全请求的逐主题表) +6. 部署后真实报告验收 + 上一轮欠账(writer 输出回溯抽查、实测 tokens/墙钟对照) +7. `docs/BUG_HISTORY.md` 条目、`BLOCKED.md`(任何触发止损的项)、`PROGRESS-report-blocked-repairs-20260902.md` +8. 全套质量门实际输出(frontend 四件 + Python 测试)