Add emergency aftermath: evacuation, investigation, review copy
Full build / Import + headless tests (push) Successful in 26s
Full build / Full desktop build + optional release (push) Failing after 4m20s

- Responder outcomes now reach the shift review
  (ShiftCoordinator.responder_outcomes), and the review screen names them.
- "evacuation" (emergency call, low danger, no weapon) actually clears the entrance:
  the door is locked, every NPC flees and is marked as leaving, and a
  security_failure reputation hit applies.
- An emergency call the situation did not justify (no weapon, danger <= 1) appends
  an investigation note, records investigation_opened, and applies the existing
  false_report hit. The review lists the investigations.
- Fix dispatch dying after the first shift: coordinator.setup() builds a new
  RadioSystem, so the responder_arrived connection made in _ready was lost on every
  venue switch/restart. _connect_radio() re-wires it beside _connect_crowd().

Tests/docs
- Headless suite 105 -> 113 (test_emergency_aftermath.gd), new smoke_emergency.gd
  covering the investigation, evacuation aftermath, and review copy.
- README controls/status/smoke checklist, TODO section moved to DONE, MEMORY notes.
- Version 0.2.5.
This commit is contained in:
zwitschi committed 2026-10-31 20:59:06 +01:00
1 parent 71b0b53705
commit 921bab796e
25 files changed
+1019 -23

No files matched your search

+80
View File
@@ -0,0 +1,80 @@
import tempfile
import unittest
from pathlib import Path
from PIL import Image
import screen_designs
class ScreenDesignsTests(unittest.TestCase):
def setUp(self):
self.temp_dir = tempfile.TemporaryDirectory()
self.root = Path(self.temp_dir.name)
def tearDown(self):
self.temp_dir.cleanup()
def test_catalogue_is_well_formed(self):
names = [screen["name"] for screen in screen_designs.SCREENS]
self.assertEqual(len(names), len(set(names)),
"screen names must be unique")
refs = [screen["ref"] for screen in screen_designs.SCREENS
if screen["ref"]]
self.assertEqual(len(refs), len(set(refs)),
"screenshot refs must be unique")
for screen in screen_designs.SCREENS:
self.assertTrue(screen["prompt"].strip())
self.assertTrue(screen["regions"])
for region in screen["regions"]:
x0, y0, x1, y1, label = region
self.assertLess(x0, x1)
self.assertLess(y0, y1)
self.assertTrue(0 <= x0 <= 1 and 0 <= x1 <= 1)
self.assertTrue(0 <= y0 <= 1 and 0 <= y1 <= 1)
self.assertTrue(label.strip())
def test_draft_wireframe_matches_reference_dimensions(self):
output = self.root / "draft.png"
screen = screen_designs.SCREENS[0]
screen_designs._draw_wireframe(screen, output)
with Image.open(output) as image:
self.assertEqual(image.size,
(screen_designs.WIDTH, screen_designs.HEIGHT))
def test_mae_is_zero_for_identical_images(self):
path = self.root / "identical.png"
Image.new("RGB", (1280, 720), (40, 80, 120)).save(path)
left = screen_designs._load_rgb(path)
right = screen_designs._load_rgb(path)
self.assertAlmostEqual(screen_designs._mae(left, right), 0.0, places=1)
def test_histogram_distance_is_zero_for_identical_images(self):
path = self.root / "identical.png"
Image.new("RGB", (1280, 720), (40, 80, 120)).save(path)
left = screen_designs._load_rgb(path)
right = screen_designs._load_rgb(path)
self.assertAlmostEqual(
screen_designs._histogram_distance(left, right), 0.0, places=3)
def test_blank_frame_is_flagged_as_bad(self):
reference = self.root / "ref.png"
capture = self.root / "cap.png"
Image.new("RGB", (1280, 720), (200, 200, 200)).save(reference)
Image.new("RGB", (1280, 720), (0, 0, 0)).save(capture)
report = screen_designs.compare_screenshot(reference, capture)
self.assertEqual(report["quality"], "bad")
self.assertTrue(any("near-blank" in e for e in report["errors"]))
def test_wrong_aspect_is_flagged_as_bad(self):
reference = self.root / "ref.png"
capture = self.root / "cap.png"
Image.new("RGB", (1280, 720), (100, 120, 140)).save(reference)
Image.new("RGB", (640, 640), (100, 120, 140)).save(capture)
report = screen_designs.compare_screenshot(reference, capture)
self.assertEqual(report["quality"], "bad")
self.assertTrue(any("aspect" in e for e in report["errors"]))
if __name__ == "__main__":
unittest.main()