Files
Jyotisha/docs/tasks/TASK-ephemeris-page-20260915.md
T
Jesse_ChenandClaude Opus 5 6f74aa6704 docs(tasks): brief the read-only chart and ephemeris pages
Splits the remaining work into three briefs that own disjoint files so
agents can run them in parallel. The qizheng brief is widened to own
scripts/jyotish_api_server.py outright and register all three read-only
endpoints (/api/qizheng, /api/western, /api/ephemeris_events), because
the chart page needs a tropical natal route that no path exposes today
and the ephemeris page needs ingress/station scanning that /api/transit
does not provide.

The chart-page brief owns app-sidebar.tsx and adds both nav entries; the
ephemeris-page brief owns only its own route. Checking the tree changed
one plan: vedic-chart-svg.tsx is also imported by rectification-board, so
the component stays where it is instead of moving to a shared layer.

BUG ranges are pre-allocated per brief to keep parallel work from
colliding, and the panchanga Lahiri/Raman split found while prototyping
is filed as investigating rather than fixed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
2026-09-15 07:09:23 +00:00

10 KiB
Raw Blame History

TASK-ephemeris-page-20260915 · P1 星历页

基线

  • 代码基线:origin/staging = 2d7698ea(文档树基线 b3ccef4c,纯文档提交,代码未变)。
  • 并行关系:本单与 TASK-qizheng-native-chart-20260915(后端)、TASK-chart-page-20260915(前端星盘页)同期并行。三份单没有共享代码文件,见「文件归属」。
  • 原型:会话内已交付可点原型(桌面 1440 与手机 390 两套,日期箭头可点,三天数据全部实跑)。实现以本单文字为准,原型作为视觉与信息层级参照。
  • Skill 版本 6.9.16,本单不 bump

为什么要有这一页

引擎侧已经算得出、但产品层一条都没露的东西:

引擎有没有 现在露没露
Panchanga 五要素 有,/api/panchanga_range 没露,只作为模型的输入
行运位置 有,/api/chart 传任意日期即可 没露
换座与顺逆停滞 需要新端点(由 qizheng 单交付 /api/ephemeris_events 从来没做
「今日」 有,/api/daily-starlanguage 露了,但是模型生成的三句话45 秒超时、烧点数

也就是说,连「今天的五要素是什么」这种纯查表的东西,现在都要让模型去说一遍。这一页把它们直接摆出来:秒开、零点数、不调模型

决策记录

产品负责人在 2026-09-15 的对话中授权:

  1. 新建一个不消耗点数、不调模型的只读星历页。
  2. 内容三段:今日五要素Panchanga)、当日行运(含相对本命上升的宫位)、未来九十天换座与停滞
  3. 日期可前后切换。
  4. 这一页是天象本身,不是对用户的判断。页面不得出现任何运势结论。
  5. 页面底部固定一个出口:「带这天去提问」,把当前日期带进对话。免费层的职责是把人送进对话,不是死胡同。
  6. 不做竞品那种「每月取一个采样点 + 套模板」的年度报告——我们已经有真报告,加一个糊出来的月历只会和它打架。

硬红线

  1. frontend/src/app/page.tsxorigin/staging1951 行,上限 2000 且不得再增长。本页必须是独立 route。
  2. 不得扣点、不得调模型。 新增 BFF 不许 import @/lib/consultation-billing、不许 import @/mastra。这一页出现 spinner / 骨架 / 「正在加载」即为不通过。
  3. 不得做任何运势解释。 事件列表只写「某星 进入 某座」「某星 停滞转顺 · 度数」,不得附加一个字的含义。Yoga / Karana 的吉凶字段来自引擎,可以照搬标签,但不得展开成建议
  4. 不得做三套坐标系之间的换算或叠加。
  5. tsc --noEmit 通过;npm run lint 0 errornext build/○ Static;首屏 gzip ±2%。
  6. 测试总数不得低于开工时实测;改既有断言要写「原值 / 新值 / 原因」三栏。
  7. 不改数据库结构、不动迁移。
  8. 改 UI 的同一提交内更新 frontend/DESIGN.md;文案对照 frontend/docs/VOICE.md
  9. 一行后端代码都不许改scripts/jyotish_api_server.py 归 qizheng 单独占);不许改 frontend/src/components/app-sidebar.tsx(归 chart-page 单独占)。

文件归属(并行前提)

