feat(qizheng): vendor stem-branch and expose three read-only chart APIs
Add Apache-2.0 @4n6h4x0r/stem-branch 0.8.0, a seven-governors adapter, and POST /api/qizheng, /api/western, /api/ephemeris_events. BUG-700 remains blocked (do not call --pillars). BUG-701 and BUG-702 are resolved. BUG-703 is investigating (panchanga Lahiri). Skill is not bumped.
This commit is contained in:
@@ -10869,3 +10869,67 @@
|
||||
- 相关记录:BUG-553
|
||||
- 复发自:BUG-553
|
||||
- 修复版本:待发布
|
||||
|
||||
## BUG-700 | vendored 七政引擎四柱时柱按 UTC 墙钟计算
|
||||
|
||||
- 状态:blocked
|
||||
- 首次发现:2026-09-15
|
||||
- 最近更新:2026-09-15
|
||||
- 影响面:vendored `@4n6h4x0r/stem-branch` 0.8.0 CLI 的 `--pillars`;本仓 `/api/qizheng` 适配器
|
||||
- 用户现象:把带时区偏移的 ISO 时刻交给 `--pillars` 时,时柱按 UTC 墙钟而不是出生地本地民用时。中国用户会得到错 8 小时的时柱;午夜前后日柱也会错。
|
||||
- 触发条件:CLI `--pillars --json` 且 `--date` 带 `+HH:MM` / `-HH:MM` 偏移。
|
||||
- 根因:同一时间入口同时服务「天文时刻」(要 UTC)和「历法干支」(要本地民用时)。本轮不修引擎。
|
||||
- 修复:本轮不调用 `--pillars` / `--luck` / `--polaris` / `--qimen` / `--liuren`。`/api/qizheng` 只走七政四余库函数。四柱不在本单产品范围。
|
||||
- 验证:适配器源码与 `_NODE_EVAL` 不含上述子命令;`tests/test_qizheng_chart_engine.py` 锁死不得调用。三组对照(同一本地墙上 13:24):带 `+08:00` 偏移 → 时柱为卯;去掉偏移 → 时柱为未;写 `+00:00` → 时柱为未。本地民用时应为未。
|
||||
- 防复发:绝不把带时区偏移的 ISO 字符串喂给需要本地民用时的子命令。若将来做四柱,必须先解决本条,并继续遵守 BUG-245 / BUG-246「所有星盘计算入口必须统一补算历史 offset」。任务书所称 BUG-905 与此同族;本仓当前无独立 BUG-905 条目。
|
||||
- 相关记录:BUG-245、BUG-246
|
||||
- 复发自:无
|
||||
- 修复版本:未修(blocked)
|
||||
|
||||
## BUG-701 | 计都派别 `ketuMode: apogee` 未暴露为参数
|
||||
|
||||
- 状态:resolved
|
||||
- 首次发现:2026-09-15
|
||||
- 最近更新:2026-09-15
|
||||
- 影响面:七政四余本命、`scripts/qizheng_chart_engine.py`、`POST /api/qizheng`
|
||||
- 用户现象:引擎默认 `ketuMode=apogee`,计都落在月孛附近而不是罗睺对点。请求侧看不到、也改不了这一派。
|
||||
- 触发条件:调用七政四余且未传 `ketu_mode` / `sidereal_mode`。
|
||||
- 根因:vendored CLI 不把 `ketuMode` / `siderealMode` 做成旗标;适配器若只透传 CLI 默认值,派别会静默生效。
|
||||
- 修复:`ketu_mode` 与 `sidereal_mode` 从请求体读取,缺省 `apogee` / `{type: modern}`,回写进 `calculation`。实现走 `dist/index.cjs` 的 `getSevenGovernorsChart(..., options)`,因为 CLI 没有对应旗标。
|
||||
- 验证:`tests/test_qizheng_chart_engine.py` 覆盖默认回写与 `descending-node` 覆盖(计都与罗睺约 180°)。
|
||||
- 防复发:计都派别与宿度起算口径必须是显式参数,不得只靠引擎默认。
|
||||
- 相关记录:BUG-702
|
||||
- 复发自:无
|
||||
- 修复版本:待发布
|
||||
|
||||
## BUG-702 | 适配器 boundary 把空神煞与未闭合庙旺说成已生成
|
||||
|
||||
- 状态:resolved
|
||||
- 首次发现:2026-09-15
|
||||
- 最近更新:2026-09-15
|
||||
- 影响面:`scripts/qizheng_chart_engine.py` 的 `boundary` / `dignities`
|
||||
- 用户现象:文案写已生成神煞和当前庙旺;实测神煞为空,11 曜庙旺除太阳「陷」外全是「平」。
|
||||
- 触发条件:读取七政四余响应的 boundary / dignities。
|
||||
- 根因:boundary 按引擎能力清单写,不按本次实际输出写。庙旺表 132 格只闭合 9 格,`runtime_promotable_count = 0`,不能当判定用。
|
||||
- 修复:boundary 不再出现「神煞」二字;庙旺带 `unclosed` 且 `may_enter_conclusions=false`,并引用 132/9/`runtime_promotable_count=0` 口径。解读层、报告层、咨询层不得引用庙旺。
|
||||
- 验证:`tests/test_qizheng_chart_engine.py`、`tests/test_qizheng_api_productization.py` 断言 boundary 不含「神煞」,dignities.status 为 unclosed。
|
||||
- 防复发:boundary 必须按本次实际输出写;庙旺在未闭合前不得进入结论。
|
||||
- 相关记录:BUG-701
|
||||
- 复发自:无
|
||||
- 修复版本:待发布
|
||||
|
||||
## BUG-703 | `/api/panchanga_range` 岁差写死 Lahiri,与账户默认 Raman 不一致
|
||||
|
||||
- 状态:investigating
|
||||
- 首次发现:2026-09-15
|
||||
- 最近更新:2026-09-15
|
||||
- 影响面:`POST /api/panchanga_range`、星历/今日路径的五要素
|
||||
- 用户现象:账户默认岁差是 Raman,本命盘按 Raman 算;同一用户在 panchanga 范围接口看到的五要素口径却是 Lahiri。
|
||||
- 触发条件:`POST /api/panchanga_range` 即使请求带 `ayanamsa=raman`,响应 `report.calculation_policy.panchanga` 仍写 `SwissEph Lahiri at sunrise-relative reference time`。
|
||||
- 根因:本轮只记录,不猜测。是统一到 Raman 还是声明 panchanga 永远用 Lahiri,属产品决策。
|
||||
- 修复:未修。
|
||||
- 验证:未修,无回归测试。
|
||||
- 防复发:待产品决策后另出单。岁差必须按请求参数走,不得写死。
|
||||
- 相关记录:无
|
||||
- 复发自:无
|
||||
- 修复版本:未修(investigating)
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
# PROGRESS · TASK-qizheng-native-chart-20260915
|
||||
|
||||
分支:`codex/qizheng-native-chart-20260915`
|
||||
开工基线:`4cacea8e`(任务书四份已在 staging;代码基线仍是 `2d7698ea` 之后的 staging 全量)
|
||||
本机:Windows。Python 用 Anaconda 3.11.7(`pytest` + `pyswisseph` 已装)。仓库 `.venv` 是指向 `/workspace/Jyotisha/.venv` 的 git symlink,Windows 上不是可用目录。
|
||||
|
||||
## 开工核对
|
||||
|
||||
| 项 | 结果 |
|
||||
| --- | --- |
|
||||
| `git status -sb` | `codex/qizheng-native-chart-20260915...origin/staging` |
|
||||
| `scripts/jyotish_api_server.py` 行数 | 开工 11313;上限 11363 |
|
||||
| `docs/BUG_HISTORY.md` 最大号 | BUG-699。本单使用 **700–703**,未被占用 |
|
||||
| Skill | `6.9.16`,**未 bump** |
|
||||
| `pre_work_check.py` | python_runtime / fragment_scan / external_engine_adapters / remote_visibility 均 ok。focused_tests 两条 `test_preflight_fragment_scan.py` 红:本机没有 `.workbuddy/skills/jyotish-vedic-astrology` 镜像路径,且 fragment candidate_count 5 < residue 14。与本单改动无关,未修 |
|
||||
|
||||
## 任务 1 · vendored 归档与镜像 Node
|
||||
|
||||
- 上游 Git `https://github.com/732642856/yinduzhanxing` @ `a911c890` 本机取不到(HTTPS 认证失败、SSH 无密钥、页面 404)。见 `BLOCKED.md`。
|
||||
- `vendor/stem-branch/{LICENSE,README.md,package.json,dist/cli.cjs}` 取自 npm `@4n6h4x0r/stem-branch@0.8.0`(Apache-2.0)。`cli.cjs` **45,963 行 / 2,682,464 B**,与任务书一致。
|
||||
- 另归档 `dist/index.cjs`:发布 CLI 没有 `ketuMode` / `siderealMode` 旗标,BUG-701 需要库函数入口。
|
||||
- 仓库根 `NOTICE`:包名、0.8.0、Apache-2.0、上游地址、取入方式。
|
||||
- `deploy/railway-api.Dockerfile`:`nodejs` 运行时(不装 npm/构建链),`COPY vendor ./vendor`。
|
||||
- `deploy/gated-paths.txt`:新增 `vendor/**`。
|
||||
- **镜像构建 / 容器内 `node --version`:无 Docker,未跑,不写成通过。** 宿主机 `node --version` = `v22.23.2`。镜像体积变化:未知。
|
||||
|
||||
## 任务 2 · 适配器
|
||||
|
||||
`scripts/qizheng_chart_engine.py`:只调 `getSevenGovernorsChart`;禁止 `--pillars` 等子命令。`ketu_mode` / `sidereal_mode` 从请求读取并回写。`coordinate_system=qizheng_mansion_degrees_from_jiao`。boundary 无「神煞」,庙旺 `unclosed`。五种错误路径结构化,不 500、不外泄 stderr。
|
||||
|
||||
实跑虚构资料 `1990-04-09T13:24:00+08:00 / 31.19N 121.44E`:
|
||||
|
||||
| 项 | 值 |
|
||||
| --- | --- |
|
||||
| 太阳 | 宿度 177.94 奎 7.44° 亥宮 陷 |
|
||||
| 罗睺 | 宿度 112.09 女 5.09° 丑宮 |
|
||||
| 计都(apogee) | 宿度 27.46 亢 15.46°(近月孛,非罗睺对点) |
|
||||
| 紫炁 | 宿度 33.34 房 0.34° 卯宮 |
|
||||
| 命宫 | 星 · 午宮 |
|
||||
| 宫 / 相位 / 神煞 | 12 / 27 / 0 |
|
||||
|
||||
## 任务 3 · 三个只读端点
|
||||
|
||||
`scripts/jyotish_api_server.py` 净增 **21 行**(11313 → 11334,预算 32,上限 11363)。三个 handler 各 ≤ 8 行。已纳入 `JYOTISH_HEAVY_COMPUTE_CONCURRENCY`。
|
||||
|
||||
- `/api/qizheng` 见上。
|
||||
- `/api/western` → `build_tropical_natal_chart`;`house_system` 默认 `P` 可覆盖;回归黄道边界句含 Raman 岁差差值。
|
||||
- `/api/ephemeris_events`:90 天 Raman 窗口 **14** 条(ingress 8 + station 6),Lahiri 同窗 16 条且不同;>730 天 400。
|
||||
|
||||
本地 `POST http://127.0.0.1:5200/api/qizheng`(与任务书 curl 等价;PowerShell 下 `curl.exe -d` 引号被吃掉,改用 Python `urllib`,status 200):
|
||||
|
||||
```json
|
||||
{"success": true, "endpoint": "qizheng", "coordinate_system": "qizheng_mansion_degrees_from_jiao", "calculation": {"engine": "@4n6h4x0r/stem-branch", "engine_version": "0.8.0", "ketu_mode": "apogee", "sidereal_mode": {"type": "modern"}, "engine_ketu_mode": "apogee", "engine_sidereal_mode": {"type": "modern"}, "iso_local": "1990-04-09T13:24:00+08:00", "timeout_seconds": 20}, "ascendant": {"mansion": "星", "palace": "午宮"}, "bodies.sun": {"siderealLon": 177.94225865978694, "mansion": "奎", "mansionDegree": 7.442258659786944, "palace": "亥宮"}}
|
||||
```
|
||||
|
||||
`GET /api/health`:`status=ok`,`swisseph_available=true`。本地 `git_commit` 为 unknown(未部署)。
|
||||
|
||||
## 任务 4 · Bug
|
||||
|
||||
| 号 | 状态 |
|
||||
| --- | --- |
|
||||
| BUG-700 | blocked(不调用 `--pillars`) |
|
||||
| BUG-701 | resolved(派别参数化) |
|
||||
| BUG-702 | resolved(boundary / 庙旺 unclosed) |
|
||||
| BUG-703 | investigating(panchanga Lahiri,本轮不修) |
|
||||
|
||||
## 测试
|
||||
|
||||
Anaconda `python -m pytest`:
|
||||
|
||||
- `tests/test_qizheng_chart_engine.py`
|
||||
- `tests/test_qizheng_api_productization.py`
|
||||
- `tests/test_readonly_chart_endpoints.py`
|
||||
- `tests/test_ephemeris_events.py`
|
||||
- `tests/test_api_server_growth_contract.py`
|
||||
- `tests/test_api_heavy_compute_gate.py`
|
||||
- `tests/test_western_chart_engine.py`
|
||||
|
||||
**36 passed**。
|
||||
|
||||
`run_quality_gate.py --profile quick`:本机无 Docker,`npm test` 预期仍是既有 27 条 DB 失败,不得写成全绿。Python 段另缺 `timezonefinder` / `mcp`(见根 `BLOCKED.md`)。上述定向测试已绿。新测试已列入 `CORE_PYTEST_TARGETS`。
|
||||
|
||||
## 让步
|
||||
|
||||
无。3b/3c 已交付。限流已接入。`raw_engine_output` 已落地并去掉路径键。
|
||||
|
||||
## 合入
|
||||
|
||||
本单最先合入 staging。不提升 `main`、不改 workflow、不动 DNS。
|
||||
@@ -222,7 +222,7 @@
|
||||
|
||||
| `TASK-rectification-house-lord-gochara-research-20260913.md` | `PROGRESS-rectification-house-lord-gochara-research-20260913.md` | 研究单:宫主触发与木星/土星过运(合冲本命宫主、罗睺紧密合、年精度、用于 block 选上升)四种放宽,20 例公开 AA 离线量 block 层与 minute 层两组指标;引擎里已有宫主/功能吉凶/受控过运,只量缺的四条 | 待验收(无收益,关闭;不立实现单) | `codex/rectification-house-lord-gochara-research-20260913` |
|
||||
|
||||
| `TASK-qizheng-native-chart-20260915.md` | `PROGRESS-qizheng-native-chart-20260915.md` | **后端单(独占 `scripts/jyotish_api_server.py`)**:vendored `stem-branch` 0.8.0(Apache-2.0)归档 + API 镜像 Node runtime + 七政适配器(计都派别与宿度坐标系参数化、boundary 按实测重写)+ 三个只读端点 `/api/qizheng`、`/api/western`、`/api/ephemeris_events`。实证三条:四柱时柱按 UTC 算(BUG-700,本轮不修不调用)、`ketuMode` 写死未暴露(BUG-701)、boundary 把空神煞与未闭合庙旺说成已生成(BUG-702)。BUG 段 700–703 | 待领取 | — |
|
||||
| `TASK-qizheng-native-chart-20260915.md` | `PROGRESS-qizheng-native-chart-20260915.md` | **后端单(独占 `scripts/jyotish_api_server.py`)**:vendored `stem-branch` 0.8.0(Apache-2.0)归档 + API 镜像 Node runtime + 七政适配器(计都派别与宿度坐标系参数化、boundary 按实测重写)+ 三个只读端点 `/api/qizheng`、`/api/western`、`/api/ephemeris_events`。实证三条:四柱时柱按 UTC 算(BUG-700,本轮不修不调用)、`ketuMode` 写死未暴露(BUG-701)、boundary 把空神煞与未闭合庙旺说成已生成(BUG-702)。BUG 段 700–703 | 已实现,推送中 | `codex/qizheng-native-chart-20260915` |
|
||||
| `TASK-chart-page-20260915.md` | `PROGRESS-chart-page-20260915.md` | **前端单(独占 `app-sidebar.tsx`,同时加星盘与星历两个入口)**:P0 只读星盘页,五个 Tab(星盘 / 基础信息 / 大运 / 西洋盘 / 七政四余),中宫排盘参数卡,三套坐标系各自标注且禁止互相换算。不扣点不调模型不出 spinner;不碰 `page.tsx`(1951/2000);**不搬 `vedic-chart-svg.tsx`**(rectification-board 也在用)。BUG 段 704–706 | 待领取 | — |
|
||||
| `TASK-ephemeris-page-20260915.md` | `PROGRESS-ephemeris-page-20260915.md` | **前端单**:P1 星历页,今日五要素 + 当日行运(相对本命宫位)+ 未来九十天换座与停滞,底部「带这天去提问」出口。页面不得出现任何运势判断。含实证缺陷:panchanga 写死 Lahiri 与账户 Raman 分裂(BUG-707,只标注不修)。侧边栏入口由 chart-page 单交付。BUG 段 707–709 | 待领取 | — |
|
||||
| `TASK-api-server-decomposition-20260916.md` | `PROGRESS-api-server-decomposition-20260916.md` | **重构单(串行在 qizheng 单之后)**:把业务逻辑搬出 `JyotishAPIHandler`。核心不是行数,是全仓 3 处靠 `JyotishAPIHandler.__new__` 伪造空壳 handler 借方法(`consultation_workflow_service` ×2、`capture_report_blocked_repairs_golden`、`local_accuracy_report`,MCP 也走这条),依赖方向反了、handler 没有 `headers`/`wfile` 随时可炸。四阶段:拆 `__new__` 后门 → 抽 ≥150 行业务方法 → `do_POST`/`do_GET` 改路由表 → 重新冻结行数 baseline(余量 300→50)。纯搬运不改行为,`test_api_server_security.py` 3841 行断言一条不许改。预计 11,314 → 约 9,230 行。BUG 段 710+ | 待领取 | — |
|
||||
|
||||
Reference in New Issue
Block a user