Files
Jyotisha/docs/tasks/TASK-api-server-backdoor-close-20260916.md
T
Jesse_ChenandClaude Opus 5 37e6c519f7 docs(tasks): 校正状态板 + 状态下沉第二批 + 后门单 + 对账清单
① 状态板校正:09-15~16 这 10 份任务书的实现早已合入 staging 并经逐单
   验收,状态板却仍写「待领取 / 待验收」。改成「已验收」并补上落点 SHA
   与验收要点;顺带补齐 8 个 PROGRESS 列。防复发写进「命名与归档」:
   实现合入的同一次推送必须同时改状态板那一行。

② 新增 TASK-home-state-lowering-batch2-20260916(不占 BUG 号):
   第一批 f8e607c2 已验收(useState 66→52、useRef 41→39、散装
   rectification* 归零)。本单搬剩下三簇 session*10 / profile*6 /
   synastry*4,目标 52→≤36;并修第一批尾巴——
   createRectificationShellSetters 每帧新身份多出的那条 exhaustive-deps
   warning(119→120),正解是稳住 setter 身份而不是塞进 deps。

③ 新增 TASK-api-server-backdoor-close-20260916(不占 BUG 号):
   实测四处 __new__ 的传递闭包只有 8 方法 / 314 行且 0 个碰 HTTP 上下文,
   占全类 4%。所以关后门不必捆绑 2,000+ 行体量搬运。产品拍板阶段 2/3
   不立单,由 3b17c1b2 换好的门禁长期推进。原 decomposition 单标为已取代。

④ 新增 RECONCILE-20260916:另外 7 份 09-10~14 的单没有 PROGRESS、但
   引用的 BUG 号都是 resolved,无法从 README 判断,列成一页纸让执行方
   回填;另附三条确定没做的证据、两条未闭环状态、BLK-001 仍红。

纯文档推送,不触发门禁、不发布镜像、不部署。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
2026-09-16 01:13:26 +00:00

