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

288 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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` | 丁**卯**(卯时 = 0507 时) | 辛**未** |
| `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` 追加本单。