Add explicit stairs and measure elevator congestion with real actors

This commit is contained in:
Takeshi
2026-09-09 14:26:38 +09:00
parent e246ce382b
commit fb4ad23190
57 changed files with 3030 additions and 162 deletions
+16 -6
View File
@@ -15,21 +15,28 @@ func _run() -> void:
var clock: Variant = fixture[&"clock"]
clock.advance_minutes(3)
var current: Dictionary = runtime.create_snapshot()
_expect(current[&"systems"][&"runtime"][&"runtime_schema_version"] == 8, "Runtime emits schema8 with elevator aggregate")
_expect(current[&"systems"][&"runtime"][&"runtime_schema_version"] == 9, "Runtime emits schema9 with elevator and explicit vertical-route aggregates")
var legacy := current.duplicate(true)
var data: Dictionary = legacy[&"systems"][&"runtime"]
data[&"runtime_schema_version"] = 7
data.erase(&"elevators")
data.erase(&"legacy_stairs")
data[&"path"][&"schema_version"] = 3
data[&"path"].erase(&"vertical_walk_blockers")
_expect(runtime.restore_snapshot(legacy), "genuine v7 without lifts migrates from Path3 into Runtime8")
_expect(runtime.create_snapshot() == current, "empty-lift migration preserves every existing system exactly")
data[&"path"].erase(&"vertical_walk_requires_connector")
data[&"path"].erase(&"transit_actor_ids")
_expect(runtime.restore_snapshot(legacy), "genuine v7 without lifts migrates from Path3 into Runtime9")
var migrated: Dictionary = runtime.create_snapshot()
var expected := current.duplicate(true)
# Closing the old implicit-WALK topology bumps only the Path graph revision.
expected[&"systems"][&"runtime"][&"path"][&"graph_revision"] += 1
_expect(migrated == expected, "empty-lift migration preserves all state except the explicit topology revision")
var bad := current.duplicate(true)
bad[&"systems"][&"runtime"][&"runtime_schema_version"] = 7
_expect(_rejects(runtime, bad), "outer-only downgrade retaining elevator state is rejected atomically")
bad = current.duplicate(true)
bad[&"systems"][&"runtime"].erase(&"elevators")
_expect(_rejects(runtime, bad), "Runtime8 cannot omit elevator aggregate")
_expect(_rejects(runtime, bad), "Runtime9 cannot omit elevator aggregate")
bad = current.duplicate(true)
bad[&"systems"][&"runtime"][&"elevators"][&"current_minute"] -= 1
_expect(_rejects(runtime, bad), "elevator clock must match Runtime domain minute")
@@ -53,7 +60,7 @@ func _run() -> void:
var trip: Dictionary = runtime.elevators.get_actor_trip(actor_id)
_expect(trip.get(&"state") == PathService.ELEVATOR_REQUEST_BOARDED, "save fixture owns a physical cabin seat")
current = runtime.create_snapshot()
_expect(runtime.restore_snapshot(current), "Runtime8 restores actual cabin actor and projected origin crosslinks")
_expect(runtime.restore_snapshot(current), "Runtime9 restores actual cabin actor and projected origin crosslinks")
bad = current.duplicate(true)
bad[&"systems"][&"runtime"][&"elevators"][&"trips"][0][&"actor_id"] = &"staff:missing_person"
bad[&"systems"][&"runtime"][&"elevators"][&"shafts"][0][&"boarded"][0] = &"staff:missing_person"
@@ -100,13 +107,16 @@ func _test_attendance_migration() -> void:
worker.state = StaffRuntime.State.AVAILABLE
runtime.facility_service.set_operational_status(facility.instance_id, {&"active_staff_ids": [&"staff_akane"]}, clock.absolute_minute)
var logical: Dictionary = runtime.create_snapshot()
_expect(_rejects(runtime, logical), "Runtime8 rejects an AVAILABLE employee counted at a distant workplace")
_expect(_rejects(runtime, logical), "Runtime9 rejects an AVAILABLE employee counted at a distant workplace")
var legacy := logical.duplicate(true)
var data: Dictionary = legacy[&"systems"][&"runtime"]
data[&"runtime_schema_version"] = 7
data.erase(&"elevators")
data.erase(&"legacy_stairs")
data[&"path"][&"schema_version"] = 3
data[&"path"].erase(&"vertical_walk_blockers")
data[&"path"].erase(&"vertical_walk_requires_connector")
data[&"path"].erase(&"transit_actor_ids")
_expect(runtime.restore_snapshot(legacy), "genuine v7 logical attendance migrates into physical attendance")
facility = runtime.facility_service.get_instance(facility.instance_id)
worker = runtime.staff_service.get_staff(&"staff_akane")