#!/usr/bin/env python3 """build_snapshot.py 的无网络离线测试。""" import pathlib import sys import unittest PROJECT_ROOT = pathlib.Path(__file__).resolve().parents[3] SCRIPT_DIR = PROJECT_ROOT / "muse" / "lifecycle" / "context" / "skills" / "固定任务上下文" / "scripts" sys.path.insert(0, str(SCRIPT_DIR)) from build_snapshot import ( # noqa: E402 SnapshotError, build_snapshot, build_snapshot_manifest, filter_milestones, filter_outline_windows, normalize_chapter, remove_terminal_fields, ) META = { "targetChapter": 489, "referenceWork": {"id": "deep-space", "version": "v1"}, "evaluationSetVersion": "set-v1", "strategyVersion": "strategy-v1", "authorizationSnapshot": { "id": "auth-1", "version": "v1", "immutable": True, "sourceVersion": "work-v1", "sourceStatus": "active", "allowedPurpose": ["offline_evaluation"], "checkedAt": "2026-07-19T00:00:00Z", "revalidationAt": "2026-07-20T00:00:00Z", }, "runPermissions": {"purpose": "offline_evaluation", "mode": "dry_run"}, "armConfig": {"arms": ["outline_only", "outline_plus_cards", "outline_plus_placebo_cards"]}, } class BuildSnapshotTest(unittest.TestCase): def test_normalize_chapter_rejects_guessing(self): self.assertEqual(normalize_chapter(488), 488) self.assertEqual(normalize_chapter(" 488 "), 488) self.assertIsNone(normalize_chapter(True)) self.assertIsNone(normalize_chapter(488.0)) self.assertIsNone(normalize_chapter("第488章")) def test_milestones_are_frozen_by_absolute_chapter(self): kept, omitted = filter_milestones( [ {"章": 487, "台阶": "已知"}, {"章": "488", "台阶": "已知字符串"}, {"章": "489", "台阶": "未来"}, {"章": "487-490", "台阶": "跨冻结点"}, {"台阶": "没有章号"}, ], 488, ) self.assertEqual([item["台阶"] for item in kept], ["已知", "已知字符串"]) self.assertEqual( [item["reason"] for item in omitted], ["future_or_crosses_as_of", "future_or_crosses_as_of", "missing_or_unbounded_chapter"], ) self.assertTrue(all("台阶" not in item for item in omitted)) def test_outline_windows_require_complete_to_order(self): kept, omitted = filter_outline_windows( [ {"window_no": 2, "from_order": 401, "to_order": 430}, {"window_no": 1, "from_order": 431, "to_order": 490}, {"window_no": 3, "from_order": "bad", "to_order": 500}, ], 488, ) self.assertEqual([item["from_order"] for item in kept], [401]) self.assertEqual([item["reason"] for item in omitted], ["future_or_crosses_as_of", "missing_or_invalid_window_bounds"]) def test_terminal_fields_are_removed_recursively(self): value = { "name": "苏铭", "current_state": "终局状态", "nested": {"future_arc": "未来计划", "safe": "保留"}, "items": [{"终态摘要": "不应出现"}, {"safe": "保留"}], } self.assertEqual(remove_terminal_fields(value), {"name": "苏铭", "nested": {"safe": "保留"}, "items": [{}, {"safe": "保留"}]}) def test_nested_card_history_is_frozen(self): result = build_snapshot( { "cards": [ { "name": "生物机甲", "milestones": [ {"chapter": 488, "step": "可见"}, {"chapter": 489, "step": "未来"}, ], "current_state": "终态字段不得透传", } ] }, 488, "v0", target_chapter=489, manifest_metadata=META, ) card = result["snapshot"]["cards"][0] self.assertEqual(card["milestones"], [{"chapter": 488, "step": "可见"}]) self.assertNotIn("current_state", card) self.assertEqual(result["manifest"]["omittedSources"][0]["reason"], "future_or_crosses_as_of") def test_manifest_is_stable_and_does_not_store_payload(self): kwargs = { "as_of": 488, "target_chapter": 489, "snapshot_version": "v0", "reference_work": META["referenceWork"], "evaluation_set_version": META["evaluationSetVersion"], "strategy_version": META["strategyVersion"], "authorization_snapshot": META["authorizationSnapshot"], "run_permissions": META["runPermissions"], "arm_config": META["armConfig"], "sections": {"l0": {"sourceId": "task", "sourceVersion": "1", "payload": {"target": 489}}}, "final_report": {"status": "ready", "hashes": {"sourceHash": "abc"}}, } first = build_snapshot_manifest(**kwargs) second = build_snapshot_manifest(**kwargs) self.assertEqual(first, second) self.assertNotIn("payload", first["sections"]["l0"]) self.assertEqual(len(first["manifestSha256"]), 64) self.assertNotIn("原书", str(first["finalReport"])) def test_final_report_rejects_original_text_fields(self): with self.assertRaises(SnapshotError): build_snapshot_manifest( as_of=488, target_chapter=489, snapshot_version="v0", reference_work=META["referenceWork"], evaluation_set_version=META["evaluationSetVersion"], strategy_version=META["strategyVersion"], authorization_snapshot=META["authorizationSnapshot"], run_permissions=META["runPermissions"], arm_config=META["armConfig"], sections={}, final_report={"raw_text": "原书全文"}, ) def test_unknown_chapter_collection_is_filtered_and_terminal_fields_are_audited(self): result = build_snapshot( { "chapters": [{"chapter": 489, "fact": "未来"}, {"chapter": 488, "fact": "已知"}], "cards": [{"name": "事件", "event_result": "未来结果", "relationshipPlan": "未来计划"}], }, 488, "v0", target_chapter=489, manifest_metadata=META, ) self.assertEqual(result["snapshot"]["chapters"], [{"chapter": 488, "fact": "已知"}]) self.assertNotIn("event_result", result["snapshot"]["cards"][0]) self.assertNotIn("relationshipPlan", result["snapshot"]["cards"][0]) reasons = [item["reason"] for item in result["manifest"]["omittedSources"]] self.assertIn("future_or_crosses_as_of", reasons) self.assertTrue(any(item["reason"] == "terminal_field_removed" for item in result["manifest"]["omittedFields"])) def test_unknown_top_level_section_fails_closed(self): with self.assertRaises(SnapshotError): build_snapshot( {"chapters": [], "futurePayload": "不得透传"}, 488, "v0", target_chapter=489, manifest_metadata=META, ) def test_final_report_is_closed_set(self): with self.assertRaises(SnapshotError): build_snapshot_manifest( target_chapter=489, as_of=488, snapshot_version="v0", reference_work=META["referenceWork"], evaluation_set_version=META["evaluationSetVersion"], strategy_version=META["strategyVersion"], authorization_snapshot=META["authorizationSnapshot"], run_permissions=META["runPermissions"], arm_config=META["armConfig"], sections={}, final_report={"payload": "原书全文"}, ) if __name__ == "__main__": unittest.main()