本单拥有frontend/src/app/ephemeris/**frontend/src/app/api/ephemeris/**frontend/src/components/ephemeris/**frontend/src/lib/ephemeris-*.ts

本单不许碰scripts/**deploy/**vendor/**frontend/src/components/app-sidebar.tsxfrontend/src/app/chart/**frontend/src/app/api/chart-view/**frontend/src/components/personal-report/**frontend/src/components/rectification-*

三方共享、只许追加各自小节docs/BUG_HISTORY.mdCHANGELOG.mdfrontend/DESIGN.md。合入顺序 qizheng → chart-page → ephemeris-page;本单最后合,rebase 时按各自小节重放,不得覆盖对方。

侧边栏入口由 TASK-chart-page-20260915 交付(它会同时加「星盘」「星历」两个入口)。本单只交付 /ephemeris 这个 route 本身;在对方合入前,页面通过直接访问 URL 验收。

任务分解

任务 1 · BFF 路由 frontend/src/app/api/ephemeris/route.ts

骨架参照 frontend/src/app/api/daily-starlanguage/route.tsruntime = "nodejs"maxDurationjyotishApiBasecreateServerSupabaseClientACCOUNT_BIRTH_SELECT + globalBirthProfileFromAccountRowconsumeUserRequestRateLimit),但不 import 计费与 mastra。

  • 入参:目标日期(默认今天,按用户时区)。出生资料只从服务端自有资料读。
  • 上游调用:
    • /api/panchanga_range(五要素)
    • /api/chart(目标日期的行运位置;宫位由「行运星座号 − 本命上升星座号」推出)
    • /api/ephemeris_events(未来九十天换座与停滞,由 qizheng 单交付
  • 端点未上线的降级/api/ephemeris_events 不可用时该字段返回 unavailable,页面渲染静态说明,不得抛错、不得让整页失败
  • 响应窄合同 + zod 校验,新增 frontend/src/lib/ephemeris-contract.ts
  • 未登录返回 401。未设置出生资料时,五要素仍可返回(它与本命盘无关),行运的「相对本命」字段置空并注明。

验收标准

  • 新增 frontend/tests/ephemeris-route.test.ts:未登录 401;无出生资料时五要素仍返回、相对本命为空;ephemeris_events 不可用时降级;响应通过 zod 校验。
  • fixture 来自真实引擎响应golden),不得手造形状。
  • 断言未触发任何计费路径。

任务 2 · 页面 frontend/src/app/ephemeris/

三段,顺序固定:

  1. 日期条:前一天 / 后一天 / 「今天」。三个都是 ≥44px 的真按钮。
  2. 今日五要素Vara、Tithi、Nakshatra(含第几足)、Yoga、Karana。桌面五张卡一行,手机改成一张卡里的五行(标签左、值右)。
  3. 当日行运:九个星体的星座与度数、相对本命宫位、顺逆。桌面表格,手机堆叠行。
  4. 未来九十天:按日期升序的事件列表,只写事实。

底部一张卡:一句「这一页是天象本身,不是对你的判断」+ 主按钮「带这天去提问」(把当前日期带进新对话)。

验收标准

  • tsc --noEmit 0 错;npm run lint 0 error。
  • 组件测试:日期前后切换会换掉五要素与行运;unavailable 时事件段渲染静态说明;手机宽度下五要素为纵向一张卡。
  • 正文 ≥ 14px,12–13px 只给短标签与元信息;触摸目标 ≥ 44px。
  • frontend/DESIGN.md 追加「星历页」小节。
  • 文案对照 frontend/docs/VOICE.md逐条检查不含运势判断

任务 3 · 岁差口径标注(BUG-707)

立单时实跑发现的真实缺陷,本单必须在界面上诚实标出来:

/api/panchanga_range 的响应里 report.calculation_policy.panchanga 写的是 "SwissEph Lahiri at sunrise-relative reference time",而账户默认岁差自 801024592026-08-20)起已经是 Raman/api/chart 也确实按 Raman 算。

后果:同一个用户,在星盘页看到的是 Raman 盘,在星历页看到的五要素却是 Lahiri 口径。

复现:

POST /api/panchanga_range {"start_date":"2026-09-14","end_date":"2026-09-16","lat":31.19,"lon":121.44,"tz":8,"ayanamsa":"raman"}
读 report.calculation_policy.panchanga

本单的处置(不要越界)

  • 不修。统一到 Raman 还是明确声明 panchanga 永远用 Lahiri,是产品决策,另出单。
  • 五要素卡片下方必须出现一行说明:这一段按 Lahiri 计算,与星盘页的岁差设置不同。措辞对照 frontend/docs/VOICE.md,不得写成故障或道歉。
  • 行运段用的是 /api/chart,走账户岁差,这一段不要加这句——否则会误导。
  • docs/BUG_HISTORY.mdBUG-707,状态 investigating:写清现象、复现、影响面(星盘页 vs 星历页口径分裂)。不要猜根因、不要顺手改默认值。
    • qizheng 单也记了同一现象(BUG-703 investigating)。开工时若发现对方已经记了,关联它、不要重复开号,把本单的编号让出来。

验收标准

  • 五要素段出现该说明,行运段不出现。
  • docs/BUG_HISTORY.md 有对应记录,或明确关联 BUG-703。

让步顺序

  1. 先保证 任务 1 + 任务 2 的前三段(日期条 / 五要素 / 当日行运)。这三段不依赖新端点,可以完全独立交付
  2. 「未来九十天」可以只落 unavailable 形态,等 /api/ephemeris_events 上线再点亮。
  3. 「带这天去提问」若接对话的链路复杂,可以先做成跳到新对话并预填日期文本。
  4. 不可让步:不碰 page.tsx、不碰 sidebar、不扣点不调模型、无 spinner、页面无运势判断、任务 3 的岁差标注。

开工前置命令

cd /workspace/Jyotisha
git status -sb
git fetch origin --prune
git worktree add -b codex/ephemeris-page-20260915 .worktrees/ephemeris-page-20260915 origin/staging
cd .worktrees/ephemeris-page-20260915/frontend
npm ci
./node_modules/.bin/tsc --noEmit
npm run lint
npm test 2>&1 | tail -20                          # 记下测试总数
npx next build 2>&1 | grep -E "^[│├└]| / " | head # 记下 `/` 的 Static 标记与首屏 gzip
wc -l src/app/page.tsx                            # 应为 1951

BUG 编号起点

origin/staging 上当前最大号 BUG-699。三份并行单预分配:qizheng 单 700703、chart-page 单 704706、本单 707709。任务 3 用 BUG-707(若 qizheng 单已记 BUG-703,改为关联,本单不另开号)。

进度与记录

  • 进度记录:docs/tasks/PROGRESS-ephemeris-page-20260915.md,本单状态板一行。
  • 环境缺口写 BLOCKED.md
  • 真人验收清单写进 docs/testing/:日期前后切换、五要素随日期变化、事件列表降级形态、「带这天去提问」真的把日期带进了对话。
  • CHANGELOG.md 写用户可感知的变化,注明 Skill 版本未 bump
  • 索引:docs/tasks/README.md 追加本单。