Files
Jyotisha/docs/tasks/PROGRESS-api-server-service-extract-20261013.md
T
jesse-uxandGrok (agent loop) c7350bcafb 把星盘接口的计算和 HTTP 拆成两个类,离线入口不再伪造请求对象。
方法体未改。定向测试 383 通过;1 条校正回归在基线上同样失败,断言未改。快速门和全量 pytest 未跑。

Co-Authored-By: Grok (agent loop)
2026-10-16 10:24:42 +08:00

89 lines
7.2 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.
# PROGRESS · API 计算与 HTTP 拆类(2026-10-16)
- 分支:`codex/api-server-service-extract-20261013`
- 任务书里的基线 `2994588ad4d858dead4835943e5883c5aa2b03f8` 已过期。本分支从当前 `origin/staging` `fbf04f0b5f31cd8421bc4546840b1c833aaed810` 新建,没有上游。该提交已包含 #69 与 #68。
- 没有新 BUG 编号。结构改造,不写 `docs/BUG_HISTORY.md`,不写 `CHANGELOG.md`。
## 开工重测
| 指标 | 任务书写作时 | 开工实测 |
| --- | --- | --- |
| `scripts/jyotish_api_server.py` 换行数 | 10970 | **10906** |
| 四空格 `def`(合同口径) | 218 | **217**(BUG-1341 已下调,本单保持) |
| `JyotishAPIHandler` 类方法 | 215 | **214** |
| `JyotishAPIHandler.__new__` 合计 | 31 | **31**(`scripts/` 2 + `tests/` 29,不含合同文件) |
| 行数基线 / 上限 | 10924 / 11224 | 基线不动。搬后换行数 **10920**,低于基线 |
HTTP 侧按「直接碰 HTTP 成员或覆写 `BaseHTTPRequestHandler`,再向上收到调用闭包」重算,仍是 15 个方法,外加 `server_version`:
- 直接:`_json`、`_html`、`_send_cors_headers`、`_enforce_request_security`、`_job_access_token`、`do_OPTIONS`、`do_GET`、`do_POST`、`_read_json_body`
- 调用者:`_error_json`、`_require_dynamic_rectification_token`、`_get_high_rigor_job`、`_get_chart_job`、`_compute_dynamic_rectification_opportunities`、`_compute_dynamic_rectification_score`
类里没有 `self.xxx =` 赋值。
## 做了什么
- 同一文件里把原类改成 `JyotishComputeService`(199 个计算方法),新增 `JyotishAPIHandler(BaseHTTPRequestHandler, JyotishComputeService)`,放入上面 15 个方法和 `server_version`。`ThreadingHTTPServer` 仍用 `JyotishAPIHandler`。
- 方法体与基线逐个 `ast.dump` 相等:旧类 214 个方法,新文件 214 个方法,不一致 **0**。换类的成员是这 15 个方法加 `server_version`,共 16 个。
- `scripts/consultation_workflow_service.py` 和 `scripts/capture_report_blocked_repairs_golden.py` 改为 `JyotishComputeService()`。`scripts/` 里 `JyotishAPIHandler.__new__` 为 **0**。
- 只用计算方法的 17 个测试文件同样改了构造。`tests/test_active_rectification_api.py` 里 3 处补丁从 HTTP 类改到计算类,否则补丁打不中实例。断言没改。
- 增长合同:总伪造 31 → **5**,生产伪造 2 → **0**,方法数 217 不变,行数基线 10924 不动。新增两条守卫:计算类不是 HTTP 处理器子类(并钉住 MRO 与 `server_version`);计算类方法体不碰 HTTP 成员、也不调用上述 15 个方法。
- 搬前 golden 连跑两次哈希一致,落在 `tests/golden/api_server_service_extract_v1.json`(只存 sha256 和键路径类型)。采集脚本:`scripts/research/api_service_extract_golden.py`。搬后对照由 `tests/test_api_service_extract_golden.py` 重算,通过。
构造语句三栏(17 个测试文件和 2 个生产文件,每处相同):
| 原值 | 新值 | 原因 |
| --- | --- | --- |
| `JyotishAPIHandler.__new__(JyotishAPIHandler)` | `JyotishComputeService()` | 计算类可以正常实例化,不必再绕过 HTTP 构造 |
`tests/test_active_rectification_api.py` 另有三处:
| 原值 | 新值 | 原因 |
| --- | --- | --- |
| 补丁打在 `JyotishAPIHandler` | 补丁打在 `JyotishComputeService` | 实例已是计算类,补丁必须打在实例的类上。断言未改 |
未改的 HTTP 侧伪造(5 处,合同新基线就是这 5 处):`test_api_server_security.py`、`test_api_async_job_contract.py`、`test_runtime_security_p0.py`、`test_dynamic_rectification_scoring.py`、`test_professional_report_reference_api.py`。其中安全测试文件 `git diff` 为空。
## 命令和结果
| 检查 | 命令 | 结果数字 |
| --- | --- | --- |
| 搬前 golden 连跑两次 | 基线上采集 MCP / HTTP / 报告裁剪 / 证据助手 | 8 个哈希两次相同 |
| 搬后 golden | `pytest tests/test_api_service_extract_golden.py`(含在下面那条里) | 通过,与搬前哈希一致 |
| 任务书点名测试 + 改过的测试 + 两个调用了采集入口的测试 | `pytest` 上述文件 `-q --tb=line` | **383 通过,1 失败**,约 1046 秒 |
| 方法体对比 | 基线文件与工作树 `ast.dump` | 214 对 214,不一致 0 |
| 反向:计算类临时写 `self.headers` | `test_compute_service_methods_do_not_touch_http` | 失败后已撤回 |
| 反向:`scripts/` 临时加一处伪造标记 | `test_scripts_handler_forgeries_must_not_grow` | 1 > 0,失败后已撤回 |
| 安全测试文件 | `git diff -- tests/test_api_server_security.py` | 空 |
| 生产伪造 | 在 `scripts/**/*.py` 搜伪造标记 | **0** |
| 换行数 | 文件内 `\n` 个数 | 10906 → **10920**(上限 11224) |
| 隐私标记 | `pytest tests/test_repo_privacy_markers.py -q` | 退出码 0 |
搬前哈希(去掉两个墙钟字段后的规范 JSON):
| 案例 | sha256 | 字节 |
| --- | --- | ---: |
| mcp.career | `ad38a539cf9036143333acd538567b7eb94528d537c46ef326905ebc47527a05` | 543868 |
| http.career | `6a6ca421d942e2577e587647324ef9521ea14841a74a6850c11f629df4d9ba96` | 420555 |
| mcp.wealth | `9aaacf64d08f17bca2d3f6b020b1dbb1ec07eaee7727b04bba90430fcbf594d3` | 542629 |
| http.wealth | `f22368bbde38b76dc44e2995c34f7809ca96442405c1f13e39f53c4a2dd90a62` | 419316 |
| mcp.relationship | `be70fd603b1de52026ad40f0d6582a27cb8b148018474fcd7d8c4134509b40ae` | 537785 |
| http.relationship | `4405ae821aef81ec03660994d9f8f4104ae3388f339407bfe2721d05d662059b` | 414472 |
| repairs | `41d48a453fbd5d616de083fe07bb8d318c3f60ad2e127764237ef6ae50cc6175` | 74700 |
| evidence | `27975ba40a9ee89fc19543a18cb2ee60fb2477b8a6e8f14004ad411adfc408a2` | 2092 |
MCP 与 HTTP 彼此不相等:MCP 走 `surface=skill_mcp`,HTTP 方法默认 `api_web`,并且 HTTP 方法还会多挂一层咨询全文。这是原来的两条路径,不是这次拆类造成的。每条路径搬前搬后各自一致。
## 那 1 条失败
`tests/test_active_rectification_api.py::test_long_real_conversation_reaches_vedastro_after_local_range_is_narrow` 期望时间窗 `05:07–05:08`,实际得到 `07:00–07:02`。把该测试文件还原到基线后再跑,失败内容相同。不是拆类引入的,也不是「用到了 HTTP」。按任务书,这种红不回退该文件。断言没改。同文件其余测试在本轮通过。
## 偏离
- 任务书交付物写了「删两处死代码」。硬红线写明零引用函数只记进度、本单不删。`_strict_adjudication_bundle_from_contract` 与 `_high_rigor_job_path` 仍只在定义处出现,没有删。
- 后续「把咨询闭包搬出文件、改依赖方向」没做。那一步要改安全测试的补丁落点,任务书明确不做。
- `AGENTS.md` §6 没有写死伪造数字 31 或 2,所以没改措辞。
- `skills/jyotish-vedic-astrology/scripts/` 里的同名副本没改。任务书点名的是 `scripts/`。合同计数也不含技能副本。
- 另有若干 `object.__new__(JyotishAPIHandler)`,不在合同计数里,调用的是计算方法,经继承仍可用。本单没改。
- 没跑:Python 快速门、全量 pytest、前端 `npm test`、`test:db`。没动数据库,也没对生产或 staging 做压测或登录。