From 187fa375f591fb9b7f256cd70aa347fb38a6d5f8 Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Fri, 16 Oct 2026 11:10:12 +0800 Subject: [PATCH] docs(tasks): api-server service extract fix brief (issue #70) Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LutgzyJqNhPpZy1nFsJtN3 --- ...api-server-service-extract-fix-20261016.md | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 docs/tasks/TASK-api-server-service-extract-fix-20261016.md diff --git a/docs/tasks/TASK-api-server-service-extract-fix-20261016.md b/docs/tasks/TASK-api-server-service-extract-fix-20261016.md new file mode 100644 index 00000000..9613fc20 --- /dev/null +++ b/docs/tasks/TASK-api-server-service-extract-fix-20261016.md @@ -0,0 +1,72 @@ +# TASK · API 单体拆类 · 修复单(issue #70,第 1 次打回) + +- 日期:2026-10-16 +- 被验提交:`c7350bcafbff64d3c526c2dbf3995c9845b3b66e`(分支 `codex/api-server-service-extract-20261013`) +- 原任务书:`docs/tasks/TASK-api-server-service-extract-20261013.md` +- 执行方:Grok;在**同一分支**上追加提交(基于 `c7350bcaf`,不改写已推历史);若 `origin/staging` 已前进,用 `git merge origin/staging`,不要 rebase +- BUG 编号:无(仍属结构改造) + +## 验收结论(Claude,Linux) + +拆类本身**通过**;新增的金样测试**未通过**,因此整单打回。 + +| 项 | 结论 | 证据 | +| --- | --- | --- | +| T2 纯移动 | 通过 | AST 对比:基线与本分支 215 个方法名集合相同、方法体逐个 `ast.dump` 相等;模块级函数与其他顶层语句全等;`JyotishComputeService` 200 个方法,`JyotishAPIHandler` 15 个 HTTP 方法 + `server_version` + docstring | +| T3 生产伪造归零 | 通过 | `grep -rn "JyotishAPIHandler.__new__" scripts` 0 命中 | +| T3 结果等价 | 通过(Claude 自证) | 基线工作树与本分支各跑 `capture_mcp('career')`(清缓存),逐字段比对只差 3 个 `manifest_path` 绝对路径(两个工作树目录名不同);基线连跑两次 0 差异;`repairs`、`evidence` 两路哈希两边相同 | +| T4 测试伪造下调 | 通过 | 17 个文件只改构造语句与类型注解;伪造合计 31 → 5 | +| T5 合同与守卫 | 通过(附一处文字要求,见 F3) | 两条新守卫在本机绿 | +| `test_api_server_security.py` 零改动 | 通过 | `git diff --stat` 空 | +| 本机 API 冒烟 | 通过 | 基线与本分支并排:`/api/health` 200、`/api/chart` 虚构盘 200(只差时间戳字段)、非 JSON 400、`text/plain` 415、3 MB 请求体 400、未知路径 404、OPTIONS 200、`Server: JyotishAPI/6.9.14` 头,响应体逐字相同 | +| **T1 金样测试** | **未通过** | 见 F1、F2 | +| 全量 pytest(`-n 4`)与基线逐名比对 | **未通过** | 本分支比基线多 2 条失败:`test_api_service_extract_golden.py::test_api_service_extract_golden_matches_baseline`(单独跑也红)、`test_capture_commercial_astrology_e2e_contexts.py::test_capture_writes_runtime_contexts_without_required_layer_echo`(单独跑绿,并行红,见 F2) | + +## F1 · 金样哈希含本机绝对路径,换机器必红(必做) + +**现象**:本机单独跑 `pytest tests/test_api_service_extract_golden.py`,7 条哈希全部不等,如 `http.career sha256 6a6ca4… != 0c8ef6… bytes 420555 != 441296`。 + +**根因**:咨询工作流响应里有 `external_parity_gate.manifest_path`、`real_case_calibration.holdout_replay_manifest.manifest_path`、`real_case_calibration.outcome_replay_manifest.manifest_path` 等字段,值是运行机器上的绝对路径。`canonical_text` 只去掉了两个墙钟字段,没处理路径,所以金样只在采集它的那台 Windows 机器、那个目录下成立。CI 和任何其他检出都会红。 + +**修法**: + +1. 在 `scripts/research/api_service_extract_golden.py` 的规范化里,把所有字符串值中的仓库根目录绝对路径(`str(ROOT)`,以及 Windows 下的正斜杠 / 反斜杠两种写法)替换成固定占位符 ``,并把其后的路径分隔符统一成 `/`。不要按字段名白名单去删,避免以后新增路径字段又漏。 +2. 在**基线**(`origin/staging` 上本单开工时的 SHA,写进 `fixtureProvenance`)重新采集金样,覆盖 `tests/golden/api_server_service_extract_v1.json`。 +3. 在本分支上用 `check_golden()` 对照,全部相等。 + +**验收标准**:Claude 在 Linux 上、任意检出目录下单独跑这条测试为绿;Grok 在 Windows 上同样为绿。PROGRESS 里贴两次采集(基线、本分支)的 8 个哈希。 + +## F2 · 测试过程中删除共用排盘缓存目录,并行时打红别的测试(必做) + +**现象**:全量 `pytest -n 4` 时 `test_capture_commercial_astrology_e2e_contexts.py::test_capture_writes_runtime_contexts_without_required_layer_echo` 变红;单独跑为绿,基线全量也为绿。 + +**根因**:`clear_chart_cache()` 对仓库内的 `scratch/local/api_chart_cache` 做 `shutil.rmtree`。全量测试多进程并行,其他测试正在读写同一个目录,被中途删掉。研究脚本手动跑时清缓存没问题,但放进 pytest 就成了共享状态破坏。 + +**修法**(二选一,推荐 a): + +- a. 不删目录,改为在采集期间设置环境变量 `JYOTISH_API_CHART_CACHE_TTL_SECONDS=0` 让排盘缓存不生效(现有测试 `tests/test_commercial_domain_calculation_contract.py` 已用这个办法),采集结束恢复原值。先确认 TTL 为 0 时确实既不读也不写缓存;若仍会写入,则同时用 `monkeypatch` / 临时目录把 `_api_chart_cache_dir` 指向 `tmp_path`。 +- b. 测试里用 `monkeypatch.setattr(jyotish_api_server, "_api_chart_cache_dir", lambda: tmp_path / "cache")`,研究脚本的 `clear_chart_cache` 只清这个临时目录。 + +**验收标准**: + +- 金样测试里不再出现对仓库内 `scratch/local/api_chart_cache` 的删除(`grep -n rmtree` 只允许作用于临时目录)。 +- 本分支全量 `pytest -n 4` 的失败清单与基线逐名一致(Claude 复跑)。 +- 金样结论不变(缓存不生效时与清空缓存时的输出相同;如有差异,在 PROGRESS 写明并以「缓存不生效」为准重采)。 + +## F3 · 方法数常量旁的旧三栏被改写(必做,小) + +`tests/test_api_server_growth_contract.py` 里 `JYOTISH_API_HANDLER_METHOD_COUNT_BASELINE` 上方原有的三栏(`原值:218(删占位回退之前)/ 新值:217 / 原因:BUG-1341 …`)被改成了 `原值:217 / 新值:217 / 原因:…`,丢了 BUG-1341 那次下调的记录。 + +**修法**:恢复原来三行原样;本单的说明(数值未变)如需保留,另起一行注释写在其后,不覆盖历史。 + +**验收标准**:`git diff origin/staging -- tests/test_api_server_growth_contract.py` 中,原有三栏三行不再出现在删除行里。 + +## 不要做 + +- 不改拆类本身(T2/T3/T4 已通过),不动 `scripts/jyotish_api_server.py`。 +- 不改 `tests/test_api_server_security.py`。 +- 不放宽金样比对(不许改成只比键路径或字节数)。 + +## 回报 + +在 issue #70 回报新 SHA,表格里写:金样单独跑结果(Windows)、全量 pytest 失败清单相对基线的差(若 Windows 能跑)、F3 的 diff 片段。