f8c3635d40
sol-reviewer round-2 IMPORTANT: relay env vars had no scope classification, so the two readers disagreed under a multiplexed profile scope — gateway/config.py (scope-aware getenv) dropped a process-env GATEWAY_RELAY_URL during the scoped runner reload while gateway/relay's relay_url()/register_relay_adapter()/self-provision (direct os.environ reads) still saw it. Result: adapter registered but Platform.RELAY absent from config, so the connect loop never dialed and direct adapters stayed up. The inverse split (profile-only stamp: config enables RELAY, registration finds no URL) was equally dead. GATEWAY_RELAY_* ROUTING stamps (URL, ENDPOINT, ALLOW_DIRECT_PLATFORMS, PLATFORMS, BOT_IDS, ROUTE_KEYS, INSTANCE_ID, WAKE_URL, DISPLAY_NAME) are now in _GLOBAL_ENV_EXACT: deployment config read from os.environ under any scope, exactly like the API_SERVER listener settings (#69379), so every reader resolves the same value. Relay AUTH material (SECRET, ID, DELIVERY_KEY, IDP_*) is deliberately NOT global — it stays profile-scoped with the fail-closed multiplex guard, mirroring the non-secret/secret line the terminal env blocklist already draws (tools/environments/local.py). The round-1 multiplex regression test asserted the now-rejected semantic (profile-scoped stamps win); it is inverted to pin the global-stamp contract: a process-env stamp survives the profile scope (sweep runs, matching registration), and a profile-only .env stamp does NOT activate relay.