#!/usr/bin/env python3 """冻结幂等键(manifest, context)对真实库集成测试。 example_context_freeze 是 append-only 表(触发器禁止 UPDATE/DELETE), 无法物理清理测试行;因此本测试零新增:回读一条既有冻结行,按其 manifest+context 原值重放,验证幂等回读同一行、不新增。 "同清单不同上下文各得其所"由 2026-08-23 两阶段烟测实证(候选 164 的 冻结在旧 manifest 单键下永远落不了库,迁移后落库成功并通过接受前置检查), 并由迁移 114 的 (manifest, context) 唯一索引在库级保证。 跑法(需可达 muse-example): .venv/bin/python tests/skills/准备任务上下文/test_persist_freeze_db.py """ from __future__ import annotations import pathlib import sys import unittest PROJECT_ROOT = pathlib.Path(__file__).resolve().parents[3] SCRIPT_DIR = PROJECT_ROOT / "muse" / "lifecycle" / "context" / "skills" / "准备任务上下文" / "scripts" for path in (SCRIPT_DIR,): if str(path) not in sys.path: sys.path.insert(0, str(path)) from muse_db import connect # noqa: E402 from persist_context_freeze import persist_freeze # noqa: E402 class FreezeReplayIdempotencyDbTest(unittest.TestCase): def test_replay_existing_freeze_is_idempotent_no_new_row(self): with connect(readonly=True) as conn: row = conn.execute( "SELECT work_id, target_chapter, as_of_chapter, manifest_sha256, " "context_sha256 FROM example_context_freeze ORDER BY id DESC LIMIT 1" ).fetchone() self.assertIsNotNone(row, "需要至少一条既有冻结行") work_id, target_chapter, as_of, manifest_sha, context_sha = row assemble_result = { "context": { "workId": work_id, "targetChapter": target_chapter, "asOf": as_of, "contextSnapshot": { "manifestId": "sha256:" + manifest_sha, "contextSha256": "sha256:" + context_sha, }, "retrievalManifest": {"sources": []}, } } with connect(readonly=True) as conn: before = conn.execute( "SELECT count(*) FROM example_context_freeze WHERE manifest_sha256=%s", (manifest_sha,), ).fetchone()[0] out = persist_freeze(assemble_result) self.assertEqual(out["status"], "frozen") self.assertEqual(out["manifest_sha256"], manifest_sha) self.assertEqual(out["context_sha256"], context_sha) with connect(readonly=True) as conn: after = conn.execute( "SELECT count(*) FROM example_context_freeze WHERE manifest_sha256=%s", (manifest_sha,), ).fetchone()[0] self.assertEqual(after, before, "幂等重放不得新增行") if __name__ == "__main__": unittest.main()