diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index 1710809c..2a6d641a 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -36378,7 +36378,8 @@ - 根因:咨询结果里的清单路径是仓库根目录的绝对路径,规范化只去掉了两个墙钟字段。采集脚本又把这个共用缓存目录整个删掉。缓存有效期为 0 时,现有读函数直接返回空、写函数不落盘。BUG-1060 已经要求采集时把有效期设为 0,因为命中缓存会改变列表顺序;这次新脚本没有沿用,改成了删目录。 - 修复:所有字符串值里的仓库根目录绝对路径(反斜杠、正斜杠,以及 Windows 扩展前缀)换成 ``,后面的分隔符统一成 `/`。不按字段名挑选。采集期间设置 `JYOTISH_API_CHART_CACHE_TTL_SECONDS=0`,结束恢复原值,不再删除缓存目录。在基线 `fbf04f0b5f31cd8421bc4546840b1c833aaed810` 与本分支各采集一次,8 个哈希相同,用这份结果覆盖金样。方法数常量旁被盖住的 BUG-1341 三栏已恢复,本单说明另起一行。 - 验证:有效期为 0 时读取结果为空,缓存目录文件数采集前后都是 2。基线与本分支 8 个哈希逐个相同。金样、增长合同、以及上次并行变红的那一条一起跑,11 通过、0 失败。没有改那条在改代码之前就已经失败的校正测试的断言。 -- 防复发:金样测试仍要求 sha256 与键路径类型全等,没有改成只比键或字节数。采集脚本里不再删除仓库内缓存目录。 +- 补充(2026-10-16,第二次验收):换路径后在 Linux 上仍对不齐。更深的根因:`defer_optional_external_evidence=True` 时 VedAstro 观察在后台线程跑、主流程只等固定秒数(`scripts/vedastro_foreground.py`),还会读写快照与负缓存目录,所以哈希取决于机器快慢与本机缓存状态。产品负责人在 issue #70 选 B:删除常驻测试 `tests/test_api_service_extract_golden.py`,采集脚本与金样文件留作同一台机器上的手动对照工具。拆类等价性改由验收时逐方法 AST 比对、基线与分支逐字段比对(只差工作树路径)和本机 API 冒烟证明。 +- 防复发:采集脚本不再删除仓库内缓存目录;脚本文档写明只能在同一台机器上比较。整份咨询输出的哈希不再作为跨机器的测试门禁。 - 相关记录:BUG-1060 - 复发自:无 - 修复版本:分支 `codex/api-server-service-extract-20261013`。修复单写明无 BUG 编号;本条是验收打回的测试失败。开工时本分支最大已用编号是 BUG-1358,1351、1352、1353 已有条目,本条用 BUG-1359。 diff --git a/docs/tasks/PROGRESS-api-server-service-extract-fix-20261016.md b/docs/tasks/PROGRESS-api-server-service-extract-fix-20261016.md index c85e1865..0bda54d6 100644 --- a/docs/tasks/PROGRESS-api-server-service-extract-fix-20261016.md +++ b/docs/tasks/PROGRESS-api-server-service-extract-fix-20261016.md @@ -51,3 +51,19 @@ - 修复单写「无 BUG 编号」。本轮按仓库规则补了 BUG-1359,原因见上。 - 没有把「删除共用缓存」和「有效期为 0」再各采一次来拆开那 122 字节。删除共用目录会再次打到别的测试,修复单不允许。金样以「缓存不生效」为准。 - 没跑全量 `pytest -n 4`,所以不能在这里声称失败清单已与基线逐名一致。 + +## Claude 验收记录(2026-10-16,产品选 B 后) + +- 第二次验收(`a7fe7e9dd`):F2、F3 通过;金样在 Linux 仍红,根因是咨询流程里 VedAstro 观察在后台线程运行、只等固定秒数,哈希取决于机器快慢与本机快照缓存(详见 `TASK-api-server-service-extract-fix-20261016-2.md`)。按规则第 2 次打回转产品拍板。 +- 产品负责人在 issue #70 选 **B**:由 Claude 删除常驻测试,采集脚本与金样文件留作同一台机器上的手动对照工具。 + +| 改动 | 原值 | 新值 | 原因 | +| --- | --- | --- | --- | +| `tests/test_api_service_extract_golden.py` | 1 条测试,跨机器重算整份咨询输出哈希 | 删除 | 哈希取决于后台线程等待结果与本机缓存,不能跨机器复现;拆类等价性已由下面三项证明 | +| `scripts/research/api_service_extract_golden.py` 文档 | — | 写明是手动工具、只能同机比较 | 防止以后再被当成门禁 | + +拆类等价性证据(Claude,Linux): + +- AST:基线与分支 215 个方法名集合相同、方法体逐个相等;模块级函数与其他顶层语句全等;`JyotishComputeService` 200 个方法,`JyotishAPIHandler` 15 个 HTTP 方法 + `server_version`。 +- 结果:基线与分支各跑 `capture_mcp('career')`,逐字段只差 3 个 `manifest_path`(两个工作树目录名不同);基线连跑两次 0 差异;`repairs`、`evidence` 哈希两边相同。 +- 冒烟:本机并排起服务,`/api/health` 200、虚构盘 `/api/chart` 200(只差时间戳)、非 JSON 400、`text/plain` 415、3 MB 请求体 400、未知路径 404、OPTIONS 200、`Server` 头相同。 diff --git a/scripts/research/api_service_extract_golden.py b/scripts/research/api_service_extract_golden.py index 59a95a42..e5457cfc 100644 --- a/scripts/research/api_service_extract_golden.py +++ b/scripts/research/api_service_extract_golden.py @@ -3,6 +3,11 @@ Fictional smoke chart only. Clock fields are removed before hashing. Absolute repository paths in string values are replaced with . Payload values are not written; the golden file stores sha256 and key-path types. + +Manual tool, not a pytest gate (2026-10-16, issue #70 option B). The +consultation output includes a VedAstro observation that runs on a background +thread with a join timeout, so hashes depend on machine speed and on the +local snapshot caches. Compare captures from one machine only. """ from __future__ import annotations diff --git a/tests/test_api_service_extract_golden.py b/tests/test_api_service_extract_golden.py deleted file mode 100644 index 9d8de38a..00000000 --- a/tests/test_api_service_extract_golden.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Recompute the fictional smoke chart and compare canonical hashes. - -The stored golden keeps sha256 and key-path types only. -""" -from __future__ import annotations - -import importlib.util -from pathlib import Path - - -def test_api_service_extract_golden_matches_baseline() -> None: - path = Path(__file__).resolve().parents[1] / "scripts" / "research" / "api_service_extract_golden.py" - spec = importlib.util.spec_from_file_location("api_service_extract_golden", path) - assert spec is not None and spec.loader is not None - module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(module) - assert module.check_golden() == []