① 状态板校正: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
144 lines
9.1 KiB
Markdown
144 lines
9.1 KiB
Markdown
# 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`)
|