tests/gateway/test_platform_base.py::TestSecretCaptureGuidance::test_gateway_secret_capture_message_points_to_local_setup tests/gateway/test_platform_base.py::TestSafeUrlForLog::test_strips_query_fragment_and_userinfo tests/gateway/test_platform_base.py::TestSafeUrlForLog::test_truncates_long_values tests/gateway/test_platform_base.py::TestSafeUrlForLog::test_handles_small_and_non_positive_max_len tests/gateway/test_platform_base.py::TestMessageEventIsCommand::test_slash_command tests/gateway/test_platform_base.py::TestMessageEventIsCommand::test_regular_text tests/gateway/test_platform_base.py::TestMessageEventIsCommand::test_empty_text tests/gateway/test_platform_base.py::TestMessageEventIsCommand::test_slash_only tests/gateway/test_platform_base.py::TestMessageEventGetCommand::test_simple_command tests/gateway/test_platform_base.py::TestMessageEventGetCommand::test_command_with_args tests/gateway/test_platform_base.py::TestMessageEventGetCommand::test_not_a_command tests/gateway/test_platform_base.py::TestMessageEventGetCommand::test_command_is_lowercased tests/gateway/test_platform_base.py::TestMessageEventGetCommand::test_slash_only_returns_empty tests/gateway/test_platform_base.py::TestMessageEventGetCommand::test_command_with_at_botname tests/gateway/test_platform_base.py::TestMessageEventGetCommand::test_command_with_at_botname_and_args tests/gateway/test_platform_base.py::TestMessageEventGetCommand::test_command_mixed_case_with_at_botname tests/gateway/test_platform_base.py::TestMessageEventGetCommandArgs::test_command_with_args tests/gateway/test_platform_base.py::TestMessageEventGetCommandArgs::test_command_without_args tests/gateway/test_platform_base.py::TestMessageEventGetCommandArgs::test_not_a_command_returns_full_text tests/gateway/test_platform_base.py::TestExtractImages::test_no_images tests/gateway/test_platform_base.py::TestExtractImages::test_markdown_image_with_image_ext tests/gateway/test_platform_base.py::TestExtractImages::test_markdown_image_jpg tests/gateway/test_platform_base.py::TestExtractImages::test_markdown_image_jpeg tests/gateway/test_platform_base.py::TestExtractImages::test_markdown_image_gif tests/gateway/test_platform_base.py::TestExtractImages::test_markdown_image_webp tests/gateway/test_platform_base.py::TestExtractImages::test_fal_media_cdn tests/gateway/test_platform_base.py::TestExtractImages::test_fal_cdn_url tests/gateway/test_platform_base.py::TestExtractImages::test_replicate_delivery tests/gateway/test_platform_base.py::TestExtractImages::test_non_image_ext_not_extracted tests/gateway/test_platform_base.py::TestExtractImages::test_html_img_tag tests/gateway/test_platform_base.py::TestExtractImages::test_html_img_self_closing tests/gateway/test_platform_base.py::TestExtractImages::test_html_img_with_closing_tag tests/gateway/test_platform_base.py::TestExtractImages::test_multiple_images tests/gateway/test_platform_base.py::TestExtractImages::test_mixed_markdown_and_html tests/gateway/test_platform_base.py::TestExtractImages::test_cleaned_content_trims_excess_newlines tests/gateway/test_platform_base.py::TestExtractImages::test_non_http_url_not_matched tests/gateway/test_platform_base.py::TestExtractImages::test_non_image_link_preserved_when_mixed_with_images tests/gateway/test_platform_base.py::TestExtractMedia::test_no_media tests/gateway/test_platform_base.py::TestExtractMedia::test_single_media_tag tests/gateway/test_platform_base.py::TestExtractMedia::test_media_with_voice_directive tests/gateway/test_platform_base.py::TestExtractMedia::test_multiple_media_tags tests/gateway/test_platform_base.py::TestExtractMedia::test_voice_directive_removed_from_content tests/gateway/test_platform_base.py::TestExtractMedia::test_media_with_text_before tests/gateway/test_platform_base.py::TestExtractMedia::test_cleaned_content_trims_excess_newlines tests/gateway/test_platform_base.py::TestExtractMedia::test_media_tag_allows_optional_whitespace_after_colon tests/gateway/test_platform_base.py::TestExtractMedia::test_media_tag_strips_wrapping_quotes_and_backticks tests/gateway/test_platform_base.py::TestExtractMedia::test_media_tag_supports_quoted_paths_with_spaces tests/gateway/test_platform_base.py::TestExtractMedia::test_media_tag_supports_unquoted_flac_paths_with_spaces tests/gateway/test_platform_base.py::TestExtractMedia::test_as_document_directive_stripped_from_cleaned_text tests/gateway/test_platform_base.py::TestExtractMedia::test_as_document_directive_alone_does_not_attach_voice_flag tests/gateway/test_platform_base.py::TestExtractMedia::test_both_directives_can_coexist tests/gateway/test_platform_base.py::TestExtractMedia::test_media_tag_windows_backslash_path tests/gateway/test_platform_base.py::TestExtractMedia::test_media_tag_windows_forward_slash_path tests/gateway/test_platform_base.py::TestExtractMedia::test_media_tag_windows_drive_root tests/gateway/test_platform_base.py::TestExtractMedia::test_media_tag_unix_paths_still_work tests/gateway/test_platform_base.py::TestExtractMedia::test_relative_path_still_ignored tests/gateway/test_platform_base.py::TestExtractMedia::test_media_in_fenced_code_block_ignored tests/gateway/test_platform_base.py::TestExtractMedia::test_media_in_inline_code_ignored tests/gateway/test_platform_base.py::TestExtractMedia::test_media_in_blockquote_ignored tests/gateway/test_platform_base.py::TestExtractMedia::test_media_outside_code_blocks_still_extracted tests/gateway/test_platform_base.py::TestExtractMedia::test_media_mixed_code_and_prose tests/gateway/test_platform_base.py::TestExtractMedia::test_inline_code_survives_when_real_media_present tests/gateway/test_platform_base.py::TestMediaInsideSerializedJson::test_media_in_json_value_not_extracted tests/gateway/test_platform_base.py::TestMediaInsideSerializedJson::test_media_in_pretty_json_value_not_extracted tests/gateway/test_platform_base.py::TestMediaInsideSerializedJson::test_media_in_json_array_not_extracted tests/gateway/test_platform_base.py::TestMediaInsideSerializedJson::test_media_in_nested_json_value_not_extracted tests/gateway/test_platform_base.py::TestMediaInsideSerializedJson::test_media_in_embedded_serialized_reply_not_extracted tests/gateway/test_platform_base.py::TestMediaInsideSerializedJson::test_media_at_line_start_still_extracted tests/gateway/test_platform_base.py::TestMediaInsideSerializedJson::test_media_after_prose_same_line_still_extracted tests/gateway/test_platform_base.py::TestMediaInsideSerializedJson::test_media_indented_still_extracted tests/gateway/test_platform_base.py::TestMediaInsideSerializedJson::test_quoted_path_media_still_extracted tests/gateway/test_platform_base.py::TestMediaInsideSerializedJson::test_tts_two_line_still_extracted tests/gateway/test_platform_base.py::TestMediaInsideSerializedJson::test_json_embedded_media_kept_verbatim_in_cleaned_text tests/gateway/test_platform_base.py::TestMediaInsideSerializedJson::test_cleaned_text_after_directive_not_truncated tests/gateway/test_platform_base.py::TestMediaExtensionAllowlistParity::test_previously_dropped_extensions_now_extract tests/gateway/test_platform_base.py::TestMediaExtensionAllowlistParity::test_extract_media_and_local_files_share_one_extension_set tests/gateway/test_platform_base.py::TestMediaExtensionAllowlistParity::test_unknown_extension_not_black_holed_by_cleanup tests/gateway/test_platform_base.py::TestMediaExtensionAllowlistParity::test_known_extension_tag_is_stripped_from_body tests/gateway/test_platform_base.py::TestMediaDeliveryPathValidation::test_allows_existing_file_inside_safe_root tests/gateway/test_platform_base.py::TestMediaDeliveryPathValidation::test_rejects_existing_file_outside_safe_root tests/gateway/test_platform_base.py::TestMediaDeliveryPathValidation::test_rejects_symlink_escape_from_safe_root tests/gateway/test_platform_base.py::TestMediaDeliveryPathValidation::test_filter_keeps_safe_media_and_drops_unsafe tests/gateway/test_platform_base.py::TestMediaDeliveryPathValidation::test_allows_operator_configured_extra_root tests/gateway/test_platform_base.py::TestMediaDeliveryPathValidation::test_recency_trust_allows_freshly_produced_file tests/gateway/test_platform_base.py::TestMediaDeliveryPathValidation::test_recency_trust_rejects_old_file tests/gateway/test_platform_base.py::TestMediaDeliveryPathValidation::test_recency_trust_disabled_falls_back_to_pure_allowlist tests/gateway/test_platform_base.py::TestMediaDeliveryPathValidation::test_recency_trust_denies_system_paths_even_when_fresh tests/gateway/test_platform_base.py::TestMediaDeliveryPathValidation::test_recency_trust_allows_pdf_in_project_dir tests/gateway/test_platform_base.py::TestMediaDeliveryPathValidation::test_filter_keeps_recently_produced_files tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_accepts_stale_file_outside_allowlist tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_accepts_any_extension_not_on_denylist tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_denylist_still_blocks_credentials tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_denylist_blocks_system_prefixes tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_denylist_blocks_hermes_credentials tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_denylist_blocks_hermes_config_in_active_profile tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_denylist_blocks_shared_hermes_root_config_for_profiles tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_strict_mode_envvar_restores_legacy_behavior tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_strict_mode_truthy_aliases tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_filter_passes_default_files_through tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_root_home_deliverable_is_accepted tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_root_home_credential_subdir_still_blocked tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_root_home_hermes_env_still_blocked tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_other_users_home_still_blocked_for_nonroot tests/gateway/test_platform_base.py::TestMediaDeliveryDefaultMode::test_root_home_workdir_symlink_to_credential_blocked tests/gateway/test_platform_base.py::TestShouldSendMediaAsAudio::test_unknown_extension_returns_false tests/gateway/test_platform_base.py::TestShouldSendMediaAsAudio::test_non_telegram_platforms_route_all_audio tests/gateway/test_platform_base.py::TestShouldSendMediaAsAudio::test_telegram_mp3_and_m4a_route_to_audio tests/gateway/test_platform_base.py::TestShouldSendMediaAsAudio::test_telegram_wav_and_flac_fall_through_to_document tests/gateway/test_platform_base.py::TestShouldSendMediaAsAudio::test_telegram_ogg_opus_only_when_voice_flagged tests/gateway/test_platform_base.py::TestShouldSendMediaAsAudio::test_accepts_platform_enum tests/gateway/test_platform_base.py::TestTruncateMessage::test_short_message_single_chunk tests/gateway/test_platform_base.py::TestTruncateMessage::test_exact_length_single_chunk tests/gateway/test_platform_base.py::TestTruncateMessage::test_long_message_splits tests/gateway/test_platform_base.py::TestTruncateMessage::test_chunks_have_indicators tests/gateway/test_platform_base.py::TestTruncateMessage::test_code_block_first_chunk_closed tests/gateway/test_platform_base.py::TestTruncateMessage::test_code_block_language_tag_carried tests/gateway/test_platform_base.py::TestTruncateMessage::test_continuation_chunks_have_balanced_fences tests/gateway/test_platform_base.py::TestTruncateMessage::test_each_chunk_under_max_length tests/gateway/test_platform_base.py::TestGetHumanDelay::test_off_mode tests/gateway/test_platform_base.py::TestGetHumanDelay::test_default_is_off tests/gateway/test_platform_base.py::TestGetHumanDelay::test_natural_mode_range tests/gateway/test_platform_base.py::TestGetHumanDelay::test_natural_mode_ignores_malformed_custom_env_vars tests/gateway/test_platform_base.py::TestGetHumanDelay::test_custom_mode_uses_env_vars tests/gateway/test_platform_base.py::TestGetHumanDelay::test_custom_mode_tolerates_malformed_env_vars tests/gateway/test_platform_base.py::TestUtf16Len::test_ascii tests/gateway/test_platform_base.py::TestUtf16Len::test_bmp_cjk tests/gateway/test_platform_base.py::TestUtf16Len::test_emoji_surrogate_pair tests/gateway/test_platform_base.py::TestUtf16Len::test_mixed tests/gateway/test_platform_base.py::TestUtf16Len::test_musical_symbol tests/gateway/test_platform_base.py::TestUtf16Len::test_empty tests/gateway/test_platform_base.py::TestPrefixWithinUtf16Limit::test_fits_entirely tests/gateway/test_platform_base.py::TestPrefixWithinUtf16Limit::test_ascii_truncation tests/gateway/test_platform_base.py::TestPrefixWithinUtf16Limit::test_does_not_split_surrogate_pair tests/gateway/test_platform_base.py::TestPrefixWithinUtf16Limit::test_emoji_at_limit tests/gateway/test_platform_base.py::TestPrefixWithinUtf16Limit::test_all_emoji tests/gateway/test_platform_base.py::TestPrefixWithinUtf16Limit::test_empty tests/gateway/test_platform_base.py::TestTruncateMessageUtf16::test_short_emoji_message_no_split tests/gateway/test_platform_base.py::TestTruncateMessageUtf16::test_emoji_near_limit_triggers_split tests/gateway/test_platform_base.py::TestTruncateMessageUtf16::test_each_utf16_chunk_within_limit tests/gateway/test_platform_base.py::TestTruncateMessageUtf16::test_all_content_preserved tests/gateway/test_platform_base.py::TestTruncateMessageUtf16::test_code_blocks_preserved_with_utf16 tests/gateway/test_platform_base.py::TestProxyKwargsForAiohttp::test_none_returns_empty tests/gateway/test_platform_base.py::TestProxyKwargsForAiohttp::test_http_proxy_uses_connector_when_aiohttp_socks_available tests/gateway/test_platform_base.py::TestProxyKwargsForAiohttp::test_socks_proxy_uses_connector tests/gateway/test_platform_base.py::TestProxyKwargsForAiohttp::test_http_proxy_falls_back_without_aiohttp_socks tests/gateway/test_platform_base.py::TestMediaDeliveryDiagnosability::test_rejected_path_appears_in_log tests/gateway/test_platform_base.py::TestMediaDeliveryDiagnosability::test_crafted_null_path_does_not_abort_batch tests/gateway/test_platform_base.py::TestMediaDeliveryDiagnosability::test_extract_media_tolerates_crafted_null_path tests/gateway/test_platform_base.py::TestMediaDeliveryDiagnosability::test_log_safe_path_neutralises_line_breaks tests/gateway/test_platform_base.py::TestMediaDeliveryDiagnosability::test_canonical_cache_roots_present