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
288 lines
22 KiB
Markdown
288 lines
22 KiB
Markdown
# TASK-qizheng-native-chart-20260915 · 接入原生七政四余排盘,并开出三个只读计算端点
|
||
|
||
> **2026-09-15 修订(立单当天)**:本单扩了范围。原版只做 `/api/qizheng`;核对后发现 P0 星盘页与 P1 星历页还各缺一个后端端点,而三者都要改 `scripts/jyotish_api_server.py`。为了让后续两份前端单能真并行,**把三个端点的注册全部收进本单**,由本单独占该文件的写权。两份前端单一行后端代码都不碰。
|
||
|
||
## 基线
|
||
|
||
- 代码基线:`origin/staging` = `2d7698ea`(`fix(chat): keep stored rectification titles on open`)。
|
||
- 上游来源:`/workspace/yinduzhanxing`,分支 **`codex/add-birth-time-rectification-skill`**,commit **`a911c890`**(`feat: add native qizheng chart adapter`,2026-09-15 14:14 +0800)。
|
||
- 注意:上游 `main` 仍是 `a6f47abd`(2026-09-03),即我们 09-03 那轮已同步的 commit。本单要的东西**只在这条分支上**,不在 main。
|
||
- 同分支另有 `6c27aab6 fix: harden report export and validation gates` 与 `8bba9cb5 docs: record 2026-09-15 governance audit`,**不在本单范围**,不要顺手带进来。
|
||
- Skill 版本:`6.9.16`,本单**不 bump**(不新增解读口径,只新增计算与只读接口)。
|
||
- 开工前置检查已在立单时跑过:`scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45` 全绿(python_runtime / fragment_scan / external_engine_adapters / remote_visibility / focused_tests 均 ok)。执行方开工时必须**重跑**。
|
||
|
||
## 上游带来了什么
|
||
|
||
`a911c890` 的实质不是继续做考据,而是**vendored 了一个开源引擎**:
|
||
|
||
| 文件 | 说明 |
|
||
| --- | --- |
|
||
| `scripts/qizheng_chart_engine.py` | 168 行纯适配器,`subprocess` 调 vendored CLI |
|
||
| `vendor/stem-branch/dist/cli.cjs` | **45,963 行 / 2.68 MB** 单文件 bundle |
|
||
| `vendor/stem-branch/{LICENSE,README.md,package.json}` | `@4n6h4x0r/stem-branch` **0.8.0**,**Apache-2.0** |
|
||
| `scripts/jyotish_api_server.py` | +10 行,挂 `/api/qizheng` |
|
||
|
||
**许可证是本单能立的前提**:Apache-2.0 是 permissive,与本仓 MIT 兼容(对照:PyJHora 是 AGPL,只能黑盒对数,见 `docs/research/open_source_integration_priority_table_2026_07_03.md`)。Apache-2.0 §4 要求保留 LICENSE 与 attribution,任务 1 里必须落实。
|
||
|
||
### 立单前的实测(在本机跑通,不是读代码推断)
|
||
|
||
用示例出生资料 `1990-04-09T13:24:00+08:00 / 31.19N 121.44E`:
|
||
|
||
```
|
||
bodies: 七政(日月水金火木土)+ 四余(罗睺 计都 月孛 紫炁),共 11 曜
|
||
太阳 宿度 177.94 奎 7.44° 亥宮 陷
|
||
罗睺 宿度 112.09 女 5.09° 丑宮 平
|
||
紫炁 宿度 33.34 房 0.34° 卯宮 平
|
||
palaces: 12(地支宮 + 人事宮 + 所辖宿 + 占星)
|
||
ascendant: 星宿 · 午宮 aspects: 27 dignities: 11 曜全有
|
||
```
|
||
|
||
宿度自角宿初度起算,内部自洽(太阳 177.94 = 奎宿累计 + 7.44)。
|
||
|
||
## 事故实证
|
||
|
||
以下三条全部是实跑复现的,**不是猜测**。复现命令见每条末尾(`CLI` 指 `vendor/stem-branch/dist/cli.cjs`)。
|
||
|
||
### 实证 1 · 四柱时柱按 UTC 墙钟计算(BUG-700)
|
||
|
||
vendored CLI 的 `--pillars` 读的是 UTC 墙钟,不是出生地本地时间:
|
||
|
||
| 传入 | 引擎回的时柱 | 应为 |
|
||
| --- | --- | --- |
|
||
| `1990-04-09T13:24:00+08:00` | 丁**卯**(卯时 = 05–07 时) | 辛**未** |
|
||
| `1990-04-09T13:24:00`(裸) | 辛**未** | 辛未 ✓ |
|
||
| `1990-04-09T13:24:00+00:00` | 辛**未** | — |
|
||
|
||
而上游适配器 `scripts/qizheng_chart_engine.py` 的 `_iso_local()` **带偏移量**输出(`f"...{sign}{offset_hours:02d}:{offset_minutes:02d}"`)。也就是说:**一旦把 `--pillars` 接到同一个适配器上,每个中国用户的时柱都会错 8 小时**,午夜前后日柱也会跟着错。
|
||
|
||
`--seven-governors` 不受影响:天文量要的正是正确的 UTC 时刻,带偏移量是对的。
|
||
|
||
```
|
||
node CLI --date "1990-04-09T13:24:00+08:00" --lat 31.19 --lng 121.44 --pillars --json
|
||
node CLI --date "1990-04-09T13:24:00" --lat 31.19 --lng 121.44 --pillars --json
|
||
```
|
||
|
||
这条与 `docs/BUG_HISTORY.md` 的 BUG-245 / BUG-905 是同一族防复发条款(「所有星盘计算入口必须统一补算历史 offset」),必须在新记录里关联。
|
||
|
||
### 实证 2 · 计都派别被写死,且未暴露(BUG-701)
|
||
|
||
引擎回 `ketuMode: "apogee"`。实测计都落在 **亢 15.46°**,月孛 **亢 14.23°**——两者只差 1.2°,**不是罗睺的对点**(罗睺 女 5.09°,对点应在 133° 附近)。
|
||
|
||
这是真实的派别分歧,换一派整张盘变。上游适配器的 `boundary` 文案提了紫气 / 庙旺 / 限法差异,**唯独没提 ketu mode**,请求侧也没有参数可以选。
|
||
|
||
### 实证 3 · boundary 文案与实际输出不符(BUG-702)
|
||
|
||
上游 `_normalize()` 的 boundary 写:
|
||
|
||
> 「已生成完整七政四余本命结构:七政、四余、二十八宿、十二宫、命宫、相位、**神煞**和**当前庙旺**字段。」
|
||
|
||
实测:
|
||
|
||
- `starSpirits: 0` —— **神煞是空的**。
|
||
- `dignities` 11 曜里,除太阳记「陷」外**全部返回「平」**。
|
||
|
||
第二条对得上上游自己的台账:`references/oracle/qizheng_runtime_truth_closure_status_2026_08_29.json` 的 `promotion_decision.may_update_runtime_dignity_table = false`,`runtime_promotable_count = 0`;`qizheng_positive_layer_runtime_gate_2026_08_30.json` 63 格**全部 blocked**;十一体 × 十二宫共 132 格的庙旺表只拿到 **9 格**直接证据。
|
||
|
||
**庙旺这一列现在没有可用的判定,只能当占位。**
|
||
|
||
## 根因
|
||
|
||
1. vendored 引擎把「天文时刻」和「历法干支」用了同一个时间入口,前者要 UTC、后者要本地民用时,混用导致时柱错位。
|
||
2. 适配器把派别选择(`ketuMode`、`siderealMode`)当成引擎内部细节透传,没有提升为产品参数。
|
||
3. boundary 文案是按引擎**能力清单**写的,不是按**本次实际输出**写的,于是把空字段说成已生成。
|
||
|
||
## 决策记录
|
||
|
||
产品负责人在 2026-09-15 的对话中授权:
|
||
|
||
1. **接入七政四余原生排盘**,走 vendored `stem-branch`(Apache-2.0)路线,不再自己做 132 格考据。
|
||
2. **本单只做引擎与只读接口**,前端另出一单(原因见「范围边界」)。
|
||
3. **不做八字 / 四柱**。`--pillars` 存在实证 1 的缺陷,本轮不修、不调用;只把它记成红线与 BUG,避免后来者踩。
|
||
4. **计都派别与宿度起算口径必须让用户看得见**,按岁差(`ayanamsa`)既有的做法处理成显式参数,不接受引擎默认静默生效。
|
||
5. **庙旺不得进入任何结论**。它可以出现在响应里,但必须带 `unclosed` 标记;解读层、报告层、咨询层一律不得引用。
|
||
|
||
本单不推翻既有红线。特别地,AGENTS.md §6「`scripts/jyotish_api_server.py` must not grow」继续有效,见任务 3 的硬上限。
|
||
|
||
## 硬红线
|
||
|
||
1. **`--pillars` / `--luck` / `--polaris` / `--qimen` / `--liuren` 等其余子命令,本单一律不得调用。** vendored CLI 里有它们,但只有 `--seven-governors` 在本单验收范围内。
|
||
2. **绝不把带时区偏移的 ISO 字符串喂给需要本地民用时的子命令。** 若将来要做四柱,必须先解决实证 1,并在 `docs/BUG_HISTORY.md` 关联 BUG-700 / BUG-245 / BUG-905。
|
||
3. **宿度不是恒星黄经。** 引擎的 `siderealLon` 自角宿初度起算,与本仓 Raman / Lahiri 恒星黄经、与西洋回归黄道都不是同一套。响应里必须显式标注坐标系,任何界面都不得做三套之间的度数换算,也不得把两套结果叠加成「双重印证」。
|
||
4. **庙旺(dignities)不得进入结论。** 见决策记录 5。
|
||
5. `scripts/jyotish_api_server.py` **不得新增 handler 主体**,只允许薄注册,见任务 3。
|
||
6. `frontend/src/app/page.tsx` 在 `origin/staging` 上是 **1951 行**,不得再增长;本单不碰前端。
|
||
7. 不得顺手升级依赖、不得顺手修不在本单里的 warning;发现了写进 `BLOCKED.md` 或进度记录。
|
||
8. 不得把 `/workspace/yinduzhanxing` 当作运行主仓;从它那里只取 `a911c890` 的文件内容,不引用它的路径。
|
||
|
||
## 范围边界
|
||
|
||
**本单做**:vendored 归档、镜像 Node runtime、适配器、只读接口、测试、Bug 记录。
|
||
|
||
**本单不做**:任何前端文件。
|
||
|
||
**并行与文件归属**。同期还有两份前端单,三份单之间**没有任何共享代码文件**,可以并行开工:
|
||
|
||
| 文件 / 目录 | 归属 |
|
||
| --- | --- |
|
||
| `vendor/**`、`NOTICE`、`deploy/**` | 本单 |
|
||
| `scripts/qizheng_chart_engine.py`、`scripts/ephemeris_events.py` | 本单 |
|
||
| **`scripts/jyotish_api_server.py`** | **本单独占**。两份前端单一行都不许改 |
|
||
| `tests/**`(本单新增的三个文件) | 本单 |
|
||
| `frontend/src/app/chart/**`、`frontend/src/app/api/chart-view/**`、`frontend/src/components/app-sidebar.tsx` | `TASK-chart-page-20260915` |
|
||
| `frontend/src/app/ephemeris/**`、`frontend/src/app/api/ephemeris/**`、`frontend/src/lib/ephemeris-*.ts` | `TASK-ephemeris-page-20260915` |
|
||
| `docs/BUG_HISTORY.md`、`CHANGELOG.md`、`frontend/DESIGN.md` | 三方都写,**只许追加各自小节**,合入顺序 本单 → chart-page → ephemeris-page |
|
||
|
||
前端对本单的依赖是**运行时依赖,不是代码依赖**:端点没上线时,前端对应区块渲染静态说明,端点合入后自然点亮。
|
||
|
||
原型(五个 Tab 的完整形态、中宫排盘参数卡、三套坐标系的边界文案)已经画好,两份前端单都会引用它。
|
||
|
||
## 任务分解
|
||
|
||
### 任务 1 · vendored 归档与 API 镜像 Node runtime
|
||
|
||
**这是后续全部任务的阻塞项,必须先完成。**
|
||
|
||
- 从上游 `a911c890` 取入以下四个文件,路径保持一致:
|
||
`vendor/stem-branch/LICENSE`、`vendor/stem-branch/README.md`、`vendor/stem-branch/package.json`、`vendor/stem-branch/dist/cli.cjs`。
|
||
- 新增仓库根 `NOTICE`(或在既有归属文件中追加):注明 `@4n6h4x0r/stem-branch` 0.8.0、Apache-2.0、上游地址与取入 commit。Apache-2.0 §4 要求保留 LICENSE 与 attribution,这一条是合规必需,不是可选。
|
||
- `deploy/railway-api.Dockerfile`:装 **Node.js 运行时**(当前基底是 `python:3.12-slim`,全文无 node / npm)。只要运行时,不要 npm、不要构建工具链;装完清理 apt 列表,与既有 `build-essential` 的 purge 写法保持一致风格。
|
||
- 同文件新增 `COPY vendor ./vendor`(现有 COPY 列表在第 17–22 行区间:`SKILL.md mcp_server.py` / `assets` / `jyotish_vedic` / `references` / `scripts` / `skills`)。
|
||
- `deploy/gated-paths.txt`:新增 `vendor/**`。**当前清单里没有它**,不加的话 vendored 引擎的任何改动都不会触发门禁、不会重建镜像。
|
||
|
||
**验收标准**
|
||
|
||
- 本地构建 API 镜像成功;容器内 `node --version` 有输出。
|
||
- 容器内 `python -c "from pathlib import Path; assert Path('/app/vendor/stem-branch/dist/cli.cjs').exists()"` 通过。
|
||
- `/api/health` 仍为 `200` 且 `swisseph_available = true`。
|
||
- 镜像体积变化(MB)写进 `docs/tasks/PROGRESS-qizheng-native-chart-20260915.md`;超过 +150 MB 要说明原因。
|
||
- 无 Docker 时:把构建与容器内验证写进 `BLOCKED.md`,并给出宿主机上 `node --version` 与 CLI 实跑的替代证据,**不得写成「通过」**。
|
||
|
||
### 任务 2 · 适配器 `scripts/qizheng_chart_engine.py`
|
||
|
||
以上游 168 行版本为起点,但必须做以下修改:
|
||
|
||
- **派别参数化**:`ketu_mode`、`sidereal_mode` 从请求体读取,缺省值在模块常量里写死并回写进响应的 `calculation` 段。响应必须能让调用方看出这次用的是哪一派。
|
||
- **boundary 文案按实际输出重写**:不得出现「神煞」(实测为空);庙旺必须标注为未闭合,附上 `references/oracle/qizheng_runtime_truth_closure_status_2026_08_29.json` 的口径(132 格只闭合 9 格、`runtime_promotable_count = 0`)。
|
||
- **坐标系标注**:响应顶层显式带 `coordinate_system: "qizheng_mansion_degrees_from_jiao"`(命名可调,但必须一眼看出不是恒星黄经、不是回归黄道)。
|
||
- **错误路径**:`node` 不存在、CLI 文件缺失、超时、stdout 非 JSON、CLI 非零退出——五种都要落到结构化错误,不得 500,不得把 stderr 原文整段外泄。
|
||
- 保留 `raw_engine_output` 供审计,但确认其中不含任何本机路径或环境信息。
|
||
|
||
**验收标准**
|
||
|
||
- 新增 `tests/test_qizheng_chart_engine.py`:
|
||
- fixture 来自**真实引擎响应**(golden),不得手造形状(AGENTS.md §7.4)。
|
||
- 覆盖:11 曜齐全、12 宫齐全、命宫存在、`coordinate_system` 存在、`ketu_mode` 可被请求覆盖且回写、庙旺带未闭合标记、boundary 不含「神煞」。
|
||
- 覆盖五种错误路径各一条。
|
||
- `.venv/bin/python -m pytest tests/test_qizheng_chart_engine.py` fail=0。
|
||
- `.venv/bin/python scripts/run_quality_gate.py --profile quick` 通过。
|
||
|
||
### 任务 3 · 三个只读端点薄注册(本单独占 `scripts/jyotish_api_server.py` 写权)
|
||
|
||
- 在 `scripts/jyotish_api_server.py` 的路由分支处新增一条 `elif path == '/api/qizheng':`。参照点:`origin/staging` 上 `elif path == '/api/chart':` 在 **3497 行**。
|
||
- handler 用既有的 `_load_local_module('qizheng_chart_engine')` 模式(该函数已存在,见 137 / 413 / 1009 行的用法),函数体 **≤ 8 行**,只做加载、调用、把领域异常翻成 `BadRequest`。
|
||
- **行数硬上限**:`origin/staging` 上该文件是 **11313 行**,契约上限是 **11363**(`tests/test_api_server_growth_contract.py`,baseline 11063 + 300 余量),**总余额只有 50 行**。三个端点加起来,本轮对该文件的净增 **不得超过 32 行**。超了就把 handler 再压薄,不要动契约。
|
||
- 端点是只读计算,按既有重计算端点的口径纳入 `JYOTISH_HEAVY_COMPUTE_CONCURRENCY` 限流(默认 2,饱和 429)。CLI 子进程 20 秒超时要与限流口径对得上。
|
||
|
||
#### 3b · `/api/western`(回归黄道本命盘)
|
||
|
||
前端「西洋盘」Tab 需要,但**当前没有任何路由暴露它**:`scripts/western_chart_engine.py` 的 `build_tropical_natal_chart` 只在 `/api/consult` 内部被 `_western_evidence_packet_from_body` 间接调用(见 `jyotish_api_server.py:2205`)。
|
||
|
||
- 新增 `elif path == '/api/western':`,薄注册直接调 `build_tropical_natal_chart`(**不要**走 `build_tropical_western_evidence_packet`,那条带 `route_packet` 是咨询链概念)。
|
||
- `house_system` 从请求读,默认 `P`(Placidus),回写进响应。
|
||
- 响应必须显式带坐标系标注(`zodiac: "tropical"` 引擎已有,再加一条人类可读的边界句),并写明与恒星黄道的岁差差值。
|
||
- handler 函数体 ≤ 8 行。
|
||
|
||
#### 3c · `/api/ephemeris_events`(区间换座与停滞)
|
||
|
||
前端「未来九十天」需要。`/api/transit` 返回的是**对本命的触发点**(`transit_trigger.search_all_transit_triggers`,见 `jyotish_api_server.py:9947` 一带),**不是换座与顺逆停滞**,不能复用。
|
||
|
||
- 新增模块 `scripts/ephemeris_events.py`(**计算主体放这里,不进 api_server**):给定起止日期、岁差、交点模式,逐日扫描并返回 `ingress`(进入星座)与 `station`(停滞转顺 / 转逆)两类事件。
|
||
- 区间上限与既有过境端点对齐(`transit search range must be <= 730 days`,见 `jyotish_api_server.py:9929`),超限返回 400。
|
||
- 岁差必须按请求参数走,**不得写死**(附录里那条 panchanga 写死 Lahiri 的教训就在这)。
|
||
- 新增 `elif path == '/api/ephemeris_events':`,handler 函数体 ≤ 8 行。
|
||
- 参考实现口径(立单时用 pyswisseph 实跑过,`1990` 那组资料 2026-09-15 起 90 天、Raman、六星体得到 **14 条**事件):逐日取黄经与速度,星座号变化记 ingress,速度符号翻转记 station。
|
||
|
||
**验收标准**
|
||
|
||
- `.venv/bin/python -m pytest tests/test_api_server_growth_contract.py` 通过。
|
||
- 新增 `tests/test_qizheng_api_productization.py`(上游同名文件可参考,但断言按本仓合同重写):正常请求返回 11 曜 12 宫;缺 `lat` / `lon` 返回 400 而非 500;node 不可用时返回结构化错误。
|
||
- 新增 `tests/test_readonly_chart_endpoints.py`:`/api/western` 返回十一项行星 + 十二宫 cusp + 相位 + 元素模式分布,`house_system` 可覆盖并回写;`/api/ephemeris_events` 在 90 天窗口返回按日期升序的事件列表,两类事件都有,超过 730 天返回 400,岁差参数生效(同一区间 Raman 与 Lahiri 的结果不相同)。
|
||
- 新增 `tests/test_ephemeris_events.py`:模块级单测,golden 来自真实引擎输出。
|
||
- `curl -s -X POST http://127.0.0.1:5200/api/qizheng -d '{"year":1990,"month":4,"day":9,"hour":13,"minute":24,"lat":31.19,"lon":121.44,"tz":8}'` 的输出贴进进度记录(脱敏不需要,示例资料是虚构的)。
|
||
|
||
### 任务 4 · Bug 记录
|
||
|
||
在**同一变更**内更新 `docs/BUG_HISTORY.md`,新增连续编号(起点见下):
|
||
|
||
- **BUG-700**|vendored 引擎四柱时柱按 UTC 墙钟计算。状态 `blocked`(本轮不修,不调用 `--pillars`)。必须写明三组实测对照、关联 BUG-245 / BUG-905 的「所有星盘计算入口必须统一补算历史 offset」防复发条款,并把红线 2 写进防复发栏。
|
||
- **BUG-701**|计都派别(`ketuMode: apogee`)未暴露为参数。状态 `resolved`(任务 2 参数化后)。
|
||
- **BUG-702**|适配器 boundary 文案把空的神煞与未闭合的庙旺说成已生成。状态 `resolved`(任务 2 改写后)。
|
||
|
||
- **BUG-703**|`/api/panchanga_range` 岁差写死 Lahiri,与账户默认 Raman 不一致。状态 `investigating`(本轮只记录,不修,见附录)。
|
||
|
||
不得把姓名、出生资料、邮箱、用户/案例 ID、Cookie、JWT、密钥、完整请求体或模型原文写进去(AGENTS.md §5.6)。
|
||
|
||
## 让步顺序
|
||
|
||
资源不够时按这个顺序砍,**不得自行调整**:
|
||
|
||
1. 先保证 任务 1 + 任务 2 + 任务 3a + 任务 4。没有镜像 Node 与适配器,这一单等于没做。
|
||
2. 任务 3 的限流接入可以延后,但路由与行数上限不能延后。
|
||
3. 3b 与 3c 若来不及,可以拆到本单的第二次推送,但**必须仍由本单交付**——不得让前端单去改 `scripts/jyotish_api_server.py`。延后时要在进度记录里写明,并通知两份前端单:对应区块先渲染「该数据源尚未上线」。
|
||
4. `raw_engine_output` 的审计字段可以先不落地,改为进度记录里说明。
|
||
5. **不可让步**:许可证归档(Apache-2.0 §4)、`vendor/**` 进 gated-paths、庙旺不得进结论、`--pillars` 不得调用、api_server 行数上限。
|
||
|
||
## 开工前置命令
|
||
|
||
```bash
|
||
cd /workspace/Jyotisha
|
||
git status -sb # 确认分支,主检出常被别的会话切走
|
||
git fetch origin --prune
|
||
git worktree add -b codex/qizheng-native-chart-20260915 \
|
||
.worktrees/qizheng-native-chart-20260915 origin/staging
|
||
cd .worktrees/qizheng-native-chart-20260915
|
||
python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45
|
||
grep -nE "BUG-[0-9]{3}" docs/BUG_HISTORY.md | tail -5 # 核对当前最大号
|
||
wc -l scripts/jyotish_api_server.py # 应为 11313,上限 11363
|
||
```
|
||
|
||
取上游文件(只取内容,不引用上游路径作为运行时依赖):
|
||
|
||
```bash
|
||
cd /workspace/yinduzhanxing
|
||
git fetch origin codex/add-birth-time-rectification-skill
|
||
for f in vendor/stem-branch/LICENSE vendor/stem-branch/README.md \
|
||
vendor/stem-branch/package.json vendor/stem-branch/dist/cli.cjs; do
|
||
git show a911c890:"$f" # 写入目标 worktree 的同名路径
|
||
done
|
||
```
|
||
|
||
交付:`git push origin HEAD:staging`(会触发 `backend-quality-gate`,因为 `scripts/**`、`deploy/**`、`vendor/**` 都在门禁路径内),推送后必须核对远端 SHA,并确认 `/api/health` 的 `deployment.gitCommit` 等于本次提交。
|
||
|
||
## BUG 编号起点
|
||
|
||
`origin/staging` 上 `docs/BUG_HISTORY.md` 的当前最大号是 **BUG-699**。
|
||
|
||
三份并行单**预分配编号段**,各自不得越界;开工时仍要重新核对当前最大号(可能已被别的会话占用,占用了就整体后移并通知另外两单):
|
||
|
||
| 单 | 编号段 |
|
||
| --- | --- |
|
||
| 本单(七政 + 只读端点) | **BUG-700 ~ 703** |
|
||
| `TASK-chart-page-20260915` | BUG-704 ~ 706 |
|
||
| `TASK-ephemeris-page-20260915` | BUG-707 ~ 709 |
|
||
|
||
## 附:本轮发现但不在本单范围
|
||
|
||
立单期间实跑我们自己的引擎时发现一条与七政无关的口径不一致,**不要在本单修**,但请在本单的 Bug 记录里记成 **BUG-703 `investigating`**,避免丢失:
|
||
|
||
- **panchanga 岁差与账户设置不一致**。`/api/panchanga_range` 的响应里 `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`。
|
||
- 处置:记 `investigating`,写明现象与复现,**不要猜根因、不要顺手改默认值**。是统一到 Raman 还是明确声明 panchanga 永远用 Lahiri,是产品决策,另出单。
|
||
|
||
## 进度与记录
|
||
|
||
- 进度记录:`docs/tasks/PROGRESS-qizheng-native-chart-20260915.md`,本单状态板一行。
|
||
- 被环境挡住的写 `BLOCKED.md`(预期缺口:无 Docker → 镜像构建与容器内 `node --version` 无法验证)。
|
||
- 用户可感知的行为变化写 `CHANGELOG.md`;本单只新增只读接口,Skill 版本不 bump,在 CHANGELOG 里写明「未 bump」。
|
||
- 索引:`docs/tasks/README.md` 追加本单。
|