docs(tasks): 后门单改写为 mixin 方案(产品选 B),修正闭包规模
第一版写「8 方法 / 314 行」错了一个数量级。错因:闭包只跟 self._x(),而 _compute_consultation_workflow 只有 6 行、转给模块级 execute_consultation_workflow(self, ...),那个函数体 394 行、对传进来的 handler 调 16 个方法再往下扇出。跟丢那一跳,300 行被当成了全部。 执行方重算:约 115 方法 / 4,104 行,占全类 51% 方法;碰 HTTP 上下文的 仍是 0 个——本单成立的前提没变。 产品在 A/B/C 中选定 B(mixin 抽取),并授权把 §4「不得搬 ≥150 行业务 方法」按本意解释:那条红线针对的是 C 那种逐行改写,而 mixin 是把方法体 原样挪家、self 含义不变、靠 MRO 解析,HTTP 那一面零变化。决策记录里已 写明这是该红线的推翻记录。 新增 spike 闸门:搬进 mixin 后 test_api_server_security.py 一字不改直接 跑,绿则继续、红则退回 A(7 方法/300 行、关 2 个伪造点)。已查明两个降 风险事实(security 测试无结构性断言、增长合同用整文件正则),并点名真 风险是循环 import——闭包引用同文件 44 个模块级函数 + 21 个常量/类。 另修正 __new__ 归零口径:合同基线 33 = scripts 4 + tests 29,tests 侧含 不许改的 security 测试,所以归零只针对 scripts 侧 4 → 0。 纯文档推送,不触发门禁、不发布镜像、不部署。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
This commit is contained in:
co-authored by
Claude Opus 5
parent
dc8cae316e
commit
5094fd2620
@@ -246,7 +246,7 @@
|
||||
| `TASK-rectification-engine-memoization-fix-20260915.md` | `PROGRESS-rectification-engine-memoization-fix-20260915.md` | **验收修复单(只改测试,一行实现不许动)**:BUG-721 的实现**等价性成立**(我在改前 `6b3248bf` / 改后 `e4788dfc` 同机跑同一 payload,`candidate_scores` 逐字相同),9 条计数断言全过;但等价 golden 在本机复现不出来——4 处浮点尾数差(score 1.0e-4 ×2、`margin_percent` 1.1e-3 ×2)。**复发自 BUG-712**(「不得对全精度浮点做整体 `==`」,那一单只落在 ephemeris 一处)。而 `tests/test_rectification_*.py` 在 `CORE_PYTEST_TARGETS` 里,**staging 门禁靠机器舍入碰巧一致才是绿的**。修法:主证据换成**同进程差分**(把 static context 的四个缓存键置 `None` 即可回退旧路径,A/B 严格相等),golden 降为离散字段严格相等 + 浮点带容差(容差按实测 1.1e-3 推);**禁止重建 golden 来「修」**。另含六份 golden 的仓库级排查。BUG-733 | 已验收 | `2b7b4565`(BUG-733)。同进程差分立为主证据,golden 降为离散严格+浮点容差;本机 14 条全绿 |
|
||||
| `TASK-consultation-residual-hotspots-20260916.md` | `PROGRESS-consultation-residual-hotspots-20260916.md` | **性能单(与拆解单文件不重叠,可并行)**:BUG-727 的快照缓存已验收生效(逐轮 trace 确认每轮 hit、响应体 52 万→40 万字符),但耗时没降——重测 6 次调用 5.30 s 里**网络仍占 70 %**(poll 2.42 + ssl read 0.76 + 握手 0.56),本地占星计算只剩 **2.4 %**。剩下那一次外网是 `gateway_status → probe_official_rest_health → probe_calculate_health`:**它不是 ping,是把一份虚构排盘 POST 给 `api.vedastro.org`**,而且 `consume_rate_token()` 会**烧掉对方一个业务限流令牌**,还不复用连接(6 次调用 3 次 TLS 握手,单次 0.186 s),结果零 TTL(BUG-734)。另 `yoga_engine._eval_custom` 对静态规则表的 192 条表达式**每请求重新编译 102 次**(多语句的还要先抛一次 SyntaxError 再 parse+改写 AST+compile),占 9.4 %(BUG-735)。修法:探测加 TTL(成功 60 s / 失败 10 s,配置变即失效,**诊断端点必须 force_refresh 保持实时**)+ 共享 opener;表达式缓存 code object。**硬红线:绝不缓存 yoga 求值结果**(会跨用户串盘)。等价证明用 BUG-733 的同进程差分,不再写跨机 golden。BUG 段 734–735 | 待验收 | `codex/consultation-residual-hotspots-20260916`:6.3 探测 TTL 与 6.1 编译缓存均完成,**6.2 共享 opener 按让步顺序砍掉**——实测 `urllib.request` 无连接池,模块级共享 opener 在 6 次请求下仍开 6 条 TCP 连接,按任务书写法只能骗过「同一个 opener 实例」的断言而省不掉任何握手,另立单。同口径实测:6 轮前台请求探测 6→1 次、握手 5→1 次、对方限流令牌 6→1 个(**改前第 6 轮探测自己被限流、报出假 `official_blocked`**);yoga 每次检测源码编译 386→第二次起 0,单次 27.4→3.3 ms。等价用 192 条表达式 ×3 盘的同进程差分。`force_refresh` 默认取 `True`(与任务书写的 `False` 相反):诊断端点调的是裸 `gateway_status()` 且该文件不得改,默认实时才不会让运维看到旧结论 |
|
||||
| `TASK-home-state-lowering-batch2-20260916.md` | — | **状态下沉第二批(纯前端,与另两单可并行)**:第一批 `f8e607c2` 已验收(useState 66→52、useRef 41→39、散装 `rectification*` 归零、全量套件两侧完全相同)。本单照同一套做法搬剩下三簇:`session*` **10** 个(`useSessionManagement` 仍要解构约 40 个参数)、`profile*` **6** 个、`synastry*` **4** 个(无 hook,散在 `Home()`),目标 useState 52 → **≤36**。另修第一批留下的尾巴:`createRectificationShellSetters` 在 render 体里无记忆化 → 每帧新身份 → 多一条 `exhaustive-deps` warning(119→**120**),**正解是稳住 setter 身份、不是塞进 deps**(塞进去会每帧重拉入口摘要),本单要把 warning 降回 119。零行为变化;先分类再动手。不占 BUG 号 | 待领取 | — |
|
||||
| `TASK-api-server-backdoor-close-20260916.md` | — | **取代 decomposition 单的阶段 1(纯 Python,与另两单可并行)**:实测四处 `__new__` 的**传递闭包只有 8 个方法 / 314 行,且 0 个碰 HTTP 上下文**(占全类 4%)。所以「关后门」是一次 314 行纯搬运,不需要捆绑 2,000+ 行的体量搬运。产品拍板:**阶段 2/3 不立单**,由 `3b17c1b2` 换好的门禁(类方法数 + `__new__` 计数只许降)长期推进。唯一成功判据:`grep -c "JyotishAPIHandler.__new__"` **收到 0** 并写进合同测试。`test_api_server_security.py` 的 3,841 行断言一条不许改。不占 BUG 号 | 待领取 | — |
|
||||
| `TASK-api-server-backdoor-close-20260916.md` | — | **取代 decomposition 单的阶段 1** · **第二版(2026-09-16 改写)**:第一版的「8 方法 / 314 行」**错了一个数量级**——闭包只跟了 `self._x()`,漏掉 `_compute_consultation_workflow` 那 6 行委托转给模块级 `execute_consultation_workflow(self, ...)` 的一跳。执行方重算实测 **115 方法 / 4,104 行(占全类 51% 方法),但碰 HTTP 上下文的仍是 0 个**。产品在 A/B/C 中**选定 B(mixin 抽取)**:方法体原样搬进 `ConsultationComputeMixin`,`JyotishAPIHandler(BaseHTTPRequestHandler, Mixin)` 靠 MRO 解析,离线调用方直接实例化 mixin——四个伪造点全关。**产品同时授权:§4 那条「不得搬 ≥150 行业务方法」按本意解释(本意是防逐行改写的 C 案),mixin 放行。** 必须先过 **spike 闸门**:搬完后 `test_api_server_security.py` 一字不改直接跑,绿则继续、红则退回 A(只搬 7 方法/300 行、关 2 个伪造点)。真风险是循环 import——闭包引用同文件 44 个模块级函数 + 21 个常量。`__new__` 归零只针对 scripts 侧 4→0(tests 侧 29 处含不许改的 security 测试,保持不增长)。阶段 3 仍不做。不占 BUG 号 | 待领取 | — |
|
||||
| `RECONCILE-20260916.md` | — | **对账清单(不是任务书)**:状态板与现实脱节(09-15~16 那 10 份早已合入却仍写「待领取/待验收」,本轮已修正),所以另外 7 份 09-10~14 的单**不能拿 README 当证据**——它们没有 `PROGRESS-*.md`,但引用的 BUG 号都是 `resolved`。要么被别的单顺带修了没留记录,要么压根没做。每行回一个「做了/没做」即可。另附三条我已查到确定没做的证据、两条状态未闭环的、以及 BLK-001 仍红(2026-09-16 在 `4f643aa0` 复跑确认) | 待产品负责人 / 执行方回填 | — |
|
||||
|
||||
## 命名与归档
|
||||
|
||||
@@ -1,143 +1,161 @@
|
||||
# TASK · 关掉 `JyotishAPIHandler.__new__` 后门(314 行纯搬运)
|
||||
# TASK · 关掉 `JyotishAPIHandler.__new__` 后门(mixin 抽取)
|
||||
|
||||
- 日期:2026-09-16
|
||||
- 基线 commit:`origin/staging` @ `4f643aa0`
|
||||
- 日期:2026-09-16(**2026-09-16 第二版:闭包规模与方案全部改写,见 §1.1**)
|
||||
- 基线 commit:`origin/staging` @ `dc8cae31`
|
||||
- 执行分支:`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 行搬进独立模块。**纯搬运,零行为变化。**
|
||||
- 落点:`scripts/jyotish_api_server.py`、新建的 `scripts/consultation_compute_mixin.py`(名字可另议)、`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.3
|
||||
- 与已合入的 residual-hotspots、home-state-lowering-batch2 无文件重叠
|
||||
- 规模:约 115 个方法 / 4,104 行**整体移进 mixin,方法体一字不改**。零行为变化。
|
||||
|
||||
---
|
||||
|
||||
## 1. 为什么把范围缩到 314 行
|
||||
## 1. 第一版的规模前提是错的
|
||||
|
||||
原任务书四个阶段(拆 `__new__` → 抽 ≥150 行方法 → `do_POST` 改路由表 → 重新冻结)方向是对的,但它把「关后门」和「体量搬运」捆在了一起。我按调用链实测算了阶段 1 的**传递闭包**(从四处伪造实际借用的方法出发,跟着 `self._x()` 一路追):
|
||||
第一版写「8 个方法 / 314 行」,**错了一个数量级**。错因已定位:闭包只跟了 `self._x()`,而 `_compute_consultation_workflow` 只有 6 行,转给**模块级**的 `execute_consultation_workflow(self, ...)`——那个函数体 394 行、直接对传进来的 `handler` 调 16 个方法,再往下扇出。跟丢了那一跳,300 行就被当成了全部。
|
||||
|
||||
执行方按 §5.1 重算后的实测:
|
||||
|
||||
| | 数量 |
|
||||
| --- | ---: |
|
||||
| 需要搬的方法 | **8 个** |
|
||||
| 合计行数 | **314 行** |
|
||||
| 其中真的碰 HTTP 上下文(`self.headers` / `wfile` / `rfile` / `path` / `client_address`) | **0 个** |
|
||||
| 占 `JyotishAPIHandler` 全类(225 方法 / 8,219 行)的比例 | **4 % / 4 %** |
|
||||
| 需要搬的类方法 | **约 115 个** |
|
||||
| 合计行数 | **约 4,104 行** |
|
||||
| 其中碰 HTTP 上下文(`self.headers` / `wfile` / `rfile` / `path` / `client_address`) | **0 个** |
|
||||
| 占 `JyotishAPIHandler`(225 方法 / 8,219 行) | 51 % 方法 / 36 % 行 |
|
||||
|
||||
**关后门只需要一次 314 行的纯搬运,而且这 8 个方法一个都不碰 HTTP,没有隐藏耦合。**
|
||||
闭包按入口干净地劈成两半:
|
||||
|
||||
四处伪造实际借用的入口方法只有 5 个:
|
||||
| 部分 | 规模 | 覆盖的伪造点 |
|
||||
| --- | ---: | --- |
|
||||
| vedastro 证据 + 合盘 | 7 方法 / 300 行 | `consultation_workflow_service.py:27`、`local_accuracy_report.py:141` |
|
||||
| 咨询工作流 | 114 方法 / 4,086 行 | `consultation_workflow_service.py:20`、`capture_report_blocked_repairs_golden.py:59` |
|
||||
|
||||
| 位置 | 借用的方法 |
|
||||
| --- | --- |
|
||||
| `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` |
|
||||
**「0 个碰 HTTP 上下文」这条前提仍然成立**,这是本单能做的基础。
|
||||
|
||||
## 2. 事故实证
|
||||
## 2. 事故实证(未变)
|
||||
|
||||
```python
|
||||
handler = JyotishAPIHandler.__new__(JyotishAPIHandler) # 不跑 __init__ 的空壳
|
||||
```
|
||||
|
||||
`__new__` 绕过 `BaseHTTPRequestHandler.__init__`,造出来的对象**没有 `headers` / `wfile` / `rfile` / `client_address`**。今天能跑,只是因为被借用的这 8 个方法碰巧没碰它们——我逐个查过,`0` 个碰。
|
||||
`__new__` 绕过 `BaseHTTPRequestHandler.__init__`,造出来的对象没有 `headers` / `wfile` / `rfile` / `client_address`。今天能跑只是因为被借用的方法碰巧没碰它们——实测 115 个里 0 个碰。
|
||||
|
||||
**这是一颗类型检查看不见的地雷**:任何人往这 8 个方法(或它们调用的任何方法)里加一行 `self.headers.get(...)`,MCP 与两个离线脚本就会在运行时 `AttributeError`,而单元测试与 `tsc` 都发现不了。
|
||||
**这是一颗类型检查看不见的地雷**:任何人往这些方法里加一行 `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`)。
|
||||
更根本的是依赖方向反了:`consultation_workflow_service.py` 自称「shared consultation workflow boundary for API and MCP callers」,实际却反过来依赖 HTTP 单体文件。全仓 43 个文件依赖该模块。
|
||||
|
||||
## 3. 决策记录
|
||||
|
||||
产品 2026-09-16 拍板:
|
||||
产品 2026-09-16 在 A / B / C 三案中**选定 B(mixin 抽取)**,并明确:
|
||||
|
||||
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。** 这是本单唯一不可伪造的成功判据。
|
||||
1. **§4 的「不得搬 ≥150 行业务方法」按本意解释,mixin 放行。** 那条红线的本意是「别做可能悄悄改行为的大重构」,针对的是 C 那种把方法逐行改写成模块级函数。**mixin 是把方法体原样挪个家:`self` 含义不变、方法集合不变、靠 MRO 解析,HTTP 那一面完全没有变化。** 执行方不得以「任务书第一版禁止搬 ≥150 行方法」为由拒改——这一条就是那条红线的推翻记录。
|
||||
2. **目标是 `__new__` 在 `scripts/` 生产侧归零。** 合同测试现行基线 `NEW_COUNT_BASELINE = 33`(scripts 4 + tests 29)。`tests/` 里那 29 处含 `test_api_server_security.py`,而该文件一个字不许改,所以 **tests 侧保持不增长即可,归零只针对 scripts 侧 4 → 0**。
|
||||
3. **原 decomposition 单的阶段 3(`do_POST` 78 个 elif 改路由表)仍然不做**,由 `3b17c1b2` 换好的门禁(类方法数 + `__new__` 计数只许降)长期推进。阶段 2 被本单以 mixin 形式吸收。
|
||||
4. **B 必须先过 spike 闸门**(见 §5.2)。spike 红了就退回 A(只搬 7 方法 / 300 行、关掉 2 个伪造点),**不得硬做**。
|
||||
5. **纯搬运,零行为变化。** `tests/test_api_server_security.py` 的 3,841 行断言一条不许改。
|
||||
|
||||
## 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` 里加了走缓存模块的分支。**照常搬运,不得把它改回去。**
|
||||
1. **`tests/test_api_server_security.py` 一条断言不许改。** 它红了说明不是纯搬运——回去改实现,不是改断言。这是判断「mixin 有没有搬坏」的主证据。
|
||||
2. **方法体一字不改。** mixin 里的方法必须与搬走前逐字相同(除了必要的 import 调整)。允许用 `git diff -M` / `--color-moved` 之类的手段证明是移动而非改写,并把证明写进进度记录。
|
||||
3. **mixin 模块不得 import `jyotish_api_server`。** 那等于把后门换了个地方开。要有断言钉住这个方向。
|
||||
4. **不得改 `do_POST` / `do_GET` 的路由结构**(阶段 3 不做)。
|
||||
5. 搬完后 `JyotishAPIHandler` 仍须通过继承拥有这些方法——**HTTP 侧的可见行为必须零变化**。
|
||||
6. 不得顺手升级依赖、不得顺手修不在本单里的 warning。
|
||||
|
||||
## 5. 任务分解
|
||||
|
||||
### 5.1 先自己把闭包算一遍
|
||||
### 5.1 重算闭包(已完成,结论见 §1)
|
||||
|
||||
不要抄本任务书的 8 个方法。开工时用同样的方法重算(从 5 个入口方法出发,跟着 `self._x()` 追传递闭包,并标出哪些碰 HTTP 上下文),结果写进进度记录。代码可能已经漂移。
|
||||
执行方已按第一版 §5.1 重算并提交在 `dfd65528`(仅文档提交)。开工时以当时代码复核一次即可,不必从头再算。
|
||||
|
||||
- 验收:进度记录里有闭包清单、行数、以及「碰 HTTP 上下文的有几个」。
|
||||
- 验收:若重算出来**有**方法碰 HTTP 上下文,**停手**,把那几个列出来先问——本单的前提是它们都不碰。
|
||||
### 5.2 spike 闸门(**必须先做,不产出正式交付**)
|
||||
|
||||
### 5.2 把闭包搬进独立模块
|
||||
一次性验证,目的是回答「mixin 搬动会不会打红安全测试、会不会解不开循环 import」:
|
||||
|
||||
按职责放进 `scripts/` 下的新模块(建议按 vedastro 证据 / 咨询工作流 / 合盘分组,不要一股脑塞一个文件)。`JyotishAPIHandler` 里对应位置改成薄调用。
|
||||
1. 把闭包里的方法整体移进 `ConsultationComputeMixin`,`JyotishAPIHandler(BaseHTTPRequestHandler, ConsultationComputeMixin)`。
|
||||
2. **`tests/test_api_server_security.py` 一个字不改直接跑。**
|
||||
|
||||
- 验收:`scripts/jyotish_api_server.py` 的类方法数下降,新值写进合同测试。
|
||||
- 验收:新模块不 import `jyotish_api_server`,有断言。
|
||||
判定:
|
||||
|
||||
### 5.3 三个调用方改成直接 import
|
||||
- **绿** → B 可行,继续 5.3。
|
||||
- **红** → 记录红在哪、为什么,**退回 A**(只搬 vedastro 证据 + 合盘那 7 方法 / 300 行,关掉 2 个伪造点,scripts 侧 4 → 2),并在进度记录里写明 B 为什么不可行。
|
||||
|
||||
`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`)仍然可用——至少一条端到端断言。
|
||||
- `test_api_server_security.py` 里**没有任何** `__dict__` / `inspect` / `__qualname__` / `__module__` 结构性断言,只按行为断言。
|
||||
- 增长合同数类方法用的是整文件正则 `^ (?:async )?def`,方法搬到别的文件后计数自然下降,口径不用改。
|
||||
|
||||
### 5.4 合同测试收基线
|
||||
**B 的真风险是循环 import**:闭包里的方法引用了同文件的 **44 个模块级函数**与 **21 个模块级常量/类**(`execute_consultation_workflow`、`BadRequest`、`_load_local_module` 等)。这些要么跟着搬进 mixin 模块、要么提到第三个共享模块。spike 必须把这一条也验掉——解不开就是 A。
|
||||
|
||||
`tests/test_api_server_growth_contract.py`:`__new__` 计数基线 4 → **0**;类方法数基线更新为收尾实测值;行数粗护栏 baseline 重设为收尾实测 + 300。同步更新文件顶部 docstring 的日期与说明。
|
||||
- 验收:spike 结论(绿/红、红在哪)写进进度记录,无论走 B 还是退 A。
|
||||
|
||||
- 验收:人为加回一处 `JyotishAPIHandler.__new__` 必须让测试变红(贴反向验证)。
|
||||
### 5.3 正式搬运
|
||||
|
||||
按 spike 验证过的形状做完整搬运。若闭包在两个入口上确实可分(§1 那张表),建议拆成两个 mixin(vedastro 证据 + 合盘 / 咨询工作流),便于将来继续细分;但不强制。
|
||||
|
||||
- 验收:`JyotishAPIHandler` 的方法数显著下降,新值写进合同测试。
|
||||
- 验收:mixin 模块不 import `jyotish_api_server`,有断言。
|
||||
- 验收:`git diff` 能证明方法体是移动而非改写。
|
||||
|
||||
### 5.4 四个调用方改成直接用 mixin
|
||||
|
||||
`consultation_workflow_service.py`(两处)、`capture_report_blocked_repairs_golden.py`、`local_accuracy_report.py` 改成实例化 mixin,删掉 `JyotishAPIHandler.__new__` 与对 `jyotish_api_server` 的 import。
|
||||
|
||||
- 验收:四个文件都不再 import `jyotish_api_server`。
|
||||
- 验收:MCP 侧(`mcp_server.py:741` / `:4749` 经由 `consultation_workflow_service`)仍可用——至少一条端到端断言。
|
||||
|
||||
### 5.5 合同测试收基线
|
||||
|
||||
`tests/test_api_server_growth_contract.py`:`__new__` 的 **scripts 侧**计数收到 0(tests 侧保持不增长);类方法数基线更新为收尾实测值;行数粗护栏 baseline 重设为收尾实测 + 300。同步更新文件顶部 docstring 的日期与说明。
|
||||
|
||||
- 验收:人为加回一处 `JyotishAPIHandler.__new__`(在 `scripts/` 下)必须让测试变红(贴反向验证)。
|
||||
- 验收:人为加一个类方法必须变红(贴反向验证)。
|
||||
- 验收:该文件既有的三条断言(`AGENTS.md` 必须含 `must not grow` / `thinly registered`、该测试必须在 `CORE_PYTEST_TARGETS` 与快速门里)仍绿。
|
||||
|
||||
### 5.5 记录
|
||||
### 5.6 记录
|
||||
|
||||
本单不产生 Bug 记录(结构改造,不是缺陷),不进 `CHANGELOG.md`(无用户可感知变化)。进度记录里必须有:闭包清单、搬前/搬后的类方法数与行数、两次反向验证结果。
|
||||
本单不产生 Bug 记录(结构改造,不是缺陷),不进 `CHANGELOG.md`。进度记录里必须有:spike 结论、闭包清单、搬前/搬后的类方法数与行数、两次反向验证结果、方法体未改写的证明。
|
||||
|
||||
同轮把原 `TASK-api-server-decomposition-20260916` 在状态板上标成**已取代(阶段 1 由本单完成;阶段 2/3 不立单,由门禁长期推进)**。
|
||||
同轮把原 `TASK-api-server-decomposition-20260916` 在状态板上标成**已取代**。
|
||||
|
||||
## 6. 让步顺序
|
||||
|
||||
1. 5.1 **不得砍**——闭包没重算就动手,等于拿本任务书的旧数字赌代码没漂。
|
||||
2. 5.2 + 5.3 是主体,必须一起做(只搬不改调用方,后门还在)。
|
||||
3. 5.4 不得砍——`__new__` 计数收到 0 是本单唯一的成功判据。
|
||||
4. 5.5 不得砍。
|
||||
1. 5.2 spike **不得砍**——它是 B 与 A 的分水岭。
|
||||
2. spike 绿则 5.3 + 5.4 必须一起做(只搬不改调用方,后门还在)。
|
||||
3. spike 红则整单退化为 A,并在进度记录里写清楚,**不要硬做 B**。
|
||||
4. 5.5、5.6 不得砍。
|
||||
|
||||
## 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
|
||||
cd .worktrees/api-server-backdoor-close-20260916 # 分支已存在,rebase 到最新 staging
|
||||
git rebase origin/staging
|
||||
git status -sb | head -1
|
||||
# 重算基线
|
||||
grep -rn "JyotishAPIHandler.__new__" --include=*.py . | grep -v "skills/.*/versions/"
|
||||
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
|
||||
tests/test_consultation_consumer_context.py tests/test_vedastro_gateway.py \
|
||||
tests/test_vedastro_snapshot_cache.py
|
||||
.venv/bin/python scripts/run_quality_gate.py --profile quick # 退出码不要隔着管道取
|
||||
```
|
||||
|
||||
**注意**:快速门当前在本机退出 1,唯一原因是无 `rsync`(`staging-backend-workflows.test.ts`)与无 Docker 的既有环境缺口,见 `BLOCKED.md` BLK-002 / BLK-003。**pytest 段必须是 0 failed**(`dc8cae31` 之后是 792 passed / 1 skipped)。
|
||||
|
||||
## 8. BUG 编号起点
|
||||
|
||||
本单不占 BUG 号。基线 `4f643aa0` 上最大号 **BUG-733**;734/735 已被 `TASK-consultation-residual-hotspots-20260916` 预占。
|
||||
本单不占 BUG 号。基线 `dc8cae31` 上最大号 **BUG-736**。
|
||||
|
||||
## 9. 不在本单范围
|
||||
|
||||
- 阶段 2(抽 ≥150 行业务方法)与阶段 3(`do_POST` 路由表)——**不立单,由门禁长期推进**
|
||||
- `execute_consultation_workflow` 里的任何业务逻辑改动
|
||||
- 外网探测与 yoga 编译缓存(见 `TASK-consultation-residual-hotspots-20260916`)
|
||||
- 阶段 3(`do_POST` 78 个 elif 改路由表)——不立单,由门禁长期推进
|
||||
- `execute_consultation_workflow` 里的任何业务逻辑改动(只能整体搬,不能改)
|
||||
- `tests/` 下那 29 处 `__new__`(保持不增长即可)
|
||||
|
||||
Reference in New Issue
Block a user