Files
Jyotisha/docs/tasks/TASK-report-english-edition-20260929.md
T

10 KiB
Raw Blame History

TASK · 个人报告中英两版 · 2026-09-29

执行方:coding agent。验收:Claude。 分支 codex/report-english-edition-20260929,worktree .worktrees/report-english-edition-20260929。 串行依赖:必须在 TASK-report-reader-polish-20260929.md 合入 staging 之后,基于当时的 origin/staging 开工。两单都改 report-actions.tsx、report-export-drawer.tsx、scripts/pl9_reader_export.py。

0. 基线

  • 写单时的 origin/staging 是 5febb111;开工基线以 reader-polish 合入后的实测 SHA 为准,写进 docs/tasks/PROGRESS-report-english-edition-20260929.md。
  • 开工前必读 AGENTS §9 预检(涉及引擎输出),跑 python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45。

1. 事实(行号按符号定位)

  1. 报告全文由程序生成,不经过模型。 personal-report-longform-generate.ts → fetchLongformMarkdown 调 Python /api/professional_report_reference(edition: "reader_main")。scripts/professional_report_reference.py → build_professional_report_reference 只算一次 full_reading,再由 pl9_reader_export._pl9_export_markdown_for_edition 渲染成 Markdown。
  2. 中文是「先按 PL9 英文口径渲染,再逐词汉化」得到的。 pl9_reader_export.py → _render_pl9_user_markdown → _sanitize_pl9_public_markdown → _strip_pl9_user_engineering_markers:这几个函数用 replacements、nakshatra_terms、glossary_terms、natural_replacements、cleanups 几张表,把英文术语、工程词替换成中文。模板里还有约 440 行直接写死的中文(章节标题,例如 '## 强度、关系与 Ashtakavarga 技术页(PL9 p30-p60 对标)')。
  3. 语言开关已经埋了,但基本没用上:_pl9_report_language(packet) 读 packet['report_language'],只有 2 处用到。
  4. 瑜伽规则库 references/yoga_rules.json:共 477 条,启用 406 条。每条有英文 name,但 effects、条件描述、combo_template(如 "{a}与{b}同在第{h}宫")只有中文。
  5. scripts/reader_dasha_applicability.py 有 20 行中文。前端的 fact tables、图盘标签(report-fact-table-display、chartAriaLabel、chartBlockText 里的「第 N 宫」)是中文写死的。
  6. 存储:计算快照存在 personal_report_sections,保留行 section_id = "longform-calculation-snapshot-v1",内容是 personal-report-longform-snapshot.ts → snapshotSchema(strictObject,version: 1,字段有 markdown、contentSha256、factTables、charts、readerDashaApplicability),经 complete_personal_report_section RPC 写入。另有 personal_report_longform_appendices 表,每份报告存一份 markdown。
  7. 虚构案例 golden frontend/tests/fixtures/report-reader-main-fictional.json:77,208 字符,其中汉字 10,418 个,不同的中文片段 381 个。

2. 决策记录(产品 2026-09-29 授权)

  1. 每份新报告都同时有中文版和英文版,用户不用单独操作。
  2. 英文版不用模型逐份翻译。做法是同一次引擎计算、同一个 packet 渲染两遍:report_language = zh 一遍,= en 一遍。这样两版数字必然一致,也不增加模型费用和计算次数。(Claude 原先按「报告由模型撰写」估的 A/B/C 三个方案,前提不成立,全部作废。)
  3. 词典类中文内容(瑜伽效果和条件、模板标题、Dasha 适用性说明、前端表头)要补静态英文对照,提交进仓库。执行方可以借助模型起草译文,但运行时不得调用模型。术语采用 PL9 / BPHS 通行的英文写法(Exalted、Debilitated、Own Sign、Mooltrikona、Sub-lord …)。
  4. 英文版是从属产物:英文渲染失败或检查不通过时,只把英文版标成不可用,中文报告照常 ready,不能因为英文版失败让整份报告失败。
  5. 英文版上线前生成的报告不补英文版(旧快照只存了中文 markdown,没有 packet,补译需要重算,数字可能漂移)。这类报告的阅读页不显示语言切换,导出弹窗里提示一句「这份报告生成于英文版上线前,重新生成即可获得中英两版」。
  6. 阅读页操作栏加「中文 / English」切换,语言写进 URL(?lang=en),刷新后保持。切换只换报告正文、目录、图盘标签、核对表;应用外壳(侧栏、标题栏、按钮)保持中文。
  7. 导出弹窗导出当前语言的版本,英文文件名加 -EN。当前是中文且有英文版时,弹窗顶部显示提示:「要拿去问 ChatGPT、Claude 等 AI?建议切到 English 再导出,术语与原典一致,AI 读得更准。」旁边给一个按钮直接切到英文。文案最终版对照 VOICE.md。

