Files
Jyotisha/docs/tasks/TASK-chart-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

12 KiB
Raw Blame History

TASK-chart-page-20260915 · P0 星盘事实页(五个 Tab)

基线

  • 代码基线:origin/staging = 2d7698ea(文档树基线 b3ccef4c,纯文档提交,代码未变)。
  • 并行关系:本单与 TASK-qizheng-native-chart-20260915(后端)、TASK-ephemeris-page-20260915(前端星历页)同期并行。三份单没有共享代码文件,见「文件归属」。
  • 原型:会话内已交付可点原型(五个 Tab 的完整形态、中宫排盘参数卡、三套坐标系边界文案、桌面 1440 与手机 390 两套)。原型里的数据全部是实跑引擎输出,不是编的;实现时以本单文字为准,原型作为视觉与信息层级参照。
  • Skill 版本 6.9.16,本单不 bump(不新增解读口径,只把已算出的事实露出来)。

为什么要有这一页

当前产品里,用户填完出生资料看不见自己的盘

  • VedicChartSvgfrontend/src/components/personal-report/vedic-chart-svg.tsx,只被三处引用——personal-report-document-view.tsxpersonal-report-markdown-view.tsx(用其中的 NorthIndianChartSvg)、rectification-board.tsx。也就是说,盘面只在已生成报告校正进行中才出现。
  • 侧边栏「星盘资料」是 ChartLibraryPanelfrontend/src/components/chart-library-panel.tsx),只管出生资料的增删改查,不画盘
  • 结果:第一次看见自己的盘必须先花点数、等模型。

而引擎侧 /api/chart/api/dasha/chara/api/nakshatra_full 早就在;星宿与 Pada 在 scripts/dasha_analyzer.py 已经算出来。这一页不新增任何计算,只是把已有结果摆出来。

决策记录

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

  1. 新建一个不消耗点数、不调模型、打开即有的只读星盘页。
  2. Tab 顺序定为 星盘 / 基础信息 / 大运 / 西洋盘 / 七政四余
  3. 体系分在 Tab 这一层;分盘 chip(D1–D30)只在印度体系内部使用。不得把西洋盘或七政四余做成第 13 个 chip。
  4. 盘的中宫放「排盘参数卡」:钟表时间与校正状态、出生地与经纬、岁差与交点模式、上升与月亮星宿、当前大运分运、引擎名。手机上放不下,只留岁差两行,完整参数改成盘下方一张卡。
  5. 三套坐标系必须各自在中宫写明自己是什么,并显式点名不能互相换算,也不得把两边结论叠加成「双重印证」。
  6. 「传统象征」词条层可以做,但必须带边界句「是词条式释义,不是对你个人的判断」,且不得出现任何运势判断

本单推翻的一处早期说法

立单核对时发现:VedicChartSvg 并非「只被 personal-report 引用」,rectification-board.tsx 也在用。因此本单不搬这个文件。 新页面直接从现有路径 @/components/personal-report/vedic-chart-svg 引入。搬家会同时碰校正热点文件,与并行的校正轮次冲突;若将来要搬,单独一轮只做搬家。

硬红线

  1. frontend/src/app/page.tsxorigin/staging 上是 1951 行AGENTS.md §6 定了 2000 行上限且「不得再增长」。本页必须是独立 route,一行都不许加进 page.tsx
  2. 不得搬动 vedic-chart-svg.tsx,见上。也不得改动它的导出签名——三个既有调用点必须零改动。
  3. 不得扣点、不得调模型。 新增的 BFF 路由不许 import @/lib/consultation-billing 或任何 mastra agent。这一页出现 spinner / 骨架 / 「正在加载」即为不通过(AGENTS.md §6:揭幕后不得出现加载动画,流式生成中除外)。
  4. ./node_modules/.bin/tsc --noEmit 通过;npm run lint 0 error
  5. next build/ 仍是 ○ Static;首屏 gzip 变化在 ±2% 内,超出要在进度记录里给出原因。新 route 自身不要求 Static(它读账户数据)。
  6. 测试总数不得低于开工时 origin/staging 的实测。改任何既有断言必须写「原值 / 新值 / 原因」三栏。
  7. 不改数据库结构;本单不得顺带动迁移。
  8. 改 UI 的同一提交内更新 frontend/DESIGN.md;新文案先对照 frontend/docs/VOICE.md
  9. 一行后端代码都不许改,特别是 scripts/jyotish_api_server.py——它归 TASK-qizheng-native-chart-20260915 独占。

