#!/usr/bin/env python3 """Focused BAT-002 live-battle specification assertions.""" from __future__ import annotations import json import unittest from pathlib import Path ROOT = Path(__file__).resolve().parents[1] PAGE = ROOT / "docs/design-authority/pages/BAT-002-live-battle" def load(path: Path): return json.loads(path.read_text(encoding="utf-8")) class Bat002SpecificationTests(unittest.TestCase): def setUp(self) -> None: self.contract = load(PAGE / "page-contract.json") self.matrix = load(PAGE / "state-matrix.json") def test_index_preserves_spec_package_through_runtime_states(self) -> None: index = load(ROOT / "docs/design-authority/design-index.json") page = index["pages"]["BAT-002"] self.assertIn(page["status"], { "IMPLEMENTATION_IN_PROGRESS", "IMPLEMENTED_AWAITING_OWNER_RUNTIME_REVIEW", "VERIFIED_AWAITING_OWNER_ACCEPTANCE", "COMPLETE", }) self.assertEqual(page["contract"], "pages/BAT-002-live-battle/page-contract.json") self.assertEqual(page["state_matrix"], "pages/BAT-002-live-battle/state-matrix.json") def test_contract_and_matrix_cover_the_same_states(self) -> None: self.assertEqual(self.contract["page_id"], "BAT-002") self.assertIn(self.contract["state"], { "IMPLEMENTATION_IN_PROGRESS", "IMPLEMENTED_AWAITING_OWNER_RUNTIME_REVIEW", "VERIFIED_AWAITING_OWNER_ACCEPTANCE", "COMPLETE", }) self.assertEqual(set(self.contract["states"]), set(self.matrix["states"])) self.assertEqual(set(self.contract["states"]), set(self.contract["transition_graph"])) declared_states = set(self.contract["states"]) for destinations in self.contract["transition_graph"].values(): self.assertTrue(set(destinations).issubset(declared_states)) self.assertEqual(self.contract["responsive_policy"]["text_scale"], 100) self.assertEqual(self.matrix["required_text_scales"], [100]) self.assertEqual(set(self.matrix["required_locales"]), {"zh_CN", "en"}) self.assertEqual( set(self.matrix["required_viewports"]), {"760x360", "844x390", "1280x720"}, ) def test_waiting_error_and_interruption_states_are_explicit(self) -> None: waiting = self.matrix["states"]["waiting_for_next_event"] self.assertEqual(waiting["exact_english_copy"], "Waiting for next event") invalid = self.matrix["states"]["invalid_event_data"] self.assertEqual(invalid["timeline"], "paused") self.assertEqual(invalid["primary_action"], "retry_snapshot") self.assertIn("safe_exit", invalid["secondary_actions"]) interrupted = self.matrix["states"]["interrupted_background"] self.assertEqual(interrupted["primary_action"], "open_bat006") self.assertEqual(interrupted["timeline"], "frozen") def test_live_battle_is_automatic_and_diagnostic_only(self) -> None: corpus = " ".join(self.contract["constraints"] + self.matrix["required_boundaries"]) for forbidden in ("attack", "skill", "target-selection", "reorder", "equip", "Reserve-entry"): self.assertIn(forbidden, corpus) self.assertEqual( set(self.contract["required_event_families"]), set(self.matrix["required_event_families"]), ) for required in ("melee_contact", "healing_source_and_recipient_change", "knockout_and_line_collapse"): self.assertIn(required, self.contract["required_event_families"]) def test_page_ownership_and_stopping_boundary_are_truthful(self) -> None: ownership = self.contract["control_ownership"] for page_id in ("BAT-003", "BAT-004", "BAT-005", "BAT-006", "OUT-001"): self.assertIn(page_id, " ".join(ownership.values())) outcome = self.matrix["states"]["outcome_locked"] self.assertEqual(outcome["primary_action"], "open_out001") self.assertIn("no reward", outcome["guard"]) gate = self.contract["implementation_gate"] self.assertIn("No image generation", gate) self.assertIn("must not apply reward", gate) def test_visual_authority_is_existing_hand_drawn_battle_direction(self) -> None: provenance = " ".join(self.contract["provenance"]) constraints = " ".join(self.contract["constraints"]) self.assertIn("05_battle_ui_japanese_scale.png", provenance) self.assertIn("phase6_battle_scale_04", provenance) self.assertIn("functional provenance only", provenance) self.assertIn("Pixel art", constraints) self.assertIn("card-wall replacement", constraints) if __name__ == "__main__": unittest.main()