Files
Jyotisha/docs/tasks/TASK-api-server-service-extract-fix-20261016.md
T

6.4 KiB
Raw Blame History

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 下的正斜杠 / 反斜杠两种写法)替换成固定占位符 <ROOT>,并把其后的路径分隔符统一成 /。不要按字段名白名单去删,避免以后新增路径字段又漏。
  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 片段。