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
10 KiB
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 的对话中授权:
- 新建一个不消耗点数、不调模型的只读星历页。
- 内容三段:今日五要素(Panchanga)、当日行运(含相对本命上升的宫位)、未来九十天换座与停滞。
- 日期可前后切换。
- 这一页是天象本身,不是对用户的判断。页面不得出现任何运势结论。
- 页面底部固定一个出口:「带这天去提问」,把当前日期带进对话。免费层的职责是把人送进对话,不是死胡同。
- 不做竞品那种「每月取一个采样点 + 套模板」的年度报告——我们已经有真报告,加一个糊出来的月历只会和它打架。
硬红线
frontend/src/app/page.tsx在origin/staging上 1951 行,上限 2000 且不得再增长。本页必须是独立 route。- 不得扣点、不得调模型。 新增 BFF 不许 import
@/lib/consultation-billing、不许 import@/mastra。这一页出现 spinner / 骨架 / 「正在加载」即为不通过。 - 不得做任何运势解释。 事件列表只写「某星 进入 某座」「某星 停滞转顺 · 度数」,不得附加一个字的含义。Yoga / Karana 的吉凶字段来自引擎,可以照搬标签,但不得展开成建议。
- 不得做三套坐标系之间的换算或叠加。
tsc --noEmit通过;npm run lint0 error;next build后/仍○ Static;首屏 gzip ±2%。- 测试总数不得低于开工时实测;改既有断言要写「原值 / 新值 / 原因」三栏。
- 不改数据库结构、不动迁移。
- 改 UI 的同一提交内更新
frontend/DESIGN.md;文案对照frontend/docs/VOICE.md。 - 一行后端代码都不许改(
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.tsx、frontend/src/app/chart/**、frontend/src/app/api/chart-view/**、frontend/src/components/personal-report/**、frontend/src/components/rectification-*。
三方共享、只许追加各自小节:docs/BUG_HISTORY.md、CHANGELOG.md、frontend/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.ts(runtime = "nodejs"、maxDuration、jyotishApiBase、createServerSupabaseClient、ACCOUNT_BIRTH_SELECT + globalBirthProfileFromAccountRow、consumeUserRequestRateLimit),但不 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/
三段,顺序固定:
- 日期条:前一天 / 后一天 / 「今天」。三个都是 ≥44px 的真按钮。
- 今日五要素:Vara、Tithi、Nakshatra(含第几足)、Yoga、Karana。桌面五张卡一行,手机改成一张卡里的五行(标签左、值右)。
- 当日行运:九个星体的星座与度数、相对本命宫位、顺逆。桌面表格,手机堆叠行。
- 未来九十天:按日期升序的事件列表,只写事实。
底部一张卡:一句「这一页是天象本身,不是对你的判断」+ 主按钮「带这天去提问」(把当前日期带进新对话)。
验收标准
tsc --noEmit0 错;npm run lint0 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",而账户默认岁差自 80102459(2026-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.md记 BUG-707,状态investigating:写清现象、复现、影响面(星盘页 vs 星历页口径分裂)。不要猜根因、不要顺手改默认值。- qizheng 单也记了同一现象(BUG-703
investigating)。开工时若发现对方已经记了,关联它、不要重复开号,把本单的编号让出来。
- qizheng 单也记了同一现象(BUG-703
验收标准
- 五要素段出现该说明,行运段不出现。
docs/BUG_HISTORY.md有对应记录,或明确关联 BUG-703。
让步顺序
- 先保证 任务 1 + 任务 2 的前三段(日期条 / 五要素 / 当日行运)。这三段不依赖新端点,可以完全独立交付。
- 「未来九十天」可以只落
unavailable形态,等/api/ephemeris_events上线再点亮。 - 「带这天去提问」若接对话的链路复杂,可以先做成跳到新对话并预填日期文本。
- 不可让步:不碰
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 单 700–703、chart-page 单 704–706、本单 707–709。任务 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追加本单。