muse-agent-example/.claude/skills/detect/scripts/test_check_writer_candidate.py

200 lines
7.7 KiB
Python

#!/usr/bin/env python3
"""正文候选机械硬门的细纲、证据和 Unicode 绑定测试。"""
from __future__ import annotations
import copy
import hashlib
import pathlib
import sys
import unittest
SCRIPT_DIR = pathlib.Path(__file__).resolve().parent
SKILLS_DIR = SCRIPT_DIR.parents[1]
CONTINUATION_DIR = SKILLS_DIR / "continuation" / "scripts"
READ_CONTEXT_DIR = SKILLS_DIR / "read-context" / "scripts"
for path in (SCRIPT_DIR, CONTINUATION_DIR, READ_CONTEXT_DIR):
sys.path.insert(0, str(path))
from test_run_writer import _bound_context, _bound_output # noqa: E402
from check_writer_candidate import check_writer_candidate # noqa: E402
from writer_contract import han_count # noqa: E402
def _candidate_body() -> str:
"""构造同时满足四类细纲机械锚点和动态篇幅的候选正文。"""
prefix = "林澈完成围攻突围,又把旧徽章压回掌心。"
hook = "城门忽然打开"
filler_count = 4000 - han_count(prefix) - han_count(hook)
return prefix + "文" * filler_count + hook
def _requirements() -> dict:
"""构造可信上下文层派生的机械硬约束。"""
return {
"requiredEvents": [
{"requirementId": "event-1", "anchors": ["完成围攻突围"]},
],
"requiredCharacters": ["林澈"],
"foreshadowingActions": [
{"requirementId": "foreshadow-1", "anchors": ["旧徽章"]},
],
"chapterEndHook": {
"requirementId": "hook-1",
"anchors": ["城门忽然打开"],
"maxDistanceFromEnd": 20,
},
"detectedNewSettings": [],
"frozenConflicts": [],
}
def _rehash(output: dict) -> None:
"""正文变更后同步候选和 claim 哈希,供单项硬门测试使用。"""
digest = "sha256:" + hashlib.sha256(output["candidateBody"].encode("utf-8")).hexdigest()
output["candidateSha256"] = digest
for claim in output["claimLedger"]:
claim["candidateSha256"] = digest
def _valid_pair() -> tuple[dict, dict]:
"""构造一组能通过严格合同和机械硬门的上下文与候选。"""
context = _bound_context()
output = _bound_output(context, body=_candidate_body())
return context, output
class CheckWriterCandidateTest(unittest.TestCase):
def test_missing_event_character_foreshadow_or_hook_blocks(self):
context, output = _valid_pair()
mutations = {
"HARD_EVENT_MISSING": ("完成围攻突围", "完成撤离"),
"REQUIRED_CHARACTER_MISSING": ("林澈", "无名人"),
"FORESHADOWING_ACTION_MISSING": ("旧徽章", "旧物件"),
"CHAPTER_END_HOOK_MISSING": ("城门忽然打开", "风声渐渐平息"),
}
for expected_code, (old, new) in mutations.items():
candidate = copy.deepcopy(output)
candidate["candidateBody"] = candidate["candidateBody"].replace(old, new)
_rehash(candidate)
report = check_writer_candidate(context, candidate, _requirements())
with self.subTest(expected_code=expected_code):
self.assertFalse(report["passed"])
self.assertIn(expected_code, {item["code"] for item in report["blockingFailures"]})
def test_candidate_claim_hash_unicode_offset_and_evidence_reference_block(self):
context, output = _valid_pair()
cases = {}
bad_candidate_hash = copy.deepcopy(output)
bad_candidate_hash["candidateSha256"] = "sha256:" + "f" * 64
cases["CANDIDATE_HASH_MISMATCH"] = bad_candidate_hash
bad_claim_hash = copy.deepcopy(output)
bad_claim_hash["claimLedger"][0]["candidateSha256"] = "sha256:" + "e" * 64
cases["CLAIM_HASH_MISMATCH"] = bad_claim_hash
bad_unicode_offset = copy.deepcopy(output)
bad_unicode_offset["candidateBody"] = "林澈🙂" + bad_unicode_offset["candidateBody"][2:]
_rehash(bad_unicode_offset)
bad_unicode_offset["claimLedger"][0]["endCodePoint"] = len(bad_unicode_offset["candidateBody"]) + 1
cases["CLAIM_UNICODE_OFFSET_INVALID"] = bad_unicode_offset
bad_evidence = copy.deepcopy(output)
bad_evidence["claimLedger"][0]["factEvidenceId"] = "fact-missing"
cases["CLAIM_EVIDENCE_MISSING"] = bad_evidence
for expected_code, candidate in cases.items():
report = check_writer_candidate(context, candidate, _requirements())
with self.subTest(expected_code=expected_code):
self.assertFalse(report["passed"])
self.assertIn(expected_code, {item["code"] for item in report["blockingFailures"]})
def test_candidate_body_outside_dynamic_length_contract_blocks(self):
"""机械门必须独立复核动态篇幅,不能只信 writer adapter。"""
context, output = _valid_pair()
output["candidateBody"] = "文" * 1000
_rehash(output)
report = check_writer_candidate(context, output, _requirements())
self.assertFalse(report["passed"])
self.assertIn(
"CANDIDATE_LENGTH_OUT_OF_RANGE",
{item["code"] for item in report["blockingFailures"]},
)
def test_new_setting_must_have_overlapping_declaration(self):
context, output = _valid_pair()
marker = "赤霄城"
insertion_start = len("林澈完成围攻突围,又把旧徽章压回掌心。")
output["candidateBody"] = (
output["candidateBody"][:insertion_start]
+ marker
+ output["candidateBody"][insertion_start + len(marker):]
)
_rehash(output)
requirements = _requirements()
requirements["detectedNewSettings"] = [
{
"settingId": "setting-1",
"factType": "location",
"startCodePoint": insertion_start,
"endCodePoint": insertion_start + len(marker),
}
]
blocked = check_writer_candidate(context, output, requirements)
self.assertIn("NEW_SETTING_UNDECLARED", {item["code"] for item in blocked["blockingFailures"]})
output["newSettingDeclarations"] = [
{
"declarationId": "declaration-1",
"factType": "location",
"text": marker,
"startCodePoint": insertion_start,
"endCodePoint": insertion_start + len(marker),
}
]
passed = check_writer_candidate(context, output, requirements)
self.assertTrue(passed["passed"])
def test_frozen_fact_conflict_blocks_with_traceable_source(self):
context, output = _valid_pair()
requirements = _requirements()
requirements["frozenConflicts"] = [
{
"conflictId": "conflict-1",
"message": "候选把已毁地点写成完好",
"sourceRef": "state:8@state-v1",
}
]
report = check_writer_candidate(context, output, requirements)
self.assertFalse(report["passed"])
failure = next(item for item in report["blockingFailures"] if item["code"] == "FROZEN_FACT_CONFLICT")
self.assertEqual(failure["sourceRef"], "state:8@state-v1")
def test_valid_candidate_passes_mechanical_gate_and_exposes_semantic_interface(self):
context, output = _valid_pair()
report = check_writer_candidate(context, output, _requirements())
self.assertTrue(report["passed"])
self.assertEqual(report["candidateSha256"], output["candidateSha256"])
self.assertEqual(report["semanticReview"]["status"], "pending")
self.assertEqual(
set(report["semanticReview"]["checks"]),
{"hard_event_semantics", "claim_truth_alignment", "knowledge_scope", "ability_cost_consistency"},
)
if __name__ == "__main__":
unittest.main()