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

9.1 KiB
Raw Blame History

TASK · 关掉 JyotishAPIHandler.__new__ 后门(314 行纯搬运)

  • 日期:2026-09-16
  • 基线 commitorigin/staging @ 4f643aa0
  • 执行分支:codex/api-server-backdoor-close-20260916
  • 落点:scripts/jyotish_api_server.py、新建的 scripts/ 下模块、scripts/consultation_workflow_service.pyscripts/capture_report_blocked_repairs_golden.pyscripts/local_accuracy_report.pytests/test_api_server_growth_contract.py
  • 取代 TASK-api-server-decomposition-20260916 的阶段 1;该单其余阶段的处置见 §3.2
  • TASK-consultation-residual-hotspots-20260916vedastro_* / 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. 事故实证

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.pylocal_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. 开工前置命令

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.mdAGENTS §9);原 TASK-api-server-decomposition-20260916.md(它对根因的分析仍然有效,只是范围被本单收窄)。

验收命令:

.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-733734/735 已被 TASK-consultation-residual-hotspots-20260916 预占。

9. 不在本单范围

  • 阶段 2(抽 ≥150 行业务方法)与阶段 3(do_POST 路由表)——不立单,由门禁长期推进
  • execute_consultation_workflow 里的任何业务逻辑改动
  • 外网探测与 yoga 编译缓存(见 TASK-consultation-residual-hotspots-20260916