Files
Jyotisha/docs/tasks/TASK-report-skill-parity-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

178 lines
14 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.
# 任务书 · 个人报告内容对齐 skill 解读深度(2026-09-01
基线:`origin/staging` @ `8617eb56`
## 为什么要做
个人报告的目标体验是"像本地 Agent 调用 jyotish skill 那样解盘"。当前管道做不到,且存在一个**结构性矛盾**:
1. **引擎算了,管道丢了。** Python 引擎的 `/api/consultation_workflow` 响应里已经带全量 `chart``scripts/jyotish_api_server.py:2406` 整体透传),其中 `chart.ai_prompt_pack.evidence_snapshot``scripts/jyotish_engine.py` ~1700–1790 行)包含:功能吉凶星表、shadbala 排名、SAV 分值、当前 Mahadasha/Antardasha、dasa convergence top domains、`career_narrative` / `relationship_narrative` / `finance_narrative`(服务器生成的中文 headline/strengths/risks/boundaries,见 `_build_career_narrative_payload` 等,~1264 行起);`chart.modules.yoga.yogas` 有 Yoga 名单;`chart.modules.guided_topics` 有逐主题的证据化条目。**报告路径的提取层把这些全部丢弃**:`frontend/src/lib/personal-report-generation.ts``buildReportEvidencePacket`(:484)只留行星/宫位/上升、两条 Dasha 时间线、varga 宫位占据和技法执行回执。
2. **Claim card 是回执,不是结论。** `buildReportEvidenceBundleV2`:991claim card 构造在 :11211144)产出的 `conclusion` 是模板句"服务器已闭合XX所需的最低证据组…",`supportingFacts` 是"D9 已执行并纳入本主题证据计划"。里面没有任何占星学结论。
3. **写作端被合同锁死。** `frontend/src/mastra/personal-report.ts` 的指令与 `skills/jyotish-personal-report/SKILL.md` 都规定:claimCards 是唯一结论来源,不得从盘面自行推导含义。结论来源没有结论 → 写作模型要么输出空洞合规文本,要么悄悄违规解读原始盘面(schema 查不出来)。
4. **写作端没有任何解读方法论。** 本地 Agent 调 skill 时能读 `references/` 下 188 个解读文件(宫位含义、现代措辞、误区纠正、判读方法);报告写作模型一个字都拿不到。
## 决策记录(覆盖既有默认,执行方据此放行)
产品负责人 2026-09-01 确认并授权本轮三件事:
- **(a)** 扩展 `ReportEvidenceBundleV2`,承载服务器生成的解读性事实与主题叙事种子(来源仅限引擎响应中服务器自产字段,仍走 allowlist + 净化 + 确定性校验);
- **(b)** claim card 的 `conclusion` / `supportingFacts` 从执行回执升级为真实占星结论(内容全部由服务器确定性投影生成,不引入模型自由发挥);
- **(c)** 为写作 agent 注入**静态、蒸馏过的**解读知识包(产品自有语料,非用户数据)。
**授权不包括**:放松输入隔离(聊天史、工具轨迹、raw workflow、SKILL.md 原文仍不得进写作 prompt)、放松 writer 输出 schema、改变 assertionLevel 推导与防升级校验、改数据库结构。
## 硬红线
1. **输入隔离不放松。** 写作 agent 仍然 no skills / no tools / no memory。进入 prompt 的只有:过滤后的 bundle、section plan、已完成标题、以及任务 3 的静态知识包。知识包内不得含文件路径、内部模块名、引擎/供应商名、prompt 模板或任何用户数据。
2. **Bundle 内自由文本只许来自服务器自产生成器**(叙事种子、guided topic 文案)。用户 `question` 文本、模型历史输出一律不得写入 bundle。所有新字段必须有长度上限、数量上限与字符净化,Zod 校验保持 `.strict()`
3. **writer 输出 schema 只可收紧,不可放宽。** `assertionLevel` 防升级校验(`validateReportEvidenceBundleV2` 中 consensus ≥2 verified 等规则)一条不得删改。
4. **本轮不得改数据库结构、不得新增迁移。** `personal_report_sections` / `report_document` 语义不变。
5. **章节串行生成的既有红线延续**,不得顺手并发化。
6. **成本必须被证明可控。** bundle 变大后,每章 prompt 必须沿用 `filterReportEvidenceBundleForSection``personal-report-generation.ts:2178` 附近)的过滤思路:新增的解读性事实与知识包都要按主题裁剪,只随本章下发。PROGRESS 里给改前改后的每章 `inputTokens` 对照;若 p50 超过改前 2 倍,停下摆数据,不得直接接受。
7. **隐私红线延续**:测试与 fixture 只用虚构 smoke 出生数据;telemetry 只记指标名与数值,不得记 bundle、叙事、知识包内容。
8. 推 staging 前 `./node_modules/.bin/tsc --noEmit` 必须通过(**不要用 `npx tsc`**,会装到空包 `tsc@2.0.4`)。不得改 `.gitea/workflows/**`,不得自行提升 main。
9. **不得修改既有测试断言**——除非该断言锁的正是本轮要改的缺陷本身(claim card 回执文案、bundle 字段清单属于此类);改动必须在断言上方注明原值与原因,并在 PROGRESS 单列。
让步顺序:数据不损坏 > 隔离与真相边界不回退 > 功能与测试不回归 > 可验证的内容改进 > 成本 > 代码整洁。
## 开工前置
```bash
git fetch origin --prune
git worktree add -b codex/report-skill-parity-20260901 \
../.worktrees/report-skill-parity-20260901 origin/staging
```
`pre_work_error_ledger.md`,跑 `scripts/pre_work_check.py`,读 `frontend/AGENTS.md`,改前在 `docs/BUG_HISTORY.md` 检索同类记录。
**先读这几个文件再动手**
- `frontend/src/lib/personal-report-generation.ts` —— `buildReportEvidencePacket``buildReportEvidenceBundleV2`、claim card 构造、`filterReportEvidenceBundleForSection`
- `frontend/src/lib/report-evidence-bundle-v2.ts` —— bundle schema、canonical 序列化与 hash、防升级校验
- `frontend/src/mastra/personal-report.ts` —— writer 指令、`sectionPrompt``cachedSystemMessage` 用法
- `frontend/src/mastra/consultation-workflow.ts` —— workflow 响应契约(`chart` 为 passthrough record
- `scripts/jyotish_engine.py` ~1264–1830 —— 叙事种子生成器与 `_build_ai_prompt_pack`
- `skills/jyotish-personal-report/SKILL.md` —— 报告 skill 合同(任务 3 需同步更新)
---
## 任务 0(P0,门控)· 固定引擎响应契约快照
### 做法
- 用**虚构 smoke 出生数据**真实调用一次本地 Python API `/api/consultation_workflow`(每个报告主题各一次即可),把响应中后续任务依赖的字段**存在性与类型**(只记 key 路径和类型,不记值)写进 PROGRESS:
- `chart.ai_prompt_pack.evidence_snapshot.functional_benefic_malefic`
- `chart.ai_prompt_pack.evidence_snapshot.strength.shadbala_ranking` / `.sav_scores`
- `chart.ai_prompt_pack.evidence_snapshot.timing.vimshottari`(含 antardasha/ `.convergence_top_domains`
- `chart.ai_prompt_pack.evidence_snapshot.career_narrative` / `relationship_narrative` / `finance_narrative`
- `chart.modules.yoga.yogas`
- `chart.modules.guided_topics`
- 据此在前端新增**契约 fixture 测试**(合成数据),锁住任务 1 的提取函数对这些路径的读取行为。
### 验收
- PROGRESS 有逐字段的存在性清单。
- 某字段实际缺失时:该解读层在后续任务中标记为不可提取并**跳过**,不得伪造,不得为此大改 Python 引擎(真要补引擎字段属于止损分支,单独说明改动面,只允许在响应中**新增**字段)。
---
## 任务 1(P0)· Bundle 承载解读性事实
### 做法
`report-evidence-bundle-v2.ts``ReportEvidenceBundleV2` 新增两组字段(`schemaVersion` 字面量保持 `report_evidence_bundle.v2`,新字段全部必填但允许空数组/null,保持 `.strict()`):
1. `interpretiveFacts`(结构化、闭合词表优先):
- `yogas``{ name(≤80, 净化 pattern), category(闭合枚举,按引擎实际输出归并), planets(celestial 枚举数组), evidenceRef }[]`,数量上限 40
- `functionalRoles``{ planet(celestial 枚举), role(benefic|malefic|neutral|yogakaraka 等闭合枚举), evidenceRef }[]`
- `shadbalaRanking``{ planet, rank(int), rupa(number|null) }[]`(相对强弱定位,上限 9
- `savScores``{ house(1-12), score(number) }[]` + `savTotal(number|null)`
- `currentDasha``{ mahadasha, antardasha, start, end }`(沿用既有 dashaPeriod 校验)
- `convergenceDomains``string[]`(≤6 条,每条 ≤80 字符,净化)
2. `themeNarrativeSeeds`:按主题 `{ theme, headline(≤300), strengths(string[] ≤8×≤400), risks(string[] ≤8×≤400), boundaries(string[] ≤8×≤400), evidenceRefs }[]`——内容只允许来自引擎叙事种子生成器与 `guided_topics` 文案字段,写入前做长度截断与控制字符过滤。
`personal-report-generation.ts`
- `buildReportEvidencePacket` / `buildReportEvidenceBundleV2` 新增对上述路径的提取(allowlist 风格:未知 key 永不复制;行星/宫位经既有 `safeCelestialName` / 枚举净化)。
- **确定性要求**:新增数组在构建端排序(进 `sortedBundleContent` 的规范化范围),保证 `bundleHash` 可复现;hash 计算覆盖新字段。
- `filterReportEvidenceBundleForSection` 同步扩展:`themeNarrativeSeeds` 只保留本章主题;`interpretiveFacts` 按该章 `evidenceRefs` / 主题相关性裁剪(yoga、功能吉凶为通用层可全量保留,但要在 PROGRESS 用数据说明每章 prompt 增量)。
### 验收
- 单元测试:给定任务 0 的 fixture,断言提取出的每类事实的条数、净化行为(非法行星名被丢弃、超长截断)、以及 bundle hash 在字段顺序扰动下不变。
- `validateReportEvidenceBundleV2` 对新增字段的越界输入(超长、未知枚举、非法 ref)fail closed。
---
## 任务 2P0)· Claim card 从回执升级为结论
### 做法
`buildReportEvidenceBundleV2` 的 claim card 构造(:11211144):
- `conclusion`:由该主题的叙事种子 headline + 最多 2 条 strengths **确定性拼装**(无种子时回退到现状回执文案并把 `assertionLevel` 压到不高于 `single_system_inference`)。
- `supportingFacts`:从 `interpretiveFacts` 与叙事种子生成真实事实条目(如"D10 已执行;A10/Karma Pada 进入主链"),每条绑定真实存在的 evidenceRefrisks 进 `counterFacts`boundaries 进 `verificationQuestions` 或保留在种子内由 writer 引用。
- `assertionLevel` 推导规则**一字不改**;不得因内容变富而提升级别。
- blocked 主题逻辑不变。
同步收紧 writer 侧:`personal-report.ts` 指令中"Use its claimCards exclusively for narrative conclusions"保持,并明确 `themeNarrativeSeeds` / `interpretiveFacts` 属于可引用事实层。
### 验收
- 单元测试:有种子主题的 conclusion 含真实占星内容且非模板句;无种子主题回退且级别受压;consensus 校验回归测试全绿。
- 端到端一份 smoke 报告:抽查任一 write 章节,叙事中出现的 yoga 名/强弱/大运表述均能回溯到 bundle 内条目(人工抽查 3 处,PROGRESS 记录)。
---
## 任务 3(P1)· 写作端静态解读知识包
### 做法
- 新建 `frontend/src/lib/report-interpretation-packs/`(纯静态 TS 常量或构建期内联的文本),**从本仓 `references/` 蒸馏**(重点:`modern-language-guide.md``common-misconceptions.md``house-domain-planet-mapping.md`、各主题判读要点)。每主题一个包 + 一个通用包;单包 ≤ 3,000 字符;内容只写"怎么解释、怎么措辞、哪些断语禁止",不写具体人的断语,不含路径/内部名词。
-`createPersonalReportAgent` 的章节调用里,把「通用包 + 本章主题包」放进 `cachedSystemMessage` 缓存边界之前的系统内容,吃 prompt cache;摘要调用只带通用包。
- 更新 writer 指令与 `skills/jyotish-personal-report/SKILL.md`(版本号 +1):知识包仅约束**措辞与解释方式**,不得据此产生 bundle 之外的新占星断言;claimCards + interpretiveFacts + 叙事种子仍是唯一事实来源。
### 验收
- 单元测试:每个主题都能解析到知识包;知识包内容通过一个"违禁词/路径扫描"断言(不含 `references/``scripts/`、引擎名、`SKILL.md` 字样等)。
- 端到端对照:同一 smoke 盘改前改后各生成一次,PROGRESS 给出两版任一相同主题章节全文对照与每章 `inputTokens`(含 cache 命中)对照。
### 止损
- 知识包导致每章 `inputTokens` p50 超改前 2 倍且 cache 未命中:先查 `cachedSystemMessage` 是否生效,不得直接砍证据来凑成本。
---
## 任务 4P2)· 观测与对照
- telemetry(沿用现有隐私边界)补记每章 bundle 内 `interpretiveFacts` 条数与知识包字符数(数值,不记内容)。
- staging 部署后真实生成一份报告,PROGRESS 给出:章节数、每章 in/out tokens、总墙钟时间、与改前(PROGRESS-report-sectioned-20260830.md 的数据)对照。
## 不在本轮范围
- 写作 agent 的工具循环 / 只读检索工具(P2 另立项)。
- MEVG / web 验证接入报告端。
- Python 引擎侧新增计算模块或改动既有模块输出(除任务 0 止损分支允许的"响应新增字段")。
- 聊天路径(consultation-tools / agent-reply)的证据消费方式。
- 章节并发、模型更换、计费改动。
## 收尾
- PROGRESS 文件名写 `PROGRESS-report-skill-parity-20260901.md`(不要写成 `PROGRESS.md`)。
- 任务 0 可与任务 1–2 合并推送;任务 3 建议单独一次推送便于对照。staging push 触发全量构建+部署,流水线 `validate``publish``deploy` 全链路约 20 分钟,推送后核对 `https://staging.jyotisha.chat/api/health``.deployment.gitCommit`
- 不自行提升 main。
## 交付物清单
1. 任务 0 契约快照(字段存在性清单 + fixture 测试)
2. bundle 新字段 schema + 提取 + 净化 + hash 覆盖 + fail-closed 测试
3. `filterReportEvidenceBundleForSection` 的主题裁剪扩展与每章 prompt 增量数据
4. 实质化 claim cards + 回退与级别压制逻辑 + consensus 回归测试
5. 端到端抽查记录:叙事内容可回溯到 bundle(≥3 处)
6. 解读知识包目录 + 违禁词扫描测试 + `skills/jyotish-personal-report/SKILL.md` 更新
7. 改前改后同盘同主题章节全文对照 + tokens/墙钟对照
8. `docs/BUG_HISTORY.md` 条目(编号先对远端确认)
9. `BLOCKED.md`:任何触发止损的项
10. `PROGRESS-report-skill-parity-20260901.md`
11. `tsc --noEmit` / `eslint`0 error/ `tsx --test`(失败清单与基线逐条比对)/ `next build` 的实际输出