144 lines
9.1 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 · 关掉 `JyotishAPIHandler.__new__` 后门(314 行纯搬运)
- 日期:2026-09-16
- 基线 commit`origin/staging` @ `4f643aa0`
- 执行分支:`codex/api-server-backdoor-close-20260916`
- 落点:`scripts/jyotish_api_server.py`、新建的 `scripts/` 下模块、`scripts/consultation_workflow_service.py``scripts/capture_report_blocked_repairs_golden.py``scripts/local_accuracy_report.py``tests/test_api_server_growth_contract.py`
- **取代 `TASK-api-server-decomposition-20260916` 的阶段 1**;该单其余阶段的处置见 §3.2
-`TASK-consultation-residual-hotspots-20260916``vedastro_*` / `yoga_engine`)、`TASK-home-state-lowering-batch2-20260916`(纯前端)**无文件重叠,三单可并行**
- 规模:8 个方法 / 314 行搬进独立模块。**纯搬运,零行为变化。**
---
## 1. 为什么把范围缩到 314 行
原任务书四个阶段(拆 `__new__` → 抽 ≥150 行方法 → `do_POST` 改路由表 → 重新冻结)方向是对的,但它把「关后门」和「体量搬运」捆在了一起。我按调用链实测算了阶段 1 的**传递闭包**(从四处伪造实际借用的方法出发,跟着 `self._x()` 一路追):
| | 数量 |
| --- | ---: |
| 需要搬的方法 | **8 个** |
| 合计行数 | **314 行** |
| 其中真的碰 HTTP 上下文(`self.headers` / `wfile` / `rfile` / `path` / `client_address` | **0 个** |
| 占 `JyotishAPIHandler` 全类(225 方法 / 8,219 行)的比例 | **4 % / 4 %** |
**关后门只需要一次 314 行的纯搬运,而且这 8 个方法一个都不碰 HTTP,没有隐藏耦合。**
四处伪造实际借用的入口方法只有 5 个:
| 位置 | 借用的方法 |
| --- | --- |
| `scripts/consultation_workflow_service.py:20` / `:27` | `_compute_vedastro_gateway_archives``_high_rigor_vedastro_official_summary``_interpretation_source_runtime_coverage` |
| `scripts/capture_report_blocked_repairs_golden.py:59` | `_compute_consultation_workflow` |
| `scripts/local_accuracy_report.py:141` | `_compute_synastry` |
## 2. 事故实证
```python
handler = JyotishAPIHandler.__new__(JyotishAPIHandler) # 不跑 __init__ 的空壳
```
`__new__` 绕过 `BaseHTTPRequestHandler.__init__`,造出来的对象**没有 `headers` / `wfile` / `rfile` / `client_address`**。今天能跑,只是因为被借用的这 8 个方法碰巧没碰它们——我逐个查过,`0` 个碰。
**这是一颗类型检查看不见的地雷**:任何人往这 8 个方法(或它们调用的任何方法)里加一行 `self.headers.get(...)`MCP 与两个离线脚本就会在运行时 `AttributeError`,而单元测试与 `tsc` 都发现不了。
更根本的是依赖方向反了:`consultation_workflow_service.py` 的 docstring 自称是「shared consultation workflow boundary for API and MCP callers」,实际却**反过来依赖 HTTP 单体文件**,只为借它身上的方法。
全仓依赖该模块的文件有 **43 个**`scripts/``tests/``mcp_server.py`)。
## 3. 决策记录
产品 2026-09-16 拍板:
1. **只做「关后门」这一件事,不做体量搬运。** 原任务书的阶段 2(抽 7 个 ≥150 行方法,2,073 行)与阶段 3(78 个 `elif` 改路由表)**本轮不做**。理由:那是 2,000+ 行的大搬运、零用户价值,而 `tests/test_api_server_security.py` 有 3,841 行断言绑在这个类上——风险与收益不匹配。
2. **阶段 2/3 不另立单,改由门禁长期推进。** `3b17c1b2` 已把增长冻结的主门从行数换成「**类方法数不得增长 + `__new__` 计数不得增长**」。这意味着以后任何想往这个类里加方法的改动都会被拦,只能往外搬——**换口径本身已经替代了一次性大搬运的必要性**。这条写进 `docs/tasks/README.md` 的状态板备注,避免下一轮有人又提。
3. **纯搬运,零行为变化。** `tests/test_api_server_security.py` 的 3,841 行断言**一条不许改**。
4. **收尾把 `__new__` 计数基线收到 0。** 这是本单唯一不可伪造的成功判据。
## 4. 硬红线
1. **`grep -rn "JyotishAPIHandler.__new__" --include=*.py .`(排除 `skills/*/versions/**`)必须零命中**,并且这条断言要写进 `tests/test_api_server_growth_contract.py`,基线从 4 收到 **0**
2. **`tests/test_api_server_security.py` 一条断言不许改。** 若它红了,说明不是纯搬运——回去改实现,不是改断言。
3. **不得顺手搬阶段 2/3 的方法。** 类方法数会因本单下降,把新值写进合同测试即可;**不得**为了多降一点而扩大范围。
4. 搬出去的模块**不得**再反向 import `jyotish_api_server`——那等于把后门换了个地方开。要有一条断言钉住这个方向。
5. 本单会与 `TASK-consultation-external-evidence-cache-20260915`(已合入 `e61535f4`)的改动共处同一文件:它在 `execute_consultation_workflow` 里加了走缓存模块的分支。**照常搬运,不得把它改回去。**
6. 不得顺手升级依赖、不得顺手修不在本单里的 warning。
## 5. 任务分解
### 5.1 先自己把闭包算一遍
不要抄本任务书的 8 个方法。开工时用同样的方法重算(从 5 个入口方法出发,跟着 `self._x()` 追传递闭包,并标出哪些碰 HTTP 上下文),结果写进进度记录。代码可能已经漂移。
- 验收:进度记录里有闭包清单、行数、以及「碰 HTTP 上下文的有几个」。
- 验收:若重算出来**有**方法碰 HTTP 上下文,**停手**,把那几个列出来先问——本单的前提是它们都不碰。
### 5.2 把闭包搬进独立模块
按职责放进 `scripts/` 下的新模块(建议按 vedastro 证据 / 咨询工作流 / 合盘分组,不要一股脑塞一个文件)。`JyotishAPIHandler` 里对应位置改成薄调用。
- 验收:`scripts/jyotish_api_server.py` 的类方法数下降,新值写进合同测试。
- 验收:新模块不 import `jyotish_api_server`,有断言。
### 5.3 三个调用方改成直接 import
`consultation_workflow_service.py`(两处)、`capture_report_blocked_repairs_golden.py``local_accuracy_report.py` 改成直接 import 新模块,删掉 `JyotishAPIHandler.__new__` 与对 `jyotish_api_server` 的 import。
- 验收:三个文件都不再 import `jyotish_api_server`
- 验收:MCP 侧(`mcp_server.py:741` / `:4749` 经由 `consultation_workflow_service`)仍然可用——至少一条端到端断言。
### 5.4 合同测试收基线
`tests/test_api_server_growth_contract.py``__new__` 计数基线 4 → **0**;类方法数基线更新为收尾实测值;行数粗护栏 baseline 重设为收尾实测 + 300。同步更新文件顶部 docstring 的日期与说明。
- 验收:人为加回一处 `JyotishAPIHandler.__new__` 必须让测试变红(贴反向验证)。
- 验收:人为加一个类方法必须变红(贴反向验证)。
- 验收:该文件既有的三条断言(`AGENTS.md` 必须含 `must not grow` / `thinly registered`、该测试必须在 `CORE_PYTEST_TARGETS` 与快速门里)仍绿。
### 5.5 记录
本单不产生 Bug 记录(结构改造,不是缺陷),不进 `CHANGELOG.md`(无用户可感知变化)。进度记录里必须有:闭包清单、搬前/搬后的类方法数与行数、两次反向验证结果。
同轮把原 `TASK-api-server-decomposition-20260916` 在状态板上标成**已取代(阶段 1 由本单完成;阶段 2/3 不立单,由门禁长期推进)**。
## 6. 让步顺序
1. 5.1 **不得砍**——闭包没重算就动手,等于拿本任务书的旧数字赌代码没漂。
2. 5.2 + 5.3 是主体,必须一起做(只搬不改调用方,后门还在)。
3. 5.4 不得砍——`__new__` 计数收到 0 是本单唯一的成功判据。
4. 5.5 不得砍。
## 7. 开工前置命令
```bash
git fetch origin --prune
git worktree add -b codex/api-server-backdoor-close-20260916 \
.worktrees/api-server-backdoor-close-20260916 origin/staging
cd .worktrees/api-server-backdoor-close-20260916
git status -sb | head -1
# 重算基线
grep -rn "JyotishAPIHandler.__new__" --include=*.py . | grep -v "skills/.*/versions/"
grep -cE '^ (async )?def ' scripts/jyotish_api_server.py
wc -l scripts/jyotish_api_server.py
python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45 # AGENTS §9
```
开工前必读:`docs/research/pre_work_error_ledger.md`AGENTS §9);原 `TASK-api-server-decomposition-20260916.md`(它对根因的分析仍然有效,只是范围被本单收窄)。
验收命令:
```bash
.venv/bin/python -m pytest tests/test_api_server_security.py tests/test_api_server_growth_contract.py \
tests/test_consultation_consumer_context.py tests/test_vedastro_gateway.py
.venv/bin/python scripts/run_quality_gate.py --profile quick
```
## 8. BUG 编号起点
本单不占 BUG 号。基线 `4f643aa0` 上最大号 **BUG-733**734/735 已被 `TASK-consultation-residual-hotspots-20260916` 预占。
## 9. 不在本单范围
- 阶段 2(抽 ≥150 行业务方法)与阶段 3(`do_POST` 路由表)——**不立单,由门禁长期推进**
- `execute_consultation_workflow` 里的任何业务逻辑改动
- 外网探测与 yoga 编译缓存(见 `TASK-consultation-residual-hotspots-20260916`