文件归属(并行前提)

本单拥有

  • frontend/src/app/chart/**(新 route
  • frontend/src/app/api/chart-view/**(新 BFF
  • frontend/src/components/chart-page/**(新组件目录)
  • frontend/src/components/app-sidebar.tsx —— 本单独占。本单同时加「星盘」与「星历」两个入口,星历页那一单不碰这个文件。
  • frontend/src/lib/chart-view-*.ts

本单不许碰scripts/**deploy/**vendor/**frontend/src/app/ephemeris/**frontend/src/app/api/ephemeris/**frontend/src/lib/ephemeris-*.tsfrontend/src/components/personal-report/**frontend/src/components/rectification-*

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

任务分解

任务 1 · BFF 路由 frontend/src/app/api/chart-view/route.ts

按既有路由的写法(参照 frontend/src/app/api/daily-starlanguage/route.ts 的骨架:export const runtime = "nodejs"maxDurationjyotishApiBase = process.env.JYOTISH_API_BASE ?? "http://127.0.0.1:5200"createServerSupabaseClientACCOUNT_BIRTH_SELECT + globalBirthProfileFromAccountRowconsumeUserRequestRateLimit),但:

  • 不 import consultation-billing、不 import @/mastra
  • 出生资料只从服务端自有资料读,不接受前端传入的出生参数(沿用 server-owned-birth-profile 的既有边界)。
  • 未登录返回 401
  • 上游调用:/api/chart(主)+ /api/dasha/charaChara 大运)。
    • 坑,必须照做/api/dasha 单独调会忽略月亮黄经、回默认 Ketu balance;大运要从 /api/chart 响应的 dasha 段取。/api/dasha/chara/api/varga_full 必须把 planetsascendanthouses 一起传进去,否则返回 planets must include longitude data
  • 西洋盘与七政四余走 /api/western/api/qizheng(由 qizheng 单交付)。这两个端点未上线时,本路由对应字段返回 unavailable,不得抛错、不得让整页失败。
  • 响应是一个窄合同(新增 frontend/src/lib/chart-view-contract.ts,zod 校验),只含页面要用的字段,不透传引擎全量响应。

验收标准

  • 新增 frontend/tests/chart-view-route.test.ts:未登录 401;资料不全返回结构化提示而非 500;/api/western/api/qizheng 不可用时该字段为 unavailable 且其余 Tab 正常;响应通过 zod 校验。
  • fixture 必须来自真实引擎响应(golden),不得手造形状(AGENTS.md §7.4)。
  • 全程零扣点:测试里断言未调用任何计费路径。

任务 2 · 页面与五个 Tab frontend/src/app/chart/

页面结构按原型:页眉(眉标「直接计算 · 打开即有 · 不消耗点数」+ 标题 + 出生资料一行)→ 五个 Tab → 内容区。

  • 星盘:D1–D30 分盘 chip(一行可换行)+ 盘面 + 右侧行星位置表(星体 / 星座与度数 / 宫位 / 状态)。盘面复用 VedicChartSvg从现有路径引入,不搬文件)。
  • 基础信息:每个星体一张卡——D1 落座与宫位、本命星宿 + 第几足 + 星宿主、D9 落座、传统象征一行(灰字 + 顶部边界卡)。
  • 大运Vimshottari 与 Chara 两条轨并列,当前段高亮。底部固定一句:只有两条同时指向同一段时间才算证据,单轨命中降一级置信度。
    • Chara 的正式名称是 Chara Dashakn_rao 变体),引擎 method 字段就这么写的,不要写成 Narayana
    • 分运(antardasha)若从引擎拿不到,可以按标准比例从大运边界推,但必须在界面上注明「按标准比例推出,不是引擎单独返回的字段」
  • 西洋盘:圆盘(外圈黄道十二宫、Placidus 不等宽宫位、上升在左、度数逆时针)+ 元素模式分布 + 主要相位表。右栏第一张必须是边界卡。
  • 七政四余:十二地支宫方格(巳午未申在上,寅丑子亥在下)+ 人事宫 + 所辖宿 + 十一曜宿度表。必须出现三条口径:宿度自角宿起算、计都派别、庙旺未闭合。

中宫排盘参数卡:桌面放六行;手机上盘宽只有约 318px,中宫塞不下,只留岁差两行,完整参数改成盘下方一张卡。原型里这两种形态都画了。

验收标准

  • tsc --noEmit 0 错;npm run lint 0 error。
  • 新增组件测试:五个 Tab 都能切换;unavailable 的 Tab 渲染静态说明而不是报错;手机宽度下中宫只有两行且完整参数卡出现在盘下方。
  • 视觉:frontend/DESIGN.md 追加「只读星盘页」小节,写清 Tab 体系边界、中宫参数卡、三套坐标系的各自标注。
  • 文案对照 frontend/docs/VOICE.md
  • 触摸目标 ≥ 44px;正文 ≥ 14px,12–13px 只给短标签与元信息(DESIGN.md §3)。盘内 SVG 文字按缩放后实际像素计,不得低于 12px。

任务 3 · 侧边栏入口(本单独占)

  • frontend/src/components/app-sidebar.tsx(367 行)在「新建对话」之后、「我的报告」之前新增两个入口:星盘星历
  • 两个入口都要有折叠态图标(DESIGN.md「Sidebar shell · Collapsed content」要求折叠时仍可达)。
  • 当前项使用既有的白玻璃面 + 2px 深棕标记,不得新造一套选中态。
  • 星历入口现在会指向一个尚未存在的 route(由 TASK-ephemeris-page-20260915 交付)。本单先建一个最小占位页 frontend/src/app/ephemeris/page.tsx不。 本单不创建 ephemeris 目录(归属对方)。做法:星历入口在对方 route 落地前指向 /ephemeris,本地开发会 404,这是预期的;在进度记录里写明,并在 PR 描述里注明合入顺序。

验收标准

  • 侧边栏三态(桌面展开 288px / 平板折叠 64px / 手机抽屉)下两个入口都可达。
  • frontend/tests/touch-target-contract.test.ts 通过。
  • 不得改动既有入口的顺序与文案。

让步顺序

  1. 先保证 任务 1 + 任务 2 的前三个 Tab(星盘 / 基础信息 / 大运)。这三个不依赖任何新端点,可以完全独立交付
  2. 西洋盘、七政四余两个 Tab 可以只落 unavailable 形态,等对方端点上线再点亮。
  3. 「传统象征」词条层可以延后;延后时基础信息卡只保留事实三行。
  4. 不可让步:不碰 page.tsx、不搬 vedic-chart-svg.tsx、不扣点不调模型、无 spinner、三套坐标系的边界标注、/ 仍 Static。

开工前置命令

cd /workspace/Jyotisha
git status -sb
git fetch origin --prune
git worktree add -b codex/chart-page-20260915 .worktrees/chart-page-20260915 origin/staging
cd .worktrees/chart-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

无 Docker 时 npm run test:db 的失败清单要与基线逐条比对,写进 BLOCKED.md,不得写成「通过」。

BUG 编号起点

origin/stagingdocs/BUG_HISTORY.md 当前最大号 BUG-699。三份并行单预分配:qizheng 单 700703、本单 704706、ephemeris-page 单 707709。本单是新功能,正常情况下不需要开 BUG 号;只有实现中发现既有缺陷才用,用满要通知另外两单整体后移。

进度与记录

  • 进度记录:docs/tasks/PROGRESS-chart-page-20260915.md,本单状态板一行。
  • 环境缺口写 BLOCKED.md(预期:无 Docker → test:db 阻塞;无登录态与 Chrome → 浏览器级走查留给 docs/testing/)。
  • 真人验收清单写进 docs/testing/:五个 Tab 切换、手机宽度中宫两行、折叠侧边栏两个入口可达、未登录跳转。
  • CHANGELOG.md 写用户可感知的变化,注明 Skill 版本未 bump
  • 索引:docs/tasks/README.md 追加本单。