{"kind":"contract_scenarios","contract_version":"v0.4.6","api_version":"0.4.6","stability":"locked_before_godot_rendering","scenario_count":4,"scenario_ids":["foundation_contract_boot","tutorial_move_resolve_replay","combat_supply_edge_build_victory","contract_error_envelope"],"golden_fixture_ids":["fixture_manifest","foundation_contract_boot","tutorial_move_resolve_replay","combat_supply_edge_build_victory","contract_error_envelope"],"golden_rules":["no gameplay decision is made by Godot","orders are queued first and fully validated by resolve","state mutation happens only through resolve","replay events are the animation/debug source for clients","errors use the contract error envelope","smoke checks runtime contracts, not visual copy text"],"scenarios":[{"scenario_id":"foundation_contract_boot","fixture_id":"foundation_contract_boot","purpose":"Client and smoke verify runtime, versions and available contracts before doing gameplay calls.","steps":[{"step":1,"method":"GET","path":"/api/health","expect":{"kind":"health","status":"ok"}},{"step":2,"method":"GET","path":"/api/version","expect":{"kind":"version","version":"0.4.6"}},{"step":3,"method":"GET","path":"/api/contracts","expect":{"kind":"contract_index","contract_version":"v0.4.6"}},{"step":4,"method":"GET","path":"/api/contracts/godot","expect":{"kind":"godot_contract","server_authoritative":true}}],"required_replay_events":[],"client_asserts":["contract_version matches across health/version/contracts","server_authoritative is true"]},{"scenario_id":"tutorial_move_resolve_replay","fixture_id":"tutorial_move_resolve_replay","purpose":"Godot can create a tutorial match, queue one move order, resolve it and replay the movement.","steps":[{"step":1,"method":"POST","path":"/api/matches","body":{"map_id":"tutorial_valley","ruleset_id":"gen1"},"expect":{"kind":"match"}},{"step":2,"method":"GET","path":"/api/matches/{match_id}/state","expect":{"kind":"match_state"}},{"step":3,"method":"POST","path":"/api/matches/{match_id}/orders","body":{"orders":[{"type":"move_unit","player_id":"player_1","payload":{"unit_id":"u_p1_standard_1","from":"h_0_0","to":"h_1_0"}}]},"expect":{"kind":"order_submit","accepted":true}},{"step":4,"method":"POST","path":"/api/matches/{match_id}/resolve","expect":{"kind":"resolve_result","status":"resolved"}},{"step":5,"method":"GET","path":"/api/matches/{match_id}/replay","expect":{"kind":"replay"}}],"required_replay_events":["unit_moved","supply_updated","production_resolved","score_updated","turn_resolved"],"client_asserts":["resolve.event_count equals len(resolve.events)","state.turn advances","unit tile changes only after resolve"]},{"scenario_id":"combat_supply_edge_build_victory","fixture_id":"combat_supply_edge_build_victory","purpose":"The full backend demo loop covers attack, supply, edge control, build order and victory/score read model.","steps":[{"step":1,"method":"POST","path":"/api/matches/{match_id}/orders","body":{"orders":[{"type":"attack_unit","player_id":"player_1","payload":{"attacker_id":"u_p1_standard_1","defender_id":"u_p2_standard_1","from":"h_1_0","to":"h_2_0"}}]},"expect":{"kind":"order_submit"}},{"step":2,"method":"POST","path":"/api/matches/{match_id}/resolve","expect":{"kind":"resolve_result"}},{"step":3,"method":"GET","path":"/api/matches/{match_id}/supply","expect":{"supply":"object"}},{"step":4,"method":"POST","path":"/api/matches/{match_id}/orders","body":{"orders":[{"type":"claim_edge","player_id":"player_1","payload":{"unit_id":"u_p1_standard_1","from":"h_2_0","to":"h_3_0"}}]},"expect":{"kind":"order_submit"}},{"step":5,"method":"GET","path":"/api/matches/{match_id}/build-options?player_id=player_1","expect":{"build_options":"object"}},{"step":6,"method":"POST","path":"/api/matches/{match_id}/orders","body":{"orders":[{"type":"build_unit","player_id":"player_1","payload":{"unit_type":"fast","tile_id":"h_0_0"}}]},"expect":{"kind":"order_submit"}},{"step":7,"method":"GET","path":"/api/matches/{match_id}/victory","expect":{"kind":"victory"}}],"required_replay_events":["combat_resolved","unit_destroyed","edge_claimed","unit_created","score_updated"],"client_asserts":["combat and build are explicit orders","supply and victory are server read models","replay order remains sorted"]},{"scenario_id":"contract_error_envelope","fixture_id":"contract_error_envelope","purpose":"Clients receive predictable error envelopes instead of raw framework errors.","steps":[{"step":1,"method":"GET","path":"/api/matches/not-a-real-match/state","expect_status":404,"expect":{"kind":"error","status":"error"}}],"required_replay_events":[],"client_asserts":["errors include kind, contract_version, status and error.http_status"]}],"links":{"contracts":"/api/contracts","godot_contract":"/api/contracts/godot","health":"/api/health","maps":"/api/maps","golden_fixtures":"/api/contracts/fixtures","godot_source":"client-godot/project.godot","godot_export_preset":"client-godot/export_presets.cfg","godot_web_slot":"web/public/game/index.html","snapshot_script":"scripts/snapshot_safe.sh","scene_registry":"client-godot/scripts/scene_registry.gd","scene_instancing_check":"scripts/check_godot_scene_instancing.sh","input_foundation_check":"scripts/check_godot_input_foundation.sh"}}