Integrate mission-owned chat administration and menu

This commit is contained in:
2026-09-19 23:49:54 +02:00
parent 27989b85a3
commit 5e742691ad
154 changed files with 19498 additions and 134 deletions
+1 -1
View File
@@ -151,7 +151,7 @@ def inspect(session):
'qualification': 'packed-only ordinary startup consumption only; original package build verdict and current source acceptance remain separate'}
report['failed'] = not passed
report['ready'] = passed
report['verifier_sha256'] = {name: digest(read(Path(__file__).resolve().parent/name)) for name in ('archive_packed.py', 'headless_game.py', 'native_report.py')}
report['verifier_sha256'] = {name: digest(read(Path(__file__).resolve().parent/name)) for name in ('archive_packed.py', 'headless_game.py', 'native_report.py', 'project_schema.py')}
files['report.json'] = encoded(report)
archive_kind = {'schema_version': metadata['schema_version'], 'kind': 'packed-'+project+'-consumption', 'packed_launch_id': metadata['launch_id'],
'build_qualified': False, 'release_qualified': False}
+2 -2
View File
@@ -9,7 +9,7 @@ def check():
for p in sorted((ROOT/'addons').glob('*/addon.gproj')):
text=p.read_text();g=re.search(r'GUID "([A-F0-9]{16})"',text)[1]
assert g not in ids,f'Duplicate addon GUID: {p}'
ids[g]=p.parent.name;graph[g]=re.findall(r'"([A-F0-9]{16})"',text[text.index('Dependencies'):])
ids[g]=p.parent.name;graph[g]=re.findall(r'"([A-F0-9]{16})"',re.search(r'\bDependencies\s*\{([^{}]*)\}',text)[1])
assert len(ids)==5,'Expected five addon projects'
def walk(g,stack):
assert g not in stack,'Dependency cycle: '+str(stack+[g])
@@ -59,7 +59,7 @@ def check():
assert set(mapped)==set(inventory['script_paths']), 'Original inventory has untracked or unknown entries'
print(f'PASS: {len(mapped)} original script entries tracked across {len(feature_ids)} unfinished responsibilities')
print(f'PASS: {len(ids)} isolated addons, acyclic dependencies, {len(resources)} unique resources, exact vanilla references')
for name in ['test_intel_admin.py', 'test_intel_reroll.py', 'test_intel_discovery_feedback.py', 'test_hq_report_selection.py', 'test_casualty_feedback.py', 'test_initial_admission_exhaustion.py', 'test_prison_held_action_proof.py', 'test_prison_held_action_evidence.py', 'test_prison_held_input_adapter.py', 'test_prison_held_runner.py', 'test_prison_coarse_facing.py', 'test_aircraft_field_probe.py', 'test_aircraft_field_runner.py', 'test_aircraft_field_rules.py', 'test_aircraft_field_envelope.py', 'test_aircraft_field_flight.py', 'test_command_maintenance.py', 'test_aircraft_service.py', 'test_aircraft_service_cancel_runner.py', 'test_prison_action_selection_proof.py', 'test_prison_action_selection_evidence.py', 'test_ordinary_gate_choices.py', 'test_aircraft_control_bridge.py', 'test_prison_alignment_proof.py', 'test_prison_alignment_evidence.py', 'test_aircraft_route_demand.py', 'test_prison_approach_proof.py', 'test_prison_approach_evidence.py', 'test_ordinary_gate_evidence.py', 'test_ordinary_gate_observer.py', 'test_ordinary_look_observer.py', 'test_ordinary_look_evidence.py', 'test_relative_look_runner.py', 'test_radio_waiting_text.py', 'test_inventory_control_runner.py', 'test_inventory_layout.py', 'test_headless_input_proof.py', 'test_headless_input_exercise_runner.py', 'test_private_prefix_cleanup.py', 'test_runner_private_cleanup.py', 'test_ordinary_input_runner.py', 'test_ordinary_input_observer.py', 'test_aircraft_route_envelope.py', 'test_aircraft_route_policy.py', 'test_aircraft_route_probe.py', 'test_rough_intel_feedback.py', 'test_headless_display_probe.py', 'test_headless_display_runner.py', 'test_preparation_status.py', 'test_hint_delivery.py', 'test_native_end_lifecycle.py', 'test_native_end_runner.py', 'test_escape_result_wording.py', 'test_native_stats.py', 'test_aircraft_translation.py', 'test_spawn_retry_budget.py', 'test_action_feedback.py', 'test_native_aircraft_control.py', 'test_aircraft_flight_policy.py', 'test_aircraft_flight_envelope.py', 'test_ordinary_screenshot.py', 'test_participant_selection.py', 'test_native_shared_map_ownership.py', 'test_shared_map_ownership.py', 'test_intel_registration.py', 'test_mortar_activity_completion.py', 'test_packed_chat_game.py', 'test_native_mortar_refresh.py', 'test_archive_packed.py', 'test_mortar_refresh.py', 'test_packed_core_game.py', 'test_pak_inventory.py', 'test_native_mortar_salvo.py', 'test_spectator_guidance.py', 'test_native_package.py', 'test_item_station_teardown.py', 'test_source_bundle.py', 'test_native_flight_footprint.py', 'test_native_flight_input_diagnostics.py', 'test_mortar_logistics.py', 'test_mortar_courier_storage.py','test_powered_flight_pad.py','test_prison_escape_policy.py','test_powered_flight_policy.py','test_flight_action_runner.py','test_native_local_admission_probe.py','test_mortar_report_ledger.py','test_dedicated_native.py','test_native_mortar_transfer.py','test_mortar_aim_renewal.py','test_dedicated_preflight.py','test_mortar_transactions.py','test_native_mortar_probe.py','test_diagnostic_no_splash.py','test_casualty_incapacitation.py','test_casualty_remove_probe.py','test_extraction_placement_policy.py','test_guard_cancellation_policy.py','test_casualty_ground_policy.py','test_casualty_reservation_death.py','test_casualty_loading_policy.py','test_initial_guard_policy.py','test_headless_game_runner.py','test_vanilla_game_control.py','test_archive_game_control.py','test_site_discovery_policy.py','test_faction_catalog_scope.py','test_mission_rules.py','test_admin_setting_policy.py', 'test_player_admission_policy.py','test_progression_identity.py','test_discovery_map_position.py','test_local_admission.py','test_prison_placement_policy.py', 'test_recovery_policy.py','test_time_policy.py','test_environment_policy.py','test_environment_restart_runner.py', 'test_inventory_enumeration_policy.py','test_radio_defence_policy.py','test_radio_feedback_policy.py','test_performance_comparison.py','test_release_check.py','test_settings_migration.py','hq_network_regression.py','helicopter_availability_regression.py','mortar_salvo_regression.py']:
for name in ['test_admin_tick_delivery.py', 'test_project_schema.py', 'test_admin_session.py', 'test_admin_providers.py', 'test_admin_menu.py', 'test_admin_player_tools.py', 'test_intel_admin.py', 'test_intel_reroll.py', 'test_intel_discovery_feedback.py', 'test_hq_report_selection.py', 'test_casualty_feedback.py', 'test_initial_admission_exhaustion.py', 'test_prison_held_action_proof.py', 'test_prison_held_action_evidence.py', 'test_prison_held_input_adapter.py', 'test_prison_held_runner.py', 'test_prison_coarse_facing.py', 'test_aircraft_field_probe.py', 'test_aircraft_field_runner.py', 'test_aircraft_field_rules.py', 'test_aircraft_field_envelope.py', 'test_aircraft_field_flight.py', 'test_command_maintenance.py', 'test_aircraft_service.py', 'test_aircraft_service_cancel_runner.py', 'test_prison_action_selection_proof.py', 'test_prison_action_selection_evidence.py', 'test_ordinary_gate_choices.py', 'test_aircraft_control_bridge.py', 'test_prison_alignment_proof.py', 'test_prison_alignment_evidence.py', 'test_aircraft_route_demand.py', 'test_prison_approach_proof.py', 'test_prison_approach_evidence.py', 'test_ordinary_gate_evidence.py', 'test_ordinary_gate_observer.py', 'test_ordinary_look_observer.py', 'test_ordinary_look_evidence.py', 'test_relative_look_runner.py', 'test_radio_waiting_text.py', 'test_inventory_control_runner.py', 'test_inventory_layout.py', 'test_headless_input_proof.py', 'test_headless_input_exercise_runner.py', 'test_private_prefix_cleanup.py', 'test_runner_private_cleanup.py', 'test_ordinary_input_runner.py', 'test_ordinary_input_observer.py', 'test_aircraft_route_envelope.py', 'test_aircraft_route_policy.py', 'test_aircraft_route_probe.py', 'test_rough_intel_feedback.py', 'test_headless_display_probe.py', 'test_headless_display_runner.py', 'test_preparation_status.py', 'test_hint_delivery.py', 'test_native_end_lifecycle.py', 'test_native_end_runner.py', 'test_escape_result_wording.py', 'test_native_stats.py', 'test_aircraft_translation.py', 'test_spawn_retry_budget.py', 'test_action_feedback.py', 'test_native_aircraft_control.py', 'test_aircraft_flight_policy.py', 'test_aircraft_flight_envelope.py', 'test_ordinary_screenshot.py', 'test_participant_selection.py', 'test_native_shared_map_ownership.py', 'test_shared_map_ownership.py', 'test_intel_registration.py', 'test_mortar_activity_completion.py', 'test_packed_chat_game.py', 'test_native_mortar_refresh.py', 'test_archive_packed.py', 'test_mortar_refresh.py', 'test_packed_core_game.py', 'test_pak_inventory.py', 'test_native_mortar_salvo.py', 'test_spectator_guidance.py', 'test_native_package.py', 'test_item_station_teardown.py', 'test_source_bundle.py', 'test_native_flight_footprint.py', 'test_native_flight_input_diagnostics.py', 'test_mortar_logistics.py', 'test_mortar_courier_storage.py','test_powered_flight_pad.py','test_prison_escape_policy.py','test_powered_flight_policy.py','test_flight_action_runner.py','test_native_local_admission_probe.py','test_mortar_report_ledger.py','test_dedicated_native.py','test_native_mortar_transfer.py','test_mortar_aim_renewal.py','test_dedicated_preflight.py','test_mortar_transactions.py','test_native_mortar_probe.py','test_diagnostic_no_splash.py','test_casualty_incapacitation.py','test_casualty_remove_probe.py','test_extraction_placement_policy.py','test_guard_cancellation_policy.py','test_casualty_ground_policy.py','test_casualty_reservation_death.py','test_casualty_loading_policy.py','test_initial_guard_policy.py','test_headless_game_runner.py','test_vanilla_game_control.py','test_archive_game_control.py','test_site_discovery_policy.py','test_faction_catalog_scope.py','test_mission_rules.py','test_admin_setting_policy.py', 'test_player_admission_policy.py','test_progression_identity.py','test_discovery_map_position.py','test_local_admission.py','test_prison_placement_policy.py', 'test_recovery_policy.py','test_time_policy.py','test_environment_policy.py','test_environment_restart_runner.py', 'test_inventory_enumeration_policy.py','test_radio_defence_policy.py','test_radio_feedback_policy.py','test_performance_comparison.py','test_release_check.py','test_settings_migration.py','hq_network_regression.py','helicopter_availability_regression.py','mortar_salvo_regression.py']:
subprocess.run([sys.executable,str(ROOT/'tests'/name)],check=True)
print('All repository checks passed. Native compilation and multiplayer tests are separate requirements.')
if __name__=='__main__':check()
+4 -3
View File
@@ -17,6 +17,7 @@ import time
import uuid
from native_provenance import snapshot, persist, bindings, seal_run
from native_report import analyze
from project_schema import parse_project
ROOT = Path(__file__).resolve().parents[1]
PROFILE_MARKER = '.erri-game-profile.json'
@@ -66,10 +67,10 @@ def packed_inventory(folder, project='core'):
result[name] = {'bytes': path.stat().st_size, 'sha256': digest.hexdigest()}
name, guid, dependencies = PACKED_PROJECTS[project]
text = (folder/'addon.gproj').read_text()
match = re.fullmatch(r'\s*GameProject\s*\{\s*ID\s+"'+name+r'"\s+GUID\s+"'+guid+r'"\s+TITLE\s+"[^"\r\n]+"\s+Dependencies\s*\{((?:\s*"[0-9A-F]{16}"\s*)+)\}\s*\}\s*', text)
actual = re.findall(r'"([0-9A-F]{16})"', match[1]) if match else []
match = parse_project(text, allow_core_menu=project == 'core')
actual = re.findall(r'"([0-9A-F]{16})"', match[4]) if match else []
expected = {PACKED_BASE, *(PACKED_PROJECTS[key][1] for key in dependencies)}
if not match or set(actual) != expected or len(actual) != len(expected):
if not match or match[1] != name or match[2] != guid or set(actual) != expected or len(actual) != len(expected):
refuse('Packed project identity or exact declared dependencies do not match '+project)
return result
+1 -1
View File
@@ -15,7 +15,7 @@ from native_report import analyze
ROOT = Path(__file__).resolve().parents[1]
FIXTURE = ROOT/'tests/native/inventory_control'
HELPERS = ('headless_workbench.py','headless_game.py','private_prefix_cleanup.py','native_provenance.py','source_manifest.py','native_report.py','archive_native.py')
HELPERS = ('headless_workbench.py','headless_game.py','private_prefix_cleanup.py','native_provenance.py','source_manifest.py','native_report.py','archive_native.py','project_schema.py')
EXPECTED_ERROR = 'OverlayWidget Frame0 has invalid slot GridWidgetSlot for slot manipulation function used, expected: LayoutSlot'
+32
View File
@@ -0,0 +1,32 @@
"""Strict reviewed addon project grammar shared by source and packed validation.
The optional Core menu configuration preserves vanilla and adds one owned resource.
This is deliberately not a general Enfusion project parser: unreviewed settings,
other platforms, resource substitutions and omissions from the exact list fail.
Identity and exact dependency closure remain the caller's responsibility.
"""
import re
CORE_MENU_CONFIGURATION = r"""
Configurations\s*\{\s*
GameProjectConfig\s+PC\s*\{\s*
MenuManagerSettings\s+MenuManagerSettings\s+"\{50C890C996B0A6FC\}"\s*\{\s*
MenuConfigs\s*\{\s*
"\{C747AFB6B750CE9A\}Configs/System/chimeraMenus\.conf"\s*
"\{B48C7FA12692DE03\}Configs/ERR/AdminMenus\.conf"\s*
\}\s*\}\s*\}\s*\}
"""
def parse_project(text, *, allow_core_menu=False):
"""Return identity/GUID/title/dependency captures, or None for unreviewed syntax."""
extension = ''
if allow_core_menu:
extension = '(?:' + CORE_MENU_CONFIGURATION + r'\s*)?'
return re.fullmatch(
r'\s*GameProject\s*\{\s*'
r'ID\s+"([^"\r\n]+)"\s*'
r'GUID\s+"([A-F0-9]{16})"\s*'
r'TITLE\s+"([^"\r\n]+)"\s*'
r'Dependencies\s*\{((?:\s*"[A-F0-9]{16}"\s*)+)\}\s*'
+ extension + r'\}\s*', text, re.VERBOSE)
+4 -3
View File
@@ -15,6 +15,7 @@ import sys
sys.dont_write_bytecode = True
from source_manifest import addon_manifest
from project_schema import parse_project
from release_check import audit, read_json, evidence_path
ROOT = Path(__file__).resolve().parents[1]
@@ -124,7 +125,7 @@ def validate(payload, root):
raise ValueError('successor identity catalog differs from the five owned projects')
for name, (identity, guid, deps) in PROJECTS.items():
text = payload.get(f'addons/{name}/addon.gproj', b'').decode('utf-8')
match = re.fullmatch(r'\s*GameProject\s*\{\s*ID "([^"\n]+)"\s*GUID "([A-F0-9]{16})"\s*TITLE "([^"\n]+)"\s*Dependencies\s*\{([\s"A-F0-9]*)\}\s*\}\s*', text)
match = parse_project(text, allow_core_menu=name == 'core')
expected = {BASE, *(PROJECTS[d][1] for d in deps)}
found = re.findall(r'"([A-F0-9]{16})"', match[4]) if match else []
if not match or match[1] != identity or match[2] != guid or set(found) != expected or len(found) != len(expected):
@@ -146,12 +147,12 @@ def validate(payload, root):
raise ValueError('successor resource reuses a vanilla identity')
for name, data in payload.items():
suffix = PurePosixPath(name).suffix
if suffix in {'.meta', '.gproj'}:
if suffix == '.meta':
continue
text = data.decode('utf-8') # Current reviewed handoff contains text assets only.
if re.search(r'\b(?:ESCT\w*|SCRTC_\w+|SCRT_\w+|EAI_\w+)\b', text):
raise ValueError(f'original ecosystem dependency: {name}')
if suffix not in {'.c', '.layer'} and name + '.meta' not in payload:
if suffix not in {'.c', '.layer', '.gproj'} and name + '.meta' not in payload:
raise ValueError(f'resource lacks successor metadata: {name}')
owner = name.split('/')[1]
visible = {owner, *PROJECTS[owner][2]}