3. 硬红线

  1. 中文版逐字节不变:用同一 packet 渲染,本单前后 golden 的中文 markdown 必须完全相同(diff 为空)。
  2. 英文版不得含汉字:re.search(r'\p{Script=Han}', md_en) 必须为空(Python 用 regex 模块,或用 [㐀-鿿豈-﫿])。检查不通过时,按决策 4 把英文版标成不可用,不得带着汉字发出去。
  3. 两版数字一致:从中、英 markdown 按顺序抽取数字 token(度数、日期、分数、宫号),两个序列必须相等。这条写成合同测试。
  4. 英文版同样要过公开投影与泄漏检查(projectOrdinaryReportMarkdown、ordinaryOutputLeaks),以及 Python 侧的英文版工程词清洗。parameter_sensitive、source_path 这类工程词在英文版里也要换成公开措辞,不得原样透出。
  5. 不新增重计算:引擎只算一次,一次请求返回两种语言;不得前端再发一次引擎请求。
  6. 优先不动数据库:英文内容放进快照 payload(snapshotSchema 升 version: 2,新增 en 子对象,包含 markdown、sha、可选的 readerDashaApplicability)。v1 快照必须仍能读取(旧报告)。确实需要加列时,按 AGENTS §7-6 只能加、不能改或删,并真跑 npm run test:db。
  7. golden 必须来自真实引擎输出(AGENTS §7-4),用虚构出生资料;不得手造形状。
  8. scripts/jyotish_api_server.py 不得增长;新代码放进 professional_report_reference.py、pl9_reader_export.py 或新模块。

4. 任务分解

编号 内容 验收标准
E1 引擎:/api/professional_report_reference 接受 languages: ["zh","en"],同一 packet 渲染两遍,响应新增 markdown_en(和 reader_dasha_applicability_en)。不传时行为与现在完全相同 定向测试:不传 languages 时响应逐字节等于基线;传入时中文版等于基线,英文版无汉字,数字序列相等
E2 pl9_reader_export 英文路径:report_language == 'en' 时跳过汉化表,只做英文版工程词清洗;模板标题补英文(去掉 PL9 pNN 页码,与中文版一致);reader-polish 定下的新标题和新表头也要有英文对应(Planet / Sign lord / Star lord / Sub lord / Sub-sub lord / Status / Strength) 多个虚构案例(至少 3 个:昼生、夜生、南半球)英文 golden 无汉字;人工抽读 20 处并在进度记录列出
E3 yoga_rules.json 406 条启用规则补 effects_en、combo_template_en(以及渲染中用到的其他中文字段的英文版);reader_dasha_applicability.py 补英文 合同测试:每条启用规则都有非空英文字段且不含汉字;英文模板的占位符集合与中文模板一致
E4 前端生成链:fetchLongformMarkdown 请求两种语言;快照 v2 存英文版;英文检查失败时只写中文,并记录 en_unavailable 原因码 单测:英文缺失或含汉字时,报告仍然 ready,英文标为不可用;v1 快照可读
E5 路由:GET /api/reports/:id 在有英文版时返回 longformMarkdownEn(经公开投影) route-core 单测覆盖有英文、无英文、旧报告三种情况
E6 阅读页:语言切换(?lang=en);目录、懒渲染、到底部按钮在英文版下正常;buildLongformOutline 的 EAGER_H2 等中文正则补英文对应;核对表、图盘标签的英文映射 组件测试:切换后正文、目录、表头全部变成英文;无英文版时不渲染切换
E7 导出弹窗:导出当前语言,英文文件名加 -EN;AI 提示与「切到 English」按钮(§2-7);旧报告显示提示文案(§2-5);预估文件大小按当前语言计算 单测:导出内容等于当前语言的块;提示只在「中文 + 有英文版」时出现
E8 文档:DESIGN.md(切换控件、提示条)、VOICE.md(新增英文口径说明)、CONTEXT.md(术语:报告语言版本)、CHANGELOG.md 同一提交内更新

5. 让步顺序

E7 的 AI 提示和 E6 的 URL 持久化可以最后做。E1~E5 与红线 1~4 不让步。英文译文质量不达标时,宁可英文版标成不可用,也不发半中半英的报告。

6. 开工前置命令

git fetch origin --prune
git log --oneline origin/staging | grep -i "reader-polish\|report-reader-polish"   # 确认前置单已合入
git worktree add -b codex/report-english-edition-20260929 .worktrees/report-english-edition-20260929 origin/staging
cd .worktrees/report-english-edition-20260929
python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45
grep -oE "BUG-[0-9]{4}" docs/BUG_HISTORY.md | sort -u | tail -1
cd frontend && npm test 2>&1 | grep -E "^(not )?ok [0-9]+ - " | sed -E 's/^(not )?ok [0-9]+ - //' | sort > /tmp/names-before.txt

7. BUG 编号

本单是新功能,原则上不占 BUG 号。开发中发现的缺陷(例如汉化替换误伤、快照读取问题)从 reader-polish 用完后的下一个号起,按实际占用顺延,并写进进度记录。

8. 交付与验收口径

  • 前端四件套(tsc、lint、test 名单只增不减、build 后 / 仍 Static,首屏 gzip ±2%);Python 定向测试加 run_quality_gate.py --profile quick。
  • 部署后在 staging 用受控账号生成一份新报告,确认:中文版与改动前观感一致;English 切换可用;导出的英文文件不含汉字。没有受控账号时,写进 BLOCKED.md 与 docs/testing/report-english-edition-20260929.md,不得写成「通过」。